Skip to content

Commit

Permalink
Fix: number-align should align line/number baselines (#4024)
Browse files Browse the repository at this point in the history
  • Loading branch information
Leedehai committed May 7, 2024
1 parent c0576c6 commit aa38b96
Show file tree
Hide file tree
Showing 16 changed files with 88 additions and 43 deletions.
109 changes: 70 additions & 39 deletions crates/typst/src/math/equation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,42 +389,34 @@ fn add_equation_number(
region_size_x: Abs,
full_number_width: Abs,
) -> Frame {
let first = equation_builder
.frames
.first()
.map_or((equation_builder.size, Point::zero()), |(frame, point)| {
(frame.size(), *point)
});
let last = equation_builder
.frames
.last()
.map_or((equation_builder.size, Point::zero()), |(frame, point)| {
(frame.size(), *point)
});
let first =
equation_builder.frames.first().map_or(
(equation_builder.size, Point::zero(), Abs::zero()),
|(frame, pos)| (frame.size(), *pos, frame.baseline()),
);
let last =
equation_builder.frames.last().map_or(
(equation_builder.size, Point::zero(), Abs::zero()),
|(frame, pos)| (frame.size(), *pos, frame.baseline()),
);
let line_count = equation_builder.frames.len();
let mut equation = equation_builder.build();

let width = if region_size_x.is_finite() {
region_size_x
} else {
equation.width() + 2.0 * full_number_width
};
let height = match number_align.y {
FixedAlignment::Start => {
let (size, point) = first;
let excess_above = (number.height() - size.y) / 2.0 - point.y;
equation.height() + Abs::zero().max(excess_above)
}
FixedAlignment::Center => equation.height().max(number.height()),
FixedAlignment::End => {
let (size, point) = last;
let excess_below =
(number.height() + size.y) / 2.0 - equation.height() + point.y;
equation.height() + Abs::zero().max(excess_below)
}
};
let resizing_offset = equation.resize(
Size::new(width, height),
Axes::<FixedAlignment>::new(equation_align, number_align.y.inv()),

let is_multiline = line_count >= 2;
let resizing_offset = resize_equation(
&mut equation,
&number,
number_align,
equation_align,
width,
is_multiline,
[first, last],
);
equation.translate(Point::with_x(match (equation_align, number_align.x) {
(FixedAlignment::Start, FixedAlignment::Start) => full_number_width,
Expand All @@ -437,19 +429,58 @@ fn add_equation_number(
FixedAlignment::End => equation.width() - number.width(),
_ => unreachable!(),
};
let dh = |h1: Abs, h2: Abs| (h1 - h2) / 2.0;
let y = match number_align.y {
FixedAlignment::Start => {
let (size, point) = first;
resizing_offset.y + point.y + dh(size.y, number.height())
}
FixedAlignment::Center => dh(equation.height(), number.height()),
FixedAlignment::End => {
let (size, point) = last;
resizing_offset.y + point.y + dh(size.y, number.height())
let y = {
let align_baselines = |(_, pos, baseline): (_, Point, Abs), number: &Frame| {
resizing_offset.y + pos.y + baseline - number.baseline()
};
match number_align.y {
FixedAlignment::Start => align_baselines(first, &number),
FixedAlignment::Center if !is_multiline => align_baselines(first, &number),
// In this case, the center lines (not baselines) of the number frame
// and the equation frame shall be aligned.
FixedAlignment::Center => (equation.height() - number.height()) / 2.0,
FixedAlignment::End => align_baselines(last, &number),
}
};

equation.push_frame(Point::new(x, y), number);
equation
}

/// Resize the equation's frame accordingly so that it emcompasses the number.
fn resize_equation(
equation: &mut Frame,
number: &Frame,
number_align: Axes<FixedAlignment>,
equation_align: FixedAlignment,
width: Abs,
is_multiline: bool,
[first, last]: [(Axes<Abs>, Point, Abs); 2],
) -> Point {
if matches!(number_align.y, FixedAlignment::Center if is_multiline) {
// In this case, the center lines (not baselines) of the number frame
// and the equation frame shall be aligned.
let height = equation.height().max(number.height());
return equation.resize(
Size::new(width, height),
Axes::<FixedAlignment>::new(equation_align, FixedAlignment::Center),
);
}

let excess_above = Abs::zero().max({
let (.., baseline) = first;
number.baseline() - baseline
});
let excess_below = Abs::zero().max({
let (size, .., baseline) = last;
(number.height() - number.baseline()) - (size.y - baseline)
});
let height = equation.height() + excess_above + excess_below;

let resizing_offset = equation.resize(
Size::new(width, height),
Axes::<FixedAlignment>::new(equation_align, FixedAlignment::Start),
);
equation.translate(Point::with_y(excess_above));
resizing_offset + Point::with_y(excess_above)
}
4 changes: 2 additions & 2 deletions crates/typst/src/math/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,8 @@ impl Iterator for LeftRightAlternator {
pub struct MathRunFrameBuilder {
/// The size of the resulting frame.
pub size: Size,
/// Sub frames for each row, and the positions where they should be pushed into
/// the resulting frame.
/// Each row's frame, and the position where the frame should
/// be pushed into the resulting frame.
pub frames: Vec<(Frame, Point)>,
}

Expand Down
Binary file modified tests/ref/math-equation-align-numbered.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-number-align-end.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-number-align-left.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/ref/math-equation-number-align-monoline.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-number-align-multiline-bottom.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-number-align-multiline-expand.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-number-align-multiline-top-start.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-number-align-right.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-number-align-start.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-number-align.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/math-equation-numbering.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/outline.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref/ref-supplements.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 16 additions & 2 deletions tests/suite/math/equation.typ
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ $ a + b = c $
// Error: 52-67 expected `start`, `left`, `right`, or `end`, found center
#set math.equation(numbering: "(1)", number-align: center + bottom)

--- math-equation-number-align-monoline ---
#set math.equation(numbering: "(1)")
$ p = sum_k k ln a $

#set math.equation(numbering: "(1)", number-align: top)
$ p = sum_k k ln a $

#set math.equation(numbering: "(1)", number-align: bottom)
$ p = sum_k k ln a $

--- math-equation-number-align-multiline ---
#set math.equation(numbering: "(1)")

Expand All @@ -163,13 +173,17 @@ $ p &= ln a b \

$ p &= ln a b \
&= ln a + ln b $
$ q &= sum_k k ln a \
&= sum_k ln A $

--- math-equation-number-align-multiline-bottom ---
#show math.equation: set align(left)
#set math.equation(numbering: "(1)", number-align: bottom)

$ q &= ln sqrt(a b) \
&= 1/2 (ln a + ln b) $
$ p &= ln a b \
&= ln a + ln b $
$ q &= sum_k ln A \
&= sum_k k ln a $

--- math-equation-number-align-multiline-expand ---
// Tests that if the numbering's layout box vertically exceeds the box of
Expand Down

0 comments on commit aa38b96

Please sign in to comment.