From a551398a54d213ba87f88ff5c4cd193c8a684369 Mon Sep 17 00:00:00 2001 From: Patryk Kubiak Date: Mon, 5 Oct 2026 15:06:30 +0200 Subject: [PATCH] dmvs_html: what a car HMI page needs - listeners, inline SVG, images From converting a second real page (a 480x272 car HMI in Tailwind): Scripts - addEventListener('click', ...) and el.onclick = ... set up while the page loads, with arrow / function expressions closing over their scope; querySelector() / querySelectorAll() (css_select), forEach() unrolled, getAttribute(), el.click() running an element's handlers, string concatenation. - Several class changes of an element in one handler are one look of it (MOD_CLASSES "+a -b", a _look variable for its looks). - visibility: hidden fades as opacity 0. Layout and style - tailwind.config's theme.extend.fontFamily (Inter as font-sans). - The static position of an absolutely positioned flex child follows justify-content / align-items. - content: '' makes a ::before / ::after box (a nav indicator). Images - object-fit / object-position of ; background-image: url() under its gradients, background-size, background-position (also in the background shorthand); filter: blur() blurs the image - as dmvsi_image_t width / height / blur and DMVSI_IMAGE_* placement. Tailwind's bg-cover, bg-center, object-cover, ... - Inline : a replaced element whose subtree is written into an SVG file of its box's size ($TMPDIR, -svg.svg), the viewBox and camelCase names kept, currentColor resolved; drawn as an image (dmimg_svg rasterizes it). The dmodOS fixture converts to the same view as before. Needs dmvsi with dmvsi_image_t width / height / blur. Co-Authored-By: Claude Opus 5.5 --- CMakeLists.txt | 1 + Makefile | 2 +- README.md | 24 +- src/css.c | 43 +++ src/dmvs_html.c | 22 ++ src/layout.c | 35 +- src/paint.c | 66 +++- src/private.h | 20 ++ src/script.c | 739 +++++++++++++++++++++++++++++++++++------ src/style.c | 158 ++++++++- src/svg.c | 255 ++++++++++++++ src/tailwind.c | 156 ++++++++- tests/dmvs_html_test.c | 132 ++++++++ 13 files changed, 1542 insertions(+), 111 deletions(-) create mode 100644 src/svg.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 37802d3..6c47ad7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ dmod_add_library(${DMOD_MODULE_NAME} ${DMOD_MODULE_VERSION} src/style.c src/layout.c src/paint.c + src/svg.c src/script.c ) diff --git a/Makefile b/Makefile index d5f558a..519e4ca 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ DMOD_MODULE_VERSION=0.1 DMOD_AUTHOR_NAME=Patryk Kubiak # The list of C sources -DMOD_CSOURCES=src/dmvs_html.c src/html.c src/css.c src/tailwind.c src/style.c src/layout.c src/paint.c src/script.c +DMOD_CSOURCES=src/dmvs_html.c src/html.c src/css.c src/tailwind.c src/style.c src/layout.c src/paint.c src/svg.c src/script.c # The list of C++ sources DMOD_CXXSOURCES= diff --git a/README.md b/README.md index 1079b19..3e9ac91 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,9 @@ it works out at conversion and makes the view's variables and handlers. **HTML** - elements, attributes, text with character references, the end tags a page may leave out, ``, `
`. `")); + dmvsi_doc_t doc = convert(TEST_FILE("listeners.html"), "screen", 0, 0, &status); + DMOD_TEST_EXPECT_EQ(status, 0); + if (doc == NULL) + return; + const dmvsi_node_t* root = dmvsi_root(doc); + + /* forEach is unrolled: each tab is clicked with a handler of its own, and looks active by a variable */ + const dmvsi_node_t* a = group_named(root->first, "a"); + const dmvsi_node_t* b = group_named(root->first, "b"); + DMOD_TEST_EXPECT_TRUE(a != NULL && b != NULL && a->click != 0 && b->click != 0 && a->click != b->click); + if (a != NULL && b != NULL) + { + const dmvsi_action_t* acts = NULL; + uint32_t n = dmvsi_handler_actions(doc, b->click, &acts); + bool sets = false; + for (uint32_t i = 0; i < n; i++) + sets = sets || acts[i].kind == DMVSI_ACT_SET; + DMOD_TEST_EXPECT_TRUE(sets); + } + dmvsi_free(doc); +}