4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
10 * These functions are primarily involved with metafile playback or anything
11 * that touches a HMETAFILE.
12 * For recording of metafiles look in graphics/metafiledrv/
14 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
15 * global memory handles so these cannot be interchanged.
17 * Memory-based metafiles are just stored as a continuous block of memory with
18 * a METAHEADER at the head with METARECORDs appended to it. mtType is
19 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
20 * disk-based metafile - even mtType is METAFILE_MEMORY.
21 * 16bit HMETAFILE16s are global handles to this block
22 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
24 * Disk-based metafiles are rather different. HMETAFILE16s point to a
25 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
26 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
27 * more 0, then 2 which may be a time stamp of the file and then the path of
28 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
36 #include "wine/winbase16.h"
41 #include "debugtools.h"
44 DEFAULT_DEBUG_CHANNEL(metafile)
46 /******************************************************************
49 * Add a handle to an external handle table and return the index
51 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
55 for (i = 0; i < htlen; i++)
57 if (*(ht->objectHandle + i) == 0)
59 *(ht->objectHandle + i) = hobj;
67 /******************************************************************
68 * MF_Create_HMETATFILE
70 * Creates a (32 bit) HMETAFILE object from a METAHEADER
72 * HMETAFILEs are GDI objects.
74 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
76 HMETAFILE hmf = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC );
77 METAFILEOBJ *metaObj = (METAFILEOBJ *)GDI_HEAP_LOCK( hmf );
79 GDI_HEAP_UNLOCK( hmf );
83 /******************************************************************
84 * MF_Create_HMETATFILE16
86 * Creates a HMETAFILE16 object from a METAHEADER
88 * HMETAFILE16s are Global memory handles.
90 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
95 if(mh->mtType == METAFILE_MEMORY)
96 size = mh->mtSize * sizeof(WORD);
98 size = sizeof(METAHEADER) + sizeof(METAHEADERDISK);
100 hmf = GLOBAL_CreateBlock( GMEM_MOVEABLE, mh, mh->mtSize * sizeof(WORD),
101 GetCurrentPDB16(), FALSE, FALSE, FALSE, NULL );
105 /******************************************************************
108 * Returns ptr to METAHEADER associated with HMETAFILE
109 * Should be followed by call to MF_ReleaseMetaHeader
111 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
113 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
114 return metaObj ? metaObj->mh : 0;
117 /******************************************************************
120 * Returns ptr to METAHEADER associated with HMETAFILE16
121 * Should be followed by call to MF_ReleaseMetaHeader16
123 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
125 return GlobalLock16(hmf);
128 /******************************************************************
129 * MF_ReleaseMetaHeader
131 * Releases METAHEADER associated with HMETAFILE
133 static BOOL MF_ReleaseMetaHeader( HMETAFILE hmf )
135 return GDI_HEAP_UNLOCK( hmf );
138 /******************************************************************
139 * MF_ReleaseMetaHeader16
141 * Releases METAHEADER associated with HMETAFILE16
143 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
145 return GlobalUnlock16( hmf );
149 /******************************************************************
150 * DeleteMetaFile16 (GDI.127)
152 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
154 return !GlobalFree16( hmf );
157 /******************************************************************
158 * DeleteMetaFile (GDI32.69)
160 * Delete a memory-based metafile.
163 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
165 METAHEADER *mh = MF_GetMetaHeader( hmf );
167 if(!mh) return FALSE;
168 HeapFree( SystemHeap, 0, mh );
169 GDI_FreeObject( hmf );
173 /******************************************************************
176 * Returns a pointer to a memory based METAHEADER read in from file HFILE
179 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
182 DWORD BytesRead, size;
184 size = sizeof(METAHEADER);
185 mh = HeapAlloc( SystemHeap, 0, size );
187 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
189 HeapFree( SystemHeap, 0, mh );
192 size = mh->mtSize * 2;
193 mh = HeapReAlloc( SystemHeap, 0, mh, size );
195 size -= sizeof(METAHEADER);
196 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
199 HeapFree( SystemHeap, 0, mh );
203 if (mh->mtType != METAFILE_MEMORY) {
204 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
205 mh->mtType = METAFILE_MEMORY;
210 /******************************************************************
211 * GetMetaFile16 (GDI.124)
213 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
218 TRACE("%s\n", lpFilename);
223 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
224 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
227 mh = MF_ReadMetaFile(hFile);
230 return MF_Create_HMETAFILE16( mh );
233 /******************************************************************
234 * GetMetaFileA (GDI32.197)
236 * Read a metafile from a file. Returns handle to a memory-based metafile.
238 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
243 TRACE("%s\n", lpFilename);
248 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
249 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
252 mh = MF_ReadMetaFile(hFile);
255 return MF_Create_HMETAFILE( mh );
260 /******************************************************************
261 * GetMetaFileW (GDI32.199)
263 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
268 TRACE("%s\n", debugstr_w(lpFilename));
273 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
274 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
277 mh = MF_ReadMetaFile(hFile);
280 return MF_Create_HMETAFILE( mh );
284 /******************************************************************
285 * MF_LoadDiskBasedMetaFile
287 * Creates a new memory-based metafile from a disk-based one.
289 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
295 if(mh->mtType != METAFILE_DISK) {
296 ERR("Not a disk based metafile\n");
299 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
301 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
302 OPEN_EXISTING, 0, -1)) == HFILE_ERROR) {
303 WARN("Can't open file of disk based metafile\n");
306 mh2 = MF_ReadMetaFile(hfile);
311 /******************************************************************
312 * MF_CreateMetaHeaderDisk
314 * Take a memory based METAHEADER and change it to a disk based METAHEADER
315 * assosiated with filename. Note: Trashes contents of old one.
317 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
322 mh = HeapReAlloc( SystemHeap, 0, mh,
323 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
324 mh->mtType = METAFILE_DISK;
325 size = HeapSize( SystemHeap, 0, mh );
326 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
327 strcpy(mhd->filename, filename);
331 /******************************************************************
332 * CopyMetaFile16 (GDI.151)
334 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
336 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
337 METAHEADER *mh2 = NULL;
340 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
344 if(mh->mtType == METAFILE_DISK)
345 mh2 = MF_LoadDiskBasedMetaFile(mh);
347 mh2 = HeapAlloc( SystemHeap, 0, mh->mtSize * 2 );
348 memcpy( mh2, mh, mh->mtSize * 2 );
350 MF_ReleaseMetaHeader16( hSrcMetaFile );
352 if(lpFilename) { /* disk based metafile */
353 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
354 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
355 HeapFree( SystemHeap, 0, mh2 );
358 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
360 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
363 return MF_Create_HMETAFILE16( mh2 );
367 /******************************************************************
368 * CopyMetaFileA (GDI32.23)
370 * Copies the metafile corresponding to hSrcMetaFile to either
371 * a disk file, if a filename is given, or to a new memory based
372 * metafile, if lpFileName is NULL.
376 * Handle to metafile copy on success, NULL on failure.
380 * Copying to disk returns NULL even if successful.
382 HMETAFILE WINAPI CopyMetaFileA(
383 HMETAFILE hSrcMetaFile, /* handle of metafile to copy */
384 LPCSTR lpFilename /* filename if copying to a file */
386 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
387 METAHEADER *mh2 = NULL;
390 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
394 if(mh->mtType == METAFILE_DISK)
395 mh2 = MF_LoadDiskBasedMetaFile(mh);
397 mh2 = HeapAlloc( SystemHeap, 0, mh->mtSize * 2 );
398 memcpy( mh2, mh, mh->mtSize * 2 );
400 MF_ReleaseMetaHeader( hSrcMetaFile );
402 if(lpFilename) { /* disk based metafile */
403 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
404 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
405 HeapFree( SystemHeap, 0, mh2 );
408 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
410 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
413 return MF_Create_HMETAFILE( mh2 );
417 /******************************************************************
418 * CopyMetaFileW (GDI32.24)
420 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
423 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
424 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
425 HeapFree( GetProcessHeap(), 0, p );
430 /******************************************************************
431 * IsValidMetaFile (GDI.410)
433 * Attempts to check if a given metafile is correctly formatted.
434 * Currently, the only things verified are several properties of the
438 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
441 * This is not exactly what windows does, see _Undocumented_Windows_
444 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
447 METAHEADER *mh = MF_GetMetaHeader16(hmf);
449 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
450 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
451 if (mh->mtVersion == MFVERSION)
453 MF_ReleaseMetaHeader16(hmf);
455 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
460 /*******************************************************************
463 * Helper for PlayMetaFile
465 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
478 if (!mh) return FALSE;
479 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
480 mh = MF_LoadDiskBasedMetaFile(mh);
481 if(!mh) return FALSE;
485 /* save the current pen, brush and font */
486 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
488 hBrush = dc->w.hBrush;
490 GDI_HEAP_UNLOCK(hdc);
491 /* create the handle table */
492 ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY,
493 sizeof(HANDLETABLE16) * mh->mtNoObjects);
494 if(!ht) return FALSE;
496 /* loop through metafile playing records */
497 offset = mh->mtHeaderSize * 2;
498 while (offset < mh->mtSize * 2)
500 mr = (METARECORD *)((char *)mh + offset);
501 TRACE("offset=%04x,size=%08lx\n",
505 "Entry got size 0 at offset %d, total mf length is %ld\n",
506 offset,mh->mtSize*2);
507 break; /* would loop endlessly otherwise */
509 offset += mr->rdSize * 2;
510 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
513 SelectObject(hdc, hBrush);
514 SelectObject(hdc, hPen);
515 SelectObject(hdc, hFont);
517 /* free objects in handle table */
518 for(i = 0; i < mh->mtNoObjects; i++)
519 if(*(ht->objectHandle + i) != 0)
520 DeleteObject(*(ht->objectHandle + i));
522 /* free handle table */
523 HeapFree( SystemHeap, 0, ht );
525 HeapFree( SystemHeap, 0, mh );
529 /******************************************************************
530 * PlayMetaFile16 (GDI.123)
533 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
536 METAHEADER *mh = MF_GetMetaHeader16( hmf );
537 ret = MF_PlayMetaFile( hdc, mh );
538 MF_ReleaseMetaHeader16( hmf );
542 /******************************************************************
543 * PlayMetaFile (GDI32.265)
545 * Renders the metafile specified by hmf in the DC specified by
546 * hdc. Returns FALSE on failure, TRUE on success.
548 BOOL WINAPI PlayMetaFile(
549 HDC hdc, /* handle of DC to render in */
550 HMETAFILE hmf /* handle of metafile to render */
554 METAHEADER *mh = MF_GetMetaHeader( hmf );
555 ret = MF_PlayMetaFile( hdc, mh );
556 MF_ReleaseMetaHeader( hmf );
561 /******************************************************************
562 * EnumMetaFile16 (GDI.175)
565 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
566 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
568 METAHEADER *mh = MF_GetMetaHeader16(hmf);
579 BOOL16 result = TRUE, loaded = FALSE;
581 TRACE("(%04x, %04x, %08lx, %08lx)\n",
582 hdc, hmf, (DWORD)lpEnumFunc, lpData);
585 if(!mh) return FALSE;
586 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
587 mh = MF_LoadDiskBasedMetaFile(mh);
588 if(!mh) return FALSE;
592 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
594 hBrush = dc->w.hBrush;
596 GDI_HEAP_UNLOCK(hdc);
598 /* create the handle table */
600 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
601 sizeof(HANDLETABLE16) * mh->mtNoObjects);
602 spht = WIN16_GlobalLock16(hHT);
604 seg = GlobalHandleToSel16(hmf);
605 offset = mh->mtHeaderSize * 2;
607 /* loop through metafile records */
609 while (offset < (mh->mtSize * 2))
611 mr = (METARECORD *)((char *)mh + offset);
612 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
613 (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
614 mh->mtNoObjects, (LONG)lpData ))
621 offset += (mr->rdSize * 2);
624 SelectObject(hdc, hBrush);
625 SelectObject(hdc, hPen);
626 SelectObject(hdc, hFont);
628 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
630 /* free objects in handle table */
631 for(i = 0; i < mh->mtNoObjects; i++)
632 if(*(ht->objectHandle + i) != 0)
633 DeleteObject(*(ht->objectHandle + i));
635 /* free handle table */
638 HeapFree( SystemHeap, 0, mh );
639 MF_ReleaseMetaHeader16(hmf);
643 /******************************************************************
644 * EnumMetaFile (GDI32.88)
646 * Loop through the metafile records in hmf, calling the user-specified
647 * function for each one, stopping when the user's function returns FALSE
648 * (which is considered to be failure)
649 * or when no records are left (which is considered to be success).
652 * TRUE on success, FALSE on failure.
655 * Niels de carpentier, april 1996
657 BOOL WINAPI EnumMetaFile(
660 MFENUMPROC lpEnumFunc,
663 METAHEADER *mh = MF_GetMetaHeader(hmf);
666 BOOL result = TRUE, loaded = FALSE;
668 DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
673 TRACE("(%08x,%08x,%p,%p)\n",
674 hdc, hmf, lpEnumFunc, (void*)lpData);
676 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
677 mh = MF_LoadDiskBasedMetaFile(mh);
682 /* save the current pen, brush and font */
685 hBrush = dc->w.hBrush;
687 GDI_HEAP_UNLOCK(hdc);
690 ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY,
691 sizeof(HANDLETABLE) * mh->mtNoObjects);
693 /* loop through metafile records */
694 offset = mh->mtHeaderSize * 2;
696 while (offset < (mh->mtSize * 2))
698 mr = (METARECORD *)((char *)mh + offset);
699 TRACE("Calling EnumFunc with record type %x\n",
701 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
707 offset += (mr->rdSize * 2);
710 /* restore pen, brush and font */
711 SelectObject(hdc, hBrush);
712 SelectObject(hdc, hPen);
713 SelectObject(hdc, hFont);
715 /* free objects in handle table */
716 for(i = 0; i < mh->mtNoObjects; i++)
717 if(*(ht->objectHandle + i) != 0)
718 DeleteObject(*(ht->objectHandle + i));
720 /* free handle table */
721 HeapFree( SystemHeap, 0, ht);
723 HeapFree( SystemHeap, 0, mh );
724 MF_ReleaseMetaHeader(hmf);
728 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
729 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
730 /******************************************************************
731 * PlayMetaFileRecord16 (GDI.176)
733 * Render a single metafile record specified by *mr in the DC hdc, while
734 * using the handle table *ht, of length nHandles,
735 * to store metafile objects.
738 * The following metafile records are unimplemented:
740 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
741 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
742 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
745 void WINAPI PlayMetaFileRecord16(
746 HDC16 hdc, /* DC to render metafile into */
747 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
748 METARECORD *mr, /* pointer to metafile record to render */
749 UINT16 nHandles /* size of handle table */
754 BITMAPINFOHEADER *infohdr;
756 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
757 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
759 switch (mr->rdFunction)
764 case META_DELETEOBJECT:
765 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
766 *(ht->objectHandle + *(mr->rdParm)) = 0;
769 case META_SETBKCOLOR:
770 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
774 SetBkMode16(hdc, *(mr->rdParm));
777 case META_SETMAPMODE:
778 SetMapMode16(hdc, *(mr->rdParm));
782 SetROP216(hdc, *(mr->rdParm));
786 SetRelAbs16(hdc, *(mr->rdParm));
789 case META_SETPOLYFILLMODE:
790 SetPolyFillMode16(hdc, *(mr->rdParm));
793 case META_SETSTRETCHBLTMODE:
794 SetStretchBltMode16(hdc, *(mr->rdParm));
797 case META_SETTEXTCOLOR:
798 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
801 case META_SETWINDOWORG:
802 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
805 case META_SETWINDOWEXT:
806 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
809 case META_SETVIEWPORTORG:
810 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
813 case META_SETVIEWPORTEXT:
814 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
817 case META_OFFSETWINDOWORG:
818 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
821 case META_SCALEWINDOWEXT:
822 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
823 *(mr->rdParm + 1), *(mr->rdParm));
826 case META_OFFSETVIEWPORTORG:
827 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
830 case META_SCALEVIEWPORTEXT:
831 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
832 *(mr->rdParm + 1), *(mr->rdParm));
836 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
840 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
843 case META_EXCLUDECLIPRECT:
844 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
845 *(mr->rdParm + 1), *(mr->rdParm) );
848 case META_INTERSECTCLIPRECT:
849 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
850 *(mr->rdParm + 1), *(mr->rdParm) );
854 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
855 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
856 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
857 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
861 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
862 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
866 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
867 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
871 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
872 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
873 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
874 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
878 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
879 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
883 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
884 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
885 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
889 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
890 *(mr->rdParm + 3), *(mr->rdParm + 2),
891 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
899 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
900 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
903 case META_OFFSETCLIPRGN:
904 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
909 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
910 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
911 (char *)(mr->rdParm + 1), s1);
915 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
918 case META_POLYPOLYGON:
919 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
920 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
924 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
928 RestoreDC(hdc, (INT16)*(mr->rdParm));
931 case META_SELECTOBJECT:
932 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
936 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
937 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
938 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
939 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
942 case META_CREATEPATTERNBRUSH:
943 switch (*(mr->rdParm))
946 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
947 MF_AddHandle(ht, nHandles,
948 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
953 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
957 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
958 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
959 ptr = GlobalLock16(hndl);
960 memcpy(ptr, mr->rdParm + 2, s1);
961 GlobalUnlock16(hndl);
962 MF_AddHandle(ht, nHandles,
963 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
968 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
974 case META_CREATEPENINDIRECT:
975 MF_AddHandle(ht, nHandles,
976 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
979 case META_CREATEFONTINDIRECT:
980 MF_AddHandle(ht, nHandles,
981 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
984 case META_CREATEBRUSHINDIRECT:
985 MF_AddHandle(ht, nHandles,
986 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
989 case META_CREATEPALETTE:
990 MF_AddHandle(ht, nHandles,
991 CreatePalette16((LPLOGPALETTE)mr->rdParm));
994 case META_SETTEXTALIGN:
995 SetTextAlign16(hdc, *(mr->rdParm));
998 case META_SELECTPALETTE:
999 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1003 case META_SETMAPPERFLAGS:
1004 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1007 case META_REALIZEPALETTE:
1008 RealizePalette16(hdc);
1012 FIXME("META_ESCAPE unimplemented.\n");
1015 case META_EXTTEXTOUT:
1016 MF_Play_MetaExtTextOut( hdc, mr );
1019 case META_STRETCHDIB:
1021 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1022 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1023 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1024 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1025 mr->rdParm[4],mr->rdParm[3],bits,info,
1026 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1030 case META_DIBSTRETCHBLT:
1032 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1033 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1034 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1035 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1036 mr->rdParm[3],mr->rdParm[2],bits,info,
1037 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1041 case META_STRETCHBLT:
1043 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1044 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1045 mr->rdParm[11], /*Height*/
1046 mr->rdParm[13], /*Planes*/
1047 mr->rdParm[14], /*BitsPixel*/
1048 (LPSTR)&mr->rdParm[15]); /*bits*/
1049 SelectObject(hdcSrc,hbitmap);
1050 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1051 mr->rdParm[7],mr->rdParm[6],
1052 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1053 mr->rdParm[3],mr->rdParm[2],
1054 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1061 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1062 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1063 mr->rdParm[8]/*Height*/,
1064 mr->rdParm[10]/*Planes*/,
1065 mr->rdParm[11]/*BitsPixel*/,
1066 (LPSTR)&mr->rdParm[12]/*bits*/);
1067 SelectObject(hdcSrc,hbitmap);
1068 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1069 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1070 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1071 MAKELONG(0,mr->rdParm[0]));
1076 case META_CREATEREGION:
1078 HRGN hrgn = CreateRectRgn(0,0,0,0);
1080 MF_Play_MetaCreateRegion(mr, hrgn);
1081 MF_AddHandle(ht, nHandles, hrgn);
1085 case META_FILLREGION:
1086 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1087 *(ht->objectHandle + *(mr->rdParm)));
1090 case META_FRAMEREGION:
1091 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1092 *(ht->objectHandle + *(mr->rdParm+2)),
1093 *(mr->rdParm+1), *(mr->rdParm));
1096 case META_INVERTREGION:
1097 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1100 case META_PAINTREGION:
1101 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1104 case META_SELECTCLIPREGION:
1105 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1108 case META_DIBCREATEPATTERNBRUSH:
1109 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1110 but there's no difference */
1112 TRACE("%d\n",*(mr->rdParm));
1113 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1114 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1115 ptr = GlobalLock16(hndl);
1116 memcpy(ptr, mr->rdParm + 2, s1);
1117 GlobalUnlock16(hndl);
1118 MF_AddHandle(ht, nHandles,
1119 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1123 case META_DIBBITBLT:
1124 /* In practice I've found that there are two layouts for
1125 META_DIBBITBLT, one (the first here) is the usual one when a src
1126 dc is actually passed to it, the second occurs when the src dc is
1127 passed in as NULL to the creating BitBlt. As the second case has
1128 no dib, a size check will suffice to distinguish.
1130 Caolan.McNamara@ul.ie */
1132 if (mr->rdSize > 12) {
1133 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1134 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1136 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1137 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1138 mr->rdParm[5], mr->rdParm[4], bits, info,
1140 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1141 } else { /* equivalent to a PatBlt */
1142 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1143 mr->rdParm[6], mr->rdParm[5],
1144 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1148 case META_SETTEXTCHAREXTRA:
1149 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1152 case META_SETTEXTJUSTIFICATION:
1153 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1156 case META_EXTFLOODFILL:
1157 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1158 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1162 case META_SETDIBTODEV:
1164 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1165 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1166 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1167 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1168 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1169 mr->rdParm[2], mr->rdParm[1], bits, info,
1174 #define META_UNIMP(x) case x: \
1175 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1177 META_UNIMP(META_DRAWTEXT)
1178 META_UNIMP(META_ANIMATEPALETTE)
1179 META_UNIMP(META_SETPALENTRIES)
1180 META_UNIMP(META_RESIZEPALETTE)
1181 META_UNIMP(META_RESETDC)
1182 META_UNIMP(META_STARTDOC)
1183 META_UNIMP(META_STARTPAGE)
1184 META_UNIMP(META_ENDPAGE)
1185 META_UNIMP(META_ABORTDOC)
1186 META_UNIMP(META_ENDDOC)
1187 META_UNIMP(META_CREATEBRUSH)
1188 META_UNIMP(META_CREATEBITMAPINDIRECT)
1189 META_UNIMP(META_CREATEBITMAP)
1193 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1198 /******************************************************************
1199 * PlayMetaFileRecord (GDI32.266)
1201 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1202 METARECORD *metarecord, UINT handles )
1204 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1205 handles*sizeof(HANDLETABLE16));
1207 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1209 for (i=0; i<handles; i++)
1210 ht->objectHandle[i] = handletable->objectHandle[i];
1211 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1212 for (i=0; i<handles; i++)
1213 handletable->objectHandle[i] = ht->objectHandle[i];
1214 GlobalFree((HGLOBAL)ht);
1218 /******************************************************************
1219 * GetMetaFileBits (GDI.159)
1221 * Trade in a metafile object handle for a handle to the metafile memory.
1225 HGLOBAL16 WINAPI GetMetaFileBits16(
1226 HMETAFILE16 hmf /* metafile handle */
1229 TRACE("hMem out: %04x\n", hmf);
1233 /******************************************************************
1234 * SetMetaFileBits (GDI.160)
1236 * Trade in a metafile memory handle for a handle to a metafile object.
1237 * The memory region should hold a proper metafile, otherwise
1238 * problems will occur when it is used. Validity of the memory is not
1239 * checked. The function is essentially just the identity function.
1241 HMETAFILE16 WINAPI SetMetaFileBits16(
1243 /* handle to a memory region holding a metafile */
1246 TRACE("hmf out: %04x\n", hMem);
1251 /******************************************************************
1252 * SetMetaFileBitsBetter (GDI.196)
1254 * Trade in a metafile memory handle for a handle to a metafile object,
1255 * making a cursory check (using IsValidMetaFile()) that the memory
1256 * handle points to a valid metafile.
1259 * Handle to a metafile on success, NULL on failure..
1261 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1263 if( IsValidMetaFile16( hMeta ) )
1264 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1265 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1266 return (HMETAFILE16)0;
1269 /******************************************************************
1270 * SetMetaFileBitsEx (GDI32.323)
1272 * Create a metafile from raw data. No checking of the data is performed.
1273 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1275 HMETAFILE WINAPI SetMetaFileBitsEx(
1276 UINT size, /* size of metafile, in bytes */
1277 const BYTE *lpData /* pointer to metafile data */
1280 METAHEADER *mh = HeapAlloc( SystemHeap, 0, size );
1282 memcpy(mh, lpData, size);
1283 return MF_Create_HMETAFILE(mh);
1286 /*****************************************************************
1287 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1289 * Copies the data from metafile _hmf_ into the buffer _buf_.
1290 * If _buf_ is zero, returns size of buffer required. Otherwise,
1291 * returns number of bytes copied.
1293 UINT WINAPI GetMetaFileBitsEx(
1294 HMETAFILE hmf, /* metafile */
1295 UINT nSize, /* size of buf */
1296 LPVOID buf /* buffer to receive raw metafile data */
1298 METAHEADER *mh = MF_GetMetaHeader(hmf);
1301 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1302 if (!mh) return 0; /* FIXME: error code */
1303 if(mh->mtType == METAFILE_DISK)
1304 FIXME("Disk-based metafile?\n");
1305 mfSize = mh->mtSize * 2;
1307 MF_ReleaseMetaHeader(hmf);
1308 TRACE("returning size %d\n", mfSize);
1311 if(mfSize > nSize) mfSize = nSize;
1312 memmove(buf, mh, mfSize);
1313 MF_ReleaseMetaHeader(hmf);
1317 /******************************************************************
1318 * GetWinMetaFileBits [GDI32.241]
1320 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1321 UINT cbBuffer, LPBYTE lpbBuffer,
1322 INT fnMapMode, HDC hdcRef)
1324 FIXME("(%d,%d,%p,%d,%d): stub\n",
1325 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1329 /******************************************************************
1330 * MF_Play_MetaCreateRegion
1332 * Handles META_CREATEREGION for PlayMetaFileRecord().
1336 * The layout of the record looks something like this:
1341 * 2 Looks like a handle? - not constant
1343 * 4 Total number of bytes
1344 * 5 No. of seperate bands = n [see below]
1345 * 6 Largest number of x co-ords in a band
1346 * 7-10 Bounding box x1 y1 x2 y2
1349 * Regions are divided into bands that are uniform in the
1350 * y-direction. Each band consists of pairs of on/off x-coords and is
1352 * m y0 y1 x1 x2 x3 ... xm m
1353 * into successive rdParm[]s.
1355 * This is probably just a dump of the internal RGNOBJ?
1361 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1366 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1368 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1369 band++, start = end + 1) {
1370 if(*start / 2 != (*start + 1) / 2) {
1371 WARN("Delimiter not even.\n");
1372 DeleteObject( hrgn2 );
1376 end = start + *start + 3;
1377 if(end > (WORD *)mr + mr->rdSize) {
1378 WARN("End points outside record.\n");
1379 DeleteObject( hrgn2 );
1383 if(*start != *end) {
1384 WARN("Mismatched delimiters.\n");
1385 DeleteObject( hrgn2 );
1389 y0 = *(INT16 *)(start + 1);
1390 y1 = *(INT16 *)(start + 2);
1391 for(pair = 0; pair < *start / 2; pair++) {
1392 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1393 *(INT16 *)(start + 4 + 2*pair), y1 );
1394 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1397 DeleteObject( hrgn2 );
1402 /******************************************************************
1403 * MF_Play_MetaExtTextOut
1405 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1408 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1415 s1 = mr->rdParm[2]; /* String length */
1416 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1417 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1418 /* rec len without dx array */
1420 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1422 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1424 if (mr->rdSize == len / 2)
1425 dxx = NULL; /* determine if array present */
1427 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1428 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1430 TRACE("%s len: %ld\n", sot, mr->rdSize);
1432 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1433 len, s1, mr->rdSize, mr->rdParm[3]);
1434 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1436 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1437 mr->rdParm[0], /* Y position */
1438 mr->rdParm[3], /* options */
1439 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1442 s1, dxx); /* length, dx array */
1444 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);