#include <cairo-script-interpreter.h>
#endif
+typedef struct _Context Context;
+
+struct _Context
+{
+ GHashTable *named_nodes;
+ GHashTable *named_textures;
+};
+
typedef struct _Declaration Declaration;
struct _Declaration
{
const char *name;
- gboolean (* parse_func) (GtkCssParser *parser, gpointer result);
+ gboolean (* parse_func) (GtkCssParser *parser, Context *context, gpointer result);
void (* clear_func) (gpointer data);
gpointer result;
};
+static void
+context_init (Context *context)
+{
+ memset (context, 0, sizeof (Context));
+}
+
+static void
+context_finish (Context *context)
+{
+ g_clear_pointer (&context->named_nodes, g_hash_table_unref);
+ g_clear_pointer (&context->named_textures, g_hash_table_unref);
+}
+
static gboolean
parse_rect (GtkCssParser *parser,
+ Context *context,
gpointer out_rect)
{
double numbers[4];
static gboolean
parse_vec4 (GtkCssParser *parser,
+ Context *context,
gpointer out_vec4)
{
double numbers[4];
static gboolean
parse_texture (GtkCssParser *parser,
+ Context *context,
gpointer out_data)
{
GdkTexture *texture;
static gboolean
parse_script (GtkCssParser *parser,
+ Context *context,
gpointer out_data)
{
#ifdef HAVE_CAIRO_SCRIPT_INTERPRETER
static gboolean
parse_rounded_rect (GtkCssParser *parser,
+ Context *context,
gpointer out_rect)
{
graphene_rect_t r;
double d;
guint i;
- if (!parse_rect (parser, &r))
+ if (!parse_rect (parser, context, &r))
return FALSE;
if (!gtk_css_parser_try_delim (parser, '/'))
static gboolean
parse_color (GtkCssParser *parser,
+ Context *context,
gpointer out_color)
{
return gdk_rgba_parser_parse (parser, out_color);
static gboolean
parse_double (GtkCssParser *parser,
+ Context *context,
gpointer out_double)
{
return gtk_css_parser_consume_number (parser, out_double);
static gboolean
parse_point (GtkCssParser *parser,
+ Context *context,
gpointer out_point)
{
double x, y;
static gboolean
parse_transform (GtkCssParser *parser,
+ Context *context,
gpointer out_transform)
{
GskTransform *transform;
static gboolean
parse_string (GtkCssParser *parser,
+ Context *context,
gpointer out_string)
{
const GtkCssToken *token;
static gboolean
parse_stops (GtkCssParser *parser,
+ Context *context,
gpointer out_stops)
{
GArray *stops;
static gboolean
parse_float4 (GtkCssParser *parser,
+ Context *context,
gpointer out_floats)
{
float *floats = (float *) out_floats;
static gboolean
parse_colors4 (GtkCssParser *parser,
+ Context *context,
gpointer out_colors)
{
GdkRGBA colors[4];
static gboolean
parse_shadows (GtkCssParser *parser,
+ Context *context,
gpointer out_shadows)
{
GArray *shadows = out_shadows;
static gboolean
parse_scaling_filter (GtkCssParser *parser,
+ Context *context,
gpointer out_filter)
{
for (unsigned int i = 0; i < G_N_ELEMENTS (scaling_filters); i++)
static gboolean
parse_blend_mode (GtkCssParser *parser,
+ Context *context,
gpointer out_mode)
{
guint i;
static gboolean
parse_mask_mode (GtkCssParser *parser,
+ Context *context,
gpointer out_mode)
{
guint i;
static gboolean
parse_font (GtkCssParser *parser,
+ Context *context,
gpointer out_font)
{
PangoFont *font;
static gboolean
parse_glyphs (GtkCssParser *parser,
+ Context *context,
gpointer out_glyphs)
{
PangoGlyphString *glyph_string;
}
static gboolean
-parse_node (GtkCssParser *parser, gpointer out_node);
+parse_node (GtkCssParser *parser, Context *context, gpointer out_node);
static void
clear_node (gpointer inout_node)
}
static GskRenderNode *
-parse_container_node (GtkCssParser *parser)
+parse_container_node (GtkCssParser *parser,
+ Context *context)
{
GPtrArray *nodes;
const GtkCssToken *token;
*/
gtk_css_parser_start_semicolon_block (parser, GTK_CSS_TOKEN_OPEN_CURLY);
- if (parse_node (parser, &node))
+ if (parse_node (parser, context, &node))
g_ptr_array_add (nodes, node);
gtk_css_parser_end_block (parser);
static guint
parse_declarations (GtkCssParser *parser,
+ Context *context,
const Declaration *declarations,
guint n_declarations)
{
if (declarations[i].clear_func)
declarations[i].clear_func (declarations[i].result);
}
- if (!declarations[i].parse_func (parser, declarations[i].result))
+ if (!declarations[i].parse_func (parser, context, declarations[i].result))
{
/* nothing to do */
}
}
static GskRenderNode *
-parse_color_node (GtkCssParser *parser)
+parse_color_node (GtkCssParser *parser,
+ Context *context)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
GdkRGBA color = GDK_RGBA("FF00CC");
{ "color", parse_color, NULL, &color },
};
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
return gsk_color_node_new (&color, &bounds);
}
static GskRenderNode *
parse_linear_gradient_node_internal (GtkCssParser *parser,
+ Context *context,
gboolean repeating)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (stops == NULL)
{
GskColorStop from = { 0.0, GDK_RGBA("AAFF00") };
}
static GskRenderNode *
-parse_linear_gradient_node (GtkCssParser *parser)
+parse_linear_gradient_node (GtkCssParser *parser,
+ Context *context)
{
- return parse_linear_gradient_node_internal (parser, FALSE);
+ return parse_linear_gradient_node_internal (parser, context, FALSE);
}
static GskRenderNode *
-parse_repeating_linear_gradient_node (GtkCssParser *parser)
+parse_repeating_linear_gradient_node (GtkCssParser *parser,
+ Context *context)
{
- return parse_linear_gradient_node_internal (parser, TRUE);
+ return parse_linear_gradient_node_internal (parser, context, TRUE);
}
static GskRenderNode *
parse_radial_gradient_node_internal (GtkCssParser *parser,
+ Context *context,
gboolean repeating)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (stops == NULL)
{
GskColorStop from = { 0.0, GDK_RGBA("AAFF00") };
}
static GskRenderNode *
-parse_radial_gradient_node (GtkCssParser *parser)
+parse_radial_gradient_node (GtkCssParser *parser,
+ Context *context)
{
- return parse_radial_gradient_node_internal (parser, FALSE);
+ return parse_radial_gradient_node_internal (parser, context, FALSE);
}
static GskRenderNode *
-parse_repeating_radial_gradient_node (GtkCssParser *parser)
+parse_repeating_radial_gradient_node (GtkCssParser *parser,
+ Context *context)
{
- return parse_radial_gradient_node_internal (parser, TRUE);
+ return parse_radial_gradient_node_internal (parser, context, TRUE);
}
static GskRenderNode *
-parse_conic_gradient_node (GtkCssParser *parser)
+parse_conic_gradient_node (GtkCssParser *parser,
+ Context *context)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
graphene_point_t center = GRAPHENE_POINT_INIT (25, 25);
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (stops == NULL)
{
GskColorStop from = { 0.0, GDK_RGBA("AAFF00") };
}
static GskRenderNode *
-parse_inset_shadow_node (GtkCssParser *parser)
+parse_inset_shadow_node (GtkCssParser *parser,
+ Context *context)
{
GskRoundedRect outline = GSK_ROUNDED_RECT_INIT (0, 0, 50, 50);
GdkRGBA color = GDK_RGBA("000000");
{ "blur", parse_double, NULL, &blur }
};
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
return gsk_inset_shadow_node_new (&outline, &color, dx, dy, spread, blur);
}
static gboolean
parse_shader (GtkCssParser *parser,
+ Context *context,
gpointer out_shader_info)
{
ShaderInfo *shader_info = out_shader_info;
GBytes *bytes;
GskGLShader *shader;
- if (!parse_string (parser, &sourcecode))
+ if (!parse_string (parser, context, &sourcecode))
return FALSE;
bytes = g_bytes_new_take (sourcecode, strlen (sourcecode));
}
static gboolean
-parse_shader_args (GtkCssParser *parser, gpointer data)
+parse_shader_args (GtkCssParser *parser,
+ Context *context,
+ gpointer data)
{
ShaderInfo *shader_info = data;
int n_uniforms;
}
static GskRenderNode *
-parse_glshader_node (GtkCssParser *parser)
+parse_glshader_node (GtkCssParser *parser,
+ Context *context)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
GskRenderNode *child[4] = { NULL, };
GBytes *args = NULL;
int len, i;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
for (len = 0; len < 4; len++)
{
}
static GskRenderNode *
-parse_mask_node (GtkCssParser *parser)
+parse_mask_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *source = NULL;
GskRenderNode *mask = NULL;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS(declarations));
if (source == NULL)
source = create_default_render_node ();
if (mask == NULL)
}
static GskRenderNode *
-parse_border_node (GtkCssParser *parser)
+parse_border_node (GtkCssParser *parser,
+ Context *context)
{
GskRoundedRect outline = GSK_ROUNDED_RECT_INIT (0, 0, 50, 50);
float widths[4] = { 1, 1, 1, 1 };
{ "colors", parse_colors4, NULL, &colors }
};
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
return gsk_border_node_new (&outline, widths, colors);
}
static GskRenderNode *
-parse_texture_node (GtkCssParser *parser)
+parse_texture_node (GtkCssParser *parser,
+ Context *context)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
GdkTexture *texture = NULL;
};
GskRenderNode *node;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (texture == NULL)
texture = create_default_texture ();
}
static GskRenderNode *
-parse_texture_scale_node (GtkCssParser *parser)
+parse_texture_scale_node (GtkCssParser *parser,
+ Context *context)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
GdkTexture *texture = NULL;
};
GskRenderNode *node;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (texture == NULL)
texture = create_default_texture ();
}
static GskRenderNode *
-parse_cairo_node (GtkCssParser *parser)
+parse_cairo_node (GtkCssParser *parser,
+ Context *context)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
GdkTexture *pixels = NULL;
};
GskRenderNode *node;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
node = gsk_cairo_node_new (&bounds);
}
static GskRenderNode *
-parse_outset_shadow_node (GtkCssParser *parser)
+parse_outset_shadow_node (GtkCssParser *parser,
+ Context *context)
{
GskRoundedRect outline = GSK_ROUNDED_RECT_INIT (0, 0, 50, 50);
GdkRGBA color = GDK_RGBA("000000");
{ "blur", parse_double, NULL, &blur }
};
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
return gsk_outset_shadow_node_new (&outline, &color, dx, dy, spread, blur);
}
static GskRenderNode *
-parse_transform_node (GtkCssParser *parser)
+parse_transform_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *child = NULL;
GskTransform *transform = NULL;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
}
static GskRenderNode *
-parse_opacity_node (GtkCssParser *parser)
+parse_opacity_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *child = NULL;
double opacity = 0.5;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
}
static GskRenderNode *
-parse_color_matrix_node (GtkCssParser *parser)
+parse_color_matrix_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *child = NULL;
graphene_matrix_t matrix;
graphene_vec4_init (&offset, 0, 0, 0, 0);
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
}
static GskRenderNode *
-parse_cross_fade_node (GtkCssParser *parser)
+parse_cross_fade_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *start = NULL;
GskRenderNode *end = NULL;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (start == NULL)
start = gsk_color_node_new (&GDK_RGBA("AAFF00"), &GRAPHENE_RECT_INIT (0, 0, 50, 50));
if (end == NULL)
}
static GskRenderNode *
-parse_blend_node (GtkCssParser *parser)
+parse_blend_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *bottom = NULL;
GskRenderNode *top = NULL;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (bottom == NULL)
bottom = gsk_color_node_new (&GDK_RGBA("AAFF00"), &GRAPHENE_RECT_INIT (0, 0, 50, 50));
if (top == NULL)
}
static GskRenderNode *
-parse_repeat_node (GtkCssParser *parser)
+parse_repeat_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *child = NULL;
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 0, 0);
GskRenderNode *result;
guint parse_result;
- parse_result = parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_result = parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
}
static GskRenderNode *
-parse_text_node (GtkCssParser *parser)
+parse_text_node (GtkCssParser *parser,
+ Context *context)
{
PangoFont *font = NULL;
graphene_point_t offset = GRAPHENE_POINT_INIT (0, 0);
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (font == NULL)
{
}
static GskRenderNode *
-parse_blur_node (GtkCssParser *parser)
+parse_blur_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *child = NULL;
double blur_radius = 1.0;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
}
static GskRenderNode *
-parse_clip_node (GtkCssParser *parser)
+parse_clip_node (GtkCssParser *parser,
+ Context *context)
{
GskRoundedRect clip = GSK_ROUNDED_RECT_INIT (0, 0, 50, 50);
GskRenderNode *child = NULL;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
}
static GskRenderNode *
-parse_rounded_clip_node (GtkCssParser *parser)
+parse_rounded_clip_node (GtkCssParser *parser,
+ Context *context)
{
GskRoundedRect clip = GSK_ROUNDED_RECT_INIT (0, 0, 50, 50);
GskRenderNode *child = NULL;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
}
static GskRenderNode *
-parse_shadow_node (GtkCssParser *parser)
+parse_shadow_node (GtkCssParser *parser,
+ Context *context)
{
GskRenderNode *child = NULL;
GArray *shadows = g_array_new (FALSE, TRUE, sizeof (GskShadow));
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
}
static GskRenderNode *
-parse_debug_node (GtkCssParser *parser)
+parse_debug_node (GtkCssParser *parser,
+ Context *context)
{
char *message = NULL;
GskRenderNode *child = NULL;
};
GskRenderNode *result;
- parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
+ parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
static gboolean
parse_node (GtkCssParser *parser,
+ Context *context,
gpointer out_node)
{
static struct {
const char *name;
- GskRenderNode * (* func) (GtkCssParser *);
+ GskRenderNode * (* func) (GtkCssParser *, Context *);
} node_parsers[] = {
{ "blend", parse_blend_node },
{ "blur", parse_blur_node },
return FALSE;
}
gtk_css_parser_end_block_prelude (parser);
- node = node_parsers[i].func (parser);
+ node = node_parsers[i].func (parser, context);
if (node)
{
if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
{
GskRenderNode *root = NULL;
GtkCssParser *parser;
+ Context context;
struct {
GskParseErrorFunc error_func;
gpointer user_data;
parser = gtk_css_parser_new_for_bytes (bytes, NULL, gsk_render_node_parser_error,
&error_func_pair, NULL);
- root = parse_container_node (parser);
+ context_init (&context);
+ root = parse_container_node (parser, &context);
if (root && gsk_container_node_get_n_children (root) == 1)
{
root = child;
}
+ context_finish (&context);
gtk_css_parser_unref (parser);
return root;