summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/typst/src/layout/align.rs8
-rw-r--r--crates/typst/src/math/equation.rs102
-rw-r--r--tests/ref/math/equation-block-align.png (renamed from tests/ref/math/block-alignment.png)bin5170 -> 5170 bytes
-rw-r--r--tests/ref/math/equation-number.pngbin0 -> 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.typ96
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
index 8736312a..8736312a 100644
--- a/tests/ref/math/block-alignment.png
+++ b/tests/ref/math/equation-block-align.png
Binary files differ
diff --git a/tests/ref/math/equation-number.png b/tests/ref/math/equation-number.png
new file mode 100644
index 00000000..96a1f21a
--- /dev/null
+++ b/tests/ref/math/equation-number.png
Binary files differ
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)