From 0320cd64ebfd86bac6318ed5299fc871d3cdcfe7 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 26 Sep 2026 18:32:30 +0900 Subject: [PATCH] better alpha blending --- include/Mw/Draw.h | 6 +++ include/Mw/LowLevel.h | 5 +- include/Mw/TypeDefs.h | 13 +++-- src/backend/cairo.c | 9 ++-- src/backend/cocoa.m | 6 +-- src/backend/gdi.c | 9 ++++ src/backend/wayland/interfaces.c | 26 ++++----- src/backend/wayland/wayland.c | 14 ++--- src/backend/x11.c | 4 ++ src/core.c | 93 ++++++++++++++++++++------------ src/dialog/colorpicker.c | 2 +- src/dialog/filechooser.c | 12 ++--- src/dialog/messagebox.c | 2 +- src/draw.c | 38 +++++++++++-- src/text/ft2.c | 2 +- src/text/gdi.c | 2 +- src/text/stbtt.c | 2 +- src/text/text.c | 2 +- src/widget/calendar.c | 6 +-- src/widget/label.c | 2 +- src/widget/opengl.c | 2 +- 21 files changed, 170 insertions(+), 87 deletions(-) diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index 12d3d453..aec81984 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -184,6 +184,12 @@ MWDECL unsigned char* MWAPI MwPixmapGetRaw(MwLLPixmap pixmap); */ MWDECL void MWAPI MwPixmapGetSize(MwLLPixmap pixmap, MwRect* rect); +/*! + * @brief Destroys the pixmap + * @param pixmap Pixmap + */ +MWDECL void MWAPI MwDestroyPixmap(MwLLPixmap pixmap); + /*! * @brief Creates a pixmap from XPM data * @param handle Widget diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 8822f68a..6ae7f2c6 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -34,7 +34,7 @@ enum MwLLBackends { }; struct _MwLLCommon { - void* user; + void* internal; int copy_buffer; int type; int coordinate_type; @@ -58,7 +58,8 @@ struct _MwLLCommonPixmap { int width; int height; unsigned char* raw; - void* user; + unsigned char* before_blend; + void* internal; }; #ifdef USE_DBUS diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 7ac9417c..c9a7575b 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -99,11 +99,14 @@ struct _MwWidget { int prop_event; int held; - void* internal; - void* opaque; - void* user; - void (*draw_inject)(MwWidget handle); - void (*destroy_inject)(MwWidget handle); + void* internal; + void* opaque; + void* user; + MwHandler draw_inject; + MwHandler destroy_inject; + MwHandlerProp prop_inject_pixmap; /* this is for pixmap; do not use */ + + MwLLPixmap* pixmaps; MwIntegerKeyValue* integer; MwTextKeyValue* text; diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 49f315c7..6764f6ff 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -46,10 +46,12 @@ MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, if(width >= INT16_MAX) width = INT16_MAX; if(height >= INT16_MAX) height = INT16_MAX; - r->common.width = width; - r->common.height = height; - r->common.raw = malloc(4 * width * height); + r->common.width = width; + r->common.height = height; + r->common.raw = malloc(4 * width * height); + r->common.before_blend = malloc(4 * width * height); memcpy(r->common.raw, data, 4 * width * height); + memcpy(r->common.before_blend, data, 4 * width * height); r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); @@ -80,6 +82,7 @@ void MwLLCairoPixmapUpdate(MwLLPixmap r) { void MwLLCairoDestroyPixmap(MwLLPixmap pixmap) { cairo_surface_destroy(pixmap->wayland.cs); + free(pixmap->common.before_blend); free(pixmap->common.raw); free(pixmap); } diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 85b8b5bd..06e7c0e2 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -64,7 +64,7 @@ static inline NSPoint localPointFlip(NSPoint point, NSView* view) { /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, key, k); if(h) { int i; @@ -78,7 +78,7 @@ static void recursive_dispatch_key(MwLL handle, int* k) { }; /* Recursively dispatch a key released event to a widget and its children */ static void recursive_dispatch_key_released(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, key_released, k); if(h) { int i; @@ -637,7 +637,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [topmost_parent->cocoa.real->view setNeedsDisplay:true]; MwLLDispatch(topmost_parent, draw, NULL); - h = (MwWidget)topmost_parent->common.user; + h = (MwWidget)topmost_parent->common.intenral; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 2013b9a1..65432d94 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -665,6 +665,14 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid memcpy(r->common.raw, data, 4 * width * height); + r->common.before_blend = malloc(width * height * 4); + if(!r->common.before_blend) { + printf("Out Of Memory\n"); + return NULL; + } + + memcpy(r->common.before_blend, data, 4 * width * height); + r->common.width = width; r->common.height = height; @@ -740,6 +748,7 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap r) { } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + free(pixmap->common.before_blend); free(pixmap->common.raw); DeleteObject(pixmap->gdi.hMask); DeleteObject(pixmap->gdi.hMask2); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 1b9fe1a5..6ad54067 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -23,7 +23,7 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, key, k); if(h) { int i; @@ -37,7 +37,7 @@ static void recursive_dispatch_key(MwLL handle, int* k) { }; /* Recursively dispatch a key released event to a widget and its children */ static void recursive_dispatch_key_released(MwLL handle, int* k) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, key_released, k); if(h) { int i; @@ -52,7 +52,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { /* Recursively dispatch a move event to a widget and its children */ static void recursive_dispatch_move(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { @@ -165,8 +165,8 @@ static void wl_data_device_leave(void* data, static MwBool motion_cursor_change(MwLL self, wl_clipboard_device_context_t* ctx) { if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) { return MwTRUE; - } else if(self->common.user) { - MwWidget w = self->common.user; + } else if(self->common.intenral) { + MwWidget w = self->common.intenral; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -190,8 +190,8 @@ static MwBool motion_cursor_change(MwLL self, wl_clipboard_device_context_t* ctx static void clipboard_dispatch(MwLL self, char* buf) { if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL && self->wayland.accepts_dnd) { MwLLDispatch(self, drag_and_drop, buf); - } else if(self->common.user) { - MwWidget w = self->common.user; + } else if(self->common.intenral) { + MwWidget w = self->common.intenral; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -722,7 +722,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time }; static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, down, p); if(h) { int i; @@ -735,7 +735,7 @@ static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { } }; static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; MwLLDispatch(handle, up, p); if(h) { int i; @@ -793,8 +793,8 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { break; } - if(self->common.user) { - MwWidget w = self->common.user; + if(self->common.intenral) { + MwWidget w = self->common.intenral; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -963,8 +963,8 @@ static void keyboard_leave(void* data, }; void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down) { - if(self->common.user) { - MwWidget w = self->common.user; + if(self->common.intenral) { + MwWidget w = self->common.intenral; int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 973b6f47..b3dbcac2 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -14,8 +14,8 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { - if(handle->common.user) { - MwWidget w = handle->common.user; + if(handle->common.intenral) { + MwWidget w = handle->common.intenral; int i; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { @@ -30,7 +30,7 @@ static int event_loop(MwLL handle); /* Recursively dispatch a resize event to a widget and its children */ static void recursive_dispatch_resize(MwLL handle) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.intenral; if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { @@ -45,7 +45,7 @@ static void recursive_dispatch_resize(MwLL handle) { static void recursive_render(MwLL handle) { int i; - for(i = 0; i < arrlen(((MwWidget)handle->common.user)->children); i++) recursive_render(((MwWidget)handle->common.user)->children[i]->lowlevel); + for(i = 0; i < arrlen(((MwWidget)handle->common.intenral)->children); i++) recursive_render(((MwWidget)handle->common.intenral)->children[i]->lowlevel); MwLLForceRender(handle); } @@ -512,7 +512,7 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); if(parent) { - MwWidget p = parent->common.user; + MwWidget p = parent->common.intenral; while(topmost_parent->wayland.parent) { topmost_parent = topmost_parent->wayland.parent; } @@ -1944,11 +1944,11 @@ static void MwLLRaiseImpl(MwLL handle) { MwLL topmost_parent = handle; int children_num; while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - children_num = arrlen(((MwWidget)topmost_parent->common.user)->children); + children_num = arrlen(((MwWidget)topmost_parent->common.intenral)->children); if(children_num > 1) { printf("%d\n", children_num); - MwWidget last_child = ((MwWidget)topmost_parent->common.user)->children[children_num - 1]; + MwWidget last_child = ((MwWidget)topmost_parent->common.intenral)->children[children_num - 1]; wl_subsurface_place_above(handle->wayland.sublevel->subsurface, last_child->lowlevel->wayland.framebuffer.surface); } }*/ diff --git a/src/backend/x11.c b/src/backend/x11.c index b713821e..e44b3a15 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1097,6 +1097,9 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid r->common.raw = malloc(4 * width * height); memcpy(r->common.raw, data, 4 * width * height); + r->common.before_blend = malloc(4 * width * height); + memcpy(r->common.before_blend, data, 4 * width * height); + XGetWindowAttributes(handle->x11.display, handle->x11.window, &attr); r->common.width = width; @@ -1152,6 +1155,7 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap r) { } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + free(pixmap->common.before_blend); free(pixmap->common.raw); XDestroyImage(pixmap->x11.image); XDestroyImage(pixmap->x11.mask); diff --git a/src/core.c b/src/core.c index 9776c184..a2e520fd 100644 --- a/src/core.c +++ b/src/core.c @@ -30,11 +30,17 @@ } \ } +#define PROP(handle, key) \ + { \ + MwDispatch3((handle), prop_change, (key)); \ + if((handle)->prop_inject_pixmap != NULL) handle->prop_inject_pixmap((handle), (key)); \ + } + static void MWAPI MwVaListApply_Internal(MwWidget handle, va_list va, int only_early); static MwWidget MWAPI MwCreateWidget_Internal(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height, int do_prop, va_list prop); static void lldrawhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; #ifdef PERIODIC MwWidget top; #endif @@ -67,7 +73,7 @@ static void lldrawhandler(MwLL handle, void* data) { } static void lluphandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; MwMouse* p = data; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -82,7 +88,7 @@ static void lluphandler(MwLL handle, void* data) { } static void lldownhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; MwMouse* p = data; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -96,7 +102,7 @@ static void lldownhandler(MwLL handle, void* data) { } static void llresizehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; #ifdef RESIZE_ON_TICK MwWidget top; #endif @@ -129,7 +135,7 @@ static void llresizehandler(MwLL handle, void* data) { } static void llclosehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; (void)data; @@ -147,7 +153,7 @@ static void llclosehandler(MwLL handle, void* data) { } static void llmovehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; MwPoint* p = data; h->mouse_point.x = p->x; @@ -158,7 +164,7 @@ static void llmovehandler(MwLL handle, void* data) { } static void llkeyhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int key = *(int*)data; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -168,7 +174,7 @@ static void llkeyhandler(MwLL handle, void* data) { } static void llkeyrelhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -176,7 +182,7 @@ static void llkeyrelhandler(MwLL handle, void* data) { } static void llfocusinhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -184,7 +190,7 @@ static void llfocusinhandler(MwLL handle, void* data) { } static void llfocusouthandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -192,7 +198,7 @@ static void llfocusouthandler(MwLL handle, void* data) { } static void llclipboardhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -201,7 +207,7 @@ static void llclipboardhandler(MwLL handle, void* data) { } static void lldraganddrophandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int n; if((n = MwGetInteger(h, MwNdisabled)) != MwDEFAULT && n) return; @@ -222,7 +228,7 @@ static void lldraganddrophandler(MwLL handle, void* data) { #define IsFirstVisible(handle) ((handle)->widget_class != NULL && ((handle)->parent == NULL || (handle)->parent->widget_class == NULL)) static void lldarkthemehandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; + MwWidget h = (MwWidget)handle->common.internal; int* ptr = data; int s; @@ -260,16 +266,18 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, } else { h->lowlevel = NULL; } - h->widget_class = widget_class; - h->pressed = 0; - h->close = 0; - h->destroy_queue = NULL; - h->prop_event = 1; - h->draw_inject = NULL; - h->destroy_inject = NULL; - h->tick_list = NULL; - h->destroyed = 0; - h->bgcolor = NULL; + h->widget_class = widget_class; + h->pressed = 0; + h->close = 0; + h->destroy_queue = NULL; + h->prop_event = 1; + h->draw_inject = NULL; + h->destroy_inject = NULL; + h->prop_inject_pixmap = NULL; + h->pixmaps = NULL; + h->tick_list = NULL; + h->destroyed = 0; + h->bgcolor = NULL; h->berserk = 0; h->last_tick = MwTimeGetTick(); @@ -288,7 +296,7 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name, if(parent == NULL) h->top_step = 1; if(h->lowlevel != NULL) { - h->lowlevel->common.user = h; + h->lowlevel->common.internal = h; h->lowlevel->common.handler->draw = lldrawhandler; h->lowlevel->common.handler->up = lluphandler; h->lowlevel->common.handler->down = lldownhandler; @@ -456,6 +464,9 @@ void MwFreeWidget(MwWidget handle) { arrfree(handle->destroy_queue); arrfree(handle->tick_list); + while(arrlen(handle->pixmaps) > 0) MwDestroyPixmap(handle->pixmaps[0]); + arrfree(handle->pixmaps); + arrfree(handle->draw_queue); arrfree(handle->resize_queue); @@ -628,6 +639,20 @@ static void force_render_all(MwWidget handle) { if(handle->lowlevel != NULL) MwForceRender(handle); } +static void notify_all_bgfg_prop(MwWidget handle) { + int i; + + for(i = 0; i < arrlen(handle->children); i++) { + notify_all_bgfg_prop(handle->children[i]); + } + + PROP(handle, MwNbackground); + PROP(handle, MwNforeground); + PROP(handle, MwNsubBackground); + PROP(handle, MwNsubForeground); + MwForceRender(handle); +} + void MwSetInteger(MwWidget handle, const char* key, int n) { int xy; int wh = 0; @@ -653,7 +678,7 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { MwDispatch3(handle, props_change, keys); arrfree(keys); - MwDispatch3(handle, prop_change, key); + PROP(handle, key); } if(handle->parent != NULL && handle->parent->prop_event) { @@ -663,7 +688,7 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { if(strcmp(key, MwNforceInverted) == 0) { MwForceRender(handle); } - if(strcmp(key, MwNmodernLook) == 0 || strcmp(key, MwNdarkTheme) == 0 || strcmp(key, MwNbitmapFont) == 0) { + if(strcmp(key, MwNmodernLook) == 0 || strcmp(key, MwNbitmapFont) == 0) { force_render_all(handle); } @@ -677,6 +702,8 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { } if(h->lowlevel != NULL) MwLLSetDarkTheme(h->lowlevel, n); + + notify_all_bgfg_prop(handle); } if(strcmp(key, MwNacceptsDnD) == 0 && n) { @@ -706,7 +733,7 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { MwDispatch3(handle, props_change, keys); arrfree(keys); - MwDispatch3(handle, prop_change, key); + PROP(handle, key); } if(handle->parent != NULL && handle->parent->prop_event) { @@ -738,7 +765,7 @@ void MwSetVoid(MwWidget handle, const char* key, void* value) { MwDispatch3(handle, props_change, keys); arrfree(keys); - MwDispatch3(handle, prop_change, key); + PROP(handle, key); } if(handle->parent != NULL && handle->parent->prop_event) { @@ -918,8 +945,8 @@ static void MwVaListApply_Internal(MwWidget handle, va_list va, int only_early) if(x != MwDEFAULT && y != MwDEFAULT) { MwLLSetXY(handle->lowlevel, x, y); if(handle->prop_event) { - MwDispatch3(handle, prop_change, MwNx); - MwDispatch3(handle, prop_change, MwNy); + PROP(handle, MwNx); + PROP(handle, MwNy); } } else { if(x != MwDEFAULT) { @@ -931,8 +958,8 @@ static void MwVaListApply_Internal(MwWidget handle, va_list va, int only_early) if(w != MwDEFAULT && h != MwDEFAULT) { MwLLSetWH(handle->lowlevel, w, h); if(handle->prop_event) { - MwDispatch3(handle, prop_change, MwNwidth); - MwDispatch3(handle, prop_change, MwNheight); + PROP(handle, MwNwidth); + PROP(handle, MwNheight); } } else { if(w != MwDEFAULT) { @@ -947,7 +974,7 @@ static void MwVaListApply_Internal(MwWidget handle, va_list va, int only_early) if(handle->prop_event) { for(i = 0; keys[i] != NULL; i++) { - MwDispatch3(handle, prop_change, keys[i]); + PROP(handle, keys[i]); } MwDispatch3(handle, props_change, keys); diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 378b7960..2019f202 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -220,7 +220,7 @@ static void MWAPI color_picker_tick(MwWidget handle, void* user, } static void color_picker_destroy(color_picker_t* picker) { - MwLLDestroyPixmap(picker->color_picker_pixmap); + MwDestroyPixmap(picker->color_picker_pixmap); free(picker); } diff --git a/src/dialog/filechooser.c b/src/dialog/filechooser.c index b1fcc9b2..e7f1e28f 100644 --- a/src/dialog/filechooser.c +++ b/src/dialog/filechooser.c @@ -43,12 +43,12 @@ static void destroy(MwWidget handle) { for(i = 0; i < arrlen(fc->entries); i++) MwDirectoryFreeEntry(fc->entries[i]); arrfree(fc->entries); - MwLLDestroyPixmap(fc->dir); - MwLLDestroyPixmap(fc->file); - MwLLDestroyPixmap(fc->back); - MwLLDestroyPixmap(fc->forward); - MwLLDestroyPixmap(fc->up); - MwLLDestroyPixmap(fc->computer); + MwDestroyPixmap(fc->dir); + MwDestroyPixmap(fc->file); + MwDestroyPixmap(fc->back); + MwDestroyPixmap(fc->forward); + MwDestroyPixmap(fc->up); + MwDestroyPixmap(fc->computer); free(handle->opaque); } diff --git a/src/dialog/messagebox.c b/src/dialog/messagebox.c index ff72bc84..d536f10f 100644 --- a/src/dialog/messagebox.c +++ b/src/dialog/messagebox.c @@ -21,7 +21,7 @@ static void spawn_button(MwWidget handle, int x, int y, int id, const char* text static void messagebox_destroy_inject(MwWidget handle) { void* px; - if((px = MwGetVoid(handle, MwNpixmap)) != NULL) MwLLDestroyPixmap(px); + if((px = MwGetVoid(handle, MwNpixmap)) != NULL) MwDestroyPixmap(px); } static void MWAPI messagebox_close(MwWidget handle, void* user, void* call) { diff --git a/src/draw.c b/src/draw.c index 88c34f09..649741a5 100644 --- a/src/draw.c +++ b/src/draw.c @@ -953,29 +953,43 @@ MwLLPixmap MwLoadImage(MwWidget handle, const char* path) { return px; } +static void pixmap_prop(MwWidget handle, const char* prop) { + if(strcmp(prop, MwNbackground) == 0 || strcmp(prop, MwNsubBackground) == 0) { + int i; + + for(i = 0; i < arrlen(handle->pixmaps); i++) MwPixmapReloadRaw(handle->pixmaps[i], NULL); + } +} + MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height) { MwLLPixmap px = MwLLCreatePixmap(handle->lowlevel, rgb, width, height); - px->common.user = handle; + px->common.internal = handle; MwPixmapReloadRaw(px, rgb); + handle->prop_inject_pixmap = pixmap_prop; + + arrput(handle->pixmaps, px); + return px; } void MwPixmapReloadRaw(MwLLPixmap px, unsigned char* rgb) { int i; - MwWidget handle = px->common.user; + MwWidget handle = px->common.internal; MwLLColor base = handle->bgcolor == NULL ? MwParseColor(handle, MwGetText(handle, MwNbackground)) : handle->bgcolor; + if(rgb != NULL) memcpy(px->common.before_blend, rgb, px->common.width * px->common.height * 4); + memset(px->common.raw, 0, px->common.width * px->common.height * 4); for(i = 0; i < px->common.width * px->common.height; i++) { - unsigned char* pin = &rgb[i * 4]; + unsigned char* pin = &px->common.before_blend[i * 4]; unsigned char* pout = &px->common.raw[i * 4]; double a = pin[3]; a /= 255; if(a != 0) { -#if 1 +#if 0 a = 1; #endif pout[0] = (unsigned char)(pin[0] * a); @@ -1003,6 +1017,22 @@ void MwPixmapGetSize(MwLLPixmap pixmap, MwRect* rect) { rect->height = pixmap->common.height; } +void MwDestroyPixmap(MwLLPixmap pixmap) { + int i; + MwWidget handle = pixmap->common.internal; + + for(i = 0; i < arrlen(handle->pixmaps); i++) { + if(handle->pixmaps[i] == pixmap) { + arrdel(handle->pixmaps, i); + break; + } + } + + if(arrlen(handle->pixmaps) == 0) handle->prop_inject_pixmap = NULL; + + MwLLDestroyPixmap(pixmap); +} + void MwColorGet(MwLLColor color, int* red, int* green, int* blue) { *red = color->common.red; *green = color->common.green; diff --git a/src/text/ft2.c b/src/text/ft2.c index 13e8208c..10cd1ad0 100644 --- a/src/text/ft2.c +++ b/src/text/ft2.c @@ -93,7 +93,7 @@ static int ft2_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c r.height = th; MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); + MwDestroyPixmap(p); free(px); return 0; diff --git a/src/text/gdi.c b/src/text/gdi.c index 91ccac94..eb7df4ea 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -103,7 +103,7 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c r.height = th; MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); + MwDestroyPixmap(p); free(px); DeleteObject(hbm); diff --git a/src/text/stbtt.c b/src/text/stbtt.c index bd267414..67fe0ce6 100644 --- a/src/text/stbtt.c +++ b/src/text/stbtt.c @@ -80,7 +80,7 @@ static int stbtt_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const r.height = th; MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); + MwDestroyPixmap(p); free(px); return 0; diff --git a/src/text/text.c b/src/text/text.c index 1c9f6e6d..b39f064f 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -330,7 +330,7 @@ static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, r.height = th; MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); + MwDestroyPixmap(p); free(px); } diff --git a/src/widget/calendar.c b/src/widget/calendar.c index 3fa304b9..f5793f25 100644 --- a/src/widget/calendar.c +++ b/src/widget/calendar.c @@ -191,7 +191,7 @@ static void draw(MwWidget handle) { r2.x = (r.width - r2.width) / 2; r2.y = r2.y + gh * 2; MwLLDrawPixmap(handle->lowlevel, &r2, px); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); px = blit(handle, months[MwGetInteger(handle, MwNmonth)], cb, ct, gh); r2 = r3; @@ -200,7 +200,7 @@ static void draw(MwWidget handle) { r2.x = (r.width - r2.width) / 2; r2.y = r2.y + h - gh * 2 - r2.height; MwLLDrawPixmap(handle->lowlevel, &r2, px); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); MwStringPrintIntoBuffer(buf, 5, "%d", MwGetInteger(handle, MwNyear)); @@ -211,7 +211,7 @@ static void draw(MwWidget handle) { r2.x = (r.width - r2.width) / 2; r2.y = r2.y + h + gh * 6; MwLLDrawPixmap(handle->lowlevel, &r2, px); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); MwLLFreeColor(cf); MwLLFreeColor(ct); diff --git a/src/widget/label.c b/src/widget/label.c index a0be9ca5..eecca474 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -309,7 +309,7 @@ static void draw_seven_segment(MwWidget handle) { free(raw); - MwLLDestroyPixmap(px); + MwDestroyPixmap(px); } static void draw_normal(MwWidget handle) { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index c9bb3f49..e3578a76 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -617,7 +617,7 @@ static void frontbuffer_resize(MwWidget handle) { free(o->frontbuffer_data); } if(o->frontbuffer) { - MwLLDestroyPixmap(o->frontbuffer); + MwDestroyPixmap(o->frontbuffer); } if(o->gbm_surface) { o->gbm_surface_destroy(o->gbm_surface);