dwrite: Use file mapping for local file stream.
[wine/multimedia.git] / dlls / dwrite / tests / font.c
blob221a5d3ee52f8451e0a025508d040f5425edc070
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 #define COBJMACROS
24 #include "windows.h"
25 #include "dwrite_1.h"
27 #include "wine/test.h"
29 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
30 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
31 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
33 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
35 #define EXPECT_HR(hr,hr_exp) \
36 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
38 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
39 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
41 ULONG rc;
42 IUnknown_AddRef(obj);
43 rc = IUnknown_Release(obj);
44 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
47 static inline void *heap_alloc(size_t len)
49 return HeapAlloc(GetProcessHeap(), 0, len);
52 static inline BOOL heap_free(void *mem)
54 return HeapFree(GetProcessHeap(), 0, mem);
57 static const WCHAR test_fontfile[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
58 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
59 static const WCHAR blahW[] = {'B','l','a','h','!',0};
61 static IDWriteFactory *create_factory(void)
63 IDWriteFactory *factory;
64 HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
65 ok(hr == S_OK, "got 0x%08x\n", hr);
66 return factory;
69 struct test_fontenumerator
71 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface;
72 LONG ref;
74 DWORD index;
75 IDWriteFontFile *font_file;
78 static inline struct test_fontenumerator *impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator* iface)
80 return CONTAINING_RECORD(iface, struct test_fontenumerator, IDWriteFontFileEnumerator_iface);
83 static HRESULT WINAPI singlefontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
85 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileEnumerator))
87 *obj = iface;
88 IDWriteFontFileEnumerator_AddRef(iface);
89 return S_OK;
91 return E_NOINTERFACE;
94 static ULONG WINAPI singlefontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
96 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
97 return InterlockedIncrement(&This->ref);
100 static ULONG WINAPI singlefontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
102 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
103 ULONG ref = InterlockedDecrement(&This->ref);
104 if (!ref) {
105 IDWriteFontFile_Release(This->font_file);
106 heap_free(This);
108 return ref;
111 static HRESULT WINAPI singlefontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **font_file)
113 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
114 IDWriteFontFile_AddRef(This->font_file);
115 *font_file = This->font_file;
116 return S_OK;
119 static HRESULT WINAPI singlefontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
121 struct test_fontenumerator *This = impl_from_IDWriteFontFileEnumerator(iface);
123 if (This->index > 1) {
124 *current = FALSE;
125 return S_OK;
128 This->index++;
129 *current = TRUE;
130 return S_OK;
133 static const struct IDWriteFontFileEnumeratorVtbl singlefontfileenumeratorvtbl =
135 singlefontfileenumerator_QueryInterface,
136 singlefontfileenumerator_AddRef,
137 singlefontfileenumerator_Release,
138 singlefontfileenumerator_MoveNext,
139 singlefontfileenumerator_GetCurrentFontFile
142 static HRESULT create_enumerator(IDWriteFontFile *font_file, IDWriteFontFileEnumerator **ret)
144 struct test_fontenumerator *enumerator;
146 enumerator = heap_alloc(sizeof(struct test_fontenumerator));
147 if (!enumerator)
148 return E_OUTOFMEMORY;
150 enumerator->IDWriteFontFileEnumerator_iface.lpVtbl = &singlefontfileenumeratorvtbl;
151 enumerator->ref = 1;
152 enumerator->index = 0;
153 enumerator->font_file = font_file;
154 IDWriteFontFile_AddRef(font_file);
156 *ret = &enumerator->IDWriteFontFileEnumerator_iface;
157 return S_OK;
160 struct test_fontcollectionloader
162 IDWriteFontCollectionLoader IDWriteFontFileCollectionLoader_iface;
163 IDWriteFontFileLoader *loader;
166 static inline struct test_fontcollectionloader *impl_from_IDWriteFontFileCollectionLoader(IDWriteFontCollectionLoader* iface)
168 return CONTAINING_RECORD(iface, struct test_fontcollectionloader, IDWriteFontFileCollectionLoader_iface);
171 static HRESULT WINAPI resourcecollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
173 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontCollectionLoader))
175 *obj = iface;
176 IDWriteFontCollectionLoader_AddRef(iface);
177 return S_OK;
179 return E_NOINTERFACE;
182 static ULONG WINAPI resourcecollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
184 return 2;
187 static ULONG WINAPI resourcecollectionloader_Release(IDWriteFontCollectionLoader *iface)
189 return 1;
192 static HRESULT WINAPI resourcecollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory,
193 const void * collectionKey, UINT32 collectionKeySize, IDWriteFontFileEnumerator ** fontFileEnumerator)
195 struct test_fontcollectionloader *This = impl_from_IDWriteFontFileCollectionLoader(iface);
196 IDWriteFontFile *font_file;
197 HRESULT hr;
199 IDWriteFactory_CreateCustomFontFileReference(factory, collectionKey, collectionKeySize, This->loader, &font_file);
201 hr = create_enumerator(font_file, fontFileEnumerator);
202 ok(hr == S_OK, "got 0x%08x\n", hr);
204 IDWriteFontFile_Release(font_file);
205 return hr;
208 static const struct IDWriteFontCollectionLoaderVtbl resourcecollectionloadervtbl = {
209 resourcecollectionloader_QueryInterface,
210 resourcecollectionloader_AddRef,
211 resourcecollectionloader_Release,
212 resourcecollectionloader_CreateEnumeratorFromKey
215 /* Here is a functional custom font set of interfaces */
216 struct test_fontdatastream
218 IDWriteFontFileStream IDWriteFontFileStream_iface;
219 LONG ref;
221 LPVOID data;
222 DWORD size;
225 static inline struct test_fontdatastream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream* iface)
227 return CONTAINING_RECORD(iface, struct test_fontdatastream, IDWriteFontFileStream_iface);
230 static HRESULT WINAPI fontdatastream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
232 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
234 *obj = iface;
235 IDWriteFontFileStream_AddRef(iface);
236 return S_OK;
238 *obj = NULL;
239 return E_NOINTERFACE;
242 static ULONG WINAPI fontdatastream_AddRef(IDWriteFontFileStream *iface)
244 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
245 ULONG ref = InterlockedIncrement(&This->ref);
246 return ref;
249 static ULONG WINAPI fontdatastream_Release(IDWriteFontFileStream *iface)
251 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
252 ULONG ref = InterlockedDecrement(&This->ref);
253 if (ref == 0)
254 HeapFree(GetProcessHeap(), 0, This);
255 return ref;
258 static HRESULT WINAPI fontdatastream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
260 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
261 *fragment_context = NULL;
262 if (offset+fragment_size > This->size)
264 *fragment_start = NULL;
265 return E_FAIL;
267 else
269 *fragment_start = (BYTE*)This->data + offset;
270 return S_OK;
274 static void WINAPI fontdatastream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
276 /* Do Nothing */
279 static HRESULT WINAPI fontdatastream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
281 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
282 *size = This->size;
283 return S_OK;
286 static HRESULT WINAPI fontdatastream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
288 return E_NOTIMPL;
291 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl =
293 fontdatastream_QueryInterface,
294 fontdatastream_AddRef,
295 fontdatastream_Release,
296 fontdatastream_ReadFileFragment,
297 fontdatastream_ReleaseFileFragment,
298 fontdatastream_GetFileSize,
299 fontdatastream_GetLastWriteTime
302 static HRESULT create_fontdatastream(LPVOID data, UINT size, IDWriteFontFileStream** iface)
304 struct test_fontdatastream *This = HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream));
305 if (!This)
306 return E_OUTOFMEMORY;
308 This->data = data;
309 This->size = size;
310 This->ref = 1;
311 This->IDWriteFontFileStream_iface.lpVtbl = &fontdatastreamvtbl;
313 *iface = &This->IDWriteFontFileStream_iface;
314 return S_OK;
317 static HRESULT WINAPI resourcefontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
319 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
321 *obj = iface;
322 return S_OK;
324 *obj = NULL;
325 return E_NOINTERFACE;
328 static ULONG WINAPI resourcefontfileloader_AddRef(IDWriteFontFileLoader *iface)
330 return 2;
333 static ULONG WINAPI resourcefontfileloader_Release(IDWriteFontFileLoader *iface)
335 return 1;
338 static HRESULT WINAPI resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
340 LPVOID data;
341 DWORD size;
342 HGLOBAL mem;
344 mem = LoadResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
345 ok(mem != NULL, "Failed to lock font resource\n");
346 if (mem)
348 size = SizeofResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
349 data = LockResource(mem);
350 return create_fontdatastream(data, size, fontFileStream);
352 return E_FAIL;
355 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl = {
356 resourcefontfileloader_QueryInterface,
357 resourcefontfileloader_AddRef,
358 resourcefontfileloader_Release,
359 resourcefontfileloader_CreateStreamFromKey
362 static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
364 static void test_CreateFontFromLOGFONT(void)
366 static const WCHAR tahomaspW[] = {'T','a','h','o','m','a',' ',0};
367 IDWriteGdiInterop *interop;
368 DWRITE_FONT_WEIGHT weight;
369 DWRITE_FONT_STYLE style;
370 IDWriteFont *font;
371 LOGFONTW logfont;
372 LONG weights[][2] = {
373 {FW_NORMAL, DWRITE_FONT_WEIGHT_NORMAL},
374 {FW_BOLD, DWRITE_FONT_WEIGHT_BOLD},
375 { 0, DWRITE_FONT_WEIGHT_NORMAL},
376 { 50, DWRITE_FONT_WEIGHT_NORMAL},
377 {150, DWRITE_FONT_WEIGHT_NORMAL},
378 {250, DWRITE_FONT_WEIGHT_NORMAL},
379 {350, DWRITE_FONT_WEIGHT_NORMAL},
380 {450, DWRITE_FONT_WEIGHT_NORMAL},
381 {650, DWRITE_FONT_WEIGHT_BOLD},
382 {750, DWRITE_FONT_WEIGHT_BOLD},
383 {850, DWRITE_FONT_WEIGHT_BOLD},
384 {950, DWRITE_FONT_WEIGHT_BOLD},
385 {960, DWRITE_FONT_WEIGHT_BOLD},
387 OUTLINETEXTMETRICW otm;
388 IDWriteFactory *factory;
389 HRESULT hr;
390 BOOL ret;
391 HDC hdc;
392 HFONT hfont;
393 BOOL exists;
394 int i;
395 UINT r;
397 factory = create_factory();
399 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
400 EXPECT_HR(hr, S_OK);
402 if (0)
403 /* null out parameter crashes this call */
404 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, NULL);
406 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, &font);
407 EXPECT_HR(hr, E_INVALIDARG);
409 memset(&logfont, 0, sizeof(logfont));
410 logfont.lfHeight = 12;
411 logfont.lfWidth = 12;
412 logfont.lfWeight = FW_NORMAL;
413 logfont.lfItalic = 1;
414 lstrcpyW(logfont.lfFaceName, tahomaW);
416 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
417 EXPECT_HR(hr, S_OK);
419 hfont = CreateFontIndirectW(&logfont);
420 hdc = CreateCompatibleDC(0);
421 SelectObject(hdc, hfont);
423 otm.otmSize = sizeof(otm);
424 r = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
425 ok(r, "got %d\n", r);
426 DeleteDC(hdc);
427 DeleteObject(hfont);
429 exists = TRUE;
430 hr = IDWriteFont_HasCharacter(font, 0xd800, &exists);
431 ok(hr == S_OK, "got 0x%08x\n", hr);
432 ok(exists == FALSE, "got %d\n", exists);
434 exists = FALSE;
435 hr = IDWriteFont_HasCharacter(font, 0x20, &exists);
436 ok(hr == S_OK, "got 0x%08x\n", hr);
437 ok(exists == TRUE, "got %d\n", exists);
439 /* now check properties */
440 weight = IDWriteFont_GetWeight(font);
441 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
443 style = IDWriteFont_GetStyle(font);
444 todo_wine {
445 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
446 ok(otm.otmfsSelection == 1, "got 0x%08x\n", otm.otmfsSelection);
448 ret = IDWriteFont_IsSymbolFont(font);
449 ok(!ret, "got %d\n", ret);
451 IDWriteFont_Release(font);
453 /* weight values */
454 for (i = 0; i < sizeof(weights)/(2*sizeof(LONG)); i++)
456 memset(&logfont, 0, sizeof(logfont));
457 logfont.lfHeight = 12;
458 logfont.lfWidth = 12;
459 logfont.lfWeight = weights[i][0];
460 lstrcpyW(logfont.lfFaceName, tahomaW);
462 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
463 EXPECT_HR(hr, S_OK);
465 weight = IDWriteFont_GetWeight(font);
466 ok(weight == weights[i][1],
467 "%d: got %d, expected %d\n", i, weight, weights[i][1]);
469 IDWriteFont_Release(font);
472 /* weight not from enum */
473 memset(&logfont, 0, sizeof(logfont));
474 logfont.lfHeight = 12;
475 logfont.lfWidth = 12;
476 logfont.lfWeight = 550;
477 lstrcpyW(logfont.lfFaceName, tahomaW);
479 font = NULL;
480 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
481 ok(hr == S_OK, "got 0x%08x\n", hr);
483 weight = IDWriteFont_GetWeight(font);
484 ok(weight == DWRITE_FONT_WEIGHT_NORMAL || broken(weight == DWRITE_FONT_WEIGHT_BOLD) /* win7 w/o SP */,
485 "got %d\n", weight);
486 IDWriteFont_Release(font);
488 /* empty or nonexistent face name */
489 memset(&logfont, 0, sizeof(logfont));
490 logfont.lfHeight = 12;
491 logfont.lfWidth = 12;
492 logfont.lfWeight = FW_NORMAL;
493 lstrcpyW(logfont.lfFaceName, blahW);
495 font = (void*)0xdeadbeef;
496 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
497 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
498 ok(font == NULL, "got %p\n", font);
500 /* Try with name 'Tahoma ' */
501 memset(&logfont, 0, sizeof(logfont));
502 logfont.lfHeight = 12;
503 logfont.lfWidth = 12;
504 logfont.lfWeight = FW_NORMAL;
505 lstrcpyW(logfont.lfFaceName, tahomaspW);
507 font = (void*)0xdeadbeef;
508 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
509 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
510 ok(font == NULL, "got %p\n", font);
512 /* empty string as a facename */
513 memset(&logfont, 0, sizeof(logfont));
514 logfont.lfHeight = 12;
515 logfont.lfWidth = 12;
516 logfont.lfWeight = FW_NORMAL;
518 font = (void*)0xdeadbeef;
519 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
520 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
521 ok(font == NULL, "got %p\n", font);
523 IDWriteGdiInterop_Release(interop);
524 IDWriteFactory_Release(factory);
527 static void test_CreateBitmapRenderTarget(void)
529 IDWriteBitmapRenderTarget *target, *target2;
530 IDWriteBitmapRenderTarget1 *target1;
531 IDWriteGdiInterop *interop;
532 IDWriteFactory *factory;
533 HBITMAP hbm, hbm2;
534 DWRITE_MATRIX m;
535 DIBSECTION ds;
536 HRESULT hr;
537 FLOAT pdip;
538 SIZE size;
539 HDC hdc;
540 int ret;
542 factory = create_factory();
544 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
545 EXPECT_HR(hr, S_OK);
547 target = NULL;
548 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target);
549 EXPECT_HR(hr, S_OK);
551 if (0) /* crashes on native */
552 hr = IDWriteBitmapRenderTarget_GetSize(target, NULL);
554 size.cx = size.cy = -1;
555 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
556 EXPECT_HR(hr, S_OK);
557 ok(size.cx == 0, "got %d\n", size.cx);
558 ok(size.cy == 0, "got %d\n", size.cy);
560 target2 = NULL;
561 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target2);
562 EXPECT_HR(hr, S_OK);
563 ok(target != target2, "got %p, %p\n", target2, target);
564 IDWriteBitmapRenderTarget_Release(target2);
566 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
567 ok(hdc != NULL, "got %p\n", hdc);
569 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
570 ok(hbm != NULL, "got %p\n", hbm);
572 /* check DIB properties */
573 ret = GetObjectW(hbm, sizeof(ds), &ds);
574 ok(ret == sizeof(BITMAP), "got %d\n", ret);
575 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
576 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
577 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
578 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
579 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
581 IDWriteBitmapRenderTarget_Release(target);
583 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
584 ok(!hbm, "got %p\n", hbm);
586 target = NULL;
587 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 10, 5, &target);
588 EXPECT_HR(hr, S_OK);
590 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
591 ok(hdc != NULL, "got %p\n", hdc);
593 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
594 ok(hbm != NULL, "got %p\n", hbm);
596 /* check DIB properties */
597 ret = GetObjectW(hbm, sizeof(ds), &ds);
598 ok(ret == sizeof(ds), "got %d\n", ret);
599 ok(ds.dsBm.bmWidth == 10, "got %d\n", ds.dsBm.bmWidth);
600 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
601 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
602 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
603 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
605 size.cx = size.cy = -1;
606 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
607 EXPECT_HR(hr, S_OK);
608 ok(size.cx == 10, "got %d\n", size.cx);
609 ok(size.cy == 5, "got %d\n", size.cy);
611 /* resize to same size */
612 hr = IDWriteBitmapRenderTarget_Resize(target, 10, 5);
613 ok(hr == S_OK, "got 0x%08x\n", hr);
615 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
616 ok(hbm2 == hbm, "got %p, %p\n", hbm2, hbm);
618 /* shrink */
619 hr = IDWriteBitmapRenderTarget_Resize(target, 5, 5);
620 ok(hr == S_OK, "got 0x%08x\n", hr);
622 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
623 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
625 hr = IDWriteBitmapRenderTarget_Resize(target, 20, 5);
626 ok(hr == S_OK, "got 0x%08x\n", hr);
628 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
629 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
631 hr = IDWriteBitmapRenderTarget_Resize(target, 1, 5);
632 ok(hr == S_OK, "got 0x%08x\n", hr);
634 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
635 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
637 ret = GetObjectW(hbm2, sizeof(ds), &ds);
638 ok(ret == sizeof(ds), "got %d\n", ret);
639 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
640 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
641 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
642 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
643 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
645 /* empty rectangle */
646 hr = IDWriteBitmapRenderTarget_Resize(target, 0, 5);
647 ok(hr == S_OK, "got 0x%08x\n", hr);
649 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
650 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
652 ret = GetObjectW(hbm2, sizeof(ds), &ds);
653 ok(ret == sizeof(BITMAP), "got %d\n", ret);
654 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
655 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
656 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
657 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
658 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
660 /* transform tests */
661 if (0) /* crashes on native */
662 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, NULL);
664 memset(&m, 0xcc, sizeof(m));
665 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
666 ok(hr == S_OK, "got 0x%08x\n", hr);
667 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);
668 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
670 memset(&m, 0, sizeof(m));
671 hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, &m);
672 ok(hr == S_OK, "got 0x%08x\n", hr);
674 memset(&m, 0xcc, sizeof(m));
675 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
676 ok(hr == S_OK, "got 0x%08x\n", hr);
677 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);
678 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
680 hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, NULL);
681 ok(hr == S_OK, "got 0x%08x\n", hr);
683 memset(&m, 0xcc, sizeof(m));
684 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
685 ok(hr == S_OK, "got 0x%08x\n", hr);
686 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);
687 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
689 /* pixels per dip */
690 pdip = IDWriteBitmapRenderTarget_GetPixelsPerDip(target);
691 ok(pdip == 1.0, "got %.2f\n", pdip);
693 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, 2.0);
694 ok(hr == S_OK, "got 0x%08x\n", hr);
696 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, -1.0);
697 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
699 hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, 0.0);
700 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
702 pdip = IDWriteBitmapRenderTarget_GetPixelsPerDip(target);
703 ok(pdip == 2.0, "got %.2f\n", pdip);
705 hr = IDWriteBitmapRenderTarget_QueryInterface(target, &IID_IDWriteBitmapRenderTarget1, (void**)&target1);
706 if (hr == S_OK) {
707 DWRITE_TEXT_ANTIALIAS_MODE mode;
709 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
710 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, "got %d\n", mode);
712 hr = IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE+1);
713 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
715 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
716 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, "got %d\n", mode);
718 hr = IDWriteBitmapRenderTarget1_SetTextAntialiasMode(target1, DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
719 ok(hr == S_OK, "got 0x%08x\n", hr);
721 mode = IDWriteBitmapRenderTarget1_GetTextAntialiasMode(target1);
722 ok(mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE, "got %d\n", mode);
724 IDWriteBitmapRenderTarget1_Release(target1);
726 else
727 win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
729 IDWriteBitmapRenderTarget_Release(target);
730 IDWriteGdiInterop_Release(interop);
731 IDWriteFactory_Release(factory);
734 static void test_GetFontFamily(void)
736 IDWriteFontCollection *collection, *collection2;
737 IDWriteFontCollection *syscoll;
738 IDWriteFontFamily *family, *family2;
739 IDWriteGdiInterop *interop;
740 IDWriteFont *font, *font2;
741 IDWriteFactory *factory;
742 LOGFONTW logfont;
743 HRESULT hr;
745 factory = create_factory();
747 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
748 EXPECT_HR(hr, S_OK);
750 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscoll, FALSE);
751 ok(hr == S_OK, "got 0x%08x\n", hr);
753 memset(&logfont, 0, sizeof(logfont));
754 logfont.lfHeight = 12;
755 logfont.lfWidth = 12;
756 logfont.lfWeight = FW_NORMAL;
757 logfont.lfItalic = 1;
758 lstrcpyW(logfont.lfFaceName, tahomaW);
760 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
761 ok(hr == S_OK, "got 0x%08x\n", hr);
763 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
764 ok(hr == S_OK, "got 0x%08x\n", hr);
765 ok(font2 != font, "got %p, %p\n", font2, font);
767 if (0) /* crashes on native */
768 hr = IDWriteFont_GetFontFamily(font, NULL);
770 EXPECT_REF(font, 1);
771 hr = IDWriteFont_GetFontFamily(font, &family);
772 EXPECT_HR(hr, S_OK);
773 EXPECT_REF(font, 1);
774 EXPECT_REF(family, 2);
776 hr = IDWriteFont_GetFontFamily(font, &family2);
777 EXPECT_HR(hr, S_OK);
778 ok(family2 == family, "got %p, previous %p\n", family2, family);
779 EXPECT_REF(font, 1);
780 EXPECT_REF(family, 3);
781 IDWriteFontFamily_Release(family2);
783 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFamily, (void**)&family2);
784 EXPECT_HR(hr, E_NOINTERFACE);
785 ok(family2 == NULL, "got %p\n", family2);
787 hr = IDWriteFont_GetFontFamily(font2, &family2);
788 ok(hr == S_OK, "got 0x%08x\n", hr);
789 ok(family2 != family, "got %p, %p\n", family2, family);
791 collection = NULL;
792 hr = IDWriteFontFamily_GetFontCollection(family, &collection);
793 ok(hr == S_OK, "got 0x%08x\n", hr);
795 collection2 = NULL;
796 hr = IDWriteFontFamily_GetFontCollection(family2, &collection2);
797 ok(hr == S_OK, "got 0x%08x\n", hr);
798 ok(collection == collection2, "got %p, %p\n", collection, collection2);
799 ok(collection == syscoll, "got %p, %p\n", collection, syscoll);
801 IDWriteFontCollection_Release(syscoll);
802 IDWriteFontCollection_Release(collection2);
803 IDWriteFontCollection_Release(collection);
804 IDWriteFontFamily_Release(family2);
805 IDWriteFontFamily_Release(family);
806 IDWriteFont_Release(font);
807 IDWriteFont_Release(font2);
808 IDWriteGdiInterop_Release(interop);
809 IDWriteFactory_Release(factory);
812 static void test_GetFamilyNames(void)
814 IDWriteFontFamily *family;
815 IDWriteLocalizedStrings *names, *names2;
816 IDWriteGdiInterop *interop;
817 IDWriteFactory *factory;
818 IDWriteFont *font;
819 LOGFONTW logfont;
820 WCHAR buffer[100];
821 HRESULT hr;
822 UINT32 len;
824 factory = create_factory();
826 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
827 EXPECT_HR(hr, S_OK);
829 memset(&logfont, 0, sizeof(logfont));
830 logfont.lfHeight = 12;
831 logfont.lfWidth = 12;
832 logfont.lfWeight = FW_NORMAL;
833 logfont.lfItalic = 1;
834 lstrcpyW(logfont.lfFaceName, tahomaW);
836 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
837 EXPECT_HR(hr, S_OK);
839 hr = IDWriteFont_GetFontFamily(font, &family);
840 EXPECT_HR(hr, S_OK);
842 if (0) /* crashes on native */
843 hr = IDWriteFontFamily_GetFamilyNames(family, NULL);
845 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
846 ok(hr == S_OK, "got 0x%08x\n", hr);
847 EXPECT_REF(names, 1);
849 hr = IDWriteFontFamily_GetFamilyNames(family, &names2);
850 ok(hr == S_OK, "got 0x%08x\n", hr);
851 EXPECT_REF(names2, 1);
852 ok(names != names2, "got %p, was %p\n", names2, names);
854 IDWriteLocalizedStrings_Release(names2);
856 /* GetStringLength */
857 if (0) /* crashes on native */
858 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, NULL);
860 len = 100;
861 hr = IDWriteLocalizedStrings_GetStringLength(names, 10, &len);
862 ok(hr == E_FAIL, "got 0x%08x\n", hr);
863 ok(len == (UINT32)-1, "got %u\n", len);
865 len = 0;
866 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, &len);
867 ok(hr == S_OK, "got 0x%08x\n", hr);
868 ok(len > 0, "got %u\n", len);
870 /* GetString */
871 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 0);
872 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
874 hr = IDWriteLocalizedStrings_GetString(names, 10, NULL, 0);
875 ok(hr == E_FAIL, "got 0x%08x\n", hr);
877 if (0)
878 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 100);
880 buffer[0] = 1;
881 hr = IDWriteLocalizedStrings_GetString(names, 10, buffer, 100);
882 ok(hr == E_FAIL, "got 0x%08x\n", hr);
883 ok(buffer[0] == 0, "got %x\n", buffer[0]);
885 buffer[0] = 1;
886 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len-1);
887 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
888 ok(buffer[0] == 0, "got %x\n", buffer[0]);
890 buffer[0] = 1;
891 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len);
892 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
893 ok(buffer[0] == 0, "got %x\n", buffer[0]);
895 buffer[0] = 0;
896 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len+1);
897 ok(hr == S_OK, "got 0x%08x\n", hr);
898 ok(buffer[0] != 0, "got %x\n", buffer[0]);
900 IDWriteLocalizedStrings_Release(names);
902 IDWriteFontFamily_Release(family);
903 IDWriteFont_Release(font);
904 IDWriteGdiInterop_Release(interop);
905 IDWriteFactory_Release(factory);
908 static void test_CreateFontFace(void)
910 IDWriteFontFace *fontface, *fontface2;
911 IDWriteFontCollection *collection;
912 IDWriteGdiInterop *interop;
913 IDWriteFont *font, *font2;
914 IDWriteFontFamily *family;
915 IDWriteFactory *factory;
916 LOGFONTW logfont;
917 HRESULT hr;
919 factory = create_factory();
921 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
922 EXPECT_HR(hr, S_OK);
924 memset(&logfont, 0, sizeof(logfont));
925 logfont.lfHeight = 12;
926 logfont.lfWidth = 12;
927 logfont.lfWeight = FW_NORMAL;
928 logfont.lfItalic = 1;
929 lstrcpyW(logfont.lfFaceName, tahomaW);
931 font = NULL;
932 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
933 ok(hr == S_OK, "got 0x%08x\n", hr);
935 font2 = NULL;
936 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
937 ok(hr == S_OK, "got 0x%08x\n", hr);
938 ok(font != font2, "got %p, %p\n", font, font2);
940 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface);
941 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
943 if (0) /* crashes on native */
944 hr = IDWriteFont_CreateFontFace(font, NULL);
946 fontface = NULL;
947 hr = IDWriteFont_CreateFontFace(font, &fontface);
948 ok(hr == S_OK, "got 0x%08x\n", hr);
950 fontface2 = NULL;
951 hr = IDWriteFont_CreateFontFace(font, &fontface2);
952 ok(hr == S_OK, "got 0x%08x\n", hr);
953 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
954 IDWriteFontFace_Release(fontface2);
956 fontface2 = NULL;
957 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
958 ok(hr == S_OK, "got 0x%08x\n", hr);
959 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
960 IDWriteFontFace_Release(fontface2);
962 IDWriteFont_Release(font2);
963 IDWriteFont_Release(font);
965 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFont, (void**)&font);
966 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL), "got 0x%08x\n", hr);
968 IDWriteFontFace_Release(fontface);
969 IDWriteGdiInterop_Release(interop);
971 /* Create from system collection */
972 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
973 ok(hr == S_OK, "got 0x%08x\n", hr);
975 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
976 ok(hr == S_OK, "got 0x%08x\n", hr);
978 font = NULL;
979 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
980 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
981 ok(hr == S_OK, "got 0x%08x\n", hr);
983 font2 = NULL;
984 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
985 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font2);
986 ok(hr == S_OK, "got 0x%08x\n", hr);
987 ok(font != font2, "got %p, %p\n", font, font2);
989 fontface = NULL;
990 hr = IDWriteFont_CreateFontFace(font, &fontface);
991 ok(hr == S_OK, "got 0x%08x\n", hr);
993 fontface2 = NULL;
994 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
995 ok(hr == S_OK, "got 0x%08x\n", hr);
996 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
998 IDWriteFontFace_Release(fontface);
999 IDWriteFontFace_Release(fontface2);
1000 IDWriteFont_Release(font2);
1001 IDWriteFont_Release(font);
1002 IDWriteFontFamily_Release(family);
1003 IDWriteFontCollection_Release(collection);
1004 IDWriteFactory_Release(factory);
1007 static void test_GetMetrics(void)
1009 IDWriteGdiInterop *interop;
1010 DWRITE_FONT_METRICS metrics;
1011 IDWriteFontFace *fontface;
1012 IDWriteFactory *factory;
1013 OUTLINETEXTMETRICW otm;
1014 IDWriteFont1 *font1;
1015 IDWriteFont *font;
1016 LOGFONTW logfont;
1017 HRESULT hr;
1018 HDC hdc;
1019 HFONT hfont;
1020 int ret;
1022 factory = create_factory();
1024 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1025 EXPECT_HR(hr, S_OK);
1027 memset(&logfont, 0, sizeof(logfont));
1028 logfont.lfHeight = 12;
1029 logfont.lfWidth = 12;
1030 logfont.lfWeight = FW_NORMAL;
1031 logfont.lfItalic = 1;
1032 lstrcpyW(logfont.lfFaceName, tahomaW);
1034 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1035 ok(hr == S_OK, "got 0x%08x\n", hr);
1037 hfont = CreateFontIndirectW(&logfont);
1038 hdc = CreateCompatibleDC(0);
1039 SelectObject(hdc, hfont);
1041 otm.otmSize = sizeof(otm);
1042 ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
1043 ok(ret, "got %d\n", ret);
1044 DeleteDC(hdc);
1045 DeleteObject(hfont);
1047 if (0) /* crashes on native */
1048 IDWriteFont_GetMetrics(font, NULL);
1050 memset(&metrics, 0, sizeof(metrics));
1051 IDWriteFont_GetMetrics(font, &metrics);
1053 ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
1054 ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
1055 ok(metrics.descent != 0, "descent %u\n", metrics.descent);
1056 todo_wine
1057 ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
1058 ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
1059 ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
1060 ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
1061 ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
1062 ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
1063 ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
1065 hr = IDWriteFont_CreateFontFace(font, &fontface);
1066 ok(hr == S_OK, "got 0x%08x\n", hr);
1068 memset(&metrics, 0, sizeof(metrics));
1069 IDWriteFontFace_GetMetrics(fontface, &metrics);
1071 ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
1072 ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
1073 ok(metrics.descent != 0, "descent %u\n", metrics.descent);
1074 todo_wine
1075 ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
1076 ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
1077 ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
1078 ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
1079 ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
1080 ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
1081 ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
1083 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
1084 if (hr == S_OK) {
1085 DWRITE_FONT_METRICS1 metrics1;
1086 IDWriteFontFace1 *fontface1;
1088 memset(&metrics1, 0, sizeof(metrics1));
1089 IDWriteFont1_GetMetrics(font1, &metrics1);
1091 ok(metrics1.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics1.designUnitsPerEm);
1092 ok(metrics1.ascent != 0, "ascent %u\n", metrics1.ascent);
1093 ok(metrics1.descent != 0, "descent %u\n", metrics1.descent);
1094 todo_wine
1095 ok(metrics1.lineGap == 0, "lineGap %d\n", metrics1.lineGap);
1096 ok(metrics1.capHeight, "capHeight %u\n", metrics1.capHeight);
1097 ok(metrics1.xHeight != 0, "xHeight %u\n", metrics1.xHeight);
1098 ok(metrics1.underlinePosition < 0, "underlinePosition %d\n", metrics1.underlinePosition);
1099 ok(metrics1.underlineThickness != 0, "underlineThickness %u\n", metrics1.underlineThickness);
1100 ok(metrics1.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics1.strikethroughPosition);
1101 ok(metrics1.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics1.strikethroughThickness);
1102 ok(metrics1.glyphBoxLeft < 0, "glyphBoxLeft %d\n", metrics1.glyphBoxLeft);
1103 ok(metrics1.glyphBoxTop > 0, "glyphBoxTop %d\n", metrics1.glyphBoxTop);
1104 ok(metrics1.glyphBoxRight > 0, "glyphBoxRight %d\n", metrics1.glyphBoxRight);
1105 ok(metrics1.glyphBoxBottom < 0, "glyphBoxBottom %d\n", metrics1.glyphBoxBottom);
1106 ok(metrics1.subscriptPositionY < 0, "subscriptPositionY %d\n", metrics1.subscriptPositionY);
1107 ok(metrics1.subscriptSizeX > 0, "subscriptSizeX %d\n", metrics1.subscriptSizeX);
1108 ok(metrics1.subscriptSizeY > 0, "subscriptSizeY %d\n", metrics1.subscriptSizeY);
1109 ok(metrics1.superscriptPositionY > 0, "superscriptPositionY %d\n", metrics1.superscriptPositionY);
1110 ok(metrics1.superscriptSizeX > 0, "superscriptSizeX %d\n", metrics1.superscriptSizeX);
1111 ok(metrics1.superscriptSizeY > 0, "superscriptSizeY %d\n", metrics1.superscriptSizeY);
1112 ok(!metrics1.hasTypographicMetrics, "hasTypographicMetrics %d\n", metrics1.hasTypographicMetrics);
1114 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
1115 ok(hr == S_OK, "got 0x%08x\n", hr);
1117 memset(&metrics1, 0, sizeof(metrics1));
1118 IDWriteFontFace1_GetMetrics(fontface1, &metrics1);
1120 ok(metrics1.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics1.designUnitsPerEm);
1121 ok(metrics1.ascent != 0, "ascent %u\n", metrics1.ascent);
1122 ok(metrics1.descent != 0, "descent %u\n", metrics1.descent);
1123 todo_wine
1124 ok(metrics1.lineGap == 0, "lineGap %d\n", metrics1.lineGap);
1125 ok(metrics1.capHeight, "capHeight %u\n", metrics1.capHeight);
1126 ok(metrics1.xHeight != 0, "xHeight %u\n", metrics1.xHeight);
1127 ok(metrics1.underlinePosition < 0, "underlinePosition %d\n", metrics1.underlinePosition);
1128 ok(metrics1.underlineThickness != 0, "underlineThickness %u\n", metrics1.underlineThickness);
1129 ok(metrics1.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics1.strikethroughPosition);
1130 ok(metrics1.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics1.strikethroughThickness);
1131 ok(metrics1.glyphBoxLeft < 0, "glyphBoxLeft %d\n", metrics1.glyphBoxLeft);
1132 ok(metrics1.glyphBoxTop > 0, "glyphBoxTop %d\n", metrics1.glyphBoxTop);
1133 ok(metrics1.glyphBoxRight > 0, "glyphBoxRight %d\n", metrics1.glyphBoxRight);
1134 ok(metrics1.glyphBoxBottom < 0, "glyphBoxBottom %d\n", metrics1.glyphBoxBottom);
1135 ok(metrics1.subscriptPositionY < 0, "subscriptPositionY %d\n", metrics1.subscriptPositionY);
1136 ok(metrics1.subscriptSizeX > 0, "subscriptSizeX %d\n", metrics1.subscriptSizeX);
1137 ok(metrics1.subscriptSizeY > 0, "subscriptSizeY %d\n", metrics1.subscriptSizeY);
1138 ok(metrics1.superscriptPositionY > 0, "superscriptPositionY %d\n", metrics1.superscriptPositionY);
1139 ok(metrics1.superscriptSizeX > 0, "superscriptSizeX %d\n", metrics1.superscriptSizeX);
1140 ok(metrics1.superscriptSizeY > 0, "superscriptSizeY %d\n", metrics1.superscriptSizeY);
1141 ok(!metrics1.hasTypographicMetrics, "hasTypographicMetrics %d\n", metrics1.hasTypographicMetrics);
1143 IDWriteFontFace1_Release(fontface1);
1144 IDWriteFont1_Release(font1);
1146 else
1147 win_skip("DWRITE_FONT_METRICS1 is not supported.\n");
1149 IDWriteFontFace_Release(fontface);
1151 IDWriteFont_Release(font);
1152 IDWriteGdiInterop_Release(interop);
1153 IDWriteFactory_Release(factory);
1156 static void test_system_fontcollection(void)
1158 IDWriteFontCollection *collection, *coll2;
1159 IDWriteLocalFontFileLoader *localloader;
1160 IDWriteFactory *factory, *factory2;
1161 IDWriteFontFileLoader *loader;
1162 IDWriteFontFamily *family;
1163 IDWriteFontFace *fontface;
1164 IDWriteFontFile *file;
1165 IDWriteFont *font;
1166 HRESULT hr;
1167 UINT32 i;
1168 BOOL ret;
1170 factory = create_factory();
1172 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1173 ok(hr == S_OK, "got 0x%08x\n", hr);
1175 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, FALSE);
1176 ok(hr == S_OK, "got 0x%08x\n", hr);
1177 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
1178 IDWriteFontCollection_Release(coll2);
1180 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, TRUE);
1181 ok(hr == S_OK, "got 0x%08x\n", hr);
1182 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
1183 IDWriteFontCollection_Release(coll2);
1185 factory2 = create_factory();
1186 hr = IDWriteFactory_GetSystemFontCollection(factory2, &coll2, FALSE);
1187 ok(hr == S_OK, "got 0x%08x\n", hr);
1188 ok(coll2 != collection, "got %p, was %p\n", coll2, collection);
1189 IDWriteFontCollection_Release(coll2);
1190 IDWriteFactory_Release(factory2);
1192 i = IDWriteFontCollection_GetFontFamilyCount(collection);
1193 ok(i, "got %u\n", i);
1195 /* invalid index */
1196 family = (void*)0xdeadbeef;
1197 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
1198 ok(hr == E_FAIL, "got 0x%08x\n", hr);
1199 ok(family == NULL, "got %p\n", family);
1201 ret = FALSE;
1202 i = (UINT32)-1;
1203 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaW, &i, &ret);
1204 ok(hr == S_OK, "got 0x%08x\n", hr);
1205 ok(ret, "got %d\n", ret);
1206 ok(i != (UINT32)-1, "got %u\n", i);
1208 /* get back local file loader */
1209 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
1210 ok(hr == S_OK, "got 0x%08x\n", hr);
1212 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1213 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1214 ok(hr == S_OK, "got 0x%08x\n", hr);
1215 IDWriteFontFamily_Release(family);
1217 hr = IDWriteFont_CreateFontFace(font, &fontface);
1218 ok(hr == S_OK, "got 0x%08x\n", hr);
1219 IDWriteFont_Release(font);
1221 i = 1;
1222 file = NULL;
1223 hr = IDWriteFontFace_GetFiles(fontface, &i, &file);
1224 ok(hr == S_OK, "got 0x%08x\n", hr);
1225 ok(file != NULL, "got %p\n", file);
1227 hr = IDWriteFontFile_GetLoader(file, &loader);
1228 ok(hr == S_OK, "got 0x%08x\n", hr);
1229 IDWriteFontFile_Release(file);
1231 hr = IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
1232 ok(hr == S_OK, "got 0x%08x\n", hr);
1233 IDWriteLocalFontFileLoader_Release(localloader);
1235 /* local loader is not registered by default */
1236 hr = IDWriteFactory_RegisterFontFileLoader(factory, loader);
1237 ok(hr == S_OK || broken(hr == DWRITE_E_ALREADYREGISTERED), "got 0x%08x\n", hr);
1238 hr = IDWriteFactory_UnregisterFontFileLoader(factory, loader);
1239 ok(hr == S_OK || broken(hr == E_INVALIDARG), "got 0x%08x\n", hr);
1241 /* try with a different factory */
1242 factory2 = create_factory();
1243 hr = IDWriteFactory_RegisterFontFileLoader(factory2, loader);
1244 ok(hr == S_OK || broken(hr == DWRITE_E_ALREADYREGISTERED), "got 0x%08x\n", hr);
1245 hr = IDWriteFactory_RegisterFontFileLoader(factory2, loader);
1246 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1247 hr = IDWriteFactory_UnregisterFontFileLoader(factory2, loader);
1248 ok(hr == S_OK || broken(hr == E_INVALIDARG), "got 0x%08x\n", hr);
1249 hr = IDWriteFactory_UnregisterFontFileLoader(factory2, loader);
1250 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1251 IDWriteFactory_Release(factory2);
1253 IDWriteFontFileLoader_Release(loader);
1255 ret = TRUE;
1256 i = 0;
1257 hr = IDWriteFontCollection_FindFamilyName(collection, blahW, &i, &ret);
1258 ok(hr == S_OK, "got 0x%08x\n", hr);
1259 ok(!ret, "got %d\n", ret);
1260 ok(i == (UINT32)-1, "got %u\n", i);
1262 IDWriteFontCollection_Release(collection);
1263 IDWriteFactory_Release(factory);
1266 static void test_ConvertFontFaceToLOGFONT(void)
1268 DWRITE_FONT_SIMULATIONS sim;
1269 IDWriteGdiInterop *interop;
1270 IDWriteFontFace *fontface;
1271 IDWriteFactory *factory;
1272 IDWriteFont *font;
1273 LOGFONTW logfont;
1274 HRESULT hr;
1276 factory = create_factory();
1278 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1279 ok(hr == S_OK, "got 0x%08x\n", hr);
1281 memset(&logfont, 0, sizeof(logfont));
1282 logfont.lfHeight = 12;
1283 logfont.lfWidth = 12;
1284 logfont.lfEscapement = 100;
1285 logfont.lfWeight = FW_NORMAL;
1286 logfont.lfItalic = 1;
1287 logfont.lfUnderline = 1;
1288 logfont.lfStrikeOut = 1;
1290 lstrcpyW(logfont.lfFaceName, tahomaW);
1292 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
1293 ok(hr == S_OK, "got 0x%08x\n", hr);
1295 hr = IDWriteFont_CreateFontFace(font, &fontface);
1296 ok(hr == S_OK, "got 0x%08x\n", hr);
1298 sim = IDWriteFont_GetSimulations(font);
1299 ok(sim == DWRITE_FONT_SIMULATIONS_OBLIQUE, "sim %d\n", sim);
1301 sim = IDWriteFontFace_GetSimulations(fontface);
1302 ok(sim == DWRITE_FONT_SIMULATIONS_OBLIQUE, "sim %d\n", sim);
1304 IDWriteFont_Release(font);
1306 if (0) /* crashes on native */
1308 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, NULL, NULL);
1309 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, NULL);
1312 memset(&logfont, 0xa, sizeof(logfont));
1313 logfont.lfFaceName[0] = 0;
1315 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, &logfont);
1316 ok(hr == S_OK, "got 0x%08x\n", hr);
1317 ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight);
1318 ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth);
1319 ok(logfont.lfWeight == FW_NORMAL, "got %d\n", logfont.lfWeight);
1320 ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement);
1321 ok(logfont.lfItalic == 1, "got %d\n", logfont.lfItalic);
1322 ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline);
1323 ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut);
1324 todo_wine
1325 ok(!lstrcmpW(logfont.lfFaceName, tahomaW), "got %s\n", wine_dbgstr_w(logfont.lfFaceName));
1327 IDWriteGdiInterop_Release(interop);
1328 IDWriteFontFace_Release(fontface);
1329 IDWriteFactory_Release(factory);
1332 static HRESULT WINAPI fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
1334 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileEnumerator))
1336 *obj = iface;
1337 IDWriteFontFileEnumerator_AddRef(iface);
1338 return S_OK;
1340 return E_NOINTERFACE;
1343 static ULONG WINAPI fontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
1345 return 2;
1348 static ULONG WINAPI fontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
1350 return 1;
1353 static HRESULT WINAPI fontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file)
1355 *file = NULL;
1356 return E_FAIL;
1359 static HRESULT WINAPI fontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
1361 *current = FALSE;
1362 return S_OK;
1365 static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl =
1367 fontfileenumerator_QueryInterface,
1368 fontfileenumerator_AddRef,
1369 fontfileenumerator_Release,
1370 fontfileenumerator_MoveNext,
1371 fontfileenumerator_GetCurrentFontFile,
1374 static HRESULT WINAPI fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
1376 *obj = iface;
1377 return S_OK;
1380 static ULONG WINAPI fontcollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
1382 return 2;
1385 static ULONG WINAPI fontcollectionloader_Release(IDWriteFontCollectionLoader *iface)
1387 return 1;
1390 static HRESULT WINAPI fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory, const void *key,
1391 UINT32 key_size, IDWriteFontFileEnumerator **ret)
1393 static IDWriteFontFileEnumerator enumerator = { &dwritefontfileenumeratorvtbl };
1394 *ret = &enumerator;
1395 return S_OK;
1398 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl = {
1399 fontcollectionloader_QueryInterface,
1400 fontcollectionloader_AddRef,
1401 fontcollectionloader_Release,
1402 fontcollectionloader_CreateEnumeratorFromKey
1405 static void test_CustomFontCollection(void)
1407 static const WCHAR fontnameW[] = {'w','i','n','e','_','t','e','s','t',0};
1408 IDWriteFontCollectionLoader collection = { &dwritefontcollectionloadervtbl };
1409 IDWriteFontCollectionLoader collection2 = { &dwritefontcollectionloadervtbl };
1410 IDWriteFontCollectionLoader collection3 = { &dwritefontcollectionloadervtbl };
1411 IDWriteFontCollection *font_collection = NULL;
1412 static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
1413 struct test_fontcollectionloader resource_collection = { { &resourcecollectionloadervtbl }, &rloader };
1414 IDWriteFontFamily *family, *family2, *family3;
1415 IDWriteFontFace *idfontface, *idfontface2;
1416 IDWriteFontFile *fontfile, *fontfile2;
1417 IDWriteLocalizedStrings *string;
1418 IDWriteFont *idfont, *idfont2;
1419 IDWriteFactory *factory;
1420 UINT32 index, count;
1421 BOOL exists;
1422 HRESULT hr;
1423 HRSRC font;
1425 factory = create_factory();
1427 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, NULL);
1428 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1430 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, NULL);
1431 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1433 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
1434 ok(hr == S_OK, "got 0x%08x\n", hr);
1435 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection2);
1436 ok(hr == S_OK, "got 0x%08x\n", hr);
1437 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
1438 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1440 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1441 ok(hr == S_OK, "got 0x%08x\n", hr);
1442 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface);
1443 ok(hr == S_OK, "got 0x%08x\n", hr);
1445 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection3, "Billy", 6, &font_collection);
1446 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1448 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection, "Billy", 6, &font_collection);
1449 ok(hr == S_OK, "got 0x%08x\n", hr);
1450 IDWriteFontCollection_Release(font_collection);
1452 hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection2, "Billy", 6, &font_collection);
1453 ok(hr == S_OK, "got 0x%08x\n", hr);
1454 IDWriteFontCollection_Release(font_collection);
1456 hr = IDWriteFactory_CreateCustomFontCollection(factory, (IDWriteFontCollectionLoader*)0xdeadbeef, "Billy", 6, &font_collection);
1457 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1459 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1460 ok(font != NULL, "Failed to find font resource\n");
1462 hr = IDWriteFactory_CreateCustomFontCollection(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface,
1463 &font, sizeof(HRSRC), &font_collection);
1464 ok(hr == S_OK, "got 0x%08x\n",hr);
1466 index = 1;
1467 exists = FALSE;
1468 hr = IDWriteFontCollection_FindFamilyName(font_collection, fontnameW, &index, &exists);
1469 ok(hr == S_OK, "got 0x%08x\n", hr);
1470 ok(index == 0, "got index %i\n", index);
1471 ok(exists, "got exists %i\n", exists);
1473 count = IDWriteFontCollection_GetFontFamilyCount(font_collection);
1474 ok(count == 1, "got %u\n", count);
1476 family = NULL;
1477 hr = IDWriteFontCollection_GetFontFamily(font_collection, 0, &family);
1478 ok(hr == S_OK, "got 0x%08x\n", hr);
1479 EXPECT_REF(family, 1);
1481 family2 = NULL;
1482 hr = IDWriteFontCollection_GetFontFamily(font_collection, 0, &family2);
1483 ok(hr == S_OK, "got 0x%08x\n", hr);
1484 EXPECT_REF(family2, 1);
1485 ok(family != family2, "got %p, %p\n", family, family2);
1487 hr = IDWriteFontFamily_GetFont(family, 0, &idfont);
1488 ok(hr == S_OK, "got 0x%08x\n", hr);
1489 EXPECT_REF(idfont, 1);
1490 EXPECT_REF(family, 2);
1491 hr = IDWriteFontFamily_GetFont(family, 0, &idfont2);
1492 ok(hr == S_OK, "got 0x%08x\n", hr);
1493 EXPECT_REF(idfont2, 1);
1494 EXPECT_REF(family, 3);
1495 ok(idfont != idfont2, "got %p, %p\n", idfont, idfont2);
1496 IDWriteFont_Release(idfont2);
1498 hr = IDWriteFont_GetInformationalStrings(idfont, DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE, &string, &exists);
1499 ok(hr == S_OK, "got 0x%08x\n", hr);
1500 ok(exists, "got %d\n", exists);
1501 EXPECT_REF(string, 1);
1503 family3 = NULL;
1504 hr = IDWriteFont_GetFontFamily(idfont, &family3);
1505 ok(hr == S_OK, "got 0x%08x\n", hr);
1506 EXPECT_REF(family, 3);
1507 ok(family == family3, "got %p, %p\n", family, family3);
1508 IDWriteFontFamily_Release(family3);
1510 idfontface = NULL;
1511 hr = IDWriteFont_CreateFontFace(idfont, &idfontface);
1512 ok(hr == S_OK, "got 0x%08x\n", hr);
1513 EXPECT_REF(idfont, 1);
1515 idfont2 = NULL;
1516 hr = IDWriteFontFamily_GetFont(family2, 0, &idfont2);
1517 ok(hr == S_OK, "got 0x%08x\n", hr);
1518 EXPECT_REF(idfont2, 1);
1519 EXPECT_REF(idfont, 1);
1520 ok(idfont2 != idfont, "Font instances shoudl not match\n");
1522 idfontface2 = NULL;
1523 hr = IDWriteFont_CreateFontFace(idfont2, &idfontface2);
1524 ok(hr == S_OK, "got 0x%08x\n", hr);
1525 ok(idfontface2 == idfontface, "fontfaces should match\n");
1527 index = 1;
1528 fontfile = NULL;
1529 hr = IDWriteFontFace_GetFiles(idfontface, &index, &fontfile);
1530 ok(hr == S_OK, "got 0x%08x\n", hr);
1532 index = 1;
1533 fontfile2 = NULL;
1534 hr = IDWriteFontFace_GetFiles(idfontface2, &index, &fontfile2);
1535 ok(hr == S_OK, "got 0x%08x\n", hr);
1536 ok(fontfile == fontfile2, "fontfiles should match\n");
1538 IDWriteFont_Release(idfont);
1539 IDWriteFont_Release(idfont2);
1540 IDWriteFontFile_Release(fontfile);
1541 IDWriteFontFile_Release(fontfile2);
1542 IDWriteFontFace_Release(idfontface);
1543 IDWriteFontFace_Release(idfontface2);
1544 IDWriteFontFamily_Release(family2);
1545 IDWriteFontFamily_Release(family);
1546 IDWriteFontCollection_Release(font_collection);
1548 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
1549 ok(hr == S_OK, "got 0x%08x\n", hr);
1550 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
1551 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1552 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection2);
1553 ok(hr == S_OK, "got 0x%08x\n", hr);
1554 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface);
1555 ok(hr == S_OK, "got 0x%08x\n", hr);
1556 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1557 ok(hr == S_OK, "got 0x%08x\n", hr);
1559 IDWriteFactory_Release(factory);
1562 static HRESULT WINAPI fontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
1564 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
1566 *obj = iface;
1567 IDWriteFontFileLoader_AddRef(iface);
1568 return S_OK;
1571 *obj = NULL;
1572 return E_NOINTERFACE;
1575 static ULONG WINAPI fontfileloader_AddRef(IDWriteFontFileLoader *iface)
1577 return 2;
1580 static ULONG WINAPI fontfileloader_Release(IDWriteFontFileLoader *iface)
1582 return 1;
1585 static HRESULT WINAPI fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1587 return 0x8faecafe;
1590 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl = {
1591 fontfileloader_QueryInterface,
1592 fontfileloader_AddRef,
1593 fontfileloader_Release,
1594 fontfileloader_CreateStreamFromKey
1597 static void test_CreateCustomFontFileReference(void)
1599 IDWriteFontFileLoader floader = { &dwritefontfileloadervtbl };
1600 IDWriteFontFileLoader floader2 = { &dwritefontfileloadervtbl };
1601 IDWriteFontFileLoader floader3 = { &dwritefontfileloadervtbl };
1602 IDWriteFactory *factory, *factory2;
1603 IDWriteFontFile *file, *file2;
1604 BOOL support;
1605 DWRITE_FONT_FILE_TYPE file_type;
1606 DWRITE_FONT_FACE_TYPE face_type;
1607 UINT32 count;
1608 IDWriteFontFace *face, *face2;
1609 HRESULT hr;
1610 HRSRC fontrsrc;
1611 UINT32 codePoints[1] = {0xa8};
1612 UINT16 indices[1];
1614 factory = create_factory();
1615 factory2 = create_factory();
1617 hr = IDWriteFactory_RegisterFontFileLoader(factory, NULL);
1618 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1619 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
1620 ok(hr == S_OK, "got 0x%08x\n", hr);
1621 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader2);
1622 ok(hr == S_OK, "got 0x%08x\n", hr);
1623 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
1624 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1625 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1626 ok(hr == S_OK, "got 0x%08x\n", hr);
1628 file = NULL;
1629 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &file);
1630 ok(hr == S_OK, "got 0x%08x\n", hr);
1631 IDWriteFontFile_Release(file);
1633 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader3, &file);
1634 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1636 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, NULL, &file);
1637 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1639 file = NULL;
1640 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &file);
1641 ok(hr == S_OK, "got 0x%08x\n", hr);
1643 file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE;
1644 face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE;
1645 support = TRUE;
1646 count = 1;
1647 IDWriteFontFile_Analyze(file, &support, &file_type, &face_type, &count);
1648 ok(hr == S_OK, "got 0x%08x\n", hr);
1649 ok(support == FALSE, "got %i\n", support);
1650 ok(file_type == DWRITE_FONT_FILE_TYPE_UNKNOWN, "got %i\n", file_type);
1651 ok(face_type == DWRITE_FONT_FACE_TYPE_UNKNOWN, "got %i\n", face_type);
1652 ok(count == 0, "got %i\n", count);
1654 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_CFF, 1, &file, 0, 0, &face);
1655 ok(hr == 0x8faecafe, "got 0x%08x\n", hr);
1656 IDWriteFontFile_Release(file);
1658 fontrsrc = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1659 ok(fontrsrc != NULL, "Failed to find font resource\n");
1661 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontrsrc, sizeof(HRSRC), &rloader, &file);
1662 ok(hr == S_OK, "got 0x%08x\n", hr);
1664 file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1665 face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1666 support = FALSE;
1667 count = 0;
1668 hr = IDWriteFontFile_Analyze(file, &support, &file_type, &face_type, &count);
1669 ok(hr == S_OK, "got 0x%08x\n", hr);
1670 ok(support == TRUE, "got %i\n", support);
1671 ok(file_type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", file_type);
1672 ok(face_type == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face_type);
1673 ok(count == 1, "got %i\n", count);
1675 /* invalid index */
1676 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 1, DWRITE_FONT_SIMULATIONS_NONE, &face);
1677 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1679 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face);
1680 ok(hr == S_OK, "got 0x%08x\n", hr);
1682 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
1683 ok(hr == S_OK, "got 0x%08x\n", hr);
1684 /* fontface instances are reused starting with win7 */
1685 ok(face == face2 || broken(face != face2), "got %p, %p\n", face, face2);
1686 IDWriteFontFace_Release(face2);
1688 /* file was created with different factory */
1689 face2 = NULL;
1690 hr = IDWriteFactory_CreateFontFace(factory2, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
1691 todo_wine
1692 ok(hr == S_OK, "got 0x%08x\n", hr);
1693 if (face2)
1694 IDWriteFontFace_Release(face2);
1696 file2 = NULL;
1697 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontrsrc, sizeof(HRSRC), &rloader, &file2);
1698 ok(hr == S_OK, "got 0x%08x\n", hr);
1699 ok(file != file2, "got %p, %p\n", file, file2);
1701 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file2, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
1702 ok(hr == S_OK, "got 0x%08x\n", hr);
1703 /* fontface instances are reused starting with win7 */
1704 ok(face == face2 || broken(face != face2), "got %p, %p\n", face, face2);
1705 IDWriteFontFace_Release(face2);
1706 IDWriteFontFile_Release(file2);
1708 hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 1, indices);
1709 ok(hr == S_OK, "got 0x%08x\n", hr);
1710 ok(indices[0] == 6, "got index %i\n", indices[0]);
1711 IDWriteFontFace_Release(face);
1712 IDWriteFontFile_Release(file);
1714 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
1715 ok(hr == S_OK, "got 0x%08x\n", hr);
1716 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
1717 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1718 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader2);
1719 ok(hr == S_OK, "got 0x%08x\n", hr);
1720 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1721 ok(hr == S_OK, "got 0x%08x\n", hr);
1723 IDWriteFactory_Release(factory2);
1724 IDWriteFactory_Release(factory);
1727 static void create_testfontfile(const WCHAR *filename)
1729 DWORD written;
1730 HANDLE file;
1731 HRSRC res;
1732 void *ptr;
1733 file = CreateFileW(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1734 ok( file != INVALID_HANDLE_VALUE, "file creation failed\n" );
1736 res = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1737 ok( res != 0, "couldn't find resource\n" );
1738 ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
1739 WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
1740 ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
1741 CloseHandle( file );
1744 static void test_CreateFontFileReference(void)
1746 HRESULT hr;
1747 IDWriteFontFile *ffile = NULL;
1748 BOOL support;
1749 DWRITE_FONT_FILE_TYPE type;
1750 DWRITE_FONT_FACE_TYPE face;
1751 UINT32 count;
1752 IDWriteFontFace *fface = NULL;
1753 IDWriteFactory *factory;
1755 create_testfontfile(test_fontfile);
1756 factory = create_factory();
1758 hr = IDWriteFactory_CreateFontFileReference(factory, test_fontfile, NULL, &ffile);
1759 ok(hr == S_OK, "got 0x%08x\n",hr);
1761 support = FALSE;
1762 type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1763 face = DWRITE_FONT_FACE_TYPE_CFF;
1764 count = 0;
1765 hr = IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
1766 ok(hr == S_OK, "got 0x%08x\n", hr);
1767 ok(support == TRUE, "got %i\n", support);
1768 ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type);
1769 ok(face == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face);
1770 ok(count == 1, "got %i\n", count);
1772 hr = IDWriteFactory_CreateFontFace(factory, face, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fface);
1773 ok(hr == S_OK, "got 0x%08x\n", hr);
1775 IDWriteFontFace_Release(fface);
1776 IDWriteFontFile_Release(ffile);
1777 IDWriteFactory_Release(factory);
1779 DeleteFileW(test_fontfile);
1782 static void test_shared_isolated(void)
1784 IDWriteFactory *isolated, *isolated2;
1785 IDWriteFactory *shared, *shared2;
1786 HRESULT hr;
1788 /* invalid type */
1789 shared = NULL;
1790 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&shared);
1791 ok(hr == S_OK, "got 0x%08x\n", hr);
1792 ok(shared != NULL, "got %p\n", shared);
1793 IDWriteFactory_Release(shared);
1795 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared);
1796 ok(hr == S_OK, "got 0x%08x\n", hr);
1798 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
1799 ok(hr == S_OK, "got 0x%08x\n", hr);
1800 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
1802 IDWriteFactory_Release(shared);
1803 IDWriteFactory_Release(shared2);
1805 /* we got 2 references, released 2 - still same pointer is returned */
1806 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
1807 ok(hr == S_OK, "got 0x%08x\n", hr);
1808 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
1809 IDWriteFactory_Release(shared2);
1811 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated);
1812 ok(hr == S_OK, "got 0x%08x\n", hr);
1814 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated2);
1815 ok(hr == S_OK, "got 0x%08x\n", hr);
1816 ok(isolated != isolated2, "got %p, and %p\n", isolated, isolated2);
1817 IDWriteFactory_Release(isolated2);
1819 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&isolated2);
1820 ok(hr == S_OK, "got 0x%08x\n", hr);
1821 ok(shared != isolated2, "got %p, and %p\n", shared, isolated2);
1823 IDWriteFactory_Release(isolated);
1824 IDWriteFactory_Release(isolated2);
1827 static void test_GetUnicodeRanges(void)
1829 DWRITE_UNICODE_RANGE *ranges, r;
1830 IDWriteFontFile *ffile = NULL;
1831 IDWriteFontFace1 *fontface1;
1832 IDWriteFontFace *fontface;
1833 IDWriteFactory *factory;
1834 UINT32 count;
1835 HRESULT hr;
1836 HRSRC font;
1838 factory = create_factory();
1840 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1841 ok(hr == S_OK, "got 0x%08x\n", hr);
1843 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1844 ok(font != NULL, "Failed to find font resource\n");
1846 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
1847 ok(hr == S_OK, "got 0x%08x\n", hr);
1849 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1850 ok(hr == S_OK, "got 0x%08x\n", hr);
1851 IDWriteFontFile_Release(ffile);
1853 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
1854 IDWriteFontFace_Release(fontface);
1855 if (hr != S_OK) {
1856 win_skip("GetUnicodeRanges() is not supported.\n");
1857 IDWriteFactory_Release(factory);
1858 return;
1861 count = 0;
1862 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 0, NULL, &count);
1863 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1864 ok(count > 0, "got %u\n", count);
1866 count = 1;
1867 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, NULL, &count);
1868 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1869 ok(count == 0, "got %u\n", count);
1871 count = 0;
1872 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, &r, &count);
1873 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1874 ok(count > 1, "got %u\n", count);
1876 ranges = heap_alloc(count*sizeof(DWRITE_UNICODE_RANGE));
1877 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, count, ranges, &count);
1878 ok(hr == S_OK, "got 0x%08x\n", hr);
1880 ranges[0].first = ranges[0].last = 0;
1881 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, ranges, &count);
1882 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1883 ok(ranges[0].first != 0 && ranges[0].last != 0, "got 0x%x-0x%0x\n", ranges[0].first, ranges[0].last);
1885 heap_free(ranges);
1887 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1888 ok(hr == S_OK, "got 0x%08x\n", hr);
1890 IDWriteFontFace1_Release(fontface1);
1891 IDWriteFactory_Release(factory);
1894 static void test_GetFontFromFontFace(void)
1896 IDWriteFontFace *fontface, *fontface2;
1897 IDWriteFontCollection *collection;
1898 IDWriteFont *font, *font2, *font3;
1899 IDWriteFontFamily *family;
1900 IDWriteFactory *factory;
1901 HRESULT hr;
1903 factory = create_factory();
1905 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1906 ok(hr == S_OK, "got 0x%08x\n", hr);
1908 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1909 ok(hr == S_OK, "got 0x%08x\n", hr);
1911 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1912 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1913 ok(hr == S_OK, "got 0x%08x\n", hr);
1915 hr = IDWriteFont_CreateFontFace(font, &fontface);
1916 ok(hr == S_OK, "got 0x%08x\n", hr);
1918 font2 = NULL;
1919 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font2);
1920 ok(hr == S_OK, "got 0x%08x\n", hr);
1921 ok(font2 != font, "got %p, %p\n", font2, font);
1923 font3 = NULL;
1924 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font3);
1925 ok(hr == S_OK, "got 0x%08x\n", hr);
1926 ok(font3 != font && font3 != font2, "got %p, %p, %p\n", font3, font2, font);
1928 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
1929 ok(hr == S_OK, "got 0x%08x\n", hr);
1930 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
1931 IDWriteFontFace_Release(fontface2);
1933 hr = IDWriteFont_CreateFontFace(font3, &fontface2);
1934 ok(hr == S_OK, "got 0x%08x\n", hr);
1935 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
1936 IDWriteFontFace_Release(fontface2);
1938 IDWriteFont_Release(font);
1939 IDWriteFont_Release(font2);
1940 IDWriteFont_Release(font3);
1941 IDWriteFontFace_Release(fontface);
1942 IDWriteFontFamily_Release(family);
1943 IDWriteFontCollection_Release(collection);
1944 IDWriteFactory_Release(factory);
1947 static void test_GetFirstMatchingFont(void)
1949 DWRITE_FONT_SIMULATIONS simulations;
1950 IDWriteFontCollection *collection;
1951 IDWriteFont *font, *font2;
1952 IDWriteFontFamily *family;
1953 IDWriteFactory *factory;
1954 UINT32 index;
1955 BOOL exists;
1956 HRESULT hr;
1958 factory = create_factory();
1960 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1961 ok(hr == S_OK, "got 0x%08x\n", hr);
1963 index = ~0;
1964 exists = FALSE;
1965 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaW, &index, &exists);
1966 ok(hr == S_OK, "got 0x%08x\n", hr);
1967 ok(exists, "got %d\n", exists);
1969 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
1970 ok(hr == S_OK, "got 0x%08x\n", hr);
1972 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1973 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1974 ok(hr == S_OK, "got 0x%08x\n", hr);
1976 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1977 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font2);
1978 ok(hr == S_OK, "got 0x%08x\n", hr);
1979 ok(font != font2, "got %p, %p\n", font, font2);
1980 IDWriteFont_Release(font);
1982 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1983 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_ITALIC, &font);
1984 ok(hr == S_OK, "got 0x%08x\n", hr);
1986 simulations = IDWriteFont_GetSimulations(font);
1987 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "%d\n", simulations);
1989 IDWriteFont_Release(font);
1990 IDWriteFont_Release(font2);
1991 IDWriteFontFamily_Release(family);
1992 IDWriteFontCollection_Release(collection);
1993 IDWriteFactory_Release(factory);
1996 static void test_GetInformationalStrings(void)
1998 IDWriteLocalizedStrings *strings, *strings2;
1999 IDWriteFontCollection *collection;
2000 IDWriteFontFamily *family;
2001 IDWriteFactory *factory;
2002 IDWriteFont *font;
2003 BOOL exists;
2004 HRESULT hr;
2006 factory = create_factory();
2008 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
2009 ok(hr == S_OK, "got 0x%08x\n", hr);
2011 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
2012 ok(hr == S_OK, "got 0x%08x\n", hr);
2014 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2015 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2016 ok(hr == S_OK, "got 0x%08x\n", hr);
2018 exists = TRUE;
2019 strings = (void*)0xdeadbeef;
2020 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1, &strings, &exists);
2021 ok(hr == S_OK, "got 0x%08x\n", hr);
2022 ok(exists == FALSE, "got %d\n", exists);
2023 ok(strings == NULL, "got %p\n", strings);
2025 exists = TRUE;
2026 strings = NULL;
2027 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_NONE, &strings, &exists);
2028 ok(hr == S_OK, "got 0x%08x\n", hr);
2029 ok(exists == FALSE, "got %d\n", exists);
2031 exists = FALSE;
2032 strings = NULL;
2033 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists);
2034 ok(hr == S_OK, "got 0x%08x\n", hr);
2035 ok(exists == TRUE, "got %d\n", exists);
2037 /* strings instance is not reused */
2038 strings2 = NULL;
2039 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings2, &exists);
2040 ok(hr == S_OK, "got 0x%08x\n", hr);
2041 ok(strings2 != strings, "got %p, %p\n", strings2, strings);
2043 IDWriteLocalizedStrings_Release(strings);
2044 IDWriteLocalizedStrings_Release(strings2);
2045 IDWriteFont_Release(font);
2046 IDWriteFontFamily_Release(family);
2047 IDWriteFontCollection_Release(collection);
2048 IDWriteFactory_Release(factory);
2051 static void test_GetGdiInterop(void)
2053 IDWriteGdiInterop *interop, *interop2;
2054 IDWriteFactory *factory, *factory2;
2055 IDWriteFont *font;
2056 LOGFONTW logfont;
2057 HRESULT hr;
2059 factory = create_factory();
2061 interop = NULL;
2062 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2063 ok(hr == S_OK, "got 0x%08x\n", hr);
2065 interop2 = NULL;
2066 hr = IDWriteFactory_GetGdiInterop(factory, &interop2);
2067 ok(hr == S_OK, "got 0x%08x\n", hr);
2068 ok(interop == interop2, "got %p, %p\n", interop, interop2);
2069 IDWriteGdiInterop_Release(interop2);
2071 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory2);
2072 ok(hr == S_OK, "got 0x%08x\n", hr);
2074 /* each factory gets its own interop */
2075 interop2 = NULL;
2076 hr = IDWriteFactory_GetGdiInterop(factory2, &interop2);
2077 ok(hr == S_OK, "got 0x%08x\n", hr);
2078 ok(interop != interop2, "got %p, %p\n", interop, interop2);
2080 /* release factory - interop still works */
2081 IDWriteFactory_Release(factory2);
2083 memset(&logfont, 0, sizeof(logfont));
2084 logfont.lfHeight = 12;
2085 logfont.lfWidth = 12;
2086 logfont.lfWeight = FW_NORMAL;
2087 logfont.lfItalic = 1;
2088 lstrcpyW(logfont.lfFaceName, tahomaW);
2090 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop2, &logfont, &font);
2091 ok(hr == S_OK, "got 0x%08x\n", hr);
2093 IDWriteGdiInterop_Release(interop2);
2094 IDWriteGdiInterop_Release(interop);
2095 IDWriteFactory_Release(factory);
2098 static void test_CreateFontFaceFromHdc(void)
2100 IDWriteGdiInterop *interop;
2101 IDWriteFontFace *fontface;
2102 IDWriteFactory *factory;
2103 HFONT hfont, oldhfont;
2104 LOGFONTW logfont;
2105 HRESULT hr;
2106 HDC hdc;
2108 factory = create_factory();
2110 interop = NULL;
2111 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2112 ok(hr == S_OK, "got 0x%08x\n", hr);
2114 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, NULL, &fontface);
2115 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2117 memset(&logfont, 0, sizeof(logfont));
2118 logfont.lfHeight = 12;
2119 logfont.lfWidth = 12;
2120 logfont.lfWeight = FW_NORMAL;
2121 logfont.lfItalic = 1;
2122 lstrcpyW(logfont.lfFaceName, tahomaW);
2124 hfont = CreateFontIndirectW(&logfont);
2125 hdc = CreateCompatibleDC(0);
2126 oldhfont = SelectObject(hdc, hfont);
2128 fontface = NULL;
2129 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, hdc, &fontface);
2130 ok(hr == S_OK, "got 0x%08x\n", hr);
2131 IDWriteFontFace_Release(fontface);
2132 DeleteObject(SelectObject(hdc, oldhfont));
2133 DeleteDC(hdc);
2135 IDWriteGdiInterop_Release(interop);
2136 IDWriteFactory_Release(factory);
2139 static void test_GetSimulations(void)
2141 DWRITE_FONT_SIMULATIONS simulations;
2142 IDWriteGdiInterop *interop;
2143 IDWriteFontFace *fontface;
2144 IDWriteFactory *factory;
2145 IDWriteFont *font;
2146 LOGFONTW logfont;
2147 HRESULT hr;
2149 factory = create_factory();
2151 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2152 ok(hr == S_OK, "got 0x%08x\n", hr);
2154 memset(&logfont, 0, sizeof(logfont));
2155 logfont.lfHeight = 12;
2156 logfont.lfWidth = 12;
2157 logfont.lfWeight = FW_NORMAL;
2158 logfont.lfItalic = 1;
2159 lstrcpyW(logfont.lfFaceName, tahomaW);
2161 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2162 ok(hr == S_OK, "got 0x%08x\n", hr);
2164 simulations = IDWriteFont_GetSimulations(font);
2165 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "got %d\n", simulations);
2166 hr = IDWriteFont_CreateFontFace(font, &fontface);
2167 ok(hr == S_OK, "got 0x%08x\n", hr);
2168 simulations = IDWriteFontFace_GetSimulations(fontface);
2169 ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "got %d\n", simulations);
2170 IDWriteFontFace_Release(fontface);
2171 IDWriteFont_Release(font);
2173 memset(&logfont, 0, sizeof(logfont));
2174 logfont.lfHeight = 12;
2175 logfont.lfWidth = 12;
2176 logfont.lfWeight = FW_NORMAL;
2177 logfont.lfItalic = 0;
2178 lstrcpyW(logfont.lfFaceName, tahomaW);
2180 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2181 ok(hr == S_OK, "got 0x%08x\n", hr);
2183 simulations = IDWriteFont_GetSimulations(font);
2184 ok(simulations == DWRITE_FONT_SIMULATIONS_NONE, "got %d\n", simulations);
2185 hr = IDWriteFont_CreateFontFace(font, &fontface);
2186 ok(hr == S_OK, "got 0x%08x\n", hr);
2187 simulations = IDWriteFontFace_GetSimulations(fontface);
2188 ok(simulations == DWRITE_FONT_SIMULATIONS_NONE, "got %d\n", simulations);
2189 IDWriteFontFace_Release(fontface);
2190 IDWriteFont_Release(font);
2192 IDWriteGdiInterop_Release(interop);
2193 IDWriteFactory_Release(factory);
2196 static void test_GetFaceNames(void)
2198 static const WCHAR obliqueW[] = {'O','b','l','i','q','u','e',0};
2199 static const WCHAR enus2W[] = {'e','n','-','U','s',0};
2200 static const WCHAR enusW[] = {'e','n','-','u','s',0};
2201 IDWriteLocalizedStrings *strings, *strings2;
2202 IDWriteGdiInterop *interop;
2203 IDWriteFactory *factory;
2204 UINT32 count, index;
2205 IDWriteFont *font;
2206 LOGFONTW logfont;
2207 WCHAR buffW[255];
2208 BOOL exists;
2209 HRESULT hr;
2211 factory = create_factory();
2213 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2214 ok(hr == S_OK, "got 0x%08x\n", hr);
2216 memset(&logfont, 0, sizeof(logfont));
2217 logfont.lfHeight = 12;
2218 logfont.lfWidth = 12;
2219 logfont.lfWeight = FW_NORMAL;
2220 logfont.lfItalic = 1;
2221 lstrcpyW(logfont.lfFaceName, tahomaW);
2223 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
2224 ok(hr == S_OK, "got 0x%08x\n", hr);
2226 hr = IDWriteFont_GetFaceNames(font, &strings);
2227 ok(hr == S_OK, "got 0x%08x\n", hr);
2229 hr = IDWriteFont_GetFaceNames(font, &strings2);
2230 ok(hr == S_OK, "got 0x%08x\n", hr);
2231 ok(strings != strings2, "got %p, %p\n", strings2, strings);
2232 IDWriteLocalizedStrings_Release(strings2);
2234 count = IDWriteLocalizedStrings_GetCount(strings);
2235 ok(count == 1, "got %d\n", count);
2237 index = 1;
2238 exists = FALSE;
2239 hr = IDWriteLocalizedStrings_FindLocaleName(strings, enus2W, &index, &exists);
2240 ok(hr == S_OK, "got 0x%08x\n", hr);
2241 ok(index == 0 && exists, "got %d, %d\n", index, exists);
2243 count = 0;
2244 hr = IDWriteLocalizedStrings_GetLocaleNameLength(strings, 1, &count);
2245 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2246 ok(count == ~0, "got %d\n", count);
2248 /* for simulated faces names are also simulated */
2249 buffW[0] = 0;
2250 hr = IDWriteLocalizedStrings_GetLocaleName(strings, 0, buffW, sizeof(buffW)/sizeof(WCHAR));
2251 ok(hr == S_OK, "got 0x%08x\n", hr);
2252 ok(!lstrcmpW(buffW, enusW), "got %s\n", wine_dbgstr_w(buffW));
2254 buffW[0] = 0;
2255 hr = IDWriteLocalizedStrings_GetString(strings, 0, buffW, sizeof(buffW)/sizeof(WCHAR));
2256 ok(hr == S_OK, "got 0x%08x\n", hr);
2257 ok(!lstrcmpW(buffW, obliqueW), "got %s\n", wine_dbgstr_w(buffW));
2258 IDWriteLocalizedStrings_Release(strings);
2260 IDWriteFont_Release(font);
2261 IDWriteGdiInterop_Release(interop);
2262 IDWriteFactory_Release(factory);
2265 struct local_refkey
2267 FILETIME writetime;
2268 WCHAR name[1];
2271 static void test_TryGetFontTable(void)
2273 IDWriteLocalFontFileLoader *localloader;
2274 WIN32_FILE_ATTRIBUTE_DATA info;
2275 const struct local_refkey *key;
2276 IDWriteFontFileLoader *loader;
2277 const void *table, *table2;
2278 IDWriteFontFace *fontface;
2279 void *context, *context2;
2280 IDWriteFactory *factory;
2281 IDWriteFontFile *file;
2282 WCHAR buffW[MAX_PATH];
2283 BOOL exists, ret;
2284 UINT32 size, len;
2285 HRESULT hr;
2287 create_testfontfile(test_fontfile);
2289 factory = create_factory();
2291 hr = IDWriteFactory_CreateFontFileReference(factory, test_fontfile, NULL, &file);
2292 ok(hr == S_OK, "got 0x%08x\n",hr);
2294 key = NULL;
2295 size = 0;
2296 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2297 ok(hr == S_OK, "got 0x%08x\n", hr);
2298 ok(size != 0, "got %u\n", size);
2300 ret = GetFileAttributesExW(test_fontfile, GetFileExInfoStandard, &info);
2301 ok(ret, "got %d\n", ret);
2302 ok(!memcmp(&info.ftLastWriteTime, &key->writetime, sizeof(key->writetime)), "got wrong write time\n");
2304 hr = IDWriteFontFile_GetLoader(file, &loader);
2305 ok(hr == S_OK, "got 0x%08x\n", hr);
2306 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2307 IDWriteFontFileLoader_Release(loader);
2309 hr = IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader, key, size, &len);
2310 ok(hr == S_OK, "got 0x%08x\n", hr);
2311 ok(lstrlenW(key->name) == len, "path length %d\n", len);
2313 hr = IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader, key, size, buffW, sizeof(buffW)/sizeof(WCHAR));
2314 ok(hr == S_OK, "got 0x%08x\n", hr);
2315 ok(!lstrcmpW(buffW, key->name), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(key->name));
2316 IDWriteLocalFontFileLoader_Release(localloader);
2318 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, 0, &fontface);
2319 ok(hr == S_OK, "got 0x%08x\n",hr);
2321 exists = FALSE;
2322 context = (void*)0xdeadbeef;
2323 table = NULL;
2324 hr = IDWriteFontFace_TryGetFontTable(fontface, MS_CMAP_TAG, &table, &size, &context, &exists);
2325 ok(hr == S_OK, "got 0x%08x\n",hr);
2326 ok(exists == TRUE, "got %d\n", exists);
2327 todo_wine
2328 ok(context == NULL && table != NULL, "cmap: context %p, table %p\n", context, table);
2330 exists = FALSE;
2331 context2 = (void*)0xdeadbeef;
2332 table2 = NULL;
2333 hr = IDWriteFontFace_TryGetFontTable(fontface, MS_CMAP_TAG, &table2, &size, &context2, &exists);
2334 ok(hr == S_OK, "got 0x%08x\n",hr);
2335 ok(exists == TRUE, "got %d\n", exists);
2336 todo_wine
2337 ok(context2 == context && table2 == table, "cmap: context2 %p, table2 %p\n", context2, table2);
2339 IDWriteFontFace_ReleaseFontTable(fontface, context2);
2340 IDWriteFontFace_ReleaseFontTable(fontface, context);
2342 IDWriteFontFace_Release(fontface);
2343 IDWriteFontFile_Release(file);
2344 IDWriteFactory_Release(factory);
2345 DeleteFileW(test_fontfile);
2348 static void test_ConvertFontToLOGFONT(void)
2350 IDWriteFactory *factory, *factory2;
2351 IDWriteFontCollection *collection;
2352 IDWriteGdiInterop *interop;
2353 IDWriteFontFamily *family;
2354 IDWriteFont *font;
2355 LOGFONTW logfont;
2356 BOOL system;
2357 HRESULT hr;
2359 factory = create_factory();
2360 factory2 = create_factory();
2362 interop = NULL;
2363 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
2364 ok(hr == S_OK, "got 0x%08x\n", hr);
2366 hr = IDWriteFactory_GetSystemFontCollection(factory2, &collection, FALSE);
2367 ok(hr == S_OK, "got 0x%08x\n", hr);
2369 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
2370 ok(hr == S_OK, "got 0x%08x\n", hr);
2372 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
2373 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
2374 ok(hr == S_OK, "got 0x%08x\n", hr);
2376 if (0) { /* crashes on native */
2377 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, NULL, NULL);
2378 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, &logfont, NULL);
2379 IDWriteGdiInterop_ConvertFontToLOGFONT(interop, font, NULL, &system);
2381 system = TRUE;
2382 hr = IDWriteGdiInterop_ConvertFontToLOGFONT(interop, NULL, &logfont, &system);
2383 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2384 ok(!system, "got %d\n", system);
2386 system = FALSE;
2387 memset(&logfont, 0, sizeof(logfont));
2388 hr = IDWriteGdiInterop_ConvertFontToLOGFONT(interop, font, &logfont, &system);
2389 ok(hr == S_OK, "got 0x%08x\n", hr);
2390 ok(system, "got %d\n", system);
2391 ok(logfont.lfFaceName[0] != 0, "got face name %s\n", wine_dbgstr_w(logfont.lfFaceName));
2393 IDWriteFactory_Release(factory2);
2395 IDWriteFontCollection_Release(collection);
2396 IDWriteFontFamily_Release(family);
2397 IDWriteFont_Release(font);
2398 IDWriteGdiInterop_Release(interop);
2399 IDWriteFactory_Release(factory);
2402 static void test_CreateStreamFromKey(void)
2404 IDWriteLocalFontFileLoader *localloader;
2405 IDWriteFontFileStream *stream, *stream2;
2406 IDWriteFontFileLoader *loader;
2407 IDWriteFactory *factory;
2408 IDWriteFontFile *file;
2409 UINT64 writetime;
2410 void *key;
2411 UINT32 size;
2412 HRESULT hr;
2414 factory = create_factory();
2416 create_testfontfile(test_fontfile);
2418 hr = IDWriteFactory_CreateFontFileReference(factory, test_fontfile, NULL, &file);
2419 ok(hr == S_OK, "got 0x%08x\n",hr);
2421 key = NULL;
2422 size = 0;
2423 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2424 ok(hr == S_OK, "got 0x%08x\n", hr);
2425 ok(size != 0, "got %u\n", size);
2427 hr = IDWriteFontFile_GetLoader(file, &loader);
2428 ok(hr == S_OK, "got 0x%08x\n", hr);
2429 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2430 IDWriteFontFileLoader_Release(loader);
2432 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2433 ok(hr == S_OK, "got 0x%08x\n", hr);
2434 EXPECT_REF(stream, 1);
2436 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream2);
2437 ok(hr == S_OK, "got 0x%08x\n", hr);
2438 ok(stream == stream2, "got %p, %p\n", stream, stream2);
2439 EXPECT_REF(stream, 2);
2440 IDWriteFontFileStream_Release(stream);
2441 IDWriteFontFileStream_Release(stream2);
2443 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2444 ok(hr == S_OK, "got 0x%08x\n", hr);
2445 EXPECT_REF(stream, 1);
2447 writetime = 0;
2448 hr = IDWriteFontFileStream_GetLastWriteTime(stream, &writetime);
2449 ok(hr == S_OK, "got 0x%08x\n", hr);
2450 ok(writetime != 0, "got %08x%08x\n", (UINT)(writetime >> 32), (UINT)writetime);
2452 IDWriteFontFileStream_Release(stream);
2454 IDWriteLocalFontFileLoader_Release(localloader);
2455 IDWriteFactory_Release(factory);
2456 DeleteFileW(test_fontfile);
2459 static void test_ReadFileFragment(void)
2461 IDWriteLocalFontFileLoader *localloader;
2462 IDWriteFontFileStream *stream;
2463 IDWriteFontFileLoader *loader;
2464 IDWriteFactory *factory;
2465 IDWriteFontFile *file;
2466 const void *fragment, *fragment2;
2467 void *key, *context, *context2;
2468 UINT64 filesize;
2469 UINT32 size;
2470 HRESULT hr;
2472 factory = create_factory();
2474 create_testfontfile(test_fontfile);
2476 hr = IDWriteFactory_CreateFontFileReference(factory, test_fontfile, NULL, &file);
2477 ok(hr == S_OK, "got 0x%08x\n",hr);
2479 key = NULL;
2480 size = 0;
2481 hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size);
2482 ok(hr == S_OK, "got 0x%08x\n", hr);
2483 ok(size != 0, "got %u\n", size);
2485 hr = IDWriteFontFile_GetLoader(file, &loader);
2486 ok(hr == S_OK, "got 0x%08x\n", hr);
2487 IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
2488 IDWriteFontFileLoader_Release(loader);
2490 hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
2491 ok(hr == S_OK, "got 0x%08x\n", hr);
2493 hr = IDWriteFontFileStream_GetFileSize(stream, &filesize);
2494 ok(hr == S_OK, "got 0x%08x\n", hr);
2496 /* reading past the end of the stream */
2497 fragment = (void*)0xdeadbeef;
2498 context = (void*)0xdeadbeef;
2499 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize+1, &context);
2500 ok(hr == E_FAIL, "got 0x%08x\n", hr);
2501 ok(context == NULL, "got %p\n", context);
2502 ok(fragment == NULL, "got %p\n", fragment);
2504 fragment = (void*)0xdeadbeef;
2505 context = (void*)0xdeadbeef;
2506 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize, &context);
2507 ok(hr == S_OK, "got 0x%08x\n", hr);
2508 ok(context == NULL, "got %p\n", context);
2509 ok(fragment != NULL, "got %p\n", fragment);
2511 fragment2 = (void*)0xdeadbeef;
2512 context2 = (void*)0xdeadbeef;
2513 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment2, 0, filesize, &context2);
2514 ok(hr == S_OK, "got 0x%08x\n", hr);
2515 ok(context2 == NULL, "got %p\n", context2);
2516 ok(fragment == fragment2, "got %p, %p\n", fragment, fragment2);
2518 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
2519 IDWriteFontFileStream_ReleaseFileFragment(stream, context2);
2521 /* fragment is released, try again */
2522 fragment = (void*)0xdeadbeef;
2523 context = (void*)0xdeadbeef;
2524 hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize, &context);
2525 ok(hr == S_OK, "got 0x%08x\n", hr);
2526 ok(context == NULL, "got %p\n", context);
2527 ok(fragment == fragment2, "got %p, %p\n", fragment, fragment2);
2528 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
2530 IDWriteFontFileStream_Release(stream);
2531 IDWriteLocalFontFileLoader_Release(localloader);
2532 IDWriteFactory_Release(factory);
2533 DeleteFileW(test_fontfile);
2536 START_TEST(font)
2538 IDWriteFactory *factory;
2540 if (!(factory = create_factory())) {
2541 win_skip("failed to create factory\n");
2542 return;
2545 test_CreateFontFromLOGFONT();
2546 test_CreateBitmapRenderTarget();
2547 test_GetFontFamily();
2548 test_GetFamilyNames();
2549 test_CreateFontFace();
2550 test_GetMetrics();
2551 test_system_fontcollection();
2552 test_ConvertFontFaceToLOGFONT();
2553 test_CustomFontCollection();
2554 test_CreateCustomFontFileReference();
2555 test_CreateFontFileReference();
2556 test_shared_isolated();
2557 test_GetUnicodeRanges();
2558 test_GetFontFromFontFace();
2559 test_GetFirstMatchingFont();
2560 test_GetInformationalStrings();
2561 test_GetGdiInterop();
2562 test_CreateFontFaceFromHdc();
2563 test_GetSimulations();
2564 test_GetFaceNames();
2565 test_TryGetFontTable();
2566 test_ConvertFontToLOGFONT();
2567 test_CreateStreamFromKey();
2568 test_ReadFileFragment();
2570 IDWriteFactory_Release(factory);