From 4cac79efd99b8b68d47e80f4cd8c18f23c376c38 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Tue, 17 Oct 2023 11:35:13 -0400 Subject: [PATCH] src/svgtiny_css.c: add user handler function This function needs to be passed to dom_node_set_user_data() in set_libcss_node_data(), but we couldn't implement it before our css_select_handler was defined, because it passes the address of that select handler to css_libcss_node_data_handler(). --- src/svgtiny_css.c | 76 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/src/svgtiny_css.c b/src/svgtiny_css.c index e24bd0b..f86e3da 100644 --- a/src/svgtiny_css.c +++ b/src/svgtiny_css.c @@ -1858,6 +1858,59 @@ css_error ua_default_for_property(void *pw, uint32_t property, } +/** + * A "user handler" function that we pass to dom_node_set_user_data() + * in set_libcss_node_data(). The set_libcss_node_data() documentation + * says that if the node (on which data is set) is is deleted or + * cloned, or if its ancestors are modified, then we must call + * css_libcss_node_data_handler() on the user data. This function + * basically just checks to see which DOM event has happened and + * calls css_libcss_node_data_handler() when any of those criteria + * are met. + */ +static void svgtiny_dom_user_data_handler(dom_node_operation operation, + dom_string *key, void *data, struct dom_node *src, + struct dom_node *dst) +{ + /* Technically we should compare "key" against the one used in + * get/set_libcss_node_data(), but at the moment libcss is the + * only user of this libdom feature, and eliding the compare + * saves us the trouble of figuring out how to reference that + * interned_userdata_key from this handler. */ + UNUSED(key); + + if (data == NULL) { + /* No data */ + return; + } + + /* Check the DOM operation, and make the corresponding call to + * css_libcss_node_data_handler(). No error handling is done. + */ + switch (operation) { + case DOM_NODE_CLONED: + css_libcss_node_data_handler(&svgtiny_select_handler, + CSS_NODE_CLONED, + NULL, src, dst, data); + break; + case DOM_NODE_RENAMED: + css_libcss_node_data_handler(&svgtiny_select_handler, + CSS_NODE_MODIFIED, + NULL, src, NULL, data); + break; + case DOM_NODE_IMPORTED: + case DOM_NODE_ADOPTED: + case DOM_NODE_DELETED: + css_libcss_node_data_handler(&svgtiny_select_handler, + CSS_NODE_DELETED, + NULL, src, NULL, data); + break; + default: + /* Our list of cases should have been exhaustive */ + assert(false); + } +} + /** * Store libcss data on a node * @@ -1869,13 +1922,15 @@ css_error ua_default_for_property(void *pw, uint32_t property, * \param node Libdom SVG node on which to store the data * \param libcss_node_data Pointer to the data to store * - * \return Always returns CSS_OK + * \return CSS_OK on success, CSS_NOMEM if libdom runs out of memory, + * or CSS_INVALID if any other error occurs */ css_error set_libcss_node_data(void *pw, void *node, void *libcss_node_data) { struct svgtiny_parse_state *state; void *old_data; + dom_exception err; /* A unique "userdata key" (a string) is used to identify this * data. The fourth parameter (NULL) is a "user handler @@ -1883,13 +1938,20 @@ css_error set_libcss_node_data(void *pw, void *node, * it to NULL to avoid a circular reference mess that would * break the build temporarily. */ state = (struct svgtiny_parse_state *)pw; - dom_node_set_user_data((dom_node *)node, - state->interned_userdata_key, - libcss_node_data, - NULL, - &old_data); - /* dom_node_set_user_data() always returns DOM_NO_ERR */ + err = dom_node_set_user_data((dom_node *)node, + state->interned_userdata_key, + libcss_node_data, + NULL, + &old_data); + + if (err == DOM_NO_MEM_ERR) { + return CSS_NOMEM; + } + else if (err != DOM_NO_ERR) { + return CSS_INVALID; + } + return CSS_OK; } -- 2.49.0