From: Michael Orlitzky Date: Sat, 7 Jun 2025 15:17:04 +0000 (-0400) Subject: src/svgtiny.c: parse styles in svgtiny_parse_inline_style() X-Git-Url: https://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=100c5be75722327cf20ad16816361f8ffcd45600;p=libsvgtiny.git src/svgtiny.c: parse styles in svgtiny_parse_inline_style() 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. --- diff --git a/src/svgtiny_parse.c b/src/svgtiny_parse.c index 566a8c0..180b50c 100644 --- a/src/svgtiny_parse.c +++ b/src/svgtiny_parse.c @@ -1535,14 +1535,23 @@ svgtiny_parse_inline_style(dom_element *node, const char *declaration_start; 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; + /* style attribute */ exc = dom_element_get_attribute(node, state->interned_style, &attr); if (exc != DOM_NO_ERR) { @@ -1578,8 +1587,49 @@ svgtiny_parse_inline_style(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 svgtiny_OK; + } + 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 svgtiny_LIBCSS_ERROR; + } + + 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); } return svgtiny_OK;