DirectWrite support #28
1 changed files with 94 additions and 2 deletions
commit
3a849267fc
|
|
@ -195,6 +195,77 @@ fail:
|
||||||
return ttf;
|
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) {
|
static int dw_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, MwLLColor color) {
|
||||||
IDWriteBitmapRenderTarget *target;
|
IDWriteBitmapRenderTarget *target;
|
||||||
RECT rc;
|
RECT rc;
|
||||||
|
|
@ -202,18 +273,39 @@ static int dw_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const ch
|
||||||
DWRITE_GLYPH_RUN glyphRun;
|
DWRITE_GLYPH_RUN glyphRun;
|
||||||
DWRITE_FONT_METRICS metrics;
|
DWRITE_FONT_METRICS metrics;
|
||||||
LONG width, height;
|
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);
|
IDWriteFontFace_GetMetrics(ttf->font_face, &metrics);
|
||||||
|
|
||||||
GetClientRect(handle->lowlevel->gdi.hWnd, &rc);
|
GetClientRect(handle->lowlevel->gdi.hWnd, &rc);
|
||||||
MapWindowPoints(handle->lowlevel->gdi.hWnd, GetParent(handle->lowlevel->gdi.hWnd), (LPPOINT)&rc, 2);
|
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;
|
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);
|
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);
|
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);
|
IDWriteBitmapRenderTarget_Release(target);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue