Repository: typst/typst
File: crates/typst-render/src/lib.rs (Rust)

Code before:
    text: &TextItem,
    id: GlyphId,
) -> Option<()> {
    let ts = &state.transform;
    let ppem = text.size.to_f32() * ts.sy;

    // Render a glyph directly as a path. This only happens when the fast glyph
    // rasterization can't be used due to very large text size or weird
    // scale/skewing transforms.
    if ppem > 100.0
        || ts.kx != 0.0
        || ts.ky != 0.0
        || ts.sx != ts.sy
        || text.stroke.is_some()
    {
        let path = {
            let mut builder = WrappedPathBuilder(sk::PathBuilder::new());
            text.font.ttf().outline_glyph(id, &mut builder)?;
            builder.0.finish()?
        };

        let scale = text.size.to_f32() / text.font.units_per_em() as f32;

        let mut pixmap = None;

        let rule = sk::FillRule::default();

        // Flip vertically because font design coordinate
        // system is Y-up.
        let ts = ts.pre_scale(scale, -scale);
        if let Some(FixedStroke {
            paint,
            thickness,
            line_cap,
            line_join,
            dash_pattern,
            miter_limit,
        }) = &text.stroke
        {
            if thickness.to_f32() > 0.0 {
                let dash = dash_pattern.as_ref().and_then(to_sk_dash_pattern);

                let paint = to_sk_paint(
                    paint,
                    state.pre_concat(sk::Transform::from_scale(scale, -scale)),
                    Size::zero(),
                    false,
                    None,
                    &mut pixmap,
                    None,
                );

Review comment (suggestion):
@Dherse could you review the stroking code here? I think you are most familiar with how the transforms work and how arguments to `to_sk_paint` should be configured.

Code after:
    text: &TextItem,
    id: GlyphId,
) -> Option<()> {
    let ts = &state.transform;
    let ppem = text.size.to_f32() * ts.sy;

    // Render a glyph directly as a path. This only happens when the fast glyph
    // rasterization can't be used due to very large text size or weird
    // scale/skewing transforms.
    if ppem > 100.0
        || ts.kx != 0.0
        || ts.ky != 0.0
        || ts.sx != ts.sy
        || text.stroke.is_some()
    {
        let path = {
            let mut builder = WrappedPathBuilder(sk::PathBuilder::new());
            text.font.ttf().outline_glyph(id, &mut builder)?;
            builder.0.finish()?
        };

        let scale = text.size.to_f32() / text.font.units_per_em() as f32;

        let mut pixmap = None;

        let rule = sk::FillRule::default();

        // Flip vertically because font design coordinate
        // system is Y-up.
        let ts = ts.pre_scale(scale, -scale);
        let state_ts = state.pre_concat(sk::Transform::from_scale(scale, -scale));
        let paint = to_sk_paint(
            &text.fill,
            state_ts,
            Size::zero(),
            true,
            None,
            &mut pixmap,
            None,
        );
        canvas.fill_path(&path, &paint, rule, ts, state.mask);

        if let Some(FixedStroke {
            paint,
            thickness,
            line_cap,
            line_join,
            dash_pattern,
            miter_limit,
        }) = &text.stroke
        {