dwrite: Implement CreateFontFaceFromHdc().
[wine.git] / dlls / dwrite / tests / font.c
blob1bb775484961be900b1a953cf624202d9c9bd290
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 IDWriteFactory *factory;
52 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
53 static const WCHAR blahW[] = {'B','l','a','h','!',0};
55 /* Here is a functional custom font set of interfaces */
56 struct test_fontdatastream
58 IDWriteFontFileStream IDWriteFontFileStream_iface;
59 LONG ref;
61 LPVOID data;
62 DWORD size;
65 static inline struct test_fontdatastream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream* iface)
67 return CONTAINING_RECORD(iface, struct test_fontdatastream, IDWriteFontFileStream_iface);
70 static HRESULT WINAPI fontdatastream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
72 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
74 *obj = iface;
75 IDWriteFontFileStream_AddRef(iface);
76 return S_OK;
78 *obj = NULL;
79 return E_NOINTERFACE;
82 static ULONG WINAPI fontdatastream_AddRef(IDWriteFontFileStream *iface)
84 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
85 ULONG ref = InterlockedIncrement(&This->ref);
86 return ref;
89 static ULONG WINAPI fontdatastream_Release(IDWriteFontFileStream *iface)
91 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
92 ULONG ref = InterlockedDecrement(&This->ref);
93 if (ref == 0)
94 HeapFree(GetProcessHeap(), 0, This);
95 return ref;
98 static HRESULT WINAPI fontdatastream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
100 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
101 *fragment_context = NULL;
102 if (offset+fragment_size > This->size)
104 *fragment_start = NULL;
105 return E_FAIL;
107 else
109 *fragment_start = (BYTE*)This->data + offset;
110 return S_OK;
114 static void WINAPI fontdatastream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
116 /* Do Nothing */
119 static HRESULT WINAPI fontdatastream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
121 struct test_fontdatastream *This = impl_from_IDWriteFontFileStream(iface);
122 *size = This->size;
123 return S_OK;
126 static HRESULT WINAPI fontdatastream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
128 return E_NOTIMPL;
131 static const IDWriteFontFileStreamVtbl fontdatastreamvtbl =
133 fontdatastream_QueryInterface,
134 fontdatastream_AddRef,
135 fontdatastream_Release,
136 fontdatastream_ReadFileFragment,
137 fontdatastream_ReleaseFileFragment,
138 fontdatastream_GetFileSize,
139 fontdatastream_GetLastWriteTime
142 static HRESULT create_fontdatastream(LPVOID data, UINT size, IDWriteFontFileStream** iface)
144 struct test_fontdatastream *This = HeapAlloc(GetProcessHeap(), 0, sizeof(struct test_fontdatastream));
145 if (!This)
146 return E_OUTOFMEMORY;
148 This->data = data;
149 This->size = size;
150 This->ref = 1;
151 This->IDWriteFontFileStream_iface.lpVtbl = &fontdatastreamvtbl;
153 *iface = &This->IDWriteFontFileStream_iface;
154 return S_OK;
157 static HRESULT WINAPI resourcefontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
159 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
161 *obj = iface;
162 return S_OK;
164 *obj = NULL;
165 return E_NOINTERFACE;
168 static ULONG WINAPI resourcefontfileloader_AddRef(IDWriteFontFileLoader *iface)
170 return 2;
173 static ULONG WINAPI resourcefontfileloader_Release(IDWriteFontFileLoader *iface)
175 return 1;
178 static HRESULT WINAPI resourcefontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
180 LPVOID data;
181 DWORD size;
182 HGLOBAL mem;
184 mem = LoadResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
185 ok(mem != NULL, "Failed to lock font resource\n");
186 if (mem)
188 size = SizeofResource(GetModuleHandleA(NULL), *(HRSRC*)fontFileReferenceKey);
189 data = LockResource(mem);
190 return create_fontdatastream(data, size, fontFileStream);
192 return E_FAIL;
195 static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl = {
196 resourcefontfileloader_QueryInterface,
197 resourcefontfileloader_AddRef,
198 resourcefontfileloader_Release,
199 resourcefontfileloader_CreateStreamFromKey
202 static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
204 static void test_CreateFontFromLOGFONT(void)
206 static const WCHAR tahomaspW[] = {'T','a','h','o','m','a',' ',0};
207 IDWriteGdiInterop *interop;
208 DWRITE_FONT_WEIGHT weight;
209 DWRITE_FONT_STYLE style;
210 IDWriteFont *font;
211 LOGFONTW logfont;
212 LONG weights[][2] = {
213 {FW_NORMAL, DWRITE_FONT_WEIGHT_NORMAL},
214 {FW_BOLD, DWRITE_FONT_WEIGHT_BOLD},
215 { 0, DWRITE_FONT_WEIGHT_NORMAL},
216 { 50, DWRITE_FONT_WEIGHT_NORMAL},
217 {150, DWRITE_FONT_WEIGHT_NORMAL},
218 {250, DWRITE_FONT_WEIGHT_NORMAL},
219 {350, DWRITE_FONT_WEIGHT_NORMAL},
220 {450, DWRITE_FONT_WEIGHT_NORMAL},
221 {650, DWRITE_FONT_WEIGHT_BOLD},
222 {750, DWRITE_FONT_WEIGHT_BOLD},
223 {850, DWRITE_FONT_WEIGHT_BOLD},
224 {950, DWRITE_FONT_WEIGHT_BOLD},
225 {960, DWRITE_FONT_WEIGHT_BOLD},
227 OUTLINETEXTMETRICW otm;
228 HRESULT hr;
229 BOOL ret;
230 HDC hdc;
231 HFONT hfont;
232 BOOL exists;
233 int i;
234 UINT r;
236 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
237 EXPECT_HR(hr, S_OK);
239 if (0)
240 /* null out parameter crashes this call */
241 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, NULL);
243 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, &font);
244 EXPECT_HR(hr, E_INVALIDARG);
246 memset(&logfont, 0, sizeof(logfont));
247 logfont.lfHeight = 12;
248 logfont.lfWidth = 12;
249 logfont.lfWeight = FW_NORMAL;
250 logfont.lfItalic = 1;
251 lstrcpyW(logfont.lfFaceName, tahomaW);
253 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
254 EXPECT_HR(hr, S_OK);
256 hfont = CreateFontIndirectW(&logfont);
257 hdc = CreateCompatibleDC(0);
258 SelectObject(hdc, hfont);
260 otm.otmSize = sizeof(otm);
261 r = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
262 ok(r, "got %d\n", r);
263 DeleteDC(hdc);
264 DeleteObject(hfont);
266 exists = TRUE;
267 hr = IDWriteFont_HasCharacter(font, 0xd800, &exists);
268 ok(hr == S_OK, "got 0x%08x\n", hr);
269 ok(exists == FALSE, "got %d\n", exists);
271 exists = FALSE;
272 hr = IDWriteFont_HasCharacter(font, 0x20, &exists);
273 ok(hr == S_OK, "got 0x%08x\n", hr);
274 ok(exists == TRUE, "got %d\n", exists);
276 /* now check properties */
277 weight = IDWriteFont_GetWeight(font);
278 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
280 style = IDWriteFont_GetStyle(font);
281 todo_wine {
282 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
283 ok(otm.otmfsSelection == 1, "got 0x%08x\n", otm.otmfsSelection);
285 ret = IDWriteFont_IsSymbolFont(font);
286 ok(!ret, "got %d\n", ret);
288 IDWriteFont_Release(font);
290 /* weight values */
291 for (i = 0; i < sizeof(weights)/(2*sizeof(LONG)); i++)
293 memset(&logfont, 0, sizeof(logfont));
294 logfont.lfHeight = 12;
295 logfont.lfWidth = 12;
296 logfont.lfWeight = weights[i][0];
297 lstrcpyW(logfont.lfFaceName, tahomaW);
299 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
300 EXPECT_HR(hr, S_OK);
302 weight = IDWriteFont_GetWeight(font);
303 ok(weight == weights[i][1],
304 "%d: got %d, expected %d\n", i, weight, weights[i][1]);
305 IDWriteFont_Release(font);
308 /* weight not from enum */
309 memset(&logfont, 0, sizeof(logfont));
310 logfont.lfHeight = 12;
311 logfont.lfWidth = 12;
312 logfont.lfWeight = 550;
313 lstrcpyW(logfont.lfFaceName, tahomaW);
315 font = NULL;
316 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
317 ok(hr == S_OK, "got 0x%08x\n", hr);
319 weight = IDWriteFont_GetWeight(font);
320 ok(weight == DWRITE_FONT_WEIGHT_NORMAL || broken(weight == DWRITE_FONT_WEIGHT_BOLD) /* win7 w/o SP */,
321 "got %d\n", weight);
322 IDWriteFont_Release(font);
324 /* empty or nonexistent face name */
325 memset(&logfont, 0, sizeof(logfont));
326 logfont.lfHeight = 12;
327 logfont.lfWidth = 12;
328 logfont.lfWeight = FW_NORMAL;
329 lstrcpyW(logfont.lfFaceName, blahW);
331 font = (void*)0xdeadbeef;
332 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
333 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
334 ok(font == NULL, "got %p\n", font);
336 /* Try with name 'Tahoma ' */
337 memset(&logfont, 0, sizeof(logfont));
338 logfont.lfHeight = 12;
339 logfont.lfWidth = 12;
340 logfont.lfWeight = FW_NORMAL;
341 lstrcpyW(logfont.lfFaceName, tahomaspW);
343 font = (void*)0xdeadbeef;
344 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
345 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
346 ok(font == NULL, "got %p\n", font);
348 /* empty string as a facename */
349 memset(&logfont, 0, sizeof(logfont));
350 logfont.lfHeight = 12;
351 logfont.lfWidth = 12;
352 logfont.lfWeight = FW_NORMAL;
354 font = (void*)0xdeadbeef;
355 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
356 ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr);
357 ok(font == NULL, "got %p\n", font);
359 IDWriteGdiInterop_Release(interop);
362 static void test_CreateBitmapRenderTarget(void)
364 IDWriteBitmapRenderTarget *target, *target2;
365 IDWriteGdiInterop *interop;
366 HBITMAP hbm, hbm2;
367 DWRITE_MATRIX m;
368 DIBSECTION ds;
369 HRESULT hr;
370 SIZE size;
371 HDC hdc;
372 int ret;
374 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
375 EXPECT_HR(hr, S_OK);
377 target = NULL;
378 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target);
379 EXPECT_HR(hr, S_OK);
381 if (0) /* crashes on native */
382 hr = IDWriteBitmapRenderTarget_GetSize(target, NULL);
384 size.cx = size.cy = -1;
385 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
386 EXPECT_HR(hr, S_OK);
387 ok(size.cx == 0, "got %d\n", size.cx);
388 ok(size.cy == 0, "got %d\n", size.cy);
390 target2 = NULL;
391 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target2);
392 EXPECT_HR(hr, S_OK);
393 ok(target != target2, "got %p, %p\n", target2, target);
394 IDWriteBitmapRenderTarget_Release(target2);
396 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
397 ok(hdc != NULL, "got %p\n", hdc);
399 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
400 ok(hbm != NULL, "got %p\n", hbm);
402 /* check DIB properties */
403 ret = GetObjectW(hbm, sizeof(ds), &ds);
404 ok(ret == sizeof(BITMAP), "got %d\n", ret);
405 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
406 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
407 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
408 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
409 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
411 IDWriteBitmapRenderTarget_Release(target);
413 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
414 ok(!hbm, "got %p\n", hbm);
416 target = NULL;
417 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 10, 5, &target);
418 EXPECT_HR(hr, S_OK);
420 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
421 ok(hdc != NULL, "got %p\n", hdc);
423 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
424 ok(hbm != NULL, "got %p\n", hbm);
426 /* check DIB properties */
427 ret = GetObjectW(hbm, sizeof(ds), &ds);
428 ok(ret == sizeof(ds), "got %d\n", ret);
429 ok(ds.dsBm.bmWidth == 10, "got %d\n", ds.dsBm.bmWidth);
430 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
431 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
432 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
433 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
435 size.cx = size.cy = -1;
436 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
437 EXPECT_HR(hr, S_OK);
438 ok(size.cx == 10, "got %d\n", size.cx);
439 ok(size.cy == 5, "got %d\n", size.cy);
441 /* resize to same size */
442 hr = IDWriteBitmapRenderTarget_Resize(target, 10, 5);
443 ok(hr == S_OK, "got 0x%08x\n", hr);
445 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
446 ok(hbm2 == hbm, "got %p, %p\n", hbm2, hbm);
448 /* shrink */
449 hr = IDWriteBitmapRenderTarget_Resize(target, 5, 5);
450 ok(hr == S_OK, "got 0x%08x\n", hr);
452 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
453 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
455 hr = IDWriteBitmapRenderTarget_Resize(target, 20, 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 hr = IDWriteBitmapRenderTarget_Resize(target, 1, 5);
462 ok(hr == S_OK, "got 0x%08x\n", hr);
464 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
465 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
467 ret = GetObjectW(hbm2, sizeof(ds), &ds);
468 ok(ret == sizeof(ds), "got %d\n", ret);
469 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
470 ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
471 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
472 ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
473 ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
475 /* empty rectangle */
476 hr = IDWriteBitmapRenderTarget_Resize(target, 0, 5);
477 ok(hr == S_OK, "got 0x%08x\n", hr);
479 hbm2 = GetCurrentObject(hdc, OBJ_BITMAP);
480 ok(hbm2 != hbm, "got %p, %p\n", hbm2, hbm);
482 ret = GetObjectW(hbm2, sizeof(ds), &ds);
483 ok(ret == sizeof(BITMAP), "got %d\n", ret);
484 ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
485 ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
486 ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
487 ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
488 ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
490 /* transform tests */
491 if (0) /* crashes on native */
492 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, NULL);
494 memset(&m, 0xcc, sizeof(m));
495 hr = IDWriteBitmapRenderTarget_GetCurrentTransform(target, &m);
496 ok(hr == S_OK, "got 0x%08x\n", hr);
497 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);
498 ok(m.dx == 0.0 && m.dy == 0.0, "got %.1f,%.1f\n", m.dx, m.dy);
500 IDWriteBitmapRenderTarget_Release(target);
501 IDWriteGdiInterop_Release(interop);
504 static void test_GetFontFamily(void)
506 IDWriteFontCollection *collection, *collection2;
507 IDWriteFontCollection *syscoll;
508 IDWriteFontFamily *family, *family2;
509 IDWriteGdiInterop *interop;
510 IDWriteFont *font, *font2;
511 LOGFONTW logfont;
512 HRESULT hr;
514 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
515 EXPECT_HR(hr, S_OK);
517 hr = IDWriteFactory_GetSystemFontCollection(factory, &syscoll, FALSE);
518 ok(hr == S_OK, "got 0x%08x\n", hr);
520 memset(&logfont, 0, sizeof(logfont));
521 logfont.lfHeight = 12;
522 logfont.lfWidth = 12;
523 logfont.lfWeight = FW_NORMAL;
524 logfont.lfItalic = 1;
525 lstrcpyW(logfont.lfFaceName, tahomaW);
527 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
528 ok(hr == S_OK, "got 0x%08x\n", hr);
530 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2);
531 ok(hr == S_OK, "got 0x%08x\n", hr);
532 ok(font2 != font, "got %p, %p\n", font2, font);
534 if (0) /* crashes on native */
535 hr = IDWriteFont_GetFontFamily(font, NULL);
537 EXPECT_REF(font, 1);
538 hr = IDWriteFont_GetFontFamily(font, &family);
539 EXPECT_HR(hr, S_OK);
540 EXPECT_REF(font, 1);
541 EXPECT_REF(family, 2);
543 hr = IDWriteFont_GetFontFamily(font, &family2);
544 EXPECT_HR(hr, S_OK);
545 ok(family2 == family, "got %p, previous %p\n", family2, family);
546 EXPECT_REF(font, 1);
547 EXPECT_REF(family, 3);
548 IDWriteFontFamily_Release(family2);
550 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFamily, (void**)&family2);
551 EXPECT_HR(hr, E_NOINTERFACE);
552 ok(family2 == NULL, "got %p\n", family2);
554 hr = IDWriteFont_GetFontFamily(font2, &family2);
555 ok(hr == S_OK, "got 0x%08x\n", hr);
556 ok(family2 != family, "got %p, %p\n", family2, family);
558 collection = NULL;
559 hr = IDWriteFontFamily_GetFontCollection(family, &collection);
560 todo_wine
561 ok(hr == S_OK, "got 0x%08x\n", hr);
563 collection2 = NULL;
564 hr = IDWriteFontFamily_GetFontCollection(family2, &collection2);
565 todo_wine
566 ok(hr == S_OK, "got 0x%08x\n", hr);
567 ok(collection == collection2, "got %p, %p\n", collection, collection2);
568 todo_wine
569 ok(collection == syscoll, "got %p, %p\n", collection, syscoll);
571 IDWriteFontCollection_Release(syscoll);
572 if (collection2)
573 IDWriteFontCollection_Release(collection2);
574 if (collection)
575 IDWriteFontCollection_Release(collection);
576 IDWriteFontFamily_Release(family2);
577 IDWriteFontFamily_Release(family);
578 IDWriteFont_Release(font);
579 IDWriteFont_Release(font2);
580 IDWriteGdiInterop_Release(interop);
583 static void test_GetFamilyNames(void)
585 IDWriteFontFamily *family;
586 IDWriteLocalizedStrings *names, *names2;
587 IDWriteGdiInterop *interop;
588 IDWriteFont *font;
589 LOGFONTW logfont;
590 WCHAR buffer[100];
591 HRESULT hr;
592 UINT32 len;
594 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
595 EXPECT_HR(hr, S_OK);
597 memset(&logfont, 0, sizeof(logfont));
598 logfont.lfHeight = 12;
599 logfont.lfWidth = 12;
600 logfont.lfWeight = FW_NORMAL;
601 logfont.lfItalic = 1;
602 lstrcpyW(logfont.lfFaceName, tahomaW);
604 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
605 EXPECT_HR(hr, S_OK);
607 hr = IDWriteFont_GetFontFamily(font, &family);
608 EXPECT_HR(hr, S_OK);
610 if (0) /* crashes on native */
611 hr = IDWriteFontFamily_GetFamilyNames(family, NULL);
613 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
614 ok(hr == S_OK, "got 0x%08x\n", hr);
615 EXPECT_REF(names, 1);
617 hr = IDWriteFontFamily_GetFamilyNames(family, &names2);
618 ok(hr == S_OK, "got 0x%08x\n", hr);
619 EXPECT_REF(names2, 1);
620 ok(names != names2, "got %p, was %p\n", names2, names);
622 IDWriteLocalizedStrings_Release(names2);
624 /* GetStringLength */
625 if (0) /* crashes on native */
626 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, NULL);
628 len = 100;
629 hr = IDWriteLocalizedStrings_GetStringLength(names, 10, &len);
630 ok(hr == E_FAIL, "got 0x%08x\n", hr);
631 ok(len == (UINT32)-1, "got %u\n", len);
633 len = 0;
634 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, &len);
635 ok(hr == S_OK, "got 0x%08x\n", hr);
636 ok(len > 0, "got %u\n", len);
638 /* GetString */
639 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 0);
640 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
642 hr = IDWriteLocalizedStrings_GetString(names, 10, NULL, 0);
643 ok(hr == E_FAIL, "got 0x%08x\n", hr);
645 if (0)
646 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 100);
648 buffer[0] = 1;
649 hr = IDWriteLocalizedStrings_GetString(names, 10, buffer, 100);
650 ok(hr == E_FAIL, "got 0x%08x\n", hr);
651 ok(buffer[0] == 0, "got %x\n", buffer[0]);
653 buffer[0] = 1;
654 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len-1);
655 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
656 ok(buffer[0] == 0, "got %x\n", buffer[0]);
658 buffer[0] = 1;
659 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len);
660 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
661 ok(buffer[0] == 0, "got %x\n", buffer[0]);
663 buffer[0] = 0;
664 hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len+1);
665 ok(hr == S_OK, "got 0x%08x\n", hr);
666 ok(buffer[0] != 0, "got %x\n", buffer[0]);
668 IDWriteLocalizedStrings_Release(names);
670 IDWriteFontFamily_Release(family);
671 IDWriteFont_Release(font);
672 IDWriteGdiInterop_Release(interop);
675 static void test_CreateFontFace(void)
677 IDWriteFontFace *fontface, *fontface2;
678 IDWriteGdiInterop *interop;
679 IDWriteFont *font;
680 LOGFONTW logfont;
681 HRESULT hr;
683 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
684 EXPECT_HR(hr, S_OK);
686 memset(&logfont, 0, sizeof(logfont));
687 logfont.lfHeight = 12;
688 logfont.lfWidth = 12;
689 logfont.lfWeight = FW_NORMAL;
690 logfont.lfItalic = 1;
691 lstrcpyW(logfont.lfFaceName, tahomaW);
693 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
694 ok(hr == S_OK, "got 0x%08x\n", hr);
696 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface);
697 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
699 if (0) /* crashes on native */
700 hr = IDWriteFont_CreateFontFace(font, NULL);
702 hr = IDWriteFont_CreateFontFace(font, &fontface);
703 ok(hr == S_OK, "got 0x%08x\n", hr);
705 hr = IDWriteFont_CreateFontFace(font, &fontface2);
706 ok(hr == S_OK, "got 0x%08x\n", hr);
707 ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
708 /* the fontface refcount is increased here */
709 IDWriteFontFace_Release(fontface);
710 IDWriteFont_Release(font);
712 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFont, (void**)&font);
713 ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL), "got 0x%08x\n", hr);
715 IDWriteFontFace_Release(fontface);
716 IDWriteGdiInterop_Release(interop);
719 static void test_GetMetrics(void)
721 IDWriteGdiInterop *interop;
722 DWRITE_FONT_METRICS metrics;
723 OUTLINETEXTMETRICW otm;
724 IDWriteFont *font;
725 LOGFONTW logfont;
726 HRESULT hr;
727 HDC hdc;
728 HFONT hfont;
729 int ret;
731 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
732 EXPECT_HR(hr, S_OK);
734 memset(&logfont, 0, sizeof(logfont));
735 logfont.lfHeight = 12;
736 logfont.lfWidth = 12;
737 logfont.lfWeight = FW_NORMAL;
738 logfont.lfItalic = 1;
739 lstrcpyW(logfont.lfFaceName, tahomaW);
741 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
742 ok(hr == S_OK, "got 0x%08x\n", hr);
744 hfont = CreateFontIndirectW(&logfont);
745 hdc = CreateCompatibleDC(0);
746 SelectObject(hdc, hfont);
748 otm.otmSize = sizeof(otm);
749 ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
750 ok(ret, "got %d\n", ret);
751 DeleteDC(hdc);
752 DeleteObject(hfont);
754 if (0) /* crashes on native */
755 IDWriteFont_GetMetrics(font, NULL);
757 memset(&metrics, 0, sizeof(metrics));
758 IDWriteFont_GetMetrics(font, &metrics);
760 ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
761 ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
762 ok(metrics.descent != 0, "descent %u\n", metrics.descent);
763 todo_wine
764 ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
765 ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
766 ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
767 ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
768 ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
769 ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
770 ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
772 IDWriteFont_Release(font);
773 IDWriteGdiInterop_Release(interop);
776 static void test_system_fontcollection(void)
778 IDWriteFontCollection *collection, *coll2;
779 IDWriteFontFamily *family;
780 IDWriteFactory *factory2;
781 HRESULT hr;
782 UINT32 i;
783 BOOL ret;
785 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
786 ok(hr == S_OK, "got 0x%08x\n", hr);
788 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, FALSE);
789 ok(hr == S_OK, "got 0x%08x\n", hr);
790 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
791 IDWriteFontCollection_Release(coll2);
793 hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, TRUE);
794 ok(hr == S_OK, "got 0x%08x\n", hr);
795 ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
796 IDWriteFontCollection_Release(coll2);
798 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory2);
799 ok(hr == S_OK, "got 0x%08x\n", hr);
800 hr = IDWriteFactory_GetSystemFontCollection(factory2, &coll2, FALSE);
801 ok(hr == S_OK, "got 0x%08x\n", hr);
802 ok(coll2 != collection, "got %p, was %p\n", coll2, collection);
803 IDWriteFontCollection_Release(coll2);
804 IDWriteFactory_Release(factory2);
806 i = IDWriteFontCollection_GetFontFamilyCount(collection);
807 ok(i, "got %u\n", i);
809 /* invalid index */
810 family = (void*)0xdeadbeef;
811 hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
812 ok(hr == E_FAIL, "got 0x%08x\n", hr);
813 ok(family == NULL, "got %p\n", family);
815 ret = FALSE;
816 i = (UINT32)-1;
817 hr = IDWriteFontCollection_FindFamilyName(collection, tahomaW, &i, &ret);
818 ok(hr == S_OK, "got 0x%08x\n", hr);
819 ok(ret, "got %d\n", ret);
820 ok(i != (UINT32)-1, "got %u\n", i);
822 ret = TRUE;
823 i = 0;
824 hr = IDWriteFontCollection_FindFamilyName(collection, blahW, &i, &ret);
825 ok(hr == S_OK, "got 0x%08x\n", hr);
826 ok(!ret, "got %d\n", ret);
827 ok(i == (UINT32)-1, "got %u\n", i);
829 IDWriteFontCollection_Release(collection);
832 static void test_ConvertFontFaceToLOGFONT(void)
834 IDWriteGdiInterop *interop;
835 IDWriteFontFace *fontface;
836 IDWriteFont *font;
837 LOGFONTW logfont;
838 HRESULT hr;
840 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
841 ok(hr == S_OK, "got 0x%08x\n", hr);
843 memset(&logfont, 0, sizeof(logfont));
844 logfont.lfHeight = 12;
845 logfont.lfWidth = 12;
846 logfont.lfEscapement = 100;
847 logfont.lfWeight = FW_NORMAL;
848 logfont.lfItalic = 1;
849 logfont.lfUnderline = 1;
850 logfont.lfStrikeOut = 1;
852 lstrcpyW(logfont.lfFaceName, tahomaW);
854 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
855 ok(hr == S_OK, "got 0x%08x\n", hr);
857 hr = IDWriteFont_CreateFontFace(font, &fontface);
858 ok(hr == S_OK, "got 0x%08x\n", hr);
859 IDWriteFont_Release(font);
861 if (0) /* crashes on native */
863 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, NULL, NULL);
864 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, NULL);
867 memset(&logfont, 0xa, sizeof(logfont));
868 logfont.lfFaceName[0] = 0;
870 hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, &logfont);
871 ok(hr == S_OK, "got 0x%08x\n", hr);
872 ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight);
873 ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth);
874 ok(logfont.lfWeight == FW_NORMAL, "got %d\n", logfont.lfWeight);
875 ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement);
876 ok(logfont.lfItalic == 1, "got %d\n", logfont.lfItalic);
877 ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline);
878 ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut);
879 ok(!lstrcmpW(logfont.lfFaceName, tahomaW), "got %s\n", wine_dbgstr_w(logfont.lfFaceName));
881 IDWriteGdiInterop_Release(interop);
882 IDWriteFontFace_Release(fontface);
885 static HRESULT WINAPI fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
887 *obj = iface;
888 return S_OK;
891 static ULONG WINAPI fontcollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
893 return 2;
896 static ULONG WINAPI fontcollectionloader_Release(IDWriteFontCollectionLoader *iface)
898 return 1;
901 static HRESULT WINAPI fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory * factory, const void * collectionKey, UINT32 collectionKeySize, IDWriteFontFileEnumerator ** fontFileEnumerator)
903 return S_OK;
906 static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervtbl = {
907 fontcollectionloader_QueryInterface,
908 fontcollectionloader_AddRef,
909 fontcollectionloader_Release,
910 fontcollectionloader_CreateEnumeratorFromKey
913 static void test_CustomFontCollection(void)
915 IDWriteFontCollectionLoader collection = { &dwritefontcollectionloadervtbl };
916 IDWriteFontCollectionLoader collection2 = { &dwritefontcollectionloadervtbl };
917 HRESULT hr;
919 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, NULL);
920 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
922 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, NULL);
923 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
925 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
926 ok(hr == S_OK, "got 0x%08x\n", hr);
927 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection2);
928 ok(hr == S_OK, "got 0x%08x\n", hr);
929 hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
930 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
932 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
933 ok(hr == S_OK, "got 0x%08x\n", hr);
934 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
935 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
936 hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection2);
937 ok(hr == S_OK, "got 0x%08x\n", hr);
940 static HRESULT WINAPI fontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
942 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader))
944 *obj = iface;
945 IDWriteFontFileLoader_AddRef(iface);
946 return S_OK;
949 *obj = NULL;
950 return E_NOINTERFACE;
953 static ULONG WINAPI fontfileloader_AddRef(IDWriteFontFileLoader *iface)
955 return 2;
958 static ULONG WINAPI fontfileloader_Release(IDWriteFontFileLoader *iface)
960 return 1;
963 static HRESULT WINAPI fontfileloader_CreateStreamFromKey(IDWriteFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
965 return 0x8faecafe;
968 static const struct IDWriteFontFileLoaderVtbl dwritefontfileloadervtbl = {
969 fontfileloader_QueryInterface,
970 fontfileloader_AddRef,
971 fontfileloader_Release,
972 fontfileloader_CreateStreamFromKey
975 static void test_FontLoader(void)
977 IDWriteFontFileLoader floader = { &dwritefontfileloadervtbl };
978 IDWriteFontFileLoader floader2 = { &dwritefontfileloadervtbl };
979 IDWriteFontFileLoader floader3 = { &dwritefontfileloadervtbl };
980 IDWriteFontFile *ffile = NULL;
981 BOOL support = 1;
982 DWRITE_FONT_FILE_TYPE type = 1;
983 DWRITE_FONT_FACE_TYPE face = 1;
984 UINT32 count = 1;
985 IDWriteFontFace *fface = NULL;
986 HRESULT hr;
987 HRSRC font;
988 UINT32 codePoints[1] = {0xa8};
989 UINT16 indices[1];
991 hr = IDWriteFactory_RegisterFontFileLoader(factory, NULL);
992 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
993 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
994 ok(hr == S_OK, "got 0x%08x\n", hr);
995 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader2);
996 ok(hr == S_OK, "got 0x%08x\n", hr);
997 hr = IDWriteFactory_RegisterFontFileLoader(factory, &floader);
998 ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
999 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1000 ok(hr == S_OK, "got 0x%08x\n", hr);
1002 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &ffile);
1003 ok(hr == S_OK, "got 0x%08x\n", hr);
1004 if (SUCCEEDED(hr))
1005 IDWriteFontFile_Release(ffile);
1007 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader3, &ffile);
1008 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1009 if (SUCCEEDED(hr))
1010 IDWriteFontFile_Release(ffile);
1012 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, NULL, &ffile);
1013 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1014 if (SUCCEEDED(hr))
1015 IDWriteFontFile_Release(ffile);
1017 hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &ffile);
1018 ok(hr == S_OK, "got 0x%08x\n", hr);
1019 IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
1020 ok(hr == S_OK, "got 0x%08x\n", hr);
1021 ok(support == FALSE, "got %i\n", support);
1022 ok(type == DWRITE_FONT_FILE_TYPE_UNKNOWN, "got %i\n", type);
1023 ok(face == DWRITE_FONT_FACE_TYPE_UNKNOWN, "got %i\n", face);
1024 ok(count == 0, "got %i\n", count);
1026 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_CFF, 1, &ffile, 0, 0, &fface);
1027 ok(hr == 0x8faecafe, "got 0x%08x\n", hr);
1028 IDWriteFontFile_Release(ffile);
1030 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1031 ok(font != NULL, "Failed to find font resource\n");
1032 if (font)
1034 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
1035 ok(hr == S_OK, "got 0x%08x\n", hr);
1037 hr = IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
1038 ok(hr == S_OK, "got 0x%08x\n", hr);
1039 ok(support == TRUE, "got %i\n", support);
1040 ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type);
1041 ok(face == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face);
1042 ok(count == 1, "got %i\n", count);
1044 /* invalid index */
1045 hr = IDWriteFactory_CreateFontFace(factory, face, 1, &ffile, 1, DWRITE_FONT_SIMULATIONS_NONE, &fface);
1046 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1048 hr = IDWriteFactory_CreateFontFace(factory, face, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fface);
1049 ok(hr == S_OK, "got 0x%08x\n", hr);
1050 hr = IDWriteFontFace_GetGlyphIndices(fface, codePoints, 1, indices);
1051 ok(hr == S_OK, "got 0x%08x\n", hr);
1052 ok(indices[0] == 6, "got index %i\n",indices[0]);
1053 IDWriteFontFace_Release(fface);
1054 IDWriteFontFile_Release(ffile);
1057 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
1058 ok(hr == S_OK, "got 0x%08x\n", hr);
1059 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);
1060 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1061 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader2);
1062 ok(hr == S_OK, "got 0x%08x\n", hr);
1063 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1064 ok(hr == S_OK, "got 0x%08x\n", hr);
1067 static void test_CreateFontFileReference(void)
1069 DWORD written;
1070 HANDLE file;
1071 HRSRC res;
1072 void *ptr;
1073 HRESULT hr;
1074 WCHAR font_name[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
1075 IDWriteFontFile *ffile = NULL;
1076 BOOL support = 1;
1077 DWRITE_FONT_FILE_TYPE type = 1;
1078 DWRITE_FONT_FACE_TYPE face = 1;
1079 UINT32 count = 1;
1080 IDWriteFontFace *fface = NULL;
1082 file = CreateFileW(font_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1083 ok( file != INVALID_HANDLE_VALUE, "file creation failed\n" );
1084 if (file == INVALID_HANDLE_VALUE) return;
1086 res = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1087 ok( res != 0, "couldn't find resource\n" );
1088 ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
1089 WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
1090 ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
1091 CloseHandle( file );
1093 hr = IDWriteFactory_CreateFontFileReference(factory, font_name, NULL, &ffile);
1094 ok(hr == S_OK, "got 0x%08x\n",hr);
1096 IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
1097 ok(hr == S_OK, "got 0x%08x\n", hr);
1098 ok(support == TRUE, "got %i\n", support);
1099 ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type);
1100 ok(face == DWRITE_FONT_FACE_TYPE_TRUETYPE, "got %i\n", face);
1101 ok(count == 1, "got %i\n", count);
1103 hr = IDWriteFactory_CreateFontFace(factory, face, 1, &ffile, 0, 0, &fface);
1104 ok(hr == S_OK, "got 0x%08x\n",hr);
1106 IDWriteFontFace_Release(fface);
1107 IDWriteFontFile_Release(ffile);
1109 DeleteFileW(font_name);
1112 static void test_shared_isolated(void)
1114 IDWriteFactory *isolated, *isolated2;
1115 IDWriteFactory *shared, *shared2;
1116 HRESULT hr;
1118 /* invalid type */
1119 shared = NULL;
1120 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&shared);
1121 ok(hr == S_OK, "got 0x%08x\n", hr);
1122 ok(shared != NULL, "got %p\n", shared);
1123 IDWriteFactory_Release(shared);
1125 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared);
1126 ok(hr == S_OK, "got 0x%08x\n", hr);
1128 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
1129 ok(hr == S_OK, "got 0x%08x\n", hr);
1130 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
1132 IDWriteFactory_Release(shared);
1133 IDWriteFactory_Release(shared2);
1135 /* we got 2 references, released 2 - still same pointer is returned */
1136 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
1137 ok(hr == S_OK, "got 0x%08x\n", hr);
1138 ok(shared == shared2, "got %p, and %p\n", shared, shared2);
1139 IDWriteFactory_Release(shared2);
1141 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated);
1142 ok(hr == S_OK, "got 0x%08x\n", hr);
1144 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated2);
1145 ok(hr == S_OK, "got 0x%08x\n", hr);
1146 ok(isolated != isolated2, "got %p, and %p\n", isolated, isolated2);
1147 IDWriteFactory_Release(isolated2);
1149 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&isolated2);
1150 ok(hr == S_OK, "got 0x%08x\n", hr);
1151 ok(shared != isolated2, "got %p, and %p\n", shared, isolated2);
1153 IDWriteFactory_Release(isolated);
1154 IDWriteFactory_Release(isolated2);
1157 static void test_GetUnicodeRanges(void)
1159 DWRITE_UNICODE_RANGE *ranges, r;
1160 IDWriteFontFile *ffile = NULL;
1161 IDWriteFontFace1 *fontface1;
1162 IDWriteFontFace *fontface;
1163 UINT32 count;
1164 HRESULT hr;
1165 HRSRC font;
1167 hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
1168 ok(hr == S_OK, "got 0x%08x\n", hr);
1170 font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
1171 ok(font != NULL, "Failed to find font resource\n");
1173 hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
1174 ok(hr == S_OK, "got 0x%08x\n", hr);
1176 hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
1177 ok(hr == S_OK, "got 0x%08x\n", hr);
1178 IDWriteFontFile_Release(ffile);
1180 hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
1181 IDWriteFontFace_Release(fontface);
1182 if (hr != S_OK) {
1183 win_skip("GetUnicodeRanges() is not supported.\n");
1184 return;
1187 count = 0;
1188 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 0, NULL, &count);
1189 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1190 ok(count > 0, "got %u\n", count);
1192 count = 1;
1193 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, NULL, &count);
1194 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1195 ok(count == 0, "got %u\n", count);
1197 count = 0;
1198 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, &r, &count);
1199 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1200 ok(count > 1, "got %u\n", count);
1202 ranges = heap_alloc(count*sizeof(DWRITE_UNICODE_RANGE));
1203 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, count, ranges, &count);
1204 ok(hr == S_OK, "got 0x%08x\n", hr);
1206 ranges[0].first = ranges[0].last = 0;
1207 hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, ranges, &count);
1208 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
1209 ok(ranges[0].first != 0 && ranges[0].last != 0, "got 0x%x-0x%0x\n", ranges[0].first, ranges[0].last);
1211 heap_free(ranges);
1213 hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
1214 ok(hr == S_OK, "got 0x%08x\n", hr);
1216 IDWriteFontFace1_Release(fontface1);
1219 static void test_GetFontFromFontFace(void)
1221 IDWriteFontFace *fontface, *fontface2;
1222 IDWriteFontCollection *collection;
1223 IDWriteFont *font, *font2, *font3;
1224 IDWriteFontFamily *family;
1225 HRESULT hr;
1227 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1228 ok(hr == S_OK, "got 0x%08x\n", hr);
1230 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1231 ok(hr == S_OK, "got 0x%08x\n", hr);
1233 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1234 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1235 ok(hr == S_OK, "got 0x%08x\n", hr);
1237 hr = IDWriteFont_CreateFontFace(font, &fontface);
1238 ok(hr == S_OK, "got 0x%08x\n", hr);
1240 font2 = NULL;
1241 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font2);
1242 todo_wine
1243 ok(hr == S_OK, "got 0x%08x\n", hr);
1244 ok(font2 != font, "got %p, %p\n", font2, font);
1246 font3 = NULL;
1247 hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font3);
1248 todo_wine {
1249 ok(hr == S_OK, "got 0x%08x\n", hr);
1250 ok(font3 != font && font3 != font2, "got %p, %p, %p\n", font3, font2, font);
1253 if (font2) {
1254 hr = IDWriteFont_CreateFontFace(font2, &fontface2);
1255 ok(hr == S_OK, "got 0x%08x\n", hr);
1256 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
1257 IDWriteFontFace_Release(fontface2);
1260 if (font3) {
1261 hr = IDWriteFont_CreateFontFace(font3, &fontface2);
1262 ok(hr == S_OK, "got 0x%08x\n", hr);
1263 ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface);
1264 IDWriteFontFace_Release(fontface2);
1267 if (font)
1268 IDWriteFont_Release(font);
1269 if (font2)
1270 IDWriteFont_Release(font2);
1271 if (font3)
1272 IDWriteFont_Release(font3);
1273 IDWriteFontFace_Release(fontface);
1274 IDWriteFontFamily_Release(family);
1275 IDWriteFontCollection_Release(collection);
1278 static void test_GetFirstMatchingFont(void)
1280 IDWriteFontCollection *collection;
1281 IDWriteFont *font, *font2;
1282 IDWriteFontFamily *family;
1283 HRESULT hr;
1285 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1286 ok(hr == S_OK, "got 0x%08x\n", hr);
1288 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1289 ok(hr == S_OK, "got 0x%08x\n", hr);
1291 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1292 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1293 ok(hr == S_OK, "got 0x%08x\n", hr);
1295 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1296 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font2);
1297 ok(hr == S_OK, "got 0x%08x\n", hr);
1298 ok(font != font2, "got %p, %p\n", font, font2);
1300 IDWriteFont_Release(font);
1301 IDWriteFont_Release(font2);
1302 IDWriteFontFamily_Release(family);
1303 IDWriteFontCollection_Release(collection);
1306 static void test_GetInformationalStrings(void)
1308 IDWriteLocalizedStrings *strings, *strings2;
1309 IDWriteFontCollection *collection;
1310 IDWriteFontFamily *family;
1311 IDWriteFont *font;
1312 BOOL exists;
1313 HRESULT hr;
1315 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
1316 ok(hr == S_OK, "got 0x%08x\n", hr);
1318 hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
1319 ok(hr == S_OK, "got 0x%08x\n", hr);
1321 hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
1322 DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
1323 ok(hr == S_OK, "got 0x%08x\n", hr);
1325 exists = TRUE;
1326 strings = (void*)0xdeadbeef;
1327 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1, &strings, &exists);
1328 todo_wine {
1329 ok(hr == S_OK, "got 0x%08x\n", hr);
1330 ok(exists == FALSE, "got %d\n", exists);
1331 ok(strings == NULL, "got %p\n", strings);
1333 exists = FALSE;
1334 strings = NULL;
1335 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists);
1336 todo_wine {
1337 ok(hr == S_OK, "got 0x%08x\n", hr);
1338 ok(exists == TRUE, "got %d\n", exists);
1341 exists = TRUE;
1342 strings = NULL;
1343 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_NONE, &strings, &exists);
1344 todo_wine {
1345 ok(hr == S_OK, "got 0x%08x\n", hr);
1346 ok(exists == FALSE, "got %d\n", exists);
1349 /* strings instance is not reused */
1350 strings2 = NULL;
1351 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings2, &exists);
1352 todo_wine {
1353 ok(hr == S_OK, "got 0x%08x\n", hr);
1354 ok(strings2 != strings, "got %p, %p\n", strings2, strings);
1357 if (strings)
1358 IDWriteLocalizedStrings_Release(strings);
1359 if (strings2)
1360 IDWriteLocalizedStrings_Release(strings2);
1361 IDWriteFont_Release(font);
1362 IDWriteFontFamily_Release(family);
1363 IDWriteFontCollection_Release(collection);
1366 static void test_GetGdiInterop(void)
1368 IDWriteGdiInterop *interop, *interop2;
1369 IDWriteFactory *factory2;
1370 IDWriteFont *font;
1371 LOGFONTW logfont;
1372 HRESULT hr;
1374 interop = NULL;
1375 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1376 ok(hr == S_OK, "got 0x%08x\n", hr);
1378 interop2 = NULL;
1379 hr = IDWriteFactory_GetGdiInterop(factory, &interop2);
1380 ok(hr == S_OK, "got 0x%08x\n", hr);
1381 ok(interop == interop2, "got %p, %p\n", interop, interop2);
1382 IDWriteGdiInterop_Release(interop2);
1384 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory2);
1385 ok(hr == S_OK, "got 0x%08x\n", hr);
1387 /* each factory gets its own interop */
1388 interop2 = NULL;
1389 hr = IDWriteFactory_GetGdiInterop(factory2, &interop2);
1390 ok(hr == S_OK, "got 0x%08x\n", hr);
1391 ok(interop != interop2, "got %p, %p\n", interop, interop2);
1393 /* release factory - interop still works */
1394 IDWriteFactory_Release(factory2);
1396 memset(&logfont, 0, sizeof(logfont));
1397 logfont.lfHeight = 12;
1398 logfont.lfWidth = 12;
1399 logfont.lfWeight = FW_NORMAL;
1400 logfont.lfItalic = 1;
1401 lstrcpyW(logfont.lfFaceName, tahomaW);
1403 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop2, &logfont, &font);
1404 ok(hr == S_OK, "got 0x%08x\n", hr);
1406 IDWriteGdiInterop_Release(interop2);
1407 IDWriteGdiInterop_Release(interop);
1410 static void test_CreateFontFaceFromHdc(void)
1412 IDWriteGdiInterop *interop;
1413 IDWriteFontFace *fontface;
1414 HFONT hfont, oldhfont;
1415 LOGFONTW logfont;
1416 HRESULT hr;
1417 HDC hdc;
1419 interop = NULL;
1420 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
1421 ok(hr == S_OK, "got 0x%08x\n", hr);
1423 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, NULL, &fontface);
1424 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1426 memset(&logfont, 0, sizeof(logfont));
1427 logfont.lfHeight = 12;
1428 logfont.lfWidth = 12;
1429 logfont.lfWeight = FW_NORMAL;
1430 logfont.lfItalic = 1;
1431 lstrcpyW(logfont.lfFaceName, tahomaW);
1433 hfont = CreateFontIndirectW(&logfont);
1434 hdc = CreateCompatibleDC(0);
1435 oldhfont = SelectObject(hdc, hfont);
1437 fontface = NULL;
1438 hr = IDWriteGdiInterop_CreateFontFaceFromHdc(interop, hdc, &fontface);
1439 ok(hr == S_OK, "got 0x%08x\n", hr);
1440 IDWriteFontFace_Release(fontface);
1441 DeleteObject(SelectObject(hdc, oldhfont));
1442 DeleteDC(hdc);
1444 IDWriteGdiInterop_Release(interop);
1447 START_TEST(font)
1449 HRESULT hr;
1451 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
1452 ok(hr == S_OK, "got 0x%08x\n", hr);
1453 if (hr != S_OK)
1455 win_skip("failed to create factory\n");
1456 return;
1459 test_CreateFontFromLOGFONT();
1460 test_CreateBitmapRenderTarget();
1461 test_GetFontFamily();
1462 test_GetFamilyNames();
1463 test_CreateFontFace();
1464 test_GetMetrics();
1465 test_system_fontcollection();
1466 test_ConvertFontFaceToLOGFONT();
1467 test_CustomFontCollection();
1468 test_FontLoader();
1469 test_CreateFontFileReference();
1470 test_shared_isolated();
1471 test_GetUnicodeRanges();
1472 test_GetFontFromFontFace();
1473 test_GetFirstMatchingFont();
1474 test_GetInformationalStrings();
1475 test_GetGdiInterop();
1476 test_CreateFontFaceFromHdc();
1478 IDWriteFactory_Release(factory);