Merged DDBitmap and physBitmap into the generic bitmap structure
[wine/multimedia.git] / objects / enhmetafile.c
bloba2e4965884b2c9ac4f275c0066f9dbc89de8e73f
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, first_A;
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 first_A = lstrlenA( buf );
212 buf += first_A + 1;
213 lstrcpynWtoA(buf, (WCHAR *) ((char *) emh + emh->offDescription+2*(first+1)),
214 size - first_A - 1); /* i18n ready */
215 first_A += lstrlenA(buf) + 1;
217 EMF_ReleaseEnhMetaHeader(hmf);
218 return min(size, first_A);
221 /*****************************************************************************
222 * GetEnhMetaFileDescription32W (GDI32.177)
224 * Copies the description string of an enhanced metafile into a buffer
225 * _buf_.
227 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
228 * number of characters copied.
230 UINT WINAPI GetEnhMetaFileDescriptionW(
231 HENHMETAFILE hmf, /* enhanced metafile */
232 UINT size, /* size of buf */
233 LPWSTR buf /* buffer to receive description */
236 LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
238 if(!emh) return FALSE;
239 if(emh->nDescription == 0 || emh->offDescription == 0) {
240 EMF_ReleaseEnhMetaHeader(hmf);
241 return 0;
243 if (!buf || !size ) {
244 EMF_ReleaseEnhMetaHeader(hmf);
245 return emh->nDescription;
248 memmove(buf, (char *) emh + emh->offDescription,
249 min(size,emh->nDescription));
250 EMF_ReleaseEnhMetaHeader(hmf);
251 return min(size, emh->nDescription);
254 /****************************************************************************
255 * SetEnhMetaFileBits (GDI32.315)
257 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
259 HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf)
261 ENHMETAHEADER *emh = HeapAlloc( GetProcessHeap(), 0, bufsize );
262 memmove(emh, buf, bufsize);
263 return EMF_Create_HENHMETAFILE( emh, 0, 0 );
266 INT CALLBACK cbCountSizeOfEnhMetaFile( HDC a,
267 LPHANDLETABLE b,
268 LPENHMETARECORD lpEMR,
269 INT c,
270 LPVOID lpData )
272 LPUINT uSizeOfRecordData = (LPUINT)lpData;
274 *uSizeOfRecordData += lpEMR->nSize;
276 return TRUE;
279 /*****************************************************************************
280 * GetEnhMetaFileBits (GDI32.175)
283 UINT WINAPI GetEnhMetaFileBits(
284 HENHMETAFILE hmf,
285 UINT bufsize,
286 LPBYTE buf
289 LPENHMETAHEADER lpEnhMetaFile;
290 UINT uEnhMetaFileSize = 0;
292 FIXME( "(%04x,%u,%p): untested\n", hmf, bufsize, buf );
294 /* Determine the required buffer size */
295 /* Enumerate all records and count their size */
296 if( !EnumEnhMetaFile( 0, hmf, cbCountSizeOfEnhMetaFile, &uEnhMetaFileSize, NULL ) )
298 ERR( "Unable to enumerate enhanced metafile!\n" );
299 return 0;
302 if( buf == NULL )
304 return uEnhMetaFileSize;
307 /* Copy the lesser of the two byte counts */
308 uEnhMetaFileSize = min( uEnhMetaFileSize, bufsize );
310 /* Copy everything */
311 lpEnhMetaFile = EMF_GetEnhMetaHeader( hmf );
313 if( lpEnhMetaFile == NULL )
315 return 0;
318 /* Use memmove just in case they overlap */
319 memmove(buf, lpEnhMetaFile, bufsize);
321 EMF_ReleaseEnhMetaHeader( hmf );
323 return bufsize;
326 /*****************************************************************************
327 * PlayEnhMetaFileRecord (GDI32.264)
329 * Render a single enhanced metafile record in the device context hdc.
331 * RETURNS
332 * TRUE (non zero) on success, FALSE on error.
333 * BUGS
334 * Many unimplemented records.
335 * No error handling on record play failures (ie checking return codes)
337 BOOL WINAPI PlayEnhMetaFileRecord(
338 HDC hdc, /* device context in which to render EMF record */
339 LPHANDLETABLE handletable, /* array of handles to be used in rendering record */
340 const ENHMETARECORD *mr, /* EMF record to render */
341 UINT handles /* size of handle array */
344 int type;
345 TRACE(
346 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
347 hdc, handletable, mr, handles);
348 if (!mr) return FALSE;
350 type = mr->iType;
352 TRACE(" type=%d\n", type);
353 switch(type)
355 case EMR_HEADER:
357 #if 0
358 ENHMETAHEADER* h = (LPENHMETAHEADER)mr;
359 XFORM dcTransform;
361 /* Scale the enhanced metafile according to the reference hdc
362 it was created with */
363 if( h->szlDevice.cx )
365 dcTransform.eM11 = (FLOAT)( (DOUBLE)GetDeviceCaps( hdc, HORZRES ) /
366 (DOUBLE)h->szlDevice.cx );
368 else
370 ERR( "Invalid szlDevice.cx in header\n" );
371 dcTransform.eM11 = (FLOAT)1.0;
374 if( h->szlDevice.cy )
376 dcTransform.eM22 = (FLOAT)( (DOUBLE)GetDeviceCaps( hdc, VERTRES ) /
377 (DOUBLE)h->szlDevice.cy );
379 else
381 ERR( "Invalid szlDevice.cy in header\n" );
382 dcTransform.eM22 = (FLOAT)1.0;
385 dcTransform.eM12 = dcTransform.eM21 = (FLOAT)0;
386 dcTransform.eDx = dcTransform.eDy = (FLOAT)0;
388 ModifyWorldTransform( hdc, &dcTransform, MWT_RIGHTMULTIPLY );
389 #endif
390 break;
392 case EMR_EOF:
393 break;
394 case EMR_GDICOMMENT:
396 PEMRGDICOMMENT lpGdiComment = (PEMRGDICOMMENT)mr;
397 /* In an enhanced metafile, there can be both public and private GDI comments */
398 GdiComment( hdc, lpGdiComment->cbData, lpGdiComment->Data );
399 break;
401 case EMR_SETMAPMODE:
403 DWORD mode = mr->dParm[0];
404 SetMapMode(hdc, mode);
405 break;
407 case EMR_SETBKMODE:
409 DWORD mode = mr->dParm[0];
410 SetBkMode(hdc, mode);
411 break;
413 case EMR_SETBKCOLOR:
415 DWORD mode = mr->dParm[0];
416 SetBkColor(hdc, mode);
417 break;
419 case EMR_SETPOLYFILLMODE:
421 DWORD mode = mr->dParm[0];
422 SetPolyFillMode(hdc, mode);
423 break;
425 case EMR_SETROP2:
427 DWORD mode = mr->dParm[0];
428 SetROP2(hdc, mode);
429 break;
431 case EMR_SETSTRETCHBLTMODE:
433 DWORD mode = mr->dParm[0];
434 SetStretchBltMode(hdc, mode);
435 break;
437 case EMR_SETTEXTALIGN:
439 DWORD align = mr->dParm[0];
440 SetTextAlign(hdc, align);
441 break;
443 case EMR_SETTEXTCOLOR:
445 DWORD color = mr->dParm[0];
446 SetTextColor(hdc, color);
447 break;
449 case EMR_SAVEDC:
451 SaveDC(hdc);
452 break;
454 case EMR_RESTOREDC:
456 RestoreDC(hdc, mr->dParm[0]);
457 break;
459 case EMR_INTERSECTCLIPRECT:
461 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
462 bottom = mr->dParm[3];
463 IntersectClipRect(hdc, left, top, right, bottom);
464 break;
466 case EMR_SELECTOBJECT:
468 DWORD obj = mr->dParm[0];
469 SelectObject(hdc, (handletable->objectHandle)[obj]);
470 break;
472 case EMR_DELETEOBJECT:
474 DWORD obj = mr->dParm[0];
475 DeleteObject( (handletable->objectHandle)[obj]);
476 (handletable->objectHandle)[obj] = 0;
477 break;
479 case EMR_SETWINDOWORGEX:
481 DWORD x = mr->dParm[0], y = mr->dParm[1];
482 SetWindowOrgEx(hdc, x, y, NULL);
483 break;
485 case EMR_SETWINDOWEXTEX:
487 DWORD x = mr->dParm[0], y = mr->dParm[1];
488 SetWindowExtEx(hdc, x, y, NULL);
489 break;
491 case EMR_SETVIEWPORTORGEX:
493 DWORD x = mr->dParm[0], y = mr->dParm[1];
494 SetViewportOrgEx(hdc, x, y, NULL);
495 break;
497 case EMR_SETVIEWPORTEXTEX:
499 DWORD x = mr->dParm[0], y = mr->dParm[1];
500 SetViewportExtEx(hdc, x, y, NULL);
501 break;
503 case EMR_CREATEPEN:
505 DWORD obj = mr->dParm[0];
506 (handletable->objectHandle)[obj] =
507 CreatePenIndirect((LOGPEN *) &(mr->dParm[1]));
508 break;
510 case EMR_EXTCREATEPEN:
512 DWORD obj = mr->dParm[0];
513 DWORD style = mr->dParm[1], brush = mr->dParm[2];
514 LOGBRUSH *b = (LOGBRUSH *) &mr->dParm[3];
515 FIXME("Some ExtCreatePen args not handled\n");
516 (handletable->objectHandle)[obj] =
517 ExtCreatePen(style, brush, b, 0, NULL);
518 break;
520 case EMR_CREATEBRUSHINDIRECT:
522 DWORD obj = mr->dParm[0];
523 (handletable->objectHandle)[obj] =
524 CreateBrushIndirect((LOGBRUSH *) &(mr->dParm[1]));
525 break;
527 case EMR_EXTCREATEFONTINDIRECTW:
529 DWORD obj = mr->dParm[0];
530 (handletable->objectHandle)[obj] =
531 CreateFontIndirectW((LOGFONTW *) &(mr->dParm[1]));
532 break;
534 case EMR_MOVETOEX:
536 DWORD x = mr->dParm[0], y = mr->dParm[1];
537 MoveToEx(hdc, x, y, NULL);
538 break;
540 case EMR_LINETO:
542 DWORD x = mr->dParm[0], y = mr->dParm[1];
543 LineTo(hdc, x, y);
544 break;
546 case EMR_RECTANGLE:
548 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
549 bottom = mr->dParm[3];
550 Rectangle(hdc, left, top, right, bottom);
551 break;
553 case EMR_ELLIPSE:
555 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
556 bottom = mr->dParm[3];
557 Ellipse(hdc, left, top, right, bottom);
558 break;
560 case EMR_POLYGON16:
562 /* 0-3 : a bounding rectangle? */
563 INT count = mr->dParm[4];
564 FIXME("Some Polygon16 args not handled\n");
565 Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
566 break;
568 case EMR_POLYLINE16:
570 /* 0-3 : a bounding rectangle? */
571 INT count = mr->dParm[4];
572 FIXME("Some Polyline16 args not handled\n");
573 Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
574 break;
576 #if 0
577 case EMR_POLYPOLYGON16:
579 PEMRPOLYPOLYGON16 lpPolyPoly16 = (PEMRPOLYPOLYGON16)mr;
581 PolyPolygon16( hdc,
582 lpPolyPoly16->apts,
583 lpPolyPoly16->aPolyCounts,
584 lpPolyPoly16->nPolys );
586 break;
588 #endif
589 case EMR_STRETCHDIBITS:
591 LONG xDest = mr->dParm[4];
592 LONG yDest = mr->dParm[5];
593 LONG xSrc = mr->dParm[6];
594 LONG ySrc = mr->dParm[7];
595 LONG cxSrc = mr->dParm[8];
596 LONG cySrc = mr->dParm[9];
597 DWORD offBmiSrc = mr->dParm[10];
598 DWORD offBitsSrc = mr->dParm[12];
599 DWORD iUsageSrc = mr->dParm[14];
600 DWORD dwRop = mr->dParm[15];
601 LONG cxDest = mr->dParm[16];
602 LONG cyDest = mr->dParm[17];
604 StretchDIBits(hdc,xDest,yDest,cxDest,cyDest,
605 xSrc,ySrc,cxSrc,cySrc,
606 ((char *)mr)+offBitsSrc,
607 (const BITMAPINFO *)(((char *)mr)+offBmiSrc),
608 iUsageSrc,dwRop);
609 break;
611 case EMR_EXTTEXTOUTW:
613 /* 0-3: ??? */
614 DWORD flags = mr->dParm[4];
615 /* 5, 6: ??? */
616 DWORD x = mr->dParm[7], y = mr->dParm[8];
617 DWORD count = mr->dParm[9];
618 /* 10-16: ??? */
619 LPWSTR str = (LPWSTR)& mr->dParm[17];
620 /* trailing info: dx array? */
621 FIXME("Many ExtTextOut args not handled\n");
622 ExtTextOutW(hdc, x, y, flags, /* lpRect */ NULL,
623 str, count, /* lpDx */ NULL);
624 break;
627 case EMR_CREATEPALETTE:
629 PEMRCREATEPALETTE lpCreatePal = (PEMRCREATEPALETTE)mr;
631 (handletable->objectHandle)[ lpCreatePal->ihPal ] =
632 CreatePalette( &lpCreatePal->lgpl );
634 break;
637 case EMR_SELECTPALETTE:
639 PEMRSELECTPALETTE lpSelectPal = (PEMRSELECTPALETTE)mr;
641 /* FIXME: Should this be forcing background mode? */
642 (handletable->objectHandle)[ lpSelectPal->ihPal ] =
643 SelectPalette( hdc, lpSelectPal->ihPal, FALSE );
644 break;
647 case EMR_REALIZEPALETTE:
649 RealizePalette( hdc );
650 break;
653 #if 0
654 case EMR_EXTSELECTCLIPRGN:
656 PEMREXTSELECTCLIPRGN lpRgn = (PEMREXTSELECTCLIPRGN)mr;
658 /* Need to make a region out of the RGNDATA we have */
659 ExtSelectClipRgn( hdc, ..., (INT)(lpRgn->iMode) );
662 #endif
664 case EMR_SETMETARGN:
666 SetMetaRgn( hdc );
667 break;
670 case EMR_SETWORLDTRANSFORM:
672 PEMRSETWORLDTRANSFORM lpXfrm = (PEMRSETWORLDTRANSFORM)mr;
674 SetWorldTransform( hdc, &lpXfrm->xform );
676 break;
679 case EMR_POLYBEZIER:
681 PEMRPOLYBEZIER lpPolyBez = (PEMRPOLYBEZIER)mr;
683 FIXME( "Bounding rectangle ignored for EMR_POLYBEZIER\n" );
684 PolyBezier( hdc, (const LPPOINT)lpPolyBez->aptl, (UINT)lpPolyBez->cptl );
686 break;
689 case EMR_POLYGON:
691 PEMRPOLYGON lpPoly = (PEMRPOLYGON)mr;
693 FIXME( "Bounding rectangle ignored for EMR_POLYGON\n" );
694 Polygon( hdc, (const LPPOINT)lpPoly->aptl, (UINT)lpPoly->cptl );
696 break;
699 case EMR_POLYLINE:
701 PEMRPOLYLINE lpPolyLine = (PEMRPOLYLINE)mr;
703 FIXME( "Bounding rectangle ignored for EMR_POLYLINE\n" );
704 Polyline( hdc, (const LPPOINT)lpPolyLine->aptl, (UINT)lpPolyLine->cptl );
706 break;
709 case EMR_POLYBEZIERTO:
711 PEMRPOLYBEZIERTO lpPolyBezierTo = (PEMRPOLYBEZIERTO)mr;
713 FIXME( "Bounding rectangle ignored for EMR_POLYBEZIERTO\n" );
714 PolyBezierTo( hdc, (const LPPOINT)lpPolyBezierTo->aptl, (UINT)lpPolyBezierTo->cptl );
716 break;
719 case EMR_POLYLINETO:
721 PEMRPOLYLINETO lpPolyLineTo = (PEMRPOLYLINETO)mr;
723 FIXME( "Bounding rectangle ignored for EMR_POLYLINETO\n" );
724 PolylineTo( hdc, (const LPPOINT)lpPolyLineTo->aptl, (UINT)lpPolyLineTo->cptl );
726 break;
729 case EMR_POLYPOLYLINE:
731 PEMRPOLYPOLYLINE lpPolyPolyLine = (PEMRPOLYPOLYLINE)mr;
733 FIXME( "Bounding rectangle ignored for EMR_POLYPOLYLINE\n" );
734 PolyPolyline( hdc,
735 (const LPPOINT)lpPolyPolyLine->aptl,
736 lpPolyPolyLine->aPolyCounts,
737 lpPolyPolyLine->nPolys );
739 break;
742 case EMR_POLYPOLYGON:
744 PEMRPOLYPOLYGON lpPolyPolygon = (PEMRPOLYPOLYGON)mr;
745 INT* lpPolyCounts;
746 UINT i;
748 /* We get the polygon point counts in a dword struct. Transform
749 this into an INT struct */
750 lpPolyCounts = (INT*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
751 sizeof(INT)*lpPolyPolygon->cptl );
753 for( i=0; i<lpPolyPolygon->cptl; i++ )
755 lpPolyCounts[i] = (INT)lpPolyPolygon->aPolyCounts[i];
758 FIXME( "Bounding rectangle ignored for EMR_POLYPOLYGON\n" );
759 PolyPolygon( hdc, (const LPPOINT)lpPolyPolygon->aptl,
760 lpPolyCounts, lpPolyPolygon->nPolys );
762 HeapFree( GetProcessHeap(), 0, lpPolyCounts );
764 break;
767 case EMR_SETBRUSHORGEX:
769 PEMRSETBRUSHORGEX lpSetBrushOrgEx = (PEMRSETBRUSHORGEX)mr;
771 SetBrushOrgEx( hdc,
772 (INT)lpSetBrushOrgEx->ptlOrigin.x,
773 (INT)lpSetBrushOrgEx->ptlOrigin.y,
774 NULL );
776 break;
779 case EMR_SETPIXELV:
781 PEMRSETPIXELV lpSetPixelV = (PEMRSETPIXELV)mr;
783 SetPixelV( hdc,
784 (INT)lpSetPixelV->ptlPixel.x,
785 (INT)lpSetPixelV->ptlPixel.y,
786 lpSetPixelV->crColor );
788 break;
791 case EMR_SETMAPPERFLAGS:
793 PEMRSETMAPPERFLAGS lpSetMapperFlags = (PEMRSETMAPPERFLAGS)mr;
795 SetMapperFlags( hdc, lpSetMapperFlags->dwFlags );
797 break;
800 case EMR_SETCOLORADJUSTMENT:
802 PEMRSETCOLORADJUSTMENT lpSetColorAdjust = (PEMRSETCOLORADJUSTMENT)mr;
804 SetColorAdjustment( hdc, &lpSetColorAdjust->ColorAdjustment );
806 break;
809 case EMR_OFFSETCLIPRGN:
811 PEMROFFSETCLIPRGN lpOffsetClipRgn = (PEMROFFSETCLIPRGN)mr;
813 OffsetClipRgn( hdc,
814 (INT)lpOffsetClipRgn->ptlOffset.x,
815 (INT)lpOffsetClipRgn->ptlOffset.y );
817 break;
820 case EMR_EXCLUDECLIPRECT:
822 PEMREXCLUDECLIPRECT lpExcludeClipRect = (PEMREXCLUDECLIPRECT)mr;
824 ExcludeClipRect( hdc,
825 lpExcludeClipRect->rclClip.left,
826 lpExcludeClipRect->rclClip.top,
827 lpExcludeClipRect->rclClip.right,
828 lpExcludeClipRect->rclClip.bottom );
830 break;
833 case EMR_SCALEVIEWPORTEXTEX:
835 PEMRSCALEVIEWPORTEXTEX lpScaleViewportExtEx = (PEMRSCALEVIEWPORTEXTEX)mr;
837 ScaleViewportExtEx( hdc,
838 lpScaleViewportExtEx->xNum,
839 lpScaleViewportExtEx->xDenom,
840 lpScaleViewportExtEx->yNum,
841 lpScaleViewportExtEx->yDenom,
842 NULL );
844 break;
847 case EMR_SCALEWINDOWEXTEX:
849 PEMRSCALEWINDOWEXTEX lpScaleWindowExtEx = (PEMRSCALEWINDOWEXTEX)mr;
851 ScaleWindowExtEx( hdc,
852 lpScaleWindowExtEx->xNum,
853 lpScaleWindowExtEx->xDenom,
854 lpScaleWindowExtEx->yNum,
855 lpScaleWindowExtEx->yDenom,
856 NULL );
858 break;
861 case EMR_MODIFYWORLDTRANSFORM:
863 PEMRMODIFYWORLDTRANSFORM lpModifyWorldTrans = (PEMRMODIFYWORLDTRANSFORM)mr;
865 ModifyWorldTransform( hdc, &lpModifyWorldTrans->xform,
866 lpModifyWorldTrans->iMode );
868 break;
871 case EMR_ANGLEARC:
873 PEMRANGLEARC lpAngleArc = (PEMRANGLEARC)mr;
875 AngleArc( hdc,
876 (INT)lpAngleArc->ptlCenter.x, (INT)lpAngleArc->ptlCenter.y,
877 lpAngleArc->nRadius, lpAngleArc->eStartAngle,
878 lpAngleArc->eSweepAngle );
880 break;
883 case EMR_ROUNDRECT:
885 PEMRROUNDRECT lpRoundRect = (PEMRROUNDRECT)mr;
887 RoundRect( hdc,
888 lpRoundRect->rclBox.left,
889 lpRoundRect->rclBox.top,
890 lpRoundRect->rclBox.right,
891 lpRoundRect->rclBox.bottom,
892 lpRoundRect->szlCorner.cx,
893 lpRoundRect->szlCorner.cy );
895 break;
898 case EMR_ARC:
900 PEMRARC lpArc = (PEMRARC)mr;
902 Arc( hdc,
903 (INT)lpArc->rclBox.left,
904 (INT)lpArc->rclBox.top,
905 (INT)lpArc->rclBox.right,
906 (INT)lpArc->rclBox.bottom,
907 (INT)lpArc->ptlStart.x,
908 (INT)lpArc->ptlStart.y,
909 (INT)lpArc->ptlEnd.x,
910 (INT)lpArc->ptlEnd.y );
912 break;
915 case EMR_CHORD:
917 PEMRCHORD lpChord = (PEMRCHORD)mr;
919 Chord( hdc,
920 (INT)lpChord->rclBox.left,
921 (INT)lpChord->rclBox.top,
922 (INT)lpChord->rclBox.right,
923 (INT)lpChord->rclBox.bottom,
924 (INT)lpChord->ptlStart.x,
925 (INT)lpChord->ptlStart.y,
926 (INT)lpChord->ptlEnd.x,
927 (INT)lpChord->ptlEnd.y );
929 break;
932 case EMR_PIE:
934 PEMRPIE lpPie = (PEMRPIE)mr;
936 Pie( hdc,
937 (INT)lpPie->rclBox.left,
938 (INT)lpPie->rclBox.top,
939 (INT)lpPie->rclBox.right,
940 (INT)lpPie->rclBox.bottom,
941 (INT)lpPie->ptlStart.x,
942 (INT)lpPie->ptlStart.y,
943 (INT)lpPie->ptlEnd.x,
944 (INT)lpPie->ptlEnd.y );
946 break;
949 case EMR_ARCTO:
951 PEMRARC lpArcTo = (PEMRARC)mr;
953 ArcTo( hdc,
954 (INT)lpArcTo->rclBox.left,
955 (INT)lpArcTo->rclBox.top,
956 (INT)lpArcTo->rclBox.right,
957 (INT)lpArcTo->rclBox.bottom,
958 (INT)lpArcTo->ptlStart.x,
959 (INT)lpArcTo->ptlStart.y,
960 (INT)lpArcTo->ptlEnd.x,
961 (INT)lpArcTo->ptlEnd.y );
963 break;
966 case EMR_EXTFLOODFILL:
968 PEMREXTFLOODFILL lpExtFloodFill = (PEMREXTFLOODFILL)mr;
970 ExtFloodFill( hdc,
971 (INT)lpExtFloodFill->ptlStart.x,
972 (INT)lpExtFloodFill->ptlStart.y,
973 lpExtFloodFill->crColor,
974 (UINT)lpExtFloodFill->iMode );
976 break;
979 case EMR_POLYDRAW:
981 PEMRPOLYDRAW lpPolyDraw = (PEMRPOLYDRAW)mr;
983 FIXME( "Bounding rectangle ignored for EMR_POLYDRAW\n" );
984 PolyDraw( hdc,
985 (const LPPOINT)lpPolyDraw->aptl,
986 lpPolyDraw->abTypes,
987 (INT)lpPolyDraw->cptl );
989 break;
992 case EMR_SETARCDIRECTION:
994 PEMRSETARCDIRECTION lpSetArcDirection = (PEMRSETARCDIRECTION)mr;
996 SetArcDirection( hdc, (INT)lpSetArcDirection->iArcDirection );
998 break;
1001 case EMR_SETMITERLIMIT:
1003 PEMRSETMITERLIMIT lpSetMiterLimit = (PEMRSETMITERLIMIT)mr;
1005 SetMiterLimit( hdc, lpSetMiterLimit->eMiterLimit, NULL );
1007 break;
1010 case EMR_BEGINPATH:
1012 BeginPath( hdc );
1013 break;
1016 case EMR_ENDPATH:
1018 EndPath( hdc );
1019 break;
1022 case EMR_CLOSEFIGURE:
1024 CloseFigure( hdc );
1025 break;
1028 case EMR_FILLPATH:
1030 /*PEMRFILLPATH lpFillPath = (PEMRFILLPATH)mr;*/
1032 FIXME( "Bounding rectangle ignored for EMR_FILLPATH\n" );
1033 FillPath( hdc );
1035 break;
1038 case EMR_STROKEANDFILLPATH:
1040 /*PEMRSTROKEANDFILLPATH lpStrokeAndFillPath = (PEMRSTROKEANDFILLPATH)mr;*/
1042 FIXME( "Bounding rectangle ignored for EMR_STROKEANDFILLPATH\n" );
1043 StrokeAndFillPath( hdc );
1045 break;
1048 case EMR_STROKEPATH:
1050 /*PEMRSTROKEPATH lpStrokePath = (PEMRSTROKEPATH)mr;*/
1052 FIXME( "Bounding rectangle ignored for EMR_STROKEPATH\n" );
1053 StrokePath( hdc );
1055 break;
1058 case EMR_FLATTENPATH:
1060 FlattenPath( hdc );
1061 break;
1064 case EMR_WIDENPATH:
1066 WidenPath( hdc );
1067 break;
1070 case EMR_SELECTCLIPPATH:
1072 PEMRSELECTCLIPPATH lpSelectClipPath = (PEMRSELECTCLIPPATH)mr;
1074 SelectClipPath( hdc, (INT)lpSelectClipPath->iMode );
1076 break;
1079 case EMR_ABORTPATH:
1081 AbortPath( hdc );
1082 break;
1085 case EMR_CREATECOLORSPACE:
1087 PEMRCREATECOLORSPACE lpCreateColorSpace = (PEMRCREATECOLORSPACE)mr;
1089 (handletable->objectHandle)[lpCreateColorSpace->ihCS] =
1090 CreateColorSpaceA( &lpCreateColorSpace->lcs );
1092 break;
1095 case EMR_SETCOLORSPACE:
1097 PEMRSETCOLORSPACE lpSetColorSpace = (PEMRSETCOLORSPACE)mr;
1099 SetColorSpace( hdc,
1100 (handletable->objectHandle)[lpSetColorSpace->ihCS] );
1102 break;
1105 case EMR_DELETECOLORSPACE:
1107 PEMRDELETECOLORSPACE lpDeleteColorSpace = (PEMRDELETECOLORSPACE)mr;
1109 DeleteColorSpace( (handletable->objectHandle)[lpDeleteColorSpace->ihCS] );
1111 break;
1114 case EMR_SETICMMODE:
1116 PERMSETICMMODE lpSetICMMode = (PERMSETICMMODE)mr;
1118 SetICMMode( hdc,
1119 (INT)lpSetICMMode->iMode );
1121 break;
1124 case EMR_PIXELFORMAT:
1126 INT iPixelFormat;
1127 PEMRPIXELFORMAT lpPixelFormat = (PEMRPIXELFORMAT)mr;
1129 iPixelFormat = ChoosePixelFormat( hdc, &lpPixelFormat->pfd );
1130 SetPixelFormat( hdc, iPixelFormat, &lpPixelFormat->pfd );
1132 break;
1135 case EMR_SETPALETTEENTRIES:
1137 PEMRSETPALETTEENTRIES lpSetPaletteEntries = (PEMRSETPALETTEENTRIES)mr;
1139 SetPaletteEntries( (handletable->objectHandle)[lpSetPaletteEntries->ihPal],
1140 (UINT)lpSetPaletteEntries->iStart,
1141 (UINT)lpSetPaletteEntries->cEntries,
1142 lpSetPaletteEntries->aPalEntries );
1144 break;
1147 case EMR_RESIZEPALETTE:
1149 PEMRRESIZEPALETTE lpResizePalette = (PEMRRESIZEPALETTE)mr;
1151 ResizePalette( (handletable->objectHandle)[lpResizePalette->ihPal],
1152 (UINT)lpResizePalette->cEntries );
1154 break;
1157 case EMR_CREATEDIBPATTERNBRUSHPT:
1159 PEMRCREATEDIBPATTERNBRUSHPT lpCreate = (PEMRCREATEDIBPATTERNBRUSHPT)mr;
1161 /* This is a BITMAPINFO struct followed directly by bitmap bits */
1162 LPVOID lpPackedStruct = HeapAlloc( GetProcessHeap(),
1164 lpCreate->cbBmi + lpCreate->cbBits );
1165 /* Now pack this structure */
1166 memcpy( lpPackedStruct,
1167 ((BYTE*)lpCreate) + lpCreate->offBmi,
1168 lpCreate->cbBmi );
1169 memcpy( ((BYTE*)lpPackedStruct) + lpCreate->cbBmi,
1170 ((BYTE*)lpCreate) + lpCreate->offBits,
1171 lpCreate->cbBits );
1173 (handletable->objectHandle)[lpCreate->ihBrush] =
1174 CreateDIBPatternBrushPt( lpPackedStruct,
1175 (UINT)lpCreate->iUsage );
1177 break;
1180 case EMR_BITBLT:
1181 case EMR_STRETCHBLT:
1182 case EMR_MASKBLT:
1183 case EMR_PLGBLT:
1184 case EMR_SETDIBITSTODEVICE:
1185 case EMR_EXTTEXTOUTA:
1186 case EMR_POLYBEZIER16:
1187 case EMR_POLYBEZIERTO16:
1188 case EMR_POLYLINETO16:
1189 case EMR_POLYPOLYLINE16:
1190 case EMR_POLYPOLYGON16:
1191 case EMR_POLYDRAW16:
1192 case EMR_CREATEMONOBRUSH:
1193 case EMR_POLYTEXTOUTA:
1194 case EMR_POLYTEXTOUTW:
1195 case EMR_FILLRGN:
1196 case EMR_FRAMERGN:
1197 case EMR_INVERTRGN:
1198 case EMR_PAINTRGN:
1199 case EMR_GLSRECORD:
1200 case EMR_GLSBOUNDEDRECORD:
1201 default:
1202 /* From docs: If PlayEnhMetaFileRecord doesn't recognize a
1203 record then ignore and return TRUE. */
1204 FIXME("type %d is unimplemented\n", type);
1205 break;
1207 return TRUE;
1211 /*****************************************************************************
1213 * EnumEnhMetaFile32 (GDI32.79)
1215 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
1216 * for each
1217 * record. Returns when either every record has been used or
1218 * when _EnhMetaFunc_ returns FALSE.
1221 * RETURNS
1222 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
1223 * returns FALSE.
1225 * BUGS
1226 * Ignores rect.
1228 BOOL WINAPI EnumEnhMetaFile(
1229 HDC hdc, /* device context to pass to _EnhMetaFunc_ */
1230 HENHMETAFILE hmf, /* EMF to walk */
1231 ENHMFENUMPROC callback, /* callback function */
1232 LPVOID data, /* optional data for callback function */
1233 const RECT *rect /* bounding rectangle for rendered metafile */
1236 BOOL ret = TRUE;
1237 LPENHMETARECORD p = (LPENHMETARECORD) EMF_GetEnhMetaHeader(hmf);
1238 INT count;
1239 HANDLETABLE *ht;
1241 if(!p) return FALSE;
1242 count = ((LPENHMETAHEADER) p)->nHandles;
1243 ht = HeapAlloc( GetProcessHeap(), 0, sizeof(HANDLETABLE)*count);
1244 ht->objectHandle[0] = hmf;
1245 while (ret) {
1246 ret = (*callback)(hdc, ht, p, count, data);
1247 if (p->iType == EMR_EOF) break;
1248 p = (LPENHMETARECORD) ((char *) p + p->nSize);
1250 HeapFree( GetProcessHeap(), 0, ht);
1251 EMF_ReleaseEnhMetaHeader(hmf);
1252 return ret;
1256 /**************************************************************************
1257 * PlayEnhMetaFile (GDI32.263)
1259 * Renders an enhanced metafile into a specified rectangle *lpRect
1260 * in device context hdc.
1262 * BUGS
1263 * Almost entirely unimplemented
1266 BOOL WINAPI PlayEnhMetaFile(
1267 HDC hdc, /* DC to render into */
1268 HENHMETAFILE hmf, /* metafile to render */
1269 const RECT *lpRect /* rectangle to place metafile inside */
1272 LPENHMETARECORD p = (LPENHMETARECORD) EMF_GetEnhMetaHeader(hmf);
1273 INT count;
1274 HANDLETABLE *ht;
1275 BOOL ret = FALSE;
1276 INT savedMode = 0;
1278 if(!p) return FALSE;
1279 count = ((LPENHMETAHEADER) p)->nHandles;
1280 ht = HeapAlloc( GetProcessHeap(), 0, sizeof(HANDLETABLE) * count);
1281 if (lpRect) {
1282 LPENHMETAHEADER h = (LPENHMETAHEADER) p;
1283 FLOAT xscale = (h->rclBounds.right - h->rclBounds.left) /
1284 (lpRect->right - lpRect->left);
1285 FLOAT yscale = (h->rclBounds.bottom - h->rclBounds.top) /
1286 (lpRect->bottom - lpRect->top);
1287 XFORM xform;
1288 xform.eM11 = xscale;
1289 xform.eM12 = 0;
1290 xform.eM21 = 0;
1291 xform.eM22 = yscale;
1292 xform.eDx = lpRect->left;
1293 xform.eDy = lpRect->top;
1294 FIXME("play into rect doesn't work\n");
1295 savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
1296 if (!SetWorldTransform(hdc, &xform)) {
1297 WARN("World transform failed!\n");
1301 ht->objectHandle[0] = hmf;
1302 while (1) {
1303 PlayEnhMetaFileRecord(hdc, ht, p, count);
1304 if (p->iType == EMR_EOF) break;
1305 p = (LPENHMETARECORD) ((char *) p + p->nSize); /* casted so that arithmetic is in bytes */
1307 HeapFree( GetProcessHeap(), 0, ht );
1308 EMF_ReleaseEnhMetaHeader(hmf);
1309 if (savedMode) SetGraphicsMode(hdc, savedMode);
1310 ret = TRUE; /* FIXME: calculate a more accurate return value */
1311 return ret;
1314 /*****************************************************************************
1315 * DeleteEnhMetaFile (GDI32.68)
1317 * Deletes an enhanced metafile and frees the associated storage.
1319 BOOL WINAPI DeleteEnhMetaFile(HENHMETAFILE hmf)
1321 return EMF_Delete_HENHMETAFILE( hmf );
1324 /*****************************************************************************
1325 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
1329 HENHMETAFILE WINAPI CopyEnhMetaFileA(
1330 HENHMETAFILE hmfSrc,
1331 LPCSTR file)
1333 ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst;
1334 HENHMETAFILE hmfDst;
1336 if(!emrSrc) return FALSE;
1337 if (!file) {
1338 emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes );
1339 memcpy( emrDst, emrSrc, emrSrc->nBytes );
1340 hmfDst = EMF_Create_HENHMETAFILE( emrDst, 0, 0 );
1341 } else {
1342 HFILE hFile;
1343 hFile = CreateFileA( file, GENERIC_WRITE | GENERIC_READ, 0, NULL,
1344 CREATE_ALWAYS, 0, -1);
1345 WriteFile( hFile, emrSrc, emrSrc->nBytes, 0, 0);
1346 hmfDst = EMF_GetEnhMetaFile( hFile );
1348 EMF_ReleaseEnhMetaHeader( hmfSrc );
1349 return hmfDst;
1353 /* Struct to be used to be passed in the LPVOID parameter for cbEnhPaletteCopy */
1354 typedef struct tagEMF_PaletteCopy
1356 UINT cEntries;
1357 LPPALETTEENTRY lpPe;
1358 } EMF_PaletteCopy;
1360 /***************************************************************
1361 * Find the EMR_EOF record and then use it to find the
1362 * palette entries for this enhanced metafile.
1363 * The lpData is actually a pointer to a EMF_PaletteCopy struct
1364 * which contains the max number of elements to copy and where
1365 * to copy them to.
1367 * NOTE: To be used by GetEnhMetaFilePaletteEntries only!
1369 INT CALLBACK cbEnhPaletteCopy( HDC a,
1370 LPHANDLETABLE b,
1371 LPENHMETARECORD lpEMR,
1372 INT c,
1373 LPVOID lpData )
1376 if ( lpEMR->iType == EMR_EOF )
1378 PEMREOF lpEof = (PEMREOF)lpEMR;
1379 EMF_PaletteCopy* info = (EMF_PaletteCopy*)lpData;
1380 DWORD dwNumPalToCopy = min( lpEof->nPalEntries, info->cEntries );
1382 TRACE( "copying 0x%08lx palettes\n", dwNumPalToCopy );
1384 memcpy( (LPVOID)info->lpPe,
1385 (LPVOID)(((LPSTR)lpEof) + lpEof->offPalEntries),
1386 sizeof( *(info->lpPe) ) * dwNumPalToCopy );
1388 /* Update the passed data as a return code */
1389 info->lpPe = NULL; /* Palettes were copied! */
1390 info->cEntries = (UINT)dwNumPalToCopy;
1392 return FALSE; /* That's all we need */
1395 return TRUE;
1398 /*****************************************************************************
1399 * GetEnhMetaFilePaletteEntries (GDI32.179)
1401 * Copy the palette and report size
1403 * BUGS: Error codes (SetLastError) are not set on failures
1405 UINT WINAPI GetEnhMetaFilePaletteEntries( HENHMETAFILE hEmf,
1406 UINT cEntries,
1407 LPPALETTEENTRY lpPe )
1409 ENHMETAHEADER* enhHeader = EMF_GetEnhMetaHeader( hEmf );
1410 UINT uReturnValue = GDI_ERROR;
1411 EMF_PaletteCopy infoForCallBack;
1413 TRACE( "(%04x,%d,%p)\n", hEmf, cEntries, lpPe );
1415 /* First check if there are any palettes associated with
1416 this metafile. */
1417 if ( enhHeader->nPalEntries == 0 )
1419 /* No palette associated with this enhanced metafile */
1420 uReturnValue = 0;
1421 goto done;
1424 /* Is the user requesting the number of palettes? */
1425 if ( lpPe == NULL )
1427 uReturnValue = (UINT)enhHeader->nPalEntries;
1428 goto done;
1431 /* Copy cEntries worth of PALETTEENTRY structs into the buffer */
1432 infoForCallBack.cEntries = cEntries;
1433 infoForCallBack.lpPe = lpPe;
1435 if ( !EnumEnhMetaFile( 0, hEmf, cbEnhPaletteCopy,
1436 &infoForCallBack, NULL ) )
1438 goto done;
1441 /* Verify that the callback executed correctly */
1442 if ( infoForCallBack.lpPe != NULL )
1444 /* Callback proc had error! */
1445 ERR( "cbEnhPaletteCopy didn't execute correctly\n" );
1446 goto done;
1449 uReturnValue = infoForCallBack.cEntries;
1451 done:
1453 EMF_ReleaseEnhMetaHeader( hEmf );
1455 return uReturnValue;
1458 /******************************************************************
1459 * SetWinMetaFileBits (GDI32.343)
1461 * Translate from old style to new style.
1463 * BUGS: - This doesn't take the DC and scaling into account
1464 * - Most record conversions aren't implemented
1465 * - Handle slot assignement is primative and most likely doesn't work
1467 HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
1468 CONST BYTE *lpbBuffer,
1469 HDC hdcRef,
1470 CONST METAFILEPICT *lpmfp
1473 HENHMETAFILE hMf;
1474 LPVOID lpNewEnhMetaFileBuffer = NULL;
1475 UINT uNewEnhMetaFileBufferSize = 0;
1476 BOOL bFoundEOF = FALSE;
1478 FIXME( "(%d,%p,%04x,%p):stub\n", cbBuffer, lpbBuffer, hdcRef, lpmfp );
1480 /* 1. Get the header - skip over this and get straight to the records */
1482 uNewEnhMetaFileBufferSize = sizeof( ENHMETAHEADER );
1483 lpNewEnhMetaFileBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1484 uNewEnhMetaFileBufferSize );
1486 if( lpNewEnhMetaFileBuffer == NULL )
1488 goto error;
1491 /* Fill in the header record */
1493 LPENHMETAHEADER lpNewEnhMetaFileHeader = (LPENHMETAHEADER)lpNewEnhMetaFileBuffer;
1495 lpNewEnhMetaFileHeader->iType = EMR_HEADER;
1496 lpNewEnhMetaFileHeader->nSize = sizeof( ENHMETAHEADER );
1498 /* FIXME: Not right. Must be able to get this from the DC */
1499 lpNewEnhMetaFileHeader->rclBounds.left = 0;
1500 lpNewEnhMetaFileHeader->rclBounds.right = 0;
1501 lpNewEnhMetaFileHeader->rclBounds.top = 0;
1502 lpNewEnhMetaFileHeader->rclBounds.bottom = 0;
1504 /* FIXME: Not right. Must be able to get this from the DC */
1505 lpNewEnhMetaFileHeader->rclFrame.left = 0;
1506 lpNewEnhMetaFileHeader->rclFrame.right = 0;
1507 lpNewEnhMetaFileHeader->rclFrame.top = 0;
1508 lpNewEnhMetaFileHeader->rclFrame.bottom = 0;
1510 lpNewEnhMetaFileHeader->nHandles = 0; /* No handles yet */
1512 /* FIXME: Add in the rest of the fields to the header */
1513 /* dSignature
1514 nVersion
1515 nRecords
1516 sReserved
1517 nDescription
1518 offDescription
1519 nPalEntries
1520 szlDevice
1521 szlMillimeters
1522 cbPixelFormat
1523 offPixelFormat,
1524 bOpenGL */
1527 (char*)lpbBuffer += ((METAHEADER*)lpbBuffer)->mtHeaderSize * 2; /* Point past the header - FIXME: metafile quirk? */
1529 /* 2. Enum over individual records and convert them to the new type of records */
1530 while( !bFoundEOF )
1533 LPMETARECORD lpMetaRecord = (LPMETARECORD)lpbBuffer;
1535 #define EMF_ReAllocAndAdjustPointers( a , b ) \
1537 LPVOID lpTmp; \
1538 lpTmp = HeapReAlloc( GetProcessHeap(), 0, \
1539 lpNewEnhMetaFileBuffer, \
1540 uNewEnhMetaFileBufferSize + (b) ); \
1541 if( lpTmp == NULL ) { ERR( "No memory!\n" ); goto error; } \
1542 lpNewEnhMetaFileBuffer = lpTmp; \
1543 lpRecord = (a)( (char*)lpNewEnhMetaFileBuffer + uNewEnhMetaFileBufferSize ); \
1544 uNewEnhMetaFileBufferSize += (b); \
1547 switch( lpMetaRecord->rdFunction )
1549 case META_EOF:
1551 PEMREOF lpRecord;
1552 size_t uRecord = sizeof(*lpRecord);
1554 EMF_ReAllocAndAdjustPointers(PEMREOF,uRecord);
1556 /* Fill the new record - FIXME: This is not right */
1557 lpRecord->emr.iType = EMR_EOF;
1558 lpRecord->emr.nSize = sizeof( *lpRecord );
1559 lpRecord->nPalEntries = 0; /* FIXME */
1560 lpRecord->offPalEntries = 0; /* FIXME */
1561 lpRecord->nSizeLast = 0; /* FIXME */
1563 /* No more records after this one */
1564 bFoundEOF = TRUE;
1566 FIXME( "META_EOF conversion not correct\n" );
1567 break;
1570 case META_SETMAPMODE:
1572 PEMRSETMAPMODE lpRecord;
1573 size_t uRecord = sizeof(*lpRecord);
1575 EMF_ReAllocAndAdjustPointers(PEMRSETMAPMODE,uRecord);
1577 lpRecord->emr.iType = EMR_SETMAPMODE;
1578 lpRecord->emr.nSize = sizeof( *lpRecord );
1580 lpRecord->iMode = lpMetaRecord->rdParm[0];
1582 break;
1585 case META_DELETEOBJECT: /* Select and Delete structures are the same */
1586 case META_SELECTOBJECT:
1588 PEMRDELETEOBJECT lpRecord;
1589 size_t uRecord = sizeof(*lpRecord);
1591 EMF_ReAllocAndAdjustPointers(PEMRDELETEOBJECT,uRecord);
1593 if( lpMetaRecord->rdFunction == META_DELETEOBJECT )
1595 lpRecord->emr.iType = EMR_DELETEOBJECT;
1597 else
1599 lpRecord->emr.iType = EMR_SELECTOBJECT;
1601 lpRecord->emr.nSize = sizeof( *lpRecord );
1603 lpRecord->ihObject = lpMetaRecord->rdParm[0]; /* FIXME: Handle */
1605 break;
1608 case META_POLYGON: /* This is just plain busted. I don't know what I'm doing */
1610 PEMRPOLYGON16 lpRecord; /* FIXME: Should it be a poly or poly16? */
1611 size_t uRecord = sizeof(*lpRecord);
1613 EMF_ReAllocAndAdjustPointers(PEMRPOLYGON16,uRecord);
1615 /* FIXME: This is mostly all wrong */
1616 lpRecord->emr.iType = EMR_POLYGON16;
1617 lpRecord->emr.nSize = sizeof( *lpRecord );
1619 lpRecord->rclBounds.left = 0;
1620 lpRecord->rclBounds.right = 0;
1621 lpRecord->rclBounds.top = 0;
1622 lpRecord->rclBounds.bottom = 0;
1624 lpRecord->cpts = 0;
1625 lpRecord->apts[0].x = 0;
1626 lpRecord->apts[0].y = 0;
1628 FIXME( "META_POLYGON conversion not correct\n" );
1630 break;
1633 case META_SETPOLYFILLMODE:
1635 PEMRSETPOLYFILLMODE lpRecord;
1636 size_t uRecord = sizeof(*lpRecord);
1638 EMF_ReAllocAndAdjustPointers(PEMRSETPOLYFILLMODE,uRecord);
1640 lpRecord->emr.iType = EMR_SETPOLYFILLMODE;
1641 lpRecord->emr.nSize = sizeof( *lpRecord );
1643 lpRecord->iMode = lpMetaRecord->rdParm[0];
1645 break;
1648 case META_SETWINDOWORG:
1650 PEMRSETWINDOWORGEX lpRecord; /* Seems to be the closest thing */
1651 size_t uRecord = sizeof(*lpRecord);
1653 EMF_ReAllocAndAdjustPointers(PEMRSETWINDOWORGEX,uRecord);
1655 lpRecord->emr.iType = EMR_SETWINDOWORGEX;
1656 lpRecord->emr.nSize = sizeof( *lpRecord );
1658 lpRecord->ptlOrigin.x = lpMetaRecord->rdParm[1];
1659 lpRecord->ptlOrigin.y = lpMetaRecord->rdParm[0];
1661 break;
1664 case META_SETWINDOWEXT: /* Structure is the same for SETWINDOWEXT & SETVIEWPORTEXT */
1665 case META_SETVIEWPORTEXT:
1667 PEMRSETWINDOWEXTEX lpRecord;
1668 size_t uRecord = sizeof(*lpRecord);
1670 EMF_ReAllocAndAdjustPointers(PEMRSETWINDOWEXTEX,uRecord);
1672 if ( lpMetaRecord->rdFunction == META_SETWINDOWEXT )
1674 lpRecord->emr.iType = EMR_SETWINDOWORGEX;
1676 else
1678 lpRecord->emr.iType = EMR_SETVIEWPORTEXTEX;
1680 lpRecord->emr.nSize = sizeof( *lpRecord );
1682 lpRecord->szlExtent.cx = lpMetaRecord->rdParm[1];
1683 lpRecord->szlExtent.cy = lpMetaRecord->rdParm[0];
1685 break;
1688 case META_CREATEBRUSHINDIRECT:
1690 PEMRCREATEBRUSHINDIRECT lpRecord;
1691 size_t uRecord = sizeof(*lpRecord);
1693 EMF_ReAllocAndAdjustPointers(PEMRCREATEBRUSHINDIRECT,uRecord);
1695 lpRecord->emr.iType = EMR_CREATEBRUSHINDIRECT;
1696 lpRecord->emr.nSize = sizeof( *lpRecord );
1698 lpRecord->ihBrush = ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nHandles;
1699 lpRecord->lb.lbStyle = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbStyle;
1700 lpRecord->lb.lbColor = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbColor;
1701 lpRecord->lb.lbHatch = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbHatch;
1703 ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nHandles += 1; /* New handle */
1705 break;
1709 /* These are all unimplemented and as such are intended to fall through to the default case */
1710 case META_SETBKCOLOR:
1711 case META_SETBKMODE:
1712 case META_SETROP2:
1713 case META_SETRELABS:
1714 case META_SETSTRETCHBLTMODE:
1715 case META_SETTEXTCOLOR:
1716 case META_SETVIEWPORTORG:
1717 case META_OFFSETWINDOWORG:
1718 case META_SCALEWINDOWEXT:
1719 case META_OFFSETVIEWPORTORG:
1720 case META_SCALEVIEWPORTEXT:
1721 case META_LINETO:
1722 case META_MOVETO:
1723 case META_EXCLUDECLIPRECT:
1724 case META_INTERSECTCLIPRECT:
1725 case META_ARC:
1726 case META_ELLIPSE:
1727 case META_FLOODFILL:
1728 case META_PIE:
1729 case META_RECTANGLE:
1730 case META_ROUNDRECT:
1731 case META_PATBLT:
1732 case META_SAVEDC:
1733 case META_SETPIXEL:
1734 case META_OFFSETCLIPRGN:
1735 case META_TEXTOUT:
1736 case META_POLYPOLYGON:
1737 case META_POLYLINE:
1738 case META_RESTOREDC:
1739 case META_CHORD:
1740 case META_CREATEPATTERNBRUSH:
1741 case META_CREATEPENINDIRECT:
1742 case META_CREATEFONTINDIRECT:
1743 case META_CREATEPALETTE:
1744 case META_SETTEXTALIGN:
1745 case META_SELECTPALETTE:
1746 case META_SETMAPPERFLAGS:
1747 case META_REALIZEPALETTE:
1748 case META_ESCAPE:
1749 case META_EXTTEXTOUT:
1750 case META_STRETCHDIB:
1751 case META_DIBSTRETCHBLT:
1752 case META_STRETCHBLT:
1753 case META_BITBLT:
1754 case META_CREATEREGION:
1755 case META_FILLREGION:
1756 case META_FRAMEREGION:
1757 case META_INVERTREGION:
1758 case META_PAINTREGION:
1759 case META_SELECTCLIPREGION:
1760 case META_DIBCREATEPATTERNBRUSH:
1761 case META_DIBBITBLT:
1762 case META_SETTEXTCHAREXTRA:
1763 case META_SETTEXTJUSTIFICATION:
1764 case META_EXTFLOODFILL:
1765 case META_SETDIBTODEV:
1766 case META_DRAWTEXT:
1767 case META_ANIMATEPALETTE:
1768 case META_SETPALENTRIES:
1769 case META_RESIZEPALETTE:
1770 case META_RESETDC:
1771 case META_STARTDOC:
1772 case META_STARTPAGE:
1773 case META_ENDPAGE:
1774 case META_ABORTDOC:
1775 case META_ENDDOC:
1776 case META_CREATEBRUSH:
1777 case META_CREATEBITMAPINDIRECT:
1778 case META_CREATEBITMAP:
1779 /* Fall through to unimplemented */
1780 default:
1782 /* Not implemented yet */
1783 FIXME( "Conversion of record type 0x%x not implemented.\n", lpMetaRecord->rdFunction );
1784 break;
1788 /* Move to the next record */
1789 (char*)lpbBuffer += ((LPMETARECORD)lpbBuffer)->rdSize * 2; /* FIXME: Seem to be doing this in metafile.c */
1791 #undef ReAllocAndAdjustPointers
1794 /* We know the last of the header information now */
1795 ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nBytes = uNewEnhMetaFileBufferSize;
1797 /* Create the enhanced metafile */
1798 hMf = SetEnhMetaFileBits( uNewEnhMetaFileBufferSize, (const BYTE*)lpNewEnhMetaFileBuffer );
1800 if( !hMf )
1801 ERR( "Problem creating metafile. Did the conversion fail somewhere?\n" );
1803 return hMf;
1805 error:
1806 /* Free the data associated with our copy since it's been copied */
1807 HeapFree( GetProcessHeap(), 0, lpNewEnhMetaFileBuffer );
1809 return 0;