4 * Copyright 2003 Marcus Meissner
5 * Copyright 2006 (Google) Benjamin Arai
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include <wine/test.h>
43 DEFINE_GUID(GUID_NULL
,0,0,0,0,0,0,0,0,0,0,0);
45 static WCHAR MSSansSerif_font
[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
46 static WCHAR system_font
[] = { 'S','y','s','t','e','m',0 };
47 static WCHAR arial_font
[] = { 'A','r','i','a','l',0 };
48 static WCHAR marlett_font
[] = { 'M','a','r','l','e','t','t',0 };
50 static HMODULE hOleaut32
;
52 static HRESULT (WINAPI
*pOleCreateFontIndirect
)(LPFONTDESC
,REFIID
,LPVOID
*);
54 #define EXPECT_HR(hr,hr_exp) \
55 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
57 /* Create a font with cySize given by lo_size, hi_size, */
58 /* SetRatio to ratio_logical, ratio_himetric, */
59 /* check that resulting hfont has height hfont_height. */
60 /* Various checks along the way. */
61 static void test_ifont_size(LONG lo_size
, LONG hi_size
,
62 LONG ratio_logical
, LONG ratio_himetric
,
63 LONG hfont_height
, const char * test_name
)
74 fd
.cbSizeofstruct
= sizeof(FONTDESC
);
75 fd
.lpstrName
= arial_font
; /* using scalable instead of bitmap font reduces errors due to font realization */
76 S(fd
.cySize
).Lo
= lo_size
;
77 S(fd
.cySize
).Hi
= hi_size
;
81 fd
.fUnderline
= FALSE
;
82 fd
.fStrikethrough
= FALSE
;
84 /* Create font, test that it worked. */
85 hres
= pOleCreateFontIndirect(&fd
, &IID_IFont
, &pvObj
);
87 ok(hres
== S_OK
,"%s: OCFI returns 0x%08x instead of S_OK.\n",
89 ok(pvObj
!= NULL
,"%s: OCFI returns NULL.\n", test_name
);
91 /* Change the scaling ratio */
92 hres
= IFont_SetRatio(ifnt
, ratio_logical
, ratio_himetric
);
93 ok((ratio_logical
&& ratio_himetric
) ? hres
== S_OK
: hres
== E_FAIL
,
94 "%s: IFont_SetRatio unexpectedly returned 0x%08x.\n", test_name
, hres
);
97 hres
= IFont_get_Size(ifnt
, &psize
);
98 ok(hres
== S_OK
,"%s: IFont_get_size returns 0x%08x instead of S_OK.\n",
101 /* Check returned size - allow for errors due to rounding & font realization. */
102 ok((abs(S(psize
).Lo
- lo_size
) < 10000) && S(psize
).Hi
== hi_size
,
103 "%s: IFont_get_Size: Lo=%d, Hi=%d; expected Lo=%d, Hi=%d.\n",
104 test_name
, S(psize
).Lo
, S(psize
).Hi
, lo_size
, hi_size
);
106 /* Check hFont size. */
107 hres
= IFont_get_hFont (ifnt
, &hfont
);
108 ok(hres
== S_OK
, "%s: IFont_get_hFont returns 0x%08x instead of S_OK.\n",
110 rtnval
= GetObjectA(hfont
, sizeof(LOGFONTA
), &lf
);
111 ok(rtnval
> 0, "GetObject(hfont) failed\n");
113 /* Since font scaling may encounter rounding errors, allow 1 pixel deviation. */
114 ok(abs(lf
.lfHeight
- hfont_height
) <= 1,
115 "%s: hFont has lf.lfHeight=%d, expected %d.\n",
116 test_name
, lf
.lfHeight
, hfont_height
);
122 static void test_ifont_sizes(void)
124 /* Test various size operations and conversions. */
125 /* Add more as needed. */
127 /* Results of first 2 tests depend on display resolution. */
129 LONG dpi
= GetDeviceCaps(hdc
, LOGPIXELSY
); /* expected results depend on display DPI */
131 if(dpi
== 96) /* normal resolution display */
133 test_ifont_size(180000, 0, 0, 0, -24, "default"); /* normal font */
134 test_ifont_size(186000, 0, 0, 0, -25, "rounding"); /* test rounding */
135 } else if(dpi
== 72) /* low resolution display */
137 test_ifont_size(180000, 0, 0, 0, -18, "default"); /* normal font */
138 test_ifont_size(186000, 0, 0, 0, -19, "rounding"); /* test rounding */
139 } else if(dpi
== 120) /* high resolution display */
141 test_ifont_size(180000, 0, 0, 0, -30, "default"); /* normal font */
142 test_ifont_size(186000, 0, 0, 0, -31, "rounding"); /* test rounding */
144 skip("Skipping resolution dependent font size tests - display resolution is %d\n", dpi
);
146 /* Next 4 tests specify a scaling ratio, so display resolution is not a factor. */
147 test_ifont_size(180000, 0, 72, 2540, -18, "ratio1"); /* change ratio */
148 test_ifont_size(180000, 0, 144, 2540, -36, "ratio2"); /* another ratio */
149 test_ifont_size(180000, 0, 72, 1270, -36, "ratio3"); /* yet another ratio */
150 test_ifont_size(186000, 0, 72, 2540, -19, "rounding+ratio"); /* test rounding with ratio */
152 /* test various combinations of logical == himetric */
153 test_ifont_size(180000, 0, 10, 10, -635, "identical ratio 1");
154 test_ifont_size(240000, 0, 10, 10, -848, "identical ratio 2");
155 test_ifont_size(300000, 0, 10, 10, -1058, "identical ratio 3");
157 /* test various combinations of logical and himetric both set to 1 */
158 test_ifont_size(180000, 0, 1, 1, -24, "1:1 ratio 1");
159 test_ifont_size(240000, 0, 1, 1, -32, "1:1 ratio 2");
160 test_ifont_size(300000, 0, 1, 1, -40, "1:1 ratio 3");
162 /* test various combinations of logical set to 1 */
163 test_ifont_size(180000, 0, 1, 0, -24, "1:0 ratio 1");
164 test_ifont_size(240000, 0, 1, 0, -32, "1:0 ratio 2");
165 test_ifont_size(300000, 0, 1, 0, -40, "1:0 ratio 3");
167 /* test various combinations of himetric set to 1 */
168 test_ifont_size(180000, 0, 0, 1, -24, "0:1 ratio 1");
169 test_ifont_size(240000, 0, 0, 1, -32, "0:1 ratio 2");
170 test_ifont_size(300000, 0, 0, 1, -40, "0:1 ratio 3");
172 /* test various combinations of 2:1 logical:himetric */
173 test_ifont_size(180000, 0, 2, 1, -1270, "2:1 ratio 1");
174 test_ifont_size(240000, 0, 2, 1, -1694, "2:1 ratio 2");
175 test_ifont_size(300000, 0, 2, 1, -2117, "2:1 ratio 3");
177 /* test various combinations of 1:2 logical:himetric */
178 test_ifont_size(180000, 0, 1, 2, -318, "1:2 ratio 1");
179 test_ifont_size(240000, 0, 1, 2, -424, "1:2 ratio 2");
180 test_ifont_size(300000, 0, 1, 2, -529, "1:2 ratio 3");
182 /* test various combinations of logical and himetric both set to 2 */
183 test_ifont_size(180000, 0, 2, 2, -635, "2:2 ratio 1");
184 test_ifont_size(240000, 0, 2, 2, -848, "2:2 ratio 2");
185 test_ifont_size(300000, 0, 2, 2, -1058, "2:2 ratio 3");
188 static void test_QueryInterface(void)
195 hr
= pOleCreateFontIndirect(NULL
, &IID_IFont
, NULL
);
196 EXPECT_HR(hr
, E_POINTER
);
198 hr
= pOleCreateFontIndirect(NULL
, &IID_IFont
, &pvObj
);
202 ok(font
!= NULL
,"OCFI (NULL,..) returns NULL, instead of !NULL\n");
205 hr
= IFont_QueryInterface( font
, &IID_IFont
, &pvObj
);
208 /* Test if QueryInterface increments ref counter for IFONTs */
209 ref
= IFont_AddRef(font
);
211 broken(ref
== 1), /* win95 */
212 "IFont_QI expected ref value 3 but instead got %d\n", ref
);
215 ok(pvObj
!= NULL
,"IFont_QI does return NULL, instead of a ptr\n");
221 static void test_type_info(void)
225 IFontDisp
* fontdisp
= NULL
;
227 WCHAR name_Name
[] = {'N','a','m','e',0};
230 LCID en_us
= MAKELCID(MAKELANGID(LANG_ENGLISH
,SUBLANG_ENGLISH_US
),
232 DISPPARAMS dispparams
;
235 pOleCreateFontIndirect(NULL
, &IID_IFontDisp
, &pvObj
);
238 hres
= IFontDisp_GetTypeInfo(fontdisp
, 0, en_us
, &pTInfo
);
239 ok(hres
== S_OK
, "GTI returned 0x%08x instead of S_OK.\n", hres
);
240 ok(pTInfo
!= NULL
, "GTI returned NULL.\n");
242 hres
= ITypeInfo_GetNames(pTInfo
, DISPID_FONT_NAME
, names
, 3, &n
);
243 ok(hres
== S_OK
, "GetNames returned 0x%08x instead of S_OK.\n", hres
);
244 ok(n
== 1, "GetNames returned %d names instead of 1.\n", n
);
245 ok(!lstrcmpiW(names
[0],name_Name
), "DISPID_FONT_NAME doesn't get 'Names'.\n");
246 SysFreeString(names
[0]);
248 ITypeInfo_Release(pTInfo
);
250 dispparams
.cNamedArgs
= 0;
251 dispparams
.rgdispidNamedArgs
= NULL
;
252 dispparams
.cArgs
= 0;
253 dispparams
.rgvarg
= NULL
;
254 VariantInit(&varresult
);
255 hres
= IFontDisp_Invoke(fontdisp
, DISPID_FONT_NAME
, &IID_NULL
,
256 LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
,
258 ok(hres
== S_OK
, "IFontDisp_Invoke return 0x%08x instead of S_OK.\n", hres
);
259 VariantClear(&varresult
);
261 IFontDisp_Release(fontdisp
);
264 static HRESULT WINAPI
FontEventsDisp_QueryInterface(
265 IFontEventsDisp
*iface
,
266 /* [in] */ REFIID riid
,
267 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
269 if (IsEqualIID(riid
, &IID_IFontEventsDisp
) || IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
271 IFontEventsDisp_AddRef(iface
);
278 return E_NOINTERFACE
;
282 static ULONG WINAPI
FontEventsDisp_AddRef(
283 IFontEventsDisp
*iface
)
288 static ULONG WINAPI
FontEventsDisp_Release(
289 IFontEventsDisp
*iface
)
294 static int fonteventsdisp_invoke_called
= 0;
296 static HRESULT WINAPI
FontEventsDisp_Invoke(
297 IFontEventsDisp __RPC_FAR
* iface
,
298 /* [in] */ DISPID dispIdMember
,
299 /* [in] */ REFIID riid
,
300 /* [in] */ LCID lcid
,
301 /* [in] */ WORD wFlags
,
302 /* [out][in] */ DISPPARAMS __RPC_FAR
*pDispParams
,
303 /* [out] */ VARIANT __RPC_FAR
*pVarResult
,
304 /* [out] */ EXCEPINFO __RPC_FAR
*pExcepInfo
,
305 /* [out] */ UINT __RPC_FAR
*puArgErr
)
307 static const WCHAR wszBold
[] = {'B','o','l','d',0};
308 ok(wFlags
== INVOKE_FUNC
, "invoke flags should have been INVOKE_FUNC instead of 0x%x\n", wFlags
);
309 ok(dispIdMember
== DISPID_FONT_CHANGED
, "dispIdMember should have been DISPID_FONT_CHANGED instead of 0x%x\n", dispIdMember
);
310 ok(pDispParams
->cArgs
== 1, "pDispParams->cArgs should have been 1 instead of %d\n", pDispParams
->cArgs
);
311 ok(V_VT(&pDispParams
->rgvarg
[0]) == VT_BSTR
, "VT of first param should have been VT_BSTR instead of %d\n", V_VT(&pDispParams
->rgvarg
[0]));
312 ok(!lstrcmpW(V_BSTR(&pDispParams
->rgvarg
[0]), wszBold
), "String in first param should have been \"Bold\"\n");
314 fonteventsdisp_invoke_called
++;
318 static IFontEventsDispVtbl FontEventsDisp_Vtbl
=
320 FontEventsDisp_QueryInterface
,
321 FontEventsDisp_AddRef
,
322 FontEventsDisp_Release
,
326 FontEventsDisp_Invoke
329 static IFontEventsDisp FontEventsDisp
= { &FontEventsDisp_Vtbl
};
331 static void test_font_events_disp(void)
335 IConnectionPointContainer
*pCPC
;
336 IConnectionPoint
*pCP
;
340 IFontDisp
*pFontDisp
;
341 DISPPARAMS dispparams
;
344 fontdesc
.cbSizeofstruct
= sizeof(fontdesc
);
345 fontdesc
.lpstrName
= MSSansSerif_font
;
346 fontdesc
.cySize
.int64
= 12 * 10000; /* 12 pt */
347 fontdesc
.sWeight
= FW_NORMAL
;
348 fontdesc
.sCharset
= 0;
349 fontdesc
.fItalic
= FALSE
;
350 fontdesc
.fUnderline
= FALSE
;
351 fontdesc
.fStrikethrough
= FALSE
;
353 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void **)&pFont
);
356 hr
= IFont_QueryInterface(pFont
, &IID_IConnectionPointContainer
, (void **)&pCPC
);
359 hr
= IConnectionPointContainer_FindConnectionPoint(pCPC
, &IID_IFontEventsDisp
, &pCP
);
361 IConnectionPointContainer_Release(pCPC
);
363 hr
= IConnectionPoint_Advise(pCP
, (IUnknown
*)&FontEventsDisp
, &dwCookie
);
365 IConnectionPoint_Release(pCP
);
367 hr
= IFont_put_Bold(pFont
, TRUE
);
370 ok(fonteventsdisp_invoke_called
== 1, "IFontEventDisp::Invoke wasn't called once\n");
372 hr
= IFont_QueryInterface(pFont
, &IID_IFontDisp
, (void **)&pFontDisp
);
375 V_VT(&vararg
) = VT_BOOL
;
376 V_BOOL(&vararg
) = VARIANT_FALSE
;
377 dispparams
.cNamedArgs
= 0;
378 dispparams
.rgdispidNamedArgs
= NULL
;
379 dispparams
.cArgs
= 1;
380 dispparams
.rgvarg
= &vararg
;
381 hr
= IFontDisp_Invoke(pFontDisp
, DISPID_FONT_BOLD
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
384 IFontDisp_Release(pFontDisp
);
386 ok(fonteventsdisp_invoke_called
== 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
387 fonteventsdisp_invoke_called
);
389 hr
= IFont_Clone(pFont
, &pFont2
);
391 IFont_Release(pFont
);
393 hr
= IFont_put_Bold(pFont2
, FALSE
);
396 /* this test shows that the notification routine isn't called again */
397 ok(fonteventsdisp_invoke_called
== 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
398 fonteventsdisp_invoke_called
);
400 IFont_Release(pFont2
);
403 static void test_names_ids(WCHAR
* w_name_1
, const char* a_name_1
,
404 WCHAR
* w_name_2
, const char* a_name_2
,
405 LCID lcid
, DISPID id_1
, DISPID id_2
,
406 HRESULT hres_expect
, int numnames
)
409 IFontDisp
*fontdisp
= NULL
;
411 DISPID rgDispId
[2] = {0xdeadbeef, 0xdeadbeef};
412 LPOLESTR names
[2] = {w_name_1
, w_name_2
};
414 pOleCreateFontIndirect(NULL
, &IID_IFontDisp
, &pvObj
);
417 hres
= IFontDisp_GetIDsOfNames(fontdisp
, &IID_NULL
, names
, numnames
,
421 ok(hres
== hres_expect
,
422 "GetIDsOfNames: \"%s\", \"%s\" returns 0x%08x, expected 0x%08x.\n",
423 a_name_1
, a_name_2
, hres
, hres_expect
);
425 /* test first DISPID */
426 ok(rgDispId
[0]==id_1
,
427 "GetIDsOfNames: \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n",
428 a_name_1
, rgDispId
[0], id_1
);
430 /* test second DISPID is present */
433 ok(rgDispId
[1]==id_2
,
434 "GetIDsOfNames: ..., \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n",
435 a_name_2
, rgDispId
[1], id_2
);
438 IFontDisp_Release(fontdisp
);
441 static void test_GetIDsOfNames(void)
443 WCHAR name_Name
[] = {'N','a','m','e',0};
444 WCHAR name_Italic
[] = {'I','t','a','l','i','c',0};
445 WCHAR name_Size
[] = {'S','i','z','e',0};
446 WCHAR name_Bold
[] = {'B','o','l','d',0};
447 WCHAR name_Underline
[] = {'U','n','d','e','r','l','i','n','e',0};
448 WCHAR name_Strikethrough
[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
449 WCHAR name_Weight
[] = {'W','e','i','g','h','t',0};
450 WCHAR name_Charset
[] = {'C','h','a','r','s','e','t',0};
451 WCHAR name_Foo
[] = {'F','o','o',0};
452 WCHAR name_nAmE
[] = {'n','A','m','E',0};
453 WCHAR name_Nom
[] = {'N','o','m',0};
455 LCID en_us
= MAKELCID(MAKELANGID(LANG_ENGLISH
,SUBLANG_ENGLISH_US
),
457 LCID fr_fr
= MAKELCID(MAKELANGID(LANG_FRENCH
,SUBLANG_FRENCH
),
460 /* Test DISPID_FONTs for the various properties. */
461 test_names_ids(name_Name
, "Name", NULL
, "", en_us
,
462 DISPID_FONT_NAME
, 0, S_OK
,1);
463 test_names_ids(name_Size
, "Size", NULL
, "", en_us
,
464 DISPID_FONT_SIZE
, 0, S_OK
,1);
465 test_names_ids(name_Bold
, "Bold", NULL
, "", en_us
,
466 DISPID_FONT_BOLD
, 0, S_OK
,1);
467 test_names_ids(name_Italic
, "Italic", NULL
, "", en_us
,
468 DISPID_FONT_ITALIC
, 0, S_OK
,1);
469 test_names_ids(name_Underline
, "Underline", NULL
, "", en_us
,
470 DISPID_FONT_UNDER
, 0, S_OK
,1);
471 test_names_ids(name_Strikethrough
, "Strikethrough", NULL
, "", en_us
,
472 DISPID_FONT_STRIKE
, 0, S_OK
,1);
473 test_names_ids(name_Weight
, "Weight", NULL
, "", en_us
,
474 DISPID_FONT_WEIGHT
, 0, S_OK
,1);
475 test_names_ids(name_Charset
, "Charset", NULL
, "", en_us
,
476 DISPID_FONT_CHARSET
, 0, S_OK
,1);
478 /* Capitalization doesn't matter. */
479 test_names_ids(name_nAmE
, "nAmE", NULL
, "", en_us
,
480 DISPID_FONT_NAME
, 0, S_OK
,1);
483 test_names_ids(name_Foo
, "Foo", NULL
, "", en_us
,
484 DISPID_UNKNOWN
, 0, DISP_E_UNKNOWNNAME
,1);
486 /* Pass several names: first is processed, */
487 /* second gets DISPID_UNKNOWN and doesn't affect retval. */
488 test_names_ids(name_Italic
, "Italic", name_Name
, "Name", en_us
,
489 DISPID_FONT_ITALIC
, DISPID_UNKNOWN
, S_OK
,2);
490 test_names_ids(name_Italic
, "Italic", name_Foo
, "Foo", en_us
,
491 DISPID_FONT_ITALIC
, DISPID_UNKNOWN
, S_OK
,2);
493 /* Locale ID has no effect. */
494 test_names_ids(name_Name
, "Name", NULL
, "", fr_fr
,
495 DISPID_FONT_NAME
, 0, S_OK
,1);
496 test_names_ids(name_Nom
, "This is not a font", NULL
, "", fr_fr
,
497 DISPID_UNKNOWN
, 0, DISP_E_UNKNOWNNAME
,1);
499 /* One of the arguments are invalid */
500 test_names_ids(name_Name
, "Name", NULL
, "", en_us
,
501 0xdeadbeef, 0xdeadbeef, E_INVALIDARG
,0);
502 test_names_ids(name_Italic
, "Italic", NULL
, "", en_us
,
503 0xdeadbeef, 0xdeadbeef, E_INVALIDARG
,0);
504 test_names_ids(name_Foo
, "Foo", NULL
, "", en_us
,
505 0xdeadbeef, 0xdeadbeef, E_INVALIDARG
,0);
507 /* Crazy locale ID? */
508 test_names_ids(name_Name
, "Name", NULL
, "", -1,
509 DISPID_FONT_NAME
, 0, S_OK
,1);
512 static void test_Invoke(void)
517 DISPPARAMS dispparams
;
520 hr
= pOleCreateFontIndirect(NULL
, &IID_IFontDisp
, (void **)&fontdisp
);
523 V_VT(&vararg
) = VT_BOOL
;
524 V_BOOL(&vararg
) = VARIANT_FALSE
;
525 dispparams
.cNamedArgs
= 0;
526 dispparams
.rgdispidNamedArgs
= NULL
;
527 dispparams
.cArgs
= 1;
528 dispparams
.rgvarg
= &vararg
;
529 hr
= IFontDisp_Invoke(fontdisp
, DISPID_FONT_BOLD
, &IID_IFontDisp
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
530 EXPECT_HR(hr
, DISP_E_UNKNOWNINTERFACE
);
532 dispparams
.cArgs
= 0;
533 dispparams
.rgvarg
= NULL
;
534 hr
= IFontDisp_Invoke(fontdisp
, DISPID_FONT_BOLD
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, &dispparams
, NULL
, NULL
, NULL
);
535 EXPECT_HR(hr
, DISP_E_BADPARAMCOUNT
);
537 hr
= IFontDisp_Invoke(fontdisp
, DISPID_FONT_BOLD
, &IID_NULL
, 0, DISPATCH_PROPERTYPUT
, NULL
, NULL
, NULL
, NULL
);
538 EXPECT_HR(hr
, DISP_E_PARAMNOTOPTIONAL
);
540 hr
= IFontDisp_Invoke(fontdisp
, DISPID_FONT_BOLD
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, NULL
, NULL
, NULL
);
541 EXPECT_HR(hr
, DISP_E_PARAMNOTOPTIONAL
);
543 hr
= IFontDisp_Invoke(fontdisp
, DISPID_FONT_BOLD
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, &varresult
, NULL
, NULL
);
546 hr
= IFontDisp_Invoke(fontdisp
, DISPID_FONT_BOLD
, &IID_NULL
, 0, DISPATCH_METHOD
, NULL
, &varresult
, NULL
, NULL
);
547 EXPECT_HR(hr
, DISP_E_MEMBERNOTFOUND
);
549 hr
= IFontDisp_Invoke(fontdisp
, 0xdeadbeef, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, NULL
, &varresult
, NULL
, NULL
);
550 EXPECT_HR(hr
, DISP_E_MEMBERNOTFOUND
);
552 dispparams
.cArgs
= 1;
553 dispparams
.rgvarg
= &vararg
;
554 hr
= IFontDisp_Invoke(fontdisp
, DISPID_FONT_BOLD
, &IID_NULL
, 0, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, NULL
, NULL
);
557 IFontDisp_Release(fontdisp
);
560 static void test_IsEqual(void)
567 /* Basic font description */
568 fd
.cbSizeofstruct
= sizeof(FONTDESC
);
569 fd
.lpstrName
= system_font
;
570 S(fd
.cySize
).Lo
= 100;
571 S(fd
.cySize
).Hi
= 100;
575 fd
.fUnderline
= FALSE
;
576 fd
.fStrikethrough
= FALSE
;
579 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt
);
581 /* Test equal fonts */
582 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
583 hres
= IFont_IsEqual(ifnt
,ifnt2
);
585 "IFont_IsEqual: (EQUAL) Expected S_OK but got 0x%08x\n",hres
);
586 IFont_Release(ifnt2
);
588 /* Check for bad pointer */
589 hres
= IFont_IsEqual(ifnt
,NULL
);
590 ok(hres
== E_POINTER
,
591 "IFont_IsEqual: (NULL) Expected 0x80004003 but got 0x%08x\n",hres
);
594 fd
.lpstrName
= arial_font
;
595 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
596 hres
= IFont_IsEqual(ifnt
,ifnt2
);
598 "IFont_IsEqual: (strName) Expected S_FALSE but got 0x%08x\n",hres
);
599 fd
.lpstrName
= system_font
;
600 IFont_Release(ifnt2
);
602 /* Test lo font size */
603 S(fd
.cySize
).Lo
= 10000;
604 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
605 hres
= IFont_IsEqual(ifnt
,ifnt2
);
607 "IFont_IsEqual: (Lo font size) Expected S_FALSE but got 0x%08x\n",hres
);
608 S(fd
.cySize
).Lo
= 100;
609 IFont_Release(ifnt2
);
611 /* Test hi font size */
612 S(fd
.cySize
).Hi
= 10000;
613 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
614 hres
= IFont_IsEqual(ifnt
,ifnt2
);
616 "IFont_IsEqual: (Hi font size) Expected S_FALSE but got 0x%08x\n",hres
);
617 S(fd
.cySize
).Hi
= 100;
618 IFont_Release(ifnt2
);
620 /* Test font weight */
622 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
623 hres
= IFont_IsEqual(ifnt
,ifnt2
);
625 "IFont_IsEqual: (Weight) Expected S_FALSE but got 0x%08x\n",hres
);
627 IFont_Release(ifnt2
);
631 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
632 hres
= IFont_IsEqual(ifnt
,ifnt2
);
634 "IFont_IsEqual: (Charset) Expected S_FALSE but got 0x%08x\n",hres
);
636 IFont_Release(ifnt2
);
638 /* Test italic setting */
640 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
641 hres
= IFont_IsEqual(ifnt
,ifnt2
);
643 "IFont_IsEqual: (Italic) Expected S_FALSE but got 0x%08x\n",hres
);
645 IFont_Release(ifnt2
);
647 /* Test underline setting */
648 fd
.fUnderline
= TRUE
;
649 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
650 hres
= IFont_IsEqual(ifnt
,ifnt2
);
652 "IFont_IsEqual: (Underline) Expected S_FALSE but got 0x%08x\n",hres
);
653 fd
.fUnderline
= FALSE
;
654 IFont_Release(ifnt2
);
656 /* Test strikethrough setting */
657 fd
.fStrikethrough
= TRUE
;
658 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
659 hres
= IFont_IsEqual(ifnt
,ifnt2
);
661 "IFont_IsEqual: (Strikethrough) Expected S_FALSE but got 0x%08x\n",hres
);
662 fd
.fStrikethrough
= FALSE
;
663 IFont_Release(ifnt2
);
669 static void test_ReleaseHfont(void)
672 LPVOID pvObj1
= NULL
;
673 LPVOID pvObj2
= NULL
;
680 /* Basic font description */
681 fd
.cbSizeofstruct
= sizeof(FONTDESC
);
682 fd
.lpstrName
= system_font
;
683 S(fd
.cySize
).Lo
= 100;
684 S(fd
.cySize
).Hi
= 100;
688 fd
.fUnderline
= FALSE
;
689 fd
.fStrikethrough
= FALSE
;
691 /* Create HFONTs and IFONTs */
692 pOleCreateFontIndirect(&fd
, &IID_IFont
, &pvObj1
);
694 IFont_get_hFont(ifnt1
,&hfnt1
);
695 fd
.lpstrName
= arial_font
;
696 pOleCreateFontIndirect(&fd
, &IID_IFont
, &pvObj2
);
698 IFont_get_hFont(ifnt2
,&hfnt2
);
700 /* Try invalid HFONT */
701 hres
= IFont_ReleaseHfont(ifnt1
,NULL
);
702 ok(hres
== E_INVALIDARG
,
703 "IFont_ReleaseHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n",
706 /* Try to add a bad HFONT */
707 hres
= IFont_ReleaseHfont(ifnt1
,(HFONT
)32);
709 "IFont_ReleaseHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n",
712 /* Release all refs */
713 hres
= IFont_ReleaseHfont(ifnt1
,hfnt1
);
715 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
718 hres
= IFont_ReleaseHfont(ifnt2
,hfnt2
);
720 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
723 /* Check that both lists are empty */
724 hres
= IFont_ReleaseHfont(ifnt1
,hfnt1
);
726 "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
729 /* The list should be empty */
730 hres
= IFont_ReleaseHfont(ifnt2
,hfnt2
);
732 "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
735 IFont_Release(ifnt1
);
736 IFont_Release(ifnt2
);
739 static void test_AddRefHfont(void)
750 /* Basic font description */
751 fd
.cbSizeofstruct
= sizeof(FONTDESC
);
752 fd
.lpstrName
= system_font
;
753 S(fd
.cySize
).Lo
= 100;
754 S(fd
.cySize
).Hi
= 100;
758 fd
.fUnderline
= FALSE
;
759 fd
.fStrikethrough
= FALSE
;
761 /* Create HFONTs and IFONTs */
762 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt1
);
763 IFont_get_hFont(ifnt1
,&hfnt1
);
764 fd
.lpstrName
= arial_font
;
765 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt2
);
766 IFont_get_hFont(ifnt2
,&hfnt2
);
768 /* Try invalid HFONT */
769 hres
= IFont_AddRefHfont(ifnt1
,NULL
);
770 ok(hres
== E_INVALIDARG
,
771 "IFont_AddRefHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n",
774 /* Try to add a bad HFONT */
775 hres
= IFont_AddRefHfont(ifnt1
,(HFONT
)32);
777 "IFont_AddRefHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n",
780 /* Add simple IFONT HFONT pair */
781 hres
= IFont_AddRefHfont(ifnt1
,hfnt1
);
783 "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
786 /* IFONT and HFONT do not have to be the same (always looks at HFONT) */
787 hres
= IFont_AddRefHfont(ifnt2
,hfnt1
);
789 "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
792 /* Release all hfnt1 refs */
793 hres
= IFont_ReleaseHfont(ifnt1
,hfnt1
);
795 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
798 hres
= IFont_ReleaseHfont(ifnt1
,hfnt1
);
800 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
803 hres
= IFont_ReleaseHfont(ifnt1
,hfnt1
);
805 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
808 /* Check if hfnt1 is empty */
809 hres
= IFont_ReleaseHfont(ifnt1
,hfnt1
);
811 "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
814 /* Release all hfnt2 refs */
815 hres
= IFont_ReleaseHfont(ifnt2
,hfnt2
);
817 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
820 /* Check if hfnt2 is empty */
821 hres
= IFont_ReleaseHfont(ifnt2
,hfnt2
);
823 "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
826 /* Show that releasing an IFONT does not always release it from the HFONT cache. */
828 IFont_Release(ifnt1
);
830 /* Add a reference for destroyed hfnt1 */
831 hres
= IFont_AddRefHfont(ifnt2
,hfnt1
);
833 "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
836 /* Decrement reference for destroyed hfnt1 */
837 hres
= IFont_ReleaseHfont(ifnt2
,hfnt1
);
839 hres
== S_FALSE
, /* <= win2k */
840 "IFont_AddRefHfont: (Release ref) Expected S_OK or S_FALSE but got 0x%08x\n",
843 /* Shows that releasing all IFONT's does clear the HFONT cache. */
845 IFont_Release(ifnt2
);
847 /* Need to make a new IFONT for testing */
848 fd
.fUnderline
= TRUE
;
849 pOleCreateFontIndirect(&fd
, &IID_IFont
, (void **)&ifnt3
);
850 IFont_get_hFont(ifnt3
,&hfnt3
);
852 /* Add a reference for destroyed hfnt1 */
853 hres
= IFont_AddRefHfont(ifnt3
,hfnt1
);
855 "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
858 /* Decrement reference for destroyed hfnt1 */
859 hres
= IFont_ReleaseHfont(ifnt3
,hfnt1
);
861 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
864 IFont_Release(ifnt3
);
867 static void test_returns(void)
873 fontdesc
.cbSizeofstruct
= sizeof(fontdesc
);
874 fontdesc
.lpstrName
= MSSansSerif_font
;
875 fontdesc
.cySize
.int64
= 12 * 10000; /* 12 pt */
876 fontdesc
.sWeight
= FW_NORMAL
;
877 fontdesc
.sCharset
= 0;
878 fontdesc
.fItalic
= FALSE
;
879 fontdesc
.fUnderline
= FALSE
;
880 fontdesc
.fStrikethrough
= FALSE
;
882 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void **)&pFont
);
885 hr
= IFont_put_Name(pFont
, NULL
);
886 EXPECT_HR(hr
, CTL_E_INVALIDPROPERTYVALUE
);
888 hr
= IFont_get_Name(pFont
, NULL
);
889 EXPECT_HR(hr
, E_POINTER
);
891 hr
= IFont_get_Size(pFont
, NULL
);
892 EXPECT_HR(hr
, E_POINTER
);
894 hr
= IFont_get_Bold(pFont
, NULL
);
895 EXPECT_HR(hr
, E_POINTER
);
897 IFont_Release(pFont
);
900 static void test_hfont_lifetime(void)
905 HFONT hfont
, first_hfont
= NULL
;
910 fontdesc
.cbSizeofstruct
= sizeof(fontdesc
);
911 fontdesc
.lpstrName
= arial_font
;
912 fontdesc
.cySize
.int64
= 12 * 10000; /* 12 pt */
913 fontdesc
.sWeight
= FW_NORMAL
;
914 fontdesc
.sCharset
= ANSI_CHARSET
;
915 fontdesc
.fItalic
= FALSE
;
916 fontdesc
.fUnderline
= FALSE
;
917 fontdesc
.fStrikethrough
= FALSE
;
919 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void **)&font
);
922 hr
= IFont_get_hFont(font
, &hfont
);
925 /* show that if the font is updated the old hfont is deleted when the
926 new font is realized */
927 for(i
= 0; i
< 100; i
++)
929 HFONT last_hfont
= hfont
;
931 size
.int64
= (i
+ 10) * 20000;
933 obj_type
= GetObjectType(hfont
);
934 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
936 hr
= IFont_put_Size(font
, size
);
939 /* put_Size doesn't cause the new font to be realized */
940 obj_type
= GetObjectType(last_hfont
);
941 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
943 hr
= IFont_get_hFont(font
, &hfont
);
946 obj_type
= GetObjectType(last_hfont
);
947 ok(obj_type
== 0, "%d: got obj type %d\n", i
, obj_type
);
950 /* now show that if we take a reference on the hfont, it persists
951 until the font object is released */
952 for(i
= 0; i
< 100; i
++)
954 size
.int64
= (i
+ 10) * 20000;
956 obj_type
= GetObjectType(hfont
);
957 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
959 hr
= IFont_put_Size(font
, size
);
962 hr
= IFont_get_hFont(font
, &hfont
);
965 hr
= IFont_AddRefHfont(font
, hfont
);
968 if(i
== 0) first_hfont
= hfont
;
969 obj_type
= GetObjectType(first_hfont
);
970 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
975 obj_type
= GetObjectType(first_hfont
);
976 ok(obj_type
== 0, "got obj type %d\n", obj_type
);
978 /* An AddRefHfont followed by a ReleaseHfont means the font doesn't not persist
979 through re-realization */
981 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void **)&font
);
984 hr
= IFont_get_hFont(font
, &hfont
);
987 for(i
= 0; i
< 100; i
++)
989 HFONT last_hfont
= hfont
;
991 size
.int64
= (i
+ 10) * 20000;
993 obj_type
= GetObjectType(hfont
);
994 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
996 hr
= IFont_put_Size(font
, size
);
999 /* put_Size doesn't cause the new font to be realized */
1000 obj_type
= GetObjectType(last_hfont
);
1001 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
1003 hr
= IFont_get_hFont(font
, &hfont
);
1004 EXPECT_HR(hr
, S_OK
);
1006 hr
= IFont_AddRefHfont(font
, hfont
);
1007 EXPECT_HR(hr
, S_OK
);
1009 hr
= IFont_ReleaseHfont(font
, hfont
);
1010 EXPECT_HR(hr
, S_OK
);
1012 obj_type
= GetObjectType(last_hfont
);
1013 ok(obj_type
== 0, "%d: got obj type %d\n", i
, obj_type
);
1016 /* Interestingly if we release a nonexistent reference on the hfont,
1017 * it persists until the font object is released
1019 for(i
= 0; i
< 100; i
++)
1021 size
.int64
= (i
+ 10) * 20000;
1023 obj_type
= GetObjectType(hfont
);
1024 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
1026 hr
= IFont_put_Size(font
, size
);
1027 EXPECT_HR(hr
, S_OK
);
1029 hr
= IFont_get_hFont(font
, &hfont
);
1030 EXPECT_HR(hr
, S_OK
);
1032 hr
= IFont_ReleaseHfont(font
, hfont
);
1033 EXPECT_HR(hr
, S_OK
);
1035 if(i
== 0) first_hfont
= hfont
;
1036 obj_type
= GetObjectType(first_hfont
);
1037 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
1040 IFont_Release(font
);
1042 obj_type
= GetObjectType(first_hfont
);
1043 ok(obj_type
== 0, "got obj type %d\n", obj_type
);
1045 /* If we take two internal references on a hfont then we can release
1046 it twice. So it looks like there's a total reference count
1047 that includes internal and external references */
1049 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void **)&font
);
1050 EXPECT_HR(hr
, S_OK
);
1051 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void **)&font2
);
1052 EXPECT_HR(hr
, S_OK
);
1054 hr
= IFont_get_hFont(font
, &hfont
);
1055 EXPECT_HR(hr
, S_OK
);
1056 hr
= IFont_get_hFont(font2
, &first_hfont
);
1057 EXPECT_HR(hr
, S_OK
);
1059 ok(hfont
== first_hfont
, "fonts differ\n");
1060 hr
= IFont_ReleaseHfont(font
, hfont
);
1061 EXPECT_HR(hr
, S_OK
);
1062 hr
= IFont_ReleaseHfont(font
, hfont
);
1064 EXPECT_HR(hr
, S_OK
);
1065 hr
= IFont_ReleaseHfont(font
, hfont
);
1066 EXPECT_HR(hr
, S_FALSE
);
1068 obj_type
= GetObjectType(hfont
);
1069 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
1071 IFont_Release(font
);
1073 obj_type
= GetObjectType(hfont
);
1074 ok(obj_type
== OBJ_FONT
, "got obj type %d\n", obj_type
);
1076 IFont_Release(font2
);
1078 obj_type
= GetObjectType(hfont
);
1079 ok(obj_type
== 0, "got obj type %d\n", obj_type
);
1082 static void test_realization(void)
1090 /* Try to create a symbol only font (marlett) with charset
1091 set to ANSI. This will result in another, ANSI, font
1093 fontdesc
.cbSizeofstruct
= sizeof(fontdesc
);
1094 fontdesc
.lpstrName
= marlett_font
;
1095 fontdesc
.cySize
.int64
= 12 * 10000; /* 12 pt */
1096 fontdesc
.sWeight
= FW_NORMAL
;
1097 fontdesc
.sCharset
= ANSI_CHARSET
;
1098 fontdesc
.fItalic
= FALSE
;
1099 fontdesc
.fUnderline
= FALSE
;
1100 fontdesc
.fStrikethrough
= FALSE
;
1102 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void **)&font
);
1103 EXPECT_HR(hr
, S_OK
);
1105 hr
= IFont_get_Charset(font
, &cs
);
1106 EXPECT_HR(hr
, S_OK
);
1107 ok(cs
== ANSI_CHARSET
, "got charset %d\n", cs
);
1109 IFont_Release(font
);
1111 /* Now create an ANSI font and change the name to marlett */
1113 fontdesc
.lpstrName
= arial_font
;
1115 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void **)&font
);
1116 EXPECT_HR(hr
, S_OK
);
1118 hr
= IFont_get_Charset(font
, &cs
);
1119 EXPECT_HR(hr
, S_OK
);
1120 ok(cs
== ANSI_CHARSET
, "got charset %d\n", cs
);
1122 name
= SysAllocString(marlett_font
);
1123 hr
= IFont_put_Name(font
, name
);
1124 EXPECT_HR(hr
, S_OK
);
1125 SysFreeString(name
);
1127 hr
= IFont_get_Name(font
, &name
);
1128 EXPECT_HR(hr
, S_OK
);
1129 ok(!lstrcmpiW(name
, marlett_font
), "got name %s\n", wine_dbgstr_w(name
));
1130 SysFreeString(name
);
1132 hr
= IFont_get_Charset(font
, &cs
);
1133 EXPECT_HR(hr
, S_OK
);
1134 ok(cs
== SYMBOL_CHARSET
, "got charset %d\n", cs
);
1136 IFont_Release(font
);
1139 static void test_OleCreateFontIndirect(void)
1145 fontdesc
.cbSizeofstruct
= sizeof(fontdesc
);
1146 fontdesc
.lpstrName
= arial_font
;
1147 fontdesc
.cySize
.int64
= 12 * 10000; /* 12 pt */
1148 fontdesc
.sWeight
= FW_NORMAL
;
1149 fontdesc
.sCharset
= ANSI_CHARSET
;
1150 fontdesc
.fItalic
= FALSE
;
1151 fontdesc
.fUnderline
= FALSE
;
1152 fontdesc
.fStrikethrough
= FALSE
;
1154 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void**)&font
);
1155 EXPECT_HR(hr
, S_OK
);
1156 IFont_Release(font
);
1158 /* play with cbSizeofstruct value */
1159 fontdesc
.cbSizeofstruct
= sizeof(fontdesc
)-1;
1160 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void**)&font
);
1161 EXPECT_HR(hr
, S_OK
);
1162 IFont_Release(font
);
1164 fontdesc
.cbSizeofstruct
= sizeof(fontdesc
)+1;
1165 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void**)&font
);
1166 EXPECT_HR(hr
, S_OK
);
1167 IFont_Release(font
);
1169 fontdesc
.cbSizeofstruct
= 0;
1170 hr
= pOleCreateFontIndirect(&fontdesc
, &IID_IFont
, (void**)&font
);
1171 EXPECT_HR(hr
, S_OK
);
1172 IFont_Release(font
);
1177 hOleaut32
= GetModuleHandleA("oleaut32.dll");
1178 pOleCreateFontIndirect
= (void*)GetProcAddress(hOleaut32
, "OleCreateFontIndirect");
1179 if (!pOleCreateFontIndirect
)
1181 win_skip("OleCreateFontIndirect not available\n");
1185 test_QueryInterface();
1188 test_font_events_disp();
1189 test_GetIDsOfNames();
1192 test_ReleaseHfont();
1195 test_hfont_lifetime();
1197 test_OleCreateFontIndirect();