X-Git-Url: https://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Fsvgtiny.c;h=3ad6eecb192eaa90b84e0c94b4adff9815383064;hb=8e76cd125e02d4c0d09ad34eea8f46c0511704f0;hp=f6319305c3d2f1c76504766879b9ef55a9e219ea;hpb=545123c6ec9a3d3903e713c1c2919762417538dd;p=libsvgtiny.git diff --git a/src/svgtiny.c b/src/svgtiny.c index f631930..3ad6eec 100644 --- a/src/svgtiny.c +++ b/src/svgtiny.c @@ -697,22 +697,21 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram, lwc_string_unref(svg_name_lwc); dom_string_unref(svg_name); - /* get graphic dimensions */ + /* initialize the state struct with zeros */ memset(&state, 0, sizeof(state)); + + /* get graphic dimensions */ state.diagram = diagram; state.document = document; state.viewport_width = viewport_width; state.viewport_height = viewport_height; - /* Initialize CSS context */ - if (state.select_ctx == NULL) { - css_code = css_select_ctx_create(&state.select_ctx); - if (css_code != CSS_OK) { - dom_node_unref(svg); - dom_node_unref(document); - return svgtiny_LIBCSS_ERROR; - } + css_code = css_select_ctx_create(&state.select_ctx); + if (css_code != CSS_OK) { + dom_node_unref(svg); + dom_node_unref(document); + return svgtiny_LIBCSS_ERROR; } #define SVGTINY_STRING_ACTION2(s,n) \ @@ -2072,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); @@ -2142,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); } }