Add fractional spacing inline item

This commit is contained in:
mkorje 2025-05-30 19:22:26 +10:00
parent 3e7a39e968
commit cd9600170b
No known key found for this signature in database
9 changed files with 63 additions and 18 deletions

View File

@ -201,9 +201,12 @@ pub fn collect<'a>(
for item in elem.layout(engine, locator.next(&elem.span()), styles, region)? {
match item {
InlineItem::Space(space, weak) => {
InlineItem::Absolute(space, weak) => {
collector.push_item(Item::Absolute(space, weak));
}
InlineItem::Fractional(fr) => {
collector.push_item(Item::Fractional(fr, None));
}
InlineItem::Frame(mut frame) => {
frame.modify(&FrameModifiers::get_in(styles));
apply_baseline_shift(&mut frame, styles);

View File

@ -7,7 +7,7 @@ use ttf_parser::{GlyphId, Rect};
use typst_library::foundations::StyleChain;
use typst_library::introspection::Tag;
use typst_library::layout::{
Abs, Axis, Corner, Em, Frame, FrameItem, Point, Size, VAlignment,
Abs, Axis, Corner, Em, Fr, Frame, FrameItem, Point, Size, VAlignment,
};
use typst_library::math::{EquationElem, MathSize};
use typst_library::text::{Font, Glyph, Lang, Region, TextElem, TextItem};
@ -24,7 +24,8 @@ pub enum MathFragment {
Glyph(GlyphFragment),
Variant(VariantFragment),
Frame(FrameFragment),
Spacing(Abs, bool),
Absolute(Abs, bool),
Fractional(Fr),
Space(Abs),
Linebreak,
Align,
@ -41,7 +42,7 @@ impl MathFragment {
Self::Glyph(glyph) => glyph.width,
Self::Variant(variant) => variant.frame.width(),
Self::Frame(fragment) => fragment.frame.width(),
Self::Spacing(amount, _) => *amount,
Self::Absolute(amount, _) => *amount,
Self::Space(amount) => *amount,
_ => Abs::zero(),
}
@ -87,7 +88,8 @@ impl MathFragment {
Self::Glyph(glyph) => glyph.class,
Self::Variant(variant) => variant.class,
Self::Frame(fragment) => fragment.class,
Self::Spacing(_, _) => MathClass::Space,
Self::Absolute(_, _) => MathClass::Space,
Self::Fractional(_) => MathClass::Space,
Self::Space(_) => MathClass::Space,
Self::Linebreak => MathClass::Space,
Self::Align => MathClass::Special,

View File

@ -75,7 +75,7 @@ pub fn layout_lr(
fragments.retain(|fragment| {
let discard = (index == start_idx + 1 && opening_exists
|| index + 2 == end_idx && closing_exists)
&& matches!(fragment, MathFragment::Spacing(_, true));
&& matches!(fragment, MathFragment::Absolute(_, true));
index += 1;
!discard
});

View File

@ -635,11 +635,17 @@ fn layout_h(
ctx: &mut MathContext,
styles: StyleChain,
) -> SourceResult<()> {
if let Spacing::Rel(rel) = elem.amount {
if rel.rel.is_zero() {
ctx.push(MathFragment::Spacing(rel.abs.resolve(styles), elem.weak(styles)));
}
if elem.amount.is_zero() {
return Ok(());
}
ctx.push(match elem.amount {
Spacing::Fr(fr) => MathFragment::Fractional(fr),
Spacing::Rel(rel) => MathFragment::Absolute(
rel.resolve(styles).relative_to(ctx.region.size.x),
elem.weak(styles),
),
});
Ok(())
}

View File

@ -33,14 +33,14 @@ impl MathRun {
}
// Explicit spacing disables automatic spacing.
MathFragment::Spacing(width, weak) => {
MathFragment::Absolute(width, weak) => {
last = None;
space = None;
if weak {
match resolved.last_mut() {
None => continue,
Some(MathFragment::Spacing(prev, true)) => {
Some(MathFragment::Absolute(prev, true)) => {
*prev = (*prev).max(width);
continue;
}
@ -52,6 +52,14 @@ impl MathRun {
continue;
}
// Same as explicit spacing that isn't weak.
MathFragment::Fractional(_) => {
last = None;
space = None;
resolved.push(fragment);
continue;
}
// Alignment points are resolved later.
MathFragment::Align => {
resolved.push(fragment);
@ -99,7 +107,7 @@ impl MathRun {
resolved.push(fragment);
}
if let Some(MathFragment::Spacing(_, true)) = resolved.last() {
if let Some(MathFragment::Absolute(_, true)) = resolved.last() {
resolved.pop();
}
@ -299,7 +307,7 @@ impl MathRun {
let mut space_is_visible = false;
let is_space = |f: &MathFragment| {
matches!(f, MathFragment::Space(_) | MathFragment::Spacing(_, _))
matches!(f, MathFragment::Space(_) | MathFragment::Absolute(_, _))
};
let is_line_break_opportunity = |class, next_fragment| match class {
// Don't split when two relations are in a row or when preceding a
@ -314,7 +322,7 @@ impl MathRun {
let mut iter = self.0.into_iter().peekable();
while let Some(fragment) = iter.next() {
if space_is_visible && is_space(&fragment) {
items.push(InlineItem::Space(fragment.width(), true));
items.push(InlineItem::Absolute(fragment.width(), true));
continue;
}
@ -346,7 +354,7 @@ impl MathRun {
space_is_visible = true;
if let Some(f_next) = iter.peek() {
if !is_space(f_next) {
items.push(InlineItem::Space(Abs::zero(), true));
items.push(InlineItem::Absolute(Abs::zero(), true));
}
}
} else {
@ -435,7 +443,7 @@ fn spacing(
let resolve = |v: Em, size_ref: &MathFragment| -> Option<MathFragment> {
let width = size_ref.font_size().map_or(Abs::zero(), |size| v.at(size));
Some(MathFragment::Spacing(width, false))
Some(MathFragment::Absolute(width, false))
};
let script = |f: &MathFragment| f.math_size().is_some_and(|s| s <= MathSize::Script);

View File

@ -174,7 +174,9 @@ impl Packed<InlineElem> {
#[derive(Debug, Clone)]
pub enum InlineItem {
/// Absolute spacing between other items, and whether it is weak.
Space(Abs, bool),
Absolute(Abs, bool),
/// Fractional spacing between other items.
Fractional(Fr),
/// Layouted inline-level content.
Frame(Frame),
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

View File

@ -63,6 +63,30 @@ $#place(dx: 5em)[a] + b$
// Validate that ignorant elements are layouted
#context test(counter("test").get(), (3,))
--- math-spacing-relative ---
// Test relative spacing.
$ A #h(50%) B \
A#block(width: 50%);B \
A #block(width: 50%) B \
A space #h(50%) space B $
--- math-spacing-relative-inline ---
// Test relative spacing in inline math.
#let mtext = text.with(font: "Libertinus Serif")
Hello#h(40%)world \
Hello#box(width: 40%);world \
Hello$#h(40%)$world \
Hello$#box(width: 40%)$world \
$mtext("Hello") #h(40%) mtext("world")$ \
$mtext("Hello")#box(width: 40%);mtext("world")$
Hello #h(40%) world \
Hello #box(width: 40%) world \
Hello $#h(40%)$ world \
Hello $#box(width: 40%)$ world \
$mtext("Hello") #h(40%) space mtext("world")$ \
$mtext("Hello") #box(width: 40%) mtext("world")$
--- issue-1052-math-number-spacing ---
// Test spacing after numbers in math.
$