diff options
| author | damaxwell <damaxwell@alaska.edu> | 2023-07-18 05:41:35 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-18 15:41:35 +0200 |
| commit | 7dc605307cf7d69a3476b8b6fc4786f683c3289b (patch) | |
| tree | 2ec3b739bfb1ee935ac4a04df0d4ab276e4410bf | |
| parent | 0c94d2b34e77edbd116c9f7be591ca710363b844 (diff) | |
Improved math root layout (#1743)
| -rw-r--r-- | crates/typst-library/src/math/root.rs | 73 | ||||
| -rw-r--r-- | tests/ref/bugs/math-realize.png | bin | 21192 -> 21176 bytes | |||
| -rw-r--r-- | tests/ref/math/accent.png | bin | 8080 -> 8045 bytes | |||
| -rw-r--r-- | tests/ref/math/attach-p1.png | bin | 13740 -> 14576 bytes | |||
| -rw-r--r-- | tests/ref/math/attach-p2.png | bin | 11071 -> 11553 bytes | |||
| -rw-r--r-- | tests/ref/math/frac.png | bin | 28867 -> 28849 bytes | |||
| -rw-r--r-- | tests/ref/math/numbering.png | bin | 12019 -> 12050 bytes | |||
| -rw-r--r-- | tests/ref/math/root.png | bin | 12575 -> 12554 bytes | |||
| -rw-r--r-- | tests/ref/math/style.png | bin | 23825 -> 23817 bytes |
9 files changed, 31 insertions, 42 deletions
diff --git a/crates/typst-library/src/math/root.rs b/crates/typst-library/src/math/root.rs index d1c5f46a..0cf5679a 100644 --- a/crates/typst-library/src/math/root.rs +++ b/crates/typst-library/src/math/root.rs @@ -46,10 +46,11 @@ impl LayoutMath for RootElem { /// Layout a root. /// -/// https://www.w3.org/TR/mathml-core/#radicals-msqrt-mroot +/// TeXbook page 443, page 360 +/// See also: https://www.w3.org/TR/mathml-core/#radicals-msqrt-mroot fn layout( ctx: &mut MathContext, - mut index: Option<&Content>, + index: Option<&Content>, radicand: &Content, span: Span, ) -> SourceResult<()> { @@ -71,25 +72,23 @@ fn layout( // Layout root symbol. let target = radicand.height() + thickness + gap; - let sqrt = precomposed(ctx, index, target) - .map(|frame| { - index = None; - frame - }) - .unwrap_or_else(|| { - let glyph = GlyphFragment::new(ctx, '√', span); - glyph.stretch_vertical(ctx, target, Abs::zero()).frame - }); + let sqrt = GlyphFragment::new(ctx, '√', span) + .stretch_vertical(ctx, target, Abs::zero()) + .frame; // Layout the index. - // Script-script style looks too small, we use Script style instead. - ctx.style(ctx.style.with_size(MathSize::Script)); + ctx.style(ctx.style.with_size(MathSize::ScriptScript)); let index = index.map(|elem| ctx.layout_frame(elem)).transpose()?; ctx.unstyle(); - let gap = gap.max((sqrt.height() - radicand.height() - thickness) / 2.0); - let descent = radicand.descent() + gap; - let inner_ascent = extra_ascender + thickness + gap + radicand.ascent(); + // TeXbook, page 443, item 11 + // Keep original gap, and then distribute any remaining free space + // equally above and below. + let gap = gap.max((sqrt.height() - thickness - radicand.height() + gap) / 2.0); + + let sqrt_ascent = radicand.ascent() + gap + thickness; + let descent = sqrt.height() - sqrt_ascent; + let inner_ascent = sqrt_ascent + extra_ascender; let mut sqrt_offset = Abs::zero(); let mut shift_up = Abs::zero(); @@ -97,23 +96,32 @@ fn layout( if let Some(index) = &index { sqrt_offset = kern_before + index.width() + kern_after; - shift_up = raise_factor * sqrt.height() - descent + index.descent(); + // The formula below for how much raise the index by comes from + // the TeXbook, page 360, in the definition of `\root`. + // However, the `+ index.descent()` part is different from TeX. + // Without it, descenders can collide with the surd, a rarity + // in practice, but possible. MS Word also adjusts index positions + // for descenders. + shift_up = raise_factor * (inner_ascent - descent) + index.descent(); ascent.set_max(shift_up + index.ascent()); } - let radicant_offset = sqrt_offset + sqrt.width(); - let width = radicant_offset + radicand.width(); + let radicand_x = sqrt_offset + sqrt.width(); + let radicand_y = ascent - radicand.ascent(); + let width = radicand_x + radicand.width(); let size = Size::new(width, ascent + descent); - let sqrt_pos = Point::new(sqrt_offset, ascent - inner_ascent); - let line_pos = Point::new(radicant_offset, ascent - inner_ascent + thickness / 2.0); - let radicand_pos = Point::new(radicant_offset, ascent - radicand.ascent()); + // The extra "- thickness" comes from the fact that the sqrt is placed + // in `push_frame` with respect to its top, not its baseline. + let sqrt_pos = Point::new(sqrt_offset, radicand_y - gap - thickness); + let line_pos = Point::new(radicand_x, radicand_y - gap - (thickness / 2.0)); + let radicand_pos = Point::new(radicand_x, radicand_y); let mut frame = Frame::new(size); frame.set_baseline(ascent); if let Some(index) = index { - let index_pos = Point::new(kern_before, ascent - shift_up - index.ascent()); + let index_pos = Point::new(kern_before, ascent - index.ascent() - shift_up); frame.push_frame(index_pos, index); } @@ -135,22 +143,3 @@ fn layout( Ok(()) } - -/// Select a precomposed radical, if the font has it. -fn precomposed(ctx: &MathContext, index: Option<&Content>, target: Abs) -> Option<Frame> { - let elem = index?.to::<TextElem>()?; - let c = match elem.text().as_str() { - "3" => '∛', - "4" => '∜', - _ => return None, - }; - - ctx.ttf.glyph_index(c)?; - let glyph = GlyphFragment::new(ctx, c, elem.span()); - let variant = glyph.stretch_vertical(ctx, target, Abs::zero()).frame; - if variant.height() < target { - return None; - } - - Some(variant) -} diff --git a/tests/ref/bugs/math-realize.png b/tests/ref/bugs/math-realize.png Binary files differindex 5ce129f6..f5043984 100644 --- a/tests/ref/bugs/math-realize.png +++ b/tests/ref/bugs/math-realize.png diff --git a/tests/ref/math/accent.png b/tests/ref/math/accent.png Binary files differindex 1065576e..78d5f498 100644 --- a/tests/ref/math/accent.png +++ b/tests/ref/math/accent.png diff --git a/tests/ref/math/attach-p1.png b/tests/ref/math/attach-p1.png Binary files differindex 0b9b8f34..0c2f2bed 100644 --- a/tests/ref/math/attach-p1.png +++ b/tests/ref/math/attach-p1.png diff --git a/tests/ref/math/attach-p2.png b/tests/ref/math/attach-p2.png Binary files differindex 242be908..d956059d 100644 --- a/tests/ref/math/attach-p2.png +++ b/tests/ref/math/attach-p2.png diff --git a/tests/ref/math/frac.png b/tests/ref/math/frac.png Binary files differindex 94990208..0b81e37b 100644 --- a/tests/ref/math/frac.png +++ b/tests/ref/math/frac.png diff --git a/tests/ref/math/numbering.png b/tests/ref/math/numbering.png Binary files differindex 3952dea0..b8b462ba 100644 --- a/tests/ref/math/numbering.png +++ b/tests/ref/math/numbering.png diff --git a/tests/ref/math/root.png b/tests/ref/math/root.png Binary files differindex 017582a4..af5c41ea 100644 --- a/tests/ref/math/root.png +++ b/tests/ref/math/root.png diff --git a/tests/ref/math/style.png b/tests/ref/math/style.png Binary files differindex cf962574..c9bf5d64 100644 --- a/tests/ref/math/style.png +++ b/tests/ref/math/style.png |
