From 99b393110e622971c29d34dfb9d9d7b660131b20 Mon Sep 17 00:00:00 2001 From: +merlan #flirora Date: Tue, 4 Jun 2024 11:22:56 -0400 Subject: [PATCH] Align corner brackets to the top and bottom when scaling (#4200) --- crates/typst/src/layout/align.rs | 10 ++++++++++ crates/typst/src/math/fragment.rs | 12 ++++++++++-- crates/typst/src/math/lr.rs | 4 +++- crates/typst/src/math/matrix.rs | 6 ++++-- crates/typst/src/math/mod.rs | 10 +++++++++- tests/ref/issue-4188-lr-corner-brackets.png | Bin 0 -> 368 bytes tests/suite/math/delimited.typ | 4 ++++ 7 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 tests/ref/issue-4188-lr-corner-brackets.png diff --git a/crates/typst/src/layout/align.rs b/crates/typst/src/layout/align.rs index 957444122..188796923 100644 --- a/crates/typst/src/layout/align.rs +++ b/crates/typst/src/layout/align.rs @@ -416,6 +416,16 @@ impl VAlignment { Self::Bottom => Self::Top, } } + + /// Returns the position of this alignment in a container with the given + /// extent. + pub fn position(self, extent: Abs) -> Abs { + match self { + Self::Top => Abs::zero(), + Self::Horizon => extent / 2.0, + Self::Bottom => extent, + } + } } impl FixAlignment for VAlignment { diff --git a/crates/typst/src/math/fragment.rs b/crates/typst/src/math/fragment.rs index ef865b380..63c42cbce 100644 --- a/crates/typst/src/math/fragment.rs +++ b/crates/typst/src/math/fragment.rs @@ -6,7 +6,9 @@ use ttf_parser::{GlyphId, Rect}; use unicode_math_class::MathClass; use crate::foundations::StyleChain; -use crate::layout::{Abs, Corner, Em, Frame, FrameItem, HideElem, Point, Size}; +use crate::layout::{ + Abs, Corner, Em, Frame, FrameItem, HideElem, Point, Size, VAlignment, +}; use crate::math::{ scaled_font_size, EquationElem, Limits, MathContext, MathSize, Scaled, }; @@ -408,9 +410,15 @@ impl VariantFragment { /// Vertically adjust the fragment's frame so that it is centered /// on the axis. pub fn center_on_axis(&mut self, ctx: &MathContext) { + self.align_on_axis(ctx, VAlignment::Horizon) + } + + /// Vertically adjust the fragment's frame so that it is aligned + /// to the given alignment on the axis. + pub fn align_on_axis(&mut self, ctx: &MathContext, align: VAlignment) { let h = self.frame.height(); let axis = ctx.constants.axis_height().scaled(ctx, self.font_size); - self.frame.set_baseline(h / 2.0 + axis); + self.frame.set_baseline(align.inv().position(h + axis * 2.0)); } } diff --git a/crates/typst/src/math/lr.rs b/crates/typst/src/math/lr.rs index 671aa7df9..e542b8db4 100644 --- a/crates/typst/src/math/lr.rs +++ b/crates/typst/src/math/lr.rs @@ -10,6 +10,8 @@ use crate::math::{ }; use crate::text::TextElem; +use super::delimiter_alignment; + /// How much less high scaled delimiters can be than what they wrap. pub(super) const DELIM_SHORT_FALL: Em = Em::new(0.1); @@ -160,7 +162,7 @@ fn scale( let short_fall = DELIM_SHORT_FALL.at(glyph.font_size); let mut stretched = glyph.stretch_vertical(ctx, height, short_fall); - stretched.center_on_axis(ctx); + stretched.align_on_axis(ctx, delimiter_alignment(stretched.c)); *fragment = MathFragment::Variant(stretched); if let Some(class) = apply { diff --git a/crates/typst/src/math/matrix.rs b/crates/typst/src/math/matrix.rs index 138a494bc..2581cfee1 100644 --- a/crates/typst/src/math/matrix.rs +++ b/crates/typst/src/math/matrix.rs @@ -20,6 +20,8 @@ use crate::text::TextElem; use crate::utils::Numeric; use crate::visualize::{FixedStroke, Geometry, LineCap, Shape, Stroke}; +use super::delimiter_alignment; + const DEFAULT_ROW_GAP: Em = Em::new(0.5); const DEFAULT_COL_GAP: Em = Em::new(0.5); const VERTICAL_PADDING: Ratio = Ratio::new(0.1); @@ -610,7 +612,7 @@ fn layout_delimiters( if let Some(left) = left { let mut left = GlyphFragment::new(ctx, styles, left, span) .stretch_vertical(ctx, target, short_fall); - left.center_on_axis(ctx); + left.align_on_axis(ctx, delimiter_alignment(left.c)); ctx.push(left); } @@ -619,7 +621,7 @@ fn layout_delimiters( if let Some(right) = right { let mut right = GlyphFragment::new(ctx, styles, right, span) .stretch_vertical(ctx, target, short_fall); - right.center_on_axis(ctx); + right.align_on_axis(ctx, delimiter_alignment(right.c)); ctx.push(right); } diff --git a/crates/typst/src/math/mod.rs b/crates/typst/src/math/mod.rs index a97f56dc9..3b493b81a 100644 --- a/crates/typst/src/math/mod.rs +++ b/crates/typst/src/math/mod.rs @@ -46,7 +46,7 @@ use crate::foundations::{ StyledElem, }; use crate::introspection::TagElem; -use crate::layout::{BoxElem, Frame, FrameItem, HElem, Point, Size, Spacing}; +use crate::layout::{BoxElem, Frame, FrameItem, HElem, Point, Size, Spacing, VAlignment}; use crate::realize::{process, BehavedBuilder}; use crate::text::{LinebreakElem, SpaceElem, TextElem}; @@ -317,3 +317,11 @@ impl LayoutMath for Content { Ok(()) } } + +fn delimiter_alignment(delimiter: char) -> VAlignment { + match delimiter { + '\u{231c}' | '\u{231d}' => VAlignment::Top, + '\u{231e}' | '\u{231f}' => VAlignment::Bottom, + _ => VAlignment::Horizon, + } +} diff --git a/tests/ref/issue-4188-lr-corner-brackets.png b/tests/ref/issue-4188-lr-corner-brackets.png new file mode 100644 index 0000000000000000000000000000000000000000..c932def2124de000369bad0aad7b91d43f3abba4 GIT binary patch literal 368 zcmV-$0gwKPP)&wZ6FTcDv3SByG`W9~ zi$PQ;jE`U=z<1ZZU~x(;-tY%qGUWk?T#Y0$AHx9uuV8VCAA9e z&nFoBkNKWc)JR+}L;qzQfpMO={Y(7-VV-VmY+MQzzLEUj?;cFeso4LKf2m+`-Ln5) zzhInIbN@R%fiQnOfByVEECLSvcSa