gsk: Make glyph parsing more flexible

It is a bit annoying that one has to specify the glyph width
when specifying glyphs numerically for a text node, since this
information really is part of the font.

Make the parser more flexible, and allow to specify just the glyph
ids, without an explicit width. In this case, the width will be
determined from the font.

With this, glyphs can now be specified in any of the follwing
ways:

glyphs: "ABC";              (ASCII)
glyphs: 23, 45, 1001;       (Glyph IDs)
glyphs: 23 10, 100 11.1;    (Glyph IDs and advance widths)
glyphs: 23 10 1 2 color;    (with offsets and flags)

Tests have been updated to cover these variants.
This commit is contained in:
Matthias Clasen
2024-03-01 09:12:11 -05:00
parent aec2f50d82
commit f5159e1ecb
4 changed files with 42 additions and 17 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

@@ -1,6 +1,6 @@
text {
color: rgb(50,50,50);
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;
}

View File

@@ -1,6 +1,6 @@
text {
color: rgb(50,50,50);
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;
}