1 /* 2 * OLEFONT test program 3 * 4 * Copyright 2003 Marcus Meissner 5 * Copyright 2006 (Google) Benjamin Arai 6 * 7 * 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. 12 * 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. 17 * 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 21 */ 22 23 #include <stdarg.h> 24 #include <stdio.h> 25 #include <math.h> 26 #include <float.h> 27 28 #define COBJMACROS 29 30 #include <wine/test.h> 31 #include <windef.h> 32 #include <winbase.h> 33 #include <winuser.h> 34 #include <wingdi.h> 35 #include <winnls.h> 36 #include <winerror.h> 37 #include <winnt.h> 38 #include <initguid.h> 39 #include <wtypes.h> 40 #include <olectl.h> 41 #include <ocidl.h> 42 43 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); 44 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 }; 49 50 static HMODULE hOleaut32; 51 52 static HRESULT (WINAPI *pOleCreateFontIndirect)(LPFONTDESC,REFIID,LPVOID*); 53 54 #define EXPECT_HR(hr,hr_exp) \ 55 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp) 56 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(LONGLONG size, LONG ratio_logical, LONG ratio_himetric, 62 LONG hfont_height, const char * test_name) 63 { 64 FONTDESC fd; 65 LPVOID pvObj = NULL; 66 IFont* ifnt = NULL; 67 HFONT hfont; 68 LOGFONTA lf; 69 CY psize; 70 HRESULT hres; 71 DWORD rtnval; 72 73 fd.cbSizeofstruct = sizeof(FONTDESC); 74 fd.lpstrName = arial_font; /* using scalable instead of bitmap font reduces errors due to font realization */ 75 fd.cySize.int64 = size; 76 fd.sWeight = 0; 77 fd.sCharset = 0; 78 fd.fItalic = FALSE; 79 fd.fUnderline = FALSE; 80 fd.fStrikethrough = FALSE; 81 82 /* Create font, test that it worked. */ 83 hres = pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj); 84 ifnt = pvObj; 85 ok(hres == S_OK,"%s: OCFI returns 0x%08x instead of S_OK.\n", 86 test_name, hres); 87 ok(pvObj != NULL,"%s: OCFI returns NULL.\n", test_name); 88 89 /* Change the scaling ratio */ 90 hres = IFont_SetRatio(ifnt, ratio_logical, ratio_himetric); 91 ok((ratio_logical && ratio_himetric) ? hres == S_OK : hres == E_FAIL, 92 "%s: IFont_SetRatio unexpectedly returned 0x%08x.\n", test_name, hres); 93 94 /* Read back size. */ 95 hres = IFont_get_Size(ifnt, &psize); 96 ok(hres == S_OK,"%s: IFont_get_size returns 0x%08x instead of S_OK.\n", 97 test_name, hres); 98 99 /* Check returned size - allow for errors due to rounding & font realization. */ 100 ok((psize.int64 - size) < 10000 && (psize.int64 - size) > -10000, 101 "%s: IFont_get_Size: Lo=%d, Hi=%d; expected Lo=%d, Hi=%d.\n", 102 test_name, S(psize).Lo, S(psize).Hi, fd.cySize.Lo, fd.cySize.Hi); 103 104 /* Check hFont size. */ 105 hres = IFont_get_hFont (ifnt, &hfont); 106 ok(hres == S_OK, "%s: IFont_get_hFont returns 0x%08x instead of S_OK.\n", 107 test_name, hres); 108 rtnval = GetObjectA(hfont, sizeof(LOGFONTA), &lf); 109 ok(rtnval > 0, "GetObject(hfont) failed\n"); 110 111 /* Since font scaling may encounter rounding errors, allow 1 pixel deviation. */ 112 ok(abs(lf.lfHeight - hfont_height) <= 1, 113 "%s: hFont has lf.lfHeight=%d, expected %d.\n", 114 test_name, lf.lfHeight, hfont_height); 115 116 /* Free IFont. */ 117 IFont_Release(ifnt); 118 } 119 120 static void test_ifont_sizes(void) 121 { 122 /* Test various size operations and conversions. */ 123 /* Add more as needed. */ 124 125 /* Results of first 2 tests depend on display resolution. */ 126 HDC hdc = GetDC(0); 127 LONG dpi = GetDeviceCaps(hdc, LOGPIXELSY); /* expected results depend on display DPI */ 128 ReleaseDC(0, hdc); 129 if(dpi == 96) /* normal resolution display */ 130 { 131 test_ifont_size(180000, 0, 0, -24, "default"); /* normal font */ 132 test_ifont_size(186000, 0, 0, -25, "rounding"); /* test rounding */ 133 } else if(dpi == 72) /* low resolution display */ 134 { 135 test_ifont_size(180000, 0, 0, -18, "default"); /* normal font */ 136 test_ifont_size(186000, 0, 0, -19, "rounding"); /* test rounding */ 137 } else if(dpi == 120) /* high resolution display */ 138 { 139 test_ifont_size(180000, 0, 0, -30, "default"); /* normal font */ 140 test_ifont_size(186000, 0, 0, -31, "rounding"); /* test rounding */ 141 } else 142 skip("Skipping resolution dependent font size tests - display resolution is %d\n", dpi); 143 144 /* Next 4 tests specify a scaling ratio, so display resolution is not a factor. */ 145 test_ifont_size(180000, 72, 2540, -18, "ratio1"); /* change ratio */ 146 test_ifont_size(180000, 144, 2540, -36, "ratio2"); /* another ratio */ 147 test_ifont_size(180000, 72, 1270, -36, "ratio3"); /* yet another ratio */ 148 test_ifont_size(186000, 72, 2540, -19, "rounding+ratio"); /* test rounding with ratio */ 149 150 /* test various combinations of logical == himetric */ 151 test_ifont_size(180000, 10, 10, -635, "identical ratio 1"); 152 test_ifont_size(240000, 10, 10, -848, "identical ratio 2"); 153 test_ifont_size(300000, 10, 10, -1058, "identical ratio 3"); 154 155 /* test various combinations of logical and himetric both set to 1 */ 156 test_ifont_size(180000, 1, 1, -24, "1:1 ratio 1"); 157 test_ifont_size(240000, 1, 1, -32, "1:1 ratio 2"); 158 test_ifont_size(300000, 1, 1, -40, "1:1 ratio 3"); 159 160 /* test various combinations of logical set to 1 */ 161 test_ifont_size(180000, 1, 0, -24, "1:0 ratio 1"); 162 test_ifont_size(240000, 1, 0, -32, "1:0 ratio 2"); 163 test_ifont_size(300000, 1, 0, -40, "1:0 ratio 3"); 164 165 /* test various combinations of himetric set to 1 */ 166 test_ifont_size(180000, 0, 1, -24, "0:1 ratio 1"); 167 test_ifont_size(240000, 0, 1, -32, "0:1 ratio 2"); 168 test_ifont_size(300000, 0, 1, -40, "0:1 ratio 3"); 169 170 /* test various combinations of 2:1 logical:himetric */ 171 test_ifont_size(180000, 2, 1, -1270, "2:1 ratio 1"); 172 test_ifont_size(240000, 2, 1, -1694, "2:1 ratio 2"); 173 test_ifont_size(300000, 2, 1, -2117, "2:1 ratio 3"); 174 175 /* test various combinations of 1:2 logical:himetric */ 176 test_ifont_size(180000, 1, 2, -318, "1:2 ratio 1"); 177 test_ifont_size(240000, 1, 2, -424, "1:2 ratio 2"); 178 test_ifont_size(300000, 1, 2, -529, "1:2 ratio 3"); 179 180 /* test various combinations of logical and himetric both set to 2 */ 181 test_ifont_size(180000, 2, 2, -635, "2:2 ratio 1"); 182 test_ifont_size(240000, 2, 2, -848, "2:2 ratio 2"); 183 test_ifont_size(300000, 2, 2, -1058, "2:2 ratio 3"); 184 } 185 186 static void test_QueryInterface(void) 187 { 188 LPVOID pvObj = NULL; 189 HRESULT hr; 190 IFont* font = NULL; 191 LONG ref; 192 193 hr = pOleCreateFontIndirect(NULL, &IID_IFont, NULL); 194 EXPECT_HR(hr, E_POINTER); 195 196 hr = pOleCreateFontIndirect(NULL, &IID_IFont, &pvObj); 197 font = pvObj; 198 199 EXPECT_HR(hr, S_OK); 200 ok(font != NULL,"OCFI (NULL,..) returns NULL, instead of !NULL\n"); 201 202 pvObj = NULL; 203 hr = IFont_QueryInterface( font, &IID_IFont, &pvObj); 204 EXPECT_HR(hr, S_OK); 205 206 /* Test if QueryInterface increments ref counter for IFONTs */ 207 ref = IFont_AddRef(font); 208 ok(ref == 3 || 209 broken(ref == 1), /* win95 */ 210 "IFont_QI expected ref value 3 but instead got %d\n", ref); 211 IFont_Release(font); 212 213 ok(pvObj != NULL,"IFont_QI does return NULL, instead of a ptr\n"); 214 215 IFont_Release(font); 216 IFont_Release(font); 217 } 218 219 static void test_type_info(void) 220 { 221 LPVOID pvObj = NULL; 222 HRESULT hres; 223 IFontDisp* fontdisp = NULL; 224 ITypeInfo* pTInfo; 225 WCHAR name_Name[] = {'N','a','m','e',0}; 226 BSTR names[3]; 227 UINT n; 228 LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), 229 SORT_DEFAULT); 230 DISPPARAMS dispparams; 231 VARIANT varresult; 232 233 pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj); 234 fontdisp = pvObj; 235 236 hres = IFontDisp_GetTypeInfo(fontdisp, 0, en_us, &pTInfo); 237 ok(hres == S_OK, "GTI returned 0x%08x instead of S_OK.\n", hres); 238 ok(pTInfo != NULL, "GTI returned NULL.\n"); 239 240 hres = ITypeInfo_GetNames(pTInfo, DISPID_FONT_NAME, names, 3, &n); 241 ok(hres == S_OK, "GetNames returned 0x%08x instead of S_OK.\n", hres); 242 ok(n == 1, "GetNames returned %d names instead of 1.\n", n); 243 ok(!lstrcmpiW(names[0],name_Name), "DISPID_FONT_NAME doesn't get 'Names'.\n"); 244 SysFreeString(names[0]); 245 246 ITypeInfo_Release(pTInfo); 247 248 dispparams.cNamedArgs = 0; 249 dispparams.rgdispidNamedArgs = NULL; 250 dispparams.cArgs = 0; 251 dispparams.rgvarg = NULL; 252 VariantInit(&varresult); 253 hres = IFontDisp_Invoke(fontdisp, DISPID_FONT_NAME, &IID_NULL, 254 LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, 255 NULL, NULL); 256 ok(hres == S_OK, "IFontDisp_Invoke return 0x%08x instead of S_OK.\n", hres); 257 VariantClear(&varresult); 258 259 IFontDisp_Release(fontdisp); 260 } 261 262 static HRESULT WINAPI FontEventsDisp_QueryInterface(IFontEventsDisp *iface, REFIID riid, void **ppvObject) 263 { 264 if (IsEqualIID(riid, &IID_IFontEventsDisp) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch)) 265 { 266 IFontEventsDisp_AddRef(iface); 267 *ppvObject = iface; 268 return S_OK; 269 } 270 else 271 { 272 *ppvObject = NULL; 273 return E_NOINTERFACE; 274 } 275 } 276 277 static ULONG WINAPI FontEventsDisp_AddRef( 278 IFontEventsDisp *iface) 279 { 280 return 2; 281 } 282 283 static ULONG WINAPI FontEventsDisp_Release( 284 IFontEventsDisp *iface) 285 { 286 return 1; 287 } 288 289 static HRESULT WINAPI FontEventsDisp_GetTypeInfoCount(IFontEventsDisp *iface, UINT *pctinfo) 290 { 291 ok(0, "unexpected call\n"); 292 return E_NOTIMPL; 293 } 294 295 static HRESULT WINAPI FontEventsDisp_GetTypeInfo(IFontEventsDisp *iface, UINT itinfo, LCID lcid, ITypeInfo **pptinfo) 296 { 297 ok(0, "unexpected call\n"); 298 return E_NOTIMPL; 299 } 300 301 static HRESULT WINAPI FontEventsDisp_GetIDsOfNames(IFontEventsDisp *iface, REFIID riid, LPOLESTR *names, UINT cNames, LCID lcid, 302 DISPID *dispid) 303 { 304 ok(0, "unexpected call\n"); 305 return E_NOTIMPL; 306 } 307 308 static int fonteventsdisp_invoke_called; 309 static BSTR fonteventsdisp_invoke_arg0; 310 311 static HRESULT WINAPI FontEventsDisp_Invoke( 312 IFontEventsDisp *iface, 313 DISPID dispid, 314 REFIID riid, 315 LCID lcid, 316 WORD wFlags, 317 DISPPARAMS *pDispParams, 318 VARIANT *pVarResult, 319 EXCEPINFO *pExcepInfo, 320 UINT *puArgErr) 321 { 322 VARIANTARG *arg0 = &pDispParams->rgvarg[0]; 323 324 ok(dispid == DISPID_FONT_CHANGED, "expected DISPID_FONT_CHANGED instead of 0x%x\n", dispid); 325 ok(IsEqualGUID(riid, &GUID_NULL), "got riid %s\n", wine_dbgstr_guid(riid)); 326 ok(wFlags == INVOKE_FUNC, "expected INVOKE_FUNC instead of 0x%x\n", wFlags); 327 ok(pDispParams->cArgs == 1, "expected arg count 1, got %d\n", pDispParams->cArgs); 328 ok(V_VT(arg0) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(arg0)); 329 330 fonteventsdisp_invoke_arg0 = SysAllocString(V_BSTR(arg0)); 331 fonteventsdisp_invoke_called++; 332 return S_OK; 333 } 334 335 static IFontEventsDispVtbl FontEventsDisp_Vtbl = 336 { 337 FontEventsDisp_QueryInterface, 338 FontEventsDisp_AddRef, 339 FontEventsDisp_Release, 340 FontEventsDisp_GetTypeInfoCount, 341 FontEventsDisp_GetTypeInfo, 342 FontEventsDisp_GetIDsOfNames, 343 FontEventsDisp_Invoke 344 }; 345 346 static IFontEventsDisp FontEventsDisp = { &FontEventsDisp_Vtbl }; 347 348 struct font_dispid 349 { 350 DISPID dispid; 351 const WCHAR *name; 352 }; 353 354 static void test_font_events_disp(void) 355 { 356 static const WCHAR nameW[] = {'N','a','m','e',0}; 357 static const WCHAR sizeW[] = {'S','i','z','e',0}; 358 static const WCHAR boldW[] = {'B','o','l','d',0}; 359 static const WCHAR italicW[] = {'I','t','a','l','i','c',0}; 360 static const WCHAR underlineW[] = {'U','n','d','e','r','l','i','n','e',0}; 361 static const WCHAR strikeW[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0}; 362 static const WCHAR weightW[] = {'W','e','i','g','h','t',0}; 363 static const WCHAR charsetW[] = {'C','h','a','r','s','e','t',0}; 364 365 static const struct font_dispid font_dispids[] = 366 { 367 { DISPID_FONT_NAME, nameW }, 368 { DISPID_FONT_SIZE, sizeW }, 369 { DISPID_FONT_BOLD, boldW }, 370 { DISPID_FONT_ITALIC, italicW }, 371 { DISPID_FONT_UNDER, underlineW }, 372 { DISPID_FONT_STRIKE, strikeW }, 373 { DISPID_FONT_WEIGHT, weightW }, 374 { DISPID_FONT_CHARSET, charsetW } 375 }; 376 377 IFont *pFont; 378 IFont *pFont2; 379 IConnectionPointContainer *pCPC; 380 IConnectionPoint *pCP; 381 FONTDESC fontdesc; 382 HRESULT hr; 383 DWORD dwCookie; 384 IFontDisp *pFontDisp; 385 DISPPARAMS dispparams; 386 VARIANTARG vararg; 387 INT i; 388 389 fontdesc.cbSizeofstruct = sizeof(fontdesc); 390 fontdesc.lpstrName = MSSansSerif_font; 391 fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */ 392 fontdesc.sWeight = FW_NORMAL; 393 fontdesc.sCharset = 0; 394 fontdesc.fItalic = FALSE; 395 fontdesc.fUnderline = FALSE; 396 fontdesc.fStrikethrough = FALSE; 397 398 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&pFont); 399 EXPECT_HR(hr, S_OK); 400 401 hr = IFont_QueryInterface(pFont, &IID_IConnectionPointContainer, (void **)&pCPC); 402 EXPECT_HR(hr, S_OK); 403 404 hr = IConnectionPointContainer_FindConnectionPoint(pCPC, &IID_IFontEventsDisp, &pCP); 405 EXPECT_HR(hr, S_OK); 406 IConnectionPointContainer_Release(pCPC); 407 408 hr = IConnectionPoint_Advise(pCP, (IUnknown *)&FontEventsDisp, &dwCookie); 409 EXPECT_HR(hr, S_OK); 410 IConnectionPoint_Release(pCP); 411 412 fonteventsdisp_invoke_called = 0; 413 fonteventsdisp_invoke_arg0 = NULL; 414 hr = IFont_put_Bold(pFont, TRUE); 415 EXPECT_HR(hr, S_OK); 416 417 ok(fonteventsdisp_invoke_called == 1, "IFontEventDisp::Invoke wasn't called once\n"); 418 SysFreeString(fonteventsdisp_invoke_arg0); 419 420 hr = IFont_QueryInterface(pFont, &IID_IFontDisp, (void **)&pFontDisp); 421 EXPECT_HR(hr, S_OK); 422 423 for (i = 0; i < ARRAY_SIZE(font_dispids); i++) 424 { 425 switch (font_dispids[i].dispid) 426 { 427 case DISPID_FONT_NAME: 428 { 429 static const WCHAR arialW[] = {'A','r','i','a','l',0}; 430 V_VT(&vararg) = VT_BSTR; 431 V_BSTR(&vararg) = SysAllocString(arialW); 432 break; 433 } 434 case DISPID_FONT_SIZE: 435 V_VT(&vararg) = VT_CY; 436 S(V_CY(&vararg)).Lo = 25; 437 S(V_CY(&vararg)).Hi = 0; 438 break; 439 case DISPID_FONT_BOLD: 440 V_VT(&vararg) = VT_BOOL; 441 V_BOOL(&vararg) = VARIANT_FALSE; 442 break; 443 case DISPID_FONT_ITALIC: 444 case DISPID_FONT_UNDER: 445 case DISPID_FONT_STRIKE: 446 V_VT(&vararg) = VT_BOOL; 447 V_BOOL(&vararg) = VARIANT_TRUE; 448 break; 449 case DISPID_FONT_WEIGHT: 450 V_VT(&vararg) = VT_I2; 451 V_I2(&vararg) = FW_BLACK; 452 break; 453 case DISPID_FONT_CHARSET: 454 V_VT(&vararg) = VT_I2; 455 V_I2(&vararg) = 1; 456 break; 457 default: 458 ; 459 } 460 461 dispparams.cNamedArgs = 0; 462 dispparams.rgdispidNamedArgs = NULL; 463 dispparams.cArgs = 1; 464 dispparams.rgvarg = &vararg; 465 fonteventsdisp_invoke_called = 0; 466 hr = IFontDisp_Invoke(pFontDisp, font_dispids[i].dispid, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); 467 ok(hr == S_OK, "dispid=%d, got 0x%08x\n", font_dispids[i].dispid, hr); 468 ok(fonteventsdisp_invoke_called == 1, "dispid=%d, DISPID_FONT_CHANGED not called, got %d\n", font_dispids[i].dispid, 469 fonteventsdisp_invoke_called); 470 if (hr == S_OK) 471 { 472 ok(!lstrcmpW(font_dispids[i].name, fonteventsdisp_invoke_arg0), "dispid=%d, got %s, expected %s\n", 473 font_dispids[i].dispid, wine_dbgstr_w(fonteventsdisp_invoke_arg0), wine_dbgstr_w(font_dispids[i].name)); 474 SysFreeString(fonteventsdisp_invoke_arg0); 475 } 476 VariantClear(&vararg); 477 } 478 479 IFontDisp_Release(pFontDisp); 480 481 hr = IFont_Clone(pFont, &pFont2); 482 EXPECT_HR(hr, S_OK); 483 IFont_Release(pFont); 484 485 /* this test shows that the notification routine isn't called again */ 486 fonteventsdisp_invoke_called = 0; 487 hr = IFont_put_Bold(pFont2, FALSE); 488 EXPECT_HR(hr, S_OK); 489 ok(fonteventsdisp_invoke_called == 0, "got %d\n", fonteventsdisp_invoke_called); 490 491 IFont_Release(pFont2); 492 } 493 494 static void test_names_ids(WCHAR* w_name_1, const char* a_name_1, 495 WCHAR* w_name_2, const char* a_name_2, 496 LCID lcid, DISPID id_1, DISPID id_2, 497 HRESULT hres_expect, int numnames) 498 { 499 LPVOID pvObj = NULL; 500 IFontDisp *fontdisp = NULL; 501 HRESULT hres; 502 DISPID rgDispId[2] = {0xdeadbeef, 0xdeadbeef}; 503 LPOLESTR names[2] = {w_name_1, w_name_2}; 504 505 pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj); 506 fontdisp = pvObj; 507 508 hres = IFontDisp_GetIDsOfNames(fontdisp, &IID_NULL, names, numnames, 509 lcid, rgDispId); 510 511 /* test hres */ 512 ok(hres == hres_expect, 513 "GetIDsOfNames: \"%s\", \"%s\" returns 0x%08x, expected 0x%08x.\n", 514 a_name_1, a_name_2, hres, hres_expect); 515 516 /* test first DISPID */ 517 ok(rgDispId[0]==id_1, 518 "GetIDsOfNames: \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n", 519 a_name_1, rgDispId[0], id_1); 520 521 /* test second DISPID is present */ 522 if (numnames == 2) 523 { 524 ok(rgDispId[1]==id_2, 525 "GetIDsOfNames: ..., \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n", 526 a_name_2, rgDispId[1], id_2); 527 } 528 529 IFontDisp_Release(fontdisp); 530 } 531 532 static void test_GetIDsOfNames(void) 533 { 534 WCHAR name_Name[] = {'N','a','m','e',0}; 535 WCHAR name_Italic[] = {'I','t','a','l','i','c',0}; 536 WCHAR name_Size[] = {'S','i','z','e',0}; 537 WCHAR name_Bold[] = {'B','o','l','d',0}; 538 WCHAR name_Underline[] = {'U','n','d','e','r','l','i','n','e',0}; 539 WCHAR name_Strikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0}; 540 WCHAR name_Weight[] = {'W','e','i','g','h','t',0}; 541 WCHAR name_Charset[] = {'C','h','a','r','s','e','t',0}; 542 WCHAR name_Foo[] = {'F','o','o',0}; 543 WCHAR name_nAmE[] = {'n','A','m','E',0}; 544 WCHAR name_Nom[] = {'N','o','m',0}; 545 546 LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), 547 SORT_DEFAULT); 548 LCID fr_fr = MAKELCID(MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH), 549 SORT_DEFAULT); 550 551 /* Test DISPID_FONTs for the various properties. */ 552 test_names_ids(name_Name, "Name", NULL, "", en_us, 553 DISPID_FONT_NAME, 0, S_OK,1); 554 test_names_ids(name_Size, "Size", NULL, "", en_us, 555 DISPID_FONT_SIZE, 0, S_OK,1); 556 test_names_ids(name_Bold, "Bold", NULL, "", en_us, 557 DISPID_FONT_BOLD, 0, S_OK,1); 558 test_names_ids(name_Italic, "Italic", NULL, "", en_us, 559 DISPID_FONT_ITALIC, 0, S_OK,1); 560 test_names_ids(name_Underline, "Underline", NULL, "", en_us, 561 DISPID_FONT_UNDER, 0, S_OK,1); 562 test_names_ids(name_Strikethrough, "Strikethrough", NULL, "", en_us, 563 DISPID_FONT_STRIKE, 0, S_OK,1); 564 test_names_ids(name_Weight, "Weight", NULL, "", en_us, 565 DISPID_FONT_WEIGHT, 0, S_OK,1); 566 test_names_ids(name_Charset, "Charset", NULL, "", en_us, 567 DISPID_FONT_CHARSET, 0, S_OK,1); 568 569 /* Capitalization doesn't matter. */ 570 test_names_ids(name_nAmE, "nAmE", NULL, "", en_us, 571 DISPID_FONT_NAME, 0, S_OK,1); 572 573 /* Unknown name. */ 574 test_names_ids(name_Foo, "Foo", NULL, "", en_us, 575 DISPID_UNKNOWN, 0, DISP_E_UNKNOWNNAME,1); 576 577 /* Pass several names: first is processed, */ 578 /* second gets DISPID_UNKNOWN and doesn't affect retval. */ 579 test_names_ids(name_Italic, "Italic", name_Name, "Name", en_us, 580 DISPID_FONT_ITALIC, DISPID_UNKNOWN, S_OK,2); 581 test_names_ids(name_Italic, "Italic", name_Foo, "Foo", en_us, 582 DISPID_FONT_ITALIC, DISPID_UNKNOWN, S_OK,2); 583 584 /* Locale ID has no effect. */ 585 test_names_ids(name_Name, "Name", NULL, "", fr_fr, 586 DISPID_FONT_NAME, 0, S_OK,1); 587 test_names_ids(name_Nom, "This is not a font", NULL, "", fr_fr, 588 DISPID_UNKNOWN, 0, DISP_E_UNKNOWNNAME,1); 589 590 /* One of the arguments are invalid */ 591 test_names_ids(name_Name, "Name", NULL, "", en_us, 592 0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0); 593 test_names_ids(name_Italic, "Italic", NULL, "", en_us, 594 0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0); 595 test_names_ids(name_Foo, "Foo", NULL, "", en_us, 596 0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0); 597 598 /* Crazy locale ID? */ 599 test_names_ids(name_Name, "Name", NULL, "", -1, 600 DISPID_FONT_NAME, 0, S_OK,1); 601 } 602 603 static void test_Invoke(void) 604 { 605 IFontDisp *fontdisp; 606 HRESULT hr; 607 VARIANTARG vararg; 608 DISPPARAMS dispparams; 609 VARIANT varresult; 610 611 hr = pOleCreateFontIndirect(NULL, &IID_IFontDisp, (void **)&fontdisp); 612 EXPECT_HR(hr, S_OK); 613 614 V_VT(&vararg) = VT_BOOL; 615 V_BOOL(&vararg) = VARIANT_FALSE; 616 dispparams.cNamedArgs = 0; 617 dispparams.rgdispidNamedArgs = NULL; 618 dispparams.cArgs = 1; 619 dispparams.rgvarg = &vararg; 620 hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_IFontDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); 621 EXPECT_HR(hr, DISP_E_UNKNOWNINTERFACE); 622 623 dispparams.cArgs = 0; 624 dispparams.rgvarg = NULL; 625 hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); 626 EXPECT_HR(hr, DISP_E_BADPARAMCOUNT); 627 628 hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL); 629 EXPECT_HR(hr, DISP_E_PARAMNOTOPTIONAL); 630 631 hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL); 632 EXPECT_HR(hr, DISP_E_PARAMNOTOPTIONAL); 633 634 hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL); 635 EXPECT_HR(hr, S_OK); 636 637 hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_METHOD, NULL, &varresult, NULL, NULL); 638 EXPECT_HR(hr, DISP_E_MEMBERNOTFOUND); 639 640 hr = IFontDisp_Invoke(fontdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL); 641 EXPECT_HR(hr, DISP_E_MEMBERNOTFOUND); 642 643 dispparams.cArgs = 1; 644 dispparams.rgvarg = &vararg; 645 hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL); 646 EXPECT_HR(hr, S_OK); 647 648 IFontDisp_Release(fontdisp); 649 } 650 651 static void test_IsEqual(void) 652 { 653 FONTDESC fd; 654 IFont* ifnt = NULL; 655 IFont* ifnt2 = NULL; 656 HRESULT hres; 657 658 /* Basic font description */ 659 fd.cbSizeofstruct = sizeof(FONTDESC); 660 fd.lpstrName = system_font; 661 S(fd.cySize).Lo = 100; 662 S(fd.cySize).Hi = 100; 663 fd.sWeight = 0; 664 fd.sCharset = 0; 665 fd.fItalic = FALSE; 666 fd.fUnderline = FALSE; 667 fd.fStrikethrough = FALSE; 668 669 /* Create font */ 670 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt); 671 672 /* Test equal fonts */ 673 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 674 hres = IFont_IsEqual(ifnt,ifnt2); 675 ok(hres == S_OK, 676 "IFont_IsEqual: (EQUAL) Expected S_OK but got 0x%08x\n",hres); 677 IFont_Release(ifnt2); 678 679 /* Check for bad pointer */ 680 hres = IFont_IsEqual(ifnt,NULL); 681 ok(hres == E_POINTER, 682 "IFont_IsEqual: (NULL) Expected 0x80004003 but got 0x%08x\n",hres); 683 684 /* Test strName */ 685 fd.lpstrName = arial_font; 686 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 687 hres = IFont_IsEqual(ifnt,ifnt2); 688 ok(hres == S_FALSE, 689 "IFont_IsEqual: (strName) Expected S_FALSE but got 0x%08x\n",hres); 690 fd.lpstrName = system_font; 691 IFont_Release(ifnt2); 692 693 /* Test lo font size */ 694 S(fd.cySize).Lo = 10000; 695 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 696 hres = IFont_IsEqual(ifnt,ifnt2); 697 ok(hres == S_FALSE, 698 "IFont_IsEqual: (Lo font size) Expected S_FALSE but got 0x%08x\n",hres); 699 S(fd.cySize).Lo = 100; 700 IFont_Release(ifnt2); 701 702 /* Test hi font size */ 703 S(fd.cySize).Hi = 10000; 704 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 705 hres = IFont_IsEqual(ifnt,ifnt2); 706 ok(hres == S_FALSE, 707 "IFont_IsEqual: (Hi font size) Expected S_FALSE but got 0x%08x\n",hres); 708 S(fd.cySize).Hi = 100; 709 IFont_Release(ifnt2); 710 711 /* Test font weight */ 712 fd.sWeight = 100; 713 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 714 hres = IFont_IsEqual(ifnt,ifnt2); 715 ok(hres == S_FALSE, 716 "IFont_IsEqual: (Weight) Expected S_FALSE but got 0x%08x\n",hres); 717 fd.sWeight = 0; 718 IFont_Release(ifnt2); 719 720 /* Test charset */ 721 fd.sCharset = 1; 722 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 723 hres = IFont_IsEqual(ifnt,ifnt2); 724 ok(hres == S_FALSE, 725 "IFont_IsEqual: (Charset) Expected S_FALSE but got 0x%08x\n",hres); 726 fd.sCharset = 0; 727 IFont_Release(ifnt2); 728 729 /* Test italic setting */ 730 fd.fItalic = TRUE; 731 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 732 hres = IFont_IsEqual(ifnt,ifnt2); 733 ok(hres == S_FALSE, 734 "IFont_IsEqual: (Italic) Expected S_FALSE but got 0x%08x\n",hres); 735 fd.fItalic = FALSE; 736 IFont_Release(ifnt2); 737 738 /* Test underline setting */ 739 fd.fUnderline = TRUE; 740 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 741 hres = IFont_IsEqual(ifnt,ifnt2); 742 ok(hres == S_FALSE, 743 "IFont_IsEqual: (Underline) Expected S_FALSE but got 0x%08x\n",hres); 744 fd.fUnderline = FALSE; 745 IFont_Release(ifnt2); 746 747 /* Test strikethrough setting */ 748 fd.fStrikethrough = TRUE; 749 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 750 hres = IFont_IsEqual(ifnt,ifnt2); 751 ok(hres == S_FALSE, 752 "IFont_IsEqual: (Strikethrough) Expected S_FALSE but got 0x%08x\n",hres); 753 fd.fStrikethrough = FALSE; 754 IFont_Release(ifnt2); 755 756 /* Free IFont. */ 757 IFont_Release(ifnt); 758 } 759 760 static void test_ReleaseHfont(void) 761 { 762 FONTDESC fd; 763 LPVOID pvObj1 = NULL; 764 LPVOID pvObj2 = NULL; 765 IFont* ifnt1 = NULL; 766 IFont* ifnt2 = NULL; 767 HFONT hfnt1 = 0; 768 HFONT hfnt2 = 0; 769 HRESULT hres; 770 771 /* Basic font description */ 772 fd.cbSizeofstruct = sizeof(FONTDESC); 773 fd.lpstrName = system_font; 774 S(fd.cySize).Lo = 100; 775 S(fd.cySize).Hi = 100; 776 fd.sWeight = 0; 777 fd.sCharset = 0; 778 fd.fItalic = FALSE; 779 fd.fUnderline = FALSE; 780 fd.fStrikethrough = FALSE; 781 782 /* Create HFONTs and IFONTs */ 783 pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj1); 784 ifnt1 = pvObj1; 785 IFont_get_hFont(ifnt1,&hfnt1); 786 fd.lpstrName = arial_font; 787 pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2); 788 ifnt2 = pvObj2; 789 IFont_get_hFont(ifnt2,&hfnt2); 790 791 /* Try invalid HFONT */ 792 hres = IFont_ReleaseHfont(ifnt1,NULL); 793 ok(hres == E_INVALIDARG, 794 "IFont_ReleaseHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n", 795 hres); 796 797 /* Try to add a bad HFONT */ 798 hres = IFont_ReleaseHfont(ifnt1,(HFONT)32); 799 ok(hres == S_FALSE, 800 "IFont_ReleaseHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n", 801 hres); 802 803 /* Release all refs */ 804 hres = IFont_ReleaseHfont(ifnt1,hfnt1); 805 ok(hres == S_OK, 806 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n", 807 hres); 808 809 hres = IFont_ReleaseHfont(ifnt2,hfnt2); 810 ok(hres == S_OK, 811 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n", 812 hres); 813 814 /* Check that both lists are empty */ 815 hres = IFont_ReleaseHfont(ifnt1,hfnt1); 816 ok(hres == S_FALSE, 817 "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n", 818 hres); 819 820 /* The list should be empty */ 821 hres = IFont_ReleaseHfont(ifnt2,hfnt2); 822 ok(hres == S_FALSE, 823 "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n", 824 hres); 825 826 IFont_Release(ifnt1); 827 IFont_Release(ifnt2); 828 } 829 830 static void test_AddRefHfont(void) 831 { 832 FONTDESC fd; 833 IFont* ifnt1 = NULL; 834 IFont* ifnt2 = NULL; 835 IFont* ifnt3 = NULL; 836 HFONT hfnt1 = 0; 837 HFONT hfnt2 = 0; 838 HFONT hfnt3 = 0; 839 HRESULT hres; 840 841 /* Basic font description */ 842 fd.cbSizeofstruct = sizeof(FONTDESC); 843 fd.lpstrName = system_font; 844 S(fd.cySize).Lo = 100; 845 S(fd.cySize).Hi = 100; 846 fd.sWeight = 0; 847 fd.sCharset = 0; 848 fd.fItalic = FALSE; 849 fd.fUnderline = FALSE; 850 fd.fStrikethrough = FALSE; 851 852 /* Create HFONTs and IFONTs */ 853 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt1); 854 IFont_get_hFont(ifnt1,&hfnt1); 855 fd.lpstrName = arial_font; 856 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2); 857 IFont_get_hFont(ifnt2,&hfnt2); 858 859 /* Try invalid HFONT */ 860 hres = IFont_AddRefHfont(ifnt1,NULL); 861 ok(hres == E_INVALIDARG, 862 "IFont_AddRefHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n", 863 hres); 864 865 /* Try to add a bad HFONT */ 866 hres = IFont_AddRefHfont(ifnt1,(HFONT)32); 867 ok(hres == S_FALSE, 868 "IFont_AddRefHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n", 869 hres); 870 871 /* Add simple IFONT HFONT pair */ 872 hres = IFont_AddRefHfont(ifnt1,hfnt1); 873 ok(hres == S_OK, 874 "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n", 875 hres); 876 877 /* IFONT and HFONT do not have to be the same (always looks at HFONT) */ 878 hres = IFont_AddRefHfont(ifnt2,hfnt1); 879 ok(hres == S_OK, 880 "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n", 881 hres); 882 883 /* Release all hfnt1 refs */ 884 hres = IFont_ReleaseHfont(ifnt1,hfnt1); 885 ok(hres == S_OK, 886 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n", 887 hres); 888 889 hres = IFont_ReleaseHfont(ifnt1,hfnt1); 890 ok(hres == S_OK, 891 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n", 892 hres); 893 894 hres = IFont_ReleaseHfont(ifnt1,hfnt1); 895 ok(hres == S_OK, 896 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n", 897 hres); 898 899 /* Check if hfnt1 is empty */ 900 hres = IFont_ReleaseHfont(ifnt1,hfnt1); 901 ok(hres == S_FALSE, 902 "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n", 903 hres); 904 905 /* Release all hfnt2 refs */ 906 hres = IFont_ReleaseHfont(ifnt2,hfnt2); 907 ok(hres == S_OK, 908 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n", 909 hres); 910 911 /* Check if hfnt2 is empty */ 912 hres = IFont_ReleaseHfont(ifnt2,hfnt2); 913 ok(hres == S_FALSE, 914 "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n", 915 hres); 916 917 /* Show that releasing an IFONT does not always release it from the HFONT cache. */ 918 919 IFont_Release(ifnt1); 920 921 /* Add a reference for destroyed hfnt1 */ 922 hres = IFont_AddRefHfont(ifnt2,hfnt1); 923 ok(hres == S_OK, 924 "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n", 925 hres); 926 927 /* Decrement reference for destroyed hfnt1 */ 928 hres = IFont_ReleaseHfont(ifnt2,hfnt1); 929 ok(hres == S_OK || 930 hres == S_FALSE, /* <= win2k */ 931 "IFont_AddRefHfont: (Release ref) Expected S_OK or S_FALSE but got 0x%08x\n", 932 hres); 933 934 /* Shows that releasing all IFONT's does clear the HFONT cache. */ 935 936 IFont_Release(ifnt2); 937 938 /* Need to make a new IFONT for testing */ 939 fd.fUnderline = TRUE; 940 pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt3); 941 IFont_get_hFont(ifnt3,&hfnt3); 942 943 /* Add a reference for destroyed hfnt1 */ 944 hres = IFont_AddRefHfont(ifnt3,hfnt1); 945 ok(hres == S_FALSE, 946 "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n", 947 hres); 948 949 /* Decrement reference for destroyed hfnt1 */ 950 hres = IFont_ReleaseHfont(ifnt3,hfnt1); 951 ok(hres == S_FALSE, 952 "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n", 953 hres); 954 955 IFont_Release(ifnt3); 956 } 957 958 static void test_returns(void) 959 { 960 IFont *pFont; 961 FONTDESC fontdesc; 962 HRESULT hr; 963 964 fontdesc.cbSizeofstruct = sizeof(fontdesc); 965 fontdesc.lpstrName = MSSansSerif_font; 966 fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */ 967 fontdesc.sWeight = FW_NORMAL; 968 fontdesc.sCharset = 0; 969 fontdesc.fItalic = FALSE; 970 fontdesc.fUnderline = FALSE; 971 fontdesc.fStrikethrough = FALSE; 972 973 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&pFont); 974 EXPECT_HR(hr, S_OK); 975 976 hr = IFont_put_Name(pFont, NULL); 977 EXPECT_HR(hr, CTL_E_INVALIDPROPERTYVALUE); 978 979 hr = IFont_get_Name(pFont, NULL); 980 EXPECT_HR(hr, E_POINTER); 981 982 hr = IFont_get_Size(pFont, NULL); 983 EXPECT_HR(hr, E_POINTER); 984 985 hr = IFont_get_Bold(pFont, NULL); 986 EXPECT_HR(hr, E_POINTER); 987 988 IFont_Release(pFont); 989 } 990 991 static void test_hfont_lifetime(void) 992 { 993 IFont *font, *font2; 994 FONTDESC fontdesc; 995 HRESULT hr; 996 HFONT hfont, first_hfont = NULL; 997 CY size; 998 DWORD obj_type; 999 int i; 1000 1001 fontdesc.cbSizeofstruct = sizeof(fontdesc); 1002 fontdesc.lpstrName = arial_font; 1003 fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */ 1004 fontdesc.sWeight = FW_NORMAL; 1005 fontdesc.sCharset = ANSI_CHARSET; 1006 fontdesc.fItalic = FALSE; 1007 fontdesc.fUnderline = FALSE; 1008 fontdesc.fStrikethrough = FALSE; 1009 1010 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&font); 1011 EXPECT_HR(hr, S_OK); 1012 1013 hr = IFont_get_hFont(font, &hfont); 1014 EXPECT_HR(hr, S_OK); 1015 1016 /* show that if the font is updated the old hfont is deleted when the 1017 new font is realized */ 1018 for(i = 0; i < 100; i++) 1019 { 1020 HFONT last_hfont = hfont; 1021 1022 size.int64 = (i + 10) * 20000; 1023 1024 obj_type = GetObjectType(hfont); 1025 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1026 1027 hr = IFont_put_Size(font, size); 1028 EXPECT_HR(hr, S_OK); 1029 1030 /* put_Size doesn't cause the new font to be realized */ 1031 obj_type = GetObjectType(last_hfont); 1032 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1033 1034 hr = IFont_get_hFont(font, &hfont); 1035 EXPECT_HR(hr, S_OK); 1036 1037 obj_type = GetObjectType(last_hfont); 1038 ok(obj_type == 0, "%d: got obj type %d\n", i, obj_type); 1039 } 1040 1041 /* now show that if we take a reference on the hfont, it persists 1042 until the font object is released */ 1043 for(i = 0; i < 100; i++) 1044 { 1045 size.int64 = (i + 10) * 20000; 1046 1047 obj_type = GetObjectType(hfont); 1048 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1049 1050 hr = IFont_put_Size(font, size); 1051 EXPECT_HR(hr, S_OK); 1052 1053 hr = IFont_get_hFont(font, &hfont); 1054 EXPECT_HR(hr, S_OK); 1055 1056 hr = IFont_AddRefHfont(font, hfont); 1057 EXPECT_HR(hr, S_OK); 1058 1059 if(i == 0) first_hfont = hfont; 1060 obj_type = GetObjectType(first_hfont); 1061 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1062 } 1063 1064 IFont_Release(font); 1065 1066 obj_type = GetObjectType(first_hfont); 1067 ok(obj_type == 0, "got obj type %d\n", obj_type); 1068 1069 /* An AddRefHfont followed by a ReleaseHfont means the font doesn't not persist 1070 through re-realization */ 1071 1072 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&font); 1073 EXPECT_HR(hr, S_OK); 1074 1075 hr = IFont_get_hFont(font, &hfont); 1076 EXPECT_HR(hr, S_OK); 1077 1078 for(i = 0; i < 100; i++) 1079 { 1080 HFONT last_hfont = hfont; 1081 1082 size.int64 = (i + 10) * 20000; 1083 1084 obj_type = GetObjectType(hfont); 1085 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1086 1087 hr = IFont_put_Size(font, size); 1088 EXPECT_HR(hr, S_OK); 1089 1090 /* put_Size doesn't cause the new font to be realized */ 1091 obj_type = GetObjectType(last_hfont); 1092 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1093 1094 hr = IFont_get_hFont(font, &hfont); 1095 EXPECT_HR(hr, S_OK); 1096 1097 hr = IFont_AddRefHfont(font, hfont); 1098 EXPECT_HR(hr, S_OK); 1099 1100 hr = IFont_ReleaseHfont(font, hfont); 1101 EXPECT_HR(hr, S_OK); 1102 1103 obj_type = GetObjectType(last_hfont); 1104 ok(obj_type == 0, "%d: got obj type %d\n", i, obj_type); 1105 } 1106 1107 /* Interestingly if we release a nonexistent reference on the hfont, 1108 * it persists until the font object is released 1109 */ 1110 for(i = 0; i < 100; i++) 1111 { 1112 size.int64 = (i + 10) * 20000; 1113 1114 obj_type = GetObjectType(hfont); 1115 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1116 1117 hr = IFont_put_Size(font, size); 1118 EXPECT_HR(hr, S_OK); 1119 1120 hr = IFont_get_hFont(font, &hfont); 1121 EXPECT_HR(hr, S_OK); 1122 1123 hr = IFont_ReleaseHfont(font, hfont); 1124 EXPECT_HR(hr, S_OK); 1125 1126 if(i == 0) first_hfont = hfont; 1127 obj_type = GetObjectType(first_hfont); 1128 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1129 } 1130 1131 IFont_Release(font); 1132 1133 obj_type = GetObjectType(first_hfont); 1134 ok(obj_type == 0, "got obj type %d\n", obj_type); 1135 1136 /* If we take two internal references on a hfont then we can release 1137 it twice. So it looks like there's a total reference count 1138 that includes internal and external references */ 1139 1140 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&font); 1141 EXPECT_HR(hr, S_OK); 1142 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&font2); 1143 EXPECT_HR(hr, S_OK); 1144 1145 hr = IFont_get_hFont(font, &hfont); 1146 EXPECT_HR(hr, S_OK); 1147 hr = IFont_get_hFont(font2, &first_hfont); 1148 EXPECT_HR(hr, S_OK); 1149 todo_wine 1150 ok(hfont == first_hfont, "fonts differ\n"); 1151 hr = IFont_ReleaseHfont(font, hfont); 1152 EXPECT_HR(hr, S_OK); 1153 hr = IFont_ReleaseHfont(font, hfont); 1154 todo_wine 1155 EXPECT_HR(hr, S_OK); 1156 hr = IFont_ReleaseHfont(font, hfont); 1157 EXPECT_HR(hr, S_FALSE); 1158 1159 obj_type = GetObjectType(hfont); 1160 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1161 1162 IFont_Release(font); 1163 1164 obj_type = GetObjectType(hfont); 1165 ok(obj_type == OBJ_FONT, "got obj type %d\n", obj_type); 1166 1167 IFont_Release(font2); 1168 1169 obj_type = GetObjectType(hfont); 1170 ok(obj_type == 0, "got obj type %d\n", obj_type); 1171 } 1172 1173 static void test_realization(void) 1174 { 1175 IFont *font; 1176 FONTDESC fontdesc; 1177 HRESULT hr; 1178 BSTR name; 1179 SHORT cs; 1180 1181 /* Try to create a symbol only font (marlett) with charset 1182 set to ANSI. This will result in another, ANSI, font 1183 being selected */ 1184 fontdesc.cbSizeofstruct = sizeof(fontdesc); 1185 fontdesc.lpstrName = marlett_font; 1186 fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */ 1187 fontdesc.sWeight = FW_NORMAL; 1188 fontdesc.sCharset = ANSI_CHARSET; 1189 fontdesc.fItalic = FALSE; 1190 fontdesc.fUnderline = FALSE; 1191 fontdesc.fStrikethrough = FALSE; 1192 1193 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&font); 1194 EXPECT_HR(hr, S_OK); 1195 1196 hr = IFont_get_Charset(font, &cs); 1197 EXPECT_HR(hr, S_OK); 1198 ok(cs == ANSI_CHARSET, "got charset %d\n", cs); 1199 1200 IFont_Release(font); 1201 1202 /* Now create an ANSI font and change the name to marlett */ 1203 1204 fontdesc.lpstrName = arial_font; 1205 1206 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&font); 1207 EXPECT_HR(hr, S_OK); 1208 1209 hr = IFont_get_Charset(font, &cs); 1210 EXPECT_HR(hr, S_OK); 1211 ok(cs == ANSI_CHARSET, "got charset %d\n", cs); 1212 1213 name = SysAllocString(marlett_font); 1214 hr = IFont_put_Name(font, name); 1215 EXPECT_HR(hr, S_OK); 1216 SysFreeString(name); 1217 1218 hr = IFont_get_Name(font, &name); 1219 EXPECT_HR(hr, S_OK); 1220 ok(!lstrcmpiW(name, marlett_font), "got name %s\n", wine_dbgstr_w(name)); 1221 SysFreeString(name); 1222 1223 hr = IFont_get_Charset(font, &cs); 1224 EXPECT_HR(hr, S_OK); 1225 ok(cs == SYMBOL_CHARSET, "got charset %d\n", cs); 1226 1227 IFont_Release(font); 1228 } 1229 1230 static void test_OleCreateFontIndirect(void) 1231 { 1232 FONTDESC fontdesc; 1233 IUnknown *unk, *unk2; 1234 IFont *font; 1235 HRESULT hr; 1236 1237 fontdesc.cbSizeofstruct = sizeof(fontdesc); 1238 fontdesc.lpstrName = arial_font; 1239 fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */ 1240 fontdesc.sWeight = FW_NORMAL; 1241 fontdesc.sCharset = ANSI_CHARSET; 1242 fontdesc.fItalic = FALSE; 1243 fontdesc.fUnderline = FALSE; 1244 fontdesc.fStrikethrough = FALSE; 1245 1246 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void**)&font); 1247 EXPECT_HR(hr, S_OK); 1248 IFont_Release(font); 1249 1250 /* play with cbSizeofstruct value */ 1251 fontdesc.cbSizeofstruct = sizeof(fontdesc)-1; 1252 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void**)&font); 1253 EXPECT_HR(hr, S_OK); 1254 IFont_Release(font); 1255 1256 fontdesc.cbSizeofstruct = sizeof(fontdesc)+1; 1257 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void**)&font); 1258 EXPECT_HR(hr, S_OK); 1259 IFont_Release(font); 1260 1261 fontdesc.cbSizeofstruct = 0; 1262 hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void**)&font); 1263 EXPECT_HR(hr, S_OK); 1264 IFont_Release(font); 1265 1266 hr = OleInitialize(NULL); 1267 ok(hr == S_OK, "got 0x%08x\n", hr); 1268 1269 hr = CoGetClassObject(&CLSID_StdFont, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&unk); 1270 ok(hr == S_OK, "got 0x%08x\n", hr); 1271 1272 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void**)&unk2); 1273 ok(hr == S_OK, "got 0x%08x\n", hr); 1274 1275 IUnknown_Release(unk); 1276 IUnknown_Release(unk2); 1277 1278 OleUninitialize(); 1279 } 1280 1281 START_TEST(olefont) 1282 { 1283 hOleaut32 = GetModuleHandleA("oleaut32.dll"); 1284 pOleCreateFontIndirect = (void*)GetProcAddress(hOleaut32, "OleCreateFontIndirect"); 1285 if (!pOleCreateFontIndirect) 1286 { 1287 win_skip("OleCreateFontIndirect not available\n"); 1288 return; 1289 } 1290 1291 test_QueryInterface(); 1292 test_type_info(); 1293 test_ifont_sizes(); 1294 test_font_events_disp(); 1295 test_GetIDsOfNames(); 1296 test_Invoke(); 1297 test_IsEqual(); 1298 test_ReleaseHfont(); 1299 test_AddRefHfont(); 1300 test_returns(); 1301 test_hfont_lifetime(); 1302 test_realization(); 1303 test_OleCreateFontIndirect(); 1304 } 1305