mirror of
https://github.com/typst/typst
synced 2025-05-13 12:36:23 +08:00
Spans in math
This commit is contained in:
parent
2720a44b96
commit
ad05ba5925
@ -66,7 +66,7 @@ impl LayoutMath for AccentNode {
|
|||||||
// Forcing the accent to be at least as large as the base makes it too
|
// Forcing the accent to be at least as large as the base makes it too
|
||||||
// wide in many case.
|
// wide in many case.
|
||||||
let Accent(c) = self.accent();
|
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 short_fall = ACCENT_SHORT_FALL.scaled(ctx);
|
||||||
let variant = glyph.stretch_horizontal(ctx, base.width(), short_fall);
|
let variant = glyph.stretch_horizontal(ctx, base.width(), short_fall);
|
||||||
let accent = variant.frame;
|
let accent = variant.frame;
|
||||||
|
@ -124,13 +124,15 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
|
|||||||
.into_frame())
|
.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();
|
let mut chars = text.chars();
|
||||||
if let Some(glyph) = chars
|
if let Some(glyph) = chars
|
||||||
.next()
|
.next()
|
||||||
.filter(|_| chars.next().is_none())
|
.filter(|_| chars.next().is_none())
|
||||||
.map(|c| self.style.styled_char(c))
|
.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.
|
// A single letter that is available in the math font.
|
||||||
if self.style.size == MathSize::Display
|
if self.style.size == MathSize::Display
|
||||||
@ -146,7 +148,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
|
|||||||
let mut fragments = vec![];
|
let mut fragments = vec![];
|
||||||
for c in text.chars() {
|
for c in text.chars() {
|
||||||
let c = self.style.styled_char(c);
|
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);
|
let frame = MathRow::new(fragments).to_frame(self);
|
||||||
self.push(FrameFragment::new(self, frame));
|
self.push(FrameFragment::new(self, frame));
|
||||||
@ -158,7 +160,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
|
|||||||
style = style.with_italic(false);
|
style = style.with_italic(false);
|
||||||
}
|
}
|
||||||
let text: EcoString = text.chars().map(|c| style.styled_char(c)).collect();
|
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(
|
self.push(
|
||||||
FrameFragment::new(self, frame)
|
FrameFragment::new(self, frame)
|
||||||
.with_class(MathClass::Alphabetic)
|
.with_class(MathClass::Alphabetic)
|
||||||
|
@ -89,7 +89,9 @@ fn scale(
|
|||||||
) {
|
) {
|
||||||
let glyph = match fragment {
|
let glyph = match fragment {
|
||||||
MathFragment::Glyph(glyph) => glyph.clone(),
|
MathFragment::Glyph(glyph) => glyph.clone(),
|
||||||
MathFragment::Variant(variant) => GlyphFragment::new(ctx, variant.c),
|
MathFragment::Variant(variant) => {
|
||||||
|
GlyphFragment::new(ctx, variant.c, variant.span)
|
||||||
|
}
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ pub struct FracNode {
|
|||||||
|
|
||||||
impl LayoutMath for FracNode {
|
impl LayoutMath for FracNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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 {
|
impl LayoutMath for BinomNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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,
|
num: &Content,
|
||||||
denom: &Content,
|
denom: &Content,
|
||||||
binom: bool,
|
binom: bool,
|
||||||
|
span: Span,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
let short_fall = DELIM_SHORT_FALL.scaled(ctx);
|
let short_fall = DELIM_SHORT_FALL.scaled(ctx);
|
||||||
let axis = scaled!(ctx, axis_height);
|
let axis = scaled!(ctx, axis_height);
|
||||||
@ -121,9 +122,13 @@ fn layout(
|
|||||||
frame.push_frame(denom_pos, denom);
|
frame.push_frame(denom_pos, denom);
|
||||||
|
|
||||||
if binom {
|
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(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 {
|
} else {
|
||||||
frame.push(
|
frame.push(
|
||||||
line_pos,
|
line_pos,
|
||||||
|
@ -147,21 +147,22 @@ pub struct GlyphFragment {
|
|||||||
pub style: MathStyle,
|
pub style: MathStyle,
|
||||||
pub font_size: Abs,
|
pub font_size: Abs,
|
||||||
pub class: Option<MathClass>,
|
pub class: Option<MathClass>,
|
||||||
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlyphFragment {
|
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();
|
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 c = ctx.style.styled_char(c);
|
||||||
let id = ctx.ttf.glyph_index(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 advance = ctx.ttf.glyph_hor_advance(id).unwrap_or_default();
|
||||||
let italics = italics_correction(ctx, id).unwrap_or_default();
|
let italics = italics_correction(ctx, id).unwrap_or_default();
|
||||||
let bbox = ctx.ttf.glyph_bounding_box(id).unwrap_or(Rect {
|
let bbox = ctx.ttf.glyph_bounding_box(id).unwrap_or(Rect {
|
||||||
@ -192,6 +193,7 @@ impl GlyphFragment {
|
|||||||
':' => Some(MathClass::Relation),
|
':' => Some(MathClass::Relation),
|
||||||
_ => unicode_math_class::class(c),
|
_ => unicode_math_class::class(c),
|
||||||
},
|
},
|
||||||
|
span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +210,7 @@ impl GlyphFragment {
|
|||||||
font_size: self.font_size,
|
font_size: self.font_size,
|
||||||
italics_correction: self.italics_correction,
|
italics_correction: self.italics_correction,
|
||||||
class: self.class,
|
class: self.class,
|
||||||
|
span: self.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +225,7 @@ impl GlyphFragment {
|
|||||||
c: self.c,
|
c: self.c,
|
||||||
x_advance: Em::from_length(self.width, self.font_size),
|
x_advance: Em::from_length(self.width, self.font_size),
|
||||||
x_offset: Em::zero(),
|
x_offset: Em::zero(),
|
||||||
span: Span::detached(),
|
span: self.span,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
@ -249,6 +252,7 @@ pub struct VariantFragment {
|
|||||||
pub style: MathStyle,
|
pub style: MathStyle,
|
||||||
pub font_size: Abs,
|
pub font_size: Abs,
|
||||||
pub class: Option<MathClass>,
|
pub class: Option<MathClass>,
|
||||||
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for VariantFragment {
|
impl Debug for VariantFragment {
|
||||||
|
@ -36,7 +36,13 @@ impl LayoutMath for VecNode {
|
|||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||||
let delim = self.delim(ctx.styles());
|
let delim = self.delim(ctx.styles());
|
||||||
let frame = layout_vec_body(ctx, &self.children(), Align::Center)?;
|
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<()> {
|
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||||
let delim = self.delim(ctx.styles());
|
let delim = self.delim(ctx.styles());
|
||||||
let frame = layout_mat_body(ctx, &self.rows())?;
|
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<()> {
|
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||||
let delim = self.delim(ctx.styles());
|
let delim = self.delim(ctx.styles());
|
||||||
let frame = layout_vec_body(ctx, &self.children(), Align::Left)?;
|
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,
|
mut frame: Frame,
|
||||||
left: Option<char>,
|
left: Option<char>,
|
||||||
right: Option<char>,
|
right: Option<char>,
|
||||||
|
span: Span,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
let axis = scaled!(ctx, axis_height);
|
let axis = scaled!(ctx, axis_height);
|
||||||
let short_fall = DELIM_SHORT_FALL.scaled(ctx);
|
let short_fall = DELIM_SHORT_FALL.scaled(ctx);
|
||||||
@ -296,14 +309,17 @@ fn layout_delimiters(
|
|||||||
frame.set_baseline(height / 2.0 + axis);
|
frame.set_baseline(height / 2.0 + axis);
|
||||||
|
|
||||||
if let Some(left) = left {
|
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));
|
ctx.push(FrameFragment::new(ctx, frame));
|
||||||
|
|
||||||
if let Some(right) = right {
|
if let Some(right) = right {
|
||||||
ctx.push(
|
ctx.push(
|
||||||
GlyphFragment::new(ctx, right).stretch_vertical(ctx, target, short_fall),
|
GlyphFragment::new(ctx, right, span)
|
||||||
|
.stretch_vertical(ctx, target, short_fall),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ impl LayoutMath for Content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(node) = self.to::<TextNode>() {
|
if let Some(node) = self.to::<TextNode>() {
|
||||||
ctx.layout_text(&node.text())?;
|
ctx.layout_text(node)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ pub struct SqrtNode {
|
|||||||
|
|
||||||
impl LayoutMath for SqrtNode {
|
impl LayoutMath for SqrtNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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 {
|
impl LayoutMath for RootNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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,
|
ctx: &mut MathContext,
|
||||||
mut index: Option<&Content>,
|
mut index: Option<&Content>,
|
||||||
radicand: &Content,
|
radicand: &Content,
|
||||||
|
span: Span,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
let gap = scaled!(
|
let gap = scaled!(
|
||||||
ctx,
|
ctx,
|
||||||
@ -80,7 +81,7 @@ fn layout(
|
|||||||
frame
|
frame
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
let glyph = GlyphFragment::new(ctx, '√');
|
let glyph = GlyphFragment::new(ctx, '√', span);
|
||||||
glyph.stretch_vertical(ctx, target, Abs::zero()).frame
|
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)?;
|
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;
|
let variant = glyph.stretch_vertical(ctx, target, Abs::zero()).frame;
|
||||||
if variant.height() < target {
|
if variant.height() < target {
|
||||||
return None;
|
return None;
|
||||||
|
@ -73,7 +73,7 @@ fn stretch_glyph(
|
|||||||
|
|
||||||
// This is either good or the best we've got.
|
// This is either good or the best we've got.
|
||||||
if short_target <= best_advance || construction.assembly.is_none() {
|
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.
|
// Assemble from parts.
|
||||||
@ -142,7 +142,7 @@ fn assemble(
|
|||||||
advance += ratio * (max_overlap - min_overlap);
|
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));
|
selected.push((fragment, advance));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,6 +181,7 @@ fn assemble(
|
|||||||
font_size: base.font_size,
|
font_size: base.font_size,
|
||||||
italics_correction: Abs::zero(),
|
italics_correction: Abs::zero(),
|
||||||
class: base.class,
|
class: base.class,
|
||||||
|
span: base.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ pub struct UnderlineNode {
|
|||||||
|
|
||||||
impl LayoutMath for UnderlineNode {
|
impl LayoutMath for UnderlineNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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 {
|
impl LayoutMath for OverlineNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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 {
|
impl LayoutMath for UnderbraceNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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 {
|
impl LayoutMath for OverbraceNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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 {
|
impl LayoutMath for UnderbracketNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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 {
|
impl LayoutMath for OverbracketNode {
|
||||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
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,
|
c: char,
|
||||||
gap: Em,
|
gap: Em,
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
|
span: Span,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
let gap = gap.scaled(ctx);
|
let gap = gap.scaled(ctx);
|
||||||
let body = ctx.layout_row(body)?;
|
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 stretched = glyph.stretch_horizontal(ctx, body.width(), Abs::zero());
|
||||||
|
|
||||||
let mut rows = vec![body, stretched.into()];
|
let mut rows = vec![body, stretched.into()];
|
||||||
|
@ -107,6 +107,7 @@ impl Synthesize for HeadingNode {
|
|||||||
|
|
||||||
let node = self
|
let node = self
|
||||||
.clone()
|
.clone()
|
||||||
|
.with_level(self.level(styles))
|
||||||
.with_outlined(self.outlined(styles))
|
.with_outlined(self.outlined(styles))
|
||||||
.with_numbers(numbering.is_some().then(|| counter.take()))
|
.with_numbers(numbering.is_some().then(|| counter.take()))
|
||||||
.with_numbering(numbering)
|
.with_numbering(numbering)
|
||||||
|
@ -368,7 +368,7 @@ fn eval_markup(
|
|||||||
*node = mem::take(node).labelled(label);
|
*node = mem::take(node).labelled(label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value => seq.push(value.display()),
|
value => seq.push(value.display().spanned(expr.span())),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,6 +458,12 @@ impl Eval for ast::Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ast::Expr {
|
||||||
|
fn eval_display(&self, vm: &mut Vm) -> SourceResult<Content> {
|
||||||
|
Ok(self.eval(vm)?.display().spanned(self.span()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Eval for ast::Text {
|
impl Eval for ast::Text {
|
||||||
type Output = Content;
|
type Output = Content;
|
||||||
|
|
||||||
@ -619,10 +625,9 @@ impl Eval for ast::Math {
|
|||||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
Ok(Content::sequence(
|
Ok(Content::sequence(
|
||||||
self.exprs()
|
self.exprs()
|
||||||
.map(|expr| Ok(expr.eval(vm)?.display()))
|
.map(|expr| expr.eval_display(vm))
|
||||||
.collect::<SourceResult<_>>()?,
|
.collect::<SourceResult<_>>()?,
|
||||||
)
|
))
|
||||||
.spanned(self.span()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,9 +651,9 @@ impl Eval for ast::MathDelimited {
|
|||||||
type Output = Content;
|
type Output = Content;
|
||||||
|
|
||||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
let open = self.open().eval(vm)?.display();
|
let open = self.open().eval_display(vm)?;
|
||||||
let body = self.body().eval(vm)?;
|
let body = self.body().eval(vm)?;
|
||||||
let close = self.close().eval(vm)?.display();
|
let close = self.close().eval_display(vm)?;
|
||||||
Ok((vm.items.math_delimited)(open, body, close))
|
Ok((vm.items.math_delimited)(open, body, close))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -657,12 +662,9 @@ impl Eval for ast::MathAttach {
|
|||||||
type Output = Content;
|
type Output = Content;
|
||||||
|
|
||||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
let base = self.base().eval(vm)?.display();
|
let base = self.base().eval_display(vm)?;
|
||||||
let bottom = self
|
let bottom = self.bottom().map(|expr| expr.eval_display(vm)).transpose()?;
|
||||||
.bottom()
|
let top = self.top().map(|expr| expr.eval_display(vm)).transpose()?;
|
||||||
.map(|expr| expr.eval(vm).map(Value::display))
|
|
||||||
.transpose()?;
|
|
||||||
let top = self.top().map(|expr| expr.eval(vm).map(Value::display)).transpose()?;
|
|
||||||
Ok((vm.items.math_attach)(base, bottom, top))
|
Ok((vm.items.math_attach)(base, bottom, top))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -671,8 +673,8 @@ impl Eval for ast::MathFrac {
|
|||||||
type Output = Content;
|
type Output = Content;
|
||||||
|
|
||||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
let num = self.num().eval(vm)?.display();
|
let num = self.num().eval_display(vm)?;
|
||||||
let denom = self.denom().eval(vm)?.display();
|
let denom = self.denom().eval_display(vm)?;
|
||||||
Ok((vm.items.math_frac)(num, denom))
|
Ok((vm.items.math_frac)(num, denom))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1038,7 +1040,7 @@ impl Eval for ast::FuncCall {
|
|||||||
body += arg;
|
body += arg;
|
||||||
}
|
}
|
||||||
return Ok(Value::Content(
|
return Ok(Value::Content(
|
||||||
callee.display()
|
callee.display().spanned(callee_span)
|
||||||
+ (vm.items.math_delimited)(
|
+ (vm.items.math_delimited)(
|
||||||
(vm.items.text)('('.into()),
|
(vm.items.text)('('.into()),
|
||||||
body,
|
body,
|
||||||
|
@ -15,7 +15,7 @@ use typst::diag::{bail, FileError, FileResult};
|
|||||||
use typst::doc::{Document, Element, Frame, Meta};
|
use typst::doc::{Document, Element, Frame, Meta};
|
||||||
use typst::eval::{func, Library, Value};
|
use typst::eval::{func, Library, Value};
|
||||||
use typst::font::{Font, FontBook};
|
use typst::font::{Font, FontBook};
|
||||||
use typst::geom::{Abs, RgbaColor, Sides, Smart};
|
use typst::geom::{Abs, Color, RgbaColor, Sides, Smart};
|
||||||
use typst::syntax::{Source, SourceId, Span, SyntaxNode};
|
use typst::syntax::{Source, SourceId, Span, SyntaxNode};
|
||||||
use typst::util::{Buffer, PathExt};
|
use typst::util::{Buffer, PathExt};
|
||||||
use typst::World;
|
use typst::World;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user