Added Korean resources.
[wine] / objects / enhmetafile.c
1 /*
2  * Enhanced metafile functions
3  * Copyright 1998 Douglas Ridgway
4  *           1999 Huw D M Davies
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * NOTES:
21  *
22  * The enhanced format consists of the following elements:
23  *
24  *    A header
25  *    A table of handles to GDI objects
26  *    An array of metafile records
27  *    A private palette
28  *
29  *
30  *  The standard format consists of a header and an array of metafile records.
31  *
32  */
33
34 #include "config.h"
35 #include "wine/port.h"
36
37 #include <string.h>
38 #include <assert.h>
39 #include "winnls.h"
40 #include "winbase.h"
41 #include "wingdi.h"
42 #include "winerror.h"
43 #include "gdi.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile);
47
48 typedef struct
49 {
50     GDIOBJHDR      header;
51     ENHMETAHEADER  *emh;
52     BOOL           on_disk;   /* true if metafile is on disk */
53 } ENHMETAFILEOBJ;
54
55
56 /****************************************************************************
57  *          EMF_Create_HENHMETAFILE
58  */
59 HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk )
60 {
61     HENHMETAFILE hmf = 0;
62     ENHMETAFILEOBJ *metaObj = GDI_AllocObject( sizeof(ENHMETAFILEOBJ),
63                                                ENHMETAFILE_MAGIC, &hmf, NULL );
64     if (metaObj)
65     {
66         metaObj->emh = emh;
67         metaObj->on_disk = on_disk;
68         GDI_ReleaseObj( hmf );
69     }
70     return hmf;
71 }
72
73 /****************************************************************************
74  *          EMF_Delete_HENHMETAFILE
75  */
76 static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf )
77 {
78     ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf,
79                                                            ENHMETAFILE_MAGIC );
80     if(!metaObj) return FALSE;
81
82     if(metaObj->on_disk)
83         UnmapViewOfFile( metaObj->emh );
84     else
85         HeapFree( GetProcessHeap(), 0, metaObj->emh );
86     return GDI_FreeObject( hmf, metaObj );
87 }
88
89 /******************************************************************
90  *         EMF_GetEnhMetaHeader
91  *
92  * Returns ptr to ENHMETAHEADER associated with HENHMETAFILE
93  */
94 static ENHMETAHEADER *EMF_GetEnhMetaHeader( HENHMETAFILE hmf )
95 {
96     ENHMETAHEADER *ret = NULL;
97     ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf, ENHMETAFILE_MAGIC );
98     TRACE("hmf %04x -> enhmetaObj %p\n", hmf, metaObj);
99     if (metaObj)
100     {
101         ret = metaObj->emh;
102         GDI_ReleaseObj( hmf );
103     }
104     return ret;
105 }
106
107 /*****************************************************************************
108  *         EMF_GetEnhMetaFile
109  *
110  */
111 static HENHMETAFILE EMF_GetEnhMetaFile( HANDLE hFile )
112 {
113     ENHMETAHEADER *emh;
114     HANDLE hMapping;
115
116     hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
117     emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
118     CloseHandle( hMapping );
119
120     if (!emh) return 0;
121
122     if (emh->iType != EMR_HEADER || emh->dSignature != ENHMETA_SIGNATURE) {
123         WARN("Invalid emf header type 0x%08lx sig 0x%08lx.\n",
124              emh->iType, emh->dSignature);
125         UnmapViewOfFile( emh );
126         return 0;
127     }
128     return EMF_Create_HENHMETAFILE( emh, TRUE );
129 }
130
131
132 /*****************************************************************************
133  *          GetEnhMetaFileA (GDI32.@)
134  *
135  *
136  */
137 HENHMETAFILE WINAPI GetEnhMetaFileA(
138              LPCSTR lpszMetaFile  /* [in] filename of enhanced metafile */
139     )
140 {
141     HENHMETAFILE hmf;
142     HANDLE hFile;
143
144     hFile = CreateFileA(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0,
145                         OPEN_EXISTING, 0, 0);
146     if (hFile == INVALID_HANDLE_VALUE) {
147         WARN("could not open %s\n", lpszMetaFile);
148         return 0;
149     }
150     hmf = EMF_GetEnhMetaFile( hFile );
151     CloseHandle( hFile );
152     return hmf;
153 }
154
155 /*****************************************************************************
156  *          GetEnhMetaFileW  (GDI32.@)
157  */
158 HENHMETAFILE WINAPI GetEnhMetaFileW(
159              LPCWSTR lpszMetaFile)  /* [in] filename of enhanced metafile */
160 {
161     HENHMETAFILE hmf;
162     HANDLE hFile;
163
164     hFile = CreateFileW(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0,
165                         OPEN_EXISTING, 0, 0);
166     if (hFile == INVALID_HANDLE_VALUE) {
167         WARN("could not open %s\n", debugstr_w(lpszMetaFile));
168         return 0;
169     }
170     hmf = EMF_GetEnhMetaFile( hFile );
171     CloseHandle( hFile );
172     return hmf;
173 }
174
175 /*****************************************************************************
176  *        GetEnhMetaFileHeader  (GDI32.@)
177  *
178  *  If buf is NULL, returns the size of buffer required.
179  *  Otherwise, copy up to bufsize bytes of enhanced metafile header into
180  *  buf.
181  */
182 UINT WINAPI GetEnhMetaFileHeader(
183        HENHMETAFILE hmf,   /* [in] enhanced metafile */
184        UINT bufsize,       /* [in] size of buffer */
185        LPENHMETAHEADER buf /* [out] buffer */
186     )
187 {
188     LPENHMETAHEADER emh;
189     UINT size;
190
191     emh = EMF_GetEnhMetaHeader(hmf);
192     if(!emh) return FALSE;
193     size = emh->nSize;
194     if (!buf) return size;
195     size = min(size, bufsize);
196     memmove(buf, emh, size);
197     return size;
198 }
199
200
201 /*****************************************************************************
202  *          GetEnhMetaFileDescriptionA  (GDI32.@)
203  */
204 UINT WINAPI GetEnhMetaFileDescriptionA(
205        HENHMETAFILE hmf, /* [in] enhanced metafile */
206        UINT size,        /* [in] size of buf */
207        LPSTR buf         /* [out] buffer to receive description */
208     )
209 {
210      LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
211      DWORD len;
212      WCHAR *descrW;
213
214      if(!emh) return FALSE;
215      if(emh->nDescription == 0 || emh->offDescription == 0) return 0;
216      descrW = (WCHAR *) ((char *) emh + emh->offDescription);
217      len = WideCharToMultiByte( CP_ACP, 0, descrW, emh->nDescription, NULL, 0, NULL, NULL );
218
219      if (!buf || !size ) return len;
220
221      len = min( size, len );
222      WideCharToMultiByte( CP_ACP, 0, descrW, emh->nDescription, buf, len, NULL, NULL );
223      return len;
224 }
225
226 /*****************************************************************************
227  *          GetEnhMetaFileDescriptionW  (GDI32.@)
228  *
229  *  Copies the description string of an enhanced metafile into a buffer
230  *  _buf_.
231  *
232  *  If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
233  *  number of characters copied.
234  */
235 UINT WINAPI GetEnhMetaFileDescriptionW(
236        HENHMETAFILE hmf, /* [in] enhanced metafile */
237        UINT size,        /* [in] size of buf */
238        LPWSTR buf        /* [out] buffer to receive description */
239     )
240 {
241      LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
242
243      if(!emh) return FALSE;
244      if(emh->nDescription == 0 || emh->offDescription == 0) return 0;
245      if (!buf || !size ) return emh->nDescription;
246
247      memmove(buf, (char *) emh + emh->offDescription, min(size,emh->nDescription)*sizeof(WCHAR));
248      return min(size, emh->nDescription);
249 }
250
251 /****************************************************************************
252  *    SetEnhMetaFileBits (GDI32.@)
253  *
254  *  Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
255  */
256 HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf)
257 {
258     ENHMETAHEADER *emh = HeapAlloc( GetProcessHeap(), 0, bufsize );
259     memmove(emh, buf, bufsize);
260     return EMF_Create_HENHMETAFILE( emh, FALSE );
261 }
262
263 /*****************************************************************************
264  *  GetEnhMetaFileBits (GDI32.@)
265  *
266  */
267 UINT WINAPI GetEnhMetaFileBits(
268     HENHMETAFILE hmf,
269     UINT bufsize,
270     LPBYTE buf
271 )
272 {
273     LPENHMETAHEADER emh = EMF_GetEnhMetaHeader( hmf );
274     UINT size;
275
276     if(!emh) return 0;
277
278     size = emh->nBytes;
279     if( buf == NULL ) return size;
280
281     size = min( size, bufsize );
282     memmove(buf, emh, size);
283     return size;
284 }
285
286 /*****************************************************************************
287  *           PlayEnhMetaFileRecord  (GDI32.@)
288  *
289  *  Render a single enhanced metafile record in the device context hdc.
290  *
291  *  RETURNS
292  *    TRUE (non zero) on success, FALSE on error.
293  *  BUGS
294  *    Many unimplemented records.
295  *    No error handling on record play failures (ie checking return codes)
296  */
297 BOOL WINAPI PlayEnhMetaFileRecord(
298      HDC hdc,                   /* [in] device context in which to render EMF record */
299      LPHANDLETABLE handletable, /* [in] array of handles to be used in rendering record */
300      const ENHMETARECORD *mr,   /* [in] EMF record to render */
301      UINT handles               /* [in] size of handle array */
302      )
303 {
304   int type;
305   TRACE(
306         "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
307           hdc, handletable, mr, handles);
308   if (!mr) return FALSE;
309
310   type = mr->iType;
311
312   TRACE(" type=%d\n", type);
313   switch(type)
314     {
315     case EMR_HEADER:
316       break;
317     case EMR_EOF:
318       break;
319     case EMR_GDICOMMENT:
320       {
321         PEMRGDICOMMENT lpGdiComment = (PEMRGDICOMMENT)mr;
322         /* In an enhanced metafile, there can be both public and private GDI comments */
323         GdiComment( hdc, lpGdiComment->cbData, lpGdiComment->Data );
324         break;
325       }
326     case EMR_SETMAPMODE:
327       {
328         PEMRSETMAPMODE pSetMapMode = (PEMRSETMAPMODE) mr;
329         SetMapMode(hdc, pSetMapMode->iMode);
330         break;
331       }
332     case EMR_SETBKMODE:
333       {
334         PEMRSETBKMODE pSetBkMode = (PEMRSETBKMODE) mr;
335         SetBkMode(hdc, pSetBkMode->iMode);
336         break;
337       }
338     case EMR_SETBKCOLOR:
339       {
340         PEMRSETBKCOLOR pSetBkColor = (PEMRSETBKCOLOR) mr;
341         SetBkColor(hdc, pSetBkColor->crColor);
342         break;
343       }
344     case EMR_SETPOLYFILLMODE:
345       {
346         PEMRSETPOLYFILLMODE pSetPolyFillMode = (PEMRSETPOLYFILLMODE) mr;
347         SetPolyFillMode(hdc, pSetPolyFillMode->iMode);
348         break;
349       }
350     case EMR_SETROP2:
351       {
352         PEMRSETROP2 pSetROP2 = (PEMRSETROP2) mr;
353         SetROP2(hdc, pSetROP2->iMode);
354         break;
355       }
356     case EMR_SETSTRETCHBLTMODE:
357       {
358         PEMRSETSTRETCHBLTMODE pSetStretchBltMode = (PEMRSETSTRETCHBLTMODE) mr;
359         SetStretchBltMode(hdc, pSetStretchBltMode->iMode);
360         break;
361       }
362     case EMR_SETTEXTALIGN:
363       {
364         PEMRSETTEXTALIGN pSetTextAlign = (PEMRSETTEXTALIGN) mr;
365         SetTextAlign(hdc, pSetTextAlign->iMode);
366         break;
367       }
368     case EMR_SETTEXTCOLOR:
369       {
370         PEMRSETTEXTCOLOR pSetTextColor = (PEMRSETTEXTCOLOR) mr;
371         SetTextColor(hdc, pSetTextColor->crColor);
372         break;
373       }
374     case EMR_SAVEDC:
375       {
376         SaveDC(hdc);
377         break;
378       }
379     case EMR_RESTOREDC:
380       {
381         PEMRRESTOREDC pRestoreDC = (PEMRRESTOREDC) mr;
382         RestoreDC(hdc, pRestoreDC->iRelative);
383         break;
384       }
385     case EMR_INTERSECTCLIPRECT:
386       {
387         PEMRINTERSECTCLIPRECT pClipRect = (PEMRINTERSECTCLIPRECT) mr;
388         IntersectClipRect(hdc, pClipRect->rclClip.left, pClipRect->rclClip.top,
389                           pClipRect->rclClip.right, pClipRect->rclClip.bottom);
390         break;
391       }
392     case EMR_SELECTOBJECT:
393       {
394         PEMRSELECTOBJECT pSelectObject = (PEMRSELECTOBJECT) mr;
395         if( pSelectObject->ihObject & 0x80000000 ) {
396           /* High order bit is set - it's a stock object
397            * Strip the high bit to get the index.
398            * See MSDN article Q142319
399            */
400           SelectObject( hdc, GetStockObject( pSelectObject->ihObject &
401                                              0x7fffffff ) );
402         } else {
403           /* High order bit wasn't set - not a stock object
404            */
405               SelectObject( hdc,
406                         (handletable->objectHandle)[pSelectObject->ihObject] );
407         }
408         break;
409       }
410     case EMR_DELETEOBJECT:
411       {
412         PEMRDELETEOBJECT pDeleteObject = (PEMRDELETEOBJECT) mr;
413         DeleteObject( (handletable->objectHandle)[pDeleteObject->ihObject]);
414         (handletable->objectHandle)[pDeleteObject->ihObject] = 0;
415         break;
416       }
417     case EMR_SETWINDOWORGEX:
418       {
419           /*
420            * FIXME: The call to SetWindowOrgEx prevents EMFs from being scrolled
421            *        by an application. This is very BAD!!!
422            */
423 #if 0
424         PEMRSETWINDOWORGEX pSetWindowOrgEx = (PEMRSETWINDOWORGEX) mr;
425         SetWindowOrgEx(hdc, pSetWindowOrgEx->ptlOrigin.x,
426                        pSetWindowOrgEx->ptlOrigin.y, NULL);
427 #endif
428         break;
429       }
430     case EMR_SETWINDOWEXTEX:
431       {
432         PEMRSETWINDOWEXTEX pSetWindowExtEx = (PEMRSETWINDOWEXTEX) mr;
433         SetWindowExtEx(hdc, pSetWindowExtEx->szlExtent.cx,
434                        pSetWindowExtEx->szlExtent.cy, NULL);
435         break;
436       }
437     case EMR_SETVIEWPORTORGEX:
438       {
439         PEMRSETVIEWPORTORGEX pSetViewportOrgEx = (PEMRSETVIEWPORTORGEX) mr;
440         SetViewportOrgEx(hdc, pSetViewportOrgEx->ptlOrigin.x,
441                          pSetViewportOrgEx->ptlOrigin.y, NULL);
442         break;
443       }
444     case EMR_SETVIEWPORTEXTEX:
445       {
446         PEMRSETVIEWPORTEXTEX pSetViewportExtEx = (PEMRSETVIEWPORTEXTEX) mr;
447         SetViewportExtEx(hdc, pSetViewportExtEx->szlExtent.cx,
448                          pSetViewportExtEx->szlExtent.cy, NULL);
449         break;
450       }
451     case EMR_CREATEPEN:
452       {
453         PEMRCREATEPEN pCreatePen = (PEMRCREATEPEN) mr;
454         (handletable->objectHandle)[pCreatePen->ihPen] =
455           CreatePenIndirect(&pCreatePen->lopn);
456         break;
457       }
458     case EMR_EXTCREATEPEN:
459       {
460         PEMREXTCREATEPEN pPen = (PEMREXTCREATEPEN) mr;
461         LOGBRUSH lb;
462         lb.lbStyle = pPen->elp.elpBrushStyle;
463         lb.lbColor = pPen->elp.elpColor;
464         lb.lbHatch = pPen->elp.elpHatch;
465
466         if(pPen->offBmi || pPen->offBits)
467           FIXME("EMR_EXTCREATEPEN: Need to copy brush bitmap\n");
468
469         (handletable->objectHandle)[pPen->ihPen] =
470           ExtCreatePen(pPen->elp.elpPenStyle, pPen->elp.elpWidth, &lb,
471                        pPen->elp.elpNumEntries, pPen->elp.elpStyleEntry);
472         break;
473       }
474     case EMR_CREATEBRUSHINDIRECT:
475       {
476         PEMRCREATEBRUSHINDIRECT pBrush = (PEMRCREATEBRUSHINDIRECT) mr;
477         (handletable->objectHandle)[pBrush->ihBrush] =
478           CreateBrushIndirect(&pBrush->lb);
479         break;
480       }
481     case EMR_EXTCREATEFONTINDIRECTW:
482       {
483         PEMREXTCREATEFONTINDIRECTW pFont = (PEMREXTCREATEFONTINDIRECTW) mr;
484         (handletable->objectHandle)[pFont->ihFont] =
485           CreateFontIndirectW(&pFont->elfw.elfLogFont);
486         break;
487       }
488     case EMR_MOVETOEX:
489       {
490         PEMRMOVETOEX pMoveToEx = (PEMRMOVETOEX) mr;
491         MoveToEx(hdc, pMoveToEx->ptl.x, pMoveToEx->ptl.y, NULL);
492         break;
493       }
494     case EMR_LINETO:
495       {
496         PEMRLINETO pLineTo = (PEMRLINETO) mr;
497         LineTo(hdc, pLineTo->ptl.x, pLineTo->ptl.y);
498         break;
499       }
500     case EMR_RECTANGLE:
501       {
502         PEMRRECTANGLE pRect = (PEMRRECTANGLE) mr;
503         Rectangle(hdc, pRect->rclBox.left, pRect->rclBox.top,
504                   pRect->rclBox.right, pRect->rclBox.bottom);
505         break;
506       }
507     case EMR_ELLIPSE:
508       {
509         PEMRELLIPSE pEllipse = (PEMRELLIPSE) mr;
510         Ellipse(hdc, pEllipse->rclBox.left, pEllipse->rclBox.top,
511                 pEllipse->rclBox.right, pEllipse->rclBox.bottom);
512         break;
513       }
514     case EMR_POLYGON16:
515       {
516         PEMRPOLYGON16 pPoly = (PEMRPOLYGON16) mr;
517         /* Shouldn't use Polygon16 since pPoly->cpts is DWORD */
518         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
519                                 pPoly->cpts * sizeof(POINT) );
520         DWORD i;
521         for(i = 0; i < pPoly->cpts; i++)
522           CONV_POINT16TO32(pPoly->apts + i, pts + i);
523         Polygon(hdc, pts, pPoly->cpts);
524         HeapFree( GetProcessHeap(), 0, pts );
525         break;
526       }
527     case EMR_POLYLINE16:
528       {
529         PEMRPOLYLINE16 pPoly = (PEMRPOLYLINE16) mr;
530         /* Shouldn't use Polyline16 since pPoly->cpts is DWORD */
531         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
532                                 pPoly->cpts * sizeof(POINT) );
533         DWORD i;
534         for(i = 0; i < pPoly->cpts; i++)
535           CONV_POINT16TO32(pPoly->apts + i, pts + i);
536         Polyline(hdc, pts, pPoly->cpts);
537         HeapFree( GetProcessHeap(), 0, pts );
538         break;
539       }
540     case EMR_POLYLINETO16:
541       {
542         PEMRPOLYLINETO16 pPoly = (PEMRPOLYLINETO16) mr;
543         /* Shouldn't use PolylineTo16 since pPoly->cpts is DWORD */
544         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
545                                 pPoly->cpts * sizeof(POINT) );
546         DWORD i;
547         for(i = 0; i < pPoly->cpts; i++)
548           CONV_POINT16TO32(pPoly->apts + i, pts + i);
549         PolylineTo(hdc, pts, pPoly->cpts);
550         HeapFree( GetProcessHeap(), 0, pts );
551         break;
552       }
553     case EMR_POLYBEZIER16:
554       {
555         PEMRPOLYBEZIER16 pPoly = (PEMRPOLYBEZIER16) mr;
556         /* Shouldn't use PolyBezier16 since pPoly->cpts is DWORD */
557         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
558                                 pPoly->cpts * sizeof(POINT) );
559         DWORD i;
560         for(i = 0; i < pPoly->cpts; i++)
561           CONV_POINT16TO32(pPoly->apts + i, pts + i);
562         PolyBezier(hdc, pts, pPoly->cpts);
563         HeapFree( GetProcessHeap(), 0, pts );
564         break;
565       }
566     case EMR_POLYBEZIERTO16:
567       {
568         PEMRPOLYBEZIERTO16 pPoly = (PEMRPOLYBEZIERTO16) mr;
569         /* Shouldn't use PolyBezierTo16 since pPoly->cpts is DWORD */
570         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
571                                 pPoly->cpts * sizeof(POINT) );
572         DWORD i;
573         for(i = 0; i < pPoly->cpts; i++)
574           CONV_POINT16TO32(pPoly->apts + i, pts + i);
575         PolyBezierTo(hdc, pts, pPoly->cpts);
576         HeapFree( GetProcessHeap(), 0, pts );
577         break;
578       }
579     case EMR_POLYPOLYGON16:
580       {
581         PEMRPOLYPOLYGON16 pPolyPoly = (PEMRPOLYPOLYGON16) mr;
582         /* NB POINTS array doesn't start at pPolyPoly->apts it's actually
583            pPolyPoly->aPolyCounts + pPolyPoly->nPolys */
584
585         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
586                                 pPolyPoly->cpts * sizeof(POINT) );
587         DWORD i;
588         for(i = 0; i < pPolyPoly->cpts; i++)
589           CONV_POINT16TO32((POINT16*) (pPolyPoly->aPolyCounts +
590                                       pPolyPoly->nPolys) + i, pts + i);
591
592         PolyPolygon(hdc, pts, (INT*)pPolyPoly->aPolyCounts, pPolyPoly->nPolys);
593         HeapFree( GetProcessHeap(), 0, pts );
594         break;
595       }
596     case EMR_POLYPOLYLINE16:
597       {
598         PEMRPOLYPOLYLINE16 pPolyPoly = (PEMRPOLYPOLYLINE16) mr;
599         /* NB POINTS array doesn't start at pPolyPoly->apts it's actually
600            pPolyPoly->aPolyCounts + pPolyPoly->nPolys */
601
602         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
603                                 pPolyPoly->cpts * sizeof(POINT) );
604         DWORD i;
605         for(i = 0; i < pPolyPoly->cpts; i++)
606           CONV_POINT16TO32((POINT16*) (pPolyPoly->aPolyCounts +
607                                       pPolyPoly->nPolys) + i, pts + i);
608
609         PolyPolyline(hdc, pts, pPolyPoly->aPolyCounts, pPolyPoly->nPolys);
610         HeapFree( GetProcessHeap(), 0, pts );
611         break;
612       }
613
614     case EMR_STRETCHDIBITS:
615       {
616         EMRSTRETCHDIBITS *pStretchDIBits = (EMRSTRETCHDIBITS *)mr;
617
618         StretchDIBits(hdc,
619                       pStretchDIBits->xDest,
620                       pStretchDIBits->yDest,
621                       pStretchDIBits->cxDest,
622                       pStretchDIBits->cyDest,
623                       pStretchDIBits->xSrc,
624                       pStretchDIBits->ySrc,
625                       pStretchDIBits->cxSrc,
626                       pStretchDIBits->cySrc,
627                       (BYTE *)mr + pStretchDIBits->offBitsSrc,
628                       (const BITMAPINFO *)((BYTE *)mr + pStretchDIBits->offBmiSrc),
629                       pStretchDIBits->iUsageSrc,
630                       pStretchDIBits->dwRop);
631         break;
632       }
633
634     case EMR_EXTTEXTOUTA:
635     {
636         PEMREXTTEXTOUTA pExtTextOutA = (PEMREXTTEXTOUTA)mr;
637         RECT rc;
638
639         rc.left = pExtTextOutA->emrtext.rcl.left;
640         rc.top = pExtTextOutA->emrtext.rcl.top;
641         rc.right = pExtTextOutA->emrtext.rcl.right;
642         rc.bottom = pExtTextOutA->emrtext.rcl.bottom;
643         ExtTextOutA(hdc, pExtTextOutA->emrtext.ptlReference.x, pExtTextOutA->emrtext.ptlReference.y,
644             pExtTextOutA->emrtext.fOptions, &rc,
645             (LPSTR)((BYTE *)mr + pExtTextOutA->emrtext.offString), pExtTextOutA->emrtext.nChars,
646             (INT *)((BYTE *)mr + pExtTextOutA->emrtext.offDx));
647         break;
648     }
649
650     case EMR_EXTTEXTOUTW:
651     {
652         PEMREXTTEXTOUTW pExtTextOutW = (PEMREXTTEXTOUTW)mr;
653         RECT rc;
654
655         rc.left = pExtTextOutW->emrtext.rcl.left;
656         rc.top = pExtTextOutW->emrtext.rcl.top;
657         rc.right = pExtTextOutW->emrtext.rcl.right;
658         rc.bottom = pExtTextOutW->emrtext.rcl.bottom;
659         ExtTextOutW(hdc, pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y,
660             pExtTextOutW->emrtext.fOptions, &rc,
661             (LPWSTR)((BYTE *)mr + pExtTextOutW->emrtext.offString), pExtTextOutW->emrtext.nChars,
662             (INT *)((BYTE *)mr + pExtTextOutW->emrtext.offDx));
663         break;
664     }
665
666     case EMR_CREATEPALETTE:
667       {
668         PEMRCREATEPALETTE lpCreatePal = (PEMRCREATEPALETTE)mr;
669
670         (handletable->objectHandle)[ lpCreatePal->ihPal ] =
671                 CreatePalette( &lpCreatePal->lgpl );
672
673         break;
674       }
675
676     case EMR_SELECTPALETTE:
677       {
678         PEMRSELECTPALETTE lpSelectPal = (PEMRSELECTPALETTE)mr;
679
680         if( lpSelectPal->ihPal & 0x80000000 ) {
681                 SelectPalette( hdc, GetStockObject(lpSelectPal->ihPal & 0x7fffffff), TRUE);
682         } else {
683         (handletable->objectHandle)[ lpSelectPal->ihPal ] =
684                 SelectPalette( hdc, (handletable->objectHandle)[lpSelectPal->ihPal], TRUE);
685         }
686         break;
687       }
688
689     case EMR_REALIZEPALETTE:
690       {
691         RealizePalette( hdc );
692         break;
693       }
694
695     case EMR_EXTSELECTCLIPRGN:
696       {
697         PEMREXTSELECTCLIPRGN lpRgn = (PEMREXTSELECTCLIPRGN)mr;
698         HRGN hRgn = ExtCreateRegion(NULL, lpRgn->cbRgnData, (RGNDATA *)lpRgn->RgnData);
699         ExtSelectClipRgn(hdc, hRgn, (INT)(lpRgn->iMode));
700         /* ExtSelectClipRgn created a copy of the region */
701         DeleteObject(hRgn);
702         break;
703       }
704
705     case EMR_SETMETARGN:
706       {
707         SetMetaRgn( hdc );
708         break;
709       }
710
711     case EMR_SETWORLDTRANSFORM:
712       {
713         PEMRSETWORLDTRANSFORM lpXfrm = (PEMRSETWORLDTRANSFORM)mr;
714         SetWorldTransform( hdc, &lpXfrm->xform );
715         break;
716       }
717
718     case EMR_POLYBEZIER:
719       {
720         PEMRPOLYBEZIER lpPolyBez = (PEMRPOLYBEZIER)mr;
721         PolyBezier(hdc, (const LPPOINT)lpPolyBez->aptl, (UINT)lpPolyBez->cptl);
722         break;
723       }
724
725     case EMR_POLYGON:
726       {
727         PEMRPOLYGON lpPoly = (PEMRPOLYGON)mr;
728         Polygon( hdc, (const LPPOINT)lpPoly->aptl, (UINT)lpPoly->cptl );
729         break;
730       }
731
732     case EMR_POLYLINE:
733       {
734         PEMRPOLYLINE lpPolyLine = (PEMRPOLYLINE)mr;
735         Polyline(hdc, (const LPPOINT)lpPolyLine->aptl, (UINT)lpPolyLine->cptl);
736         break;
737       }
738
739     case EMR_POLYBEZIERTO:
740       {
741         PEMRPOLYBEZIERTO lpPolyBezierTo = (PEMRPOLYBEZIERTO)mr;
742         PolyBezierTo( hdc, (const LPPOINT)lpPolyBezierTo->aptl,
743                       (UINT)lpPolyBezierTo->cptl );
744         break;
745       }
746
747     case EMR_POLYLINETO:
748       {
749         PEMRPOLYLINETO lpPolyLineTo = (PEMRPOLYLINETO)mr;
750         PolylineTo( hdc, (const LPPOINT)lpPolyLineTo->aptl,
751                     (UINT)lpPolyLineTo->cptl );
752         break;
753       }
754
755     case EMR_POLYPOLYLINE:
756       {
757         PEMRPOLYPOLYLINE pPolyPolyline = (PEMRPOLYPOLYLINE) mr;
758         /* NB Points at pPolyPolyline->aPolyCounts + pPolyPolyline->nPolys */
759
760         PolyPolyline(hdc, (LPPOINT)(pPolyPolyline->aPolyCounts +
761                                     pPolyPolyline->nPolys),
762                      pPolyPolyline->aPolyCounts,
763                      pPolyPolyline->nPolys );
764
765         break;
766       }
767
768     case EMR_POLYPOLYGON:
769       {
770         PEMRPOLYPOLYGON pPolyPolygon = (PEMRPOLYPOLYGON) mr;
771
772         /* NB Points at pPolyPolygon->aPolyCounts + pPolyPolygon->nPolys */
773
774         PolyPolygon(hdc, (LPPOINT)(pPolyPolygon->aPolyCounts +
775                                    pPolyPolygon->nPolys),
776                     (INT*)pPolyPolygon->aPolyCounts, pPolyPolygon->nPolys );
777         break;
778       }
779
780     case EMR_SETBRUSHORGEX:
781       {
782         PEMRSETBRUSHORGEX lpSetBrushOrgEx = (PEMRSETBRUSHORGEX)mr;
783
784         SetBrushOrgEx( hdc,
785                        (INT)lpSetBrushOrgEx->ptlOrigin.x,
786                        (INT)lpSetBrushOrgEx->ptlOrigin.y,
787                        NULL );
788
789         break;
790       }
791
792     case EMR_SETPIXELV:
793       {
794         PEMRSETPIXELV lpSetPixelV = (PEMRSETPIXELV)mr;
795
796         SetPixelV( hdc,
797                    (INT)lpSetPixelV->ptlPixel.x,
798                    (INT)lpSetPixelV->ptlPixel.y,
799                    lpSetPixelV->crColor );
800
801         break;
802       }
803
804     case EMR_SETMAPPERFLAGS:
805       {
806         PEMRSETMAPPERFLAGS lpSetMapperFlags = (PEMRSETMAPPERFLAGS)mr;
807
808         SetMapperFlags( hdc, lpSetMapperFlags->dwFlags );
809
810         break;
811       }
812
813     case EMR_SETCOLORADJUSTMENT:
814       {
815         PEMRSETCOLORADJUSTMENT lpSetColorAdjust = (PEMRSETCOLORADJUSTMENT)mr;
816
817         SetColorAdjustment( hdc, &lpSetColorAdjust->ColorAdjustment );
818
819         break;
820       }
821
822     case EMR_OFFSETCLIPRGN:
823       {
824         PEMROFFSETCLIPRGN lpOffsetClipRgn = (PEMROFFSETCLIPRGN)mr;
825
826         OffsetClipRgn( hdc,
827                        (INT)lpOffsetClipRgn->ptlOffset.x,
828                        (INT)lpOffsetClipRgn->ptlOffset.y );
829
830         break;
831       }
832
833     case EMR_EXCLUDECLIPRECT:
834       {
835         PEMREXCLUDECLIPRECT lpExcludeClipRect = (PEMREXCLUDECLIPRECT)mr;
836
837         ExcludeClipRect( hdc,
838                          lpExcludeClipRect->rclClip.left,
839                          lpExcludeClipRect->rclClip.top,
840                          lpExcludeClipRect->rclClip.right,
841                          lpExcludeClipRect->rclClip.bottom  );
842
843          break;
844       }
845
846     case EMR_SCALEVIEWPORTEXTEX:
847       {
848         PEMRSCALEVIEWPORTEXTEX lpScaleViewportExtEx = (PEMRSCALEVIEWPORTEXTEX)mr;
849
850         ScaleViewportExtEx( hdc,
851                             lpScaleViewportExtEx->xNum,
852                             lpScaleViewportExtEx->xDenom,
853                             lpScaleViewportExtEx->yNum,
854                             lpScaleViewportExtEx->yDenom,
855                             NULL );
856
857         break;
858       }
859
860     case EMR_SCALEWINDOWEXTEX:
861       {
862         PEMRSCALEWINDOWEXTEX lpScaleWindowExtEx = (PEMRSCALEWINDOWEXTEX)mr;
863
864         ScaleWindowExtEx( hdc,
865                           lpScaleWindowExtEx->xNum,
866                           lpScaleWindowExtEx->xDenom,
867                           lpScaleWindowExtEx->yNum,
868                           lpScaleWindowExtEx->yDenom,
869                           NULL );
870
871         break;
872       }
873
874     case EMR_MODIFYWORLDTRANSFORM:
875       {
876         PEMRMODIFYWORLDTRANSFORM lpModifyWorldTrans = (PEMRMODIFYWORLDTRANSFORM)mr;
877
878         ModifyWorldTransform( hdc, &lpModifyWorldTrans->xform,
879                               lpModifyWorldTrans->iMode );
880
881         break;
882       }
883
884     case EMR_ANGLEARC:
885       {
886         PEMRANGLEARC lpAngleArc = (PEMRANGLEARC)mr;
887
888         AngleArc( hdc,
889                  (INT)lpAngleArc->ptlCenter.x, (INT)lpAngleArc->ptlCenter.y,
890                  lpAngleArc->nRadius, lpAngleArc->eStartAngle,
891                  lpAngleArc->eSweepAngle );
892
893         break;
894       }
895
896     case EMR_ROUNDRECT:
897       {
898         PEMRROUNDRECT lpRoundRect = (PEMRROUNDRECT)mr;
899
900         RoundRect( hdc,
901                    lpRoundRect->rclBox.left,
902                    lpRoundRect->rclBox.top,
903                    lpRoundRect->rclBox.right,
904                    lpRoundRect->rclBox.bottom,
905                    lpRoundRect->szlCorner.cx,
906                    lpRoundRect->szlCorner.cy );
907
908         break;
909       }
910
911     case EMR_ARC:
912       {
913         PEMRARC lpArc = (PEMRARC)mr;
914
915         Arc( hdc,
916              (INT)lpArc->rclBox.left,
917              (INT)lpArc->rclBox.top,
918              (INT)lpArc->rclBox.right,
919              (INT)lpArc->rclBox.bottom,
920              (INT)lpArc->ptlStart.x,
921              (INT)lpArc->ptlStart.y,
922              (INT)lpArc->ptlEnd.x,
923              (INT)lpArc->ptlEnd.y );
924
925         break;
926       }
927
928     case EMR_CHORD:
929       {
930         PEMRCHORD lpChord = (PEMRCHORD)mr;
931
932         Chord( hdc,
933              (INT)lpChord->rclBox.left,
934              (INT)lpChord->rclBox.top,
935              (INT)lpChord->rclBox.right,
936              (INT)lpChord->rclBox.bottom,
937              (INT)lpChord->ptlStart.x,
938              (INT)lpChord->ptlStart.y,
939              (INT)lpChord->ptlEnd.x,
940              (INT)lpChord->ptlEnd.y );
941
942         break;
943       }
944
945     case EMR_PIE:
946       {
947         PEMRPIE lpPie = (PEMRPIE)mr;
948
949         Pie( hdc,
950              (INT)lpPie->rclBox.left,
951              (INT)lpPie->rclBox.top,
952              (INT)lpPie->rclBox.right,
953              (INT)lpPie->rclBox.bottom,
954              (INT)lpPie->ptlStart.x,
955              (INT)lpPie->ptlStart.y,
956              (INT)lpPie->ptlEnd.x,
957              (INT)lpPie->ptlEnd.y );
958
959        break;
960       }
961
962     case EMR_ARCTO:
963       {
964         PEMRARC lpArcTo = (PEMRARC)mr;
965
966         ArcTo( hdc,
967                (INT)lpArcTo->rclBox.left,
968                (INT)lpArcTo->rclBox.top,
969                (INT)lpArcTo->rclBox.right,
970                (INT)lpArcTo->rclBox.bottom,
971                (INT)lpArcTo->ptlStart.x,
972                (INT)lpArcTo->ptlStart.y,
973                (INT)lpArcTo->ptlEnd.x,
974                (INT)lpArcTo->ptlEnd.y );
975
976         break;
977       }
978
979     case EMR_EXTFLOODFILL:
980       {
981         PEMREXTFLOODFILL lpExtFloodFill = (PEMREXTFLOODFILL)mr;
982
983         ExtFloodFill( hdc,
984                       (INT)lpExtFloodFill->ptlStart.x,
985                       (INT)lpExtFloodFill->ptlStart.y,
986                       lpExtFloodFill->crColor,
987                       (UINT)lpExtFloodFill->iMode );
988
989         break;
990       }
991
992     case EMR_POLYDRAW:
993       {
994         PEMRPOLYDRAW lpPolyDraw = (PEMRPOLYDRAW)mr;
995         PolyDraw( hdc,
996                   (const LPPOINT)lpPolyDraw->aptl,
997                   lpPolyDraw->abTypes,
998                   (INT)lpPolyDraw->cptl );
999
1000         break;
1001       }
1002
1003     case EMR_SETARCDIRECTION:
1004       {
1005         PEMRSETARCDIRECTION lpSetArcDirection = (PEMRSETARCDIRECTION)mr;
1006         SetArcDirection( hdc, (INT)lpSetArcDirection->iArcDirection );
1007         break;
1008       }
1009
1010     case EMR_SETMITERLIMIT:
1011       {
1012         PEMRSETMITERLIMIT lpSetMiterLimit = (PEMRSETMITERLIMIT)mr;
1013         SetMiterLimit( hdc, lpSetMiterLimit->eMiterLimit, NULL );
1014         break;
1015       }
1016
1017     case EMR_BEGINPATH:
1018       {
1019         BeginPath( hdc );
1020         break;
1021       }
1022
1023     case EMR_ENDPATH:
1024       {
1025         EndPath( hdc );
1026         break;
1027       }
1028
1029     case EMR_CLOSEFIGURE:
1030       {
1031         CloseFigure( hdc );
1032         break;
1033       }
1034
1035     case EMR_FILLPATH:
1036       {
1037         /*PEMRFILLPATH lpFillPath = (PEMRFILLPATH)mr;*/
1038         FillPath( hdc );
1039         break;
1040       }
1041
1042     case EMR_STROKEANDFILLPATH:
1043       {
1044         /*PEMRSTROKEANDFILLPATH lpStrokeAndFillPath = (PEMRSTROKEANDFILLPATH)mr;*/
1045         StrokeAndFillPath( hdc );
1046         break;
1047       }
1048
1049     case EMR_STROKEPATH:
1050       {
1051         /*PEMRSTROKEPATH lpStrokePath = (PEMRSTROKEPATH)mr;*/
1052         StrokePath( hdc );
1053         break;
1054       }
1055
1056     case EMR_FLATTENPATH:
1057       {
1058         FlattenPath( hdc );
1059         break;
1060       }
1061
1062     case EMR_WIDENPATH:
1063       {
1064         WidenPath( hdc );
1065         break;
1066       }
1067
1068     case EMR_SELECTCLIPPATH:
1069       {
1070         PEMRSELECTCLIPPATH lpSelectClipPath = (PEMRSELECTCLIPPATH)mr;
1071         SelectClipPath( hdc, (INT)lpSelectClipPath->iMode );
1072         break;
1073       }
1074
1075     case EMR_ABORTPATH:
1076       {
1077         AbortPath( hdc );
1078         break;
1079       }
1080
1081     case EMR_CREATECOLORSPACE:
1082       {
1083         PEMRCREATECOLORSPACE lpCreateColorSpace = (PEMRCREATECOLORSPACE)mr;
1084         (handletable->objectHandle)[lpCreateColorSpace->ihCS] =
1085            CreateColorSpaceA( &lpCreateColorSpace->lcs );
1086         break;
1087       }
1088
1089     case EMR_SETCOLORSPACE:
1090       {
1091         PEMRSETCOLORSPACE lpSetColorSpace = (PEMRSETCOLORSPACE)mr;
1092         SetColorSpace( hdc,
1093                        (handletable->objectHandle)[lpSetColorSpace->ihCS] );
1094         break;
1095       }
1096
1097     case EMR_DELETECOLORSPACE:
1098       {
1099         PEMRDELETECOLORSPACE lpDeleteColorSpace = (PEMRDELETECOLORSPACE)mr;
1100         DeleteColorSpace( (handletable->objectHandle)[lpDeleteColorSpace->ihCS] );
1101         break;
1102       }
1103
1104     case EMR_SETICMMODE:
1105       {
1106         PERMSETICMMODE lpSetICMMode = (PERMSETICMMODE)mr;
1107         SetICMMode( hdc, (INT)lpSetICMMode->iMode );
1108         break;
1109       }
1110
1111     case EMR_PIXELFORMAT:
1112       {
1113         INT iPixelFormat;
1114         PEMRPIXELFORMAT lpPixelFormat = (PEMRPIXELFORMAT)mr;
1115
1116         iPixelFormat = ChoosePixelFormat( hdc, &lpPixelFormat->pfd );
1117         SetPixelFormat( hdc, iPixelFormat, &lpPixelFormat->pfd );
1118
1119         break;
1120       }
1121
1122     case EMR_SETPALETTEENTRIES:
1123       {
1124         PEMRSETPALETTEENTRIES lpSetPaletteEntries = (PEMRSETPALETTEENTRIES)mr;
1125
1126         SetPaletteEntries( (handletable->objectHandle)[lpSetPaletteEntries->ihPal],
1127                            (UINT)lpSetPaletteEntries->iStart,
1128                            (UINT)lpSetPaletteEntries->cEntries,
1129                            lpSetPaletteEntries->aPalEntries );
1130
1131         break;
1132       }
1133
1134     case EMR_RESIZEPALETTE:
1135       {
1136         PEMRRESIZEPALETTE lpResizePalette = (PEMRRESIZEPALETTE)mr;
1137
1138         ResizePalette( (handletable->objectHandle)[lpResizePalette->ihPal],
1139                        (UINT)lpResizePalette->cEntries );
1140
1141         break;
1142       }
1143
1144     case EMR_CREATEDIBPATTERNBRUSHPT:
1145       {
1146         PEMRCREATEDIBPATTERNBRUSHPT lpCreate = (PEMRCREATEDIBPATTERNBRUSHPT)mr;
1147
1148         /* This is a BITMAPINFO struct followed directly by bitmap bits */
1149         LPVOID lpPackedStruct = HeapAlloc( GetProcessHeap(),
1150                                            0,
1151                                            lpCreate->cbBmi + lpCreate->cbBits );
1152         /* Now pack this structure */
1153         memcpy( lpPackedStruct,
1154                 ((BYTE*)lpCreate) + lpCreate->offBmi,
1155                 lpCreate->cbBmi );
1156         memcpy( ((BYTE*)lpPackedStruct) + lpCreate->cbBmi,
1157                 ((BYTE*)lpCreate) + lpCreate->offBits,
1158                 lpCreate->cbBits );
1159
1160         (handletable->objectHandle)[lpCreate->ihBrush] =
1161            CreateDIBPatternBrushPt( lpPackedStruct,
1162                                     (UINT)lpCreate->iUsage );
1163
1164         break;
1165       }
1166
1167     case EMR_CREATEMONOBRUSH:
1168     {
1169         PEMRCREATEMONOBRUSH pCreateMonoBrush = (PEMRCREATEMONOBRUSH)mr;
1170         BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pCreateMonoBrush->offBmi);
1171         HBITMAP hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1172                 (BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
1173         (handletable->objectHandle)[pCreateMonoBrush->ihBrush] = CreatePatternBrush(hBmp);
1174         /* CreatePatternBrush created a copy of the bitmap */
1175         DeleteObject(hBmp);
1176         break;
1177     }
1178
1179     case EMR_BITBLT:
1180     {
1181         PEMRBITBLT pBitBlt = (PEMRBITBLT)mr;
1182         HDC hdcSrc = CreateCompatibleDC(hdc);
1183         HBRUSH hBrush, hBrushOld;
1184         HBITMAP hBmp, hBmpOld;
1185         BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pBitBlt->offBmiSrc);
1186
1187         SetWorldTransform(hdcSrc, &pBitBlt->xformSrc);
1188
1189         hBrush = CreateSolidBrush(pBitBlt->crBkColorSrc);
1190         hBrushOld = SelectObject(hdcSrc, hBrush);
1191         PatBlt(hdcSrc, pBitBlt->rclBounds.left, pBitBlt->rclBounds.top,
1192                pBitBlt->rclBounds.right - pBitBlt->rclBounds.left,
1193                pBitBlt->rclBounds.bottom - pBitBlt->rclBounds.top, PATCOPY);
1194         SelectObject(hdcSrc, hBrushOld);
1195         DeleteObject(hBrush);
1196
1197         hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1198                               (BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
1199         hBmpOld = SelectObject(hdcSrc, hBmp);
1200         BitBlt(hdc,
1201                pBitBlt->xDest,
1202                pBitBlt->yDest,
1203                pBitBlt->cxDest,
1204                pBitBlt->cyDest,
1205                hdcSrc,
1206                pBitBlt->xSrc,
1207                pBitBlt->ySrc,
1208                pBitBlt->dwRop);
1209         SelectObject(hdcSrc, hBmpOld);
1210         DeleteObject(hBmp);
1211         DeleteDC(hdcSrc);
1212         break;
1213     }
1214
1215     case EMR_STRETCHBLT:
1216     {
1217         PEMRSTRETCHBLT pStretchBlt= (PEMRSTRETCHBLT)mr;
1218         HDC hdcSrc = CreateCompatibleDC(hdc);
1219         HBRUSH hBrush, hBrushOld;
1220         HBITMAP hBmp, hBmpOld;
1221         BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pStretchBlt->offBmiSrc);
1222
1223         SetWorldTransform(hdcSrc, &pStretchBlt->xformSrc);
1224
1225         hBrush = CreateSolidBrush(pStretchBlt->crBkColorSrc);
1226         hBrushOld = SelectObject(hdcSrc, hBrush);
1227         PatBlt(hdcSrc, pStretchBlt->rclBounds.left, pStretchBlt->rclBounds.top,
1228                pStretchBlt->rclBounds.right - pStretchBlt->rclBounds.left,
1229                pStretchBlt->rclBounds.bottom - pStretchBlt->rclBounds.top, PATCOPY);
1230         SelectObject(hdcSrc, hBrushOld);
1231         DeleteObject(hBrush);
1232
1233         hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1234                               (BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
1235         hBmpOld = SelectObject(hdcSrc, hBmp);
1236         StretchBlt(hdc,
1237                pStretchBlt->xDest,
1238                pStretchBlt->yDest,
1239                pStretchBlt->cxDest,
1240                pStretchBlt->cyDest,
1241                hdcSrc,
1242                pStretchBlt->xSrc,
1243                pStretchBlt->ySrc,
1244                pStretchBlt->cxSrc,
1245                pStretchBlt->cySrc,
1246                pStretchBlt->dwRop);
1247         SelectObject(hdcSrc, hBmpOld);
1248         DeleteObject(hBmp);
1249         DeleteDC(hdcSrc);
1250         break;
1251     }
1252
1253     case EMR_MASKBLT:
1254     {
1255         PEMRMASKBLT pMaskBlt= (PEMRMASKBLT)mr;
1256         HDC hdcSrc = CreateCompatibleDC(hdc);
1257         HBRUSH hBrush, hBrushOld;
1258         HBITMAP hBmp, hBmpOld, hBmpMask;
1259         BITMAPINFO *pbi;
1260
1261         SetWorldTransform(hdcSrc, &pMaskBlt->xformSrc);
1262
1263         hBrush = CreateSolidBrush(pMaskBlt->crBkColorSrc);
1264         hBrushOld = SelectObject(hdcSrc, hBrush);
1265         PatBlt(hdcSrc, pMaskBlt->rclBounds.left, pMaskBlt->rclBounds.top,
1266                pMaskBlt->rclBounds.right - pMaskBlt->rclBounds.left,
1267                pMaskBlt->rclBounds.bottom - pMaskBlt->rclBounds.top, PATCOPY);
1268         SelectObject(hdcSrc, hBrushOld);
1269         DeleteObject(hBrush);
1270
1271         pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiMask);
1272         hBmpMask = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1273                               (BYTE *)mr + pMaskBlt->offBitsMask, pbi, pMaskBlt->iUsageMask);
1274
1275         pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiSrc);
1276         hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1277                               (BYTE *)mr + pMaskBlt->offBitsSrc, pbi, pMaskBlt->iUsageSrc);
1278         hBmpOld = SelectObject(hdcSrc, hBmp);
1279         MaskBlt(hdc,
1280                 pMaskBlt->xDest,
1281                 pMaskBlt->yDest,
1282                 pMaskBlt->cxDest,
1283                 pMaskBlt->cyDest,
1284                 hdcSrc,
1285                 pMaskBlt->xSrc,
1286                 pMaskBlt->ySrc,
1287                 hBmpMask,
1288                 pMaskBlt->xMask,
1289                 pMaskBlt->yMask,
1290                 pMaskBlt->dwRop);
1291         SelectObject(hdcSrc, hBmpOld);
1292         DeleteObject(hBmp);
1293         DeleteObject(hBmpMask);
1294         DeleteDC(hdcSrc);
1295         break;
1296     }
1297
1298     case EMR_PLGBLT:
1299     {
1300         PEMRPLGBLT pPlgBlt= (PEMRPLGBLT)mr;
1301         HDC hdcSrc = CreateCompatibleDC(hdc);
1302         HBRUSH hBrush, hBrushOld;
1303         HBITMAP hBmp, hBmpOld, hBmpMask;
1304         BITMAPINFO *pbi;
1305         POINT pts[3];
1306
1307         SetWorldTransform(hdcSrc, &pPlgBlt->xformSrc);
1308
1309         pts[0].x = pPlgBlt->aptlDst[0].x; pts[0].y = pPlgBlt->aptlDst[0].y;
1310         pts[1].x = pPlgBlt->aptlDst[1].x; pts[1].y = pPlgBlt->aptlDst[1].y;
1311         pts[2].x = pPlgBlt->aptlDst[2].x; pts[2].y = pPlgBlt->aptlDst[2].y;
1312
1313         hBrush = CreateSolidBrush(pPlgBlt->crBkColorSrc);
1314         hBrushOld = SelectObject(hdcSrc, hBrush);
1315         PatBlt(hdcSrc, pPlgBlt->rclBounds.left, pPlgBlt->rclBounds.top,
1316                pPlgBlt->rclBounds.right - pPlgBlt->rclBounds.left,
1317                pPlgBlt->rclBounds.bottom - pPlgBlt->rclBounds.top, PATCOPY);
1318         SelectObject(hdcSrc, hBrushOld);
1319         DeleteObject(hBrush);
1320
1321         pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiMask);
1322         hBmpMask = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1323                               (BYTE *)mr + pPlgBlt->offBitsMask, pbi, pPlgBlt->iUsageMask);
1324
1325         pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiSrc);
1326         hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1327                               (BYTE *)mr + pPlgBlt->offBitsSrc, pbi, pPlgBlt->iUsageSrc);
1328         hBmpOld = SelectObject(hdcSrc, hBmp);
1329         PlgBlt(hdc,
1330                pts,
1331                hdcSrc,
1332                pPlgBlt->xSrc,
1333                pPlgBlt->ySrc,
1334                pPlgBlt->cxSrc,
1335                pPlgBlt->cySrc,
1336                hBmpMask,
1337                pPlgBlt->xMask,
1338                pPlgBlt->yMask);
1339         SelectObject(hdcSrc, hBmpOld);
1340         DeleteObject(hBmp);
1341         DeleteObject(hBmpMask);
1342         DeleteDC(hdcSrc);
1343         break;
1344     }
1345
1346     case EMR_SETDIBITSTODEVICE:
1347     {
1348         PEMRSETDIBITSTODEVICE pSetDIBitsToDevice = (PEMRSETDIBITSTODEVICE)mr;
1349
1350         SetDIBitsToDevice(hdc,
1351                           pSetDIBitsToDevice->xDest,
1352                           pSetDIBitsToDevice->yDest,
1353                           pSetDIBitsToDevice->cxSrc,
1354                           pSetDIBitsToDevice->cySrc,
1355                           pSetDIBitsToDevice->xSrc,
1356                           pSetDIBitsToDevice->ySrc,
1357                           pSetDIBitsToDevice->iStartScan,
1358                           pSetDIBitsToDevice->cScans,
1359                           (BYTE *)mr + pSetDIBitsToDevice->offBitsSrc,
1360                           (BITMAPINFO *)((BYTE *)mr + pSetDIBitsToDevice->offBmiSrc),
1361                           pSetDIBitsToDevice->iUsageSrc);
1362         break;
1363     }
1364
1365     case EMR_POLYTEXTOUTA:
1366     {
1367         PEMRPOLYTEXTOUTA pPolyTextOutA = (PEMRPOLYTEXTOUTA)mr;
1368         POLYTEXTA *polytextA = HeapAlloc(GetProcessHeap(), 0, pPolyTextOutA->cStrings * sizeof(POLYTEXTA));
1369         LONG i;
1370         XFORM xform, xformOld;
1371         int gModeOld;
1372
1373         gModeOld = SetGraphicsMode(hdc, pPolyTextOutA->iGraphicsMode);
1374         GetWorldTransform(hdc, &xformOld);
1375
1376         xform.eM11 = pPolyTextOutA->exScale;
1377         xform.eM12 = 0.0;
1378         xform.eM21 = 0.0;
1379         xform.eM22 = pPolyTextOutA->eyScale;
1380         xform.eDx = 0.0;
1381         xform.eDy = 0.0;
1382         SetWorldTransform(hdc, &xform);
1383
1384         /* Set up POLYTEXTA structures */
1385         for(i = 0; i < pPolyTextOutA->cStrings; i++)
1386         {
1387             polytextA[i].x = pPolyTextOutA->aemrtext[i].ptlReference.x;
1388             polytextA[i].y = pPolyTextOutA->aemrtext[i].ptlReference.y;
1389             polytextA[i].n = pPolyTextOutA->aemrtext[i].nChars;
1390             polytextA[i].lpstr = (LPSTR)((BYTE *)mr + pPolyTextOutA->aemrtext[i].offString);
1391             polytextA[i].uiFlags = pPolyTextOutA->aemrtext[i].fOptions;
1392             polytextA[i].rcl.left = pPolyTextOutA->aemrtext[i].rcl.left;
1393             polytextA[i].rcl.right = pPolyTextOutA->aemrtext[i].rcl.right;
1394             polytextA[i].rcl.top = pPolyTextOutA->aemrtext[i].rcl.top;
1395             polytextA[i].rcl.bottom = pPolyTextOutA->aemrtext[i].rcl.bottom;
1396             polytextA[i].pdx = (int *)((BYTE *)mr + pPolyTextOutA->aemrtext[i].offDx);
1397         }
1398         PolyTextOutA(hdc, polytextA, pPolyTextOutA->cStrings);
1399         HeapFree(GetProcessHeap(), 0, polytextA);
1400
1401         SetWorldTransform(hdc, &xformOld);
1402         SetGraphicsMode(hdc, gModeOld);
1403         break;
1404     }
1405
1406     case EMR_POLYTEXTOUTW:
1407     {
1408         PEMRPOLYTEXTOUTW pPolyTextOutW = (PEMRPOLYTEXTOUTW)mr;
1409         POLYTEXTW *polytextW = HeapAlloc(GetProcessHeap(), 0, pPolyTextOutW->cStrings * sizeof(POLYTEXTW));
1410         LONG i;
1411         XFORM xform, xformOld;
1412         int gModeOld;
1413
1414         gModeOld = SetGraphicsMode(hdc, pPolyTextOutW->iGraphicsMode);
1415         GetWorldTransform(hdc, &xformOld);
1416
1417         xform.eM11 = pPolyTextOutW->exScale;
1418         xform.eM12 = 0.0;
1419         xform.eM21 = 0.0;
1420         xform.eM22 = pPolyTextOutW->eyScale;
1421         xform.eDx = 0.0;
1422         xform.eDy = 0.0;
1423         SetWorldTransform(hdc, &xform);
1424
1425         /* Set up POLYTEXTW structures */
1426         for(i = 0; i < pPolyTextOutW->cStrings; i++)
1427         {
1428             polytextW[i].x = pPolyTextOutW->aemrtext[i].ptlReference.x;
1429             polytextW[i].y = pPolyTextOutW->aemrtext[i].ptlReference.y;
1430             polytextW[i].n = pPolyTextOutW->aemrtext[i].nChars;
1431             polytextW[i].lpstr = (LPWSTR)((BYTE *)mr + pPolyTextOutW->aemrtext[i].offString);
1432             polytextW[i].uiFlags = pPolyTextOutW->aemrtext[i].fOptions;
1433             polytextW[i].rcl.left = pPolyTextOutW->aemrtext[i].rcl.left;
1434             polytextW[i].rcl.right = pPolyTextOutW->aemrtext[i].rcl.right;
1435             polytextW[i].rcl.top = pPolyTextOutW->aemrtext[i].rcl.top;
1436             polytextW[i].rcl.bottom = pPolyTextOutW->aemrtext[i].rcl.bottom;
1437             polytextW[i].pdx = (int *)((BYTE *)mr + pPolyTextOutW->aemrtext[i].offDx);
1438         }
1439         PolyTextOutW(hdc, polytextW, pPolyTextOutW->cStrings);
1440         HeapFree(GetProcessHeap(), 0, polytextW);
1441
1442         SetWorldTransform(hdc, &xformOld);
1443         SetGraphicsMode(hdc, gModeOld);
1444         break;
1445     }
1446
1447     case EMR_FILLRGN:
1448     {
1449         PEMRFILLRGN pFillRgn = (PEMRFILLRGN)mr;
1450         HRGN hRgn = ExtCreateRegion(NULL, pFillRgn->cbRgnData, (RGNDATA *)pFillRgn->RgnData);
1451         FillRgn(hdc,
1452                 hRgn,
1453                 (handletable->objectHandle)[pFillRgn->ihBrush]);
1454         DeleteObject(hRgn);
1455         break;
1456     }
1457
1458     case EMR_FRAMERGN:
1459     {
1460         PEMRFRAMERGN pFrameRgn = (PEMRFRAMERGN)mr;
1461         HRGN hRgn = ExtCreateRegion(NULL, pFrameRgn->cbRgnData, (RGNDATA *)pFrameRgn->RgnData);
1462         FrameRgn(hdc,
1463                  hRgn,
1464                  (handletable->objectHandle)[pFrameRgn->ihBrush],
1465                  pFrameRgn->szlStroke.cx,
1466                  pFrameRgn->szlStroke.cy);
1467         DeleteObject(hRgn);
1468         break;
1469     }
1470
1471     case EMR_INVERTRGN:
1472     {
1473         PEMRINVERTRGN pInvertRgn = (PEMRINVERTRGN)mr;
1474         HRGN hRgn = ExtCreateRegion(NULL, pInvertRgn->cbRgnData, (RGNDATA *)pInvertRgn->RgnData);
1475         InvertRgn(hdc, hRgn);
1476         DeleteObject(hRgn);
1477         break;
1478     }
1479
1480     case EMR_PAINTRGN:
1481     {
1482         PEMRPAINTRGN pPaintRgn = (PEMRPAINTRGN)mr;
1483         HRGN hRgn = ExtCreateRegion(NULL, pPaintRgn->cbRgnData, (RGNDATA *)pPaintRgn->RgnData);
1484         PaintRgn(hdc, hRgn);
1485         DeleteObject(hRgn);
1486         break;
1487     }
1488
1489     case EMR_POLYDRAW16:
1490     case EMR_GLSRECORD:
1491     case EMR_GLSBOUNDEDRECORD:
1492     default:
1493       /* From docs: If PlayEnhMetaFileRecord doesn't recognize a
1494                     record then ignore and return TRUE. */
1495       FIXME("type %d is unimplemented\n", type);
1496       break;
1497     }
1498   return TRUE;
1499 }
1500
1501
1502 /*****************************************************************************
1503  *
1504  *        EnumEnhMetaFile  (GDI32.@)
1505  *
1506  *  Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
1507  *  for each
1508  *  record. Returns when either every record has been used or
1509  *  when _EnhMetaFunc_ returns FALSE.
1510  *
1511  *
1512  * RETURNS
1513  *  TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
1514  *  returns FALSE.
1515  *
1516  * BUGS
1517  *   Ignores rect.
1518  */
1519 BOOL WINAPI EnumEnhMetaFile(
1520      HDC hdc,                /* [in] device context to pass to _EnhMetaFunc_ */
1521      HENHMETAFILE hmf,       /* [in] EMF to walk */
1522      ENHMFENUMPROC callback, /* [in] callback function */
1523      LPVOID data,            /* [in] optional data for callback function */
1524      const RECT *lpRect      /* [in] bounding rectangle for rendered metafile */
1525     )
1526 {
1527     BOOL ret;
1528     ENHMETAHEADER *emh;
1529     ENHMETARECORD *emr;
1530     DWORD offset;
1531     UINT i;
1532     HANDLETABLE *ht;
1533     INT savedMode = 0;
1534     FLOAT xSrcPixSize, ySrcPixSize, xscale, yscale;
1535     XFORM savedXform, xform;
1536     HPEN hPen = (HPEN)NULL;
1537     HBRUSH hBrush = (HBRUSH)NULL;
1538     HFONT hFont = (HFONT)NULL;
1539
1540     if(!lpRect)
1541     {
1542         SetLastError(ERROR_INVALID_PARAMETER);
1543         return FALSE;
1544     }
1545
1546     emh = EMF_GetEnhMetaHeader(hmf);
1547     if(!emh) {
1548         SetLastError(ERROR_INVALID_HANDLE);
1549         return FALSE;
1550     }
1551
1552     ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1553                     sizeof(HANDLETABLE) * emh->nHandles );
1554     if(!ht)
1555     {
1556         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1557         return FALSE;
1558     }
1559     ht->objectHandle[0] = hmf;
1560
1561     if (hdc)
1562     {
1563         TRACE("rect: %d,%d - %d,%d. rclFrame: %ld,%ld - %ld,%ld\n",
1564               lpRect->left, lpRect->top, lpRect->right, lpRect->bottom,
1565               emh->rclFrame.left, emh->rclFrame.top, emh->rclFrame.right,
1566               emh->rclFrame.bottom);
1567
1568         xSrcPixSize = (FLOAT) emh->szlMillimeters.cx / emh->szlDevice.cx;
1569         ySrcPixSize = (FLOAT) emh->szlMillimeters.cy / emh->szlDevice.cy;
1570         xscale = (FLOAT)(lpRect->right - lpRect->left) * 100.0 /
1571           (emh->rclFrame.right - emh->rclFrame.left) * xSrcPixSize;
1572         yscale = (FLOAT)(lpRect->bottom - lpRect->top) * 100.0 /
1573           (emh->rclFrame.bottom - emh->rclFrame.top) * ySrcPixSize;
1574
1575         xform.eM11 = xscale;
1576         xform.eM12 = 0;
1577         xform.eM21 = 0;
1578         xform.eM22 = yscale;
1579         xform.eDx = (FLOAT) lpRect->left - (lpRect->right - lpRect->left) *
1580           emh->rclFrame.left / (emh->rclFrame.right - emh->rclFrame.left);
1581         xform.eDy = (FLOAT) lpRect->top - (lpRect->bottom - lpRect->top) *
1582           emh->rclFrame.top / (emh->rclFrame.bottom - emh->rclFrame.top);
1583
1584         savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
1585         GetWorldTransform(hdc, &savedXform);
1586
1587         if (!ModifyWorldTransform(hdc, &xform, MWT_RIGHTMULTIPLY)) {
1588             ERR("World transform failed!\n");
1589         }
1590
1591         /* save the current pen, brush and font */
1592         hPen = GetCurrentObject(hdc, OBJ_PEN);
1593         hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
1594         hFont = GetCurrentObject(hdc, OBJ_FONT);
1595     }
1596
1597     TRACE("nSize = %ld, nBytes = %ld, nHandles = %d, nRecords = %ld, nPalEntries = %ld\n",
1598         emh->nSize, emh->nBytes, emh->nHandles, emh->nRecords, emh->nPalEntries);
1599
1600     ret = TRUE;
1601     offset = 0;
1602     while(ret && offset < emh->nBytes)
1603     {
1604         emr = (ENHMETARECORD *)((char *)emh + offset);
1605         TRACE("Calling EnumFunc with record type %ld, size %ld\n", emr->iType, emr->nSize);
1606         ret = (*callback)(hdc, ht, emr, emh->nHandles, data);
1607         offset += emr->nSize;
1608     }
1609
1610     if (hdc)
1611     {
1612         /* restore pen, brush and font */
1613         SelectObject(hdc, hBrush);
1614         SelectObject(hdc, hPen);
1615         SelectObject(hdc, hFont);
1616
1617         SetWorldTransform(hdc, &savedXform);
1618         if (savedMode)
1619             SetGraphicsMode(hdc, savedMode);
1620     }
1621
1622     for(i = 1; i < emh->nHandles; i++) /* Don't delete element 0 (hmf) */
1623         if( (ht->objectHandle)[i] )
1624             DeleteObject( (ht->objectHandle)[i] );
1625
1626     HeapFree( GetProcessHeap(), 0, ht );
1627     return ret;
1628 }
1629
1630 static INT CALLBACK EMF_PlayEnhMetaFileCallback(HDC hdc, HANDLETABLE *ht,
1631                                                 ENHMETARECORD *emr,
1632                                                 INT handles, LPVOID data)
1633 {
1634     return PlayEnhMetaFileRecord(hdc, ht, emr, handles);
1635 }
1636
1637 /**************************************************************************
1638  *    PlayEnhMetaFile  (GDI32.@)
1639  *
1640  *    Renders an enhanced metafile into a specified rectangle *lpRect
1641  *    in device context hdc.
1642  *
1643  */
1644 BOOL WINAPI PlayEnhMetaFile(
1645        HDC hdc,           /* [in] DC to render into */
1646        HENHMETAFILE hmf,  /* [in] metafile to render */
1647        const RECT *lpRect /* [in] rectangle to place metafile inside */
1648       )
1649 {
1650     return EnumEnhMetaFile(hdc, hmf, EMF_PlayEnhMetaFileCallback, NULL,
1651                            lpRect);
1652 }
1653
1654 /*****************************************************************************
1655  *  DeleteEnhMetaFile (GDI32.@)
1656  *
1657  *  Deletes an enhanced metafile and frees the associated storage.
1658  */
1659 BOOL WINAPI DeleteEnhMetaFile(HENHMETAFILE hmf)
1660 {
1661     return EMF_Delete_HENHMETAFILE( hmf );
1662 }
1663
1664 /*****************************************************************************
1665  *  CopyEnhMetaFileA (GDI32.@)  Duplicate an enhanced metafile
1666  *
1667  *
1668  */
1669 HENHMETAFILE WINAPI CopyEnhMetaFileA(
1670     HENHMETAFILE hmfSrc,
1671     LPCSTR file)
1672 {
1673     ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst;
1674     HENHMETAFILE hmfDst;
1675
1676     if(!emrSrc) return FALSE;
1677     if (!file) {
1678         emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes );
1679         memcpy( emrDst, emrSrc, emrSrc->nBytes );
1680         hmfDst = EMF_Create_HENHMETAFILE( emrDst, FALSE );
1681     } else {
1682         HANDLE hFile;
1683         hFile = CreateFileA( file, GENERIC_WRITE | GENERIC_READ, 0, NULL,
1684                              CREATE_ALWAYS, 0, 0);
1685         WriteFile( hFile, emrSrc, emrSrc->nBytes, 0, 0);
1686         hmfDst = EMF_GetEnhMetaFile( hFile );
1687         CloseHandle( hFile );
1688     }
1689     return hmfDst;
1690 }
1691
1692
1693 /* Struct to be used to be passed in the LPVOID parameter for cbEnhPaletteCopy */
1694 typedef struct tagEMF_PaletteCopy
1695 {
1696    UINT cEntries;
1697    LPPALETTEENTRY lpPe;
1698 } EMF_PaletteCopy;
1699
1700 /***************************************************************
1701  * Find the EMR_EOF record and then use it to find the
1702  * palette entries for this enhanced metafile.
1703  * The lpData is actually a pointer to a EMF_PaletteCopy struct
1704  * which contains the max number of elements to copy and where
1705  * to copy them to.
1706  *
1707  * NOTE: To be used by GetEnhMetaFilePaletteEntries only!
1708  */
1709 INT CALLBACK cbEnhPaletteCopy( HDC a,
1710                                LPHANDLETABLE b,
1711                                LPENHMETARECORD lpEMR,
1712                                INT c,
1713                                LPVOID lpData )
1714 {
1715
1716   if ( lpEMR->iType == EMR_EOF )
1717   {
1718     PEMREOF lpEof = (PEMREOF)lpEMR;
1719     EMF_PaletteCopy* info = (EMF_PaletteCopy*)lpData;
1720     DWORD dwNumPalToCopy = min( lpEof->nPalEntries, info->cEntries );
1721
1722     TRACE( "copying 0x%08lx palettes\n", dwNumPalToCopy );
1723
1724     memcpy( (LPVOID)info->lpPe,
1725             (LPVOID)(((LPSTR)lpEof) + lpEof->offPalEntries),
1726             sizeof( *(info->lpPe) ) * dwNumPalToCopy );
1727
1728     /* Update the passed data as a return code */
1729     info->lpPe     = NULL; /* Palettes were copied! */
1730     info->cEntries = (UINT)dwNumPalToCopy;
1731
1732     return FALSE; /* That's all we need */
1733   }
1734
1735   return TRUE;
1736 }
1737
1738 /*****************************************************************************
1739  *  GetEnhMetaFilePaletteEntries (GDI32.@)
1740  *
1741  *  Copy the palette and report size
1742  *
1743  *  BUGS: Error codes (SetLastError) are not set on failures
1744  */
1745 UINT WINAPI GetEnhMetaFilePaletteEntries( HENHMETAFILE hEmf,
1746                                           UINT cEntries,
1747                                           LPPALETTEENTRY lpPe )
1748 {
1749   ENHMETAHEADER* enhHeader = EMF_GetEnhMetaHeader( hEmf );
1750   EMF_PaletteCopy infoForCallBack;
1751
1752   TRACE( "(%04x,%d,%p)\n", hEmf, cEntries, lpPe );
1753
1754   /* First check if there are any palettes associated with
1755      this metafile. */
1756   if ( enhHeader->nPalEntries == 0 ) return 0;
1757
1758   /* Is the user requesting the number of palettes? */
1759   if ( lpPe == NULL ) return (UINT)enhHeader->nPalEntries;
1760
1761   /* Copy cEntries worth of PALETTEENTRY structs into the buffer */
1762   infoForCallBack.cEntries = cEntries;
1763   infoForCallBack.lpPe     = lpPe;
1764
1765   if ( !EnumEnhMetaFile( 0, hEmf, cbEnhPaletteCopy,
1766                          &infoForCallBack, NULL ) )
1767       return GDI_ERROR;
1768
1769   /* Verify that the callback executed correctly */
1770   if ( infoForCallBack.lpPe != NULL )
1771   {
1772      /* Callback proc had error! */
1773      ERR( "cbEnhPaletteCopy didn't execute correctly\n" );
1774      return GDI_ERROR;
1775   }
1776
1777   return infoForCallBack.cEntries;
1778 }
1779
1780 /******************************************************************
1781  *         SetWinMetaFileBits   (GDI32.@)
1782  *
1783  *         Translate from old style to new style.
1784  *
1785  * BUGS: - This doesn't take the DC and scaling into account
1786  *       - Most record conversions aren't implemented
1787  *       - Handle slot assignement is primative and most likely doesn't work
1788  */
1789 HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
1790                                            CONST BYTE *lpbBuffer,
1791                                            HDC hdcRef,
1792                                            CONST METAFILEPICT *lpmfp
1793                                            )
1794 {
1795      HENHMETAFILE    hMf;
1796      LPVOID          lpNewEnhMetaFileBuffer = NULL;
1797      UINT            uNewEnhMetaFileBufferSize = 0;
1798      BOOL            bFoundEOF = FALSE;
1799
1800      FIXME( "(%d,%p,%04x,%p):stub\n", cbBuffer, lpbBuffer, hdcRef, lpmfp );
1801
1802      /* 1. Get the header - skip over this and get straight to the records  */
1803
1804      uNewEnhMetaFileBufferSize = sizeof( ENHMETAHEADER );
1805      lpNewEnhMetaFileBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1806                                          uNewEnhMetaFileBufferSize );
1807
1808      if( lpNewEnhMetaFileBuffer == NULL )
1809      {
1810        goto error;
1811      }
1812
1813      /* Fill in the header record */
1814      {
1815        LPENHMETAHEADER lpNewEnhMetaFileHeader = (LPENHMETAHEADER)lpNewEnhMetaFileBuffer;
1816
1817        lpNewEnhMetaFileHeader->iType = EMR_HEADER;
1818        lpNewEnhMetaFileHeader->nSize = sizeof( ENHMETAHEADER );
1819
1820        /* FIXME: Not right. Must be able to get this from the DC */
1821        lpNewEnhMetaFileHeader->rclBounds.left   = 0;
1822        lpNewEnhMetaFileHeader->rclBounds.right  = 0;
1823        lpNewEnhMetaFileHeader->rclBounds.top    = 0;
1824        lpNewEnhMetaFileHeader->rclBounds.bottom = 0;
1825
1826        /* FIXME: Not right. Must be able to get this from the DC */
1827        lpNewEnhMetaFileHeader->rclFrame.left   = 0;
1828        lpNewEnhMetaFileHeader->rclFrame.right  = 0;
1829        lpNewEnhMetaFileHeader->rclFrame.top    = 0;
1830        lpNewEnhMetaFileHeader->rclFrame.bottom = 0;
1831
1832        lpNewEnhMetaFileHeader->dSignature=ENHMETA_SIGNATURE;
1833        lpNewEnhMetaFileHeader->nVersion=0x10000;
1834        lpNewEnhMetaFileHeader->nBytes = lpNewEnhMetaFileHeader->nSize;
1835        lpNewEnhMetaFileHeader->sReserved=0;
1836
1837         /* FIXME: if there is a description add it */
1838         lpNewEnhMetaFileHeader->nDescription=0;
1839         lpNewEnhMetaFileHeader->offDescription=0;
1840
1841         lpNewEnhMetaFileHeader->nHandles = 0; /* No handles yet */
1842         lpNewEnhMetaFileHeader->nRecords = 0;
1843
1844         /* I am pretty sure this starts at 0 and grows as entries are added */
1845         lpNewEnhMetaFileHeader->nPalEntries = 0;
1846
1847         /* Size in Pixels */
1848         lpNewEnhMetaFileHeader->szlDevice.cx = GetDeviceCaps(hdcRef,HORZRES);
1849         lpNewEnhMetaFileHeader->szlDevice.cy = GetDeviceCaps(hdcRef,VERTRES);
1850
1851         /* Size in mm */
1852         lpNewEnhMetaFileHeader->szlMillimeters.cx =
1853                                         GetDeviceCaps(hdcRef,HORZSIZE);
1854         lpNewEnhMetaFileHeader->szlMillimeters.cy =
1855                                         GetDeviceCaps(hdcRef,VERTSIZE);
1856
1857        /* FIXME: Add in the rest of the fields to the header */
1858        /* cbPixelFormat
1859           offPixelFormat,
1860           bOpenGL */
1861      }
1862
1863      (char*)lpbBuffer += ((METAHEADER*)lpbBuffer)->mtHeaderSize * 2; /* Point past the header - FIXME: metafile quirk? */
1864
1865      /* 2. Enum over individual records and convert them to the new type of records */
1866      while( !bFoundEOF )
1867      {
1868
1869         LPMETARECORD lpMetaRecord = (LPMETARECORD)lpbBuffer;
1870
1871 #define EMF_ReAllocAndAdjustPointers( a , b ) \
1872                                         { \
1873                                           LPVOID lpTmp; \
1874                                           lpTmp = HeapReAlloc( GetProcessHeap(), 0, \
1875                                                                lpNewEnhMetaFileBuffer, \
1876                                                                uNewEnhMetaFileBufferSize + (b) ); \
1877                                           if( lpTmp == NULL ) { ERR( "No memory!\n" ); goto error; } \
1878                                           lpNewEnhMetaFileBuffer = lpTmp; \
1879                                           lpRecord = (a)( (char*)lpNewEnhMetaFileBuffer + uNewEnhMetaFileBufferSize ); \
1880                                           uNewEnhMetaFileBufferSize += (b); \
1881                                         }
1882
1883         switch( lpMetaRecord->rdFunction )
1884         {
1885           case META_EOF:
1886           {
1887              PEMREOF lpRecord;
1888              size_t uRecord = sizeof(*lpRecord);
1889
1890              EMF_ReAllocAndAdjustPointers(PEMREOF,uRecord);
1891
1892              /* Fill the new record - FIXME: This is not right */
1893              lpRecord->emr.iType = EMR_EOF;
1894              lpRecord->emr.nSize = sizeof( *lpRecord );
1895              lpRecord->nPalEntries = 0;     /* FIXME */
1896              lpRecord->offPalEntries = 0;   /* FIXME */
1897              lpRecord->nSizeLast = 0;       /* FIXME */
1898
1899              /* No more records after this one */
1900              bFoundEOF = TRUE;
1901
1902              FIXME( "META_EOF conversion not correct\n" );
1903              break;
1904           }
1905
1906           case META_SETMAPMODE:
1907           {
1908              PEMRSETMAPMODE lpRecord;
1909              size_t uRecord = sizeof(*lpRecord);
1910
1911              EMF_ReAllocAndAdjustPointers(PEMRSETMAPMODE,uRecord);
1912
1913              lpRecord->emr.iType = EMR_SETMAPMODE;
1914              lpRecord->emr.nSize = sizeof( *lpRecord );
1915
1916              lpRecord->iMode = lpMetaRecord->rdParm[0];
1917
1918              break;
1919           }
1920
1921           case META_DELETEOBJECT: /* Select and Delete structures are the same */
1922           case META_SELECTOBJECT:
1923           {
1924             PEMRDELETEOBJECT lpRecord;
1925             size_t uRecord = sizeof(*lpRecord);
1926
1927             EMF_ReAllocAndAdjustPointers(PEMRDELETEOBJECT,uRecord);
1928
1929             if( lpMetaRecord->rdFunction == META_DELETEOBJECT )
1930             {
1931               lpRecord->emr.iType = EMR_DELETEOBJECT;
1932             }
1933             else
1934             {
1935               lpRecord->emr.iType = EMR_SELECTOBJECT;
1936             }
1937             lpRecord->emr.nSize = sizeof( *lpRecord );
1938
1939             lpRecord->ihObject = lpMetaRecord->rdParm[0]; /* FIXME: Handle */
1940
1941             break;
1942           }
1943
1944           case META_POLYGON: /* This is just plain busted. I don't know what I'm doing */
1945           {
1946              PEMRPOLYGON16 lpRecord; /* FIXME: Should it be a poly or poly16? */
1947              size_t uRecord = sizeof(*lpRecord);
1948
1949              EMF_ReAllocAndAdjustPointers(PEMRPOLYGON16,uRecord);
1950
1951              /* FIXME: This is mostly all wrong */
1952              lpRecord->emr.iType = EMR_POLYGON16;
1953              lpRecord->emr.nSize = sizeof( *lpRecord );
1954
1955              lpRecord->rclBounds.left   = 0;
1956              lpRecord->rclBounds.right  = 0;
1957              lpRecord->rclBounds.top    = 0;
1958              lpRecord->rclBounds.bottom = 0;
1959
1960              lpRecord->cpts = 0;
1961              lpRecord->apts[0].x = 0;
1962              lpRecord->apts[0].y = 0;
1963
1964              FIXME( "META_POLYGON conversion not correct\n" );
1965
1966              break;
1967           }
1968
1969           case META_SETPOLYFILLMODE:
1970           {
1971              PEMRSETPOLYFILLMODE lpRecord;
1972              size_t uRecord = sizeof(*lpRecord);
1973
1974              EMF_ReAllocAndAdjustPointers(PEMRSETPOLYFILLMODE,uRecord);
1975
1976              lpRecord->emr.iType = EMR_SETPOLYFILLMODE;
1977              lpRecord->emr.nSize = sizeof( *lpRecord );
1978
1979              lpRecord->iMode = lpMetaRecord->rdParm[0];
1980
1981              break;
1982           }
1983
1984           case META_SETWINDOWORG:
1985           {
1986              PEMRSETWINDOWORGEX lpRecord; /* Seems to be the closest thing */
1987              size_t uRecord = sizeof(*lpRecord);
1988
1989              EMF_ReAllocAndAdjustPointers(PEMRSETWINDOWORGEX,uRecord);
1990
1991              lpRecord->emr.iType = EMR_SETWINDOWORGEX;
1992              lpRecord->emr.nSize = sizeof( *lpRecord );
1993
1994              lpRecord->ptlOrigin.x = lpMetaRecord->rdParm[1];
1995              lpRecord->ptlOrigin.y = lpMetaRecord->rdParm[0];
1996
1997              break;
1998           }
1999
2000           case META_SETWINDOWEXT:  /* Structure is the same for SETWINDOWEXT & SETVIEWPORTEXT */
2001           case META_SETVIEWPORTEXT:
2002           {
2003              PEMRSETWINDOWEXTEX lpRecord;
2004              size_t uRecord = sizeof(*lpRecord);
2005
2006              EMF_ReAllocAndAdjustPointers(PEMRSETWINDOWEXTEX,uRecord);
2007
2008              if ( lpMetaRecord->rdFunction == META_SETWINDOWEXT )
2009              {
2010                lpRecord->emr.iType = EMR_SETWINDOWORGEX;
2011              }
2012              else
2013              {
2014                lpRecord->emr.iType = EMR_SETVIEWPORTEXTEX;
2015              }
2016              lpRecord->emr.nSize = sizeof( *lpRecord );
2017
2018              lpRecord->szlExtent.cx = lpMetaRecord->rdParm[1];
2019              lpRecord->szlExtent.cy = lpMetaRecord->rdParm[0];
2020
2021              break;
2022           }
2023
2024           case META_CREATEBRUSHINDIRECT:
2025           {
2026              PEMRCREATEBRUSHINDIRECT lpRecord;
2027              size_t uRecord = sizeof(*lpRecord);
2028
2029              EMF_ReAllocAndAdjustPointers(PEMRCREATEBRUSHINDIRECT,uRecord);
2030
2031              lpRecord->emr.iType = EMR_CREATEBRUSHINDIRECT;
2032              lpRecord->emr.nSize = sizeof( *lpRecord );
2033
2034              lpRecord->ihBrush    = ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nHandles;
2035              lpRecord->lb.lbStyle = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbStyle;
2036              lpRecord->lb.lbColor = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbColor;
2037              lpRecord->lb.lbHatch = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbHatch;
2038
2039              ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nHandles += 1; /* New handle */
2040
2041              break;
2042           }
2043
2044           case META_LINETO:
2045           case META_MOVETO:
2046           {
2047              PEMRLINETO lpRecord;
2048              size_t uRecord = sizeof(*lpRecord);
2049
2050              EMF_ReAllocAndAdjustPointers(PEMRLINETO,uRecord);
2051
2052              if ( lpMetaRecord->rdFunction == META_LINETO )
2053              {
2054                lpRecord->emr.iType = EMR_LINETO;
2055              }
2056              else
2057              {
2058                lpRecord->emr.iType = EMR_MOVETOEX;
2059              }
2060              lpRecord->emr.nSize = sizeof( *lpRecord );
2061
2062              lpRecord->ptl.x = lpMetaRecord->rdParm[1];
2063              lpRecord->ptl.y = lpMetaRecord->rdParm[0];
2064
2065              break;
2066             }
2067
2068           case META_SETTEXTCOLOR:
2069           case META_SETBKCOLOR:
2070           {
2071              PEMRSETBKCOLOR lpRecord;
2072              size_t uRecord = sizeof(*lpRecord);
2073
2074              EMF_ReAllocAndAdjustPointers(PEMRSETBKCOLOR,uRecord);
2075
2076              if ( lpMetaRecord->rdFunction == META_SETTEXTCOLOR )
2077              {
2078                lpRecord->emr.iType = EMR_SETTEXTCOLOR;
2079              }
2080              else
2081              {
2082                lpRecord->emr.iType = EMR_SETBKCOLOR;
2083              }
2084              lpRecord->emr.nSize = sizeof( *lpRecord );
2085
2086              lpRecord->crColor = MAKELONG(lpMetaRecord->rdParm[0],
2087                                     lpMetaRecord->rdParm[1]);
2088
2089              break;
2090           }
2091
2092
2093
2094           /* These are all unimplemented and as such are intended to fall through to the default case */
2095           case META_SETBKMODE:
2096           case META_SETROP2:
2097           case META_SETRELABS:
2098           case META_SETSTRETCHBLTMODE:
2099           case META_SETVIEWPORTORG:
2100           case META_OFFSETWINDOWORG:
2101           case META_SCALEWINDOWEXT:
2102           case META_OFFSETVIEWPORTORG:
2103           case META_SCALEVIEWPORTEXT:
2104           case META_EXCLUDECLIPRECT:
2105           case META_INTERSECTCLIPRECT:
2106           case META_ARC:
2107           case META_ELLIPSE:
2108           case META_FLOODFILL:
2109           case META_PIE:
2110           case META_RECTANGLE:
2111           case META_ROUNDRECT:
2112           case META_PATBLT:
2113           case META_SAVEDC:
2114           case META_SETPIXEL:
2115           case META_OFFSETCLIPRGN:
2116           case META_TEXTOUT:
2117           case META_POLYPOLYGON:
2118           case META_POLYLINE:
2119           case META_RESTOREDC:
2120           case META_CHORD:
2121           case META_CREATEPATTERNBRUSH:
2122           case META_CREATEPENINDIRECT:
2123           case META_CREATEFONTINDIRECT:
2124           case META_CREATEPALETTE:
2125           case META_SETTEXTALIGN:
2126           case META_SELECTPALETTE:
2127           case META_SETMAPPERFLAGS:
2128           case META_REALIZEPALETTE:
2129           case META_ESCAPE:
2130           case META_EXTTEXTOUT:
2131           case META_STRETCHDIB:
2132           case META_DIBSTRETCHBLT:
2133           case META_STRETCHBLT:
2134           case META_BITBLT:
2135           case META_CREATEREGION:
2136           case META_FILLREGION:
2137           case META_FRAMEREGION:
2138           case META_INVERTREGION:
2139           case META_PAINTREGION:
2140           case META_SELECTCLIPREGION:
2141           case META_DIBCREATEPATTERNBRUSH:
2142           case META_DIBBITBLT:
2143           case META_SETTEXTCHAREXTRA:
2144           case META_SETTEXTJUSTIFICATION:
2145           case META_EXTFLOODFILL:
2146           case META_SETDIBTODEV:
2147           case META_DRAWTEXT:
2148           case META_ANIMATEPALETTE:
2149           case META_SETPALENTRIES:
2150           case META_RESIZEPALETTE:
2151           case META_RESETDC:
2152           case META_STARTDOC:
2153           case META_STARTPAGE:
2154           case META_ENDPAGE:
2155           case META_ABORTDOC:
2156           case META_ENDDOC:
2157           case META_CREATEBRUSH:
2158           case META_CREATEBITMAPINDIRECT:
2159           case META_CREATEBITMAP:
2160           /* Fall through to unimplemented */
2161           default:
2162           {
2163             /* Not implemented yet */
2164             FIXME( "Conversion of record type 0x%x not implemented.\n", lpMetaRecord->rdFunction );
2165             break;
2166           }
2167        }
2168
2169        /* Move to the next record */
2170        (char*)lpbBuffer += ((LPMETARECORD)lpbBuffer)->rdSize * 2; /* FIXME: Seem to be doing this in metafile.c */
2171
2172 #undef ReAllocAndAdjustPointers
2173      }
2174
2175      /* We know the last of the header information now */
2176      ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nBytes = uNewEnhMetaFileBufferSize;
2177
2178      /* Create the enhanced metafile */
2179      hMf = SetEnhMetaFileBits( uNewEnhMetaFileBufferSize, (const BYTE*)lpNewEnhMetaFileBuffer );
2180
2181      if( !hMf )
2182        ERR( "Problem creating metafile. Did the conversion fail somewhere?\n" );
2183
2184      return hMf;
2185
2186 error:
2187      /* Free the data associated with our copy since it's been copied */
2188      HeapFree( GetProcessHeap(), 0, lpNewEnhMetaFileBuffer );
2189
2190      return 0;
2191 }