Temporarily implemented the LCMAP_SORTKEY flag in the LCMapStringW()
[wine.git] / objects / enhmetafile.c
blob6a4e3f8a5a090b6fb9ba5dc86a238c6c9e3aecaa
1 /*
2 * Enhanced metafile functions
3 * Copyright 1998 Douglas Ridgway
4 * 1999 Huw D M Davies
6 *
7 * The enhanced format consists of the following elements:
9 * A header
10 * A table of handles to GDI objects
11 * An array of metafile records
12 * A private palette
15 * The standard format consists of a header and an array of metafile records.
17 */
19 #include <string.h>
20 #include <assert.h>
21 #include "winbase.h"
22 #include "wingdi.h"
23 #include "wine/winestring.h"
24 #include "winerror.h"
25 #include "enhmetafile.h"
26 #include "debugtools.h"
27 #include "heap.h"
28 #include "metafile.h"
30 DEFAULT_DEBUG_CHANNEL(enhmetafile)
32 /* Prototypes */
33 BOOL WINAPI EnumEnhMetaFile( HDC hdc, HENHMETAFILE hmf, ENHMFENUMPROC callback,
34 LPVOID data, const RECT *rect );
37 /****************************************************************************
38 * EMF_Create_HENHMETAFILE
40 HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, HFILE hFile, HANDLE
41 hMapping )
43 HENHMETAFILE hmf = GDI_AllocObject( sizeof(ENHMETAFILEOBJ),
44 ENHMETAFILE_MAGIC );
45 ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_HEAP_LOCK( hmf );
46 metaObj->emh = emh;
47 metaObj->hFile = hFile;
48 metaObj->hMapping = hMapping;
49 GDI_HEAP_UNLOCK( hmf );
50 return hmf;
53 /****************************************************************************
54 * EMF_Delete_HENHMETAFILE
56 static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf )
58 ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf,
59 ENHMETAFILE_MAGIC );
60 if(!metaObj) return FALSE;
61 if(metaObj->hMapping) {
62 UnmapViewOfFile( metaObj->emh );
63 CloseHandle( metaObj->hMapping );
64 CloseHandle( metaObj->hFile );
65 } else
66 HeapFree( GetProcessHeap(), 0, metaObj->emh );
67 return GDI_FreeObject( hmf );
70 /******************************************************************
71 * EMF_GetEnhMetaHeader
73 * Returns ptr to ENHMETAHEADER associated with HENHMETAFILE
74 * Should be followed by call to EMF_ReleaseEnhMetaHeader
76 static ENHMETAHEADER *EMF_GetEnhMetaHeader( HENHMETAFILE hmf )
78 ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf,
79 ENHMETAFILE_MAGIC );
80 TRACE("hmf %04x -> enhmetaObj %p\n", hmf, metaObj);
81 return metaObj ? metaObj->emh : NULL;
84 /******************************************************************
85 * EMF_ReleaseEnhMetaHeader
87 * Releases ENHMETAHEADER associated with HENHMETAFILE
89 static BOOL EMF_ReleaseEnhMetaHeader( HENHMETAFILE hmf )
91 return GDI_HEAP_UNLOCK( hmf );
94 /*****************************************************************************
95 * EMF_GetEnhMetaFile
98 static HENHMETAFILE EMF_GetEnhMetaFile( HFILE hFile )
100 ENHMETAHEADER *emh;
101 HANDLE hMapping;
103 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
104 emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
106 if (emh->iType != EMR_HEADER || emh->dSignature != ENHMETA_SIGNATURE) {
107 WARN("Invalid emf header type 0x%08lx sig 0x%08lx.\n",
108 emh->iType, emh->dSignature);
109 UnmapViewOfFile( emh );
110 CloseHandle( hMapping );
111 return 0;
113 return EMF_Create_HENHMETAFILE( emh, hFile, hMapping );
117 /*****************************************************************************
118 * GetEnhMetaFileA (GDI32.174)
122 HENHMETAFILE WINAPI GetEnhMetaFileA(
123 LPCSTR lpszMetaFile /* filename of enhanced metafile */
126 HENHMETAFILE hmf;
127 HFILE hFile;
129 hFile = CreateFileA(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0,
130 OPEN_EXISTING, 0, 0);
131 if (hFile == INVALID_HANDLE_VALUE) {
132 WARN("could not open %s\n", lpszMetaFile);
133 return 0;
135 hmf = EMF_GetEnhMetaFile( hFile );
136 if(!hmf)
137 CloseHandle( hFile );
138 return hmf;
141 /*****************************************************************************
142 * GetEnhMetaFile32W (GDI32.180)
144 HENHMETAFILE WINAPI GetEnhMetaFileW(
145 LPCWSTR lpszMetaFile) /* filename of enhanced metafile */
147 HENHMETAFILE hmf;
148 HFILE hFile;
150 hFile = CreateFileW(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0,
151 OPEN_EXISTING, 0, 0);
152 if (hFile == INVALID_HANDLE_VALUE) {
153 WARN("could not open %s\n", debugstr_w(lpszMetaFile));
154 return 0;
156 hmf = EMF_GetEnhMetaFile( hFile );
157 if(!hmf)
158 CloseHandle( hFile );
159 return hmf;
162 /*****************************************************************************
163 * GetEnhMetaFileHeader (GDI32.178)
165 * If _buf_ is NULL, returns the size of buffer required.
166 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
167 * _buf.
169 UINT WINAPI GetEnhMetaFileHeader(
170 HENHMETAFILE hmf, /* enhanced metafile */
171 UINT bufsize, /* size of buffer */
172 LPENHMETAHEADER buf /* buffer */
175 LPENHMETAHEADER emh;
177 if (!buf) return sizeof(ENHMETAHEADER);
178 emh = EMF_GetEnhMetaHeader(hmf);
179 if(!emh) return FALSE;
180 memmove(buf, emh, MIN(sizeof(ENHMETAHEADER), bufsize));
181 EMF_ReleaseEnhMetaHeader(hmf);
182 return MIN(sizeof(ENHMETAHEADER), bufsize);
186 /*****************************************************************************
187 * GetEnhMetaFileDescription32A (GDI32.176)
189 UINT WINAPI GetEnhMetaFileDescriptionA(
190 HENHMETAFILE hmf, /* enhanced metafile */
191 UINT size, /* size of buf */
192 LPSTR buf /* buffer to receive description */
195 LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
196 INT first;
198 if(!emh) return FALSE;
199 if(emh->nDescription == 0 || emh->offDescription == 0) {
200 EMF_ReleaseEnhMetaHeader(hmf);
201 return 0;
203 if (!buf || !size ) {
204 EMF_ReleaseEnhMetaHeader(hmf);
205 return emh->nDescription;
208 first = lstrlenW( (WCHAR *) ((char *) emh + emh->offDescription));
210 lstrcpynWtoA(buf, (WCHAR *) ((char *) emh + emh->offDescription), size);
211 buf += first + 1;
212 lstrcpynWtoA(buf, (WCHAR *) ((char *) emh + emh->offDescription+2*(first+1)),
213 size - first - 1);
215 EMF_ReleaseEnhMetaHeader(hmf);
216 return MIN(size, emh->nDescription);
219 /*****************************************************************************
220 * GetEnhMetaFileDescription32W (GDI32.177)
222 * Copies the description string of an enhanced metafile into a buffer
223 * _buf_.
225 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
226 * number of characters copied.
228 UINT WINAPI GetEnhMetaFileDescriptionW(
229 HENHMETAFILE hmf, /* enhanced metafile */
230 UINT size, /* size of buf */
231 LPWSTR buf /* buffer to receive description */
234 LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
236 if(!emh) return FALSE;
237 if(emh->nDescription == 0 || emh->offDescription == 0) {
238 EMF_ReleaseEnhMetaHeader(hmf);
239 return 0;
241 if (!buf || !size ) {
242 EMF_ReleaseEnhMetaHeader(hmf);
243 return emh->nDescription;
246 memmove(buf, (char *) emh + emh->offDescription,
247 MIN(size,emh->nDescription));
248 EMF_ReleaseEnhMetaHeader(hmf);
249 return MIN(size, emh->nDescription);
252 /****************************************************************************
253 * SetEnhMetaFileBits (GDI32.315)
255 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
257 HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf)
259 ENHMETAHEADER *emh = HeapAlloc( GetProcessHeap(), 0, bufsize );
260 memmove(emh, buf, bufsize);
261 return EMF_Create_HENHMETAFILE( emh, 0, 0 );
264 INT CALLBACK cbCountSizeOfEnhMetaFile( HDC a,
265 LPHANDLETABLE b,
266 LPENHMETARECORD lpEMR,
267 INT c,
268 LPVOID lpData )
270 LPUINT uSizeOfRecordData = (LPUINT)lpData;
272 *uSizeOfRecordData += lpEMR->nSize;
274 return TRUE;
277 /*****************************************************************************
278 * GetEnhMetaFileBits (GDI32.175)
281 UINT WINAPI GetEnhMetaFileBits(
282 HENHMETAFILE hmf,
283 UINT bufsize,
284 LPBYTE buf
287 LPENHMETAHEADER lpEnhMetaFile;
288 UINT uEnhMetaFileSize = 0;
290 FIXME( "(%04x,%u,%p): untested\n", hmf, bufsize, buf );
292 /* Determine the required buffer size */
293 /* Enumerate all records and count their size */
294 if( !EnumEnhMetaFile( 0, hmf, cbCountSizeOfEnhMetaFile, &uEnhMetaFileSize, NULL ) )
296 ERR( "Unable to enumerate enhanced metafile!\n" );
297 return 0;
300 if( buf == NULL )
302 return uEnhMetaFileSize;
305 /* Copy the lesser of the two byte counts */
306 uEnhMetaFileSize = MIN( uEnhMetaFileSize, bufsize );
308 /* Copy everything */
309 lpEnhMetaFile = EMF_GetEnhMetaHeader( hmf );
311 if( lpEnhMetaFile == NULL )
313 return 0;
316 /* Use memmove just in case they overlap */
317 memmove(buf, lpEnhMetaFile, bufsize);
319 EMF_ReleaseEnhMetaHeader( hmf );
321 return bufsize;
324 /*****************************************************************************
325 * PlayEnhMetaFileRecord (GDI32.264)
327 * Render a single enhanced metafile record in the device context hdc.
329 * RETURNS
330 * TRUE (non zero) on success, FALSE on error.
331 * BUGS
332 * Many unimplemented records.
333 * No error handling on record play failures (ie checking return codes)
335 BOOL WINAPI PlayEnhMetaFileRecord(
336 HDC hdc, /* device context in which to render EMF record */
337 LPHANDLETABLE handletable, /* array of handles to be used in rendering record */
338 const ENHMETARECORD *mr, /* EMF record to render */
339 UINT handles /* size of handle array */
342 int type;
343 TRACE(
344 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
345 hdc, handletable, mr, handles);
346 if (!mr) return FALSE;
348 type = mr->iType;
350 TRACE(" type=%d\n", type);
351 switch(type)
353 case EMR_HEADER:
355 #if 0
356 ENHMETAHEADER* h = (LPENHMETAHEADER)mr;
357 XFORM dcTransform;
359 /* Scale the enhanced metafile according to the reference hdc
360 it was created with */
361 if( h->szlDevice.cx )
363 dcTransform.eM11 = (FLOAT)( (DOUBLE)GetDeviceCaps( hdc, HORZRES ) /
364 (DOUBLE)h->szlDevice.cx );
366 else
368 ERR( "Invalid szlDevice.cx in header\n" );
369 dcTransform.eM11 = (FLOAT)1.0;
372 if( h->szlDevice.cy )
374 dcTransform.eM22 = (FLOAT)( (DOUBLE)GetDeviceCaps( hdc, VERTRES ) /
375 (DOUBLE)h->szlDevice.cy );
377 else
379 ERR( "Invalid szlDevice.cy in header\n" );
380 dcTransform.eM22 = (FLOAT)1.0;
383 dcTransform.eM12 = dcTransform.eM21 = (FLOAT)0;
384 dcTransform.eDx = dcTransform.eDy = (FLOAT)0;
386 ModifyWorldTransform( hdc, &dcTransform, MWT_RIGHTMULTIPLY );
387 #endif
388 break;
390 case EMR_EOF:
391 break;
392 case EMR_GDICOMMENT:
394 PEMRGDICOMMENT lpGdiComment = (PEMRGDICOMMENT)mr;
395 /* In an enhanced metafile, there can be both public and private GDI comments */
396 GdiComment( hdc, lpGdiComment->cbData, lpGdiComment->Data );
397 break;
399 case EMR_SETMAPMODE:
401 DWORD mode = mr->dParm[0];
402 SetMapMode(hdc, mode);
403 break;
405 case EMR_SETBKMODE:
407 DWORD mode = mr->dParm[0];
408 SetBkMode(hdc, mode);
409 break;
411 case EMR_SETBKCOLOR:
413 DWORD mode = mr->dParm[0];
414 SetBkColor(hdc, mode);
415 break;
417 case EMR_SETPOLYFILLMODE:
419 DWORD mode = mr->dParm[0];
420 SetPolyFillMode(hdc, mode);
421 break;
423 case EMR_SETROP2:
425 DWORD mode = mr->dParm[0];
426 SetROP2(hdc, mode);
427 break;
429 case EMR_SETSTRETCHBLTMODE:
431 DWORD mode = mr->dParm[0];
432 SetStretchBltMode(hdc, mode);
433 break;
435 case EMR_SETTEXTALIGN:
437 DWORD align = mr->dParm[0];
438 SetTextAlign(hdc, align);
439 break;
441 case EMR_SETTEXTCOLOR:
443 DWORD color = mr->dParm[0];
444 SetTextColor(hdc, color);
445 break;
447 case EMR_SAVEDC:
449 SaveDC(hdc);
450 break;
452 case EMR_RESTOREDC:
454 RestoreDC(hdc, mr->dParm[0]);
455 break;
457 case EMR_INTERSECTCLIPRECT:
459 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
460 bottom = mr->dParm[3];
461 IntersectClipRect(hdc, left, top, right, bottom);
462 break;
464 case EMR_SELECTOBJECT:
466 DWORD obj = mr->dParm[0];
467 SelectObject(hdc, (handletable->objectHandle)[obj]);
468 break;
470 case EMR_DELETEOBJECT:
472 DWORD obj = mr->dParm[0];
473 DeleteObject( (handletable->objectHandle)[obj]);
474 (handletable->objectHandle)[obj] = 0;
475 break;
477 case EMR_SETWINDOWORGEX:
479 DWORD x = mr->dParm[0], y = mr->dParm[1];
480 SetWindowOrgEx(hdc, x, y, NULL);
481 break;
483 case EMR_SETWINDOWEXTEX:
485 DWORD x = mr->dParm[0], y = mr->dParm[1];
486 SetWindowExtEx(hdc, x, y, NULL);
487 break;
489 case EMR_SETVIEWPORTORGEX:
491 DWORD x = mr->dParm[0], y = mr->dParm[1];
492 SetViewportOrgEx(hdc, x, y, NULL);
493 break;
495 case EMR_SETVIEWPORTEXTEX:
497 DWORD x = mr->dParm[0], y = mr->dParm[1];
498 SetViewportExtEx(hdc, x, y, NULL);
499 break;
501 case EMR_CREATEPEN:
503 DWORD obj = mr->dParm[0];
504 (handletable->objectHandle)[obj] =
505 CreatePenIndirect((LOGPEN *) &(mr->dParm[1]));
506 break;
508 case EMR_EXTCREATEPEN:
510 DWORD obj = mr->dParm[0];
511 DWORD style = mr->dParm[1], brush = mr->dParm[2];
512 LOGBRUSH *b = (LOGBRUSH *) &mr->dParm[3];
513 FIXME("Some ExtCreatePen args not handled\n");
514 (handletable->objectHandle)[obj] =
515 ExtCreatePen(style, brush, b, 0, NULL);
516 break;
518 case EMR_CREATEBRUSHINDIRECT:
520 DWORD obj = mr->dParm[0];
521 (handletable->objectHandle)[obj] =
522 CreateBrushIndirect((LOGBRUSH *) &(mr->dParm[1]));
523 break;
525 case EMR_EXTCREATEFONTINDIRECTW:
527 DWORD obj = mr->dParm[0];
528 (handletable->objectHandle)[obj] =
529 CreateFontIndirectW((LOGFONTW *) &(mr->dParm[1]));
530 break;
532 case EMR_MOVETOEX:
534 DWORD x = mr->dParm[0], y = mr->dParm[1];
535 MoveToEx(hdc, x, y, NULL);
536 break;
538 case EMR_LINETO:
540 DWORD x = mr->dParm[0], y = mr->dParm[1];
541 LineTo(hdc, x, y);
542 break;
544 case EMR_RECTANGLE:
546 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
547 bottom = mr->dParm[3];
548 Rectangle(hdc, left, top, right, bottom);
549 break;
551 case EMR_ELLIPSE:
553 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
554 bottom = mr->dParm[3];
555 Ellipse(hdc, left, top, right, bottom);
556 break;
558 case EMR_POLYGON16:
560 /* 0-3 : a bounding rectangle? */
561 INT count = mr->dParm[4];
562 FIXME("Some Polygon16 args not handled\n");
563 Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
564 break;
566 case EMR_POLYLINE16:
568 /* 0-3 : a bounding rectangle? */
569 INT count = mr->dParm[4];
570 FIXME("Some Polyline16 args not handled\n");
571 Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
572 break;
574 #if 0
575 case EMR_POLYPOLYGON16:
577 PEMRPOLYPOLYGON16 lpPolyPoly16 = (PEMRPOLYPOLYGON16)mr;
579 PolyPolygon16( hdc,
580 lpPolyPoly16->apts,
581 lpPolyPoly16->aPolyCounts,
582 lpPolyPoly16->nPolys );
584 break;
586 #endif
587 case EMR_STRETCHDIBITS:
589 LONG xDest = mr->dParm[4];
590 LONG yDest = mr->dParm[5];
591 LONG xSrc = mr->dParm[6];
592 LONG ySrc = mr->dParm[7];
593 LONG cxSrc = mr->dParm[8];
594 LONG cySrc = mr->dParm[9];
595 DWORD offBmiSrc = mr->dParm[10];
596 DWORD offBitsSrc = mr->dParm[12];
597 DWORD iUsageSrc = mr->dParm[14];
598 DWORD dwRop = mr->dParm[15];
599 LONG cxDest = mr->dParm[16];
600 LONG cyDest = mr->dParm[17];
602 StretchDIBits(hdc,xDest,yDest,cxDest,cyDest,
603 xSrc,ySrc,cxSrc,cySrc,
604 ((char *)mr)+offBitsSrc,
605 (const BITMAPINFO *)(((char *)mr)+offBmiSrc),
606 iUsageSrc,dwRop);
607 break;
609 case EMR_EXTTEXTOUTW:
611 /* 0-3: ??? */
612 DWORD flags = mr->dParm[4];
613 /* 5, 6: ??? */
614 DWORD x = mr->dParm[7], y = mr->dParm[8];
615 DWORD count = mr->dParm[9];
616 /* 10-16: ??? */
617 LPWSTR str = (LPWSTR)& mr->dParm[17];
618 /* trailing info: dx array? */
619 FIXME("Many ExtTextOut args not handled\n");
620 ExtTextOutW(hdc, x, y, flags, /* lpRect */ NULL,
621 str, count, /* lpDx */ NULL);
622 break;
625 case EMR_CREATEPALETTE:
627 PEMRCREATEPALETTE lpCreatePal = (PEMRCREATEPALETTE)mr;
629 (handletable->objectHandle)[ lpCreatePal->ihPal ] =
630 CreatePalette( &lpCreatePal->lgpl );
632 break;
635 case EMR_SELECTPALETTE:
637 PEMRSELECTPALETTE lpSelectPal = (PEMRSELECTPALETTE)mr;
639 /* FIXME: Should this be forcing background mode? */
640 (handletable->objectHandle)[ lpSelectPal->ihPal ] =
641 SelectPalette( hdc, lpSelectPal->ihPal, FALSE );
642 break;
645 case EMR_REALIZEPALETTE:
647 RealizePalette( hdc );
648 break;
651 #if 0
652 case EMR_EXTSELECTCLIPRGN:
654 PEMREXTSELECTCLIPRGN lpRgn = (PEMREXTSELECTCLIPRGN)mr;
656 /* Need to make a region out of the RGNDATA we have */
657 ExtSelectClipRgn( hdc, ..., (INT)(lpRgn->iMode) );
660 #endif
662 case EMR_SETMETARGN:
664 SetMetaRgn( hdc );
665 break;
668 case EMR_SETWORLDTRANSFORM:
670 PEMRSETWORLDTRANSFORM lpXfrm = (PEMRSETWORLDTRANSFORM)mr;
672 SetWorldTransform( hdc, &lpXfrm->xform );
674 break;
677 case EMR_POLYBEZIER:
679 PEMRPOLYBEZIER lpPolyBez = (PEMRPOLYBEZIER)mr;
681 FIXME( "Bounding rectangle ignored for EMR_POLYBEZIER\n" );
682 PolyBezier( hdc, (const LPPOINT)lpPolyBez->aptl, (UINT)lpPolyBez->cptl );
684 break;
687 case EMR_POLYGON:
689 PEMRPOLYGON lpPoly = (PEMRPOLYGON)mr;
691 FIXME( "Bounding rectangle ignored for EMR_POLYGON\n" );
692 Polygon( hdc, (const LPPOINT)lpPoly->aptl, (UINT)lpPoly->cptl );
694 break;
697 case EMR_POLYLINE:
699 PEMRPOLYLINE lpPolyLine = (PEMRPOLYLINE)mr;
701 FIXME( "Bounding rectangle ignored for EMR_POLYLINE\n" );
702 Polyline( hdc, (const LPPOINT)lpPolyLine->aptl, (UINT)lpPolyLine->cptl );
704 break;
707 case EMR_POLYBEZIERTO:
709 PEMRPOLYBEZIERTO lpPolyBezierTo = (PEMRPOLYBEZIERTO)mr;
711 FIXME( "Bounding rectangle ignored for EMR_POLYBEZIERTO\n" );
712 PolyBezierTo( hdc, (const LPPOINT)lpPolyBezierTo->aptl, (UINT)lpPolyBezierTo->cptl );
714 break;
717 case EMR_POLYLINETO:
719 PEMRPOLYLINETO lpPolyLineTo = (PEMRPOLYLINETO)mr;
721 FIXME( "Bounding rectangle ignored for EMR_POLYLINETO\n" );
722 PolylineTo( hdc, (const LPPOINT)lpPolyLineTo->aptl, (UINT)lpPolyLineTo->cptl );
724 break;
727 case EMR_POLYPOLYLINE:
729 PEMRPOLYPOLYLINE lpPolyPolyLine = (PEMRPOLYPOLYLINE)mr;
731 FIXME( "Bounding rectangle ignored for EMR_POLYPOLYLINE\n" );
732 PolyPolyline( hdc,
733 (const LPPOINT)lpPolyPolyLine->aptl,
734 lpPolyPolyLine->aPolyCounts,
735 lpPolyPolyLine->nPolys );
737 break;
740 case EMR_POLYPOLYGON:
742 PEMRPOLYPOLYGON lpPolyPolygon = (PEMRPOLYPOLYGON)mr;
743 INT* lpPolyCounts;
744 UINT i;
746 /* We get the polygon point counts in a dword struct. Transform
747 this into an INT struct */
748 lpPolyCounts = (INT*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
749 sizeof(INT)*lpPolyPolygon->cptl );
751 for( i=0; i<lpPolyPolygon->cptl; i++ )
753 lpPolyCounts[i] = (INT)lpPolyPolygon->aPolyCounts[i];
756 FIXME( "Bounding rectangle ignored for EMR_POLYPOLYGON\n" );
757 PolyPolygon( hdc, (const LPPOINT)lpPolyPolygon->aptl,
758 lpPolyCounts, lpPolyPolygon->nPolys );
760 HeapFree( GetProcessHeap(), 0, lpPolyCounts );
762 break;
765 case EMR_SETBRUSHORGEX:
767 PEMRSETBRUSHORGEX lpSetBrushOrgEx = (PEMRSETBRUSHORGEX)mr;
769 SetBrushOrgEx( hdc,
770 (INT)lpSetBrushOrgEx->ptlOrigin.x,
771 (INT)lpSetBrushOrgEx->ptlOrigin.y,
772 NULL );
774 break;
777 case EMR_SETPIXELV:
779 PEMRSETPIXELV lpSetPixelV = (PEMRSETPIXELV)mr;
781 SetPixelV( hdc,
782 (INT)lpSetPixelV->ptlPixel.x,
783 (INT)lpSetPixelV->ptlPixel.y,
784 lpSetPixelV->crColor );
786 break;
789 case EMR_SETMAPPERFLAGS:
791 PEMRSETMAPPERFLAGS lpSetMapperFlags = (PEMRSETMAPPERFLAGS)mr;
793 SetMapperFlags( hdc, lpSetMapperFlags->dwFlags );
795 break;
798 case EMR_SETCOLORADJUSTMENT:
800 PEMRSETCOLORADJUSTMENT lpSetColorAdjust = (PEMRSETCOLORADJUSTMENT)mr;
802 SetColorAdjustment( hdc, &lpSetColorAdjust->ColorAdjustment );
804 break;
807 case EMR_OFFSETCLIPRGN:
809 PEMROFFSETCLIPRGN lpOffsetClipRgn = (PEMROFFSETCLIPRGN)mr;
811 OffsetClipRgn( hdc,
812 (INT)lpOffsetClipRgn->ptlOffset.x,
813 (INT)lpOffsetClipRgn->ptlOffset.y );
815 break;
818 case EMR_EXCLUDECLIPRECT:
820 PEMREXCLUDECLIPRECT lpExcludeClipRect = (PEMREXCLUDECLIPRECT)mr;
822 ExcludeClipRect( hdc,
823 lpExcludeClipRect->rclClip.left,
824 lpExcludeClipRect->rclClip.top,
825 lpExcludeClipRect->rclClip.right,
826 lpExcludeClipRect->rclClip.bottom );
828 break;
831 case EMR_SCALEVIEWPORTEXTEX:
833 PEMRSCALEVIEWPORTEXTEX lpScaleViewportExtEx = (PEMRSCALEVIEWPORTEXTEX)mr;
835 ScaleViewportExtEx( hdc,
836 lpScaleViewportExtEx->xNum,
837 lpScaleViewportExtEx->xDenom,
838 lpScaleViewportExtEx->yNum,
839 lpScaleViewportExtEx->yDenom,
840 NULL );
842 break;
845 case EMR_SCALEWINDOWEXTEX:
847 PEMRSCALEWINDOWEXTEX lpScaleWindowExtEx = (PEMRSCALEWINDOWEXTEX)mr;
849 ScaleWindowExtEx( hdc,
850 lpScaleWindowExtEx->xNum,
851 lpScaleWindowExtEx->xDenom,
852 lpScaleWindowExtEx->yNum,
853 lpScaleWindowExtEx->yDenom,
854 NULL );
856 break;
859 case EMR_MODIFYWORLDTRANSFORM:
861 PEMRMODIFYWORLDTRANSFORM lpModifyWorldTrans = (PEMRMODIFYWORLDTRANSFORM)mr;
863 ModifyWorldTransform( hdc, &lpModifyWorldTrans->xform,
864 lpModifyWorldTrans->iMode );
866 break;
869 case EMR_ANGLEARC:
871 PEMRANGLEARC lpAngleArc = (PEMRANGLEARC)mr;
873 AngleArc( hdc,
874 (INT)lpAngleArc->ptlCenter.x, (INT)lpAngleArc->ptlCenter.y,
875 lpAngleArc->nRadius, lpAngleArc->eStartAngle,
876 lpAngleArc->eSweepAngle );
878 break;
881 case EMR_ROUNDRECT:
883 PEMRROUNDRECT lpRoundRect = (PEMRROUNDRECT)mr;
885 RoundRect( hdc,
886 lpRoundRect->rclBox.left,
887 lpRoundRect->rclBox.top,
888 lpRoundRect->rclBox.right,
889 lpRoundRect->rclBox.bottom,
890 lpRoundRect->szlCorner.cx,
891 lpRoundRect->szlCorner.cy );
893 break;
896 case EMR_ARC:
898 PEMRARC lpArc = (PEMRARC)mr;
900 Arc( hdc,
901 (INT)lpArc->rclBox.left,
902 (INT)lpArc->rclBox.top,
903 (INT)lpArc->rclBox.right,
904 (INT)lpArc->rclBox.bottom,
905 (INT)lpArc->ptlStart.x,
906 (INT)lpArc->ptlStart.y,
907 (INT)lpArc->ptlEnd.x,
908 (INT)lpArc->ptlEnd.y );
910 break;
913 case EMR_CHORD:
915 PEMRCHORD lpChord = (PEMRCHORD)mr;
917 Chord( hdc,
918 (INT)lpChord->rclBox.left,
919 (INT)lpChord->rclBox.top,
920 (INT)lpChord->rclBox.right,
921 (INT)lpChord->rclBox.bottom,
922 (INT)lpChord->ptlStart.x,
923 (INT)lpChord->ptlStart.y,
924 (INT)lpChord->ptlEnd.x,
925 (INT)lpChord->ptlEnd.y );
927 break;
930 case EMR_PIE:
932 PEMRPIE lpPie = (PEMRPIE)mr;
934 Pie( hdc,
935 (INT)lpPie->rclBox.left,
936 (INT)lpPie->rclBox.top,
937 (INT)lpPie->rclBox.right,
938 (INT)lpPie->rclBox.bottom,
939 (INT)lpPie->ptlStart.x,
940 (INT)lpPie->ptlStart.y,
941 (INT)lpPie->ptlEnd.x,
942 (INT)lpPie->ptlEnd.y );
944 break;
947 case EMR_ARCTO:
949 PEMRARC lpArcTo = (PEMRARC)mr;
951 ArcTo( hdc,
952 (INT)lpArcTo->rclBox.left,
953 (INT)lpArcTo->rclBox.top,
954 (INT)lpArcTo->rclBox.right,
955 (INT)lpArcTo->rclBox.bottom,
956 (INT)lpArcTo->ptlStart.x,
957 (INT)lpArcTo->ptlStart.y,
958 (INT)lpArcTo->ptlEnd.x,
959 (INT)lpArcTo->ptlEnd.y );
961 break;
964 case EMR_EXTFLOODFILL:
966 PEMREXTFLOODFILL lpExtFloodFill = (PEMREXTFLOODFILL)mr;
968 ExtFloodFill( hdc,
969 (INT)lpExtFloodFill->ptlStart.x,
970 (INT)lpExtFloodFill->ptlStart.y,
971 lpExtFloodFill->crColor,
972 (UINT)lpExtFloodFill->iMode );
974 break;
977 case EMR_POLYDRAW:
979 PEMRPOLYDRAW lpPolyDraw = (PEMRPOLYDRAW)mr;
981 FIXME( "Bounding rectangle ignored for EMR_POLYDRAW\n" );
982 PolyDraw( hdc,
983 (const LPPOINT)lpPolyDraw->aptl,
984 lpPolyDraw->abTypes,
985 (INT)lpPolyDraw->cptl );
987 break;
990 case EMR_SETARCDIRECTION:
992 PEMRSETARCDIRECTION lpSetArcDirection = (PEMRSETARCDIRECTION)mr;
994 SetArcDirection( hdc, (INT)lpSetArcDirection->iArcDirection );
996 break;
999 case EMR_SETMITERLIMIT:
1001 PEMRSETMITERLIMIT lpSetMiterLimit = (PEMRSETMITERLIMIT)mr;
1003 SetMiterLimit( hdc, lpSetMiterLimit->eMiterLimit, NULL );
1005 break;
1008 case EMR_BEGINPATH:
1010 BeginPath( hdc );
1011 break;
1014 case EMR_ENDPATH:
1016 EndPath( hdc );
1017 break;
1020 case EMR_CLOSEFIGURE:
1022 CloseFigure( hdc );
1023 break;
1026 case EMR_FILLPATH:
1028 /*PEMRFILLPATH lpFillPath = (PEMRFILLPATH)mr;*/
1030 FIXME( "Bounding rectangle ignored for EMR_FILLPATH\n" );
1031 FillPath( hdc );
1033 break;
1036 case EMR_STROKEANDFILLPATH:
1038 /*PEMRSTROKEANDFILLPATH lpStrokeAndFillPath = (PEMRSTROKEANDFILLPATH)mr;*/
1040 FIXME( "Bounding rectangle ignored for EMR_STROKEANDFILLPATH\n" );
1041 StrokeAndFillPath( hdc );
1043 break;
1046 case EMR_STROKEPATH:
1048 /*PEMRSTROKEPATH lpStrokePath = (PEMRSTROKEPATH)mr;*/
1050 FIXME( "Bounding rectangle ignored for EMR_STROKEPATH\n" );
1051 StrokePath( hdc );
1053 break;
1056 case EMR_FLATTENPATH:
1058 FlattenPath( hdc );
1059 break;
1062 case EMR_WIDENPATH:
1064 WidenPath( hdc );
1065 break;
1068 case EMR_SELECTCLIPPATH:
1070 PEMRSELECTCLIPPATH lpSelectClipPath = (PEMRSELECTCLIPPATH)mr;
1072 SelectClipPath( hdc, (INT)lpSelectClipPath->iMode );
1074 break;
1077 case EMR_ABORTPATH:
1079 AbortPath( hdc );
1080 break;
1083 case EMR_CREATECOLORSPACE:
1085 PEMRCREATECOLORSPACE lpCreateColorSpace = (PEMRCREATECOLORSPACE)mr;
1087 (handletable->objectHandle)[lpCreateColorSpace->ihCS] =
1088 CreateColorSpaceA( &lpCreateColorSpace->lcs );
1090 break;
1093 case EMR_SETCOLORSPACE:
1095 PEMRSETCOLORSPACE lpSetColorSpace = (PEMRSETCOLORSPACE)mr;
1097 SetColorSpace( hdc,
1098 (handletable->objectHandle)[lpSetColorSpace->ihCS] );
1100 break;
1103 case EMR_DELETECOLORSPACE:
1105 PEMRDELETECOLORSPACE lpDeleteColorSpace = (PEMRDELETECOLORSPACE)mr;
1107 DeleteColorSpace( (handletable->objectHandle)[lpDeleteColorSpace->ihCS] );
1109 break;
1112 case EMR_SETICMMODE:
1114 PERMSETICMMODE lpSetICMMode = (PERMSETICMMODE)mr;
1116 SetICMMode( hdc,
1117 (INT)lpSetICMMode->iMode );
1119 break;
1122 case EMR_PIXELFORMAT:
1124 INT iPixelFormat;
1125 PEMRPIXELFORMAT lpPixelFormat = (PEMRPIXELFORMAT)mr;
1127 iPixelFormat = ChoosePixelFormat( hdc, &lpPixelFormat->pfd );
1128 SetPixelFormat( hdc, iPixelFormat, &lpPixelFormat->pfd );
1130 break;
1133 case EMR_SETPALETTEENTRIES:
1135 PEMRSETPALETTEENTRIES lpSetPaletteEntries = (PEMRSETPALETTEENTRIES)mr;
1137 SetPaletteEntries( (handletable->objectHandle)[lpSetPaletteEntries->ihPal],
1138 (UINT)lpSetPaletteEntries->iStart,
1139 (UINT)lpSetPaletteEntries->cEntries,
1140 lpSetPaletteEntries->aPalEntries );
1142 break;
1145 case EMR_RESIZEPALETTE:
1147 PEMRRESIZEPALETTE lpResizePalette = (PEMRRESIZEPALETTE)mr;
1149 ResizePalette( (handletable->objectHandle)[lpResizePalette->ihPal],
1150 (UINT)lpResizePalette->cEntries );
1152 break;
1155 case EMR_CREATEDIBPATTERNBRUSHPT:
1157 PEMRCREATEDIBPATTERNBRUSHPT lpCreate = (PEMRCREATEDIBPATTERNBRUSHPT)mr;
1159 /* This is a BITMAPINFO struct followed directly by bitmap bits */
1160 LPVOID lpPackedStruct = HeapAlloc( GetProcessHeap(),
1162 lpCreate->cbBmi + lpCreate->cbBits );
1163 /* Now pack this structure */
1164 memcpy( lpPackedStruct,
1165 ((BYTE*)lpCreate) + lpCreate->offBmi,
1166 lpCreate->cbBmi );
1167 memcpy( ((BYTE*)lpPackedStruct) + lpCreate->cbBmi,
1168 ((BYTE*)lpCreate) + lpCreate->offBits,
1169 lpCreate->cbBits );
1171 (handletable->objectHandle)[lpCreate->ihBrush] =
1172 CreateDIBPatternBrushPt( lpPackedStruct,
1173 (UINT)lpCreate->iUsage );
1175 break;
1178 case EMR_BITBLT:
1179 case EMR_STRETCHBLT:
1180 case EMR_MASKBLT:
1181 case EMR_PLGBLT:
1182 case EMR_SETDIBITSTODEVICE:
1183 case EMR_EXTTEXTOUTA:
1184 case EMR_POLYBEZIER16:
1185 case EMR_POLYBEZIERTO16:
1186 case EMR_POLYLINETO16:
1187 case EMR_POLYPOLYLINE16:
1188 case EMR_POLYPOLYGON16:
1189 case EMR_POLYDRAW16:
1190 case EMR_CREATEMONOBRUSH:
1191 case EMR_POLYTEXTOUTA:
1192 case EMR_POLYTEXTOUTW:
1193 case EMR_FILLRGN:
1194 case EMR_FRAMERGN:
1195 case EMR_INVERTRGN:
1196 case EMR_PAINTRGN:
1197 case EMR_GLSRECORD:
1198 case EMR_GLSBOUNDEDRECORD:
1199 default:
1200 /* From docs: If PlayEnhMetaFileRecord doesn't recognize a
1201 record then ignore and return TRUE. */
1202 FIXME("type %d is unimplemented\n", type);
1203 break;
1205 return TRUE;
1209 /*****************************************************************************
1211 * EnumEnhMetaFile32 (GDI32.79)
1213 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
1214 * for each
1215 * record. Returns when either every record has been used or
1216 * when _EnhMetaFunc_ returns FALSE.
1219 * RETURNS
1220 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
1221 * returns FALSE.
1223 * BUGS
1224 * Ignores rect.
1226 BOOL WINAPI EnumEnhMetaFile(
1227 HDC hdc, /* device context to pass to _EnhMetaFunc_ */
1228 HENHMETAFILE hmf, /* EMF to walk */
1229 ENHMFENUMPROC callback, /* callback function */
1230 LPVOID data, /* optional data for callback function */
1231 const RECT *rect /* bounding rectangle for rendered metafile */
1234 BOOL ret = TRUE;
1235 LPENHMETARECORD p = (LPENHMETARECORD) EMF_GetEnhMetaHeader(hmf);
1236 INT count;
1237 HANDLETABLE *ht;
1239 if(!p) return FALSE;
1240 count = ((LPENHMETAHEADER) p)->nHandles;
1241 ht = HeapAlloc( GetProcessHeap(), 0, sizeof(HANDLETABLE)*count);
1242 ht->objectHandle[0] = hmf;
1243 while (ret) {
1244 ret = (*callback)(hdc, ht, p, count, data);
1245 if (p->iType == EMR_EOF) break;
1246 p = (LPENHMETARECORD) ((char *) p + p->nSize);
1248 HeapFree( GetProcessHeap(), 0, ht);
1249 EMF_ReleaseEnhMetaHeader(hmf);
1250 return ret;
1254 /**************************************************************************
1255 * PlayEnhMetaFile (GDI32.263)
1257 * Renders an enhanced metafile into a specified rectangle *lpRect
1258 * in device context hdc.
1260 * BUGS
1261 * Almost entirely unimplemented
1264 BOOL WINAPI PlayEnhMetaFile(
1265 HDC hdc, /* DC to render into */
1266 HENHMETAFILE hmf, /* metafile to render */
1267 const RECT *lpRect /* rectangle to place metafile inside */
1270 LPENHMETARECORD p = (LPENHMETARECORD) EMF_GetEnhMetaHeader(hmf);
1271 INT count;
1272 HANDLETABLE *ht;
1273 BOOL ret = FALSE;
1274 INT savedMode = 0;
1276 if(!p) return FALSE;
1277 count = ((LPENHMETAHEADER) p)->nHandles;
1278 ht = HeapAlloc( GetProcessHeap(), 0, sizeof(HANDLETABLE) * count);
1279 if (lpRect) {
1280 LPENHMETAHEADER h = (LPENHMETAHEADER) p;
1281 FLOAT xscale = (h->rclBounds.right - h->rclBounds.left) /
1282 (lpRect->right - lpRect->left);
1283 FLOAT yscale = (h->rclBounds.bottom - h->rclBounds.top) /
1284 (lpRect->bottom - lpRect->top);
1285 XFORM xform;
1286 xform.eM11 = xscale;
1287 xform.eM12 = 0;
1288 xform.eM21 = 0;
1289 xform.eM22 = yscale;
1290 xform.eDx = lpRect->left;
1291 xform.eDy = lpRect->top;
1292 FIXME("play into rect doesn't work\n");
1293 savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
1294 if (!SetWorldTransform(hdc, &xform)) {
1295 WARN("World transform failed!\n");
1299 ht->objectHandle[0] = hmf;
1300 while (1) {
1301 PlayEnhMetaFileRecord(hdc, ht, p, count);
1302 if (p->iType == EMR_EOF) break;
1303 p = (LPENHMETARECORD) ((char *) p + p->nSize); /* casted so that arithmetic is in bytes */
1305 HeapFree( GetProcessHeap(), 0, ht );
1306 EMF_ReleaseEnhMetaHeader(hmf);
1307 if (savedMode) SetGraphicsMode(hdc, savedMode);
1308 ret = TRUE; /* FIXME: calculate a more accurate return value */
1309 return ret;
1312 /*****************************************************************************
1313 * DeleteEnhMetaFile (GDI32.68)
1315 * Deletes an enhanced metafile and frees the associated storage.
1317 BOOL WINAPI DeleteEnhMetaFile(HENHMETAFILE hmf)
1319 return EMF_Delete_HENHMETAFILE( hmf );
1322 /*****************************************************************************
1323 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
1327 HENHMETAFILE WINAPI CopyEnhMetaFileA(
1328 HENHMETAFILE hmfSrc,
1329 LPCSTR file)
1331 ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst;
1332 HENHMETAFILE hmfDst;
1334 if(!emrSrc) return FALSE;
1335 if (!file) {
1336 emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes );
1337 memcpy( emrDst, emrSrc, emrSrc->nBytes );
1338 hmfDst = EMF_Create_HENHMETAFILE( emrDst, 0, 0 );
1339 } else {
1340 HFILE hFile;
1341 hFile = CreateFileA( file, GENERIC_WRITE | GENERIC_READ, 0, NULL,
1342 CREATE_ALWAYS, 0, -1);
1343 WriteFile( hFile, emrSrc, emrSrc->nBytes, 0, 0);
1344 hmfDst = EMF_GetEnhMetaFile( hFile );
1346 EMF_ReleaseEnhMetaHeader( hmfSrc );
1347 return hmfDst;
1351 /* Struct to be used to be passed in the LPVOID parameter for cbEnhPaletteCopy */
1352 typedef struct tagEMF_PaletteCopy
1354 UINT cEntries;
1355 LPPALETTEENTRY lpPe;
1356 } EMF_PaletteCopy;
1358 /***************************************************************
1359 * Find the EMR_EOF record and then use it to find the
1360 * palette entries for this enhanced metafile.
1361 * The lpData is actually a pointer to a EMF_PaletteCopy struct
1362 * which contains the max number of elements to copy and where
1363 * to copy them to.
1365 * NOTE: To be used by GetEnhMetaFilePaletteEntries only!
1367 INT CALLBACK cbEnhPaletteCopy( HDC a,
1368 LPHANDLETABLE b,
1369 LPENHMETARECORD lpEMR,
1370 INT c,
1371 LPVOID lpData )
1374 if ( lpEMR->iType == EMR_EOF )
1376 PEMREOF lpEof = (PEMREOF)lpEMR;
1377 EMF_PaletteCopy* info = (EMF_PaletteCopy*)lpData;
1378 DWORD dwNumPalToCopy = MIN( lpEof->nPalEntries, info->cEntries );
1380 TRACE( "copying 0x%08lx palettes\n", dwNumPalToCopy );
1382 memcpy( (LPVOID)info->lpPe,
1383 (LPVOID)(((LPSTR)lpEof) + lpEof->offPalEntries),
1384 sizeof( *(info->lpPe) ) * dwNumPalToCopy );
1386 /* Update the passed data as a return code */
1387 info->lpPe = NULL; /* Palettes were copied! */
1388 info->cEntries = (UINT)dwNumPalToCopy;
1390 return FALSE; /* That's all we need */
1393 return TRUE;
1396 /*****************************************************************************
1397 * GetEnhMetaFilePaletteEntries (GDI32.179)
1399 * Copy the palette and report size
1401 * BUGS: Error codes (SetLastError) are not set on failures
1403 UINT WINAPI GetEnhMetaFilePaletteEntries( HENHMETAFILE hEmf,
1404 UINT cEntries,
1405 LPPALETTEENTRY lpPe )
1407 ENHMETAHEADER* enhHeader = EMF_GetEnhMetaHeader( hEmf );
1408 UINT uReturnValue = GDI_ERROR;
1409 EMF_PaletteCopy infoForCallBack;
1411 TRACE( "(%04x,%d,%p)\n", hEmf, cEntries, lpPe );
1413 /* First check if there are any palettes associated with
1414 this metafile. */
1415 if ( enhHeader->nPalEntries == 0 )
1417 /* No palette associated with this enhanced metafile */
1418 uReturnValue = 0;
1419 goto done;
1422 /* Is the user requesting the number of palettes? */
1423 if ( lpPe == NULL )
1425 uReturnValue = (UINT)enhHeader->nPalEntries;
1426 goto done;
1429 /* Copy cEntries worth of PALETTEENTRY structs into the buffer */
1430 infoForCallBack.cEntries = cEntries;
1431 infoForCallBack.lpPe = lpPe;
1433 if ( !EnumEnhMetaFile( 0, hEmf, cbEnhPaletteCopy,
1434 &infoForCallBack, NULL ) )
1436 goto done;
1439 /* Verify that the callback executed correctly */
1440 if ( infoForCallBack.lpPe != NULL )
1442 /* Callback proc had error! */
1443 ERR( "cbEnhPaletteCopy didn't execute correctly\n" );
1444 goto done;
1447 uReturnValue = infoForCallBack.cEntries;
1449 done:
1451 EMF_ReleaseEnhMetaHeader( hEmf );
1453 return uReturnValue;
1456 /******************************************************************
1457 * SetWinMetaFileBits (GDI32.343)
1459 * Translate from old style to new style.
1461 * BUGS: - This doesn't take the DC and scaling into account
1462 * - Most record conversions aren't implemented
1463 * - Handle slot assignement is primative and most likely doesn't work
1465 HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
1466 CONST BYTE *lpbBuffer,
1467 HDC hdcRef,
1468 CONST METAFILEPICT *lpmfp
1471 HENHMETAFILE hMf;
1472 LPVOID lpNewEnhMetaFileBuffer = NULL;
1473 UINT uNewEnhMetaFileBufferSize = 0;
1474 BOOL bFoundEOF = FALSE;
1476 FIXME( "(%d,%p,%04x,%p):stub\n", cbBuffer, lpbBuffer, hdcRef, lpmfp );
1478 /* 1. Get the header - skip over this and get straight to the records */
1480 uNewEnhMetaFileBufferSize = sizeof( ENHMETAHEADER );
1481 lpNewEnhMetaFileBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1482 uNewEnhMetaFileBufferSize );
1484 if( lpNewEnhMetaFileBuffer == NULL )
1486 goto error;
1489 /* Fill in the header record */
1491 LPENHMETAHEADER lpNewEnhMetaFileHeader = (LPENHMETAHEADER)lpNewEnhMetaFileBuffer;
1493 lpNewEnhMetaFileHeader->iType = EMR_HEADER;
1494 lpNewEnhMetaFileHeader->nSize = sizeof( ENHMETAHEADER );
1496 /* FIXME: Not right. Must be able to get this from the DC */
1497 lpNewEnhMetaFileHeader->rclBounds.left = 0;
1498 lpNewEnhMetaFileHeader->rclBounds.right = 0;
1499 lpNewEnhMetaFileHeader->rclBounds.top = 0;
1500 lpNewEnhMetaFileHeader->rclBounds.bottom = 0;
1502 /* FIXME: Not right. Must be able to get this from the DC */
1503 lpNewEnhMetaFileHeader->rclFrame.left = 0;
1504 lpNewEnhMetaFileHeader->rclFrame.right = 0;
1505 lpNewEnhMetaFileHeader->rclFrame.top = 0;
1506 lpNewEnhMetaFileHeader->rclFrame.bottom = 0;
1508 lpNewEnhMetaFileHeader->nHandles = 0; /* No handles yet */
1510 /* FIXME: Add in the rest of the fields to the header */
1511 /* dSignature
1512 nVersion
1513 nRecords
1514 sReserved
1515 nDescription
1516 offDescription
1517 nPalEntries
1518 szlDevice
1519 szlMillimeters
1520 cbPixelFormat
1521 offPixelFormat,
1522 bOpenGL */
1525 (char*)lpbBuffer += ((METAHEADER*)lpbBuffer)->mtHeaderSize * 2; /* Point past the header - FIXME: metafile quirk? */
1527 /* 2. Enum over individual records and convert them to the new type of records */
1528 while( !bFoundEOF )
1531 LPMETARECORD lpMetaRecord = (LPMETARECORD)lpbBuffer;
1533 #define EMF_ReAllocAndAdjustPointers( a , b ) \
1535 LPVOID lpTmp; \
1536 lpTmp = HeapReAlloc( GetProcessHeap(), 0, \
1537 lpNewEnhMetaFileBuffer, \
1538 uNewEnhMetaFileBufferSize + (b) ); \
1539 if( lpTmp == NULL ) { ERR( "No memory!\n" ); goto error; } \
1540 lpNewEnhMetaFileBuffer = lpTmp; \
1541 lpRecord = (a)( (char*)lpNewEnhMetaFileBuffer + uNewEnhMetaFileBufferSize ); \
1542 uNewEnhMetaFileBufferSize += (b); \
1545 switch( lpMetaRecord->rdFunction )
1547 case META_EOF:
1549 PEMREOF lpRecord;
1550 size_t uRecord = sizeof(*lpRecord);
1552 EMF_ReAllocAndAdjustPointers(PEMREOF,uRecord);
1554 /* Fill the new record - FIXME: This is not right */
1555 lpRecord->emr.iType = EMR_EOF;
1556 lpRecord->emr.nSize = sizeof( *lpRecord );
1557 lpRecord->nPalEntries = 0; /* FIXME */
1558 lpRecord->offPalEntries = 0; /* FIXME */
1559 lpRecord->nSizeLast = 0; /* FIXME */
1561 /* No more records after this one */
1562 bFoundEOF = TRUE;
1564 FIXME( "META_EOF conversion not correct\n" );
1565 break;
1568 case META_SETMAPMODE:
1570 PEMRSETMAPMODE lpRecord;
1571 size_t uRecord = sizeof(*lpRecord);
1573 EMF_ReAllocAndAdjustPointers(PEMRSETMAPMODE,uRecord);
1575 lpRecord->emr.iType = EMR_SETMAPMODE;
1576 lpRecord->emr.nSize = sizeof( *lpRecord );
1578 lpRecord->iMode = lpMetaRecord->rdParm[0];
1580 break;
1583 case META_DELETEOBJECT: /* Select and Delete structures are the same */
1584 case META_SELECTOBJECT:
1586 PEMRDELETEOBJECT lpRecord;
1587 size_t uRecord = sizeof(*lpRecord);
1589 EMF_ReAllocAndAdjustPointers(PEMRDELETEOBJECT,uRecord);
1591 if( lpMetaRecord->rdFunction == META_DELETEOBJECT )
1593 lpRecord->emr.iType = EMR_DELETEOBJECT;
1595 else
1597 lpRecord->emr.iType = EMR_SELECTOBJECT;
1599 lpRecord->emr.nSize = sizeof( *lpRecord );
1601 lpRecord->ihObject = lpMetaRecord->rdParm[0]; /* FIXME: Handle */
1603 break;
1606 case META_POLYGON: /* This is just plain busted. I don't know what I'm doing */
1608 PEMRPOLYGON16 lpRecord; /* FIXME: Should it be a poly or poly16? */
1609 size_t uRecord = sizeof(*lpRecord);
1611 EMF_ReAllocAndAdjustPointers(PEMRPOLYGON16,uRecord);
1613 /* FIXME: This is mostly all wrong */
1614 lpRecord->emr.iType = EMR_POLYGON16;
1615 lpRecord->emr.nSize = sizeof( *lpRecord );
1617 lpRecord->rclBounds.left = 0;
1618 lpRecord->rclBounds.right = 0;
1619 lpRecord->rclBounds.top = 0;
1620 lpRecord->rclBounds.bottom = 0;
1622 lpRecord->cpts = 0;
1623 lpRecord->apts[0].x = 0;
1624 lpRecord->apts[0].y = 0;
1626 FIXME( "META_POLYGON conversion not correct\n" );
1628 break;
1631 case META_SETPOLYFILLMODE:
1633 PEMRSETPOLYFILLMODE lpRecord;
1634 size_t uRecord = sizeof(*lpRecord);
1636 EMF_ReAllocAndAdjustPointers(PEMRSETPOLYFILLMODE,uRecord);
1638 lpRecord->emr.iType = EMR_SETPOLYFILLMODE;
1639 lpRecord->emr.nSize = sizeof( *lpRecord );
1641 lpRecord->iMode = lpMetaRecord->rdParm[0];
1643 break;
1646 case META_SETWINDOWORG:
1648 PEMRSETWINDOWORGEX lpRecord; /* Seems to be the closest thing */
1649 size_t uRecord = sizeof(*lpRecord);
1651 EMF_ReAllocAndAdjustPointers(PEMRSETWINDOWORGEX,uRecord);
1653 lpRecord->emr.iType = EMR_SETWINDOWORGEX;
1654 lpRecord->emr.nSize = sizeof( *lpRecord );
1656 lpRecord->ptlOrigin.x = lpMetaRecord->rdParm[1];
1657 lpRecord->ptlOrigin.y = lpMetaRecord->rdParm[0];
1659 break;
1662 case META_SETWINDOWEXT: /* Structure is the same for SETWINDOWEXT & SETVIEWPORTEXT */
1663 case META_SETVIEWPORTEXT:
1665 PEMRSETWINDOWEXTEX lpRecord;
1666 size_t uRecord = sizeof(*lpRecord);
1668 EMF_ReAllocAndAdjustPointers(PEMRSETWINDOWEXTEX,uRecord);
1670 if ( lpMetaRecord->rdFunction == META_SETWINDOWEXT )
1672 lpRecord->emr.iType = EMR_SETWINDOWORGEX;
1674 else
1676 lpRecord->emr.iType = EMR_SETVIEWPORTEXTEX;
1678 lpRecord->emr.nSize = sizeof( *lpRecord );
1680 lpRecord->szlExtent.cx = lpMetaRecord->rdParm[1];
1681 lpRecord->szlExtent.cy = lpMetaRecord->rdParm[0];
1683 break;
1686 case META_CREATEBRUSHINDIRECT:
1688 PEMRCREATEBRUSHINDIRECT lpRecord;
1689 size_t uRecord = sizeof(*lpRecord);
1691 EMF_ReAllocAndAdjustPointers(PEMRCREATEBRUSHINDIRECT,uRecord);
1693 lpRecord->emr.iType = EMR_CREATEBRUSHINDIRECT;
1694 lpRecord->emr.nSize = sizeof( *lpRecord );
1696 lpRecord->ihBrush = ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nHandles;
1697 lpRecord->lb.lbStyle = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbStyle;
1698 lpRecord->lb.lbColor = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbColor;
1699 lpRecord->lb.lbHatch = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbHatch;
1701 ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nHandles += 1; /* New handle */
1703 break;
1707 /* These are all unimplemented and as such are intended to fall through to the default case */
1708 case META_SETBKCOLOR:
1709 case META_SETBKMODE:
1710 case META_SETROP2:
1711 case META_SETRELABS:
1712 case META_SETSTRETCHBLTMODE:
1713 case META_SETTEXTCOLOR:
1714 case META_SETVIEWPORTORG:
1715 case META_OFFSETWINDOWORG:
1716 case META_SCALEWINDOWEXT:
1717 case META_OFFSETVIEWPORTORG:
1718 case META_SCALEVIEWPORTEXT:
1719 case META_LINETO:
1720 case META_MOVETO:
1721 case META_EXCLUDECLIPRECT:
1722 case META_INTERSECTCLIPRECT:
1723 case META_ARC:
1724 case META_ELLIPSE:
1725 case META_FLOODFILL:
1726 case META_PIE:
1727 case META_RECTANGLE:
1728 case META_ROUNDRECT:
1729 case META_PATBLT:
1730 case META_SAVEDC:
1731 case META_SETPIXEL:
1732 case META_OFFSETCLIPRGN:
1733 case META_TEXTOUT:
1734 case META_POLYPOLYGON:
1735 case META_POLYLINE:
1736 case META_RESTOREDC:
1737 case META_CHORD:
1738 case META_CREATEPATTERNBRUSH:
1739 case META_CREATEPENINDIRECT:
1740 case META_CREATEFONTINDIRECT:
1741 case META_CREATEPALETTE:
1742 case META_SETTEXTALIGN:
1743 case META_SELECTPALETTE:
1744 case META_SETMAPPERFLAGS:
1745 case META_REALIZEPALETTE:
1746 case META_ESCAPE:
1747 case META_EXTTEXTOUT:
1748 case META_STRETCHDIB:
1749 case META_DIBSTRETCHBLT:
1750 case META_STRETCHBLT:
1751 case META_BITBLT:
1752 case META_CREATEREGION:
1753 case META_FILLREGION:
1754 case META_FRAMEREGION:
1755 case META_INVERTREGION:
1756 case META_PAINTREGION:
1757 case META_SELECTCLIPREGION:
1758 case META_DIBCREATEPATTERNBRUSH:
1759 case META_DIBBITBLT:
1760 case META_SETTEXTCHAREXTRA:
1761 case META_SETTEXTJUSTIFICATION:
1762 case META_EXTFLOODFILL:
1763 case META_SETDIBTODEV:
1764 case META_DRAWTEXT:
1765 case META_ANIMATEPALETTE:
1766 case META_SETPALENTRIES:
1767 case META_RESIZEPALETTE:
1768 case META_RESETDC:
1769 case META_STARTDOC:
1770 case META_STARTPAGE:
1771 case META_ENDPAGE:
1772 case META_ABORTDOC:
1773 case META_ENDDOC:
1774 case META_CREATEBRUSH:
1775 case META_CREATEBITMAPINDIRECT:
1776 case META_CREATEBITMAP:
1777 /* Fall through to unimplemented */
1778 default:
1780 /* Not implemented yet */
1781 FIXME( "Conversion of record type 0x%x not implemented.\n", lpMetaRecord->rdFunction );
1782 break;
1786 /* Move to the next record */
1787 (char*)lpbBuffer += ((LPMETARECORD)lpbBuffer)->rdSize * 2; /* FIXME: Seem to be doing this in metafile.c */
1789 #undef ReAllocAndAdjustPointers
1792 /* We know the last of the header information now */
1793 ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nBytes = uNewEnhMetaFileBufferSize;
1795 /* Create the enhanced metafile */
1796 hMf = SetEnhMetaFileBits( uNewEnhMetaFileBufferSize, (const BYTE*)lpNewEnhMetaFileBuffer );
1798 if( !hMf )
1799 ERR( "Problem creating metafile. Did the conversion fail somewhere?\n" );
1801 return hMf;
1803 error:
1804 /* Free the data associated with our copy since it's been copied */
1805 HeapFree( GetProcessHeap(), 0, lpNewEnhMetaFileBuffer );
1807 return 0;