From 3a849267fc7f124ea93e332aa559f697350e2c89 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 17 Jul 2026 00:47:31 -0700 Subject: [PATCH] text is now drawn --- src/text/directwrite.c | 96 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/src/text/directwrite.c b/src/text/directwrite.c index 2747c5f..f9d8181 100644 --- a/src/text/directwrite.c +++ b/src/text/directwrite.c @@ -195,6 +195,77 @@ fail: return ttf; } +static UINT32 *str_to_codepoints(const char *str, UINT codePage, UINT32 *pCount) +{ + int wideLen; + WCHAR *wideBuf; + UINT32 *codePoints; + UINT32 count; + int i; + + if (pCount != NULL) { + *pCount = 0; + } + if (str == NULL) { + return NULL; + } + + /* Size query; result includes the terminating null. */ + wideLen = MultiByteToWideChar(codePage, 0, str, -1, NULL, 0); + if (wideLen <= 0) { + return NULL; + } + + wideBuf = (WCHAR *)malloc((size_t)wideLen * sizeof(WCHAR)); + if (wideBuf == NULL) { + return NULL; + } + + if (MultiByteToWideChar(codePage, 0, str, -1, wideBuf, wideLen) == 0) { + free(wideBuf); + return NULL; + } + + /* One code point per UTF-16 unit is the worst case (no surrogate + pairs), so wideLen is always a safe upper bound for the output. */ + codePoints = (UINT32 *)malloc((size_t)wideLen * sizeof(UINT32)); + if (codePoints == NULL) { + free(wideBuf); + return NULL; + } + + count = 0; + i = 0; + while (wideBuf[i] != 0) { + WCHAR unit = wideBuf[i]; + + if (unit >= 0xD800 && unit <= 0xDBFF && + wideBuf[i + 1] >= 0xDC00 && wideBuf[i + 1] <= 0xDFFF) { + /* High + low surrogate -> one supplementary-plane code point. */ + UINT32 hi = (UINT32)(unit - 0xD800); + UINT32 lo = (UINT32)(wideBuf[i + 1] - 0xDC00); + + codePoints[count] = 0x10000u + (hi << 10) + lo; + count++; + i += 2; + } else { + /* Ordinary BMP character (or a lone/invalid surrogate, passed + through as-is -- GetGlyphIndices will just report .notdef + for it). */ + codePoints[count] = (UINT32)unit; + count++; + i += 1; + } + } + + free(wideBuf); + + if (pCount != NULL) { + *pCount = count; + } + return codePoints; +} + static int dw_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwLLColor color) { IDWriteBitmapRenderTarget *target; RECT rc; @@ -202,18 +273,39 @@ static int dw_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const ch DWRITE_GLYPH_RUN glyphRun; DWRITE_FONT_METRICS metrics; LONG width, height; + IDWriteRenderingParams * rendering_params; + UINT32 codepoint_len; + UINT32* codepoints; + UINT16 *index; + + codepoints = str_to_codepoints(text, CP_UTF8, &codepoint_len); + index = malloc(sizeof(UINT16) * codepoint_len); + IDWriteFontFace_GetMetrics(ttf->font_face, &metrics); GetClientRect(handle->lowlevel->gdi.hWnd, &rc); MapWindowPoints(handle->lowlevel->gdi.hWnd, GetParent(handle->lowlevel->gdi.hWnd), (LPPOINT)&rc, 2); + IDWriteFactory_CreateRenderingParams(ttf->write_factory, &rendering_params); + + IDWriteFontFace_GetGlyphIndices(ttf->font_face, codepoints, codepoint_len, index); + + glyphRun.fontFace = ttf->font_face; + glyphRun.fontEmSize = (ttf->px*96.f)/72.f; + glyphRun.glyphCount = codepoint_len; + glyphRun.glyphIndices = index; + width = rc.right - rc.left; - height = MwTextHeight(handle, ttf, text); + height = rc.bottom - rc.top; + IDWriteGdiInterop_CreateBitmapRenderTarget(ttf->gdiInterop, handle->lowlevel->gdi.hDC, width, height, &target); + IDWriteBitmapRenderTarget_DrawGlyphRun(target, point->x, point->y, DWRITE_MEASURING_MODE_GDI_NATURAL, &glyphRun, rendering_params, RGB(color->common.red, color->common.green, color->common.blue), NULL); + + memoryHDC = IDWriteBitmapRenderTarget_GetMemoryDC(target); - BitBlt(handle->lowlevel->gdi.hDC, point->x , point->y, width, height, memoryHDC, 0, 0, SRCCOPY | NOMIRRORBITMAP); + BitBlt(handle->lowlevel->gdi.hDC, 0,0, width, height, memoryHDC, 0, 0, SRCCOPY | NOMIRRORBITMAP); IDWriteBitmapRenderTarget_Release(target);