h
Some checks are pending
pyrite-dev/milsko/pipeline/head Build started...

This commit is contained in:
IoI_xD 2026-07-17 02:11:32 -07:00
commit e37e0f661f

View file

@ -17,6 +17,15 @@
#include "dwrite.h"
#include "dwrite_3.h"
typedef struct CustomTextRenderer {
IDWriteTextRendererVtbl *lpVtbl;
LONG refCount;
IDWriteFactory6 * write_factory;
IDWriteBitmapRenderTarget * target;
} CustomTextRenderer;
static CustomTextRenderer *CustomTextRenderer_Create(IDWriteFactory6 * write_factory, IDWriteBitmapRenderTarget * target);
static struct dw {
HMODULE d2d1_lib;
HMODULE dwrite_lib;
@ -31,10 +40,7 @@ struct _MwFLFont {
MwBool valid;
IDWriteFactory6* write_factory;
IDWriteTextFormat* dTextFormat;
ID2D1Factory* d2dFactory;
ID2D1HwndRenderTarget* rt;
ID2D1SolidColorBrush* blackBrush;
IDWriteGdiInterop *gdiInterop;
IDWriteFontFile * file;
@ -42,6 +48,8 @@ struct _MwFLFont {
IDWriteFontSetBuilder2 * font_builder;
IDWriteFontSet* font_set;
IDWriteFontCollection1* font_collection;
IDWriteTextFormat * text_format;
IDWriteTextFormat * text_layout;
LOGFONTW logfont;
HFONT font;
@ -175,18 +183,23 @@ static void* dw_MwFontLoad(unsigned char* data, unsigned int size, int px) {
goto fail;
}
hr = IDWriteFactory6_GetGdiInterop(ttf->write_factory, &ttf->gdiInterop);
if(!SUCCEEDED(hr)) {
printf("GetGdiInterop failed for TTF (%08lx), cannot use DirectWrite\n",hr);
goto fail;
}
IDWriteGdiInterop_ConvertFontFaceToLOGFONT(ttf->gdiInterop, ttf->font_face, &ttf->logfont);
hr = IDWriteFactory_CreateTextFormat(ttf->write_factory, L"milsko font", (IDWriteFontCollection*)ttf->font_collection, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, px, L"en-US", &ttf->text_format);
if(!SUCCEEDED(hr)) {
printf("IDWriteGdiInterop_ConvertFontFaceToLOGFONT failed for TTF (%08lx), cannot use DirectWrite\n",hr);
printf("IDWriteFactory_CreateTextFormat failed for TTF (%08lx), cannot use DirectWrite\n",hr);
goto fail;
}
ttf->valid = MwTRUE;
return ttf;
@ -195,127 +208,44 @@ 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;
HDC memoryHDC;
DWRITE_GLYPH_RUN glyphRun;
DWRITE_FONT_METRICS metrics;
LONG width, height;
IDWriteRenderingParams * rendering_params;
UINT32 codepoint_len;
UINT32* codepoints;
UINT16 *index;
IDWriteTextLayout * text_layout;
IDWriteBitmapRenderTarget *target = NULL;
HRESULT hr;
RECT rc = {0};
HDC memoryHDC = NULL;
DWRITE_FONT_METRICS metrics = {0};
LONG width = 0, height = 0;
size_t wtext_len = strlen(text) * sizeof(UINT32);
WCHAR* wtext = malloc(wtext_len);
CustomTextRenderer * texRenderer;
codepoints = str_to_codepoints(text, CP_UTF8, &codepoint_len);
index = malloc(sizeof(UINT16) * codepoint_len);
MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, wtext_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 = rc.bottom - rc.top;
hr = IDWriteFactory_CreateTextLayout(ttf->write_factory, wtext, wtext_len, ttf->text_format, width, height, &text_layout);
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);
texRenderer = CustomTextRenderer_Create(ttf->write_factory, target);
memoryHDC = IDWriteBitmapRenderTarget_GetMemoryDC(target);
BitBlt(handle->lowlevel->gdi.hDC, 0,0, width, height, memoryHDC, 0, 0, SRCCOPY | NOMIRRORBITMAP);
IDWriteTextLayout_Draw(text_layout, target, (IDWriteTextRenderer*)texRenderer, point->x, point->y);
IDWriteBitmapRenderTarget_Release(target);
/*SelectObject(handle->lowlevel->gdi.hDC, &ttf->logfont);
TextOut(handle->lowlevel->gdi.hDC, point->x, point->y, text, ttf->px);*/
return 0;
}
static int dw_MwTextWidth(MwFLFont ttf, const char* text) {
int tw = 1;
int tw = (ttf->px * strlen(text)) / 2;
return tw + 1;
}
@ -326,7 +256,7 @@ static int dw_MwTextHeight(MwFLFont ttf, int count) {
IDWriteFontFace_GetMetrics(ttf->font_face, &metrics);
height = ceil(((float)metrics.capHeight * ttf->px / metrics.designUnitsPerEm) * count);
height = ceil(((float)metrics.capHeight * ttf->px / metrics.designUnitsPerEm) * count) * 2;
return height;
}
@ -339,6 +269,172 @@ static void dw_MwFontFree(void* handle) {
free(ttf);
}
/* ---- IUnknown ---- */
static HRESULT STDMETHODCALLTYPE CTR_QueryInterface(
IDWriteTextRenderer *iface, REFIID riid, void **ppvObject)
{
if (!ppvObject)
return E_POINTER;
if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDWritePixelSnapping) ||
IsEqualGUID(riid, &IID_IDWriteTextRenderer))
{
*ppvObject = iface;
iface->lpVtbl->AddRef(iface);
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE CTR_AddRef(IDWriteTextRenderer *iface)
{
CustomTextRenderer *This = (CustomTextRenderer *)iface;
return InterlockedIncrement(&This->refCount);
}
static ULONG STDMETHODCALLTYPE CTR_Release(IDWriteTextRenderer *iface)
{
CustomTextRenderer *This = (CustomTextRenderer *)iface;
LONG ref = InterlockedDecrement(&This->refCount);
if (ref == 0)
HeapFree(GetProcessHeap(), 0, This);
return (ULONG)ref;
}
/* ---- IDWritePixelSnapping (base interface, treated as "core") ---- */
static HRESULT STDMETHODCALLTYPE CTR_IsPixelSnappingDisabled(
IDWriteTextRenderer *iface, void *clientDrawingContext, BOOL *isDisabled)
{
(void)iface; (void)clientDrawingContext;
if (!isDisabled)
return E_POINTER;
*isDisabled = FALSE;
return S_OK;
}
static HRESULT STDMETHODCALLTYPE CTR_GetCurrentTransform(
IDWriteTextRenderer *iface, void *clientDrawingContext, DWRITE_MATRIX *transform)
{
(void)iface; (void)clientDrawingContext;
if (!transform)
return E_POINTER;
transform->m11 = 1.0f;
transform->m12 = 0.0f;
transform->m21 = 0.0f;
transform->m22 = 1.0f;
transform->dx = 0.0f;
transform->dy = 0.0f;
return S_OK;
}
static HRESULT STDMETHODCALLTYPE CTR_GetPixelsPerDip(
IDWriteTextRenderer *iface, void *clientDrawingContext, FLOAT *pixelsPerDip)
{
(void)iface; (void)clientDrawingContext;
if (!pixelsPerDip)
return E_POINTER;
*pixelsPerDip = 1.0f;
return S_OK;
}
static HRESULT STDMETHODCALLTYPE CTR_DrawGlyphRun(
IDWriteTextRenderer *iface,
void *clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
DWRITE_GLYPH_RUN const *glyphRun,
DWRITE_GLYPH_RUN_DESCRIPTION const *glyphRunDescription,
IUnknown *clientDrawingEffect)
{
IDWriteRenderingParams *params;
CustomTextRenderer * This = (CustomTextRenderer*)iface;
IDWriteFactory6_CreateRenderingParams(This->write_factory, &params);
return IDWriteBitmapRenderTarget_DrawGlyphRun(This->target, baselineOriginX, baselineOriginY, measuringMode, glyphRun, params, RGB(255,255,255), NULL);
}
static HRESULT STDMETHODCALLTYPE CTR_DrawUnderline(
IDWriteTextRenderer *iface,
void *clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_UNDERLINE const *underline,
IUnknown *clientDrawingEffect)
{
(void)iface; (void)clientDrawingContext; (void)baselineOriginX;
(void)baselineOriginY; (void)underline; (void)clientDrawingEffect;
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE CTR_DrawStrikethrough(
IDWriteTextRenderer *iface,
void *clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_STRIKETHROUGH const *strikethrough,
IUnknown *clientDrawingEffect)
{
(void)iface; (void)clientDrawingContext; (void)baselineOriginX;
(void)baselineOriginY; (void)strikethrough; (void)clientDrawingEffect;
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE CTR_DrawInlineObject(
IDWriteTextRenderer *iface,
void *clientDrawingContext,
FLOAT originX,
FLOAT originY,
IDWriteInlineObject *inlineObject,
BOOL isSideways,
BOOL isRightToLeft,
IUnknown *clientDrawingEffect)
{
(void)iface; (void)clientDrawingContext; (void)originX; (void)originY;
(void)inlineObject; (void)isSideways; (void)isRightToLeft;
(void)clientDrawingEffect;
return E_NOTIMPL;
}
/* ---- Vtable instance ---- */
static IDWriteTextRendererVtbl CTR_Vtbl = {
CTR_QueryInterface,
CTR_AddRef,
CTR_Release,
CTR_IsPixelSnappingDisabled,
CTR_GetCurrentTransform,
CTR_GetPixelsPerDip,
CTR_DrawGlyphRun,
CTR_DrawUnderline,
CTR_DrawStrikethrough,
CTR_DrawInlineObject
};
/* ---- Constructor ---- */
static CustomTextRenderer *CustomTextRenderer_Create(IDWriteFactory6 * write_factory, IDWriteBitmapRenderTarget * target)
{
CustomTextRenderer *obj =
(CustomTextRenderer *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(CustomTextRenderer));
if (!obj)
return NULL;
obj->lpVtbl = &CTR_Vtbl;
obj->refCount = 1;
obj->write_factory = write_factory;
obj->target = target;
return obj;
}
int MWFL_DWSetup(void) {
/* Try and load DirectWrite. If it fails, return 1, signifying we default to bitmap drawing. */
dw_table.d2d1_lib = LoadLibrary("D2d1.dll");