1 /* 2 * Unit tests for metafile functions 3 * 4 * Copyright (c) 2002 Dmitry Timoshkov 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "precomp.h" 22 23 static LOGFONTA orig_lf; 24 static BOOL emr_processed = FALSE; 25 26 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */ 27 #define LINE_X 55.0f 28 #define LINE_Y 15.0f 29 30 static INT (WINAPI * pGetRelAbs)(HDC, DWORD); 31 static INT (WINAPI * pSetRelAbs)(HDC, INT); 32 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF); 33 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF); 34 35 #define GDI_GET_PROC(func) \ 36 p ## func = (void *)GetProcAddress(hGDI, #func); \ 37 if(!p ## func) \ 38 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \ 39 40 static void init_function_pointers(void) 41 { 42 HMODULE hGDI; 43 44 pGetRelAbs = NULL; 45 pSetRelAbs = NULL; 46 47 hGDI = GetModuleHandleA("gdi32.dll"); 48 assert(hGDI); 49 GDI_GET_PROC(GetRelAbs); 50 GDI_GET_PROC(SetRelAbs); 51 GDI_GET_PROC(SetDCBrushColor); 52 GDI_GET_PROC(SetDCPenColor); 53 } 54 55 static DWORD rgn_rect_count(HRGN hrgn) 56 { 57 DWORD size; 58 RGNDATA *data; 59 60 if (!hrgn) return 0; 61 if (!(size = GetRegionData(hrgn, 0, NULL))) return 0; 62 if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return 0; 63 GetRegionData(hrgn, size, data); 64 size = data->rdh.nCount; 65 HeapFree(GetProcessHeap(), 0, data); 66 return size; 67 } 68 69 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, 70 const ENHMETARECORD *emr, int n_objs, LPARAM param) 71 { 72 static int n_record; 73 DWORD i; 74 const INT *dx; 75 INT *orig_dx = (INT *)param; 76 LOGFONTA device_lf; 77 INT ret; 78 79 if(!hdc) return 1; 80 81 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs); 82 83 switch (emr->iType) 84 { 85 case EMR_HEADER: 86 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc)); 87 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc)); 88 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc)); 89 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc)); 90 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc)); 91 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc)); 92 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc)); 93 94 /* GetBkMode, GetRelAbs do not get reset to the default value */ 95 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc)); 96 if(pSetRelAbs && pGetRelAbs) 97 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0)); 98 99 n_record = 0; 100 break; 101 102 case EMR_EXTTEXTOUTA: 103 { 104 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr; 105 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx); 106 107 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf); 108 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError()); 109 110 /* compare up to lfOutPrecision, other values are not interesting, 111 * and in fact sometimes arbitrary adapted by Win9x. 112 */ 113 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n"); 114 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n"); 115 116 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++) 117 { 118 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n", 119 n_record, i, dx[i], orig_dx[i]); 120 } 121 n_record++; 122 emr_processed = TRUE; 123 break; 124 } 125 126 case EMR_EXTTEXTOUTW: 127 { 128 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr; 129 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx); 130 131 SetLastError(0xdeadbeef); 132 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf); 133 ok( ret == sizeof(device_lf) || 134 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */ 135 "GetObjectA error %d\n", GetLastError()); 136 137 /* compare up to lfOutPrecision, other values are not interesting, 138 * and in fact sometimes arbitrary adapted by Win9x. 139 */ 140 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n"); 141 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n"); 142 143 ok(!emr_ExtTextOutW->rclBounds.left, "emr_ExtTextOutW->rclBounds.left = %d\n", 144 emr_ExtTextOutW->rclBounds.left); 145 ok(emr_ExtTextOutW->rclBounds.right != -1, "emr_ExtTextOutW->rclBounds.right = %d\n", 146 emr_ExtTextOutW->rclBounds.right); 147 ok(emr_ExtTextOutW->rclBounds.bottom != -1, "emr_ExtTextOutW->rclBounds.bottom = %d\n", 148 emr_ExtTextOutW->rclBounds.bottom); 149 150 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++) 151 { 152 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n", 153 n_record, i, dx[i], orig_dx[i]); 154 } 155 n_record++; 156 emr_processed = TRUE; 157 break; 158 } 159 160 default: 161 break; 162 } 163 164 return 1; 165 } 166 167 static void test_ExtTextOut(void) 168 { 169 HWND hwnd; 170 HDC hdcDisplay, hdcMetafile; 171 HENHMETAFILE hMetafile; 172 HFONT hFont; 173 static const char text[] = "Simple text to test ExtTextOut on metafiles"; 174 INT i, len, dx[256]; 175 static const RECT rc = { 0, 0, 100, 100 }; 176 BOOL ret; 177 178 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text)); 179 180 /* Win9x doesn't play EMFs on invisible windows */ 181 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE, 182 0, 0, 200, 200, 0, 0, 0, NULL); 183 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError()); 184 185 hdcDisplay = GetDC(hwnd); 186 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError()); 187 188 trace("hdcDisplay %p\n", hdcDisplay); 189 190 SetMapMode(hdcDisplay, MM_TEXT); 191 192 memset(&orig_lf, 0, sizeof(orig_lf)); 193 194 orig_lf.lfCharSet = ANSI_CHARSET; 195 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; 196 orig_lf.lfWeight = FW_DONTCARE; 197 orig_lf.lfHeight = 7; 198 orig_lf.lfQuality = DEFAULT_QUALITY; 199 lstrcpyA(orig_lf.lfFaceName, "Arial"); 200 hFont = CreateFontIndirectA(&orig_lf); 201 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError()); 202 203 hFont = SelectObject(hdcDisplay, hFont); 204 205 len = lstrlenA(text); 206 for (i = 0; i < len; i++) 207 { 208 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]); 209 ok( ret, "GetCharWidthA error %d\n", GetLastError()); 210 } 211 hFont = SelectObject(hdcDisplay, hFont); 212 213 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL); 214 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError()); 215 216 trace("hdcMetafile %p\n", hdcMetafile); 217 218 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY, 219 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n"); 220 221 hFont = SelectObject(hdcMetafile, hFont); 222 223 /* 1. pass NULL lpDx */ 224 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL); 225 ok( ret, "ExtTextOutA error %d\n", GetLastError()); 226 227 /* 2. pass custom lpDx */ 228 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx); 229 ok( ret, "ExtTextOutA error %d\n", GetLastError()); 230 231 /* 3. pass NULL lprc */ 232 ret = ExtTextOutA(hdcMetafile, 0, 40, 0, NULL, text, lstrlenA(text), NULL); 233 ok( ret, "ExtTextOutA error %d\n", GetLastError()); 234 235 /* 4. test with unmatched BeginPath/EndPath calls */ 236 ret = BeginPath(hdcMetafile); 237 ok( ret, "BeginPath error %d\n", GetLastError()); 238 ret = BeginPath(hdcMetafile); 239 ok( ret, "BeginPath error %d\n", GetLastError()); 240 ret = EndPath(hdcMetafile); 241 ok( ret, "BeginPath error %d\n", GetLastError()); 242 ret = ExtTextOutA(hdcMetafile, 0, 60, 0, NULL, text, lstrlenA(text), NULL); 243 ok( ret, "ExtTextOutA error %d\n", GetLastError()); 244 245 hFont = SelectObject(hdcMetafile, hFont); 246 ret = DeleteObject(hFont); 247 ok( ret, "DeleteObject error %d\n", GetLastError()); 248 249 hMetafile = CloseEnhMetaFile(hdcMetafile); 250 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 251 252 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n"); 253 254 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc); 255 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError()); 256 257 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING ); 258 SetBkColor(hdcDisplay, RGB(0xff, 0, 0)); 259 SetTextColor(hdcDisplay, RGB(0, 0xff, 0)); 260 SetROP2(hdcDisplay, R2_NOT); 261 SetArcDirection(hdcDisplay, AD_CLOCKWISE); 262 SetPolyFillMode(hdcDisplay, WINDING); 263 SetStretchBltMode(hdcDisplay, HALFTONE); 264 265 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE); 266 SetBkMode(hdcDisplay, OPAQUE); 267 268 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc); 269 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError()); 270 271 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING), 272 "text align %08x\n", GetTextAlign(hdcDisplay)); 273 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay)); 274 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay)); 275 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay)); 276 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay)); 277 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay)); 278 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay)); 279 280 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n"); 281 282 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL), 283 "A valid hdc has to require a valid rc\n"); 284 285 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL), 286 "A null hdc does not require a valid rc\n"); 287 288 ret = DeleteEnhMetaFile(hMetafile); 289 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError()); 290 ret = ReleaseDC(hwnd, hdcDisplay); 291 ok( ret, "ReleaseDC error %d\n", GetLastError()); 292 DestroyWindow(hwnd); 293 } 294 295 struct eto_scale_test_record 296 { 297 INT graphics_mode; 298 INT map_mode; 299 double ex_scale; 300 double ey_scale; 301 BOOL processed; 302 }; 303 304 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table, 305 const ENHMETARECORD *emr, int n_objs, LPARAM param) 306 { 307 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param; 308 309 if (emr->iType == EMR_EXTTEXTOUTW) 310 { 311 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr; 312 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001, 313 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale); 314 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001, 315 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale); 316 test->processed = TRUE; 317 } 318 319 return 1; 320 } 321 322 static void test_ExtTextOutScale(void) 323 { 324 const RECT rc = { 0, 0, 100, 100 }; 325 const WCHAR str[] = {'a',0 }; 326 struct eto_scale_test_record test; 327 HDC hdcDisplay, hdcMetafile; 328 HENHMETAFILE hMetafile; 329 HWND hwnd; 330 SIZE wndext, vportext; 331 int horzSize, vertSize, horzRes, vertRes; 332 int ret; 333 int i; 334 335 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE, 336 0, 0, 200, 200, 0, 0, 0, NULL); 337 ok(hwnd != 0, "CreateWindowExA failed\n"); 338 339 hdcDisplay = GetDC(hwnd); 340 ok(hdcDisplay != 0, "GetDC failed\n"); 341 342 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE); 343 horzRes = GetDeviceCaps(hdcDisplay, HORZRES); 344 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE); 345 vertRes = GetDeviceCaps(hdcDisplay, VERTRES); 346 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n"); 347 348 for (i = 0; i < 16; i++) 349 { 350 test.graphics_mode = i / 8 + 1; 351 test.map_mode = i % 8 + 1; 352 353 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode); 354 ok(ret, "SetGraphicsMode failed\n"); 355 ret = SetMapMode(hdcDisplay, test.map_mode); 356 ok(ret, "SetMapMode failed\n"); 357 358 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC)) 359 { 360 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL); 361 ok(ret, "SetWindowExtEx failed\n"); 362 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL); 363 ok(ret, "SetViewportExtEx failed\n"); 364 } 365 366 ret = GetViewportExtEx(hdcDisplay, &vportext); 367 ok(ret, "GetViewportExtEx failed\n"); 368 ret = GetWindowExtEx(hdcDisplay, &wndext); 369 ok(ret, "GetWindowExtEx failed\n"); 370 371 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n", 372 test.graphics_mode, test.map_mode, 373 wndext.cx, wndext.cy, vportext.cx, vportext.cy, 374 horzSize, horzRes, vertSize, vertRes); 375 376 if (test.graphics_mode == GM_COMPATIBLE) 377 { 378 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) / 379 ((FLOAT)wndext.cx / (FLOAT)vportext.cx); 380 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) / 381 ((FLOAT)wndext.cy / (FLOAT)vportext.cy); 382 } 383 else 384 { 385 test.ex_scale = 0.0; 386 test.ey_scale = 0.0; 387 } 388 389 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL); 390 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n"); 391 392 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode); 393 ok(ret, "SetGraphicsMode failed\n"); 394 ret = SetMapMode(hdcMetafile, test.map_mode); 395 ok(ret, "SetMapMode failed\n"); 396 397 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC)) 398 { 399 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL); 400 ok(ret, "SetWindowExtEx failed\n"); 401 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL); 402 ok(ret, "SetViewportExtEx failed\n"); 403 } 404 405 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL); 406 ok(ret, "ExtTextOutW failed\n"); 407 408 hMetafile = CloseEnhMetaFile(hdcMetafile); 409 ok(hMetafile != 0, "CloseEnhMetaFile failed\n"); 410 411 test.processed = 0; 412 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc); 413 ok(ret, "EnumEnhMetaFile failed\n"); 414 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n"); 415 416 ret = DeleteEnhMetaFile(hMetafile); 417 ok(ret, "DeleteEnhMetaFile failed\n"); 418 } 419 420 ret = ReleaseDC(hwnd, hdcDisplay); 421 ok(ret, "ReleaseDC failed\n"); 422 DestroyWindow(hwnd); 423 } 424 425 426 static void check_dc_state(HDC hdc, int restore_no, 427 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y, 428 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y) 429 { 430 BOOL ret; 431 XFORM xform; 432 POINT vp_org, win_org; 433 SIZE vp_size, win_size; 434 FLOAT xscale, yscale, edx, edy; 435 436 SetLastError(0xdeadbeef); 437 ret = GetWorldTransform(hdc, &xform); 438 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here; 439 ok(ret, "GetWorldTransform error %u\n", GetLastError()); 440 441 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy); 442 443 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12); 444 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21); 445 446 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x; 447 trace("x scale %f\n", xscale); 448 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n", 449 restore_no, vp_ext_x, wnd_ext_x, xform.eM11); 450 451 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y; 452 trace("y scale %f\n", yscale); 453 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n", 454 restore_no, vp_ext_y, wnd_ext_y, xform.eM22); 455 456 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x; 457 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx); 458 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y; 459 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy); 460 461 return; 462 463 win9x_here: 464 465 GetWindowOrgEx(hdc, &win_org); 466 GetViewportOrgEx(hdc, &vp_org); 467 GetWindowExtEx(hdc, &win_size); 468 GetViewportExtEx(hdc, &vp_size); 469 470 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x); 471 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y); 472 473 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x); 474 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y); 475 476 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx); 477 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy); 478 479 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx); 480 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy); 481 } 482 483 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, 484 const ENHMETARECORD *emr, int n_objs, LPARAM param) 485 { 486 BOOL ret; 487 XFORM xform; 488 POINT pt; 489 SIZE size; 490 static int save_state; 491 static int restore_no; 492 static int select_no; 493 494 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n", 495 hdc, emr->iType, emr->nSize, (void *)param); 496 497 SetLastError(0xdeadbeef); 498 ret = GetWorldTransform(hdc, &xform); 499 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 500 { 501 ret = GetWindowOrgEx(hdc, &pt); 502 ok(ret, "GetWindowOrgEx error %u\n", GetLastError()); 503 trace("window org (%d,%d)\n", pt.x, pt.y); 504 ret = GetViewportOrgEx(hdc, &pt); 505 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 506 trace("vport org (%d,%d)\n", pt.x, pt.y); 507 ret = GetWindowExtEx(hdc, &size); 508 ok(ret, "GetWindowExtEx error %u\n", GetLastError()); 509 trace("window ext (%d,%d)\n", size.cx, size.cy); 510 ret = GetViewportExtEx(hdc, &size); 511 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 512 trace("vport ext (%d,%d)\n", size.cx, size.cy); 513 } 514 else 515 { 516 ok(ret, "GetWorldTransform error %u\n", GetLastError()); 517 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy); 518 } 519 520 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs); 521 522 switch (emr->iType) 523 { 524 case EMR_HEADER: 525 { 526 static RECT exp_bounds = { 0, 0, 150, 150 }; 527 RECT bounds; 528 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr; 529 530 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n", 531 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom, 532 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom); 533 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy, 534 emf->szlDevice.cx, emf->szlDevice.cy); 535 536 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom); 537 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n"); 538 539 save_state = 0; 540 restore_no = 0; 541 select_no = 0; 542 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1); 543 break; 544 } 545 546 case EMR_LINETO: 547 { 548 const EMRLINETO *line = (const EMRLINETO *)emr; 549 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x); 550 break; 551 } 552 case EMR_SETWINDOWORGEX: 553 { 554 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr; 555 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y); 556 break; 557 } 558 case EMR_SETWINDOWEXTEX: 559 { 560 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr; 561 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy); 562 break; 563 } 564 case EMR_SETVIEWPORTORGEX: 565 { 566 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr; 567 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y); 568 break; 569 } 570 case EMR_SETVIEWPORTEXTEX: 571 { 572 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr; 573 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy); 574 break; 575 } 576 case EMR_SAVEDC: 577 save_state++; 578 trace("EMR_SAVEDC\n"); 579 break; 580 581 case EMR_RESTOREDC: 582 { 583 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr; 584 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative); 585 586 switch(++restore_no) 587 { 588 case 1: 589 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative); 590 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478); 591 break; 592 case 2: 593 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative); 594 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872); 595 break; 596 case 3: 597 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative); 598 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276); 599 break; 600 } 601 ok(restore_no <= 3, "restore_no %d\n", restore_no); 602 save_state += restoredc->iRelative; 603 break; 604 } 605 case EMR_SELECTOBJECT: 606 { 607 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr; 608 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject); 609 select_no ++; 610 break; 611 } 612 case EMR_EOF: 613 ok(save_state == 0, "EOF save_state %d\n", save_state); 614 ok(select_no == 3, "Too many/few selects %i\n",select_no); 615 break; 616 } 617 618 SetLastError(0xdeadbeef); 619 ret = GetWorldTransform(hdc, &xform); 620 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 621 { 622 ret = GetWindowOrgEx(hdc, &pt); 623 ok(ret, "GetWindowOrgEx error %u\n", GetLastError()); 624 trace("window org (%d,%d)\n", pt.x, pt.y); 625 ret = GetViewportOrgEx(hdc, &pt); 626 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 627 trace("vport org (%d,%d)\n", pt.x, pt.y); 628 ret = GetWindowExtEx(hdc, &size); 629 ok(ret, "GetWindowExtEx error %u\n", GetLastError()); 630 trace("window ext (%d,%d)\n", size.cx, size.cy); 631 ret = GetViewportExtEx(hdc, &size); 632 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 633 trace("vport ext (%d,%d)\n", size.cx, size.cy); 634 } 635 else 636 { 637 ok(ret, "GetWorldTransform error %u\n", GetLastError()); 638 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy); 639 } 640 641 return 1; 642 } 643 644 static void test_SaveDC(void) 645 { 646 HDC hdcMetafile, hdcDisplay; 647 HENHMETAFILE hMetafile; 648 HWND hwnd; 649 int ret; 650 POINT pt; 651 SIZE size; 652 HFONT hFont,hFont2,hFontOld,hFontCheck; 653 static const RECT rc = { 0, 0, 150, 150 }; 654 655 /* Win9x doesn't play EMFs on invisible windows */ 656 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE, 657 0, 0, 200, 200, 0, 0, 0, NULL); 658 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError()); 659 660 hdcDisplay = GetDC(hwnd); 661 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError()); 662 663 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL); 664 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError()); 665 666 SetMapMode(hdcMetafile, MM_ANISOTROPIC); 667 668 /* Need to write something to the emf, otherwise Windows won't play it back */ 669 LineTo(hdcMetafile, 150, 150); 670 671 SetWindowOrgEx(hdcMetafile, 0, 0, NULL); 672 SetViewportOrgEx(hdcMetafile, 0, 0, NULL); 673 SetWindowExtEx(hdcMetafile, 110, 110, NULL ); 674 SetViewportExtEx(hdcMetafile, 120, 120, NULL ); 675 676 /* Force Win9x to update DC state */ 677 SetPixelV(hdcMetafile, 50, 50, 0); 678 679 ret = GetViewportOrgEx(hdcMetafile, &pt); 680 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 681 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x); 682 ret = GetViewportExtEx(hdcMetafile, &size); 683 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 684 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx); 685 ret = SaveDC(hdcMetafile); 686 ok(ret == 1, "ret = %d\n", ret); 687 688 SetWindowOrgEx(hdcMetafile, -1, -1, NULL); 689 SetViewportOrgEx(hdcMetafile, 10, 10, NULL); 690 SetWindowExtEx(hdcMetafile, 150, 150, NULL ); 691 SetViewportExtEx(hdcMetafile, 200, 200, NULL ); 692 693 /* Force Win9x to update DC state */ 694 SetPixelV(hdcMetafile, 50, 50, 0); 695 696 ret = GetViewportOrgEx(hdcMetafile, &pt); 697 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 698 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x); 699 ret = GetViewportExtEx(hdcMetafile, &size); 700 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 701 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx); 702 ret = SaveDC(hdcMetafile); 703 ok(ret == 2, "ret = %d\n", ret); 704 705 SetWindowOrgEx(hdcMetafile, -2, -2, NULL); 706 SetViewportOrgEx(hdcMetafile, 20, 20, NULL); 707 SetWindowExtEx(hdcMetafile, 120, 120, NULL ); 708 SetViewportExtEx(hdcMetafile, 300, 300, NULL ); 709 SetPolyFillMode( hdcMetafile, ALTERNATE ); 710 SetBkColor( hdcMetafile, 0 ); 711 712 /* Force Win9x to update DC state */ 713 SetPixelV(hdcMetafile, 50, 50, 0); 714 715 ret = GetViewportOrgEx(hdcMetafile, &pt); 716 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 717 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x); 718 ret = GetViewportExtEx(hdcMetafile, &size); 719 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 720 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx); 721 ret = SaveDC(hdcMetafile); 722 ok(ret == 3, "ret = %d\n", ret); 723 724 SetWindowOrgEx(hdcMetafile, -3, -3, NULL); 725 SetViewportOrgEx(hdcMetafile, 30, 30, NULL); 726 SetWindowExtEx(hdcMetafile, 200, 200, NULL ); 727 SetViewportExtEx(hdcMetafile, 400, 400, NULL ); 728 729 SetPolyFillMode( hdcMetafile, WINDING ); 730 SetBkColor( hdcMetafile, 0x123456 ); 731 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" ); 732 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" ); 733 734 /* Force Win9x to update DC state */ 735 SetPixelV(hdcMetafile, 50, 50, 0); 736 737 ret = GetViewportOrgEx(hdcMetafile, &pt); 738 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 739 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x); 740 ret = GetViewportExtEx(hdcMetafile, &size); 741 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 742 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx); 743 ret = RestoreDC(hdcMetafile, -1); 744 ok(ret, "ret = %d\n", ret); 745 746 ret = GetViewportOrgEx(hdcMetafile, &pt); 747 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 748 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x); 749 ret = GetViewportExtEx(hdcMetafile, &size); 750 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 751 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx); 752 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" ); 753 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" ); 754 ret = SaveDC(hdcMetafile); 755 ok(ret == 3, "ret = %d\n", ret); 756 757 ret = GetViewportOrgEx(hdcMetafile, &pt); 758 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 759 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x); 760 ret = GetViewportExtEx(hdcMetafile, &size); 761 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 762 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx); 763 ret = RestoreDC(hdcMetafile, 1); 764 ok(ret, "ret = %d\n", ret); 765 ret = GetViewportOrgEx(hdcMetafile, &pt); 766 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 767 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x); 768 ret = GetViewportExtEx(hdcMetafile, &size); 769 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 770 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx); 771 772 SetWindowOrgEx(hdcMetafile, -4, -4, NULL); 773 SetViewportOrgEx(hdcMetafile, 40, 40, NULL); 774 SetWindowExtEx(hdcMetafile, 500, 500, NULL ); 775 SetViewportExtEx(hdcMetafile, 50, 50, NULL ); 776 777 /* Force Win9x to update DC state */ 778 SetPixelV(hdcMetafile, 50, 50, 0); 779 780 ret = GetViewportOrgEx(hdcMetafile, &pt); 781 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 782 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x); 783 ret = GetViewportExtEx(hdcMetafile, &size); 784 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 785 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx); 786 ret = SaveDC(hdcMetafile); 787 ok(ret == 1, "ret = %d\n", ret); 788 789 ret = GetViewportOrgEx(hdcMetafile, &pt); 790 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 791 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x); 792 ret = GetViewportExtEx(hdcMetafile, &size); 793 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 794 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx); 795 ret = SaveDC(hdcMetafile); 796 ok(ret == 2, "ret = %d\n", ret); 797 798 memset(&orig_lf, 0, sizeof(orig_lf)); 799 orig_lf.lfCharSet = ANSI_CHARSET; 800 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; 801 orig_lf.lfWeight = FW_DONTCARE; 802 orig_lf.lfHeight = 7; 803 orig_lf.lfQuality = DEFAULT_QUALITY; 804 lstrcpyA(orig_lf.lfFaceName, "Arial"); 805 hFont = CreateFontIndirectA(&orig_lf); 806 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError()); 807 808 hFontOld = SelectObject(hdcMetafile, hFont); 809 810 hFont2 = CreateFontIndirectA(&orig_lf); 811 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError()); 812 hFontCheck = SelectObject(hdcMetafile, hFont2); 813 ok(hFontCheck == hFont, "Font not selected\n"); 814 815 /* Force Win9x to update DC state */ 816 SetPixelV(hdcMetafile, 50, 50, 0); 817 818 ret = RestoreDC(hdcMetafile, 1); 819 ok(ret, "ret = %d\n", ret); 820 ret = GetViewportOrgEx(hdcMetafile, &pt); 821 ok(ret, "GetViewportOrgEx error %u\n", GetLastError()); 822 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x); 823 ret = GetViewportExtEx(hdcMetafile, &size); 824 ok(ret, "GetViewportExtEx error %u\n", GetLastError()); 825 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx); 826 827 hFontCheck = SelectObject(hdcMetafile, hFontOld); 828 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2, 829 "Font not reverted with DC Restore\n"); 830 831 ret = RestoreDC(hdcMetafile, -20); 832 ok(!ret, "ret = %d\n", ret); 833 ret = RestoreDC(hdcMetafile, 20); 834 ok(!ret, "ret = %d\n", ret); 835 836 hMetafile = CloseEnhMetaFile(hdcMetafile); 837 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 838 839 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc); 840 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret); 841 842 ret = DeleteObject(hFont); 843 ok( ret, "DeleteObject error %d\n", GetLastError()); 844 ret = DeleteObject(hFont2); 845 ok( ret, "DeleteObject error %d\n", GetLastError()); 846 ret = DeleteEnhMetaFile(hMetafile); 847 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError()); 848 ret = ReleaseDC(hwnd, hdcDisplay); 849 ok( ret, "ReleaseDC error %d\n", GetLastError()); 850 DestroyWindow(hwnd); 851 } 852 853 static void test_mf_SaveDC(void) 854 { 855 HDC hdcMetafile; 856 HMETAFILE hMetafile; 857 int ret; 858 POINT pt; 859 SIZE size; 860 HFONT hFont,hFont2,hFontOld,hFontCheck; 861 862 hdcMetafile = CreateMetaFileA(NULL); 863 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError()); 864 865 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC); 866 ok (ret, "SetMapMode should not fail\n"); 867 868 /* Need to write something to the emf, otherwise Windows won't play it back */ 869 LineTo(hdcMetafile, 150, 150); 870 871 pt.x = pt.y = 5555; 872 SetWindowOrgEx(hdcMetafile, 0, 0, &pt); 873 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y); 874 pt.x = pt.y = 5555; 875 SetViewportOrgEx(hdcMetafile, 0, 0, &pt); 876 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y); 877 size.cx = size.cy = 5555; 878 SetWindowExtEx(hdcMetafile, 110, 110, &size ); 879 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy ); 880 size.cx = size.cy = 5555; 881 SetViewportExtEx(hdcMetafile, 120, 120, &size ); 882 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy ); 883 884 /* Force Win9x to update DC state */ 885 SetPixelV(hdcMetafile, 50, 50, 0); 886 887 ret = GetViewportOrgEx(hdcMetafile, &pt); 888 todo_wine ok (!ret, "GetViewportOrgEx should fail\n"); 889 ret = GetViewportExtEx(hdcMetafile, &size); 890 todo_wine ok (!ret, "GetViewportExtEx should fail\n"); 891 ret = SaveDC(hdcMetafile); 892 ok(ret == 1, "ret = %d\n", ret); 893 894 SetWindowOrgEx(hdcMetafile, -1, -1, NULL); 895 SetViewportOrgEx(hdcMetafile, 10, 10, NULL); 896 SetWindowExtEx(hdcMetafile, 150, 150, NULL ); 897 SetViewportExtEx(hdcMetafile, 200, 200, NULL ); 898 899 /* Force Win9x to update DC state */ 900 SetPixelV(hdcMetafile, 50, 50, 0); 901 902 ret = SaveDC(hdcMetafile); 903 ok(ret == 1, "ret = %d\n", ret); 904 905 SetWindowOrgEx(hdcMetafile, -2, -2, NULL); 906 SetViewportOrgEx(hdcMetafile, 20, 20, NULL); 907 SetWindowExtEx(hdcMetafile, 120, 120, NULL ); 908 SetViewportExtEx(hdcMetafile, 300, 300, NULL ); 909 910 /* Force Win9x to update DC state */ 911 SetPixelV(hdcMetafile, 50, 50, 0); 912 SetPolyFillMode( hdcMetafile, ALTERNATE ); 913 SetBkColor( hdcMetafile, 0 ); 914 915 ret = SaveDC(hdcMetafile); 916 ok(ret == 1, "ret = %d\n", ret); 917 918 SetWindowOrgEx(hdcMetafile, -3, -3, NULL); 919 SetViewportOrgEx(hdcMetafile, 30, 30, NULL); 920 SetWindowExtEx(hdcMetafile, 200, 200, NULL ); 921 SetViewportExtEx(hdcMetafile, 400, 400, NULL ); 922 923 SetPolyFillMode( hdcMetafile, WINDING ); 924 SetBkColor( hdcMetafile, 0x123456 ); 925 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" ); 926 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" ); 927 928 /* Force Win9x to update DC state */ 929 SetPixelV(hdcMetafile, 50, 50, 0); 930 931 ret = RestoreDC(hdcMetafile, -1); 932 ok(ret, "ret = %d\n", ret); 933 934 ret = SaveDC(hdcMetafile); 935 ok(ret == 1, "ret = %d\n", ret); 936 937 ret = RestoreDC(hdcMetafile, 1); 938 ok(ret, "ret = %d\n", ret); 939 940 SetWindowOrgEx(hdcMetafile, -4, -4, NULL); 941 SetViewportOrgEx(hdcMetafile, 40, 40, NULL); 942 SetWindowExtEx(hdcMetafile, 500, 500, NULL ); 943 SetViewportExtEx(hdcMetafile, 50, 50, NULL ); 944 945 /* Force Win9x to update DC state */ 946 SetPixelV(hdcMetafile, 50, 50, 0); 947 948 ret = SaveDC(hdcMetafile); 949 ok(ret == 1, "ret = %d\n", ret); 950 951 ret = SaveDC(hdcMetafile); 952 ok(ret == 1, "ret = %d\n", ret); 953 954 memset(&orig_lf, 0, sizeof(orig_lf)); 955 orig_lf.lfCharSet = ANSI_CHARSET; 956 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; 957 orig_lf.lfWeight = FW_DONTCARE; 958 orig_lf.lfHeight = 7; 959 orig_lf.lfQuality = DEFAULT_QUALITY; 960 lstrcpyA(orig_lf.lfFaceName, "Arial"); 961 hFont = CreateFontIndirectA(&orig_lf); 962 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError()); 963 964 hFontOld = SelectObject(hdcMetafile, hFont); 965 966 hFont2 = CreateFontIndirectA(&orig_lf); 967 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError()); 968 hFontCheck = SelectObject(hdcMetafile, hFont2); 969 ok(hFontCheck == hFont, "Font not selected\n"); 970 971 /* Force Win9x to update DC state */ 972 SetPixelV(hdcMetafile, 50, 50, 0); 973 974 ret = RestoreDC(hdcMetafile, 1); 975 ok(ret, "ret = %d\n", ret); 976 977 hFontCheck = SelectObject(hdcMetafile, hFontOld); 978 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n"); 979 980 /* restore level is ignored */ 981 ret = RestoreDC(hdcMetafile, -20); 982 ok(ret, "ret = %d\n", ret); 983 ret = RestoreDC(hdcMetafile, 20); 984 ok(ret, "ret = %d\n", ret); 985 ret = RestoreDC(hdcMetafile, 0); 986 ok(ret, "ret = %d\n", ret); 987 988 hMetafile = CloseMetaFile(hdcMetafile); 989 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 990 991 ret = DeleteMetaFile(hMetafile); 992 ok( ret, "DeleteMetaFile error %d\n", GetLastError()); 993 ret = DeleteObject(hFont); 994 ok( ret, "DeleteObject error %d\n", GetLastError()); 995 ret = DeleteObject(hFont2); 996 ok( ret, "DeleteObject error %d\n", GetLastError()); 997 } 998 999 1000 /* Win-format metafile (mfdrv) tests */ 1001 /* These tests compare the generated metafiles byte-by-byte */ 1002 /* with the nominal results. */ 1003 1004 /* Maximum size of sample metafiles in bytes. */ 1005 #define MF_BUFSIZE 1024 1006 1007 /* 8x8 bitmap data for a pattern brush */ 1008 static const unsigned char SAMPLE_PATTERN_BRUSH[] = { 1009 0x01, 0x00, 0x02, 0x00, 1010 0x03, 0x00, 0x04, 0x00, 1011 0x05, 0x00, 0x06, 0x00, 1012 0x07, 0x00, 0x08, 0x00 1013 }; 1014 1015 /* Sample metafiles to be compared to the outputs of the 1016 * test functions. 1017 */ 1018 1019 static const unsigned char MF_BLANK_BITS[] = { 1020 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00, 1021 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1022 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 1023 }; 1024 1025 static const unsigned char MF_GRAPHICS_BITS[] = { 1026 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00, 1027 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 1028 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02, 1029 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 1030 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 1031 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00, 1032 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00, 1033 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 1034 0x00, 0x00, 0x00, 0x00 1035 }; 1036 1037 static const unsigned char MF_PATTERN_BRUSH_BITS[] = { 1038 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00, 1039 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00, 1040 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01, 1041 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 1042 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 1043 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 1044 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1045 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1047 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00, 1048 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 1049 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1050 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 1051 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1052 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1053 0x00, 0x00 1054 }; 1055 1056 static const unsigned char MF_DCBRUSH_BITS[] = 1057 { 1058 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00, 1059 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 1060 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02, 1061 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 1062 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 1063 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00, 1064 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1065 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00, 1066 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00, 1067 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00, 1068 0x00, 0x00, 0x00, 0x00 1069 }; 1070 1071 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] = 1072 { 1073 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00, 1074 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 1075 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a, 1076 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, 1077 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00, 1078 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 1079 0x00, 0x00 1080 }; 1081 1082 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] = 1083 { 1084 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1086 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1088 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff, 1089 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1090 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1091 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1093 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 1094 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 1095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1096 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00, 1097 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00, 1098 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 1099 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1100 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 1101 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 1102 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41, 1103 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 1104 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 1105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1106 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 1107 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00, 1108 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 1109 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1110 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1111 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 1112 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1113 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1114 0x14, 0x00, 0x00, 0x00 1115 }; 1116 1117 static const unsigned char MF_LINETO_BITS[] = { 1118 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00, 1119 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1120 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 1121 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00, 1122 0x00, 0x00 1123 }; 1124 1125 static const unsigned char EMF_LINETO_BITS[] = { 1126 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1128 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1130 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, 1131 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1132 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 1133 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1135 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 1136 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 1137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1138 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00, 1139 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00, 1140 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 1141 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80, 1142 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73, 1143 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 1144 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00, 1145 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1146 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 1147 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00, 1148 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 1149 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 1150 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1151 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 1152 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1153 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 1154 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1155 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1156 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1157 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00, 1158 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 1159 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1160 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00, 1161 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1162 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 1163 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1164 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 1165 }; 1166 1167 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = { 1168 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1170 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1172 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 1173 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1174 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 1175 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1177 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 1178 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 1179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1180 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00, 1181 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00, 1182 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 1183 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80, 1184 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73, 1185 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 1186 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00, 1187 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1188 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 1189 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00, 1190 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 1191 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 1192 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1193 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1194 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1195 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1196 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1197 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1198 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1199 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00, 1200 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 1201 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1202 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00, 1203 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1204 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 1205 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1206 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 1207 }; 1208 1209 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = { 1210 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1212 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1214 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, 1215 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1216 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 1217 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1219 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 1220 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 1221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1222 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00, 1223 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 1224 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 1225 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 1226 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 1227 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 1228 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 1229 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 1230 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 1231 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1232 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00, 1233 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80, 1234 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1235 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1236 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1237 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1238 0x14, 0x00, 0x00, 0x00 1239 }; 1240 1241 static const unsigned char EMF_BITBLT[] = 1242 { 1243 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1245 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1247 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 1248 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1249 0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1250 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1252 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00, 1253 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 1254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1255 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00, 1256 0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 1257 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1258 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1259 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1260 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1261 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00, 1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1263 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 1264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1266 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 1267 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 1268 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 1269 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1270 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 1271 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1280 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1282 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1284 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1285 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 1286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1288 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1292 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 1293 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1294 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1295 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1296 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1297 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00, 1298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1299 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00, 1300 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c, 1301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1302 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 1303 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 1304 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 1305 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 1306 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1307 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 1308 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 1309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1317 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1318 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1319 0x14, 0x00, 0x00, 0x00 1320 }; 1321 1322 static const unsigned char EMF_DCBRUSH_BITS[] = 1323 { 1324 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1325 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 1326 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 1327 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 1328 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00, 1329 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1330 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 1331 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1333 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 1334 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 1335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1336 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00, 1337 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00, 1338 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80, 1339 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1340 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00, 1341 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 1342 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00, 1343 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 1344 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 1345 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 1346 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1348 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00, 1349 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 1350 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 1351 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 1352 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 1353 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1354 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 1355 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 1356 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00, 1357 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 1358 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 1359 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 1360 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 1361 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 1362 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1363 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1364 0x14, 0x00, 0x00, 0x00 1365 }; 1366 1367 static const unsigned char EMF_BEZIER_BITS[] = 1368 { 1369 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1371 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 1372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1373 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00, 1374 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1375 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 1376 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1378 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 1379 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00, 1380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1381 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00, 1382 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00, 1383 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1384 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1385 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1386 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 1387 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00, 1388 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 1389 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 1390 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1391 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 1392 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00, 1393 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 1394 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1395 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 1396 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 1397 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1398 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1399 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 1400 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1401 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1402 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 1403 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1404 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 1405 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1406 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 1407 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1408 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1409 0x14, 0x00, 0x00, 0x00 1410 }; 1411 1412 static const unsigned char EMF_POLYPOLYLINE_BITS[] = 1413 { 1414 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1415 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1416 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 1417 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00, 1418 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00, 1419 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1420 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 1421 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1423 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00, 1424 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 1425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1426 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00, 1427 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00, 1428 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1429 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 1430 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 1431 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 1432 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1433 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 1434 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 1435 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1436 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 1437 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 1438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1439 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1440 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 1441 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 1442 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00, 1443 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 1444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1445 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1446 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1447 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 1448 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1449 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 1450 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 1451 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 1452 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1453 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 1454 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 1455 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 1456 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1457 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 1458 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 1459 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 1460 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1461 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1462 0x14, 0x00, 0x00, 0x00 1463 }; 1464 1465 static const unsigned char EMF_GRADIENTFILL_BITS[] = 1466 { 1467 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 1468 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 1469 0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 1470 0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00, 1471 0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00, 1472 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 1473 0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1474 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1476 0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00, 1477 0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 1478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1479 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00, 1480 0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00, 1481 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 1482 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00, 1483 0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 1484 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 1485 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 1486 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80, 1487 0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 1488 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 1489 0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 1490 0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde, 1491 0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 1492 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 1493 0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00, 1494 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 1495 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 1496 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 1497 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1498 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 1499 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 1500 0x14, 0x00, 0x00, 0x00 1501 }; 1502 1503 /* For debugging or dumping the raw metafiles produced by 1504 * new test functions. 1505 */ 1506 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr, 1507 INT nobj, LPARAM param) 1508 { 1509 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n", 1510 hdc, mr->rdFunction, mr->rdSize, (void *)param); 1511 return TRUE; 1512 } 1513 1514 /* For debugging or dumping the raw metafiles produced by 1515 * new test functions. 1516 */ 1517 1518 static void dump_mf_bits (const HMETAFILE mf, const char *desc) 1519 { 1520 BYTE buf[MF_BUFSIZE]; 1521 UINT mfsize, i; 1522 1523 if (!winetest_debug) return; 1524 1525 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf); 1526 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc); 1527 1528 printf ("MetaFile %s has bits:\n{\n ", desc); 1529 for (i=0; i<mfsize; i++) 1530 { 1531 printf ("0x%02x", buf[i]); 1532 if (i == mfsize-1) 1533 printf ("\n"); 1534 else if (i % 8 == 7) 1535 printf (",\n "); 1536 else 1537 printf (", "); 1538 } 1539 printf ("};\n"); 1540 } 1541 1542 /* Compare the metafile produced by a test function with the 1543 * expected raw metafile data in "bits". 1544 * Return value is 0 for a perfect match, 1545 * -1 if lengths aren't equal, 1546 * otherwise returns the number of non-matching bytes. 1547 */ 1548 1549 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize, 1550 const char *desc) 1551 { 1552 unsigned char buf[MF_BUFSIZE]; 1553 UINT mfsize, i; 1554 int diff; 1555 1556 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf); 1557 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc); 1558 if (mfsize < MF_BUFSIZE) 1559 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", 1560 desc, mfsize, bsize); 1561 else 1562 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n", 1563 desc, mfsize, bsize); 1564 if (mfsize != bsize) 1565 return -1; 1566 1567 diff = 0; 1568 for (i=0; i<bsize; i++) 1569 { 1570 if (buf[i] != bits[i]) 1571 diff++; 1572 } 1573 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n", 1574 desc, mfsize, bsize, diff); 1575 1576 return diff; 1577 } 1578 1579 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc) 1580 { 1581 unsigned char buf[MF_BUFSIZE]; 1582 DWORD mfsize, rd_size, i; 1583 int diff; 1584 HANDLE hfile; 1585 BOOL ret; 1586 1587 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 1588 assert(hfile != INVALID_HANDLE_VALUE); 1589 1590 mfsize = GetFileSize(hfile, NULL); 1591 assert(mfsize <= MF_BUFSIZE); 1592 1593 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL); 1594 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError()); 1595 1596 CloseHandle(hfile); 1597 1598 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize); 1599 1600 if (mfsize != bsize) 1601 return -1; 1602 1603 diff = 0; 1604 for (i=0; i<bsize; i++) 1605 { 1606 if (buf[i] != bits[i]) 1607 diff++; 1608 } 1609 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n", 1610 desc, mfsize, bsize, diff); 1611 1612 return diff; 1613 } 1614 1615 /* For debugging or dumping the raw EMFs produced by 1616 * new test functions. 1617 */ 1618 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc) 1619 { 1620 BYTE buf[MF_BUFSIZE]; 1621 UINT mfsize, i; 1622 1623 if (!winetest_debug) return; 1624 1625 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf); 1626 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc); 1627 1628 printf("EMF %s has bits:\n{\n ", desc); 1629 for (i = 0; i < mfsize; i++) 1630 { 1631 printf ("0x%02x", buf[i]); 1632 if (i == mfsize-1) 1633 printf ("\n"); 1634 else if (i % 8 == 7) 1635 printf (",\n "); 1636 else 1637 printf (", "); 1638 } 1639 printf ("};\n"); 1640 } 1641 1642 static void dump_emf_records(const HENHMETAFILE mf, const char *desc) 1643 { 1644 BYTE *emf; 1645 BYTE buf[MF_BUFSIZE]; 1646 UINT mfsize, offset; 1647 1648 if (!winetest_debug) return; 1649 1650 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf); 1651 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError()); 1652 1653 printf("EMF %s has records:\n", desc); 1654 1655 emf = buf; 1656 offset = 0; 1657 while(offset < mfsize) 1658 { 1659 EMR *emr = (EMR *)(emf + offset); 1660 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize); 1661 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/ 1662 offset += emr->nSize; 1663 } 1664 } 1665 1666 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc) 1667 { 1668 const BYTE *buf; 1669 DWORD i; 1670 1671 if (!winetest_debug) return; 1672 1673 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType); 1674 buf = (const BYTE *)emr; 1675 for (i = 0; i < emr->nSize; i++) 1676 { 1677 printf ("0x%02x", buf[i]); 1678 if (i == emr->nSize - 1) 1679 printf ("\n"); 1680 else if (i % 8 == 7) 1681 printf (",\n"); 1682 else 1683 printf (", "); 1684 } 1685 printf ("};\n"); 1686 } 1687 1688 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto) 1689 { 1690 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top, 1691 eto->rclBounds.right, eto->rclBounds.bottom); 1692 trace("iGraphicsMode %u\n", eto->iGraphicsMode); 1693 trace("exScale: %f\n", eto->exScale); 1694 trace("eyScale: %f\n", eto->eyScale); 1695 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y); 1696 trace("emrtext.nChars %u\n", eto->emrtext.nChars); 1697 trace("emrtext.offString %#x\n", eto->emrtext.offString); 1698 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions); 1699 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top, 1700 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom); 1701 trace("emrtext.offDx %#x\n", eto->emrtext.offDx); 1702 } 1703 1704 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2, 1705 const char *desc, BOOL ignore_scaling) 1706 { 1707 int diff; 1708 1709 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n", 1710 desc, emr1->iType, emr2->iType); 1711 1712 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n", 1713 desc, emr1->nSize, emr2->nSize); 1714 1715 /* iType and nSize mismatches are fatal */ 1716 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE; 1717 1718 /* contents of EMR_GDICOMMENT are not interesting */ 1719 if (emr1->iType == EMR_GDICOMMENT) return TRUE; 1720 1721 /* different Windows versions setup DC scaling differently when 1722 * converting an old style metafile to an EMF. 1723 */ 1724 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX || 1725 emr1->iType == EMR_SETVIEWPORTEXTEX)) 1726 return TRUE; 1727 1728 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA) 1729 { 1730 EMREXTTEXTOUTW *eto1, *eto2; 1731 1732 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize); 1733 memcpy(eto1, emr1, emr1->nSize); 1734 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize); 1735 memcpy(eto2, emr2, emr2->nSize); 1736 1737 /* different Windows versions setup DC scaling differently */ 1738 eto1->exScale = eto1->eyScale = 0.0; 1739 eto2->exScale = eto2->eyScale = 0.0; 1740 1741 diff = memcmp(eto1, eto2, emr1->nSize); 1742 if (diff) 1743 { 1744 dump_EMREXTTEXTOUT(eto1); 1745 dump_EMREXTTEXTOUT(eto2); 1746 } 1747 HeapFree(GetProcessHeap(), 0, eto1); 1748 HeapFree(GetProcessHeap(), 0, eto2); 1749 } 1750 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping")) 1751 { 1752 /* We have to take care of NT4 differences here */ 1753 diff = memcmp(emr1, emr2, emr1->nSize); 1754 if (diff) 1755 { 1756 ENHMETARECORD *emr_nt4; 1757 1758 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize); 1759 memcpy(emr_nt4, emr2, emr2->nSize); 1760 /* Correct the nRgnSize field */ 1761 emr_nt4->dParm[5] = sizeof(RECT); 1762 1763 diff = memcmp(emr1, emr_nt4, emr1->nSize); 1764 if (!diff) 1765 win_skip("Catered for NT4 differences\n"); 1766 1767 HeapFree(GetProcessHeap(), 0, emr_nt4); 1768 } 1769 } 1770 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16) 1771 { 1772 EMRPOLYBEZIER16 *eto1, *eto2; 1773 1774 eto1 = (EMRPOLYBEZIER16*)emr1; 1775 eto2 = (EMRPOLYBEZIER16*)emr2; 1776 1777 diff = eto1->cpts != eto2->cpts; 1778 if(!diff) 1779 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS)); 1780 } 1781 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER) 1782 { 1783 EMRPOLYBEZIER *eto1, *eto2; 1784 1785 eto1 = (EMRPOLYBEZIER*)emr1; 1786 eto2 = (EMRPOLYBEZIER*)emr2; 1787 1788 diff = eto1->cptl != eto2->cptl; 1789 if(!diff) 1790 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL)); 1791 } 1792 else 1793 diff = memcmp(emr1, emr2, emr1->nSize); 1794 1795 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType); 1796 1797 if (diff) 1798 { 1799 dump_emf_record(emr1, "expected bits"); 1800 dump_emf_record(emr2, "actual bits"); 1801 } 1802 1803 return diff == 0; /* report all non-fatal record mismatches */ 1804 } 1805 1806 /* Compare the EMF produced by a test function with the 1807 * expected raw EMF data in "bits". 1808 * Return value is 0 for a perfect match, 1809 * -1 if lengths aren't equal, 1810 * otherwise returns the number of non-matching bytes. 1811 */ 1812 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits, 1813 UINT bsize, const char *desc, 1814 BOOL ignore_scaling) 1815 { 1816 unsigned char buf[MF_BUFSIZE]; 1817 UINT mfsize, offset1, offset2, diff_nt4, diff_9x; 1818 const ENHMETAHEADER *emh1, *emh2; 1819 1820 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf); 1821 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError()); 1822 1823 /* ENHMETAHEADER size could differ, depending on platform */ 1824 diff_nt4 = sizeof(SIZEL); 1825 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD); 1826 1827 if (mfsize < MF_BUFSIZE) 1828 { 1829 ok(mfsize == bsize || 1830 broken(mfsize == bsize - diff_nt4) || /* NT4 */ 1831 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */ 1832 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize); 1833 } 1834 else 1835 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n", 1836 desc, mfsize, bsize); 1837 1838 /* basic things must match */ 1839 emh1 = (const ENHMETAHEADER *)bits; 1840 emh2 = (const ENHMETAHEADER *)buf; 1841 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType); 1842 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize); 1843 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes); 1844 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature); 1845 1846 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType); 1847 ok(emh1->nSize == emh2->nSize || 1848 broken(emh1->nSize - diff_nt4 == emh2->nSize) || 1849 broken(emh1->nSize - diff_9x == emh2->nSize), 1850 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize); 1851 ok(emh1->rclBounds.left == emh2->rclBounds.left, "%s: expected rclBounds.left = %d, got %d\n", 1852 desc, emh1->rclBounds.left, emh2->rclBounds.left); 1853 ok(emh1->rclBounds.top == emh2->rclBounds.top, "%s: expected rclBounds.top = %d, got %d\n", 1854 desc, emh1->rclBounds.top, emh2->rclBounds.top); 1855 ok(emh1->rclBounds.right == emh2->rclBounds.right, "%s: expected rclBounds.right = %d, got %d\n", 1856 desc, emh1->rclBounds.right, emh2->rclBounds.right); 1857 ok(emh1->rclBounds.bottom == emh2->rclBounds.bottom, "%s: expected rclBounds.bottom = %d, got %d\n", 1858 desc, emh1->rclBounds.bottom, emh2->rclBounds.bottom); 1859 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature); 1860 ok(emh1->nBytes == emh2->nBytes || 1861 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) || 1862 broken(emh1->nBytes - diff_9x == emh2->nBytes), 1863 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes); 1864 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords); 1865 1866 offset1 = emh1->nSize; 1867 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */ 1868 while (offset1 < emh1->nBytes) 1869 { 1870 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1); 1871 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2); 1872 1873 trace("%s: EMF record %u, size %u/record %u, size %u\n", 1874 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize); 1875 1876 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1; 1877 1878 /* We have already bailed out if iType or nSize don't match */ 1879 offset1 += emr1->nSize; 1880 offset2 += emr2->nSize; 1881 } 1882 return 0; 1883 } 1884 1885 1886 /* tests blitting to an EMF */ 1887 static void test_emf_BitBlt(void) 1888 { 1889 HDC hdcDisplay, hdcMetafile, hdcBitmap; 1890 HBITMAP hBitmap, hOldBitmap; 1891 HENHMETAFILE hMetafile; 1892 #define BMP_DIM 4 1893 BITMAPINFOHEADER bmih = 1894 { 1895 sizeof(BITMAPINFOHEADER), 1896 BMP_DIM,/* biWidth */ 1897 BMP_DIM,/* biHeight */ 1898 1, /* biPlanes */ 1899 24, /* biBitCount */ 1900 BI_RGB, /* biCompression */ 1901 0, /* biXPelsPerMeter */ 1902 0, /* biYPelsPerMeter */ 1903 0, /* biClrUsed */ 1904 0, /* biClrImportant */ 1905 }; 1906 void *bits; 1907 XFORM xform; 1908 BOOL ret; 1909 1910 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL); 1911 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() ); 1912 1913 hdcBitmap = CreateCompatibleDC(hdcDisplay); 1914 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" ); 1915 ok(SetGraphicsMode(hdcBitmap, GM_ADVANCED), "SetGraphicsMode failed\n"); 1916 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937); 1917 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937); 1918 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih, 1919 DIB_RGB_COLORS, &bits, NULL, 0); 1920 hOldBitmap = SelectObject(hdcBitmap, hBitmap); 1921 1922 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL); 1923 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" ); 1924 1925 /* First fill the bitmap DC with something recognizable, like BLACKNESS */ 1926 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS); 1927 ok( ret, "BitBlt(BLACKNESS) failed\n" ); 1928 1929 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY); 1930 ok( ret, "BitBlt(SRCCOPY) failed\n" ); 1931 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS); 1932 ok( ret, "BitBlt(WHITENESS) failed\n" ); 1933 1934 ok(SetMapMode(hdcBitmap, MM_ANISOTROPIC), "SetMapMode failed\n"); 1935 ok(SetWindowOrgEx(hdcBitmap, 0, 0, NULL), "SetWindowOrgEx failed\n"); 1936 ok(SetWindowExtEx(hdcBitmap, 400, 400, NULL), "SetWindowExtEx failed\n"); 1937 ok(SetViewportOrgEx(hdcBitmap, 0, 0, NULL), "SetViewportOrgEx failed\n"); 1938 ok(SetViewportExtEx(hdcBitmap, BMP_DIM, BMP_DIM, NULL), "SetViewportExtEx failed\n"); 1939 memset(&xform, 0, sizeof(xform)); 1940 xform.eM11 = 0.5; 1941 xform.eM22 = 1.0; 1942 ok(SetWorldTransform(hdcBitmap, &xform), "SetWorldTransform failed\n"); 1943 1944 ret = StretchBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, 400, 400, SRCCOPY); 1945 ok( ret, "StretchBlt(SRCCOPY) failed\n" ); 1946 1947 hMetafile = CloseEnhMetaFile(hdcMetafile); 1948 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" ); 1949 1950 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT), 1951 "emf_BitBlt", FALSE) != 0) 1952 { 1953 dump_emf_bits(hMetafile, "emf_BitBlt"); 1954 dump_emf_records(hMetafile, "emf_BitBlt"); 1955 } 1956 1957 SelectObject(hdcBitmap, hOldBitmap); 1958 DeleteObject(hBitmap); 1959 DeleteDC(hdcBitmap); 1960 DeleteDC(hdcDisplay); 1961 #undef BMP_DIM 1962 } 1963 1964 static void test_emf_DCBrush(void) 1965 { 1966 HDC hdcMetafile; 1967 HENHMETAFILE hMetafile; 1968 HBRUSH hBrush; 1969 HPEN hPen; 1970 BOOL ret; 1971 COLORREF color; 1972 1973 if (!pSetDCBrushColor || !pSetDCPenColor) 1974 { 1975 win_skip( "SetDCBrush/PenColor not supported\n" ); 1976 return; 1977 } 1978 1979 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL); 1980 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" ); 1981 1982 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH)); 1983 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError()); 1984 1985 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN)); 1986 ok(hPen != 0, "SelectObject error %d.\n", GetLastError()); 1987 1988 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) ); 1989 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color ); 1990 1991 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) ); 1992 ok( color == 0, "SetDCPenColor returned %x\n", color ); 1993 1994 Rectangle( hdcMetafile, 10, 10, 20, 20 ); 1995 1996 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) ); 1997 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color ); 1998 1999 hMetafile = CloseEnhMetaFile(hdcMetafile); 2000 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" ); 2001 2002 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS), 2003 "emf_DC_Brush", FALSE ) != 0) 2004 { 2005 dump_emf_bits(hMetafile, "emf_DC_Brush"); 2006 dump_emf_records(hMetafile, "emf_DC_Brush"); 2007 } 2008 ret = DeleteEnhMetaFile(hMetafile); 2009 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError()); 2010 ret = DeleteObject(hBrush); 2011 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError()); 2012 ret = DeleteObject(hPen); 2013 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError()); 2014 } 2015 2016 /* Test a blank metafile. May be used as a template for new tests. */ 2017 2018 static void test_mf_Blank(void) 2019 { 2020 HDC hdcMetafile; 2021 HMETAFILE hMetafile; 2022 INT caps; 2023 BOOL ret; 2024 INT type; 2025 2026 hdcMetafile = CreateMetaFileA(NULL); 2027 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError()); 2028 trace("hdcMetafile %p\n", hdcMetafile); 2029 2030 /* Tests on metafile initialization */ 2031 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY); 2032 ok (caps == DT_METAFILE, 2033 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps); 2034 2035 hMetafile = CloseMetaFile(hdcMetafile); 2036 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError()); 2037 type = GetObjectType(hMetafile); 2038 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type); 2039 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n"); 2040 2041 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), 2042 "mf_blank") != 0) 2043 { 2044 dump_mf_bits(hMetafile, "mf_Blank"); 2045 EnumMetaFile(0, hMetafile, mf_enum_proc, 0); 2046 } 2047 2048 ret = DeleteMetaFile(hMetafile); 2049 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError()); 2050 } 2051 2052 static void test_CopyMetaFile(void) 2053 { 2054 HDC hdcMetafile; 2055 HMETAFILE hMetafile, hmf_copy; 2056 BOOL ret; 2057 char temp_path[MAX_PATH]; 2058 char mf_name[MAX_PATH]; 2059 INT type; 2060 2061 hdcMetafile = CreateMetaFileA(NULL); 2062 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError()); 2063 trace("hdcMetafile %p\n", hdcMetafile); 2064 2065 hMetafile = CloseMetaFile(hdcMetafile); 2066 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError()); 2067 type = GetObjectType(hMetafile); 2068 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type); 2069 2070 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), 2071 "mf_blank") != 0) 2072 { 2073 dump_mf_bits(hMetafile, "mf_Blank"); 2074 EnumMetaFile(0, hMetafile, mf_enum_proc, 0); 2075 } 2076 2077 GetTempPathA(MAX_PATH, temp_path); 2078 GetTempFileNameA(temp_path, "wmf", 0, mf_name); 2079 2080 hmf_copy = CopyMetaFileA(hMetafile, mf_name); 2081 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError()); 2082 2083 type = GetObjectType(hmf_copy); 2084 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type); 2085 2086 ret = DeleteMetaFile(hMetafile); 2087 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError()); 2088 2089 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0) 2090 { 2091 dump_mf_bits(hmf_copy, "mf_Blank"); 2092 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0); 2093 } 2094 2095 ret = DeleteMetaFile(hmf_copy); 2096 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError()); 2097 2098 DeleteFileA(mf_name); 2099 } 2100 2101 static void test_SetMetaFileBits(void) 2102 { 2103 HMETAFILE hmf; 2104 INT type; 2105 BOOL ret; 2106 BYTE buf[256]; 2107 METAHEADER *mh; 2108 2109 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS); 2110 trace("hmf %p\n", hmf); 2111 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError()); 2112 type = GetObjectType(hmf); 2113 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type); 2114 2115 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) 2116 { 2117 dump_mf_bits(hmf, "mf_Graphics"); 2118 EnumMetaFile(0, hmf, mf_enum_proc, 0); 2119 } 2120 2121 ret = DeleteMetaFile(hmf); 2122 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError()); 2123 2124 /* NULL data crashes XP SP1 */ 2125 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/ 2126 2127 /* Now with zero size */ 2128 SetLastError(0xdeadbeef); 2129 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS); 2130 trace("hmf %p\n", hmf); 2131 ok(!hmf, "SetMetaFileBitsEx should fail\n"); 2132 ok(GetLastError() == ERROR_INVALID_DATA || 2133 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ 2134 "wrong error %d\n", GetLastError()); 2135 2136 /* Now with odd size */ 2137 SetLastError(0xdeadbeef); 2138 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS); 2139 trace("hmf %p\n", hmf); 2140 ok(!hmf, "SetMetaFileBitsEx should fail\n"); 2141 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError()); 2142 2143 /* Now with zeroed out header fields */ 2144 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS)); 2145 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS)); 2146 mh = (METAHEADER *)buf; 2147 /* corruption of any of the below fields leads to a failure */ 2148 mh->mtType = 0; 2149 mh->mtVersion = 0; 2150 mh->mtHeaderSize = 0; 2151 SetLastError(0xdeadbeef); 2152 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); 2153 trace("hmf %p\n", hmf); 2154 ok(!hmf, "SetMetaFileBitsEx should fail\n"); 2155 ok(GetLastError() == ERROR_INVALID_DATA || 2156 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ 2157 "wrong error %d\n", GetLastError()); 2158 2159 /* Now with corrupted mtSize field */ 2160 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS)); 2161 mh = (METAHEADER *)buf; 2162 /* corruption of mtSize doesn't lead to a failure */ 2163 mh->mtSize *= 2; 2164 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); 2165 trace("hmf %p\n", hmf); 2166 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError()); 2167 2168 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) 2169 { 2170 dump_mf_bits(hmf, "mf_Graphics"); 2171 EnumMetaFile(0, hmf, mf_enum_proc, 0); 2172 } 2173 2174 ret = DeleteMetaFile(hmf); 2175 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError()); 2176 2177 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */ 2178 /* Now with zeroed out mtSize field */ 2179 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS)); 2180 mh = (METAHEADER *)buf; 2181 /* zeroing mtSize doesn't lead to a failure */ 2182 mh->mtSize = 0; 2183 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); 2184 trace("hmf %p\n", hmf); 2185 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError()); 2186 2187 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) 2188 { 2189 dump_mf_bits(hmf, "mf_Graphics"); 2190 EnumMetaFile(0, hmf, mf_enum_proc, 0); 2191 } 2192 2193 ret = DeleteMetaFile(hmf); 2194 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError()); 2195 #endif 2196 } 2197 2198 /* Simple APIs from mfdrv/graphics.c 2199 */ 2200 2201 static void test_mf_Graphics(void) 2202 { 2203 HDC hdcMetafile; 2204 HMETAFILE hMetafile; 2205 POINT oldpoint; 2206 BOOL ret; 2207 2208 hdcMetafile = CreateMetaFileA(NULL); 2209 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError()); 2210 trace("hdcMetafile %p\n", hdcMetafile); 2211 2212 ret = MoveToEx(hdcMetafile, 1, 1, NULL); 2213 ok( ret, "MoveToEx error %d.\n", GetLastError()); 2214 ret = LineTo(hdcMetafile, 2, 2); 2215 ok( ret, "LineTo error %d.\n", GetLastError()); 2216 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint); 2217 ok( ret, "MoveToEx error %d.\n", GetLastError()); 2218 2219 /* oldpoint gets garbage under Win XP, so the following test would 2220 * work under Wine but fails under Windows: 2221 * 2222 * ok((oldpoint.x == 2) && (oldpoint.y == 2), 2223 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n", 2224 * oldpoint.x, oldpoint.y); 2225 */ 2226 2227 ret = Ellipse(hdcMetafile, 0, 0, 2, 2); 2228 ok( ret, "Ellipse error %d.\n", GetLastError()); 2229 2230 hMetafile = CloseMetaFile(hdcMetafile); 2231 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError()); 2232 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n"); 2233 2234 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), 2235 "mf_Graphics") != 0) 2236 { 2237 dump_mf_bits(hMetafile, "mf_Graphics"); 2238 EnumMetaFile(0, hMetafile, mf_enum_proc, 0); 2239 } 2240 2241 ret = DeleteMetaFile(hMetafile); 2242 ok( ret, "DeleteMetaFile(%p) error %d\n", 2243 hMetafile, GetLastError()); 2244 } 2245 2246 static void test_mf_PatternBrush(void) 2247 { 2248 HDC hdcMetafile; 2249 HMETAFILE hMetafile; 2250 LOGBRUSH *orig_lb; 2251 HBRUSH hBrush; 2252 BOOL ret; 2253 2254 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH)); 2255 2256 orig_lb->lbStyle = BS_PATTERN; 2257 orig_lb->lbColor = RGB(0, 0, 0); 2258 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH); 2259 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError()); 2260 2261 hBrush = CreateBrushIndirect (orig_lb); 2262 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError()); 2263 2264 hdcMetafile = CreateMetaFileA(NULL); 2265 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError()); 2266 trace("hdcMetafile %p\n", hdcMetafile); 2267 2268 hBrush = SelectObject(hdcMetafile, hBrush); 2269 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError()); 2270 2271 hMetafile = CloseMetaFile(hdcMetafile); 2272 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError()); 2273 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n"); 2274 2275 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS), 2276 "mf_Pattern_Brush") != 0) 2277 { 2278 dump_mf_bits(hMetafile, "mf_Pattern_Brush"); 2279 EnumMetaFile(0, hMetafile, mf_enum_proc, 0); 2280 } 2281 2282 ret = DeleteMetaFile(hMetafile); 2283 ok( ret, "DeleteMetaFile error %d\n", GetLastError()); 2284 ret = DeleteObject(hBrush); 2285 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError()); 2286 ret = DeleteObject((HBITMAP)orig_lb->lbHatch); 2287 ok( ret, "DeleteObject(HBITMAP) error %d\n", 2288 GetLastError()); 2289 HeapFree (GetProcessHeap(), 0, orig_lb); 2290 } 2291 2292 static void test_mf_DCBrush(void) 2293 { 2294 HDC hdcMetafile; 2295 HMETAFILE hMetafile; 2296 HBRUSH hBrush; 2297 HPEN hPen; 2298 BOOL ret; 2299 COLORREF color; 2300 2301 if (!pSetDCBrushColor || !pSetDCPenColor) 2302 { 2303 win_skip( "SetDCBrush/PenColor not supported\n" ); 2304 return; 2305 } 2306 2307 hdcMetafile = CreateMetaFileA(NULL); 2308 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" ); 2309 2310 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH)); 2311 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError()); 2312 2313 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN)); 2314 ok(hPen != 0, "SelectObject error %d.\n", GetLastError()); 2315 2316 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) ); 2317 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color ); 2318 2319 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) ); 2320 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color ); 2321 2322 Rectangle( hdcMetafile, 10, 10, 20, 20 ); 2323 2324 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) ); 2325 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color ); 2326 2327 hMetafile = CloseMetaFile(hdcMetafile); 2328 ok( hMetafile != 0, "CloseMetaFile failed\n" ); 2329 2330 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0) 2331 { 2332 dump_mf_bits(hMetafile, "mf_DCBrush"); 2333 EnumMetaFile(0, hMetafile, mf_enum_proc, 0); 2334 } 2335 ret = DeleteMetaFile(hMetafile); 2336 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError()); 2337 } 2338 2339 static void test_mf_ExtTextOut_on_path(void) 2340 { 2341 HDC hdcMetafile; 2342 HMETAFILE hMetafile; 2343 BOOL ret; 2344 static const INT dx[4] = { 3, 5, 8, 12 }; 2345 2346 hdcMetafile = CreateMetaFileA(NULL); 2347 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError()); 2348 trace("hdcMetafile %p\n", hdcMetafile); 2349 2350 ret = BeginPath(hdcMetafile); 2351 ok(!ret, "BeginPath on metafile DC should fail\n"); 2352 2353 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx); 2354 ok(ret, "ExtTextOut error %d\n", GetLastError()); 2355 2356 ret = EndPath(hdcMetafile); 2357 ok(!ret, "EndPath on metafile DC should fail\n"); 2358 2359 hMetafile = CloseMetaFile(hdcMetafile); 2360 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError()); 2361 2362 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS), 2363 "mf_TextOut_on_path") != 0) 2364 { 2365 dump_mf_bits(hMetafile, "mf_TextOut_on_path"); 2366 EnumMetaFile(0, hMetafile, mf_enum_proc, 0); 2367 } 2368 2369 ret = DeleteMetaFile(hMetafile); 2370 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError()); 2371 } 2372 2373 static void test_emf_ExtTextOut_on_path(void) 2374 { 2375 HWND hwnd; 2376 HDC hdcDisplay, hdcMetafile; 2377 HENHMETAFILE hMetafile; 2378 BOOL ret; 2379 static const INT dx[4] = { 3, 5, 8, 12 }; 2380 2381 /* Win9x doesn't play EMFs on invisible windows */ 2382 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE, 2383 0, 0, 200, 200, 0, 0, 0, NULL); 2384 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError()); 2385 2386 hdcDisplay = GetDC(hwnd); 2387 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError()); 2388 2389 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL); 2390 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError()); 2391 2392 ret = BeginPath(hdcMetafile); 2393 ok(ret, "BeginPath error %d\n", GetLastError()); 2394 2395 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx); 2396 todo_wine ok(ret, "ExtTextOut error %d\n", GetLastError()); 2397 2398 ret = EndPath(hdcMetafile); 2399 ok(ret, "EndPath error %d\n", GetLastError()); 2400 2401 hMetafile = CloseEnhMetaFile(hdcMetafile); 2402 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 2403 2404 /* this doesn't succeed yet: EMF has correct size, all EMF records 2405 * are there, but their contents don't match for different reasons. 2406 */ 2407 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS), 2408 "emf_TextOut_on_path", FALSE) != 0) 2409 { 2410 dump_emf_bits(hMetafile, "emf_TextOut_on_path"); 2411 dump_emf_records(hMetafile, "emf_TextOut_on_path"); 2412 } 2413 2414 ret = DeleteEnhMetaFile(hMetafile); 2415 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError()); 2416 ret = ReleaseDC(hwnd, hdcDisplay); 2417 ok(ret, "ReleaseDC error %d\n", GetLastError()); 2418 DestroyWindow(hwnd); 2419 } 2420 2421 static const unsigned char EMF_CLIPPING[] = 2422 { 2423 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 2424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2425 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 2426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2427 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 2428 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 2429 0x04, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 2430 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2432 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00, 2433 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 2434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2435 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00, 2436 0x30, 0xda, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 2437 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 2438 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 2439 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 2440 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 2441 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 2442 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 2443 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 2444 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 2445 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 2446 0x00, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 2447 0x08, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 2448 0x18, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 2449 0x64, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 2450 0xff, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 2451 0x08, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 2452 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 2453 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 2454 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 2455 0x14, 0x00, 0x00, 0x00 2456 }; 2457 2458 static void translate( POINT *pt, UINT count, const XFORM *xform ) 2459 { 2460 while (count--) 2461 { 2462 FLOAT x = (FLOAT)pt->x; 2463 FLOAT y = (FLOAT)pt->y; 2464 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 ); 2465 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 ); 2466 pt++; 2467 } 2468 } 2469 2470 /* Compare rectangles allowing rounding errors */ 2471 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2) 2472 { 2473 return abs(rc1->left - rc2->left) <= 1 && 2474 abs(rc1->top - rc2->top) <= 1 && 2475 abs(rc1->right - rc2->right) <= 1 && 2476 abs(rc1->bottom - rc2->bottom) <= 1; 2477 } 2478 2479 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, 2480 const ENHMETARECORD *emr, int n_objs, LPARAM param) 2481 { 2482 if (emr->iType == EMR_EXTSELECTCLIPRGN) 2483 { 2484 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr; 2485 union _rgn 2486 { 2487 RGNDATA data; 2488 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)]; 2489 }; 2490 const union _rgn *rgn1; 2491 union _rgn rgn2; 2492 RECT rect, rc_transformed; 2493 const RECT *rc = (const RECT *)param; 2494 HRGN hrgn; 2495 XFORM xform; 2496 INT ret; 2497 BOOL is_win9x; 2498 2499 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n", 2500 clip->cbRgnData, clip->iMode); 2501 2502 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode); 2503 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT), 2504 "too small data block: %u bytes\n", clip->cbRgnData); 2505 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT)) 2506 return 0; 2507 2508 rgn1 = (const union _rgn *)clip->RgnData; 2509 2510 trace("size %u, type %u, count %u, rgn size %u, bound %s\n", 2511 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType, 2512 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize, 2513 wine_dbgstr_rect(&rgn1->data.rdh.rcBound)); 2514 2515 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n"); 2516 2517 rect = *(const RECT *)rgn1->data.Buffer; 2518 trace("rect %s\n", wine_dbgstr_rect(&rect)); 2519 ok(EqualRect(&rect, rc), "rects don't match\n"); 2520 2521 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize); 2522 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType); 2523 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount); 2524 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) || 2525 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */ 2526 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize); 2527 2528 hrgn = CreateRectRgn(0, 0, 0, 0); 2529 2530 memset(&xform, 0, sizeof(xform)); 2531 SetLastError(0xdeadbeef); 2532 ret = GetWorldTransform(hdc, &xform); 2533 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED; 2534 if (!is_win9x) 2535 ok(ret, "GetWorldTransform error %u\n", GetLastError()); 2536 2537 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22); 2538 2539 ret = GetClipRgn(hdc, hrgn); 2540 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret); 2541 2542 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs); 2543 2544 ret = GetClipRgn(hdc, hrgn); 2545 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret); 2546 2547 /* Win9x returns empty clipping region */ 2548 if (is_win9x) return 1; 2549 2550 ret = GetRegionData(hrgn, 0, NULL); 2551 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret); 2552 2553 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data); 2554 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret); 2555 2556 trace("size %u, type %u, count %u, rgn size %u, bound %s\n", rgn2.data.rdh.dwSize, 2557 rgn2.data.rdh.iType, rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize, 2558 wine_dbgstr_rect(&rgn2.data.rdh.rcBound)); 2559 2560 rect = rgn2.data.rdh.rcBound; 2561 rc_transformed = *rc; 2562 translate((POINT *)&rc_transformed, 2, &xform); 2563 trace("transformed %s\n", wine_dbgstr_rect(&rc_transformed)); 2564 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n"); 2565 2566 rect = *(const RECT *)rgn2.data.Buffer; 2567 trace("rect %s\n", wine_dbgstr_rect(&rect)); 2568 rc_transformed = *rc; 2569 translate((POINT *)&rc_transformed, 2, &xform); 2570 trace("transformed %s\n", wine_dbgstr_rect(&rc_transformed)); 2571 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n"); 2572 2573 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize); 2574 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType); 2575 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount); 2576 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) || 2577 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */ 2578 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize); 2579 2580 DeleteObject(hrgn); 2581 } 2582 return 1; 2583 } 2584 2585 static void test_emf_clipping(void) 2586 { 2587 static const RECT rc = { 0, 0, 100, 100 }; 2588 RECT rc_clip = { 100, 100, 1024, 1024 }; 2589 HWND hwnd; 2590 HDC hdc; 2591 HENHMETAFILE hemf; 2592 HRGN hrgn; 2593 INT ret; 2594 RECT rc_res, rc_sclip; 2595 2596 SetLastError(0xdeadbeef); 2597 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL); 2598 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError()); 2599 2600 /* Need to write something to the emf, otherwise Windows won't play it back */ 2601 LineTo(hdc, 1, 1); 2602 2603 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); 2604 ret = SelectClipRgn(hdc, hrgn); 2605 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); 2606 2607 BeginPath(hdc); 2608 Rectangle(hdc, rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); 2609 EndPath(hdc); 2610 ret = SelectClipPath(hdc, RGN_AND); 2611 ok(ret, "SelectClipPath error %d\n", GetLastError()); 2612 2613 SetLastError(0xdeadbeef); 2614 hemf = CloseEnhMetaFile(hdc); 2615 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 2616 2617 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING), 2618 "emf_clipping", FALSE) != 0) 2619 { 2620 dump_emf_bits(hemf, "emf_clipping"); 2621 dump_emf_records(hemf, "emf_clipping"); 2622 } 2623 2624 DeleteObject(hrgn); 2625 2626 /* Win9x doesn't play EMFs on invisible windows */ 2627 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE, 2628 0, 0, 200, 200, 0, 0, 0, NULL); 2629 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError()); 2630 2631 hdc = GetDC(hwnd); 2632 2633 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc); 2634 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError()); 2635 2636 DeleteEnhMetaFile(hemf); 2637 ReleaseDC(hwnd, hdc); 2638 DestroyWindow(hwnd); 2639 2640 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL); 2641 2642 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); 2643 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom); 2644 SelectClipRgn(hdc, hrgn); 2645 SetRect(&rc_res, -1, -1, -1, -1); 2646 ret = GetClipBox(hdc, &rc_res); 2647 ok(ret == SIMPLEREGION, "got %d\n", ret); 2648 ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip), 2649 wine_dbgstr_rect(&rc_res)); 2650 2651 OffsetRect(&rc_sclip, -100, -100); 2652 ret = OffsetClipRgn(hdc, -100, -100); 2653 ok(ret == SIMPLEREGION, "got %d\n", ret); 2654 SetRect(&rc_res, -1, -1, -1, -1); 2655 ret = GetClipBox(hdc, &rc_res); 2656 ok(ret == SIMPLEREGION, "got %d\n", ret); 2657 ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip), 2658 wine_dbgstr_rect(&rc_res)); 2659 2660 ret = IntersectClipRect(hdc, 0, 0, 100, 100); 2661 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret); 2662 if (ret == COMPLEXREGION) 2663 { 2664 /* XP returns COMPLEXREGION although region contains only 1 rect */ 2665 ret = GetClipRgn(hdc, hrgn); 2666 ok(ret == 1, "expected 1, got %d\n", ret); 2667 ret = rgn_rect_count(hrgn); 2668 ok(ret == 1, "expected 1, got %d\n", ret); 2669 } 2670 SetRect(&rc_res, -1, -1, -1, -1); 2671 ret = GetClipBox(hdc, &rc_res); 2672 ok(ret == SIMPLEREGION, "got %d\n", ret); 2673 ok(EqualRect(&rc_res, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rc), 2674 wine_dbgstr_rect(&rc_res)); 2675 2676 SetRect(&rc_sclip, 0, 0, 100, 50); 2677 ret = ExcludeClipRect(hdc, 0, 50, 100, 100); 2678 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret); 2679 if (ret == COMPLEXREGION) 2680 { 2681 /* XP returns COMPLEXREGION although region contains only 1 rect */ 2682 ret = GetClipRgn(hdc, hrgn); 2683 ok(ret == 1, "expected 1, got %d\n", ret); 2684 ret = rgn_rect_count(hrgn); 2685 ok(ret == 1, "expected 1, got %d\n", ret); 2686 } 2687 SetRect(&rc_res, -1, -1, -1, -1); 2688 ret = GetClipBox(hdc, &rc_res); 2689 ok(ret == SIMPLEREGION, "got %d\n", ret); 2690 ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip), 2691 wine_dbgstr_rect(&rc_res)); 2692 2693 hemf = CloseEnhMetaFile(hdc); 2694 DeleteEnhMetaFile(hemf); 2695 DeleteObject(hrgn); 2696 } 2697 2698 static const unsigned char MF_CLIP_BITS[] = { 2699 /* METAHEADER */ 2700 0x01, 0x00, /* mtType */ 2701 0x09, 0x00, /* mtHeaderSize */ 2702 0x00, 0x03, /* mtVersion */ 2703 0x32, 0x00, 0x00, 0x00, /* mtSize */ 2704 0x01, 0x00, /* mtNoObjects */ 2705 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */ 2706 0x00, 0x00, /* reserved */ 2707 2708 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */ 2709 0x14, 0x00, 0x00, 0x00, /* rdSize in words */ 2710 0xff, 0x06, /* META_CREATEREGION */ 2711 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00, 2712 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00, 2713 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00, 2714 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00, 2715 0x02, 0x00, 2716 2717 /* METARECORD for SelectObject */ 2718 0x04, 0x00, 0x00, 0x00, 2719 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */ 2720 0x00, 0x00, 2721 2722 /* METARECORD */ 2723 0x04, 0x00, 0x00, 0x00, 2724 0xf0, 0x01, /* META_DELETEOBJECT */ 2725 0x00, 0x00, 2726 2727 /* METARECORD for MoveTo(1,0x30) */ 2728 0x05, 0x00, 0x00, 0x00, /* rdSize in words */ 2729 0x14, 0x02, /* META_MOVETO */ 2730 0x30, 0x00, /* y */ 2731 0x01, 0x00, /* x */ 2732 2733 /* METARECORD for LineTo(0x20, 0x30) */ 2734 0x05, 0x00, 0x00, 0x00, /* rdSize in words */ 2735 0x13, 0x02, /* META_LINETO */ 2736 0x30, 0x00, /* y */ 2737 0x20, 0x00, /* x */ 2738 2739 /* EOF */ 2740 0x03, 0x00, 0x00, 0x00, 2741 0x00, 0x00 2742 }; 2743 2744 static int clip_mf_enum_proc_seen_selectclipregion; 2745 static int clip_mf_enum_proc_seen_selectobject; 2746 2747 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table, 2748 METARECORD *mr, int n_objs, LPARAM param) 2749 { 2750 switch (mr->rdFunction) { 2751 case META_SELECTCLIPREGION: 2752 clip_mf_enum_proc_seen_selectclipregion++; 2753 break; 2754 case META_SELECTOBJECT: 2755 clip_mf_enum_proc_seen_selectobject++; 2756 break; 2757 } 2758 return 1; 2759 } 2760 2761 static void test_mf_clipping(void) 2762 { 2763 /* left top right bottom */ 2764 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 }; 2765 HWND hwnd; 2766 HDC hdc; 2767 HMETAFILE hmf; 2768 HRGN hrgn; 2769 INT ret; 2770 2771 SetLastError(0xdeadbeef); 2772 hdc = CreateMetaFileA(NULL); 2773 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError()); 2774 2775 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); 2776 ret = SelectClipRgn(hdc, hrgn); 2777 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */ 2778 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret); 2779 2780 /* Draw a line that starts off left of the clip region and ends inside it */ 2781 MoveToEx(hdc, 0x1, 0x30, NULL); 2782 LineTo(hdc, 0x20, 0x30); 2783 2784 SetLastError(0xdeadbeef); 2785 hmf = CloseMetaFile(hdc); 2786 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError()); 2787 2788 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS), 2789 "mf_clipping") != 0) 2790 { 2791 dump_mf_bits(hmf, "mf_clipping"); 2792 } 2793 2794 DeleteObject(hrgn); 2795 2796 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE, 2797 0, 0, 200, 200, 0, 0, 0, NULL); 2798 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError()); 2799 2800 hdc = GetDC(hwnd); 2801 2802 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip); 2803 ok(ret, "EnumMetaFile error %d\n", GetLastError()); 2804 2805 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */ 2806 ok(clip_mf_enum_proc_seen_selectclipregion == 0, 2807 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion); 2808 ok(clip_mf_enum_proc_seen_selectobject == 1, 2809 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject); 2810 2811 DeleteMetaFile(hmf); 2812 ReleaseDC(hwnd, hdc); 2813 DestroyWindow(hwnd); 2814 } 2815 2816 static const unsigned char MF_PATH_BITS[] = 2817 { 2818 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00, 2819 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 2820 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02, 2821 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 2822 0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00, 2823 0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00, 2824 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00, 2825 0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 2826 0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00, 2827 0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00, 2828 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 2829 }; 2830 2831 static void test_mf_GetPath(void) 2832 { 2833 HDC hdc; 2834 HMETAFILE hmf; 2835 BOOL ret; 2836 int size; 2837 2838 SetLastError(0xdeadbeef); 2839 hdc = CreateMetaFileA(NULL); 2840 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError()); 2841 2842 BeginPath(hdc); 2843 ret = MoveToEx(hdc, 50, 50, NULL); 2844 ok( ret, "MoveToEx error %d.\n", GetLastError()); 2845 ret = LineTo(hdc, 50, 150); 2846 ok( ret, "LineTo error %d.\n", GetLastError()); 2847 ret = LineTo(hdc, 150, 150); 2848 ok( ret, "LineTo error %d.\n", GetLastError()); 2849 ret = LineTo(hdc, 150, 50); 2850 ok( ret, "LineTo error %d.\n", GetLastError()); 2851 ret = LineTo(hdc, 50, 50); 2852 ok( ret, "LineTo error %d.\n", GetLastError()); 2853 Rectangle(hdc, 10, 10, 20, 20); 2854 EndPath(hdc); 2855 2856 size = GetPath(hdc, NULL, NULL, 0); 2857 ok( size == -1, "GetPath returned %d.\n", size); 2858 2859 hmf = CloseMetaFile(hdc); 2860 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError()); 2861 2862 if (compare_mf_bits (hmf, MF_PATH_BITS, sizeof(MF_PATH_BITS), "mf_GetPath") != 0) 2863 { 2864 dump_mf_bits(hmf, "mf_GetPath"); 2865 EnumMetaFile(0, hmf, mf_enum_proc, 0); 2866 } 2867 2868 ret = DeleteMetaFile(hmf); 2869 ok( ret, "DeleteMetaFile error %d\n", GetLastError()); 2870 } 2871 2872 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData) 2873 { 2874 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData; 2875 POINT mapping[2] = { { 0, 0 }, { 10, 10 } }; 2876 /* When using MM_TEXT Win9x does not update the mapping mode 2877 * until a record is played which actually outputs something */ 2878 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj); 2879 LPtoDP(hdc, mapping, 2); 2880 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n", 2881 lpEMFR->iType, lpEMFR->nSize, 2882 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y); 2883 2884 if (lpEMFR->iType == EMR_LINETO) 2885 { 2886 INT x0, y0, x1, y1; 2887 if (!lpMFP || lpMFP->mm == MM_TEXT) 2888 { 2889 x0 = 0; 2890 y0 = 0; 2891 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5); 2892 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5); 2893 } 2894 else 2895 { 2896 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm); 2897 2898 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES)); 2899 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES)); 2900 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES)); 2901 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES)); 2902 } 2903 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1, 2904 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n", 2905 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y, 2906 x0, y0, x1, y1); 2907 } 2908 return TRUE; 2909 } 2910 2911 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp) 2912 { 2913 HDC hdcMf; 2914 HMETAFILE hmf; 2915 HENHMETAFILE hemf; 2916 BOOL ret; 2917 UINT size; 2918 LPBYTE pBits; 2919 2920 hdcMf = CreateMetaFileA(NULL); 2921 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError()); 2922 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y); 2923 ok(ret, "LineTo failed with error %d\n", GetLastError()); 2924 hmf = CloseMetaFile(hdcMf); 2925 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError()); 2926 2927 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0) 2928 { 2929 dump_mf_bits(hmf, "mf_LineTo"); 2930 EnumMetaFile(0, hmf, mf_enum_proc, 0); 2931 } 2932 2933 size = GetMetaFileBitsEx(hmf, 0, NULL); 2934 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError()); 2935 pBits = HeapAlloc(GetProcessHeap(), 0, size); 2936 GetMetaFileBitsEx(hmf, size, pBits); 2937 DeleteMetaFile(hmf); 2938 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp); 2939 HeapFree(GetProcessHeap(), 0, pBits); 2940 return hemf; 2941 } 2942 2943 static void test_mf_conversions(void) 2944 { 2945 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n"); 2946 { 2947 HDC hdcOffscreen = CreateCompatibleDC(NULL); 2948 HENHMETAFILE hemf; 2949 METAFILEPICT mfp; 2950 RECT rect = { 0, 0, 100, 100 }; 2951 mfp.mm = MM_ANISOTROPIC; 2952 mfp.xExt = 100; 2953 mfp.yExt = 100; 2954 mfp.hMF = NULL; 2955 hemf = create_converted_emf(&mfp); 2956 2957 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS), 2958 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0) 2959 { 2960 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC"); 2961 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC"); 2962 } 2963 2964 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect); 2965 2966 DeleteEnhMetaFile(hemf); 2967 DeleteDC(hdcOffscreen); 2968 } 2969 2970 trace("Testing MF->EMF conversion (MM_TEXT)\n"); 2971 { 2972 HDC hdcOffscreen = CreateCompatibleDC(NULL); 2973 HENHMETAFILE hemf; 2974 METAFILEPICT mfp; 2975 RECT rect = { 0, 0, 100, 100 }; 2976 mfp.mm = MM_TEXT; 2977 mfp.xExt = 0; 2978 mfp.yExt = 0; 2979 mfp.hMF = NULL; 2980 hemf = create_converted_emf(&mfp); 2981 2982 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS), 2983 "emf_LineTo MM_TEXT", TRUE) != 0) 2984 { 2985 dump_emf_bits(hemf, "emf_LineTo MM_TEXT"); 2986 dump_emf_records(hemf, "emf_LineTo MM_TEXT"); 2987 } 2988 2989 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect); 2990 2991 DeleteEnhMetaFile(hemf); 2992 DeleteDC(hdcOffscreen); 2993 } 2994 2995 trace("Testing MF->EMF conversion (NULL mfp)\n"); 2996 { 2997 HDC hdcOffscreen = CreateCompatibleDC(NULL); 2998 HENHMETAFILE hemf; 2999 RECT rect = { 0, 0, 100, 100 }; 3000 hemf = create_converted_emf(NULL); 3001 3002 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS), 3003 "emf_LineTo NULL", TRUE) != 0) 3004 { 3005 dump_emf_bits(hemf, "emf_LineTo NULL"); 3006 dump_emf_records(hemf, "emf_LineTo NULL"); 3007 } 3008 3009 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect); 3010 3011 DeleteEnhMetaFile(hemf); 3012 DeleteDC(hdcOffscreen); 3013 } 3014 } 3015 3016 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull, 3017 LONG mm, LONG xExt, LONG yExt, 3018 RECTL * rclBounds, RECTL * rclFrame) 3019 { 3020 METAFILEPICT mfp; 3021 METAFILEPICT * mfpPtr = NULL; 3022 HENHMETAFILE emf; 3023 ENHMETAHEADER header; 3024 UINT res; 3025 3026 if (!mfpIsNull) 3027 { 3028 mfp.mm = mm; 3029 mfp.xExt = xExt; 3030 mfp.yExt = yExt; 3031 mfpPtr = &mfp; 3032 } 3033 3034 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr); 3035 ok(emf != NULL, "SetWinMetaFileBits failed\n"); 3036 if (!emf) return FALSE; 3037 res = GetEnhMetaFileHeader(emf, sizeof(header), &header); 3038 ok(res != 0, "GetEnhMetaHeader failed\n"); 3039 DeleteEnhMetaFile(emf); 3040 if (!res) return FALSE; 3041 3042 *rclBounds = header.rclBounds; 3043 *rclFrame = header.rclFrame; 3044 return TRUE; 3045 } 3046 3047 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull, 3048 LONG mm, LONG xExt, LONG yExt, 3049 RECTL * rclBoundsExpected, RECTL * rclFrameExpected) 3050 { 3051 RECTL rclBounds, rclFrame; 3052 3053 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame)) 3054 { 3055 const char * msg; 3056 char buf[64]; 3057 3058 if (mfpIsNull) 3059 { 3060 msg = "mfp == NULL"; 3061 } 3062 else 3063 { 3064 const char * mm_str; 3065 switch (mm) 3066 { 3067 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break; 3068 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break; 3069 default: mm_str = "Unexpected"; 3070 } 3071 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt); 3072 msg = buf; 3073 } 3074 3075 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg); 3076 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg); 3077 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg); 3078 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg); 3079 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg); 3080 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg); 3081 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg); 3082 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg); 3083 } 3084 } 3085 3086 static void test_SetWinMetaFileBits(void) 3087 { 3088 HMETAFILE wmf; 3089 HDC wmfDC; 3090 BYTE * buffer; 3091 UINT buffer_size; 3092 RECT rect; 3093 UINT res; 3094 RECTL rclBoundsAnisotropic, rclFrameAnisotropic; 3095 RECTL rclBoundsIsotropic, rclFrameIsotropic; 3096 RECTL rclBounds, rclFrame; 3097 HDC dc; 3098 LONG diffx, diffy; 3099 3100 wmfDC = CreateMetaFileA(NULL); 3101 ok(wmfDC != NULL, "CreateMetaFile failed\n"); 3102 if (!wmfDC) return; 3103 3104 SetWindowExtEx(wmfDC, 100, 100, NULL); 3105 SetRect(&rect, 0, 0, 50, 50); 3106 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH)); 3107 wmf = CloseMetaFile(wmfDC); 3108 ok(wmf != NULL, "Metafile creation failed\n"); 3109 if (!wmf) return; 3110 3111 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL); 3112 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n"); 3113 if (buffer_size == 0) 3114 { 3115 DeleteMetaFile(wmf); 3116 return; 3117 } 3118 3119 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size); 3120 ok(buffer != NULL, "HeapAlloc failed\n"); 3121 if (!buffer) 3122 { 3123 DeleteMetaFile(wmf); 3124 return; 3125 } 3126 3127 res = GetMetaFileBitsEx(wmf, buffer_size, buffer); 3128 ok(res == buffer_size, "GetMetaFileBitsEx failed\n"); 3129 DeleteMetaFile(wmf); 3130 if (res != buffer_size) 3131 { 3132 HeapFree(GetProcessHeap(), 0, buffer); 3133 return; 3134 } 3135 3136 /* Get the reference bounds and frame */ 3137 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3138 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic); 3139 3140 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 && 3141 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0, 3142 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n"); 3143 3144 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n"); 3145 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n"); 3146 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom; 3147 if (diffx < 0) diffx = -diffx; 3148 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n"); 3149 3150 dc = CreateCompatibleDC(NULL); 3151 3152 /* Allow 1 mm difference (rounding errors) */ 3153 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2; 3154 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2; 3155 if (diffx < 0) diffx = -diffx; 3156 if (diffy < 0) diffy = -diffy; 3157 todo_wine 3158 { 3159 ok(diffx <= 1 && diffy <= 1, 3160 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n", 3161 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom); 3162 } 3163 3164 /* Allow 1 mm difference (rounding errors) */ 3165 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2; 3166 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2; 3167 if (diffx < 0) diffx = -diffx; 3168 if (diffy < 0) diffy = -diffy; 3169 todo_wine 3170 { 3171 ok(diffx <= 1 && diffy <= 1, 3172 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n", 3173 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100); 3174 } 3175 DeleteDC(dc); 3176 3177 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */ 3178 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3179 3180 /* If xExt or yExt is zero or negative, the whole device surface is used */ 3181 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3182 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic); 3183 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3184 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic); 3185 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3186 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic); 3187 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3188 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic); 3189 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3190 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic); 3191 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3192 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic); 3193 3194 /* MSDN says that negative xExt and yExt values specify a ratio. 3195 Check that this is wrong and the whole device surface is used */ 3196 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic); 3197 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic); 3198 3199 /* Ordinary conversions */ 3200 3201 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame)) 3202 { 3203 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000, 3204 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n"); 3205 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom, 3206 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n"); 3207 } 3208 3209 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame)) 3210 { 3211 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000, 3212 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n"); 3213 ok(rclBounds.left == 0 && rclBounds.top == 0, 3214 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n"); 3215 3216 /* Wine has a rounding error */ 3217 diffx = rclBounds.right - rclBounds.bottom; 3218 if (diffx < 0) diffx = -diffx; 3219 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n"); 3220 } 3221 3222 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame)) 3223 { 3224 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000, 3225 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n"); 3226 } 3227 3228 HeapFree(GetProcessHeap(), 0, buffer); 3229 } 3230 3231 static BOOL near_match(int x, int y) 3232 { 3233 int epsilon = min(abs(x), abs(y)); 3234 3235 epsilon = max(epsilon/100, 2); 3236 3237 if(x < y - epsilon || x > y + epsilon) return FALSE; 3238 return TRUE; 3239 } 3240 3241 static void getwinmetafilebits(UINT mode, int scale, RECT *rc) 3242 { 3243 HENHMETAFILE emf, emf2; 3244 HDC display_dc, emf_dc; 3245 ENHMETAHEADER *enh_header, *enh2_header; 3246 UINT size, emf_size, i, emf2_size; 3247 WORD check = 0; 3248 DWORD rec_num = 0; 3249 METAHEADER *mh = NULL; 3250 METARECORD *rec; 3251 INT horz_res, vert_res, horz_size, vert_size; 3252 INT curve_caps, line_caps, poly_caps; 3253 METAFILEPICT mfp; 3254 3255 display_dc = GetDC(NULL); 3256 ok(display_dc != NULL, "display_dc is NULL\n"); 3257 3258 horz_res = GetDeviceCaps(display_dc, HORZRES); 3259 vert_res = GetDeviceCaps(display_dc, VERTRES); 3260 horz_size = GetDeviceCaps(display_dc, HORZSIZE); 3261 vert_size = GetDeviceCaps(display_dc, VERTSIZE); 3262 3263 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL); 3264 ok(emf_dc != NULL, "emf_dc is NULL\n"); 3265 3266 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS); 3267 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps); 3268 3269 line_caps = GetDeviceCaps(emf_dc, LINECAPS); 3270 ok(line_caps == 254, "expect 254 got %d\n", line_caps); 3271 3272 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS); 3273 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps); 3274 3275 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */ 3276 Rectangle(emf_dc, 0, 0, 1000, 20); 3277 emf = CloseEnhMetaFile(emf_dc); 3278 ok(emf != NULL, "emf is NULL\n"); 3279 3280 emf_size = GetEnhMetaFileBits(emf, 0, NULL); 3281 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size); 3282 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header); 3283 DeleteEnhMetaFile(emf); 3284 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs 3285 have different resolutions */ 3286 enh_header->szlDevice.cx *= scale; 3287 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header); 3288 ok(emf != NULL, "emf is NULL\n"); 3289 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n"); 3290 3291 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc); 3292 ok(size || 3293 broken(size == 0), /* some versions of winxp fail for some reason */ 3294 "GetWinMetaFileBits returns 0\n"); 3295 if(!size) goto end; 3296 mh = HeapAlloc(GetProcessHeap(), 0, size); 3297 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc); 3298 3299 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i]; 3300 ok(check == 0, "check %04x\n", check); 3301 3302 rec = (METARECORD*)(mh + 1); 3303 3304 while(rec->rdSize && rec->rdFunction) 3305 { 3306 const DWORD chunk_size = 0x2000; 3307 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size; 3308 3309 if(rec_num < mfcomment_chunks) 3310 { 3311 DWORD this_chunk_size = chunk_size; 3312 3313 if(rec_num == mfcomment_chunks - 1) 3314 this_chunk_size = emf_size - rec_num * chunk_size; 3315 3316 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2); 3317 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction); 3318 if(rec->rdSize < (this_chunk_size + 44) / 2) break; 3319 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]); 3320 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34); 3321 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */ 3322 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */ 3323 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]); 3324 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]); 3325 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]); 3326 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]); 3327 /* parm[8] is the checksum, tested above */ 3328 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]); 3329 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]); 3330 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]); 3331 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */ 3332 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]); 3333 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size); 3334 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]); 3335 ok(*(DWORD*)(rec->rdParm + 15) == emf_size - this_chunk_size - rec_num * chunk_size, "got %08x\n", *(DWORD*)(rec->rdParm + 15)); /* DWORD size remaining after current chunk */ 3336 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size); 3337 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n"); 3338 } 3339 3340 else if(rec_num == mfcomment_chunks) 3341 { 3342 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction); 3343 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]); 3344 } 3345 else if(rec_num == mfcomment_chunks + 1) 3346 { 3347 POINT pt; 3348 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction); 3349 switch(mode) 3350 { 3351 case MM_TEXT: 3352 case MM_ISOTROPIC: 3353 case MM_ANISOTROPIC: 3354 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1; 3355 pt.x = MulDiv(rc->left, horz_res, horz_size * 100); 3356 break; 3357 case MM_LOMETRIC: 3358 pt.y = MulDiv(-rc->top, 1, 10) + 1; 3359 pt.x = MulDiv( rc->left, 1, 10); 3360 break; 3361 case MM_HIMETRIC: 3362 pt.y = -rc->top + 1; 3363 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */ 3364 break; 3365 case MM_LOENGLISH: 3366 pt.y = MulDiv(-rc->top, 10, 254) + 1; 3367 pt.x = MulDiv( rc->left, 10, 254); 3368 break; 3369 case MM_HIENGLISH: 3370 pt.y = MulDiv(-rc->top, 100, 254) + 1; 3371 pt.x = MulDiv( rc->left, 100, 254); 3372 break; 3373 case MM_TWIPS: 3374 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1; 3375 pt.x = MulDiv( rc->left, 72 * 20, 2540); 3376 break; 3377 default: 3378 pt.x = pt.y = 0; 3379 } 3380 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y); 3381 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x); 3382 } 3383 if(rec_num == mfcomment_chunks + 2) 3384 { 3385 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction); 3386 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)), 3387 "got %d\n", (short)rec->rdParm[0]); 3388 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)), 3389 "got %d\n", (short)rec->rdParm[1]); 3390 } 3391 3392 rec_num++; 3393 rec = (METARECORD*)((WORD*)rec + rec->rdSize); 3394 } 3395 3396 /* Show that we get the original back when we do the reverse conversion. 3397 mfp is ignored in this case. */ 3398 mfp.mm = MM_ISOTROPIC; 3399 mfp.xExt = 0xcafe; 3400 mfp.yExt = 0xbeef; 3401 emf2 = SetWinMetaFileBits( size, (BYTE*)mh, NULL, &mfp ); 3402 ok( !!emf2, "got NULL\n" ); 3403 emf2_size = GetEnhMetaFileBits( emf2, 0, NULL ); 3404 enh2_header = HeapAlloc( GetProcessHeap(), 0, emf2_size ); 3405 emf2_size = GetEnhMetaFileBits( emf2, emf2_size, (BYTE*)enh2_header ); 3406 ok( emf_size == emf2_size, "%d %d\n", emf_size, emf2_size ); 3407 ok( !memcmp( enh_header, enh2_header, emf_size ), "mismatch\n" ); 3408 HeapFree( GetProcessHeap(), 0, enh2_header ); 3409 DeleteEnhMetaFile( emf2 ); 3410 3411 end: 3412 HeapFree(GetProcessHeap(), 0, mh); 3413 HeapFree(GetProcessHeap(), 0, enh_header); 3414 DeleteEnhMetaFile(emf); 3415 3416 ReleaseDC(NULL, display_dc); 3417 } 3418 3419 static void test_GetWinMetaFileBits(void) 3420 { 3421 UINT mode; 3422 RECT frames[] = 3423 { 3424 { 1000, 2000, 3000, 6000}, 3425 {-1000, 2000, 3000, 6000}, 3426 { 1000, -2000, 3000, 6000}, 3427 { 1005, 2005, 3000, 6000}, 3428 {-1005, -2005, 3000, 6000}, 3429 {-1005, -2010, 3000, 6000}, 3430 {-1005, 2010, 3000, 6000}, 3431 { 0, 0, 1, 1}, 3432 { -1, -1, 1, 1}, 3433 { 0, 0, 0, 0} 3434 }; 3435 3436 for(mode = MM_MIN; mode <= MM_MAX; mode++) 3437 { 3438 RECT *rc; 3439 for(rc = frames; rc->right - rc->left > 0; rc++) 3440 { 3441 getwinmetafilebits(mode, 1, rc); 3442 getwinmetafilebits(mode, 2, rc); 3443 } 3444 } 3445 } 3446 3447 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC); 3448 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC); 3449 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC); 3450 3451 static void test_gdiis(void) 3452 { 3453 RECT rect = {0,0,100,100}; 3454 HDC hdc, hemfDC, hmfDC; 3455 HENHMETAFILE hemf; 3456 HMODULE hgdi32; 3457 3458 /* resolve all the functions */ 3459 hgdi32 = GetModuleHandleA("gdi32.dll"); 3460 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC"); 3461 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC"); 3462 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC"); 3463 3464 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC) 3465 { 3466 win_skip("Needed GdiIs* functions are not available\n"); 3467 return; 3468 } 3469 3470 /* try with nothing */ 3471 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n"); 3472 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n"); 3473 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n"); 3474 3475 /* try with a metafile */ 3476 hmfDC = CreateMetaFileA(NULL); 3477 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n"); 3478 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n"); 3479 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n"); 3480 DeleteMetaFile(CloseMetaFile(hmfDC)); 3481 3482 /* try with an enhanced metafile */ 3483 hdc = GetDC(NULL); 3484 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL); 3485 ok(hemfDC != NULL, "failed to create emf\n"); 3486 3487 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n"); 3488 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n"); 3489 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n"); 3490 3491 hemf = CloseEnhMetaFile(hemfDC); 3492 ok(hemf != NULL, "failed to close EMF\n"); 3493 DeleteEnhMetaFile(hemf); 3494 ReleaseDC(NULL,hdc); 3495 } 3496 3497 static void test_SetEnhMetaFileBits(void) 3498 { 3499 BYTE data[256]; 3500 HENHMETAFILE hemf; 3501 ENHMETAHEADER *emh; 3502 3503 memset(data, 0xAA, sizeof(data)); 3504 SetLastError(0xdeadbeef); 3505 hemf = SetEnhMetaFileBits(sizeof(data), data); 3506 ok(!hemf, "SetEnhMetaFileBits should fail\n"); 3507 ok(GetLastError() == ERROR_INVALID_DATA || 3508 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */ 3509 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); 3510 3511 emh = (ENHMETAHEADER *)data; 3512 memset(emh, 0, sizeof(*emh)); 3513 3514 emh->iType = EMR_HEADER; 3515 emh->nSize = sizeof(*emh); 3516 emh->dSignature = ENHMETA_SIGNATURE; 3517 /* emh->nVersion = 0x10000; XP doesn't care about version */ 3518 emh->nBytes = sizeof(*emh); 3519 /* emh->nRecords = 1; XP doesn't care about records */ 3520 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */ 3521 3522 SetLastError(0xdeadbeef); 3523 hemf = SetEnhMetaFileBits(emh->nBytes, data); 3524 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError()); 3525 DeleteEnhMetaFile(hemf); 3526 3527 /* XP refuses to load unaligned EMF */ 3528 emh->nBytes++; 3529 SetLastError(0xdeadbeef); 3530 hemf = SetEnhMetaFileBits(emh->nBytes, data); 3531 ok(!hemf || 3532 broken(hemf != NULL), /* Win9x, WinMe */ 3533 "SetEnhMetaFileBits should fail\n"); 3534 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError()); 3535 DeleteEnhMetaFile(hemf); 3536 3537 emh->dSignature = 0; 3538 emh->nBytes--; 3539 SetLastError(0xdeadbeef); 3540 hemf = SetEnhMetaFileBits(emh->nBytes, data); 3541 ok(!hemf || 3542 broken(hemf != NULL), /* Win9x, WinMe */ 3543 "SetEnhMetaFileBits should fail\n"); 3544 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError()); 3545 DeleteEnhMetaFile(hemf); 3546 } 3547 3548 static void test_emf_polybezier(void) 3549 { 3550 HDC hdcMetafile; 3551 HENHMETAFILE hemf; 3552 POINT pts[4]; 3553 BOOL ret; 3554 3555 SetLastError(0xdeadbeef); 3556 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL); 3557 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError()); 3558 3559 pts[0].x = pts[0].y = 10; 3560 pts[1].x = pts[1].y = 20; 3561 pts[2].x = pts[2].y = 15; 3562 pts[3].x = pts[3].y = 25; 3563 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */ 3564 ok( ret, "PolyBezierTo failed\n" ); 3565 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */ 3566 ok( ret, "PolyBezier failed\n" ); 3567 3568 pts[0].x = pts[0].y = 32769; 3569 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */ 3570 ok( ret, "PolyBezier failed\n" ); 3571 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */ 3572 ok( ret, "PolyBezierTo failed\n" ); 3573 3574 hemf = CloseEnhMetaFile(hdcMetafile); 3575 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 3576 3577 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS), 3578 "emf_Bezier", FALSE) != 0) 3579 { 3580 dump_emf_bits(hemf, "emf_Bezier"); 3581 dump_emf_records(hemf, "emf_Bezier"); 3582 } 3583 3584 DeleteEnhMetaFile(hemf); 3585 } 3586 3587 static const unsigned char EMF_PATH_BITS[] = 3588 { 3589 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 3590 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 3591 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 3592 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 3593 0x70, 0x17, 0x00, 0x00, 0x70, 0x17, 0x00, 0x00, 3594 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 3595 0xf8, 0x02, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 3596 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3598 0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 3599 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 3600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3601 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00, 3602 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00, 3603 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 3604 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 3605 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 3606 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 3607 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 3608 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 3609 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 3610 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 3611 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 3612 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 3613 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 3614 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 3615 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 3616 0x13, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 3617 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 3618 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 3619 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 3620 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 3621 0x15, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 3622 0x28, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 3623 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 3624 0x1a, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 3625 0x1b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 3626 0x17, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 3627 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 3628 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 3629 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 3630 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 3631 0x15, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 3632 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 3633 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 3634 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 3635 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 3636 0x15, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 3637 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 3638 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 3639 0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 3640 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 3641 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 3642 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 3643 0x05, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 3644 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3645 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 3646 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 3647 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00, 3648 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 3649 0x59, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 3650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3651 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 3652 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 3653 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 3654 0x14, 0x00, 0x14, 0x00, 0x5a, 0x00, 0x00, 0x00, 3655 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3656 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 3657 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 3658 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 3659 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 3660 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 3661 0x14, 0x00, 0x14, 0x00, 0x5c, 0x00, 0x00, 0x00, 3662 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3663 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 3664 0xff, 0xff, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00, 3665 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00, 3666 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 3667 0x1e, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x14, 0x00, 3668 0x14, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x14, 0x00, 3669 0x14, 0x00, 0x0a, 0x00, 0x06, 0x02, 0x04, 0x04, 3670 0x04, 0x02, 0x03, 0x06, 0x02, 0x00, 0x00, 0x00, 3671 0x29, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 3672 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 3673 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x42, 3674 0x00, 0x00, 0x34, 0x43, 0x3c, 0x00, 0x00, 0x00, 3675 0x08, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 3676 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 3677 0x0a, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 3678 0x96, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 3679 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3680 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 3681 0xff, 0xff, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00, 3682 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3683 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 3684 }; 3685 3686 static const unsigned char EMF_EMPTY_PATH_BITS[] = 3687 { 3688 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 3689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3690 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 3691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3692 0xd8, 0xff, 0xff, 0xff, 0xd8, 0xff, 0xff, 0xff, 3693 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, 3694 0xc8, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 3695 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3697 0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 3698 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 3699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3700 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00, 3701 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00, 3702 0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 3703 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 3704 0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 3705 0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 3706 0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 3707 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 3708 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 3709 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 3710 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 3711 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3712 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 3713 }; 3714 3715 static void test_emf_paths(void) 3716 { 3717 POINT pts[9] = {{10, 10}, {20, 10}, {10, 20}, {20, 20}, {30, 30}, {40, 20}, {20, 30}, {20, 20}, {20, 10}}; 3718 DWORD counts[2] = {2, 2}; 3719 BYTE types[9] = { PT_MOVETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, 3720 PT_LINETO | PT_CLOSEFIGURE, PT_MOVETO, PT_LINETO }; 3721 HDC hdcMetafile; 3722 HENHMETAFILE hemf; 3723 BOOL ret; 3724 int size; 3725 3726 SetLastError(0xdeadbeef); 3727 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL); 3728 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError()); 3729 3730 BeginPath(hdcMetafile); 3731 ret = MoveToEx(hdcMetafile, 50, 50, NULL); 3732 ok( ret, "MoveToEx error %d.\n", GetLastError()); 3733 ret = LineTo(hdcMetafile, 50, 150); 3734 ok( ret, "LineTo error %d.\n", GetLastError()); 3735 ret = LineTo(hdcMetafile, 150, 150); 3736 ok( ret, "LineTo error %d.\n", GetLastError()); 3737 ret = LineTo(hdcMetafile, 150, 50); 3738 ok( ret, "LineTo error %d.\n", GetLastError()); 3739 ret = LineTo(hdcMetafile, 50, 50); 3740 ok( ret, "LineTo error %d.\n", GetLastError()); 3741 Rectangle(hdcMetafile, 10, 10, 20, 20); 3742 Arc(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21); 3743 ArcTo(hdcMetafile, 23, 23, 37, 27, 37, 27, 23, 23); 3744 Chord(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21); 3745 Pie(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21); 3746 Ellipse(hdcMetafile, 10, 10, 20, 20); 3747 RoundRect(hdcMetafile, 10, 10, 20, 20, 3, 5); 3748 Polyline(hdcMetafile, pts, 4); 3749 PolylineTo(hdcMetafile, pts, 4); 3750 PolyPolyline(hdcMetafile, pts, counts, 2); 3751 PolyDraw(hdcMetafile, pts, types, 9); 3752 AngleArc(hdcMetafile, 37, 36, 23, 90, 180); 3753 EndPath(hdcMetafile); 3754 3755 size = GetPath(hdcMetafile, NULL, NULL, 0); 3756 ok( size == 112, "GetPath returned %d.\n", size); 3757 3758 ret = StrokeAndFillPath( hdcMetafile ); 3759 ok( ret, "StrokeAndFillPath failed err %d\n", GetLastError() ); 3760 ret = StrokeAndFillPath( hdcMetafile ); 3761 ok( !ret, "StrokeAndFillPath succeeded\n" ); 3762 3763 hemf = CloseEnhMetaFile(hdcMetafile); 3764 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 3765 3766 if (compare_emf_bits(hemf, EMF_PATH_BITS, sizeof(EMF_PATH_BITS), "test_emf_paths", FALSE) != 0) 3767 { 3768 dump_emf_bits(hemf, "test_emf_paths"); 3769 dump_emf_records(hemf, "test_emf_paths"); 3770 } 3771 3772 DeleteEnhMetaFile(hemf); 3773 3774 SetLastError(0xdeadbeef); 3775 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL); 3776 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError()); 3777 3778 ret = BeginPath(hdcMetafile); 3779 ok( ret, "BeginPath failed error %d\n", GetLastError() ); 3780 ret = CloseFigure(hdcMetafile); 3781 ok( ret, "CloseFigure failed error %d\n", GetLastError() ); 3782 ret = BeginPath(hdcMetafile); 3783 ok( ret, "BeginPath failed error %d\n", GetLastError() ); 3784 ret = EndPath(hdcMetafile); 3785 ok( ret, "EndPath failed error %d\n", GetLastError() ); 3786 ret = EndPath(hdcMetafile); 3787 ok( !ret, "EndPath succeeded\n" ); 3788 ret = CloseFigure(hdcMetafile); 3789 ok( !ret, "CloseFigure succeeded\n" ); 3790 ret = BeginPath(hdcMetafile); 3791 ok( ret, "BeginPath failed error %d\n", GetLastError() ); 3792 ret = AbortPath(hdcMetafile); 3793 ok( ret, "AbortPath failed error %d\n", GetLastError() ); 3794 ret = AbortPath(hdcMetafile); 3795 ok( ret, "AbortPath failed error %d\n", GetLastError() ); 3796 3797 hemf = CloseEnhMetaFile(hdcMetafile); 3798 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 3799 3800 if (compare_emf_bits(hemf, EMF_EMPTY_PATH_BITS, sizeof(EMF_EMPTY_PATH_BITS), "empty path", FALSE) != 0) 3801 { 3802 dump_emf_bits(hemf, "empty path"); 3803 dump_emf_records(hemf, "empty path"); 3804 } 3805 3806 DeleteEnhMetaFile(hemf); 3807 } 3808 3809 static void test_emf_PolyPolyline(void) 3810 { 3811 HDC hdcMetafile; 3812 HENHMETAFILE hemf; 3813 POINT pts[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}}; 3814 DWORD counts[2]; 3815 BOOL ret; 3816 3817 SetLastError(0xdeadbeef); 3818 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL); 3819 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError()); 3820 3821 ret = PolyPolyline(hdcMetafile, NULL, NULL, 0); 3822 ok( !ret, "PolyPolyline\n" ); 3823 3824 SetLastError( 0xdeadbeef ); 3825 counts[0] = 0; 3826 counts[1] = 1; 3827 ret = PolyPolyline(hdcMetafile, pts, counts, 2); 3828 ok( !ret, "PolyPolyline\n" ); 3829 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() ); 3830 3831 SetLastError( 0xdeadbeef ); 3832 counts[0] = 1; 3833 counts[1] = 1; 3834 ret = PolyPolyline(hdcMetafile, pts, counts, 2); 3835 ok( !ret, "PolyPolyline\n" ); 3836 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() ); 3837 3838 SetLastError( 0xdeadbeef ); 3839 counts[0] = 2; 3840 counts[1] = 1; 3841 ret = PolyPolyline(hdcMetafile, pts, counts, 2); 3842 ok( !ret, "PolyPolyline\n" ); 3843 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() ); 3844 3845 counts[0] = 2; 3846 counts[1] = 2; 3847 ret = PolyPolyline(hdcMetafile, pts, counts, 2); 3848 ok( ret, "PolyPolyline\n" ); 3849 3850 hemf = CloseEnhMetaFile(hdcMetafile); 3851 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError()); 3852 3853 if(compare_emf_bits(hemf, EMF_POLYPOLYLINE_BITS, sizeof(EMF_POLYPOLYLINE_BITS), 3854 "emf_PolyPolyline", FALSE) != 0) 3855 { 3856 dump_emf_bits(hemf, "emf_PolyPolyline"); 3857 dump_emf_records(hemf, "emf_PolyPolyline"); 3858 } 3859 3860 DeleteEnhMetaFile(hemf); 3861 } 3862 3863 static void test_emf_GradientFill(void) 3864 { 3865 HDC mf; 3866 HENHMETAFILE hemf; 3867 TRIVERTEX v[] = 3868 { 3869 { 1, 10, 0xff00, 0x8000, 0x0000, 0x8001 }, 3870 { 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 }, 3871 { 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 }, 3872 { 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 }, 3873 { 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 } 3874 }; 3875 GRADIENT_TRIANGLE tri[] = { { 0, 1, 2 }, { 3, 1, 0 } }; 3876 BOOL ret; 3877 3878 mf = CreateEnhMetaFileA( GetDC( 0 ), NULL, NULL, NULL ); 3879 ok( mf != 0, "CreateEnhMetaFileA error %d\n", GetLastError() ); 3880 3881 /* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug 3882 * means it allocates three mesh indices rather than two per 3883 * rectangle. This results in uninitialised values being written 3884 * to the EMF which is rather difficult to test against. 3885 * 3886 * Note also that the final vertex here is not required, yet it is 3887 * written to the EMF, but is not considered in the bounds 3888 * calculation. 3889 */ 3890 ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]), 3891 GRADIENT_FILL_TRIANGLE ); 3892 ok( ret, "GradientFill\n" ); 3893 3894 hemf = CloseEnhMetaFile( mf ); 3895 ok( hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError() ); 3896 3897 if (compare_emf_bits( hemf, EMF_GRADIENTFILL_BITS, sizeof(EMF_GRADIENTFILL_BITS), 3898 "emf_GradientFill", FALSE ) != 0) 3899 { 3900 dump_emf_bits( hemf, "emf_GradientFill" ); 3901 dump_emf_records( hemf, "emf_GradientFill" ); 3902 } 3903 3904 DeleteEnhMetaFile( hemf ); 3905 } 3906 3907 START_TEST(metafile) 3908 { 3909 init_function_pointers(); 3910 3911 /* For enhanced metafiles (enhmfdrv) */ 3912 test_ExtTextOut(); 3913 test_ExtTextOutScale(); 3914 test_SaveDC(); 3915 test_emf_BitBlt(); 3916 test_emf_DCBrush(); 3917 test_emf_ExtTextOut_on_path(); 3918 test_emf_clipping(); 3919 test_emf_polybezier(); 3920 test_emf_paths(); 3921 test_emf_PolyPolyline(); 3922 test_emf_GradientFill(); 3923 3924 /* For win-format metafiles (mfdrv) */ 3925 test_mf_SaveDC(); 3926 test_mf_Blank(); 3927 test_mf_Graphics(); 3928 test_mf_PatternBrush(); 3929 test_mf_DCBrush(); 3930 test_CopyMetaFile(); 3931 test_SetMetaFileBits(); 3932 test_mf_ExtTextOut_on_path(); 3933 test_mf_clipping(); 3934 test_mf_GetPath(); 3935 3936 /* For metafile conversions */ 3937 test_mf_conversions(); 3938 test_SetWinMetaFileBits(); 3939 test_GetWinMetaFileBits(); 3940 3941 test_gdiis(); 3942 test_SetEnhMetaFileBits(); 3943 } 3944