dwrite: Return advances using freetype cache system.
[wine.git] / dlls / dwrite / tests / font.c
blob7617dbb1beccb83fbc77b8fbeff56affebc268b9
1 /*
2 * Font related tests
4 * Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
5 * Copyright 2014 Aric Stewart for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <math.h>
23 #include <limits.h>
25 #define COBJMACROS
27 #include "windows.h"
28 #include "winternl.h"
29 #include "dwrite_2.h"
30 #include "initguid.h"
31 #include "d2d1.h"
33 #include "wine/test.h"
35 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
36 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
37 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
39 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
40 #define MS_VDMX_TAG MS_MAKE_TAG('V','D','M','X')
41 #define MS_GASP_TAG MS_MAKE_TAG('g','a','s','p')
42 #define MS_CPAL_TAG MS_MAKE_TAG('C','P','A','L')
44 #define EXPECT_HR(hr,hr_exp) \
45 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
47 #define DEFINE_EXPECT(func) \
48 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
50 #define SET_EXPECT(func) \
51 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
53 #define CHECK_EXPECT2(func) \
54 do { \
55 ok(expect_ ##func, "unexpected call " #func "\n"); \
56 called_ ## func = TRUE; \
57 }while(0)
59 #define CHECK_EXPECT(func) \
60 do { \
61 CHECK_EXPECT2(func); \
62 expect_ ## func = FALSE; \
63 }while(0)
65 #define CHECK_CALLED(func) \
66 do { \
67 ok(called_ ## func, "expected " #func "\n"); \
68 expect_ ## func = called_ ## func = FALSE; \
69 }while(0)
71 #define CLEAR_CALLED(func) \
72 expect_ ## func = called_ ## func = FALSE
74 DEFINE_EXPECT(setfillmode);
76 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
77 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
79 ULONG rc;
80 IUnknown_AddRef(obj);
81 rc = IUnknown_Release(obj);
82 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
85 static inline void *heap_alloc(size_t len)
87 return HeapAlloc(GetProcessHeap(), 0, len);
90 static inline BOOL heap_free(void *mem)
92 return HeapFree(GetProcessHeap(), 0, mem);
95 static const WCHAR test_fontfile[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
96 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
97 static const WCHAR arialW[] = {'A','r','i','a','l',0};
98 static const WCHAR tahomaUppercaseW[] = {'T','A','H','O','M','A',0};
99 static const WCHAR tahomaStrangecaseW[] = {'t','A','h','O','m','A',0};
100 static const WCHAR blahW[] = {'B','l','a','h','!',0};
102 static IDWriteFactory *create_factory(void)
104 IDWriteFactory *factory;
105 HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
106 ok(hr == S_OK, "got 0x%08x\n", hr);
107 return factory;
110 static IDWriteFontFace *create_fontface(IDWriteFactory *factory)
112 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
113 IDWriteGdiInterop *interop;
114 IDWriteFontFace *fontface;
115 IDWriteFont *font;
116 LOGFONTW logfont;
117 HRESULT hr;
119 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
120 ok(hr == S_OK, "got 0x%08x\n", hr);
122 memset(&logfont, 0, sizeof(logfont));
123 logfont.lfHeight = 12;
124 logfont.lfWidth = 12;
125 logfont.lfWeight = FW_NORMAL;
126 logfont.lfItalic = 1;
127 lstrcpyW(logfont.lfFaceName, tahomaW);
129 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
130 ok(hr == S_OK, "got 0x%08x\n", hr);
132 hr = IDWriteFont_CreateFontFace(font, &fontface);
133 ok(hr == S_OK, "got 0x%08x\n", hr);
135 IDWriteFont_Release(font);
136 IDWriteGdiInterop_Release(interop);
138 return fontface;
141 static WCHAR *create_testfontfile(const WCHAR *filename)
143 static WCHAR pathW[MAX_PATH];
144 DWORD written;
145 HANDLE file;
146 HRSRC res;
147 void *ptr;
149 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
150 lstrcatW(pathW, filename);
152 file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
153 ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW),
154 GetLastError());
156 res = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
157 ok( res != 0, "couldn't find resource\n" );
158 ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
159 WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
160 ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
161 CloseHandle( file );
163 return pathW;
166 #define DELETE_FONTFILE(filename) _delete_testfontfile(filename, __LINE__)
167 static void _delete_testfontfile(const WCHAR *filename, int line)
169 BOOL ret = DeleteFileW(filename);
170 ok_(__FILE__,line)(ret, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename), GetLastError());
173 struct test_fontenumerator
175 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface;
176 LONG ref;
178 DWORD index;
179 IDWriteFontFile *font_file;
182 static inline struct test_fontenumerator *impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator* iface)
184 return CONTAINING_RECORD(iface, struct test_fontenumerator, IDWriteFontFileEnumerator_iface);
187 static HRESULT WINAPI singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
189 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileEnumerator))
191 *obj = iface;
192 IDWriteFontFileEnumerator_AddRef(iface);
193 return S_OK;
195 return E_NOINTERFACE;
198 static ULONG WINAPI singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
200 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
201 return InterlockedIncrement(&This->ref);
204 static ULONG WINAPI singlefontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
206 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
207 ULONG ref = InterlockedDecrement(&This->ref);
208 if (!ref) {
209 IDWriteFontFile_Release(This->font_file);
210 heap_free(This);
212 return ref;
215 static HRESULT WINAPI singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **font_file)
217 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
218 IDWriteFontFile_AddRef(This->font_file);
219 *font_file = This->font_file;
220 return S_OK;
223 static HRESULT WINAPI singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
225 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
227 if (This->index > 1) {
228 *current = FALSE;
229 return S_OK;
232 This->index++;
233 *current = TRUE;
234 return S_OK;
237 static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl =
239 singlefontfileenumerator_QueryInterface,
240 singlefontfileenumerator_AddRef,
241 singlefontfileenumerator_Release,
242 singlefontfileenumerator_MoveNext,
243 singlefontfileenumerator_GetCurrentFontFile
246 static HRESULT create_enumerator(IDWriteFontFile *font_file, IDWriteFontFileEnumerator **ret)
248 struct test_fontenumerator *enumerator;
250 enumerator = heap_alloc(sizeof(struct test_fontenumerator));
251 if (!enumerator)
252 return E_OUTOFMEMORY;
254 enumerator->IDWriteFontFileEnumerator_iface.lpVtbl = &singlefontfileenumeratorvtbl;
255 enumerator->ref = 1;
256 enumerator->index = 0;
257 enumerator->font_file = font_file;
258 IDWriteFontFile_AddRef(font_file);
260 *ret = &enumerator->IDWriteFontFileEnumerator_iface;
261 return S_OK;
264 struct test_fontcollectionloader
266 IDWriteFontCollectionLoader IDWriteFontFileCollectionLoader_iface;
267 IDWriteFontFileLoader *loader;
270 static inline struct test_fontcollectionloader *impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader* iface)
272 return CONTAINING_RECORD(iface, struct test_fontcollectionloader, IDWriteFontFileCollectionLoader_iface);
275 static HRESULT WINAPI resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
277 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontCollectionLoader))
279 *obj = iface;
280 IDWriteFontCollectionLoader_AddRef(iface);
281 return S_OK;
283 return E_NOINTERFACE;
286 static ULONG WINAPI resourcecollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
288 return 2;
291 static ULONG WINAPI resourcecollectionloader_Release(IDWriteFontCollectionLoader *iface)
293 return 1;
296 static HRESULT WINAPI resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory,
297 const void * collectionKey, UINT32 collectionKeySize, IDWriteFontFileEnumerator ** fontFileEnumerator)
299 struct test_fontcollectionloader *This = impl_from_IDWriteFontFileCollectionLoader(iface);
300 IDWriteFontFile *font_file;
301 HRESULT hr;
303 IDWriteFactory_CreateCustomFontFileReference(factory, collectionKey, collectionKeySize, This->loader, &font_file);
305 hr = create_enumerator(font_file, fontFileEnumerator);
306 ok(hr == S_OK, "got 0x%08x\n", hr);
308 IDWriteFontFile_Release(font_file);
309 return hr;
312 static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl = {
313 resourcecollectionloader_QueryInterface,
314 resourcecollectionloader_AddRef,
315 resourcecollectionloader_Release,
316 resourcecollectionloader_CreateEnumeratorFromKey
319 /* Here is a functional custom font set of interfaces */
320 struct test_fontdatastream
322 IDWriteFontFileStream IDWriteFontFileStream_iface;
323 LONG ref;
325 LPVOID data;
326 DWORD size;
329 static inline struct test_fontdatastream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream* iface)
331 return CONTAINING_RECORD(iface, struct test_fontdatastream, IDWriteFontFileStream_iface);
334 static HRESULT WINAPI fontdatastream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
336 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
338 *obj = iface;
339 IDWriteFontFileStream_AddRef(iface);
340 return S_OK;
342 *obj = NULL;
343 return E_NOINTERFACE;
346 static ULONG WINAPI fontdatastream_AddRef(IDWriteFontFileStream *iface)
348 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
349 ULONG ref = InterlockedIncrement(&This->ref);
350 return ref;
353 static ULONG WINAPI fontdatastream_Release(IDWriteFontFileStream *iface)
355 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
356 ULONG ref = InterlockedDecrement(&This->ref);
357 if (ref == 0)
358 HeapFree(GetProcessHeap(), 0, This);
359 return ref;
362 static HRESULT WINAPI fontdatastream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
364 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
365 *fragment_context = NULL;
366 if (offset+fragment_size > This->size)
368 *fragment_start = NULL;
369 return E_FAIL;
371 else
373 *fragment_start = (BYTE*)This->data + offset;
374 return S_OK;
378 static void WINAPI fontdatastream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
380 /* Do Nothing */
383 static HRESULT WINAPI fontdatastream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
385 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
386 *size = This->size;
387 return S_OK;
390 static HRESULT WINAPI fontdatastream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
392 return E_NOTIMPL;
395 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl =
397 fontdatastream_QueryInterface,
398 fontdatastream_AddRef,
399 fontdatastream_Release,
400 fontdatastream_ReadFileFragment,
401 fontdatastream_ReleaseFileFragment,
402 fontdatastream_GetFileSize,
403 fontdatastream_GetLastWriteTime
406 static HRESULT create_fontdatastream(LPVOID data, UINT size, IDWriteFontFileStream** iface)
408 struct test_fontdatastream *This = HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream));
409 if (!This)
410 return E_OUTOFMEMORY;
412 This->data = data;
413 This->size = size;
414 This->ref = 1;
415 This->IDWriteFontFileStream_iface.lpVtbl = &fontdatastreamvtbl;
417 *iface = &This->IDWriteFontFileStream_iface;
418 return S_OK;
421 static HRESULT WINAPI resourcefontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
423 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
425 *obj = iface;
426 return S_OK;
428 *obj = NULL;
429 return E_NOINTERFACE;
432 static ULONG WINAPI resourcefontfileloader_AddRef(IDWriteFontFileLoader *iface)
434 return 2;
437 static ULONG WINAPI resourcefontfileloader_Release(IDWriteFontFileLoader *iface)
439 return 1;
442 static HRESULT WINAPI resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
444 LPVOID data;
445 DWORD size;
446 HGLOBAL mem;
448 mem = LoadResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
449 ok(mem != NULL, "Failed to lock font resource\n");
450 if (mem)
452 size = SizeofResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
453 data = LockResource(mem);
454 return create_fontdatastream(data, size, fontFileStream);
456 return E_FAIL;
459 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl = {
460 resourcefontfileloader_QueryInterface,
461 resourcefontfileloader_AddRef,
462 resourcefontfileloader_Release,
463 resourcefontfileloader_CreateStreamFromKey
466 static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
468 static D2D1_POINT_2F g_startpoints[2];
469 static int g_startpoint_count;
471 static HRESULT WINAPI test_geometrysink_QueryInterface(ID2D1SimplifiedGeometrySink *iface, REFIID riid, void **ret)
473 if (IsEqualIID(riid, &IID_ID2D1SimplifiedGeometrySink) ||
474 IsEqualIID(riid, &IID_IUnknown))
476 *ret = iface;
477 ID2D1SimplifiedGeometrySink_AddRef(iface);
478 return S_OK;
481 *ret = NULL;
482 return E_NOINTERFACE;
485 static ULONG WINAPI test_geometrysink_AddRef(ID2D1SimplifiedGeometrySink *iface)
487 return 2;
490 static ULONG WINAPI test_geometrysink_Release(ID2D1SimplifiedGeometrySink *iface)
492 return 1;
495 static void WINAPI test_geometrysink_SetFillMode(ID2D1SimplifiedGeometrySink *iface, D2D1_FILL_MODE mode)
497 CHECK_EXPECT(setfillmode);
498 ok(mode == D2D1_FILL_MODE_WINDING, "fill mode %d\n", mode);
501 static void WINAPI test_geometrysink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface, D2D1_PATH_SEGMENT flags)
503 ok(0, "unexpected SetSegmentFlags() - flags %d\n", flags);
506 static void WINAPI test_geometrysink_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
507 D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin)
509 ok(figureBegin == D2D1_FIGURE_BEGIN_FILLED, "begin figure %d\n", figureBegin);
510 if (g_startpoint_count < sizeof(g_startpoints)/sizeof(g_startpoints[0]))
511 g_startpoints[g_startpoint_count] = startPoint;
512 g_startpoint_count++;
515 static void WINAPI test_geometrysink_AddLines(ID2D1SimplifiedGeometrySink *iface,
516 const D2D1_POINT_2F *points, UINT32 count)
520 static void WINAPI test_geometrysink_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
521 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
525 static void WINAPI test_geometrysink_EndFigure(ID2D1SimplifiedGeometrySink *iface, D2D1_FIGURE_END figureEnd)
527 ok(figureEnd == D2D1_FIGURE_END_CLOSED, "end figure %d\n", figureEnd);
530 static HRESULT WINAPI test_geometrysink_Close(ID2D1SimplifiedGeometrySink *iface)
532 ok(0, "unexpected Close()\n");
533 return E_NOTIMPL;
536 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink_vtbl = {
537 test_geometrysink_QueryInterface,
538 test_geometrysink_AddRef,
539 test_geometrysink_Release,
540 test_geometrysink_SetFillMode,
541 test_geometrysink_SetSegmentFlags,
542 test_geometrysink_BeginFigure,
543 test_geometrysink_AddLines,
544 test_geometrysink_AddBeziers,
545 test_geometrysink_EndFigure,
546 test_geometrysink_Close
549 static void WINAPI test_geometrysink2_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
550 D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin)
552 ok(0, "unexpected call\n");
555 static void WINAPI test_geometrysink2_AddLines(ID2D1SimplifiedGeometrySink *iface,
556 const D2D1_POINT_2F *points, UINT32 count)
558 ok(0, "unexpected call\n");
561 static void WINAPI test_geometrysink2_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
562 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
564 ok(0, "unexpected call\n");
567 static void WINAPI test_geometrysink2_EndFigure(ID2D1SimplifiedGeometrySink *iface, D2D1_FIGURE_END figureEnd)
569 ok(0, "unexpected call\n");
572 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink2_vtbl = {
573 test_geometrysink_QueryInterface,
574 test_geometrysink_AddRef,
575 test_geometrysink_Release,
576 test_geometrysink_SetFillMode,
577 test_geometrysink_SetSegmentFlags,
578 test_geometrysink2_BeginFigure,
579 test_geometrysink2_AddLines,
580 test_geometrysink2_AddBeziers,
581 test_geometrysink2_EndFigure,
582 test_geometrysink_Close
585 static ID2D1SimplifiedGeometrySink test_geomsink = { &test_geometrysink_vtbl };
586 static ID2D1SimplifiedGeometrySink test_geomsink2 = { &test_geometrysink2_vtbl };
588 static void test_CreateFontFromLOGFONT(void)
590 static const WCHAR tahomaspW[] = {'T','a','h','o','m','a',' ',0};
591 IDWriteGdiInterop *interop;
592 DWRITE_FONT_WEIGHT weight;
593 DWRITE_FONT_STYLE style;
594 IDWriteFont *font;
595 LOGFONTW logfont;
596 LONG weights[][2] = {
597 {FW_NORMAL, DWRITE_FONT_WEIGHT_NORMAL},
598 {FW_BOLD, DWRITE_FONT_WEIGHT_BOLD},
599 { 0, DWRITE_FONT_WEIGHT_NORMAL},
600 { 50, DWRITE_FONT_WEIGHT_NORMAL},
601 {150, DWRITE_FONT_WEIGHT_NORMAL},
602 {250, DWRITE_FONT_WEIGHT_NORMAL},
603 {350, DWRITE_FONT_WEIGHT_NORMAL},
604 {450, DWRITE_FONT_WEIGHT_NORMAL},
605 {650, DWRITE_FONT_WEIGHT_BOLD},
606 {750, DWRITE_FONT_WEIGHT_BOLD},
607 {850, DWRITE_FONT_WEIGHT_BOLD},
608 {950, DWRITE_FONT_WEIGHT_BOLD},
609 {960, DWRITE_FONT_WEIGHT_BOLD},
611 OUTLINETEXTMETRICW otm;
612 IDWriteFactory *factory;
613 HRESULT hr;
614 BOOL ret;
615 HDC hdc;
616 HFONT hfont;
617 BOOL exists;
618 int i;
619 UINT r;
621 factory = create_factory();
623 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
624 EXPECT_HR(hr, S_OK);
626 if (0)
627 /* null out parameter crashes this call */
628 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, NULL);
630 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, &font);
631 EXPECT_HR(hr, E_INVALIDARG);
633 memset(&logfont, 0, sizeof(logfont));
634 logfont.lfHeight = 12;
635 logfont.lfWidth = 12;
636 logfont.lfWeight = FW_NORMAL;
637 logfont.lfItalic = 1;
638 lstrcpyW(logfont.lfFaceName, tahomaW);
640 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
641 EXPECT_HR(hr, S_OK);
643 hfont = CreateFontIndirectW(&logfont);
644 hdc = CreateCompatibleDC(0);
645 SelectObject(hdc, hfont);
647 otm.otmSize = sizeof(otm);
648 r = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
649 ok(r, "got %d\n", r);
650 DeleteDC(hdc);
651 DeleteObject(hfont);
653 exists = TRUE;
654 hr = IDWriteFont_HasCharacter(font, 0xd800, &exists);
655 ok(hr == S_OK, "got 0x%08x\n", hr);
656 ok(exists == FALSE, "got %d\n", exists);
658 exists = FALSE;
659 hr = IDWriteFont_HasCharacter(font, 0x20, &exists);
660 ok(hr == S_OK, "got 0x%08x\n", hr);
661 ok(exists == TRUE, "got %d\n", exists);
663 /* now check properties */
664 weight = IDWriteFont_GetWeight(font);
665 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
667 style = IDWriteFont_GetStyle(font);
668 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
669 todo_wine
670 ok(otm.otmfsSelection == 1, "got 0x%08x\n", otm.otmfsSelection);
672 ret = IDWriteFont_IsSymbolFont(font);
673 ok(!ret, "got %d\n", ret);
675 IDWriteFont_Release(font);
677 /* weight values */
678 for (i = 0; i < sizeof(weights)/(2*sizeof(LONG)); i++)
680 memset(&logfont, 0, sizeof(logfont));
681 logfont.lfHeight = 12;
682 logfont.lfWidth = 12;
683 logfont.lfWeight = weights[i][0];
684 lstrcpyW(logfont.lfFaceName, tahomaW);
686 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
687 EXPECT_HR(hr, S_OK);
689 weight = IDWriteFont_GetWeight(font);
690 ok(weight == weights[i][1],
691 "%d: got %d, expected %d\n", i, weight, weights[i][1]);
693 IDWriteFont_Release(font);
696 /* weight not from enum */
697 memset(&logfont, 0, sizeof(logfont));
698 logfont.lfHeight = 12;
699 logfont.lfWidth = 12;
700 logfont.lfWeight = 550;
701 lstrcpyW(logfont.lfFaceName, tahomaW);
703 font = NULL;
704 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
705 ok(hr == S_OK, "got 0x%08x\n", hr);
707 weight = IDWriteFont_GetWeight(font);
708 ok(weight == DWRITE_FONT_WEIGHT_NORMAL || weight == DWRITE_FONT_WEIGHT_BOLD,
709 "got %d\n", weight);
710 IDWriteFont_Release(font);
712 /* empty or nonexistent face name */
713 memset(&logfont, 0, sizeof(logfont));
714 logfont.lfHeight = 12;
715 logfont.lfWidth = 12;
716 logfont.lfWeight = FW_NORMAL;
717 lstrcpyW(logfont.lfFaceName, blahW);
719 font = (void*)0xdeadbeef;
720 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
721 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
722 ok(font == NULL, "got %p\n", font);
724 /* Try with name 'Tahoma ' */
725 memset(&logfont, 0, sizeof(logfont));
726 logfont.lfHeight = 12;
727 logfont.lfWidth = 12;
728 logfont.lfWeight = FW_NORMAL;
729 lstrcpyW(logfont.lfFaceName, tahomaspW);
731 font = (void*)0xdeadbeef;
732 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
733 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
734 ok(font == NULL, "got %p\n", font);
736 /* empty string as a facename */
737 memset(&logfont, 0, sizeof(logfont));
738 logfont.lfHeight = 12;
739 logfont.lfWidth = 12;
740 logfont.lfWeight = FW_NORMAL;
742 font = (void*)0xdeadbeef;
743 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
744 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
745 ok(font == NULL, "got %p\n", font);
747 IDWriteGdiInterop_Release(interop);
748 IDWriteFactory_Release(factory);
751 static void test_CreateBitmapRenderTarget(void)
753 IDWriteBitmapRenderTarget *target, *target2;
754 IDWriteBitmapRenderTarget1 *target1;
755 IDWriteGdiInterop *interop;
756 IDWriteFactory *factory;
757 HBITMAP hbm, hbm2;
758 DWRITE_MATRIX m;
759 DIBSECTION ds;
760 XFORM xform;
761 COLORREF c;
762 HRESULT hr;
763 FLOAT pdip;
764 SIZE size;
765 HDC hdc;
766 int ret;
768 factory = create_factory();
770 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
771 EXPECT_HR(hr, S_OK);
773 target = NULL;
774 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target);
775 EXPECT_HR(hr, S_OK);
777 if (0) /* crashes on native */
778 hr = IDWriteBitmapRenderTarget_GetSize(target, NULL);
780 size.cx = size.cy = -1;
781 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
782 EXPECT_HR(hr, S_OK);
783 ok(size.cx == 0, "got %d\n", size.cx);
784 ok(size.cy == 0, "got %d\n", size.cy);
786 target2 = NULL;
787 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target2);
788 EXPECT_HR(hr, S_OK);
789 ok(target != target2, "got %p, %p\n", target2, target);
790 IDWriteBitmapRenderTarget_Release(target2);
792 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
793 ok(hdc != NULL, "got %p\n", hdc);
795 /* test mode */
796 ret = GetGraphicsMode(hdc);
797 ok(ret == GM_ADVANCED, "got %d\n", ret);
799 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
800 ok(hbm != NULL, "got %p\n", hbm);
802 /* check DIB properties */
803 ret = GetObjectW(hbm, sizeof(ds), &ds);
804 ok(ret == sizeof(BITMAP), "got %d\n", ret);
805 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
806 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
807 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
808 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
809 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
811 IDWriteBitmapRenderTarget_Release(target);
813 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
814 ok(!hbm, "got %p\n", hbm);
816 target = NULL;
817 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 10, 5, &target);
818 EXPECT_HR(hr, S_OK);
820 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
821 ok(hdc != NULL, "got %p\n", hdc);
823 /* test context settings */
824 c = GetTextColor(hdc);
825 ok(c == RGB(0, 0, 0), "got 0x%08x\n", c);
826 ret = GetBkMode(hdc);
827 ok(ret == OPAQUE, "got %d\n", ret);
828 c = GetBkColor(hdc);
829 ok(c == RGB(255, 255, 255), "got 0x%08x\n", c);
831 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
832 ok(hbm != NULL, "got %p\n", hbm);
834 /* check DIB properties */
835 ret = GetObjectW(hbm, sizeof(ds), &ds);
836 ok(ret == sizeof(ds), "got %d\n", ret);
837 ok(ds.dsBm.bmWidth == 10, "got %d\n", ds.dsBm.bmWidth);
838 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
839 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
840 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
841 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
843 size.cx = size.cy = -1;
844 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
845 EXPECT_HR(hr, S_OK);
846 ok(size.cx == 10, "got %d\n", size.cx);
847 ok(size.cy == 5, "got %d\n", size.cy);
849 /* resize to same size */
850 hr = IDWriteBitmapRenderTarget_Resize(target, 10, 5);
851 ok(hr == S_OK, "got 0x%08x\n", hr);
853 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
854 ok(hbm2 == hbm, "got %p, %p\n", hbm2, hbm);
856 /* shrink */
857 hr = IDWriteBitmapRenderTarget_Resize(target, 5, 5);
858 ok(hr == S_OK, "got 0x%08x\n", hr);
860 size.cx = size.cy = -1;
861 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
862 ok(hr == S_OK, "got 0x%08x\n", hr);
863 ok(size.cx == 5, "got %d\n", size.cx);
864 ok(size.cy == 5, "got %d\n", size.cy);
866 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
867 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
869 hr = IDWriteBitmapRenderTarget_Resize(target, 20, 5);
870 ok(hr == S_OK, "got 0x%08x\n", hr);
872 size.cx = size.cy = -1;
873 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
874 ok(hr == S_OK, "got 0x%08x\n", hr);
875 ok(size.cx == 20, "got %d\n", size.cx);
876 ok(size.cy == 5, "got %d\n", size.cy);
878 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
879 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
881 hr = IDWriteBitmapRenderTarget_Resize(target, 1, 5);
882 ok(hr == S_OK, "got 0x%08x\n", hr);
884 size.cx = size.cy = -1;
885 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
886 ok(hr == S_OK, "got 0x%08x\n", hr);
887 ok(size.cx == 1, "got %d\n", size.cx);
888 ok(size.cy == 5, "got %d\n", size.cy);
890 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
891 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
893 ret = GetObjectW(hbm2, sizeof(ds), &ds);
894 ok(ret == sizeof(ds), "got %d\n", ret);
895 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
896 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
897 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
898 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
899 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
901 /* empty rectangle */
902 hr = IDWriteBitmapRenderTarget_Resize(target, 0, 5);
903 ok(hr == S_OK, "got 0x%08x\n", hr);
905 size.cx = size.cy = -1;
906 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
907 ok(hr == S_OK, "got 0x%08x\n", hr);
908 ok(size.cx == 0, "got %d\n", size.cx);
909 ok(size.cy == 5, "got %d\n", size.cy);
911 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
912 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
914 ret = GetObjectW(hbm2, sizeof(ds), &ds);
915 ok(ret == sizeof(BITMAP), "got %d\n", ret);
916 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
917 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
918 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
919 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
920 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
922 /* transform tests, current hdc transform is not immediately affected */
923 if (0) /* crashes on native */
924 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, NULL);
926 memset(&m, 0xcc, sizeof(m));
927 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
928 ok(hr == S_OK, "got 0x%08x\n", hr);
929 ok(m.m11 == 1.0 && m.m22 == 1.0 && m.m12 == 0.0 && m.m21 == 0.0, "got %.1f,%.1f,%.1f,%.1f\n", m.m11, m.m22, m.m12, m.m21);
930 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
931 ret = GetWorldTransform(hdc, &xform);
932 ok(ret, "got %d\n", ret);
933 ok(xform.eM11 == 1.0 && xform.eM22 == 1.0 && xform.eM12 == 0.0 && xform.eM21 == 0.0, "got wrong transform\n");
934 ok(xform.eDx == 0.0 && xform.eDy == 0.0, "got %.1f,%.1f\n", xform.eDx, xform.eDy);
936 memset(&m, 0, sizeof(m));
937 hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, &m);
938 ok(hr == S_OK, "got 0x%08x\n", hr);
940 memset(&m, 0xcc, sizeof(m));
941 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
942 ok(hr == S_OK, "got 0x%08x\n", hr);
943 ok(m.m11 == 0.0 && m.m22 == 0.0 && m.m12 == 0.0 && m.m21 == 0.0, "got %.1f,%.1f,%.1f,%.1f\n", m.m11, m.m22, m.m12, m.m21);
944 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
945 ret = GetWorldTransform(hdc, &xform);
946 ok(ret, "got %d\n", ret);
947 ok(xform.eM11 == 1.0 && xform.eM22 == 1.0 && xform.eM12 == 0.0 && xform.eM21 == 0.0, "got wrong transform\n");
948 ok(xform.eDx == 0.0 && xform.eDy == 0.0, "got %.1f,%.1f\n", xform.eDx, xform.eDy);
950 memset(&m, 0, sizeof(m));
951 m.m11 = 2.0; m.m22 = 1.0;
952 hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, &m);
953 ok(hr == S_OK, "got 0x%08x\n", hr);
954 ret = GetWorldTransform(hdc, &xform);
955 ok(ret, "got %d\n", ret);
956 ok(xform.eM11 == 1.0 && xform.eM22 == 1.0 && xform.eM12 == 0.0 && xform.eM21 == 0.0, "got wrong transform\n");
957 ok(xform.eDx == 0.0 && xform.eDy == 0.0, "got %.1f,%.1f\n", xform.eDx, xform.eDy);
959 hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, NULL);
960 ok(hr == S_OK, "got 0x%08x\n", hr);
962 memset(&m, 0xcc, sizeof(m));
963 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
964 ok(hr == S_OK, "got 0x%08x\n", hr);
965 ok(m.m11 == 1.0 && m.m22 == 1.0 && m.m12 == 0.0 && m.m21 == 0.0, "got %.1f,%.1f,%.1f,%.1f\n", m.m11, m.m22, m.m12, m.m21);
966 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
968 /* pixels per dip */
969 pdip = IDWriteBitmapRenderTarget_GetPixelsPerDip(target);
970 ok(pdip == 1.0, "got %.2f\n", pdip);
972 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, 2.0);
973 ok(hr == S_OK, "got 0x%08x\n", hr);
975 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, -1.0);
976 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
978 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, 0.0);
979 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
981 pdip = IDWriteBitmapRenderTarget_GetPixelsPerDip(target);
982 ok(pdip == 2.0, "got %.2f\n", pdip);
984 hr = IDWriteBitmapRenderTarget_QueryInterface(target, &IID_IDWriteBitmapRenderTarget1, (void**)&target1);
985 if (hr == S_OK) {
986 DWRITE_TEXT_ANTIALIAS_MODE mode;
988 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
989 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, "got %d\n", mode);
991 hr = IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE+1);
992 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
994 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
995 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, "got %d\n", mode);
997 hr = IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
998 ok(hr == S_OK, "got 0x%08x\n", hr);
1000 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
1001 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE, "got %d\n", mode);
1003 IDWriteBitmapRenderTarget1_Release(target1);
1005 else
1006 win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
1008 IDWriteBitmapRenderTarget_Release(target);
1009 IDWriteGdiInterop_Release(interop);
1010 IDWriteFactory_Release(factory);
1013 static void test_GetFontFamily(void)
1015 IDWriteFontCollection *collection, *collection2;
1016 IDWriteFontCollection *syscoll;
1017 IDWriteFontFamily *family, *family2;
1018 IDWriteGdiInterop *interop;
1019 IDWriteFont *font, *font2;
1020 IDWriteFactory *factory;
1021 LOGFONTW logfont;
1022 HRESULT hr;
1024 factory = create_factory();
1026 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1027 EXPECT_HR(hr, S_OK);
1029 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscoll, FALSE);
1030 ok(hr == S_OK, "got 0x%08x\n", hr);
1032 memset(&logfont, 0, sizeof(logfont));
1033 logfont.lfHeight = 12;
1034 logfont.lfWidth = 12;
1035 logfont.lfWeight = FW_NORMAL;
1036 logfont.lfItalic = 1;
1037 lstrcpyW(logfont.lfFaceName, tahomaW);
1039 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1040 ok(hr == S_OK, "got 0x%08x\n", hr);
1042 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
1043 ok(hr == S_OK, "got 0x%08x\n", hr);
1044 ok(font2 != font, "got %p, %p\n", font2, font);
1046 if (0) /* crashes on native */
1047 hr = IDWriteFont_GetFontFamily(font, NULL);
1049 EXPECT_REF(font, 1);
1050 hr = IDWriteFont_GetFontFamily(font, &family);
1051 EXPECT_HR(hr, S_OK);
1052 EXPECT_REF(font, 1);
1053 EXPECT_REF(family, 2);
1055 hr = IDWriteFont_GetFontFamily(font, &family2);
1056 EXPECT_HR(hr, S_OK);
1057 ok(family2 == family, "got %p, previous %p\n", family2, family);
1058 EXPECT_REF(font, 1);
1059 EXPECT_REF(family, 3);
1060 IDWriteFontFamily_Release(family2);
1062 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFamily, (void**)&family2);
1063 EXPECT_HR(hr, E_NOINTERFACE);
1064 ok(family2 == NULL, "got %p\n", family2);
1066 hr = IDWriteFont_GetFontFamily(font2, &family2);
1067 ok(hr == S_OK, "got 0x%08x\n", hr);
1068 ok(family2 != family, "got %p, %p\n", family2, family);
1070 collection = NULL;
1071 hr = IDWriteFontFamily_GetFontCollection(family, &collection);
1072 ok(hr == S_OK, "got 0x%08x\n", hr);
1074 collection2 = NULL;
1075 hr = IDWriteFontFamily_GetFontCollection(family2, &collection2);
1076 ok(hr == S_OK, "got 0x%08x\n", hr);
1077 ok(collection == collection2, "got %p, %p\n", collection, collection2);
1078 ok(collection == syscoll, "got %p, %p\n", collection, syscoll);
1080 IDWriteFontCollection_Release(syscoll);
1081 IDWriteFontCollection_Release(collection2);
1082 IDWriteFontCollection_Release(collection);
1083 IDWriteFontFamily_Release(family2);
1084 IDWriteFontFamily_Release(family);
1085 IDWriteFont_Release(font);
1086 IDWriteFont_Release(font2);
1087 IDWriteGdiInterop_Release(interop);
1088 IDWriteFactory_Release(factory);
1091 static void test_GetFamilyNames(void)
1093 IDWriteFontFamily *family;
1094 IDWriteLocalizedStrings *names, *names2;
1095 IDWriteGdiInterop *interop;
1096 IDWriteFactory *factory;
1097 IDWriteFont *font;
1098 LOGFONTW logfont;
1099 WCHAR buffer[100];
1100 HRESULT hr;
1101 UINT32 len;
1103 factory = create_factory();
1105 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1106 EXPECT_HR(hr, S_OK);
1108 memset(&logfont, 0, sizeof(logfont));
1109 logfont.lfHeight = 12;
1110 logfont.lfWidth = 12;
1111 logfont.lfWeight = FW_NORMAL;
1112 logfont.lfItalic = 1;
1113 lstrcpyW(logfont.lfFaceName, tahomaW);
1115 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1116 EXPECT_HR(hr, S_OK);
1118 hr = IDWriteFont_GetFontFamily(font, &family);
1119 EXPECT_HR(hr, S_OK);
1121 if (0) /* crashes on native */
1122 hr = IDWriteFontFamily_GetFamilyNames(family, NULL);
1124 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
1125 ok(hr == S_OK, "got 0x%08x\n", hr);
1126 EXPECT_REF(names, 1);
1128 hr = IDWriteFontFamily_GetFamilyNames(family, &names2);
1129 ok(hr == S_OK, "got 0x%08x\n", hr);
1130 EXPECT_REF(names2, 1);
1131 ok(names != names2, "got %p, was %p\n", names2, names);
1133 IDWriteLocalizedStrings_Release(names2);
1135 /* GetStringLength */
1136 if (0) /* crashes on native */
1137 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, NULL);
1139 len = 100;
1140 hr = IDWriteLocalizedStrings_GetStringLength(names, 10, &len);
1141 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1142 ok(len == (UINT32)-1, "got %u\n", len);
1144 len = 0;
1145 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, &len);
1146 ok(hr == S_OK, "got 0x%08x\n", hr);
1147 ok(len > 0, "got %u\n", len);
1149 /* GetString */
1150 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 0);
1151 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1153 hr = IDWriteLocalizedStrings_GetString(names, 10, NULL, 0);
1154 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1156 if (0)
1157 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 100);
1159 buffer[0] = 1;
1160 hr = IDWriteLocalizedStrings_GetString(names, 10, buffer, 100);
1161 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1162 ok(buffer[0] == 0, "got %x\n", buffer[0]);
1164 buffer[0] = 1;
1165 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len-1);
1166 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1167 ok(buffer[0] == 0, "got %x\n", buffer[0]);
1169 buffer[0] = 1;
1170 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len);
1171 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1172 ok(buffer[0] == 0, "got %x\n", buffer[0]);
1174 buffer[0] = 0;
1175 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len+1);
1176 ok(hr == S_OK, "got 0x%08x\n", hr);
1177 ok(buffer[0] != 0, "got %x\n", buffer[0]);
1179 IDWriteLocalizedStrings_Release(names);
1181 IDWriteFontFamily_Release(family);
1182 IDWriteFont_Release(font);
1183 IDWriteGdiInterop_Release(interop);
1184 IDWriteFactory_Release(factory);
1187 static void test_CreateFontFace(void)
1189 IDWriteFontFace *fontface, *fontface2;
1190 IDWriteFontCollection *collection;
1191 DWRITE_FONT_FILE_TYPE file_type;
1192 DWRITE_FONT_FACE_TYPE face_type;
1193 IDWriteGdiInterop *interop;
1194 IDWriteFont *font, *font2;
1195 IDWriteFontFamily *family;
1196 IDWriteFactory *factory;
1197 IDWriteFontFile *file;
1198 LOGFONTW logfont;
1199 BOOL supported;
1200 UINT32 count;
1201 WCHAR *path;
1202 HRESULT hr;
1204 factory = create_factory();
1206 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1207 EXPECT_HR(hr, S_OK);
1209 memset(&logfont, 0, sizeof(logfont));
1210 logfont.lfHeight = 12;
1211 logfont.lfWidth = 12;
1212 logfont.lfWeight = FW_NORMAL;
1213 logfont.lfItalic = 1;
1214 lstrcpyW(logfont.lfFaceName, tahomaW);
1216 font = NULL;
1217 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1218 ok(hr == S_OK, "got 0x%08x\n", hr);
1220 font2 = NULL;
1221 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
1222 ok(hr == S_OK, "got 0x%08x\n", hr);
1223 ok(font != font2, "got %p, %p\n", font, font2);
1225 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface);
1226 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1228 if (0) /* crashes on native */
1229 hr = IDWriteFont_CreateFontFace(font, NULL);
1231 fontface = NULL;
1232 hr = IDWriteFont_CreateFontFace(font, &fontface);
1233 ok(hr == S_OK, "got 0x%08x\n", hr);
1235 fontface2 = NULL;
1236 hr = IDWriteFont_CreateFontFace(font, &fontface2);
1237 ok(hr == S_OK, "got 0x%08x\n", hr);
1238 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
1239 IDWriteFontFace_Release(fontface2);
1241 fontface2 = NULL;
1242 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
1243 ok(hr == S_OK, "got 0x%08x\n", hr);
1244 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
1245 IDWriteFontFace_Release(fontface2);
1247 IDWriteFont_Release(font2);
1248 IDWriteFont_Release(font);
1250 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFont, (void**)&font);
1251 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL), "got 0x%08x\n", hr);
1253 IDWriteFontFace_Release(fontface);
1254 IDWriteGdiInterop_Release(interop);
1256 /* Create from system collection */
1257 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1258 ok(hr == S_OK, "got 0x%08x\n", hr);
1260 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1261 ok(hr == S_OK, "got 0x%08x\n", hr);
1263 font = NULL;
1264 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1265 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1266 ok(hr == S_OK, "got 0x%08x\n", hr);
1268 font2 = NULL;
1269 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1270 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font2);
1271 ok(hr == S_OK, "got 0x%08x\n", hr);
1272 ok(font != font2, "got %p, %p\n", font, font2);
1274 fontface = NULL;
1275 hr = IDWriteFont_CreateFontFace(font, &fontface);
1276 ok(hr == S_OK, "got 0x%08x\n", hr);
1278 fontface2 = NULL;
1279 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
1280 ok(hr == S_OK, "got 0x%08x\n", hr);
1281 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
1283 IDWriteFontFace_Release(fontface);
1284 IDWriteFontFace_Release(fontface2);
1285 IDWriteFont_Release(font2);
1286 IDWriteFont_Release(font);
1287 IDWriteFontFamily_Release(family);
1288 IDWriteFontCollection_Release(collection);
1290 /* IDWriteFactory::CreateFontFace() */
1291 path = create_testfontfile(test_fontfile);
1292 factory = create_factory();
1294 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
1295 ok(hr == S_OK, "got 0x%08x\n",hr);
1297 supported = FALSE;
1298 file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1299 face_type = DWRITE_FONT_FACE_TYPE_CFF;
1300 count = 0;
1301 hr = IDWriteFontFile_Analyze(file, &supported, &file_type, &face_type, &count);
1302 ok(hr == S_OK, "got 0x%08x\n", hr);
1303 ok(supported == TRUE, "got %i\n", supported);
1304 ok(file_type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", file_type);
1305 ok(face_type == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face_type);
1306 ok(count == 1, "got %i\n", count);
1308 /* try mismatching face type, the one that's not supported */
1309 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_CFF, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1310 todo_wine
1311 ok(hr == DWRITE_E_FILEFORMAT, "got 0x%08x\n", hr);
1313 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION, 1, &file, 0,
1314 DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1315 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1317 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_RAW_CFF, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1318 todo_wine
1319 ok(hr == DWRITE_E_UNSUPPORTEDOPERATION || broken(hr == E_INVALIDARG) /* older versions */, "got 0x%08x\n", hr);
1321 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TYPE1, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1322 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1324 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_VECTOR, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1325 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1327 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_BITMAP, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1328 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1330 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_UNKNOWN, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1331 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1333 IDWriteFontFile_Release(file);
1334 IDWriteFactory_Release(factory);
1335 DELETE_FONTFILE(path);
1338 static void test_GetMetrics(void)
1340 IDWriteGdiInterop *interop;
1341 DWRITE_FONT_METRICS metrics;
1342 IDWriteFontFace *fontface;
1343 IDWriteFactory *factory;
1344 OUTLINETEXTMETRICW otm;
1345 IDWriteFont1 *font1;
1346 IDWriteFont *font;
1347 LOGFONTW logfont;
1348 HRESULT hr;
1349 HDC hdc;
1350 HFONT hfont;
1351 int ret;
1353 factory = create_factory();
1355 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1356 EXPECT_HR(hr, S_OK);
1358 memset(&logfont, 0, sizeof(logfont));
1359 logfont.lfHeight = 12;
1360 logfont.lfWidth = 12;
1361 logfont.lfWeight = FW_NORMAL;
1362 logfont.lfItalic = 1;
1363 lstrcpyW(logfont.lfFaceName, tahomaW);
1365 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1366 ok(hr == S_OK, "got 0x%08x\n", hr);
1368 hfont = CreateFontIndirectW(&logfont);
1369 hdc = CreateCompatibleDC(0);
1370 SelectObject(hdc, hfont);
1372 otm.otmSize = sizeof(otm);
1373 ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
1374 ok(ret, "got %d\n", ret);
1375 DeleteDC(hdc);
1376 DeleteObject(hfont);
1378 if (0) /* crashes on native */
1379 IDWriteFont_GetMetrics(font, NULL);
1381 memset(&metrics, 0, sizeof(metrics));
1382 IDWriteFont_GetMetrics(font, &metrics);
1384 ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
1385 ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
1386 ok(metrics.descent != 0, "descent %u\n", metrics.descent);
1387 ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
1388 ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
1389 ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
1390 ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
1391 ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
1392 ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
1393 ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
1395 hr = IDWriteFont_CreateFontFace(font, &fontface);
1396 ok(hr == S_OK, "got 0x%08x\n", hr);
1398 memset(&metrics, 0, sizeof(metrics));
1399 IDWriteFontFace_GetMetrics(fontface, &metrics);
1401 ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
1402 ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
1403 ok(metrics.descent != 0, "descent %u\n", metrics.descent);
1404 ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
1405 ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
1406 ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
1407 ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
1408 ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
1409 ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
1410 ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
1412 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
1413 if (hr == S_OK) {
1414 DWRITE_FONT_METRICS1 metrics1;
1415 IDWriteFontFace1 *fontface1;
1417 memset(&metrics1, 0, sizeof(metrics1));
1418 IDWriteFont1_GetMetrics(font1, &metrics1);
1420 ok(metrics1.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics1.designUnitsPerEm);
1421 ok(metrics1.ascent != 0, "ascent %u\n", metrics1.ascent);
1422 ok(metrics1.descent != 0, "descent %u\n", metrics1.descent);
1423 ok(metrics1.lineGap == 0, "lineGap %d\n", metrics1.lineGap);
1424 ok(metrics1.capHeight, "capHeight %u\n", metrics1.capHeight);
1425 ok(metrics1.xHeight != 0, "xHeight %u\n", metrics1.xHeight);
1426 ok(metrics1.underlinePosition < 0, "underlinePosition %d\n", metrics1.underlinePosition);
1427 ok(metrics1.underlineThickness != 0, "underlineThickness %u\n", metrics1.underlineThickness);
1428 ok(metrics1.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics1.strikethroughPosition);
1429 ok(metrics1.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics1.strikethroughThickness);
1430 ok(metrics1.glyphBoxLeft < 0, "glyphBoxLeft %d\n", metrics1.glyphBoxLeft);
1431 ok(metrics1.glyphBoxTop > 0, "glyphBoxTop %d\n", metrics1.glyphBoxTop);
1432 ok(metrics1.glyphBoxRight > 0, "glyphBoxRight %d\n", metrics1.glyphBoxRight);
1433 ok(metrics1.glyphBoxBottom < 0, "glyphBoxBottom %d\n", metrics1.glyphBoxBottom);
1434 ok(metrics1.subscriptPositionY < 0, "subscriptPositionY %d\n", metrics1.subscriptPositionY);
1435 ok(metrics1.subscriptSizeX > 0, "subscriptSizeX %d\n", metrics1.subscriptSizeX);
1436 ok(metrics1.subscriptSizeY > 0, "subscriptSizeY %d\n", metrics1.subscriptSizeY);
1437 ok(metrics1.superscriptPositionY > 0, "superscriptPositionY %d\n", metrics1.superscriptPositionY);
1438 ok(metrics1.superscriptSizeX > 0, "superscriptSizeX %d\n", metrics1.superscriptSizeX);
1439 ok(metrics1.superscriptSizeY > 0, "superscriptSizeY %d\n", metrics1.superscriptSizeY);
1440 ok(!metrics1.hasTypographicMetrics, "hasTypographicMetrics %d\n", metrics1.hasTypographicMetrics);
1442 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
1443 ok(hr == S_OK, "got 0x%08x\n", hr);
1445 memset(&metrics1, 0, sizeof(metrics1));
1446 IDWriteFontFace1_GetMetrics(fontface1, &metrics1);
1448 ok(metrics1.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics1.designUnitsPerEm);
1449 ok(metrics1.ascent != 0, "ascent %u\n", metrics1.ascent);
1450 ok(metrics1.descent != 0, "descent %u\n", metrics1.descent);
1451 ok(metrics1.lineGap == 0, "lineGap %d\n", metrics1.lineGap);
1452 ok(metrics1.capHeight, "capHeight %u\n", metrics1.capHeight);
1453 ok(metrics1.xHeight != 0, "xHeight %u\n", metrics1.xHeight);
1454 ok(metrics1.underlinePosition < 0, "underlinePosition %d\n", metrics1.underlinePosition);
1455 ok(metrics1.underlineThickness != 0, "underlineThickness %u\n", metrics1.underlineThickness);
1456 ok(metrics1.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics1.strikethroughPosition);
1457 ok(metrics1.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics1.strikethroughThickness);
1458 ok(metrics1.glyphBoxLeft < 0, "glyphBoxLeft %d\n", metrics1.glyphBoxLeft);
1459 ok(metrics1.glyphBoxTop > 0, "glyphBoxTop %d\n", metrics1.glyphBoxTop);
1460 ok(metrics1.glyphBoxRight > 0, "glyphBoxRight %d\n", metrics1.glyphBoxRight);
1461 ok(metrics1.glyphBoxBottom < 0, "glyphBoxBottom %d\n", metrics1.glyphBoxBottom);
1462 ok(metrics1.subscriptPositionY < 0, "subscriptPositionY %d\n", metrics1.subscriptPositionY);
1463 ok(metrics1.subscriptSizeX > 0, "subscriptSizeX %d\n", metrics1.subscriptSizeX);
1464 ok(metrics1.subscriptSizeY > 0, "subscriptSizeY %d\n", metrics1.subscriptSizeY);
1465 ok(metrics1.superscriptPositionY > 0, "superscriptPositionY %d\n", metrics1.superscriptPositionY);
1466 ok(metrics1.superscriptSizeX > 0, "superscriptSizeX %d\n", metrics1.superscriptSizeX);
1467 ok(metrics1.superscriptSizeY > 0, "superscriptSizeY %d\n", metrics1.superscriptSizeY);
1468 ok(!metrics1.hasTypographicMetrics, "hasTypographicMetrics %d\n", metrics1.hasTypographicMetrics);
1470 IDWriteFontFace1_Release(fontface1);
1471 IDWriteFont1_Release(font1);
1473 else
1474 win_skip("DWRITE_FONT_METRICS1 is not supported.\n");
1476 IDWriteFontFace_Release(fontface);
1478 IDWriteFont_Release(font);
1479 IDWriteGdiInterop_Release(interop);
1480 IDWriteFactory_Release(factory);
1483 static void test_system_fontcollection(void)
1485 IDWriteFontCollection *collection, *coll2;
1486 IDWriteLocalFontFileLoader *localloader;
1487 IDWriteFactory *factory, *factory2;
1488 IDWriteFontFileLoader *loader;
1489 IDWriteFontFamily *family;
1490 IDWriteFontFace *fontface;
1491 IDWriteFontFile *file;
1492 IDWriteFont *font;
1493 HRESULT hr;
1494 UINT32 i;
1495 BOOL ret;
1497 factory = create_factory();
1499 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1500 ok(hr == S_OK, "got 0x%08x\n", hr);
1502 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, FALSE);
1503 ok(hr == S_OK, "got 0x%08x\n", hr);
1504 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
1505 IDWriteFontCollection_Release(coll2);
1507 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, TRUE);
1508 ok(hr == S_OK, "got 0x%08x\n", hr);
1509 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
1510 IDWriteFontCollection_Release(coll2);
1512 factory2 = create_factory();
1513 hr = IDWriteFactory_GetSystemFontCollection(factory2, &coll2, FALSE);
1514 ok(hr == S_OK, "got 0x%08x\n", hr);
1515 ok(coll2 != collection, "got %p, was %p\n", coll2, collection);
1516 IDWriteFontCollection_Release(coll2);
1517 IDWriteFactory_Release(factory2);
1519 i = IDWriteFontCollection_GetFontFamilyCount(collection);
1520 ok(i, "got %u\n", i);
1522 /* invalid index */
1523 family = (void*)0xdeadbeef;
1524 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
1525 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1526 ok(family == NULL, "got %p\n", family);
1528 ret = FALSE;
1529 i = (UINT32)-1;
1530 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaW, &i, &ret);
1531 ok(hr == S_OK, "got 0x%08x\n", hr);
1532 ok(ret, "got %d\n", ret);
1533 ok(i != (UINT32)-1, "got %u\n", i);
1535 ret = FALSE;
1536 i = (UINT32)-1;
1537 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaUppercaseW, &i, &ret);
1538 ok(hr == S_OK, "got 0x%08x\n", hr);
1539 ok(ret, "got %d\n", ret);
1540 ok(i != (UINT32)-1, "got %u\n", i);
1542 ret = FALSE;
1543 i = (UINT32)-1;
1544 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaStrangecaseW, &i, &ret);
1545 ok(hr == S_OK, "got 0x%08x\n", hr);
1546 ok(ret, "got %d\n", ret);
1547 ok(i != (UINT32)-1, "got %u\n", i);
1549 /* get back local file loader */
1550 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
1551 ok(hr == S_OK, "got 0x%08x\n", hr);
1553 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1554 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1555 ok(hr == S_OK, "got 0x%08x\n", hr);
1556 IDWriteFontFamily_Release(family);
1558 hr = IDWriteFont_CreateFontFace(font, &fontface);
1559 ok(hr == S_OK, "got 0x%08x\n", hr);
1560 IDWriteFont_Release(font);
1562 i = 1;
1563 file = NULL;
1564 hr = IDWriteFontFace_GetFiles(fontface, &i, &file);
1565 ok(hr == S_OK, "got 0x%08x\n", hr);
1566 ok(file != NULL, "got %p\n", file);
1568 hr = IDWriteFontFile_GetLoader(file, &loader);
1569 ok(hr == S_OK, "got 0x%08x\n", hr);
1570 IDWriteFontFile_Release(file);
1572 hr = IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
1573 ok(hr == S_OK, "got 0x%08x\n", hr);
1574 IDWriteLocalFontFileLoader_Release(localloader);
1576 /* local loader is not registered by default */
1577 hr = IDWriteFactory_RegisterFontFileLoader(factory, loader);
1578 ok(hr == S_OK || broken(hr == DWRITE_E_ALREADYREGISTERED), "got 0x%08x\n", hr);
1579 hr = IDWriteFactory_UnregisterFontFileLoader(factory, loader);
1580 ok(hr == S_OK || broken(hr == E_INVALIDARG), "got 0x%08x\n", hr);
1582 /* try with a different factory */
1583 factory2 = create_factory();
1584 hr = IDWriteFactory_RegisterFontFileLoader(factory2, loader);
1585 ok(hr == S_OK || broken(hr == DWRITE_E_ALREADYREGISTERED), "got 0x%08x\n", hr);
1586 hr = IDWriteFactory_RegisterFontFileLoader(factory2, loader);
1587 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1588 hr = IDWriteFactory_UnregisterFontFileLoader(factory2, loader);
1589 ok(hr == S_OK || broken(hr == E_INVALIDARG), "got 0x%08x\n", hr);
1590 hr = IDWriteFactory_UnregisterFontFileLoader(factory2, loader);
1591 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1592 IDWriteFactory_Release(factory2);
1594 IDWriteFontFileLoader_Release(loader);
1596 ret = TRUE;
1597 i = 0;
1598 hr = IDWriteFontCollection_FindFamilyName(collection, blahW, &i, &ret);
1599 ok(hr == S_OK, "got 0x%08x\n", hr);
1600 ok(!ret, "got %d\n", ret);
1601 ok(i == (UINT32)-1, "got %u\n", i);
1603 IDWriteFontCollection_Release(collection);
1604 IDWriteFactory_Release(factory);
1607 static void test_ConvertFontFaceToLOGFONT(void)
1609 DWRITE_FONT_SIMULATIONS sim;
1610 IDWriteGdiInterop *interop;
1611 IDWriteFontFace *fontface;
1612 IDWriteFactory *factory;
1613 IDWriteFont *font;
1614 LOGFONTW logfont;
1615 HRESULT hr;
1617 factory = create_factory();
1619 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1620 ok(hr == S_OK, "got 0x%08x\n", hr);
1622 memset(&logfont, 0, sizeof(logfont));
1623 logfont.lfHeight = 12;
1624 logfont.lfWidth = 12;
1625 logfont.lfEscapement = 100;
1626 logfont.lfWeight = FW_NORMAL;
1627 logfont.lfItalic = 1;
1628 logfont.lfUnderline = 1;
1629 logfont.lfStrikeOut = 1;
1631 lstrcpyW(logfont.lfFaceName, tahomaW);
1633 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1634 ok(hr == S_OK, "got 0x%08x\n", hr);
1636 hr = IDWriteFont_CreateFontFace(font, &fontface);
1637 ok(hr == S_OK, "got 0x%08x\n", hr);
1639 sim = IDWriteFont_GetSimulations(font);
1640 ok(sim == DWRITE_FONT_SIMULATIONS_OBLIQUE, "sim %d\n", sim);
1642 sim = IDWriteFontFace_GetSimulations(fontface);
1643 ok(sim == DWRITE_FONT_SIMULATIONS_OBLIQUE, "sim %d\n", sim);
1645 IDWriteFont_Release(font);
1647 if (0) /* crashes on native */
1649 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, NULL, NULL);
1650 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, NULL);
1653 memset(&logfont, 0xa, sizeof(logfont));
1654 logfont.lfFaceName[0] = 0;
1656 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, &logfont);
1657 ok(hr == S_OK, "got 0x%08x\n", hr);
1658 ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight);
1659 ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth);
1660 ok(logfont.lfWeight == FW_NORMAL, "got %d\n", logfont.lfWeight);
1661 ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement);
1662 ok(logfont.lfItalic == 1, "got %d\n", logfont.lfItalic);
1663 ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline);
1664 ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut);
1665 ok(!lstrcmpW(logfont.lfFaceName, tahomaW), "got %s\n", wine_dbgstr_w(logfont.lfFaceName));
1667 IDWriteGdiInterop_Release(interop);
1668 IDWriteFontFace_Release(fontface);
1669 IDWriteFactory_Release(factory);
1672 static HRESULT WINAPI fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
1674 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileEnumerator))
1676 *obj = iface;
1677 IDWriteFontFileEnumerator_AddRef(iface);
1678 return S_OK;
1680 return E_NOINTERFACE;
1683 static ULONG WINAPI fontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
1685 return 2;
1688 static ULONG WINAPI fontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
1690 return 1;
1693 static HRESULT WINAPI fontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file)
1695 *file = NULL;
1696 return E_FAIL;
1699 static HRESULT WINAPI fontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
1701 *current = FALSE;
1702 return S_OK;
1705 static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl =
1707 fontfileenumerator_QueryInterface,
1708 fontfileenumerator_AddRef,
1709 fontfileenumerator_Release,
1710 fontfileenumerator_MoveNext,
1711 fontfileenumerator_GetCurrentFontFile,
1714 static HRESULT WINAPI fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
1716 *obj = iface;
1717 return S_OK;
1720 static ULONG WINAPI fontcollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
1722 return 2;
1725 static ULONG WINAPI fontcollectionloader_Release(IDWriteFontCollectionLoader *iface)
1727 return 1;
1730 static HRESULT WINAPI fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory, const void *key,
1731 UINT32 key_size, IDWriteFontFileEnumerator **ret)
1733 static IDWriteFontFileEnumerator enumerator = { &dwritefontfileenumeratorvtbl };
1734 *ret = &enumerator;
1735 return S_OK;
1738 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl = {
1739 fontcollectionloader_QueryInterface,
1740 fontcollectionloader_AddRef,
1741 fontcollectionloader_Release,
1742 fontcollectionloader_CreateEnumeratorFromKey
1745 static void test_CustomFontCollection(void)
1747 static const WCHAR fontnameW[] = {'w','i','n','e','_','t','e','s','t',0};
1748 IDWriteFontCollectionLoader collection = { &dwritefontcollectionloadervtbl };
1749 IDWriteFontCollectionLoader collection2 = { &dwritefontcollectionloadervtbl };
1750 IDWriteFontCollectionLoader collection3 = { &dwritefontcollectionloadervtbl };
1751 IDWriteFontCollection *font_collection = NULL;
1752 static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
1753 struct test_fontcollectionloader resource_collection = { { &resourcecollectionloadervtbl }, &rloader };
1754 IDWriteFontFamily *family, *family2, *family3;
1755 IDWriteFontFace *idfontface, *idfontface2;
1756 IDWriteFontFile *fontfile, *fontfile2;
1757 IDWriteLocalizedStrings *string;
1758 IDWriteFont *idfont, *idfont2;
1759 IDWriteFactory *factory;
1760 UINT32 index, count;
1761 BOOL exists;
1762 HRESULT hr;
1763 HRSRC font;
1765 factory = create_factory();
1767 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, NULL);
1768 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1770 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, NULL);
1771 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1773 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
1774 ok(hr == S_OK, "got 0x%08x\n", hr);
1775 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection2);
1776 ok(hr == S_OK, "got 0x%08x\n", hr);
1777 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
1778 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1780 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1781 ok(hr == S_OK, "got 0x%08x\n", hr);
1782 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface);
1783 ok(hr == S_OK, "got 0x%08x\n", hr);
1785 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection3, "Billy", 6, &font_collection);
1786 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1788 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection, "Billy", 6, &font_collection);
1789 ok(hr == S_OK, "got 0x%08x\n", hr);
1790 IDWriteFontCollection_Release(font_collection);
1792 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection2, "Billy", 6, &font_collection);
1793 ok(hr == S_OK, "got 0x%08x\n", hr);
1794 IDWriteFontCollection_Release(font_collection);
1796 hr = IDWriteFactory_CreateCustomFontCollection(factory, (IDWriteFontCollectionLoader*)0xdeadbeef, "Billy", 6, &font_collection);
1797 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1799 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1800 ok(font != NULL, "Failed to find font resource\n");
1802 hr = IDWriteFactory_CreateCustomFontCollection(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface,
1803 &font, sizeof(HRSRC), &font_collection);
1804 ok(hr == S_OK, "got 0x%08x\n",hr);
1806 index = 1;
1807 exists = FALSE;
1808 hr = IDWriteFontCollection_FindFamilyName(font_collection, fontnameW, &index, &exists);
1809 ok(hr == S_OK, "got 0x%08x\n", hr);
1810 ok(index == 0, "got index %i\n", index);
1811 ok(exists, "got exists %i\n", exists);
1813 count = IDWriteFontCollection_GetFontFamilyCount(font_collection);
1814 ok(count == 1, "got %u\n", count);
1816 family = NULL;
1817 hr = IDWriteFontCollection_GetFontFamily(font_collection, 0, &family);
1818 ok(hr == S_OK, "got 0x%08x\n", hr);
1819 EXPECT_REF(family, 1);
1821 family2 = NULL;
1822 hr = IDWriteFontCollection_GetFontFamily(font_collection, 0, &family2);
1823 ok(hr == S_OK, "got 0x%08x\n", hr);
1824 EXPECT_REF(family2, 1);
1825 ok(family != family2, "got %p, %p\n", family, family2);
1827 hr = IDWriteFontFamily_GetFont(family, 0, &idfont);
1828 ok(hr == S_OK, "got 0x%08x\n", hr);
1829 EXPECT_REF(idfont, 1);
1830 EXPECT_REF(family, 2);
1831 hr = IDWriteFontFamily_GetFont(family, 0, &idfont2);
1832 ok(hr == S_OK, "got 0x%08x\n", hr);
1833 EXPECT_REF(idfont2, 1);
1834 EXPECT_REF(family, 3);
1835 ok(idfont != idfont2, "got %p, %p\n", idfont, idfont2);
1836 IDWriteFont_Release(idfont2);
1838 hr = IDWriteFont_GetInformationalStrings(idfont, DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE, &string, &exists);
1839 ok(hr == S_OK, "got 0x%08x\n", hr);
1840 ok(exists, "got %d\n", exists);
1841 EXPECT_REF(string, 1);
1843 family3 = NULL;
1844 hr = IDWriteFont_GetFontFamily(idfont, &family3);
1845 ok(hr == S_OK, "got 0x%08x\n", hr);
1846 EXPECT_REF(family, 3);
1847 ok(family == family3, "got %p, %p\n", family, family3);
1848 IDWriteFontFamily_Release(family3);
1850 idfontface = NULL;
1851 hr = IDWriteFont_CreateFontFace(idfont, &idfontface);
1852 ok(hr == S_OK, "got 0x%08x\n", hr);
1853 EXPECT_REF(idfont, 1);
1855 idfont2 = NULL;
1856 hr = IDWriteFontFamily_GetFont(family2, 0, &idfont2);
1857 ok(hr == S_OK, "got 0x%08x\n", hr);
1858 EXPECT_REF(idfont2, 1);
1859 EXPECT_REF(idfont, 1);
1860 ok(idfont2 != idfont, "Font instances should not match\n");
1862 idfontface2 = NULL;
1863 hr = IDWriteFont_CreateFontFace(idfont2, &idfontface2);
1864 ok(hr == S_OK, "got 0x%08x\n", hr);
1865 ok(idfontface2 == idfontface, "fontfaces should match\n");
1867 index = 1;
1868 fontfile = NULL;
1869 hr = IDWriteFontFace_GetFiles(idfontface, &index, &fontfile);
1870 ok(hr == S_OK, "got 0x%08x\n", hr);
1872 index = 1;
1873 fontfile2 = NULL;
1874 hr = IDWriteFontFace_GetFiles(idfontface2, &index, &fontfile2);
1875 ok(hr == S_OK, "got 0x%08x\n", hr);
1876 ok(fontfile == fontfile2, "fontfiles should match\n");
1878 IDWriteFont_Release(idfont);
1879 IDWriteFont_Release(idfont2);
1880 IDWriteFontFile_Release(fontfile);
1881 IDWriteFontFile_Release(fontfile2);
1882 IDWriteFontFace_Release(idfontface);
1883 IDWriteFontFace_Release(idfontface2);
1884 IDWriteFontFamily_Release(family2);
1885 IDWriteFontFamily_Release(family);
1886 IDWriteFontCollection_Release(font_collection);
1888 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
1889 ok(hr == S_OK, "got 0x%08x\n", hr);
1890 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
1891 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1892 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection2);
1893 ok(hr == S_OK, "got 0x%08x\n", hr);
1894 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface);
1895 ok(hr == S_OK, "got 0x%08x\n", hr);
1896 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1897 ok(hr == S_OK, "got 0x%08x\n", hr);
1899 IDWriteFactory_Release(factory);
1902 static HRESULT WINAPI fontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
1904 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
1906 *obj = iface;
1907 IDWriteFontFileLoader_AddRef(iface);
1908 return S_OK;
1911 *obj = NULL;
1912 return E_NOINTERFACE;
1915 static ULONG WINAPI fontfileloader_AddRef(IDWriteFontFileLoader *iface)
1917 return 2;
1920 static ULONG WINAPI fontfileloader_Release(IDWriteFontFileLoader *iface)
1922 return 1;
1925 static HRESULT WINAPI fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1927 return 0x8faecafe;
1930 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl = {
1931 fontfileloader_QueryInterface,
1932 fontfileloader_AddRef,
1933 fontfileloader_Release,
1934 fontfileloader_CreateStreamFromKey
1937 static void test_CreateCustomFontFileReference(void)
1939 IDWriteFontFileLoader floader = { &dwritefontfileloadervtbl };
1940 IDWriteFontFileLoader floader2 = { &dwritefontfileloadervtbl };
1941 IDWriteFontFileLoader floader3 = { &dwritefontfileloadervtbl };
1942 IDWriteFactory *factory, *factory2;
1943 IDWriteFontFile *file, *file2;
1944 BOOL support;
1945 DWRITE_FONT_FILE_TYPE file_type;
1946 DWRITE_FONT_FACE_TYPE face_type;
1947 UINT32 count;
1948 IDWriteFontFace *face, *face2;
1949 HRESULT hr;
1950 HRSRC fontrsrc;
1951 UINT32 codePoints[1] = {0xa8};
1952 UINT16 indices[2];
1954 factory = create_factory();
1955 factory2 = create_factory();
1957 hr = IDWriteFactory_RegisterFontFileLoader(factory, NULL);
1958 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1959 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
1960 ok(hr == S_OK, "got 0x%08x\n", hr);
1961 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader2);
1962 ok(hr == S_OK, "got 0x%08x\n", hr);
1963 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
1964 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1965 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1966 ok(hr == S_OK, "got 0x%08x\n", hr);
1968 file = NULL;
1969 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &file);
1970 ok(hr == S_OK, "got 0x%08x\n", hr);
1971 IDWriteFontFile_Release(file);
1973 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader3, &file);
1974 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1976 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, NULL, &file);
1977 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1979 file = NULL;
1980 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &file);
1981 ok(hr == S_OK, "got 0x%08x\n", hr);
1983 file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE;
1984 face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE;
1985 support = TRUE;
1986 count = 1;
1987 hr = IDWriteFontFile_Analyze(file, &support, &file_type, &face_type, &count);
1988 ok(hr == 0x8faecafe, "got 0x%08x\n", hr);
1989 ok(support == FALSE, "got %i\n", support);
1990 ok(file_type == DWRITE_FONT_FILE_TYPE_UNKNOWN, "got %i\n", file_type);
1991 ok(face_type == DWRITE_FONT_FACE_TYPE_UNKNOWN, "got %i\n", face_type);
1992 ok(count == 0, "got %i\n", count);
1994 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_CFF, 1, &file, 0, 0, &face);
1995 ok(hr == 0x8faecafe, "got 0x%08x\n", hr);
1996 IDWriteFontFile_Release(file);
1998 fontrsrc = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1999 ok(fontrsrc != NULL, "Failed to find font resource\n");
2001 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontrsrc, sizeof(HRSRC), &rloader, &file);
2002 ok(hr == S_OK, "got 0x%08x\n", hr);
2004 file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
2005 face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
2006 support = FALSE;
2007 count = 0;
2008 hr = IDWriteFontFile_Analyze(file, &support, &file_type, &face_type, &count);
2009 ok(hr == S_OK, "got 0x%08x\n", hr);
2010 ok(support == TRUE, "got %i\n", support);
2011 ok(file_type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", file_type);
2012 ok(face_type == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face_type);
2013 ok(count == 1, "got %i\n", count);
2015 /* invalid index */
2016 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 1, DWRITE_FONT_SIMULATIONS_NONE, &face);
2017 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2019 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face);
2020 ok(hr == S_OK, "got 0x%08x\n", hr);
2022 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
2023 ok(hr == S_OK, "got 0x%08x\n", hr);
2024 /* fontface instances are reused starting with win7 */
2025 ok(face == face2 || broken(face != face2), "got %p, %p\n", face, face2);
2026 IDWriteFontFace_Release(face2);
2028 /* file was created with different factory */
2029 face2 = NULL;
2030 hr = IDWriteFactory_CreateFontFace(factory2, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
2031 todo_wine
2032 ok(hr == S_OK, "got 0x%08x\n", hr);
2033 if (face2)
2034 IDWriteFontFace_Release(face2);
2036 file2 = NULL;
2037 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontrsrc, sizeof(HRSRC), &rloader, &file2);
2038 ok(hr == S_OK, "got 0x%08x\n", hr);
2039 ok(file != file2, "got %p, %p\n", file, file2);
2041 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file2, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
2042 ok(hr == S_OK, "got 0x%08x\n", hr);
2043 /* fontface instances are reused starting with win7 */
2044 ok(face == face2 || broken(face != face2), "got %p, %p\n", face, face2);
2045 IDWriteFontFace_Release(face2);
2046 IDWriteFontFile_Release(file2);
2048 hr = IDWriteFontFace_GetGlyphIndices(face, NULL, 0, NULL);
2049 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* win8 */, "got 0x%08x\n", hr);
2051 hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 0, NULL);
2052 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* win8 */, "got 0x%08x\n", hr);
2054 hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 0, indices);
2055 ok(hr == S_OK, "got 0x%08x\n", hr);
2057 hr = IDWriteFontFace_GetGlyphIndices(face, NULL, 0, indices);
2058 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* win8 */, "got 0x%08x\n", hr);
2060 indices[0] = indices[1] = 11;
2061 hr = IDWriteFontFace_GetGlyphIndices(face, NULL, 1, indices);
2062 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2063 ok(indices[0] == 0, "got index %i\n", indices[0]);
2064 ok(indices[1] == 11, "got index %i\n", indices[1]);
2066 if (0) /* crashes on native */
2067 hr = IDWriteFontFace_GetGlyphIndices(face, NULL, 1, NULL);
2069 hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 1, indices);
2070 ok(hr == S_OK, "got 0x%08x\n", hr);
2071 ok(indices[0] == 6, "got index %i\n", indices[0]);
2072 IDWriteFontFace_Release(face);
2073 IDWriteFontFile_Release(file);
2075 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
2076 ok(hr == S_OK, "got 0x%08x\n", hr);
2077 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
2078 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2079 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader2);
2080 ok(hr == S_OK, "got 0x%08x\n", hr);
2081 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
2082 ok(hr == S_OK, "got 0x%08x\n", hr);
2084 IDWriteFactory_Release(factory2);
2085 IDWriteFactory_Release(factory);
2088 static void test_CreateFontFileReference(void)
2090 HRESULT hr;
2091 IDWriteFontFile *ffile = NULL;
2092 BOOL support;
2093 DWRITE_FONT_FILE_TYPE type;
2094 DWRITE_FONT_FACE_TYPE face;
2095 UINT32 count;
2096 IDWriteFontFace *fface = NULL;
2097 IDWriteFactory *factory;
2098 WCHAR *path;
2100 path = create_testfontfile(test_fontfile);
2101 factory = create_factory();
2103 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &ffile);
2104 ok(hr == S_OK, "got 0x%08x\n",hr);
2106 support = FALSE;
2107 type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
2108 face = DWRITE_FONT_FACE_TYPE_CFF;
2109 count = 0;
2110 hr = IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
2111 ok(hr == S_OK, "got 0x%08x\n", hr);
2112 ok(support == TRUE, "got %i\n", support);
2113 ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type);
2114 ok(face == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face);
2115 ok(count == 1, "got %i\n", count);
2117 hr = IDWriteFactory_CreateFontFace(factory, face, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fface);
2118 ok(hr == S_OK, "got 0x%08x\n", hr);
2120 IDWriteFontFace_Release(fface);
2121 IDWriteFontFile_Release(ffile);
2122 IDWriteFactory_Release(factory);
2124 DELETE_FONTFILE(path);
2127 static void test_shared_isolated(void)
2129 IDWriteFactory *isolated, *isolated2;
2130 IDWriteFactory *shared, *shared2;
2131 HRESULT hr;
2133 /* invalid type */
2134 shared = NULL;
2135 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&shared);
2136 ok(hr == S_OK, "got 0x%08x\n", hr);
2137 ok(shared != NULL, "got %p\n", shared);
2138 IDWriteFactory_Release(shared);
2140 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared);
2141 ok(hr == S_OK, "got 0x%08x\n", hr);
2143 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
2144 ok(hr == S_OK, "got 0x%08x\n", hr);
2145 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
2147 IDWriteFactory_Release(shared);
2148 IDWriteFactory_Release(shared2);
2150 /* we got 2 references, released 2 - still same pointer is returned */
2151 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
2152 ok(hr == S_OK, "got 0x%08x\n", hr);
2153 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
2154 IDWriteFactory_Release(shared2);
2156 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated);
2157 ok(hr == S_OK, "got 0x%08x\n", hr);
2159 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated2);
2160 ok(hr == S_OK, "got 0x%08x\n", hr);
2161 ok(isolated != isolated2, "got %p, and %p\n", isolated, isolated2);
2162 IDWriteFactory_Release(isolated2);
2164 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&isolated2);
2165 ok(hr == S_OK, "got 0x%08x\n", hr);
2166 ok(shared != isolated2, "got %p, and %p\n", shared, isolated2);
2168 IDWriteFactory_Release(isolated);
2169 IDWriteFactory_Release(isolated2);
2172 static void test_GetUnicodeRanges(void)
2174 DWRITE_UNICODE_RANGE *ranges, r;
2175 IDWriteFontFile *ffile = NULL;
2176 IDWriteFontFace1 *fontface1;
2177 IDWriteFontFace *fontface;
2178 IDWriteFactory *factory;
2179 UINT32 count;
2180 HRESULT hr;
2181 HRSRC font;
2183 factory = create_factory();
2185 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
2186 ok(hr == S_OK, "got 0x%08x\n", hr);
2188 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
2189 ok(font != NULL, "Failed to find font resource\n");
2191 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
2192 ok(hr == S_OK, "got 0x%08x\n", hr);
2194 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
2195 ok(hr == S_OK, "got 0x%08x\n", hr);
2196 IDWriteFontFile_Release(ffile);
2198 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
2199 IDWriteFontFace_Release(fontface);
2200 if (hr != S_OK) {
2201 win_skip("GetUnicodeRanges() is not supported.\n");
2202 IDWriteFactory_Release(factory);
2203 return;
2206 count = 0;
2207 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 0, NULL, &count);
2208 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
2209 ok(count > 0, "got %u\n", count);
2211 count = 1;
2212 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, NULL, &count);
2213 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2214 ok(count == 0, "got %u\n", count);
2216 count = 0;
2217 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, &r, &count);
2218 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
2219 ok(count > 1, "got %u\n", count);
2221 ranges = heap_alloc(count*sizeof(DWRITE_UNICODE_RANGE));
2222 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, count, ranges, &count);
2223 ok(hr == S_OK, "got 0x%08x\n", hr);
2225 ranges[0].first = ranges[0].last = 0;
2226 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, ranges, &count);
2227 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
2228 ok(ranges[0].first != 0 && ranges[0].last != 0, "got 0x%x-0x%0x\n", ranges[0].first, ranges[0].last);
2230 heap_free(ranges);
2232 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
2233 ok(hr == S_OK, "got 0x%08x\n", hr);
2235 IDWriteFontFace1_Release(fontface1);
2236 IDWriteFactory_Release(factory);
2239 static void test_GetFontFromFontFace(void)
2241 IDWriteFontFace *fontface, *fontface2;
2242 IDWriteFontCollection *collection;
2243 IDWriteFont *font, *font2, *font3;
2244 IDWriteFontFamily *family;
2245 IDWriteFactory *factory;
2246 IDWriteFontFile *file;
2247 WCHAR *path;
2248 HRESULT hr;
2250 factory = create_factory();
2252 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
2253 ok(hr == S_OK, "got 0x%08x\n", hr);
2255 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
2256 ok(hr == S_OK, "got 0x%08x\n", hr);
2258 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2259 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2260 ok(hr == S_OK, "got 0x%08x\n", hr);
2262 hr = IDWriteFont_CreateFontFace(font, &fontface);
2263 ok(hr == S_OK, "got 0x%08x\n", hr);
2265 font2 = NULL;
2266 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font2);
2267 ok(hr == S_OK, "got 0x%08x\n", hr);
2268 ok(font2 != font, "got %p, %p\n", font2, font);
2270 font3 = NULL;
2271 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font3);
2272 ok(hr == S_OK, "got 0x%08x\n", hr);
2273 ok(font3 != font && font3 != font2, "got %p, %p, %p\n", font3, font2, font);
2275 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
2276 ok(hr == S_OK, "got 0x%08x\n", hr);
2277 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
2278 IDWriteFontFace_Release(fontface2);
2280 hr = IDWriteFont_CreateFontFace(font3, &fontface2);
2281 ok(hr == S_OK, "got 0x%08x\n", hr);
2282 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
2283 IDWriteFontFace_Release(fontface2);
2284 IDWriteFontFace_Release(fontface);
2285 IDWriteFont_Release(font3);
2286 IDWriteFactory_Release(factory);
2288 /* fontface that wasn't created from this collection */
2289 factory = create_factory();
2290 path = create_testfontfile(test_fontfile);
2292 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2293 ok(hr == S_OK, "got 0x%08x\n",hr);
2295 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
2296 ok(hr == S_OK, "got 0x%08x\n", hr);
2297 IDWriteFontFile_Release(file);
2299 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font3);
2300 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
2301 ok(font3 == NULL, "got %p\n", font3);
2302 IDWriteFontFace_Release(fontface);
2304 IDWriteFont_Release(font);
2305 IDWriteFont_Release(font2);
2306 IDWriteFontFamily_Release(family);
2307 IDWriteFontCollection_Release(collection);
2308 IDWriteFactory_Release(factory);
2309 DELETE_FONTFILE(path);
2312 static IDWriteFont *get_font(IDWriteFactory *factory, const WCHAR *name, DWRITE_FONT_STYLE style)
2314 IDWriteFontCollection *collection;
2315 IDWriteFontFamily *family;
2316 IDWriteFont *font = NULL;
2317 UINT32 index;
2318 BOOL exists;
2319 HRESULT hr;
2321 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
2322 ok(hr == S_OK, "got 0x%08x\n", hr);
2324 index = ~0;
2325 exists = FALSE;
2326 hr = IDWriteFontCollection_FindFamilyName(collection, name, &index, &exists);
2327 ok(hr == S_OK, "got 0x%08x\n", hr);
2328 if (!exists) goto not_found;
2330 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
2331 ok(hr == S_OK, "got 0x%08x\n", hr);
2333 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2334 DWRITE_FONT_STRETCH_NORMAL, style, &font);
2335 ok(hr == S_OK, "got 0x%08x\n", hr);
2337 IDWriteFontFamily_Release(family);
2338 not_found:
2339 IDWriteFontCollection_Release(collection);
2340 return font;
2343 static IDWriteFont *get_tahoma_instance(IDWriteFactory *factory, DWRITE_FONT_STYLE style)
2345 IDWriteFont *font = get_font(factory, tahomaW, style);
2346 ok(font != NULL, "failed to get Tahoma\n");
2347 return font;
2350 static void test_GetFirstMatchingFont(void)
2352 DWRITE_FONT_SIMULATIONS simulations;
2353 IDWriteFont *font, *font2;
2354 IDWriteFactory *factory;
2356 factory = create_factory();
2358 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
2359 font2 = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
2360 ok(font != font2, "got %p, %p\n", font, font2);
2361 IDWriteFont_Release(font);
2362 IDWriteFont_Release(font2);
2364 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_ITALIC);
2365 simulations = IDWriteFont_GetSimulations(font);
2366 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "%d\n", simulations);
2367 IDWriteFont_Release(font);
2369 IDWriteFactory_Release(factory);
2372 static void test_GetInformationalStrings(void)
2374 IDWriteLocalizedStrings *strings, *strings2;
2375 IDWriteFontCollection *collection;
2376 IDWriteFontFamily *family;
2377 IDWriteFactory *factory;
2378 IDWriteFont *font;
2379 BOOL exists;
2380 HRESULT hr;
2382 factory = create_factory();
2384 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
2385 ok(hr == S_OK, "got 0x%08x\n", hr);
2387 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
2388 ok(hr == S_OK, "got 0x%08x\n", hr);
2390 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2391 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2392 ok(hr == S_OK, "got 0x%08x\n", hr);
2394 exists = TRUE;
2395 strings = (void*)0xdeadbeef;
2396 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1, &strings, &exists);
2397 ok(hr == S_OK, "got 0x%08x\n", hr);
2398 ok(exists == FALSE, "got %d\n", exists);
2399 ok(strings == NULL, "got %p\n", strings);
2401 exists = TRUE;
2402 strings = NULL;
2403 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_NONE, &strings, &exists);
2404 ok(hr == S_OK, "got 0x%08x\n", hr);
2405 ok(exists == FALSE, "got %d\n", exists);
2407 exists = FALSE;
2408 strings = NULL;
2409 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists);
2410 ok(hr == S_OK, "got 0x%08x\n", hr);
2411 ok(exists == TRUE, "got %d\n", exists);
2413 /* strings instance is not reused */
2414 strings2 = NULL;
2415 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings2, &exists);
2416 ok(hr == S_OK, "got 0x%08x\n", hr);
2417 ok(strings2 != strings, "got %p, %p\n", strings2, strings);
2419 IDWriteLocalizedStrings_Release(strings);
2420 IDWriteLocalizedStrings_Release(strings2);
2421 IDWriteFont_Release(font);
2422 IDWriteFontFamily_Release(family);
2423 IDWriteFontCollection_Release(collection);
2424 IDWriteFactory_Release(factory);
2427 static void test_GetGdiInterop(void)
2429 IDWriteGdiInterop *interop, *interop2;
2430 IDWriteFactory *factory, *factory2;
2431 IDWriteFont *font;
2432 LOGFONTW logfont;
2433 HRESULT hr;
2435 factory = create_factory();
2437 interop = NULL;
2438 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2439 ok(hr == S_OK, "got 0x%08x\n", hr);
2441 interop2 = NULL;
2442 hr = IDWriteFactory_GetGdiInterop(factory, &interop2);
2443 ok(hr == S_OK, "got 0x%08x\n", hr);
2444 ok(interop == interop2, "got %p, %p\n", interop, interop2);
2445 IDWriteGdiInterop_Release(interop2);
2447 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory2);
2448 ok(hr == S_OK, "got 0x%08x\n", hr);
2450 /* each factory gets its own interop */
2451 interop2 = NULL;
2452 hr = IDWriteFactory_GetGdiInterop(factory2, &interop2);
2453 ok(hr == S_OK, "got 0x%08x\n", hr);
2454 ok(interop != interop2, "got %p, %p\n", interop, interop2);
2456 /* release factory - interop still works */
2457 IDWriteFactory_Release(factory2);
2459 memset(&logfont, 0, sizeof(logfont));
2460 logfont.lfHeight = 12;
2461 logfont.lfWidth = 12;
2462 logfont.lfWeight = FW_NORMAL;
2463 logfont.lfItalic = 1;
2464 lstrcpyW(logfont.lfFaceName, tahomaW);
2466 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop2, &logfont, &font);
2467 ok(hr == S_OK, "got 0x%08x\n", hr);
2468 IDWriteFont_Release(font);
2470 IDWriteGdiInterop_Release(interop2);
2471 IDWriteGdiInterop_Release(interop);
2472 IDWriteFactory_Release(factory);
2475 static void test_CreateFontFaceFromHdc(void)
2477 IDWriteGdiInterop *interop;
2478 IDWriteFontFace *fontface;
2479 IDWriteFactory *factory;
2480 HFONT hfont, oldhfont;
2481 LOGFONTW logfont;
2482 HRESULT hr;
2483 HDC hdc;
2485 factory = create_factory();
2487 interop = NULL;
2488 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2489 ok(hr == S_OK, "got 0x%08x\n", hr);
2491 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, NULL, &fontface);
2492 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2494 memset(&logfont, 0, sizeof(logfont));
2495 logfont.lfHeight = 12;
2496 logfont.lfWidth = 12;
2497 logfont.lfWeight = FW_NORMAL;
2498 logfont.lfItalic = 1;
2499 lstrcpyW(logfont.lfFaceName, tahomaW);
2501 hfont = CreateFontIndirectW(&logfont);
2502 hdc = CreateCompatibleDC(0);
2503 oldhfont = SelectObject(hdc, hfont);
2505 fontface = NULL;
2506 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, hdc, &fontface);
2507 ok(hr == S_OK, "got 0x%08x\n", hr);
2508 IDWriteFontFace_Release(fontface);
2509 DeleteObject(SelectObject(hdc, oldhfont));
2510 DeleteDC(hdc);
2512 IDWriteGdiInterop_Release(interop);
2513 IDWriteFactory_Release(factory);
2516 static void test_GetSimulations(void)
2518 DWRITE_FONT_SIMULATIONS simulations;
2519 IDWriteGdiInterop *interop;
2520 IDWriteFontFace *fontface;
2521 IDWriteFactory *factory;
2522 IDWriteFont *font;
2523 LOGFONTW logfont;
2524 HRESULT hr;
2526 factory = create_factory();
2528 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2529 ok(hr == S_OK, "got 0x%08x\n", hr);
2531 memset(&logfont, 0, sizeof(logfont));
2532 logfont.lfHeight = 12;
2533 logfont.lfWidth = 12;
2534 logfont.lfWeight = FW_NORMAL;
2535 logfont.lfItalic = 1;
2536 lstrcpyW(logfont.lfFaceName, tahomaW);
2538 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2539 ok(hr == S_OK, "got 0x%08x\n", hr);
2541 simulations = IDWriteFont_GetSimulations(font);
2542 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "got %d\n", simulations);
2543 hr = IDWriteFont_CreateFontFace(font, &fontface);
2544 ok(hr == S_OK, "got 0x%08x\n", hr);
2545 simulations = IDWriteFontFace_GetSimulations(fontface);
2546 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "got %d\n", simulations);
2547 IDWriteFontFace_Release(fontface);
2548 IDWriteFont_Release(font);
2550 memset(&logfont, 0, sizeof(logfont));
2551 logfont.lfHeight = 12;
2552 logfont.lfWidth = 12;
2553 logfont.lfWeight = FW_NORMAL;
2554 logfont.lfItalic = 0;
2555 lstrcpyW(logfont.lfFaceName, tahomaW);
2557 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2558 ok(hr == S_OK, "got 0x%08x\n", hr);
2560 simulations = IDWriteFont_GetSimulations(font);
2561 ok(simulations == DWRITE_FONT_SIMULATIONS_NONE, "got %d\n", simulations);
2562 hr = IDWriteFont_CreateFontFace(font, &fontface);
2563 ok(hr == S_OK, "got 0x%08x\n", hr);
2564 simulations = IDWriteFontFace_GetSimulations(fontface);
2565 ok(simulations == DWRITE_FONT_SIMULATIONS_NONE, "got %d\n", simulations);
2566 IDWriteFontFace_Release(fontface);
2567 IDWriteFont_Release(font);
2569 IDWriteGdiInterop_Release(interop);
2570 IDWriteFactory_Release(factory);
2573 static void test_GetFaceNames(void)
2575 static const WCHAR obliqueW[] = {'O','b','l','i','q','u','e',0};
2576 static const WCHAR enus2W[] = {'e','n','-','U','s',0};
2577 static const WCHAR enusW[] = {'e','n','-','u','s',0};
2578 IDWriteLocalizedStrings *strings, *strings2;
2579 IDWriteGdiInterop *interop;
2580 IDWriteFactory *factory;
2581 UINT32 count, index;
2582 IDWriteFont *font;
2583 LOGFONTW logfont;
2584 WCHAR buffW[255];
2585 BOOL exists;
2586 HRESULT hr;
2588 factory = create_factory();
2590 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2591 ok(hr == S_OK, "got 0x%08x\n", hr);
2593 memset(&logfont, 0, sizeof(logfont));
2594 logfont.lfHeight = 12;
2595 logfont.lfWidth = 12;
2596 logfont.lfWeight = FW_NORMAL;
2597 logfont.lfItalic = 1;
2598 lstrcpyW(logfont.lfFaceName, tahomaW);
2600 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2601 ok(hr == S_OK, "got 0x%08x\n", hr);
2603 hr = IDWriteFont_GetFaceNames(font, &strings);
2604 ok(hr == S_OK, "got 0x%08x\n", hr);
2606 hr = IDWriteFont_GetFaceNames(font, &strings2);
2607 ok(hr == S_OK, "got 0x%08x\n", hr);
2608 ok(strings != strings2, "got %p, %p\n", strings2, strings);
2609 IDWriteLocalizedStrings_Release(strings2);
2611 count = IDWriteLocalizedStrings_GetCount(strings);
2612 ok(count == 1, "got %d\n", count);
2614 index = 1;
2615 exists = FALSE;
2616 hr = IDWriteLocalizedStrings_FindLocaleName(strings, enus2W, &index, &exists);
2617 ok(hr == S_OK, "got 0x%08x\n", hr);
2618 ok(index == 0 && exists, "got %d, %d\n", index, exists);
2620 count = 0;
2621 hr = IDWriteLocalizedStrings_GetLocaleNameLength(strings, 1, &count);
2622 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2623 ok(count == ~0, "got %d\n", count);
2625 /* for simulated faces names are also simulated */
2626 buffW[0] = 0;
2627 hr = IDWriteLocalizedStrings_GetLocaleName(strings, 0, buffW, sizeof(buffW)/sizeof(WCHAR));
2628 ok(hr == S_OK, "got 0x%08x\n", hr);
2629 ok(!lstrcmpW(buffW, enusW), "got %s\n", wine_dbgstr_w(buffW));
2631 buffW[0] = 0;
2632 hr = IDWriteLocalizedStrings_GetString(strings, 0, buffW, sizeof(buffW)/sizeof(WCHAR));
2633 ok(hr == S_OK, "got 0x%08x\n", hr);
2634 ok(!lstrcmpW(buffW, obliqueW), "got %s\n", wine_dbgstr_w(buffW));
2635 IDWriteLocalizedStrings_Release(strings);
2637 IDWriteFont_Release(font);
2638 IDWriteGdiInterop_Release(interop);
2639 IDWriteFactory_Release(factory);
2642 struct local_refkey
2644 FILETIME writetime;
2645 WCHAR name[1];
2648 static void test_TryGetFontTable(void)
2650 IDWriteLocalFontFileLoader *localloader;
2651 WIN32_FILE_ATTRIBUTE_DATA info;
2652 const struct local_refkey *key;
2653 IDWriteFontFileLoader *loader;
2654 const void *table, *table2;
2655 IDWriteFontFace *fontface;
2656 void *context, *context2;
2657 IDWriteFactory *factory;
2658 IDWriteFontFile *file;
2659 WCHAR buffW[MAX_PATH];
2660 BOOL exists, ret;
2661 UINT32 size, len;
2662 WCHAR *path;
2663 HRESULT hr;
2665 path = create_testfontfile(test_fontfile);
2667 factory = create_factory();
2669 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2670 ok(hr == S_OK, "got 0x%08x\n",hr);
2672 key = NULL;
2673 size = 0;
2674 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2675 ok(hr == S_OK, "got 0x%08x\n", hr);
2676 ok(size != 0, "got %u\n", size);
2678 ret = GetFileAttributesExW(path, GetFileExInfoStandard, &info);
2679 ok(ret, "got %d\n", ret);
2680 ok(!memcmp(&info.ftLastWriteTime, &key->writetime, sizeof(key->writetime)), "got wrong write time\n");
2682 hr = IDWriteFontFile_GetLoader(file, &loader);
2683 ok(hr == S_OK, "got 0x%08x\n", hr);
2684 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2685 IDWriteFontFileLoader_Release(loader);
2687 hr = IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader, key, size, &len);
2688 ok(hr == S_OK, "got 0x%08x\n", hr);
2689 ok(lstrlenW(key->name) == len, "path length %d\n", len);
2691 hr = IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader, key, size, buffW, sizeof(buffW)/sizeof(WCHAR));
2692 ok(hr == S_OK, "got 0x%08x\n", hr);
2693 ok(!lstrcmpW(buffW, key->name), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(key->name));
2694 IDWriteLocalFontFileLoader_Release(localloader);
2696 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, 0, &fontface);
2697 ok(hr == S_OK, "got 0x%08x\n",hr);
2699 exists = FALSE;
2700 context = (void*)0xdeadbeef;
2701 table = NULL;
2702 hr = IDWriteFontFace_TryGetFontTable(fontface, MS_CMAP_TAG, &table, &size, &context, &exists);
2703 ok(hr == S_OK, "got 0x%08x\n",hr);
2704 ok(exists == TRUE, "got %d\n", exists);
2705 ok(context == NULL && table != NULL, "cmap: context %p, table %p\n", context, table);
2707 exists = FALSE;
2708 context2 = (void*)0xdeadbeef;
2709 table2 = NULL;
2710 hr = IDWriteFontFace_TryGetFontTable(fontface, MS_CMAP_TAG, &table2, &size, &context2, &exists);
2711 ok(hr == S_OK, "got 0x%08x\n",hr);
2712 ok(exists == TRUE, "got %d\n", exists);
2713 ok(context2 == context && table2 == table, "cmap: context2 %p, table2 %p\n", context2, table2);
2715 IDWriteFontFace_ReleaseFontTable(fontface, context2);
2716 IDWriteFontFace_ReleaseFontTable(fontface, context);
2718 IDWriteFontFace_Release(fontface);
2719 IDWriteFontFile_Release(file);
2720 IDWriteFactory_Release(factory);
2721 DELETE_FONTFILE(path);
2724 static void test_ConvertFontToLOGFONT(void)
2726 IDWriteFactory *factory, *factory2;
2727 IDWriteFontCollection *collection;
2728 IDWriteGdiInterop *interop;
2729 IDWriteFontFamily *family;
2730 IDWriteFont *font;
2731 LOGFONTW logfont;
2732 BOOL system;
2733 HRESULT hr;
2735 factory = create_factory();
2736 factory2 = create_factory();
2738 interop = NULL;
2739 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2740 ok(hr == S_OK, "got 0x%08x\n", hr);
2742 hr = IDWriteFactory_GetSystemFontCollection(factory2, &collection, FALSE);
2743 ok(hr == S_OK, "got 0x%08x\n", hr);
2745 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
2746 ok(hr == S_OK, "got 0x%08x\n", hr);
2748 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2749 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2750 ok(hr == S_OK, "got 0x%08x\n", hr);
2752 if (0) { /* crashes on native */
2753 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, NULL, NULL);
2754 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, &logfont, NULL);
2755 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, font, NULL, &system);
2758 memset(&logfont, 0xcc, sizeof(logfont));
2759 system = TRUE;
2760 hr = IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, &logfont, &system);
2761 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2762 ok(!system, "got %d\n", system);
2763 ok(logfont.lfFaceName[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont.lfFaceName));
2765 system = FALSE;
2767 logfont.lfHeight = 10;
2768 logfont.lfWidth = 11;
2769 logfont.lfEscapement = 10;
2770 logfont.lfOrientation = 10;
2771 logfont.lfWeight = 0;
2772 logfont.lfItalic = 1;
2773 logfont.lfUnderline = 1;
2774 logfont.lfStrikeOut = 1;
2775 logfont.lfCharSet = 0;
2776 logfont.lfOutPrecision = 0;
2777 logfont.lfClipPrecision = 0;
2778 logfont.lfQuality = 0;
2779 logfont.lfPitchAndFamily = 0;
2780 logfont.lfFaceName[0] = 0;
2782 hr = IDWriteGdiInterop_ConvertFontToLOGFONT(interop, font, &logfont, &system);
2783 ok(hr == S_OK, "got 0x%08x\n", hr);
2784 ok(system, "got %d\n", system);
2786 ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight);
2787 ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth);
2788 ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement);
2789 ok(logfont.lfOrientation == 0, "got %d\n", logfont.lfOrientation);
2790 ok(logfont.lfWeight > 0, "got %d\n", logfont.lfWeight);
2791 ok(logfont.lfItalic == 0, "got %d\n", logfont.lfItalic);
2792 ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline);
2793 ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut);
2794 ok(logfont.lfCharSet == DEFAULT_CHARSET, "got %d\n", logfont.lfCharSet);
2795 ok(logfont.lfOutPrecision == OUT_OUTLINE_PRECIS, "got %d\n", logfont.lfOutPrecision);
2796 ok(logfont.lfClipPrecision == 0, "got %d\n", logfont.lfClipPrecision);
2797 ok(logfont.lfQuality == 0, "got %d\n", logfont.lfQuality);
2798 ok(logfont.lfPitchAndFamily == 0, "got %d\n", logfont.lfPitchAndFamily);
2799 ok(logfont.lfFaceName[0] != 0, "got face name %s\n", wine_dbgstr_w(logfont.lfFaceName));
2801 IDWriteFactory_Release(factory2);
2803 IDWriteFontCollection_Release(collection);
2804 IDWriteFontFamily_Release(family);
2805 IDWriteFont_Release(font);
2806 IDWriteGdiInterop_Release(interop);
2807 IDWriteFactory_Release(factory);
2810 static void test_CreateStreamFromKey(void)
2812 IDWriteLocalFontFileLoader *localloader;
2813 IDWriteFontFileStream *stream, *stream2;
2814 IDWriteFontFileLoader *loader;
2815 IDWriteFactory *factory;
2816 IDWriteFontFile *file;
2817 UINT64 writetime;
2818 WCHAR *path;
2819 void *key;
2820 UINT32 size;
2821 HRESULT hr;
2823 factory = create_factory();
2825 path = create_testfontfile(test_fontfile);
2827 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2828 ok(hr == S_OK, "got 0x%08x\n",hr);
2830 key = NULL;
2831 size = 0;
2832 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2833 ok(hr == S_OK, "got 0x%08x\n", hr);
2834 ok(size != 0, "got %u\n", size);
2836 hr = IDWriteFontFile_GetLoader(file, &loader);
2837 ok(hr == S_OK, "got 0x%08x\n", hr);
2838 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2839 IDWriteFontFileLoader_Release(loader);
2841 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2842 ok(hr == S_OK, "got 0x%08x\n", hr);
2843 EXPECT_REF(stream, 1);
2845 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream2);
2846 ok(hr == S_OK, "got 0x%08x\n", hr);
2847 ok(stream == stream2 || broken(stream != stream2) /* Win7 SP0 */, "got %p, %p\n", stream, stream2);
2848 if (stream == stream2)
2849 EXPECT_REF(stream, 2);
2850 IDWriteFontFileStream_Release(stream);
2851 IDWriteFontFileStream_Release(stream2);
2853 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2854 ok(hr == S_OK, "got 0x%08x\n", hr);
2855 EXPECT_REF(stream, 1);
2857 writetime = 0;
2858 hr = IDWriteFontFileStream_GetLastWriteTime(stream, &writetime);
2859 ok(hr == S_OK, "got 0x%08x\n", hr);
2860 ok(writetime != 0, "got %08x%08x\n", (UINT)(writetime >> 32), (UINT)writetime);
2862 IDWriteFontFileStream_Release(stream);
2864 IDWriteLocalFontFileLoader_Release(localloader);
2865 IDWriteFactory_Release(factory);
2866 DELETE_FONTFILE(path);
2869 static void test_ReadFileFragment(void)
2871 IDWriteLocalFontFileLoader *localloader;
2872 IDWriteFontFileStream *stream;
2873 IDWriteFontFileLoader *loader;
2874 IDWriteFactory *factory;
2875 IDWriteFontFile *file;
2876 const void *fragment, *fragment2;
2877 void *key, *context, *context2;
2878 UINT64 filesize;
2879 UINT32 size;
2880 WCHAR *path;
2881 HRESULT hr;
2883 factory = create_factory();
2885 path = create_testfontfile(test_fontfile);
2887 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2888 ok(hr == S_OK, "got 0x%08x\n",hr);
2890 key = NULL;
2891 size = 0;
2892 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2893 ok(hr == S_OK, "got 0x%08x\n", hr);
2894 ok(size != 0, "got %u\n", size);
2896 hr = IDWriteFontFile_GetLoader(file, &loader);
2897 ok(hr == S_OK, "got 0x%08x\n", hr);
2898 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2899 IDWriteFontFileLoader_Release(loader);
2901 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2902 ok(hr == S_OK, "got 0x%08x\n", hr);
2904 hr = IDWriteFontFileStream_GetFileSize(stream, &filesize);
2905 ok(hr == S_OK, "got 0x%08x\n", hr);
2907 /* reading past the end of the stream */
2908 fragment = (void*)0xdeadbeef;
2909 context = (void*)0xdeadbeef;
2910 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize+1, &context);
2911 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2912 ok(context == NULL, "got %p\n", context);
2913 ok(fragment == NULL, "got %p\n", fragment);
2915 fragment = (void*)0xdeadbeef;
2916 context = (void*)0xdeadbeef;
2917 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize, &context);
2918 ok(hr == S_OK, "got 0x%08x\n", hr);
2919 ok(context == NULL, "got %p\n", context);
2920 ok(fragment != NULL, "got %p\n", fragment);
2922 fragment2 = (void*)0xdeadbeef;
2923 context2 = (void*)0xdeadbeef;
2924 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment2, 0, filesize, &context2);
2925 ok(hr == S_OK, "got 0x%08x\n", hr);
2926 ok(context2 == NULL, "got %p\n", context2);
2927 ok(fragment == fragment2, "got %p, %p\n", fragment, fragment2);
2929 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
2930 IDWriteFontFileStream_ReleaseFileFragment(stream, context2);
2932 /* fragment is released, try again */
2933 fragment = (void*)0xdeadbeef;
2934 context = (void*)0xdeadbeef;
2935 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize, &context);
2936 ok(hr == S_OK, "got 0x%08x\n", hr);
2937 ok(context == NULL, "got %p\n", context);
2938 ok(fragment == fragment2, "got %p, %p\n", fragment, fragment2);
2939 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
2941 IDWriteFontFileStream_Release(stream);
2942 IDWriteLocalFontFileLoader_Release(localloader);
2943 IDWriteFactory_Release(factory);
2944 DELETE_FONTFILE(path);
2947 static void test_GetDesignGlyphMetrics(void)
2949 DWRITE_GLYPH_METRICS metrics[2];
2950 IDWriteFontFace *fontface;
2951 IDWriteFactory *factory;
2952 IDWriteFontFile *file;
2953 UINT16 indices[2];
2954 UINT32 codepoint;
2955 WCHAR *path;
2956 HRESULT hr;
2958 factory = create_factory();
2960 path = create_testfontfile(test_fontfile);
2962 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2963 ok(hr == S_OK, "got 0x%08x\n",hr);
2965 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file,
2966 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
2967 ok(hr == S_OK, "got 0x%08x\n",hr);
2968 IDWriteFontFile_Release(file);
2970 codepoint = 'A';
2971 indices[0] = 0;
2972 hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &indices[0]);
2973 ok(hr == S_OK, "got 0x%08x\n", hr);
2974 ok(indices[0] > 0, "got %u\n", indices[0]);
2976 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, NULL, 0, metrics, FALSE);
2977 ok(hr == E_INVALIDARG, "got 0x%08x\n",hr);
2979 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, NULL, 1, metrics, FALSE);
2980 ok(hr == E_INVALIDARG, "got 0x%08x\n",hr);
2982 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, indices, 0, metrics, FALSE);
2983 ok(hr == S_OK, "got 0x%08x\n",hr);
2985 /* missing glyphs are ignored */
2986 indices[1] = 1;
2987 memset(metrics, 0xcc, sizeof(metrics));
2988 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, indices, 2, metrics, FALSE);
2989 ok(hr == S_OK, "got 0x%08x\n",hr);
2990 ok(metrics[0].advanceWidth == 1000, "got %d\n", metrics[0].advanceWidth);
2991 ok(metrics[1].advanceWidth == 0, "got %d\n", metrics[1].advanceWidth);
2993 IDWriteFontFace_Release(fontface);
2994 IDWriteFactory_Release(factory);
2995 DELETE_FONTFILE(path);
2998 static void test_IsMonospacedFont(void)
3000 static const WCHAR courierW[] = {'C','o','u','r','i','e','r',' ','N','e','w',0};
3001 IDWriteFontCollection *collection;
3002 IDWriteFactory *factory;
3003 UINT32 index;
3004 BOOL exists;
3005 HRESULT hr;
3007 factory = create_factory();
3008 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
3009 ok(hr == S_OK, "got 0x%08x\n", hr);
3011 exists = FALSE;
3012 hr = IDWriteFontCollection_FindFamilyName(collection, courierW, &index, &exists);
3013 ok(hr == S_OK, "got 0x%08x\n", hr);
3014 if (exists) {
3015 IDWriteFontFamily *family;
3016 IDWriteFont1 *font1;
3017 IDWriteFont *font;
3019 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
3020 ok(hr == S_OK, "got 0x%08x\n", hr);
3022 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
3023 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
3024 ok(hr == S_OK, "got 0x%08x\n", hr);
3025 IDWriteFontFamily_Release(family);
3027 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
3028 if (hr == S_OK) {
3029 IDWriteFontFace1 *fontface1;
3030 IDWriteFontFace *fontface;
3031 BOOL is_monospaced;
3033 is_monospaced = IDWriteFont1_IsMonospacedFont(font1);
3034 ok(is_monospaced, "got %d\n", is_monospaced);
3036 hr = IDWriteFont1_CreateFontFace(font1, &fontface);
3037 ok(hr == S_OK, "got 0x%08x\n", hr);
3038 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3039 ok(hr == S_OK, "got 0x%08x\n", hr);
3040 is_monospaced = IDWriteFontFace1_IsMonospacedFont(fontface1);
3041 ok(is_monospaced, "got %d\n", is_monospaced);
3042 IDWriteFontFace1_Release(fontface1);
3044 IDWriteFontFace_Release(fontface);
3045 IDWriteFont1_Release(font1);
3047 else
3048 win_skip("IsMonospacedFont() is not supported.\n");
3050 else
3051 skip("Courier New font not found.\n");
3053 IDWriteFontCollection_Release(collection);
3056 static void test_GetDesignGlyphAdvances(void)
3058 IDWriteFontFace1 *fontface1;
3059 IDWriteFontFace *fontface;
3060 IDWriteFactory *factory;
3061 IDWriteFontFile *file;
3062 WCHAR *path;
3063 HRESULT hr;
3065 factory = create_factory();
3067 path = create_testfontfile(test_fontfile);
3069 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3070 ok(hr == S_OK, "got 0x%08x\n", hr);
3072 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file,
3073 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
3074 ok(hr == S_OK, "got 0x%08x\n", hr);
3075 IDWriteFontFile_Release(file);
3077 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3078 if (hr == S_OK) {
3079 UINT32 codepoint;
3080 UINT16 index;
3081 INT32 advance;
3083 codepoint = 'A';
3084 index = 0;
3085 hr = IDWriteFontFace1_GetGlyphIndices(fontface1, &codepoint, 1, &index);
3086 ok(hr == S_OK, "got 0x%08x\n", hr);
3087 ok(index > 0, "got %u\n", index);
3089 advance = 0;
3090 hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, &index, &advance, FALSE);
3091 ok(hr == S_OK, "got 0x%08x\n", hr);
3092 ok(advance == 1000, "got %i\n", advance);
3094 advance = 0;
3095 hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, &index, &advance, TRUE);
3096 ok(hr == S_OK, "got 0x%08x\n", hr);
3097 todo_wine
3098 ok(advance == 2048, "got %i\n", advance);
3100 IDWriteFontFace1_Release(fontface1);
3102 else
3103 win_skip("GetDesignGlyphAdvances() is not supported.\n");
3105 IDWriteFontFace_Release(fontface);
3106 IDWriteFactory_Release(factory);
3107 DELETE_FONTFILE(path);
3110 static void test_GetGlyphRunOutline(void)
3112 DWRITE_GLYPH_OFFSET offsets[2];
3113 IDWriteFactory *factory;
3114 IDWriteFontFile *file;
3115 IDWriteFontFace *face;
3116 UINT32 codepoint;
3117 FLOAT advances[2];
3118 UINT16 glyphs[2];
3119 WCHAR *path;
3120 HRESULT hr;
3122 path = create_testfontfile(test_fontfile);
3123 factory = create_factory();
3125 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3126 ok(hr == S_OK, "got 0x%08x\n",hr);
3128 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face);
3129 ok(hr == S_OK, "got 0x%08x\n", hr);
3130 IDWriteFontFile_Release(file);
3132 codepoint = 'A';
3133 glyphs[0] = 0;
3134 hr = IDWriteFontFace_GetGlyphIndices(face, &codepoint, 1, glyphs);
3135 ok(hr == S_OK, "got 0x%08x\n", hr);
3136 ok(glyphs[0] > 0, "got %u\n", glyphs[0]);
3137 glyphs[1] = glyphs[0];
3139 hr = IDWriteFontFace_GetGlyphRunOutline(face, 2048.0, glyphs, advances, offsets, 1, FALSE, FALSE, NULL);
3140 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3142 hr = IDWriteFontFace_GetGlyphRunOutline(face, 2048.0, NULL, NULL, offsets, 1, FALSE, FALSE, &test_geomsink);
3143 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3145 advances[0] = 1.0;
3146 advances[1] = 0.0;
3148 offsets[0].advanceOffset = 1.0;
3149 offsets[0].ascenderOffset = 1.0;
3150 offsets[1].advanceOffset = 0.0;
3151 offsets[1].ascenderOffset = 0.0;
3153 /* default advances, no offsets */
3154 memset(g_startpoints, 0, sizeof(g_startpoints));
3155 g_startpoint_count = 0;
3156 SET_EXPECT(setfillmode);
3157 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 2, FALSE, FALSE, &test_geomsink);
3158 ok(hr == S_OK, "got 0x%08x\n", hr);
3159 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3160 if (g_startpoint_count == 2) {
3161 /* glyph advance of 500 is applied */
3162 ok(g_startpoints[0].x == 229.5 && g_startpoints[0].y == -629.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
3163 ok(g_startpoints[1].x == 729.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
3165 CHECK_CALLED(setfillmode);
3167 /* default advances, no offsets, RTL */
3168 memset(g_startpoints, 0, sizeof(g_startpoints));
3169 g_startpoint_count = 0;
3170 SET_EXPECT(setfillmode);
3171 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 2, FALSE, TRUE, &test_geomsink);
3172 ok(hr == S_OK, "got 0x%08x\n", hr);
3173 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3174 if (g_startpoint_count == 2) {
3175 /* advance is -500 now */
3176 ok(g_startpoints[0].x == -270.5 && g_startpoints[0].y == -629.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
3177 ok(g_startpoints[1].x == -770.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
3179 CHECK_CALLED(setfillmode);
3181 /* default advances, additional offsets */
3182 memset(g_startpoints, 0, sizeof(g_startpoints));
3183 g_startpoint_count = 0;
3184 SET_EXPECT(setfillmode);
3185 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, offsets, 2, FALSE, FALSE, &test_geomsink);
3186 ok(hr == S_OK, "got 0x%08x\n", hr);
3187 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3188 if (g_startpoint_count == 2) {
3189 /* offsets applied to first contour */
3190 ok(g_startpoints[0].x == 230.5 && g_startpoints[0].y == -630.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
3191 ok(g_startpoints[1].x == 729.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
3193 CHECK_CALLED(setfillmode);
3195 /* default advances, additional offsets, RTL */
3196 memset(g_startpoints, 0, sizeof(g_startpoints));
3197 g_startpoint_count = 0;
3198 SET_EXPECT(setfillmode);
3199 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, offsets, 2, FALSE, TRUE, &test_geomsink);
3200 ok(hr == S_OK, "got 0x%08x\n", hr);
3201 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3202 if (g_startpoint_count == 2) {
3203 ok(g_startpoints[0].x == -271.5 && g_startpoints[0].y == -630.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
3204 ok(g_startpoints[1].x == -770.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
3206 CHECK_CALLED(setfillmode);
3208 /* custom advances and offsets, offset turns total advance value to zero */
3209 memset(g_startpoints, 0, sizeof(g_startpoints));
3210 g_startpoint_count = 0;
3211 SET_EXPECT(setfillmode);
3212 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, advances, offsets, 2, FALSE, FALSE, &test_geomsink);
3213 ok(hr == S_OK, "got 0x%08x\n", hr);
3214 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3215 if (g_startpoint_count == 2) {
3216 ok(g_startpoints[0].x == 230.5 && g_startpoints[0].y == -630.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
3217 ok(g_startpoints[1].x == 230.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
3219 CHECK_CALLED(setfillmode);
3221 /* 0 glyph count */
3222 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 0, FALSE, FALSE, &test_geomsink2);
3223 ok(hr == S_OK, "got 0x%08x\n", hr);
3225 IDWriteFactory_Release(factory);
3226 IDWriteFontFace_Release(face);
3227 DELETE_FONTFILE(path);
3229 /* space glyph */
3230 factory = create_factory();
3231 face = create_fontface(factory);
3233 codepoint = ' ';
3234 glyphs[0] = 0;
3235 hr = IDWriteFontFace_GetGlyphIndices(face, &codepoint, 1, glyphs);
3236 ok(hr == S_OK, "got 0x%08x\n", hr);
3237 ok(glyphs[0] > 0, "got %u\n", glyphs[0]);
3239 SET_EXPECT(setfillmode);
3240 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 1, FALSE, FALSE, &test_geomsink2);
3241 ok(hr == S_OK, "got 0x%08x\n", hr);
3242 CHECK_CALLED(setfillmode);
3244 IDWriteFactory_Release(factory);
3245 IDWriteFontFace_Release(face);
3248 static void test_GetEudcFontCollection(void)
3250 IDWriteFontCollection *coll, *coll2;
3251 IDWriteFactory1 *factory1;
3252 IDWriteFactory *factory;
3253 HRESULT hr;
3255 factory = create_factory();
3257 hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory1, (void**)&factory1);
3258 IDWriteFactory_Release(factory);
3259 if (hr != S_OK) {
3260 win_skip("GetEudcFontCollection() is not supported.\n");
3261 return;
3264 hr = IDWriteFactory1_GetEudcFontCollection(factory1, &coll, FALSE);
3265 ok(hr == S_OK, "got 0x%08x\n", hr);
3266 hr = IDWriteFactory1_GetEudcFontCollection(factory1, &coll2, FALSE);
3267 ok(hr == S_OK, "got 0x%08x\n", hr);
3268 ok(coll == coll2, "got %p, %p\n", coll, coll2);
3269 IDWriteFontCollection_Release(coll);
3270 IDWriteFontCollection_Release(coll2);
3272 IDWriteFactory1_Release(factory1);
3275 static void test_GetCaretMetrics(void)
3277 DWRITE_FONT_METRICS1 metrics;
3278 IDWriteFontFace1 *fontface1;
3279 DWRITE_CARET_METRICS caret;
3280 IDWriteFontFace *fontface;
3281 IDWriteFactory *factory;
3282 IDWriteFontFile *file;
3283 IDWriteFont *font;
3284 WCHAR *path;
3285 HRESULT hr;
3287 path = create_testfontfile(test_fontfile);
3288 factory = create_factory();
3290 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3291 ok(hr == S_OK, "got 0x%08x\n", hr);
3293 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
3294 ok(hr == S_OK, "got 0x%08x\n", hr);
3295 IDWriteFontFile_Release(file);
3297 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3298 IDWriteFontFace_Release(fontface);
3299 if (hr != S_OK) {
3300 win_skip("GetCaretMetrics() is not supported.\n");
3301 IDWriteFactory_Release(factory);
3302 DELETE_FONTFILE(path);
3303 return;
3306 memset(&caret, 0xcc, sizeof(caret));
3307 IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
3308 ok(caret.slopeRise == 1, "got %d\n", caret.slopeRise);
3309 ok(caret.slopeRun == 0, "got %d\n", caret.slopeRun);
3310 ok(caret.offset == 0, "got %d\n", caret.offset);
3311 IDWriteFontFace1_Release(fontface1);
3312 IDWriteFactory_Release(factory);
3314 /* now with Tahoma Normal */
3315 factory = create_factory();
3316 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
3317 hr = IDWriteFont_CreateFontFace(font, &fontface);
3318 ok(hr == S_OK, "got 0x%08x\n", hr);
3319 IDWriteFont_Release(font);
3320 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3321 ok(hr == S_OK, "got 0x%08x\n", hr);
3322 IDWriteFontFace_Release(fontface);
3324 memset(&caret, 0xcc, sizeof(caret));
3325 IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
3326 ok(caret.slopeRise == 1, "got %d\n", caret.slopeRise);
3327 ok(caret.slopeRun == 0, "got %d\n", caret.slopeRun);
3328 ok(caret.offset == 0, "got %d\n", caret.offset);
3329 IDWriteFontFace1_Release(fontface1);
3331 /* simulated italic */
3332 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_ITALIC);
3333 hr = IDWriteFont_CreateFontFace(font, &fontface);
3334 ok(hr == S_OK, "got 0x%08x\n", hr);
3335 IDWriteFont_Release(font);
3336 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3337 ok(hr == S_OK, "got 0x%08x\n", hr);
3338 IDWriteFontFace_Release(fontface);
3340 IDWriteFontFace1_GetMetrics(fontface1, &metrics);
3342 memset(&caret, 0xcc, sizeof(caret));
3343 IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
3344 ok(caret.slopeRise == metrics.designUnitsPerEm, "got %d\n", caret.slopeRise);
3345 ok(caret.slopeRun > 0, "got %d\n", caret.slopeRun);
3346 ok(caret.offset == 0, "got %d\n", caret.offset);
3347 IDWriteFontFace1_Release(fontface1);
3349 IDWriteFactory_Release(factory);
3350 DELETE_FONTFILE(path);
3353 static void test_GetGlyphCount(void)
3355 IDWriteFontFace *fontface;
3356 IDWriteFactory *factory;
3357 IDWriteFontFile *file;
3358 UINT16 count;
3359 WCHAR *path;
3360 HRESULT hr;
3362 path = create_testfontfile(test_fontfile);
3363 factory = create_factory();
3365 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3366 ok(hr == S_OK, "got 0x%08x\n", hr);
3368 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
3369 ok(hr == S_OK, "got 0x%08x\n", hr);
3370 IDWriteFontFile_Release(file);
3372 count = IDWriteFontFace_GetGlyphCount(fontface);
3373 ok(count == 7, "got %u\n", count);
3375 IDWriteFontFace_Release(fontface);
3376 IDWriteFactory_Release(factory);
3377 DELETE_FONTFILE(path);
3380 static void test_GetKerningPairAdjustments(void)
3382 IDWriteFontFace1 *fontface1;
3383 IDWriteFontFace *fontface;
3384 IDWriteFactory *factory;
3385 IDWriteFontFile *file;
3386 WCHAR *path;
3387 HRESULT hr;
3389 path = create_testfontfile(test_fontfile);
3390 factory = create_factory();
3392 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3393 ok(hr == S_OK, "got 0x%08x\n", hr);
3395 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
3396 ok(hr == S_OK, "got 0x%08x\n", hr);
3397 IDWriteFontFile_Release(file);
3399 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3400 if (hr == S_OK) {
3401 INT32 adjustments[1];
3403 hr = IDWriteFontFace1_GetKerningPairAdjustments(fontface1, 0, NULL, NULL);
3404 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* win8 */, "got 0x%08x\n", hr);
3406 if (0) /* crashes on native */
3407 hr = IDWriteFontFace1_GetKerningPairAdjustments(fontface1, 1, NULL, NULL);
3409 adjustments[0] = 1;
3410 hr = IDWriteFontFace1_GetKerningPairAdjustments(fontface1, 1, NULL, adjustments);
3411 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3412 ok(adjustments[0] == 0, "got %d\n", adjustments[0]);
3414 IDWriteFontFace1_Release(fontface1);
3416 else
3417 win_skip("GetKerningPairAdjustments() is not supported.\n");
3419 IDWriteFontFace_Release(fontface);
3420 IDWriteFactory_Release(factory);
3421 DELETE_FONTFILE(path);
3424 static void test_CreateRenderingParams(void)
3426 IDWriteRenderingParams2 *params2;
3427 IDWriteRenderingParams1 *params1;
3428 IDWriteRenderingParams *params;
3429 DWRITE_RENDERING_MODE mode;
3430 IDWriteFactory *factory;
3431 HRESULT hr;
3433 factory = create_factory();
3435 hr = IDWriteFactory_CreateCustomRenderingParams(factory, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT,
3436 DWRITE_RENDERING_MODE_DEFAULT, &params);
3437 ok(hr == S_OK, "got 0x%08x\n", hr);
3439 hr = IDWriteRenderingParams_QueryInterface(params, &IID_IDWriteRenderingParams1, (void**)&params1);
3440 if (hr == S_OK) {
3441 FLOAT enhcontrast;
3443 /* test what enhanced contrast setting set by default to */
3444 enhcontrast = IDWriteRenderingParams1_GetGrayscaleEnhancedContrast(params1);
3445 ok(enhcontrast == 1.0, "got %.2f\n", enhcontrast);
3446 IDWriteRenderingParams1_Release(params1);
3448 hr = IDWriteRenderingParams_QueryInterface(params, &IID_IDWriteRenderingParams2, (void**)&params2);
3449 if (hr == S_OK) {
3450 DWRITE_GRID_FIT_MODE gridfit;
3452 /* default gridfit mode */
3453 gridfit = IDWriteRenderingParams2_GetGridFitMode(params2);
3454 ok(gridfit == DWRITE_GRID_FIT_MODE_DEFAULT, "got %d\n", gridfit);
3456 IDWriteRenderingParams2_Release(params2);
3458 else
3459 win_skip("IDWriteRenderingParams2 not supported.\n");
3461 else
3462 win_skip("IDWriteRenderingParams1 not supported.\n");
3464 IDWriteRenderingParams_Release(params);
3466 hr = IDWriteFactory_CreateRenderingParams(factory, &params);
3467 ok(hr == S_OK, "got 0x%08x\n", hr);
3469 mode = IDWriteRenderingParams_GetRenderingMode(params);
3470 ok(mode == DWRITE_RENDERING_MODE_DEFAULT, "got %d\n", mode);
3471 IDWriteRenderingParams_Release(params);
3473 IDWriteFactory_Release(factory);
3476 static void test_CreateGlyphRunAnalysis(void)
3478 static const DWRITE_RENDERING_MODE rendermodes[] = {
3479 DWRITE_RENDERING_MODE_ALIASED,
3480 DWRITE_RENDERING_MODE_GDI_CLASSIC,
3481 DWRITE_RENDERING_MODE_GDI_NATURAL,
3482 DWRITE_RENDERING_MODE_NATURAL,
3483 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC,
3486 IDWriteGlyphRunAnalysis *analysis;
3487 IDWriteFactory *factory;
3488 DWRITE_GLYPH_RUN run;
3489 IDWriteFontFace *face;
3490 UINT16 glyph, glyphs[10];
3491 FLOAT advance;
3492 HRESULT hr;
3493 UINT32 ch;
3494 RECT rect, rect2;
3495 DWRITE_GLYPH_OFFSET offset;
3496 DWRITE_GLYPH_METRICS metrics;
3497 DWRITE_FONT_METRICS fm;
3498 int i;
3500 factory = create_factory();
3501 face = create_fontface(factory);
3503 ch = 'A';
3504 glyph = 0;
3505 hr = IDWriteFontFace_GetGlyphIndices(face, &ch, 1, &glyph);
3506 ok(hr == S_OK, "got 0x%08x\n", hr);
3507 ok(glyph > 0, "got %u\n", glyph);
3509 hr = IDWriteFontFace_GetDesignGlyphMetrics(face, &glyph, 1, &metrics, FALSE);
3510 ok(hr == S_OK, "got 0x%08x\n", hr);
3511 advance = metrics.advanceWidth;
3513 offset.advanceOffset = 0.0;
3514 offset.ascenderOffset = 0.0;
3516 run.fontFace = face;
3517 run.fontEmSize = 24.0;
3518 run.glyphCount = 1;
3519 run.glyphIndices = &glyph;
3520 run.glyphAdvances = &advance;
3521 run.glyphOffsets = &offset;
3522 run.isSideways = FALSE;
3523 run.bidiLevel = 0;
3525 /* default mode is not allowed */
3526 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3527 DWRITE_RENDERING_MODE_DEFAULT, DWRITE_MEASURING_MODE_NATURAL,
3528 0.0, 0.0, &analysis);
3529 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3531 /* outline too */
3532 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3533 DWRITE_RENDERING_MODE_OUTLINE, DWRITE_MEASURING_MODE_NATURAL,
3534 0.0, 0.0, &analysis);
3535 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3537 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3538 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
3539 0.0, 0.0, &analysis);
3540 ok(hr == S_OK, "got 0x%08x\n", hr);
3542 /* invalid texture type */
3543 memset(&rect, 0xcc, sizeof(rect));
3544 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1+1, &rect);
3545 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3546 ok(rect.left == 0 && rect.right == 0 &&
3547 rect.top == 0 && rect.bottom == 0, "unexpected rect\n");
3549 /* check how origin affects bounds */
3550 memset(&rect, 0, sizeof(rect));
3551 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3552 ok(hr == S_OK, "got 0x%08x\n", hr);
3553 ok(!IsRectEmpty(&rect), "got empty rect\n");
3554 IDWriteGlyphRunAnalysis_Release(analysis);
3556 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3557 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
3558 10.0, -5.0, &analysis);
3559 ok(hr == S_OK, "got 0x%08x\n", hr);
3561 memset(&rect2, 0, sizeof(rect2));
3562 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect2);
3563 ok(hr == S_OK, "got 0x%08x\n", hr);
3564 ok(!IsRectEmpty(&rect2), "got empty rect\n");
3565 IDWriteGlyphRunAnalysis_Release(analysis);
3567 ok(!EqualRect(&rect, &rect2), "got equal bounds\n");
3568 OffsetRect(&rect, 10, -5);
3569 ok(EqualRect(&rect, &rect2), "got different bounds\n");
3571 for (i = 0; i < sizeof(rendermodes)/sizeof(rendermodes[0]); i++) {
3572 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3573 rendermodes[i], DWRITE_MEASURING_MODE_NATURAL,
3574 0.0, 0.0, &analysis);
3575 ok(hr == S_OK, "got 0x%08x\n", hr);
3577 if (rendermodes[i] == DWRITE_RENDERING_MODE_ALIASED) {
3578 memset(&rect, 0, sizeof(rect));
3579 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3580 ok(hr == S_OK, "got 0x%08x\n", hr);
3581 ok(!IsRectEmpty(&rect), "got empty rect\n");
3583 rect.left = rect.top = 0;
3584 rect.bottom = rect.right = 1;
3585 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
3586 ok(hr == S_OK, "got 0x%08x\n", hr);
3587 ok(IsRectEmpty(&rect), "unexpected empty rect\n");
3589 else {
3590 rect.left = rect.top = 0;
3591 rect.bottom = rect.right = 1;
3592 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3593 ok(hr == S_OK, "got 0x%08x\n", hr);
3594 ok(IsRectEmpty(&rect), "got empty rect\n");
3596 memset(&rect, 0, sizeof(rect));
3597 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
3598 ok(hr == S_OK, "got 0x%08x\n", hr);
3599 ok(!IsRectEmpty(&rect), "got empty rect\n");
3602 IDWriteGlyphRunAnalysis_Release(analysis);
3605 IDWriteFontFace_GetMetrics(run.fontFace, &fm);
3607 /* check bbox for a single glyph run */
3608 for (run.fontEmSize = 1.0; run.fontEmSize <= 100.0; run.fontEmSize += 1.0) {
3609 DWRITE_GLYPH_METRICS gm;
3610 LONG bboxX, bboxY;
3612 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3613 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
3614 0.0, 0.0, &analysis);
3615 ok(hr == S_OK, "got 0x%08x\n", hr);
3617 memset(&rect, 0, sizeof(rect));
3618 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3619 ok(hr == S_OK, "got 0x%08x\n", hr);
3621 hr = IDWriteFontFace_GetGdiCompatibleGlyphMetrics(run.fontFace, run.fontEmSize, 1.0, NULL,
3622 DWRITE_MEASURING_MODE_GDI_CLASSIC, run.glyphIndices, 1, &gm, run.isSideways);
3623 ok(hr == S_OK, "got 0x%08x\n", hr);
3625 /* metrics are in design units */
3626 bboxX = (int)floorf((gm.advanceWidth - gm.leftSideBearing - gm.rightSideBearing) * run.fontEmSize / fm.designUnitsPerEm + 0.5f);
3627 bboxY = (int)floorf((gm.advanceHeight - gm.topSideBearing - gm.bottomSideBearing) * run.fontEmSize / fm.designUnitsPerEm + 0.5f);
3629 rect.right -= rect.left;
3630 rect.bottom -= rect.top;
3631 ok(abs(bboxX - rect.right) <= 2, "%.0f: bbox width %d, from metrics %d\n", run.fontEmSize, rect.right, bboxX);
3632 ok(abs(bboxY - rect.bottom) <= 2, "%.0f: bbox height %d, from metrics %d\n", run.fontEmSize, rect.bottom, bboxY);
3634 IDWriteGlyphRunAnalysis_Release(analysis);
3637 /* without offsets */
3638 run.fontFace = face;
3639 run.fontEmSize = 24.0;
3640 run.glyphCount = 1;
3641 run.glyphIndices = &glyph;
3642 run.glyphAdvances = &advance;
3643 run.glyphOffsets = NULL;
3644 run.isSideways = FALSE;
3645 run.bidiLevel = 0;
3647 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3648 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
3649 0.0, 0.0, &analysis);
3650 ok(hr == S_OK, "got 0x%08x\n", hr);
3652 SetRectEmpty(&rect);
3653 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3654 ok(hr == S_OK, "got 0x%08x\n", hr);
3655 ok(!IsRectEmpty(&rect), "got empty bounds\n");
3657 IDWriteGlyphRunAnalysis_Release(analysis);
3659 /* without explicit advances */
3660 run.fontFace = face;
3661 run.fontEmSize = 24.0;
3662 run.glyphCount = 1;
3663 run.glyphIndices = &glyph;
3664 run.glyphAdvances = NULL;
3665 run.glyphOffsets = NULL;
3666 run.isSideways = FALSE;
3667 run.bidiLevel = 0;
3669 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3670 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
3671 0.0, 0.0, &analysis);
3672 ok(hr == S_OK, "got 0x%08x\n", hr);
3674 SetRectEmpty(&rect);
3675 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3676 ok(hr == S_OK, "got 0x%08x\n", hr);
3677 ok(!IsRectEmpty(&rect), "got empty bounds\n");
3679 IDWriteGlyphRunAnalysis_Release(analysis);
3681 glyphs[0] = glyphs[1] = glyph;
3682 run.fontFace = face;
3683 run.fontEmSize = 24.0;
3684 run.glyphCount = 2;
3685 run.glyphIndices = glyphs;
3686 run.glyphAdvances = NULL;
3687 run.glyphOffsets = NULL;
3688 run.isSideways = FALSE;
3689 run.bidiLevel = 0;
3691 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3692 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
3693 0.0, 0.0, &analysis);
3694 ok(hr == S_OK, "got 0x%08x\n", hr);
3696 SetRectEmpty(&rect2);
3697 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect2);
3698 ok(hr == S_OK, "got 0x%08x\n", hr);
3699 ok(!IsRectEmpty(&rect2), "got empty bounds\n");
3700 ok(!EqualRect(&rect, &rect2), "got wrong rect2\n");
3702 IDWriteGlyphRunAnalysis_Release(analysis);
3704 IDWriteFontFace_Release(face);
3705 IDWriteFactory_Release(factory);
3708 #define round(x) ((int)floor((x) + 0.5))
3710 struct VDMX_Header
3712 WORD version;
3713 WORD numRecs;
3714 WORD numRatios;
3717 struct VDMX_Ratio
3719 BYTE bCharSet;
3720 BYTE xRatio;
3721 BYTE yStartRatio;
3722 BYTE yEndRatio;
3725 struct VDMX_group
3727 WORD recs;
3728 BYTE startsz;
3729 BYTE endsz;
3732 struct VDMX_vTable
3734 WORD yPelHeight;
3735 SHORT yMax;
3736 SHORT yMin;
3739 #ifdef WORDS_BIGENDIAN
3740 #define GET_BE_WORD(x) (x)
3741 #else
3742 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
3743 #endif
3745 static const struct VDMX_group *find_vdmx_group(const struct VDMX_Header *hdr)
3747 WORD num_ratios, i, group_offset = 0;
3748 struct VDMX_Ratio *ratios = (struct VDMX_Ratio*)(hdr + 1);
3749 BYTE dev_x_ratio = 1, dev_y_ratio = 1;
3751 num_ratios = GET_BE_WORD(hdr->numRatios);
3753 for (i = 0; i < num_ratios; i++)
3755 if (!ratios[i].bCharSet) continue;
3757 if ((ratios[i].xRatio == 0 && ratios[i].yStartRatio == 0 &&
3758 ratios[i].yEndRatio == 0) ||
3759 (ratios[i].xRatio == dev_x_ratio && ratios[i].yStartRatio <= dev_y_ratio &&
3760 ratios[i].yEndRatio >= dev_y_ratio))
3762 group_offset = GET_BE_WORD(*((WORD *)(ratios + num_ratios) + i));
3763 break;
3766 if (group_offset)
3767 return (const struct VDMX_group *)((BYTE *)hdr + group_offset);
3768 return NULL;
3771 static BOOL get_vdmx_size(const struct VDMX_group *group, int emsize, int *a, int *d)
3773 WORD recs, i;
3774 const struct VDMX_vTable *tables;
3776 if (!group) return FALSE;
3778 recs = GET_BE_WORD(group->recs);
3779 if (emsize < group->startsz || emsize >= group->endsz) return FALSE;
3781 tables = (const struct VDMX_vTable *)(group + 1);
3782 for (i = 0; i < recs; i++)
3784 WORD ppem = GET_BE_WORD(tables[i].yPelHeight);
3785 if (ppem > emsize)
3787 /* FIXME: Supposed to interpolate */
3788 trace("FIXME interpolate %d\n", emsize);
3789 return FALSE;
3792 if (ppem == emsize)
3794 *a = (SHORT)GET_BE_WORD(tables[i].yMax);
3795 *d = -(SHORT)GET_BE_WORD(tables[i].yMin);
3796 return TRUE;
3799 return FALSE;
3802 static void test_metrics_cmp(FLOAT emsize, const DWRITE_FONT_METRICS *metrics, const DWRITE_FONT_METRICS1 *expected)
3804 ok(metrics->designUnitsPerEm == expected->designUnitsPerEm, "%.2f: emsize: got %u expect %u\n",
3805 emsize, metrics->designUnitsPerEm, expected->designUnitsPerEm);
3806 ok(metrics->ascent == expected->ascent, "%.2f a: got %u expect %u\n",
3807 emsize, metrics->ascent, expected->ascent);
3808 ok(metrics->descent == expected->descent, "%.2f d: got %u expect %u\n",
3809 emsize, metrics->descent, expected->descent);
3810 ok(metrics->lineGap == expected->lineGap, "%.2f lg: got %d expect %d\n",
3811 emsize, metrics->lineGap, expected->lineGap);
3812 ok(metrics->capHeight == expected->capHeight, "%.2f capH: got %u expect %u\n",
3813 emsize, metrics->capHeight, expected->capHeight);
3814 ok(metrics->xHeight == expected->xHeight, "%.2f xH: got %u expect %u\n",
3815 emsize, metrics->xHeight, expected->xHeight);
3816 ok(metrics->underlinePosition == expected->underlinePosition, "%.2f ulP: got %d expect %d\n",
3817 emsize, metrics->underlinePosition, expected->underlinePosition);
3818 ok(metrics->underlineThickness == expected->underlineThickness, "%.2f ulTh: got %u expect %u\n",
3819 emsize, metrics->underlineThickness, expected->underlineThickness);
3820 ok(metrics->strikethroughPosition == expected->strikethroughPosition, "%.2f stP: got %d expect %d\n",
3821 emsize, metrics->strikethroughPosition, expected->strikethroughPosition);
3822 ok(metrics->strikethroughThickness == expected->strikethroughThickness, "%.2f stTh: got %u expect %u\n",
3823 emsize, metrics->strikethroughThickness, expected->strikethroughThickness);
3826 static void test_metrics1_cmp(FLOAT emsize, const DWRITE_FONT_METRICS1 *metrics, const DWRITE_FONT_METRICS1 *expected)
3828 ok(metrics->designUnitsPerEm == expected->designUnitsPerEm, "%.2f: emsize: got %u expect %u\n",
3829 emsize, metrics->designUnitsPerEm, expected->designUnitsPerEm);
3830 ok(metrics->ascent == expected->ascent, "%.2f a: got %u expect %u\n",
3831 emsize, metrics->ascent, expected->ascent);
3832 ok(metrics->descent == expected->descent, "%.2f d: got %u expect %u\n",
3833 emsize, metrics->descent, expected->descent);
3834 ok(metrics->lineGap == expected->lineGap, "%.2f lg: got %d expect %d\n",
3835 emsize, metrics->lineGap, expected->lineGap);
3836 ok(metrics->capHeight == expected->capHeight, "%.2f capH: got %u expect %u\n",
3837 emsize, metrics->capHeight, expected->capHeight);
3838 ok(metrics->xHeight == expected->xHeight, "%.2f xH: got %u expect %u\n",
3839 emsize, metrics->xHeight, expected->xHeight);
3840 ok(metrics->underlinePosition == expected->underlinePosition, "%.2f ulP: got %d expect %d\n",
3841 emsize, metrics->underlinePosition, expected->underlinePosition);
3842 ok(metrics->underlineThickness == expected->underlineThickness, "%.2f ulTh: got %u expect %u\n",
3843 emsize, metrics->underlineThickness, expected->underlineThickness);
3844 ok(metrics->strikethroughPosition == expected->strikethroughPosition, "%.2f stP: got %d expect %d\n",
3845 emsize, metrics->strikethroughPosition, expected->strikethroughPosition);
3846 ok(metrics->strikethroughThickness == expected->strikethroughThickness, "%.2f stTh: got %u expect %u\n",
3847 emsize, metrics->strikethroughThickness, expected->strikethroughThickness);
3848 ok(metrics->glyphBoxLeft == expected->glyphBoxLeft, "%.2f box left: got %d expect %d\n",
3849 emsize, metrics->glyphBoxLeft, expected->glyphBoxLeft);
3850 if (0) { /* this is not consistent */
3851 ok(metrics->glyphBoxTop == expected->glyphBoxTop, "%.2f box top: got %d expect %d\n",
3852 emsize, metrics->glyphBoxTop, expected->glyphBoxTop);
3853 ok(metrics->glyphBoxRight == expected->glyphBoxRight, "%.2f box right: got %d expect %d\n",
3854 emsize, metrics->glyphBoxRight, expected->glyphBoxRight);
3856 ok(metrics->glyphBoxBottom == expected->glyphBoxBottom, "%.2f box bottom: got %d expect %d\n",
3857 emsize, metrics->glyphBoxBottom, expected->glyphBoxBottom);
3858 ok(metrics->subscriptPositionX == expected->subscriptPositionX, "%.2f subX: got %d expect %d\n",
3859 emsize, metrics->subscriptPositionX, expected->subscriptPositionX);
3860 ok(metrics->subscriptPositionY == expected->subscriptPositionY, "%.2f subY: got %d expect %d\n",
3861 emsize, metrics->subscriptPositionY, expected->subscriptPositionY);
3862 ok(metrics->subscriptSizeX == expected->subscriptSizeX, "%.2f subsizeX: got %d expect %d\n",
3863 emsize, metrics->subscriptSizeX, expected->subscriptSizeX);
3864 ok(metrics->subscriptPositionY == expected->subscriptPositionY, "%.2f subsizeY: got %d expect %d\n",
3865 emsize, metrics->subscriptSizeY, expected->subscriptSizeY);
3866 ok(metrics->superscriptPositionX == expected->superscriptPositionX, "%.2f supX: got %d expect %d\n",
3867 emsize, metrics->superscriptPositionX, expected->superscriptPositionX);
3868 if (0)
3869 ok(metrics->superscriptPositionY == expected->superscriptPositionY, "%.2f supY: got %d expect %d\n",
3870 emsize, metrics->superscriptPositionY, expected->superscriptPositionY);
3871 ok(metrics->superscriptSizeX == expected->superscriptSizeX, "%.2f supsizeX: got %d expect %d\n",
3872 emsize, metrics->superscriptSizeX, expected->superscriptSizeX);
3873 ok(metrics->superscriptSizeY == expected->superscriptSizeY, "%.2f supsizeY: got %d expect %d\n",
3874 emsize, metrics->superscriptSizeY, expected->superscriptSizeY);
3875 ok(metrics->hasTypographicMetrics == expected->hasTypographicMetrics, "%.2f hastypo: got %d expect %d\n",
3876 emsize, metrics->hasTypographicMetrics, expected->hasTypographicMetrics);
3879 struct compatmetrics_test {
3880 DWRITE_MATRIX m;
3881 FLOAT ppdip;
3882 FLOAT emsize;
3885 static struct compatmetrics_test compatmetrics_tests[] = {
3886 { { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0, 5.0 },
3887 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 1.0, 5.0 },
3888 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 2.0, 5.0 },
3889 { { 0.0, 0.0, 0.0, 3.0, 0.0, 0.0 }, 2.0, 5.0 },
3890 { { 0.0, 0.0, 0.0, -3.0, 0.0, 0.0 }, 2.0, 5.0 },
3891 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 2.0, 5.0 },
3892 { { 1.0, 0.0, 0.0, 1.0, 5.0, 0.0 }, 2.0, 5.0 },
3893 { { 1.0, 0.0, 0.0, 1.0, 0.0, 5.0 }, 2.0, 5.0 },
3896 static void get_expected_metrics(IDWriteFontFace *fontface, struct compatmetrics_test *ptr,
3897 DWRITE_FONT_METRICS *expected)
3899 HRESULT hr;
3901 memset(expected, 0, sizeof(*expected));
3902 hr = IDWriteFontFace_GetGdiCompatibleMetrics(fontface, ptr->ppdip * fabsf(ptr->m.m22) * ptr->emsize, 1.0, NULL, expected);
3903 ok(hr == S_OK, "got %08x\n", hr);
3906 static void test_GetGdiCompatibleMetrics_face(IDWriteFontFace *face)
3908 IDWriteFontFace1 *fontface1 = NULL;
3909 HRESULT hr;
3910 DWRITE_FONT_METRICS design_metrics, comp_metrics;
3911 DWRITE_FONT_METRICS1 design_metrics1, expected;
3912 FLOAT emsize, scale;
3913 int ascent, descent;
3914 const struct VDMX_Header *vdmx;
3915 UINT32 vdmx_len;
3916 void *vdmx_ctx;
3917 BOOL exists;
3918 const struct VDMX_group *vdmx_group = NULL;
3919 int i;
3921 hr = IDWriteFontFace_QueryInterface(face, &IID_IDWriteFontFace1, (void**)&fontface1);
3922 if (hr != S_OK)
3923 win_skip("gdi compatible DWRITE_FONT_METRICS1 are not supported.\n");
3925 if (fontface1) {
3926 IDWriteFontFace1_GetMetrics(fontface1, &design_metrics1);
3927 memcpy(&design_metrics, &design_metrics1, sizeof(design_metrics));
3929 else
3930 IDWriteFontFace_GetMetrics(face, &design_metrics);
3932 hr = IDWriteFontFace_TryGetFontTable(face, MS_VDMX_TAG, (const void **)&vdmx,
3933 &vdmx_len, &vdmx_ctx, &exists);
3934 if (hr != S_OK || !exists)
3935 vdmx = NULL;
3936 else
3937 vdmx_group = find_vdmx_group(vdmx);
3939 /* negative emsize */
3940 memset(&comp_metrics, 0xcc, sizeof(comp_metrics));
3941 memset(&expected, 0, sizeof(expected));
3942 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, -10.0, 1.0, NULL, &comp_metrics);
3943 ok(hr == E_INVALIDARG, "got %08x\n", hr);
3944 test_metrics_cmp(0.0, &comp_metrics, &expected);
3946 /* zero emsize */
3947 memset(&comp_metrics, 0xcc, sizeof(comp_metrics));
3948 memset(&expected, 0, sizeof(expected));
3949 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, 0.0, 1.0, NULL, &comp_metrics);
3950 ok(hr == E_INVALIDARG, "got %08x\n", hr);
3951 test_metrics_cmp(0.0, &comp_metrics, &expected);
3953 /* zero pixels per dip */
3954 memset(&comp_metrics, 0xcc, sizeof(comp_metrics));
3955 memset(&expected, 0, sizeof(expected));
3956 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, 5.0, 0.0, NULL, &comp_metrics);
3957 ok(hr == E_INVALIDARG, "got %08x\n", hr);
3958 test_metrics_cmp(5.0, &comp_metrics, &expected);
3960 memset(&comp_metrics, 0xcc, sizeof(comp_metrics));
3961 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, 5.0, -1.0, NULL, &comp_metrics);
3962 ok(hr == E_INVALIDARG, "got %08x\n", hr);
3963 test_metrics_cmp(5.0, &comp_metrics, &expected);
3965 for (i = 0; i < sizeof(compatmetrics_tests)/sizeof(compatmetrics_tests[0]); i++) {
3966 struct compatmetrics_test *ptr = &compatmetrics_tests[i];
3968 get_expected_metrics(face, ptr, (DWRITE_FONT_METRICS*)&expected);
3969 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, ptr->emsize, ptr->ppdip, &ptr->m, &comp_metrics);
3970 ok(hr == S_OK, "got %08x\n", hr);
3971 test_metrics_cmp(ptr->emsize, &comp_metrics, &expected);
3974 for (emsize = 5; emsize <= design_metrics.designUnitsPerEm; emsize++)
3976 DWRITE_FONT_METRICS1 comp_metrics1, expected;
3978 if (fontface1) {
3979 hr = IDWriteFontFace1_GetGdiCompatibleMetrics(fontface1, emsize, 1.0, NULL, &comp_metrics1);
3980 ok(hr == S_OK, "got %08x\n", hr);
3982 else {
3983 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, emsize, 1.0, NULL, &comp_metrics);
3984 ok(hr == S_OK, "got %08x\n", hr);
3987 scale = emsize / design_metrics.designUnitsPerEm;
3988 if (!get_vdmx_size(vdmx_group, emsize, &ascent, &descent))
3990 ascent = round(design_metrics.ascent * scale);
3991 descent = round(design_metrics.descent * scale);
3994 expected.designUnitsPerEm = design_metrics.designUnitsPerEm;
3995 expected.ascent = round(ascent / scale );
3996 expected.descent = round(descent / scale );
3997 expected.lineGap = round(round(design_metrics.lineGap * scale) / scale);
3998 expected.capHeight = round(round(design_metrics.capHeight * scale) / scale);
3999 expected.xHeight = round(round(design_metrics.xHeight * scale) / scale);
4000 expected.underlinePosition = round(round(design_metrics.underlinePosition * scale) / scale);
4001 expected.underlineThickness = round(round(design_metrics.underlineThickness * scale) / scale);
4002 expected.strikethroughPosition = round(round(design_metrics.strikethroughPosition * scale) / scale);
4003 expected.strikethroughThickness = round(round(design_metrics.strikethroughThickness * scale) / scale);
4005 if (fontface1) {
4006 expected.glyphBoxLeft = round(round(design_metrics1.glyphBoxLeft * scale) / scale);
4008 if (0) { /* those two fail on Tahoma and Win7 */
4009 expected.glyphBoxTop = round(round(design_metrics1.glyphBoxTop * scale) / scale);
4010 expected.glyphBoxRight = round(round(design_metrics1.glyphBoxRight * scale) / scale);
4012 expected.glyphBoxBottom = round(round(design_metrics1.glyphBoxBottom * scale) / scale);
4013 expected.subscriptPositionX = round(round(design_metrics1.subscriptPositionX * scale) / scale);
4014 expected.subscriptPositionY = round(round(design_metrics1.subscriptPositionY * scale) / scale);
4015 expected.subscriptSizeX = round(round(design_metrics1.subscriptSizeX * scale) / scale);
4016 expected.subscriptSizeY = round(round(design_metrics1.subscriptSizeY * scale) / scale);
4017 expected.superscriptPositionX = round(round(design_metrics1.superscriptPositionX * scale) / scale);
4018 if (0) /* this fails for 3 emsizes, Tahoma from [5, 2048] range */
4019 expected.superscriptPositionY = round(round(design_metrics1.superscriptPositionY * scale) / scale);
4020 expected.superscriptSizeX = round(round(design_metrics1.superscriptSizeX * scale) / scale);
4021 expected.superscriptSizeY = round(round(design_metrics1.superscriptSizeY * scale) / scale);
4022 expected.hasTypographicMetrics = design_metrics1.hasTypographicMetrics;
4024 test_metrics1_cmp(emsize, &comp_metrics1, &expected);
4026 else
4027 test_metrics_cmp(emsize, &comp_metrics, &expected);
4031 if (fontface1)
4032 IDWriteFontFace1_Release(fontface1);
4033 if (vdmx) IDWriteFontFace_ReleaseFontTable(face, vdmx_ctx);
4036 static void test_GetGdiCompatibleMetrics(void)
4038 IDWriteFactory *factory;
4039 IDWriteFont *font;
4040 IDWriteFontFace *fontface;
4041 HRESULT hr;
4043 factory = create_factory();
4045 font = get_font(factory, tahomaW, DWRITE_FONT_STYLE_NORMAL);
4046 hr = IDWriteFont_CreateFontFace(font, &fontface);
4047 ok(hr == S_OK, "got 0x%08x\n", hr);
4048 IDWriteFont_Release(font);
4049 test_GetGdiCompatibleMetrics_face(fontface);
4050 IDWriteFontFace_Release(fontface);
4052 font = get_font(factory, arialW, DWRITE_FONT_STYLE_NORMAL);
4053 if (!font)
4054 skip("Skipping tests with Arial\n");
4055 else
4057 hr = IDWriteFont_CreateFontFace(font, &fontface);
4058 ok(hr == S_OK, "got 0x%08x\n", hr);
4059 IDWriteFont_Release(font);
4061 test_GetGdiCompatibleMetrics_face(fontface);
4062 IDWriteFontFace_Release(fontface);
4065 IDWriteFactory_Release(factory);
4068 static void test_GetPanose(void)
4070 IDWriteFactory *factory;
4071 IDWriteFont1 *font1;
4072 IDWriteFont *font;
4073 HRESULT hr;
4075 factory = create_factory();
4076 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
4078 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
4079 IDWriteFont_Release(font);
4080 if (hr == S_OK) {
4081 DWRITE_PANOSE panose;
4083 if (0) /* crashes on native */
4084 IDWriteFont1_GetPanose(font1, NULL);
4086 memset(&panose, 0, sizeof(panose));
4087 IDWriteFont1_GetPanose(font1, &panose);
4088 ok(panose.familyKind == DWRITE_PANOSE_FAMILY_TEXT_DISPLAY,
4089 "got %u\n", panose.familyKind);
4090 ok(panose.text.serifStyle == DWRITE_PANOSE_SERIF_STYLE_NORMAL_SANS,
4091 "got %u\n", panose.text.serifStyle);
4092 ok(panose.text.weight == DWRITE_PANOSE_WEIGHT_MEDIUM,
4093 "got %u\n", panose.text.weight);
4094 ok(panose.text.proportion == DWRITE_PANOSE_PROPORTION_EVEN_WIDTH,
4095 "got %u\n", panose.text.proportion);
4096 ok(panose.text.contrast == DWRITE_PANOSE_CONTRAST_VERY_LOW,
4097 "got %u\n", panose.text.contrast);
4098 ok(panose.text.strokeVariation == DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_VERTICAL,
4099 "got %u\n", panose.text.strokeVariation);
4100 ok(panose.text.armStyle == DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_VERTICAL,
4101 "got %u\n", panose.text.armStyle);
4102 ok(panose.text.letterform == DWRITE_PANOSE_LETTERFORM_NORMAL_BOXED,
4103 "got %u\n", panose.text.letterform);
4104 ok(panose.text.midline == DWRITE_PANOSE_MIDLINE_STANDARD_TRIMMED,
4105 "got %u\n", panose.text.midline);
4106 ok(panose.text.xHeight == DWRITE_PANOSE_XHEIGHT_CONSTANT_LARGE,
4107 "got %u\n", panose.text.xHeight);
4109 IDWriteFont1_Release(font1);
4111 else
4112 win_skip("GetPanose() is not supported.\n");
4114 IDWriteFactory_Release(factory);
4117 static INT32 get_gdi_font_advance(HDC hdc, FLOAT emsize)
4119 LOGFONTW logfont;
4120 HFONT hfont;
4121 BOOL ret;
4122 ABC abc;
4124 memset(&logfont, 0, sizeof(logfont));
4125 logfont.lfHeight = (LONG)-emsize;
4126 logfont.lfWeight = FW_NORMAL;
4127 logfont.lfQuality = CLEARTYPE_QUALITY;
4128 lstrcpyW(logfont.lfFaceName, tahomaW);
4130 hfont = CreateFontIndirectW(&logfont);
4131 SelectObject(hdc, hfont);
4133 ret = GetCharABCWidthsW(hdc, 'A', 'A', &abc);
4134 ok(ret, "got %d\n", ret);
4136 DeleteObject(hfont);
4138 return abc.abcA + abc.abcB + abc.abcC;
4141 static void test_GetGdiCompatibleGlyphAdvances(void)
4143 IDWriteFontFace1 *fontface1;
4144 IDWriteFontFace *fontface;
4145 IDWriteFactory *factory;
4146 IDWriteFont *font;
4147 HRESULT hr;
4148 HDC hdc;
4149 UINT32 codepoint;
4150 UINT16 glyph;
4151 FLOAT emsize;
4152 DWRITE_FONT_METRICS1 fm;
4153 INT32 advance;
4155 factory = create_factory();
4156 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
4158 hr = IDWriteFont_CreateFontFace(font, &fontface);
4159 ok(hr == S_OK, "got 0x%08x\n", hr);
4160 IDWriteFont_Release(font);
4162 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
4163 IDWriteFontFace_Release(fontface);
4165 if (hr != S_OK) {
4166 IDWriteFactory_Release(factory);
4167 win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
4168 return;
4171 codepoint = 'A';
4172 glyph = 0;
4173 hr = IDWriteFontFace1_GetGlyphIndices(fontface1, &codepoint, 1, &glyph);
4174 ok(hr == S_OK, "got 0x%08x\n", hr);
4175 ok(glyph > 0, "got %u\n", glyph);
4177 /* zero emsize */
4178 advance = 1;
4179 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 0.0,
4180 1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4181 ok(hr == S_OK, "got 0x%08x\n", hr);
4182 ok(advance == 0, "got %d\n", advance);
4184 /* negative emsize */
4185 advance = 1;
4186 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, -1.0,
4187 1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4188 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4189 ok(advance == 0, "got %d\n", advance);
4191 /* zero ppdip */
4192 advance = 1;
4193 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 1.0,
4194 0.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4195 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4196 ok(advance == 0, "got %d\n", advance);
4198 /* negative ppdip */
4199 advance = 1;
4200 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 1.0,
4201 -1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4202 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4203 ok(advance == 0, "got %d\n", advance);
4205 IDWriteFontFace1_GetMetrics(fontface1, &fm);
4207 hdc = CreateCompatibleDC(0);
4209 for (emsize = 1.0; emsize <= fm.designUnitsPerEm; emsize += 1.0) {
4210 INT32 gdi_advance;
4212 gdi_advance = get_gdi_font_advance(hdc, emsize);
4213 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, emsize,
4214 1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4215 ok(hr == S_OK, "got 0x%08x\n", hr);
4217 /* advance is in design units */
4218 advance = (int)floorf(emsize * advance / fm.designUnitsPerEm + 0.5f);
4219 ok((advance - gdi_advance) <= 2, "%.0f: got advance %d, expected %d\n", emsize, advance, gdi_advance);
4222 DeleteObject(hdc);
4224 IDWriteFactory_Release(factory);
4227 static WORD get_gasp_flags(IDWriteFontFace *fontface, FLOAT emsize)
4229 WORD num_recs, version;
4230 const WORD *ptr;
4231 WORD flags = 0;
4232 UINT32 size;
4233 BOOL exists;
4234 void *ctxt;
4235 HRESULT hr;
4237 exists = FALSE;
4238 hr = IDWriteFontFace_TryGetFontTable(fontface, MS_GASP_TAG,
4239 (const void**)&ptr, &size, &ctxt, &exists);
4240 ok(hr == S_OK, "got 0x%08x\n", hr);
4242 if (!exists)
4243 goto done;
4245 version = GET_BE_WORD( *ptr++ );
4246 num_recs = GET_BE_WORD( *ptr++ );
4247 if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD)) {
4248 ok(0, "unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs);
4249 goto done;
4252 while (num_recs--)
4254 flags = GET_BE_WORD( *(ptr + 1) );
4255 if (emsize <= GET_BE_WORD( *ptr )) break;
4256 ptr += 2;
4259 done:
4260 IDWriteFontFace_ReleaseFontTable(fontface, ctxt);
4261 return flags;
4264 #define GASP_GRIDFIT 0x0001
4265 #define GASP_DOGRAY 0x0002
4266 #define GASP_SYMMETRIC_GRIDFIT 0x0004
4267 #define GASP_SYMMETRIC_SMOOTHING 0x0008
4269 static BOOL g_is_vista;
4270 static DWRITE_RENDERING_MODE get_expected_rendering_mode(FLOAT emsize, WORD gasp, DWRITE_MEASURING_MODE mode,
4271 DWRITE_OUTLINE_THRESHOLD threshold)
4273 static const FLOAT aa_threshold = 100.0f;
4274 static const FLOAT a_threshold = 350.0f;
4275 static const FLOAT naturalemsize = 20.0f;
4276 FLOAT v;
4278 /* outline threshold */
4279 if (g_is_vista)
4280 v = mode == DWRITE_MEASURING_MODE_NATURAL ? aa_threshold : a_threshold;
4281 else
4282 v = threshold == DWRITE_OUTLINE_THRESHOLD_ANTIALIASED ? aa_threshold : a_threshold;
4284 if (emsize >= v)
4285 return DWRITE_RENDERING_MODE_OUTLINE;
4287 switch (mode)
4289 case DWRITE_MEASURING_MODE_NATURAL:
4290 if (!(gasp & GASP_SYMMETRIC_SMOOTHING) && (emsize <= naturalemsize))
4291 return DWRITE_RENDERING_MODE_NATURAL;
4292 else
4293 return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
4294 case DWRITE_MEASURING_MODE_GDI_CLASSIC:
4295 return DWRITE_RENDERING_MODE_GDI_CLASSIC;
4296 case DWRITE_MEASURING_MODE_GDI_NATURAL:
4297 return DWRITE_RENDERING_MODE_GDI_NATURAL;
4298 default:
4302 /* should be unreachable */
4303 return DWRITE_RENDERING_MODE_DEFAULT;
4306 static DWRITE_GRID_FIT_MODE get_expected_gridfit_mode(FLOAT emsize, WORD gasp, DWRITE_MEASURING_MODE mode,
4307 DWRITE_OUTLINE_THRESHOLD threshold)
4309 static const FLOAT aa_threshold = 100.0f;
4310 static const FLOAT a_threshold = 350.0f;
4311 FLOAT v;
4313 v = threshold == DWRITE_OUTLINE_THRESHOLD_ANTIALIASED ? aa_threshold : a_threshold;
4314 if (emsize >= v)
4315 return DWRITE_GRID_FIT_MODE_DISABLED;
4317 if (mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || mode == DWRITE_MEASURING_MODE_GDI_NATURAL)
4318 return DWRITE_GRID_FIT_MODE_ENABLED;
4320 return (gasp & (GASP_GRIDFIT|GASP_SYMMETRIC_GRIDFIT)) ? DWRITE_GRID_FIT_MODE_ENABLED : DWRITE_GRID_FIT_MODE_DISABLED;
4323 struct recommendedmode_test
4325 DWRITE_MEASURING_MODE measuring;
4326 DWRITE_OUTLINE_THRESHOLD threshold;
4329 static const struct recommendedmode_test recmode_tests[] = {
4330 { DWRITE_MEASURING_MODE_NATURAL, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4331 { DWRITE_MEASURING_MODE_GDI_CLASSIC, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4332 { DWRITE_MEASURING_MODE_GDI_NATURAL, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4335 static const struct recommendedmode_test recmode_tests1[] = {
4336 { DWRITE_MEASURING_MODE_NATURAL, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4337 { DWRITE_MEASURING_MODE_GDI_CLASSIC, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4338 { DWRITE_MEASURING_MODE_GDI_NATURAL, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4339 { DWRITE_MEASURING_MODE_NATURAL, DWRITE_OUTLINE_THRESHOLD_ALIASED },
4340 { DWRITE_MEASURING_MODE_GDI_CLASSIC, DWRITE_OUTLINE_THRESHOLD_ALIASED },
4341 { DWRITE_MEASURING_MODE_GDI_NATURAL, DWRITE_OUTLINE_THRESHOLD_ALIASED },
4344 static void test_GetRecommendedRenderingMode(void)
4346 IDWriteRenderingParams *params;
4347 IDWriteFontFace2 *fontface2;
4348 IDWriteFontFace1 *fontface1;
4349 IDWriteFontFace *fontface;
4350 DWRITE_RENDERING_MODE mode;
4351 IDWriteFactory *factory;
4352 FLOAT emsize;
4353 HRESULT hr;
4355 factory = create_factory();
4356 fontface = create_fontface(factory);
4358 fontface1 = NULL;
4359 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
4360 if (hr != S_OK)
4361 win_skip("IDWriteFontFace1::GetRecommendedRenderingMode() is not supported.\n");
4363 fontface2 = NULL;
4364 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace2, (void**)&fontface2);
4365 if (hr != S_OK)
4366 win_skip("IDWriteFontFace2::GetRecommendedRenderingMode() is not supported.\n");
4368 if (0) /* crashes on native */
4369 hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, 3.0, 1.0,
4370 DWRITE_MEASURING_MODE_GDI_CLASSIC, NULL, NULL);
4372 mode = 10;
4373 hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, 3.0, 1.0,
4374 DWRITE_MEASURING_MODE_GDI_CLASSIC, NULL, &mode);
4375 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4376 ok(mode == DWRITE_RENDERING_MODE_DEFAULT, "got %d\n", mode);
4378 hr = IDWriteFactory_CreateRenderingParams(factory, &params);
4379 ok(hr == S_OK, "got 0x%08x\n", hr);
4381 /* detect old dwrite version, that is using higher threshold value */
4382 g_is_vista = fontface1 == NULL;
4384 for (emsize = 1.0; emsize < 500.0; emsize += 1.0) {
4385 WORD gasp = get_gasp_flags(fontface, emsize);
4386 DWRITE_RENDERING_MODE expected;
4387 int i;
4389 for (i = 0; i < sizeof(recmode_tests)/sizeof(recmode_tests[0]); i++) {
4390 mode = 10;
4391 expected = get_expected_rendering_mode(emsize, gasp, recmode_tests[i].measuring, recmode_tests[i].threshold);
4392 hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, emsize, 1.0, recmode_tests[i].measuring, params, &mode);
4393 ok(hr == S_OK, "got 0x%08x\n", hr);
4394 ok(mode == expected, "%.2f/%d: got %d, flags 0x%04x, expected %d\n", emsize, i, mode, gasp, expected);
4397 /* IDWriteFontFace1 offers another variant of this method */
4398 if (fontface1) {
4399 for (i = 0; i < sizeof(recmode_tests1)/sizeof(recmode_tests1[0]); i++) {
4400 mode = 10;
4401 expected = get_expected_rendering_mode(emsize, gasp, recmode_tests1[i].measuring, recmode_tests1[i].threshold);
4402 hr = IDWriteFontFace1_GetRecommendedRenderingMode(fontface1, emsize, 96.0, 96.0,
4403 NULL, FALSE, recmode_tests1[i].threshold, recmode_tests1[i].measuring, &mode);
4404 ok(hr == S_OK, "got 0x%08x\n", hr);
4405 ok(mode == expected, "%.2f/%d: got %d, flags 0x%04x, expected %d\n", emsize, i, mode, gasp, expected);
4409 /* IDWriteFontFace2 - another one */
4410 if (fontface2) {
4411 DWRITE_GRID_FIT_MODE gridfit, expected_gridfit;
4413 for (i = 0; i < sizeof(recmode_tests1)/sizeof(recmode_tests1[0]); i++) {
4414 mode = 10;
4415 expected = get_expected_rendering_mode(emsize, gasp, recmode_tests1[0].measuring, recmode_tests1[0].threshold);
4416 expected_gridfit = get_expected_gridfit_mode(emsize, gasp, recmode_tests1[0].measuring, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED);
4417 hr = IDWriteFontFace2_GetRecommendedRenderingMode(fontface2, emsize, 96.0, 96.0,
4418 NULL, FALSE, recmode_tests1[0].threshold, recmode_tests1[0].measuring, params, &mode, &gridfit);
4419 ok(hr == S_OK, "got 0x%08x\n", hr);
4420 ok(mode == expected, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize, mode, gasp, expected);
4421 ok(gridfit == expected_gridfit, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize, i, gridfit,
4422 gasp, expected_gridfit);
4427 IDWriteRenderingParams_Release(params);
4429 /* test how parameters override returned modes */
4430 hr = IDWriteFactory_CreateCustomRenderingParams(factory, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT,
4431 DWRITE_RENDERING_MODE_GDI_CLASSIC, &params);
4432 ok(hr == S_OK, "got 0x%08x\n", hr);
4434 mode = 10;
4435 hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, 500.0, 1.0, DWRITE_MEASURING_MODE_NATURAL, params, &mode);
4436 ok(hr == S_OK, "got 0x%08x\n", hr);
4437 ok(mode == DWRITE_RENDERING_MODE_GDI_CLASSIC, "got %d\n", mode);
4439 IDWriteRenderingParams_Release(params);
4441 if (fontface2) {
4442 IDWriteRenderingParams2 *params2;
4443 IDWriteFactory2 *factory2;
4444 DWRITE_GRID_FIT_MODE gridfit;
4446 hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory2, (void**)&factory2);
4447 ok(hr == S_OK, "got 0x%08x\n", hr);
4449 hr = IDWriteFactory2_CreateCustomRenderingParams(factory2, 1.0, 0.0, 0.0, 0.5, DWRITE_PIXEL_GEOMETRY_FLAT,
4450 DWRITE_RENDERING_MODE_OUTLINE, DWRITE_GRID_FIT_MODE_ENABLED, &params2);
4451 ok(hr == S_OK, "got 0x%08x\n", hr);
4453 mode = 10;
4454 gridfit = 10;
4455 hr = IDWriteFontFace2_GetRecommendedRenderingMode(fontface2, 5.0, 96.0, 96.0,
4456 NULL, FALSE, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
4457 NULL, &mode, &gridfit);
4458 ok(hr == S_OK, "got 0x%08x\n", hr);
4459 ok(mode == DWRITE_RENDERING_MODE_GDI_CLASSIC, "got %d\n", mode);
4460 ok(gridfit == DWRITE_GRID_FIT_MODE_ENABLED, "got %d\n", gridfit);
4462 mode = 10;
4463 gridfit = 10;
4464 hr = IDWriteFontFace2_GetRecommendedRenderingMode(fontface2, 5.0, 96.0, 96.0,
4465 NULL, FALSE, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
4466 (IDWriteRenderingParams*)params2, &mode, &gridfit);
4467 ok(hr == S_OK, "got 0x%08x\n", hr);
4468 ok(mode == DWRITE_RENDERING_MODE_OUTLINE, "got %d\n", mode);
4469 ok(gridfit == DWRITE_GRID_FIT_MODE_ENABLED, "got %d\n", gridfit);
4471 IDWriteRenderingParams2_Release(params2);
4472 IDWriteFactory2_Release(factory2);
4475 if (fontface2)
4476 IDWriteFontFace2_Release(fontface2);
4477 if (fontface1)
4478 IDWriteFontFace1_Release(fontface1);
4479 IDWriteFontFace_Release(fontface);
4480 IDWriteFactory_Release(factory);
4483 static inline BOOL float_eq(FLOAT left, FLOAT right)
4485 int x = *(int *)&left;
4486 int y = *(int *)&right;
4488 if (x < 0)
4489 x = INT_MIN - x;
4490 if (y < 0)
4491 y = INT_MIN - y;
4493 return abs(x - y) <= 8;
4496 static void test_GetAlphaBlendParams(void)
4498 static const DWRITE_RENDERING_MODE rendermodes[] = {
4499 DWRITE_RENDERING_MODE_ALIASED,
4500 DWRITE_RENDERING_MODE_GDI_CLASSIC,
4501 DWRITE_RENDERING_MODE_GDI_NATURAL,
4502 DWRITE_RENDERING_MODE_NATURAL,
4503 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC,
4506 IDWriteGlyphRunAnalysis *analysis;
4507 FLOAT gamma, contrast, ctlevel;
4508 IDWriteRenderingParams *params;
4509 DWRITE_GLYPH_METRICS metrics;
4510 DWRITE_GLYPH_OFFSET offset;
4511 IDWriteFontFace *fontface;
4512 IDWriteFactory *factory;
4513 DWRITE_GLYPH_RUN run;
4514 FLOAT advance, expected_gdi_gamma;
4515 UINT value = 0;
4516 UINT16 glyph;
4517 UINT32 ch, i;
4518 HRESULT hr;
4519 BOOL ret;
4521 factory = create_factory();
4522 fontface = create_fontface(factory);
4524 ch = 'A';
4525 glyph = 0;
4526 hr = IDWriteFontFace_GetGlyphIndices(fontface, &ch, 1, &glyph);
4527 ok(hr == S_OK, "got 0x%08x\n", hr);
4528 ok(glyph > 0, "got %u\n", glyph);
4530 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, &glyph, 1, &metrics, FALSE);
4531 ok(hr == S_OK, "got 0x%08x\n", hr);
4532 advance = metrics.advanceWidth;
4534 offset.advanceOffset = 0.0;
4535 offset.ascenderOffset = 0.0;
4537 run.fontFace = fontface;
4538 run.fontEmSize = 24.0;
4539 run.glyphCount = 1;
4540 run.glyphIndices = &glyph;
4541 run.glyphAdvances = &advance;
4542 run.glyphOffsets = &offset;
4543 run.isSideways = FALSE;
4544 run.bidiLevel = 0;
4546 hr = IDWriteFactory_CreateCustomRenderingParams(factory, 0.9, 0.3, 0.1, DWRITE_PIXEL_GEOMETRY_RGB,
4547 DWRITE_RENDERING_MODE_DEFAULT, &params);
4548 ok(hr == S_OK, "got 0x%08x\n", hr);
4550 value = 0;
4551 ret = SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST, 0, &value, 0);
4552 ok(ret, "got %d\n", ret);
4553 expected_gdi_gamma = (FLOAT)(value / 1000.0);
4555 for (i = 0; i < sizeof(rendermodes)/sizeof(rendermodes[0]); i++) {
4556 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
4557 rendermodes[i], DWRITE_MEASURING_MODE_NATURAL,
4558 0.0, 0.0, &analysis);
4559 ok(hr == S_OK, "got 0x%08x\n", hr);
4561 gamma = contrast = ctlevel = -1.0;
4562 hr = IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis, NULL, &gamma, &contrast, &ctlevel);
4563 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4564 ok(gamma == -1.0, "got %.2f\n", gamma);
4565 ok(contrast == -1.0, "got %.2f\n", contrast);
4566 ok(ctlevel == -1.0, "got %.2f\n", ctlevel);
4568 gamma = contrast = ctlevel = -1.0;
4569 hr = IDWriteGlyphRunAnalysis_GetAlphaBlendParams(analysis, params, &gamma, &contrast, &ctlevel);
4570 ok(hr == S_OK, "got 0x%08x\n", hr);
4572 if (rendermodes[i] == DWRITE_RENDERING_MODE_GDI_CLASSIC || rendermodes[i] == DWRITE_RENDERING_MODE_GDI_NATURAL) {
4573 ok(float_eq(gamma, expected_gdi_gamma), "got %.2f, expected %.2f\n", gamma, expected_gdi_gamma);
4574 ok(contrast == 0.0f, "got %.2f\n", contrast);
4575 ok(ctlevel == 1.0f, "got %.2f\n", ctlevel);
4577 else {
4578 ok(gamma == 0.9f, "got %.2f\n", gamma);
4579 ok(contrast == 0.3f, "got %.2f\n", contrast);
4580 ok(ctlevel == 0.1f, "got %.2f\n", ctlevel);
4583 IDWriteGlyphRunAnalysis_Release(analysis);
4586 IDWriteRenderingParams_Release(params);
4587 IDWriteFontFace_Release(fontface);
4588 IDWriteFactory_Release(factory);
4591 static void test_CreateAlphaTexture(void)
4593 IDWriteGlyphRunAnalysis *analysis;
4594 DWRITE_GLYPH_METRICS metrics;
4595 DWRITE_GLYPH_OFFSET offset;
4596 IDWriteFontFace *fontface;
4597 IDWriteFactory *factory;
4598 DWRITE_GLYPH_RUN run;
4599 UINT32 ch, size;
4600 BYTE buff[1024];
4601 RECT bounds, r;
4602 FLOAT advance;
4603 UINT16 glyph;
4604 HRESULT hr;
4606 factory = create_factory();
4607 fontface = create_fontface(factory);
4609 ch = 'A';
4610 glyph = 0;
4611 hr = IDWriteFontFace_GetGlyphIndices(fontface, &ch, 1, &glyph);
4612 ok(hr == S_OK, "got 0x%08x\n", hr);
4613 ok(glyph > 0, "got %u\n", glyph);
4615 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, &glyph, 1, &metrics, FALSE);
4616 ok(hr == S_OK, "got 0x%08x\n", hr);
4617 advance = metrics.advanceWidth;
4619 offset.advanceOffset = 0.0;
4620 offset.ascenderOffset = 0.0;
4622 run.fontFace = fontface;
4623 run.fontEmSize = 24.0;
4624 run.glyphCount = 1;
4625 run.glyphIndices = &glyph;
4626 run.glyphAdvances = &advance;
4627 run.glyphOffsets = &offset;
4628 run.isSideways = FALSE;
4629 run.bidiLevel = 0;
4631 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
4632 DWRITE_RENDERING_MODE_NATURAL, DWRITE_MEASURING_MODE_NATURAL,
4633 0.0, 0.0, &analysis);
4634 ok(hr == S_OK, "got 0x%08x\n", hr);
4636 SetRectEmpty(&bounds);
4637 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds);
4638 ok(hr == S_OK, "got 0x%08x\n", hr);
4639 ok(!IsRectEmpty(&bounds), "got empty rect\n");
4640 size = (bounds.right - bounds.left)*(bounds.bottom - bounds.top)*3;
4641 ok(sizeof(buff) >= size, "required %u\n", size);
4643 /* invalid type value */
4644 memset(buff, 0xcf, sizeof(buff));
4645 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1+1, &bounds, buff, sizeof(buff));
4646 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4647 ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
4649 memset(buff, 0xcf, sizeof(buff));
4650 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &bounds, buff, 2);
4651 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
4652 ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
4654 /* vista version allows texture type mismatch, mark it broken for now */
4655 memset(buff, 0xcf, sizeof(buff));
4656 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &bounds, buff, sizeof(buff));
4657 ok(hr == DWRITE_E_UNSUPPORTEDOPERATION || broken(hr == S_OK), "got 0x%08x\n", hr);
4658 ok(buff[0] == 0xcf || broken(buff[0] == 0), "got %1x\n", buff[0]);
4660 memset(buff, 0xcf, sizeof(buff));
4661 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds, buff, size-1);
4662 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
4663 ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
4665 IDWriteGlyphRunAnalysis_Release(analysis);
4667 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
4668 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
4669 0.0, 0.0, &analysis);
4670 ok(hr == S_OK, "got 0x%08x\n", hr);
4672 SetRectEmpty(&bounds);
4673 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &bounds);
4674 ok(hr == S_OK, "got 0x%08x\n", hr);
4675 ok(!IsRectEmpty(&bounds), "got empty rect\n");
4676 size = (bounds.right - bounds.left)*(bounds.bottom - bounds.top);
4677 ok(sizeof(buff) >= size, "required %u\n", size);
4679 memset(buff, 0xcf, sizeof(buff));
4680 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, NULL, buff, sizeof(buff));
4681 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4682 ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
4684 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, NULL, NULL, sizeof(buff));
4685 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4687 memset(buff, 0xcf, sizeof(buff));
4688 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, NULL, buff, 0);
4689 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4690 ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
4692 /* buffer size is not enough */
4693 memset(buff, 0xcf, sizeof(buff));
4694 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &bounds, buff, size-1);
4695 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
4696 ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
4698 /* request texture for rectangle that doesn't intersect */
4699 memset(buff, 0xcf, sizeof(buff));
4700 r = bounds;
4701 OffsetRect(&r, (bounds.right - bounds.left)*2, 0);
4702 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &r, buff, sizeof(buff));
4703 ok(hr == S_OK, "got 0x%08x\n", hr);
4704 ok(buff[0] == 0, "got %1x\n", buff[0]);
4706 memset(buff, 0xcf, sizeof(buff));
4707 r = bounds;
4708 OffsetRect(&r, (bounds.right - bounds.left)*2, 0);
4709 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &r, buff, sizeof(buff));
4710 ok(hr == S_OK, "got 0x%08x\n", hr);
4711 ok(buff[0] == 0, "got %1x\n", buff[0]);
4713 /* request texture for rectangle that doesn't intersect, small buffer */
4714 memset(buff, 0xcf, sizeof(buff));
4715 r = bounds;
4716 OffsetRect(&r, (bounds.right - bounds.left)*2, 0);
4717 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_ALIASED_1x1, &r, buff, size-1);
4718 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
4719 ok(buff[0] == 0xcf, "got %1x\n", buff[0]);
4721 /* vista version allows texture type mismatch, mark it broken for now */
4722 memset(buff, 0xcf, sizeof(buff));
4723 hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds, buff, sizeof(buff));
4724 ok(hr == DWRITE_E_UNSUPPORTEDOPERATION || broken(hr == S_OK), "got 0x%08x\n", hr);
4725 ok(buff[0] == 0xcf || broken(buff[0] == 0), "got %1x\n", buff[0]);
4727 IDWriteGlyphRunAnalysis_Release(analysis);
4728 IDWriteFontFace_Release(fontface);
4729 IDWriteFactory_Release(factory);
4732 static void test_IsSymbolFont(void)
4734 static const WCHAR symbolW[] = {'S','y','m','b','o','l',0};
4735 IDWriteFontCollection *collection;
4736 IDWriteFontFace *fontface;
4737 IDWriteFactory *factory;
4738 IDWriteFont *font;
4739 HRESULT hr;
4740 BOOL ret;
4742 factory = create_factory();
4744 /* Tahoma */
4745 fontface = create_fontface(factory);
4746 ret = IDWriteFontFace_IsSymbolFont(fontface);
4747 ok(!ret, "got %d\n", ret);
4749 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
4750 ok(hr == S_OK, "got 0x%08x\n", hr);
4752 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font);
4753 ok(hr == S_OK, "got 0x%08x\n", hr);
4755 ret = IDWriteFont_IsSymbolFont(font);
4756 ok(!ret, "got %d\n", ret);
4758 IDWriteFontCollection_Release(collection);
4759 IDWriteFont_Release(font);
4760 IDWriteFontFace_Release(fontface);
4762 /* Symbol */
4763 font = get_font(factory, symbolW, DWRITE_FONT_STYLE_NORMAL);
4764 ret = IDWriteFont_IsSymbolFont(font);
4765 ok(ret, "got %d\n", ret);
4767 hr = IDWriteFont_CreateFontFace(font, &fontface);
4768 ok(hr == S_OK, "got 0x%08x\n", hr);
4769 ret = IDWriteFontFace_IsSymbolFont(fontface);
4770 ok(ret, "got %d\n", ret);
4771 IDWriteFont_Release(font);
4773 IDWriteFactory_Release(factory);
4776 struct CPAL_Header_0
4778 USHORT version;
4779 USHORT numPaletteEntries;
4780 USHORT numPalette;
4781 USHORT numColorRecords;
4782 ULONG offsetFirstColorRecord;
4783 USHORT colorRecordIndices[1];
4786 static void test_GetPaletteEntries(void)
4788 static const WCHAR emojiW[] = {'S','e','g','o','e',' ','U','I',' ','E','m','o','j','i',0};
4789 IDWriteFontFace2 *fontface2;
4790 IDWriteFontFace *fontface;
4791 IDWriteFactory *factory;
4792 IDWriteFont *font;
4793 DWRITE_COLOR_F color;
4794 UINT32 palettecount, entrycount, size, colorrecords;
4795 void *ctxt;
4796 const struct CPAL_Header_0 *cpal_header;
4797 HRESULT hr;
4798 BOOL exists;
4800 factory = create_factory();
4802 /* Tahoma, no color support */
4803 fontface = create_fontface(factory);
4804 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace2, (void**)&fontface2);
4805 IDWriteFontFace_Release(fontface);
4806 if (hr != S_OK) {
4807 IDWriteFactory_Release(factory);
4808 win_skip("GetPaletteEntries() is not supported.\n");
4809 return;
4812 hr = IDWriteFontFace2_GetPaletteEntries(fontface2, 0, 0, 1, &color);
4813 ok(hr == DWRITE_E_NOCOLOR, "got 0x%08x\n", hr);
4814 IDWriteFontFace2_Release(fontface2);
4816 /* Segoe UI Emoji, with color support */
4817 font = get_font(factory, emojiW, DWRITE_FONT_STYLE_NORMAL);
4818 if (!font) {
4819 IDWriteFactory_Release(factory);
4820 skip("Segoe UI Emoji font not found.\n");
4821 return;
4824 hr = IDWriteFont_CreateFontFace(font, &fontface);
4825 ok(hr == S_OK, "got 0x%08x\n", hr);
4826 IDWriteFont_Release(font);
4828 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace2, (void**)&fontface2);
4829 IDWriteFontFace_Release(fontface);
4831 palettecount = IDWriteFontFace2_GetColorPaletteCount(fontface2);
4832 ok(palettecount >= 1, "got %u\n", palettecount);
4834 entrycount = IDWriteFontFace2_GetPaletteEntryCount(fontface2);
4835 ok(entrycount >= 1, "got %u\n", entrycount);
4837 exists = FALSE;
4838 hr = IDWriteFontFace2_TryGetFontTable(fontface2, MS_CPAL_TAG, (const void**)&cpal_header, &size, &ctxt, &exists);
4839 ok(hr == S_OK, "got 0x%08x\n", hr);
4840 ok(exists, "got %d\n", exists);
4841 colorrecords = GET_BE_WORD(cpal_header->numColorRecords);
4842 ok(colorrecords >= 1, "got %u\n", colorrecords);
4844 /* invalid palette index */
4845 color.r = color.g = color.b = color.a = 123.0;
4846 hr = IDWriteFontFace2_GetPaletteEntries(fontface2, palettecount, 0, 1, &color);
4847 ok(hr == DWRITE_E_NOCOLOR, "got 0x%08x\n", hr);
4848 ok(color.r == 123.0 && color.g == 123.0 && color.b == 123.0 && color.a == 123.0,
4849 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color.r, color.g, color.b, color.a);
4851 /* invalid entry index */
4852 color.r = color.g = color.b = color.a = 123.0;
4853 hr = IDWriteFontFace2_GetPaletteEntries(fontface2, 0, entrycount, 1, &color);
4854 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4855 ok(color.r == 123.0 && color.g == 123.0 && color.b == 123.0 && color.a == 123.0,
4856 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color.r, color.g, color.b, color.a);
4858 color.r = color.g = color.b = color.a = 123.0;
4859 hr = IDWriteFontFace2_GetPaletteEntries(fontface2, 0, entrycount - 1, 1, &color);
4860 ok(hr == S_OK, "got 0x%08x\n", hr);
4861 ok(color.r != 123.0 && color.g != 123.0 && color.b != 123.0 && color.a != 123.0,
4862 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color.r, color.g, color.b, color.a);
4864 /* zero return length */
4865 color.r = color.g = color.b = color.a = 123.0;
4866 hr = IDWriteFontFace2_GetPaletteEntries(fontface2, 0, 0, 0, &color);
4867 ok(hr == S_OK, "got 0x%08x\n", hr);
4868 ok(color.r == 123.0 && color.g == 123.0 && color.b == 123.0 && color.a == 123.0,
4869 "got wrong color %.2fx%.2fx%.2fx%.2f\n", color.r, color.g, color.b, color.a);
4871 IDWriteFontFace2_Release(fontface2);
4872 IDWriteFactory_Release(factory);
4875 START_TEST(font)
4877 IDWriteFactory *factory;
4879 if (!(factory = create_factory())) {
4880 win_skip("failed to create factory\n");
4881 return;
4884 test_CreateFontFromLOGFONT();
4885 test_CreateBitmapRenderTarget();
4886 test_GetFontFamily();
4887 test_GetFamilyNames();
4888 test_CreateFontFace();
4889 test_GetMetrics();
4890 test_system_fontcollection();
4891 test_ConvertFontFaceToLOGFONT();
4892 test_CustomFontCollection();
4893 test_CreateCustomFontFileReference();
4894 test_CreateFontFileReference();
4895 test_shared_isolated();
4896 test_GetUnicodeRanges();
4897 test_GetFontFromFontFace();
4898 test_GetFirstMatchingFont();
4899 test_GetInformationalStrings();
4900 test_GetGdiInterop();
4901 test_CreateFontFaceFromHdc();
4902 test_GetSimulations();
4903 test_GetFaceNames();
4904 test_TryGetFontTable();
4905 test_ConvertFontToLOGFONT();
4906 test_CreateStreamFromKey();
4907 test_ReadFileFragment();
4908 test_GetDesignGlyphMetrics();
4909 test_GetDesignGlyphAdvances();
4910 test_IsMonospacedFont();
4911 test_GetGlyphRunOutline();
4912 test_GetEudcFontCollection();
4913 test_GetCaretMetrics();
4914 test_GetGlyphCount();
4915 test_GetKerningPairAdjustments();
4916 test_CreateRenderingParams();
4917 test_CreateGlyphRunAnalysis();
4918 test_GetGdiCompatibleMetrics();
4919 test_GetPanose();
4920 test_GetGdiCompatibleGlyphAdvances();
4921 test_GetRecommendedRenderingMode();
4922 test_GetAlphaBlendParams();
4923 test_CreateAlphaTexture();
4924 test_IsSymbolFont();
4925 test_GetPaletteEntries();
4927 IDWriteFactory_Release(factory);