Split the DirectWrite boilerplate to another C++ file so we can write a new font dialog with it, maybe.
This commit is contained in:
parent
edd9b2f133
commit
88e797e2be
|
@ -42,7 +42,8 @@ CFILES += \
|
||||||
windows/window.c
|
windows/window.c
|
||||||
|
|
||||||
CXXFILES += \
|
CXXFILES += \
|
||||||
windows/drawtext.cpp
|
windows/drawtext.cpp \
|
||||||
|
windows/dwrite.cpp
|
||||||
|
|
||||||
HFILES += \
|
HFILES += \
|
||||||
windows/area.h \
|
windows/area.h \
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
// 22 december 2015
|
// 22 december 2015
|
||||||
// Before we begin, you may be wondering why this file is C++.
|
|
||||||
// Simple: <dwrite.h> is C++ only! Thanks Microsoft!
|
|
||||||
// And unlike UI Automation which accidentally just forgets the 'struct' and 'enum' tags in places, <dwrite.h> is a full C++ header file, with class definitions and the use of __uuidof. Oh well :/
|
|
||||||
#include "uipriv_windows.h"
|
#include "uipriv_windows.h"
|
||||||
|
|
||||||
// notes:
|
// notes:
|
||||||
|
@ -11,100 +8,44 @@
|
||||||
// - justficiation (how could I possibly be making this up?!)
|
// - justficiation (how could I possibly be making this up?!)
|
||||||
// - vertical text (SERIOUSLY?! WHAT THE ACTUAL FUCK, MICROSOFT?!?!?!? DID YOU NOT THINK ABOUT THIS THE FIRST TIME, TRYING TO IMPROVE THE INTERNATIONALIZATION OF WINDOWS 7?!?!?! bonus: some parts of MSDN even say 8.1 and up only!)
|
// - vertical text (SERIOUSLY?! WHAT THE ACTUAL FUCK, MICROSOFT?!?!?!? DID YOU NOT THINK ABOUT THIS THE FIRST TIME, TRYING TO IMPROVE THE INTERNATIONALIZATION OF WINDOWS 7?!?!?! bonus: some parts of MSDN even say 8.1 and up only!)
|
||||||
|
|
||||||
static IDWriteFactory *dwfactory = NULL;
|
|
||||||
|
|
||||||
HRESULT initDrawText(void)
|
|
||||||
{
|
|
||||||
// TOOD use DWRITE_FACTORY_TYPE_ISOLATED instead?
|
|
||||||
return DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
|
|
||||||
__uuidof (IDWriteFactory),
|
|
||||||
(IUnknown **) (&dwfactory));
|
|
||||||
}
|
|
||||||
|
|
||||||
void uninitDrawText(void)
|
|
||||||
{
|
|
||||||
dwfactory->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uiDrawFontFamilies {
|
struct uiDrawFontFamilies {
|
||||||
IDWriteFontCollection *fonts;
|
fontCollection *fc;
|
||||||
WCHAR userLocale[LOCALE_NAME_MAX_LENGTH];
|
|
||||||
int userLocaleSuccess;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uiDrawFontFamilies *uiDrawListFontFamilies(void)
|
uiDrawFontFamilies *uiDrawListFontFamilies(void)
|
||||||
{
|
{
|
||||||
uiDrawFontFamilies *ff;
|
struct uiDrawFontFamilies *ff;
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
ff = uiNew(uiDrawFontFamilies);
|
ff = uiNew(struct uiDrawFontFamilies);
|
||||||
// always get the latest available font information
|
ff->fc = loadFontCollection();
|
||||||
hr = dwfactory->GetSystemFontCollection(&(ff->fonts), TRUE);
|
|
||||||
if (hr != S_OK)
|
|
||||||
logHRESULT("error getting system font collection in uiDrawListFontFamilies()", hr);
|
|
||||||
ff->userLocaleSuccess = GetUserDefaultLocaleName(ff->userLocale, LOCALE_NAME_MAX_LENGTH);
|
|
||||||
return ff;
|
return ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintmax_t uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff)
|
uintmax_t uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff)
|
||||||
{
|
{
|
||||||
return ff->fonts->GetFontFamilyCount();
|
return ff->fc->fonts->GetFontFamilyCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, uintmax_t n)
|
char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, uintmax_t n)
|
||||||
{
|
{
|
||||||
IDWriteFontFamily *family;
|
IDWriteFontFamily *family;
|
||||||
IDWriteLocalizedStrings *names;
|
|
||||||
UINT32 index;
|
|
||||||
BOOL exists;
|
|
||||||
UINT32 length;
|
|
||||||
WCHAR *wname;
|
WCHAR *wname;
|
||||||
char *name;
|
char *name;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
hr = ff->fonts->GetFontFamily(n, &family);
|
hr = ff->fc->fonts->GetFontFamily(n, &family);
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
logHRESULT("error getting font out of collection in uiDrawFontFamiliesFamily()", hr);
|
logHRESULT("error getting font out of collection in uiDrawFontFamiliesFamily()", hr);
|
||||||
hr = family->GetFamilyNames(&names);
|
wname = fontCollectionFamilyName(ff->fc, family);
|
||||||
if (hr != S_OK)
|
|
||||||
logHRESULT("error getting names of font out in uiDrawFontFamiliesFamily()", hr);
|
|
||||||
|
|
||||||
// this is complex, but we ignore failure conditions to allow fallbacks
|
|
||||||
// 1) If the user locale name was successfully retrieved, try it
|
|
||||||
// 2) If the user locale name was not successfully retrieved, or that locale's string does not exist, or an error occurred, try L"en-us", the US English locale
|
|
||||||
// 3) And if that fails, assume the first one
|
|
||||||
// This algorithm is straight from MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/dd368214%28v=vs.85%29.aspx
|
|
||||||
// For step 2 to work, start by setting hr to S_OK and exists to FALSE.
|
|
||||||
// TODO does it skip step 2 entirely if step 1 fails? rewrite it to be a more pure conversion of the MSDN code?
|
|
||||||
hr = S_OK;
|
|
||||||
exists = FALSE;
|
|
||||||
if (ff->userLocaleSuccess != 0)
|
|
||||||
hr = names->FindLocaleName(ff->userLocale, &index, &exists);
|
|
||||||
if (hr != S_OK || (hr == S_OK && !exists))
|
|
||||||
hr = names->FindLocaleName(L"en-us", &index, &exists);
|
|
||||||
if (!exists)
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
hr = names->GetStringLength(index, &length);
|
|
||||||
if (hr != S_OK)
|
|
||||||
logHRESULT("error getting length of font name in uiDrawFontFamiliesFamily()", hr);
|
|
||||||
// GetStringLength() does not include the null terminator, but GetString() does
|
|
||||||
wname = (WCHAR *) uiAlloc((length + 1) * sizeof (WCHAR), "WCHAR[]");
|
|
||||||
hr = names->GetString(index, wname, length + 1);
|
|
||||||
if (hr != S_OK)
|
|
||||||
logHRESULT("error getting font name in uiDrawFontFamiliesFamily()", hr);
|
|
||||||
|
|
||||||
name = toUTF8(wname);
|
name = toUTF8(wname);
|
||||||
|
|
||||||
uiFree(wname);
|
uiFree(wname);
|
||||||
names->Release();
|
|
||||||
family->Release();
|
family->Release();
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff)
|
void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff)
|
||||||
{
|
{
|
||||||
ff->fonts->Release();
|
fontCollectionFree(ff->fc);
|
||||||
uiFree(ff);
|
uiFree(ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
// 14 april 2016
|
||||||
|
// Before we begin, you may be wondering why this file is C++.
|
||||||
|
// Simple: <dwrite.h> is C++ only! Thanks Microsoft!
|
||||||
|
// And unlike UI Automation which accidentally just forgets the 'struct' and 'enum' tags in places, <dwrite.h> is a full C++ header file, with class definitions and the use of __uuidof. Oh well :/
|
||||||
|
#include "uipriv_windows.h"
|
||||||
|
|
||||||
|
IDWriteFactory *dwfactory = NULL;
|
||||||
|
|
||||||
|
HRESULT initDrawText(void)
|
||||||
|
{
|
||||||
|
// TOOD use DWRITE_FACTORY_TYPE_ISOLATED instead?
|
||||||
|
return DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
|
||||||
|
__uuidof (IDWriteFactory),
|
||||||
|
(IUnknown **) (&dwfactory));
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninitDrawText(void)
|
||||||
|
{
|
||||||
|
dwfactory->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
fontCollection *loadFontCollection(void)
|
||||||
|
{
|
||||||
|
fontCollection *fc;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
fc = uiNew(fontCollection);
|
||||||
|
// always get the latest available font information
|
||||||
|
hr = dwfactory->GetSystemFontCollection(&(fc->fonts), TRUE);
|
||||||
|
if (hr != S_OK)
|
||||||
|
logHRESULT("error getting system font collection in loadFontCollection()", hr);
|
||||||
|
fc->userLocaleSuccess = GetUserDefaultLocaleName(fc->userLocale, LOCALE_NAME_MAX_LENGTH);
|
||||||
|
return fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
WCHAR *fontCollectionFamilyName(fontCollection *fc, IDWriteFontFamily *family)
|
||||||
|
{
|
||||||
|
IDWriteLocalizedStrings *names;
|
||||||
|
UINT32 index;
|
||||||
|
BOOL exists;
|
||||||
|
UINT32 length;
|
||||||
|
WCHAR *wname;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = family->GetFamilyNames(&names);
|
||||||
|
if (hr != S_OK)
|
||||||
|
logHRESULT("error getting names of font out in fontCollectionFamilyName()", hr);
|
||||||
|
|
||||||
|
// this is complex, but we ignore failure conditions to allow fallbacks
|
||||||
|
// 1) If the user locale name was successfully retrieved, try it
|
||||||
|
// 2) If the user locale name was not successfully retrieved, or that locale's string does not exist, or an error occurred, try L"en-us", the US English locale
|
||||||
|
// 3) And if that fails, assume the first one
|
||||||
|
// This algorithm is straight from MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/dd368214%28v=vs.85%29.aspx
|
||||||
|
// For step 2 to work, start by setting hr to S_OK and exists to FALSE.
|
||||||
|
// TODO does it skip step 2 entirely if step 1 fails? rewrite it to be a more pure conversion of the MSDN code?
|
||||||
|
hr = S_OK;
|
||||||
|
exists = FALSE;
|
||||||
|
if (fc->userLocaleSuccess != 0)
|
||||||
|
hr = names->FindLocaleName(fc->userLocale, &index, &exists);
|
||||||
|
if (hr != S_OK || (hr == S_OK && !exists))
|
||||||
|
hr = names->FindLocaleName(L"en-us", &index, &exists);
|
||||||
|
if (!exists)
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
hr = names->GetStringLength(index, &length);
|
||||||
|
if (hr != S_OK)
|
||||||
|
logHRESULT("error getting length of font name in fontCollectionFamilyName()", hr);
|
||||||
|
// GetStringLength() does not include the null terminator, but GetString() does
|
||||||
|
wname = (WCHAR *) uiAlloc((length + 1) * sizeof (WCHAR), "WCHAR[]");
|
||||||
|
hr = names->GetString(index, wname, length + 1);
|
||||||
|
if (hr != S_OK)
|
||||||
|
logHRESULT("error getting font name in fontCollectionFamilyName()", hr);
|
||||||
|
|
||||||
|
names->Release();
|
||||||
|
return wname;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fontCollectionFree(fontCollection *fc)
|
||||||
|
{
|
||||||
|
fc->fonts->Release();
|
||||||
|
uiFree(fc);
|
||||||
|
}
|
|
@ -135,9 +135,24 @@ extern ID2D1HwndRenderTarget *makeHWNDRenderTarget(HWND hwnd);
|
||||||
extern uiDrawContext *newContext(ID2D1RenderTarget *);
|
extern uiDrawContext *newContext(ID2D1RenderTarget *);
|
||||||
extern void freeContext(uiDrawContext *);
|
extern void freeContext(uiDrawContext *);
|
||||||
|
|
||||||
// drawtext.cpp
|
// dwrite.cpp
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern IDWriteFactory *dwfactory;
|
||||||
|
#endif
|
||||||
extern HRESULT initDrawText(void);
|
extern HRESULT initDrawText(void);
|
||||||
extern void uninitDrawText(void);
|
extern void uninitDrawText(void);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
struct fontCollection {
|
||||||
|
IDWriteFontCollection *fonts;
|
||||||
|
WCHAR userLocale[LOCALE_NAME_MAX_LENGTH];
|
||||||
|
int userLocaleSuccess;
|
||||||
|
};
|
||||||
|
extern fontCollection *loadFontCollection(void);
|
||||||
|
extern WCHAR *fontCollectionFamilyName(fontCollection *fc, IDWriteFontFamily *family);
|
||||||
|
extern void fontCollectionFree(fontCollection *fc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// drawtext.cpp
|
||||||
extern void doDrawText(ID2D1RenderTarget *rt, ID2D1Brush *black, double x, double y, uiDrawTextLayout *layout);
|
extern void doDrawText(ID2D1RenderTarget *rt, ID2D1Brush *black, double x, double y, uiDrawTextLayout *layout);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
Loading…
Reference in New Issue