From aec2f50d82d30324e221529dcf7754f65fe20f28 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 1 Mar 2024 09:20:14 -0500 Subject: [PATCH 1/2] testsuite: Add a forgotten test --- testsuite/gsk/meson.build | 1 + testsuite/gsk/nodeparser/text.node | 2 +- testsuite/gsk/nodeparser/text.ref.node | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 44910eefac..5c3dc2e61b 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -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', diff --git a/testsuite/gsk/nodeparser/text.node b/testsuite/gsk/nodeparser/text.node index 58cd1021f7..4ff166941b 100644 --- a/testsuite/gsk/nodeparser/text.node +++ b/testsuite/gsk/nodeparser/text.node @@ -1,6 +1,6 @@ text { 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; offset: 0 32.0186; } diff --git a/testsuite/gsk/nodeparser/text.ref.node b/testsuite/gsk/nodeparser/text.ref.node index 58cd1021f7..4ff166941b 100644 --- a/testsuite/gsk/nodeparser/text.ref.node +++ b/testsuite/gsk/nodeparser/text.ref.node @@ -1,6 +1,6 @@ text { 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; offset: 0 32.0186; } From f5159e1ecb8b56af530789ef385740106362d176 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 1 Mar 2024 09:12:11 -0500 Subject: [PATCH 2/2] 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. --- demos/node-editor/node-format.md | 2 +- gsk/gskrendernodeparser.c | 53 +++++++++++++++++++------- testsuite/gsk/nodeparser/text.node | 2 +- testsuite/gsk/nodeparser/text.ref.node | 2 +- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/demos/node-editor/node-format.md b/demos/node-editor/node-format.md index 144a3049a9..4b6096b47b 100644 --- a/demos/node-editor/node-format.md +++ b/demos/node-editor/node-format.md @@ -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 diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c index 8c27136767..aff516e86a 100644 --- a/gsk/gskrendernodeparser.c +++ b/gsk/gskrendernodeparser.c @@ -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; - gi.geometry.width = (int) (d * PANGO_SCALE); + + 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,23 +2204,36 @@ 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 (ascii == NULL) + if (gi->glyph >= PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH && + gi->glyph < PANGO_GLYPH_INVALID_INPUT) { - ascii = create_ascii_glyphs (font); - if (ascii == NULL) - return FALSE; - } + PangoGlyph idx = gi->glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH; - glyphs->glyphs[i].glyph = ascii->glyphs[glyph].glyph; - glyphs->glyphs[i].geometry.width = ascii->glyphs[glyph].geometry.width; + if (ascii == NULL) + { + ascii = create_ascii_glyphs (font); + if (ascii == NULL) + return FALSE; + } + + 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; } } diff --git a/testsuite/gsk/nodeparser/text.node b/testsuite/gsk/nodeparser/text.node index 4ff166941b..a483dc2952 100644 --- a/testsuite/gsk/nodeparser/text.node +++ b/testsuite/gsk/nodeparser/text.node @@ -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; } diff --git a/testsuite/gsk/nodeparser/text.ref.node b/testsuite/gsk/nodeparser/text.ref.node index 4ff166941b..f9220e0f49 100644 --- a/testsuite/gsk/nodeparser/text.ref.node +++ b/testsuite/gsk/nodeparser/text.ref.node @@ -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; }