4 * Copyright David W. Metcalfe, 1994
5 * Copyright Niels de Carpentier, 1996
6 * Copyright Albrecht Kleine, 1996
7 * Copyright Huw Davies, 1996
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * These functions are primarily involved with metafile playback or anything
26 * that touches a HMETAFILE.
27 * For recording of metafiles look in graphics/metafiledrv/
29 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
30 * global memory handles so these cannot be interchanged.
32 * Memory-based metafiles are just stored as a continuous block of memory with
33 * a METAHEADER at the head with METARECORDs appended to it. mtType is
34 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
35 * disk-based metafile - even mtType is METAFILE_MEMORY.
36 * 16bit HMETAFILE16s are global handles to this block
37 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
39 * Disk-based metafiles are rather different. HMETAFILE16s point to a
40 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
41 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
42 * more 0, then 2 which may be a time stamp of the file and then the path of
43 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
53 #include "wine/winbase16.h"
54 #include "wine/wingdi16.h"
59 #include "gdi_private.h"
60 #include "wine/debug.h"
62 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
79 #define MFHEADERSIZE (sizeof(METAHEADER))
80 #define MFVERSION 0x300
83 /******************************************************************
86 * Add a handle to an external handle table and return the index
88 static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
92 for (i = 0; i < htlen; i++)
94 if (*(ht->objectHandle + i) == 0)
96 *(ht->objectHandle + i) = hobj;
104 /******************************************************************
105 * MF_Create_HMETATFILE
107 * Creates a (32 bit) HMETAFILE object from a METAHEADER
109 * HMETAFILEs are GDI objects.
111 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
114 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
115 (HGDIOBJ *)&hmf, NULL );
119 GDI_ReleaseObj( hmf );
124 /******************************************************************
125 * MF_Create_HMETATFILE16
127 * Creates a HMETAFILE16 object from a METAHEADER
129 * HMETAFILE16s are Global memory handles.
131 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
134 DWORD size = mh->mtSize * sizeof(WORD);
136 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
139 METAHEADER *mh_dest = GlobalLock16(hmf);
140 memcpy(mh_dest, mh, size);
143 HeapFree(GetProcessHeap(), 0, mh);
147 /******************************************************************
150 * Returns ptr to METAHEADER associated with HMETAFILE
152 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
154 METAHEADER *ret = NULL;
155 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
159 GDI_ReleaseObj( hmf );
164 /******************************************************************
167 * Returns ptr to METAHEADER associated with HMETAFILE16
168 * Should be followed by call to MF_ReleaseMetaHeader16
170 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
172 return GlobalLock16(hmf);
175 /******************************************************************
176 * MF_ReleaseMetaHeader16
178 * Releases METAHEADER associated with HMETAFILE16
180 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
182 return GlobalUnlock16( hmf );
186 /******************************************************************
189 * Convert an array of POINT16 to an array of POINT.
190 * Result must be freed by caller.
192 static POINT *convert_points( UINT count, POINT16 *pt16 )
195 POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
198 for (i = 0; i < count; i++)
200 ret[i].x = pt16[i].x;
201 ret[i].y = pt16[i].y;
208 /******************************************************************
209 * DeleteMetaFile (GDI.127)
211 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
213 return !GlobalFree16( hmf );
216 /******************************************************************
217 * DeleteMetaFile (GDI32.@)
219 * Delete a memory-based metafile.
222 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
224 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
225 if (!metaObj) return FALSE;
226 HeapFree( GetProcessHeap(), 0, metaObj->mh );
227 GDI_FreeObject( hmf, metaObj );
231 /******************************************************************
234 * Returns a pointer to a memory based METAHEADER read in from file HFILE
237 static METAHEADER *MF_ReadMetaFile(HANDLE hfile)
240 DWORD BytesRead, size;
242 size = sizeof(METAHEADER);
243 mh = HeapAlloc( GetProcessHeap(), 0, size );
245 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
247 HeapFree( GetProcessHeap(), 0, mh );
250 if (mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION ||
251 mh->mtHeaderSize != size / 2)
253 HeapFree( GetProcessHeap(), 0, mh );
256 size = mh->mtSize * 2;
257 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
259 size -= sizeof(METAHEADER);
260 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
263 HeapFree( GetProcessHeap(), 0, mh );
267 if (mh->mtType != METAFILE_MEMORY) {
268 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
269 mh->mtType = METAFILE_MEMORY;
274 /******************************************************************
275 * GetMetaFile (GDI.124)
277 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
282 TRACE("%s\n", lpFilename);
287 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
288 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
291 mh = MF_ReadMetaFile(hFile);
294 return MF_Create_HMETAFILE16( mh );
297 /******************************************************************
298 * GetMetaFileA (GDI32.@)
300 * Read a metafile from a file. Returns handle to a memory-based metafile.
302 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
307 TRACE("%s\n", lpFilename);
312 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
313 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
316 mh = MF_ReadMetaFile(hFile);
319 return MF_Create_HMETAFILE( mh );
324 /******************************************************************
325 * GetMetaFileW (GDI32.@)
327 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
332 TRACE("%s\n", debugstr_w(lpFilename));
337 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
338 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
341 mh = MF_ReadMetaFile(hFile);
344 return MF_Create_HMETAFILE( mh );
348 /******************************************************************
349 * MF_LoadDiskBasedMetaFile
351 * Creates a new memory-based metafile from a disk-based one.
353 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
359 if(mh->mtType != METAFILE_DISK) {
360 ERR("Not a disk based metafile\n");
363 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
365 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
366 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
367 WARN("Can't open file of disk based metafile\n");
370 mh2 = MF_ReadMetaFile(hfile);
375 /******************************************************************
376 * MF_CreateMetaHeaderDisk
378 * Take a memory based METAHEADER and change it to a disk based METAHEADER
379 * assosiated with filename. Note: Trashes contents of old one.
381 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni )
385 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
386 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
387 mh->mtType = METAFILE_DISK;
388 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
391 WideCharToMultiByte(CP_ACP, 0, filename, -1,
392 mhd->filename, sizeof mhd->filename, NULL, NULL);
394 lstrcpynA( mhd->filename, filename, sizeof mhd->filename );
398 /******************************************************************
399 * CopyMetaFile (GDI.151)
401 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
403 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
404 METAHEADER *mh2 = NULL;
407 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
411 if(mh->mtType == METAFILE_DISK)
412 mh2 = MF_LoadDiskBasedMetaFile(mh);
414 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
415 memcpy( mh2, mh, mh->mtSize * 2 );
417 MF_ReleaseMetaHeader16( hSrcMetaFile );
419 if(lpFilename) { /* disk based metafile */
421 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
422 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
423 HeapFree( GetProcessHeap(), 0, mh2 );
426 WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
428 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, FALSE);
431 return MF_Create_HMETAFILE16( mh2 );
435 /******************************************************************
436 * CopyMetaFileW (GDI32.@)
438 * Copies the metafile corresponding to hSrcMetaFile to either
439 * a disk file, if a filename is given, or to a new memory based
440 * metafile, if lpFileName is NULL.
443 * hSrcMetaFile [I] handle of metafile to copy
444 * lpFilename [I] filename if copying to a file
447 * Handle to metafile copy on success, NULL on failure.
450 * Copying to disk returns NULL even if successful.
452 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile, LPCWSTR lpFilename )
454 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
455 METAHEADER *mh2 = NULL;
458 TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename));
462 if(mh->mtType == METAFILE_DISK)
463 mh2 = MF_LoadDiskBasedMetaFile(mh);
465 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
466 memcpy( mh2, mh, mh->mtSize * 2 );
469 if(lpFilename) { /* disk based metafile */
471 if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL,
472 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
473 HeapFree( GetProcessHeap(), 0, mh2 );
476 WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
480 return MF_Create_HMETAFILE( mh2 );
484 /******************************************************************
485 * CopyMetaFileA (GDI32.@)
487 HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile, LPCSTR lpFilename )
489 UNICODE_STRING lpFilenameW;
492 if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
493 else lpFilenameW.Buffer = NULL;
495 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
496 if (lpFilenameW.Buffer)
497 RtlFreeUnicodeString(&lpFilenameW);
502 /******************************************************************
503 * IsValidMetaFile (GDI.410)
505 * Attempts to check if a given metafile is correctly formatted.
506 * Currently, the only things verified are several properties of the
510 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
513 * This is not exactly what windows does, see _Undocumented_Windows_
516 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
519 METAHEADER *mh = MF_GetMetaHeader16(hmf);
521 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
522 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
523 if (mh->mtVersion == MFVERSION)
525 MF_ReleaseMetaHeader16(hmf);
527 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
532 /*******************************************************************
535 * Helper for PlayMetaFile
537 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
542 unsigned int offset = 0;
549 if (!mh) return FALSE;
550 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
551 mh = MF_LoadDiskBasedMetaFile(mh);
552 if(!mh) return FALSE;
556 /* save the current pen, brush and font */
557 hPen = GetCurrentObject(hdc, OBJ_PEN);
558 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
559 hFont = GetCurrentObject(hdc, OBJ_FONT);
561 /* create the handle table */
562 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
563 sizeof(HANDLETABLE) * mh->mtNoObjects);
564 if(!ht) return FALSE;
566 /* loop through metafile playing records */
567 offset = mh->mtHeaderSize * 2;
568 while (offset < mh->mtSize * 2)
570 mr = (METARECORD *)((char *)mh + offset);
571 TRACE("offset=%04x,size=%08lx\n",
575 "Entry got size 0 at offset %d, total mf length is %ld\n",
576 offset,mh->mtSize*2);
577 break; /* would loop endlessly otherwise */
579 offset += mr->rdSize * 2;
580 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
583 SelectObject(hdc, hBrush);
584 SelectObject(hdc, hPen);
585 SelectObject(hdc, hFont);
587 /* free objects in handle table */
588 for(i = 0; i < mh->mtNoObjects; i++)
589 if(*(ht->objectHandle + i) != 0)
590 DeleteObject(*(ht->objectHandle + i));
592 /* free handle table */
593 HeapFree( GetProcessHeap(), 0, ht );
595 HeapFree( GetProcessHeap(), 0, mh );
599 /******************************************************************
600 * PlayMetaFile (GDI.123)
603 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
606 METAHEADER *mh = MF_GetMetaHeader16( hmf );
607 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
608 MF_ReleaseMetaHeader16( hmf );
612 /******************************************************************
613 * PlayMetaFile (GDI32.@)
615 * Renders the metafile specified by hmf in the DC specified by
616 * hdc. Returns FALSE on failure, TRUE on success.
619 * hdc [I] handle of DC to render in
620 * hmf [I] handle of metafile to render
622 BOOL WINAPI PlayMetaFile( HDC hdc, HMETAFILE hmf )
624 METAHEADER *mh = MF_GetMetaHeader( hmf );
625 return MF_PlayMetaFile( hdc, mh );
629 /******************************************************************
630 * EnumMetaFile (GDI.175)
633 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
634 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
636 METAHEADER *mh = MF_GetMetaHeader16(hmf);
639 HDC hdc = HDC_32(hdc16);
642 unsigned int offset = 0;
648 BOOL16 result = TRUE, loaded = FALSE;
650 TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
652 if(!mh) return FALSE;
653 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
654 mh = MF_LoadDiskBasedMetaFile(mh);
655 if(!mh) return FALSE;
659 /* save the current pen, brush and font */
660 hPen = GetCurrentObject(hdc, OBJ_PEN);
661 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
662 hFont = GetCurrentObject(hdc, OBJ_FONT);
664 /* create the handle table */
666 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
667 sizeof(HANDLETABLE16) * mh->mtNoObjects);
668 spht = WOWGlobalLock16(hHT);
671 offset = mh->mtHeaderSize * 2;
673 /* loop through metafile records */
676 args[6] = SELECTOROF(spht);
677 args[5] = OFFSETOF(spht);
678 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
679 args[3] = LOWORD(offset);
680 args[2] = mh->mtNoObjects;
681 args[1] = HIWORD(lpData);
682 args[0] = LOWORD(lpData);
684 while (offset < (mh->mtSize * 2))
688 mr = (METARECORD *)((char *)mh + offset);
690 WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
697 offset += (mr->rdSize * 2);
698 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
699 args[3] = LOWORD(offset);
702 SelectObject(hdc, hBrush);
703 SelectObject(hdc, hPen);
704 SelectObject(hdc, hFont);
706 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
708 /* free objects in handle table */
709 for(i = 0; i < mh->mtNoObjects; i++)
710 if(*(ht->objectHandle + i) != 0)
711 DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
713 /* free handle table */
716 HeapFree( GetProcessHeap(), 0, mh );
717 MF_ReleaseMetaHeader16(hmf);
721 /******************************************************************
722 * EnumMetaFile (GDI32.@)
724 * Loop through the metafile records in hmf, calling the user-specified
725 * function for each one, stopping when the user's function returns FALSE
726 * (which is considered to be failure)
727 * or when no records are left (which is considered to be success).
730 * TRUE on success, FALSE on failure.
732 BOOL WINAPI EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc, LPARAM lpData)
734 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
739 unsigned int offset = 0;
744 TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
746 if(mh->mtType == METAFILE_DISK)
748 /* Create a memory-based copy */
749 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
753 /* save the current pen, brush and font */
754 hPen = GetCurrentObject(hdc, OBJ_PEN);
755 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
756 hFont = GetCurrentObject(hdc, OBJ_FONT);
758 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
759 sizeof(HANDLETABLE) * mh->mtNoObjects);
761 /* loop through metafile records */
762 offset = mh->mtHeaderSize * 2;
764 while (offset < (mh->mtSize * 2))
766 mr = (METARECORD *)((char *)mh + offset);
767 if(mr->rdFunction == META_EOF) {
768 TRACE("Got META_EOF so stopping\n");
771 TRACE("Calling EnumFunc with record type %x\n",
773 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
779 offset += (mr->rdSize * 2);
782 /* restore pen, brush and font */
783 SelectObject(hdc, hBrush);
784 SelectObject(hdc, hPen);
785 SelectObject(hdc, hFont);
787 /* free objects in handle table */
788 for(i = 0; i < mh->mtNoObjects; i++)
789 if(*(ht->objectHandle + i) != 0)
790 DeleteObject(*(ht->objectHandle + i));
792 /* free handle table */
793 HeapFree( GetProcessHeap(), 0, ht);
794 /* free a copy of metafile */
795 HeapFree( GetProcessHeap(), 0, mhTemp );
799 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
800 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
801 /******************************************************************
802 * PlayMetaFileRecord (GDI32.@)
804 * Render a single metafile record specified by *mr in the DC hdc, while
805 * using the handle table *ht, of length handles,
806 * to store metafile objects.
809 * The following metafile records are unimplemented:
811 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
812 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
813 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
815 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
819 BITMAPINFOHEADER *infohdr;
821 TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
823 switch (mr->rdFunction)
828 case META_DELETEOBJECT:
829 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
830 *(ht->objectHandle + mr->rdParm[0]) = 0;
833 case META_SETBKCOLOR:
834 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
838 SetBkMode(hdc, mr->rdParm[0]);
841 case META_SETMAPMODE:
842 SetMapMode(hdc, mr->rdParm[0]);
846 SetROP2(hdc, mr->rdParm[0]);
850 SetRelAbs(hdc, mr->rdParm[0]);
853 case META_SETPOLYFILLMODE:
854 SetPolyFillMode(hdc, mr->rdParm[0]);
857 case META_SETSTRETCHBLTMODE:
858 SetStretchBltMode(hdc, mr->rdParm[0]);
861 case META_SETTEXTCOLOR:
862 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
865 case META_SETWINDOWORG:
866 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
869 case META_SETWINDOWEXT:
870 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
873 case META_SETVIEWPORTORG:
874 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
877 case META_SETVIEWPORTEXT:
878 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
881 case META_OFFSETWINDOWORG:
882 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
885 case META_SCALEWINDOWEXT:
886 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
887 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
890 case META_OFFSETVIEWPORTORG:
891 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
894 case META_SCALEVIEWPORTEXT:
895 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
896 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
900 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
904 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
907 case META_EXCLUDECLIPRECT:
908 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
909 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
912 case META_INTERSECTCLIPRECT:
913 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
914 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
918 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
919 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
920 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
921 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
925 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
926 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
930 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
931 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
935 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
936 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
937 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
938 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
942 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
943 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
947 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
948 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
949 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
953 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
954 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
955 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
963 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
964 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
967 case META_OFFSETCLIPRGN:
968 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
973 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
974 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
975 (char *)(mr->rdParm + 1), s1);
979 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
981 Polygon(hdc, pt, mr->rdParm[0]);
982 HeapFree( GetProcessHeap(), 0, pt );
986 case META_POLYPOLYGON:
989 SHORT *counts = (SHORT *)(mr->rdParm + 1);
991 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
992 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
995 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
998 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
999 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
1000 HeapFree( GetProcessHeap(), 0, cnt32 );
1003 HeapFree( GetProcessHeap(), 0, pt );
1008 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
1010 Polyline( hdc, pt, mr->rdParm[0] );
1011 HeapFree( GetProcessHeap(), 0, pt );
1015 case META_RESTOREDC:
1016 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
1019 case META_SELECTOBJECT:
1020 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
1024 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1025 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1026 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1027 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1030 case META_CREATEPATTERNBRUSH:
1031 switch (mr->rdParm[0])
1034 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1035 MF_AddHandle(ht, handles,
1036 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
1039 infohdr->biBitCount,
1040 (LPSTR)(mr->rdParm +
1041 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
1045 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1046 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
1050 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1056 case META_CREATEPENINDIRECT:
1059 pen.lopnStyle = mr->rdParm[0];
1060 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
1061 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
1062 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
1063 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
1067 case META_CREATEFONTINDIRECT:
1070 font.lfHeight = (SHORT)mr->rdParm[0];
1071 font.lfWidth = (SHORT)mr->rdParm[1];
1072 font.lfEscapement = (SHORT)mr->rdParm[2];
1073 font.lfOrientation = (SHORT)mr->rdParm[3];
1074 font.lfWeight = (SHORT)mr->rdParm[4];
1075 font.lfItalic = LOBYTE(mr->rdParm[5]);
1076 font.lfUnderline = HIBYTE(mr->rdParm[5]);
1077 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
1078 font.lfCharSet = HIBYTE(mr->rdParm[6]);
1079 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
1080 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
1081 font.lfQuality = LOBYTE(mr->rdParm[8]);
1082 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
1083 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
1084 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
1088 case META_CREATEBRUSHINDIRECT:
1091 brush.lbStyle = mr->rdParm[0];
1092 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
1093 brush.lbHatch = mr->rdParm[3];
1094 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
1098 case META_CREATEPALETTE:
1099 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
1102 case META_SETTEXTALIGN:
1103 SetTextAlign(hdc, mr->rdParm[0]);
1106 case META_SELECTPALETTE:
1107 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
1110 case META_SETMAPPERFLAGS:
1111 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1114 case META_REALIZEPALETTE:
1115 GDIRealizePalette(hdc);
1119 Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
1122 case META_EXTTEXTOUT:
1123 MF_Play_MetaExtTextOut( hdc, mr );
1126 case META_STRETCHDIB:
1128 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1129 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1130 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1131 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1132 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
1133 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1137 case META_DIBSTRETCHBLT:
1139 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1140 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1141 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1142 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1143 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
1144 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1148 case META_STRETCHBLT:
1150 HDC hdcSrc = CreateCompatibleDC(hdc);
1151 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
1152 mr->rdParm[11], /*Height*/
1153 mr->rdParm[13], /*Planes*/
1154 mr->rdParm[14], /*BitsPixel*/
1155 (LPSTR)&mr->rdParm[15]); /*bits*/
1156 SelectObject(hdcSrc,hbitmap);
1157 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1158 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1159 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1160 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1161 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1168 HDC hdcSrc = CreateCompatibleDC(hdc);
1169 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
1170 mr->rdParm[8]/*Height*/,
1171 mr->rdParm[10]/*Planes*/,
1172 mr->rdParm[11]/*BitsPixel*/,
1173 (LPSTR)&mr->rdParm[12]/*bits*/);
1174 SelectObject(hdcSrc,hbitmap);
1175 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
1176 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
1177 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
1178 MAKELONG(0,mr->rdParm[0]));
1183 case META_CREATEREGION:
1185 HRGN hrgn = CreateRectRgn(0,0,0,0);
1187 MF_Play_MetaCreateRegion(mr, hrgn);
1188 MF_AddHandle(ht, handles, hrgn);
1192 case META_FILLREGION:
1193 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
1194 *(ht->objectHandle + mr->rdParm[0]));
1197 case META_FRAMEREGION:
1198 FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
1199 *(ht->objectHandle + mr->rdParm[2]),
1200 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1203 case META_INVERTREGION:
1204 InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1207 case META_PAINTREGION:
1208 PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1211 case META_SELECTCLIPREGION:
1215 if (mr->rdParm[0]) hrgn = *(ht->objectHandle + mr->rdParm[0]);
1216 SelectClipRgn(hdc, hrgn);
1220 case META_DIBCREATEPATTERNBRUSH:
1221 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1222 but there's no difference */
1223 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1226 case META_DIBBITBLT:
1227 /* In practice I've found that there are two layouts for
1228 META_DIBBITBLT, one (the first here) is the usual one when a src
1229 dc is actually passed to it, the second occurs when the src dc is
1230 passed in as NULL to the creating BitBlt. As the second case has
1231 no dib, a size check will suffice to distinguish.
1233 Caolan.McNamara@ul.ie */
1235 if (mr->rdSize > 12) {
1236 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1237 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1239 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1240 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1241 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1242 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1244 else /* equivalent to a PatBlt */
1245 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1246 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1247 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1250 case META_SETTEXTCHAREXTRA:
1251 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1254 case META_SETTEXTJUSTIFICATION:
1255 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1258 case META_EXTFLOODFILL:
1259 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1260 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1264 case META_SETDIBTODEV:
1266 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1267 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1268 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1269 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1270 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1271 mr->rdParm[2], mr->rdParm[1], bits, info,
1276 #define META_UNIMP(x) case x: \
1277 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1279 META_UNIMP(META_DRAWTEXT)
1280 META_UNIMP(META_ANIMATEPALETTE)
1281 META_UNIMP(META_SETPALENTRIES)
1282 META_UNIMP(META_RESIZEPALETTE)
1283 META_UNIMP(META_RESETDC)
1284 META_UNIMP(META_STARTDOC)
1285 META_UNIMP(META_STARTPAGE)
1286 META_UNIMP(META_ENDPAGE)
1287 META_UNIMP(META_ABORTDOC)
1288 META_UNIMP(META_ENDDOC)
1289 META_UNIMP(META_CREATEBRUSH)
1290 META_UNIMP(META_CREATEBITMAPINDIRECT)
1291 META_UNIMP(META_CREATEBITMAP)
1295 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1301 /******************************************************************
1302 * GetMetaFileBits (GDI.159)
1304 * Trade in a metafile object handle for a handle to the metafile memory.
1307 * hmf [I] metafile handle
1310 HGLOBAL16 WINAPI GetMetaFileBits16( HMETAFILE16 hmf )
1312 TRACE("hMem out: %04x\n", hmf);
1316 /******************************************************************
1317 * SetMetaFileBits (GDI.160)
1319 * Trade in a metafile memory handle for a handle to a metafile object.
1320 * The memory region should hold a proper metafile, otherwise
1321 * problems will occur when it is used. Validity of the memory is not
1322 * checked. The function is essentially just the identity function.
1325 * hMem [I] handle to a memory region holding a metafile
1327 HMETAFILE16 WINAPI SetMetaFileBits16( HGLOBAL16 hMem )
1329 TRACE("hmf out: %04x\n", hMem);
1334 /******************************************************************
1335 * SetMetaFileBitsBetter (GDI.196)
1337 * Trade in a metafile memory handle for a handle to a metafile object,
1338 * making a cursory check (using IsValidMetaFile()) that the memory
1339 * handle points to a valid metafile.
1342 * Handle to a metafile on success, NULL on failure..
1344 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1346 if( IsValidMetaFile16( hMeta ) )
1347 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1348 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1349 return (HMETAFILE16)0;
1352 /******************************************************************
1353 * SetMetaFileBitsEx (GDI32.@)
1355 * Create a metafile from raw data. No checking of the data is performed.
1356 * Use GetMetaFileBitsEx() to get raw data from a metafile.
1359 * size [I] size of metafile, in bytes
1360 * lpData [I] pointer to metafile data
1362 HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData )
1364 METAHEADER *mh = (METAHEADER *)lpData;
1366 if (size & 1) return 0;
1368 if (!size || mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION ||
1369 mh->mtHeaderSize != sizeof(METAHEADER) / 2)
1371 SetLastError(ERROR_INVALID_DATA);
1375 mh = HeapAlloc( GetProcessHeap(), 0, size );
1378 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1382 memcpy(mh, lpData, size);
1383 mh->mtSize = size / 2;
1384 return MF_Create_HMETAFILE(mh);
1387 /*****************************************************************
1388 * GetMetaFileBitsEx (GDI32.@)
1390 * Get raw metafile data.
1392 * Copies the data from metafile _hmf_ into the buffer _buf_.
1393 * If _buf_ is zero, returns size of buffer required. Otherwise,
1394 * returns number of bytes copied.
1398 * nSize [I] size of buf
1399 * buf [O] buffer to receive raw metafile data
1401 UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf )
1403 METAHEADER *mh = MF_GetMetaHeader(hmf);
1406 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1407 if (!mh) return 0; /* FIXME: error code */
1408 if(mh->mtType == METAFILE_DISK)
1409 FIXME("Disk-based metafile?\n");
1410 mfSize = mh->mtSize * 2;
1412 TRACE("returning size %d\n", mfSize);
1415 if(mfSize > nSize) mfSize = nSize;
1416 memmove(buf, mh, mfSize);
1420 /******************************************************************
1421 * GetWinMetaFileBits [GDI32.@]
1423 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1424 UINT cbBuffer, LPBYTE lpbBuffer,
1425 INT fnMapMode, HDC hdcRef)
1433 GetClipBox(hdcRef, &rc);
1434 oldMapMode = SetMapMode(hdcRef, fnMapMode);
1436 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1437 fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1439 hdcmf = CreateMetaFileA(NULL);
1440 PlayEnhMetaFile(hdcmf, hemf, &rc);
1441 hmf = CloseMetaFile(hdcmf);
1442 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1443 DeleteMetaFile(hmf);
1445 SetMapMode(hdcRef, oldMapMode);
1450 /******************************************************************
1451 * MF_Play_MetaCreateRegion
1453 * Handles META_CREATEREGION for PlayMetaFileRecord().
1455 * The layout of the record looks something like this:
1460 * 2 Looks like a handle? - not constant
1462 * 4 Total number of bytes
1463 * 5 No. of separate bands = n [see below]
1464 * 6 Largest number of x co-ords in a band
1465 * 7-10 Bounding box x1 y1 x2 y2
1468 * Regions are divided into bands that are uniform in the
1469 * y-direction. Each band consists of pairs of on/off x-coords and is
1471 * m y0 y1 x1 x2 x3 ... xm m
1472 * into successive rdParm[]s.
1474 * This is probably just a dump of the internal RGNOBJ?
1480 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1485 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1487 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1488 band++, start = end + 1) {
1489 if(*start / 2 != (*start + 1) / 2) {
1490 WARN("Delimiter not even.\n");
1491 DeleteObject( hrgn2 );
1495 end = start + *start + 3;
1496 if(end > (WORD *)mr + mr->rdSize) {
1497 WARN("End points outside record.\n");
1498 DeleteObject( hrgn2 );
1502 if(*start != *end) {
1503 WARN("Mismatched delimiters.\n");
1504 DeleteObject( hrgn2 );
1508 y0 = *(INT16 *)(start + 1);
1509 y1 = *(INT16 *)(start + 2);
1510 for(pair = 0; pair < *start / 2; pair++) {
1511 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1512 *(INT16 *)(start + 4 + 2*pair), y1 );
1513 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1516 DeleteObject( hrgn2 );
1521 /******************************************************************
1522 * MF_Play_MetaExtTextOut
1524 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1527 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1536 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1538 s1 = mr->rdParm[2]; /* String length */
1539 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1540 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1541 /* rec len without dx array */
1543 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1546 rect.left = (SHORT)mr->rdParm[4];
1547 rect.top = (SHORT)mr->rdParm[5];
1548 rect.right = (SHORT)mr->rdParm[6];
1549 rect.bottom = (SHORT)mr->rdParm[7];
1550 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1553 if (mr->rdSize == len / 2)
1554 dxx = NULL; /* determine if array present */
1556 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1558 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1559 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1560 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1563 TRACE("%s len: %ld\n", sot, mr->rdSize);
1564 WARN("Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1565 len, s1, mr->rdSize, mr->rdParm[3]);
1566 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1569 (SHORT)mr->rdParm[1], /* X position */
1570 (SHORT)mr->rdParm[0], /* Y position */
1571 mr->rdParm[3], /* options */
1572 &rect, /* rectangle */
1574 s1, dx); /* length, dx array */
1577 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1578 HeapFree( GetProcessHeap(), 0, dx );