dwrite: Implement GetRecommendedRenderingMode().
[wine.git] / dlls / dwrite / tests / font.c
blobbd001e72e80ef6c15a57bc620e9abcb6e605622d
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>
24 #define COBJMACROS
26 #include "windows.h"
27 #include "winternl.h"
28 #include "dwrite_2.h"
29 #include "initguid.h"
30 #include "d2d1.h"
32 #include "wine/test.h"
34 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
35 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
36 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
38 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
39 #define MS_VDMX_TAG MS_MAKE_TAG('V','D','M','X')
40 #define MS_GASP_TAG MS_MAKE_TAG('g','a','s','p')
42 #define EXPECT_HR(hr,hr_exp) \
43 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
45 #define DEFINE_EXPECT(func) \
46 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
48 #define SET_EXPECT(func) \
49 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
51 #define CHECK_EXPECT2(func) \
52 do { \
53 ok(expect_ ##func, "unexpected call " #func "\n"); \
54 called_ ## func = TRUE; \
55 }while(0)
57 #define CHECK_EXPECT(func) \
58 do { \
59 CHECK_EXPECT2(func); \
60 expect_ ## func = FALSE; \
61 }while(0)
63 #define CHECK_CALLED(func) \
64 do { \
65 ok(called_ ## func, "expected " #func "\n"); \
66 expect_ ## func = called_ ## func = FALSE; \
67 }while(0)
69 #define CLEAR_CALLED(func) \
70 expect_ ## func = called_ ## func = FALSE
72 DEFINE_EXPECT(setfillmode);
74 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
75 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
77 ULONG rc;
78 IUnknown_AddRef(obj);
79 rc = IUnknown_Release(obj);
80 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
83 static inline void *heap_alloc(size_t len)
85 return HeapAlloc(GetProcessHeap(), 0, len);
88 static inline BOOL heap_free(void *mem)
90 return HeapFree(GetProcessHeap(), 0, mem);
93 static const WCHAR test_fontfile[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
94 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
95 static const WCHAR arialW[] = {'A','r','i','a','l',0};
96 static const WCHAR tahomaUppercaseW[] = {'T','A','H','O','M','A',0};
97 static const WCHAR tahomaStrangecaseW[] = {'t','A','h','O','m','A',0};
98 static const WCHAR blahW[] = {'B','l','a','h','!',0};
100 static IDWriteFactory *create_factory(void)
102 IDWriteFactory *factory;
103 HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
104 ok(hr == S_OK, "got 0x%08x\n", hr);
105 return factory;
108 static IDWriteFontFace *create_fontface(IDWriteFactory *factory)
110 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
111 IDWriteGdiInterop *interop;
112 IDWriteFontFace *fontface;
113 IDWriteFont *font;
114 LOGFONTW logfont;
115 HRESULT hr;
117 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
118 ok(hr == S_OK, "got 0x%08x\n", hr);
120 memset(&logfont, 0, sizeof(logfont));
121 logfont.lfHeight = 12;
122 logfont.lfWidth = 12;
123 logfont.lfWeight = FW_NORMAL;
124 logfont.lfItalic = 1;
125 lstrcpyW(logfont.lfFaceName, tahomaW);
127 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
128 ok(hr == S_OK, "got 0x%08x\n", hr);
130 hr = IDWriteFont_CreateFontFace(font, &fontface);
131 ok(hr == S_OK, "got 0x%08x\n", hr);
133 IDWriteFont_Release(font);
134 IDWriteGdiInterop_Release(interop);
136 return fontface;
139 static WCHAR *create_testfontfile(const WCHAR *filename)
141 static WCHAR pathW[MAX_PATH];
142 DWORD written;
143 HANDLE file;
144 HRSRC res;
145 void *ptr;
147 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
148 lstrcatW(pathW, filename);
150 file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
151 ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW),
152 GetLastError());
154 res = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
155 ok( res != 0, "couldn't find resource\n" );
156 ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
157 WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
158 ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
159 CloseHandle( file );
161 return pathW;
164 #define DELETE_FONTFILE(filename) _delete_testfontfile(filename, __LINE__)
165 static void _delete_testfontfile(const WCHAR *filename, int line)
167 BOOL ret = DeleteFileW(filename);
168 ok_(__FILE__,line)(ret, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename), GetLastError());
171 struct test_fontenumerator
173 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface;
174 LONG ref;
176 DWORD index;
177 IDWriteFontFile *font_file;
180 static inline struct test_fontenumerator *impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator* iface)
182 return CONTAINING_RECORD(iface, struct test_fontenumerator, IDWriteFontFileEnumerator_iface);
185 static HRESULT WINAPI singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
187 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileEnumerator))
189 *obj = iface;
190 IDWriteFontFileEnumerator_AddRef(iface);
191 return S_OK;
193 return E_NOINTERFACE;
196 static ULONG WINAPI singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
198 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
199 return InterlockedIncrement(&This->ref);
202 static ULONG WINAPI singlefontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
204 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
205 ULONG ref = InterlockedDecrement(&This->ref);
206 if (!ref) {
207 IDWriteFontFile_Release(This->font_file);
208 heap_free(This);
210 return ref;
213 static HRESULT WINAPI singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **font_file)
215 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
216 IDWriteFontFile_AddRef(This->font_file);
217 *font_file = This->font_file;
218 return S_OK;
221 static HRESULT WINAPI singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
223 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
225 if (This->index > 1) {
226 *current = FALSE;
227 return S_OK;
230 This->index++;
231 *current = TRUE;
232 return S_OK;
235 static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl =
237 singlefontfileenumerator_QueryInterface,
238 singlefontfileenumerator_AddRef,
239 singlefontfileenumerator_Release,
240 singlefontfileenumerator_MoveNext,
241 singlefontfileenumerator_GetCurrentFontFile
244 static HRESULT create_enumerator(IDWriteFontFile *font_file, IDWriteFontFileEnumerator **ret)
246 struct test_fontenumerator *enumerator;
248 enumerator = heap_alloc(sizeof(struct test_fontenumerator));
249 if (!enumerator)
250 return E_OUTOFMEMORY;
252 enumerator->IDWriteFontFileEnumerator_iface.lpVtbl = &singlefontfileenumeratorvtbl;
253 enumerator->ref = 1;
254 enumerator->index = 0;
255 enumerator->font_file = font_file;
256 IDWriteFontFile_AddRef(font_file);
258 *ret = &enumerator->IDWriteFontFileEnumerator_iface;
259 return S_OK;
262 struct test_fontcollectionloader
264 IDWriteFontCollectionLoader IDWriteFontFileCollectionLoader_iface;
265 IDWriteFontFileLoader *loader;
268 static inline struct test_fontcollectionloader *impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader* iface)
270 return CONTAINING_RECORD(iface, struct test_fontcollectionloader, IDWriteFontFileCollectionLoader_iface);
273 static HRESULT WINAPI resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
275 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontCollectionLoader))
277 *obj = iface;
278 IDWriteFontCollectionLoader_AddRef(iface);
279 return S_OK;
281 return E_NOINTERFACE;
284 static ULONG WINAPI resourcecollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
286 return 2;
289 static ULONG WINAPI resourcecollectionloader_Release(IDWriteFontCollectionLoader *iface)
291 return 1;
294 static HRESULT WINAPI resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory,
295 const void * collectionKey, UINT32 collectionKeySize, IDWriteFontFileEnumerator ** fontFileEnumerator)
297 struct test_fontcollectionloader *This = impl_from_IDWriteFontFileCollectionLoader(iface);
298 IDWriteFontFile *font_file;
299 HRESULT hr;
301 IDWriteFactory_CreateCustomFontFileReference(factory, collectionKey, collectionKeySize, This->loader, &font_file);
303 hr = create_enumerator(font_file, fontFileEnumerator);
304 ok(hr == S_OK, "got 0x%08x\n", hr);
306 IDWriteFontFile_Release(font_file);
307 return hr;
310 static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl = {
311 resourcecollectionloader_QueryInterface,
312 resourcecollectionloader_AddRef,
313 resourcecollectionloader_Release,
314 resourcecollectionloader_CreateEnumeratorFromKey
317 /* Here is a functional custom font set of interfaces */
318 struct test_fontdatastream
320 IDWriteFontFileStream IDWriteFontFileStream_iface;
321 LONG ref;
323 LPVOID data;
324 DWORD size;
327 static inline struct test_fontdatastream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream* iface)
329 return CONTAINING_RECORD(iface, struct test_fontdatastream, IDWriteFontFileStream_iface);
332 static HRESULT WINAPI fontdatastream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
334 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
336 *obj = iface;
337 IDWriteFontFileStream_AddRef(iface);
338 return S_OK;
340 *obj = NULL;
341 return E_NOINTERFACE;
344 static ULONG WINAPI fontdatastream_AddRef(IDWriteFontFileStream *iface)
346 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
347 ULONG ref = InterlockedIncrement(&This->ref);
348 return ref;
351 static ULONG WINAPI fontdatastream_Release(IDWriteFontFileStream *iface)
353 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
354 ULONG ref = InterlockedDecrement(&This->ref);
355 if (ref == 0)
356 HeapFree(GetProcessHeap(), 0, This);
357 return ref;
360 static HRESULT WINAPI fontdatastream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
362 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
363 *fragment_context = NULL;
364 if (offset+fragment_size > This->size)
366 *fragment_start = NULL;
367 return E_FAIL;
369 else
371 *fragment_start = (BYTE*)This->data + offset;
372 return S_OK;
376 static void WINAPI fontdatastream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
378 /* Do Nothing */
381 static HRESULT WINAPI fontdatastream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
383 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
384 *size = This->size;
385 return S_OK;
388 static HRESULT WINAPI fontdatastream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
390 return E_NOTIMPL;
393 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl =
395 fontdatastream_QueryInterface,
396 fontdatastream_AddRef,
397 fontdatastream_Release,
398 fontdatastream_ReadFileFragment,
399 fontdatastream_ReleaseFileFragment,
400 fontdatastream_GetFileSize,
401 fontdatastream_GetLastWriteTime
404 static HRESULT create_fontdatastream(LPVOID data, UINT size, IDWriteFontFileStream** iface)
406 struct test_fontdatastream *This = HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream));
407 if (!This)
408 return E_OUTOFMEMORY;
410 This->data = data;
411 This->size = size;
412 This->ref = 1;
413 This->IDWriteFontFileStream_iface.lpVtbl = &fontdatastreamvtbl;
415 *iface = &This->IDWriteFontFileStream_iface;
416 return S_OK;
419 static HRESULT WINAPI resourcefontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
421 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
423 *obj = iface;
424 return S_OK;
426 *obj = NULL;
427 return E_NOINTERFACE;
430 static ULONG WINAPI resourcefontfileloader_AddRef(IDWriteFontFileLoader *iface)
432 return 2;
435 static ULONG WINAPI resourcefontfileloader_Release(IDWriteFontFileLoader *iface)
437 return 1;
440 static HRESULT WINAPI resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
442 LPVOID data;
443 DWORD size;
444 HGLOBAL mem;
446 mem = LoadResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
447 ok(mem != NULL, "Failed to lock font resource\n");
448 if (mem)
450 size = SizeofResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
451 data = LockResource(mem);
452 return create_fontdatastream(data, size, fontFileStream);
454 return E_FAIL;
457 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl = {
458 resourcefontfileloader_QueryInterface,
459 resourcefontfileloader_AddRef,
460 resourcefontfileloader_Release,
461 resourcefontfileloader_CreateStreamFromKey
464 static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
466 static D2D1_POINT_2F g_startpoints[2];
467 static int g_startpoint_count;
469 static HRESULT WINAPI test_geometrysink_QueryInterface(ID2D1SimplifiedGeometrySink *iface, REFIID riid, void **ret)
471 if (IsEqualIID(riid, &IID_ID2D1SimplifiedGeometrySink) ||
472 IsEqualIID(riid, &IID_IUnknown))
474 *ret = iface;
475 ID2D1SimplifiedGeometrySink_AddRef(iface);
476 return S_OK;
479 *ret = NULL;
480 return E_NOINTERFACE;
483 static ULONG WINAPI test_geometrysink_AddRef(ID2D1SimplifiedGeometrySink *iface)
485 return 2;
488 static ULONG WINAPI test_geometrysink_Release(ID2D1SimplifiedGeometrySink *iface)
490 return 1;
493 static void WINAPI test_geometrysink_SetFillMode(ID2D1SimplifiedGeometrySink *iface, D2D1_FILL_MODE mode)
495 CHECK_EXPECT(setfillmode);
496 ok(mode == D2D1_FILL_MODE_WINDING, "fill mode %d\n", mode);
499 static void WINAPI test_geometrysink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface, D2D1_PATH_SEGMENT flags)
501 ok(0, "unexpected SetSegmentFlags() - flags %d\n", flags);
504 static void WINAPI test_geometrysink_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
505 D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin)
507 ok(figureBegin == D2D1_FIGURE_BEGIN_FILLED, "begin figure %d\n", figureBegin);
508 if (g_startpoint_count < sizeof(g_startpoints)/sizeof(g_startpoints[0]))
509 g_startpoints[g_startpoint_count] = startPoint;
510 g_startpoint_count++;
513 static void WINAPI test_geometrysink_AddLines(ID2D1SimplifiedGeometrySink *iface,
514 const D2D1_POINT_2F *points, UINT32 count)
518 static void WINAPI test_geometrysink_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
519 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
523 static void WINAPI test_geometrysink_EndFigure(ID2D1SimplifiedGeometrySink *iface, D2D1_FIGURE_END figureEnd)
525 ok(figureEnd == D2D1_FIGURE_END_CLOSED, "end figure %d\n", figureEnd);
528 static HRESULT WINAPI test_geometrysink_Close(ID2D1SimplifiedGeometrySink *iface)
530 ok(0, "unexpected Close()\n");
531 return E_NOTIMPL;
534 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink_vtbl = {
535 test_geometrysink_QueryInterface,
536 test_geometrysink_AddRef,
537 test_geometrysink_Release,
538 test_geometrysink_SetFillMode,
539 test_geometrysink_SetSegmentFlags,
540 test_geometrysink_BeginFigure,
541 test_geometrysink_AddLines,
542 test_geometrysink_AddBeziers,
543 test_geometrysink_EndFigure,
544 test_geometrysink_Close
547 static void WINAPI test_geometrysink2_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
548 D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin)
550 ok(0, "unexpected call\n");
553 static void WINAPI test_geometrysink2_AddLines(ID2D1SimplifiedGeometrySink *iface,
554 const D2D1_POINT_2F *points, UINT32 count)
556 ok(0, "unexpected call\n");
559 static void WINAPI test_geometrysink2_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
560 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
562 ok(0, "unexpected call\n");
565 static void WINAPI test_geometrysink2_EndFigure(ID2D1SimplifiedGeometrySink *iface, D2D1_FIGURE_END figureEnd)
567 ok(0, "unexpected call\n");
570 static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink2_vtbl = {
571 test_geometrysink_QueryInterface,
572 test_geometrysink_AddRef,
573 test_geometrysink_Release,
574 test_geometrysink_SetFillMode,
575 test_geometrysink_SetSegmentFlags,
576 test_geometrysink2_BeginFigure,
577 test_geometrysink2_AddLines,
578 test_geometrysink2_AddBeziers,
579 test_geometrysink2_EndFigure,
580 test_geometrysink_Close
583 static ID2D1SimplifiedGeometrySink test_geomsink = { &test_geometrysink_vtbl };
584 static ID2D1SimplifiedGeometrySink test_geomsink2 = { &test_geometrysink2_vtbl };
586 static void test_CreateFontFromLOGFONT(void)
588 static const WCHAR tahomaspW[] = {'T','a','h','o','m','a',' ',0};
589 IDWriteGdiInterop *interop;
590 DWRITE_FONT_WEIGHT weight;
591 DWRITE_FONT_STYLE style;
592 IDWriteFont *font;
593 LOGFONTW logfont;
594 LONG weights[][2] = {
595 {FW_NORMAL, DWRITE_FONT_WEIGHT_NORMAL},
596 {FW_BOLD, DWRITE_FONT_WEIGHT_BOLD},
597 { 0, DWRITE_FONT_WEIGHT_NORMAL},
598 { 50, DWRITE_FONT_WEIGHT_NORMAL},
599 {150, DWRITE_FONT_WEIGHT_NORMAL},
600 {250, DWRITE_FONT_WEIGHT_NORMAL},
601 {350, DWRITE_FONT_WEIGHT_NORMAL},
602 {450, DWRITE_FONT_WEIGHT_NORMAL},
603 {650, DWRITE_FONT_WEIGHT_BOLD},
604 {750, DWRITE_FONT_WEIGHT_BOLD},
605 {850, DWRITE_FONT_WEIGHT_BOLD},
606 {950, DWRITE_FONT_WEIGHT_BOLD},
607 {960, DWRITE_FONT_WEIGHT_BOLD},
609 OUTLINETEXTMETRICW otm;
610 IDWriteFactory *factory;
611 HRESULT hr;
612 BOOL ret;
613 HDC hdc;
614 HFONT hfont;
615 BOOL exists;
616 int i;
617 UINT r;
619 factory = create_factory();
621 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
622 EXPECT_HR(hr, S_OK);
624 if (0)
625 /* null out parameter crashes this call */
626 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, NULL);
628 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, &font);
629 EXPECT_HR(hr, E_INVALIDARG);
631 memset(&logfont, 0, sizeof(logfont));
632 logfont.lfHeight = 12;
633 logfont.lfWidth = 12;
634 logfont.lfWeight = FW_NORMAL;
635 logfont.lfItalic = 1;
636 lstrcpyW(logfont.lfFaceName, tahomaW);
638 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
639 EXPECT_HR(hr, S_OK);
641 hfont = CreateFontIndirectW(&logfont);
642 hdc = CreateCompatibleDC(0);
643 SelectObject(hdc, hfont);
645 otm.otmSize = sizeof(otm);
646 r = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
647 ok(r, "got %d\n", r);
648 DeleteDC(hdc);
649 DeleteObject(hfont);
651 exists = TRUE;
652 hr = IDWriteFont_HasCharacter(font, 0xd800, &exists);
653 ok(hr == S_OK, "got 0x%08x\n", hr);
654 ok(exists == FALSE, "got %d\n", exists);
656 exists = FALSE;
657 hr = IDWriteFont_HasCharacter(font, 0x20, &exists);
658 ok(hr == S_OK, "got 0x%08x\n", hr);
659 ok(exists == TRUE, "got %d\n", exists);
661 /* now check properties */
662 weight = IDWriteFont_GetWeight(font);
663 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
665 style = IDWriteFont_GetStyle(font);
666 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
667 todo_wine
668 ok(otm.otmfsSelection == 1, "got 0x%08x\n", otm.otmfsSelection);
670 ret = IDWriteFont_IsSymbolFont(font);
671 ok(!ret, "got %d\n", ret);
673 IDWriteFont_Release(font);
675 /* weight values */
676 for (i = 0; i < sizeof(weights)/(2*sizeof(LONG)); i++)
678 memset(&logfont, 0, sizeof(logfont));
679 logfont.lfHeight = 12;
680 logfont.lfWidth = 12;
681 logfont.lfWeight = weights[i][0];
682 lstrcpyW(logfont.lfFaceName, tahomaW);
684 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
685 EXPECT_HR(hr, S_OK);
687 weight = IDWriteFont_GetWeight(font);
688 ok(weight == weights[i][1],
689 "%d: got %d, expected %d\n", i, weight, weights[i][1]);
691 IDWriteFont_Release(font);
694 /* weight not from enum */
695 memset(&logfont, 0, sizeof(logfont));
696 logfont.lfHeight = 12;
697 logfont.lfWidth = 12;
698 logfont.lfWeight = 550;
699 lstrcpyW(logfont.lfFaceName, tahomaW);
701 font = NULL;
702 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
703 ok(hr == S_OK, "got 0x%08x\n", hr);
705 weight = IDWriteFont_GetWeight(font);
706 ok(weight == DWRITE_FONT_WEIGHT_NORMAL || broken(weight == DWRITE_FONT_WEIGHT_BOLD) /* win7 w/o SP */,
707 "got %d\n", weight);
708 IDWriteFont_Release(font);
710 /* empty or nonexistent face name */
711 memset(&logfont, 0, sizeof(logfont));
712 logfont.lfHeight = 12;
713 logfont.lfWidth = 12;
714 logfont.lfWeight = FW_NORMAL;
715 lstrcpyW(logfont.lfFaceName, blahW);
717 font = (void*)0xdeadbeef;
718 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
719 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
720 ok(font == NULL, "got %p\n", font);
722 /* Try with name 'Tahoma ' */
723 memset(&logfont, 0, sizeof(logfont));
724 logfont.lfHeight = 12;
725 logfont.lfWidth = 12;
726 logfont.lfWeight = FW_NORMAL;
727 lstrcpyW(logfont.lfFaceName, tahomaspW);
729 font = (void*)0xdeadbeef;
730 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
731 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
732 ok(font == NULL, "got %p\n", font);
734 /* empty string as a facename */
735 memset(&logfont, 0, sizeof(logfont));
736 logfont.lfHeight = 12;
737 logfont.lfWidth = 12;
738 logfont.lfWeight = FW_NORMAL;
740 font = (void*)0xdeadbeef;
741 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
742 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
743 ok(font == NULL, "got %p\n", font);
745 IDWriteGdiInterop_Release(interop);
746 IDWriteFactory_Release(factory);
749 static void test_CreateBitmapRenderTarget(void)
751 IDWriteBitmapRenderTarget *target, *target2;
752 IDWriteBitmapRenderTarget1 *target1;
753 IDWriteGdiInterop *interop;
754 IDWriteFactory *factory;
755 HBITMAP hbm, hbm2;
756 DWRITE_MATRIX m;
757 DIBSECTION ds;
758 COLORREF c;
759 HRESULT hr;
760 FLOAT pdip;
761 SIZE size;
762 HDC hdc;
763 int ret;
765 factory = create_factory();
767 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
768 EXPECT_HR(hr, S_OK);
770 target = NULL;
771 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target);
772 EXPECT_HR(hr, S_OK);
774 if (0) /* crashes on native */
775 hr = IDWriteBitmapRenderTarget_GetSize(target, NULL);
777 size.cx = size.cy = -1;
778 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
779 EXPECT_HR(hr, S_OK);
780 ok(size.cx == 0, "got %d\n", size.cx);
781 ok(size.cy == 0, "got %d\n", size.cy);
783 target2 = NULL;
784 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target2);
785 EXPECT_HR(hr, S_OK);
786 ok(target != target2, "got %p, %p\n", target2, target);
787 IDWriteBitmapRenderTarget_Release(target2);
789 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
790 ok(hdc != NULL, "got %p\n", hdc);
792 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
793 ok(hbm != NULL, "got %p\n", hbm);
795 /* check DIB properties */
796 ret = GetObjectW(hbm, sizeof(ds), &ds);
797 ok(ret == sizeof(BITMAP), "got %d\n", ret);
798 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
799 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
800 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
801 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
802 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
804 IDWriteBitmapRenderTarget_Release(target);
806 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
807 ok(!hbm, "got %p\n", hbm);
809 target = NULL;
810 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 10, 5, &target);
811 EXPECT_HR(hr, S_OK);
813 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
814 ok(hdc != NULL, "got %p\n", hdc);
816 /* test context settings */
817 c = GetTextColor(hdc);
818 ok(c == RGB(0, 0, 0), "got 0x%08x\n", c);
819 ret = GetBkMode(hdc);
820 ok(ret == OPAQUE, "got %d\n", ret);
821 c = GetBkColor(hdc);
822 ok(c == RGB(255, 255, 255), "got 0x%08x\n", c);
824 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
825 ok(hbm != NULL, "got %p\n", hbm);
827 /* check DIB properties */
828 ret = GetObjectW(hbm, sizeof(ds), &ds);
829 ok(ret == sizeof(ds), "got %d\n", ret);
830 ok(ds.dsBm.bmWidth == 10, "got %d\n", ds.dsBm.bmWidth);
831 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
832 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
833 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
834 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
836 size.cx = size.cy = -1;
837 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
838 EXPECT_HR(hr, S_OK);
839 ok(size.cx == 10, "got %d\n", size.cx);
840 ok(size.cy == 5, "got %d\n", size.cy);
842 /* resize to same size */
843 hr = IDWriteBitmapRenderTarget_Resize(target, 10, 5);
844 ok(hr == S_OK, "got 0x%08x\n", hr);
846 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
847 ok(hbm2 == hbm, "got %p, %p\n", hbm2, hbm);
849 /* shrink */
850 hr = IDWriteBitmapRenderTarget_Resize(target, 5, 5);
851 ok(hr == S_OK, "got 0x%08x\n", hr);
853 size.cx = size.cy = -1;
854 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
855 ok(hr == S_OK, "got 0x%08x\n", hr);
856 ok(size.cx == 5, "got %d\n", size.cx);
857 ok(size.cy == 5, "got %d\n", size.cy);
859 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
860 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
862 hr = IDWriteBitmapRenderTarget_Resize(target, 20, 5);
863 ok(hr == S_OK, "got 0x%08x\n", hr);
865 size.cx = size.cy = -1;
866 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
867 ok(hr == S_OK, "got 0x%08x\n", hr);
868 ok(size.cx == 20, "got %d\n", size.cx);
869 ok(size.cy == 5, "got %d\n", size.cy);
871 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
872 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
874 hr = IDWriteBitmapRenderTarget_Resize(target, 1, 5);
875 ok(hr == S_OK, "got 0x%08x\n", hr);
877 size.cx = size.cy = -1;
878 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
879 ok(hr == S_OK, "got 0x%08x\n", hr);
880 ok(size.cx == 1, "got %d\n", size.cx);
881 ok(size.cy == 5, "got %d\n", size.cy);
883 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
884 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
886 ret = GetObjectW(hbm2, sizeof(ds), &ds);
887 ok(ret == sizeof(ds), "got %d\n", ret);
888 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
889 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
890 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
891 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
892 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
894 /* empty rectangle */
895 hr = IDWriteBitmapRenderTarget_Resize(target, 0, 5);
896 ok(hr == S_OK, "got 0x%08x\n", hr);
898 size.cx = size.cy = -1;
899 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
900 ok(hr == S_OK, "got 0x%08x\n", hr);
901 ok(size.cx == 0, "got %d\n", size.cx);
902 ok(size.cy == 5, "got %d\n", size.cy);
904 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
905 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
907 ret = GetObjectW(hbm2, sizeof(ds), &ds);
908 ok(ret == sizeof(BITMAP), "got %d\n", ret);
909 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
910 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
911 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
912 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
913 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
915 /* transform tests */
916 if (0) /* crashes on native */
917 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, NULL);
919 memset(&m, 0xcc, sizeof(m));
920 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
921 ok(hr == S_OK, "got 0x%08x\n", hr);
922 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);
923 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
925 memset(&m, 0, sizeof(m));
926 hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, &m);
927 ok(hr == S_OK, "got 0x%08x\n", hr);
929 memset(&m, 0xcc, sizeof(m));
930 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
931 ok(hr == S_OK, "got 0x%08x\n", hr);
932 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);
933 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
935 hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, NULL);
936 ok(hr == S_OK, "got 0x%08x\n", hr);
938 memset(&m, 0xcc, sizeof(m));
939 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
940 ok(hr == S_OK, "got 0x%08x\n", hr);
941 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);
942 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
944 /* pixels per dip */
945 pdip = IDWriteBitmapRenderTarget_GetPixelsPerDip(target);
946 ok(pdip == 1.0, "got %.2f\n", pdip);
948 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, 2.0);
949 ok(hr == S_OK, "got 0x%08x\n", hr);
951 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, -1.0);
952 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
954 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, 0.0);
955 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
957 pdip = IDWriteBitmapRenderTarget_GetPixelsPerDip(target);
958 ok(pdip == 2.0, "got %.2f\n", pdip);
960 hr = IDWriteBitmapRenderTarget_QueryInterface(target, &IID_IDWriteBitmapRenderTarget1, (void**)&target1);
961 if (hr == S_OK) {
962 DWRITE_TEXT_ANTIALIAS_MODE mode;
964 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
965 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, "got %d\n", mode);
967 hr = IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE+1);
968 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
970 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
971 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, "got %d\n", mode);
973 hr = IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
974 ok(hr == S_OK, "got 0x%08x\n", hr);
976 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
977 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE, "got %d\n", mode);
979 IDWriteBitmapRenderTarget1_Release(target1);
981 else
982 win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
984 IDWriteBitmapRenderTarget_Release(target);
985 IDWriteGdiInterop_Release(interop);
986 IDWriteFactory_Release(factory);
989 static void test_GetFontFamily(void)
991 IDWriteFontCollection *collection, *collection2;
992 IDWriteFontCollection *syscoll;
993 IDWriteFontFamily *family, *family2;
994 IDWriteGdiInterop *interop;
995 IDWriteFont *font, *font2;
996 IDWriteFactory *factory;
997 LOGFONTW logfont;
998 HRESULT hr;
1000 factory = create_factory();
1002 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1003 EXPECT_HR(hr, S_OK);
1005 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscoll, FALSE);
1006 ok(hr == S_OK, "got 0x%08x\n", hr);
1008 memset(&logfont, 0, sizeof(logfont));
1009 logfont.lfHeight = 12;
1010 logfont.lfWidth = 12;
1011 logfont.lfWeight = FW_NORMAL;
1012 logfont.lfItalic = 1;
1013 lstrcpyW(logfont.lfFaceName, tahomaW);
1015 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1016 ok(hr == S_OK, "got 0x%08x\n", hr);
1018 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
1019 ok(hr == S_OK, "got 0x%08x\n", hr);
1020 ok(font2 != font, "got %p, %p\n", font2, font);
1022 if (0) /* crashes on native */
1023 hr = IDWriteFont_GetFontFamily(font, NULL);
1025 EXPECT_REF(font, 1);
1026 hr = IDWriteFont_GetFontFamily(font, &family);
1027 EXPECT_HR(hr, S_OK);
1028 EXPECT_REF(font, 1);
1029 EXPECT_REF(family, 2);
1031 hr = IDWriteFont_GetFontFamily(font, &family2);
1032 EXPECT_HR(hr, S_OK);
1033 ok(family2 == family, "got %p, previous %p\n", family2, family);
1034 EXPECT_REF(font, 1);
1035 EXPECT_REF(family, 3);
1036 IDWriteFontFamily_Release(family2);
1038 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFamily, (void**)&family2);
1039 EXPECT_HR(hr, E_NOINTERFACE);
1040 ok(family2 == NULL, "got %p\n", family2);
1042 hr = IDWriteFont_GetFontFamily(font2, &family2);
1043 ok(hr == S_OK, "got 0x%08x\n", hr);
1044 ok(family2 != family, "got %p, %p\n", family2, family);
1046 collection = NULL;
1047 hr = IDWriteFontFamily_GetFontCollection(family, &collection);
1048 ok(hr == S_OK, "got 0x%08x\n", hr);
1050 collection2 = NULL;
1051 hr = IDWriteFontFamily_GetFontCollection(family2, &collection2);
1052 ok(hr == S_OK, "got 0x%08x\n", hr);
1053 ok(collection == collection2, "got %p, %p\n", collection, collection2);
1054 ok(collection == syscoll, "got %p, %p\n", collection, syscoll);
1056 IDWriteFontCollection_Release(syscoll);
1057 IDWriteFontCollection_Release(collection2);
1058 IDWriteFontCollection_Release(collection);
1059 IDWriteFontFamily_Release(family2);
1060 IDWriteFontFamily_Release(family);
1061 IDWriteFont_Release(font);
1062 IDWriteFont_Release(font2);
1063 IDWriteGdiInterop_Release(interop);
1064 IDWriteFactory_Release(factory);
1067 static void test_GetFamilyNames(void)
1069 IDWriteFontFamily *family;
1070 IDWriteLocalizedStrings *names, *names2;
1071 IDWriteGdiInterop *interop;
1072 IDWriteFactory *factory;
1073 IDWriteFont *font;
1074 LOGFONTW logfont;
1075 WCHAR buffer[100];
1076 HRESULT hr;
1077 UINT32 len;
1079 factory = create_factory();
1081 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1082 EXPECT_HR(hr, S_OK);
1084 memset(&logfont, 0, sizeof(logfont));
1085 logfont.lfHeight = 12;
1086 logfont.lfWidth = 12;
1087 logfont.lfWeight = FW_NORMAL;
1088 logfont.lfItalic = 1;
1089 lstrcpyW(logfont.lfFaceName, tahomaW);
1091 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1092 EXPECT_HR(hr, S_OK);
1094 hr = IDWriteFont_GetFontFamily(font, &family);
1095 EXPECT_HR(hr, S_OK);
1097 if (0) /* crashes on native */
1098 hr = IDWriteFontFamily_GetFamilyNames(family, NULL);
1100 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
1101 ok(hr == S_OK, "got 0x%08x\n", hr);
1102 EXPECT_REF(names, 1);
1104 hr = IDWriteFontFamily_GetFamilyNames(family, &names2);
1105 ok(hr == S_OK, "got 0x%08x\n", hr);
1106 EXPECT_REF(names2, 1);
1107 ok(names != names2, "got %p, was %p\n", names2, names);
1109 IDWriteLocalizedStrings_Release(names2);
1111 /* GetStringLength */
1112 if (0) /* crashes on native */
1113 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, NULL);
1115 len = 100;
1116 hr = IDWriteLocalizedStrings_GetStringLength(names, 10, &len);
1117 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1118 ok(len == (UINT32)-1, "got %u\n", len);
1120 len = 0;
1121 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, &len);
1122 ok(hr == S_OK, "got 0x%08x\n", hr);
1123 ok(len > 0, "got %u\n", len);
1125 /* GetString */
1126 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 0);
1127 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1129 hr = IDWriteLocalizedStrings_GetString(names, 10, NULL, 0);
1130 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1132 if (0)
1133 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 100);
1135 buffer[0] = 1;
1136 hr = IDWriteLocalizedStrings_GetString(names, 10, buffer, 100);
1137 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1138 ok(buffer[0] == 0, "got %x\n", buffer[0]);
1140 buffer[0] = 1;
1141 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len-1);
1142 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1143 ok(buffer[0] == 0, "got %x\n", buffer[0]);
1145 buffer[0] = 1;
1146 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len);
1147 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1148 ok(buffer[0] == 0, "got %x\n", buffer[0]);
1150 buffer[0] = 0;
1151 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len+1);
1152 ok(hr == S_OK, "got 0x%08x\n", hr);
1153 ok(buffer[0] != 0, "got %x\n", buffer[0]);
1155 IDWriteLocalizedStrings_Release(names);
1157 IDWriteFontFamily_Release(family);
1158 IDWriteFont_Release(font);
1159 IDWriteGdiInterop_Release(interop);
1160 IDWriteFactory_Release(factory);
1163 static void test_CreateFontFace(void)
1165 IDWriteFontFace *fontface, *fontface2;
1166 IDWriteFontCollection *collection;
1167 DWRITE_FONT_FILE_TYPE file_type;
1168 DWRITE_FONT_FACE_TYPE face_type;
1169 IDWriteGdiInterop *interop;
1170 IDWriteFont *font, *font2;
1171 IDWriteFontFamily *family;
1172 IDWriteFactory *factory;
1173 IDWriteFontFile *file;
1174 LOGFONTW logfont;
1175 BOOL supported;
1176 UINT32 count;
1177 WCHAR *path;
1178 HRESULT hr;
1180 factory = create_factory();
1182 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1183 EXPECT_HR(hr, S_OK);
1185 memset(&logfont, 0, sizeof(logfont));
1186 logfont.lfHeight = 12;
1187 logfont.lfWidth = 12;
1188 logfont.lfWeight = FW_NORMAL;
1189 logfont.lfItalic = 1;
1190 lstrcpyW(logfont.lfFaceName, tahomaW);
1192 font = NULL;
1193 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1194 ok(hr == S_OK, "got 0x%08x\n", hr);
1196 font2 = NULL;
1197 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
1198 ok(hr == S_OK, "got 0x%08x\n", hr);
1199 ok(font != font2, "got %p, %p\n", font, font2);
1201 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface);
1202 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1204 if (0) /* crashes on native */
1205 hr = IDWriteFont_CreateFontFace(font, NULL);
1207 fontface = NULL;
1208 hr = IDWriteFont_CreateFontFace(font, &fontface);
1209 ok(hr == S_OK, "got 0x%08x\n", hr);
1211 fontface2 = NULL;
1212 hr = IDWriteFont_CreateFontFace(font, &fontface2);
1213 ok(hr == S_OK, "got 0x%08x\n", hr);
1214 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
1215 IDWriteFontFace_Release(fontface2);
1217 fontface2 = NULL;
1218 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
1219 ok(hr == S_OK, "got 0x%08x\n", hr);
1220 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
1221 IDWriteFontFace_Release(fontface2);
1223 IDWriteFont_Release(font2);
1224 IDWriteFont_Release(font);
1226 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFont, (void**)&font);
1227 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL), "got 0x%08x\n", hr);
1229 IDWriteFontFace_Release(fontface);
1230 IDWriteGdiInterop_Release(interop);
1232 /* Create from system collection */
1233 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1234 ok(hr == S_OK, "got 0x%08x\n", hr);
1236 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1237 ok(hr == S_OK, "got 0x%08x\n", hr);
1239 font = NULL;
1240 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1241 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1242 ok(hr == S_OK, "got 0x%08x\n", hr);
1244 font2 = NULL;
1245 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1246 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font2);
1247 ok(hr == S_OK, "got 0x%08x\n", hr);
1248 ok(font != font2, "got %p, %p\n", font, font2);
1250 fontface = NULL;
1251 hr = IDWriteFont_CreateFontFace(font, &fontface);
1252 ok(hr == S_OK, "got 0x%08x\n", hr);
1254 fontface2 = NULL;
1255 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
1256 ok(hr == S_OK, "got 0x%08x\n", hr);
1257 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
1259 IDWriteFontFace_Release(fontface);
1260 IDWriteFontFace_Release(fontface2);
1261 IDWriteFont_Release(font2);
1262 IDWriteFont_Release(font);
1263 IDWriteFontFamily_Release(family);
1264 IDWriteFontCollection_Release(collection);
1266 /* IDWriteFactory::CreateFontFace() */
1267 path = create_testfontfile(test_fontfile);
1268 factory = create_factory();
1270 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
1271 ok(hr == S_OK, "got 0x%08x\n",hr);
1273 supported = FALSE;
1274 file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1275 face_type = DWRITE_FONT_FACE_TYPE_CFF;
1276 count = 0;
1277 hr = IDWriteFontFile_Analyze(file, &supported, &file_type, &face_type, &count);
1278 ok(hr == S_OK, "got 0x%08x\n", hr);
1279 ok(supported == TRUE, "got %i\n", supported);
1280 ok(file_type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", file_type);
1281 ok(face_type == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face_type);
1282 ok(count == 1, "got %i\n", count);
1284 /* try mismatching face type, the one that's not supported */
1285 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_CFF, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1286 todo_wine
1287 ok(hr == DWRITE_E_FILEFORMAT, "got 0x%08x\n", hr);
1289 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION, 1, &file, 0,
1290 DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1291 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1293 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_RAW_CFF, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1294 todo_wine
1295 ok(hr == DWRITE_E_UNSUPPORTEDOPERATION || broken(hr == E_INVALIDARG) /* older versions */, "got 0x%08x\n", hr);
1297 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TYPE1, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1298 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1300 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_VECTOR, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1301 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1303 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_BITMAP, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1304 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1306 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_UNKNOWN, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1307 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1309 IDWriteFontFile_Release(file);
1310 IDWriteFactory_Release(factory);
1311 DELETE_FONTFILE(path);
1314 static void test_GetMetrics(void)
1316 IDWriteGdiInterop *interop;
1317 DWRITE_FONT_METRICS metrics;
1318 IDWriteFontFace *fontface;
1319 IDWriteFactory *factory;
1320 OUTLINETEXTMETRICW otm;
1321 IDWriteFont1 *font1;
1322 IDWriteFont *font;
1323 LOGFONTW logfont;
1324 HRESULT hr;
1325 HDC hdc;
1326 HFONT hfont;
1327 int ret;
1329 factory = create_factory();
1331 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1332 EXPECT_HR(hr, S_OK);
1334 memset(&logfont, 0, sizeof(logfont));
1335 logfont.lfHeight = 12;
1336 logfont.lfWidth = 12;
1337 logfont.lfWeight = FW_NORMAL;
1338 logfont.lfItalic = 1;
1339 lstrcpyW(logfont.lfFaceName, tahomaW);
1341 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1342 ok(hr == S_OK, "got 0x%08x\n", hr);
1344 hfont = CreateFontIndirectW(&logfont);
1345 hdc = CreateCompatibleDC(0);
1346 SelectObject(hdc, hfont);
1348 otm.otmSize = sizeof(otm);
1349 ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
1350 ok(ret, "got %d\n", ret);
1351 DeleteDC(hdc);
1352 DeleteObject(hfont);
1354 if (0) /* crashes on native */
1355 IDWriteFont_GetMetrics(font, NULL);
1357 memset(&metrics, 0, sizeof(metrics));
1358 IDWriteFont_GetMetrics(font, &metrics);
1360 ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
1361 ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
1362 ok(metrics.descent != 0, "descent %u\n", metrics.descent);
1363 ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
1364 ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
1365 ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
1366 ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
1367 ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
1368 ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
1369 ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
1371 hr = IDWriteFont_CreateFontFace(font, &fontface);
1372 ok(hr == S_OK, "got 0x%08x\n", hr);
1374 memset(&metrics, 0, sizeof(metrics));
1375 IDWriteFontFace_GetMetrics(fontface, &metrics);
1377 ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
1378 ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
1379 ok(metrics.descent != 0, "descent %u\n", metrics.descent);
1380 ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
1381 ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
1382 ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
1383 ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
1384 ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
1385 ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
1386 ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
1388 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
1389 if (hr == S_OK) {
1390 DWRITE_FONT_METRICS1 metrics1;
1391 IDWriteFontFace1 *fontface1;
1393 memset(&metrics1, 0, sizeof(metrics1));
1394 IDWriteFont1_GetMetrics(font1, &metrics1);
1396 ok(metrics1.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics1.designUnitsPerEm);
1397 ok(metrics1.ascent != 0, "ascent %u\n", metrics1.ascent);
1398 ok(metrics1.descent != 0, "descent %u\n", metrics1.descent);
1399 ok(metrics1.lineGap == 0, "lineGap %d\n", metrics1.lineGap);
1400 ok(metrics1.capHeight, "capHeight %u\n", metrics1.capHeight);
1401 ok(metrics1.xHeight != 0, "xHeight %u\n", metrics1.xHeight);
1402 ok(metrics1.underlinePosition < 0, "underlinePosition %d\n", metrics1.underlinePosition);
1403 ok(metrics1.underlineThickness != 0, "underlineThickness %u\n", metrics1.underlineThickness);
1404 ok(metrics1.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics1.strikethroughPosition);
1405 ok(metrics1.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics1.strikethroughThickness);
1406 ok(metrics1.glyphBoxLeft < 0, "glyphBoxLeft %d\n", metrics1.glyphBoxLeft);
1407 ok(metrics1.glyphBoxTop > 0, "glyphBoxTop %d\n", metrics1.glyphBoxTop);
1408 ok(metrics1.glyphBoxRight > 0, "glyphBoxRight %d\n", metrics1.glyphBoxRight);
1409 ok(metrics1.glyphBoxBottom < 0, "glyphBoxBottom %d\n", metrics1.glyphBoxBottom);
1410 ok(metrics1.subscriptPositionY < 0, "subscriptPositionY %d\n", metrics1.subscriptPositionY);
1411 ok(metrics1.subscriptSizeX > 0, "subscriptSizeX %d\n", metrics1.subscriptSizeX);
1412 ok(metrics1.subscriptSizeY > 0, "subscriptSizeY %d\n", metrics1.subscriptSizeY);
1413 ok(metrics1.superscriptPositionY > 0, "superscriptPositionY %d\n", metrics1.superscriptPositionY);
1414 ok(metrics1.superscriptSizeX > 0, "superscriptSizeX %d\n", metrics1.superscriptSizeX);
1415 ok(metrics1.superscriptSizeY > 0, "superscriptSizeY %d\n", metrics1.superscriptSizeY);
1416 ok(!metrics1.hasTypographicMetrics, "hasTypographicMetrics %d\n", metrics1.hasTypographicMetrics);
1418 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
1419 ok(hr == S_OK, "got 0x%08x\n", hr);
1421 memset(&metrics1, 0, sizeof(metrics1));
1422 IDWriteFontFace1_GetMetrics(fontface1, &metrics1);
1424 ok(metrics1.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics1.designUnitsPerEm);
1425 ok(metrics1.ascent != 0, "ascent %u\n", metrics1.ascent);
1426 ok(metrics1.descent != 0, "descent %u\n", metrics1.descent);
1427 ok(metrics1.lineGap == 0, "lineGap %d\n", metrics1.lineGap);
1428 ok(metrics1.capHeight, "capHeight %u\n", metrics1.capHeight);
1429 ok(metrics1.xHeight != 0, "xHeight %u\n", metrics1.xHeight);
1430 ok(metrics1.underlinePosition < 0, "underlinePosition %d\n", metrics1.underlinePosition);
1431 ok(metrics1.underlineThickness != 0, "underlineThickness %u\n", metrics1.underlineThickness);
1432 ok(metrics1.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics1.strikethroughPosition);
1433 ok(metrics1.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics1.strikethroughThickness);
1434 ok(metrics1.glyphBoxLeft < 0, "glyphBoxLeft %d\n", metrics1.glyphBoxLeft);
1435 ok(metrics1.glyphBoxTop > 0, "glyphBoxTop %d\n", metrics1.glyphBoxTop);
1436 ok(metrics1.glyphBoxRight > 0, "glyphBoxRight %d\n", metrics1.glyphBoxRight);
1437 ok(metrics1.glyphBoxBottom < 0, "glyphBoxBottom %d\n", metrics1.glyphBoxBottom);
1438 ok(metrics1.subscriptPositionY < 0, "subscriptPositionY %d\n", metrics1.subscriptPositionY);
1439 ok(metrics1.subscriptSizeX > 0, "subscriptSizeX %d\n", metrics1.subscriptSizeX);
1440 ok(metrics1.subscriptSizeY > 0, "subscriptSizeY %d\n", metrics1.subscriptSizeY);
1441 ok(metrics1.superscriptPositionY > 0, "superscriptPositionY %d\n", metrics1.superscriptPositionY);
1442 ok(metrics1.superscriptSizeX > 0, "superscriptSizeX %d\n", metrics1.superscriptSizeX);
1443 ok(metrics1.superscriptSizeY > 0, "superscriptSizeY %d\n", metrics1.superscriptSizeY);
1444 ok(!metrics1.hasTypographicMetrics, "hasTypographicMetrics %d\n", metrics1.hasTypographicMetrics);
1446 IDWriteFontFace1_Release(fontface1);
1447 IDWriteFont1_Release(font1);
1449 else
1450 win_skip("DWRITE_FONT_METRICS1 is not supported.\n");
1452 IDWriteFontFace_Release(fontface);
1454 IDWriteFont_Release(font);
1455 IDWriteGdiInterop_Release(interop);
1456 IDWriteFactory_Release(factory);
1459 static void test_system_fontcollection(void)
1461 IDWriteFontCollection *collection, *coll2;
1462 IDWriteLocalFontFileLoader *localloader;
1463 IDWriteFactory *factory, *factory2;
1464 IDWriteFontFileLoader *loader;
1465 IDWriteFontFamily *family;
1466 IDWriteFontFace *fontface;
1467 IDWriteFontFile *file;
1468 IDWriteFont *font;
1469 HRESULT hr;
1470 UINT32 i;
1471 BOOL ret;
1473 factory = create_factory();
1475 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1476 ok(hr == S_OK, "got 0x%08x\n", hr);
1478 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, FALSE);
1479 ok(hr == S_OK, "got 0x%08x\n", hr);
1480 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
1481 IDWriteFontCollection_Release(coll2);
1483 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, TRUE);
1484 ok(hr == S_OK, "got 0x%08x\n", hr);
1485 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
1486 IDWriteFontCollection_Release(coll2);
1488 factory2 = create_factory();
1489 hr = IDWriteFactory_GetSystemFontCollection(factory2, &coll2, FALSE);
1490 ok(hr == S_OK, "got 0x%08x\n", hr);
1491 ok(coll2 != collection, "got %p, was %p\n", coll2, collection);
1492 IDWriteFontCollection_Release(coll2);
1493 IDWriteFactory_Release(factory2);
1495 i = IDWriteFontCollection_GetFontFamilyCount(collection);
1496 ok(i, "got %u\n", i);
1498 /* invalid index */
1499 family = (void*)0xdeadbeef;
1500 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
1501 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1502 ok(family == NULL, "got %p\n", family);
1504 ret = FALSE;
1505 i = (UINT32)-1;
1506 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaW, &i, &ret);
1507 ok(hr == S_OK, "got 0x%08x\n", hr);
1508 ok(ret, "got %d\n", ret);
1509 ok(i != (UINT32)-1, "got %u\n", i);
1511 ret = FALSE;
1512 i = (UINT32)-1;
1513 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaUppercaseW, &i, &ret);
1514 ok(hr == S_OK, "got 0x%08x\n", hr);
1515 ok(ret, "got %d\n", ret);
1516 ok(i != (UINT32)-1, "got %u\n", i);
1518 ret = FALSE;
1519 i = (UINT32)-1;
1520 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaStrangecaseW, &i, &ret);
1521 ok(hr == S_OK, "got 0x%08x\n", hr);
1522 ok(ret, "got %d\n", ret);
1523 ok(i != (UINT32)-1, "got %u\n", i);
1525 /* get back local file loader */
1526 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
1527 ok(hr == S_OK, "got 0x%08x\n", hr);
1529 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1530 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1531 ok(hr == S_OK, "got 0x%08x\n", hr);
1532 IDWriteFontFamily_Release(family);
1534 hr = IDWriteFont_CreateFontFace(font, &fontface);
1535 ok(hr == S_OK, "got 0x%08x\n", hr);
1536 IDWriteFont_Release(font);
1538 i = 1;
1539 file = NULL;
1540 hr = IDWriteFontFace_GetFiles(fontface, &i, &file);
1541 ok(hr == S_OK, "got 0x%08x\n", hr);
1542 ok(file != NULL, "got %p\n", file);
1544 hr = IDWriteFontFile_GetLoader(file, &loader);
1545 ok(hr == S_OK, "got 0x%08x\n", hr);
1546 IDWriteFontFile_Release(file);
1548 hr = IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
1549 ok(hr == S_OK, "got 0x%08x\n", hr);
1550 IDWriteLocalFontFileLoader_Release(localloader);
1552 /* local loader is not registered by default */
1553 hr = IDWriteFactory_RegisterFontFileLoader(factory, loader);
1554 ok(hr == S_OK || broken(hr == DWRITE_E_ALREADYREGISTERED), "got 0x%08x\n", hr);
1555 hr = IDWriteFactory_UnregisterFontFileLoader(factory, loader);
1556 ok(hr == S_OK || broken(hr == E_INVALIDARG), "got 0x%08x\n", hr);
1558 /* try with a different factory */
1559 factory2 = create_factory();
1560 hr = IDWriteFactory_RegisterFontFileLoader(factory2, loader);
1561 ok(hr == S_OK || broken(hr == DWRITE_E_ALREADYREGISTERED), "got 0x%08x\n", hr);
1562 hr = IDWriteFactory_RegisterFontFileLoader(factory2, loader);
1563 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1564 hr = IDWriteFactory_UnregisterFontFileLoader(factory2, loader);
1565 ok(hr == S_OK || broken(hr == E_INVALIDARG), "got 0x%08x\n", hr);
1566 hr = IDWriteFactory_UnregisterFontFileLoader(factory2, loader);
1567 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1568 IDWriteFactory_Release(factory2);
1570 IDWriteFontFileLoader_Release(loader);
1572 ret = TRUE;
1573 i = 0;
1574 hr = IDWriteFontCollection_FindFamilyName(collection, blahW, &i, &ret);
1575 ok(hr == S_OK, "got 0x%08x\n", hr);
1576 ok(!ret, "got %d\n", ret);
1577 ok(i == (UINT32)-1, "got %u\n", i);
1579 IDWriteFontCollection_Release(collection);
1580 IDWriteFactory_Release(factory);
1583 static void test_ConvertFontFaceToLOGFONT(void)
1585 DWRITE_FONT_SIMULATIONS sim;
1586 IDWriteGdiInterop *interop;
1587 IDWriteFontFace *fontface;
1588 IDWriteFactory *factory;
1589 IDWriteFont *font;
1590 LOGFONTW logfont;
1591 HRESULT hr;
1593 factory = create_factory();
1595 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1596 ok(hr == S_OK, "got 0x%08x\n", hr);
1598 memset(&logfont, 0, sizeof(logfont));
1599 logfont.lfHeight = 12;
1600 logfont.lfWidth = 12;
1601 logfont.lfEscapement = 100;
1602 logfont.lfWeight = FW_NORMAL;
1603 logfont.lfItalic = 1;
1604 logfont.lfUnderline = 1;
1605 logfont.lfStrikeOut = 1;
1607 lstrcpyW(logfont.lfFaceName, tahomaW);
1609 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1610 ok(hr == S_OK, "got 0x%08x\n", hr);
1612 hr = IDWriteFont_CreateFontFace(font, &fontface);
1613 ok(hr == S_OK, "got 0x%08x\n", hr);
1615 sim = IDWriteFont_GetSimulations(font);
1616 ok(sim == DWRITE_FONT_SIMULATIONS_OBLIQUE, "sim %d\n", sim);
1618 sim = IDWriteFontFace_GetSimulations(fontface);
1619 ok(sim == DWRITE_FONT_SIMULATIONS_OBLIQUE, "sim %d\n", sim);
1621 IDWriteFont_Release(font);
1623 if (0) /* crashes on native */
1625 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, NULL, NULL);
1626 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, NULL);
1629 memset(&logfont, 0xa, sizeof(logfont));
1630 logfont.lfFaceName[0] = 0;
1632 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, &logfont);
1633 ok(hr == S_OK, "got 0x%08x\n", hr);
1634 ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight);
1635 ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth);
1636 ok(logfont.lfWeight == FW_NORMAL, "got %d\n", logfont.lfWeight);
1637 ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement);
1638 ok(logfont.lfItalic == 1, "got %d\n", logfont.lfItalic);
1639 ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline);
1640 ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut);
1641 ok(!lstrcmpW(logfont.lfFaceName, tahomaW), "got %s\n", wine_dbgstr_w(logfont.lfFaceName));
1643 IDWriteGdiInterop_Release(interop);
1644 IDWriteFontFace_Release(fontface);
1645 IDWriteFactory_Release(factory);
1648 static HRESULT WINAPI fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
1650 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileEnumerator))
1652 *obj = iface;
1653 IDWriteFontFileEnumerator_AddRef(iface);
1654 return S_OK;
1656 return E_NOINTERFACE;
1659 static ULONG WINAPI fontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
1661 return 2;
1664 static ULONG WINAPI fontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
1666 return 1;
1669 static HRESULT WINAPI fontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file)
1671 *file = NULL;
1672 return E_FAIL;
1675 static HRESULT WINAPI fontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
1677 *current = FALSE;
1678 return S_OK;
1681 static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl =
1683 fontfileenumerator_QueryInterface,
1684 fontfileenumerator_AddRef,
1685 fontfileenumerator_Release,
1686 fontfileenumerator_MoveNext,
1687 fontfileenumerator_GetCurrentFontFile,
1690 static HRESULT WINAPI fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
1692 *obj = iface;
1693 return S_OK;
1696 static ULONG WINAPI fontcollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
1698 return 2;
1701 static ULONG WINAPI fontcollectionloader_Release(IDWriteFontCollectionLoader *iface)
1703 return 1;
1706 static HRESULT WINAPI fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory, const void *key,
1707 UINT32 key_size, IDWriteFontFileEnumerator **ret)
1709 static IDWriteFontFileEnumerator enumerator = { &dwritefontfileenumeratorvtbl };
1710 *ret = &enumerator;
1711 return S_OK;
1714 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl = {
1715 fontcollectionloader_QueryInterface,
1716 fontcollectionloader_AddRef,
1717 fontcollectionloader_Release,
1718 fontcollectionloader_CreateEnumeratorFromKey
1721 static void test_CustomFontCollection(void)
1723 static const WCHAR fontnameW[] = {'w','i','n','e','_','t','e','s','t',0};
1724 IDWriteFontCollectionLoader collection = { &dwritefontcollectionloadervtbl };
1725 IDWriteFontCollectionLoader collection2 = { &dwritefontcollectionloadervtbl };
1726 IDWriteFontCollectionLoader collection3 = { &dwritefontcollectionloadervtbl };
1727 IDWriteFontCollection *font_collection = NULL;
1728 static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
1729 struct test_fontcollectionloader resource_collection = { { &resourcecollectionloadervtbl }, &rloader };
1730 IDWriteFontFamily *family, *family2, *family3;
1731 IDWriteFontFace *idfontface, *idfontface2;
1732 IDWriteFontFile *fontfile, *fontfile2;
1733 IDWriteLocalizedStrings *string;
1734 IDWriteFont *idfont, *idfont2;
1735 IDWriteFactory *factory;
1736 UINT32 index, count;
1737 BOOL exists;
1738 HRESULT hr;
1739 HRSRC font;
1741 factory = create_factory();
1743 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, NULL);
1744 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1746 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, NULL);
1747 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1749 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
1750 ok(hr == S_OK, "got 0x%08x\n", hr);
1751 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection2);
1752 ok(hr == S_OK, "got 0x%08x\n", hr);
1753 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
1754 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1756 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1757 ok(hr == S_OK, "got 0x%08x\n", hr);
1758 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface);
1759 ok(hr == S_OK, "got 0x%08x\n", hr);
1761 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection3, "Billy", 6, &font_collection);
1762 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1764 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection, "Billy", 6, &font_collection);
1765 ok(hr == S_OK, "got 0x%08x\n", hr);
1766 IDWriteFontCollection_Release(font_collection);
1768 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection2, "Billy", 6, &font_collection);
1769 ok(hr == S_OK, "got 0x%08x\n", hr);
1770 IDWriteFontCollection_Release(font_collection);
1772 hr = IDWriteFactory_CreateCustomFontCollection(factory, (IDWriteFontCollectionLoader*)0xdeadbeef, "Billy", 6, &font_collection);
1773 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1775 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1776 ok(font != NULL, "Failed to find font resource\n");
1778 hr = IDWriteFactory_CreateCustomFontCollection(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface,
1779 &font, sizeof(HRSRC), &font_collection);
1780 ok(hr == S_OK, "got 0x%08x\n",hr);
1782 index = 1;
1783 exists = FALSE;
1784 hr = IDWriteFontCollection_FindFamilyName(font_collection, fontnameW, &index, &exists);
1785 ok(hr == S_OK, "got 0x%08x\n", hr);
1786 ok(index == 0, "got index %i\n", index);
1787 ok(exists, "got exists %i\n", exists);
1789 count = IDWriteFontCollection_GetFontFamilyCount(font_collection);
1790 ok(count == 1, "got %u\n", count);
1792 family = NULL;
1793 hr = IDWriteFontCollection_GetFontFamily(font_collection, 0, &family);
1794 ok(hr == S_OK, "got 0x%08x\n", hr);
1795 EXPECT_REF(family, 1);
1797 family2 = NULL;
1798 hr = IDWriteFontCollection_GetFontFamily(font_collection, 0, &family2);
1799 ok(hr == S_OK, "got 0x%08x\n", hr);
1800 EXPECT_REF(family2, 1);
1801 ok(family != family2, "got %p, %p\n", family, family2);
1803 hr = IDWriteFontFamily_GetFont(family, 0, &idfont);
1804 ok(hr == S_OK, "got 0x%08x\n", hr);
1805 EXPECT_REF(idfont, 1);
1806 EXPECT_REF(family, 2);
1807 hr = IDWriteFontFamily_GetFont(family, 0, &idfont2);
1808 ok(hr == S_OK, "got 0x%08x\n", hr);
1809 EXPECT_REF(idfont2, 1);
1810 EXPECT_REF(family, 3);
1811 ok(idfont != idfont2, "got %p, %p\n", idfont, idfont2);
1812 IDWriteFont_Release(idfont2);
1814 hr = IDWriteFont_GetInformationalStrings(idfont, DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE, &string, &exists);
1815 ok(hr == S_OK, "got 0x%08x\n", hr);
1816 ok(exists, "got %d\n", exists);
1817 EXPECT_REF(string, 1);
1819 family3 = NULL;
1820 hr = IDWriteFont_GetFontFamily(idfont, &family3);
1821 ok(hr == S_OK, "got 0x%08x\n", hr);
1822 EXPECT_REF(family, 3);
1823 ok(family == family3, "got %p, %p\n", family, family3);
1824 IDWriteFontFamily_Release(family3);
1826 idfontface = NULL;
1827 hr = IDWriteFont_CreateFontFace(idfont, &idfontface);
1828 ok(hr == S_OK, "got 0x%08x\n", hr);
1829 EXPECT_REF(idfont, 1);
1831 idfont2 = NULL;
1832 hr = IDWriteFontFamily_GetFont(family2, 0, &idfont2);
1833 ok(hr == S_OK, "got 0x%08x\n", hr);
1834 EXPECT_REF(idfont2, 1);
1835 EXPECT_REF(idfont, 1);
1836 ok(idfont2 != idfont, "Font instances should not match\n");
1838 idfontface2 = NULL;
1839 hr = IDWriteFont_CreateFontFace(idfont2, &idfontface2);
1840 ok(hr == S_OK, "got 0x%08x\n", hr);
1841 ok(idfontface2 == idfontface, "fontfaces should match\n");
1843 index = 1;
1844 fontfile = NULL;
1845 hr = IDWriteFontFace_GetFiles(idfontface, &index, &fontfile);
1846 ok(hr == S_OK, "got 0x%08x\n", hr);
1848 index = 1;
1849 fontfile2 = NULL;
1850 hr = IDWriteFontFace_GetFiles(idfontface2, &index, &fontfile2);
1851 ok(hr == S_OK, "got 0x%08x\n", hr);
1852 ok(fontfile == fontfile2, "fontfiles should match\n");
1854 IDWriteFont_Release(idfont);
1855 IDWriteFont_Release(idfont2);
1856 IDWriteFontFile_Release(fontfile);
1857 IDWriteFontFile_Release(fontfile2);
1858 IDWriteFontFace_Release(idfontface);
1859 IDWriteFontFace_Release(idfontface2);
1860 IDWriteFontFamily_Release(family2);
1861 IDWriteFontFamily_Release(family);
1862 IDWriteFontCollection_Release(font_collection);
1864 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
1865 ok(hr == S_OK, "got 0x%08x\n", hr);
1866 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
1867 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1868 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection2);
1869 ok(hr == S_OK, "got 0x%08x\n", hr);
1870 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface);
1871 ok(hr == S_OK, "got 0x%08x\n", hr);
1872 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1873 ok(hr == S_OK, "got 0x%08x\n", hr);
1875 IDWriteFactory_Release(factory);
1878 static HRESULT WINAPI fontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
1880 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
1882 *obj = iface;
1883 IDWriteFontFileLoader_AddRef(iface);
1884 return S_OK;
1887 *obj = NULL;
1888 return E_NOINTERFACE;
1891 static ULONG WINAPI fontfileloader_AddRef(IDWriteFontFileLoader *iface)
1893 return 2;
1896 static ULONG WINAPI fontfileloader_Release(IDWriteFontFileLoader *iface)
1898 return 1;
1901 static HRESULT WINAPI fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1903 return 0x8faecafe;
1906 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl = {
1907 fontfileloader_QueryInterface,
1908 fontfileloader_AddRef,
1909 fontfileloader_Release,
1910 fontfileloader_CreateStreamFromKey
1913 static void test_CreateCustomFontFileReference(void)
1915 IDWriteFontFileLoader floader = { &dwritefontfileloadervtbl };
1916 IDWriteFontFileLoader floader2 = { &dwritefontfileloadervtbl };
1917 IDWriteFontFileLoader floader3 = { &dwritefontfileloadervtbl };
1918 IDWriteFactory *factory, *factory2;
1919 IDWriteFontFile *file, *file2;
1920 BOOL support;
1921 DWRITE_FONT_FILE_TYPE file_type;
1922 DWRITE_FONT_FACE_TYPE face_type;
1923 UINT32 count;
1924 IDWriteFontFace *face, *face2;
1925 HRESULT hr;
1926 HRSRC fontrsrc;
1927 UINT32 codePoints[1] = {0xa8};
1928 UINT16 indices[2];
1930 factory = create_factory();
1931 factory2 = create_factory();
1933 hr = IDWriteFactory_RegisterFontFileLoader(factory, NULL);
1934 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1935 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
1936 ok(hr == S_OK, "got 0x%08x\n", hr);
1937 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader2);
1938 ok(hr == S_OK, "got 0x%08x\n", hr);
1939 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
1940 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1941 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1942 ok(hr == S_OK, "got 0x%08x\n", hr);
1944 file = NULL;
1945 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &file);
1946 ok(hr == S_OK, "got 0x%08x\n", hr);
1947 IDWriteFontFile_Release(file);
1949 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader3, &file);
1950 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1952 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, NULL, &file);
1953 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1955 file = NULL;
1956 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &file);
1957 ok(hr == S_OK, "got 0x%08x\n", hr);
1959 file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE;
1960 face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE;
1961 support = TRUE;
1962 count = 1;
1963 hr = IDWriteFontFile_Analyze(file, &support, &file_type, &face_type, &count);
1964 ok(hr == 0x8faecafe, "got 0x%08x\n", hr);
1965 ok(support == FALSE, "got %i\n", support);
1966 ok(file_type == DWRITE_FONT_FILE_TYPE_UNKNOWN, "got %i\n", file_type);
1967 ok(face_type == DWRITE_FONT_FACE_TYPE_UNKNOWN, "got %i\n", face_type);
1968 ok(count == 0, "got %i\n", count);
1970 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_CFF, 1, &file, 0, 0, &face);
1971 ok(hr == 0x8faecafe, "got 0x%08x\n", hr);
1972 IDWriteFontFile_Release(file);
1974 fontrsrc = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1975 ok(fontrsrc != NULL, "Failed to find font resource\n");
1977 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontrsrc, sizeof(HRSRC), &rloader, &file);
1978 ok(hr == S_OK, "got 0x%08x\n", hr);
1980 file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1981 face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1982 support = FALSE;
1983 count = 0;
1984 hr = IDWriteFontFile_Analyze(file, &support, &file_type, &face_type, &count);
1985 ok(hr == S_OK, "got 0x%08x\n", hr);
1986 ok(support == TRUE, "got %i\n", support);
1987 ok(file_type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", file_type);
1988 ok(face_type == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face_type);
1989 ok(count == 1, "got %i\n", count);
1991 /* invalid index */
1992 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 1, DWRITE_FONT_SIMULATIONS_NONE, &face);
1993 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1995 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face);
1996 ok(hr == S_OK, "got 0x%08x\n", hr);
1998 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
1999 ok(hr == S_OK, "got 0x%08x\n", hr);
2000 /* fontface instances are reused starting with win7 */
2001 ok(face == face2 || broken(face != face2), "got %p, %p\n", face, face2);
2002 IDWriteFontFace_Release(face2);
2004 /* file was created with different factory */
2005 face2 = NULL;
2006 hr = IDWriteFactory_CreateFontFace(factory2, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
2007 todo_wine
2008 ok(hr == S_OK, "got 0x%08x\n", hr);
2009 if (face2)
2010 IDWriteFontFace_Release(face2);
2012 file2 = NULL;
2013 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontrsrc, sizeof(HRSRC), &rloader, &file2);
2014 ok(hr == S_OK, "got 0x%08x\n", hr);
2015 ok(file != file2, "got %p, %p\n", file, file2);
2017 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file2, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
2018 ok(hr == S_OK, "got 0x%08x\n", hr);
2019 /* fontface instances are reused starting with win7 */
2020 ok(face == face2 || broken(face != face2), "got %p, %p\n", face, face2);
2021 IDWriteFontFace_Release(face2);
2022 IDWriteFontFile_Release(file2);
2024 hr = IDWriteFontFace_GetGlyphIndices(face, NULL, 0, NULL);
2025 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* win8 */, "got 0x%08x\n", hr);
2027 hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 0, NULL);
2028 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* win8 */, "got 0x%08x\n", hr);
2030 hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 0, indices);
2031 ok(hr == S_OK, "got 0x%08x\n", hr);
2033 hr = IDWriteFontFace_GetGlyphIndices(face, NULL, 0, indices);
2034 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* win8 */, "got 0x%08x\n", hr);
2036 indices[0] = indices[1] = 11;
2037 hr = IDWriteFontFace_GetGlyphIndices(face, NULL, 1, indices);
2038 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2039 ok(indices[0] == 0, "got index %i\n", indices[0]);
2040 ok(indices[1] == 11, "got index %i\n", indices[1]);
2042 if (0) /* crashes on native */
2043 hr = IDWriteFontFace_GetGlyphIndices(face, NULL, 1, NULL);
2045 hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 1, indices);
2046 ok(hr == S_OK, "got 0x%08x\n", hr);
2047 ok(indices[0] == 6, "got index %i\n", indices[0]);
2048 IDWriteFontFace_Release(face);
2049 IDWriteFontFile_Release(file);
2051 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
2052 ok(hr == S_OK, "got 0x%08x\n", hr);
2053 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
2054 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2055 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader2);
2056 ok(hr == S_OK, "got 0x%08x\n", hr);
2057 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
2058 ok(hr == S_OK, "got 0x%08x\n", hr);
2060 IDWriteFactory_Release(factory2);
2061 IDWriteFactory_Release(factory);
2064 static void test_CreateFontFileReference(void)
2066 HRESULT hr;
2067 IDWriteFontFile *ffile = NULL;
2068 BOOL support;
2069 DWRITE_FONT_FILE_TYPE type;
2070 DWRITE_FONT_FACE_TYPE face;
2071 UINT32 count;
2072 IDWriteFontFace *fface = NULL;
2073 IDWriteFactory *factory;
2074 WCHAR *path;
2076 path = create_testfontfile(test_fontfile);
2077 factory = create_factory();
2079 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &ffile);
2080 ok(hr == S_OK, "got 0x%08x\n",hr);
2082 support = FALSE;
2083 type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
2084 face = DWRITE_FONT_FACE_TYPE_CFF;
2085 count = 0;
2086 hr = IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
2087 ok(hr == S_OK, "got 0x%08x\n", hr);
2088 ok(support == TRUE, "got %i\n", support);
2089 ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type);
2090 ok(face == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face);
2091 ok(count == 1, "got %i\n", count);
2093 hr = IDWriteFactory_CreateFontFace(factory, face, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fface);
2094 ok(hr == S_OK, "got 0x%08x\n", hr);
2096 IDWriteFontFace_Release(fface);
2097 IDWriteFontFile_Release(ffile);
2098 IDWriteFactory_Release(factory);
2100 DELETE_FONTFILE(path);
2103 static void test_shared_isolated(void)
2105 IDWriteFactory *isolated, *isolated2;
2106 IDWriteFactory *shared, *shared2;
2107 HRESULT hr;
2109 /* invalid type */
2110 shared = NULL;
2111 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&shared);
2112 ok(hr == S_OK, "got 0x%08x\n", hr);
2113 ok(shared != NULL, "got %p\n", shared);
2114 IDWriteFactory_Release(shared);
2116 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared);
2117 ok(hr == S_OK, "got 0x%08x\n", hr);
2119 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
2120 ok(hr == S_OK, "got 0x%08x\n", hr);
2121 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
2123 IDWriteFactory_Release(shared);
2124 IDWriteFactory_Release(shared2);
2126 /* we got 2 references, released 2 - still same pointer is returned */
2127 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
2128 ok(hr == S_OK, "got 0x%08x\n", hr);
2129 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
2130 IDWriteFactory_Release(shared2);
2132 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated);
2133 ok(hr == S_OK, "got 0x%08x\n", hr);
2135 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated2);
2136 ok(hr == S_OK, "got 0x%08x\n", hr);
2137 ok(isolated != isolated2, "got %p, and %p\n", isolated, isolated2);
2138 IDWriteFactory_Release(isolated2);
2140 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&isolated2);
2141 ok(hr == S_OK, "got 0x%08x\n", hr);
2142 ok(shared != isolated2, "got %p, and %p\n", shared, isolated2);
2144 IDWriteFactory_Release(isolated);
2145 IDWriteFactory_Release(isolated2);
2148 static void test_GetUnicodeRanges(void)
2150 DWRITE_UNICODE_RANGE *ranges, r;
2151 IDWriteFontFile *ffile = NULL;
2152 IDWriteFontFace1 *fontface1;
2153 IDWriteFontFace *fontface;
2154 IDWriteFactory *factory;
2155 UINT32 count;
2156 HRESULT hr;
2157 HRSRC font;
2159 factory = create_factory();
2161 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
2162 ok(hr == S_OK, "got 0x%08x\n", hr);
2164 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
2165 ok(font != NULL, "Failed to find font resource\n");
2167 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
2168 ok(hr == S_OK, "got 0x%08x\n", hr);
2170 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
2171 ok(hr == S_OK, "got 0x%08x\n", hr);
2172 IDWriteFontFile_Release(ffile);
2174 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
2175 IDWriteFontFace_Release(fontface);
2176 if (hr != S_OK) {
2177 win_skip("GetUnicodeRanges() is not supported.\n");
2178 IDWriteFactory_Release(factory);
2179 return;
2182 count = 0;
2183 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 0, NULL, &count);
2184 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
2185 ok(count > 0, "got %u\n", count);
2187 count = 1;
2188 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, NULL, &count);
2189 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2190 ok(count == 0, "got %u\n", count);
2192 count = 0;
2193 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, &r, &count);
2194 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
2195 ok(count > 1, "got %u\n", count);
2197 ranges = heap_alloc(count*sizeof(DWRITE_UNICODE_RANGE));
2198 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, count, ranges, &count);
2199 ok(hr == S_OK, "got 0x%08x\n", hr);
2201 ranges[0].first = ranges[0].last = 0;
2202 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, ranges, &count);
2203 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
2204 ok(ranges[0].first != 0 && ranges[0].last != 0, "got 0x%x-0x%0x\n", ranges[0].first, ranges[0].last);
2206 heap_free(ranges);
2208 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
2209 ok(hr == S_OK, "got 0x%08x\n", hr);
2211 IDWriteFontFace1_Release(fontface1);
2212 IDWriteFactory_Release(factory);
2215 static void test_GetFontFromFontFace(void)
2217 IDWriteFontFace *fontface, *fontface2;
2218 IDWriteFontCollection *collection;
2219 IDWriteFont *font, *font2, *font3;
2220 IDWriteFontFamily *family;
2221 IDWriteFactory *factory;
2222 IDWriteFontFile *file;
2223 WCHAR *path;
2224 HRESULT hr;
2226 factory = create_factory();
2228 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
2229 ok(hr == S_OK, "got 0x%08x\n", hr);
2231 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
2232 ok(hr == S_OK, "got 0x%08x\n", hr);
2234 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2235 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2236 ok(hr == S_OK, "got 0x%08x\n", hr);
2238 hr = IDWriteFont_CreateFontFace(font, &fontface);
2239 ok(hr == S_OK, "got 0x%08x\n", hr);
2241 font2 = NULL;
2242 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font2);
2243 ok(hr == S_OK, "got 0x%08x\n", hr);
2244 ok(font2 != font, "got %p, %p\n", font2, font);
2246 font3 = NULL;
2247 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font3);
2248 ok(hr == S_OK, "got 0x%08x\n", hr);
2249 ok(font3 != font && font3 != font2, "got %p, %p, %p\n", font3, font2, font);
2251 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
2252 ok(hr == S_OK, "got 0x%08x\n", hr);
2253 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
2254 IDWriteFontFace_Release(fontface2);
2256 hr = IDWriteFont_CreateFontFace(font3, &fontface2);
2257 ok(hr == S_OK, "got 0x%08x\n", hr);
2258 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
2259 IDWriteFontFace_Release(fontface2);
2260 IDWriteFontFace_Release(fontface);
2261 IDWriteFont_Release(font3);
2262 IDWriteFactory_Release(factory);
2264 /* fontface that wasn't created from this collection */
2265 factory = create_factory();
2266 path = create_testfontfile(test_fontfile);
2268 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2269 ok(hr == S_OK, "got 0x%08x\n",hr);
2271 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
2272 ok(hr == S_OK, "got 0x%08x\n", hr);
2273 IDWriteFontFile_Release(file);
2275 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font3);
2276 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
2277 ok(font3 == NULL, "got %p\n", font3);
2278 IDWriteFontFace_Release(fontface);
2280 IDWriteFont_Release(font);
2281 IDWriteFont_Release(font2);
2282 IDWriteFontFamily_Release(family);
2283 IDWriteFontCollection_Release(collection);
2284 IDWriteFactory_Release(factory);
2285 DELETE_FONTFILE(path);
2288 static IDWriteFont *get_font(IDWriteFactory *factory, const WCHAR *name, DWRITE_FONT_STYLE style)
2290 IDWriteFontCollection *collection;
2291 IDWriteFontFamily *family;
2292 IDWriteFont *font = NULL;
2293 UINT32 index;
2294 BOOL exists;
2295 HRESULT hr;
2297 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
2298 ok(hr == S_OK, "got 0x%08x\n", hr);
2300 index = ~0;
2301 exists = FALSE;
2302 hr = IDWriteFontCollection_FindFamilyName(collection, name, &index, &exists);
2303 ok(hr == S_OK, "got 0x%08x\n", hr);
2304 if (!exists) goto not_found;
2306 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
2307 ok(hr == S_OK, "got 0x%08x\n", hr);
2309 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2310 DWRITE_FONT_STRETCH_NORMAL, style, &font);
2311 ok(hr == S_OK, "got 0x%08x\n", hr);
2313 IDWriteFontFamily_Release(family);
2314 not_found:
2315 IDWriteFontCollection_Release(collection);
2316 return font;
2319 static IDWriteFont *get_tahoma_instance(IDWriteFactory *factory, DWRITE_FONT_STYLE style)
2321 IDWriteFont *font = get_font(factory, tahomaW, style);
2322 ok(font != NULL, "failed to get Tahoma\n");
2323 return font;
2326 static void test_GetFirstMatchingFont(void)
2328 DWRITE_FONT_SIMULATIONS simulations;
2329 IDWriteFont *font, *font2;
2330 IDWriteFactory *factory;
2332 factory = create_factory();
2334 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
2335 font2 = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
2336 ok(font != font2, "got %p, %p\n", font, font2);
2337 IDWriteFont_Release(font);
2338 IDWriteFont_Release(font2);
2340 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_ITALIC);
2341 simulations = IDWriteFont_GetSimulations(font);
2342 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "%d\n", simulations);
2343 IDWriteFont_Release(font);
2345 IDWriteFactory_Release(factory);
2348 static void test_GetInformationalStrings(void)
2350 IDWriteLocalizedStrings *strings, *strings2;
2351 IDWriteFontCollection *collection;
2352 IDWriteFontFamily *family;
2353 IDWriteFactory *factory;
2354 IDWriteFont *font;
2355 BOOL exists;
2356 HRESULT hr;
2358 factory = create_factory();
2360 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
2361 ok(hr == S_OK, "got 0x%08x\n", hr);
2363 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
2364 ok(hr == S_OK, "got 0x%08x\n", hr);
2366 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2367 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2368 ok(hr == S_OK, "got 0x%08x\n", hr);
2370 exists = TRUE;
2371 strings = (void*)0xdeadbeef;
2372 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1, &strings, &exists);
2373 ok(hr == S_OK, "got 0x%08x\n", hr);
2374 ok(exists == FALSE, "got %d\n", exists);
2375 ok(strings == NULL, "got %p\n", strings);
2377 exists = TRUE;
2378 strings = NULL;
2379 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_NONE, &strings, &exists);
2380 ok(hr == S_OK, "got 0x%08x\n", hr);
2381 ok(exists == FALSE, "got %d\n", exists);
2383 exists = FALSE;
2384 strings = NULL;
2385 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists);
2386 ok(hr == S_OK, "got 0x%08x\n", hr);
2387 ok(exists == TRUE, "got %d\n", exists);
2389 /* strings instance is not reused */
2390 strings2 = NULL;
2391 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings2, &exists);
2392 ok(hr == S_OK, "got 0x%08x\n", hr);
2393 ok(strings2 != strings, "got %p, %p\n", strings2, strings);
2395 IDWriteLocalizedStrings_Release(strings);
2396 IDWriteLocalizedStrings_Release(strings2);
2397 IDWriteFont_Release(font);
2398 IDWriteFontFamily_Release(family);
2399 IDWriteFontCollection_Release(collection);
2400 IDWriteFactory_Release(factory);
2403 static void test_GetGdiInterop(void)
2405 IDWriteGdiInterop *interop, *interop2;
2406 IDWriteFactory *factory, *factory2;
2407 IDWriteFont *font;
2408 LOGFONTW logfont;
2409 HRESULT hr;
2411 factory = create_factory();
2413 interop = NULL;
2414 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2415 ok(hr == S_OK, "got 0x%08x\n", hr);
2417 interop2 = NULL;
2418 hr = IDWriteFactory_GetGdiInterop(factory, &interop2);
2419 ok(hr == S_OK, "got 0x%08x\n", hr);
2420 ok(interop == interop2, "got %p, %p\n", interop, interop2);
2421 IDWriteGdiInterop_Release(interop2);
2423 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory2);
2424 ok(hr == S_OK, "got 0x%08x\n", hr);
2426 /* each factory gets its own interop */
2427 interop2 = NULL;
2428 hr = IDWriteFactory_GetGdiInterop(factory2, &interop2);
2429 ok(hr == S_OK, "got 0x%08x\n", hr);
2430 ok(interop != interop2, "got %p, %p\n", interop, interop2);
2432 /* release factory - interop still works */
2433 IDWriteFactory_Release(factory2);
2435 memset(&logfont, 0, sizeof(logfont));
2436 logfont.lfHeight = 12;
2437 logfont.lfWidth = 12;
2438 logfont.lfWeight = FW_NORMAL;
2439 logfont.lfItalic = 1;
2440 lstrcpyW(logfont.lfFaceName, tahomaW);
2442 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop2, &logfont, &font);
2443 ok(hr == S_OK, "got 0x%08x\n", hr);
2444 IDWriteFont_Release(font);
2446 IDWriteGdiInterop_Release(interop2);
2447 IDWriteGdiInterop_Release(interop);
2448 IDWriteFactory_Release(factory);
2451 static void test_CreateFontFaceFromHdc(void)
2453 IDWriteGdiInterop *interop;
2454 IDWriteFontFace *fontface;
2455 IDWriteFactory *factory;
2456 HFONT hfont, oldhfont;
2457 LOGFONTW logfont;
2458 HRESULT hr;
2459 HDC hdc;
2461 factory = create_factory();
2463 interop = NULL;
2464 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2465 ok(hr == S_OK, "got 0x%08x\n", hr);
2467 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, NULL, &fontface);
2468 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2470 memset(&logfont, 0, sizeof(logfont));
2471 logfont.lfHeight = 12;
2472 logfont.lfWidth = 12;
2473 logfont.lfWeight = FW_NORMAL;
2474 logfont.lfItalic = 1;
2475 lstrcpyW(logfont.lfFaceName, tahomaW);
2477 hfont = CreateFontIndirectW(&logfont);
2478 hdc = CreateCompatibleDC(0);
2479 oldhfont = SelectObject(hdc, hfont);
2481 fontface = NULL;
2482 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, hdc, &fontface);
2483 ok(hr == S_OK, "got 0x%08x\n", hr);
2484 IDWriteFontFace_Release(fontface);
2485 DeleteObject(SelectObject(hdc, oldhfont));
2486 DeleteDC(hdc);
2488 IDWriteGdiInterop_Release(interop);
2489 IDWriteFactory_Release(factory);
2492 static void test_GetSimulations(void)
2494 DWRITE_FONT_SIMULATIONS simulations;
2495 IDWriteGdiInterop *interop;
2496 IDWriteFontFace *fontface;
2497 IDWriteFactory *factory;
2498 IDWriteFont *font;
2499 LOGFONTW logfont;
2500 HRESULT hr;
2502 factory = create_factory();
2504 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2505 ok(hr == S_OK, "got 0x%08x\n", hr);
2507 memset(&logfont, 0, sizeof(logfont));
2508 logfont.lfHeight = 12;
2509 logfont.lfWidth = 12;
2510 logfont.lfWeight = FW_NORMAL;
2511 logfont.lfItalic = 1;
2512 lstrcpyW(logfont.lfFaceName, tahomaW);
2514 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2515 ok(hr == S_OK, "got 0x%08x\n", hr);
2517 simulations = IDWriteFont_GetSimulations(font);
2518 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "got %d\n", simulations);
2519 hr = IDWriteFont_CreateFontFace(font, &fontface);
2520 ok(hr == S_OK, "got 0x%08x\n", hr);
2521 simulations = IDWriteFontFace_GetSimulations(fontface);
2522 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "got %d\n", simulations);
2523 IDWriteFontFace_Release(fontface);
2524 IDWriteFont_Release(font);
2526 memset(&logfont, 0, sizeof(logfont));
2527 logfont.lfHeight = 12;
2528 logfont.lfWidth = 12;
2529 logfont.lfWeight = FW_NORMAL;
2530 logfont.lfItalic = 0;
2531 lstrcpyW(logfont.lfFaceName, tahomaW);
2533 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2534 ok(hr == S_OK, "got 0x%08x\n", hr);
2536 simulations = IDWriteFont_GetSimulations(font);
2537 ok(simulations == DWRITE_FONT_SIMULATIONS_NONE, "got %d\n", simulations);
2538 hr = IDWriteFont_CreateFontFace(font, &fontface);
2539 ok(hr == S_OK, "got 0x%08x\n", hr);
2540 simulations = IDWriteFontFace_GetSimulations(fontface);
2541 ok(simulations == DWRITE_FONT_SIMULATIONS_NONE, "got %d\n", simulations);
2542 IDWriteFontFace_Release(fontface);
2543 IDWriteFont_Release(font);
2545 IDWriteGdiInterop_Release(interop);
2546 IDWriteFactory_Release(factory);
2549 static void test_GetFaceNames(void)
2551 static const WCHAR obliqueW[] = {'O','b','l','i','q','u','e',0};
2552 static const WCHAR enus2W[] = {'e','n','-','U','s',0};
2553 static const WCHAR enusW[] = {'e','n','-','u','s',0};
2554 IDWriteLocalizedStrings *strings, *strings2;
2555 IDWriteGdiInterop *interop;
2556 IDWriteFactory *factory;
2557 UINT32 count, index;
2558 IDWriteFont *font;
2559 LOGFONTW logfont;
2560 WCHAR buffW[255];
2561 BOOL exists;
2562 HRESULT hr;
2564 factory = create_factory();
2566 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2567 ok(hr == S_OK, "got 0x%08x\n", hr);
2569 memset(&logfont, 0, sizeof(logfont));
2570 logfont.lfHeight = 12;
2571 logfont.lfWidth = 12;
2572 logfont.lfWeight = FW_NORMAL;
2573 logfont.lfItalic = 1;
2574 lstrcpyW(logfont.lfFaceName, tahomaW);
2576 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2577 ok(hr == S_OK, "got 0x%08x\n", hr);
2579 hr = IDWriteFont_GetFaceNames(font, &strings);
2580 ok(hr == S_OK, "got 0x%08x\n", hr);
2582 hr = IDWriteFont_GetFaceNames(font, &strings2);
2583 ok(hr == S_OK, "got 0x%08x\n", hr);
2584 ok(strings != strings2, "got %p, %p\n", strings2, strings);
2585 IDWriteLocalizedStrings_Release(strings2);
2587 count = IDWriteLocalizedStrings_GetCount(strings);
2588 ok(count == 1, "got %d\n", count);
2590 index = 1;
2591 exists = FALSE;
2592 hr = IDWriteLocalizedStrings_FindLocaleName(strings, enus2W, &index, &exists);
2593 ok(hr == S_OK, "got 0x%08x\n", hr);
2594 ok(index == 0 && exists, "got %d, %d\n", index, exists);
2596 count = 0;
2597 hr = IDWriteLocalizedStrings_GetLocaleNameLength(strings, 1, &count);
2598 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2599 ok(count == ~0, "got %d\n", count);
2601 /* for simulated faces names are also simulated */
2602 buffW[0] = 0;
2603 hr = IDWriteLocalizedStrings_GetLocaleName(strings, 0, buffW, sizeof(buffW)/sizeof(WCHAR));
2604 ok(hr == S_OK, "got 0x%08x\n", hr);
2605 ok(!lstrcmpW(buffW, enusW), "got %s\n", wine_dbgstr_w(buffW));
2607 buffW[0] = 0;
2608 hr = IDWriteLocalizedStrings_GetString(strings, 0, buffW, sizeof(buffW)/sizeof(WCHAR));
2609 ok(hr == S_OK, "got 0x%08x\n", hr);
2610 ok(!lstrcmpW(buffW, obliqueW), "got %s\n", wine_dbgstr_w(buffW));
2611 IDWriteLocalizedStrings_Release(strings);
2613 IDWriteFont_Release(font);
2614 IDWriteGdiInterop_Release(interop);
2615 IDWriteFactory_Release(factory);
2618 struct local_refkey
2620 FILETIME writetime;
2621 WCHAR name[1];
2624 static void test_TryGetFontTable(void)
2626 IDWriteLocalFontFileLoader *localloader;
2627 WIN32_FILE_ATTRIBUTE_DATA info;
2628 const struct local_refkey *key;
2629 IDWriteFontFileLoader *loader;
2630 const void *table, *table2;
2631 IDWriteFontFace *fontface;
2632 void *context, *context2;
2633 IDWriteFactory *factory;
2634 IDWriteFontFile *file;
2635 WCHAR buffW[MAX_PATH];
2636 BOOL exists, ret;
2637 UINT32 size, len;
2638 WCHAR *path;
2639 HRESULT hr;
2641 path = create_testfontfile(test_fontfile);
2643 factory = create_factory();
2645 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2646 ok(hr == S_OK, "got 0x%08x\n",hr);
2648 key = NULL;
2649 size = 0;
2650 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2651 ok(hr == S_OK, "got 0x%08x\n", hr);
2652 ok(size != 0, "got %u\n", size);
2654 ret = GetFileAttributesExW(path, GetFileExInfoStandard, &info);
2655 ok(ret, "got %d\n", ret);
2656 ok(!memcmp(&info.ftLastWriteTime, &key->writetime, sizeof(key->writetime)), "got wrong write time\n");
2658 hr = IDWriteFontFile_GetLoader(file, &loader);
2659 ok(hr == S_OK, "got 0x%08x\n", hr);
2660 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2661 IDWriteFontFileLoader_Release(loader);
2663 hr = IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader, key, size, &len);
2664 ok(hr == S_OK, "got 0x%08x\n", hr);
2665 ok(lstrlenW(key->name) == len, "path length %d\n", len);
2667 hr = IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader, key, size, buffW, sizeof(buffW)/sizeof(WCHAR));
2668 ok(hr == S_OK, "got 0x%08x\n", hr);
2669 ok(!lstrcmpW(buffW, key->name), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(key->name));
2670 IDWriteLocalFontFileLoader_Release(localloader);
2672 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, 0, &fontface);
2673 ok(hr == S_OK, "got 0x%08x\n",hr);
2675 exists = FALSE;
2676 context = (void*)0xdeadbeef;
2677 table = NULL;
2678 hr = IDWriteFontFace_TryGetFontTable(fontface, MS_CMAP_TAG, &table, &size, &context, &exists);
2679 ok(hr == S_OK, "got 0x%08x\n",hr);
2680 ok(exists == TRUE, "got %d\n", exists);
2681 ok(context == NULL && table != NULL, "cmap: context %p, table %p\n", context, table);
2683 exists = FALSE;
2684 context2 = (void*)0xdeadbeef;
2685 table2 = NULL;
2686 hr = IDWriteFontFace_TryGetFontTable(fontface, MS_CMAP_TAG, &table2, &size, &context2, &exists);
2687 ok(hr == S_OK, "got 0x%08x\n",hr);
2688 ok(exists == TRUE, "got %d\n", exists);
2689 ok(context2 == context && table2 == table, "cmap: context2 %p, table2 %p\n", context2, table2);
2691 IDWriteFontFace_ReleaseFontTable(fontface, context2);
2692 IDWriteFontFace_ReleaseFontTable(fontface, context);
2694 IDWriteFontFace_Release(fontface);
2695 IDWriteFontFile_Release(file);
2696 IDWriteFactory_Release(factory);
2697 DELETE_FONTFILE(path);
2700 static void test_ConvertFontToLOGFONT(void)
2702 IDWriteFactory *factory, *factory2;
2703 IDWriteFontCollection *collection;
2704 IDWriteGdiInterop *interop;
2705 IDWriteFontFamily *family;
2706 IDWriteFont *font;
2707 LOGFONTW logfont;
2708 BOOL system;
2709 HRESULT hr;
2711 factory = create_factory();
2712 factory2 = create_factory();
2714 interop = NULL;
2715 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2716 ok(hr == S_OK, "got 0x%08x\n", hr);
2718 hr = IDWriteFactory_GetSystemFontCollection(factory2, &collection, FALSE);
2719 ok(hr == S_OK, "got 0x%08x\n", hr);
2721 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
2722 ok(hr == S_OK, "got 0x%08x\n", hr);
2724 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2725 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2726 ok(hr == S_OK, "got 0x%08x\n", hr);
2728 if (0) { /* crashes on native */
2729 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, NULL, NULL);
2730 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, &logfont, NULL);
2731 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, font, NULL, &system);
2733 system = TRUE;
2734 hr = IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, &logfont, &system);
2735 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2736 ok(!system, "got %d\n", system);
2738 system = FALSE;
2739 memset(&logfont, 0, sizeof(logfont));
2740 hr = IDWriteGdiInterop_ConvertFontToLOGFONT(interop, font, &logfont, &system);
2741 ok(hr == S_OK, "got 0x%08x\n", hr);
2742 ok(system, "got %d\n", system);
2743 ok(logfont.lfFaceName[0] != 0, "got face name %s\n", wine_dbgstr_w(logfont.lfFaceName));
2745 IDWriteFactory_Release(factory2);
2747 IDWriteFontCollection_Release(collection);
2748 IDWriteFontFamily_Release(family);
2749 IDWriteFont_Release(font);
2750 IDWriteGdiInterop_Release(interop);
2751 IDWriteFactory_Release(factory);
2754 static void test_CreateStreamFromKey(void)
2756 IDWriteLocalFontFileLoader *localloader;
2757 IDWriteFontFileStream *stream, *stream2;
2758 IDWriteFontFileLoader *loader;
2759 IDWriteFactory *factory;
2760 IDWriteFontFile *file;
2761 UINT64 writetime;
2762 WCHAR *path;
2763 void *key;
2764 UINT32 size;
2765 HRESULT hr;
2767 factory = create_factory();
2769 path = create_testfontfile(test_fontfile);
2771 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2772 ok(hr == S_OK, "got 0x%08x\n",hr);
2774 key = NULL;
2775 size = 0;
2776 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2777 ok(hr == S_OK, "got 0x%08x\n", hr);
2778 ok(size != 0, "got %u\n", size);
2780 hr = IDWriteFontFile_GetLoader(file, &loader);
2781 ok(hr == S_OK, "got 0x%08x\n", hr);
2782 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2783 IDWriteFontFileLoader_Release(loader);
2785 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2786 ok(hr == S_OK, "got 0x%08x\n", hr);
2787 EXPECT_REF(stream, 1);
2789 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream2);
2790 ok(hr == S_OK, "got 0x%08x\n", hr);
2791 ok(stream == stream2 || broken(stream != stream2) /* Win7 SP0 */, "got %p, %p\n", stream, stream2);
2792 if (stream == stream2)
2793 EXPECT_REF(stream, 2);
2794 IDWriteFontFileStream_Release(stream);
2795 IDWriteFontFileStream_Release(stream2);
2797 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2798 ok(hr == S_OK, "got 0x%08x\n", hr);
2799 EXPECT_REF(stream, 1);
2801 writetime = 0;
2802 hr = IDWriteFontFileStream_GetLastWriteTime(stream, &writetime);
2803 ok(hr == S_OK, "got 0x%08x\n", hr);
2804 ok(writetime != 0, "got %08x%08x\n", (UINT)(writetime >> 32), (UINT)writetime);
2806 IDWriteFontFileStream_Release(stream);
2808 IDWriteLocalFontFileLoader_Release(localloader);
2809 IDWriteFactory_Release(factory);
2810 DELETE_FONTFILE(path);
2813 static void test_ReadFileFragment(void)
2815 IDWriteLocalFontFileLoader *localloader;
2816 IDWriteFontFileStream *stream;
2817 IDWriteFontFileLoader *loader;
2818 IDWriteFactory *factory;
2819 IDWriteFontFile *file;
2820 const void *fragment, *fragment2;
2821 void *key, *context, *context2;
2822 UINT64 filesize;
2823 UINT32 size;
2824 WCHAR *path;
2825 HRESULT hr;
2827 factory = create_factory();
2829 path = create_testfontfile(test_fontfile);
2831 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2832 ok(hr == S_OK, "got 0x%08x\n",hr);
2834 key = NULL;
2835 size = 0;
2836 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2837 ok(hr == S_OK, "got 0x%08x\n", hr);
2838 ok(size != 0, "got %u\n", size);
2840 hr = IDWriteFontFile_GetLoader(file, &loader);
2841 ok(hr == S_OK, "got 0x%08x\n", hr);
2842 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2843 IDWriteFontFileLoader_Release(loader);
2845 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2846 ok(hr == S_OK, "got 0x%08x\n", hr);
2848 hr = IDWriteFontFileStream_GetFileSize(stream, &filesize);
2849 ok(hr == S_OK, "got 0x%08x\n", hr);
2851 /* reading past the end of the stream */
2852 fragment = (void*)0xdeadbeef;
2853 context = (void*)0xdeadbeef;
2854 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize+1, &context);
2855 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2856 ok(context == NULL, "got %p\n", context);
2857 ok(fragment == NULL, "got %p\n", fragment);
2859 fragment = (void*)0xdeadbeef;
2860 context = (void*)0xdeadbeef;
2861 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize, &context);
2862 ok(hr == S_OK, "got 0x%08x\n", hr);
2863 ok(context == NULL, "got %p\n", context);
2864 ok(fragment != NULL, "got %p\n", fragment);
2866 fragment2 = (void*)0xdeadbeef;
2867 context2 = (void*)0xdeadbeef;
2868 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment2, 0, filesize, &context2);
2869 ok(hr == S_OK, "got 0x%08x\n", hr);
2870 ok(context2 == NULL, "got %p\n", context2);
2871 ok(fragment == fragment2, "got %p, %p\n", fragment, fragment2);
2873 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
2874 IDWriteFontFileStream_ReleaseFileFragment(stream, context2);
2876 /* fragment is released, try again */
2877 fragment = (void*)0xdeadbeef;
2878 context = (void*)0xdeadbeef;
2879 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize, &context);
2880 ok(hr == S_OK, "got 0x%08x\n", hr);
2881 ok(context == NULL, "got %p\n", context);
2882 ok(fragment == fragment2, "got %p, %p\n", fragment, fragment2);
2883 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
2885 IDWriteFontFileStream_Release(stream);
2886 IDWriteLocalFontFileLoader_Release(localloader);
2887 IDWriteFactory_Release(factory);
2888 DELETE_FONTFILE(path);
2891 static void test_GetDesignGlyphMetrics(void)
2893 DWRITE_GLYPH_METRICS metrics[2];
2894 IDWriteFontFace *fontface;
2895 IDWriteFactory *factory;
2896 IDWriteFontFile *file;
2897 UINT16 indices[2];
2898 UINT32 codepoint;
2899 WCHAR *path;
2900 HRESULT hr;
2902 factory = create_factory();
2904 path = create_testfontfile(test_fontfile);
2906 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
2907 ok(hr == S_OK, "got 0x%08x\n",hr);
2909 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file,
2910 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
2911 ok(hr == S_OK, "got 0x%08x\n",hr);
2912 IDWriteFontFile_Release(file);
2914 codepoint = 'A';
2915 indices[0] = 0;
2916 hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &indices[0]);
2917 ok(hr == S_OK, "got 0x%08x\n", hr);
2918 ok(indices[0] > 0, "got %u\n", indices[0]);
2920 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, NULL, 0, metrics, FALSE);
2921 ok(hr == E_INVALIDARG, "got 0x%08x\n",hr);
2923 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, NULL, 1, metrics, FALSE);
2924 ok(hr == E_INVALIDARG, "got 0x%08x\n",hr);
2926 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, indices, 0, metrics, FALSE);
2927 ok(hr == S_OK, "got 0x%08x\n",hr);
2929 /* missing glyphs are ignored */
2930 indices[1] = 1;
2931 memset(metrics, 0xcc, sizeof(metrics));
2932 hr = IDWriteFontFace_GetDesignGlyphMetrics(fontface, indices, 2, metrics, FALSE);
2933 ok(hr == S_OK, "got 0x%08x\n",hr);
2934 ok(metrics[0].advanceWidth == 1000, "got %d\n", metrics[0].advanceWidth);
2935 ok(metrics[1].advanceWidth == 0, "got %d\n", metrics[1].advanceWidth);
2937 IDWriteFontFace_Release(fontface);
2938 IDWriteFactory_Release(factory);
2939 DELETE_FONTFILE(path);
2942 static void test_IsMonospacedFont(void)
2944 static const WCHAR courierW[] = {'C','o','u','r','i','e','r',' ','N','e','w',0};
2945 IDWriteFontCollection *collection;
2946 IDWriteFactory *factory;
2947 UINT32 index;
2948 BOOL exists;
2949 HRESULT hr;
2951 factory = create_factory();
2952 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
2953 ok(hr == S_OK, "got 0x%08x\n", hr);
2955 exists = FALSE;
2956 hr = IDWriteFontCollection_FindFamilyName(collection, courierW, &index, &exists);
2957 ok(hr == S_OK, "got 0x%08x\n", hr);
2958 if (exists) {
2959 IDWriteFontFamily *family;
2960 IDWriteFont1 *font1;
2961 IDWriteFont *font;
2963 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
2964 ok(hr == S_OK, "got 0x%08x\n", hr);
2966 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2967 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2968 ok(hr == S_OK, "got 0x%08x\n", hr);
2969 IDWriteFontFamily_Release(family);
2971 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
2972 if (hr == S_OK) {
2973 IDWriteFontFace1 *fontface1;
2974 IDWriteFontFace *fontface;
2975 BOOL is_monospaced;
2977 is_monospaced = IDWriteFont1_IsMonospacedFont(font1);
2978 ok(is_monospaced, "got %d\n", is_monospaced);
2980 hr = IDWriteFont1_CreateFontFace(font1, &fontface);
2981 ok(hr == S_OK, "got 0x%08x\n", hr);
2982 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
2983 ok(hr == S_OK, "got 0x%08x\n", hr);
2984 is_monospaced = IDWriteFontFace1_IsMonospacedFont(fontface1);
2985 ok(is_monospaced, "got %d\n", is_monospaced);
2986 IDWriteFontFace1_Release(fontface1);
2988 IDWriteFontFace_Release(fontface);
2989 IDWriteFont1_Release(font1);
2991 else
2992 win_skip("IsMonospacedFont() is not supported.\n");
2994 else
2995 skip("Courier New font not found.\n");
2997 IDWriteFontCollection_Release(collection);
3000 static void test_GetDesignGlyphAdvances(void)
3002 IDWriteFontFace1 *fontface1;
3003 IDWriteFontFace *fontface;
3004 IDWriteFactory *factory;
3005 IDWriteFontFile *file;
3006 WCHAR *path;
3007 HRESULT hr;
3009 factory = create_factory();
3011 path = create_testfontfile(test_fontfile);
3013 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3014 ok(hr == S_OK, "got 0x%08x\n", hr);
3016 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file,
3017 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
3018 ok(hr == S_OK, "got 0x%08x\n", hr);
3019 IDWriteFontFile_Release(file);
3021 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3022 if (hr == S_OK) {
3023 UINT32 codepoint;
3024 UINT16 index;
3025 INT32 advance;
3027 codepoint = 'A';
3028 index = 0;
3029 hr = IDWriteFontFace1_GetGlyphIndices(fontface1, &codepoint, 1, &index);
3030 ok(hr == S_OK, "got 0x%08x\n", hr);
3031 ok(index > 0, "got %u\n", index);
3033 advance = 0;
3034 hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, &index, &advance, FALSE);
3035 ok(hr == S_OK, "got 0x%08x\n", hr);
3036 ok(advance == 1000, "got %i\n", advance);
3038 advance = 0;
3039 hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, &index, &advance, TRUE);
3040 ok(hr == S_OK, "got 0x%08x\n", hr);
3041 ok(advance == 2048, "got %i\n", advance);
3043 IDWriteFontFace1_Release(fontface1);
3045 else
3046 win_skip("GetDesignGlyphAdvances() is not supported.\n");
3048 IDWriteFontFace_Release(fontface);
3049 IDWriteFactory_Release(factory);
3050 DELETE_FONTFILE(path);
3053 static void test_GetGlyphRunOutline(void)
3055 DWRITE_GLYPH_OFFSET offsets[2];
3056 IDWriteFactory *factory;
3057 IDWriteFontFile *file;
3058 IDWriteFontFace *face;
3059 UINT32 codepoint;
3060 FLOAT advances[2];
3061 UINT16 glyphs[2];
3062 WCHAR *path;
3063 HRESULT hr;
3065 path = create_testfontfile(test_fontfile);
3066 factory = create_factory();
3068 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3069 ok(hr == S_OK, "got 0x%08x\n",hr);
3071 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face);
3072 ok(hr == S_OK, "got 0x%08x\n", hr);
3073 IDWriteFontFile_Release(file);
3075 codepoint = 'A';
3076 glyphs[0] = 0;
3077 hr = IDWriteFontFace_GetGlyphIndices(face, &codepoint, 1, glyphs);
3078 ok(hr == S_OK, "got 0x%08x\n", hr);
3079 ok(glyphs[0] > 0, "got %u\n", glyphs[0]);
3080 glyphs[1] = glyphs[0];
3082 hr = IDWriteFontFace_GetGlyphRunOutline(face, 2048.0, glyphs, advances, offsets, 1, FALSE, FALSE, NULL);
3083 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3085 hr = IDWriteFontFace_GetGlyphRunOutline(face, 2048.0, NULL, NULL, offsets, 1, FALSE, FALSE, &test_geomsink);
3086 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3088 advances[0] = 1.0;
3089 advances[1] = 0.0;
3091 offsets[0].advanceOffset = 1.0;
3092 offsets[0].ascenderOffset = 1.0;
3093 offsets[1].advanceOffset = 0.0;
3094 offsets[1].ascenderOffset = 0.0;
3096 /* default advances, no offsets */
3097 memset(g_startpoints, 0, sizeof(g_startpoints));
3098 g_startpoint_count = 0;
3099 SET_EXPECT(setfillmode);
3100 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 2, FALSE, FALSE, &test_geomsink);
3101 ok(hr == S_OK, "got 0x%08x\n", hr);
3102 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3103 if (g_startpoint_count == 2) {
3104 /* glyph advance of 500 is applied */
3105 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);
3106 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);
3108 CHECK_CALLED(setfillmode);
3110 /* default advances, no offsets, RTL */
3111 memset(g_startpoints, 0, sizeof(g_startpoints));
3112 g_startpoint_count = 0;
3113 SET_EXPECT(setfillmode);
3114 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 2, FALSE, TRUE, &test_geomsink);
3115 ok(hr == S_OK, "got 0x%08x\n", hr);
3116 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3117 if (g_startpoint_count == 2) {
3118 /* advance is -500 now */
3119 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);
3120 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);
3122 CHECK_CALLED(setfillmode);
3124 /* default advances, additional offsets */
3125 memset(g_startpoints, 0, sizeof(g_startpoints));
3126 g_startpoint_count = 0;
3127 SET_EXPECT(setfillmode);
3128 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, offsets, 2, FALSE, FALSE, &test_geomsink);
3129 ok(hr == S_OK, "got 0x%08x\n", hr);
3130 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3131 if (g_startpoint_count == 2) {
3132 /* offsets applied to first contour */
3133 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);
3134 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);
3136 CHECK_CALLED(setfillmode);
3138 /* default advances, additional offsets, RTL */
3139 memset(g_startpoints, 0, sizeof(g_startpoints));
3140 g_startpoint_count = 0;
3141 SET_EXPECT(setfillmode);
3142 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, offsets, 2, FALSE, TRUE, &test_geomsink);
3143 ok(hr == S_OK, "got 0x%08x\n", hr);
3144 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3145 if (g_startpoint_count == 2) {
3146 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);
3147 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);
3149 CHECK_CALLED(setfillmode);
3151 /* custom advances and offsets, offset turns total advance value to zero */
3152 memset(g_startpoints, 0, sizeof(g_startpoints));
3153 g_startpoint_count = 0;
3154 SET_EXPECT(setfillmode);
3155 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, advances, offsets, 2, FALSE, FALSE, &test_geomsink);
3156 ok(hr == S_OK, "got 0x%08x\n", hr);
3157 ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
3158 if (g_startpoint_count == 2) {
3159 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);
3160 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);
3162 CHECK_CALLED(setfillmode);
3164 /* 0 glyph count */
3165 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 0, FALSE, FALSE, &test_geomsink2);
3166 ok(hr == S_OK, "got 0x%08x\n", hr);
3168 IDWriteFactory_Release(factory);
3169 IDWriteFontFace_Release(face);
3170 DELETE_FONTFILE(path);
3172 /* space glyph */
3173 factory = create_factory();
3174 face = create_fontface(factory);
3176 codepoint = ' ';
3177 glyphs[0] = 0;
3178 hr = IDWriteFontFace_GetGlyphIndices(face, &codepoint, 1, glyphs);
3179 ok(hr == S_OK, "got 0x%08x\n", hr);
3180 ok(glyphs[0] > 0, "got %u\n", glyphs[0]);
3182 SET_EXPECT(setfillmode);
3183 hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 1, FALSE, FALSE, &test_geomsink2);
3184 ok(hr == S_OK, "got 0x%08x\n", hr);
3185 CHECK_CALLED(setfillmode);
3187 IDWriteFactory_Release(factory);
3188 IDWriteFontFace_Release(face);
3191 static void test_GetEudcFontCollection(void)
3193 IDWriteFontCollection *coll, *coll2;
3194 IDWriteFactory1 *factory1;
3195 IDWriteFactory *factory;
3196 HRESULT hr;
3198 factory = create_factory();
3200 hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory1, (void**)&factory1);
3201 IDWriteFactory_Release(factory);
3202 if (hr != S_OK) {
3203 win_skip("GetEudcFontCollection() is not supported.\n");
3204 return;
3207 hr = IDWriteFactory1_GetEudcFontCollection(factory1, &coll, FALSE);
3208 ok(hr == S_OK, "got 0x%08x\n", hr);
3209 hr = IDWriteFactory1_GetEudcFontCollection(factory1, &coll2, FALSE);
3210 ok(hr == S_OK, "got 0x%08x\n", hr);
3211 ok(coll == coll2, "got %p, %p\n", coll, coll2);
3212 IDWriteFontCollection_Release(coll);
3213 IDWriteFontCollection_Release(coll2);
3215 IDWriteFactory1_Release(factory1);
3218 static void test_GetCaretMetrics(void)
3220 DWRITE_FONT_METRICS1 metrics;
3221 IDWriteFontFace1 *fontface1;
3222 DWRITE_CARET_METRICS caret;
3223 IDWriteFontFace *fontface;
3224 IDWriteFactory *factory;
3225 IDWriteFontFile *file;
3226 IDWriteFont *font;
3227 WCHAR *path;
3228 HRESULT hr;
3230 path = create_testfontfile(test_fontfile);
3231 factory = create_factory();
3233 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3234 ok(hr == S_OK, "got 0x%08x\n", hr);
3236 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
3237 ok(hr == S_OK, "got 0x%08x\n", hr);
3238 IDWriteFontFile_Release(file);
3240 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3241 IDWriteFontFace_Release(fontface);
3242 if (hr != S_OK) {
3243 win_skip("GetCaretMetrics() is not supported.\n");
3244 IDWriteFactory_Release(factory);
3245 DELETE_FONTFILE(path);
3246 return;
3249 memset(&caret, 0xcc, sizeof(caret));
3250 IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
3251 ok(caret.slopeRise == 1, "got %d\n", caret.slopeRise);
3252 ok(caret.slopeRun == 0, "got %d\n", caret.slopeRun);
3253 ok(caret.offset == 0, "got %d\n", caret.offset);
3254 IDWriteFontFace1_Release(fontface1);
3255 IDWriteFactory_Release(factory);
3257 /* now with Tahoma Normal */
3258 factory = create_factory();
3259 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
3260 hr = IDWriteFont_CreateFontFace(font, &fontface);
3261 ok(hr == S_OK, "got 0x%08x\n", hr);
3262 IDWriteFont_Release(font);
3263 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3264 ok(hr == S_OK, "got 0x%08x\n", hr);
3265 IDWriteFontFace_Release(fontface);
3267 memset(&caret, 0xcc, sizeof(caret));
3268 IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
3269 ok(caret.slopeRise == 1, "got %d\n", caret.slopeRise);
3270 ok(caret.slopeRun == 0, "got %d\n", caret.slopeRun);
3271 ok(caret.offset == 0, "got %d\n", caret.offset);
3272 IDWriteFontFace1_Release(fontface1);
3274 /* simulated italic */
3275 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_ITALIC);
3276 hr = IDWriteFont_CreateFontFace(font, &fontface);
3277 ok(hr == S_OK, "got 0x%08x\n", hr);
3278 IDWriteFont_Release(font);
3279 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3280 ok(hr == S_OK, "got 0x%08x\n", hr);
3281 IDWriteFontFace_Release(fontface);
3283 IDWriteFontFace1_GetMetrics(fontface1, &metrics);
3285 memset(&caret, 0xcc, sizeof(caret));
3286 IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
3287 ok(caret.slopeRise == metrics.designUnitsPerEm, "got %d\n", caret.slopeRise);
3288 ok(caret.slopeRun > 0, "got %d\n", caret.slopeRun);
3289 ok(caret.offset == 0, "got %d\n", caret.offset);
3290 IDWriteFontFace1_Release(fontface1);
3292 IDWriteFactory_Release(factory);
3293 DELETE_FONTFILE(path);
3296 static void test_GetGlyphCount(void)
3298 IDWriteFontFace *fontface;
3299 IDWriteFactory *factory;
3300 IDWriteFontFile *file;
3301 UINT16 count;
3302 WCHAR *path;
3303 HRESULT hr;
3305 path = create_testfontfile(test_fontfile);
3306 factory = create_factory();
3308 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3309 ok(hr == S_OK, "got 0x%08x\n", hr);
3311 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
3312 ok(hr == S_OK, "got 0x%08x\n", hr);
3313 IDWriteFontFile_Release(file);
3315 count = IDWriteFontFace_GetGlyphCount(fontface);
3316 ok(count == 7, "got %u\n", count);
3318 IDWriteFontFace_Release(fontface);
3319 IDWriteFactory_Release(factory);
3320 DELETE_FONTFILE(path);
3323 static void test_GetKerningPairAdjustments(void)
3325 IDWriteFontFace1 *fontface1;
3326 IDWriteFontFace *fontface;
3327 IDWriteFactory *factory;
3328 IDWriteFontFile *file;
3329 WCHAR *path;
3330 HRESULT hr;
3332 path = create_testfontfile(test_fontfile);
3333 factory = create_factory();
3335 hr = IDWriteFactory_CreateFontFileReference(factory, path, NULL, &file);
3336 ok(hr == S_OK, "got 0x%08x\n", hr);
3338 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
3339 ok(hr == S_OK, "got 0x%08x\n", hr);
3340 IDWriteFontFile_Release(file);
3342 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
3343 if (hr == S_OK) {
3344 INT32 adjustments[1];
3346 hr = IDWriteFontFace1_GetKerningPairAdjustments(fontface1, 0, NULL, NULL);
3347 ok(hr == E_INVALIDARG || broken(hr == S_OK) /* win8 */, "got 0x%08x\n", hr);
3349 if (0) /* crashes on native */
3350 hr = IDWriteFontFace1_GetKerningPairAdjustments(fontface1, 1, NULL, NULL);
3352 adjustments[0] = 1;
3353 hr = IDWriteFontFace1_GetKerningPairAdjustments(fontface1, 1, NULL, adjustments);
3354 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3355 ok(adjustments[0] == 0, "got %d\n", adjustments[0]);
3357 IDWriteFontFace1_Release(fontface1);
3359 else
3360 win_skip("GetKerningPairAdjustments() is not supported.\n");
3362 IDWriteFontFace_Release(fontface);
3363 IDWriteFactory_Release(factory);
3364 DELETE_FONTFILE(path);
3367 static void test_CreateRenderingParams(void)
3369 IDWriteRenderingParams2 *params2;
3370 IDWriteRenderingParams1 *params1;
3371 IDWriteRenderingParams *params;
3372 DWRITE_RENDERING_MODE mode;
3373 IDWriteFactory *factory;
3374 HRESULT hr;
3376 factory = create_factory();
3378 hr = IDWriteFactory_CreateCustomRenderingParams(factory, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT,
3379 DWRITE_RENDERING_MODE_DEFAULT, &params);
3380 ok(hr == S_OK, "got 0x%08x\n", hr);
3382 hr = IDWriteRenderingParams_QueryInterface(params, &IID_IDWriteRenderingParams1, (void**)&params1);
3383 if (hr == S_OK) {
3384 FLOAT enhcontrast;
3386 /* test what enhanced contrast setting set by default to */
3387 enhcontrast = IDWriteRenderingParams1_GetGrayscaleEnhancedContrast(params1);
3388 ok(enhcontrast == 1.0, "got %.2f\n", enhcontrast);
3389 IDWriteRenderingParams1_Release(params1);
3391 hr = IDWriteRenderingParams_QueryInterface(params, &IID_IDWriteRenderingParams2, (void**)&params2);
3392 if (hr == S_OK) {
3393 DWRITE_GRID_FIT_MODE gridfit;
3395 /* default gridfit mode */
3396 gridfit = IDWriteRenderingParams2_GetGridFitMode(params2);
3397 ok(gridfit == DWRITE_GRID_FIT_MODE_DEFAULT, "got %d\n", gridfit);
3399 IDWriteRenderingParams2_Release(params2);
3401 else
3402 win_skip("IDWriteRenderingParams2 not supported.\n");
3404 else
3405 win_skip("IDWriteRenderingParams1 not supported.\n");
3407 IDWriteRenderingParams_Release(params);
3409 hr = IDWriteFactory_CreateRenderingParams(factory, &params);
3410 ok(hr == S_OK, "got 0x%08x\n", hr);
3412 mode = IDWriteRenderingParams_GetRenderingMode(params);
3413 ok(mode == DWRITE_RENDERING_MODE_DEFAULT, "got %d\n", mode);
3414 IDWriteRenderingParams_Release(params);
3416 IDWriteFactory_Release(factory);
3419 static void test_CreateGlyphRunAnalysis(void)
3421 static const DWRITE_RENDERING_MODE rendermodes[] = {
3422 DWRITE_RENDERING_MODE_ALIASED,
3423 DWRITE_RENDERING_MODE_GDI_CLASSIC,
3424 DWRITE_RENDERING_MODE_GDI_NATURAL,
3425 DWRITE_RENDERING_MODE_NATURAL,
3426 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC,
3429 IDWriteGlyphRunAnalysis *analysis;
3430 IDWriteFactory *factory;
3431 DWRITE_GLYPH_RUN run;
3432 IDWriteFontFace *face;
3433 UINT16 glyph;
3434 FLOAT advance;
3435 HRESULT hr;
3436 UINT32 ch;
3437 RECT rect;
3438 DWRITE_GLYPH_OFFSET offset;
3439 DWRITE_GLYPH_METRICS metrics;
3440 DWRITE_FONT_METRICS fm;
3441 int i;
3443 factory = create_factory();
3444 face = create_fontface(factory);
3446 ch = 'A';
3447 glyph = 0;
3448 hr = IDWriteFontFace_GetGlyphIndices(face, &ch, 1, &glyph);
3449 ok(hr == S_OK, "got 0x%08x\n", hr);
3450 ok(glyph > 0, "got %u\n", glyph);
3452 hr = IDWriteFontFace_GetDesignGlyphMetrics(face, &glyph, 1, &metrics, FALSE);
3453 ok(hr == S_OK, "got 0x%08x\n", hr);
3454 advance = metrics.advanceWidth;
3456 offset.advanceOffset = 0.0;
3457 offset.ascenderOffset = 0.0;
3459 run.fontFace = face;
3460 run.fontEmSize = 24.0;
3461 run.glyphCount = 1;
3462 run.glyphIndices = &glyph;
3463 run.glyphAdvances = &advance;
3464 run.glyphOffsets = &offset;
3465 run.isSideways = FALSE;
3466 run.bidiLevel = 0;
3468 /* default mode is not allowed */
3469 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3470 DWRITE_RENDERING_MODE_DEFAULT, DWRITE_MEASURING_MODE_NATURAL,
3471 0.0, 0.0, &analysis);
3472 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3474 /* outline too */
3475 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3476 DWRITE_RENDERING_MODE_OUTLINE, DWRITE_MEASURING_MODE_NATURAL,
3477 0.0, 0.0, &analysis);
3478 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3480 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3481 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
3482 0.0, 0.0, &analysis);
3483 ok(hr == S_OK, "got 0x%08x\n", hr);
3485 /* invalid texture type */
3486 memset(&rect, 0xcc, sizeof(rect));
3487 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1+1, &rect);
3488 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3489 ok(rect.left == 0 && rect.right == 0 &&
3490 rect.top == 0 && rect.bottom == 0, "unexpected rect\n");
3491 IDWriteGlyphRunAnalysis_Release(analysis);
3493 for (i = 0; i < sizeof(rendermodes)/sizeof(rendermodes[0]); i++) {
3494 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3495 rendermodes[i], DWRITE_MEASURING_MODE_NATURAL,
3496 0.0, 0.0, &analysis);
3497 ok(hr == S_OK, "got 0x%08x\n", hr);
3499 if (rendermodes[i] == DWRITE_RENDERING_MODE_ALIASED) {
3500 memset(&rect, 0, sizeof(rect));
3501 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3502 todo_wine {
3503 ok(hr == S_OK, "got 0x%08x\n", hr);
3504 ok(!IsRectEmpty(&rect), "got empty rect\n");
3506 rect.left = rect.top = 0;
3507 rect.bottom = rect.right = 1;
3508 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
3509 ok(hr == S_OK, "got 0x%08x\n", hr);
3510 ok(IsRectEmpty(&rect), "unexpected empty rect\n");
3512 else {
3513 rect.left = rect.top = 0;
3514 rect.bottom = rect.right = 1;
3515 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3516 ok(hr == S_OK, "got 0x%08x\n", hr);
3517 ok(IsRectEmpty(&rect), "got empty rect\n");
3519 memset(&rect, 0, sizeof(rect));
3520 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
3521 todo_wine {
3522 ok(hr == S_OK, "got 0x%08x\n", hr);
3523 ok(!IsRectEmpty(&rect), "got empty rect\n");
3527 IDWriteGlyphRunAnalysis_Release(analysis);
3530 IDWriteFontFace_GetMetrics(run.fontFace, &fm);
3532 /* check bbox for a single glyph run */
3533 for (run.fontEmSize = 1.0; run.fontEmSize <= 100.0; run.fontEmSize += 1.0) {
3534 DWRITE_GLYPH_METRICS gm;
3535 LONG bboxX, bboxY;
3537 hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
3538 DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
3539 0.0, 0.0, &analysis);
3540 ok(hr == S_OK, "got 0x%08x\n", hr);
3542 memset(&rect, 0, sizeof(rect));
3543 hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
3544 todo_wine
3545 ok(hr == S_OK, "got 0x%08x\n", hr);
3546 if (hr != S_OK)
3547 break;
3549 hr = IDWriteFontFace_GetGdiCompatibleGlyphMetrics(run.fontFace, run.fontEmSize, 1.0, NULL,
3550 DWRITE_MEASURING_MODE_GDI_CLASSIC, run.glyphIndices, 1, &gm, run.isSideways);
3551 ok(hr == S_OK, "got 0x%08x\n", hr);
3553 /* metrics are in design units */
3554 bboxX = (int)floorf((gm.advanceWidth - gm.leftSideBearing - gm.rightSideBearing) * run.fontEmSize / fm.designUnitsPerEm + 0.5f);
3555 bboxY = (int)floorf((gm.advanceHeight - gm.topSideBearing - gm.bottomSideBearing) * run.fontEmSize / fm.designUnitsPerEm + 0.5f);
3557 rect.right -= rect.left;
3558 rect.bottom -= rect.top;
3559 ok(abs(bboxX - rect.right) <= 1, "%.0f: bbox width %d, from metrics %d\n", run.fontEmSize, rect.right, bboxX);
3560 ok(abs(bboxY - rect.bottom) <= 1, "%.0f: bbox height %d, from metrics %d\n", run.fontEmSize, rect.bottom, bboxY);
3562 IDWriteGlyphRunAnalysis_Release(analysis);
3565 IDWriteFontFace_Release(face);
3566 IDWriteFactory_Release(factory);
3569 #define round(x) ((int)floor((x) + 0.5))
3571 struct VDMX_Header
3573 WORD version;
3574 WORD numRecs;
3575 WORD numRatios;
3578 struct VDMX_Ratio
3580 BYTE bCharSet;
3581 BYTE xRatio;
3582 BYTE yStartRatio;
3583 BYTE yEndRatio;
3586 struct VDMX_group
3588 WORD recs;
3589 BYTE startsz;
3590 BYTE endsz;
3593 struct VDMX_vTable
3595 WORD yPelHeight;
3596 SHORT yMax;
3597 SHORT yMin;
3600 #ifdef WORDS_BIGENDIAN
3601 #define GET_BE_WORD(x) (x)
3602 #else
3603 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
3604 #endif
3606 static const struct VDMX_group *find_vdmx_group(const struct VDMX_Header *hdr)
3608 WORD num_ratios, i, group_offset = 0;
3609 struct VDMX_Ratio *ratios = (struct VDMX_Ratio*)(hdr + 1);
3610 BYTE dev_x_ratio = 1, dev_y_ratio = 1;
3612 num_ratios = GET_BE_WORD(hdr->numRatios);
3614 for (i = 0; i < num_ratios; i++)
3616 if (!ratios[i].bCharSet) continue;
3618 if ((ratios[i].xRatio == 0 && ratios[i].yStartRatio == 0 &&
3619 ratios[i].yEndRatio == 0) ||
3620 (ratios[i].xRatio == dev_x_ratio && ratios[i].yStartRatio <= dev_y_ratio &&
3621 ratios[i].yEndRatio >= dev_y_ratio))
3623 group_offset = GET_BE_WORD(*((WORD *)(ratios + num_ratios) + i));
3624 break;
3627 if (group_offset)
3628 return (const struct VDMX_group *)((BYTE *)hdr + group_offset);
3629 return NULL;
3632 static BOOL get_vdmx_size(const struct VDMX_group *group, int emsize, int *a, int *d)
3634 WORD recs, i;
3635 const struct VDMX_vTable *tables;
3637 if (!group) return FALSE;
3639 recs = GET_BE_WORD(group->recs);
3640 if (emsize < group->startsz || emsize >= group->endsz) return FALSE;
3642 tables = (const struct VDMX_vTable *)(group + 1);
3643 for (i = 0; i < recs; i++)
3645 WORD ppem = GET_BE_WORD(tables[i].yPelHeight);
3646 if (ppem > emsize)
3648 /* FIXME: Supposed to interpolate */
3649 trace("FIXME interpolate %d\n", emsize);
3650 return FALSE;
3653 if (ppem == emsize)
3655 *a = (SHORT)GET_BE_WORD(tables[i].yMax);
3656 *d = -(SHORT)GET_BE_WORD(tables[i].yMin);
3657 return TRUE;
3660 return FALSE;
3663 static void test_metrics_cmp(FLOAT emsize, const DWRITE_FONT_METRICS *metrics, const DWRITE_FONT_METRICS1 *expected)
3665 ok(metrics->designUnitsPerEm == expected->designUnitsPerEm, "%.2f: emsize: got %u expect %u\n",
3666 emsize, metrics->designUnitsPerEm, expected->designUnitsPerEm);
3667 ok(metrics->ascent == expected->ascent, "%.2f a: got %u expect %u\n",
3668 emsize, metrics->ascent, expected->ascent);
3669 ok(metrics->descent == expected->descent, "%.2f d: got %u expect %u\n",
3670 emsize, metrics->descent, expected->descent);
3671 ok(metrics->lineGap == expected->lineGap, "%.2f lg: got %d expect %d\n",
3672 emsize, metrics->lineGap, expected->lineGap);
3673 ok(metrics->capHeight == expected->capHeight, "%.2f capH: got %u expect %u\n",
3674 emsize, metrics->capHeight, expected->capHeight);
3675 ok(metrics->xHeight == expected->xHeight, "%.2f xH: got %u expect %u\n",
3676 emsize, metrics->xHeight, expected->xHeight);
3677 ok(metrics->underlinePosition == expected->underlinePosition, "%.2f ulP: got %d expect %d\n",
3678 emsize, metrics->underlinePosition, expected->underlinePosition);
3679 ok(metrics->underlineThickness == expected->underlineThickness, "%.2f ulTh: got %u expect %u\n",
3680 emsize, metrics->underlineThickness, expected->underlineThickness);
3681 ok(metrics->strikethroughPosition == expected->strikethroughPosition, "%.2f stP: got %d expect %d\n",
3682 emsize, metrics->strikethroughPosition, expected->strikethroughPosition);
3683 ok(metrics->strikethroughThickness == expected->strikethroughThickness, "%.2f stTh: got %u expect %u\n",
3684 emsize, metrics->strikethroughThickness, expected->strikethroughThickness);
3687 static void test_metrics1_cmp(FLOAT emsize, const DWRITE_FONT_METRICS1 *metrics, const DWRITE_FONT_METRICS1 *expected)
3689 ok(metrics->designUnitsPerEm == expected->designUnitsPerEm, "%.2f: emsize: got %u expect %u\n",
3690 emsize, metrics->designUnitsPerEm, expected->designUnitsPerEm);
3691 ok(metrics->ascent == expected->ascent, "%.2f a: got %u expect %u\n",
3692 emsize, metrics->ascent, expected->ascent);
3693 ok(metrics->descent == expected->descent, "%.2f d: got %u expect %u\n",
3694 emsize, metrics->descent, expected->descent);
3695 ok(metrics->lineGap == expected->lineGap, "%.2f lg: got %d expect %d\n",
3696 emsize, metrics->lineGap, expected->lineGap);
3697 ok(metrics->capHeight == expected->capHeight, "%.2f capH: got %u expect %u\n",
3698 emsize, metrics->capHeight, expected->capHeight);
3699 ok(metrics->xHeight == expected->xHeight, "%.2f xH: got %u expect %u\n",
3700 emsize, metrics->xHeight, expected->xHeight);
3701 ok(metrics->underlinePosition == expected->underlinePosition, "%.2f ulP: got %d expect %d\n",
3702 emsize, metrics->underlinePosition, expected->underlinePosition);
3703 ok(metrics->underlineThickness == expected->underlineThickness, "%.2f ulTh: got %u expect %u\n",
3704 emsize, metrics->underlineThickness, expected->underlineThickness);
3705 ok(metrics->strikethroughPosition == expected->strikethroughPosition, "%.2f stP: got %d expect %d\n",
3706 emsize, metrics->strikethroughPosition, expected->strikethroughPosition);
3707 ok(metrics->strikethroughThickness == expected->strikethroughThickness, "%.2f stTh: got %u expect %u\n",
3708 emsize, metrics->strikethroughThickness, expected->strikethroughThickness);
3709 ok(metrics->glyphBoxLeft == expected->glyphBoxLeft, "%.2f box left: got %d expect %d\n",
3710 emsize, metrics->glyphBoxLeft, expected->glyphBoxLeft);
3711 if (0) { /* this is not consistent */
3712 ok(metrics->glyphBoxTop == expected->glyphBoxTop, "%.2f box top: got %d expect %d\n",
3713 emsize, metrics->glyphBoxTop, expected->glyphBoxTop);
3714 ok(metrics->glyphBoxRight == expected->glyphBoxRight, "%.2f box right: got %d expect %d\n",
3715 emsize, metrics->glyphBoxRight, expected->glyphBoxRight);
3717 ok(metrics->glyphBoxBottom == expected->glyphBoxBottom, "%.2f box bottom: got %d expect %d\n",
3718 emsize, metrics->glyphBoxBottom, expected->glyphBoxBottom);
3719 ok(metrics->subscriptPositionX == expected->subscriptPositionX, "%.2f subX: got %d expect %d\n",
3720 emsize, metrics->subscriptPositionX, expected->subscriptPositionX);
3721 ok(metrics->subscriptPositionY == expected->subscriptPositionY, "%.2f subY: got %d expect %d\n",
3722 emsize, metrics->subscriptPositionY, expected->subscriptPositionY);
3723 ok(metrics->subscriptSizeX == expected->subscriptSizeX, "%.2f subsizeX: got %d expect %d\n",
3724 emsize, metrics->subscriptSizeX, expected->subscriptSizeX);
3725 ok(metrics->subscriptPositionY == expected->subscriptPositionY, "%.2f subsizeY: got %d expect %d\n",
3726 emsize, metrics->subscriptSizeY, expected->subscriptSizeY);
3727 ok(metrics->superscriptPositionX == expected->superscriptPositionX, "%.2f supX: got %d expect %d\n",
3728 emsize, metrics->superscriptPositionX, expected->superscriptPositionX);
3729 if (0)
3730 ok(metrics->superscriptPositionY == expected->superscriptPositionY, "%.2f supY: got %d expect %d\n",
3731 emsize, metrics->superscriptPositionY, expected->superscriptPositionY);
3732 ok(metrics->superscriptSizeX == expected->superscriptSizeX, "%.2f supsizeX: got %d expect %d\n",
3733 emsize, metrics->superscriptSizeX, expected->superscriptSizeX);
3734 ok(metrics->superscriptSizeY == expected->superscriptSizeY, "%.2f supsizeY: got %d expect %d\n",
3735 emsize, metrics->superscriptSizeY, expected->superscriptSizeY);
3736 ok(metrics->hasTypographicMetrics == expected->hasTypographicMetrics, "%.2f hastypo: got %d expect %d\n",
3737 emsize, metrics->hasTypographicMetrics, expected->hasTypographicMetrics);
3740 struct compatmetrics_test {
3741 DWRITE_MATRIX m;
3742 FLOAT ppdip;
3743 FLOAT emsize;
3746 static struct compatmetrics_test compatmetrics_tests[] = {
3747 { { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 1.0, 5.0 },
3748 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 1.0, 5.0 },
3749 { { 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 }, 2.0, 5.0 },
3750 { { 0.0, 0.0, 0.0, 3.0, 0.0, 0.0 }, 2.0, 5.0 },
3751 { { 0.0, 0.0, 0.0, -3.0, 0.0, 0.0 }, 2.0, 5.0 },
3752 { { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, 2.0, 5.0 },
3753 { { 1.0, 0.0, 0.0, 1.0, 5.0, 0.0 }, 2.0, 5.0 },
3754 { { 1.0, 0.0, 0.0, 1.0, 0.0, 5.0 }, 2.0, 5.0 },
3757 static void get_expected_metrics(IDWriteFontFace *fontface, struct compatmetrics_test *ptr,
3758 DWRITE_FONT_METRICS *expected)
3760 HRESULT hr;
3762 memset(expected, 0, sizeof(*expected));
3763 hr = IDWriteFontFace_GetGdiCompatibleMetrics(fontface, ptr->ppdip * fabsf(ptr->m.m22) * ptr->emsize, 1.0, NULL, expected);
3764 ok(hr == S_OK, "got %08x\n", hr);
3767 static void test_GetGdiCompatibleMetrics_face(IDWriteFontFace *face)
3769 IDWriteFontFace1 *fontface1 = NULL;
3770 HRESULT hr;
3771 DWRITE_FONT_METRICS design_metrics, comp_metrics;
3772 DWRITE_FONT_METRICS1 design_metrics1, expected;
3773 FLOAT emsize, scale;
3774 int ascent, descent;
3775 const struct VDMX_Header *vdmx;
3776 UINT32 vdmx_len;
3777 void *vdmx_ctx;
3778 BOOL exists;
3779 const struct VDMX_group *vdmx_group = NULL;
3780 int i;
3782 hr = IDWriteFontFace_QueryInterface(face, &IID_IDWriteFontFace1, (void**)&fontface1);
3783 if (hr != S_OK)
3784 win_skip("gdi compatible DWRITE_FONT_METRICS1 are not supported.\n");
3786 if (fontface1) {
3787 IDWriteFontFace1_GetMetrics(fontface1, &design_metrics1);
3788 memcpy(&design_metrics, &design_metrics1, sizeof(design_metrics));
3790 else
3791 IDWriteFontFace_GetMetrics(face, &design_metrics);
3793 hr = IDWriteFontFace_TryGetFontTable(face, MS_VDMX_TAG, (const void **)&vdmx,
3794 &vdmx_len, &vdmx_ctx, &exists);
3795 if (hr != S_OK || !exists)
3796 vdmx = NULL;
3797 else
3798 vdmx_group = find_vdmx_group(vdmx);
3800 /* negative emsize */
3801 memset(&comp_metrics, 0xcc, sizeof(comp_metrics));
3802 memset(&expected, 0, sizeof(expected));
3803 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, -10.0, 1.0, NULL, &comp_metrics);
3804 ok(hr == E_INVALIDARG, "got %08x\n", hr);
3805 test_metrics_cmp(0.0, &comp_metrics, &expected);
3807 /* zero emsize */
3808 memset(&comp_metrics, 0xcc, sizeof(comp_metrics));
3809 memset(&expected, 0, sizeof(expected));
3810 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, 0.0, 1.0, NULL, &comp_metrics);
3811 ok(hr == E_INVALIDARG, "got %08x\n", hr);
3812 test_metrics_cmp(0.0, &comp_metrics, &expected);
3814 /* zero pixels per dip */
3815 memset(&comp_metrics, 0xcc, sizeof(comp_metrics));
3816 memset(&expected, 0, sizeof(expected));
3817 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, 5.0, 0.0, NULL, &comp_metrics);
3818 ok(hr == E_INVALIDARG, "got %08x\n", hr);
3819 test_metrics_cmp(5.0, &comp_metrics, &expected);
3821 memset(&comp_metrics, 0xcc, sizeof(comp_metrics));
3822 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, 5.0, -1.0, NULL, &comp_metrics);
3823 ok(hr == E_INVALIDARG, "got %08x\n", hr);
3824 test_metrics_cmp(5.0, &comp_metrics, &expected);
3826 for (i = 0; i < sizeof(compatmetrics_tests)/sizeof(compatmetrics_tests[0]); i++) {
3827 struct compatmetrics_test *ptr = &compatmetrics_tests[i];
3829 get_expected_metrics(face, ptr, (DWRITE_FONT_METRICS*)&expected);
3830 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, ptr->emsize, ptr->ppdip, &ptr->m, &comp_metrics);
3831 ok(hr == S_OK, "got %08x\n", hr);
3832 test_metrics_cmp(ptr->emsize, &comp_metrics, &expected);
3835 for (emsize = 5; emsize <= design_metrics.designUnitsPerEm; emsize++)
3837 DWRITE_FONT_METRICS1 comp_metrics1, expected;
3839 if (fontface1) {
3840 hr = IDWriteFontFace1_GetGdiCompatibleMetrics(fontface1, emsize, 1.0, NULL, &comp_metrics1);
3841 ok(hr == S_OK, "got %08x\n", hr);
3843 else {
3844 hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, emsize, 1.0, NULL, &comp_metrics);
3845 ok(hr == S_OK, "got %08x\n", hr);
3848 scale = emsize / design_metrics.designUnitsPerEm;
3849 if (!get_vdmx_size(vdmx_group, emsize, &ascent, &descent))
3851 ascent = round(design_metrics.ascent * scale);
3852 descent = round(design_metrics.descent * scale);
3855 expected.designUnitsPerEm = design_metrics.designUnitsPerEm;
3856 expected.ascent = round(ascent / scale );
3857 expected.descent = round(descent / scale );
3858 expected.lineGap = round(round(design_metrics.lineGap * scale) / scale);
3859 expected.capHeight = round(round(design_metrics.capHeight * scale) / scale);
3860 expected.xHeight = round(round(design_metrics.xHeight * scale) / scale);
3861 expected.underlinePosition = round(round(design_metrics.underlinePosition * scale) / scale);
3862 expected.underlineThickness = round(round(design_metrics.underlineThickness * scale) / scale);
3863 expected.strikethroughPosition = round(round(design_metrics.strikethroughPosition * scale) / scale);
3864 expected.strikethroughThickness = round(round(design_metrics.strikethroughThickness * scale) / scale);
3866 if (fontface1) {
3867 expected.glyphBoxLeft = round(round(design_metrics1.glyphBoxLeft * scale) / scale);
3869 if (0) { /* those two fail on Tahoma and Win7 */
3870 expected.glyphBoxTop = round(round(design_metrics1.glyphBoxTop * scale) / scale);
3871 expected.glyphBoxRight = round(round(design_metrics1.glyphBoxRight * scale) / scale);
3873 expected.glyphBoxBottom = round(round(design_metrics1.glyphBoxBottom * scale) / scale);
3874 expected.subscriptPositionX = round(round(design_metrics1.subscriptPositionX * scale) / scale);
3875 expected.subscriptPositionY = round(round(design_metrics1.subscriptPositionY * scale) / scale);
3876 expected.subscriptSizeX = round(round(design_metrics1.subscriptSizeX * scale) / scale);
3877 expected.subscriptSizeY = round(round(design_metrics1.subscriptSizeY * scale) / scale);
3878 expected.superscriptPositionX = round(round(design_metrics1.superscriptPositionX * scale) / scale);
3879 if (0) /* this fails for 3 emsizes, Tahoma from [5, 2048] range */
3880 expected.superscriptPositionY = round(round(design_metrics1.superscriptPositionY * scale) / scale);
3881 expected.superscriptSizeX = round(round(design_metrics1.superscriptSizeX * scale) / scale);
3882 expected.superscriptSizeY = round(round(design_metrics1.superscriptSizeY * scale) / scale);
3883 expected.hasTypographicMetrics = design_metrics1.hasTypographicMetrics;
3885 test_metrics1_cmp(emsize, &comp_metrics1, &expected);
3887 else
3888 test_metrics_cmp(emsize, &comp_metrics, &expected);
3892 if (fontface1)
3893 IDWriteFontFace1_Release(fontface1);
3894 if (vdmx) IDWriteFontFace_ReleaseFontTable(face, vdmx_ctx);
3897 static void test_GetGdiCompatibleMetrics(void)
3899 IDWriteFactory *factory;
3900 IDWriteFont *font;
3901 IDWriteFontFace *fontface;
3902 HRESULT hr;
3904 factory = create_factory();
3906 font = get_font(factory, tahomaW, DWRITE_FONT_STYLE_NORMAL);
3907 hr = IDWriteFont_CreateFontFace(font, &fontface);
3908 ok(hr == S_OK, "got 0x%08x\n", hr);
3909 IDWriteFont_Release(font);
3910 test_GetGdiCompatibleMetrics_face(fontface);
3911 IDWriteFontFace_Release(fontface);
3913 font = get_font(factory, arialW, DWRITE_FONT_STYLE_NORMAL);
3914 if (!font)
3915 skip("Skipping tests with Arial\n");
3916 else
3918 hr = IDWriteFont_CreateFontFace(font, &fontface);
3919 ok(hr == S_OK, "got 0x%08x\n", hr);
3920 IDWriteFont_Release(font);
3922 test_GetGdiCompatibleMetrics_face(fontface);
3923 IDWriteFontFace_Release(fontface);
3926 IDWriteFactory_Release(factory);
3929 static void test_GetPanose(void)
3931 IDWriteFactory *factory;
3932 IDWriteFont1 *font1;
3933 IDWriteFont *font;
3934 HRESULT hr;
3936 factory = create_factory();
3937 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
3939 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
3940 IDWriteFont_Release(font);
3941 if (hr == S_OK) {
3942 DWRITE_PANOSE panose;
3944 if (0) /* crashes on native */
3945 IDWriteFont1_GetPanose(font1, NULL);
3947 memset(&panose, 0, sizeof(panose));
3948 IDWriteFont1_GetPanose(font1, &panose);
3949 ok(panose.familyKind == DWRITE_PANOSE_FAMILY_TEXT_DISPLAY,
3950 "got %u\n", panose.familyKind);
3951 ok(panose.text.serifStyle == DWRITE_PANOSE_SERIF_STYLE_NORMAL_SANS,
3952 "got %u\n", panose.text.serifStyle);
3953 ok(panose.text.weight == DWRITE_PANOSE_WEIGHT_MEDIUM,
3954 "got %u\n", panose.text.weight);
3955 ok(panose.text.proportion == DWRITE_PANOSE_PROPORTION_EVEN_WIDTH,
3956 "got %u\n", panose.text.proportion);
3957 ok(panose.text.contrast == DWRITE_PANOSE_CONTRAST_VERY_LOW,
3958 "got %u\n", panose.text.contrast);
3959 ok(panose.text.strokeVariation == DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_VERTICAL,
3960 "got %u\n", panose.text.strokeVariation);
3961 ok(panose.text.armStyle == DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_VERTICAL,
3962 "got %u\n", panose.text.armStyle);
3963 ok(panose.text.letterform == DWRITE_PANOSE_LETTERFORM_NORMAL_BOXED,
3964 "got %u\n", panose.text.letterform);
3965 ok(panose.text.midline == DWRITE_PANOSE_MIDLINE_STANDARD_TRIMMED,
3966 "got %u\n", panose.text.midline);
3967 ok(panose.text.xHeight == DWRITE_PANOSE_XHEIGHT_CONSTANT_LARGE,
3968 "got %u\n", panose.text.xHeight);
3970 IDWriteFont1_Release(font1);
3972 else
3973 win_skip("GetPanose() is not supported.\n");
3975 IDWriteFactory_Release(factory);
3978 static INT32 get_gdi_font_advance(HDC hdc, FLOAT emsize)
3980 LOGFONTW logfont;
3981 HFONT hfont;
3982 BOOL ret;
3983 ABC abc;
3985 memset(&logfont, 0, sizeof(logfont));
3986 logfont.lfHeight = (LONG)-emsize;
3987 logfont.lfWeight = FW_NORMAL;
3988 logfont.lfQuality = CLEARTYPE_QUALITY;
3989 lstrcpyW(logfont.lfFaceName, tahomaW);
3991 hfont = CreateFontIndirectW(&logfont);
3992 SelectObject(hdc, hfont);
3994 ret = GetCharABCWidthsW(hdc, 'A', 'A', &abc);
3995 ok(ret, "got %d\n", ret);
3997 DeleteObject(hfont);
3999 return abc.abcA + abc.abcB + abc.abcC;
4002 static void test_GetGdiCompatibleGlyphAdvances(void)
4004 IDWriteFontFace1 *fontface1;
4005 IDWriteFontFace *fontface;
4006 IDWriteFactory *factory;
4007 IDWriteFont *font;
4008 HRESULT hr;
4009 HDC hdc;
4010 UINT32 codepoint;
4011 UINT16 glyph;
4012 FLOAT emsize;
4013 DWRITE_FONT_METRICS1 fm;
4014 INT32 advance;
4016 factory = create_factory();
4017 font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
4019 hr = IDWriteFont_CreateFontFace(font, &fontface);
4020 ok(hr == S_OK, "got 0x%08x\n", hr);
4021 IDWriteFont_Release(font);
4023 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
4024 IDWriteFontFace_Release(fontface);
4026 if (hr != S_OK) {
4027 IDWriteFactory_Release(factory);
4028 win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
4029 return;
4032 codepoint = 'A';
4033 glyph = 0;
4034 hr = IDWriteFontFace1_GetGlyphIndices(fontface1, &codepoint, 1, &glyph);
4035 ok(hr == S_OK, "got 0x%08x\n", hr);
4036 ok(glyph > 0, "got %u\n", glyph);
4038 /* zero emsize */
4039 advance = 1;
4040 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 0.0,
4041 1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4042 ok(hr == S_OK, "got 0x%08x\n", hr);
4043 ok(advance == 0, "got %d\n", advance);
4045 /* negative emsize */
4046 advance = 1;
4047 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, -1.0,
4048 1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4049 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4050 ok(advance == 0, "got %d\n", advance);
4052 /* zero ppdip */
4053 advance = 1;
4054 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 1.0,
4055 0.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4056 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4057 ok(advance == 0, "got %d\n", advance);
4059 /* negative ppdip */
4060 advance = 1;
4061 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 1.0,
4062 -1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4063 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4064 ok(advance == 0, "got %d\n", advance);
4066 IDWriteFontFace1_GetMetrics(fontface1, &fm);
4068 hdc = CreateCompatibleDC(0);
4070 for (emsize = 1.0; emsize <= fm.designUnitsPerEm; emsize += 1.0) {
4071 INT32 gdi_advance;
4073 gdi_advance = get_gdi_font_advance(hdc, emsize);
4074 hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, emsize,
4075 1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
4076 ok(hr == S_OK, "got 0x%08x\n", hr);
4078 /* advance is in design units */
4079 advance = (int)floorf(emsize * advance / fm.designUnitsPerEm + 0.5f);
4081 /* allow 1 pixel difference for large sizes, for Tahoma this happens for 16 sizes in [1, 2048] range */
4082 if (emsize > 150.0)
4083 ok((advance - gdi_advance) <= 1, "%.0f: got advance %d, expected %d\n", emsize, advance, gdi_advance);
4084 else
4085 ok(gdi_advance == advance, "%.0f: got advance %d, expected %d\n", emsize, advance, gdi_advance);
4088 DeleteObject(hdc);
4090 IDWriteFactory_Release(factory);
4093 static WORD get_gasp_flags(IDWriteFontFace *fontface, FLOAT emsize)
4095 WORD num_recs, version;
4096 const WORD *ptr;
4097 WORD flags = 0;
4098 UINT32 size;
4099 BOOL exists;
4100 void *ctxt;
4101 HRESULT hr;
4103 exists = FALSE;
4104 hr = IDWriteFontFace_TryGetFontTable(fontface, MS_GASP_TAG,
4105 (const void**)&ptr, &size, &ctxt, &exists);
4106 ok(hr == S_OK, "got 0x%08x\n", hr);
4108 if (!exists)
4109 goto done;
4111 version = GET_BE_WORD( *ptr++ );
4112 num_recs = GET_BE_WORD( *ptr++ );
4113 if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD)) {
4114 ok(0, "unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs);
4115 goto done;
4118 while (num_recs--)
4120 flags = GET_BE_WORD( *(ptr + 1) );
4121 if (emsize <= GET_BE_WORD( *ptr )) break;
4122 ptr += 2;
4125 done:
4126 IDWriteFontFace_ReleaseFontTable(fontface, ctxt);
4127 return flags;
4130 #define GASP_GRIDFIT 0x0001
4131 #define GASP_DOGRAY 0x0002
4132 #define GASP_SYMMETRIC_GRIDFIT 0x0004
4133 #define GASP_SYMMETRIC_SMOOTHING 0x0008
4135 static BOOL g_is_vista;
4136 static DWRITE_RENDERING_MODE get_expected_rendering_mode(FLOAT emsize, WORD gasp, DWRITE_MEASURING_MODE mode,
4137 DWRITE_OUTLINE_THRESHOLD threshold)
4139 static const FLOAT aa_threshold = 100.0f;
4140 static const FLOAT a_threshold = 350.0f;
4141 static const FLOAT naturalemsize = 20.0f;
4142 FLOAT v;
4144 /* outline threshold */
4145 if (g_is_vista)
4146 v = mode == DWRITE_MEASURING_MODE_NATURAL ? aa_threshold : a_threshold;
4147 else
4148 v = threshold == DWRITE_OUTLINE_THRESHOLD_ANTIALIASED ? aa_threshold : a_threshold;
4150 if (emsize >= v)
4151 return DWRITE_RENDERING_MODE_OUTLINE;
4153 switch (mode)
4155 case DWRITE_MEASURING_MODE_NATURAL:
4156 if (!(gasp & GASP_SYMMETRIC_SMOOTHING) && (emsize <= naturalemsize))
4157 return DWRITE_RENDERING_MODE_NATURAL;
4158 else
4159 return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
4160 case DWRITE_MEASURING_MODE_GDI_CLASSIC:
4161 return DWRITE_RENDERING_MODE_GDI_CLASSIC;
4162 case DWRITE_MEASURING_MODE_GDI_NATURAL:
4163 return DWRITE_RENDERING_MODE_GDI_NATURAL;
4164 default:
4168 /* should be unreachable */
4169 return DWRITE_RENDERING_MODE_DEFAULT;
4172 static DWRITE_GRID_FIT_MODE get_expected_gridfit_mode(FLOAT emsize, WORD gasp, DWRITE_MEASURING_MODE mode,
4173 DWRITE_OUTLINE_THRESHOLD threshold)
4175 static const FLOAT aa_threshold = 100.0f;
4176 static const FLOAT a_threshold = 350.0f;
4177 FLOAT v;
4179 v = threshold == DWRITE_OUTLINE_THRESHOLD_ANTIALIASED ? aa_threshold : a_threshold;
4180 if (emsize >= v)
4181 return DWRITE_GRID_FIT_MODE_DISABLED;
4183 if (mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || mode == DWRITE_MEASURING_MODE_GDI_NATURAL)
4184 return DWRITE_GRID_FIT_MODE_ENABLED;
4186 return (gasp & (GASP_GRIDFIT|GASP_SYMMETRIC_GRIDFIT)) ? DWRITE_GRID_FIT_MODE_ENABLED : DWRITE_GRID_FIT_MODE_DISABLED;
4189 struct recommendedmode_test
4191 DWRITE_MEASURING_MODE measuring;
4192 DWRITE_OUTLINE_THRESHOLD threshold;
4195 static const struct recommendedmode_test recmode_tests[] = {
4196 { DWRITE_MEASURING_MODE_NATURAL, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4197 { DWRITE_MEASURING_MODE_GDI_CLASSIC, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4198 { DWRITE_MEASURING_MODE_GDI_NATURAL, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4201 static const struct recommendedmode_test recmode_tests1[] = {
4202 { DWRITE_MEASURING_MODE_NATURAL, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4203 { DWRITE_MEASURING_MODE_GDI_CLASSIC, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4204 { DWRITE_MEASURING_MODE_GDI_NATURAL, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED },
4205 { DWRITE_MEASURING_MODE_NATURAL, DWRITE_OUTLINE_THRESHOLD_ALIASED },
4206 { DWRITE_MEASURING_MODE_GDI_CLASSIC, DWRITE_OUTLINE_THRESHOLD_ALIASED },
4207 { DWRITE_MEASURING_MODE_GDI_NATURAL, DWRITE_OUTLINE_THRESHOLD_ALIASED },
4210 static void test_GetRecommendedRenderingMode(void)
4212 IDWriteRenderingParams *params;
4213 IDWriteFontFace2 *fontface2;
4214 IDWriteFontFace1 *fontface1;
4215 IDWriteFontFace *fontface;
4216 DWRITE_RENDERING_MODE mode;
4217 IDWriteFactory *factory;
4218 FLOAT emsize;
4219 HRESULT hr;
4221 factory = create_factory();
4222 fontface = create_fontface(factory);
4224 fontface1 = NULL;
4225 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
4226 if (hr != S_OK)
4227 win_skip("IDWriteFontFace1::GetRecommendedRenderingMode() is not supported.\n");
4229 fontface2 = NULL;
4230 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace2, (void**)&fontface2);
4231 if (hr != S_OK)
4232 win_skip("IDWriteFontFace2::GetRecommendedRenderingMode() is not supported.\n");
4234 if (0) /* crashes on native */
4235 hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, 3.0, 1.0,
4236 DWRITE_MEASURING_MODE_GDI_CLASSIC, NULL, NULL);
4238 mode = 10;
4239 hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, 3.0, 1.0,
4240 DWRITE_MEASURING_MODE_GDI_CLASSIC, NULL, &mode);
4241 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
4242 ok(mode == DWRITE_RENDERING_MODE_DEFAULT, "got %d\n", mode);
4244 hr = IDWriteFactory_CreateRenderingParams(factory, &params);
4245 ok(hr == S_OK, "got 0x%08x\n", hr);
4247 /* detect old dwrite version, that is using higher threshold value */
4248 g_is_vista = fontface1 == NULL;
4250 for (emsize = 1.0; emsize < 500.0; emsize += 1.0) {
4251 WORD gasp = get_gasp_flags(fontface, emsize);
4252 DWRITE_RENDERING_MODE expected;
4253 int i;
4255 for (i = 0; i < sizeof(recmode_tests)/sizeof(recmode_tests[0]); i++) {
4256 mode = 10;
4257 expected = get_expected_rendering_mode(emsize, gasp, recmode_tests[i].measuring, recmode_tests[i].threshold);
4258 hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, emsize, 1.0, recmode_tests[i].measuring, params, &mode);
4259 ok(hr == S_OK, "got 0x%08x\n", hr);
4260 ok(mode == expected, "%.2f/%d: got %d, flags 0x%04x, expected %d\n", emsize, i, mode, gasp, expected);
4263 /* IDWriteFontFace1 offers another variant of this method */
4264 if (fontface1) {
4265 for (i = 0; i < sizeof(recmode_tests1)/sizeof(recmode_tests1[0]); i++) {
4266 mode = 10;
4267 expected = get_expected_rendering_mode(emsize, gasp, recmode_tests1[i].measuring, recmode_tests1[i].threshold);
4268 hr = IDWriteFontFace1_GetRecommendedRenderingMode(fontface1, emsize, 96.0, 96.0,
4269 NULL, FALSE, recmode_tests1[i].threshold, recmode_tests1[i].measuring, &mode);
4270 ok(hr == S_OK, "got 0x%08x\n", hr);
4271 ok(mode == expected, "%.2f/%d: got %d, flags 0x%04x, expected %d\n", emsize, i, mode, gasp, expected);
4275 /* IDWriteFontFace2 - another one */
4276 if (fontface2) {
4277 DWRITE_GRID_FIT_MODE gridfit, expected_gridfit;
4279 for (i = 0; i < sizeof(recmode_tests1)/sizeof(recmode_tests1[0]); i++) {
4280 mode = 10;
4281 expected = get_expected_rendering_mode(emsize, gasp, recmode_tests1[0].measuring, recmode_tests1[0].threshold);
4282 expected_gridfit = get_expected_gridfit_mode(emsize, gasp, recmode_tests1[0].measuring, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED);
4283 hr = IDWriteFontFace2_GetRecommendedRenderingMode(fontface2, emsize, 96.0, 96.0,
4284 NULL, FALSE, recmode_tests1[0].threshold, recmode_tests1[0].measuring, params, &mode, &gridfit);
4285 ok(hr == S_OK, "got 0x%08x\n", hr);
4286 ok(mode == expected, "%.2f: got %d, flags 0x%04x, expected %d\n", emsize, mode, gasp, expected);
4287 ok(gridfit == expected_gridfit, "%.2f/%d: gridfit: got %d, flags 0x%04x, expected %d\n", emsize, i, gridfit,
4288 gasp, expected_gridfit);
4293 IDWriteRenderingParams_Release(params);
4295 /* test how parameters override returned modes */
4296 hr = IDWriteFactory_CreateCustomRenderingParams(factory, 1.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT,
4297 DWRITE_RENDERING_MODE_GDI_CLASSIC, &params);
4298 ok(hr == S_OK, "got 0x%08x\n", hr);
4300 mode = 10;
4301 hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, 500.0, 1.0, DWRITE_MEASURING_MODE_NATURAL, params, &mode);
4302 ok(hr == S_OK, "got 0x%08x\n", hr);
4303 ok(mode == DWRITE_RENDERING_MODE_GDI_CLASSIC, "got %d\n", mode);
4305 IDWriteRenderingParams_Release(params);
4307 if (fontface2) {
4308 IDWriteRenderingParams2 *params2;
4309 IDWriteFactory2 *factory2;
4310 DWRITE_GRID_FIT_MODE gridfit;
4312 hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory2, (void**)&factory2);
4313 ok(hr == S_OK, "got 0x%08x\n", hr);
4315 hr = IDWriteFactory2_CreateCustomRenderingParams(factory2, 1.0, 0.0, 0.0, 0.5, DWRITE_PIXEL_GEOMETRY_FLAT,
4316 DWRITE_RENDERING_MODE_OUTLINE, DWRITE_GRID_FIT_MODE_ENABLED, &params2);
4317 ok(hr == S_OK, "got 0x%08x\n", hr);
4319 mode = 10;
4320 gridfit = 10;
4321 hr = IDWriteFontFace2_GetRecommendedRenderingMode(fontface2, 5.0, 96.0, 96.0,
4322 NULL, FALSE, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
4323 NULL, &mode, &gridfit);
4324 ok(hr == S_OK, "got 0x%08x\n", hr);
4325 ok(mode == DWRITE_RENDERING_MODE_GDI_CLASSIC, "got %d\n", mode);
4326 ok(gridfit == DWRITE_GRID_FIT_MODE_ENABLED, "got %d\n", gridfit);
4328 mode = 10;
4329 gridfit = 10;
4330 hr = IDWriteFontFace2_GetRecommendedRenderingMode(fontface2, 5.0, 96.0, 96.0,
4331 NULL, FALSE, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
4332 (IDWriteRenderingParams*)params2, &mode, &gridfit);
4333 ok(hr == S_OK, "got 0x%08x\n", hr);
4334 ok(mode == DWRITE_RENDERING_MODE_OUTLINE, "got %d\n", mode);
4335 ok(gridfit == DWRITE_GRID_FIT_MODE_ENABLED, "got %d\n", gridfit);
4337 IDWriteRenderingParams2_Release(params2);
4338 IDWriteFactory2_Release(factory2);
4341 if (fontface2)
4342 IDWriteFontFace2_Release(fontface2);
4343 if (fontface1)
4344 IDWriteFontFace1_Release(fontface1);
4345 IDWriteFontFace_Release(fontface);
4346 IDWriteFactory_Release(factory);
4349 START_TEST(font)
4351 IDWriteFactory *factory;
4353 if (!(factory = create_factory())) {
4354 win_skip("failed to create factory\n");
4355 return;
4358 test_CreateFontFromLOGFONT();
4359 test_CreateBitmapRenderTarget();
4360 test_GetFontFamily();
4361 test_GetFamilyNames();
4362 test_CreateFontFace();
4363 test_GetMetrics();
4364 test_system_fontcollection();
4365 test_ConvertFontFaceToLOGFONT();
4366 test_CustomFontCollection();
4367 test_CreateCustomFontFileReference();
4368 test_CreateFontFileReference();
4369 test_shared_isolated();
4370 test_GetUnicodeRanges();
4371 test_GetFontFromFontFace();
4372 test_GetFirstMatchingFont();
4373 test_GetInformationalStrings();
4374 test_GetGdiInterop();
4375 test_CreateFontFaceFromHdc();
4376 test_GetSimulations();
4377 test_GetFaceNames();
4378 test_TryGetFontTable();
4379 test_ConvertFontToLOGFONT();
4380 test_CreateStreamFromKey();
4381 test_ReadFileFragment();
4382 test_GetDesignGlyphMetrics();
4383 test_GetDesignGlyphAdvances();
4384 test_IsMonospacedFont();
4385 test_GetGlyphRunOutline();
4386 test_GetEudcFontCollection();
4387 test_GetCaretMetrics();
4388 test_GetGlyphCount();
4389 test_GetKerningPairAdjustments();
4390 test_CreateRenderingParams();
4391 test_CreateGlyphRunAnalysis();
4392 test_GetGdiCompatibleMetrics();
4393 test_GetPanose();
4394 test_GetGdiCompatibleGlyphAdvances();
4395 test_GetRecommendedRenderingMode();
4397 IDWriteFactory_Release(factory);