faster gdi text rendering
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good

This commit is contained in:
Nishi 2026-07-19 21:04:33 +09:00
commit bc5fc10816
4 changed files with 50 additions and 35 deletions

View file

@ -34,7 +34,8 @@ struct _MwLLGDI {
struct _MwLLGDIColor { struct _MwLLGDIColor {
struct _MwLLCommonColor common; struct _MwLLCommonColor common;
HBRUSH brush; COLORREF color;
HBRUSH brush;
}; };
struct _MwLLGDIPixmap { struct _MwLLGDIPixmap {

View file

@ -502,7 +502,8 @@ static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) {
if(b < 0) b = 0; if(b < 0) b = 0;
if(c->gdi.brush != NULL) DeleteObject(c->gdi.brush); 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.red = r;
c->common.green = g; c->common.green = g;
c->common.blue = b; c->common.blue = b;

View file

@ -23,6 +23,20 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c
tw = MwTextWidth(handle, ttf, text); tw = MwTextWidth(handle, ttf, text);
th = MwTextHeight(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); px = malloc(tw * th * 4);
bmih.biSize = sizeof(bmih); bmih.biSize = sizeof(bmih);
@ -69,7 +83,6 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c
free(px); free(px);
DeleteObject(hbm); DeleteObject(hbm);
free(t); free(t);
return 0; return 0;

View file

@ -2,15 +2,15 @@
#define REMAIN (size - (data - old)) #define REMAIN (size - (data - old))
MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size) {
unsigned short n = 0; unsigned short n = 0;
int i; int i;
unsigned char* old = data; unsigned char* old = data;
MwTTFInfo info = malloc(sizeof(*info)); MwTTFInfo info = malloc(sizeof(*info));
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
if(size < 12){ if(size < 12) {
MwTTFFreeInfo(info); MwTTFFreeInfo(info);
return NULL; return NULL;
} }
@ -19,17 +19,17 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){
n |= data[4 + 1]; n |= data[4 + 1];
data += 12; data += 12;
for(i = 0; REMAIN > 0 && i < n; i++){ for(i = 0; REMAIN > 0 && i < n; i++) {
unsigned int offset = 0; unsigned int offset = 0;
unsigned int length = 0; unsigned int length = 0;
int j; int j;
if(REMAIN < (4 + 4 + 4 + 4)){ if(REMAIN < (4 + 4 + 4 + 4)) {
MwTTFFreeInfo(info); MwTTFFreeInfo(info);
return NULL; return NULL;
} }
for(j = 0; j < 4; j++){ for(j = 0; j < 4; j++) {
offset = offset << 8; offset = offset << 8;
offset |= data[4 + 4 + j]; offset |= data[4 + 4 + j];
@ -37,18 +37,18 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){
length |= data[4 + 4 + 4 + j]; length |= data[4 + 4 + 4 + j];
} }
if(memcmp(data, "OS/2", 4) == 0){ if(memcmp(data, "OS/2", 4) == 0) {
if(length >= 68){ if(length >= 68) {
unsigned char* rev = data; unsigned char* rev = data;
unsigned short us_weight = 0; unsigned short us_weight = 0;
data = old + offset; data = old + offset;
if(REMAIN < 68){ if(REMAIN < 68) {
MwTTFFreeInfo(info); MwTTFFreeInfo(info);
return NULL; return NULL;
} }
for(j = 0; j < 2; j++){ for(j = 0; j < 2; j++) {
us_weight = us_weight << 8; us_weight = us_weight << 8;
us_weight |= data[0x4 + j]; us_weight |= data[0x4 + j];
} }
@ -57,22 +57,22 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){
data = rev; data = rev;
} }
}else if(memcmp(data, "name", 4) == 0){ } else if(memcmp(data, "name", 4) == 0) {
if(length >= 6){ if(length >= 6) {
unsigned short count = 0; unsigned short count = 0;
unsigned char* rev = data; unsigned char* rev = data;
unsigned short str_off = 0; unsigned short str_off = 0;
unsigned char* beg; unsigned char* beg;
data = old + offset; data = old + offset;
if(REMAIN < (2 + 2 + 2)){ if(REMAIN < (2 + 2 + 2)) {
MwTTFFreeInfo(info); MwTTFFreeInfo(info);
return NULL; return NULL;
} }
beg = data; beg = data;
for(j = 0; j < 2; j++){ for(j = 0; j < 2; j++) {
count = count << 8; count = count << 8;
count |= data[2 + j]; count |= data[2 + j];
@ -81,19 +81,19 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){
} }
data += 2 + 2 + 2; data += 2 + 2 + 2;
for(j = 0; j < count; j++){ for(j = 0; j < count; j++) {
unsigned short platform = 0; unsigned short platform = 0;
unsigned short name = 0; unsigned short name = 0;
unsigned short nam_len = 0; unsigned short nam_len = 0;
unsigned short nam_off = 0; unsigned short nam_off = 0;
int k; int k;
if(REMAIN < (2 + 2 + 2 + 2 + 2 + 2)){ if(REMAIN < (2 + 2 + 2 + 2 + 2 + 2)) {
MwTTFFreeInfo(info); MwTTFFreeInfo(info);
return NULL; return NULL;
} }
for(k = 0; k < 2; k++){ for(k = 0; k < 2; k++) {
platform = platform << 8; platform = platform << 8;
platform |= data[0 + k]; platform |= data[0 + k];
@ -107,10 +107,10 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){
nam_off |= data[2 + 2 + 2 + 2 + 2 + k]; nam_off |= data[2 + 2 + 2 + 2 + 2 + k];
} }
/* FIXME: this does not work with surrogate */ /* FIXME: this does not work with surrogate */
if((platform == 0 || platform == 3) && name == 1){ if((platform == 0 || platform == 3) && name == 1) {
data = beg + str_off + nam_off; data = beg + str_off + nam_off;
if(REMAIN < nam_len){ if(REMAIN < nam_len) {
MwTTFFreeInfo(info); MwTTFFreeInfo(info);
return NULL; return NULL;
} }
@ -136,7 +136,7 @@ MwTTFInfo MwTTFGetInfo(unsigned char* data, int size){
return info; return info;
} }
void MwTTFFreeInfo(MwTTFInfo info){ void MwTTFFreeInfo(MwTTFInfo info) {
if(info->family != NULL) free(info->family); if(info->family != NULL) free(info->family);
free(info); free(info);
} }