Started work on previewing samples of fonts in the new font dialog. This adds all the boilerplate, including sample positioning. Also tightens up the dialog a bit. Now just to implement the actual drawing.

This commit is contained in:
Pietro Gagliardi 2016-04-16 17:58:45 -04:00
parent d994ab9205
commit 351fc59b9f
3 changed files with 197 additions and 5 deletions

View File

@ -10,6 +10,8 @@ struct fontDialog {
fontCollection *fc; fontCollection *fc;
IDWriteFontFamily **families; IDWriteFontFamily **families;
UINT32 nFamilies; UINT32 nFamilies;
IDWriteGdiInterop *gdiInterop;
RECT sampleRect;
}; };
static LRESULT cbAddString(HWND cb, WCHAR *str) static LRESULT cbAddString(HWND cb, WCHAR *str)
@ -113,7 +115,11 @@ static void familyChanged(struct fontDialog *f)
logLastError("error setting font data in styles box in familyChanged()"); logLastError("error setting font data in styles box in familyChanged()");
} }
// TODO do we preserve style selection? // TODO how do we preserve style selection? the real thing seems to have a very elaborate method of doing so
// TODO check error
SendMessageW(f->styleCombobox, CB_SETCURSEL, 0, 0);
// TODO refine this a bit
InvalidateRect(f->hwnd, NULL, TRUE/*TODO*/);
} }
static struct fontDialog *beginFontDialog(HWND hwnd, LPARAM lParam) static struct fontDialog *beginFontDialog(HWND hwnd, LPARAM lParam)
@ -122,6 +128,7 @@ static struct fontDialog *beginFontDialog(HWND hwnd, LPARAM lParam)
UINT32 i; UINT32 i;
WCHAR *wname; WCHAR *wname;
LRESULT ten; LRESULT ten;
HWND samplePlacement;
HRESULT hr; HRESULT hr;
f = uiNew(struct fontDialog); f = uiNew(struct fontDialog);
@ -189,6 +196,19 @@ static struct fontDialog *beginFontDialog(HWND hwnd, LPARAM lParam)
logLastError("error selecting Arial in the family combobox in beginFontDialog()"); logLastError("error selecting Arial in the family combobox in beginFontDialog()");
familyChanged(f); familyChanged(f);
hr = dwfactory->GetGdiInterop(&(f->gdiInterop));
if (hr != S_OK)
logHRESULT("error getting GDI interop for font dialog in beginFontDialog()", hr);
samplePlacement = GetDlgItem(f->hwnd, rcFontSamplePlacement);
if (samplePlacement == NULL)
logLastError("error getting sample placement static control handle in beginFontDialog()");
if (GetWindowRect(samplePlacement, &(f->sampleRect)) == 0)
logLastError("error getting sample placement in beginFontDialog()");
mapWindowRect(NULL, f->hwnd, &(f->sampleRect));
if (DestroyWindow(samplePlacement) == 0)
logLastError("error getting rid of the sample placement static control in beginFontDialog()");
return f; return f;
} }
@ -196,6 +216,7 @@ static void endFontDialog(struct fontDialog *f, INT_PTR code)
{ {
UINT32 i; UINT32 i;
f->gdiInterop->Release();
wipeStylesBox(f); wipeStylesBox(f);
for (i = 0; i < f->nFamilies; i++) for (i = 0; i < f->nFamilies; i++)
f->families[i]->Release(); f->families[i]->Release();
@ -220,6 +241,169 @@ static INT_PTR tryFinishDialog(struct fontDialog *f, WPARAM wParam)
return TRUE; return TRUE;
} }
class gdiRenderer : public IDWriteTextRenderer {
public:
ULONG refcount;
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IDWritePixelSnapping
STDMETHODIMP GetCurrentTransform(void *clientDrawingContext, DWRITE_MATRIX *transform);
STDMETHODIMP GetPixelsPerDip(void *clientDrawingContext, FLOAT *pixelsPerDip);
STDMETHODIMP IsPixelSnappingDisabled(void *clientDrawingContext, BOOL *isDisabled);
// IDWriteTextRenderer
STDMETHODIMP DrawGlyphRun(
void *clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
const DWRITE_GLYPH_RUN *glyphRun,
const DWRITE_GLYPH_RUN_DESCRIPTION *glyphRunDescription,
IUnknown *clientDrawingEffect);
STDMETHODIMP DrawInlineObject(void *clientDrawingContext, FLOAT originX, FLOAT originY, IDWriteInlineObject *inlineObject, BOOL isSideways, BOOL isRightToLeft, IUnknown *clientDrawingEffect);
STDMETHODIMP DrawStrikethrough(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *clientDrawingEffect);
STDMETHODIMP DrawUnderline(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, const DWRITE_UNDERLINE *underline, IUnknown *clientDrawingEffect);
};
STDMETHODIMP gdiRenderer::QueryInterface(REFIID riid, void **ppv)
{
if (ppv == NULL)
return E_POINTER;
if (riid == IID_IUnknown ||
riid == __uuidof (IDWritePixelSnapping) ||
riid == __uuidof (IDWriteTextRenderer)) {
*ppv = static_cast<IDWriteTextRenderer *>(this);
this->AddRef();
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) gdiRenderer::AddRef()
{
this->refcount++;
return this->refcount;
}
STDMETHODIMP_(ULONG) gdiRenderer::Release()
{
this->refcount--;
if (this->refcount == 0) {
delete this;
return 0;
}
return this->refcount;
}
STDMETHODIMP gdiRenderer::GetCurrentTransform(void *clientDrawingContext, DWRITE_MATRIX *transform)
{
IDWriteBitmapRenderTarget *target = (IDWriteBitmapRenderTarget *) clientDrawingContext;
return target->GetCurrentTransform(transform);
}
STDMETHODIMP gdiRenderer::GetPixelsPerDip(void *clientDrawingContext, FLOAT *pixelsPerDip)
{
IDWriteBitmapRenderTarget *target = (IDWriteBitmapRenderTarget *) clientDrawingContext;
if (pixelsPerDip == NULL)
return E_POINTER;
*pixelsPerDip = target->GetPixelsPerDip();
return S_OK;
}
STDMETHODIMP gdiRenderer::IsPixelSnappingDisabled(void *clientDrawingContext, BOOL *isDisabled)
{
// TODO this is the MSDN recommendation
if (isDisabled == NULL)
return E_POINTER;
*isDisabled = FALSE;
return S_OK;
}
STDMETHODIMP gdiRenderer::DrawGlyphRun(
void *clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
const DWRITE_GLYPH_RUN *glyphRun,
const DWRITE_GLYPH_RUN_DESCRIPTION *glyphRunDescription,
IUnknown *clientDrawingEffect)
{
IDWriteBitmapRenderTarget *target = (IDWriteBitmapRenderTarget *) clientDrawingContext;
return target->DrawGlyphRun(
baselineOriginX,
baselineOriginY,
measuringMode,
glyphRun,
NULL,
RGB(0, 0, 0),
NULL);
}
STDMETHODIMP gdiRenderer::DrawInlineObject(void *clientDrawingContext, FLOAT originX, FLOAT originY, IDWriteInlineObject *inlineObject, BOOL isSideways, BOOL isRightToLeft, IUnknown *clientDrawingEffect)
{
return E_NOTIMPL;
}
STDMETHODIMP gdiRenderer::DrawStrikethrough(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *clientDrawingEffect)
{
return E_NOTIMPL;
}
STDMETHODIMP gdiRenderer::DrawUnderline(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, const DWRITE_UNDERLINE *underline, IUnknown *clientDrawingEffect)
{
return E_NOTIMPL;
}
// TODO consider using Direct2D instead
static void doPaint(struct fontDialog *f)
{
PAINTSTRUCT ps;
HDC dc;
IDWriteBitmapRenderTarget *target;
gdiRenderer *renderer;
HDC memoryDC;
RECT memoryRect;
HRESULT hr;
dc = BeginPaint(f->hwnd, &ps);
if (dc == NULL)
logLastError("error beginning font dialog redraw in doPaint()");
hr = f->gdiInterop->CreateBitmapRenderTarget(dc,
f->sampleRect.right - f->sampleRect.left, f->sampleRect.bottom - f->sampleRect.top,
&target);
if (hr != S_OK)
logHRESULT("error creating bitmap render target for font dialog in doPaint()", hr);
renderer = new gdiRenderer;
renderer->refcount = 1;
// TODO actually draw
memoryDC = target->GetMemoryDC();
if (GetBoundsRect(memoryDC, &memoryRect, 0) == 0)
logLastError("error getting size of memory DC for font dialog in doPaint()");
if (BitBlt(dc,
f->sampleRect.left, f->sampleRect.top,
memoryRect.right - memoryRect.left, memoryRect.bottom - memoryRect.top,
memoryDC,
0, 0,
SRCCOPY | NOMIRRORBITMAP) == 0)
logLastError("error blitting sample text to font dialog in doPaint()");
renderer->Release();
target->Release();
EndPaint(f->hwnd, &ps);
}
static INT_PTR CALLBACK fontDialogDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) static INT_PTR CALLBACK fontDialogDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
struct fontDialog *f; struct fontDialog *f;
@ -236,6 +420,7 @@ static INT_PTR CALLBACK fontDialogDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, L
switch (uMsg) { switch (uMsg) {
case WM_COMMAND: case WM_COMMAND:
SetWindowLongPtrW(f->hwnd, DWLP_MSGRESULT, 0); // just in case
switch (LOWORD(wParam)) { switch (LOWORD(wParam)) {
case IDOK: case IDOK:
case IDCANCEL: case IDCANCEL:
@ -249,6 +434,10 @@ static INT_PTR CALLBACK fontDialogDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, L
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
case WM_PAINT:
doPaint(f);
SetWindowLongPtrW(f->hwnd, DWLP_MSGRESULT, 0);
return TRUE;
} }
return FALSE; return FALSE;
} }

View File

@ -6,3 +6,4 @@
#define rcFontFamilyCombobox 1000 #define rcFontFamilyCombobox 1000
#define rcFontStyleCombobox 1001 #define rcFontStyleCombobox 1001
#define rcFontSizeCombobox 1002 #define rcFontSizeCombobox 1002
#define rcFontSamplePlacement 1003

View File

@ -20,7 +20,8 @@ END
// this is for our custom DirectWrite-based font dialog (see fontdialog.cpp) // this is for our custom DirectWrite-based font dialog (see fontdialog.cpp)
// this is based on the "New Font Dialog with Syslink" in Microsoft's font.dlg // this is based on the "New Font Dialog with Syslink" in Microsoft's font.dlg
// TODO look at localization // TODO look at localization
rcFontDialog DIALOGEX 13, 54, 243, 234 // TODO make it look tighter and nicer like the real one, including the actual heights of the font family and style comboboxes
rcFontDialog DIALOGEX 13, 54, 243, 200
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_3DLOOK STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_3DLOOK
CAPTION "Font" CAPTION "Font"
FONT 9, "Segoe UI" FONT 9, "Segoe UI"
@ -40,8 +41,9 @@ BEGIN
CBS_SIMPLE | CBS_AUTOHSCROLL | CBS_DISABLENOSCROLL | CBS_SIMPLE | CBS_AUTOHSCROLL | CBS_DISABLENOSCROLL |
CBS_SORT | WS_VSCROLL | WS_TABSTOP | CBS_HASSTRINGS CBS_SORT | WS_VSCROLL | WS_TABSTOP | CBS_HASSTRINGS
GROUPBOX "Sample", -1, 114, 97, 120, 43, WS_GROUP GROUPBOX "Sample", -1, 7, 97, 227, 70, WS_GROUP
CTEXT "AaBbYyZz", rcFontSamplePlacement, 9, 106, 224, 60, SS_NOPREFIX | NOT WS_VISIBLE
DEFPUSHBUTTON "OK", IDOK, 141, 215, 45, 14, WS_GROUP DEFPUSHBUTTON "OK", IDOK, 141, 181, 45, 14, WS_GROUP
PUSHBUTTON "Cancel", IDCANCEL, 190, 215, 45, 14, WS_GROUP PUSHBUTTON "Cancel", IDCANCEL, 190, 181, 45, 14, WS_GROUP
END END