Fix: number-align should align line/number baselines (#4024)

This commit is contained in:
Leedehai 2024-05-07 09:46:18 -04:00 committed by GitHub
parent c0576c6b55
commit aa38b96849
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 88 additions and 43 deletions

View File

@ -389,18 +389,17 @@ 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() {
@ -408,23 +407,16 @@ fn add_equation_number(
} 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,
@ -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)
}

View File

@ -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)>,
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 758 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 B

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -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)")
@ -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