4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * These functions are primarily involved with metafile playback or anything
24 * that touches a HMETAFILE.
25 * For recording of metafiles look in graphics/metafiledrv/
27 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
28 * global memory handles so these cannot be interchanged.
30 * Memory-based metafiles are just stored as a continuous block of memory with
31 * a METAHEADER at the head with METARECORDs appended to it. mtType is
32 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
33 * disk-based metafile - even mtType is METAFILE_MEMORY.
34 * 16bit HMETAFILE16s are global handles to this block
35 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
37 * Disk-based metafiles are rather different. HMETAFILE16s point to a
38 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
39 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
40 * more 0, then 2 which may be a time stamp of the file and then the path of
41 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
51 #include "wine/winbase16.h"
52 #include "wine/wingdi16.h"
57 #include "wine/debug.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
70 #define MFHEADERSIZE (sizeof(METAHEADER))
71 #define MFVERSION 0x300
73 /* ### start build ### */
74 extern WORD CALLBACK MF_CallTo16_word_wllwl(MFENUMPROC16,WORD,LONG,LONG,WORD,LONG);
75 /* ### stop build ### */
77 /******************************************************************
80 * Add a handle to an external handle table and return the index
82 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
86 for (i = 0; i < htlen; i++)
88 if (*(ht->objectHandle + i) == 0)
90 *(ht->objectHandle + i) = hobj;
98 /******************************************************************
99 * MF_Create_HMETATFILE
101 * Creates a (32 bit) HMETAFILE object from a METAHEADER
103 * HMETAFILEs are GDI objects.
105 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
108 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
112 GDI_ReleaseObj( hmf );
117 /******************************************************************
118 * MF_Create_HMETATFILE16
120 * Creates a HMETAFILE16 object from a METAHEADER
122 * HMETAFILE16s are Global memory handles.
124 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
127 DWORD size = mh->mtSize * sizeof(WORD);
129 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
132 METAHEADER *mh_dest = GlobalLock16(hmf);
133 memcpy(mh_dest, mh, size);
136 HeapFree(GetProcessHeap(), 0, mh);
140 /******************************************************************
143 * Returns ptr to METAHEADER associated with HMETAFILE
145 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
147 METAHEADER *ret = NULL;
148 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
152 GDI_ReleaseObj( hmf );
157 /******************************************************************
160 * Returns ptr to METAHEADER associated with HMETAFILE16
161 * Should be followed by call to MF_ReleaseMetaHeader16
163 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
165 return GlobalLock16(hmf);
168 /******************************************************************
169 * MF_ReleaseMetaHeader16
171 * Releases METAHEADER associated with HMETAFILE16
173 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
175 return GlobalUnlock16( hmf );
179 /******************************************************************
180 * DeleteMetaFile (GDI.127)
182 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
184 return !GlobalFree16( hmf );
187 /******************************************************************
188 * DeleteMetaFile (GDI32.@)
190 * Delete a memory-based metafile.
193 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
195 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
196 if (!metaObj) return FALSE;
197 HeapFree( GetProcessHeap(), 0, metaObj->mh );
198 GDI_FreeObject( hmf, metaObj );
202 /******************************************************************
205 * Returns a pointer to a memory based METAHEADER read in from file HFILE
208 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
211 DWORD BytesRead, size;
213 size = sizeof(METAHEADER);
214 mh = HeapAlloc( GetProcessHeap(), 0, size );
216 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
218 HeapFree( GetProcessHeap(), 0, mh );
221 size = mh->mtSize * 2;
222 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
224 size -= sizeof(METAHEADER);
225 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
228 HeapFree( GetProcessHeap(), 0, mh );
232 if (mh->mtType != METAFILE_MEMORY) {
233 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
234 mh->mtType = METAFILE_MEMORY;
239 /******************************************************************
240 * GetMetaFile (GDI.124)
242 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
247 TRACE("%s\n", lpFilename);
252 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
253 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
256 mh = MF_ReadMetaFile(hFile);
259 return MF_Create_HMETAFILE16( mh );
262 /******************************************************************
263 * GetMetaFileA (GDI32.@)
265 * Read a metafile from a file. Returns handle to a memory-based metafile.
267 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
272 TRACE("%s\n", lpFilename);
277 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
278 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
281 mh = MF_ReadMetaFile(hFile);
284 return MF_Create_HMETAFILE( mh );
289 /******************************************************************
290 * GetMetaFileW (GDI32.@)
292 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
297 TRACE("%s\n", debugstr_w(lpFilename));
302 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
303 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
306 mh = MF_ReadMetaFile(hFile);
309 return MF_Create_HMETAFILE( mh );
313 /******************************************************************
314 * MF_LoadDiskBasedMetaFile
316 * Creates a new memory-based metafile from a disk-based one.
318 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
324 if(mh->mtType != METAFILE_DISK) {
325 ERR("Not a disk based metafile\n");
328 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
330 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
331 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
332 WARN("Can't open file of disk based metafile\n");
335 mh2 = MF_ReadMetaFile(hfile);
340 /******************************************************************
341 * MF_CreateMetaHeaderDisk
343 * Take a memory based METAHEADER and change it to a disk based METAHEADER
344 * assosiated with filename. Note: Trashes contents of old one.
346 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
351 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
352 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
353 mh->mtType = METAFILE_DISK;
354 size = HeapSize( GetProcessHeap(), 0, mh );
355 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
356 strcpy(mhd->filename, filename);
360 /******************************************************************
361 * CopyMetaFile (GDI.151)
363 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
365 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
366 METAHEADER *mh2 = NULL;
369 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
373 if(mh->mtType == METAFILE_DISK)
374 mh2 = MF_LoadDiskBasedMetaFile(mh);
376 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
377 memcpy( mh2, mh, mh->mtSize * 2 );
379 MF_ReleaseMetaHeader16( hSrcMetaFile );
381 if(lpFilename) { /* disk based metafile */
382 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
383 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
384 HeapFree( GetProcessHeap(), 0, mh2 );
387 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
389 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
392 return MF_Create_HMETAFILE16( mh2 );
396 /******************************************************************
397 * CopyMetaFileA (GDI32.@)
399 * Copies the metafile corresponding to hSrcMetaFile to either
400 * a disk file, if a filename is given, or to a new memory based
401 * metafile, if lpFileName is NULL.
405 * Handle to metafile copy on success, NULL on failure.
409 * Copying to disk returns NULL even if successful.
411 HMETAFILE WINAPI CopyMetaFileA(
412 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
413 LPCSTR lpFilename /* [in] filename if copying to a file */
415 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
416 METAHEADER *mh2 = NULL;
419 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
423 if(mh->mtType == METAFILE_DISK)
424 mh2 = MF_LoadDiskBasedMetaFile(mh);
426 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
427 memcpy( mh2, mh, mh->mtSize * 2 );
430 if(lpFilename) { /* disk based metafile */
431 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
432 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
433 HeapFree( GetProcessHeap(), 0, mh2 );
436 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
438 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
441 return MF_Create_HMETAFILE( mh2 );
445 /******************************************************************
446 * CopyMetaFileW (GDI32.@)
448 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
452 DWORD len = WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, NULL, 0, NULL, NULL );
453 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
457 WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, p, len, NULL, NULL );
458 ret = CopyMetaFileA( hSrcMetaFile, p );
459 HeapFree( GetProcessHeap(), 0, p );
465 /******************************************************************
466 * IsValidMetaFile (GDI.410)
468 * Attempts to check if a given metafile is correctly formatted.
469 * Currently, the only things verified are several properties of the
473 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
476 * This is not exactly what windows does, see _Undocumented_Windows_
479 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
482 METAHEADER *mh = MF_GetMetaHeader16(hmf);
484 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
485 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
486 if (mh->mtVersion == MFVERSION)
488 MF_ReleaseMetaHeader16(hmf);
490 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
495 /*******************************************************************
498 * Helper for PlayMetaFile
500 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
505 unsigned int offset = 0;
512 if (!mh) return FALSE;
513 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
514 mh = MF_LoadDiskBasedMetaFile(mh);
515 if(!mh) return FALSE;
519 /* save the current pen, brush and font */
520 hPen = GetCurrentObject(hdc, OBJ_PEN);
521 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
522 hFont = GetCurrentObject(hdc, OBJ_FONT);
524 /* create the handle table */
525 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
526 sizeof(HANDLETABLE16) * mh->mtNoObjects);
527 if(!ht) return FALSE;
529 /* loop through metafile playing records */
530 offset = mh->mtHeaderSize * 2;
531 while (offset < mh->mtSize * 2)
533 mr = (METARECORD *)((char *)mh + offset);
534 TRACE("offset=%04x,size=%08lx\n",
538 "Entry got size 0 at offset %d, total mf length is %ld\n",
539 offset,mh->mtSize*2);
540 break; /* would loop endlessly otherwise */
542 offset += mr->rdSize * 2;
543 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
546 SelectObject(hdc, hBrush);
547 SelectObject(hdc, hPen);
548 SelectObject(hdc, hFont);
550 /* free objects in handle table */
551 for(i = 0; i < mh->mtNoObjects; i++)
552 if(*(ht->objectHandle + i) != 0)
553 DeleteObject(*(ht->objectHandle + i));
555 /* free handle table */
556 HeapFree( GetProcessHeap(), 0, ht );
558 HeapFree( GetProcessHeap(), 0, mh );
562 /******************************************************************
563 * PlayMetaFile (GDI.123)
566 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
569 METAHEADER *mh = MF_GetMetaHeader16( hmf );
570 ret = MF_PlayMetaFile( hdc, mh );
571 MF_ReleaseMetaHeader16( hmf );
575 /******************************************************************
576 * PlayMetaFile (GDI32.@)
578 * Renders the metafile specified by hmf in the DC specified by
579 * hdc. Returns FALSE on failure, TRUE on success.
581 BOOL WINAPI PlayMetaFile(
582 HDC hdc, /* [in] handle of DC to render in */
583 HMETAFILE hmf /* [in] handle of metafile to render */
586 METAHEADER *mh = MF_GetMetaHeader( hmf );
587 return MF_PlayMetaFile( hdc, mh );
591 /******************************************************************
592 * EnumMetaFile (GDI.175)
595 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
596 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
598 METAHEADER *mh = MF_GetMetaHeader16(hmf);
603 unsigned int offset = 0;
608 BOOL16 result = TRUE, loaded = FALSE;
610 TRACE("(%04x, %04x, %08lx, %08lx)\n",
611 hdc, hmf, (DWORD)lpEnumFunc, lpData);
614 if(!mh) return FALSE;
615 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
616 mh = MF_LoadDiskBasedMetaFile(mh);
617 if(!mh) return FALSE;
621 /* save the current pen, brush and font */
622 hPen = GetCurrentObject(hdc, OBJ_PEN);
623 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
624 hFont = GetCurrentObject(hdc, OBJ_FONT);
626 /* create the handle table */
628 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
629 sizeof(HANDLETABLE16) * mh->mtNoObjects);
630 spht = K32WOWGlobalLock16(hHT);
633 offset = mh->mtHeaderSize * 2;
635 /* loop through metafile records */
637 while (offset < (mh->mtSize * 2))
639 mr = (METARECORD *)((char *)mh + offset);
641 if (!MF_CallTo16_word_wllwl( lpEnumFunc, hdc, spht,
642 MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
643 mh->mtNoObjects, (LONG)lpData ))
650 offset += (mr->rdSize * 2);
653 SelectObject(hdc, hBrush);
654 SelectObject(hdc, hPen);
655 SelectObject(hdc, hFont);
657 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
659 /* free objects in handle table */
660 for(i = 0; i < mh->mtNoObjects; i++)
661 if(*(ht->objectHandle + i) != 0)
662 DeleteObject(*(ht->objectHandle + i));
664 /* free handle table */
667 HeapFree( GetProcessHeap(), 0, mh );
668 MF_ReleaseMetaHeader16(hmf);
672 /******************************************************************
673 * EnumMetaFile (GDI32.@)
675 * Loop through the metafile records in hmf, calling the user-specified
676 * function for each one, stopping when the user's function returns FALSE
677 * (which is considered to be failure)
678 * or when no records are left (which is considered to be success).
681 * TRUE on success, FALSE on failure.
684 * Niels de carpentier, april 1996
686 BOOL WINAPI EnumMetaFile(
689 MFENUMPROC lpEnumFunc,
692 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
697 unsigned int offset = 0;
702 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
704 if(mh->mtType == METAFILE_DISK)
706 /* Create a memory-based copy */
707 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
711 /* save the current pen, brush and font */
712 hPen = GetCurrentObject(hdc, OBJ_PEN);
713 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
714 hFont = GetCurrentObject(hdc, OBJ_FONT);
716 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
717 sizeof(HANDLETABLE) * mh->mtNoObjects);
719 /* loop through metafile records */
720 offset = mh->mtHeaderSize * 2;
722 while (offset < (mh->mtSize * 2))
724 mr = (METARECORD *)((char *)mh + offset);
725 if(mr->rdFunction == META_EOF) {
726 TRACE("Got META_EOF so stopping\n");
729 TRACE("Calling EnumFunc with record type %x\n",
731 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
737 offset += (mr->rdSize * 2);
740 /* restore pen, brush and font */
741 SelectObject(hdc, hBrush);
742 SelectObject(hdc, hPen);
743 SelectObject(hdc, hFont);
745 /* free objects in handle table */
746 for(i = 0; i < mh->mtNoObjects; i++)
747 if(*(ht->objectHandle + i) != 0)
748 DeleteObject(*(ht->objectHandle + i));
750 /* free handle table */
751 HeapFree( GetProcessHeap(), 0, ht);
752 /* free a copy of metafile */
753 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
757 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
758 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
759 /******************************************************************
760 * PlayMetaFileRecord (GDI.176)
762 * Render a single metafile record specified by *mr in the DC hdc, while
763 * using the handle table *ht, of length nHandles,
764 * to store metafile objects.
767 * The following metafile records are unimplemented:
769 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
770 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
771 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
774 void WINAPI PlayMetaFileRecord16(
775 HDC16 hdc, /* [in] DC to render metafile into */
776 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
777 METARECORD *mr, /* [in] pointer to metafile record to render */
778 UINT16 nHandles /* [in] size of handle table */
783 BITMAPINFOHEADER *infohdr;
785 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
786 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
788 switch (mr->rdFunction)
793 case META_DELETEOBJECT:
794 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
795 *(ht->objectHandle + *(mr->rdParm)) = 0;
798 case META_SETBKCOLOR:
799 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
803 SetBkMode16(hdc, *(mr->rdParm));
806 case META_SETMAPMODE:
807 SetMapMode16(hdc, *(mr->rdParm));
811 SetROP216(hdc, *(mr->rdParm));
815 SetRelAbs16(hdc, *(mr->rdParm));
818 case META_SETPOLYFILLMODE:
819 SetPolyFillMode16(hdc, *(mr->rdParm));
822 case META_SETSTRETCHBLTMODE:
823 SetStretchBltMode16(hdc, *(mr->rdParm));
826 case META_SETTEXTCOLOR:
827 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
830 case META_SETWINDOWORG:
831 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
834 case META_SETWINDOWEXT:
835 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
838 case META_SETVIEWPORTORG:
839 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
842 case META_SETVIEWPORTEXT:
843 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
846 case META_OFFSETWINDOWORG:
847 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
850 case META_SCALEWINDOWEXT:
851 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
852 *(mr->rdParm + 1), *(mr->rdParm));
855 case META_OFFSETVIEWPORTORG:
856 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
859 case META_SCALEVIEWPORTEXT:
860 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
861 *(mr->rdParm + 1), *(mr->rdParm));
865 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
869 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
872 case META_EXCLUDECLIPRECT:
873 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
874 *(mr->rdParm + 1), *(mr->rdParm) );
877 case META_INTERSECTCLIPRECT:
878 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
879 *(mr->rdParm + 1), *(mr->rdParm) );
883 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
884 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
885 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
886 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
890 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
891 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
895 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
896 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
900 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
901 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
902 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
903 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
907 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
908 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
912 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
913 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
914 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
918 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
919 *(mr->rdParm + 3), *(mr->rdParm + 2),
920 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
928 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
929 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
932 case META_OFFSETCLIPRGN:
933 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
938 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
939 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
940 (char *)(mr->rdParm + 1), s1);
944 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
947 case META_POLYPOLYGON:
948 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
949 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
953 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
957 RestoreDC(hdc, (INT16)*(mr->rdParm));
960 case META_SELECTOBJECT:
961 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
965 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
966 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
967 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
968 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
971 case META_CREATEPATTERNBRUSH:
972 switch (*(mr->rdParm))
975 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
976 MF_AddHandle(ht, nHandles,
977 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
982 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
986 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
987 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
988 ptr = GlobalLock16(hndl);
989 memcpy(ptr, mr->rdParm + 2, s1);
990 GlobalUnlock16(hndl);
991 MF_AddHandle(ht, nHandles,
992 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
997 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1003 case META_CREATEPENINDIRECT:
1004 MF_AddHandle(ht, nHandles,
1005 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
1008 case META_CREATEFONTINDIRECT:
1009 MF_AddHandle(ht, nHandles,
1010 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
1013 case META_CREATEBRUSHINDIRECT:
1014 MF_AddHandle(ht, nHandles,
1015 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1018 case META_CREATEPALETTE:
1019 MF_AddHandle(ht, nHandles,
1020 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1023 case META_SETTEXTALIGN:
1024 SetTextAlign16(hdc, *(mr->rdParm));
1027 case META_SELECTPALETTE:
1028 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1032 case META_SETMAPPERFLAGS:
1033 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1036 case META_REALIZEPALETTE:
1037 GDIRealizePalette16(hdc);
1041 FIXME("META_ESCAPE unimplemented.\n");
1044 case META_EXTTEXTOUT:
1045 MF_Play_MetaExtTextOut( hdc, mr );
1048 case META_STRETCHDIB:
1050 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1051 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1052 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1053 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1054 mr->rdParm[4],mr->rdParm[3],bits,info,
1055 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1059 case META_DIBSTRETCHBLT:
1061 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1062 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1063 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1064 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1065 mr->rdParm[3],mr->rdParm[2],bits,info,
1066 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1070 case META_STRETCHBLT:
1072 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1073 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1074 mr->rdParm[11], /*Height*/
1075 mr->rdParm[13], /*Planes*/
1076 mr->rdParm[14], /*BitsPixel*/
1077 (LPSTR)&mr->rdParm[15]); /*bits*/
1078 SelectObject(hdcSrc,hbitmap);
1079 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1080 mr->rdParm[7],mr->rdParm[6],
1081 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1082 mr->rdParm[3],mr->rdParm[2],
1083 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1090 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1091 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1092 mr->rdParm[8]/*Height*/,
1093 mr->rdParm[10]/*Planes*/,
1094 mr->rdParm[11]/*BitsPixel*/,
1095 (LPSTR)&mr->rdParm[12]/*bits*/);
1096 SelectObject(hdcSrc,hbitmap);
1097 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1098 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1099 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1100 MAKELONG(0,mr->rdParm[0]));
1105 case META_CREATEREGION:
1107 HRGN hrgn = CreateRectRgn(0,0,0,0);
1109 MF_Play_MetaCreateRegion(mr, hrgn);
1110 MF_AddHandle(ht, nHandles, hrgn);
1114 case META_FILLREGION:
1115 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1116 *(ht->objectHandle + *(mr->rdParm)));
1119 case META_FRAMEREGION:
1120 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1121 *(ht->objectHandle + *(mr->rdParm+2)),
1122 *(mr->rdParm+1), *(mr->rdParm));
1125 case META_INVERTREGION:
1126 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1129 case META_PAINTREGION:
1130 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1133 case META_SELECTCLIPREGION:
1134 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1137 case META_DIBCREATEPATTERNBRUSH:
1138 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1139 but there's no difference */
1141 TRACE("%d\n",*(mr->rdParm));
1142 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1143 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1144 ptr = GlobalLock16(hndl);
1145 memcpy(ptr, mr->rdParm + 2, s1);
1146 GlobalUnlock16(hndl);
1147 MF_AddHandle(ht, nHandles,
1148 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1152 case META_DIBBITBLT:
1153 /* In practice I've found that there are two layouts for
1154 META_DIBBITBLT, one (the first here) is the usual one when a src
1155 dc is actually passed to it, the second occurs when the src dc is
1156 passed in as NULL to the creating BitBlt. As the second case has
1157 no dib, a size check will suffice to distinguish.
1159 Caolan.McNamara@ul.ie */
1161 if (mr->rdSize > 12) {
1162 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1163 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1165 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1166 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1167 mr->rdParm[5], mr->rdParm[4], bits, info,
1169 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1170 } else { /* equivalent to a PatBlt */
1171 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1172 mr->rdParm[6], mr->rdParm[5],
1173 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1177 case META_SETTEXTCHAREXTRA:
1178 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1181 case META_SETTEXTJUSTIFICATION:
1182 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1185 case META_EXTFLOODFILL:
1186 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1187 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1191 case META_SETDIBTODEV:
1193 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1194 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1195 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1196 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1197 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1198 mr->rdParm[2], mr->rdParm[1], bits, info,
1203 #define META_UNIMP(x) case x: \
1204 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1206 META_UNIMP(META_DRAWTEXT)
1207 META_UNIMP(META_ANIMATEPALETTE)
1208 META_UNIMP(META_SETPALENTRIES)
1209 META_UNIMP(META_RESIZEPALETTE)
1210 META_UNIMP(META_RESETDC)
1211 META_UNIMP(META_STARTDOC)
1212 META_UNIMP(META_STARTPAGE)
1213 META_UNIMP(META_ENDPAGE)
1214 META_UNIMP(META_ABORTDOC)
1215 META_UNIMP(META_ENDDOC)
1216 META_UNIMP(META_CREATEBRUSH)
1217 META_UNIMP(META_CREATEBITMAPINDIRECT)
1218 META_UNIMP(META_CREATEBITMAP)
1222 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1227 /******************************************************************
1228 * PlayMetaFileRecord (GDI32.@)
1230 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1231 METARECORD *metarecord, UINT handles )
1233 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1234 handles*sizeof(HANDLETABLE16));
1236 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1238 for (i=0; i<handles; i++)
1239 ht->objectHandle[i] = handletable->objectHandle[i];
1240 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1241 for (i=0; i<handles; i++)
1242 handletable->objectHandle[i] = ht->objectHandle[i];
1243 GlobalFree((HGLOBAL)ht);
1247 /******************************************************************
1248 * GetMetaFileBits (GDI.159)
1250 * Trade in a metafile object handle for a handle to the metafile memory.
1254 HGLOBAL16 WINAPI GetMetaFileBits16(
1255 HMETAFILE16 hmf /* [in] metafile handle */
1258 TRACE("hMem out: %04x\n", hmf);
1262 /******************************************************************
1263 * SetMetaFileBits (GDI.160)
1265 * Trade in a metafile memory handle for a handle to a metafile object.
1266 * The memory region should hold a proper metafile, otherwise
1267 * problems will occur when it is used. Validity of the memory is not
1268 * checked. The function is essentially just the identity function.
1270 HMETAFILE16 WINAPI SetMetaFileBits16(
1272 /* [in] handle to a memory region holding a metafile */
1275 TRACE("hmf out: %04x\n", hMem);
1280 /******************************************************************
1281 * SetMetaFileBitsBetter (GDI.196)
1283 * Trade in a metafile memory handle for a handle to a metafile object,
1284 * making a cursory check (using IsValidMetaFile()) that the memory
1285 * handle points to a valid metafile.
1288 * Handle to a metafile on success, NULL on failure..
1290 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1292 if( IsValidMetaFile16( hMeta ) )
1293 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1294 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1295 return (HMETAFILE16)0;
1298 /******************************************************************
1299 * SetMetaFileBitsEx (GDI32.@)
1301 * Create a metafile from raw data. No checking of the data is performed.
1302 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1304 HMETAFILE WINAPI SetMetaFileBitsEx(
1305 UINT size, /* [in] size of metafile, in bytes */
1306 const BYTE *lpData /* [in] pointer to metafile data */
1309 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1311 memcpy(mh, lpData, size);
1312 return MF_Create_HMETAFILE(mh);
1315 /*****************************************************************
1316 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1318 * Copies the data from metafile _hmf_ into the buffer _buf_.
1319 * If _buf_ is zero, returns size of buffer required. Otherwise,
1320 * returns number of bytes copied.
1322 UINT WINAPI GetMetaFileBitsEx(
1323 HMETAFILE hmf, /* [in] metafile */
1324 UINT nSize, /* [in] size of buf */
1325 LPVOID buf /* [out] buffer to receive raw metafile data */
1327 METAHEADER *mh = MF_GetMetaHeader(hmf);
1330 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1331 if (!mh) return 0; /* FIXME: error code */
1332 if(mh->mtType == METAFILE_DISK)
1333 FIXME("Disk-based metafile?\n");
1334 mfSize = mh->mtSize * 2;
1336 TRACE("returning size %d\n", mfSize);
1339 if(mfSize > nSize) mfSize = nSize;
1340 memmove(buf, mh, mfSize);
1344 /******************************************************************
1345 * GetWinMetaFileBits [GDI32.@]
1347 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1348 UINT cbBuffer, LPBYTE lpbBuffer,
1349 INT fnMapMode, HDC hdcRef)
1351 FIXME("(%d,%d,%p,%d,%d): stub\n",
1352 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1356 /******************************************************************
1357 * MF_Play_MetaCreateRegion
1359 * Handles META_CREATEREGION for PlayMetaFileRecord().
1363 * The layout of the record looks something like this:
1368 * 2 Looks like a handle? - not constant
1370 * 4 Total number of bytes
1371 * 5 No. of separate bands = n [see below]
1372 * 6 Largest number of x co-ords in a band
1373 * 7-10 Bounding box x1 y1 x2 y2
1376 * Regions are divided into bands that are uniform in the
1377 * y-direction. Each band consists of pairs of on/off x-coords and is
1379 * m y0 y1 x1 x2 x3 ... xm m
1380 * into successive rdParm[]s.
1382 * This is probably just a dump of the internal RGNOBJ?
1388 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1393 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1395 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1396 band++, start = end + 1) {
1397 if(*start / 2 != (*start + 1) / 2) {
1398 WARN("Delimiter not even.\n");
1399 DeleteObject( hrgn2 );
1403 end = start + *start + 3;
1404 if(end > (WORD *)mr + mr->rdSize) {
1405 WARN("End points outside record.\n");
1406 DeleteObject( hrgn2 );
1410 if(*start != *end) {
1411 WARN("Mismatched delimiters.\n");
1412 DeleteObject( hrgn2 );
1416 y0 = *(INT16 *)(start + 1);
1417 y1 = *(INT16 *)(start + 2);
1418 for(pair = 0; pair < *start / 2; pair++) {
1419 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1420 *(INT16 *)(start + 4 + 2*pair), y1 );
1421 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1424 DeleteObject( hrgn2 );
1429 /******************************************************************
1430 * MF_Play_MetaExtTextOut
1432 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1435 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1442 s1 = mr->rdParm[2]; /* String length */
1443 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1444 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1445 /* rec len without dx array */
1447 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1449 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1451 if (mr->rdSize == len / 2)
1452 dxx = NULL; /* determine if array present */
1454 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1455 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1457 TRACE("%s len: %ld\n", sot, mr->rdSize);
1459 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1460 len, s1, mr->rdSize, mr->rdParm[3]);
1461 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1463 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1464 mr->rdParm[0], /* Y position */
1465 mr->rdParm[3], /* options */
1466 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1469 s1, dxx); /* length, dx array */
1471 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);