From ed4af4e7777f98484593f6b046d70402d2099903 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 13 May 2019 00:47:50 +0200 Subject: [PATCH 1/2] rendernodeparser: Introduce clear_func We want to be able to clear the already parsed contents, because we need to do that when somebody parses the same property twice. --- gsk/gskrendernodeparser.c | 177 +++++++++++++++++++++++++------------- 1 file changed, 118 insertions(+), 59 deletions(-) diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c index 234ef487a4..81a2e8e899 100644 --- a/gsk/gskrendernodeparser.c +++ b/gsk/gskrendernodeparser.c @@ -17,6 +17,7 @@ struct _Declaration { const char *name; gboolean (* parse_func) (GtkCssParser *parser, gpointer result); + void (* clear_func) (gpointer data); gpointer result; }; @@ -135,6 +136,12 @@ parse_texture (GtkCssParser *parser, return TRUE; } +static void +clear_texture (gpointer inout_texture) +{ + g_clear_object ((GdkTexture **) inout_texture); +} + static gboolean parse_rounded_rect (GtkCssParser *parser, gpointer out_rect) @@ -277,6 +284,12 @@ parse_transform (GtkCssParser *parser, return TRUE; } +static void +clear_transform (gpointer inout_transform) +{ + g_clear_pointer ((GskTransform **) inout_transform, gsk_transform_unref); +} + static gboolean parse_string (GtkCssParser *parser, gpointer out_string) @@ -303,6 +316,12 @@ parse_string (GtkCssParser *parser, return TRUE; } +static void +clear_string (gpointer inout_string) +{ + g_clear_pointer ((char **) inout_string, g_free); +} + static gboolean parse_stops (GtkCssParser *parser, gpointer out_stops) @@ -353,6 +372,18 @@ error: return FALSE; } +static void +clear_stops (gpointer inout_stops) +{ + GArray **stops = (GArray **) inout_stops; + + if (*stops) + { + g_array_free (*stops, TRUE); + *stops = NULL; + } +} + static gboolean parse_colors4 (GtkCssParser *parser, gpointer out_colors) @@ -407,6 +438,12 @@ parse_shadows (GtkCssParser *parser, return check_eof (parser); } +static void +clear_shadows (gpointer inout_shadows) +{ + g_array_set_size (*(GArray **) inout_shadows, 0); +} + static const struct { GskBlendMode mode; @@ -480,6 +517,12 @@ parse_font (GtkCssParser *parser, return check_eof (parser); } +static void +clear_font (gpointer inout_font) +{ + g_clear_object ((PangoFont **) inout_font); +} + static gboolean parse_glyphs (GtkCssParser *parser, gpointer out_glyphs) @@ -533,9 +576,21 @@ parse_glyphs (GtkCssParser *parser, return check_eof (parser); } +static void +clear_glyphs (gpointer inout_glyphs) +{ + g_clear_pointer ((PangoGlyphString **) inout_glyphs, pango_glyph_string_free); +} + static gboolean parse_node (GtkCssParser *parser, gpointer out_node); +static void +clear_node (gpointer inout_node) +{ + g_clear_pointer ((GskRenderNode **) inout_node, gsk_render_node_unref); +} + static GskRenderNode * parse_container_node (GtkCssParser *parser) { @@ -599,7 +654,11 @@ parse_declarations (GtkCssParser *parser, { gtk_css_parser_consume_token (parser); if (parsed & (1 << i)) - gtk_css_parser_warn_syntax (parser, "Variable \"%s\" defined multiple times", declarations[i].name); + { + gtk_css_parser_warn_syntax (parser, "Variable \"%s\" defined multiple times", declarations[i].name); + if (declarations[i].clear_func) + declarations[i].clear_func (declarations[i].result); + } if (declarations[i].parse_func (parser, declarations[i].result)) parsed |= (1 << i); } @@ -626,8 +685,8 @@ parse_color_node (GtkCssParser *parser) graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 0, 0); GdkRGBA color = { 0, 0, 0, 1 }; const Declaration declarations[] = { - { "bounds", parse_rect, &bounds }, - { "color", parse_color, &color }, + { "bounds", parse_rect, NULL, &bounds }, + { "color", parse_color, NULL, &color }, }; parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); @@ -643,10 +702,10 @@ parse_linear_gradient_node (GtkCssParser *parser) graphene_point_t end = GRAPHENE_POINT_INIT (0, 0); GArray *stops = NULL; const Declaration declarations[] = { - { "bounds", parse_rect, &bounds }, - { "start", parse_point, &start }, - { "end", parse_point, &end }, - { "stops", parse_stops, &stops }, + { "bounds", parse_rect, NULL, &bounds }, + { "start", parse_point, NULL, &start }, + { "end", parse_point, NULL, &end }, + { "stops", parse_stops, clear_stops, &stops }, }; GskRenderNode *result; @@ -668,15 +727,15 @@ static GskRenderNode * parse_inset_shadow_node (GtkCssParser *parser) { GskRoundedRect outline = GSK_ROUNDED_RECT_INIT (0, 0, 0, 0); - GdkRGBA color = { 0, 0, 0, 0 }; - double dx, dy, blur, spread; + GdkRGBA color = { 0, 0, 0, 1 }; + double dx = 1, dy = 1, blur = 0, spread = 0; const Declaration declarations[] = { - { "outline", parse_rounded_rect, &outline }, - { "color", parse_color, &color }, - { "dx", parse_double, &dx }, - { "dy", parse_double, &dy }, - { "spread", parse_double, &spread }, - { "blur", parse_double, &blur } + { "outline", parse_rounded_rect, NULL, &outline }, + { "color", parse_color, NULL, &color }, + { "dx", parse_double, NULL, &dx }, + { "dy", parse_double, NULL, &dy }, + { "spread", parse_double, NULL, &spread }, + { "blur", parse_double, NULL, &blur } }; parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); @@ -691,9 +750,9 @@ parse_border_node (GtkCssParser *parser) graphene_rect_t widths = GRAPHENE_RECT_INIT (0, 0, 0, 0); GdkRGBA colors[4] = { { 0, 0, 0, 0 }, {0, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 0 } }; const Declaration declarations[] = { - { "outline", parse_rounded_rect, &outline }, - { "widths", parse_rect, &widths }, - { "colors", parse_colors4, &colors } + { "outline", parse_rounded_rect, NULL, &outline }, + { "widths", parse_rect, NULL, &widths }, + { "colors", parse_colors4, NULL, &colors } }; parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); @@ -707,8 +766,8 @@ parse_texture_node (GtkCssParser *parser) graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 0, 0); GdkTexture *texture = NULL; const Declaration declarations[] = { - { "bounds", parse_rect, &bounds }, - { "texture", parse_texture, &texture } + { "bounds", parse_rect, NULL, &bounds }, + { "texture", parse_texture, clear_texture, &texture } }; GskRenderNode *node; @@ -730,15 +789,15 @@ static GskRenderNode * parse_outset_shadow_node (GtkCssParser *parser) { GskRoundedRect outline = GSK_ROUNDED_RECT_INIT (0, 0, 0, 0); - GdkRGBA color = { 0, 0, 0, 0 }; - double dx, dy, blur, spread; + GdkRGBA color = { 0, 0, 0, 1 }; + double dx = 1, dy = 1, blur = 0, spread = 0; const Declaration declarations[] = { - { "outline", parse_rounded_rect, &outline }, - { "color", parse_color, &color }, - { "dx", parse_double, &dx }, - { "dy", parse_double, &dy }, - { "spread", parse_double, &spread }, - { "blur", parse_double, &blur } + { "outline", parse_rounded_rect, NULL, &outline }, + { "color", parse_color, NULL, &color }, + { "dx", parse_double, NULL, &dx }, + { "dy", parse_double, NULL, &dy }, + { "spread", parse_double, NULL, &spread }, + { "blur", parse_double, NULL, &blur } }; parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); @@ -752,8 +811,8 @@ parse_transform_node (GtkCssParser *parser) GskRenderNode *child = NULL; GskTransform *transform = NULL; const Declaration declarations[] = { - { "transform", parse_transform, &transform }, - { "child", parse_node, &child }, + { "transform", parse_transform, clear_transform, &transform }, + { "child", parse_node, clear_node, &child }, }; GskRenderNode *result; @@ -782,8 +841,8 @@ parse_opacity_node (GtkCssParser *parser) GskRenderNode *child = NULL; double opacity = 1.0; const Declaration declarations[] = { - { "opacity", parse_double, &opacity }, - { "child", parse_node, &child }, + { "opacity", parse_double, NULL, &opacity }, + { "child", parse_node, clear_node, &child }, }; GskRenderNode *result; @@ -810,9 +869,9 @@ parse_color_matrix_node (GtkCssParser *parser) graphene_rect_t offset_rect = GRAPHENE_RECT_INIT (0, 0, 0, 0); graphene_vec4_t offset; const Declaration declarations[] = { - { "matrix", parse_transform, &transform }, - { "offset", parse_rect, &offset_rect }, - { "child", parse_node, &child } + { "matrix", parse_transform, clear_transform, &transform }, + { "offset", parse_rect, NULL, &offset_rect }, + { "child", parse_node, clear_node, &child } }; GskRenderNode *result; @@ -844,9 +903,9 @@ parse_cross_fade_node (GtkCssParser *parser) GskRenderNode *end = NULL; double progress = 0.5; const Declaration declarations[] = { - { "progress", parse_double, &progress }, - { "start", parse_node, &start }, - { "end", parse_node, &end }, + { "progress", parse_double, NULL, &progress }, + { "start", parse_node, clear_node, &start }, + { "end", parse_node, clear_node, &end }, }; GskRenderNode *result; @@ -877,9 +936,9 @@ parse_blend_node (GtkCssParser *parser) GskRenderNode *top = NULL; GskBlendMode mode = GSK_BLEND_MODE_DEFAULT; const Declaration declarations[] = { - { "mode", parse_blend_mode, &mode }, - { "bottom", parse_node, &bottom }, - { "top", parse_node, &top }, + { "mode", parse_blend_mode, NULL, &mode }, + { "bottom", parse_node, clear_node, &bottom }, + { "top", parse_node, clear_node, &top }, }; GskRenderNode *result; @@ -910,9 +969,9 @@ parse_repeat_node (GtkCssParser *parser) graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 0, 0); graphene_rect_t child_bounds = GRAPHENE_RECT_INIT (0, 0, 0, 0); const Declaration declarations[] = { - { "child", parse_node, &child }, - { "bounds", parse_rect, &bounds }, - { "child-bounds", parse_rect, &child_bounds }, + { "child", parse_node, clear_node, &child }, + { "bounds", parse_rect, NULL, &bounds }, + { "child-bounds", parse_rect, NULL, &child_bounds }, }; GskRenderNode *result; guint parse_result; @@ -945,11 +1004,11 @@ parse_text_node (GtkCssParser *parser) GdkRGBA color = { 0, 0, 0, 1 }; PangoGlyphString *glyphs = NULL; const Declaration declarations[] = { - { "font", parse_font, &font }, - { "x", parse_double, &x }, - { "y", parse_double, &y }, - { "color", parse_color, &color }, - { "glyphs", parse_glyphs, &glyphs } + { "font", parse_font, clear_font, &font }, + { "x", parse_double, NULL, &x }, + { "y", parse_double, NULL, &y }, + { "color", parse_color, NULL, &color }, + { "glyphs", parse_glyphs, clear_glyphs, &glyphs } }; GskRenderNode *result; @@ -972,8 +1031,8 @@ parse_blur_node (GtkCssParser *parser) GskRenderNode *child = NULL; double blur_radius = 0.0; const Declaration declarations[] = { - { "blur", parse_double, &blur_radius }, - { "child", parse_node, &child }, + { "blur", parse_double, NULL, &blur_radius }, + { "child", parse_node, clear_node, &child }, }; GskRenderNode *result; @@ -997,8 +1056,8 @@ parse_clip_node (GtkCssParser *parser) graphene_rect_t clip = GRAPHENE_RECT_INIT (0, 0, 0, 0); GskRenderNode *child = NULL; const Declaration declarations[] = { - { "clip", parse_rect, &clip }, - { "child", parse_node, &child }, + { "clip", parse_rect, NULL, &clip }, + { "child", parse_node, clear_node, &child }, }; GskRenderNode *result; @@ -1022,8 +1081,8 @@ parse_rounded_clip_node (GtkCssParser *parser) GskRoundedRect clip = GSK_ROUNDED_RECT_INIT (0, 0, 0, 0); GskRenderNode *child = NULL; const Declaration declarations[] = { - { "clip", parse_rounded_rect, &clip }, - { "child", parse_node, &child }, + { "clip", parse_rounded_rect, NULL, &clip }, + { "child", parse_node, clear_node, &child }, }; GskRenderNode *result; @@ -1047,8 +1106,8 @@ parse_shadow_node (GtkCssParser *parser) GskRenderNode *child = NULL; GArray *shadows = g_array_new (FALSE, TRUE, sizeof (GskShadow)); const Declaration declarations[] = { - { "child", parse_node, &child }, - { "shadows", parse_shadows, shadows } + { "child", parse_node, clear_node, &child }, + { "shadows", parse_shadows, clear_shadows, shadows } }; GskRenderNode *result; @@ -1079,8 +1138,8 @@ parse_debug_node (GtkCssParser *parser) char *message = NULL; GskRenderNode *child = NULL; const Declaration declarations[] = { - { "message", parse_string, &message}, - { "child", parse_node, &child }, + { "message", parse_string, clear_string, &message}, + { "child", parse_node, clear_node, &child }, }; GskRenderNode *result; From 57061ea7dfb011081298558a3655164cf83ec050 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 13 May 2019 00:59:15 +0200 Subject: [PATCH 2/2] rendernodeparser: Move EOF test into parse_declarations() This way, we don't have to duplicate code. Plus, we can ensure to clear the erroneously parsed value that should not be used. --- gsk/gskrendernodeparser.c | 127 ++++++++++---------------------------- 1 file changed, 34 insertions(+), 93 deletions(-) diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c index 81a2e8e899..e0b881310d 100644 --- a/gsk/gskrendernodeparser.c +++ b/gsk/gskrendernodeparser.c @@ -22,24 +22,8 @@ struct _Declaration }; static gboolean -check_eof (GtkCssParser *parser) -{ - const GtkCssToken *token; - - token = gtk_css_parser_get_token (parser); - if (!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF)) - { - gtk_css_parser_error_syntax (parser, "Expected ';' at end of statement"); - return FALSE; - } - - gtk_css_parser_consume_token (parser); - return TRUE; -} - -static gboolean -parse_rect_without_semicolon (GtkCssParser *parser, - graphene_rect_t *out_rect) +parse_rect (GtkCssParser *parser, + gpointer out_rect) { double numbers[4]; @@ -54,20 +38,6 @@ parse_rect_without_semicolon (GtkCssParser *parser, return TRUE; } -static gboolean -parse_rect (GtkCssParser *parser, - gpointer out_rect) -{ - graphene_rect_t r; - - if (!parse_rect_without_semicolon (parser, &r) || - !check_eof (parser)) - return FALSE; - - graphene_rect_init_from_rect (out_rect, &r); - return TRUE; -} - static gboolean parse_texture (GtkCssParser *parser, gpointer out_data) @@ -126,12 +96,6 @@ parse_texture (GtkCssParser *parser, return FALSE; } - if (!check_eof (parser)) - { - g_object_unref (texture); - return FALSE; - } - *(GdkTexture **) out_data = texture; return TRUE; } @@ -151,13 +115,11 @@ parse_rounded_rect (GtkCssParser *parser, double d; guint i; - if (!parse_rect_without_semicolon (parser, &r)) + if (!parse_rect (parser, &r)) return FALSE; if (!gtk_css_parser_try_delim (parser, '/')) { - if (!check_eof (parser)) - return FALSE; gsk_rounded_rect_init_from_rect (out_rect, &r, 0); return TRUE; } @@ -211,9 +173,6 @@ parse_rounded_rect (GtkCssParser *parser, corners[i].height = corners[i].width; } - if (!check_eof (parser)) - return FALSE; - gsk_rounded_rect_init (out_rect, &r, &corners[0], &corners[1], &corners[2], &corners[3]); return TRUE; @@ -223,30 +182,14 @@ static gboolean parse_color (GtkCssParser *parser, gpointer out_color) { - GdkRGBA color; - - if (!gdk_rgba_parser_parse (parser, &color) || - !check_eof (parser)) - return FALSE; - - *(GdkRGBA *) out_color = color; - - return TRUE; + return gdk_rgba_parser_parse (parser, out_color); } static gboolean parse_double (GtkCssParser *parser, gpointer out_double) { - double d; - - if (!gtk_css_parser_consume_number (parser, &d) || - !check_eof (parser)) - return FALSE; - - *(double *) out_double = d; - - return TRUE; + return gtk_css_parser_consume_number (parser, out_double); } static gboolean @@ -256,8 +199,7 @@ parse_point (GtkCssParser *parser, double x, y; if (!gtk_css_parser_consume_number (parser, &x) || - !gtk_css_parser_consume_number (parser, &y) || - !check_eof (parser)) + !gtk_css_parser_consume_number (parser, &y)) return FALSE; graphene_point_init (out_point, x, y); @@ -271,14 +213,12 @@ parse_transform (GtkCssParser *parser, { GskTransform *transform; - if (!gsk_transform_parser_parse (parser, &transform) || - !check_eof (parser)) + if (!gsk_transform_parser_parse (parser, &transform)) { gsk_transform_unref (transform); return FALSE; } - gsk_transform_unref (*(GskTransform **) out_transform); *(GskTransform **) out_transform = transform; return TRUE; @@ -304,12 +244,6 @@ parse_string (GtkCssParser *parser, s = g_strdup (token->string.string); gtk_css_parser_consume_token (parser); - if (!check_eof (parser)) - { - g_free (s); - return FALSE; - } - g_free (*(char **) out_string); *(char **) out_string = s; @@ -365,7 +299,7 @@ parse_stops (GtkCssParser *parser, g_array_free (*(GArray **) out_stops, TRUE); *(GArray **) out_stops = stops; - return check_eof (parser); + return TRUE; error: g_array_free (stops, TRUE); @@ -397,7 +331,7 @@ parse_colors4 (GtkCssParser *parser, return FALSE; } - return check_eof (parser); + return TRUE; } static gboolean @@ -435,7 +369,7 @@ parse_shadows (GtkCssParser *parser, break; } - return check_eof (parser); + return TRUE; } static void @@ -477,8 +411,6 @@ parse_blend_mode (GtkCssParser *parser, { if (gtk_css_parser_try_ident (parser, blend_modes[i].name)) { - if (!check_eof (parser)) - return FALSE; *(GskBlendMode *) out_mode = blend_modes[i].mode; return TRUE; } @@ -514,7 +446,7 @@ parse_font (GtkCssParser *parser, /* Skip font name token */ gtk_css_parser_consume_token (parser); - return check_eof (parser); + return TRUE; } static void @@ -573,7 +505,7 @@ parse_glyphs (GtkCssParser *parser, *((PangoGlyphString **)out_glyphs) = glyph_string; - return check_eof (parser); + return TRUE; } static void @@ -630,45 +562,54 @@ parse_declarations (GtkCssParser *parser, { guint parsed = 0; guint i; - const GtkCssToken *token; g_assert (n_declarations < 8 * sizeof (guint)); - for (token = gtk_css_parser_get_token (parser); - !gtk_css_token_is (token, GTK_CSS_TOKEN_EOF); - token = gtk_css_parser_get_token (parser)) + while (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF)) { gtk_css_parser_start_semicolon_block (parser, GTK_CSS_TOKEN_OPEN_CURLY); for (i = 0; i < n_declarations; i++) { - if (gtk_css_token_is_ident (token, declarations[i].name)) + if (gtk_css_parser_try_ident (parser, declarations[i].name)) { - gtk_css_parser_consume_token (parser); - token = gtk_css_parser_get_token (parser); - if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COLON)) + if (!gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COLON)) { gtk_css_parser_error_syntax (parser, "Expected ':' after variable declaration"); } else { - gtk_css_parser_consume_token (parser); if (parsed & (1 << i)) { gtk_css_parser_warn_syntax (parser, "Variable \"%s\" defined multiple times", declarations[i].name); + /* Unset, just to be sure */ + parsed &= ~(1 << i); if (declarations[i].clear_func) declarations[i].clear_func (declarations[i].result); } - if (declarations[i].parse_func (parser, declarations[i].result)) - parsed |= (1 << i); + if (!declarations[i].parse_func (parser, declarations[i].result)) + { + /* nothing to do */ + } + else if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF)) + { + gtk_css_parser_error_syntax (parser, "Expected ';' at end of statement"); + if (declarations[i].clear_func) + declarations[i].clear_func (declarations[i].result); + } + else + { + parsed |= (1 << i); + } } break; } } if (i == n_declarations) { - if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT)) - gtk_css_parser_error_syntax (parser, "No variable named \"%s\"", token->string.string); + if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT)) + gtk_css_parser_error_syntax (parser, "No variable named \"%s\"", + gtk_css_parser_get_token (parser)->string.string); else gtk_css_parser_error_syntax (parser, "Expected a variable name"); }