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
|
||||
};
|
||||
|
||||
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
|
||||
// in many cases.
|
||||
|
@ -109,12 +109,12 @@ fn layout_frac_like(
|
||||
frame.push_frame(denom_pos, denom);
|
||||
|
||||
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.center_on_axis();
|
||||
ctx.push(left);
|
||||
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.center_on_axis();
|
||||
ctx.push(right);
|
||||
|
@ -4,7 +4,7 @@ use az::SaturatingAs;
|
||||
use rustybuzz::{BufferFlags, UnicodeBuffer};
|
||||
use ttf_parser::math::{GlyphAssembly, GlyphConstruction, GlyphPart};
|
||||
use ttf_parser::GlyphId;
|
||||
use typst_library::diag::warning;
|
||||
use typst_library::diag::{bail, warning, SourceResult};
|
||||
use typst_library::foundations::StyleChain;
|
||||
use typst_library::introspection::Tag;
|
||||
use typst_library::layout::{
|
||||
@ -258,21 +258,25 @@ pub struct GlyphFragment {
|
||||
}
|
||||
|
||||
impl GlyphFragment {
|
||||
/// Calls `try_new` with the given character, assuming the font has a glyph
|
||||
/// for it.
|
||||
pub fn new(font: &Font, styles: StyleChain, c: char, span: Span) -> Self {
|
||||
Self::try_new(font, styles, c.encode_utf8(&mut [0; 4]), span).unwrap()
|
||||
/// Calls `new` with the given character.
|
||||
pub fn new_char(
|
||||
font: &Font,
|
||||
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
|
||||
/// the result from shaping the string is not a single glyph or is a tofu.
|
||||
/// Try to create a new glyph out of the given string. Will bail if the
|
||||
/// result from shaping the string is not a single glyph or is a tofu.
|
||||
#[comemo::memoize]
|
||||
pub fn try_new(
|
||||
pub fn new(
|
||||
font: &Font,
|
||||
styles: StyleChain,
|
||||
text: &str,
|
||||
span: Span,
|
||||
) -> Option<GlyphFragment> {
|
||||
) -> SourceResult<GlyphFragment> {
|
||||
let mut buffer = UnicodeBuffer::new();
|
||||
buffer.push_str(text);
|
||||
buffer.set_language(language(styles));
|
||||
@ -296,7 +300,7 @@ impl GlyphFragment {
|
||||
|
||||
let buffer = rustybuzz::shape_with_plan(font.rusty(), &plan, buffer);
|
||||
if buffer.len() != 1 {
|
||||
return None;
|
||||
bail!(span, "did not get a single glyph after shaping {}", text);
|
||||
}
|
||||
|
||||
let info = buffer.glyph_infos()[0];
|
||||
@ -304,7 +308,7 @@ impl GlyphFragment {
|
||||
|
||||
// TODO: add support for coverage and fallback, like in normal text shaping.
|
||||
if info.glyph_id == 0 {
|
||||
return None;
|
||||
bail!(span, "current font is missing a glyph for {}", text);
|
||||
}
|
||||
|
||||
let cluster = info.cluster as usize;
|
||||
@ -353,7 +357,7 @@ impl GlyphFragment {
|
||||
modifiers: FrameModifiers::get_in(styles),
|
||||
};
|
||||
fragment.update_glyph();
|
||||
Some(fragment)
|
||||
Ok(fragment)
|
||||
}
|
||||
|
||||
/// 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
|
||||
// to ensure that normal matrices are aligned with others unless they are
|
||||
// way too big.
|
||||
let paren =
|
||||
GlyphFragment::new(ctx.font, styles.chain(&denom_style), '(', Span::detached());
|
||||
let paren = GlyphFragment::new_char(
|
||||
ctx.font,
|
||||
styles.chain(&denom_style),
|
||||
'(',
|
||||
Span::detached(),
|
||||
)?;
|
||||
|
||||
for (column, col) in columns.iter().zip(&mut cols) {
|
||||
for (cell, (ascent, descent)) in column.iter().zip(&mut heights) {
|
||||
@ -313,7 +317,7 @@ fn layout_delimiters(
|
||||
frame.set_baseline(height / 2.0 + axis);
|
||||
|
||||
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.center_on_axis();
|
||||
ctx.push(left);
|
||||
@ -322,7 +326,7 @@ fn layout_delimiters(
|
||||
ctx.push(FrameFragment::new(styles, frame));
|
||||
|
||||
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.center_on_axis();
|
||||
ctx.push(right);
|
||||
|
@ -49,7 +49,7 @@ pub fn layout_root(
|
||||
|
||||
// Layout root symbol.
|
||||
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);
|
||||
let sqrt = sqrt.into_frame();
|
||||
|
||||
|
@ -70,7 +70,7 @@ fn layout_inline_text(
|
||||
let mut fragments = vec![];
|
||||
for unstyled_c in text.chars() {
|
||||
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());
|
||||
}
|
||||
let frame = MathRun::new(fragments).into_frame(styles);
|
||||
@ -125,19 +125,15 @@ pub fn layout_symbol(
|
||||
_ => (elem.text, styles),
|
||||
};
|
||||
let c = styled_char(styles, unstyled_c, true);
|
||||
let fragment: MathFragment = match GlyphFragment::try_new(
|
||||
ctx.font,
|
||||
symbol_styles,
|
||||
c.encode_utf8(&mut [0; 4]),
|
||||
elem.span(),
|
||||
) {
|
||||
Some(mut glyph) => {
|
||||
let fragment: MathFragment =
|
||||
match GlyphFragment::new_char(ctx.font, symbol_styles, c, elem.span()) {
|
||||
Ok(mut glyph) => {
|
||||
adjust_glyph_layout(&mut glyph, ctx, styles);
|
||||
glyph.into()
|
||||
}
|
||||
None => {
|
||||
Err(_) => {
|
||||
// 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)?
|
||||
.into()
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ fn layout_underoverspreader(
|
||||
let body = ctx.layout_into_run(body, styles)?;
|
||||
let body_class = body.class();
|
||||
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());
|
||||
|
||||
let mut rows = vec![];
|
||||
|
Loading…
x
Reference in New Issue
Block a user