diff options
| author | Leedehai <18319900+Leedehai@users.noreply.github.com> | 2024-02-22 03:49:24 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-22 08:49:24 +0000 |
| commit | 0fe03bae6e154c30934d9f25037fa57e7381780f (patch) | |
| tree | 0bc6f3a38ad371140a80f6d62563349c0c5f37b4 | |
| parent | 4eab6deed6944ad5aedd41a1468ce7a3d168701e (diff) | |
Add `number-align` to `math.equation` [Better Equation Numbering Pt.2] (#3446)
| -rw-r--r-- | crates/typst/src/layout/align.rs | 8 | ||||
| -rw-r--r-- | crates/typst/src/math/equation.rs | 102 | ||||
| -rw-r--r-- | tests/ref/math/equation-block-align.png (renamed from tests/ref/math/block-alignment.png) | bin | 5170 -> 5170 bytes | |||
| -rw-r--r-- | tests/ref/math/equation-number.png | bin | 0 -> 18851 bytes | |||
| -rw-r--r-- | tests/typ/math/equation-block-align.typ (renamed from tests/typ/math/block-alignment.typ) | 0 | ||||
| -rw-r--r-- | tests/typ/math/equation-number.typ | 96 |
6 files changed, 170 insertions, 36 deletions
diff --git a/crates/typst/src/layout/align.rs b/crates/typst/src/layout/align.rs index 58dc7589..5f516ebe 100644 --- a/crates/typst/src/layout/align.rs +++ b/crates/typst/src/layout/align.rs @@ -356,6 +356,14 @@ impl OuterHAlignment { } } +impl Resolve for OuterHAlignment { + type Output = FixedAlignment; + + fn resolve(self, styles: StyleChain) -> Self::Output { + self.fix(TextElem::dir_in(styles)) + } +} + impl From<OuterHAlignment> for HAlignment { fn from(value: OuterHAlignment) -> Self { match value { diff --git a/crates/typst/src/math/equation.rs b/crates/typst/src/math/equation.rs index e4744aea..a272622e 100644 --- a/crates/typst/src/math/equation.rs +++ b/crates/typst/src/math/equation.rs @@ -10,8 +10,8 @@ use crate::foundations::{ }; use crate::introspection::{Count, Counter, CounterUpdate, Locatable}; use crate::layout::{ - Abs, AlignElem, Alignment, Axes, Dir, Em, FixedAlignment, Frame, LayoutMultiple, - LayoutSingle, Point, Regions, Size, + Abs, AlignElem, Alignment, Axes, Em, FixedAlignment, Frame, LayoutMultiple, + LayoutSingle, OuterHAlignment, Point, Regions, Size, }; use crate::math::{scaled_font_size, LayoutMath, MathContext, MathSize, MathVariant}; use crate::model::{Numbering, Outlinable, ParElem, Refable, Supplement}; @@ -76,6 +76,21 @@ pub struct EquationElem { #[borrowed] pub numbering: Option<Numbering>, + /// The alignment of the equation numbering. + /// + /// By default, the number is put at the `{end}` of the equation block. Both + /// `{start}` and `{end}` respects text direction; for absolute positioning, + /// use `{left}` or `{right}`. + /// + /// ```example + /// #set math.equation(numbering: "(1)", number-align: start) + /// + /// With natural units, we know: + /// $ E^2 = m^2 + p^2 $ + /// ``` + #[default(OuterHAlignment::End)] + pub number_align: OuterHAlignment, + /// A supplement for the equation. /// /// For references to equations, this is added before the referenced number. @@ -192,7 +207,6 @@ impl Packed<EquationElem> { ) -> SourceResult<Vec<MathParItem>> { assert!(!self.block(styles)); - // Find a math font. let font = find_math_font(engine, styles, self.span())?; let mut ctx = MathContext::new(engine, styles, regions, &font); @@ -231,52 +245,34 @@ impl LayoutSingle for Packed<EquationElem> { styles: StyleChain, regions: Regions, ) -> SourceResult<Frame> { - const NUMBER_GUTTER: Em = Em::new(0.5); - assert!(self.block(styles)); - // Find a math font. - let font = find_math_font(engine, styles, self.span())?; + let span = self.span(); + let font = find_math_font(engine, styles, span)?; let mut ctx = MathContext::new(engine, styles, regions, &font); let mut frame = ctx.layout_into_frame(self, styles)?; if let Some(numbering) = (**self).numbering(styles) { let pod = Regions::one(regions.base(), Axes::splat(false)); - let counter = Counter::of(EquationElem::elem()) + let number = Counter::of(EquationElem::elem()) .at(engine, self.location().unwrap())? .display(engine, numbering)? - .spanned(self.span()) + .spanned(span) .layout(engine, styles, pod)? .into_frame(); - let full_counter_width = counter.width() + NUMBER_GUTTER.resolve(styles); - let width = if regions.size.x.is_finite() { - regions.size.x - } else { - frame.width() + 2.0 * full_counter_width - }; - - let height = frame.height().max(counter.height()); - let align = AlignElem::alignment_in(styles).resolve(styles).x; - frame.resize(Size::new(width, height), Axes::splat(align)); - - let dir = TextElem::dir_in(styles); - let offset = match (align, dir) { - (FixedAlignment::Start, Dir::RTL) => full_counter_width, - (FixedAlignment::End, Dir::LTR) => -full_counter_width, - _ => Abs::zero(), - }; - frame.translate(Point::with_x(offset)); - - let x = if dir.is_positive() { - frame.width() - counter.width() - } else { - Abs::zero() - }; - let y = (frame.height() - counter.height()) / 2.0; - - frame.push_frame(Point::new(x, y), counter) + static NUMBER_GUTTER: Em = Em::new(0.5); + let full_number_width = number.width() + NUMBER_GUTTER.resolve(styles); + + add_equation_number( + &mut frame, + number, + self.number_align(styles).resolve(styles), + AlignElem::alignment_in(styles).resolve(styles).x, + regions.size.x, + full_number_width, + ); } Ok(frame) @@ -398,3 +394,37 @@ fn find_math_font( }; Ok(font) } + +fn add_equation_number( + equation: &mut Frame, + number: Frame, + number_align: FixedAlignment, + equation_align: FixedAlignment, + region_size_x: Abs, + full_number_width: Abs, +) { + let width = if region_size_x.is_finite() { + region_size_x + } else { + equation.width() + 2.0 * full_number_width + }; + + let height = equation.height().max(number.height()); + equation.resize(Size::new(width, height), Axes::splat(equation_align)); + + let offset = match (equation_align, number_align) { + (FixedAlignment::Start, FixedAlignment::Start) => full_number_width, + (FixedAlignment::End, FixedAlignment::End) => -full_number_width, + _ => Abs::zero(), + }; + equation.translate(Point::with_x(offset)); + + let x = match number_align { + FixedAlignment::Start => Abs::zero(), + FixedAlignment::End => equation.width() - number.width(), + _ => unreachable!(), + }; + let y = (equation.height() - number.height()) / 2.0; + + equation.push_frame(Point::new(x, y), number); +} diff --git a/tests/ref/math/block-alignment.png b/tests/ref/math/equation-block-align.png Binary files differindex 8736312a..8736312a 100644 --- a/tests/ref/math/block-alignment.png +++ b/tests/ref/math/equation-block-align.png diff --git a/tests/ref/math/equation-number.png b/tests/ref/math/equation-number.png Binary files differnew file mode 100644 index 00000000..96a1f21a --- /dev/null +++ b/tests/ref/math/equation-number.png diff --git a/tests/typ/math/block-alignment.typ b/tests/typ/math/equation-block-align.typ index c6c9cd89..c6c9cd89 100644 --- a/tests/typ/math/block-alignment.typ +++ b/tests/typ/math/equation-block-align.typ diff --git a/tests/typ/math/equation-number.typ b/tests/typ/math/equation-number.typ new file mode 100644 index 00000000..aefa308a --- /dev/null +++ b/tests/typ/math/equation-number.typ @@ -0,0 +1,96 @@ +// Test equation number, and its interaction with equation +// block's alignment and text direction. + +--- +#set math.equation(numbering: "(1)") + +$ a + b = c $ + +#show math.equation: set align(center) +$ a + b = c $ +#show math.equation: set align(left) +$ a + b = c $ +#show math.equation: set align(right) +$ a + b = c $ + +#set text(dir: rtl) +#show math.equation: set align(start) +$ a + b = c $ +#show math.equation: set align(end) +$ a + b = c $ + +--- +#set math.equation(numbering: "(1)", number-align: start) + +$ a + b = c $ + +#show math.equation: set align(center) +$ a + b = c $ +#show math.equation: set align(left) +$ a + b = c $ +#show math.equation: set align(right) +$ a + b = c $ + +#set text(dir: rtl) +#show math.equation: set align(start) +$ a + b = c $ +#show math.equation: set align(end) +$ a + b = c $ + +--- +#set math.equation(numbering: "(1)", number-align: end) + +$ a + b = c $ + +#show math.equation: set align(center) +$ a + b = c $ +#show math.equation: set align(left) +$ a + b = c $ +#show math.equation: set align(right) +$ a + b = c $ + +#set text(dir: rtl) +#show math.equation: set align(start) +$ a + b = c $ +#show math.equation: set align(end) +$ a + b = c $ + +--- +#set math.equation(numbering: "(1)", number-align: left) + +$ a + b = c $ + +#show math.equation: set align(center) +$ a + b = c $ +#show math.equation: set align(left) +$ a + b = c $ +#show math.equation: set align(right) +$ a + b = c $ + +#set text(dir: rtl) +#show math.equation: set align(start) +$ a + b = c $ +#show math.equation: set align(end) +$ a + b = c $ + +--- +#set math.equation(numbering: "(1)", number-align: right) + +$ a + b = c $ + +#show math.equation: set align(center) +$ a + b = c $ +#show math.equation: set align(left) +$ a + b = c $ +#show math.equation: set align(right) +$ a + b = c $ + +#set text(dir: rtl) +#show math.equation: set align(start) +$ a + b = c $ +#show math.equation: set align(end) +$ a + b = c $ + +--- +// Error: 52-58 expected `start`, `left`, `right`, or `end`, found center +#set math.equation(numbering: "(1)", number-align: center) |
