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

View File

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

View File

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

View File

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