2016-04-14 20:35:50 -05:00
// 14 april 2016
# include "uipriv_windows.h"
struct fontDialog {
HWND hwnd ;
HWND familyCombobox ;
HWND styleCombobox ;
HWND sizeCombobox ;
2016-04-17 00:34:05 -05:00
2016-04-14 20:35:50 -05:00
// TODO desc;
2016-04-17 00:34:05 -05:00
2016-04-14 20:35:50 -05:00
fontCollection * fc ;
2016-04-17 00:34:05 -05:00
2016-04-16 16:58:45 -05:00
IDWriteGdiInterop * gdiInterop ;
RECT sampleRect ;
2016-04-17 00:34:05 -05:00
// we store the current selections in case an invalid string is typed in (partial or nonexistent or invalid number)
// on OK, these are what are read
LRESULT curFamily ;
LRESULT curStyle ;
LRESULT curSize ;
2016-04-14 20:35:50 -05:00
} ;
2016-04-14 21:25:32 -05:00
static LRESULT cbAddString ( HWND cb , WCHAR * str )
{
LRESULT lr ;
lr = SendMessageW ( cb , CB_ADDSTRING , 0 , ( LPARAM ) str ) ;
if ( lr = = ( LRESULT ) CB_ERR | | lr = = ( LRESULT ) CB_ERRSPACE )
logLastError ( " error adding item to combobox in cbAddString() " ) ;
return lr ;
}
static LRESULT cbInsertStringAtTop ( HWND cb , WCHAR * str )
{
LRESULT lr ;
lr = SendMessageW ( cb , CB_INSERTSTRING , 0 , ( LPARAM ) str ) ;
if ( lr = = ( LRESULT ) CB_ERR | | lr = = ( LRESULT ) CB_ERRSPACE )
logLastError ( " error inserting item to combobox in cbInsertStringAtTop() " ) ;
return lr ;
}
2016-04-17 00:34:05 -05:00
static LRESULT cbGetItemData ( HWND cb , WPARAM item )
2016-04-15 12:18:06 -05:00
{
2016-04-17 00:34:05 -05:00
LRESULT data ;
data = SendMessageW ( cb , CB_GETITEMDATA , item , 0 ) ;
if ( data = = ( LRESULT ) CB_ERR )
logLastError ( " error getting combobox item data for font dialog in cbGetItemData() " ) ;
return data ;
}
static void cbSetItemData ( HWND cb , WPARAM item , LPARAM data )
{
if ( SendMessageW ( cb , CB_SETITEMDATA , item , data ) = = ( LRESULT ) CB_ERR )
logLastError ( " error setting combobox item data in cbSetItemData() " ) ;
}
static BOOL cbGetCurSel ( HWND cb , LRESULT * sel )
{
LRESULT n ;
n = SendMessageW ( cb , CB_GETCURSEL , 0 , 0 ) ;
if ( n = = ( LRESULT ) CB_ERR )
return FALSE ;
if ( sel ! = NULL )
* sel = n ;
return TRUE ;
}
static void cbSetCurSel ( HWND cb , WPARAM item )
{
if ( SendMessageW ( cb , CB_SETCURSEL , item , 0 ) ! = 0 )
logLastError ( " error selecting combobox item in cbSetCurSel() " ) ;
}
2016-04-15 12:18:06 -05:00
2016-04-17 00:34:05 -05:00
static LRESULT cbGetCount ( HWND cb )
{
LRESULT n ;
n = SendMessageW ( cb , CB_GETCOUNT , 0 , 0 ) ;
2016-04-15 12:18:06 -05:00
if ( n = = ( LRESULT ) CB_ERR )
2016-04-17 00:34:05 -05:00
logLastError ( " error getting combobox item count in cbGetCount() " ) ;
return n ;
}
static void cbWipeAndReleaseData ( HWND cb )
{
IUnknown * obj ;
LRESULT i , n ;
n = cbGetCount ( cb ) ;
2016-04-15 12:18:06 -05:00
for ( i = 0 ; i < n ; i + + ) {
2016-04-17 00:34:05 -05:00
obj = ( IUnknown * ) cbGetItemData ( cb , ( WPARAM ) i ) ;
obj - > Release ( ) ;
2016-04-15 12:18:06 -05:00
}
2016-04-17 00:34:05 -05:00
SendMessageW ( cb , CB_RESETCONTENT , 0 , 0 ) ;
}
static void wipeStylesBox ( struct fontDialog * f )
{
cbWipeAndReleaseData ( f - > styleCombobox ) ;
2016-04-15 12:18:06 -05:00
}
static WCHAR * fontStyleName ( struct fontDialog * f , IDWriteFont * font )
{
IDWriteLocalizedStrings * str ;
BOOL exists ;
WCHAR * wstr ;
HRESULT hr ;
2016-04-17 00:34:05 -05:00
hr = font - > GetFaceNames ( & str ) ;
2016-04-15 12:18:06 -05:00
if ( hr ! = S_OK )
2016-04-17 00:34:05 -05:00
logHRESULT ( " error getting font style name for font dialog in fontStyleName() " , hr ) ;
2016-04-15 12:18:06 -05:00
wstr = fontCollectionCorrectString ( f - > fc , str ) ;
str - > Release ( ) ;
return wstr ;
}
static void familyChanged ( struct fontDialog * f )
{
2016-04-17 00:34:05 -05:00
LRESULT pos ;
BOOL selected ;
2016-04-16 21:46:39 -05:00
IDWriteFontFamily * family ;
2016-04-17 00:34:05 -05:00
IDWriteFont * font ;
2016-04-16 21:46:39 -05:00
UINT32 i , n ;
2016-04-15 12:18:06 -05:00
WCHAR * label ;
HRESULT hr ;
2016-04-17 00:34:05 -05:00
selected = cbGetCurSel ( f - > familyCombobox , & pos ) ;
if ( ! selected ) // on deselect, do nothing
return ;
f - > curFamily = pos ;
2016-04-15 12:18:06 -05:00
2016-04-17 00:34:05 -05:00
family = ( IDWriteFontFamily * ) cbGetItemData ( f - > familyCombobox , ( WPARAM ) ( f - > curFamily ) ) ;
2016-04-15 12:18:06 -05:00
2016-04-16 21:46:39 -05:00
// TODO test mutliple streteches; all the fonts I have have only one stretch value?
2016-04-17 00:34:05 -05:00
wipeStylesBox ( f ) ;
2016-04-16 21:46:39 -05:00
n = family - > GetFontCount ( ) ;
for ( i = 0 ; i < n ; i + + ) {
2016-04-17 00:34:05 -05:00
hr = family - > GetFont ( i , & font ) ;
2016-04-15 12:18:06 -05:00
if ( hr ! = S_OK )
logHRESULT ( " error getting font for filling styles box in familyChanged() " , hr ) ;
2016-04-17 00:34:05 -05:00
label = fontStyleName ( f , font ) ;
2016-04-15 12:18:06 -05:00
pos = cbAddString ( f - > styleCombobox , label ) ;
uiFree ( label ) ;
2016-04-17 00:34:05 -05:00
cbSetItemData ( f - > styleCombobox , ( WPARAM ) pos , ( LPARAM ) font ) ;
2016-04-15 12:18:06 -05:00
}
2016-04-16 16:58:45 -05:00
// 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*/ ) ;
2016-04-15 12:18:06 -05:00
}
2016-04-14 20:35:50 -05:00
static struct fontDialog * beginFontDialog ( HWND hwnd , LPARAM lParam )
{
struct fontDialog * f ;
2016-04-17 00:34:05 -05:00
UINT32 i , nFamilies ;
IDWriteFontFamily * family ;
2016-04-14 21:25:32 -05:00
WCHAR * wname ;
2016-04-17 00:34:05 -05:00
LRESULT pos , ten ;
2016-04-16 16:58:45 -05:00
HWND samplePlacement ;
2016-04-14 21:25:32 -05:00
HRESULT hr ;
2016-04-14 20:35:50 -05:00
f = uiNew ( struct fontDialog ) ;
f - > hwnd = hwnd ;
f - > familyCombobox = GetDlgItem ( f - > hwnd , rcFontFamilyCombobox ) ;
if ( f - > familyCombobox = = NULL )
logLastError ( " error getting font family combobox handle in beginFontDialog() " ) ;
f - > styleCombobox = GetDlgItem ( f - > hwnd , rcFontStyleCombobox ) ;
if ( f - > styleCombobox = = NULL )
logLastError ( " error getting font style combobox handle in beginFontDialog() " ) ;
f - > sizeCombobox = GetDlgItem ( f - > hwnd , rcFontSizeCombobox ) ;
if ( f - > sizeCombobox = = NULL )
logLastError ( " error getting font size combobox handle in beginFontDialog() " ) ;
2016-04-14 21:25:32 -05:00
f - > fc = loadFontCollection ( ) ;
2016-04-17 00:34:05 -05:00
nFamilies = f - > fc - > fonts - > GetFontFamilyCount ( ) ;
for ( i = 0 ; i < nFamilies ; i + + ) {
hr = f - > fc - > fonts - > GetFontFamily ( i , & family ) ;
2016-04-14 21:25:32 -05:00
if ( hr ! = S_OK )
logHRESULT ( " error getting font family in beginFontDialog() " , hr ) ;
2016-04-17 00:34:05 -05:00
wname = fontCollectionFamilyName ( f - > fc , family ) ;
pos = cbAddString ( f - > familyCombobox , wname ) ;
2016-04-14 21:25:32 -05:00
uiFree ( wname ) ;
2016-04-17 00:34:05 -05:00
cbSetItemData ( f - > familyCombobox , ( WPARAM ) pos , ( LPARAM ) family ) ;
2016-04-14 21:25:32 -05:00
}
// TODO all comboboxes should select on type; these already scroll on type but not select
// TODO behavior for the real thing:
// - if prior size is in list, select and scroll to it
// - if not, select nothing and don't scroll list at all (keep at top)
// we do 8 and 9 later
ten = cbAddString ( f - > sizeCombobox , L " 10 " ) ;
cbAddString ( f - > sizeCombobox , L " 11 " ) ;
cbAddString ( f - > sizeCombobox , L " 12 " ) ;
cbAddString ( f - > sizeCombobox , L " 14 " ) ;
cbAddString ( f - > sizeCombobox , L " 16 " ) ;
cbAddString ( f - > sizeCombobox , L " 18 " ) ;
cbAddString ( f - > sizeCombobox , L " 20 " ) ;
cbAddString ( f - > sizeCombobox , L " 22 " ) ;
cbAddString ( f - > sizeCombobox , L " 24 " ) ;
cbAddString ( f - > sizeCombobox , L " 26 " ) ;
cbAddString ( f - > sizeCombobox , L " 28 " ) ;
cbAddString ( f - > sizeCombobox , L " 36 " ) ;
cbAddString ( f - > sizeCombobox , L " 48 " ) ;
cbAddString ( f - > sizeCombobox , L " 72 " ) ;
if ( SendMessageW ( f - > sizeCombobox , CB_SETCURSEL , ( WPARAM ) ten , 0 ) ! = ten )
logLastError ( " error selecting 10 in the size combobox in beginFontDialog() " ) ;
// if we just use CB_ADDSTRING 8 and 9 will appear at the bottom of the list due to lexicographical sorting
// if we use CB_INSERTSTRING instead it won't
cbInsertStringAtTop ( f - > sizeCombobox , L " 9 " ) ;
cbInsertStringAtTop ( f - > sizeCombobox , L " 8 " ) ;
// 10 moved because of the above; figure out where it is now
// we selected it earlier; getting the selection is easiest
ten = SendMessageW ( f - > sizeCombobox , CB_GETCURSEL , 0 , 0 ) ;
// and finally put 10 at the top to imitate ChooseFont()
if ( SendMessageW ( f - > sizeCombobox , CB_SETTOPINDEX , ( WPARAM ) ten , 0 ) ! = 0 )
logLastError ( " error making 10 visible in the size combobox in beginFontDialog() " ) ;
2016-04-14 21:40:01 -05:00
// note: we can't add ES_NUMBER to the combobox entry (it seems to disable the entry instead?!), so we must do validation when the box is dmissed; TODO
2016-04-14 21:25:32 -05:00
2016-04-15 12:18:06 -05:00
// TODO actually select Arial
2016-04-17 00:34:05 -05:00
cbSetCurSel ( f - > familyCombobox , 0 ) ;
2016-04-15 12:18:06 -05:00
familyChanged ( f ) ;
2016-04-16 16:58:45 -05:00
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() " ) ;
2016-04-14 20:35:50 -05:00
return f ;
}
static void endFontDialog ( struct fontDialog * f , INT_PTR code )
{
2016-04-16 16:58:45 -05:00
f - > gdiInterop - > Release ( ) ;
2016-04-15 12:18:06 -05:00
wipeStylesBox ( f ) ;
2016-04-17 00:34:05 -05:00
cbWipeAndReleaseData ( f - > familyCombobox ) ;
2016-04-14 21:25:32 -05:00
fontCollectionFree ( f - > fc ) ;
2016-04-14 20:35:50 -05:00
if ( EndDialog ( f - > hwnd , code ) = = 0 )
logLastError ( " error ending font dialog in endFontDialog() " ) ;
uiFree ( f ) ;
}
static INT_PTR tryFinishDialog ( struct fontDialog * f , WPARAM wParam )
{
// cancelling
if ( LOWORD ( wParam ) ! = IDOK ) {
endFontDialog ( f , 1 ) ;
return TRUE ;
}
// TODO
endFontDialog ( f , 2 ) ;
return TRUE ;
}
2016-04-16 16:58:45 -05:00
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 ;
2016-04-16 21:15:19 -05:00
RECT dirtyRect ;
IDWriteRenderingParams * rp ;
HRESULT hr ;
2016-04-16 16:58:45 -05:00
2016-04-16 21:15:19 -05:00
// TODO I cannot believe this is required; we really do need to switch to Direct2D
hr = dwfactory - > CreateRenderingParams ( & rp ) ;
if ( hr ! = S_OK )
return hr ;
hr = target - > DrawGlyphRun (
2016-04-16 16:58:45 -05:00
baselineOriginX ,
baselineOriginY ,
measuringMode ,
glyphRun ,
2016-04-16 21:15:19 -05:00
rp ,
2016-04-16 16:58:45 -05:00
RGB ( 0 , 0 , 0 ) ,
2016-04-16 21:15:19 -05:00
& dirtyRect ) ;
rp - > Release ( ) ;
if ( hr ! = S_OK )
return hr ;
if ( SetBoundsRect ( target - > GetMemoryDC ( ) , & dirtyRect , DCB_ACCUMULATE ) = = 0 )
// TODO
return E_FAIL ;
return S_OK ;
2016-04-16 16:58:45 -05:00
}
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 ;
}
2016-04-16 18:07:17 -05:00
// TODO rename this function
2016-04-16 16:58:45 -05:00
// TODO consider using Direct2D instead
static void doPaint ( struct fontDialog * f )
{
PAINTSTRUCT ps ;
HDC dc ;
IDWriteBitmapRenderTarget * target ;
gdiRenderer * renderer ;
2016-04-16 18:07:17 -05:00
LRESULT i ;
IDWriteFont * font ;
IDWriteLocalizedStrings * sampleStrings ;
2016-04-16 18:25:21 -05:00
BOOL exists ;
2016-04-16 18:07:17 -05:00
WCHAR * sample ;
2016-04-16 21:15:19 -05:00
WCHAR * family ;
WCHAR * wsize ;
double size ;
2016-04-16 18:07:17 -05:00
IDWriteTextFormat * format ;
IDWriteTextLayout * layout ;
2016-04-16 16:58:45 -05:00
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 ) ;
2016-04-16 21:15:19 -05:00
// TODO why is this needed?
// TODO error check
{
RECT rdraw ;
rdraw . left = 0 ;
rdraw . top = 0 ;
rdraw . right = f - > sampleRect . right - f - > sampleRect . left ;
rdraw . bottom = f - > sampleRect . bottom - f - > sampleRect . top ;
FillRect ( target - > GetMemoryDC ( ) , & rdraw , GetSysColorBrush ( COLOR_BTNFACE ) ) ;
}
2016-04-16 16:58:45 -05:00
renderer = new gdiRenderer ;
renderer - > refcount = 1 ;
2016-04-16 21:15:19 -05:00
i = SendMessageW ( f - > styleCombobox , CB_GETCURSEL , 0 , 0 ) ;
2016-04-16 18:07:17 -05:00
if ( i = = ( LRESULT ) CB_ERR )
2016-04-16 21:15:19 -05:00
{ EndPaint ( f - > hwnd , & ps ) ; return ; } // TODO something more appropriate
2016-04-16 18:07:17 -05:00
font = ( IDWriteFont * ) SendMessageW ( f - > styleCombobox , CB_GETITEMDATA , ( WPARAM ) i , 0 ) ;
if ( font = = ( IDWriteFont * ) CB_ERR )
logLastError ( " error getting font to draw font dialog sample in doPaint() " ) ;
// TOOD allow for a fallback
2016-04-16 18:25:21 -05:00
hr = font - > GetInformationalStrings ( DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT , & sampleStrings , & exists ) ;
2016-04-16 18:07:17 -05:00
if ( hr ! = S_OK )
2016-04-16 21:15:19 -05:00
exists = FALSE ;
if ( exists ) {
sample = fontCollectionCorrectString ( f - > fc , sampleStrings ) ;
sampleStrings - > Release ( ) ;
} else
sample = L " TODO get this from GTK+ instead of AaBbYyZz " ;
// TODO get this from the currently selected item
family = windowText ( f - > familyCombobox ) ;
// TODO but NOT this
wsize = windowText ( f - > sizeCombobox ) ;
// TODO error check?
size = _wtof ( wsize ) ;
uiFree ( wsize ) ;
hr = dwfactory - > CreateTextFormat ( family ,
NULL ,
font - > GetWeight ( ) ,
font - > GetStyle ( ) ,
font - > GetStretch ( ) ,
// typographic points are 1/72 inch; this parameter is 1/96 inch
// fortunately Microsoft does this too, in https://msdn.microsoft.com/en-us/library/windows/desktop/dd371554%28v=vs.85%29.aspx
size * ( 96.0 / 72.0 ) ,
// see http://stackoverflow.com/questions/28397971/idwritefactorycreatetextformat-failing and https://msdn.microsoft.com/en-us/library/windows/desktop/dd368203.aspx
// TODO use the current locale again?
L " " ,
& format ) ;
if ( hr ! = S_OK )
logHRESULT ( " error creating IDWriteTextFormat for font dialog sample in doPaint() " , hr ) ;
uiFree ( family ) ;
hr = dwfactory - > CreateTextLayout ( sample , wcslen ( sample ) ,
format ,
// FLOAT is float, not double, so this should work... TODO
// TODO we don't want wrapping here
FLT_MAX , FLT_MAX ,
& layout ) ;
if ( hr ! = S_OK )
logHRESULT ( " error creating IDWriteTextLayout for font dialog sample in doPaint() " , hr ) ;
2016-04-16 18:07:17 -05:00
2016-04-16 21:15:19 -05:00
hr = layout - > Draw ( target ,
renderer ,
0 , 0 ) ;
if ( hr ! = S_OK )
logHRESULT ( " error drawing font dialog sample text in doPaint() " , hr ) ;
2016-04-16 16:58:45 -05:00
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() " ) ;
2016-04-16 21:15:19 -05:00
layout - > Release ( ) ;
format - > Release ( ) ;
if ( exists )
uiFree ( sample ) ;
2016-04-16 16:58:45 -05:00
renderer - > Release ( ) ;
target - > Release ( ) ;
EndPaint ( f - > hwnd , & ps ) ;
}
2016-04-14 20:35:50 -05:00
static INT_PTR CALLBACK fontDialogDlgProc ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
struct fontDialog * f ;
f = ( struct fontDialog * ) GetWindowLongPtrW ( hwnd , DWLP_USER ) ;
if ( f = = NULL ) {
if ( uMsg = = WM_INITDIALOG ) {
f = beginFontDialog ( hwnd , lParam ) ;
SetWindowLongPtrW ( hwnd , DWLP_USER , ( LONG_PTR ) f ) ;
return TRUE ;
}
return FALSE ;
}
switch ( uMsg ) {
case WM_COMMAND :
2016-04-16 16:58:45 -05:00
SetWindowLongPtrW ( f - > hwnd , DWLP_MSGRESULT , 0 ) ; // just in case
2016-04-15 12:18:06 -05:00
switch ( LOWORD ( wParam ) ) {
case IDOK :
case IDCANCEL :
if ( HIWORD ( wParam ) ! = BN_CLICKED )
return FALSE ;
return tryFinishDialog ( f , wParam ) ;
case rcFontFamilyCombobox :
if ( HIWORD ( wParam ) ! = CBN_SELCHANGE )
return FALSE ;
familyChanged ( f ) ;
return TRUE ;
2016-04-16 21:15:19 -05:00
// TODO
case rcFontStyleCombobox :
case rcFontSizeCombobox :
if ( HIWORD ( wParam ) ! = CBN_SELCHANGE )
return FALSE ;
// TODO error check; refine
InvalidateRect ( f - > hwnd , NULL , TRUE ) ;
return TRUE ;
2016-04-15 12:18:06 -05:00
}
return FALSE ;
2016-04-16 16:58:45 -05:00
case WM_PAINT :
doPaint ( f ) ;
SetWindowLongPtrW ( f - > hwnd , DWLP_MSGRESULT , 0 ) ;
return TRUE ;
2016-04-14 20:35:50 -05:00
}
return FALSE ;
}
void showFontDialog ( HWND parent )
{
switch ( DialogBoxParamW ( hInstance , MAKEINTRESOURCE ( rcFontDialog ) , parent , fontDialogDlgProc , ( LPARAM ) NULL ) ) {
case 1 :
// TODO cancel
break ;
case 2 :
// TODO OK
break ;
default :
logLastError ( " error running font dialog in showFontDialog() " ) ;
}
}