]> gitweb.michael.orlitzky.com - libsvgtiny.git/blobdiff - src/svgtiny.c
src/svgtiny.c: add impotent svgtiny_preparse_styles() function
[libsvgtiny.git] / src / svgtiny.c
index 2ca5a58664f46077a5ce4358b91f16b28b06eb8c..8cb1eff2f283adf74b00eb42dc6b1bed4078bcd0 100644 (file)
@@ -17,6 +17,8 @@
 #include <dom/dom.h>
 #include <dom/bindings/xml/xmlparser.h>
 
+#include <libcss/libcss.h>
+
 #include "svgtiny.h"
 #include "svgtiny_internal.h"
 
@@ -38,6 +40,8 @@
 #define degToRad(angleInDegrees) ((angleInDegrees) * M_PI / 180.0)
 #define radToDeg(angleInRadians) ((angleInRadians) * 180.0 / M_PI)
 
+static svgtiny_code svgtiny_preparse_styles(dom_element *svg,
+               struct svgtiny_parse_state state);
 static svgtiny_code svgtiny_parse_svg(dom_element *svg,
                struct svgtiny_parse_state state);
 static svgtiny_code svgtiny_parse_path(dom_element *path,
@@ -610,6 +614,7 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram,
                const char *buffer, size_t size, const char *url,
                int viewport_width, int viewport_height)
 {
+       css_error css_code;
        dom_document *document;
        dom_exception exc;
        dom_xml_parser *parser;
@@ -695,6 +700,17 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram,
        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;
+               }
+       }
+
 #define SVGTINY_STRING_ACTION2(s,n)                                    \
        if (dom_string_create_interned((const uint8_t *) #n,            \
                                       strlen(#n), &state.interned_##s) \
@@ -723,10 +739,17 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram,
        state.stroke_width = 1;
 
        /* parse tree */
-       code = svgtiny_parse_svg(svg, state);
+       code = svgtiny_preparse_styles(svg, state);
+       if (code == svgtiny_OK) {
+               code = svgtiny_parse_svg(svg, state);
+       }
 
        dom_node_unref(svg);
        dom_node_unref(document);
+       css_code = css_select_ctx_destroy(state.select_ctx);
+       if (css_code != CSS_OK) {
+               code = svgtiny_LIBCSS_ERROR;
+       }
 
 cleanup:
        svgtiny_cleanup_state_local(&state);
@@ -738,6 +761,68 @@ cleanup:
        return code;
 }
 
+/**
+ * Parse all <style> elements within a root <svg> element. This
+ * should be called before svgtiny_parse_svg() because that function
+ * makes a single pass through the document and we'd like all style
+ * information to be available during that pass. Specifically, we'd
+ * like a <style> sheet at the end of the document to affect the
+ * rendering of elements at its beginning.
+ *
+ * The element-parsing inner loop here is essentially the same as
+ * that within svgtiny_parse_svg().
+ */
+svgtiny_code svgtiny_preparse_styles(dom_element *svg,
+               struct svgtiny_parse_state state)
+{
+       dom_element *child;
+       dom_exception exc;
+
+       exc = dom_node_get_first_child(svg, (dom_node **) (void *) &child);
+       if (exc != DOM_NO_ERR) {
+               return svgtiny_LIBDOM_ERROR;
+       }
+       while (child != NULL) {
+               dom_element *next;
+               dom_node_type nodetype;
+               svgtiny_code code = svgtiny_OK;
+
+               exc = dom_node_get_node_type(child, &nodetype);
+               if (exc != DOM_NO_ERR) {
+                       dom_node_unref(child);
+                       return svgtiny_LIBDOM_ERROR;
+               }
+               if (nodetype == DOM_ELEMENT_NODE) {
+                       dom_string *nodename;
+                       exc = dom_node_get_node_name(child, &nodename);
+                       if (exc != DOM_NO_ERR) {
+                               dom_node_unref(child);
+                               return svgtiny_LIBDOM_ERROR;
+                       }
+
+                       if (dom_string_caseless_isequal(state.interned_style,
+                                                       nodename)) {
+                               /* We have a <style> element, parse it */
+                       }
+
+
+                       dom_string_unref(nodename);
+               }
+               if (code != svgtiny_OK) {
+                       dom_node_unref(child);
+                       return code;
+               }
+               exc = dom_node_get_next_sibling(child,
+                                               (dom_node **) (void *) &next);
+               dom_node_unref(child);
+               if (exc != DOM_NO_ERR) {
+                       return svgtiny_LIBDOM_ERROR;
+               }
+               child = next;
+       }
+
+       return svgtiny_OK;
+}
 
 /**
  * Parse a <svg> or <g> element node.