DirectWrite support #28
2 changed files with 325 additions and 291 deletions
commit
4ce9ee6730
|
|
@ -312,10 +312,17 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name,
|
||||||
|
|
||||||
#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_DIRECTWRITE)
|
#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_DIRECTWRITE)
|
||||||
if(IsFirstVisible(h)) {
|
if(IsFirstVisible(h)) {
|
||||||
|
font_setup:
|
||||||
h->root_font = MwFontLoad(MwTTFData, MwTTFDataSize);
|
h->root_font = MwFontLoad(MwTTFData, MwTTFDataSize);
|
||||||
h->root_boldfont = MwFontLoad(MwBoldTTFData, MwBoldTTFDataSize);
|
h->root_boldfont = MwFontLoad(MwBoldTTFData, MwBoldTTFDataSize);
|
||||||
h->root_monofont = MwFontLoad(MwMonospaceTTFData, MwMonospaceTTFDataSize);
|
h->root_monofont = MwFontLoad(MwMonospaceTTFData, MwMonospaceTTFDataSize);
|
||||||
h->root_boldmonofont = MwFontLoad(MwBoldMonospaceTTFData, MwBoldMonospaceTTFDataSize);
|
h->root_boldmonofont = MwFontLoad(MwBoldMonospaceTTFData, MwBoldMonospaceTTFDataSize);
|
||||||
|
if(!h->root_font) {
|
||||||
|
#ifdef USE_STB_TRUETYPE
|
||||||
|
MwFL_STBTTSetup();
|
||||||
|
goto font_setup;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <Mw/Milsko.h>
|
#include <Mw/Milsko.h>
|
||||||
|
|
||||||
#include <d2d1.h>
|
#include <d2d1.h>
|
||||||
|
#include <shobjidl.h>
|
||||||
|
|
||||||
#ifndef WINBOOL
|
#ifndef WINBOOL
|
||||||
#define WINBOOL int
|
#define WINBOOL int
|
||||||
|
|
@ -18,219 +19,229 @@
|
||||||
#include "dwrite_3.h"
|
#include "dwrite_3.h"
|
||||||
|
|
||||||
typedef struct CustomTextRenderer {
|
typedef struct CustomTextRenderer {
|
||||||
IDWriteTextRendererVtbl *lpVtbl;
|
IDWriteTextRendererVtbl* lpVtbl;
|
||||||
LONG refCount;
|
LONG refCount;
|
||||||
IDWriteFactory6 * write_factory;
|
IDWriteFactory6* write_factory;
|
||||||
IDWriteBitmapRenderTarget * target;
|
IDWriteBitmapRenderTarget* target;
|
||||||
int red, blue, green;
|
int red, blue, green;
|
||||||
|
|
||||||
} CustomTextRenderer;
|
} CustomTextRenderer;
|
||||||
static CustomTextRenderer *CustomTextRenderer_Create(IDWriteFactory6 * write_factory, IDWriteBitmapRenderTarget * target, MwLLColor color);
|
static CustomTextRenderer* CustomTextRenderer_Create(IDWriteFactory6* write_factory, IDWriteBitmapRenderTarget* target, MwLLColor color);
|
||||||
|
|
||||||
static struct dw {
|
static struct dw {
|
||||||
HMODULE d2d1_lib;
|
HMODULE d2d1_lib;
|
||||||
HMODULE dwrite_lib;
|
HMODULE dwrite_lib;
|
||||||
|
|
||||||
HRESULT (*D2D1CreateFactory)(D2D1_FACTORY_TYPE factoryType, const IID* const riid, const D2D1_FACTORY_OPTIONS* pFactoryOptions, void** ppIFactory);
|
HRESULT (*D2D1CreateFactory)(D2D1_FACTORY_TYPE factoryType, const IID* const riid, const D2D1_FACTORY_OPTIONS* pFactoryOptions, void** ppIFactory);
|
||||||
HRESULT (*DWriteCreateFactory)(int factoryType, const IID* const iid, IUnknown** factory);
|
HRESULT (*DWriteCreateFactory)(int factoryType, const IID* const iid, IUnknown** factory);
|
||||||
|
|
||||||
|
HMODULE kernel32_lib;
|
||||||
} dw_table;
|
} dw_table;
|
||||||
|
|
||||||
struct _MwFLFont {
|
struct _MwFLFont {
|
||||||
int px;
|
int px;
|
||||||
void * data;
|
void* data;
|
||||||
MwBool valid;
|
MwBool valid;
|
||||||
|
|
||||||
IDWriteFactory6* write_factory;
|
IDWriteFactory6* write_factory;
|
||||||
ID2D1Factory* d2dFactory;
|
ID2D1Factory* d2dFactory;
|
||||||
IDWriteGdiInterop *gdiInterop;
|
IDWriteGdiInterop* gdiInterop;
|
||||||
|
IDWriteFontFile* file;
|
||||||
IDWriteFontFile * file;
|
IDWriteFontFace* font_face;
|
||||||
IDWriteFontFace * font_face;
|
IDWriteFontSetBuilder2* font_builder;
|
||||||
IDWriteFontSetBuilder2 * font_builder;
|
IDWriteFontSet* font_set;
|
||||||
IDWriteFontSet* font_set;
|
|
||||||
IDWriteFontCollection1* font_collection;
|
IDWriteFontCollection1* font_collection;
|
||||||
IDWriteTextFormat * text_format;
|
IDWriteTextFormat* text_format;
|
||||||
IDWriteTextFormat * text_layout;
|
|
||||||
|
|
||||||
LOGFONTW logfont;
|
LOGFONTW logfont;
|
||||||
HFONT font;
|
HFONT font;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int unpack_ttf_data(WCHAR * temp_path_name, unsigned char* data, unsigned int size) {
|
static int unpack_ttf_data(WCHAR* temp_path_name, unsigned char* data, unsigned int size) {
|
||||||
WCHAR temp_path_dir[MAX_PATH];
|
WCHAR temp_path_dir[MAX_PATH];
|
||||||
HANDLE tempFile;
|
HANDLE tempFile;
|
||||||
int hr;
|
int hr;
|
||||||
|
|
||||||
hr = GetTempPath2W(MAX_PATH, temp_path_dir);
|
hr = GetTempPathW(MAX_PATH, temp_path_dir);
|
||||||
if (hr == 0)
|
if(hr == 0) {
|
||||||
{
|
printf("GetTempPathW failed for TTF, cannot use DirectWrite\n");
|
||||||
printf("GetTempPath2 failed for TTF, cannot use DirectWrite\n");
|
return 1;
|
||||||
return 1;
|
}
|
||||||
}
|
hr = GetTempFileNameW(temp_path_dir, TEXT(L"MILSKO"), 0, temp_path_name);
|
||||||
hr = GetTempFileNameW(temp_path_dir, TEXT(L"MILSKO"), 0, temp_path_name);
|
if(hr == 0) {
|
||||||
if (hr == 0)
|
printf("GetTempFileName failed for TTF, cannot use DirectWrite\n");
|
||||||
{
|
return 1;
|
||||||
printf("GetTempFileName failed for TTF, cannot use DirectWrite\n");
|
}
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tempFile = CreateFileW(temp_path_name,
|
tempFile = CreateFileW(temp_path_name,
|
||||||
GENERIC_WRITE,
|
GENERIC_WRITE,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
CREATE_NEW,
|
CREATE_NEW,
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
NULL);
|
NULL);
|
||||||
if (tempFile == INVALID_HANDLE_VALUE)
|
if(tempFile == INVALID_HANDLE_VALUE) {
|
||||||
{
|
DWORD err = GetLastError();
|
||||||
DWORD err = GetLastError();
|
if(err == ERROR_FILE_EXISTS) {
|
||||||
if(err == ERROR_FILE_EXISTS) {
|
tempFile = CreateFileW(temp_path_name,
|
||||||
tempFile = CreateFileW(temp_path_name,
|
GENERIC_WRITE,
|
||||||
GENERIC_WRITE,
|
0,
|
||||||
0,
|
NULL,
|
||||||
NULL,
|
OPEN_ALWAYS,
|
||||||
OPEN_ALWAYS,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
NULL);
|
||||||
NULL);
|
if(tempFile != INVALID_HANDLE_VALUE) {
|
||||||
if (tempFile != INVALID_HANDLE_VALUE)
|
goto success;
|
||||||
{
|
} else {
|
||||||
goto success;
|
err = GetLastError();
|
||||||
} else {
|
}
|
||||||
err = GetLastError();
|
}
|
||||||
}
|
printf("CreateFile failed for TTF (%ld), cannot use DirectWrite\n", err);
|
||||||
}
|
return 1;
|
||||||
printf("CreateFile failed for TTF (%ld), cannot use DirectWrite\n", err);
|
}
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
success:
|
success:
|
||||||
|
|
||||||
hr = WriteFile(tempFile, data, size, NULL, NULL);
|
hr = WriteFile(tempFile, data, size, NULL, NULL);
|
||||||
if(!hr) {
|
if(!hr) {
|
||||||
printf("WriteFile failed for TTF (%ld), cannot use DirectWrite\n", GetLastError());
|
printf("WriteFile failed for TTF (%ld), cannot use DirectWrite\n", GetLastError());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(tempFile);
|
CloseHandle(tempFile);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* dw_MwFontLoad(unsigned char* data, unsigned int size, int px) {
|
static void* dw_MwFontLoad(unsigned char* data, unsigned int size, int px) {
|
||||||
MwFLFont ttf = malloc(sizeof(*ttf));
|
MwFLFont ttf = malloc(sizeof(*ttf));
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
WCHAR font_name[MAX_PATH];
|
WCHAR font_name[MAX_PATH];
|
||||||
D2D1_FACTORY_OPTIONS d2d1_options;
|
D2D1_FACTORY_OPTIONS d2d1_options;
|
||||||
|
|
||||||
d2d1_options.debugLevel = D2D1_DEBUG_LEVEL_ERROR;
|
d2d1_options.debugLevel = D2D1_DEBUG_LEVEL_ERROR;
|
||||||
|
|
||||||
|
#define INTERFACE_CHECK(x, factory) \
|
||||||
|
do { \
|
||||||
|
x* rsrc = NULL; \
|
||||||
|
if(!SUCCEEDED((hr = x##_QueryInterface(factory, &IID_##x, (void**)&rsrc)))) { \
|
||||||
|
printf("Query for interface " #x " failed (%08lX). Cannot use DirectWrite.\n", hr); \
|
||||||
|
return NULL; \
|
||||||
|
}; \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
memset(ttf, 0, sizeof(*ttf));
|
memset(ttf, 0, sizeof(*ttf));
|
||||||
ttf->data = malloc(size);
|
ttf->data = malloc(size);
|
||||||
memcpy(ttf->data, data, size);
|
memcpy(ttf->data, data, size);
|
||||||
|
|
||||||
ttf->px = px;
|
ttf->px = px;
|
||||||
|
|
||||||
hr = dw_table.D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, &d2d1_options, (void**)&ttf->d2dFactory);
|
hr = dw_table.D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, &d2d1_options, (void**)&ttf->d2dFactory);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("D2D1CreateFactory failed for TTF (%08lX), cannot use DirectWrite\n", hr);
|
printf("D2D1CreateFactory failed for TTF (%08lX), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = dw_table.DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,&IID_IDWriteFactory, (struct IUnknown**)&ttf->write_factory);
|
INTERFACE_CHECK(ID2D1Factory, ttf->d2dFactory);
|
||||||
|
|
||||||
|
hr = dw_table.DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (struct IUnknown**)&ttf->write_factory);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("DWriteCreateFactory failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
printf("DWriteCreateFactory failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
INTERFACE_CHECK(IDWriteFactory6, ttf->write_factory);
|
||||||
|
|
||||||
if(unpack_ttf_data(font_name, data, size) != 0) {
|
if(unpack_ttf_data(font_name, data, size) != 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
};
|
};
|
||||||
|
|
||||||
hr = IDWriteFactory6_CreateFontFileReference(ttf->write_factory, font_name, NULL, &ttf->file);
|
hr = IDWriteFactory6_CreateFontFileReference(ttf->write_factory, font_name, NULL, &ttf->file);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("CreateFontFileReference failed for TTF (%08lx), cannot use DirectWrite\n",hr);
|
printf("CreateFontFileReference failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
INTERFACE_CHECK(IDWriteFontFile, ttf->file);
|
||||||
|
|
||||||
hr = IDWriteFactory_CreateFontFace(ttf->write_factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ttf->file, 0, DWRITE_FONT_SIMULATIONS_NONE, &ttf->font_face);
|
hr = IDWriteFactory_CreateFontFace(ttf->write_factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ttf->file, 0, DWRITE_FONT_SIMULATIONS_NONE, &ttf->font_face);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("IDWriteFactory_CreateFontFace failed for TTF (%08lx), cannot use DirectWrite\n",hr);
|
printf("IDWriteFactory_CreateFontFace failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
INTERFACE_CHECK(IDWriteFontFace, ttf->font_face);
|
||||||
|
|
||||||
hr = IDWriteFactory6_CreateFontSetBuilder(ttf->write_factory, &ttf->font_builder);
|
hr = IDWriteFactory6_CreateFontSetBuilder(ttf->write_factory, &ttf->font_builder);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("IDWriteFactory6_CreateFontSetBuilder failed for TTF (%08lx), cannot use DirectWrite\n",hr);
|
printf("IDWriteFactory6_CreateFontSetBuilder failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
INTERFACE_CHECK(IDWriteFontSetBuilder2, ttf->font_builder);
|
||||||
|
|
||||||
hr = IDWriteFontSetBuilder2_AddFontFile(ttf->font_builder, font_name);
|
hr = IDWriteFontSetBuilder2_AddFontFile(ttf->font_builder, font_name);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("IDWriteFontSetBuilder2_AddFontFile failed for TTF (%08lx), cannot use DirectWrite\n",hr);
|
printf("IDWriteFontSetBuilder2_AddFontFile failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IDWriteFontSetBuilder_CreateFontSet(ttf->font_builder, &ttf->font_set);
|
hr = IDWriteFontSetBuilder_CreateFontSet(ttf->font_builder, &ttf->font_set);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("IDWriteFontSetBuilder_CreateFontSet failed for TTF (%08lx), cannot use DirectWrite\n",hr);
|
printf("IDWriteFontSetBuilder_CreateFontSet failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
INTERFACE_CHECK(IDWriteFontSet, ttf->font_set);
|
||||||
|
|
||||||
hr = IDWriteFactory3_CreateFontCollectionFromFontSet(ttf->write_factory, ttf->font_set, &ttf->font_collection);
|
hr = IDWriteFactory3_CreateFontCollectionFromFontSet(ttf->write_factory, ttf->font_set, &ttf->font_collection);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("IDWriteFactory3_CreateFontCollectionFromFontSet failed for TTF (%08lx), cannot use DirectWrite\n",hr);
|
printf("IDWriteFactory3_CreateFontCollectionFromFontSet failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
INTERFACE_CHECK(IDWriteFontCollection1, ttf->font_collection);
|
||||||
|
|
||||||
|
|
||||||
hr = IDWriteFactory6_GetGdiInterop(ttf->write_factory, &ttf->gdiInterop);
|
hr = IDWriteFactory6_GetGdiInterop(ttf->write_factory, &ttf->gdiInterop);
|
||||||
if(!SUCCEEDED(hr)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("GetGdiInterop failed for TTF (%08lx), cannot use DirectWrite\n",hr);
|
printf("GetGdiInterop failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
INTERFACE_CHECK(IDWriteGdiInterop, ttf->gdiInterop);
|
||||||
|
|
||||||
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);
|
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)) {
|
if(!SUCCEEDED(hr)) {
|
||||||
printf("IDWriteFactory_CreateTextFormat failed for TTF (%08lx), cannot use DirectWrite\n",hr);
|
printf("IDWriteFactory_CreateTextFormat failed for TTF (%08lx), cannot use DirectWrite\n", hr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ttf->valid = MwTRUE;
|
ttf->valid = MwTRUE;
|
||||||
return ttf;
|
return ttf;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
ttf->valid = MwFALSE;
|
ttf->valid = MwFALSE;
|
||||||
return ttf;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dw_MwTextOffset(MwFLFont ttf, const char* text) ;
|
static int dw_MwTextOffset(MwFLFont ttf, const char* text);
|
||||||
|
|
||||||
|
|
||||||
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) {
|
||||||
IDWriteTextLayout * text_layout;
|
IDWriteTextLayout* text_layout;
|
||||||
IDWriteBitmapRenderTarget *target = NULL;
|
IDWriteBitmapRenderTarget* target = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
RECT rc = {0};
|
RECT rc = {0};
|
||||||
HDC memoryHDC = NULL;
|
HDC memoryHDC = NULL;
|
||||||
DWRITE_FONT_METRICS metrics = {0};
|
DWRITE_FONT_METRICS metrics = {0};
|
||||||
LONG width = 0, height = 0, offset = 0;
|
LONG width = 0, height = 0, offset = 0;
|
||||||
WCHAR* wtext = NULL;
|
WCHAR* wtext = NULL;
|
||||||
CustomTextRenderer * texRenderer;
|
CustomTextRenderer* texRenderer;
|
||||||
size_t wtext_len = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
|
size_t wtext_len = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
|
||||||
|
|
||||||
wtext = malloc(wtext_len * 2); /* we get a weird buffer overflow when we try to free this later? allocate well above wtext_len then to prevent that. */
|
wtext = malloc(wtext_len * 2); /* we get a weird buffer overflow when we try to free this later? allocate well above wtext_len then to prevent that. */
|
||||||
memset(wtext, 0, wtext_len * 2);
|
memset(wtext, 0, wtext_len * 2);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, wtext_len);
|
MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, wtext_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);
|
||||||
|
|
||||||
width = MwTextWidth(handle,ttf, text);
|
width = MwTextWidth(handle, ttf, text);
|
||||||
height = MwTextHeight(handle, ttf, text);
|
height = MwTextHeight(handle, ttf, text);
|
||||||
offset = dw_MwTextOffset(ttf, text);
|
offset = dw_MwTextOffset(ttf, text);
|
||||||
|
|
||||||
hr = IDWriteFactory_CreateTextLayout(ttf->write_factory, wtext, wtext_len, ttf->text_format, width, height, &text_layout);
|
hr = IDWriteFactory_CreateTextLayout(ttf->write_factory, wtext, wtext_len, ttf->text_format, width, height, &text_layout);
|
||||||
|
|
||||||
|
|
@ -243,8 +254,8 @@ static int dw_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const ch
|
||||||
SetBkMode(handle->lowlevel->gdi.hDC, TRANSPARENT);
|
SetBkMode(handle->lowlevel->gdi.hDC, TRANSPARENT);
|
||||||
BitBlt(memoryHDC, 0, 0, width, height, handle->lowlevel->gdi.hDC, point->x, point->y - (height / 2), SRCCOPY);
|
BitBlt(memoryHDC, 0, 0, width, height, handle->lowlevel->gdi.hDC, point->x, point->y - (height / 2), SRCCOPY);
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if(SUCCEEDED(hr)) {
|
||||||
IDWriteTextLayout_Draw(text_layout, target, (IDWriteTextRenderer*)texRenderer, offset, 0);
|
IDWriteTextLayout_Draw(text_layout, target, (IDWriteTextRenderer*)texRenderer, offset, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BitBlt(handle->lowlevel->gdi.hDC, point->x, point->y - (height / 2), width, height, memoryHDC, 0, 0, SRCCOPY | NOMIRRORBITMAP);
|
BitBlt(handle->lowlevel->gdi.hDC, point->x, point->y - (height / 2), width, height, memoryHDC, 0, 0, SRCCOPY | NOMIRRORBITMAP);
|
||||||
|
|
@ -257,21 +268,21 @@ static int dw_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const ch
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dw_MwTextOffset(MwFLFont ttf, const char* text) {
|
static int dw_MwTextOffset(MwFLFont ttf, const char* text) {
|
||||||
IDWriteTextLayout * text_layout;
|
IDWriteTextLayout* text_layout;
|
||||||
DWRITE_FONT_METRICS metrics = {0};
|
DWRITE_FONT_METRICS metrics = {0};
|
||||||
WCHAR* wtext = NULL;
|
WCHAR* wtext = NULL;
|
||||||
size_t wtext_len = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
|
size_t wtext_len = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
|
||||||
UINT32 * codepoints = malloc(wtext_len * sizeof(UINT32));
|
UINT32* codepoints = malloc(wtext_len * sizeof(UINT32));
|
||||||
UINT16 * glyphIndices = malloc(wtext_len * sizeof(UINT16));
|
UINT16* glyphIndices = malloc(wtext_len * sizeof(UINT16));
|
||||||
int i;
|
int i;
|
||||||
DWRITE_GLYPH_METRICS * gmetrics;
|
DWRITE_GLYPH_METRICS* gmetrics;
|
||||||
int tw = 0;
|
int tw = 0;
|
||||||
|
|
||||||
wtext = malloc(wtext_len * 2); /* we get a weird buffer overflow when we try to free this later? allocate well above wtext_len then to prevent that. */
|
wtext = malloc(wtext_len * 2); /* we get a weird buffer overflow when we try to free this later? allocate well above wtext_len then to prevent that. */
|
||||||
memset(wtext, 0, wtext_len * 2);
|
memset(wtext, 0, wtext_len * 2);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, wtext_len);
|
MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, wtext_len);
|
||||||
|
|
||||||
for(i = 0; i < wtext_len; i++) codepoints[i] = wtext[i];
|
for(i = 0; i < wtext_len; i++) codepoints[i] = wtext[i];
|
||||||
|
|
||||||
IDWriteFontFace_GetMetrics(ttf->font_face, &metrics);
|
IDWriteFontFace_GetMetrics(ttf->font_face, &metrics);
|
||||||
|
|
||||||
|
|
@ -284,7 +295,7 @@ static int dw_MwTextOffset(MwFLFont ttf, const char* text) {
|
||||||
IDWriteFontFace_GetDesignGlyphMetrics(ttf->font_face, glyphIndices, wtext_len, gmetrics, FALSE);
|
IDWriteFontFace_GetDesignGlyphMetrics(ttf->font_face, glyphIndices, wtext_len, gmetrics, FALSE);
|
||||||
|
|
||||||
for(i = 0; i < strlen(text); i++) {
|
for(i = 0; i < strlen(text); i++) {
|
||||||
int add = (gmetrics[i].leftSideBearing) * ((float)ttf->px / (float)metrics.designUnitsPerEm);
|
int add = (gmetrics[i].leftSideBearing) * ((float)ttf->px / (float)metrics.designUnitsPerEm);
|
||||||
tw += add;
|
tw += add;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -294,21 +305,21 @@ static int dw_MwTextOffset(MwFLFont ttf, const char* text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dw_MwTextWidth(MwFLFont ttf, const char* text) {
|
static int dw_MwTextWidth(MwFLFont ttf, const char* text) {
|
||||||
IDWriteTextLayout * text_layout;
|
IDWriteTextLayout* text_layout;
|
||||||
DWRITE_FONT_METRICS metrics = {0};
|
DWRITE_FONT_METRICS metrics = {0};
|
||||||
WCHAR* wtext = NULL;
|
WCHAR* wtext = NULL;
|
||||||
size_t wtext_len = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
|
size_t wtext_len = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
|
||||||
UINT32 * codepoints = malloc(wtext_len * sizeof(UINT32));
|
UINT32* codepoints = malloc(wtext_len * sizeof(UINT32));
|
||||||
UINT16 * glyphIndices = malloc(wtext_len * sizeof(UINT16));
|
UINT16* glyphIndices = malloc(wtext_len * sizeof(UINT16));
|
||||||
int i;
|
int i;
|
||||||
DWRITE_GLYPH_METRICS * gmetrics;
|
DWRITE_GLYPH_METRICS* gmetrics;
|
||||||
int tw = 0;
|
int tw = 0;
|
||||||
|
|
||||||
wtext = malloc(wtext_len * 2); /* we get a weird buffer overflow when we try to free this later? allocate well above wtext_len then to prevent that. */
|
wtext = malloc(wtext_len * 2); /* we get a weird buffer overflow when we try to free this later? allocate well above wtext_len then to prevent that. */
|
||||||
memset(wtext, 0, wtext_len * 2);
|
memset(wtext, 0, wtext_len * 2);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, wtext_len);
|
MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, wtext_len);
|
||||||
|
|
||||||
for(i = 0; i < wtext_len; i++) codepoints[i] = wtext[i];
|
for(i = 0; i < wtext_len; i++) codepoints[i] = wtext[i];
|
||||||
|
|
||||||
IDWriteFontFace_GetMetrics(ttf->font_face, &metrics);
|
IDWriteFontFace_GetMetrics(ttf->font_face, &metrics);
|
||||||
|
|
||||||
|
|
@ -321,7 +332,7 @@ static int dw_MwTextWidth(MwFLFont ttf, const char* text) {
|
||||||
IDWriteFontFace_GetDesignGlyphMetrics(ttf->font_face, glyphIndices, wtext_len, gmetrics, FALSE);
|
IDWriteFontFace_GetDesignGlyphMetrics(ttf->font_face, glyphIndices, wtext_len, gmetrics, FALSE);
|
||||||
|
|
||||||
for(i = 0; i < strlen(text); i++) {
|
for(i = 0; i < strlen(text); i++) {
|
||||||
int add = (gmetrics[i].advanceWidth + gmetrics[i].leftSideBearing) * ((float)ttf->px / (float)metrics.designUnitsPerEm);
|
int add = (gmetrics[i].advanceWidth + gmetrics[i].leftSideBearing) * ((float)ttf->px / (float)metrics.designUnitsPerEm);
|
||||||
tw += add;
|
tw += add;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,11 +342,10 @@ static int dw_MwTextWidth(MwFLFont ttf, const char* text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dw_MwTextHeight(MwFLFont ttf, int count) {
|
static int dw_MwTextHeight(MwFLFont ttf, int count) {
|
||||||
(void)count;
|
(void)count;
|
||||||
return (IDWriteTextFormat2_GetFontSize(ttf->text_format) / 72.0f) * GetDeviceCaps(GetDC(NULL), LOGPIXELSY);
|
return (IDWriteTextFormat2_GetFontSize(ttf->text_format) / 72.0f) * GetDeviceCaps(GetDC(NULL), LOGPIXELSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dw_MwFontFree(void* handle) {
|
static void dw_MwFontFree(void* handle) {
|
||||||
MwFLFont ttf = handle;
|
MwFLFont ttf = handle;
|
||||||
|
|
||||||
|
|
@ -346,139 +356,144 @@ static void dw_MwFontFree(void* handle) {
|
||||||
/* ---- IUnknown ---- */
|
/* ---- IUnknown ---- */
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CTR_QueryInterface(
|
static HRESULT STDMETHODCALLTYPE CTR_QueryInterface(
|
||||||
IDWriteTextRenderer *iface, REFIID riid, void **ppvObject)
|
IDWriteTextRenderer* iface, REFIID riid, void** ppvObject) {
|
||||||
{
|
if(!ppvObject)
|
||||||
if (!ppvObject)
|
return E_POINTER;
|
||||||
return E_POINTER;
|
|
||||||
|
|
||||||
if (IsEqualGUID(riid, &IID_IUnknown) ||
|
if(IsEqualGUID(riid, &IID_IUnknown) ||
|
||||||
IsEqualGUID(riid, &IID_IDWritePixelSnapping) ||
|
IsEqualGUID(riid, &IID_IDWritePixelSnapping) ||
|
||||||
IsEqualGUID(riid, &IID_IDWriteTextRenderer))
|
IsEqualGUID(riid, &IID_IDWriteTextRenderer)) {
|
||||||
{
|
*ppvObject = iface;
|
||||||
*ppvObject = iface;
|
iface->lpVtbl->AddRef(iface);
|
||||||
iface->lpVtbl->AddRef(iface);
|
return S_OK;
|
||||||
return S_OK;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*ppvObject = NULL;
|
*ppvObject = NULL;
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG STDMETHODCALLTYPE CTR_AddRef(IDWriteTextRenderer *iface)
|
static ULONG STDMETHODCALLTYPE CTR_AddRef(IDWriteTextRenderer* iface) {
|
||||||
{
|
CustomTextRenderer* This = (CustomTextRenderer*)iface;
|
||||||
CustomTextRenderer *This = (CustomTextRenderer *)iface;
|
return InterlockedIncrement(&This->refCount);
|
||||||
return InterlockedIncrement(&This->refCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG STDMETHODCALLTYPE CTR_Release(IDWriteTextRenderer *iface)
|
static ULONG STDMETHODCALLTYPE CTR_Release(IDWriteTextRenderer* iface) {
|
||||||
{
|
CustomTextRenderer* This = (CustomTextRenderer*)iface;
|
||||||
CustomTextRenderer *This = (CustomTextRenderer *)iface;
|
LONG ref = InterlockedDecrement(&This->refCount);
|
||||||
LONG ref = InterlockedDecrement(&This->refCount);
|
if(ref == 0)
|
||||||
if (ref == 0)
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
HeapFree(GetProcessHeap(), 0, This);
|
return (ULONG)ref;
|
||||||
return (ULONG)ref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- IDWritePixelSnapping (base interface, treated as "core") ---- */
|
/* ---- IDWritePixelSnapping (base interface, treated as "core") ---- */
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CTR_IsPixelSnappingDisabled(
|
static HRESULT STDMETHODCALLTYPE CTR_IsPixelSnappingDisabled(
|
||||||
IDWriteTextRenderer *iface, void *clientDrawingContext, BOOL *isDisabled)
|
IDWriteTextRenderer* iface, void* clientDrawingContext, BOOL* isDisabled) {
|
||||||
{
|
(void)iface;
|
||||||
(void)iface; (void)clientDrawingContext;
|
(void)clientDrawingContext;
|
||||||
if (!isDisabled)
|
if(!isDisabled)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
*isDisabled = FALSE;
|
*isDisabled = FALSE;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CTR_GetCurrentTransform(
|
static HRESULT STDMETHODCALLTYPE CTR_GetCurrentTransform(
|
||||||
IDWriteTextRenderer *iface, void *clientDrawingContext, DWRITE_MATRIX *transform)
|
IDWriteTextRenderer* iface, void* clientDrawingContext, DWRITE_MATRIX* transform) {
|
||||||
{
|
(void)iface;
|
||||||
(void)iface; (void)clientDrawingContext;
|
(void)clientDrawingContext;
|
||||||
if (!transform)
|
if(!transform)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
transform->m11 = 1.0f;
|
transform->m11 = 1.0f;
|
||||||
transform->m12 = 0.0f;
|
transform->m12 = 0.0f;
|
||||||
transform->m21 = 0.0f;
|
transform->m21 = 0.0f;
|
||||||
transform->m22 = 1.0f;
|
transform->m22 = 1.0f;
|
||||||
transform->dx = 0.0f;
|
transform->dx = 0.0f;
|
||||||
transform->dy = 0.0f;
|
transform->dy = 0.0f;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CTR_GetPixelsPerDip(
|
static HRESULT STDMETHODCALLTYPE CTR_GetPixelsPerDip(
|
||||||
IDWriteTextRenderer *iface, void *clientDrawingContext, FLOAT *pixelsPerDip)
|
IDWriteTextRenderer* iface, void* clientDrawingContext, FLOAT* pixelsPerDip) {
|
||||||
{
|
(void)iface;
|
||||||
(void)iface; (void)clientDrawingContext;
|
(void)clientDrawingContext;
|
||||||
if (!pixelsPerDip)
|
if(!pixelsPerDip)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
*pixelsPerDip = 1.0f;
|
*pixelsPerDip = 1.0f;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CTR_DrawGlyphRun(
|
static HRESULT STDMETHODCALLTYPE CTR_DrawGlyphRun(
|
||||||
IDWriteTextRenderer *iface,
|
IDWriteTextRenderer* iface,
|
||||||
void *clientDrawingContext,
|
void* clientDrawingContext,
|
||||||
FLOAT baselineOriginX,
|
FLOAT baselineOriginX,
|
||||||
FLOAT baselineOriginY,
|
FLOAT baselineOriginY,
|
||||||
DWRITE_MEASURING_MODE measuringMode,
|
DWRITE_MEASURING_MODE measuringMode,
|
||||||
DWRITE_GLYPH_RUN const *glyphRun,
|
DWRITE_GLYPH_RUN const* glyphRun,
|
||||||
DWRITE_GLYPH_RUN_DESCRIPTION const *glyphRunDescription,
|
DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
|
||||||
IUnknown *clientDrawingEffect)
|
IUnknown* clientDrawingEffect) {
|
||||||
{
|
IDWriteRenderingParams* params;
|
||||||
IDWriteRenderingParams *params;
|
CustomTextRenderer* This = (CustomTextRenderer*)iface;
|
||||||
CustomTextRenderer * This = (CustomTextRenderer*)iface;
|
|
||||||
|
|
||||||
(void)clientDrawingContext;
|
(void)clientDrawingContext;
|
||||||
(void)glyphRunDescription;
|
(void)glyphRunDescription;
|
||||||
(void)clientDrawingEffect;
|
(void)clientDrawingEffect;
|
||||||
|
|
||||||
IDWriteFactory6_CreateRenderingParams(This->write_factory, ¶ms);
|
IDWriteFactory6_CreateRenderingParams(This->write_factory, ¶ms);
|
||||||
|
|
||||||
return IDWriteBitmapRenderTarget_DrawGlyphRun(This->target, baselineOriginX, baselineOriginY, measuringMode, glyphRun, params, RGB(This->red,This->green,This->blue), NULL);
|
return IDWriteBitmapRenderTarget_DrawGlyphRun(This->target, baselineOriginX, baselineOriginY, measuringMode, glyphRun, params, RGB(This->red, This->green, This->blue), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CTR_DrawUnderline(
|
static HRESULT STDMETHODCALLTYPE CTR_DrawUnderline(
|
||||||
IDWriteTextRenderer *iface,
|
IDWriteTextRenderer* iface,
|
||||||
void *clientDrawingContext,
|
void* clientDrawingContext,
|
||||||
FLOAT baselineOriginX,
|
FLOAT baselineOriginX,
|
||||||
FLOAT baselineOriginY,
|
FLOAT baselineOriginY,
|
||||||
DWRITE_UNDERLINE const *underline,
|
DWRITE_UNDERLINE const* underline,
|
||||||
IUnknown *clientDrawingEffect)
|
IUnknown* clientDrawingEffect) {
|
||||||
{
|
(void)iface;
|
||||||
(void)iface; (void)clientDrawingContext; (void)baselineOriginX;
|
(void)clientDrawingContext;
|
||||||
(void)baselineOriginY; (void)underline; (void)clientDrawingEffect;
|
(void)baselineOriginX;
|
||||||
return E_NOTIMPL;
|
(void)baselineOriginY;
|
||||||
|
(void)underline;
|
||||||
|
(void)clientDrawingEffect;
|
||||||
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CTR_DrawStrikethrough(
|
static HRESULT STDMETHODCALLTYPE CTR_DrawStrikethrough(
|
||||||
IDWriteTextRenderer *iface,
|
IDWriteTextRenderer* iface,
|
||||||
void *clientDrawingContext,
|
void* clientDrawingContext,
|
||||||
FLOAT baselineOriginX,
|
FLOAT baselineOriginX,
|
||||||
FLOAT baselineOriginY,
|
FLOAT baselineOriginY,
|
||||||
DWRITE_STRIKETHROUGH const *strikethrough,
|
DWRITE_STRIKETHROUGH const* strikethrough,
|
||||||
IUnknown *clientDrawingEffect)
|
IUnknown* clientDrawingEffect) {
|
||||||
{
|
(void)iface;
|
||||||
(void)iface; (void)clientDrawingContext; (void)baselineOriginX;
|
(void)clientDrawingContext;
|
||||||
(void)baselineOriginY; (void)strikethrough; (void)clientDrawingEffect;
|
(void)baselineOriginX;
|
||||||
return E_NOTIMPL;
|
(void)baselineOriginY;
|
||||||
|
(void)strikethrough;
|
||||||
|
(void)clientDrawingEffect;
|
||||||
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE CTR_DrawInlineObject(
|
static HRESULT STDMETHODCALLTYPE CTR_DrawInlineObject(
|
||||||
IDWriteTextRenderer *iface,
|
IDWriteTextRenderer* iface,
|
||||||
void *clientDrawingContext,
|
void* clientDrawingContext,
|
||||||
FLOAT originX,
|
FLOAT originX,
|
||||||
FLOAT originY,
|
FLOAT originY,
|
||||||
IDWriteInlineObject *inlineObject,
|
IDWriteInlineObject* inlineObject,
|
||||||
BOOL isSideways,
|
BOOL isSideways,
|
||||||
BOOL isRightToLeft,
|
BOOL isRightToLeft,
|
||||||
IUnknown *clientDrawingEffect)
|
IUnknown* clientDrawingEffect) {
|
||||||
{
|
(void)iface;
|
||||||
(void)iface; (void)clientDrawingContext; (void)originX; (void)originY;
|
(void)clientDrawingContext;
|
||||||
(void)inlineObject; (void)isSideways; (void)isRightToLeft;
|
(void)originX;
|
||||||
(void)clientDrawingEffect;
|
(void)originY;
|
||||||
return E_NOTIMPL;
|
(void)inlineObject;
|
||||||
|
(void)isSideways;
|
||||||
|
(void)isRightToLeft;
|
||||||
|
(void)clientDrawingEffect;
|
||||||
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- Vtable instance ---- */
|
/* ---- Vtable instance ---- */
|
||||||
|
|
@ -493,46 +508,58 @@ static IDWriteTextRendererVtbl CTR_Vtbl = {
|
||||||
CTR_DrawGlyphRun,
|
CTR_DrawGlyphRun,
|
||||||
CTR_DrawUnderline,
|
CTR_DrawUnderline,
|
||||||
CTR_DrawStrikethrough,
|
CTR_DrawStrikethrough,
|
||||||
CTR_DrawInlineObject
|
CTR_DrawInlineObject};
|
||||||
};
|
|
||||||
|
|
||||||
/* ---- Constructor ---- */
|
/* ---- Constructor ---- */
|
||||||
|
|
||||||
static CustomTextRenderer *CustomTextRenderer_Create(IDWriteFactory6 * write_factory, IDWriteBitmapRenderTarget * target, MwLLColor color)
|
static CustomTextRenderer* CustomTextRenderer_Create(IDWriteFactory6* write_factory, IDWriteBitmapRenderTarget* target, MwLLColor color) {
|
||||||
{
|
CustomTextRenderer* obj =
|
||||||
CustomTextRenderer *obj =
|
(CustomTextRenderer*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||||
(CustomTextRenderer *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
sizeof(CustomTextRenderer));
|
||||||
sizeof(CustomTextRenderer));
|
if(!obj)
|
||||||
if (!obj)
|
return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
obj->lpVtbl = &CTR_Vtbl;
|
obj->lpVtbl = &CTR_Vtbl;
|
||||||
obj->refCount = 1;
|
obj->refCount = 1;
|
||||||
obj->write_factory = write_factory;
|
obj->write_factory = write_factory;
|
||||||
obj->target = target;
|
obj->target = target;
|
||||||
obj->red = color->common.red;
|
obj->red = color->common.red;
|
||||||
obj->green = color->common.green;
|
obj->green = color->common.green;
|
||||||
obj->blue = color->common.blue;
|
obj->blue = color->common.blue;
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWFL_DWSetup(void) {
|
int MWFL_DWSetup(void) {
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
CoInitialize(NULL);
|
||||||
|
|
||||||
/* Try and load DirectWrite. If it fails, return 1, signifying we default to bitmap drawing. */
|
/* Try and load DirectWrite. If it fails, return 1, signifying we default to bitmap drawing. */
|
||||||
dw_table.d2d1_lib = LoadLibrary("D2d1.dll");
|
dw_table.d2d1_lib = LoadLibrary("D2d1.dll");
|
||||||
if(!dw_table.d2d1_lib) {
|
if(!dw_table.d2d1_lib) {
|
||||||
printf("D2d1.dll not found, cannot use DirectWrite\n");
|
printf("D2d1.dll not found, cannot use DirectWrite\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
dw_table.dwrite_lib = LoadLibrary("dwrite.dll");
|
dw_table.dwrite_lib = LoadLibrary("dwrite.dll");
|
||||||
if(!dw_table.dwrite_lib) {
|
if(!dw_table.dwrite_lib) {
|
||||||
printf("dwrite.dll not found, cannot use DirectWrite\n");
|
printf("dwrite.dll not found, cannot use DirectWrite\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define D2D1_LOAD(x) dw_table.x = (typeof(dw_table.x))GetProcAddress(dw_table.d2d1_lib, #x); if(!dw_table.x) {printf("Can't use DirectWrite, "#x " not found."); return 1;}
|
#define D2D1_LOAD(x) \
|
||||||
|
dw_table.x = (typeof(dw_table.x))GetProcAddress(dw_table.d2d1_lib, #x); \
|
||||||
|
if(!dw_table.x) { \
|
||||||
|
printf("Can't use DirectWrite, " #x " not found."); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
#define DWRITE_LOAD(x) dw_table.x = (typeof(dw_table.x))GetProcAddress(dw_table.dwrite_lib, #x); if(!dw_table.x) {printf("Can't use DirectWrite, "#x " not found."); return 1;}
|
#define DWRITE_LOAD(x) \
|
||||||
|
dw_table.x = (typeof(dw_table.x))GetProcAddress(dw_table.dwrite_lib, #x); \
|
||||||
|
if(!dw_table.x) { \
|
||||||
|
printf("Can't use DirectWrite, " #x " not found."); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
D2D1_LOAD(D2D1CreateFactory);
|
D2D1_LOAD(D2D1CreateFactory);
|
||||||
DWRITE_LOAD(DWriteCreateFactory);
|
DWRITE_LOAD(DWriteCreateFactory);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue