diff --git a/crates/typst/src/eval/call.rs b/crates/typst/src/eval/call.rs index fd660e94a..9e4a128f9 100644 --- a/crates/typst/src/eval/call.rs +++ b/crates/typst/src/eval/call.rs @@ -122,10 +122,13 @@ impl Eval for ast::FuncCall<'_> { let c = sym.get(); if let Some(accent) = Symbol::combining_accent(c) { let base = args.expect("base")?; + let size = args.named("size")?; args.finish()?; - return Ok(Value::Content( - AccentElem::new(base, Accent::new(accent)).pack(), - )); + let mut accent = AccentElem::new(base, Accent::new(accent)); + if let Some(size) = size { + accent = accent.with_size(size); + } + return Ok(Value::Content(accent.pack())); } } let mut body = Content::empty(); diff --git a/crates/typst/src/math/accent.rs b/crates/typst/src/math/accent.rs index 0480567c4..ba0307787 100644 --- a/crates/typst/src/math/accent.rs +++ b/crates/typst/src/math/accent.rs @@ -2,8 +2,8 @@ use ttf_parser::GlyphId; use unicode_math_class::MathClass; use crate::diag::{bail, SourceResult}; -use crate::foundations::{cast, elem, Content, NativeElement, Value}; -use crate::layout::{Abs, Em, Frame, Point, Size}; +use crate::foundations::{cast, elem, Content, NativeElement, Resolve, Smart, Value}; +use crate::layout::{Abs, Em, Frame, Length, Point, Rel, Size}; use crate::math::{ FrameFragment, GlyphFragment, LayoutMath, MathContext, MathFragment, Scaled, }; @@ -56,6 +56,9 @@ pub struct AccentElem { /// | Left arrow | `arrow.l`, `<-` | `←` | #[required] pub accent: Accent, + + /// The size of the accent, relative to the width of the base. + pub size: Smart>, } impl LayoutMath for AccentElem { @@ -74,12 +77,18 @@ impl LayoutMath for AccentElem { _ => (base.width() + base.italics_correction()) / 2.0, }; + let width = self + .size(ctx.styles()) + .unwrap_or(Rel::one()) + .resolve(ctx.styles()) + .relative_to(base.width()); + // Forcing the accent to be at least as large as the base makes it too // wide in many case. let Accent(c) = self.accent(); let glyph = GlyphFragment::new(ctx, *c, self.span()); let short_fall = ACCENT_SHORT_FALL.scaled(ctx); - let variant = glyph.stretch_horizontal(ctx, base.width(), short_fall); + let variant = glyph.stretch_horizontal(ctx, width, short_fall); let accent = variant.frame; let accent_attach = match variant.id { Some(id) => attachment(ctx, id, variant.italics_correction), diff --git a/tests/ref/math/accent.png b/tests/ref/math/accent.png index 619a066c0..b955b5adb 100644 Binary files a/tests/ref/math/accent.png and b/tests/ref/math/accent.png differ diff --git a/tests/typ/math/accent.typ b/tests/typ/math/accent.typ index cf1d3fa24..315e14b3c 100644 --- a/tests/typ/math/accent.typ +++ b/tests/typ/math/accent.typ @@ -27,3 +27,7 @@ $A^x != hat(A)^x != hat(hat(A))^x$ --- // Test high base. $ tilde(integral), tilde(integral)_a^b, tilde(integral_a^b) $ + +--- +// Test accent size. +$tilde(sum), tilde(sum, size: #50%), accent(H, hat, size: #200%)$