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)
477 if (!mh) return FALSE;
478 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
479 mh = MF_LoadDiskBasedMetaFile(mh);
480 if(!mh) return FALSE;
484 /* save the current pen, brush and font */
485 hPen = GetCurrentObject(hdc, OBJ_PEN);
486 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
487 hFont = GetCurrentObject(hdc, OBJ_FONT);
489 /* create the handle table */
490 ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY,
491 sizeof(HANDLETABLE16) * mh->mtNoObjects);
492 if(!ht) return FALSE;
494 /* loop through metafile playing records */
495 offset = mh->mtHeaderSize * 2;
496 while (offset < mh->mtSize * 2)
498 mr = (METARECORD *)((char *)mh + offset);
499 TRACE("offset=%04x,size=%08lx\n",
503 "Entry got size 0 at offset %d, total mf length is %ld\n",
504 offset,mh->mtSize*2);
505 break; /* would loop endlessly otherwise */
507 offset += mr->rdSize * 2;
508 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
511 SelectObject(hdc, hBrush);
512 SelectObject(hdc, hPen);
513 SelectObject(hdc, hFont);
515 /* free objects in handle table */
516 for(i = 0; i < mh->mtNoObjects; i++)
517 if(*(ht->objectHandle + i) != 0)
518 DeleteObject(*(ht->objectHandle + i));
520 /* free handle table */
521 HeapFree( SystemHeap, 0, ht );
523 HeapFree( SystemHeap, 0, mh );
527 /******************************************************************
528 * PlayMetaFile16 (GDI.123)
531 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
534 METAHEADER *mh = MF_GetMetaHeader16( hmf );
535 ret = MF_PlayMetaFile( hdc, mh );
536 MF_ReleaseMetaHeader16( hmf );
540 /******************************************************************
541 * PlayMetaFile (GDI32.265)
543 * Renders the metafile specified by hmf in the DC specified by
544 * hdc. Returns FALSE on failure, TRUE on success.
546 BOOL WINAPI PlayMetaFile(
547 HDC hdc, /* handle of DC to render in */
548 HMETAFILE hmf /* handle of metafile to render */
552 METAHEADER *mh = MF_GetMetaHeader( hmf );
553 ret = MF_PlayMetaFile( hdc, mh );
554 MF_ReleaseMetaHeader( hmf );
559 /******************************************************************
560 * EnumMetaFile16 (GDI.175)
563 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
564 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
566 METAHEADER *mh = MF_GetMetaHeader16(hmf);
576 BOOL16 result = TRUE, loaded = FALSE;
578 TRACE("(%04x, %04x, %08lx, %08lx)\n",
579 hdc, hmf, (DWORD)lpEnumFunc, lpData);
582 if(!mh) return FALSE;
583 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
584 mh = MF_LoadDiskBasedMetaFile(mh);
585 if(!mh) return FALSE;
589 /* save the current pen, brush and font */
590 hPen = GetCurrentObject(hdc, OBJ_PEN);
591 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
592 hFont = GetCurrentObject(hdc, OBJ_FONT);
594 /* create the handle table */
596 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
597 sizeof(HANDLETABLE16) * mh->mtNoObjects);
598 spht = WIN16_GlobalLock16(hHT);
600 seg = GlobalHandleToSel16(hmf);
601 offset = mh->mtHeaderSize * 2;
603 /* loop through metafile records */
605 while (offset < (mh->mtSize * 2))
607 mr = (METARECORD *)((char *)mh + offset);
608 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
609 (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
610 mh->mtNoObjects, (LONG)lpData ))
617 offset += (mr->rdSize * 2);
620 SelectObject(hdc, hBrush);
621 SelectObject(hdc, hPen);
622 SelectObject(hdc, hFont);
624 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
626 /* free objects in handle table */
627 for(i = 0; i < mh->mtNoObjects; i++)
628 if(*(ht->objectHandle + i) != 0)
629 DeleteObject(*(ht->objectHandle + i));
631 /* free handle table */
634 HeapFree( SystemHeap, 0, mh );
635 MF_ReleaseMetaHeader16(hmf);
639 /******************************************************************
640 * EnumMetaFile (GDI32.88)
642 * Loop through the metafile records in hmf, calling the user-specified
643 * function for each one, stopping when the user's function returns FALSE
644 * (which is considered to be failure)
645 * or when no records are left (which is considered to be success).
648 * TRUE on success, FALSE on failure.
651 * Niels de carpentier, april 1996
653 BOOL WINAPI EnumMetaFile(
656 MFENUMPROC lpEnumFunc,
659 METAHEADER *mh = MF_GetMetaHeader(hmf);
662 BOOL result = TRUE, loaded = FALSE;
668 TRACE("(%08x,%08x,%p,%p)\n",
669 hdc, hmf, lpEnumFunc, (void*)lpData);
671 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
672 mh = MF_LoadDiskBasedMetaFile(mh);
677 /* save the current pen, brush and font */
678 hPen = GetCurrentObject(hdc, OBJ_PEN);
679 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
680 hFont = GetCurrentObject(hdc, OBJ_FONT);
682 ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY,
683 sizeof(HANDLETABLE) * mh->mtNoObjects);
685 /* loop through metafile records */
686 offset = mh->mtHeaderSize * 2;
688 while (offset < (mh->mtSize * 2))
690 mr = (METARECORD *)((char *)mh + offset);
691 TRACE("Calling EnumFunc with record type %x\n",
693 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
699 offset += (mr->rdSize * 2);
702 /* restore pen, brush and font */
703 SelectObject(hdc, hBrush);
704 SelectObject(hdc, hPen);
705 SelectObject(hdc, hFont);
707 /* free objects in handle table */
708 for(i = 0; i < mh->mtNoObjects; i++)
709 if(*(ht->objectHandle + i) != 0)
710 DeleteObject(*(ht->objectHandle + i));
712 /* free handle table */
713 HeapFree( SystemHeap, 0, ht);
715 HeapFree( SystemHeap, 0, mh );
716 MF_ReleaseMetaHeader(hmf);
720 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
721 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
722 /******************************************************************
723 * PlayMetaFileRecord16 (GDI.176)
725 * Render a single metafile record specified by *mr in the DC hdc, while
726 * using the handle table *ht, of length nHandles,
727 * to store metafile objects.
730 * The following metafile records are unimplemented:
732 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
733 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
734 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
737 void WINAPI PlayMetaFileRecord16(
738 HDC16 hdc, /* DC to render metafile into */
739 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
740 METARECORD *mr, /* pointer to metafile record to render */
741 UINT16 nHandles /* size of handle table */
746 BITMAPINFOHEADER *infohdr;
748 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
749 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
751 switch (mr->rdFunction)
756 case META_DELETEOBJECT:
757 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
758 *(ht->objectHandle + *(mr->rdParm)) = 0;
761 case META_SETBKCOLOR:
762 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
766 SetBkMode16(hdc, *(mr->rdParm));
769 case META_SETMAPMODE:
770 SetMapMode16(hdc, *(mr->rdParm));
774 SetROP216(hdc, *(mr->rdParm));
778 SetRelAbs16(hdc, *(mr->rdParm));
781 case META_SETPOLYFILLMODE:
782 SetPolyFillMode16(hdc, *(mr->rdParm));
785 case META_SETSTRETCHBLTMODE:
786 SetStretchBltMode16(hdc, *(mr->rdParm));
789 case META_SETTEXTCOLOR:
790 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
793 case META_SETWINDOWORG:
794 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
797 case META_SETWINDOWEXT:
798 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
801 case META_SETVIEWPORTORG:
802 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
805 case META_SETVIEWPORTEXT:
806 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
809 case META_OFFSETWINDOWORG:
810 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
813 case META_SCALEWINDOWEXT:
814 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
815 *(mr->rdParm + 1), *(mr->rdParm));
818 case META_OFFSETVIEWPORTORG:
819 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
822 case META_SCALEVIEWPORTEXT:
823 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
824 *(mr->rdParm + 1), *(mr->rdParm));
828 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
832 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
835 case META_EXCLUDECLIPRECT:
836 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
837 *(mr->rdParm + 1), *(mr->rdParm) );
840 case META_INTERSECTCLIPRECT:
841 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
842 *(mr->rdParm + 1), *(mr->rdParm) );
846 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
847 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
848 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
849 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
853 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
854 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
858 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
859 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
863 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
864 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
865 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
866 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
870 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
871 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
875 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
876 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
877 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
881 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
882 *(mr->rdParm + 3), *(mr->rdParm + 2),
883 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
891 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
892 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
895 case META_OFFSETCLIPRGN:
896 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
901 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
902 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
903 (char *)(mr->rdParm + 1), s1);
907 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
910 case META_POLYPOLYGON:
911 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
912 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
916 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
920 RestoreDC(hdc, (INT16)*(mr->rdParm));
923 case META_SELECTOBJECT:
924 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
928 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
929 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
930 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
931 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
934 case META_CREATEPATTERNBRUSH:
935 switch (*(mr->rdParm))
938 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
939 MF_AddHandle(ht, nHandles,
940 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
945 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
949 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
950 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
951 ptr = GlobalLock16(hndl);
952 memcpy(ptr, mr->rdParm + 2, s1);
953 GlobalUnlock16(hndl);
954 MF_AddHandle(ht, nHandles,
955 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
960 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
966 case META_CREATEPENINDIRECT:
967 MF_AddHandle(ht, nHandles,
968 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
971 case META_CREATEFONTINDIRECT:
972 MF_AddHandle(ht, nHandles,
973 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
976 case META_CREATEBRUSHINDIRECT:
977 MF_AddHandle(ht, nHandles,
978 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
981 case META_CREATEPALETTE:
982 MF_AddHandle(ht, nHandles,
983 CreatePalette16((LPLOGPALETTE)mr->rdParm));
986 case META_SETTEXTALIGN:
987 SetTextAlign16(hdc, *(mr->rdParm));
990 case META_SELECTPALETTE:
991 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
995 case META_SETMAPPERFLAGS:
996 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
999 case META_REALIZEPALETTE:
1000 RealizePalette16(hdc);
1004 FIXME("META_ESCAPE unimplemented.\n");
1007 case META_EXTTEXTOUT:
1008 MF_Play_MetaExtTextOut( hdc, mr );
1011 case META_STRETCHDIB:
1013 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1014 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1015 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1016 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1017 mr->rdParm[4],mr->rdParm[3],bits,info,
1018 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1022 case META_DIBSTRETCHBLT:
1024 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1025 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1026 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1027 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1028 mr->rdParm[3],mr->rdParm[2],bits,info,
1029 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1033 case META_STRETCHBLT:
1035 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1036 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1037 mr->rdParm[11], /*Height*/
1038 mr->rdParm[13], /*Planes*/
1039 mr->rdParm[14], /*BitsPixel*/
1040 (LPSTR)&mr->rdParm[15]); /*bits*/
1041 SelectObject(hdcSrc,hbitmap);
1042 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1043 mr->rdParm[7],mr->rdParm[6],
1044 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1045 mr->rdParm[3],mr->rdParm[2],
1046 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1053 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1054 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1055 mr->rdParm[8]/*Height*/,
1056 mr->rdParm[10]/*Planes*/,
1057 mr->rdParm[11]/*BitsPixel*/,
1058 (LPSTR)&mr->rdParm[12]/*bits*/);
1059 SelectObject(hdcSrc,hbitmap);
1060 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1061 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1062 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1063 MAKELONG(0,mr->rdParm[0]));
1068 case META_CREATEREGION:
1070 HRGN hrgn = CreateRectRgn(0,0,0,0);
1072 MF_Play_MetaCreateRegion(mr, hrgn);
1073 MF_AddHandle(ht, nHandles, hrgn);
1077 case META_FILLREGION:
1078 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1079 *(ht->objectHandle + *(mr->rdParm)));
1082 case META_FRAMEREGION:
1083 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1084 *(ht->objectHandle + *(mr->rdParm+2)),
1085 *(mr->rdParm+1), *(mr->rdParm));
1088 case META_INVERTREGION:
1089 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1092 case META_PAINTREGION:
1093 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1096 case META_SELECTCLIPREGION:
1097 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1100 case META_DIBCREATEPATTERNBRUSH:
1101 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1102 but there's no difference */
1104 TRACE("%d\n",*(mr->rdParm));
1105 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1106 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1107 ptr = GlobalLock16(hndl);
1108 memcpy(ptr, mr->rdParm + 2, s1);
1109 GlobalUnlock16(hndl);
1110 MF_AddHandle(ht, nHandles,
1111 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1115 case META_DIBBITBLT:
1116 /* In practice I've found that there are two layouts for
1117 META_DIBBITBLT, one (the first here) is the usual one when a src
1118 dc is actually passed to it, the second occurs when the src dc is
1119 passed in as NULL to the creating BitBlt. As the second case has
1120 no dib, a size check will suffice to distinguish.
1122 Caolan.McNamara@ul.ie */
1124 if (mr->rdSize > 12) {
1125 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1126 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1128 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1129 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1130 mr->rdParm[5], mr->rdParm[4], bits, info,
1132 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1133 } else { /* equivalent to a PatBlt */
1134 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1135 mr->rdParm[6], mr->rdParm[5],
1136 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1140 case META_SETTEXTCHAREXTRA:
1141 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1144 case META_SETTEXTJUSTIFICATION:
1145 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1148 case META_EXTFLOODFILL:
1149 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1150 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1154 case META_SETDIBTODEV:
1156 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1157 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1158 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1159 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1160 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1161 mr->rdParm[2], mr->rdParm[1], bits, info,
1166 #define META_UNIMP(x) case x: \
1167 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1169 META_UNIMP(META_DRAWTEXT)
1170 META_UNIMP(META_ANIMATEPALETTE)
1171 META_UNIMP(META_SETPALENTRIES)
1172 META_UNIMP(META_RESIZEPALETTE)
1173 META_UNIMP(META_RESETDC)
1174 META_UNIMP(META_STARTDOC)
1175 META_UNIMP(META_STARTPAGE)
1176 META_UNIMP(META_ENDPAGE)
1177 META_UNIMP(META_ABORTDOC)
1178 META_UNIMP(META_ENDDOC)
1179 META_UNIMP(META_CREATEBRUSH)
1180 META_UNIMP(META_CREATEBITMAPINDIRECT)
1181 META_UNIMP(META_CREATEBITMAP)
1185 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1190 /******************************************************************
1191 * PlayMetaFileRecord (GDI32.266)
1193 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1194 METARECORD *metarecord, UINT handles )
1196 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1197 handles*sizeof(HANDLETABLE16));
1199 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1201 for (i=0; i<handles; i++)
1202 ht->objectHandle[i] = handletable->objectHandle[i];
1203 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1204 for (i=0; i<handles; i++)
1205 handletable->objectHandle[i] = ht->objectHandle[i];
1206 GlobalFree((HGLOBAL)ht);
1210 /******************************************************************
1211 * GetMetaFileBits (GDI.159)
1213 * Trade in a metafile object handle for a handle to the metafile memory.
1217 HGLOBAL16 WINAPI GetMetaFileBits16(
1218 HMETAFILE16 hmf /* metafile handle */
1221 TRACE("hMem out: %04x\n", hmf);
1225 /******************************************************************
1226 * SetMetaFileBits (GDI.160)
1228 * Trade in a metafile memory handle for a handle to a metafile object.
1229 * The memory region should hold a proper metafile, otherwise
1230 * problems will occur when it is used. Validity of the memory is not
1231 * checked. The function is essentially just the identity function.
1233 HMETAFILE16 WINAPI SetMetaFileBits16(
1235 /* handle to a memory region holding a metafile */
1238 TRACE("hmf out: %04x\n", hMem);
1243 /******************************************************************
1244 * SetMetaFileBitsBetter (GDI.196)
1246 * Trade in a metafile memory handle for a handle to a metafile object,
1247 * making a cursory check (using IsValidMetaFile()) that the memory
1248 * handle points to a valid metafile.
1251 * Handle to a metafile on success, NULL on failure..
1253 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1255 if( IsValidMetaFile16( hMeta ) )
1256 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1257 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1258 return (HMETAFILE16)0;
1261 /******************************************************************
1262 * SetMetaFileBitsEx (GDI32.323)
1264 * Create a metafile from raw data. No checking of the data is performed.
1265 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1267 HMETAFILE WINAPI SetMetaFileBitsEx(
1268 UINT size, /* size of metafile, in bytes */
1269 const BYTE *lpData /* pointer to metafile data */
1272 METAHEADER *mh = HeapAlloc( SystemHeap, 0, size );
1274 memcpy(mh, lpData, size);
1275 return MF_Create_HMETAFILE(mh);
1278 /*****************************************************************
1279 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1281 * Copies the data from metafile _hmf_ into the buffer _buf_.
1282 * If _buf_ is zero, returns size of buffer required. Otherwise,
1283 * returns number of bytes copied.
1285 UINT WINAPI GetMetaFileBitsEx(
1286 HMETAFILE hmf, /* metafile */
1287 UINT nSize, /* size of buf */
1288 LPVOID buf /* buffer to receive raw metafile data */
1290 METAHEADER *mh = MF_GetMetaHeader(hmf);
1293 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1294 if (!mh) return 0; /* FIXME: error code */
1295 if(mh->mtType == METAFILE_DISK)
1296 FIXME("Disk-based metafile?\n");
1297 mfSize = mh->mtSize * 2;
1299 MF_ReleaseMetaHeader(hmf);
1300 TRACE("returning size %d\n", mfSize);
1303 if(mfSize > nSize) mfSize = nSize;
1304 memmove(buf, mh, mfSize);
1305 MF_ReleaseMetaHeader(hmf);
1309 /******************************************************************
1310 * GetWinMetaFileBits [GDI32.241]
1312 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1313 UINT cbBuffer, LPBYTE lpbBuffer,
1314 INT fnMapMode, HDC hdcRef)
1316 FIXME("(%d,%d,%p,%d,%d): stub\n",
1317 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1321 /******************************************************************
1322 * MF_Play_MetaCreateRegion
1324 * Handles META_CREATEREGION for PlayMetaFileRecord().
1328 * The layout of the record looks something like this:
1333 * 2 Looks like a handle? - not constant
1335 * 4 Total number of bytes
1336 * 5 No. of seperate bands = n [see below]
1337 * 6 Largest number of x co-ords in a band
1338 * 7-10 Bounding box x1 y1 x2 y2
1341 * Regions are divided into bands that are uniform in the
1342 * y-direction. Each band consists of pairs of on/off x-coords and is
1344 * m y0 y1 x1 x2 x3 ... xm m
1345 * into successive rdParm[]s.
1347 * This is probably just a dump of the internal RGNOBJ?
1353 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1358 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1360 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1361 band++, start = end + 1) {
1362 if(*start / 2 != (*start + 1) / 2) {
1363 WARN("Delimiter not even.\n");
1364 DeleteObject( hrgn2 );
1368 end = start + *start + 3;
1369 if(end > (WORD *)mr + mr->rdSize) {
1370 WARN("End points outside record.\n");
1371 DeleteObject( hrgn2 );
1375 if(*start != *end) {
1376 WARN("Mismatched delimiters.\n");
1377 DeleteObject( hrgn2 );
1381 y0 = *(INT16 *)(start + 1);
1382 y1 = *(INT16 *)(start + 2);
1383 for(pair = 0; pair < *start / 2; pair++) {
1384 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1385 *(INT16 *)(start + 4 + 2*pair), y1 );
1386 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1389 DeleteObject( hrgn2 );
1394 /******************************************************************
1395 * MF_Play_MetaExtTextOut
1397 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1400 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1407 s1 = mr->rdParm[2]; /* String length */
1408 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1409 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1410 /* rec len without dx array */
1412 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1414 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1416 if (mr->rdSize == len / 2)
1417 dxx = NULL; /* determine if array present */
1419 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1420 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1422 TRACE("%s len: %ld\n", sot, mr->rdSize);
1424 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1425 len, s1, mr->rdSize, mr->rdParm[3]);
1426 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1428 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1429 mr->rdParm[0], /* Y position */
1430 mr->rdParm[3], /* options */
1431 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1434 s1, dxx); /* length, dx array */
1436 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);