Skip to content

freetype: route FC_MATRIX through cairo for color glyphs#10006

Open
Strykar wants to merge 1 commit into
kovidgoyal:masterfrom
Strykar:followup-b-cairo-matrix
Open

freetype: route FC_MATRIX through cairo for color glyphs#10006
Strykar wants to merge 1 commit into
kovidgoyal:masterfrom
Strykar:followup-b-cairo-matrix

Conversation

@Strykar
Copy link
Copy Markdown
Contributor

@Strykar Strykar commented May 13, 2026

Color glyphs (COLR/CBDT/SVG) go through cairo on a second FT_Face, self->face_for_cairo, opened in ensure_cairo_resources. That face never receives the FT_Set_Transform installed on self->face in face_from_descriptor (#9990): cairo owns FT_Set_Transform on its own face and derives it from the font matrix on every render (_cairo_ft_unscaled_font_set_scale in cairo-ft-font.c).

The only channel that reaches color-glyph rasterization is the cairo font matrix, not the FT face transform, so FC_MATRIX is silently dropped on that path. Stock fontconfig rules do not apply FC_MATRIX to color fonts, so this is a hand-built config edge case.

Factor the two cairo_set_font_size() call sites in set_cairo_font_size and fit_cairo_glyph into apply_cairo_font_size(), which calls cairo_set_font_matrix() with size * FC_MATRIX when has_matrix is set, and falls through to cairo_set_font_size() otherwise.

The non-matrix path is bit-identical to before. For pure shears (xx=1, yy=1) cairo_scaled_font_glyph_extents reads the post-shear bbox so the shrink loop bounds the destination correctly; the user-visible effect is that a sheared color glyph reports a wider bbox and shrinks more aggressively to fit a cell than its upright sibling. Acceptable for the hand-built edge case this PR scopes to.

FT_Matrix stores xx,xy,yx,yy in row-major order; cairo_matrix_init takes xx,yx,xy,yy.
Same matrix, transposed argument order - pinned with a comment because it is easy to flip.

Refs: #9990

Color glyphs (COLR/CBDT/SVG) go through cairo on a second FT_Face,
self->face_for_cairo, opened in ensure_cairo_resources. That face
never receives the FT_Set_Transform installed on self->face in
face_from_descriptor (kovidgoyal#9990): cairo owns FT_Set_Transform on its own
face and derives it from the font matrix on every render
(_cairo_ft_unscaled_font_set_scale in cairo-ft-font.c). The only
channel that reaches color-glyph rasterization is the cairo font
matrix, not the FT face transform, so FC_MATRIX is silently dropped on
that path. Stock fontconfig rules do not apply FC_MATRIX to color
fonts, so this is a hand-built config edge case.

Factor the two cairo_set_font_size() call sites in set_cairo_font_size
and fit_cairo_glyph into apply_cairo_font_size(), which calls
cairo_set_font_matrix() with size * FC_MATRIX when has_matrix is set,
and falls through to cairo_set_font_size() otherwise. The non-matrix
path is bit-identical to before. For pure shears (xx=1, yy=1)
cairo_scaled_font_glyph_extents reads the post-shear bbox so the
shrink loop bounds the destination correctly; the user-visible effect
is that a sheared color glyph reports a wider bbox and shrinks more
aggressively to fit a cell than its upright sibling. Acceptable for
the hand-built edge case this PR scopes to.

FT_Matrix stores xx,xy,yx,yy in row-major order;
cairo_matrix_init takes xx,yx,xy,yy. Same matrix, transposed argument
order - pinned with a comment because it is easy to flip.

Refs: kovidgoyal#9990
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant