summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--library/src/math/accent.rs2
-rw-r--r--library/src/math/align.rs5
-rw-r--r--library/src/math/attach.rs4
-rw-r--r--library/src/math/ctx.rs60
-rw-r--r--library/src/math/delimited.rs9
-rw-r--r--library/src/math/frac.rs4
-rw-r--r--library/src/math/fragment.rs70
-rw-r--r--library/src/math/matrix.rs2
-rw-r--r--library/src/math/mod.rs6
-rw-r--r--library/src/math/op.rs4
-rw-r--r--library/src/math/root.rs2
-rw-r--r--library/src/math/row.rs137
-rw-r--r--library/src/math/spacing.rs56
-rw-r--r--library/src/math/stretch.rs2
-rw-r--r--library/src/math/style.rs2
-rw-r--r--library/src/math/underover.rs3
-rw-r--r--tests/ref/math/delimited.pngbin10723 -> 10731 bytes
-rw-r--r--tests/ref/math/multiline.pngbin7956 -> 7949 bytes
-rw-r--r--tests/ref/math/op.pngbin6019 -> 6028 bytes
-rw-r--r--tests/ref/math/spacing.pngbin11600 -> 11600 bytes
-rw-r--r--tests/ref/math/style.pngbin23053 -> 23028 bytes
21 files changed, 217 insertions, 151 deletions
diff --git a/library/src/math/accent.rs b/library/src/math/accent.rs
index 8cae4268..80993925 100644
--- a/library/src/math/accent.rs
+++ b/library/src/math/accent.rs
@@ -118,7 +118,7 @@ impl LayoutMath for AccentNode {
frame.set_baseline(baseline);
frame.push_frame(accent_pos, accent);
frame.push_frame(base_pos, base.to_frame(ctx));
- ctx.push(frame);
+ ctx.push(FrameFragment::new(ctx, frame));
Ok(())
}
diff --git a/library/src/math/align.rs b/library/src/math/align.rs
index 82b461e9..e8a9c14a 100644
--- a/library/src/math/align.rs
+++ b/library/src/math/align.rs
@@ -29,8 +29,7 @@ pub(super) fn alignments(rows: &[MathRow]) -> Vec<Abs> {
let count = rows
.iter()
.map(|row| {
- row.0
- .iter()
+ row.iter()
.filter(|fragment| matches!(fragment, MathFragment::Align))
.count()
})
@@ -42,7 +41,7 @@ pub(super) fn alignments(rows: &[MathRow]) -> Vec<Abs> {
for row in rows {
let mut x = Abs::zero();
let mut i = 0;
- for fragment in &row.0 {
+ for fragment in row.iter() {
if matches!(fragment, MathFragment::Align) {
if i < current {
x = points[i];
diff --git a/library/src/math/attach.rs b/library/src/math/attach.rs
index 110ea4b7..8a1644be 100644
--- a/library/src/math/attach.rs
+++ b/library/src/math/attach.rs
@@ -231,7 +231,7 @@ fn scripts(
frame.push_frame(sub_pos, sub);
}
- ctx.push(FrameFragment::new(frame).with_class(class));
+ ctx.push(FrameFragment::new(ctx, frame).with_class(class));
Ok(())
}
@@ -284,7 +284,7 @@ fn limits(
frame.push_frame(bottom_pos, bottom);
}
- ctx.push(FrameFragment::new(frame).with_class(class));
+ ctx.push(FrameFragment::new(ctx, frame).with_class(class));
Ok(())
}
diff --git a/library/src/math/ctx.rs b/library/src/math/ctx.rs
index d682746e..4f390817 100644
--- a/library/src/math/ctx.rs
+++ b/library/src/math/ctx.rs
@@ -31,7 +31,7 @@ pub struct MathContext<'a, 'b, 'v> {
pub table: ttf_parser::math::Table<'a>,
pub constants: ttf_parser::math::Constants<'a>,
pub space_width: Em,
- pub row: MathRow,
+ pub fragments: Vec<MathFragment>,
pub map: StyleMap,
pub style: MathStyle,
pub size: Abs,
@@ -69,7 +69,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
table,
constants,
space_width,
- row: MathRow::new(),
+ fragments: vec![],
map: StyleMap::new(),
style: MathStyle {
variant: MathVariant::Serif,
@@ -88,45 +88,45 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
}
pub fn push(&mut self, fragment: impl Into<MathFragment>) {
- self.row.push(self.size, self.space_width, self.style, fragment);
+ self.fragments.push(fragment.into());
}
- pub fn extend(&mut self, row: MathRow) {
- let mut iter = row.0.into_iter();
- if let Some(first) = iter.next() {
- self.push(first);
- }
- self.row.0.extend(iter);
- }
-
- pub fn layout_non_math(&mut self, content: &Content) -> SourceResult<Frame> {
- Ok(content
- .layout(&mut self.vt, self.outer.chain(&self.map), self.regions)?
- .into_frame())
+ pub fn extend(&mut self, fragments: Vec<MathFragment>) {
+ self.fragments.extend(fragments);
}
pub fn layout_fragment(
&mut self,
node: &dyn LayoutMath,
) -> SourceResult<MathFragment> {
- let row = self.layout_row(node)?;
- Ok(if row.0.len() == 1 {
- row.0.into_iter().next().unwrap()
- } else {
- row.to_frame(self).into()
- })
+ let row = self.layout_fragments(node)?;
+ Ok(MathRow::new(row).to_fragment(self))
}
- pub fn layout_row(&mut self, node: &dyn LayoutMath) -> SourceResult<MathRow> {
- let prev = std::mem::take(&mut self.row);
+ pub fn layout_fragments(
+ &mut self,
+ node: &dyn LayoutMath,
+ ) -> SourceResult<Vec<MathFragment>> {
+ let prev = std::mem::take(&mut self.fragments);
node.layout_math(self)?;
- Ok(std::mem::replace(&mut self.row, prev))
+ Ok(std::mem::replace(&mut self.fragments, prev))
+ }
+
+ pub fn layout_row(&mut self, node: &dyn LayoutMath) -> SourceResult<MathRow> {
+ let fragments = self.layout_fragments(node)?;
+ Ok(MathRow::new(fragments))
}
pub fn layout_frame(&mut self, node: &dyn LayoutMath) -> SourceResult<Frame> {
Ok(self.layout_fragment(node)?.to_frame(self))
}
+ pub fn layout_content(&mut self, content: &Content) -> SourceResult<Frame> {
+ Ok(content
+ .layout(&mut self.vt, self.outer.chain(&self.map), self.regions)?
+ .into_frame())
+ }
+
pub fn layout_text(&mut self, text: &str) -> SourceResult<()> {
let mut chars = text.chars();
if let Some(glyph) = chars
@@ -146,13 +146,13 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
}
} else if text.chars().all(|c| c.is_ascii_digit()) {
// Numbers aren't that difficult.
- let mut vec = vec![];
+ let mut fragments = vec![];
for c in text.chars() {
let c = self.style.styled_char(c);
- vec.push(GlyphFragment::new(self, c).into());
+ fragments.push(GlyphFragment::new(self, c).into());
}
- let frame = MathRow(vec).to_frame(self);
- self.push(frame);
+ let frame = MathRow::new(fragments).to_frame(self);
+ self.push(FrameFragment::new(self, frame));
} else {
// Anything else is handled by Typst's standard text layout.
let spaced = text.graphemes(true).count() > 1;
@@ -161,9 +161,9 @@ 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_non_math(&TextNode::packed(text))?;
+ let frame = self.layout_content(&TextNode::packed(text))?;
self.push(
- FrameFragment::new(frame)
+ FrameFragment::new(self, frame)
.with_class(MathClass::Alphabetic)
.with_spaced(spaced),
);
diff --git a/library/src/math/delimited.rs b/library/src/math/delimited.rs
index cdd5718c..b69e4c39 100644
--- a/library/src/math/delimited.rs
+++ b/library/src/math/delimited.rs
@@ -60,10 +60,9 @@ impl LayoutMath for LrNode {
}
}
- let mut row = ctx.layout_row(body)?;
+ let mut fragments = ctx.layout_fragments(body)?;
let axis = scaled!(ctx, axis_height);
- let max_extent = row
- .0
+ let max_extent = fragments
.iter()
.map(|fragment| (fragment.ascent() - axis).max(fragment.descent() + axis))
.max()
@@ -75,7 +74,7 @@ impl LayoutMath for LrNode {
.resolve(ctx.styles())
.relative_to(2.0 * max_extent);
- match row.0.as_mut_slice() {
+ match fragments.as_mut_slice() {
[one] => scale(ctx, one, height, None),
[first, .., last] => {
scale(ctx, first, height, Some(MathClass::Opening));
@@ -84,7 +83,7 @@ impl LayoutMath for LrNode {
_ => {}
}
- ctx.extend(row);
+ ctx.extend(fragments);
Ok(())
}
diff --git a/library/src/math/frac.rs b/library/src/math/frac.rs
index 9f7fb9d0..283686c8 100644
--- a/library/src/math/frac.rs
+++ b/library/src/math/frac.rs
@@ -153,7 +153,7 @@ fn layout(
if binom {
ctx.push(GlyphFragment::new(ctx, '(').stretch_vertical(ctx, height, short_fall));
- ctx.push(frame);
+ ctx.push(FrameFragment::new(ctx, frame));
ctx.push(GlyphFragment::new(ctx, ')').stretch_vertical(ctx, height, short_fall));
} else {
frame.push(
@@ -165,7 +165,7 @@ fn layout(
}),
),
);
- ctx.push(frame);
+ ctx.push(FrameFragment::new(ctx, frame));
}
Ok(())
diff --git a/library/src/math/fragment.rs b/library/src/math/fragment.rs
index bef3f578..f1c374a1 100644
--- a/library/src/math/fragment.rs
+++ b/library/src/math/fragment.rs
@@ -6,7 +6,7 @@ pub enum MathFragment {
Variant(VariantFragment),
Frame(FrameFragment),
Spacing(Abs),
- Space,
+ Space(Abs),
Linebreak,
Align,
}
@@ -22,6 +22,7 @@ impl MathFragment {
Self::Variant(variant) => variant.frame.width(),
Self::Frame(fragment) => fragment.frame.width(),
Self::Spacing(amount) => *amount,
+ Self::Space(amount) => *amount,
_ => Abs::zero(),
}
}
@@ -62,6 +63,24 @@ impl MathFragment {
}
}
+ pub fn style(&self) -> Option<MathStyle> {
+ match self {
+ Self::Glyph(glyph) => Some(glyph.style),
+ Self::Variant(variant) => Some(variant.style),
+ Self::Frame(fragment) => Some(fragment.style),
+ _ => None,
+ }
+ }
+
+ pub fn font_size(&self) -> Option<Abs> {
+ match self {
+ Self::Glyph(glyph) => Some(glyph.font_size),
+ Self::Variant(variant) => Some(variant.font_size),
+ Self::Frame(fragment) => Some(fragment.font_size),
+ _ => None,
+ }
+ }
+
pub fn set_class(&mut self, class: MathClass) {
match self {
Self::Glyph(glyph) => glyph.class = Some(class),
@@ -71,8 +90,11 @@ impl MathFragment {
}
}
- pub fn participating(&self) -> bool {
- !matches!(self, Self::Space | Self::Spacing(_) | Self::Align)
+ pub fn is_spaced(&self) -> bool {
+ match self {
+ MathFragment::Frame(frame) => frame.spaced,
+ _ => self.class() == Some(MathClass::Fence),
+ }
}
pub fn italics_correction(&self) -> Abs {
@@ -111,23 +133,18 @@ impl From<FrameFragment> for MathFragment {
}
}
-impl From<Frame> for MathFragment {
- fn from(frame: Frame) -> Self {
- Self::Frame(FrameFragment::new(frame))
- }
-}
-
-#[derive(Debug, Clone, Copy)]
+#[derive(Clone, Copy)]
pub struct GlyphFragment {
pub id: GlyphId,
pub c: char,
pub lang: Lang,
pub fill: Paint,
- pub font_size: Abs,
pub width: Abs,
pub ascent: Abs,
pub descent: Abs,
pub italics_correction: Abs,
+ pub style: MathStyle,
+ pub font_size: Abs,
pub class: Option<MathClass>,
}
@@ -163,6 +180,7 @@ impl GlyphFragment {
c,
lang: ctx.styles().get(TextNode::LANG),
fill: ctx.styles().get(TextNode::FILL),
+ style: ctx.style,
font_size: ctx.size,
width,
ascent: bbox.y_max.scaled(ctx),
@@ -184,6 +202,8 @@ impl GlyphFragment {
c: self.c,
id: Some(self.id),
frame: self.to_frame(ctx),
+ style: self.style,
+ font_size: self.font_size,
italics_correction: self.italics_correction,
class: self.class,
}
@@ -210,30 +230,48 @@ impl GlyphFragment {
}
}
-#[derive(Debug, Clone)]
+impl Debug for GlyphFragment {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ write!(f, "GlyphFragment({:?})", self.c)
+ }
+}
+
+#[derive(Clone)]
pub struct VariantFragment {
pub c: char,
pub id: Option<GlyphId>,
- pub frame: Frame,
pub italics_correction: Abs,
+ pub frame: Frame,
+ pub style: MathStyle,
+ pub font_size: Abs,
pub class: Option<MathClass>,
}
+impl Debug for VariantFragment {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ write!(f, "VariantFragment({:?})", self.c)
+ }
+}
+
#[derive(Debug, Clone)]
pub struct FrameFragment {
pub frame: Frame,
- pub class: MathClass,
pub limits: bool,
pub spaced: bool,
+ pub style: MathStyle,
+ pub font_size: Abs,
+ pub class: MathClass,
}
impl FrameFragment {
- pub fn new(frame: Frame) -> Self {
+ pub fn new(ctx: &MathContext, frame: Frame) -> Self {
Self {
frame,
- class: MathClass::Normal,
limits: false,
spaced: false,
+ font_size: ctx.size,
+ style: ctx.style,
+ class: MathClass::Normal,
}
}
diff --git a/library/src/math/matrix.rs b/library/src/math/matrix.rs
index e5ae6a1d..c47f2d5e 100644
--- a/library/src/math/matrix.rs
+++ b/library/src/math/matrix.rs
@@ -307,7 +307,7 @@ fn layout_delimiters(
ctx.push(GlyphFragment::new(ctx, left).stretch_vertical(ctx, target, short_fall));
}
- ctx.push(frame);
+ ctx.push(FrameFragment::new(ctx, frame));
if let Some(right) = right {
ctx.push(
diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs
index 4e60faca..656fc2e0 100644
--- a/library/src/math/mod.rs
+++ b/library/src/math/mod.rs
@@ -261,7 +261,7 @@ impl LayoutMath for Content {
}
if self.is::<SpaceNode>() {
- ctx.push(MathFragment::Space);
+ ctx.push(MathFragment::Space(ctx.space_width.scaled(ctx)));
return Ok(());
}
@@ -288,8 +288,8 @@ impl LayoutMath for Content {
return node.layout_math(ctx);
}
- let frame = ctx.layout_non_math(self)?;
- ctx.push(FrameFragment::new(frame).with_spaced(true));
+ let frame = ctx.layout_content(self)?;
+ ctx.push(FrameFragment::new(ctx, frame).with_spaced(true));
Ok(())
}
diff --git a/library/src/math/op.rs b/library/src/math/op.rs
index 6e52cea5..8cc007ea 100644
--- a/library/src/math/op.rs
+++ b/library/src/math/op.rs
@@ -38,9 +38,9 @@ impl OpNode {
impl LayoutMath for OpNode {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
- let frame = ctx.layout_non_math(&TextNode(self.text.clone()).pack())?;
+ let frame = ctx.layout_content(&TextNode(self.text.clone()).pack())?;
ctx.push(
- FrameFragment::new(frame)
+ FrameFragment::new(ctx, frame)
.with_class(MathClass::Large)
.with_limits(self.limits),
);
diff --git a/library/src/math/root.rs b/library/src/math/root.rs
index 2d27bb11..e1c8d987 100644
--- a/library/src/math/root.rs
+++ b/library/src/math/root.rs
@@ -158,7 +158,7 @@ fn layout(
);
frame.push_frame(radicand_pos, radicand);
- ctx.push(frame);
+ ctx.push(FrameFragment::new(ctx, frame));
Ok(())
}
diff --git a/library/src/math/row.rs b/library/src/math/row.rs
index 41136a9e..ecd37f46 100644
--- a/library/src/math/row.rs
+++ b/library/src/math/row.rs
@@ -5,55 +5,55 @@ use super::*;
pub const TIGHT_LEADING: Em = Em::new(0.25);
#[derive(Debug, Default, Clone)]
-pub struct MathRow(pub Vec<MathFragment>);
+pub struct MathRow(Vec<MathFragment>);
impl MathRow {
- pub fn new() -> Self {
- Self(vec![])
- }
-
- pub fn width(&self) -> Abs {
- self.0.iter().map(|fragment| fragment.width()).sum()
- }
-
- pub fn height(&self) -> Abs {
- self.ascent() + self.descent()
- }
-
- pub fn ascent(&self) -> Abs {
- self.0.iter().map(MathFragment::ascent).max().unwrap_or_default()
- }
+ pub fn new(fragments: Vec<MathFragment>) -> Self {
+ let mut iter = fragments.into_iter().peekable();
+ let mut last: Option<usize> = None;
+ let mut space: Option<MathFragment> = None;
+ let mut resolved: Vec<MathFragment> = vec![];
+
+ while let Some(mut fragment) = iter.next() {
+ match fragment {
+ // Keep space only if supported by spaced fragments.
+ MathFragment::Space(_) => {
+ if last.is_some() {
+ space = Some(fragment);
+ }
+ continue;
+ }
- pub fn descent(&self) -> Abs {
- self.0.iter().map(MathFragment::descent).max().unwrap_or_default()
- }
+ // Explicit spacing disables automatic spacing.
+ MathFragment::Spacing(_) => {
+ last = None;
+ space = None;
+ resolved.push(fragment);
+ continue;
+ }
- pub fn push(
- &mut self,
- font_size: Abs,
- space_width: Em,
- style: MathStyle,
- fragment: impl Into<MathFragment>,
- ) {
- let mut fragment = fragment.into();
- if !fragment.participating() {
- self.0.push(fragment);
- return;
- }
+ // Alignment points are resolved later.
+ MathFragment::Align => {
+ resolved.push(fragment);
+ continue;
+ }
- let mut space = false;
- for (i, prev) in self.0.iter().enumerate().rev() {
- if !prev.participating() {
- space |= matches!(prev, MathFragment::Space);
- if matches!(prev, MathFragment::Spacing(_)) {
- break;
+ // New line, new things.
+ MathFragment::Linebreak => {
+ resolved.push(fragment);
+ space = None;
+ last = None;
+ continue;
}
- continue;
+
+ _ => {}
}
- if fragment.class() == Some(MathClass::Vary) {
- if matches!(
- prev.class(),
+ // Convert variable operators into binary operators if something
+ // precedes them.
+ if fragment.class() == Some(MathClass::Vary)
+ && matches!(
+ last.and_then(|i| resolved[i].class()),
Some(
MathClass::Normal
| MathClass::Alphabetic
@@ -62,22 +62,43 @@ impl MathRow {
| MathClass::Fence
| MathClass::Relation
)
- ) {
- fragment.set_class(MathClass::Binary);
- }
+ )
+ {
+ fragment.set_class(MathClass::Binary);
}
- let mut amount = Abs::zero();
- amount += spacing(prev, &fragment, style, space, space_width).at(font_size);
-
- if !amount.is_zero() {
- self.0.insert(i + 1, MathFragment::Spacing(amount));
+ // Insert spacing between the last and this item.
+ if let Some(i) = last {
+ if let Some(s) = spacing(&resolved[i], space.take(), &fragment) {
+ resolved.insert(i + 1, s);
+ }
}
- break;
+ last = Some(resolved.len());
+ resolved.push(fragment);
}
- self.0.push(fragment);
+ Self(resolved)
+ }
+
+ pub fn iter(&self) -> std::slice::Iter<'_, MathFragment> {
+ self.0.iter()
+ }
+
+ pub fn width(&self) -> Abs {
+ self.iter().map(MathFragment::width).sum()
+ }
+
+ pub fn height(&self) -> Abs {
+ self.ascent() + self.descent()
+ }
+
+ pub fn ascent(&self) -> Abs {
+ self.iter().map(MathFragment::ascent).max().unwrap_or_default()
+ }
+
+ pub fn descent(&self) -> Abs {
+ self.iter().map(MathFragment::descent).max().unwrap_or_default()
}
pub fn to_frame(self, ctx: &MathContext) -> Frame {
@@ -86,14 +107,22 @@ impl MathRow {
self.to_aligned_frame(ctx, &[], align)
}
+ pub fn to_fragment(self, ctx: &MathContext) -> MathFragment {
+ if self.0.len() == 1 {
+ self.0.into_iter().next().unwrap()
+ } else {
+ FrameFragment::new(ctx, self.to_frame(ctx)).into()
+ }
+ }
+
pub fn to_aligned_frame(
mut self,
ctx: &MathContext,
points: &[Abs],
align: Align,
) -> Frame {
- if self.0.iter().any(|frag| matches!(frag, MathFragment::Linebreak)) {
- let fragments = std::mem::take(&mut self.0);
+ if self.iter().any(|frag| matches!(frag, MathFragment::Linebreak)) {
+ let fragments: Vec<_> = std::mem::take(&mut self.0);
let leading = if ctx.style.size >= MathSize::Text {
ctx.styles().get(ParNode::LEADING)
} else {
@@ -140,7 +169,7 @@ impl MathRow {
if let (Some(&first), Align::Center) = (points.first(), align) {
let mut offset = first;
- for fragment in &self.0 {
+ for fragment in self.iter() {
offset -= fragment.width();
if matches!(fragment, MathFragment::Align) {
x = offset;
diff --git a/library/src/math/spacing.rs b/library/src/math/spacing.rs
index fad1c863..17267238 100644
--- a/library/src/math/spacing.rs
+++ b/library/src/math/spacing.rs
@@ -1,6 +1,5 @@
use super::*;
-pub(super) const ZERO: Em = Em::zero();
pub(super) const THIN: Em = Em::new(1.0 / 6.0);
pub(super) const MEDIUM: Em = Em::new(2.0 / 9.0);
pub(super) const THICK: Em = Em::new(5.0 / 18.0);
@@ -14,49 +13,48 @@ pub(super) fn define(math: &mut Scope) {
math.define("quad", HNode::strong(QUAD).pack());
}
-/// Determine the spacing between two fragments in a given style.
+/// Create the spacing between two fragments in a given style.
pub(super) fn spacing(
- left: &MathFragment,
- right: &MathFragment,
- style: MathStyle,
- space: bool,
- space_width: Em,
-) -> Em {
+ l: &MathFragment,
+ space: Option<MathFragment>,
+ r: &MathFragment,
+) -> Option<MathFragment> {
use MathClass::*;
- let script = style.size <= MathSize::Script;
- let class = |frag: &MathFragment| frag.class().unwrap_or(Special);
- match (class(left), class(right)) {
+
+ let class = |f: &MathFragment| f.class().unwrap_or(Special);
+ let resolve = |v: Em, f: &MathFragment| {
+ Some(MathFragment::Spacing(f.font_size().map_or(Abs::zero(), |size| v.at(size))))
+ };
+ let script =
+ |f: &MathFragment| f.style().map_or(false, |s| s.size <= MathSize::Script);
+
+ match (class(l), class(r)) {
// No spacing before punctuation; thin spacing after punctuation, unless
// in script size.
- (_, Punctuation) => ZERO,
- (Punctuation, _) if !script => THIN,
+ (_, Punctuation) => None,
+ (Punctuation, _) if !script(l) => resolve(THIN, l),
// No spacing after opening delimiters and before closing delimiters.
- (Opening, _) | (_, Closing) => ZERO,
+ (Opening, _) | (_, Closing) => None,
// Thick spacing around relations, unless followed by a another relation
// or in script size.
- (Relation, Relation) => ZERO,
- (Relation, _) | (_, Relation) if !script => THICK,
+ (Relation, Relation) => None,
+ (Relation, _) if !script(l) => resolve(THICK, l),
+ (_, Relation) if !script(r) => resolve(THICK, r),
// Medium spacing around binary operators, unless in script size.
- (Binary, _) | (_, Binary) if !script => MEDIUM,
+ (Binary, _) if !script(l) => resolve(MEDIUM, l),
+ (_, Binary) if !script(r) => resolve(MEDIUM, r),
// Thin spacing around large operators, unless next to a delimiter.
- (Large, Opening | Fence) | (Closing | Fence, Large) => ZERO,
- (Large, _) | (_, Large) => THIN,
+ (Large, Opening | Fence) | (Closing | Fence, Large) => None,
+ (Large, _) => resolve(THIN, l),
+ (_, Large) => resolve(THIN, r),
// Spacing around spaced frames.
- _ if space && (is_spaced(left) || is_spaced(right)) => space_width,
-
- _ => ZERO,
- }
-}
+ _ if (l.is_spaced() || r.is_spaced()) => space,
-/// Whether this fragment should react to adjacent spaces.
-fn is_spaced(fragment: &MathFragment) -> bool {
- match fragment {
- MathFragment::Frame(frame) => frame.spaced,
- _ => fragment.class() == Some(MathClass::Fence),
+ _ => None,
}
}
diff --git a/library/src/math/stretch.rs b/library/src/math/stretch.rs
index aee226d1..d308975d 100644
--- a/library/src/math/stretch.rs
+++ b/library/src/math/stretch.rs
@@ -177,6 +177,8 @@ fn assemble(
c: base.c,
id: None,
frame,
+ style: base.style,
+ font_size: base.font_size,
italics_correction: Abs::zero(),
class: base.class,
}
diff --git a/library/src/math/style.rs b/library/src/math/style.rs
index da2e2313..9ae77346 100644
--- a/library/src/math/style.rs
+++ b/library/src/math/style.rs
@@ -313,7 +313,7 @@ impl LayoutMath for BbNode {
}
}
-/// The style in a formula.
+/// Text properties in a formula.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct MathStyle {
/// The style variant to select.
diff --git a/library/src/math/underover.rs b/library/src/math/underover.rs
index 3a47059c..a1c27e59 100644
--- a/library/src/math/underover.rs
+++ b/library/src/math/underover.rs
@@ -270,7 +270,8 @@ fn layout(
baseline = rows.len() - 1;
}
- ctx.push(stack(ctx, rows, Align::Center, gap, baseline));
+ let frame = stack(ctx, rows, Align::Center, gap, baseline);
+ ctx.push(FrameFragment::new(ctx, frame));
Ok(())
}
diff --git a/tests/ref/math/delimited.png b/tests/ref/math/delimited.png
index ea3ab6c2..29a8c915 100644
--- a/tests/ref/math/delimited.png
+++ b/tests/ref/math/delimited.png
Binary files differ
diff --git a/tests/ref/math/multiline.png b/tests/ref/math/multiline.png
index d8b1d847..1433ba30 100644
--- a/tests/ref/math/multiline.png
+++ b/tests/ref/math/multiline.png
Binary files differ
diff --git a/tests/ref/math/op.png b/tests/ref/math/op.png
index 870250b7..bb191606 100644
--- a/tests/ref/math/op.png
+++ b/tests/ref/math/op.png
Binary files differ
diff --git a/tests/ref/math/spacing.png b/tests/ref/math/spacing.png
index fcd0d660..38d21026 100644
--- a/tests/ref/math/spacing.png
+++ b/tests/ref/math/spacing.png
Binary files differ
diff --git a/tests/ref/math/style.png b/tests/ref/math/style.png
index 04a28208..78cfe9b1 100644
--- a/tests/ref/math/style.png
+++ b/tests/ref/math/style.png
Binary files differ