Add basic multi-char symbol layout

Not perfect, but should handle most cases

Co-authored-by: Max <max@mkor.je>
This commit is contained in:
T0mstone 2025-07-23 12:52:12 +02:00
parent 632186f446
commit 5e202843c1
2 changed files with 32 additions and 34 deletions

View File

@ -300,6 +300,7 @@ impl GlyphFragment {
); );
let buffer = rustybuzz::shape_with_plan(font.rusty(), &plan, buffer); let buffer = rustybuzz::shape_with_plan(font.rusty(), &plan, buffer);
// TODO: deal with multiple glyphs.
if buffer.len() != 1 { if buffer.len() != 1 {
bail!(span, "did not get a single glyph after shaping {}", text); bail!(span, "did not get a single glyph after shaping {}", text);
} }

View File

@ -129,33 +129,29 @@ pub fn layout_symbol(
ctx: &mut MathContext, ctx: &mut MathContext,
styles: StyleChain, styles: StyleChain,
) -> SourceResult<()> { ) -> SourceResult<()> {
assert!(
elem.text.len() <= 4 && elem.text.chars().count() == 1,
"TODO: layout multi-char symbol"
);
let elem_char = elem
.text
.chars()
.next()
.expect("TODO: should an empty symbol value forbidden?");
// Switch dotless char to normal when we have the dtls OpenType feature.
// This should happen before the main styling pass.
let dtls = style_dtls();
let (unstyled_c, symbol_styles) = match try_dotless(elem_char) {
Some(c) if has_dtls_feat(ctx.font) => (c, styles.chain(&dtls)),
_ => (elem_char, styles),
};
let variant = styles.get(EquationElem::variant); let variant = styles.get(EquationElem::variant);
let bold = styles.get(EquationElem::bold); let bold = styles.get(EquationElem::bold);
let italic = styles.get(EquationElem::italic); let italic = styles.get(EquationElem::italic);
let dtls = style_dtls();
let style = MathStyle::select(unstyled_c, variant, bold, italic); let has_dtls_feat = has_dtls_feat(ctx.font);
let text: EcoString = to_style(unstyled_c, style).collect(); for cluster in elem.text.graphemes(true) {
// Switch dotless char to normal when we have the dtls OpenType feature.
// This should happen before the main styling pass.
let mut enable_dtls = false;
let text: EcoString = cluster
.chars()
.flat_map(|mut c| {
if has_dtls_feat && let Some(d) = try_dotless(c) {
enable_dtls = true;
c = d;
}
to_style(c, MathStyle::select(c, variant, bold, italic))
})
.collect();
let styles = if enable_dtls { styles.chain(&dtls) } else { styles };
let fragment: MathFragment = let fragment: MathFragment =
match GlyphFragment::new(ctx.font, symbol_styles, &text, elem.span()) { match GlyphFragment::new(ctx.font, styles, &text, elem.span()) {
Ok(mut glyph) => { Ok(mut glyph) => {
adjust_glyph_layout(&mut glyph, ctx, styles); adjust_glyph_layout(&mut glyph, ctx, styles);
glyph.into() glyph.into()
@ -167,6 +163,7 @@ pub fn layout_symbol(
} }
}; };
ctx.push(fragment); ctx.push(fragment);
}
Ok(()) Ok(())
} }