Release 1.5.29.
[wine] / dlls / dwrite / tests / font.c
1 /*
2  *    Font related tests
3  *
4  * Copyright 2012 Nikolay Sivov for CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #define COBJMACROS
22
23 #include "windows.h"
24 #include "dwrite.h"
25
26 #include "wine/test.h"
27
28 #define EXPECT_HR(hr,hr_exp) \
29     ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
30
31 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
32 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
33 {
34     ULONG rc = IUnknown_AddRef(obj);
35     IUnknown_Release(obj);
36     ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1);
37 }
38
39 static IDWriteFactory *factory;
40
41 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
42 static const WCHAR blahW[]  = {'B','l','a','h','!',0};
43
44 static void test_CreateFontFromLOGFONT(void)
45 {
46     static const WCHAR tahomaspW[] = {'T','a','h','o','m','a',' ',0};
47     IDWriteGdiInterop *interop;
48     DWRITE_FONT_WEIGHT weight;
49     DWRITE_FONT_STYLE style;
50     IDWriteFont *font;
51     LOGFONTW logfont;
52     LONG weights[][2] = {
53         {FW_NORMAL, DWRITE_FONT_WEIGHT_NORMAL},
54         {FW_BOLD, DWRITE_FONT_WEIGHT_BOLD},
55         {  0, DWRITE_FONT_WEIGHT_NORMAL},
56         { 50, DWRITE_FONT_WEIGHT_NORMAL},
57         {150, DWRITE_FONT_WEIGHT_NORMAL},
58         {250, DWRITE_FONT_WEIGHT_NORMAL},
59         {350, DWRITE_FONT_WEIGHT_NORMAL},
60         {450, DWRITE_FONT_WEIGHT_NORMAL},
61         {650, DWRITE_FONT_WEIGHT_BOLD},
62         {750, DWRITE_FONT_WEIGHT_BOLD},
63         {850, DWRITE_FONT_WEIGHT_BOLD},
64         {950, DWRITE_FONT_WEIGHT_BOLD},
65         {960, DWRITE_FONT_WEIGHT_BOLD},
66     };
67     OUTLINETEXTMETRICW otm;
68     HRESULT hr;
69     BOOL ret;
70     HDC hdc;
71     HFONT hfont;
72     int i;
73     UINT r;
74
75     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
76     EXPECT_HR(hr, S_OK);
77
78 if (0)
79     /* null out parameter crashes this call */
80     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, NULL);
81
82     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, &font);
83     EXPECT_HR(hr, E_INVALIDARG);
84
85     memset(&logfont, 0, sizeof(logfont));
86     logfont.lfHeight = 12;
87     logfont.lfWidth  = 12;
88     logfont.lfWeight = FW_NORMAL;
89     logfont.lfItalic = 1;
90     lstrcpyW(logfont.lfFaceName, tahomaW);
91
92     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
93     EXPECT_HR(hr, S_OK);
94
95     hfont = CreateFontIndirectW(&logfont);
96     hdc = CreateCompatibleDC(0);
97     SelectObject(hdc, hfont);
98
99     otm.otmSize = sizeof(otm);
100     r = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
101     ok(r, "got %d\n", r);
102     DeleteDC(hdc);
103     DeleteObject(hfont);
104
105     /* now check properties */
106     weight = IDWriteFont_GetWeight(font);
107     ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
108
109     style = IDWriteFont_GetStyle(font);
110 todo_wine {
111     ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
112     ok(otm.otmfsSelection == 1, "got 0x%08x\n", otm.otmfsSelection);
113 }
114     ret = IDWriteFont_IsSymbolFont(font);
115     ok(!ret, "got %d\n", ret);
116
117     IDWriteFont_Release(font);
118
119     /* weight values */
120     for (i = 0; i < sizeof(weights)/(2*sizeof(LONG)); i++)
121     {
122         memset(&logfont, 0, sizeof(logfont));
123         logfont.lfHeight = 12;
124         logfont.lfWidth  = 12;
125         logfont.lfWeight = weights[i][0];
126         lstrcpyW(logfont.lfFaceName, tahomaW);
127
128         hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
129         EXPECT_HR(hr, S_OK);
130
131         weight = IDWriteFont_GetWeight(font);
132         ok(weight == weights[i][1],
133             "%d: got %d, expected %d\n", i, weight, weights[i][1]);
134         IDWriteFont_Release(font);
135     }
136
137     /* weight not from enum */
138     memset(&logfont, 0, sizeof(logfont));
139     logfont.lfHeight = 12;
140     logfont.lfWidth  = 12;
141     logfont.lfWeight = 550;
142     lstrcpyW(logfont.lfFaceName, tahomaW);
143
144     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
145     EXPECT_HR(hr, S_OK);
146
147     weight = IDWriteFont_GetWeight(font);
148     ok(weight == DWRITE_FONT_WEIGHT_NORMAL || broken(weight == DWRITE_FONT_WEIGHT_BOLD) /* win7 w/o SP */,
149         "got %d\n", weight);
150     IDWriteFont_Release(font);
151
152     /* empty or nonexistent face name */
153     memset(&logfont, 0, sizeof(logfont));
154     logfont.lfHeight = 12;
155     logfont.lfWidth  = 12;
156     logfont.lfWeight = FW_NORMAL;
157     lstrcpyW(logfont.lfFaceName, blahW);
158
159     font = (void*)0xdeadbeef;
160     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
161 todo_wine {
162     EXPECT_HR(hr, DWRITE_E_NOFONT);
163     ok(font == NULL, "got %p\n", font);
164     if(font) IDWriteFont_Release(font);
165 }
166
167     memset(&logfont, 0, sizeof(logfont));
168     logfont.lfHeight = 12;
169     logfont.lfWidth  = 12;
170     logfont.lfWeight = FW_NORMAL;
171     lstrcpyW(logfont.lfFaceName, tahomaspW);
172
173     font = (void*)0xdeadbeef;
174     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
175 todo_wine {
176     EXPECT_HR(hr, DWRITE_E_NOFONT);
177     ok(font == NULL, "got %p\n", font);
178     if(font) IDWriteFont_Release(font);
179 }
180
181     memset(&logfont, 0, sizeof(logfont));
182     logfont.lfHeight = 12;
183     logfont.lfWidth  = 12;
184     logfont.lfWeight = FW_NORMAL;
185
186     font = (void*)0xdeadbeef;
187     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
188 todo_wine {
189     EXPECT_HR(hr, DWRITE_E_NOFONT);
190     ok(font == NULL, "got %p\n", font);
191     if(font) IDWriteFont_Release(font);
192 }
193
194     IDWriteGdiInterop_Release(interop);
195 }
196
197 static void test_CreateBitmapRenderTarget(void)
198 {
199     IDWriteBitmapRenderTarget *target, *target2;
200     IDWriteGdiInterop *interop;
201     DIBSECTION ds;
202     HBITMAP hbm;
203     HRESULT hr;
204     SIZE size;
205     HDC hdc;
206     int ret;
207
208     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
209     EXPECT_HR(hr, S_OK);
210
211     target = NULL;
212     hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target);
213     EXPECT_HR(hr, S_OK);
214
215 if (0) /* crashes on native */
216     hr = IDWriteBitmapRenderTarget_GetSize(target, NULL);
217
218     size.cx = size.cy = -1;
219     hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
220     EXPECT_HR(hr, S_OK);
221     ok(size.cx == 0, "got %d\n", size.cx);
222     ok(size.cy == 0, "got %d\n", size.cy);
223
224     target2 = NULL;
225     hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target2);
226     EXPECT_HR(hr, S_OK);
227     ok(target != target2, "got %p, %p\n", target2, target);
228     IDWriteBitmapRenderTarget_Release(target2);
229
230     hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
231     ok(hdc != NULL, "got %p\n", hdc);
232
233     hbm = GetCurrentObject(hdc, OBJ_BITMAP);
234     ok(hbm != NULL, "got %p\n", hbm);
235
236     /* check DIB properties */
237     ret = GetObjectW(hbm, sizeof(ds), &ds);
238     ok(ret == sizeof(BITMAP), "got %d\n", ret);
239     ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
240     ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
241     ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
242     ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
243     ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
244
245     IDWriteBitmapRenderTarget_Release(target);
246
247     hbm = GetCurrentObject(hdc, OBJ_BITMAP);
248     ok(!hbm, "got %p\n", hbm);
249
250     target = NULL;
251     hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 10, 5, &target);
252     EXPECT_HR(hr, S_OK);
253
254     hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
255     ok(hdc != NULL, "got %p\n", hdc);
256
257     hbm = GetCurrentObject(hdc, OBJ_BITMAP);
258     ok(hbm != NULL, "got %p\n", hbm);
259
260     /* check DIB properties */
261     ret = GetObjectW(hbm, sizeof(ds), &ds);
262     ok(ret == sizeof(ds), "got %d\n", ret);
263     ok(ds.dsBm.bmWidth == 10, "got %d\n", ds.dsBm.bmWidth);
264     ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
265     ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
266     ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
267     ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
268
269     size.cx = size.cy = -1;
270     hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
271     EXPECT_HR(hr, S_OK);
272     ok(size.cx == 10, "got %d\n", size.cx);
273     ok(size.cy == 5, "got %d\n", size.cy);
274
275     IDWriteBitmapRenderTarget_Release(target);
276
277     IDWriteGdiInterop_Release(interop);
278 }
279
280 static void test_GetFontFamily(void)
281 {
282     IDWriteFontFamily *family, *family2;
283     IDWriteGdiInterop *interop;
284     IDWriteFont *font;
285     LOGFONTW logfont;
286     HRESULT hr;
287
288     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
289     EXPECT_HR(hr, S_OK);
290
291     memset(&logfont, 0, sizeof(logfont));
292     logfont.lfHeight = 12;
293     logfont.lfWidth  = 12;
294     logfont.lfWeight = FW_NORMAL;
295     logfont.lfItalic = 1;
296     lstrcpyW(logfont.lfFaceName, tahomaW);
297
298     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
299     EXPECT_HR(hr, S_OK);
300
301 if (0) /* crashes on native */
302     hr = IDWriteFont_GetFontFamily(font, NULL);
303
304     EXPECT_REF(font, 1);
305     hr = IDWriteFont_GetFontFamily(font, &family);
306     EXPECT_HR(hr, S_OK);
307     EXPECT_REF(font, 1);
308     EXPECT_REF(family, 2);
309
310     hr = IDWriteFont_GetFontFamily(font, &family2);
311     EXPECT_HR(hr, S_OK);
312     ok(family2 == family, "got %p, previous %p\n", family2, family);
313     EXPECT_REF(font, 1);
314     EXPECT_REF(family, 3);
315     IDWriteFontFamily_Release(family2);
316
317     hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFamily, (void**)&family2);
318     EXPECT_HR(hr, E_NOINTERFACE);
319     ok(family2 == NULL, "got %p\n", family2);
320
321     IDWriteFontFamily_Release(family);
322     IDWriteFont_Release(font);
323     IDWriteGdiInterop_Release(interop);
324 }
325
326 static void test_GetFamilyNames(void)
327 {
328     IDWriteFontFamily *family;
329     IDWriteLocalizedStrings *names, *names2;
330     IDWriteGdiInterop *interop;
331     IDWriteFont *font;
332     LOGFONTW logfont;
333     WCHAR buffer[100];
334     HRESULT hr;
335     UINT32 len;
336
337     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
338     EXPECT_HR(hr, S_OK);
339
340     memset(&logfont, 0, sizeof(logfont));
341     logfont.lfHeight = 12;
342     logfont.lfWidth  = 12;
343     logfont.lfWeight = FW_NORMAL;
344     logfont.lfItalic = 1;
345     lstrcpyW(logfont.lfFaceName, tahomaW);
346
347     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
348     EXPECT_HR(hr, S_OK);
349
350     hr = IDWriteFont_GetFontFamily(font, &family);
351     EXPECT_HR(hr, S_OK);
352
353 if (0) /* crashes on native */
354     hr = IDWriteFontFamily_GetFamilyNames(family, NULL);
355
356     hr = IDWriteFontFamily_GetFamilyNames(family, &names);
357     ok(hr == S_OK, "got 0x%08x\n", hr);
358     EXPECT_REF(names, 1);
359
360     hr = IDWriteFontFamily_GetFamilyNames(family, &names2);
361     ok(hr == S_OK, "got 0x%08x\n", hr);
362     EXPECT_REF(names2, 1);
363     ok(names != names2, "got %p, was %p\n", names2, names);
364
365     IDWriteLocalizedStrings_Release(names2);
366
367     /* GetStringLength */
368 if (0) /* crashes on native */
369     hr = IDWriteLocalizedStrings_GetStringLength(names, 0, NULL);
370
371     len = 100;
372     hr = IDWriteLocalizedStrings_GetStringLength(names, 10, &len);
373     ok(hr == E_FAIL, "got 0x%08x\n", hr);
374     ok(len == (UINT32)-1, "got %u\n", len);
375
376     len = 0;
377     hr = IDWriteLocalizedStrings_GetStringLength(names, 0, &len);
378     ok(hr == S_OK, "got 0x%08x\n", hr);
379     ok(len > 0, "got %u\n", len);
380
381     /* GetString */
382     hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 0);
383     ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
384
385     hr = IDWriteLocalizedStrings_GetString(names, 10, NULL, 0);
386     ok(hr == E_FAIL, "got 0x%08x\n", hr);
387
388 if (0)
389     hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 100);
390
391     buffer[0] = 1;
392     hr = IDWriteLocalizedStrings_GetString(names, 10, buffer, 100);
393     ok(hr == E_FAIL, "got 0x%08x\n", hr);
394     ok(buffer[0] == 0, "got %x\n", buffer[0]);
395
396     buffer[0] = 1;
397     hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len-1);
398     ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
399     ok(buffer[0] == 0, "got %x\n", buffer[0]);
400
401     buffer[0] = 1;
402     hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len);
403     ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
404     ok(buffer[0] == 0, "got %x\n", buffer[0]);
405
406     buffer[0] = 0;
407     hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len+1);
408     ok(hr == S_OK, "got 0x%08x\n", hr);
409     ok(buffer[0] != 0, "got %x\n", buffer[0]);
410
411     IDWriteLocalizedStrings_Release(names);
412
413     IDWriteFontFamily_Release(family);
414     IDWriteFont_Release(font);
415     IDWriteGdiInterop_Release(interop);
416 }
417
418 static void test_CreateFontFace(void)
419 {
420     IDWriteFontFace *fontface, *fontface2;
421     IDWriteGdiInterop *interop;
422     IDWriteFont *font;
423     LOGFONTW logfont;
424     HRESULT hr;
425
426     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
427     EXPECT_HR(hr, S_OK);
428
429     memset(&logfont, 0, sizeof(logfont));
430     logfont.lfHeight = 12;
431     logfont.lfWidth  = 12;
432     logfont.lfWeight = FW_NORMAL;
433     logfont.lfItalic = 1;
434     lstrcpyW(logfont.lfFaceName, tahomaW);
435
436     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
437     ok(hr == S_OK, "got 0x%08x\n", hr);
438
439     hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface);
440     ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
441
442 if (0) /* crashes on native */
443     hr = IDWriteFont_CreateFontFace(font, NULL);
444
445     hr = IDWriteFont_CreateFontFace(font, &fontface);
446     ok(hr == S_OK, "got 0x%08x\n", hr);
447     EXPECT_REF(font, 1);
448     EXPECT_REF(fontface, 2);
449
450     hr = IDWriteFont_CreateFontFace(font, &fontface2);
451     ok(hr == S_OK, "got 0x%08x\n", hr);
452     ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
453     EXPECT_REF(fontface, 3);
454     EXPECT_REF(font, 1);
455
456     IDWriteFontFace_AddRef(fontface);
457     EXPECT_REF(font, 1);
458     EXPECT_REF(fontface, 4);
459     IDWriteFontFace_Release(fontface);
460     IDWriteFontFace_Release(fontface);
461
462     IDWriteFontFace_Release(fontface);
463     IDWriteFont_Release(font);
464     IDWriteGdiInterop_Release(interop);
465 }
466
467 static void test_GetMetrics(void)
468 {
469     IDWriteGdiInterop *interop;
470     DWRITE_FONT_METRICS metrics;
471     OUTLINETEXTMETRICW otm;
472     IDWriteFont *font;
473     LOGFONTW logfont;
474     HRESULT hr;
475     HDC hdc;
476     HFONT hfont;
477     int ret;
478
479     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
480     EXPECT_HR(hr, S_OK);
481
482     memset(&logfont, 0, sizeof(logfont));
483     logfont.lfHeight = 12;
484     logfont.lfWidth  = 12;
485     logfont.lfWeight = FW_NORMAL;
486     logfont.lfItalic = 1;
487     lstrcpyW(logfont.lfFaceName, tahomaW);
488
489     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
490     ok(hr == S_OK, "got 0x%08x\n", hr);
491
492     hfont = CreateFontIndirectW(&logfont);
493     hdc = CreateCompatibleDC(0);
494     SelectObject(hdc, hfont);
495
496     otm.otmSize = sizeof(otm);
497     ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
498     ok(ret, "got %d\n", ret);
499     DeleteDC(hdc);
500     DeleteObject(hfont);
501
502 if (0) /* crashes on native */
503     IDWriteFont_GetMetrics(font, NULL);
504
505     memset(&metrics, 0, sizeof(metrics));
506     IDWriteFont_GetMetrics(font, &metrics);
507
508     ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
509     ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
510     ok(metrics.descent != 0, "descent %u\n", metrics.descent);
511 todo_wine
512     ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
513     ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
514     ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
515     ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
516     ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
517     ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
518     ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
519
520     IDWriteFont_Release(font);
521     IDWriteGdiInterop_Release(interop);
522 }
523
524 static void test_system_fontcollection(void)
525 {
526     IDWriteFontCollection *collection, *coll2;
527     IDWriteFontFamily *family;
528     HRESULT hr;
529     UINT32 i;
530     BOOL ret;
531
532     hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
533     ok(hr == S_OK, "got 0x%08x\n", hr);
534
535     hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, FALSE);
536     ok(hr == S_OK, "got 0x%08x\n", hr);
537     ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
538     IDWriteFontCollection_Release(coll2);
539
540     hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, TRUE);
541     ok(hr == S_OK, "got 0x%08x\n", hr);
542     ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
543     IDWriteFontCollection_Release(coll2);
544
545     i = IDWriteFontCollection_GetFontFamilyCount(collection);
546     ok(i, "got %u\n", i);
547
548     /* invalid index */
549     family = (void*)0xdeadbeef;
550     hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
551     ok(hr == E_FAIL, "got 0x%08x\n", hr);
552     ok(family == NULL, "got %p\n", family);
553
554     ret = FALSE;
555     i = (UINT32)-1;
556     hr = IDWriteFontCollection_FindFamilyName(collection, tahomaW, &i, &ret);
557     ok(hr == S_OK, "got 0x%08x\n", hr);
558     ok(ret, "got %d\n", ret);
559     ok(i != (UINT32)-1, "got %u\n", i);
560
561     ret = TRUE;
562     i = 0;
563     hr = IDWriteFontCollection_FindFamilyName(collection, blahW, &i, &ret);
564     ok(hr == S_OK, "got 0x%08x\n", hr);
565     ok(!ret, "got %d\n", ret);
566     ok(i == (UINT32)-1, "got %u\n", i);
567
568     IDWriteFontCollection_Release(collection);
569 }
570
571 START_TEST(font)
572 {
573     HRESULT hr;
574
575     hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
576     ok(hr == S_OK, "got 0x%08x\n", hr);
577     if (hr != S_OK)
578     {
579         win_skip("failed to create factory\n");
580         return;
581     }
582
583     test_CreateFontFromLOGFONT();
584     test_CreateBitmapRenderTarget();
585     test_GetFontFamily();
586     test_GetFamilyNames();
587     test_CreateFontFace();
588     test_GetMetrics();
589     test_system_fontcollection();
590
591     IDWriteFactory_Release(factory);
592 }