mirror of
https://github.com/typst/typst
synced 2025-08-23 19:24:14 +08:00
Return SourceResult in try_new
This commit is contained in:
parent
df019567a1
commit
b7e5886e42
@ -42,7 +42,8 @@ pub fn layout_accent(
|
|||||||
styles
|
styles
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut glyph = GlyphFragment::new(ctx.font, accent_styles, accent.0, elem.span());
|
let mut glyph =
|
||||||
|
GlyphFragment::new_char(ctx.font, accent_styles, accent.0, elem.span())?;
|
||||||
|
|
||||||
// Forcing the accent to be at least as large as the base makes it too wide
|
// Forcing the accent to be at least as large as the base makes it too wide
|
||||||
// in many cases.
|
// in many cases.
|
||||||
|
@ -109,12 +109,12 @@ fn layout_frac_like(
|
|||||||
frame.push_frame(denom_pos, denom);
|
frame.push_frame(denom_pos, denom);
|
||||||
|
|
||||||
if binom {
|
if binom {
|
||||||
let mut left = GlyphFragment::new(ctx.font, styles, '(', span);
|
let mut left = GlyphFragment::new_char(ctx.font, styles, '(', span)?;
|
||||||
left.stretch_vertical(ctx, height - short_fall);
|
left.stretch_vertical(ctx, height - short_fall);
|
||||||
left.center_on_axis();
|
left.center_on_axis();
|
||||||
ctx.push(left);
|
ctx.push(left);
|
||||||
ctx.push(FrameFragment::new(styles, frame));
|
ctx.push(FrameFragment::new(styles, frame));
|
||||||
let mut right = GlyphFragment::new(ctx.font, styles, ')', span);
|
let mut right = GlyphFragment::new_char(ctx.font, styles, ')', span)?;
|
||||||
right.stretch_vertical(ctx, height - short_fall);
|
right.stretch_vertical(ctx, height - short_fall);
|
||||||
right.center_on_axis();
|
right.center_on_axis();
|
||||||
ctx.push(right);
|
ctx.push(right);
|
||||||
|
@ -4,7 +4,7 @@ use az::SaturatingAs;
|
|||||||
use rustybuzz::{BufferFlags, UnicodeBuffer};
|
use rustybuzz::{BufferFlags, UnicodeBuffer};
|
||||||
use ttf_parser::math::{GlyphAssembly, GlyphConstruction, GlyphPart};
|
use ttf_parser::math::{GlyphAssembly, GlyphConstruction, GlyphPart};
|
||||||
use ttf_parser::GlyphId;
|
use ttf_parser::GlyphId;
|
||||||
use typst_library::diag::warning;
|
use typst_library::diag::{bail, warning, SourceResult};
|
||||||
use typst_library::foundations::StyleChain;
|
use typst_library::foundations::StyleChain;
|
||||||
use typst_library::introspection::Tag;
|
use typst_library::introspection::Tag;
|
||||||
use typst_library::layout::{
|
use typst_library::layout::{
|
||||||
@ -258,21 +258,25 @@ pub struct GlyphFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GlyphFragment {
|
impl GlyphFragment {
|
||||||
/// Calls `try_new` with the given character, assuming the font has a glyph
|
/// Calls `new` with the given character.
|
||||||
/// for it.
|
pub fn new_char(
|
||||||
pub fn new(font: &Font, styles: StyleChain, c: char, span: Span) -> Self {
|
font: &Font,
|
||||||
Self::try_new(font, styles, c.encode_utf8(&mut [0; 4]), span).unwrap()
|
styles: StyleChain,
|
||||||
|
c: char,
|
||||||
|
span: Span,
|
||||||
|
) -> SourceResult<Self> {
|
||||||
|
Self::new(font, styles, c.encode_utf8(&mut [0; 4]), span)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to create a new glyph out of the given string. Will return None if
|
/// Try to create a new glyph out of the given string. Will bail if the
|
||||||
/// the result from shaping the string is not a single glyph or is a tofu.
|
/// result from shaping the string is not a single glyph or is a tofu.
|
||||||
#[comemo::memoize]
|
#[comemo::memoize]
|
||||||
pub fn try_new(
|
pub fn new(
|
||||||
font: &Font,
|
font: &Font,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
text: &str,
|
text: &str,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Option<GlyphFragment> {
|
) -> SourceResult<GlyphFragment> {
|
||||||
let mut buffer = UnicodeBuffer::new();
|
let mut buffer = UnicodeBuffer::new();
|
||||||
buffer.push_str(text);
|
buffer.push_str(text);
|
||||||
buffer.set_language(language(styles));
|
buffer.set_language(language(styles));
|
||||||
@ -296,7 +300,7 @@ impl GlyphFragment {
|
|||||||
|
|
||||||
let buffer = rustybuzz::shape_with_plan(font.rusty(), &plan, buffer);
|
let buffer = rustybuzz::shape_with_plan(font.rusty(), &plan, buffer);
|
||||||
if buffer.len() != 1 {
|
if buffer.len() != 1 {
|
||||||
return None;
|
bail!(span, "did not get a single glyph after shaping {}", text);
|
||||||
}
|
}
|
||||||
|
|
||||||
let info = buffer.glyph_infos()[0];
|
let info = buffer.glyph_infos()[0];
|
||||||
@ -304,7 +308,7 @@ impl GlyphFragment {
|
|||||||
|
|
||||||
// TODO: add support for coverage and fallback, like in normal text shaping.
|
// TODO: add support for coverage and fallback, like in normal text shaping.
|
||||||
if info.glyph_id == 0 {
|
if info.glyph_id == 0 {
|
||||||
return None;
|
bail!(span, "current font is missing a glyph for {}", text);
|
||||||
}
|
}
|
||||||
|
|
||||||
let cluster = info.cluster as usize;
|
let cluster = info.cluster as usize;
|
||||||
@ -353,7 +357,7 @@ impl GlyphFragment {
|
|||||||
modifiers: FrameModifiers::get_in(styles),
|
modifiers: FrameModifiers::get_in(styles),
|
||||||
};
|
};
|
||||||
fragment.update_glyph();
|
fragment.update_glyph();
|
||||||
Some(fragment)
|
Ok(fragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets element id and boxes in appropriate way without changing other
|
/// Sets element id and boxes in appropriate way without changing other
|
||||||
|
@ -183,8 +183,12 @@ fn layout_body(
|
|||||||
// We pad ascent and descent with the ascent and descent of the paren
|
// We pad ascent and descent with the ascent and descent of the paren
|
||||||
// to ensure that normal matrices are aligned with others unless they are
|
// to ensure that normal matrices are aligned with others unless they are
|
||||||
// way too big.
|
// way too big.
|
||||||
let paren =
|
let paren = GlyphFragment::new_char(
|
||||||
GlyphFragment::new(ctx.font, styles.chain(&denom_style), '(', Span::detached());
|
ctx.font,
|
||||||
|
styles.chain(&denom_style),
|
||||||
|
'(',
|
||||||
|
Span::detached(),
|
||||||
|
)?;
|
||||||
|
|
||||||
for (column, col) in columns.iter().zip(&mut cols) {
|
for (column, col) in columns.iter().zip(&mut cols) {
|
||||||
for (cell, (ascent, descent)) in column.iter().zip(&mut heights) {
|
for (cell, (ascent, descent)) in column.iter().zip(&mut heights) {
|
||||||
@ -313,7 +317,7 @@ fn layout_delimiters(
|
|||||||
frame.set_baseline(height / 2.0 + axis);
|
frame.set_baseline(height / 2.0 + axis);
|
||||||
|
|
||||||
if let Some(left_c) = left {
|
if let Some(left_c) = left {
|
||||||
let mut left = GlyphFragment::new(ctx.font, styles, left_c, span);
|
let mut left = GlyphFragment::new_char(ctx.font, styles, left_c, span)?;
|
||||||
left.stretch_vertical(ctx, target - short_fall);
|
left.stretch_vertical(ctx, target - short_fall);
|
||||||
left.center_on_axis();
|
left.center_on_axis();
|
||||||
ctx.push(left);
|
ctx.push(left);
|
||||||
@ -322,7 +326,7 @@ fn layout_delimiters(
|
|||||||
ctx.push(FrameFragment::new(styles, frame));
|
ctx.push(FrameFragment::new(styles, frame));
|
||||||
|
|
||||||
if let Some(right_c) = right {
|
if let Some(right_c) = right {
|
||||||
let mut right = GlyphFragment::new(ctx.font, styles, right_c, span);
|
let mut right = GlyphFragment::new_char(ctx.font, styles, right_c, span)?;
|
||||||
right.stretch_vertical(ctx, target - short_fall);
|
right.stretch_vertical(ctx, target - short_fall);
|
||||||
right.center_on_axis();
|
right.center_on_axis();
|
||||||
ctx.push(right);
|
ctx.push(right);
|
||||||
|
@ -49,7 +49,7 @@ pub fn layout_root(
|
|||||||
|
|
||||||
// Layout root symbol.
|
// Layout root symbol.
|
||||||
let target = radicand.height() + thickness + gap;
|
let target = radicand.height() + thickness + gap;
|
||||||
let mut sqrt = GlyphFragment::new(ctx.font, styles, '√', span);
|
let mut sqrt = GlyphFragment::new_char(ctx.font, styles, '√', span)?;
|
||||||
sqrt.stretch_vertical(ctx, target);
|
sqrt.stretch_vertical(ctx, target);
|
||||||
let sqrt = sqrt.into_frame();
|
let sqrt = sqrt.into_frame();
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ fn layout_inline_text(
|
|||||||
let mut fragments = vec![];
|
let mut fragments = vec![];
|
||||||
for unstyled_c in text.chars() {
|
for unstyled_c in text.chars() {
|
||||||
let c = styled_char(styles, unstyled_c, false);
|
let c = styled_char(styles, unstyled_c, false);
|
||||||
let glyph = GlyphFragment::new(ctx.font, styles, c, span);
|
let glyph = GlyphFragment::new_char(ctx.font, styles, c, span)?;
|
||||||
fragments.push(glyph.into());
|
fragments.push(glyph.into());
|
||||||
}
|
}
|
||||||
let frame = MathRun::new(fragments).into_frame(styles);
|
let frame = MathRun::new(fragments).into_frame(styles);
|
||||||
@ -125,23 +125,19 @@ pub fn layout_symbol(
|
|||||||
_ => (elem.text, styles),
|
_ => (elem.text, styles),
|
||||||
};
|
};
|
||||||
let c = styled_char(styles, unstyled_c, true);
|
let c = styled_char(styles, unstyled_c, true);
|
||||||
let fragment: MathFragment = match GlyphFragment::try_new(
|
let fragment: MathFragment =
|
||||||
ctx.font,
|
match GlyphFragment::new_char(ctx.font, symbol_styles, c, elem.span()) {
|
||||||
symbol_styles,
|
Ok(mut glyph) => {
|
||||||
c.encode_utf8(&mut [0; 4]),
|
adjust_glyph_layout(&mut glyph, ctx, styles);
|
||||||
elem.span(),
|
glyph.into()
|
||||||
) {
|
}
|
||||||
Some(mut glyph) => {
|
Err(_) => {
|
||||||
adjust_glyph_layout(&mut glyph, ctx, styles);
|
// Not in the math font, fallback to normal inline text layout.
|
||||||
glyph.into()
|
// TODO: Should replace this with proper fallback in [`GlyphFragment::new`].
|
||||||
}
|
layout_inline_text(c.encode_utf8(&mut [0; 4]), elem.span(), ctx, styles)?
|
||||||
None => {
|
.into()
|
||||||
// Not in the math font, fallback to normal inline text layout.
|
}
|
||||||
// TODO: Should replace this with proper fallback in [`GlyphFragment::try_new`].
|
};
|
||||||
layout_inline_text(c.encode_utf8(&mut [0; 4]), elem.span(), ctx, styles)?
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ctx.push(fragment);
|
ctx.push(fragment);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ fn layout_underoverspreader(
|
|||||||
let body = ctx.layout_into_run(body, styles)?;
|
let body = ctx.layout_into_run(body, styles)?;
|
||||||
let body_class = body.class();
|
let body_class = body.class();
|
||||||
let body = body.into_fragment(styles);
|
let body = body.into_fragment(styles);
|
||||||
let mut glyph = GlyphFragment::new(ctx.font, styles, c, span);
|
let mut glyph = GlyphFragment::new_char(ctx.font, styles, c, span)?;
|
||||||
glyph.stretch_horizontal(ctx, body.width());
|
glyph.stretch_horizontal(ctx, body.width());
|
||||||
|
|
||||||
let mut rows = vec![];
|
let mut rows = vec![];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user