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