dwrite: Cache fontface instances at factory level.
[wine.git] / dlls / dwrite / tests / font.c
blobbaba6c292c00f3be80ca4623e8b88ed578c00709
1 /*
2 * Font related tests
4 * Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "windows.h"
24 #include "dwrite_1.h"
26 #include "wine/test.h"
28 #define EXPECT_HR(hr,hr_exp) \
29 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
31 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
32 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
34 ULONG rc;
35 IUnknown_AddRef(obj);
36 rc = IUnknown_Release(obj);
37 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
40 static inline void *heap_alloc(size_t len)
42 return HeapAlloc(GetProcessHeap(), 0, len);
45 static inline BOOL heap_free(void *mem)
47 return HeapFree(GetProcessHeap(), 0, mem);
50 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
51 static const WCHAR blahW[] = {'B','l','a','h','!',0};
53 static IDWriteFactory *create_factory(void)
55 IDWriteFactory *factory;
56 HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
57 ok(hr == S_OK, "got 0x%08x\n", hr);
58 return factory;
61 /* Here is a functional custom font set of interfaces */
62 struct test_fontdatastream
64 IDWriteFontFileStream IDWriteFontFileStream_iface;
65 LONG ref;
67 LPVOID data;
68 DWORD size;
71 static inline struct test_fontdatastream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream* iface)
73 return CONTAINING_RECORD(iface, struct test_fontdatastream, IDWriteFontFileStream_iface);
76 static HRESULT WINAPI fontdatastream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
78 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
80 *obj = iface;
81 IDWriteFontFileStream_AddRef(iface);
82 return S_OK;
84 *obj = NULL;
85 return E_NOINTERFACE;
88 static ULONG WINAPI fontdatastream_AddRef(IDWriteFontFileStream *iface)
90 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
91 ULONG ref = InterlockedIncrement(&This->ref);
92 return ref;
95 static ULONG WINAPI fontdatastream_Release(IDWriteFontFileStream *iface)
97 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
98 ULONG ref = InterlockedDecrement(&This->ref);
99 if (ref == 0)
100 HeapFree(GetProcessHeap(), 0, This);
101 return ref;
104 static HRESULT WINAPI fontdatastream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
106 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
107 *fragment_context = NULL;
108 if (offset+fragment_size > This->size)
110 *fragment_start = NULL;
111 return E_FAIL;
113 else
115 *fragment_start = (BYTE*)This->data + offset;
116 return S_OK;
120 static void WINAPI fontdatastream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
122 /* Do Nothing */
125 static HRESULT WINAPI fontdatastream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
127 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
128 *size = This->size;
129 return S_OK;
132 static HRESULT WINAPI fontdatastream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
134 return E_NOTIMPL;
137 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl =
139 fontdatastream_QueryInterface,
140 fontdatastream_AddRef,
141 fontdatastream_Release,
142 fontdatastream_ReadFileFragment,
143 fontdatastream_ReleaseFileFragment,
144 fontdatastream_GetFileSize,
145 fontdatastream_GetLastWriteTime
148 static HRESULT create_fontdatastream(LPVOID data, UINT size, IDWriteFontFileStream** iface)
150 struct test_fontdatastream *This = HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream));
151 if (!This)
152 return E_OUTOFMEMORY;
154 This->data = data;
155 This->size = size;
156 This->ref = 1;
157 This->IDWriteFontFileStream_iface.lpVtbl = &fontdatastreamvtbl;
159 *iface = &This->IDWriteFontFileStream_iface;
160 return S_OK;
163 static HRESULT WINAPI resourcefontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
165 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
167 *obj = iface;
168 return S_OK;
170 *obj = NULL;
171 return E_NOINTERFACE;
174 static ULONG WINAPI resourcefontfileloader_AddRef(IDWriteFontFileLoader *iface)
176 return 2;
179 static ULONG WINAPI resourcefontfileloader_Release(IDWriteFontFileLoader *iface)
181 return 1;
184 static HRESULT WINAPI resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
186 LPVOID data;
187 DWORD size;
188 HGLOBAL mem;
190 mem = LoadResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
191 ok(mem != NULL, "Failed to lock font resource\n");
192 if (mem)
194 size = SizeofResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
195 data = LockResource(mem);
196 return create_fontdatastream(data, size, fontFileStream);
198 return E_FAIL;
201 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl = {
202 resourcefontfileloader_QueryInterface,
203 resourcefontfileloader_AddRef,
204 resourcefontfileloader_Release,
205 resourcefontfileloader_CreateStreamFromKey
208 static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
210 static void test_CreateFontFromLOGFONT(void)
212 static const WCHAR tahomaspW[] = {'T','a','h','o','m','a',' ',0};
213 IDWriteGdiInterop *interop;
214 DWRITE_FONT_WEIGHT weight;
215 DWRITE_FONT_STYLE style;
216 IDWriteFont *font;
217 LOGFONTW logfont;
218 LONG weights[][2] = {
219 {FW_NORMAL, DWRITE_FONT_WEIGHT_NORMAL},
220 {FW_BOLD, DWRITE_FONT_WEIGHT_BOLD},
221 { 0, DWRITE_FONT_WEIGHT_NORMAL},
222 { 50, DWRITE_FONT_WEIGHT_NORMAL},
223 {150, DWRITE_FONT_WEIGHT_NORMAL},
224 {250, DWRITE_FONT_WEIGHT_NORMAL},
225 {350, DWRITE_FONT_WEIGHT_NORMAL},
226 {450, DWRITE_FONT_WEIGHT_NORMAL},
227 {650, DWRITE_FONT_WEIGHT_BOLD},
228 {750, DWRITE_FONT_WEIGHT_BOLD},
229 {850, DWRITE_FONT_WEIGHT_BOLD},
230 {950, DWRITE_FONT_WEIGHT_BOLD},
231 {960, DWRITE_FONT_WEIGHT_BOLD},
233 OUTLINETEXTMETRICW otm;
234 IDWriteFactory *factory;
235 HRESULT hr;
236 BOOL ret;
237 HDC hdc;
238 HFONT hfont;
239 BOOL exists;
240 int i;
241 UINT r;
243 factory = create_factory();
245 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
246 EXPECT_HR(hr, S_OK);
248 if (0)
249 /* null out parameter crashes this call */
250 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, NULL);
252 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, &font);
253 EXPECT_HR(hr, E_INVALIDARG);
255 memset(&logfont, 0, sizeof(logfont));
256 logfont.lfHeight = 12;
257 logfont.lfWidth = 12;
258 logfont.lfWeight = FW_NORMAL;
259 logfont.lfItalic = 1;
260 lstrcpyW(logfont.lfFaceName, tahomaW);
262 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
263 EXPECT_HR(hr, S_OK);
265 hfont = CreateFontIndirectW(&logfont);
266 hdc = CreateCompatibleDC(0);
267 SelectObject(hdc, hfont);
269 otm.otmSize = sizeof(otm);
270 r = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
271 ok(r, "got %d\n", r);
272 DeleteDC(hdc);
273 DeleteObject(hfont);
275 exists = TRUE;
276 hr = IDWriteFont_HasCharacter(font, 0xd800, &exists);
277 ok(hr == S_OK, "got 0x%08x\n", hr);
278 ok(exists == FALSE, "got %d\n", exists);
280 exists = FALSE;
281 hr = IDWriteFont_HasCharacter(font, 0x20, &exists);
282 ok(hr == S_OK, "got 0x%08x\n", hr);
283 ok(exists == TRUE, "got %d\n", exists);
285 /* now check properties */
286 weight = IDWriteFont_GetWeight(font);
287 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
289 style = IDWriteFont_GetStyle(font);
290 todo_wine {
291 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
292 ok(otm.otmfsSelection == 1, "got 0x%08x\n", otm.otmfsSelection);
294 ret = IDWriteFont_IsSymbolFont(font);
295 ok(!ret, "got %d\n", ret);
297 IDWriteFont_Release(font);
299 /* weight values */
300 for (i = 0; i < sizeof(weights)/(2*sizeof(LONG)); i++)
302 memset(&logfont, 0, sizeof(logfont));
303 logfont.lfHeight = 12;
304 logfont.lfWidth = 12;
305 logfont.lfWeight = weights[i][0];
306 lstrcpyW(logfont.lfFaceName, tahomaW);
308 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
309 EXPECT_HR(hr, S_OK);
311 weight = IDWriteFont_GetWeight(font);
312 ok(weight == weights[i][1],
313 "%d: got %d, expected %d\n", i, weight, weights[i][1]);
314 IDWriteFont_Release(font);
317 /* weight not from enum */
318 memset(&logfont, 0, sizeof(logfont));
319 logfont.lfHeight = 12;
320 logfont.lfWidth = 12;
321 logfont.lfWeight = 550;
322 lstrcpyW(logfont.lfFaceName, tahomaW);
324 font = NULL;
325 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
326 ok(hr == S_OK, "got 0x%08x\n", hr);
328 weight = IDWriteFont_GetWeight(font);
329 ok(weight == DWRITE_FONT_WEIGHT_NORMAL || broken(weight == DWRITE_FONT_WEIGHT_BOLD) /* win7 w/o SP */,
330 "got %d\n", weight);
331 IDWriteFont_Release(font);
333 /* empty or nonexistent face name */
334 memset(&logfont, 0, sizeof(logfont));
335 logfont.lfHeight = 12;
336 logfont.lfWidth = 12;
337 logfont.lfWeight = FW_NORMAL;
338 lstrcpyW(logfont.lfFaceName, blahW);
340 font = (void*)0xdeadbeef;
341 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
342 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
343 ok(font == NULL, "got %p\n", font);
345 /* Try with name 'Tahoma ' */
346 memset(&logfont, 0, sizeof(logfont));
347 logfont.lfHeight = 12;
348 logfont.lfWidth = 12;
349 logfont.lfWeight = FW_NORMAL;
350 lstrcpyW(logfont.lfFaceName, tahomaspW);
352 font = (void*)0xdeadbeef;
353 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
354 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
355 ok(font == NULL, "got %p\n", font);
357 /* empty string as a facename */
358 memset(&logfont, 0, sizeof(logfont));
359 logfont.lfHeight = 12;
360 logfont.lfWidth = 12;
361 logfont.lfWeight = FW_NORMAL;
363 font = (void*)0xdeadbeef;
364 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
365 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
366 ok(font == NULL, "got %p\n", font);
368 IDWriteGdiInterop_Release(interop);
369 IDWriteFactory_Release(factory);
372 static void test_CreateBitmapRenderTarget(void)
374 IDWriteBitmapRenderTarget *target, *target2;
375 IDWriteGdiInterop *interop;
376 IDWriteFactory *factory;
377 HBITMAP hbm, hbm2;
378 DWRITE_MATRIX m;
379 DIBSECTION ds;
380 HRESULT hr;
381 SIZE size;
382 HDC hdc;
383 int ret;
385 factory = create_factory();
387 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
388 EXPECT_HR(hr, S_OK);
390 target = NULL;
391 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target);
392 EXPECT_HR(hr, S_OK);
394 if (0) /* crashes on native */
395 hr = IDWriteBitmapRenderTarget_GetSize(target, NULL);
397 size.cx = size.cy = -1;
398 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
399 EXPECT_HR(hr, S_OK);
400 ok(size.cx == 0, "got %d\n", size.cx);
401 ok(size.cy == 0, "got %d\n", size.cy);
403 target2 = NULL;
404 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target2);
405 EXPECT_HR(hr, S_OK);
406 ok(target != target2, "got %p, %p\n", target2, target);
407 IDWriteBitmapRenderTarget_Release(target2);
409 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
410 ok(hdc != NULL, "got %p\n", hdc);
412 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
413 ok(hbm != NULL, "got %p\n", hbm);
415 /* check DIB properties */
416 ret = GetObjectW(hbm, sizeof(ds), &ds);
417 ok(ret == sizeof(BITMAP), "got %d\n", ret);
418 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
419 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
420 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
421 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
422 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
424 IDWriteBitmapRenderTarget_Release(target);
426 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
427 ok(!hbm, "got %p\n", hbm);
429 target = NULL;
430 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 10, 5, &target);
431 EXPECT_HR(hr, S_OK);
433 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
434 ok(hdc != NULL, "got %p\n", hdc);
436 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
437 ok(hbm != NULL, "got %p\n", hbm);
439 /* check DIB properties */
440 ret = GetObjectW(hbm, sizeof(ds), &ds);
441 ok(ret == sizeof(ds), "got %d\n", ret);
442 ok(ds.dsBm.bmWidth == 10, "got %d\n", ds.dsBm.bmWidth);
443 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
444 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
445 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
446 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
448 size.cx = size.cy = -1;
449 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
450 EXPECT_HR(hr, S_OK);
451 ok(size.cx == 10, "got %d\n", size.cx);
452 ok(size.cy == 5, "got %d\n", size.cy);
454 /* resize to same size */
455 hr = IDWriteBitmapRenderTarget_Resize(target, 10, 5);
456 ok(hr == S_OK, "got 0x%08x\n", hr);
458 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
459 ok(hbm2 == hbm, "got %p, %p\n", hbm2, hbm);
461 /* shrink */
462 hr = IDWriteBitmapRenderTarget_Resize(target, 5, 5);
463 ok(hr == S_OK, "got 0x%08x\n", hr);
465 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
466 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
468 hr = IDWriteBitmapRenderTarget_Resize(target, 20, 5);
469 ok(hr == S_OK, "got 0x%08x\n", hr);
471 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
472 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
474 hr = IDWriteBitmapRenderTarget_Resize(target, 1, 5);
475 ok(hr == S_OK, "got 0x%08x\n", hr);
477 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
478 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
480 ret = GetObjectW(hbm2, sizeof(ds), &ds);
481 ok(ret == sizeof(ds), "got %d\n", ret);
482 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
483 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
484 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
485 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
486 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
488 /* empty rectangle */
489 hr = IDWriteBitmapRenderTarget_Resize(target, 0, 5);
490 ok(hr == S_OK, "got 0x%08x\n", hr);
492 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
493 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
495 ret = GetObjectW(hbm2, sizeof(ds), &ds);
496 ok(ret == sizeof(BITMAP), "got %d\n", ret);
497 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
498 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
499 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
500 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
501 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
503 /* transform tests */
504 if (0) /* crashes on native */
505 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, NULL);
507 memset(&m, 0xcc, sizeof(m));
508 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
509 ok(hr == S_OK, "got 0x%08x\n", hr);
510 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);
511 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
513 IDWriteBitmapRenderTarget_Release(target);
514 IDWriteGdiInterop_Release(interop);
515 IDWriteFactory_Release(factory);
518 static void test_GetFontFamily(void)
520 IDWriteFontCollection *collection, *collection2;
521 IDWriteFontCollection *syscoll;
522 IDWriteFontFamily *family, *family2;
523 IDWriteGdiInterop *interop;
524 IDWriteFont *font, *font2;
525 IDWriteFactory *factory;
526 LOGFONTW logfont;
527 HRESULT hr;
529 factory = create_factory();
531 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
532 EXPECT_HR(hr, S_OK);
534 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscoll, FALSE);
535 ok(hr == S_OK, "got 0x%08x\n", hr);
537 memset(&logfont, 0, sizeof(logfont));
538 logfont.lfHeight = 12;
539 logfont.lfWidth = 12;
540 logfont.lfWeight = FW_NORMAL;
541 logfont.lfItalic = 1;
542 lstrcpyW(logfont.lfFaceName, tahomaW);
544 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
545 ok(hr == S_OK, "got 0x%08x\n", hr);
547 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
548 ok(hr == S_OK, "got 0x%08x\n", hr);
549 ok(font2 != font, "got %p, %p\n", font2, font);
551 if (0) /* crashes on native */
552 hr = IDWriteFont_GetFontFamily(font, NULL);
554 EXPECT_REF(font, 1);
555 hr = IDWriteFont_GetFontFamily(font, &family);
556 EXPECT_HR(hr, S_OK);
557 EXPECT_REF(font, 1);
558 EXPECT_REF(family, 2);
560 hr = IDWriteFont_GetFontFamily(font, &family2);
561 EXPECT_HR(hr, S_OK);
562 ok(family2 == family, "got %p, previous %p\n", family2, family);
563 EXPECT_REF(font, 1);
564 EXPECT_REF(family, 3);
565 IDWriteFontFamily_Release(family2);
567 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFamily, (void**)&family2);
568 EXPECT_HR(hr, E_NOINTERFACE);
569 ok(family2 == NULL, "got %p\n", family2);
571 hr = IDWriteFont_GetFontFamily(font2, &family2);
572 ok(hr == S_OK, "got 0x%08x\n", hr);
573 ok(family2 != family, "got %p, %p\n", family2, family);
575 collection = NULL;
576 hr = IDWriteFontFamily_GetFontCollection(family, &collection);
577 todo_wine
578 ok(hr == S_OK, "got 0x%08x\n", hr);
580 collection2 = NULL;
581 hr = IDWriteFontFamily_GetFontCollection(family2, &collection2);
582 todo_wine
583 ok(hr == S_OK, "got 0x%08x\n", hr);
584 ok(collection == collection2, "got %p, %p\n", collection, collection2);
585 todo_wine
586 ok(collection == syscoll, "got %p, %p\n", collection, syscoll);
588 IDWriteFontCollection_Release(syscoll);
589 if (collection2)
590 IDWriteFontCollection_Release(collection2);
591 if (collection)
592 IDWriteFontCollection_Release(collection);
593 IDWriteFontFamily_Release(family2);
594 IDWriteFontFamily_Release(family);
595 IDWriteFont_Release(font);
596 IDWriteFont_Release(font2);
597 IDWriteGdiInterop_Release(interop);
598 IDWriteFactory_Release(factory);
601 static void test_GetFamilyNames(void)
603 IDWriteFontFamily *family;
604 IDWriteLocalizedStrings *names, *names2;
605 IDWriteGdiInterop *interop;
606 IDWriteFactory *factory;
607 IDWriteFont *font;
608 LOGFONTW logfont;
609 WCHAR buffer[100];
610 HRESULT hr;
611 UINT32 len;
613 factory = create_factory();
615 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
616 EXPECT_HR(hr, S_OK);
618 memset(&logfont, 0, sizeof(logfont));
619 logfont.lfHeight = 12;
620 logfont.lfWidth = 12;
621 logfont.lfWeight = FW_NORMAL;
622 logfont.lfItalic = 1;
623 lstrcpyW(logfont.lfFaceName, tahomaW);
625 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
626 EXPECT_HR(hr, S_OK);
628 hr = IDWriteFont_GetFontFamily(font, &family);
629 EXPECT_HR(hr, S_OK);
631 if (0) /* crashes on native */
632 hr = IDWriteFontFamily_GetFamilyNames(family, NULL);
634 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
635 ok(hr == S_OK, "got 0x%08x\n", hr);
636 EXPECT_REF(names, 1);
638 hr = IDWriteFontFamily_GetFamilyNames(family, &names2);
639 ok(hr == S_OK, "got 0x%08x\n", hr);
640 EXPECT_REF(names2, 1);
641 ok(names != names2, "got %p, was %p\n", names2, names);
643 IDWriteLocalizedStrings_Release(names2);
645 /* GetStringLength */
646 if (0) /* crashes on native */
647 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, NULL);
649 len = 100;
650 hr = IDWriteLocalizedStrings_GetStringLength(names, 10, &len);
651 ok(hr == E_FAIL, "got 0x%08x\n", hr);
652 ok(len == (UINT32)-1, "got %u\n", len);
654 len = 0;
655 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, &len);
656 ok(hr == S_OK, "got 0x%08x\n", hr);
657 ok(len > 0, "got %u\n", len);
659 /* GetString */
660 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 0);
661 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
663 hr = IDWriteLocalizedStrings_GetString(names, 10, NULL, 0);
664 ok(hr == E_FAIL, "got 0x%08x\n", hr);
666 if (0)
667 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 100);
669 buffer[0] = 1;
670 hr = IDWriteLocalizedStrings_GetString(names, 10, buffer, 100);
671 ok(hr == E_FAIL, "got 0x%08x\n", hr);
672 ok(buffer[0] == 0, "got %x\n", buffer[0]);
674 buffer[0] = 1;
675 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len-1);
676 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
677 ok(buffer[0] == 0, "got %x\n", buffer[0]);
679 buffer[0] = 1;
680 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len);
681 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
682 ok(buffer[0] == 0, "got %x\n", buffer[0]);
684 buffer[0] = 0;
685 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len+1);
686 ok(hr == S_OK, "got 0x%08x\n", hr);
687 ok(buffer[0] != 0, "got %x\n", buffer[0]);
689 IDWriteLocalizedStrings_Release(names);
691 IDWriteFontFamily_Release(family);
692 IDWriteFont_Release(font);
693 IDWriteGdiInterop_Release(interop);
694 IDWriteFactory_Release(factory);
697 static void test_CreateFontFace(void)
699 IDWriteFontFace *fontface, *fontface2;
700 IDWriteFontCollection *collection;
701 IDWriteGdiInterop *interop;
702 IDWriteFont *font, *font2;
703 IDWriteFontFamily *family;
704 IDWriteFactory *factory;
705 LOGFONTW logfont;
706 HRESULT hr;
708 factory = create_factory();
710 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
711 EXPECT_HR(hr, S_OK);
713 memset(&logfont, 0, sizeof(logfont));
714 logfont.lfHeight = 12;
715 logfont.lfWidth = 12;
716 logfont.lfWeight = FW_NORMAL;
717 logfont.lfItalic = 1;
718 lstrcpyW(logfont.lfFaceName, tahomaW);
720 font = NULL;
721 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
722 ok(hr == S_OK, "got 0x%08x\n", hr);
724 font2 = NULL;
725 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
726 ok(hr == S_OK, "got 0x%08x\n", hr);
727 ok(font != font2, "got %p, %p\n", font, font2);
729 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface);
730 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
732 if (0) /* crashes on native */
733 hr = IDWriteFont_CreateFontFace(font, NULL);
735 fontface = NULL;
736 hr = IDWriteFont_CreateFontFace(font, &fontface);
737 ok(hr == S_OK, "got 0x%08x\n", hr);
739 fontface2 = NULL;
740 hr = IDWriteFont_CreateFontFace(font, &fontface2);
741 ok(hr == S_OK, "got 0x%08x\n", hr);
742 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
743 IDWriteFontFace_Release(fontface2);
745 fontface2 = NULL;
746 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
747 ok(hr == S_OK, "got 0x%08x\n", hr);
748 todo_wine
749 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
750 IDWriteFontFace_Release(fontface2);
752 IDWriteFont_Release(font2);
753 IDWriteFont_Release(font);
755 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFont, (void**)&font);
756 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL), "got 0x%08x\n", hr);
758 IDWriteFontFace_Release(fontface);
759 IDWriteGdiInterop_Release(interop);
761 /* Create from system collection */
762 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
763 ok(hr == S_OK, "got 0x%08x\n", hr);
765 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
766 ok(hr == S_OK, "got 0x%08x\n", hr);
768 font = NULL;
769 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
770 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
771 ok(hr == S_OK, "got 0x%08x\n", hr);
773 font2 = NULL;
774 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
775 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font2);
776 ok(hr == S_OK, "got 0x%08x\n", hr);
777 ok(font != font2, "got %p, %p\n", font, font2);
779 fontface = NULL;
780 hr = IDWriteFont_CreateFontFace(font, &fontface);
781 ok(hr == S_OK, "got 0x%08x\n", hr);
783 fontface2 = NULL;
784 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
785 ok(hr == S_OK, "got 0x%08x\n", hr);
786 todo_wine
787 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
789 IDWriteFontFace_Release(fontface);
790 IDWriteFontFace_Release(fontface2);
791 IDWriteFont_Release(font2);
792 IDWriteFont_Release(font);
793 IDWriteFontFamily_Release(family);
794 IDWriteFontCollection_Release(collection);
795 IDWriteFactory_Release(factory);
798 static void test_GetMetrics(void)
800 IDWriteGdiInterop *interop;
801 DWRITE_FONT_METRICS metrics;
802 IDWriteFactory *factory;
803 OUTLINETEXTMETRICW otm;
804 IDWriteFont *font;
805 LOGFONTW logfont;
806 HRESULT hr;
807 HDC hdc;
808 HFONT hfont;
809 int ret;
811 factory = create_factory();
813 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
814 EXPECT_HR(hr, S_OK);
816 memset(&logfont, 0, sizeof(logfont));
817 logfont.lfHeight = 12;
818 logfont.lfWidth = 12;
819 logfont.lfWeight = FW_NORMAL;
820 logfont.lfItalic = 1;
821 lstrcpyW(logfont.lfFaceName, tahomaW);
823 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
824 ok(hr == S_OK, "got 0x%08x\n", hr);
826 hfont = CreateFontIndirectW(&logfont);
827 hdc = CreateCompatibleDC(0);
828 SelectObject(hdc, hfont);
830 otm.otmSize = sizeof(otm);
831 ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
832 ok(ret, "got %d\n", ret);
833 DeleteDC(hdc);
834 DeleteObject(hfont);
836 if (0) /* crashes on native */
837 IDWriteFont_GetMetrics(font, NULL);
839 memset(&metrics, 0, sizeof(metrics));
840 IDWriteFont_GetMetrics(font, &metrics);
842 ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
843 ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
844 ok(metrics.descent != 0, "descent %u\n", metrics.descent);
845 todo_wine
846 ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
847 ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
848 ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
849 ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
850 ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
851 ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
852 ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
854 IDWriteFont_Release(font);
855 IDWriteGdiInterop_Release(interop);
856 IDWriteFactory_Release(factory);
859 static void test_system_fontcollection(void)
861 IDWriteFontCollection *collection, *coll2;
862 IDWriteLocalFontFileLoader *localloader;
863 IDWriteFactory *factory, *factory2;
864 IDWriteFontFileLoader *loader;
865 IDWriteFontFamily *family;
866 IDWriteFontFace *fontface;
867 IDWriteFontFile *file;
868 IDWriteFont *font;
869 HRESULT hr;
870 UINT32 i;
871 BOOL ret;
873 factory = create_factory();
875 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
876 ok(hr == S_OK, "got 0x%08x\n", hr);
878 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, FALSE);
879 ok(hr == S_OK, "got 0x%08x\n", hr);
880 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
881 IDWriteFontCollection_Release(coll2);
883 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, TRUE);
884 ok(hr == S_OK, "got 0x%08x\n", hr);
885 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
886 IDWriteFontCollection_Release(coll2);
888 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory2);
889 ok(hr == S_OK, "got 0x%08x\n", hr);
890 hr = IDWriteFactory_GetSystemFontCollection(factory2, &coll2, FALSE);
891 ok(hr == S_OK, "got 0x%08x\n", hr);
892 ok(coll2 != collection, "got %p, was %p\n", coll2, collection);
893 IDWriteFontCollection_Release(coll2);
894 IDWriteFactory_Release(factory2);
896 i = IDWriteFontCollection_GetFontFamilyCount(collection);
897 ok(i, "got %u\n", i);
899 /* invalid index */
900 family = (void*)0xdeadbeef;
901 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
902 ok(hr == E_FAIL, "got 0x%08x\n", hr);
903 ok(family == NULL, "got %p\n", family);
905 ret = FALSE;
906 i = (UINT32)-1;
907 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaW, &i, &ret);
908 ok(hr == S_OK, "got 0x%08x\n", hr);
909 ok(ret, "got %d\n", ret);
910 ok(i != (UINT32)-1, "got %u\n", i);
912 /* get back local file loader */
913 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
914 ok(hr == S_OK, "got 0x%08x\n", hr);
916 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
917 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
918 ok(hr == S_OK, "got 0x%08x\n", hr);
919 IDWriteFontFamily_Release(family);
921 hr = IDWriteFont_CreateFontFace(font, &fontface);
922 ok(hr == S_OK, "got 0x%08x\n", hr);
923 IDWriteFont_Release(font);
925 i = 1;
926 file = NULL;
927 hr = IDWriteFontFace_GetFiles(fontface, &i, &file);
928 ok(hr == S_OK, "got 0x%08x\n", hr);
929 todo_wine
930 ok(file != NULL, "got %p\n", file);
932 if (file) {
933 hr = IDWriteFontFile_GetLoader(file, &loader);
934 ok(hr == S_OK, "got 0x%08x\n", hr);
935 IDWriteFontFile_Release(file);
937 hr = IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader);
938 ok(hr == S_OK, "got 0x%08x\n", hr);
939 IDWriteLocalFontFileLoader_Release(localloader);
941 /* local loader is not registered by default */
942 hr = IDWriteFactory_RegisterFontFileLoader(factory, loader);
943 ok(hr == S_OK || broken(hr == DWRITE_E_ALREADYREGISTERED), "got 0x%08x\n", hr);
944 hr = IDWriteFactory_UnregisterFontFileLoader(factory, loader);
945 ok(hr == S_OK || broken(hr == E_INVALIDARG), "got 0x%08x\n", hr);
946 IDWriteFontFileLoader_Release(loader);
948 ret = TRUE;
949 i = 0;
950 hr = IDWriteFontCollection_FindFamilyName(collection, blahW, &i, &ret);
951 ok(hr == S_OK, "got 0x%08x\n", hr);
952 ok(!ret, "got %d\n", ret);
953 ok(i == (UINT32)-1, "got %u\n", i);
955 IDWriteFontCollection_Release(collection);
956 IDWriteFactory_Release(factory);
959 static void test_ConvertFontFaceToLOGFONT(void)
961 IDWriteGdiInterop *interop;
962 IDWriteFontFace *fontface;
963 IDWriteFactory *factory;
964 IDWriteFont *font;
965 LOGFONTW logfont;
966 HRESULT hr;
968 factory = create_factory();
970 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
971 ok(hr == S_OK, "got 0x%08x\n", hr);
973 memset(&logfont, 0, sizeof(logfont));
974 logfont.lfHeight = 12;
975 logfont.lfWidth = 12;
976 logfont.lfEscapement = 100;
977 logfont.lfWeight = FW_NORMAL;
978 logfont.lfItalic = 1;
979 logfont.lfUnderline = 1;
980 logfont.lfStrikeOut = 1;
982 lstrcpyW(logfont.lfFaceName, tahomaW);
984 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
985 ok(hr == S_OK, "got 0x%08x\n", hr);
987 hr = IDWriteFont_CreateFontFace(font, &fontface);
988 ok(hr == S_OK, "got 0x%08x\n", hr);
989 IDWriteFont_Release(font);
991 if (0) /* crashes on native */
993 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, NULL, NULL);
994 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, NULL);
997 memset(&logfont, 0xa, sizeof(logfont));
998 logfont.lfFaceName[0] = 0;
1000 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, &logfont);
1001 ok(hr == S_OK, "got 0x%08x\n", hr);
1002 ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight);
1003 ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth);
1004 ok(logfont.lfWeight == FW_NORMAL, "got %d\n", logfont.lfWeight);
1005 ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement);
1006 ok(logfont.lfItalic == 1, "got %d\n", logfont.lfItalic);
1007 ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline);
1008 ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut);
1009 ok(!lstrcmpW(logfont.lfFaceName, tahomaW), "got %s\n", wine_dbgstr_w(logfont.lfFaceName));
1011 IDWriteGdiInterop_Release(interop);
1012 IDWriteFontFace_Release(fontface);
1013 IDWriteFactory_Release(factory);
1016 static HRESULT WINAPI fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
1018 *obj = iface;
1019 return S_OK;
1022 static ULONG WINAPI fontcollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
1024 return 2;
1027 static ULONG WINAPI fontcollectionloader_Release(IDWriteFontCollectionLoader *iface)
1029 return 1;
1032 static HRESULT WINAPI fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory * factory, const void * collectionKey, UINT32 collectionKeySize, IDWriteFontFileEnumerator ** fontFileEnumerator)
1034 return S_OK;
1037 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl = {
1038 fontcollectionloader_QueryInterface,
1039 fontcollectionloader_AddRef,
1040 fontcollectionloader_Release,
1041 fontcollectionloader_CreateEnumeratorFromKey
1044 static void test_CustomFontCollection(void)
1046 IDWriteFontCollectionLoader collection = { &dwritefontcollectionloadervtbl };
1047 IDWriteFontCollectionLoader collection2 = { &dwritefontcollectionloadervtbl };
1048 IDWriteFactory *factory;
1049 HRESULT hr;
1051 factory = create_factory();
1053 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, NULL);
1054 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1056 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, NULL);
1057 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1059 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
1060 ok(hr == S_OK, "got 0x%08x\n", hr);
1061 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection2);
1062 ok(hr == S_OK, "got 0x%08x\n", hr);
1063 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
1064 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1066 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
1067 ok(hr == S_OK, "got 0x%08x\n", hr);
1068 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
1069 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1070 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection2);
1071 ok(hr == S_OK, "got 0x%08x\n", hr);
1073 IDWriteFactory_Release(factory);
1076 static HRESULT WINAPI fontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
1078 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
1080 *obj = iface;
1081 IDWriteFontFileLoader_AddRef(iface);
1082 return S_OK;
1085 *obj = NULL;
1086 return E_NOINTERFACE;
1089 static ULONG WINAPI fontfileloader_AddRef(IDWriteFontFileLoader *iface)
1091 return 2;
1094 static ULONG WINAPI fontfileloader_Release(IDWriteFontFileLoader *iface)
1096 return 1;
1099 static HRESULT WINAPI fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1101 return 0x8faecafe;
1104 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl = {
1105 fontfileloader_QueryInterface,
1106 fontfileloader_AddRef,
1107 fontfileloader_Release,
1108 fontfileloader_CreateStreamFromKey
1111 static void test_CreateCustomFontFileReference(void)
1113 IDWriteFontFileLoader floader = { &dwritefontfileloadervtbl };
1114 IDWriteFontFileLoader floader2 = { &dwritefontfileloadervtbl };
1115 IDWriteFontFileLoader floader3 = { &dwritefontfileloadervtbl };
1116 IDWriteFactory *factory, *factory2;
1117 IDWriteFontFile *file, *file2;
1118 BOOL support;
1119 DWRITE_FONT_FILE_TYPE file_type;
1120 DWRITE_FONT_FACE_TYPE face_type;
1121 UINT32 count;
1122 IDWriteFontFace *face, *face2;
1123 HRESULT hr;
1124 HRSRC fontrsrc;
1125 UINT32 codePoints[1] = {0xa8};
1126 UINT16 indices[1];
1128 factory = create_factory();
1129 factory2 = create_factory();
1131 hr = IDWriteFactory_RegisterFontFileLoader(factory, NULL);
1132 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1133 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
1134 ok(hr == S_OK, "got 0x%08x\n", hr);
1135 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader2);
1136 ok(hr == S_OK, "got 0x%08x\n", hr);
1137 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
1138 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
1139 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1140 ok(hr == S_OK, "got 0x%08x\n", hr);
1142 file = NULL;
1143 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &file);
1144 ok(hr == S_OK, "got 0x%08x\n", hr);
1145 IDWriteFontFile_Release(file);
1147 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader3, &file);
1148 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1150 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, NULL, &file);
1151 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1153 file = NULL;
1154 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &file);
1155 ok(hr == S_OK, "got 0x%08x\n", hr);
1157 file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE;
1158 face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE;
1159 support = TRUE;
1160 count = 1;
1161 IDWriteFontFile_Analyze(file, &support, &file_type, &face_type, &count);
1162 ok(hr == S_OK, "got 0x%08x\n", hr);
1163 ok(support == FALSE, "got %i\n", support);
1164 ok(file_type == DWRITE_FONT_FILE_TYPE_UNKNOWN, "got %i\n", file_type);
1165 ok(face_type == DWRITE_FONT_FACE_TYPE_UNKNOWN, "got %i\n", face_type);
1166 ok(count == 0, "got %i\n", count);
1168 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_CFF, 1, &file, 0, 0, &face);
1169 ok(hr == 0x8faecafe, "got 0x%08x\n", hr);
1170 IDWriteFontFile_Release(file);
1172 fontrsrc = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1173 ok(fontrsrc != NULL, "Failed to find font resource\n");
1175 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontrsrc, sizeof(HRSRC), &rloader, &file);
1176 ok(hr == S_OK, "got 0x%08x\n", hr);
1178 file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1179 face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1180 support = FALSE;
1181 count = 0;
1182 hr = IDWriteFontFile_Analyze(file, &support, &file_type, &face_type, &count);
1183 ok(hr == S_OK, "got 0x%08x\n", hr);
1184 ok(support == TRUE, "got %i\n", support);
1185 ok(file_type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", file_type);
1186 ok(face_type == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face_type);
1187 ok(count == 1, "got %i\n", count);
1189 /* invalid index */
1190 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 1, DWRITE_FONT_SIMULATIONS_NONE, &face);
1191 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1193 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face);
1194 ok(hr == S_OK, "got 0x%08x\n", hr);
1196 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
1197 ok(hr == S_OK, "got 0x%08x\n", hr);
1198 /* fontface instances are reused starting with win7 */
1199 ok(face == face2 || broken(face != face2), "got %p, %p\n", face, face2);
1200 IDWriteFontFace_Release(face2);
1202 /* file was created with different factory */
1203 hr = IDWriteFactory_CreateFontFace(factory2, face_type, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
1204 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1206 file2 = NULL;
1207 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontrsrc, sizeof(HRSRC), &rloader, &file2);
1208 ok(hr == S_OK, "got 0x%08x\n", hr);
1209 ok(file != file2, "got %p, %p\n", file, file2);
1211 hr = IDWriteFactory_CreateFontFace(factory, face_type, 1, &file2, 0, DWRITE_FONT_SIMULATIONS_NONE, &face2);
1212 ok(hr == S_OK, "got 0x%08x\n", hr);
1213 /* fontface instances are reused starting with win7 */
1214 ok(face == face2 || broken(face != face2), "got %p, %p\n", face, face2);
1215 IDWriteFontFace_Release(face2);
1216 IDWriteFontFile_Release(file2);
1218 hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 1, indices);
1219 ok(hr == S_OK, "got 0x%08x\n", hr);
1220 ok(indices[0] == 6, "got index %i\n", indices[0]);
1221 IDWriteFontFace_Release(face);
1222 IDWriteFontFile_Release(file);
1224 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
1225 ok(hr == S_OK, "got 0x%08x\n", hr);
1226 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
1227 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1228 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader2);
1229 ok(hr == S_OK, "got 0x%08x\n", hr);
1230 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1231 ok(hr == S_OK, "got 0x%08x\n", hr);
1233 IDWriteFactory_Release(factory2);
1234 IDWriteFactory_Release(factory);
1237 static void test_CreateFontFileReference(void)
1239 DWORD written;
1240 HANDLE file;
1241 HRSRC res;
1242 void *ptr;
1243 HRESULT hr;
1244 WCHAR font_name[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
1245 IDWriteFontFile *ffile = NULL;
1246 BOOL support = 1;
1247 DWRITE_FONT_FILE_TYPE type = 1;
1248 DWRITE_FONT_FACE_TYPE face = 1;
1249 UINT32 count = 1;
1250 IDWriteFontFace *fface = NULL;
1251 IDWriteFactory *factory;
1253 file = CreateFileW(font_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1254 ok( file != INVALID_HANDLE_VALUE, "file creation failed\n" );
1256 res = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1257 ok( res != 0, "couldn't find resource\n" );
1258 ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
1259 WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
1260 ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
1261 CloseHandle( file );
1263 factory = create_factory();
1265 hr = IDWriteFactory_CreateFontFileReference(factory, font_name, NULL, &ffile);
1266 ok(hr == S_OK, "got 0x%08x\n",hr);
1268 IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
1269 ok(hr == S_OK, "got 0x%08x\n", hr);
1270 ok(support == TRUE, "got %i\n", support);
1271 ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type);
1272 ok(face == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face);
1273 ok(count == 1, "got %i\n", count);
1275 hr = IDWriteFactory_CreateFontFace(factory, face, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fface);
1276 ok(hr == S_OK, "got 0x%08x\n", hr);
1278 IDWriteFontFace_Release(fface);
1279 IDWriteFontFile_Release(ffile);
1280 IDWriteFactory_Release(factory);
1282 DeleteFileW(font_name);
1285 static void test_shared_isolated(void)
1287 IDWriteFactory *isolated, *isolated2;
1288 IDWriteFactory *shared, *shared2;
1289 HRESULT hr;
1291 /* invalid type */
1292 shared = NULL;
1293 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&shared);
1294 ok(hr == S_OK, "got 0x%08x\n", hr);
1295 ok(shared != NULL, "got %p\n", shared);
1296 IDWriteFactory_Release(shared);
1298 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared);
1299 ok(hr == S_OK, "got 0x%08x\n", hr);
1301 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
1302 ok(hr == S_OK, "got 0x%08x\n", hr);
1303 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
1305 IDWriteFactory_Release(shared);
1306 IDWriteFactory_Release(shared2);
1308 /* we got 2 references, released 2 - still same pointer is returned */
1309 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
1310 ok(hr == S_OK, "got 0x%08x\n", hr);
1311 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
1312 IDWriteFactory_Release(shared2);
1314 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated);
1315 ok(hr == S_OK, "got 0x%08x\n", hr);
1317 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated2);
1318 ok(hr == S_OK, "got 0x%08x\n", hr);
1319 ok(isolated != isolated2, "got %p, and %p\n", isolated, isolated2);
1320 IDWriteFactory_Release(isolated2);
1322 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&isolated2);
1323 ok(hr == S_OK, "got 0x%08x\n", hr);
1324 ok(shared != isolated2, "got %p, and %p\n", shared, isolated2);
1326 IDWriteFactory_Release(isolated);
1327 IDWriteFactory_Release(isolated2);
1330 static void test_GetUnicodeRanges(void)
1332 DWRITE_UNICODE_RANGE *ranges, r;
1333 IDWriteFontFile *ffile = NULL;
1334 IDWriteFontFace1 *fontface1;
1335 IDWriteFontFace *fontface;
1336 IDWriteFactory *factory;
1337 UINT32 count;
1338 HRESULT hr;
1339 HRSRC font;
1341 factory = create_factory();
1343 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1344 ok(hr == S_OK, "got 0x%08x\n", hr);
1346 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1347 ok(font != NULL, "Failed to find font resource\n");
1349 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
1350 ok(hr == S_OK, "got 0x%08x\n", hr);
1352 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1353 ok(hr == S_OK, "got 0x%08x\n", hr);
1354 IDWriteFontFile_Release(ffile);
1356 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
1357 IDWriteFontFace_Release(fontface);
1358 if (hr != S_OK) {
1359 win_skip("GetUnicodeRanges() is not supported.\n");
1360 IDWriteFactory_Release(factory);
1361 return;
1364 count = 0;
1365 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 0, NULL, &count);
1366 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1367 ok(count > 0, "got %u\n", count);
1369 count = 1;
1370 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, NULL, &count);
1371 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1372 ok(count == 0, "got %u\n", count);
1374 count = 0;
1375 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, &r, &count);
1376 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1377 ok(count > 1, "got %u\n", count);
1379 ranges = heap_alloc(count*sizeof(DWRITE_UNICODE_RANGE));
1380 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, count, ranges, &count);
1381 ok(hr == S_OK, "got 0x%08x\n", hr);
1383 ranges[0].first = ranges[0].last = 0;
1384 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, ranges, &count);
1385 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1386 ok(ranges[0].first != 0 && ranges[0].last != 0, "got 0x%x-0x%0x\n", ranges[0].first, ranges[0].last);
1388 heap_free(ranges);
1390 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1391 ok(hr == S_OK, "got 0x%08x\n", hr);
1393 IDWriteFontFace1_Release(fontface1);
1394 IDWriteFactory_Release(factory);
1397 static void test_GetFontFromFontFace(void)
1399 IDWriteFontFace *fontface, *fontface2;
1400 IDWriteFontCollection *collection;
1401 IDWriteFont *font, *font2, *font3;
1402 IDWriteFontFamily *family;
1403 IDWriteFactory *factory;
1404 HRESULT hr;
1406 factory = create_factory();
1408 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1409 ok(hr == S_OK, "got 0x%08x\n", hr);
1411 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1412 ok(hr == S_OK, "got 0x%08x\n", hr);
1414 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1415 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1416 ok(hr == S_OK, "got 0x%08x\n", hr);
1418 hr = IDWriteFont_CreateFontFace(font, &fontface);
1419 ok(hr == S_OK, "got 0x%08x\n", hr);
1421 font2 = NULL;
1422 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font2);
1423 todo_wine
1424 ok(hr == S_OK, "got 0x%08x\n", hr);
1425 ok(font2 != font, "got %p, %p\n", font2, font);
1427 font3 = NULL;
1428 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font3);
1429 todo_wine {
1430 ok(hr == S_OK, "got 0x%08x\n", hr);
1431 ok(font3 != font && font3 != font2, "got %p, %p, %p\n", font3, font2, font);
1434 if (font2) {
1435 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
1436 ok(hr == S_OK, "got 0x%08x\n", hr);
1437 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
1438 IDWriteFontFace_Release(fontface2);
1441 if (font3) {
1442 hr = IDWriteFont_CreateFontFace(font3, &fontface2);
1443 ok(hr == S_OK, "got 0x%08x\n", hr);
1444 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
1445 IDWriteFontFace_Release(fontface2);
1448 if (font)
1449 IDWriteFont_Release(font);
1450 if (font2)
1451 IDWriteFont_Release(font2);
1452 if (font3)
1453 IDWriteFont_Release(font3);
1454 IDWriteFontFace_Release(fontface);
1455 IDWriteFontFamily_Release(family);
1456 IDWriteFontCollection_Release(collection);
1457 IDWriteFactory_Release(factory);
1460 static void test_GetFirstMatchingFont(void)
1462 IDWriteFontCollection *collection;
1463 IDWriteFont *font, *font2;
1464 IDWriteFontFamily *family;
1465 IDWriteFactory *factory;
1466 HRESULT hr;
1468 factory = create_factory();
1470 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1471 ok(hr == S_OK, "got 0x%08x\n", hr);
1473 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1474 ok(hr == S_OK, "got 0x%08x\n", hr);
1476 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1477 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1478 ok(hr == S_OK, "got 0x%08x\n", hr);
1480 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1481 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font2);
1482 ok(hr == S_OK, "got 0x%08x\n", hr);
1483 ok(font != font2, "got %p, %p\n", font, font2);
1485 IDWriteFont_Release(font);
1486 IDWriteFont_Release(font2);
1487 IDWriteFontFamily_Release(family);
1488 IDWriteFontCollection_Release(collection);
1489 IDWriteFactory_Release(factory);
1492 static void test_GetInformationalStrings(void)
1494 IDWriteLocalizedStrings *strings, *strings2;
1495 IDWriteFontCollection *collection;
1496 IDWriteFontFamily *family;
1497 IDWriteFactory *factory;
1498 IDWriteFont *font;
1499 BOOL exists;
1500 HRESULT hr;
1502 factory = create_factory();
1504 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1505 ok(hr == S_OK, "got 0x%08x\n", hr);
1507 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1508 ok(hr == S_OK, "got 0x%08x\n", hr);
1510 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1511 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1512 ok(hr == S_OK, "got 0x%08x\n", hr);
1514 exists = TRUE;
1515 strings = (void*)0xdeadbeef;
1516 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1, &strings, &exists);
1517 ok(hr == S_OK, "got 0x%08x\n", hr);
1518 ok(exists == FALSE, "got %d\n", exists);
1519 ok(strings == NULL, "got %p\n", strings);
1521 exists = FALSE;
1522 strings = NULL;
1523 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists);
1524 todo_wine {
1525 ok(hr == S_OK, "got 0x%08x\n", hr);
1526 ok(exists == TRUE, "got %d\n", exists);
1528 exists = TRUE;
1529 strings = NULL;
1530 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_NONE, &strings, &exists);
1531 ok(hr == S_OK, "got 0x%08x\n", hr);
1532 ok(exists == FALSE, "got %d\n", exists);
1534 /* strings instance is not reused */
1535 strings2 = NULL;
1536 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings2, &exists);
1537 todo_wine {
1538 ok(hr == S_OK, "got 0x%08x\n", hr);
1539 ok(strings2 != strings, "got %p, %p\n", strings2, strings);
1542 if (strings)
1543 IDWriteLocalizedStrings_Release(strings);
1544 if (strings2)
1545 IDWriteLocalizedStrings_Release(strings2);
1546 IDWriteFont_Release(font);
1547 IDWriteFontFamily_Release(family);
1548 IDWriteFontCollection_Release(collection);
1549 IDWriteFactory_Release(factory);
1552 static void test_GetGdiInterop(void)
1554 IDWriteGdiInterop *interop, *interop2;
1555 IDWriteFactory *factory, *factory2;
1556 IDWriteFont *font;
1557 LOGFONTW logfont;
1558 HRESULT hr;
1560 factory = create_factory();
1562 interop = NULL;
1563 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1564 ok(hr == S_OK, "got 0x%08x\n", hr);
1566 interop2 = NULL;
1567 hr = IDWriteFactory_GetGdiInterop(factory, &interop2);
1568 ok(hr == S_OK, "got 0x%08x\n", hr);
1569 ok(interop == interop2, "got %p, %p\n", interop, interop2);
1570 IDWriteGdiInterop_Release(interop2);
1572 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory2);
1573 ok(hr == S_OK, "got 0x%08x\n", hr);
1575 /* each factory gets its own interop */
1576 interop2 = NULL;
1577 hr = IDWriteFactory_GetGdiInterop(factory2, &interop2);
1578 ok(hr == S_OK, "got 0x%08x\n", hr);
1579 ok(interop != interop2, "got %p, %p\n", interop, interop2);
1581 /* release factory - interop still works */
1582 IDWriteFactory_Release(factory2);
1584 memset(&logfont, 0, sizeof(logfont));
1585 logfont.lfHeight = 12;
1586 logfont.lfWidth = 12;
1587 logfont.lfWeight = FW_NORMAL;
1588 logfont.lfItalic = 1;
1589 lstrcpyW(logfont.lfFaceName, tahomaW);
1591 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop2, &logfont, &font);
1592 ok(hr == S_OK, "got 0x%08x\n", hr);
1594 IDWriteGdiInterop_Release(interop2);
1595 IDWriteGdiInterop_Release(interop);
1596 IDWriteFactory_Release(factory);
1599 static void test_CreateFontFaceFromHdc(void)
1601 IDWriteGdiInterop *interop;
1602 IDWriteFontFace *fontface;
1603 IDWriteFactory *factory;
1604 HFONT hfont, oldhfont;
1605 LOGFONTW logfont;
1606 HRESULT hr;
1607 HDC hdc;
1609 factory = create_factory();
1611 interop = NULL;
1612 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1613 ok(hr == S_OK, "got 0x%08x\n", hr);
1615 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, NULL, &fontface);
1616 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1618 memset(&logfont, 0, sizeof(logfont));
1619 logfont.lfHeight = 12;
1620 logfont.lfWidth = 12;
1621 logfont.lfWeight = FW_NORMAL;
1622 logfont.lfItalic = 1;
1623 lstrcpyW(logfont.lfFaceName, tahomaW);
1625 hfont = CreateFontIndirectW(&logfont);
1626 hdc = CreateCompatibleDC(0);
1627 oldhfont = SelectObject(hdc, hfont);
1629 fontface = NULL;
1630 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, hdc, &fontface);
1631 ok(hr == S_OK, "got 0x%08x\n", hr);
1632 IDWriteFontFace_Release(fontface);
1633 DeleteObject(SelectObject(hdc, oldhfont));
1634 DeleteDC(hdc);
1636 IDWriteGdiInterop_Release(interop);
1637 IDWriteFactory_Release(factory);
1640 START_TEST(font)
1642 IDWriteFactory *factory;
1644 if (!(factory = create_factory())) {
1645 win_skip("failed to create factory\n");
1646 return;
1649 test_CreateFontFromLOGFONT();
1650 test_CreateBitmapRenderTarget();
1651 test_GetFontFamily();
1652 test_GetFamilyNames();
1653 test_CreateFontFace();
1654 test_GetMetrics();
1655 test_system_fontcollection();
1656 test_ConvertFontFaceToLOGFONT();
1657 test_CustomFontCollection();
1658 test_CreateCustomFontFileReference();
1659 test_CreateFontFileReference();
1660 test_shared_isolated();
1661 test_GetUnicodeRanges();
1662 test_GetFontFromFontFace();
1663 test_GetFirstMatchingFont();
1664 test_GetInformationalStrings();
1665 test_GetGdiInterop();
1666 test_CreateFontFaceFromHdc();
1668 IDWriteFactory_Release(factory);