2 * Enhanced metafile functions
3 * Copyright 1998 Douglas Ridgway
7 * The enhanced format consists of the following elements:
10 * A table of handles to GDI objects
11 * An array of metafile records
15 * The standard format consists of a header and an array of metafile records.
23 #include "wine/winestring.h"
25 #include "enhmetafile.h"
26 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(enhmetafile)
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
43 HENHMETAFILE hmf = GDI_AllocObject( sizeof(ENHMETAFILEOBJ),
45 ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_HEAP_LOCK( hmf );
47 metaObj->hFile = hFile;
48 metaObj->hMapping = hMapping;
49 GDI_HEAP_UNLOCK( hmf );
53 /****************************************************************************
54 * EMF_Delete_HENHMETAFILE
56 static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf )
58 ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf,
60 if(!metaObj) return FALSE;
61 if(metaObj->hMapping) {
62 UnmapViewOfFile( metaObj->emh );
63 CloseHandle( metaObj->hMapping );
64 CloseHandle( metaObj->hFile );
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,
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 /*****************************************************************************
98 static HENHMETAFILE EMF_GetEnhMetaFile( HFILE hFile )
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 );
113 return EMF_Create_HENHMETAFILE( emh, hFile, hMapping );
117 /*****************************************************************************
118 * GetEnhMetaFileA (GDI32.174)
122 HENHMETAFILE WINAPI GetEnhMetaFileA(
123 LPCSTR lpszMetaFile /* filename of enhanced metafile */
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);
135 hmf = EMF_GetEnhMetaFile( hFile );
137 CloseHandle( hFile );
141 /*****************************************************************************
142 * GetEnhMetaFile32W (GDI32.180)
144 HENHMETAFILE WINAPI GetEnhMetaFileW(
145 LPCWSTR lpszMetaFile) /* filename of enhanced metafile */
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));
156 hmf = EMF_GetEnhMetaFile( hFile );
158 CloseHandle( hFile );
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
169 UINT WINAPI GetEnhMetaFileHeader(
170 HENHMETAFILE hmf, /* enhanced metafile */
171 UINT bufsize, /* size of buffer */
172 LPENHMETAHEADER buf /* buffer */
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);
198 if(!emh) return FALSE;
199 if(emh->nDescription == 0 || emh->offDescription == 0) {
200 EMF_ReleaseEnhMetaHeader(hmf);
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);
212 lstrcpynWtoA(buf, (WCHAR *) ((char *) emh + emh->offDescription+2*(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
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);
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,
266 LPENHMETARECORD lpEMR,
270 LPUINT uSizeOfRecordData = (LPUINT)lpData;
272 uSizeOfRecordData += lpEMR->nSize;
277 /*****************************************************************************
278 * GetEnhMetaFileBits (GDI32.175)
281 UINT WINAPI GetEnhMetaFileBits(
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" );
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 )
316 /* Use memmove just in case they overlap */
317 memmove(buf, lpEnhMetaFile, bufsize);
319 EMF_ReleaseEnhMetaHeader( hmf );
324 /*****************************************************************************
325 * PlayEnhMetaFileRecord (GDI32.264)
327 * Render a single enhanced metafile record in the device context hdc.
330 * TRUE (non zero) on success, FALSE on error.
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 */
344 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
345 hdc, handletable, mr, handles);
346 if (!mr) return FALSE;
350 TRACE(" type=%d\n", type);
356 ENHMETAHEADER* h = (LPENHMETAHEADER)mr;
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 );
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 );
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 );
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 );
401 DWORD mode = mr->dParm[0];
402 SetMapMode(hdc, mode);
407 DWORD mode = mr->dParm[0];
408 SetBkMode(hdc, mode);
413 DWORD mode = mr->dParm[0];
414 SetBkColor(hdc, mode);
417 case EMR_SETPOLYFILLMODE:
419 DWORD mode = mr->dParm[0];
420 SetPolyFillMode(hdc, mode);
425 DWORD mode = mr->dParm[0];
429 case EMR_SETSTRETCHBLTMODE:
431 DWORD mode = mr->dParm[0];
432 SetStretchBltMode(hdc, mode);
435 case EMR_SETTEXTALIGN:
437 DWORD align = mr->dParm[0];
438 SetTextAlign(hdc, align);
441 case EMR_SETTEXTCOLOR:
443 DWORD color = mr->dParm[0];
444 SetTextColor(hdc, color);
454 RestoreDC(hdc, mr->dParm[0]);
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);
464 case EMR_SELECTOBJECT:
466 DWORD obj = mr->dParm[0];
467 SelectObject(hdc, (handletable->objectHandle)[obj]);
470 case EMR_DELETEOBJECT:
472 DWORD obj = mr->dParm[0];
473 DeleteObject( (handletable->objectHandle)[obj]);
474 (handletable->objectHandle)[obj] = 0;
477 case EMR_SETWINDOWORGEX:
479 DWORD x = mr->dParm[0], y = mr->dParm[1];
480 SetWindowOrgEx(hdc, x, y, NULL);
483 case EMR_SETWINDOWEXTEX:
485 DWORD x = mr->dParm[0], y = mr->dParm[1];
486 SetWindowExtEx(hdc, x, y, NULL);
489 case EMR_SETVIEWPORTORGEX:
491 DWORD x = mr->dParm[0], y = mr->dParm[1];
492 SetViewportOrgEx(hdc, x, y, NULL);
495 case EMR_SETVIEWPORTEXTEX:
497 DWORD x = mr->dParm[0], y = mr->dParm[1];
498 SetViewportExtEx(hdc, x, y, NULL);
503 DWORD obj = mr->dParm[0];
504 (handletable->objectHandle)[obj] =
505 CreatePenIndirect((LOGPEN *) &(mr->dParm[1]));
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);
518 case EMR_CREATEBRUSHINDIRECT:
520 DWORD obj = mr->dParm[0];
521 (handletable->objectHandle)[obj] =
522 CreateBrushIndirect((LOGBRUSH *) &(mr->dParm[1]));
525 case EMR_EXTCREATEFONTINDIRECTW:
527 DWORD obj = mr->dParm[0];
528 (handletable->objectHandle)[obj] =
529 CreateFontIndirectW((LOGFONTW *) &(mr->dParm[1]));
534 DWORD x = mr->dParm[0], y = mr->dParm[1];
535 MoveToEx(hdc, x, y, NULL);
540 DWORD x = mr->dParm[0], y = mr->dParm[1];
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);
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);
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);
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);
575 case EMR_POLYPOLYGON16:
577 PEMRPOLYPOLYGON16 lpPolyPoly16 = (PEMRPOLYPOLYGON16)mr;
581 lpPolyPoly16->aPolyCounts,
582 lpPolyPoly16->nPolys );
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),
609 case EMR_EXTTEXTOUTW:
612 DWORD flags = mr->dParm[4];
614 DWORD x = mr->dParm[7], y = mr->dParm[8];
615 DWORD count = mr->dParm[9];
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);
625 case EMR_CREATEPALETTE:
627 PEMRCREATEPALETTE lpCreatePal = (PEMRCREATEPALETTE)mr;
629 (handletable->objectHandle)[ lpCreatePal->ihPal ] =
630 CreatePalette( &lpCreatePal->lgpl );
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 );
645 case EMR_REALIZEPALETTE:
647 RealizePalette( hdc );
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) );
668 case EMR_SETWORLDTRANSFORM:
670 PEMRSETWORLDTRANSFORM lpXfrm = (PEMRSETWORLDTRANSFORM)mr;
672 SetWorldTransform( hdc, &lpXfrm->xform );
679 PEMRPOLYBEZIER lpPolyBez = (PEMRPOLYBEZIER)mr;
681 FIXME( "Bounding rectangle ignored for EMR_POLYBEZIER\n" );
682 PolyBezier( hdc, (const LPPOINT)lpPolyBez->aptl, (UINT)lpPolyBez->cptl );
689 PEMRPOLYGON lpPoly = (PEMRPOLYGON)mr;
691 FIXME( "Bounding rectangle ignored for EMR_POLYGON\n" );
692 Polygon( hdc, (const LPPOINT)lpPoly->aptl, (UINT)lpPoly->cptl );
699 PEMRPOLYLINE lpPolyLine = (PEMRPOLYLINE)mr;
701 FIXME( "Bounding rectangle ignored for EMR_POLYLINE\n" );
702 Polyline( hdc, (const LPPOINT)lpPolyLine->aptl, (UINT)lpPolyLine->cptl );
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 );
719 PEMRPOLYLINETO lpPolyLineTo = (PEMRPOLYLINETO)mr;
721 FIXME( "Bounding rectangle ignored for EMR_POLYLINETO\n" );
722 PolylineTo( hdc, (const LPPOINT)lpPolyLineTo->aptl, (UINT)lpPolyLineTo->cptl );
727 case EMR_POLYPOLYLINE:
729 PEMRPOLYPOLYLINE lpPolyPolyLine = (PEMRPOLYPOLYLINE)mr;
731 FIXME( "Bounding rectangle ignored for EMR_POLYPOLYLINE\n" );
733 (const LPPOINT)lpPolyPolyLine->aptl,
734 lpPolyPolyLine->aPolyCounts,
735 lpPolyPolyLine->nPolys );
740 case EMR_POLYPOLYGON:
742 PEMRPOLYPOLYGON lpPolyPolygon = (PEMRPOLYPOLYGON)mr;
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 );
765 case EMR_SETBRUSHORGEX:
767 PEMRSETBRUSHORGEX lpSetBrushOrgEx = (PEMRSETBRUSHORGEX)mr;
770 (INT)lpSetBrushOrgEx->ptlOrigin.x,
771 (INT)lpSetBrushOrgEx->ptlOrigin.y,
779 PEMRSETPIXELV lpSetPixelV = (PEMRSETPIXELV)mr;
782 (INT)lpSetPixelV->ptlPixel.x,
783 (INT)lpSetPixelV->ptlPixel.y,
784 lpSetPixelV->crColor );
789 case EMR_SETMAPPERFLAGS:
791 PEMRSETMAPPERFLAGS lpSetMapperFlags = (PEMRSETMAPPERFLAGS)mr;
793 SetMapperFlags( hdc, lpSetMapperFlags->dwFlags );
798 case EMR_SETCOLORADJUSTMENT:
800 PEMRSETCOLORADJUSTMENT lpSetColorAdjust = (PEMRSETCOLORADJUSTMENT)mr;
802 SetColorAdjustment( hdc, &lpSetColorAdjust->ColorAdjustment );
807 case EMR_OFFSETCLIPRGN:
809 PEMROFFSETCLIPRGN lpOffsetClipRgn = (PEMROFFSETCLIPRGN)mr;
812 (INT)lpOffsetClipRgn->ptlOffset.x,
813 (INT)lpOffsetClipRgn->ptlOffset.y );
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 );
831 case EMR_SCALEVIEWPORTEXTEX:
833 PEMRSCALEVIEWPORTEXTEX lpScaleViewportExtEx = (PEMRSCALEVIEWPORTEXTEX)mr;
835 ScaleViewportExtEx( hdc,
836 lpScaleViewportExtEx->xNum,
837 lpScaleViewportExtEx->xDenom,
838 lpScaleViewportExtEx->yNum,
839 lpScaleViewportExtEx->yDenom,
845 case EMR_SCALEWINDOWEXTEX:
847 PEMRSCALEWINDOWEXTEX lpScaleWindowExtEx = (PEMRSCALEWINDOWEXTEX)mr;
849 ScaleWindowExtEx( hdc,
850 lpScaleWindowExtEx->xNum,
851 lpScaleWindowExtEx->xDenom,
852 lpScaleWindowExtEx->yNum,
853 lpScaleWindowExtEx->yDenom,
859 case EMR_MODIFYWORLDTRANSFORM:
861 PEMRMODIFYWORLDTRANSFORM lpModifyWorldTrans = (PEMRMODIFYWORLDTRANSFORM)mr;
863 ModifyWorldTransform( hdc, &lpModifyWorldTrans->xform,
864 lpModifyWorldTrans->iMode );
871 PEMRANGLEARC lpAngleArc = (PEMRANGLEARC)mr;
874 (INT)lpAngleArc->ptlCenter.x, (INT)lpAngleArc->ptlCenter.y,
875 lpAngleArc->nRadius, lpAngleArc->eStartAngle,
876 lpAngleArc->eSweepAngle );
883 PEMRROUNDRECT lpRoundRect = (PEMRROUNDRECT)mr;
886 lpRoundRect->rclBox.left,
887 lpRoundRect->rclBox.top,
888 lpRoundRect->rclBox.right,
889 lpRoundRect->rclBox.bottom,
890 lpRoundRect->szlCorner.cx,
891 lpRoundRect->szlCorner.cy );
898 PEMRARC lpArc = (PEMRARC)mr;
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 );
915 PEMRCHORD lpChord = (PEMRCHORD)mr;
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 );
932 PEMRPIE lpPie = (PEMRPIE)mr;
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 );
949 PEMRARC lpArcTo = (PEMRARC)mr;
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 );
964 case EMR_EXTFLOODFILL:
966 PEMREXTFLOODFILL lpExtFloodFill = (PEMREXTFLOODFILL)mr;
969 (INT)lpExtFloodFill->ptlStart.x,
970 (INT)lpExtFloodFill->ptlStart.y,
971 lpExtFloodFill->crColor,
972 (UINT)lpExtFloodFill->iMode );
979 PEMRPOLYDRAW lpPolyDraw = (PEMRPOLYDRAW)mr;
981 FIXME( "Bounding rectangle ignored for EMR_POLYDRAW\n" );
983 (const LPPOINT)lpPolyDraw->aptl,
985 (INT)lpPolyDraw->cptl );
990 case EMR_SETARCDIRECTION:
992 PEMRSETARCDIRECTION lpSetArcDirection = (PEMRSETARCDIRECTION)mr;
994 SetArcDirection( hdc, (INT)lpSetArcDirection->iArcDirection );
999 case EMR_SETMITERLIMIT:
1001 PEMRSETMITERLIMIT lpSetMiterLimit = (PEMRSETMITERLIMIT)mr;
1003 SetMiterLimit( hdc, lpSetMiterLimit->eMiterLimit, NULL );
1020 case EMR_CLOSEFIGURE:
1028 /*PEMRFILLPATH lpFillPath = (PEMRFILLPATH)mr;*/
1030 FIXME( "Bounding rectangle ignored for EMR_FILLPATH\n" );
1036 case EMR_STROKEANDFILLPATH:
1038 /*PEMRSTROKEANDFILLPATH lpStrokeAndFillPath = (PEMRSTROKEANDFILLPATH)mr;*/
1040 FIXME( "Bounding rectangle ignored for EMR_STROKEANDFILLPATH\n" );
1041 StrokeAndFillPath( hdc );
1046 case EMR_STROKEPATH:
1048 /*PEMRSTROKEPATH lpStrokePath = (PEMRSTROKEPATH)mr;*/
1050 FIXME( "Bounding rectangle ignored for EMR_STROKEPATH\n" );
1056 case EMR_FLATTENPATH:
1068 case EMR_SELECTCLIPPATH:
1070 PEMRSELECTCLIPPATH lpSelectClipPath = (PEMRSELECTCLIPPATH)mr;
1072 SelectClipPath( hdc, (INT)lpSelectClipPath->iMode );
1083 case EMR_CREATECOLORSPACE:
1085 PEMRCREATECOLORSPACE lpCreateColorSpace = (PEMRCREATECOLORSPACE)mr;
1087 (handletable->objectHandle)[lpCreateColorSpace->ihCS] =
1088 CreateColorSpaceA( &lpCreateColorSpace->lcs );
1093 case EMR_SETCOLORSPACE:
1095 PEMRSETCOLORSPACE lpSetColorSpace = (PEMRSETCOLORSPACE)mr;
1098 (handletable->objectHandle)[lpSetColorSpace->ihCS] );
1103 case EMR_DELETECOLORSPACE:
1105 PEMRDELETECOLORSPACE lpDeleteColorSpace = (PEMRDELETECOLORSPACE)mr;
1107 DeleteColorSpace( (handletable->objectHandle)[lpDeleteColorSpace->ihCS] );
1112 case EMR_SETICMMODE:
1114 PERMSETICMMODE lpSetICMMode = (PERMSETICMMODE)mr;
1117 (INT)lpSetICMMode->iMode );
1122 case EMR_PIXELFORMAT:
1125 PEMRPIXELFORMAT lpPixelFormat = (PEMRPIXELFORMAT)mr;
1127 iPixelFormat = ChoosePixelFormat( hdc, &lpPixelFormat->pfd );
1128 SetPixelFormat( hdc, iPixelFormat, &lpPixelFormat->pfd );
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 );
1145 case EMR_RESIZEPALETTE:
1147 PEMRRESIZEPALETTE lpResizePalette = (PEMRRESIZEPALETTE)mr;
1149 ResizePalette( (handletable->objectHandle)[lpResizePalette->ihPal],
1150 (UINT)lpResizePalette->cEntries );
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,
1167 memcpy( ((BYTE*)lpPackedStruct) + lpCreate->cbBmi,
1168 ((BYTE*)lpCreate) + lpCreate->offBits,
1171 (handletable->objectHandle)[lpCreate->ihBrush] =
1172 CreateDIBPatternBrushPt( lpPackedStruct,
1173 (UINT)lpCreate->iUsage );
1179 case EMR_STRETCHBLT:
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:
1198 case EMR_GLSBOUNDEDRECORD:
1200 /* From docs: If PlayEnhMetaFileRecord doesn't recognize a
1201 record then ignore and return TRUE. */
1202 FIXME("type %d is unimplemented\n", type);
1209 /*****************************************************************************
1211 * EnumEnhMetaFile32 (GDI32.79)
1213 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
1215 * record. Returns when either every record has been used or
1216 * when _EnhMetaFunc_ returns FALSE.
1220 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
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 */
1235 LPENHMETARECORD p = (LPENHMETARECORD) EMF_GetEnhMetaHeader(hmf);
1239 if(!p) return FALSE;
1240 count = ((LPENHMETAHEADER) p)->nHandles;
1241 ht = HeapAlloc( GetProcessHeap(), 0, sizeof(HANDLETABLE)*count);
1242 ht->objectHandle[0] = hmf;
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);
1254 /**************************************************************************
1255 * PlayEnhMetaFile (GDI32.263)
1257 * Renders an enhanced metafile into a specified rectangle *lpRect
1258 * in device context hdc.
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);
1276 if(!p) return FALSE;
1277 count = ((LPENHMETAHEADER) p)->nHandles;
1278 ht = HeapAlloc( GetProcessHeap(), 0, sizeof(HANDLETABLE) * count);
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);
1286 xform.eM11 = xscale;
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;
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 */
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,
1331 ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst;
1332 HENHMETAFILE hmfDst;
1334 if(!emrSrc) return FALSE;
1336 emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes );
1337 memcpy( emrDst, emrSrc, emrSrc->nBytes );
1338 hmfDst = EMF_Create_HENHMETAFILE( emrDst, 0, 0 );
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 );
1351 /* Struct to be used to be passed in the LPVOID parameter for cbEnhPaletteCopy */
1352 typedef struct tagEMF_PaletteCopy
1355 LPPALETTEENTRY lpPe;
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
1365 * NOTE: To be used by GetEnhMetaFilePaletteEntries only!
1367 INT CALLBACK cbEnhPaletteCopy( HDC a,
1369 LPENHMETARECORD lpEMR,
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 */
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,
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
1415 if ( enhHeader->nPalEntries == 0 )
1417 /* No palette associated with this enhanced metafile */
1422 /* Is the user requesting the number of palettes? */
1425 uReturnValue = (UINT)enhHeader->nPalEntries;
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 ) )
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" );
1447 uReturnValue = infoForCallBack.cEntries;
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,
1468 CONST METAFILEPICT *lpmfp
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 )
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 */
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 */
1531 LPMETARECORD lpMetaRecord = (LPMETARECORD)lpbBuffer;
1533 #define EMF_ReAllocAndAdjustPointers( a , b ) \
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 )
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 */
1564 FIXME( "META_EOF conversion not correct\n" );
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];
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;
1597 lpRecord->emr.iType = EMR_SELECTOBJECT;
1599 lpRecord->emr.nSize = sizeof( *lpRecord );
1601 lpRecord->ihObject = lpMetaRecord->rdParm[0]; /* FIXME: Handle */
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;
1623 lpRecord->apts[0].x = 0;
1624 lpRecord->apts[0].y = 0;
1626 FIXME( "META_POLYGON conversion not correct\n" );
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];
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];
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;
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];
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 */
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:
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:
1721 case META_EXCLUDECLIPRECT:
1722 case META_INTERSECTCLIPRECT:
1725 case META_FLOODFILL:
1727 case META_RECTANGLE:
1728 case META_ROUNDRECT:
1732 case META_OFFSETCLIPRGN:
1734 case META_POLYPOLYGON:
1736 case META_RESTOREDC:
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:
1747 case META_EXTTEXTOUT:
1748 case META_STRETCHDIB:
1749 case META_DIBSTRETCHBLT:
1750 case META_STRETCHBLT:
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:
1765 case META_ANIMATEPALETTE:
1766 case META_SETPALENTRIES:
1767 case META_RESIZEPALETTE:
1770 case META_STARTPAGE:
1774 case META_CREATEBRUSH:
1775 case META_CREATEBITMAPINDIRECT:
1776 case META_CREATEBITMAP:
1777 /* Fall through to unimplemented */
1780 /* Not implemented yet */
1781 FIXME( "Conversion of record type 0x%x not implemented.\n", lpMetaRecord->rdFunction );
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 );
1799 ERR( "Problem creating metafile. Did the conversion fail somewhere?\n" );
1804 /* Free the data associated with our copy since it's been copied */
1805 HeapFree( GetProcessHeap(), 0, lpNewEnhMetaFileBuffer );