summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-03-12 12:53:50 +0100
committerLaurenz <laurmaedje@gmail.com>2023-03-12 13:20:36 +0100
commitad05ba59256a67f429b71a8aba2cd92ed2cafac7 (patch)
tree019ccf26f7308d907c042624ccbb647f76d3491b /library
parent2720a44b965d29e9c3453c732e38554fdb6413bb (diff)
Spans in math
Diffstat (limited to 'library')
-rw-r--r--library/src/math/accent.rs2
-rw-r--r--library/src/math/ctx.rs10
-rw-r--r--library/src/math/delimited.rs4
-rw-r--r--library/src/math/frac.rs13
-rw-r--r--library/src/math/fragment.rs16
-rw-r--r--library/src/math/matrix.rs26
-rw-r--r--library/src/math/mod.rs2
-rw-r--r--library/src/math/root.rs9
-rw-r--r--library/src/math/stretch.rs5
-rw-r--r--library/src/math/underover.rs47
-rw-r--r--library/src/meta/heading.rs1
11 files changed, 100 insertions, 35 deletions
diff --git a/library/src/math/accent.rs b/library/src/math/accent.rs
index 03caf411..9ef76279 100644
--- a/library/src/math/accent.rs
+++ b/library/src/math/accent.rs
@@ -66,7 +66,7 @@ impl LayoutMath for AccentNode {
// Forcing the accent to be at least as large as the base makes it too
// wide in many case.
let Accent(c) = self.accent();
- let glyph = GlyphFragment::new(ctx, c);
+ let glyph = GlyphFragment::new(ctx, c, self.span());
let short_fall = ACCENT_SHORT_FALL.scaled(ctx);
let variant = glyph.stretch_horizontal(ctx, base.width(), short_fall);
let accent = variant.frame;
diff --git a/library/src/math/ctx.rs b/library/src/math/ctx.rs
index 991d582c..bd44546d 100644
--- a/library/src/math/ctx.rs
+++ b/library/src/math/ctx.rs
@@ -124,13 +124,15 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
.into_frame())
}
- pub fn layout_text(&mut self, text: &str) -> SourceResult<()> {
+ pub fn layout_text(&mut self, node: &TextNode) -> SourceResult<()> {
+ let text = node.text();
+ let span = node.span();
let mut chars = text.chars();
if let Some(glyph) = chars
.next()
.filter(|_| chars.next().is_none())
.map(|c| self.style.styled_char(c))
- .and_then(|c| GlyphFragment::try_new(self, c))
+ .and_then(|c| GlyphFragment::try_new(self, c, span))
{
// A single letter that is available in the math font.
if self.style.size == MathSize::Display
@@ -146,7 +148,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
let mut fragments = vec![];
for c in text.chars() {
let c = self.style.styled_char(c);
- fragments.push(GlyphFragment::new(self, c).into());
+ fragments.push(GlyphFragment::new(self, c, span).into());
}
let frame = MathRow::new(fragments).to_frame(self);
self.push(FrameFragment::new(self, frame));
@@ -158,7 +160,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
style = style.with_italic(false);
}
let text: EcoString = text.chars().map(|c| style.styled_char(c)).collect();
- let frame = self.layout_content(&TextNode::packed(text))?;
+ let frame = self.layout_content(&TextNode::packed(text).spanned(span))?;
self.push(
FrameFragment::new(self, frame)
.with_class(MathClass::Alphabetic)
diff --git a/library/src/math/delimited.rs b/library/src/math/delimited.rs
index 6f468af7..2b9ee5ed 100644
--- a/library/src/math/delimited.rs
+++ b/library/src/math/delimited.rs
@@ -89,7 +89,9 @@ fn scale(
) {
let glyph = match fragment {
MathFragment::Glyph(glyph) => glyph.clone(),
- MathFragment::Variant(variant) => GlyphFragment::new(ctx, variant.c),
+ MathFragment::Variant(variant) => {
+ GlyphFragment::new(ctx, variant.c, variant.span)
+ }
_ => return,
};
diff --git a/library/src/math/frac.rs b/library/src/math/frac.rs
index 0624832a..f670159d 100644
--- a/library/src/math/frac.rs
+++ b/library/src/math/frac.rs
@@ -32,7 +32,7 @@ pub struct FracNode {
impl LayoutMath for FracNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, &self.num(), &self.denom(), false)
+ layout(ctx, &self.num(), &self.denom(), false, self.span())
}
}
@@ -58,7 +58,7 @@ pub struct BinomNode {
impl LayoutMath for BinomNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, &self.upper(), &self.lower(), true)
+ layout(ctx, &self.upper(), &self.lower(), true, self.span())
}
}
@@ -68,6 +68,7 @@ fn layout(
num: &Content,
denom: &Content,
binom: bool,
+ span: Span,
) -> SourceResult<()> {
let short_fall = DELIM_SHORT_FALL.scaled(ctx);
let axis = scaled!(ctx, axis_height);
@@ -121,9 +122,13 @@ fn layout(
frame.push_frame(denom_pos, denom);
if binom {
- ctx.push(GlyphFragment::new(ctx, '(').stretch_vertical(ctx, height, short_fall));
+ ctx.push(
+ GlyphFragment::new(ctx, '(', span).stretch_vertical(ctx, height, short_fall),
+ );
ctx.push(FrameFragment::new(ctx, frame));
- ctx.push(GlyphFragment::new(ctx, ')').stretch_vertical(ctx, height, short_fall));
+ ctx.push(
+ GlyphFragment::new(ctx, ')', span).stretch_vertical(ctx, height, short_fall),
+ );
} else {
frame.push(
line_pos,
diff --git a/library/src/math/fragment.rs b/library/src/math/fragment.rs
index de456b82..87e28555 100644
--- a/library/src/math/fragment.rs
+++ b/library/src/math/fragment.rs
@@ -147,21 +147,22 @@ pub struct GlyphFragment {
pub style: MathStyle,
pub font_size: Abs,
pub class: Option<MathClass>,
+ pub span: Span,
}
impl GlyphFragment {
- pub fn new(ctx: &MathContext, c: char) -> Self {
+ pub fn new(ctx: &MathContext, c: char, span: Span) -> Self {
let id = ctx.ttf.glyph_index(c).unwrap_or_default();
- Self::with_id(ctx, c, id)
+ Self::with_id(ctx, c, id, span)
}
- pub fn try_new(ctx: &MathContext, c: char) -> Option<Self> {
+ pub fn try_new(ctx: &MathContext, c: char, span: Span) -> Option<Self> {
let c = ctx.style.styled_char(c);
let id = ctx.ttf.glyph_index(c)?;
- Some(Self::with_id(ctx, c, id))
+ Some(Self::with_id(ctx, c, id, span))
}
- pub fn with_id(ctx: &MathContext, c: char, id: GlyphId) -> Self {
+ pub fn with_id(ctx: &MathContext, c: char, id: GlyphId, span: Span) -> Self {
let advance = ctx.ttf.glyph_hor_advance(id).unwrap_or_default();
let italics = italics_correction(ctx, id).unwrap_or_default();
let bbox = ctx.ttf.glyph_bounding_box(id).unwrap_or(Rect {
@@ -192,6 +193,7 @@ impl GlyphFragment {
':' => Some(MathClass::Relation),
_ => unicode_math_class::class(c),
},
+ span,
}
}
@@ -208,6 +210,7 @@ impl GlyphFragment {
font_size: self.font_size,
italics_correction: self.italics_correction,
class: self.class,
+ span: self.span,
}
}
@@ -222,7 +225,7 @@ impl GlyphFragment {
c: self.c,
x_advance: Em::from_length(self.width, self.font_size),
x_offset: Em::zero(),
- span: Span::detached(),
+ span: self.span,
offset: 0,
}],
};
@@ -249,6 +252,7 @@ pub struct VariantFragment {
pub style: MathStyle,
pub font_size: Abs,
pub class: Option<MathClass>,
+ pub span: Span,
}
impl Debug for VariantFragment {
diff --git a/library/src/math/matrix.rs b/library/src/math/matrix.rs
index 6dec645c..148d79e8 100644
--- a/library/src/math/matrix.rs
+++ b/library/src/math/matrix.rs
@@ -36,7 +36,13 @@ impl LayoutMath for VecNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let delim = self.delim(ctx.styles());
let frame = layout_vec_body(ctx, &self.children(), Align::Center)?;
- layout_delimiters(ctx, frame, Some(delim.open()), Some(delim.close()))
+ layout_delimiters(
+ ctx,
+ frame,
+ Some(delim.open()),
+ Some(delim.close()),
+ self.span(),
+ )
}
}
@@ -112,7 +118,13 @@ impl LayoutMath for MatNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let delim = self.delim(ctx.styles());
let frame = layout_mat_body(ctx, &self.rows())?;
- layout_delimiters(ctx, frame, Some(delim.open()), Some(delim.close()))
+ layout_delimiters(
+ ctx,
+ frame,
+ Some(delim.open()),
+ Some(delim.close()),
+ self.span(),
+ )
}
}
@@ -152,7 +164,7 @@ impl LayoutMath for CasesNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let delim = self.delim(ctx.styles());
let frame = layout_vec_body(ctx, &self.children(), Align::Left)?;
- layout_delimiters(ctx, frame, Some(delim.open()), None)
+ layout_delimiters(ctx, frame, Some(delim.open()), None, self.span())
}
}
@@ -288,6 +300,7 @@ fn layout_delimiters(
mut frame: Frame,
left: Option<char>,
right: Option<char>,
+ span: Span,
) -> SourceResult<()> {
let axis = scaled!(ctx, axis_height);
let short_fall = DELIM_SHORT_FALL.scaled(ctx);
@@ -296,14 +309,17 @@ fn layout_delimiters(
frame.set_baseline(height / 2.0 + axis);
if let Some(left) = left {
- ctx.push(GlyphFragment::new(ctx, left).stretch_vertical(ctx, target, short_fall));
+ ctx.push(
+ GlyphFragment::new(ctx, left, span).stretch_vertical(ctx, target, short_fall),
+ );
}
ctx.push(FrameFragment::new(ctx, frame));
if let Some(right) = right {
ctx.push(
- GlyphFragment::new(ctx, right).stretch_vertical(ctx, target, short_fall),
+ GlyphFragment::new(ctx, right, span)
+ .stretch_vertical(ctx, target, short_fall),
);
}
diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs
index c11bea79..0cc7f43c 100644
--- a/library/src/math/mod.rs
+++ b/library/src/math/mod.rs
@@ -264,7 +264,7 @@ impl LayoutMath for Content {
}
if let Some(node) = self.to::<TextNode>() {
- ctx.layout_text(&node.text())?;
+ ctx.layout_text(node)?;
return Ok(());
}
diff --git a/library/src/math/root.rs b/library/src/math/root.rs
index cb01e6a1..1ab99b2b 100644
--- a/library/src/math/root.rs
+++ b/library/src/math/root.rs
@@ -18,7 +18,7 @@ pub struct SqrtNode {
impl LayoutMath for SqrtNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, None, &self.radicand())
+ layout(ctx, None, &self.radicand(), self.span())
}
}
@@ -44,7 +44,7 @@ pub struct RootNode {
impl LayoutMath for RootNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, Some(&self.index()), &self.radicand())
+ layout(ctx, Some(&self.index()), &self.radicand(), self.span())
}
}
@@ -55,6 +55,7 @@ fn layout(
ctx: &mut MathContext,
mut index: Option<&Content>,
radicand: &Content,
+ span: Span,
) -> SourceResult<()> {
let gap = scaled!(
ctx,
@@ -80,7 +81,7 @@ fn layout(
frame
})
.unwrap_or_else(|| {
- let glyph = GlyphFragment::new(ctx, '√');
+ let glyph = GlyphFragment::new(ctx, '√', span);
glyph.stretch_vertical(ctx, target, Abs::zero()).frame
});
@@ -145,7 +146,7 @@ fn precomposed(ctx: &MathContext, index: Option<&Content>, target: Abs) -> Optio
};
ctx.ttf.glyph_index(c)?;
- let glyph = GlyphFragment::new(ctx, c);
+ let glyph = GlyphFragment::new(ctx, c, node.span());
let variant = glyph.stretch_vertical(ctx, target, Abs::zero()).frame;
if variant.height() < target {
return None;
diff --git a/library/src/math/stretch.rs b/library/src/math/stretch.rs
index 1c994802..7ba6e5c1 100644
--- a/library/src/math/stretch.rs
+++ b/library/src/math/stretch.rs
@@ -73,7 +73,7 @@ fn stretch_glyph(
// This is either good or the best we've got.
if short_target <= best_advance || construction.assembly.is_none() {
- return GlyphFragment::with_id(ctx, base.c, best_id).to_variant();
+ return GlyphFragment::with_id(ctx, base.c, best_id, base.span).to_variant();
}
// Assemble from parts.
@@ -142,7 +142,7 @@ fn assemble(
advance += ratio * (max_overlap - min_overlap);
}
- let fragment = GlyphFragment::with_id(ctx, base.c, part.glyph_id);
+ let fragment = GlyphFragment::with_id(ctx, base.c, part.glyph_id, base.span);
selected.push((fragment, advance));
}
@@ -181,6 +181,7 @@ fn assemble(
font_size: base.font_size,
italics_correction: Abs::zero(),
class: base.class,
+ span: base.span,
}
}
diff --git a/library/src/math/underover.rs b/library/src/math/underover.rs
index a723ae97..cfbb30b6 100644
--- a/library/src/math/underover.rs
+++ b/library/src/math/underover.rs
@@ -22,7 +22,7 @@ pub struct UnderlineNode {
impl LayoutMath for UnderlineNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, &self.body(), &None, '\u{305}', LINE_GAP, false)
+ layout(ctx, &self.body(), &None, '\u{305}', LINE_GAP, false, self.span())
}
}
@@ -44,7 +44,7 @@ pub struct OverlineNode {
impl LayoutMath for OverlineNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, &self.body(), &None, '\u{332}', LINE_GAP, true)
+ layout(ctx, &self.body(), &None, '\u{332}', LINE_GAP, true, self.span())
}
}
@@ -70,7 +70,15 @@ pub struct UnderbraceNode {
impl LayoutMath for UnderbraceNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, &self.body(), &self.annotation(ctx.styles()), '⏟', BRACE_GAP, false)
+ layout(
+ ctx,
+ &self.body(),
+ &self.annotation(ctx.styles()),
+ '⏟',
+ BRACE_GAP,
+ false,
+ self.span(),
+ )
}
}
@@ -96,7 +104,15 @@ pub struct OverbraceNode {
impl LayoutMath for OverbraceNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, &self.body(), &self.annotation(ctx.styles()), '⏞', BRACE_GAP, true)
+ layout(
+ ctx,
+ &self.body(),
+ &self.annotation(ctx.styles()),
+ '⏞',
+ BRACE_GAP,
+ true,
+ self.span(),
+ )
}
}
@@ -122,7 +138,15 @@ pub struct UnderbracketNode {
impl LayoutMath for UnderbracketNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, &self.body(), &self.annotation(ctx.styles()), '⎵', BRACKET_GAP, false)
+ layout(
+ ctx,
+ &self.body(),
+ &self.annotation(ctx.styles()),
+ '⎵',
+ BRACKET_GAP,
+ false,
+ self.span(),
+ )
}
}
@@ -148,7 +172,15 @@ pub struct OverbracketNode {
impl LayoutMath for OverbracketNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- layout(ctx, &self.body(), &self.annotation(ctx.styles()), '⎴', BRACKET_GAP, true)
+ layout(
+ ctx,
+ &self.body(),
+ &self.annotation(ctx.styles()),
+ '⎴',
+ BRACKET_GAP,
+ true,
+ self.span(),
+ )
}
}
@@ -160,10 +192,11 @@ fn layout(
c: char,
gap: Em,
reverse: bool,
+ span: Span,
) -> SourceResult<()> {
let gap = gap.scaled(ctx);
let body = ctx.layout_row(body)?;
- let glyph = GlyphFragment::new(ctx, c);
+ let glyph = GlyphFragment::new(ctx, c, span);
let stretched = glyph.stretch_horizontal(ctx, body.width(), Abs::zero());
let mut rows = vec![body, stretched.into()];
diff --git a/library/src/meta/heading.rs b/library/src/meta/heading.rs
index e82f80c6..47047927 100644
--- a/library/src/meta/heading.rs
+++ b/library/src/meta/heading.rs
@@ -107,6 +107,7 @@ impl Synthesize for HeadingNode {
let node = self
.clone()
+ .with_level(self.level(styles))
.with_outlined(self.outlined(styles))
.with_numbers(numbering.is_some().then(|| counter.take()))
.with_numbering(numbering)