Initial fix for spacing on decorated math operators (#1023)

This commit is contained in:
Pg Biel 2023-04-28 13:49:02 -03:00 committed by GitHub
parent d5e68c731c
commit 0d8c3254b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 4 deletions

View File

@ -58,6 +58,8 @@ impl LayoutMath for AccentElem {
let base = ctx.layout_fragment(&self.base())?;
ctx.unstyle();
// Preserve class to preserve automatic spacing.
let base_class = base.class().unwrap_or(MathClass::Normal);
let base_attach = match &base {
MathFragment::Glyph(base) => {
attachment(ctx, base.id, base.italics_correction)
@ -93,7 +95,11 @@ impl LayoutMath for AccentElem {
frame.set_baseline(baseline);
frame.push_frame(accent_pos, accent);
frame.push_frame(base_pos, base.into_frame());
ctx.push(FrameFragment::new(ctx, frame).with_base_ascent(base_ascent));
ctx.push(
FrameFragment::new(ctx, frame)
.with_class(base_class)
.with_base_ascent(base_ascent),
);
Ok(())
}

View File

@ -90,7 +90,10 @@ pub struct CancelElem {
impl LayoutMath for CancelElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let mut body = ctx.layout_frame(&self.body())?;
let body = ctx.layout_fragment(&self.body())?;
// Use the same math class as the body, in order to preserve automatic spacing around it.
let body_class = body.class().unwrap_or(MathClass::Special);
let mut body = body.into_frame();
let styles = ctx.styles();
let body_size = body.size();
@ -130,7 +133,7 @@ impl LayoutMath for CancelElem {
body.push_frame(center, second_line);
}
ctx.push(FrameFragment::new(ctx, body));
ctx.push(FrameFragment::new(ctx, body).with_class(body_class));
Ok(())
}

View File

@ -95,6 +95,20 @@ impl MathRow {
self.iter().map(MathFragment::descent).max().unwrap_or_default()
}
pub fn class(&self) -> MathClass {
// Predict the class of the output of 'into_fragment'
if self.0.len() == 1 {
self.0
.first()
.and_then(|fragment| fragment.class())
.unwrap_or(MathClass::Special)
} else {
// FrameFragment::new() (inside 'into_fragment' in this branch) defaults
// to MathClass::Normal for its class.
MathClass::Normal
}
}
pub fn into_frame(self, ctx: &MathContext) -> Frame {
let styles = ctx.styles();
let align = AlignElem::alignment_in(styles).x.resolve(styles);

View File

@ -202,6 +202,7 @@ fn layout(
) -> SourceResult<()> {
let gap = gap.scaled(ctx);
let body = ctx.layout_row(body)?;
let body_class = body.class();
let glyph = GlyphFragment::new(ctx, c, span);
let stretched = glyph.stretch_horizontal(ctx, body.width(), Abs::zero());
@ -226,7 +227,7 @@ fn layout(
}
let frame = stack(ctx, rows, Align::Center, gap, baseline);
ctx.push(FrameFragment::new(ctx, frame));
ctx.push(FrameFragment::new(ctx, frame).with_class(body_class));
Ok(())
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -29,3 +29,12 @@ $a - b ident c quad (mod 2)$
// Test spacing for set comprehension.
#set page(width: auto)
$ { x in RR | x "is natural" and x < 10 } $
---
// Test spacing for operators with decorations and modifiers on them
#set page(width: auto)
$a ident b + c - d => e log 5 op("ln") 6$ \
$a cancel(ident) b overline(+) c arrow(-) d hat(=>) e cancel(log) 5 dot(op("ln")) 6$ \
$a overbrace(ident) b underline(+) c grave(-) d underbracket(=>) e circle(log) 5 caron(op("ln")) 6$ \
\
$a attach(ident, tl: a, tr: b) b attach(limits(+), t: a, b: b) c tilde(-) d breve(=>) e attach(limits(log), t: a, b: b) 5 attach(op("ln"), tr: a, bl: b) 6$