]> gitweb.michael.orlitzky.com - libsvgtiny.git/commitdiff
src/svgtiny_css.c: implement node_is_empty() select handler
authorMichael Orlitzky <michael@orlitzky.com>
Sat, 14 Oct 2023 15:39:20 +0000 (11:39 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 20 Nov 2023 16:42:26 +0000 (11:42 -0500)
src/svgtiny_css.c

index ffc9c3e6ce1baf18d6f462c40752fd64b818a3a0..ebf432d3fa6bbfeb5e0ec5aa3b67f56ab3f5dccf 100644 (file)
@@ -45,6 +45,7 @@ static css_error node_has_attribute_substring(void *pw, void *node,
 static css_error node_is_root(void *pw, void *node, bool *match);
 static css_error node_count_siblings(void *pw, void *node,
                bool same_name, bool after, int32_t *count);
+static css_error node_is_empty(void *pw, void *node, bool *is_empty);
 
 
 /**
@@ -1363,3 +1364,65 @@ css_error node_count_siblings(void *pw, void *node,
 
        return CSS_OK;
 }
+
+
+/**
+ * Determine whether or not the given element is empty
+ *
+ * An element is "nonempty" if it has a child that is either an
+ * element node or a text node.
+ *
+ * \param pw          Pointer to the current SVG parser state
+ * \param node        Libdom SVG node to check for emptiness
+ * \param is_empty    Pointer to the return value
+ *
+ * \return CSS_OK on success, or CSS_NOMEM if anything goes wrong
+ */
+css_error node_is_empty(void *pw, void *node, bool *is_empty)
+{
+       UNUSED(pw);
+       dom_node *child; /* current child node pointer */
+       dom_node *next;  /* next child node pointer */
+       dom_node_type type; /* what type of node is "child" */
+       dom_exception err;
+
+       /* Assume that it's empty by default */
+       *is_empty = true;
+
+       /* Get the given node's first child. Implementation detail:
+        * this increments the reference counter on the child node. */
+       err = dom_node_get_first_child((dom_node *)node, &child);
+       if (err != DOM_NO_ERR) {
+               return CSS_NOMEM;
+       }
+
+       /* And now loop through all children looking for a
+        * text/element node. If we find one, the original
+        * node is "nonempty" */
+       while (child != NULL) {
+               err = dom_node_get_node_type(child, &type);
+               if (err != DOM_NO_ERR) {
+                       dom_node_unref(child);
+                       return CSS_NOMEM;
+               }
+
+               if (type == DOM_ELEMENT_NODE || type == DOM_TEXT_NODE) {
+                       *is_empty = false;
+                       dom_node_unref(child);
+                       return CSS_OK;
+               }
+
+               err = dom_node_get_next_sibling(child, &next);
+               if (err != DOM_NO_ERR) {
+                       dom_node_unref(child);
+                       return CSS_NOMEM;
+               }
+
+               /* If we're moving to the next node, we can release
+                * the reference to the current one */
+               dom_node_unref(child);
+               child = next;
+       }
+
+       return CSS_OK;
+}