Return SourceResult in try_new

This commit is contained in:
mkorje 2025-06-10 22:51:20 +10:00
parent df019567a1
commit b7e5886e42
No known key found for this signature in database
7 changed files with 44 additions and 39 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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,19 +125,15 @@ 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]),
elem.span(),
) {
Some(mut glyph) => {
adjust_glyph_layout(&mut glyph, ctx, styles); adjust_glyph_layout(&mut glyph, ctx, styles);
glyph.into() glyph.into()
} }
None => { Err(_) => {
// Not in the math font, fallback to normal inline text layout. // Not in the math font, fallback to normal inline text layout.
// TODO: Should replace this with proper fallback in [`GlyphFragment::try_new`]. // TODO: Should replace this with proper fallback in [`GlyphFragment::new`].
layout_inline_text(c.encode_utf8(&mut [0; 4]), elem.span(), ctx, styles)? layout_inline_text(c.encode_utf8(&mut [0; 4]), elem.span(), ctx, styles)?
.into() .into()
} }

View File

@ -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![];