Merge branch 'matthiasc/for-main' into 'main'

gsk: Make glyph parsing more flexible

See merge request GNOME/gtk!6962
This commit is contained in:
Matthias Clasen 2024-03-01 17:49:46 +00:00
commit 9015734e65
5 changed files with 45 additions and 19 deletions

View File

@ -336,7 +336,7 @@ font that is specified in the string. It can be either a data url containing
a base64-encoded font file, or a regular url that points to a font file. a base64-encoded font file, or a regular url that points to a font file.
Glyphs can be specified as an ASCII string, or as a comma-separated list of Glyphs can be specified as an ASCII string, or as a comma-separated list of
their glyph ID and advance width. Optionally, x and y offsets and flags can their glyph IDs. Optionally, the advance width, x and y offsets and flags can
be specified as well, like this: 40 10 0 0 color. be specified as well, like this: 40 10 0 0 color.
If the given font does not exist or the given glyphs are invalid for the given If the given font does not exist or the given glyphs are invalid for the given

View File

@ -1182,6 +1182,8 @@ clear_font (gpointer inout_font)
g_clear_object ((PangoFont **) inout_font); g_clear_object ((PangoFont **) inout_font);
} }
#define GLYPH_NEEDS_WIDTH (1 << 15)
static gboolean static gboolean
parse_glyphs (GtkCssParser *parser, parse_glyphs (GtkCssParser *parser,
Context *context, Context *context,
@ -1208,6 +1210,7 @@ parse_glyphs (GtkCssParser *parser,
gtk_css_parser_error_value (parser, "Unsupported character %d in string", i); gtk_css_parser_error_value (parser, "Unsupported character %d in string", i);
} }
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + s[i]; gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + s[i];
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
pango_glyph_string_set_size (glyph_string, glyph_string->num_glyphs + 1); pango_glyph_string_set_size (glyph_string, glyph_string->num_glyphs + 1);
glyph_string->glyphs[glyph_string->num_glyphs - 1] = gi; glyph_string->glyphs[glyph_string->num_glyphs - 1] = gi;
} }
@ -1216,14 +1219,22 @@ parse_glyphs (GtkCssParser *parser,
} }
else else
{ {
if (!gtk_css_parser_consume_integer (parser, &i) || if (!gtk_css_parser_consume_integer (parser, &i))
!gtk_css_parser_consume_number (parser, &d))
{ {
pango_glyph_string_free (glyph_string); pango_glyph_string_free (glyph_string);
return FALSE; return FALSE;
} }
gi.glyph = i; gi.glyph = i;
if (gtk_css_parser_has_number (parser))
{
gtk_css_parser_consume_number (parser, &d);
gi.geometry.width = (int) (d * PANGO_SCALE); gi.geometry.width = (int) (d * PANGO_SCALE);
}
else
{
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
}
if (gtk_css_parser_has_number (parser)) if (gtk_css_parser_has_number (parser))
{ {
@ -2193,13 +2204,17 @@ unpack_glyphs (PangoFont *font,
for (i = 0; i < glyphs->num_glyphs; i++) for (i = 0; i < glyphs->num_glyphs; i++)
{ {
PangoGlyph glyph = glyphs->glyphs[i].glyph; PangoGlyphInfo *gi = &glyphs->glyphs[i];
if (glyph < PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH || if (((*(unsigned int *) &gi->attr) & GLYPH_NEEDS_WIDTH) == 0)
glyph >= PANGO_GLYPH_INVALID_INPUT)
continue; continue;
glyph = glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH; *(unsigned int *) &gi->attr &= ~GLYPH_NEEDS_WIDTH;
if (gi->glyph >= PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH &&
gi->glyph < PANGO_GLYPH_INVALID_INPUT)
{
PangoGlyph idx = gi->glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH;
if (ascii == NULL) if (ascii == NULL)
{ {
@ -2208,8 +2223,17 @@ unpack_glyphs (PangoFont *font,
return FALSE; return FALSE;
} }
glyphs->glyphs[i].glyph = ascii->glyphs[glyph].glyph; gi->glyph = ascii->glyphs[idx].glyph;
glyphs->glyphs[i].geometry.width = ascii->glyphs[glyph].geometry.width; gi->geometry.width = ascii->glyphs[idx].geometry.width;
}
else
{
PangoRectangle ink_rect;
pango_font_get_glyph_extents (font, gi->glyph, &ink_rect, NULL);
gi->geometry.width = ink_rect.width;
}
} }
g_clear_pointer (&ascii, pango_glyph_string_free); g_clear_pointer (&ascii, pango_glyph_string_free);
@ -2252,6 +2276,7 @@ parse_text_node (GtkCssParser *parser,
for (i = 0; i < strlen (text); i++) for (i = 0; i < strlen (text); i++)
{ {
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + text[i]; gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + text[i];
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
glyphs->glyphs[i] = gi; glyphs->glyphs[i] = gi;
} }
} }

View File

@ -372,6 +372,7 @@ node_parser_tests = [
'stroke.node', 'stroke.node',
'stroke.ref.node', 'stroke.ref.node',
'testswitch.node', 'testswitch.node',
'text.node',
'text-color.node', 'text-color.node',
'text-fail.node', 'text-fail.node',
'text-fail.ref.node', 'text-fail.ref.node',

View File

@ -1,6 +1,6 @@
text { text {
color: rgb(50,50,50); color: rgb(50,50,50);
font: "Cantarell 11"; font: "Cantarell 14px";
glyphs: "N", 430 5, 406 8, 417 7, 772 4, 783 5, 783 5, 793 6 0 0 same-cluster; glyphs: "N", 430, 406, 417 7, 772 4, 783 5, 783 5, 793 6 0 0 same-cluster;
offset: 0 32.0186; offset: 0 32.0186;
} }

View File

@ -1,6 +1,6 @@
text { text {
color: rgb(50,50,50); color: rgb(50,50,50);
font: "Cantarell 11"; font: "Cantarell 14px";
glyphs: "N", 430 5, 406 8, 417 7, 772 4, 783 5, 783 5, 793 6 0 0 same-cluster; glyphs: "N", 430 5, 406 7, 417 7, 772 4, 783 5, 783 5, 793 6 0 0 same-cluster;
offset: 0 32.0186; offset: 0 32.0186;
} }