dwrite: Implement GetWeight() for IDWriteFont.
[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
25 #include "initguid.h"
26 #include "dwrite.h"
27
28 #include "wine/test.h"
29
30 #define EXPECT_HR(hr,hr_exp) \
31     ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
32
33 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
34 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
35 {
36     ULONG rc = IUnknown_AddRef(obj);
37     IUnknown_Release(obj);
38     ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1);
39 }
40
41 static IDWriteFactory *factory;
42
43 static void test_CreateFontFromLOGFONT(void)
44 {
45     static const WCHAR arialW[] = {'A','r','i','a','l',0};
46     static const WCHAR arialspW[] = {'A','r','i','a','l',' ',0};
47     static const WCHAR blahW[]  = {'B','l','a','h','!',0};
48     IDWriteGdiInterop *interop;
49     DWRITE_FONT_WEIGHT weight;
50     DWRITE_FONT_STYLE style;
51     IDWriteFont *font;
52     LOGFONTW logfont;
53     LONG weights[][2] = {
54         {FW_NORMAL, DWRITE_FONT_WEIGHT_NORMAL},
55         {FW_BOLD, DWRITE_FONT_WEIGHT_BOLD},
56         {  0, DWRITE_FONT_WEIGHT_NORMAL},
57         { 50, DWRITE_FONT_WEIGHT_NORMAL},
58         {150, DWRITE_FONT_WEIGHT_NORMAL},
59         {250, DWRITE_FONT_WEIGHT_NORMAL},
60         {350, DWRITE_FONT_WEIGHT_NORMAL},
61         {450, DWRITE_FONT_WEIGHT_NORMAL},
62         {650, DWRITE_FONT_WEIGHT_BOLD},
63         {750, DWRITE_FONT_WEIGHT_BOLD},
64         {850, DWRITE_FONT_WEIGHT_BOLD},
65         {950, DWRITE_FONT_WEIGHT_BOLD},
66         {960, DWRITE_FONT_WEIGHT_BOLD},
67     };
68     HRESULT hr;
69     BOOL ret;
70     int i;
71
72     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
73     EXPECT_HR(hr, S_OK);
74
75 if (0)
76     /* null out parameter crashes this call */
77     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, NULL);
78
79     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, &font);
80     EXPECT_HR(hr, E_INVALIDARG);
81
82     memset(&logfont, 0, sizeof(logfont));
83     logfont.lfHeight = 12;
84     logfont.lfWidth  = 12;
85     logfont.lfWeight = FW_NORMAL;
86     logfont.lfItalic = 1;
87     lstrcpyW(logfont.lfFaceName, arialW);
88
89     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
90     EXPECT_HR(hr, S_OK);
91
92     /* now check properties */
93     weight = IDWriteFont_GetWeight(font);
94     ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
95
96     style = IDWriteFont_GetStyle(font);
97     ok(style == DWRITE_FONT_STYLE_ITALIC, "got %d\n", style);
98
99     ret = IDWriteFont_IsSymbolFont(font);
100     ok(!ret, "got %d\n", ret);
101
102     IDWriteFont_Release(font);
103
104     /* weight values */
105     for (i = 0; i < sizeof(weights)/(2*sizeof(LONG)); i++)
106     {
107         memset(&logfont, 0, sizeof(logfont));
108         logfont.lfHeight = 12;
109         logfont.lfWidth  = 12;
110         logfont.lfWeight = weights[i][0];
111         lstrcpyW(logfont.lfFaceName, arialW);
112
113         hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
114         EXPECT_HR(hr, S_OK);
115
116         weight = IDWriteFont_GetWeight(font);
117         ok(weight == weights[i][1],
118             "%d: got %d, expected %d\n", i, weight, weights[i][1]);
119         IDWriteFont_Release(font);
120     }
121
122     /* weight not from enum */
123     memset(&logfont, 0, sizeof(logfont));
124     logfont.lfHeight = 12;
125     logfont.lfWidth  = 12;
126     logfont.lfWeight = 550;
127     lstrcpyW(logfont.lfFaceName, arialW);
128
129     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
130     EXPECT_HR(hr, S_OK);
131
132     weight = IDWriteFont_GetWeight(font);
133     ok(weight == DWRITE_FONT_WEIGHT_NORMAL || broken(weight == DWRITE_FONT_WEIGHT_BOLD) /* win7 w/o SP */,
134         "got %d\n", weight);
135     IDWriteFont_Release(font);
136
137     /* empty or nonexistent face name */
138     memset(&logfont, 0, sizeof(logfont));
139     logfont.lfHeight = 12;
140     logfont.lfWidth  = 12;
141     logfont.lfWeight = FW_NORMAL;
142     lstrcpyW(logfont.lfFaceName, blahW);
143
144     font = (void*)0xdeadbeef;
145     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
146 todo_wine {
147     EXPECT_HR(hr, DWRITE_E_NOFONT);
148     ok(font == NULL, "got %p\n", font);
149     if(font) IDWriteFont_Release(font);
150 }
151
152     memset(&logfont, 0, sizeof(logfont));
153     logfont.lfHeight = 12;
154     logfont.lfWidth  = 12;
155     logfont.lfWeight = FW_NORMAL;
156     lstrcpyW(logfont.lfFaceName, arialspW);
157
158     font = (void*)0xdeadbeef;
159     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
160 todo_wine {
161     EXPECT_HR(hr, DWRITE_E_NOFONT);
162     ok(font == NULL, "got %p\n", font);
163     if(font) IDWriteFont_Release(font);
164 }
165
166     memset(&logfont, 0, sizeof(logfont));
167     logfont.lfHeight = 12;
168     logfont.lfWidth  = 12;
169     logfont.lfWeight = FW_NORMAL;
170
171     font = (void*)0xdeadbeef;
172     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
173 todo_wine {
174     EXPECT_HR(hr, DWRITE_E_NOFONT);
175     ok(font == NULL, "got %p\n", font);
176     if(font) IDWriteFont_Release(font);
177 }
178
179     IDWriteGdiInterop_Release(interop);
180 }
181
182 static void test_CreateBitmapRenderTarget(void)
183 {
184     IDWriteBitmapRenderTarget *target, *target2;
185     IDWriteGdiInterop *interop;
186     DIBSECTION ds;
187     HBITMAP hbm;
188     HRESULT hr;
189     SIZE size;
190     HDC hdc;
191     int ret;
192
193     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
194     EXPECT_HR(hr, S_OK);
195
196     target = NULL;
197     hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target);
198     EXPECT_HR(hr, S_OK);
199
200 if (0) /* crashes on native */
201     hr = IDWriteBitmapRenderTarget_GetSize(target, NULL);
202
203     size.cx = size.cy = -1;
204     hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
205     EXPECT_HR(hr, S_OK);
206     ok(size.cx == 0, "got %d\n", size.cx);
207     ok(size.cy == 0, "got %d\n", size.cy);
208
209     target2 = NULL;
210     hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target2);
211     EXPECT_HR(hr, S_OK);
212     ok(target != target2, "got %p, %p\n", target2, target);
213     IDWriteBitmapRenderTarget_Release(target2);
214
215     hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
216     ok(hdc != NULL, "got %p\n", hdc);
217
218     hbm = GetCurrentObject(hdc, OBJ_BITMAP);
219     ok(hbm != NULL, "got %p\n", hbm);
220
221     /* check DIB properties */
222     ret = GetObjectW(hbm, sizeof(ds), &ds);
223     ok(ret == sizeof(BITMAP), "got %d\n", ret);
224     ok(ds.dsBm.bmWidth == 1, "got %d\n", ds.dsBm.bmWidth);
225     ok(ds.dsBm.bmHeight == 1, "got %d\n", ds.dsBm.bmHeight);
226     ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
227     ok(ds.dsBm.bmBitsPixel == 1, "got %d\n", ds.dsBm.bmBitsPixel);
228     ok(!ds.dsBm.bmBits, "got %p\n", ds.dsBm.bmBits);
229
230     IDWriteBitmapRenderTarget_Release(target);
231
232     hbm = GetCurrentObject(hdc, OBJ_BITMAP);
233     ok(!hbm, "got %p\n", hbm);
234
235     target = NULL;
236     hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 10, 5, &target);
237     EXPECT_HR(hr, S_OK);
238
239     hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
240     ok(hdc != NULL, "got %p\n", hdc);
241
242     hbm = GetCurrentObject(hdc, OBJ_BITMAP);
243     ok(hbm != NULL, "got %p\n", hbm);
244
245     /* check DIB properties */
246     ret = GetObjectW(hbm, sizeof(ds), &ds);
247     ok(ret == sizeof(ds), "got %d\n", ret);
248     ok(ds.dsBm.bmWidth == 10, "got %d\n", ds.dsBm.bmWidth);
249     ok(ds.dsBm.bmHeight == 5, "got %d\n", ds.dsBm.bmHeight);
250     ok(ds.dsBm.bmPlanes == 1, "got %d\n", ds.dsBm.bmPlanes);
251     ok(ds.dsBm.bmBitsPixel == 32, "got %d\n", ds.dsBm.bmBitsPixel);
252     ok(ds.dsBm.bmBits != NULL, "got %p\n", ds.dsBm.bmBits);
253
254     size.cx = size.cy = -1;
255     hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
256     EXPECT_HR(hr, S_OK);
257     ok(size.cx == 10, "got %d\n", size.cx);
258     ok(size.cy == 5, "got %d\n", size.cy);
259
260     IDWriteBitmapRenderTarget_Release(target);
261
262     IDWriteGdiInterop_Release(interop);
263 }
264
265 static void test_GetFontFamily(void)
266 {
267     static const WCHAR arialW[] = {'A','r','i','a','l',0};
268     IDWriteFontFamily *family, *family2;
269     IDWriteGdiInterop *interop;
270     IDWriteFont *font;
271     LOGFONTW logfont;
272     HRESULT hr;
273
274     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
275     EXPECT_HR(hr, S_OK);
276
277     memset(&logfont, 0, sizeof(logfont));
278     logfont.lfHeight = 12;
279     logfont.lfWidth  = 12;
280     logfont.lfWeight = FW_NORMAL;
281     logfont.lfItalic = 1;
282     lstrcpyW(logfont.lfFaceName, arialW);
283
284     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
285     EXPECT_HR(hr, S_OK);
286
287 if (0) /* crashes on native */
288     hr = IDWriteFont_GetFontFamily(font, NULL);
289
290     EXPECT_REF(font, 1);
291     hr = IDWriteFont_GetFontFamily(font, &family);
292     EXPECT_HR(hr, S_OK);
293     EXPECT_REF(font, 1);
294     EXPECT_REF(family, 2);
295
296     hr = IDWriteFont_GetFontFamily(font, &family2);
297     EXPECT_HR(hr, S_OK);
298     ok(family2 == family, "got %p, previous %p\n", family2, family);
299     EXPECT_REF(font, 1);
300     EXPECT_REF(family, 3);
301     IDWriteFontFamily_Release(family2);
302
303     hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFamily, (void**)&family2);
304     EXPECT_HR(hr, E_NOINTERFACE);
305     ok(family2 == NULL, "got %p\n", family2);
306
307     IDWriteFontFamily_Release(family);
308     IDWriteFont_Release(font);
309     IDWriteGdiInterop_Release(interop);
310 }
311
312 static void test_GetFamilyNames(void)
313 {
314     static const WCHAR arialW[] = {'A','r','i','a','l',0};
315     IDWriteFontFamily *family;
316     IDWriteLocalizedStrings *names, *names2;
317     IDWriteGdiInterop *interop;
318     IDWriteFont *font;
319     LOGFONTW logfont;
320     WCHAR buffer[100];
321     HRESULT hr;
322     UINT32 len;
323
324     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
325     EXPECT_HR(hr, S_OK);
326
327     memset(&logfont, 0, sizeof(logfont));
328     logfont.lfHeight = 12;
329     logfont.lfWidth  = 12;
330     logfont.lfWeight = FW_NORMAL;
331     logfont.lfItalic = 1;
332     lstrcpyW(logfont.lfFaceName, arialW);
333
334     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
335     EXPECT_HR(hr, S_OK);
336
337     hr = IDWriteFont_GetFontFamily(font, &family);
338     EXPECT_HR(hr, S_OK);
339
340 if (0) /* crashes on native */
341     hr = IDWriteFontFamily_GetFamilyNames(family, NULL);
342
343     hr = IDWriteFontFamily_GetFamilyNames(family, &names);
344     ok(hr == S_OK, "got 0x%08x\n", hr);
345     EXPECT_REF(names, 1);
346
347     hr = IDWriteFontFamily_GetFamilyNames(family, &names2);
348     ok(hr == S_OK, "got 0x%08x\n", hr);
349     EXPECT_REF(names2, 1);
350     ok(names != names2, "got %p, was %p\n", names2, names);
351
352     IDWriteLocalizedStrings_Release(names2);
353
354     /* GetStringLength */
355 if (0) /* crashes on native */
356     hr = IDWriteLocalizedStrings_GetStringLength(names, 0, NULL);
357
358     len = 100;
359     hr = IDWriteLocalizedStrings_GetStringLength(names, 10, &len);
360     ok(hr == E_FAIL, "got 0x%08x\n", hr);
361     ok(len == (UINT32)-1, "got %u\n", len);
362
363     len = 0;
364     hr = IDWriteLocalizedStrings_GetStringLength(names, 0, &len);
365     ok(hr == S_OK, "got 0x%08x\n", hr);
366     ok(len > 0, "got %u\n", len);
367
368     /* GetString */
369     hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 0);
370     ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
371
372     hr = IDWriteLocalizedStrings_GetString(names, 10, NULL, 0);
373     ok(hr == E_FAIL, "got 0x%08x\n", hr);
374
375 if (0)
376     hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 100);
377
378     buffer[0] = 1;
379     hr = IDWriteLocalizedStrings_GetString(names, 10, buffer, 100);
380     ok(hr == E_FAIL, "got 0x%08x\n", hr);
381     ok(buffer[0] == 0, "got %x\n", buffer[0]);
382
383     buffer[0] = 1;
384     hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len-1);
385     ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
386     ok(buffer[0] == 0, "got %x\n", buffer[0]);
387
388     buffer[0] = 1;
389     hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len);
390     ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
391     ok(buffer[0] == 0, "got %x\n", buffer[0]);
392
393     buffer[0] = 0;
394     hr = IDWriteLocalizedStrings_GetString(names, 0, buffer, len+1);
395     ok(hr == S_OK, "got 0x%08x\n", hr);
396     ok(buffer[0] != 0, "got %x\n", buffer[0]);
397
398     IDWriteLocalizedStrings_Release(names);
399
400     IDWriteFontFamily_Release(family);
401     IDWriteFont_Release(font);
402     IDWriteGdiInterop_Release(interop);
403 }
404
405 static void test_CreateFontFace(void)
406 {
407     static const WCHAR arialW[] = {'A','r','i','a','l',0};
408     IDWriteFontFace *fontface, *fontface2;
409     IDWriteGdiInterop *interop;
410     IDWriteFont *font;
411     LOGFONTW logfont;
412     HRESULT hr;
413
414     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
415     EXPECT_HR(hr, S_OK);
416
417     memset(&logfont, 0, sizeof(logfont));
418     logfont.lfHeight = 12;
419     logfont.lfWidth  = 12;
420     logfont.lfWeight = FW_NORMAL;
421     logfont.lfItalic = 1;
422     lstrcpyW(logfont.lfFaceName, arialW);
423
424     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
425     ok(hr == S_OK, "got 0x%08x\n", hr);
426
427     hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface);
428     ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
429
430 if (0) /* crashes on native */
431     hr = IDWriteFont_CreateFontFace(font, NULL);
432
433     hr = IDWriteFont_CreateFontFace(font, &fontface);
434     ok(hr == S_OK, "got 0x%08x\n", hr);
435     EXPECT_REF(font, 1);
436     EXPECT_REF(fontface, 1);
437
438     hr = IDWriteFont_CreateFontFace(font, &fontface2);
439     ok(hr == S_OK, "got 0x%08x\n", hr);
440     ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface);
441     EXPECT_REF(fontface, 2);
442     EXPECT_REF(font, 1);
443
444     IDWriteFontFace_AddRef(fontface);
445     EXPECT_REF(font, 1);
446     EXPECT_REF(fontface, 3);
447     IDWriteFontFace_Release(fontface);
448     IDWriteFontFace_Release(fontface);
449
450     IDWriteFontFace_Release(fontface);
451     IDWriteFont_Release(font);
452     IDWriteGdiInterop_Release(interop);
453 }
454
455 START_TEST(font)
456 {
457     HRESULT hr;
458
459     hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
460     ok(hr == S_OK, "got 0x%08x\n", hr);
461     if (hr != S_OK)
462     {
463         win_skip("failed to create factory\n");
464         return;
465     }
466
467     test_CreateFontFromLOGFONT();
468     test_CreateBitmapRenderTarget();
469     test_GetFontFamily();
470     test_GetFamilyNames();
471     test_CreateFontFace();
472
473     IDWriteFactory_Release(factory);
474 }