Ignore accent when positioning superscript

This commit is contained in:
Laurenz 2023-02-02 21:21:04 +01:00
parent 3f85d005bb
commit 255044e04e
5 changed files with 39 additions and 19 deletions

View File

@ -112,13 +112,14 @@ impl LayoutMath for AccentNode {
let size = Size::new(base.width(), accent.height() + gap + base.height()); let size = Size::new(base.width(), accent.height() + gap + base.height());
let accent_pos = Point::with_x(base_attach - accent_attach); let accent_pos = Point::with_x(base_attach - accent_attach);
let base_pos = Point::with_y(accent.height() + gap); let base_pos = Point::with_y(accent.height() + gap);
let base_ascent = base.ascent();
let baseline = base_pos.y + base.ascent(); let baseline = base_pos.y + base.ascent();
let mut frame = Frame::new(size); let mut frame = Frame::new(size);
frame.set_baseline(baseline); frame.set_baseline(baseline);
frame.push_frame(accent_pos, accent); frame.push_frame(accent_pos, accent);
frame.push_frame(base_pos, base.to_frame(ctx)); frame.push_frame(base_pos, base.to_frame(ctx));
ctx.push(FrameFragment::new(ctx, frame)); ctx.push(FrameFragment::new(ctx, frame).with_base_ascent(base_ascent));
Ok(()) Ok(())
} }

View File

@ -51,12 +51,15 @@ impl LayoutMath for AttachNode {
let base = ctx.layout_fragment(&self.base)?; let base = ctx.layout_fragment(&self.base)?;
ctx.style(ctx.style.for_subscript()); ctx.style(ctx.style.for_subscript());
let top = self.top.as_ref().map(|node| ctx.layout_frame(node)).transpose()?; let top = self.top.as_ref().map(|node| ctx.layout_fragment(node)).transpose()?;
ctx.unstyle(); ctx.unstyle();
ctx.style(ctx.style.for_superscript()); ctx.style(ctx.style.for_superscript());
let bottom = let bottom = self
self.bottom.as_ref().map(|node| ctx.layout_frame(node)).transpose()?; .bottom
.as_ref()
.map(|node| ctx.layout_fragment(node))
.transpose()?;
ctx.unstyle(); ctx.unstyle();
let render_limits = self.base.is::<LimitsNode>() let render_limits = self.base.is::<LimitsNode>()
@ -145,8 +148,8 @@ impl LayoutMath for LimitsNode {
fn scripts( fn scripts(
ctx: &mut MathContext, ctx: &mut MathContext,
base: MathFragment, base: MathFragment,
sup: Option<Frame>, sup: Option<MathFragment>,
sub: Option<Frame>, sub: Option<MathFragment>,
) -> SourceResult<()> { ) -> SourceResult<()> {
let sup_shift_up = if ctx.style.cramped { let sup_shift_up = if ctx.style.cramped {
scaled!(ctx, superscript_shift_up_cramped) scaled!(ctx, superscript_shift_up_cramped)
@ -166,8 +169,13 @@ fn scripts(
let mut shift_down = Abs::zero(); let mut shift_down = Abs::zero();
if let Some(sup) = &sup { if let Some(sup) = &sup {
let ascent = match &base {
MathFragment::Frame(frame) => frame.base_ascent,
_ => base.ascent(),
};
shift_up = sup_shift_up shift_up = sup_shift_up
.max(base.ascent() - sup_drop_max) .max(ascent - sup_drop_max)
.max(sup_bottom_min + sup.descent()); .max(sup_bottom_min + sup.descent());
} }
@ -222,13 +230,13 @@ fn scripts(
if let Some(sup) = sup { if let Some(sup) = sup {
let sup_pos = let sup_pos =
Point::new(sup_delta + base_width, ascent - shift_up - sup.ascent()); Point::new(sup_delta + base_width, ascent - shift_up - sup.ascent());
frame.push_frame(sup_pos, sup); frame.push_frame(sup_pos, sup.to_frame(ctx));
} }
if let Some(sub) = sub { if let Some(sub) = sub {
let sub_pos = let sub_pos =
Point::new(sub_delta + base_width, ascent + shift_down - sub.ascent()); Point::new(sub_delta + base_width, ascent + shift_down - sub.ascent());
frame.push_frame(sub_pos, sub); frame.push_frame(sub_pos, sub.to_frame(ctx));
} }
ctx.push(FrameFragment::new(ctx, frame).with_class(class)); ctx.push(FrameFragment::new(ctx, frame).with_class(class));
@ -240,8 +248,8 @@ fn scripts(
fn limits( fn limits(
ctx: &mut MathContext, ctx: &mut MathContext,
base: MathFragment, base: MathFragment,
top: Option<Frame>, top: Option<MathFragment>,
bottom: Option<Frame>, bottom: Option<MathFragment>,
) -> SourceResult<()> { ) -> SourceResult<()> {
let upper_gap_min = scaled!(ctx, upper_limit_gap_min); let upper_gap_min = scaled!(ctx, upper_limit_gap_min);
let upper_rise_min = scaled!(ctx, upper_limit_baseline_rise_min); let upper_rise_min = scaled!(ctx, upper_limit_baseline_rise_min);
@ -275,13 +283,13 @@ fn limits(
if let Some(top) = top { if let Some(top) = top {
let top_pos = Point::with_x((width - top.width()) / 2.0 + delta); let top_pos = Point::with_x((width - top.width()) / 2.0 + delta);
frame.push_frame(top_pos, top); frame.push_frame(top_pos, top.to_frame(ctx));
} }
if let Some(bottom) = bottom { if let Some(bottom) = bottom {
let bottom_pos = let bottom_pos =
Point::new((width - bottom.width()) / 2.0 - delta, height - bottom.height()); Point::new((width - bottom.width()) / 2.0 - delta, height - bottom.height());
frame.push_frame(bottom_pos, bottom); frame.push_frame(bottom_pos, bottom.to_frame(ctx));
} }
ctx.push(FrameFragment::new(ctx, frame).with_class(class)); ctx.push(FrameFragment::new(ctx, frame).with_class(class));

View File

@ -218,7 +218,7 @@ impl GlyphFragment {
glyphs: vec![Glyph { glyphs: vec![Glyph {
id: self.id.0, id: self.id.0,
c: self.c, c: self.c,
x_advance: Em::from_length(self.width, ctx.size), x_advance: Em::from_length(self.width, self.font_size),
x_offset: Em::zero(), x_offset: Em::zero(),
}], }],
}; };
@ -256,22 +256,25 @@ impl Debug for VariantFragment {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct FrameFragment { pub struct FrameFragment {
pub frame: Frame, pub frame: Frame,
pub limits: bool,
pub spaced: bool,
pub style: MathStyle, pub style: MathStyle,
pub font_size: Abs, pub font_size: Abs,
pub class: MathClass, pub class: MathClass,
pub limits: bool,
pub spaced: bool,
pub base_ascent: Abs,
} }
impl FrameFragment { impl FrameFragment {
pub fn new(ctx: &MathContext, frame: Frame) -> Self { pub fn new(ctx: &MathContext, frame: Frame) -> Self {
let base_ascent = frame.ascent();
Self { Self {
frame, frame,
limits: false,
spaced: false,
font_size: ctx.size, font_size: ctx.size,
style: ctx.style, style: ctx.style,
class: MathClass::Normal, class: MathClass::Normal,
limits: false,
spaced: false,
base_ascent,
} }
} }
@ -286,6 +289,10 @@ impl FrameFragment {
pub fn with_spaced(self, spaced: bool) -> Self { pub fn with_spaced(self, spaced: bool) -> Self {
Self { spaced, ..self } Self { spaced, ..self }
} }
pub fn with_base_ascent(self, base_ascent: Abs) -> Self {
Self { base_ascent, ..self }
}
} }
/// Look up the italics correction for a glyph. /// Look up the italics correction for a glyph.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -2,7 +2,7 @@
--- ---
// Test function call. // Test function call.
$grave(a), acute(b), hat(f), tilde(§), macron(ä), diaer(a), ä, \ $grave(a), acute(b), hat(f), tilde(§), macron(ä), diaer(a), ä \
breve(\&), dot(!), circle(a), caron(@), arrow(Z), arrow.l(Z)$ breve(\&), dot(!), circle(a), caron(@), arrow(Z), arrow.l(Z)$
--- ---
@ -17,6 +17,10 @@ $sqrt(tilde(T)) + hat(f)/hat(g)$
// Test wide base. // Test wide base.
$arrow("ABC" + d), tilde(sum)$ $arrow("ABC" + d), tilde(sum)$
---
// Test effect of accent on superscript.
$A^x != hat(A)^x != hat(hat(A))^x$
--- ---
// Test high base. // Test high base.
$ tilde(integral), tilde(integral)_a^b, tilde(integral_a^b) $ $ tilde(integral), tilde(integral)_a^b, tilde(integral_a^b) $