From bc5fc1081640f7179c06ddb1cf737f0b3ffcda19 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 19 Jul 2026 21:04:33 +0900 Subject: [PATCH] faster gdi text rendering --- include/Mw/LowLevel/GDI.h | 3 +- src/backend/gdi.c | 3 +- src/text/gdi.c | 15 ++++++++- src/truetype.c | 64 +++++++++++++++++++-------------------- 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/include/Mw/LowLevel/GDI.h b/include/Mw/LowLevel/GDI.h index d2e2473..e505b0a 100644 --- a/include/Mw/LowLevel/GDI.h +++ b/include/Mw/LowLevel/GDI.h @@ -34,7 +34,8 @@ struct _MwLLGDI { struct _MwLLGDIColor { struct _MwLLCommonColor common; - HBRUSH brush; + COLORREF color; + HBRUSH brush; }; struct _MwLLGDIPixmap { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 62a1a1b..acc341e 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -502,7 +502,8 @@ static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { if(b < 0) b = 0; if(c->gdi.brush != NULL) DeleteObject(c->gdi.brush); - c->gdi.brush = CreateSolidBrush(GetNearestColor(dc, RGB(r, g, b))); + c->gdi.color = GetNearestColor(dc, RGB(r, g, b)); + c->gdi.brush = CreateSolidBrush(c->gdi.color); c->common.red = r; c->common.green = g; c->common.blue = b; diff --git a/src/text/gdi.c b/src/text/gdi.c index d3573b9..8915eea 100644 --- a/src/text/gdi.c +++ b/src/text/gdi.c @@ -23,6 +23,20 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c tw = MwTextWidth(handle, ttf, text); th = MwTextHeight(handle, ttf, text); + if(handle->lowlevel->common.type == MwLLBackendGDI) { + HFONT old_font = SelectObject(handle->lowlevel->gdi.hDC, ttf->font); + int old_bkmode = SetBkMode(handle->lowlevel->gdi.hDC, TRANSPARENT); + COLORREF old_color = SetTextColor(handle->lowlevel->gdi.hDC, color->gdi.color); + + TextOut(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t)); + + SetTextColor(handle->lowlevel->gdi.hDC, old_color); + SetBkMode(handle->lowlevel->gdi.hDC, old_bkmode); + SelectObject(handle->lowlevel->gdi.hDC, old_font); + + return 0; + } + px = malloc(tw * th * 4); bmih.biSize = sizeof(bmih); @@ -69,7 +83,6 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c free(px); DeleteObject(hbm); - free(t); return 0; diff --git a/src/truetype.c b/src/truetype.c index e200714..4f2c819 100644 --- a/src/truetype.c +++ b/src/truetype.c @@ -2,15 +2,15 @@ #define REMAIN (size - (data - old)) -MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ +MwTTFInfo MwTTFGetInfo(unsigned char* data, int size) { unsigned short n = 0; - int i; - unsigned char* old = data; - MwTTFInfo info = malloc(sizeof(*info)); + int i; + unsigned char* old = data; + MwTTFInfo info = malloc(sizeof(*info)); memset(info, 0, sizeof(*info)); - if(size < 12){ + if(size < 12) { MwTTFFreeInfo(info); return NULL; } @@ -19,17 +19,17 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ n |= data[4 + 1]; data += 12; - for(i = 0; REMAIN > 0 && i < n; i++){ + for(i = 0; REMAIN > 0 && i < n; i++) { unsigned int offset = 0; unsigned int length = 0; - int j; + int j; - if(REMAIN < (4 + 4 + 4 + 4)){ + if(REMAIN < (4 + 4 + 4 + 4)) { MwTTFFreeInfo(info); return NULL; } - for(j = 0; j < 4; j++){ + for(j = 0; j < 4; j++) { offset = offset << 8; offset |= data[4 + 4 + j]; @@ -37,18 +37,18 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ length |= data[4 + 4 + 4 + j]; } - if(memcmp(data, "OS/2", 4) == 0){ - if(length >= 68){ - unsigned char* rev = data; + if(memcmp(data, "OS/2", 4) == 0) { + if(length >= 68) { + unsigned char* rev = data; unsigned short us_weight = 0; data = old + offset; - if(REMAIN < 68){ + if(REMAIN < 68) { MwTTFFreeInfo(info); return NULL; } - for(j = 0; j < 2; j++){ + for(j = 0; j < 2; j++) { us_weight = us_weight << 8; us_weight |= data[0x4 + j]; } @@ -57,22 +57,22 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ data = rev; } - }else if(memcmp(data, "name", 4) == 0){ - if(length >= 6){ - unsigned short count = 0; - unsigned char* rev = data; + } else if(memcmp(data, "name", 4) == 0) { + if(length >= 6) { + unsigned short count = 0; + unsigned char* rev = data; unsigned short str_off = 0; unsigned char* beg; data = old + offset; - if(REMAIN < (2 + 2 + 2)){ + if(REMAIN < (2 + 2 + 2)) { MwTTFFreeInfo(info); return NULL; } beg = data; - for(j = 0; j < 2; j++){ + for(j = 0; j < 2; j++) { count = count << 8; count |= data[2 + j]; @@ -81,19 +81,19 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ } data += 2 + 2 + 2; - for(j = 0; j < count; j++){ + for(j = 0; j < count; j++) { unsigned short platform = 0; - unsigned short name = 0; - unsigned short nam_len = 0; - unsigned short nam_off = 0; - int k; + unsigned short name = 0; + unsigned short nam_len = 0; + unsigned short nam_off = 0; + int k; - if(REMAIN < (2 + 2 + 2 + 2 + 2 + 2)){ + if(REMAIN < (2 + 2 + 2 + 2 + 2 + 2)) { MwTTFFreeInfo(info); return NULL; } - for(k = 0; k < 2; k++){ + for(k = 0; k < 2; k++) { platform = platform << 8; platform |= data[0 + k]; @@ -107,10 +107,10 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ nam_off |= data[2 + 2 + 2 + 2 + 2 + k]; } - /* FIXME: this does not work with surrogate */ - if((platform == 0 || platform == 3) && name == 1){ + /* FIXME: this does not work with surrogate */ + if((platform == 0 || platform == 3) && name == 1) { data = beg + str_off + nam_off; - if(REMAIN < nam_len){ + if(REMAIN < nam_len) { MwTTFFreeInfo(info); return NULL; } @@ -118,7 +118,7 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ if(info->family != NULL) free(info->family); info->family = malloc(nam_len / 2 + 1); - + for(k = 0; k < nam_len / 2; k++) info->family[k] = data[k * 2 + 1]; info->family[k] = 0; } @@ -136,7 +136,7 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ return info; } -void MwTTFFreeInfo(MwTTFInfo info){ +void MwTTFFreeInfo(MwTTFInfo info) { if(info->family != NULL) free(info->family); free(info); }