From b39f418bca9d0421eca127a11a0fb65bd2c37459 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Fri, 22 May 2020 15:59:47 +0100 Subject: [PATCH] html: Add canvas node handling in dom_event Signed-off-by: Daniel Silverstone --- content/handlers/html/dom_event.c | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/content/handlers/html/dom_event.c b/content/handlers/html/dom_event.c index b702cb304..5470f2942 100644 --- a/content/handlers/html/dom_event.c +++ b/content/handlers/html/dom_event.c @@ -32,6 +32,10 @@ #include "content/content.h" #include "javascript/js.h" +#include "desktop/gui_internal.h" +#include "desktop/gui_table.h" +#include "netsurf/bitmap.h" + #include "html/private.h" #include "html/object.h" #include "html/css.h" @@ -102,6 +106,69 @@ static bool html_process_inserted_base(html_content *htmlc, dom_node *node) return true; } +/** + * deal with events from the DOM for canvas node user data + * + * \param operation The DOM operation happening + * \param key The user data key + * \param data The user data (our bitmap) + * \param src The DOM node emitting the event (our ) + * \param dst The target DOM node if applicable + */ +static void +html__canvas_user_data_handler(dom_node_operation operation, + dom_string *key, + void *data, + struct dom_node *src, + struct dom_node *dst) +{ + struct bitmap *newbitmap, *bitmap = (struct bitmap*)data, *oldbitmap = NULL; + int width, height; + size_t stride; + + if (dom_string_isequal(key,corestring_dom___ns_key_canvas_node_data) == false || data == NULL) { + /* Not for us */ + return; + } + + switch (operation) { + case DOM_NODE_CLONED: + width = guit->bitmap->get_width(bitmap); + height = guit->bitmap->get_height(bitmap); + stride = guit->bitmap->get_rowstride(bitmap); + newbitmap = guit->bitmap->create(width, height, + BITMAP_NEW); + if (newbitmap != NULL) { + if (guit->bitmap->get_rowstride(newbitmap) == stride) { + // Compatible bitmap, bung the data over + memcpy(guit->bitmap->get_buffer(newbitmap), + guit->bitmap->get_buffer(bitmap), + stride * height); + guit->bitmap->modified(newbitmap); + } + } + if (dom_node_set_user_data(dst, + corestring_dom___ns_key_canvas_node_data, + newbitmap, html__canvas_user_data_handler, + &oldbitmap) == DOM_NO_ERR) { + if (oldbitmap != NULL) + guit->bitmap->destroy(oldbitmap); + } + break; + + case DOM_NODE_RENAMED: + case DOM_NODE_IMPORTED: + case DOM_NODE_ADOPTED: + break; + + case DOM_NODE_DELETED: + guit->bitmap->destroy(bitmap); + break; + default: + NSLOG(netsurf, INFO, "User data operation not handled."); + assert(0); + } +} /** * process a canvas element being inserted into the DOM @@ -112,6 +179,72 @@ static bool html_process_inserted_base(html_content *htmlc, dom_node *node) */ static nserror html_process_inserted_canvas(html_content *htmlc, dom_node *node) { + dom_exception exc; + dom_string *width_s = NULL, *height_s = NULL; + unsigned long width = 300, height = 150; + struct bitmap *bitmap, *oldbitmap = NULL; + + exc = dom_element_get_attribute(node, + corestring_dom_width, + &width_s); + if (exc == DOM_NO_ERR && width_s != NULL) { + const char *ptr = (const char *)dom_string_data(width_s); + const char *endptr = ptr + dom_string_length(width_s); + char * ended; + unsigned long width_n = strtoul(ptr, &ended, 10); + + if (ended == endptr) { + /* parsed it all */ + width = width_n; + } + + dom_string_unref(width_s); + } + + exc = dom_element_get_attribute(node, + corestring_dom_height, + &height_s); + if (exc == DOM_NO_ERR && height_s != NULL) { + const char *ptr = (const char *)dom_string_data(height_s); + const char *endptr = ptr + dom_string_length(height_s); + char * ended; + unsigned long height_n = strtoul(ptr, &ended, 10); + + if (ended == endptr) { + /* parsed it all */ + height = height_n; + } + + dom_string_unref(height_s); + } + + bitmap = guit->bitmap->create( + (int)width, (int)height, + BITMAP_NEW); + + if (bitmap == NULL) { + return NSERROR_NOMEM; + } + + memset(guit->bitmap->get_buffer(bitmap), + 0, /* Transparent black */ + height * guit->bitmap->get_rowstride(bitmap)); + guit->bitmap->modified(bitmap); + + exc = dom_node_set_user_data(node, + corestring_dom___ns_key_canvas_node_data, + bitmap, + html__canvas_user_data_handler, + &oldbitmap); + + if (exc != DOM_NO_ERR) { + guit->bitmap->destroy(bitmap); + return NSERROR_DOM; + } + + if (oldbitmap != NULL) + guit->bitmap->destroy(oldbitmap); + return NSERROR_OK; }