4 * Copyright 2012 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
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 = IUnknown_AddRef(obj);
35 IUnknown_Release(obj);
36 ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1);
39 static IDWriteFactory *factory;
41 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
42 static const WCHAR blahW[] = {'B','l','a','h','!',0};
44 static void test_CreateFontFromLOGFONT(void)
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;
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},
67 OUTLINETEXTMETRICW otm;
75 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
79 /* null out parameter crashes this call */
80 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, NULL);
82 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, NULL, &font);
83 EXPECT_HR(hr, E_INVALIDARG);
85 memset(&logfont, 0, sizeof(logfont));
86 logfont.lfHeight = 12;
88 logfont.lfWeight = FW_NORMAL;
90 lstrcpyW(logfont.lfFaceName, tahomaW);
92 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
95 hfont = CreateFontIndirectW(&logfont);
96 hdc = CreateCompatibleDC(0);
97 SelectObject(hdc, hfont);
99 otm.otmSize = sizeof(otm);
100 r = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
101 ok(r, "got %d\n", r);
105 /* now check properties */
106 weight = IDWriteFont_GetWeight(font);
107 ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
109 style = IDWriteFont_GetStyle(font);
111 ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
112 ok(otm.otmfsSelection == 1, "got 0x%08x\n", otm.otmfsSelection);
114 ret = IDWriteFont_IsSymbolFont(font);
115 ok(!ret, "got %d\n", ret);
117 IDWriteFont_Release(font);
120 for (i = 0; i < sizeof(weights)/(2*sizeof(LONG)); i++)
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);
128 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
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);
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);
144 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
147 weight = IDWriteFont_GetWeight(font);
148 ok(weight == DWRITE_FONT_WEIGHT_NORMAL || broken(weight == DWRITE_FONT_WEIGHT_BOLD) /* win7 w/o SP */,
150 IDWriteFont_Release(font);
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);
159 font = (void*)0xdeadbeef;
160 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
162 EXPECT_HR(hr, DWRITE_E_NOFONT);
163 ok(font == NULL, "got %p\n", font);
164 if(font) IDWriteFont_Release(font);
167 memset(&logfont, 0, sizeof(logfont));
168 logfont.lfHeight = 12;
169 logfont.lfWidth = 12;
170 logfont.lfWeight = FW_NORMAL;
171 lstrcpyW(logfont.lfFaceName, tahomaspW);
173 font = (void*)0xdeadbeef;
174 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
176 EXPECT_HR(hr, DWRITE_E_NOFONT);
177 ok(font == NULL, "got %p\n", font);
178 if(font) IDWriteFont_Release(font);
181 memset(&logfont, 0, sizeof(logfont));
182 logfont.lfHeight = 12;
183 logfont.lfWidth = 12;
184 logfont.lfWeight = FW_NORMAL;
186 font = (void*)0xdeadbeef;
187 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
189 EXPECT_HR(hr, DWRITE_E_NOFONT);
190 ok(font == NULL, "got %p\n", font);
191 if(font) IDWriteFont_Release(font);
194 IDWriteGdiInterop_Release(interop);
197 static void test_CreateBitmapRenderTarget(void)
199 IDWriteBitmapRenderTarget *target, *target2;
200 IDWriteGdiInterop *interop;
208 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
212 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target);
215 if (0) /* crashes on native */
216 hr = IDWriteBitmapRenderTarget_GetSize(target, NULL);
218 size.cx = size.cy = -1;
219 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
221 ok(size.cx == 0, "got %d\n", size.cx);
222 ok(size.cy == 0, "got %d\n", size.cy);
225 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 0, 0, &target2);
227 ok(target != target2, "got %p, %p\n", target2, target);
228 IDWriteBitmapRenderTarget_Release(target2);
230 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
231 ok(hdc != NULL, "got %p\n", hdc);
233 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
234 ok(hbm != NULL, "got %p\n", hbm);
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);
245 IDWriteBitmapRenderTarget_Release(target);
247 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
248 ok(!hbm, "got %p\n", hbm);
251 hr = IDWriteGdiInterop_CreateBitmapRenderTarget(interop, NULL, 10, 5, &target);
254 hdc = IDWriteBitmapRenderTarget_GetMemoryDC(target);
255 ok(hdc != NULL, "got %p\n", hdc);
257 hbm = GetCurrentObject(hdc, OBJ_BITMAP);
258 ok(hbm != NULL, "got %p\n", hbm);
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);
269 size.cx = size.cy = -1;
270 hr = IDWriteBitmapRenderTarget_GetSize(target, &size);
272 ok(size.cx == 10, "got %d\n", size.cx);
273 ok(size.cy == 5, "got %d\n", size.cy);
275 IDWriteBitmapRenderTarget_Release(target);
277 IDWriteGdiInterop_Release(interop);
280 static void test_GetFontFamily(void)
282 IDWriteFontFamily *family, *family2;
283 IDWriteGdiInterop *interop;
288 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
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);
298 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
301 if (0) /* crashes on native */
302 hr = IDWriteFont_GetFontFamily(font, NULL);
305 hr = IDWriteFont_GetFontFamily(font, &family);
308 EXPECT_REF(family, 2);
310 hr = IDWriteFont_GetFontFamily(font, &family2);
312 ok(family2 == family, "got %p, previous %p\n", family2, family);
314 EXPECT_REF(family, 3);
315 IDWriteFontFamily_Release(family2);
317 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFamily, (void**)&family2);
318 EXPECT_HR(hr, E_NOINTERFACE);
319 ok(family2 == NULL, "got %p\n", family2);
321 IDWriteFontFamily_Release(family);
322 IDWriteFont_Release(font);
323 IDWriteGdiInterop_Release(interop);
326 static void test_GetFamilyNames(void)
328 IDWriteFontFamily *family;
329 IDWriteLocalizedStrings *names, *names2;
330 IDWriteGdiInterop *interop;
337 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
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);
347 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
350 hr = IDWriteFont_GetFontFamily(font, &family);
353 if (0) /* crashes on native */
354 hr = IDWriteFontFamily_GetFamilyNames(family, NULL);
356 hr = IDWriteFontFamily_GetFamilyNames(family, &names);
357 ok(hr == S_OK, "got 0x%08x\n", hr);
358 EXPECT_REF(names, 1);
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);
365 IDWriteLocalizedStrings_Release(names2);
367 /* GetStringLength */
368 if (0) /* crashes on native */
369 hr = IDWriteLocalizedStrings_GetStringLength(names, 0, NULL);
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);
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);
382 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 0);
383 ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
385 hr = IDWriteLocalizedStrings_GetString(names, 10, NULL, 0);
386 ok(hr == E_FAIL, "got 0x%08x\n", hr);
389 hr = IDWriteLocalizedStrings_GetString(names, 0, NULL, 100);
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]);
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]);
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]);
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]);
411 IDWriteLocalizedStrings_Release(names);
413 IDWriteFontFamily_Release(family);
414 IDWriteFont_Release(font);
415 IDWriteGdiInterop_Release(interop);
418 static void test_CreateFontFace(void)
420 IDWriteFontFace *fontface, *fontface2;
421 IDWriteGdiInterop *interop;
426 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
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);
436 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
437 ok(hr == S_OK, "got 0x%08x\n", hr);
439 hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface);
440 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
442 if (0) /* crashes on native */
443 hr = IDWriteFont_CreateFontFace(font, NULL);
445 hr = IDWriteFont_CreateFontFace(font, &fontface);
446 ok(hr == S_OK, "got 0x%08x\n", hr);
448 EXPECT_REF(fontface, 2);
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);
456 IDWriteFontFace_AddRef(fontface);
458 EXPECT_REF(fontface, 4);
459 IDWriteFontFace_Release(fontface);
460 IDWriteFontFace_Release(fontface);
462 IDWriteFontFace_Release(fontface);
463 IDWriteFont_Release(font);
464 IDWriteGdiInterop_Release(interop);
467 static void test_GetMetrics(void)
469 IDWriteGdiInterop *interop;
470 DWRITE_FONT_METRICS metrics;
471 OUTLINETEXTMETRICW otm;
479 hr = IDWriteFactory_GetGdiInterop(factory, &interop);
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);
489 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
490 ok(hr == S_OK, "got 0x%08x\n", hr);
492 hfont = CreateFontIndirectW(&logfont);
493 hdc = CreateCompatibleDC(0);
494 SelectObject(hdc, hfont);
496 otm.otmSize = sizeof(otm);
497 ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
498 ok(ret, "got %d\n", ret);
502 if (0) /* crashes on native */
503 IDWriteFont_GetMetrics(font, NULL);
505 memset(&metrics, 0, sizeof(metrics));
506 IDWriteFont_GetMetrics(font, &metrics);
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);
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);
520 IDWriteFont_Release(font);
521 IDWriteGdiInterop_Release(interop);
524 static void test_system_fontcollection(void)
526 IDWriteFontCollection *collection, *coll2;
527 IDWriteFontFamily *family;
532 hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
533 ok(hr == S_OK, "got 0x%08x\n", hr);
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);
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);
545 i = IDWriteFontCollection_GetFontFamilyCount(collection);
546 ok(i, "got %u\n", i);
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);
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);
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);
568 IDWriteFontCollection_Release(collection);
575 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
576 ok(hr == S_OK, "got 0x%08x\n", hr);
579 win_skip("failed to create factory\n");
583 test_CreateFontFromLOGFONT();
584 test_CreateBitmapRenderTarget();
585 test_GetFontFamily();
586 test_GetFamilyNames();
587 test_CreateFontFace();
589 test_system_fontcollection();
591 IDWriteFactory_Release(factory);