+
+
+/**
+ * Check if the given node is "active"
+ *
+ * This check always fails because the SVG DOM does not have the
+ * necessary information (it's a UI property).
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param node Libdom SVG node to check; unused
+ * \param is_active Pointer to the boolean return value
+ *
+ * \return Always returns CSS_OK
+ */
+css_error node_is_active(void *pw, void *node, bool *is_active)
+{
+ UNUSED(pw);
+ UNUSED(node);
+ *is_active = false;
+ return CSS_OK;
+}
+
+
+/**
+ * Check if the given node has the focus
+ *
+ * This check always fails because the SVG DOM does not have the
+ * necessary information (it's a UI property).
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param node Libdom SVG node to check; unused
+ * \param is_focus Pointer to the boolean return value
+ *
+ * \return Always returns CSS_OK
+ */
+css_error node_is_focus(void *pw, void *node, bool *is_focus)
+{
+ UNUSED(pw);
+ UNUSED(node);
+ *is_focus = false;
+ return CSS_OK;
+}
+
+
+/**
+ * Check if the given node is enabled
+ *
+ * This check always fails because the SVG DOM does not have the
+ * necessary information (it's a UI property).
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param node Libdom SVG node to check; unused
+ * \param is_enabled Pointer to the boolean return value
+ *
+ * \return Always returns CSS_OK
+ */
+css_error node_is_enabled(void *pw, void *node, bool *is_enabled)
+{
+ UNUSED(pw);
+ UNUSED(node);
+ *is_enabled = false;
+ return CSS_OK;
+}
+
+
+/**
+ * Check if the given node is disabled
+ *
+ * This check always fails because the SVG DOM does not have the
+ * necessary information (it's a UI property). Beware, until they are
+ * implemented, this is NOT the logical negation of node_is_enabled!
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param node Libdom SVG node to check; unused
+ * \param is_disabled Pointer to the boolean return value
+ *
+ * \return Always returns CSS_OK
+ */
+css_error node_is_disabled(void *pw, void *node, bool *is_disabled)
+{
+ UNUSED(pw);
+ UNUSED(node);
+ *is_disabled = false;
+ return CSS_OK;
+}
+
+
+/**
+ * Test whether or not the given node is "checked"
+ *
+ * This test always fails because the SVG DOM does not have the
+ * necessary information (it's a UI property).
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param node Libdom SVG node to check; unused
+ * \param is_checked Pointer to the boolean return value
+ *
+ * \return Always returns CSS_OK
+ */
+css_error node_is_checked(void *pw, void *node, bool *is_checked)
+{
+ UNUSED(pw);
+ UNUSED(node);
+ *is_checked = false;
+ return CSS_OK;
+}
+
+
+/**
+ * Check if the given node is the "target" of the document URL
+ *
+ * This test always fails because the SVG DOM does not have the
+ * necessary information (it's a UI property).
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param node Libdom SVG node to check; unused
+ * \param is_target Pointer to the boolean return value
+ *
+ * \return Always returns CSS_OK
+ */
+css_error node_is_target(void *pw, void *node, bool *is_target)
+{
+ UNUSED(pw);
+ UNUSED(node);
+ *is_target = false;
+ return CSS_OK;
+}
+
+
+/**
+ * Check if the given node is the given language
+ *
+ * This test is corresponds to the CSS :lang() selector and is not
+ * fully implemented yet: it looks only for "lang" attributes on the
+ * given element and its parents, and performs a simple substring
+ * check. This results in a partial implementation of CSS Level 3 for
+ * SVG 2.0. In particular, it ignores all "xml:lang" attributes in
+ * favor of the "lang" attribute that is defined only in SVG 2.0.
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param node Libdom SVG node to check
+ * \param lang The language to match
+ * \param is_lang Pointer to the boolean return value
+ *
+ * \return CSS_OK on success, or CSS_NOMEM if anything goes wrong
+ */
+static css_error node_is_lang(void *pw, void *node,
+ lwc_string *lang, bool *is_lang)
+{
+ UNUSED(pw);
+ /* SVG2 elements support both "lang" and "xml:lang"
+ * attributes; earlier versions have only the XML
+ * attribute. It would not be too hard to add support for
+ * xml:lang" here. The main difficulty standing in the way of
+ * a full Level 4 implementation is the complexity of the
+ * :lang() selector:
+ *
+ * https://www.w3.org/TR/selectors-4/#the-lang-pseudo
+ *
+ */
+
+ css_error c_err;
+ dom_exception d_err;
+ dom_node *n; /* current node */
+ dom_node *p; /* parent node */
+ bool match; /* retval from node_has_attribute_substring() */
+
+ /* Define the attribute name "lang" that we're looking for.
+ * We only use a css_qname here because that's what the
+ * node_has_attribute_substring() takes; the namespace
+ * portion of it is irrelevant. */
+ css_qname attr;
+ attr.ns = NULL;
+
+ if (lwc_intern_string("lang", 4, &attr.name) != lwc_error_ok) {
+ return CSS_NOMEM;
+ }
+
+ *is_lang = false; /* default to no match */
+ n = (dom_node *)node;
+
+ /* Loop through all parents of the given node looking for a
+ * substring match */
+ while (n != NULL) {
+ c_err = _node_has_attribute_substring(pw, (void *)n, &attr,
+ lang, &match, true);
+ if (c_err != CSS_OK) {
+ lwc_string_destroy(attr.name);
+ return c_err;
+ }
+ if (match) {
+ /* matched this element; we're done */
+ lwc_string_destroy(attr.name);
+ *is_lang = true;
+ return CSS_OK;
+ }
+
+ /* no match on this element, try its parent */
+ d_err = dom_node_get_parent_node(n, &p);
+ if (d_err != DOM_NO_ERR) {
+ lwc_string_destroy(attr.name);
+ return CSS_NOMEM;
+ }
+ n = p;
+ }
+
+ /* If we never find a match we may wind up here */
+ lwc_string_destroy(attr.name);
+ return CSS_OK;
+}
+
+
+/**
+ * User-agent defaults for CSS properties
+ *
+ * For the moment, we provide no defaults, because libsvgtiny does not
+ * yet support any CSS properties that might need them.
+ *
+ * \param pw Pointer to the current SVG parser state; unused
+ * \param property LibCSS property identifier; unused
+ * \param hint Pointer to hint object (a return value); unused
+ *
+ * \return Always returns CSS_INVALID
+ */
+css_error ua_default_for_property(void *pw, uint32_t property,
+ css_hint *hint)
+{
+ UNUSED(pw);
+ UNUSED(property);
+ UNUSED(hint);
+ return CSS_INVALID;
+}