More work on the initial font and showing styles. I have a feeling my current approach is a mistake.

This commit is contained in:
Pietro Gagliardi 2016-04-18 13:32:48 -04:00
parent 84fc5dafaa
commit ccfa3d41a3
5 changed files with 114 additions and 37 deletions

View File

@ -2,7 +2,6 @@
#import "uipriv_darwin.h"
// TODO drag and drop fonts? what other interactions does NSColorWell allow that we can do for fonts?
// TODO display style? or is it already displayed?
@interface fontButton : NSButton {
uiFontButton *libui_b;

View File

@ -1,8 +1,6 @@
// 14 april 2016
#include "uipriv_unix.h"
// TODO display style? or is it already displayed?
struct uiFontButton {
uiUnixControl c;
GtkWidget *widget;

View File

@ -6,7 +6,7 @@
struct uiFontButton {
uiWindowsControl c;
HWND hwnd;
uiDrawTextFontDescriptor desc;
struct fontDialogParams params;
BOOL already;
};
@ -23,8 +23,8 @@ static void updateFontButtonLabel(uiFontButton *b)
WCHAR text[1024];
WCHAR *family;
family = toUTF16(b->desc.Family);
_snwprintf(text, 1024, L"%s %g", family, b->desc.Size);
family = toUTF16(b->params.desc.Family);
_snwprintf(text, 1024, L"%s %s %g", family, b->params.outStyleName, b->params.desc.Size);
uiFree(family);
// TODO error check
SendMessageW(b->hwnd, WM_SETTEXT, 0, (LPARAM) text);
@ -37,17 +37,12 @@ static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult)
{
uiFontButton *b = uiFontButton(c);
HWND parent;
char *oldFamily;
if (code != BN_CLICKED)
return FALSE;
parent = GetAncestor(b->hwnd, GA_ROOT); // TODO didn't we have a function for this
oldFamily = (char *) (b->desc.Family);
if (showFontDialog(parent, &(b->desc))) {
if (b->already) // don't free the static Arial string
uiFree(oldFamily);
b->already = TRUE;
if (showFontDialog(parent, &(b->params))) {
updateFontButtonLabel(b);
// TODO event
}
@ -109,12 +104,7 @@ uiFontButton *uiNewFontButton(void)
hInstance, NULL,
TRUE);
// arbitrary defaults that will do
b->desc.Family = "Arial";
b->desc.Size = 10; // from the real font dialog
b->desc.Weight = uiDrawTextWeightNormal;
b->desc.Italic = uiDrawTextItalicNormal;
b->desc.Stretch = uiDrawTextStretchNormal;
loadInitialFontDialogParams(&(b->params));
updateFontButtonLabel(b);
uiWindowsRegisterWM_COMMANDHandler(b->hwnd, onWM_COMMAND, uiControl(b));

View File

@ -5,6 +5,7 @@
// - quote the Choose Font sample here for reference
// - the Choose Font sample defaults to Regular/Italic/Bold/Bold Italic in some case (no styles?); do we? find out what the case is
// - do we set initial family and style topmost as well?
// - this should probably just handle IDWriteFonts
struct fontDialog {
HWND hwnd;
@ -12,7 +13,7 @@ struct fontDialog {
HWND styleCombobox;
HWND sizeCombobox;
uiDrawTextFontDescriptor *desc;
struct fontDialogParams *params;
fontCollection *fc;
@ -156,7 +157,7 @@ static void wipeStylesBox(struct fontDialog *f)
cbWipeAndReleaseData(f->styleCombobox);
}
static WCHAR *fontStyleName(struct fontDialog *f, IDWriteFont *font)
static WCHAR *fontStyleName(struct fontCollection *fc, IDWriteFont *font)
{
IDWriteLocalizedStrings *str;
WCHAR *wstr;
@ -165,7 +166,7 @@ static WCHAR *fontStyleName(struct fontDialog *f, IDWriteFont *font)
hr = font->GetFaceNames(&str);
if (hr != S_OK)
logHRESULT("error getting font style name for font dialog in fontStyleName()", hr);
wstr = fontCollectionCorrectString(f->fc, str);
wstr = fontCollectionCorrectString(fc, str);
str->Release();
return wstr;
}
@ -249,7 +250,7 @@ static void familyChanged(struct fontDialog *f)
hr = family->GetFont(i, &font);
if (hr != S_OK)
logHRESULT("error getting font for filling styles box in familyChanged()", hr);
label = fontStyleName(f, font);
label = fontStyleName(f->fc, font);
pos = cbAddString(f->styleCombobox, label);
uiFree(label);
cbSetItemData(f->styleCombobox, (WPARAM) pos, (LPARAM) font);
@ -428,15 +429,15 @@ static void setupInitialFontDialogState(struct fontDialog *f)
WCHAR wsize[512]; // this should be way more than enough
LRESULT pos;
// first convert f->desc into a usable form
wfamily = toUTF16(f->desc->Family);
// first convert f->params->desc into a usable form
wfamily = toUTF16(f->params->desc.Family);
// see below for why we do this specifically
// TODO is 512 the correct number to pass to _snwprintf()?
// TODO will this revert to scientific notation?
_snwprintf(wsize, 512, L"%g", f->desc->Size);
attr.weight = f->desc->Weight;
attr.italic = f->desc->Italic;
attr.stretch = f->desc->Stretch;
_snwprintf(wsize, 512, L"%g", f->params->desc.Size);
attr.weight = f->params.desc->Weight;
attr.italic = f->params.desc->Italic;
attr.stretch = f->params.desc->Stretch;
attrToDWriteAttr(&attr);
// first let's load the size
@ -475,7 +476,7 @@ static struct fontDialog *beginFontDialog(HWND hwnd, LPARAM lParam)
f = uiNew(struct fontDialog);
f->hwnd = hwnd;
f->desc = (uiDrawTextFontDescriptor *) lParam;
f->params = (struct fontDialogParams *) lParam;
f->familyCombobox = GetDlgItem(f->hwnd, rcFontFamilyCombobox);
if (f->familyCombobox == NULL)
@ -540,17 +541,23 @@ static INT_PTR tryFinishDialog(struct fontDialog *f, WPARAM wParam)
// OK
wfamily = cbGetItemText(f->familyCombobox, f->curFamily);
f->desc->Family = toUTF8(wfamily);
uiFree(f->params->desc.Family);
f->params->desc.Family = toUTF8(wfamily);
uiFree(wfamily);
f->desc->Size = f->curSize;
f->params->desc.Size = f->curSize;
font = (IDWriteFont *) cbGetItemData(f->styleCombobox, f->curStyle);
attr.dweight = font->GetWeight();
attr.ditalic = font->GetStyle();
attr.dstretch = font->GetStretch();
dwriteAttrToAttr(&attr);
f->desc->Weight = attr.weight;
f->desc->Italic = attr.italic;
f->desc->Stretch = attr.stretch;
f->params->desc.Weight = attr.weight;
f->params->desc.Italic = attr.italic;
f->params->desc.Stretch = attr.stretch;
uiFree(f->params->outStyleName);
// TODO rename to wstr
wfamily = fontStyleName(f->fc, font);
f->params->outStyleName = toUTF8(wfamily);
uiFree(wfamily);
endFontDialog(f, 2);
return TRUE;
}
@ -614,9 +621,9 @@ static INT_PTR CALLBACK fontDialogDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, L
return FALSE;
}
BOOL showFontDialog(HWND parent, uiDrawTextFontDescriptor *desc)
BOOL showFontDialog(HWND parent, struct fontDialogParams *params)
{
switch (DialogBoxParamW(hInstance, MAKEINTRESOURCE(rcFontDialog), parent, fontDialogDlgProc, (LPARAM) desc)) {
switch (DialogBoxParamW(hInstance, MAKEINTRESOURCE(rcFontDialog), parent, fontDialogDlgProc, (LPARAM) params)) {
case 1: // cancel
return FALSE;
case 2: // ok
@ -627,3 +634,81 @@ BOOL showFontDialog(HWND parent, uiDrawTextFontDescriptor *desc)
}
return TRUE;
}
static IDWriteFontFamily *tryFindFamily(IDWriteFontCollection *fc, const WCHAR *name)
{
UINT32 index;
BOOL exists;
IDWriteFontFamily *family;
HRESULT hr;
hr = fc->FindFamilyName(name, &index, &exists);
if (hr != S_OK)
logHRESULT("error finding font family for font dialog in tryFindFamily()", hr);
if (!exists)
return NULL;
hr = fc->GetFontFamily(index, &family);
if (hr != S_OK)
logHRESULT("error extracting found font family for font dialog in tryFindFamily()", hr);
return family;
}
void loadInitialFontDialogParams(struct fontDialogParams *params)
{
struct fontCollection *fc;
IDWriteFontFamily *family;
IDWriteFont *font;
struct attr;
WCHAR *wstr;
HRESULT hr;
// Our preferred font is Arial 10 Regular.
// 10 comes from the official font dialog.
// Arial Regular is a reasonable, if arbitrary, default; it's similar to the defaults on other systems.
// If Arial isn't found, we'll use Helvetica and then MS Sans Serif as fallbacks, and if not, we'll just grab the first font family in the collection.
// We need the correct localized name for Regular (and possibly Arial too? let's say yes to be safe), so let's grab the strings from DirectWrite instead of hardcoding them.
fc = loadFontCollection();
family = tryFindFamily(fc->fonts, L"Arial");
if (family == NULL) {
family = tryFindFamily(fc->fonts, L"Helvetica");
if (family == NULL) {
family = tryFindFamily(fc->fonts, L"MS Sans Serif");
if (family == NULL) {
hr = fc->fonts->GetFontFamily(0, &family);
if (hr != S_OK)
logHRESULT("error getting first font out of font collection (worst case scenario) in loadInitialFontDialogParams()", hr);
}
}
}
// next part is simple: just get the closest match to regular
hr = family->GetFirstMatchingFont(
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
&font);
if (hr != S_OK)
logHRESULT("error getting Regular font from Arial in loadInitialFontDialogParams()", hr);
// now convert attributes in the actual font...
attr.dweight = font->GetWeight();
attr.ditalic = font->GetStyle();
attr.dstretch = font->GetStretch();
dwriteAttrToAttr(&attr);
// and finally fill the structure
wstr = fontCollectionFamilyName(fc, family);
params->desc.Family = toUTF8(wstr);
uiFree(wstr);
params->desc.Size = 10;
params->desc.Weight = attr.weight;
params->desc.Italic = attr.italic;
params->desc.Stretch = attr.stretch;
wstr = fontStyleName(fc, font);
params->outStyleName = toUTF8(wstr);
uiFree(wstr);
font->Release();
family->Release();
fontCollectionFree(fc);
}

View File

@ -170,7 +170,12 @@ extern void dwriteAttrToAttr(struct dwriteAttr *attr);
extern void doDrawText(ID2D1RenderTarget *rt, ID2D1Brush *black, double x, double y, uiDrawTextLayout *layout);
// fontdialog.cpp
extern BOOL showFontDialog(HWND parent, uiDrawTextFontDescriptor *desc);
struct fontDialogParams {
uiDrawTextFontDescriptor desc;
WCHAR *outStyleName;
};
extern BOOL showFontDialog(HWND parent, struct fontDialogParams *params);
extern void loadInitialFontDialogParams(struct fontDialogParams *params);
// d2dscratch.c
extern ATOM registerD2DScratchClass(HICON, HCURSOR);