From 0312d7177af048a89e0259f78bceda9123b517fc Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Tue, 17 Oct 2023 20:09:42 -0400 Subject: [PATCH] src/svgtiny.c: parse styles in svgtiny_parse_paint_attributes() Now that the scaffolding is in place, we do the work to parse our two supported CSS paint attributes, fill-opacity and stroke-opacity. This amounts to, * Calling svgtiny_select_style(), which is just a wrapper around css_select_style() * Passing the result to css_computed_foo_opacity() to get the computed styles * Populating fill_opacity and stroke_opacity in the parser state if the corresponding styles exist There's also a temporary hack to avoid crashing on the root node that later goes away when we implement parent/child style composition. --- src/svgtiny.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/src/svgtiny.c b/src/svgtiny.c index a77e3b4..3ad6eec 100644 --- a/src/svgtiny.c +++ b/src/svgtiny.c @@ -2071,14 +2071,23 @@ void svgtiny_parse_paint_attributes(dom_element *node, { dom_string *attr; dom_exception exc; + css_error code; + uint8_t fill_opacity_type; + css_fixed fill_opacity; + uint8_t stroke_opacity_type; + css_fixed stroke_opacity; /* We store the result of svgtiny_parse_style_inline() in * inline_sheet, and that function returns NULL on error; in * particular you do not need to css_stylesheet_destroy() the - * result if it is NULL. We initialize inline_sheet to NULL to - * retain the same semantics. */ + * result if it is NULL, and css_stylesheet_destroy() checks + * for that case. */ css_stylesheet *inline_sheet = NULL; + /* Initialize this to NULL for the same reason: so that we can + * safely destroy it later even if we never populated it. */ + css_select_results *styles = NULL; + exc = dom_element_get_attribute(node, state->interned_fill, &attr); if (exc == DOM_NO_ERR && attr != NULL) { svgtiny_parse_color(attr, &state->fill, &state->fill_grad, state); @@ -2141,8 +2150,49 @@ void svgtiny_parse_paint_attributes(dom_element *node, dom_string_unref(attr); } - if (inline_sheet != NULL) { + struct dom_element *parent; + dom_element_parent_node(node, &parent); + if (parent == NULL) { + /* This is the root node, skip it. + * + * While initialising its selection state, libcss sets its + * node_data->bloom pointer using css__get_parent_bloom(). + * But if there is no parent, that function returns, + * + * static css_bloom empty_bloom[CSS_BLOOM_SIZE]; + * + * A problem later arises because when libcss FINALISES its + * selection state, it frees node_data->bloom! That obviously + * won't work then node has no parent, i.e. if it's the root + * element. + */ css_stylesheet_destroy(inline_sheet); + return; + } + else { + /* We only needed to know if it was NULL */ + dom_node_unref(parent); + } + + code = svgtiny_select_style(state, node, inline_sheet, &styles); + css_stylesheet_destroy(inline_sheet); + if (code != CSS_OK) { + return; + } + + fill_opacity_type = css_computed_fill_opacity( + styles->styles[CSS_PSEUDO_ELEMENT_NONE], + &fill_opacity); + stroke_opacity_type = css_computed_stroke_opacity( + styles->styles[CSS_PSEUDO_ELEMENT_NONE], + &stroke_opacity); + css_select_results_destroy(styles); + + if (fill_opacity_type == CSS_FILL_OPACITY_SET) { + state->fill_opacity = FIXTOFLT(fill_opacity); + } + if (stroke_opacity_type == CSS_STROKE_OPACITY_SET) { + state->stroke_opacity = FIXTOFLT(stroke_opacity); } } -- 2.44.2