~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdi32/tests/metafile.c

Version: ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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 
 41 #define GDI_GET_PROC(func)                                     \
 42     p ## func = (void *)GetProcAddress(hGDI, #func);           \
 43     if(!p ## func)                                             \
 44         trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
 45 
 46 static void init_function_pointers(void)
 47 {
 48     HMODULE hGDI;
 49 
 50     pGetRelAbs = NULL;
 51     pSetRelAbs = NULL;
 52 
 53     hGDI = GetModuleHandleA("gdi32.dll");
 54     assert(hGDI);
 55     GDI_GET_PROC(GetRelAbs);
 56     GDI_GET_PROC(SetRelAbs);
 57 }
 58 
 59 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
 60     const ENHMETARECORD *emr, int n_objs, LPARAM param)
 61 {
 62     static int n_record;
 63     DWORD i;
 64     const INT *dx;
 65     INT *orig_dx = (INT *)param;
 66     LOGFONTA device_lf;
 67     INT ret;
 68 
 69     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
 70            hdc, emr->iType, emr->nSize, (void *)param);
 71 
 72     if(!hdc) return 1;
 73 
 74     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
 75 
 76     switch (emr->iType)
 77     {
 78     case EMR_HEADER:
 79         ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
 80         ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
 81         ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
 82         ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
 83         ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
 84         ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
 85         ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
 86 
 87         /* GetBkMode, GetRelAbs do not get reset to the default value */
 88         ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
 89         if(pSetRelAbs && pGetRelAbs)
 90             ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
 91 
 92         n_record = 0;
 93         break;
 94 
 95     case EMR_EXTTEXTOUTA:
 96     {
 97         const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
 98         dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
 99 
100         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
101         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
102 
103         /* compare up to lfOutPrecision, other values are not interesting,
104          * and in fact sometimes arbitrary adapted by Win9x.
105          */
106         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
107         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
108 
109         for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
110         {
111             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
112                                      n_record, i, dx[i], orig_dx[i]);
113         }
114         n_record++;
115         emr_processed = TRUE;
116         break;
117     }
118 
119     case EMR_EXTTEXTOUTW:
120     {
121         const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
122         dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
123 
124         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
125         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
126 
127         /* compare up to lfOutPrecision, other values are not interesting,
128          * and in fact sometimes arbitrary adapted by Win9x.
129          */
130         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
131         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
132 
133         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
134         {
135             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
136                                      n_record, i, dx[i], orig_dx[i]);
137         }
138         n_record++;
139         emr_processed = TRUE;
140         break;
141     }
142 
143     default:
144         break;
145     }
146 
147     return 1;
148 }
149 
150 static void test_ExtTextOut(void)
151 {
152     HWND hwnd;
153     HDC hdcDisplay, hdcMetafile;
154     HENHMETAFILE hMetafile;
155     HFONT hFont;
156     static const char text[] = "Simple text to test ExtTextOut on metafiles";
157     INT i, len, dx[256];
158     static const RECT rc = { 0, 0, 100, 100 };
159     BOOL ret;
160 
161     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
162 
163     /* Win9x doesn't play EMFs on invisible windows */
164     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
165                            0, 0, 200, 200, 0, 0, 0, NULL);
166     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
167 
168     hdcDisplay = GetDC(hwnd);
169     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
170 
171     trace("hdcDisplay %p\n", hdcDisplay);
172 
173     SetMapMode(hdcDisplay, MM_TEXT);
174 
175     memset(&orig_lf, 0, sizeof(orig_lf));
176 
177     orig_lf.lfCharSet = ANSI_CHARSET;
178     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
179     orig_lf.lfWeight = FW_DONTCARE;
180     orig_lf.lfHeight = 7;
181     orig_lf.lfQuality = DEFAULT_QUALITY;
182     lstrcpyA(orig_lf.lfFaceName, "Arial");
183     hFont = CreateFontIndirectA(&orig_lf);
184     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
185 
186     hFont = SelectObject(hdcDisplay, hFont);
187 
188     len = lstrlenA(text);
189     for (i = 0; i < len; i++)
190     {
191         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
192         ok( ret, "GetCharWidthA error %d\n", GetLastError());
193     }
194     hFont = SelectObject(hdcDisplay, hFont);
195 
196     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
198 
199     trace("hdcMetafile %p\n", hdcMetafile);
200 
201     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
202        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
203 
204     hFont = SelectObject(hdcMetafile, hFont);
205 
206     /* 1. pass NULL lpDx */
207     ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
208     ok( ret, "ExtTextOutA error %d\n", GetLastError());
209 
210     /* 2. pass custom lpDx */
211     ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
212     ok( ret, "ExtTextOutA error %d\n", GetLastError());
213 
214     hFont = SelectObject(hdcMetafile, hFont);
215     ret = DeleteObject(hFont);
216     ok( ret, "DeleteObject error %d\n", GetLastError());
217 
218     hMetafile = CloseEnhMetaFile(hdcMetafile);
219     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
220 
221     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
222 
223     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
224     ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
225 
226     SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
227     SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
228     SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
229     SetROP2(hdcDisplay, R2_NOT);
230     SetArcDirection(hdcDisplay, AD_CLOCKWISE);
231     SetPolyFillMode(hdcDisplay, WINDING);
232     SetStretchBltMode(hdcDisplay, HALFTONE);
233 
234     if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
235     SetBkMode(hdcDisplay, OPAQUE);
236 
237     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
238     ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
239 
240     ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
241         "text align %08x\n", GetTextAlign(hdcDisplay));
242     ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
243     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
244     ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
245     ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir  %d\n", GetArcDirection(hdcDisplay));
246     ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
247     ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
248 
249     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
250 
251     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
252        "A valid hdc has to require a valid rc\n");
253 
254     ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
255        "A null hdc does not require a valid rc\n");
256 
257     ret = DeleteEnhMetaFile(hMetafile);
258     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
259     ret = ReleaseDC(hwnd, hdcDisplay);
260     ok( ret, "ReleaseDC error %d\n", GetLastError());
261     DestroyWindow(hwnd);
262 }
263 
264 static void check_dc_state(HDC hdc, int restore_no,
265                            int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
266                            int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
267 {
268     BOOL ret;
269     XFORM xform;
270     POINT vp_org, win_org;
271     SIZE vp_size, win_size;
272     FLOAT xscale, yscale, edx, edy;
273 
274     SetLastError(0xdeadbeef);
275     ret = GetWorldTransform(hdc, &xform);
276     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
277     ok(ret, "GetWorldTransform error %u\n", GetLastError());
278 
279     trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
280 
281     ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
282     ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
283 
284     xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
285     trace("x scale %f\n", xscale);
286     ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
287        restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
288 
289     yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
290     trace("y scale %f\n", yscale);
291     ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
292        restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
293 
294     edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
295     ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
296     edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
297     ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
298 
299     return;
300 
301 win9x_here:
302 
303     GetWindowOrgEx(hdc, &win_org);
304     GetViewportOrgEx(hdc, &vp_org);
305     GetWindowExtEx(hdc, &win_size);
306     GetViewportExtEx(hdc, &vp_size);
307 
308     ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
309     ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
310 
311     ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
312     ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
313 
314     ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
315     ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
316 
317     ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
318     ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
319 }
320 
321 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
322                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
323 {
324     BOOL ret;
325     XFORM xform;
326     POINT pt;
327     SIZE size;
328     static int save_state;
329     static int restore_no;
330 
331     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
332            hdc, emr->iType, emr->nSize, (void *)param);
333 
334     trace("BEFORE:\n");
335     SetLastError(0xdeadbeef);
336     ret = GetWorldTransform(hdc, &xform);
337     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
338     {
339         ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
340         trace("window org (%d,%d)\n", pt.x, pt.y);
341         ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
342         trace("vport org (%d,%d)\n", pt.x, pt.y);
343         ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
344         trace("window ext (%d,%d)\n", size.cx, size.cy);
345         ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
346         trace("vport ext (%d,%d)\n", size.cx, size.cy);
347     }
348     else
349     {
350         ok(ret, "GetWorldTransform error %u\n", GetLastError());
351         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
352     }
353 
354     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
355 
356     switch (emr->iType)
357     {
358     case EMR_HEADER:
359     {
360         static RECT exp_bounds = { 0, 0, 150, 150 };
361         RECT bounds;
362         const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
363 
364         trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
365                emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
366                emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
367         trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
368                emf->szlDevice.cx, emf->szlDevice.cy);
369 
370         SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
371         ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
372 
373         save_state = 0;
374         restore_no = 0;
375         check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
376         break;
377     }
378 
379     case EMR_LINETO:
380         {
381             const EMRLINETO *line = (const EMRLINETO *)emr;
382             trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
383             break;
384         }
385     case EMR_SETWINDOWORGEX:
386         {
387             const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
388             trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
389             break;
390         }
391     case EMR_SETWINDOWEXTEX:
392         {
393             const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
394             trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
395             break;
396         }
397     case EMR_SETVIEWPORTORGEX:
398         {
399             const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
400             trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
401             break;
402         }
403     case EMR_SETVIEWPORTEXTEX:
404         {
405             const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
406             trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
407             break;
408         }
409     case EMR_SAVEDC:
410         save_state++;
411         trace("EMR_SAVEDC\n");
412         break;
413 
414     case EMR_RESTOREDC:
415         {
416             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
417             trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
418 
419             switch(++restore_no)
420             {
421             case 1:
422                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
423                 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
424                 break;
425             case 2:
426                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
427                 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
428                 break;
429             case 3:
430                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
431                 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
432                 break;
433             }
434             ok(restore_no <= 3, "restore_no %d\n", restore_no);
435             save_state += restoredc->iRelative;
436             break;
437         }
438     case EMR_EOF:
439         ok(save_state == 0, "EOF save_state %d\n", save_state);
440         break;
441     }
442 
443     trace("AFTER:\n");
444     SetLastError(0xdeadbeef);
445     ret = GetWorldTransform(hdc, &xform);
446     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
447     {
448         ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
449         trace("window org (%d,%d)\n", pt.x, pt.y);
450         ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
451         trace("vport org (%d,%d)\n", pt.x, pt.y);
452         ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
453         trace("window ext (%d,%d)\n", size.cx, size.cy);
454         ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
455         trace("vport ext (%d,%d)\n", size.cx, size.cy);
456     }
457     else
458     {
459         ok(ret, "GetWorldTransform error %u\n", GetLastError());
460         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
461     }
462 
463     return 1;
464 }
465 
466 static void test_SaveDC(void)
467 {
468     HDC hdcMetafile, hdcDisplay;
469     HENHMETAFILE hMetafile;
470     HWND hwnd;
471     int ret;
472     static const RECT rc = { 0, 0, 150, 150 };
473 
474     /* Win9x doesn't play EMFs on invisible windows */
475     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
476                            0, 0, 200, 200, 0, 0, 0, NULL);
477     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
478 
479     hdcDisplay = GetDC(hwnd);
480     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
481 
482     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
483     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
484 
485     SetMapMode(hdcMetafile, MM_ANISOTROPIC);
486 
487     /* Need to write something to the emf, otherwise Windows won't play it back */
488     LineTo(hdcMetafile, 150, 150);
489 
490     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
491     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
492     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
493     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
494 
495     /* Force Win9x to update DC state */
496     SetPixelV(hdcMetafile, 50, 50, 0);
497 
498     ret = SaveDC(hdcMetafile);
499     ok(ret == 1, "ret = %d\n", ret);
500 
501     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
502     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
503     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
504     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
505 
506     /* Force Win9x to update DC state */
507     SetPixelV(hdcMetafile, 50, 50, 0);
508 
509     ret = SaveDC(hdcMetafile);
510     ok(ret == 2, "ret = %d\n", ret);
511 
512     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
513     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
514     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
515     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
516 
517     /* Force Win9x to update DC state */
518     SetPixelV(hdcMetafile, 50, 50, 0);
519 
520     ret = SaveDC(hdcMetafile);
521     ok(ret == 3, "ret = %d\n", ret);
522 
523     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
524     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
525     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
526     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
527 
528     /* Force Win9x to update DC state */
529     SetPixelV(hdcMetafile, 50, 50, 0);
530 
531     ret = RestoreDC(hdcMetafile, -1);
532     ok(ret, "ret = %d\n", ret);
533 
534     ret = SaveDC(hdcMetafile);
535     ok(ret == 3, "ret = %d\n", ret);
536 
537     ret = RestoreDC(hdcMetafile, 1);
538     ok(ret, "ret = %d\n", ret);
539 
540     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
541     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
542     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
543     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
544 
545     /* Force Win9x to update DC state */
546     SetPixelV(hdcMetafile, 50, 50, 0);
547 
548     ret = SaveDC(hdcMetafile);
549     ok(ret == 1, "ret = %d\n", ret);
550 
551     ret = SaveDC(hdcMetafile);
552     ok(ret == 2, "ret = %d\n", ret);
553 
554     hMetafile = CloseEnhMetaFile(hdcMetafile);
555     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
556 
557     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
558     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
559 
560     ret = DeleteEnhMetaFile(hMetafile);
561     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
562     ret = ReleaseDC(hwnd, hdcDisplay);
563     ok( ret, "ReleaseDC error %d\n", GetLastError());
564     DestroyWindow(hwnd);
565 }
566 
567 /* Win-format metafile (mfdrv) tests */
568 /* These tests compare the generated metafiles byte-by-byte */
569 /* with the nominal results. */
570 
571 /* Maximum size of sample metafiles in bytes. */
572 #define MF_BUFSIZE 512
573 
574 /* 8x8 bitmap data for a pattern brush */
575 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
576     0x01, 0x00, 0x02, 0x00,
577     0x03, 0x00, 0x04, 0x00,
578     0x05, 0x00, 0x06, 0x00,
579     0x07, 0x00, 0x08, 0x00
580 };
581 
582 /* Sample metafiles to be compared to the outputs of the
583  * test functions.
584  */
585 
586 static const unsigned char MF_BLANK_BITS[] = {
587     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
588     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
589     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
590 };
591 
592 static const unsigned char MF_GRAPHICS_BITS[] = {
593     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
594     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
595     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
596     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
597     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
598     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
599     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
600     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
601     0x00, 0x00, 0x00, 0x00
602 };
603 
604 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
605     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
606     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
607     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
608     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
609     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
610     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
611     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
615     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
616     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
617     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
618     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
619     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
620     0x00, 0x00
621 };
622 
623 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
624 {
625     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
626     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
627     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
628     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
629     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
630     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
631     0x00, 0x00
632 };
633 
634 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
635 {
636     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
637     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
639     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
641     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
642     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
643     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
646     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
647     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
649     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
650     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
651     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
653     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
654     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
655     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
656     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
657     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
659     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
660     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
661     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
662     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
663     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
664     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
665     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
666     0x14, 0x00, 0x00, 0x00
667 };
668 
669 static const unsigned char MF_LINETO_BITS[] = {
670     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
671     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
672     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
673     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
674     0x00, 0x00
675 };
676 
677 static const unsigned char EMF_LINETO_BITS[] = {
678     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
679     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
681     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
683     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
684     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
685     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
688     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
689     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
691     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
692     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
693     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
694     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
695     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
696     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
697     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
698     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
699     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
700     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
701     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
702     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
703     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
704     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
705     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
706     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
707     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
708     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
709     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
710     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
711     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
712     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
713     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
715     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
717 };
718 
719 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
720     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
721     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
723     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
725     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
726     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
727     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
730     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
731     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
733     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
734     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
735     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
736     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
737     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
738     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
739     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
740     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
741     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
742     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
743     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
744     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
745     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
746     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
747     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
748     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
749     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
750     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
751     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
752     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
753     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
754     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
755     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
757     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
759 };
760 
761 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
762     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
763     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
765     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
767     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
768     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
769     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
772     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
773     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
775     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
776     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
777     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
778     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
779     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
780     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
781     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
782     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
783     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
784     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
785     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
786     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
787     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
788     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
789     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
790     0x14, 0x00, 0x00, 0x00
791 };
792 
793 /* For debugging or dumping the raw metafiles produced by
794  * new test functions.
795  */
796 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
797                                  INT nobj, LPARAM param)
798 {
799     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
800            hdc, mr->rdFunction, mr->rdSize, (void *)param);
801     return TRUE;
802 }
803 
804 /* For debugging or dumping the raw metafiles produced by
805  * new test functions.
806  */
807 
808 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
809 {
810     BYTE buf[MF_BUFSIZE];
811     UINT mfsize, i;
812 
813     if (!winetest_debug) return;
814 
815     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
816     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
817 
818     printf ("MetaFile %s has bits:\n{\n    ", desc);
819     for (i=0; i<mfsize; i++)
820     {
821         printf ("0x%02x", buf[i]);
822         if (i == mfsize-1)
823             printf ("\n");
824         else if (i % 8 == 7)
825             printf (",\n    ");
826         else
827             printf (", ");
828     }
829     printf ("};\n");
830 }
831 
832 /* Compare the metafile produced by a test function with the
833  * expected raw metafile data in "bits".
834  * Return value is 0 for a perfect match,
835  * -1 if lengths aren't equal,
836  * otherwise returns the number of non-matching bytes.
837  */
838 
839 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
840     const char *desc)
841 {
842     unsigned char buf[MF_BUFSIZE];
843     UINT mfsize, i;
844     int diff;
845 
846     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
847     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
848     if (mfsize < MF_BUFSIZE)
849         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
850             desc, mfsize, bsize);
851     else
852         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
853             desc, mfsize, bsize);
854     if (mfsize != bsize)
855         return -1;
856 
857     diff = 0;
858     for (i=0; i<bsize; i++)
859     {