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.@)
489 HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile, LPCSTR lpFilename )
491 UNICODE_STRING lpFilenameW;
494 if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
495 else lpFilenameW.Buffer = NULL;
497 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
498 if (lpFilenameW.Buffer)
499 RtlFreeUnicodeString(&lpFilenameW);
504 /******************************************************************
505 * IsValidMetaFile (GDI.410)
507 * Attempts to check if a given metafile is correctly formatted.
508 * Currently, the only things verified are several properties of the
512 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
515 * This is not exactly what windows does, see _Undocumented_Windows_
518 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
521 METAHEADER *mh = MF_GetMetaHeader16(hmf);
523 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
524 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
525 if (mh->mtVersion == MFVERSION)
527 MF_ReleaseMetaHeader16(hmf);
529 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
534 /*******************************************************************
537 * Helper for PlayMetaFile
539 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
544 unsigned int offset = 0;
551 if (!mh) return FALSE;
552 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
553 mh = MF_LoadDiskBasedMetaFile(mh);
554 if(!mh) return FALSE;
558 /* save the current pen, brush and font */
559 hPen = GetCurrentObject(hdc, OBJ_PEN);
560 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
561 hFont = GetCurrentObject(hdc, OBJ_FONT);
563 /* create the handle table */
564 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
565 sizeof(HANDLETABLE) * mh->mtNoObjects);
566 if(!ht) return FALSE;
568 /* loop through metafile playing records */
569 offset = mh->mtHeaderSize * 2;
570 while (offset < mh->mtSize * 2)
572 mr = (METARECORD *)((char *)mh + offset);
573 TRACE("offset=%04x,size=%08lx\n",
577 "Entry got size 0 at offset %d, total mf length is %ld\n",
578 offset,mh->mtSize*2);
579 break; /* would loop endlessly otherwise */
581 offset += mr->rdSize * 2;
582 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
585 SelectObject(hdc, hBrush);
586 SelectObject(hdc, hPen);
587 SelectObject(hdc, hFont);
589 /* free objects in handle table */
590 for(i = 0; i < mh->mtNoObjects; i++)
591 if(*(ht->objectHandle + i) != 0)
592 DeleteObject(*(ht->objectHandle + i));
594 /* free handle table */
595 HeapFree( GetProcessHeap(), 0, ht );
597 HeapFree( GetProcessHeap(), 0, mh );
601 /******************************************************************
602 * PlayMetaFile (GDI.123)
605 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
608 METAHEADER *mh = MF_GetMetaHeader16( hmf );
609 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
610 MF_ReleaseMetaHeader16( hmf );
614 /******************************************************************
615 * PlayMetaFile (GDI32.@)
617 * Renders the metafile specified by hmf in the DC specified by
618 * hdc. Returns FALSE on failure, TRUE on success.
621 * hdc [I] handle of DC to render in
622 * hmf [I] handle of metafile to render
628 BOOL WINAPI PlayMetaFile( HDC hdc, HMETAFILE hmf )
630 METAHEADER *mh = MF_GetMetaHeader( hmf );
631 return MF_PlayMetaFile( hdc, mh );
635 /******************************************************************
636 * EnumMetaFile (GDI.175)
639 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
640 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
642 METAHEADER *mh = MF_GetMetaHeader16(hmf);
645 HDC hdc = HDC_32(hdc16);
648 unsigned int offset = 0;
654 BOOL16 result = TRUE, loaded = FALSE;
656 TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
658 if(!mh) return FALSE;
659 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
660 mh = MF_LoadDiskBasedMetaFile(mh);
661 if(!mh) return FALSE;
665 /* save the current pen, brush and font */
666 hPen = GetCurrentObject(hdc, OBJ_PEN);
667 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
668 hFont = GetCurrentObject(hdc, OBJ_FONT);
670 /* create the handle table */
672 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
673 sizeof(HANDLETABLE16) * mh->mtNoObjects);
674 spht = WOWGlobalLock16(hHT);
677 offset = mh->mtHeaderSize * 2;
679 /* loop through metafile records */
682 args[6] = SELECTOROF(spht);
683 args[5] = OFFSETOF(spht);
684 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
685 args[3] = LOWORD(offset);
686 args[2] = mh->mtNoObjects;
687 args[1] = HIWORD(lpData);
688 args[0] = LOWORD(lpData);
690 while (offset < (mh->mtSize * 2))
694 mr = (METARECORD *)((char *)mh + offset);
696 WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
703 offset += (mr->rdSize * 2);
704 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
705 args[3] = LOWORD(offset);
708 SelectObject(hdc, hBrush);
709 SelectObject(hdc, hPen);
710 SelectObject(hdc, hFont);
712 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
714 /* free objects in handle table */
715 for(i = 0; i < mh->mtNoObjects; i++)
716 if(*(ht->objectHandle + i) != 0)
717 DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
719 /* free handle table */
722 HeapFree( GetProcessHeap(), 0, mh );
723 MF_ReleaseMetaHeader16(hmf);
727 /******************************************************************
728 * EnumMetaFile (GDI32.@)
730 * Loop through the metafile records in hmf, calling the user-specified
731 * function for each one, stopping when the user's function returns FALSE
732 * (which is considered to be failure)
733 * or when no records are left (which is considered to be success).
736 * TRUE on success, FALSE on failure.
738 BOOL WINAPI EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc, LPARAM lpData)
740 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
745 unsigned int offset = 0;
750 TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
752 if(mh->mtType == METAFILE_DISK)
754 /* Create a memory-based copy */
755 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
759 /* save the current pen, brush and font */
760 hPen = GetCurrentObject(hdc, OBJ_PEN);
761 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
762 hFont = GetCurrentObject(hdc, OBJ_FONT);
764 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
765 sizeof(HANDLETABLE) * mh->mtNoObjects);
767 /* loop through metafile records */
768 offset = mh->mtHeaderSize * 2;
770 while (offset < (mh->mtSize * 2))
772 mr = (METARECORD *)((char *)mh + offset);
773 if(mr->rdFunction == META_EOF) {
774 TRACE("Got META_EOF so stopping\n");
777 TRACE("Calling EnumFunc with record type %x\n",
779 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
785 offset += (mr->rdSize * 2);
788 /* restore pen, brush and font */
789 SelectObject(hdc, hBrush);
790 SelectObject(hdc, hPen);
791 SelectObject(hdc, hFont);
793 /* free objects in handle table */
794 for(i = 0; i < mh->mtNoObjects; i++)
795 if(*(ht->objectHandle + i) != 0)
796 DeleteObject(*(ht->objectHandle + i));
798 /* free handle table */
799 HeapFree( GetProcessHeap(), 0, ht);
800 /* free a copy of metafile */
801 HeapFree( GetProcessHeap(), 0, mhTemp );
805 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
806 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
807 /******************************************************************
808 * PlayMetaFileRecord (GDI32.@)
810 * Render a single metafile record specified by *mr in the DC hdc, while
811 * using the handle table *ht, of length handles,
812 * to store metafile objects.
815 * The following metafile records are unimplemented:
817 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
818 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
819 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
821 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
825 BITMAPINFOHEADER *infohdr;
827 TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
829 switch (mr->rdFunction)
834 case META_DELETEOBJECT:
835 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
836 *(ht->objectHandle + mr->rdParm[0]) = 0;
839 case META_SETBKCOLOR:
840 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
844 SetBkMode(hdc, mr->rdParm[0]);
847 case META_SETMAPMODE:
848 SetMapMode(hdc, mr->rdParm[0]);
852 SetROP2(hdc, mr->rdParm[0]);
856 SetRelAbs(hdc, mr->rdParm[0]);
859 case META_SETPOLYFILLMODE:
860 SetPolyFillMode(hdc, mr->rdParm[0]);
863 case META_SETSTRETCHBLTMODE:
864 SetStretchBltMode(hdc, mr->rdParm[0]);
867 case META_SETTEXTCOLOR:
868 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
871 case META_SETWINDOWORG:
872 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
875 case META_SETWINDOWEXT:
876 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
879 case META_SETVIEWPORTORG:
880 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
883 case META_SETVIEWPORTEXT:
884 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
887 case META_OFFSETWINDOWORG:
888 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
891 case META_SCALEWINDOWEXT:
892 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
893 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
896 case META_OFFSETVIEWPORTORG:
897 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
900 case META_SCALEVIEWPORTEXT:
901 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
902 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
906 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
910 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
913 case META_EXCLUDECLIPRECT:
914 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
915 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
918 case META_INTERSECTCLIPRECT:
919 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
920 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
924 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
925 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
926 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
927 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
931 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
932 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
936 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
937 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
941 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
942 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
943 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
944 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
948 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
949 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
953 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
954 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
955 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
959 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
960 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
961 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
969 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
970 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
973 case META_OFFSETCLIPRGN:
974 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
979 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
980 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
981 (char *)(mr->rdParm + 1), s1);
985 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
987 Polygon(hdc, pt, mr->rdParm[0]);
988 HeapFree( GetProcessHeap(), 0, pt );
992 case META_POLYPOLYGON:
995 SHORT *counts = (SHORT *)(mr->rdParm + 1);
997 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
998 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
1001 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
1004 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
1005 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
1006 HeapFree( GetProcessHeap(), 0, cnt32 );
1009 HeapFree( GetProcessHeap(), 0, pt );
1014 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
1016 Polyline( hdc, pt, mr->rdParm[0] );
1017 HeapFree( GetProcessHeap(), 0, pt );
1021 case META_RESTOREDC:
1022 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
1025 case META_SELECTOBJECT:
1026 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
1030 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1031 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1032 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1033 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1036 case META_CREATEPATTERNBRUSH:
1037 switch (mr->rdParm[0])
1040 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1041 MF_AddHandle(ht, handles,
1042 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
1045 infohdr->biBitCount,
1046 (LPSTR)(mr->rdParm +
1047 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
1051 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1052 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
1056 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1062 case META_CREATEPENINDIRECT:
1065 pen.lopnStyle = mr->rdParm[0];
1066 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
1067 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
1068 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
1069 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
1073 case META_CREATEFONTINDIRECT:
1076 font.lfHeight = (SHORT)mr->rdParm[0];
1077 font.lfWidth = (SHORT)mr->rdParm[1];
1078 font.lfEscapement = (SHORT)mr->rdParm[2];
1079 font.lfOrientation = (SHORT)mr->rdParm[3];
1080 font.lfWeight = (SHORT)mr->rdParm[4];
1081 font.lfItalic = LOBYTE(mr->rdParm[5]);
1082 font.lfUnderline = HIBYTE(mr->rdParm[5]);
1083 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
1084 font.lfCharSet = HIBYTE(mr->rdParm[6]);
1085 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
1086 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
1087 font.lfQuality = LOBYTE(mr->rdParm[8]);
1088 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
1089 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
1090 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
1094 case META_CREATEBRUSHINDIRECT:
1097 brush.lbStyle = mr->rdParm[0];
1098 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
1099 brush.lbHatch = mr->rdParm[3];
1100 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
1104 case META_CREATEPALETTE:
1105 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
1108 case META_SETTEXTALIGN:
1109 SetTextAlign(hdc, mr->rdParm[0]);
1112 case META_SELECTPALETTE:
1113 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
1116 case META_SETMAPPERFLAGS:
1117 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1120 case META_REALIZEPALETTE:
1121 GDIRealizePalette(hdc);
1125 Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
1128 case META_EXTTEXTOUT:
1129 MF_Play_MetaExtTextOut( hdc, mr );
1132 case META_STRETCHDIB:
1134 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1135 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1136 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1137 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1138 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
1139 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1143 case META_DIBSTRETCHBLT:
1145 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1146 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1147 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1148 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1149 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
1150 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1154 case META_STRETCHBLT:
1156 HDC hdcSrc = CreateCompatibleDC(hdc);
1157 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
1158 mr->rdParm[11], /*Height*/
1159 mr->rdParm[13], /*Planes*/
1160 mr->rdParm[14], /*BitsPixel*/
1161 (LPSTR)&mr->rdParm[15]); /*bits*/
1162 SelectObject(hdcSrc,hbitmap);
1163 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1164 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1165 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1166 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1167 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1174 HDC hdcSrc = CreateCompatibleDC(hdc);
1175 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
1176 mr->rdParm[8]/*Height*/,
1177 mr->rdParm[10]/*Planes*/,
1178 mr->rdParm[11]/*BitsPixel*/,
1179 (LPSTR)&mr->rdParm[12]/*bits*/);
1180 SelectObject(hdcSrc,hbitmap);
1181 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
1182 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
1183 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
1184 MAKELONG(0,mr->rdParm[0]));
1189 case META_CREATEREGION:
1191 HRGN hrgn = CreateRectRgn(0,0,0,0);
1193 MF_Play_MetaCreateRegion(mr, hrgn);
1194 MF_AddHandle(ht, handles, hrgn);
1198 case META_FILLREGION:
1199 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
1200 *(ht->objectHandle + mr->rdParm[0]));
1203 case META_FRAMEREGION:
1204 FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
1205 *(ht->objectHandle + mr->rdParm[2]),
1206 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1209 case META_INVERTREGION:
1210 InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1213 case META_PAINTREGION:
1214 PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1217 case META_SELECTCLIPREGION:
1221 if (mr->rdParm[0]) hrgn = *(ht->objectHandle + mr->rdParm[0]);
1222 SelectClipRgn(hdc, hrgn);
1226 case META_DIBCREATEPATTERNBRUSH:
1227 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1228 but there's no difference */
1229 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1232 case META_DIBBITBLT:
1233 /* In practice I've found that there are two layouts for
1234 META_DIBBITBLT, one (the first here) is the usual one when a src
1235 dc is actually passed to it, the second occurs when the src dc is
1236 passed in as NULL to the creating BitBlt. As the second case has
1237 no dib, a size check will suffice to distinguish.
1239 Caolan.McNamara@ul.ie */
1241 if (mr->rdSize > 12) {
1242 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1243 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1245 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1246 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1247 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1248 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1250 else /* equivalent to a PatBlt */
1251 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1252 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1253 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1256 case META_SETTEXTCHAREXTRA:
1257 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1260 case META_SETTEXTJUSTIFICATION:
1261 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1264 case META_EXTFLOODFILL:
1265 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1266 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1270 case META_SETDIBTODEV:
1272 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1273 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1274 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1275 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1276 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1277 mr->rdParm[2], mr->rdParm[1], bits, info,
1282 #define META_UNIMP(x) case x: \
1283 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1285 META_UNIMP(META_DRAWTEXT)
1286 META_UNIMP(META_ANIMATEPALETTE)
1287 META_UNIMP(META_SETPALENTRIES)
1288 META_UNIMP(META_RESIZEPALETTE)
1289 META_UNIMP(META_RESETDC)
1290 META_UNIMP(META_STARTDOC)
1291 META_UNIMP(META_STARTPAGE)
1292 META_UNIMP(META_ENDPAGE)
1293 META_UNIMP(META_ABORTDOC)
1294 META_UNIMP(META_ENDDOC)
1295 META_UNIMP(META_CREATEBRUSH)
1296 META_UNIMP(META_CREATEBITMAPINDIRECT)
1297 META_UNIMP(META_CREATEBITMAP)
1301 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1307 /******************************************************************
1308 * GetMetaFileBits (GDI.159)
1310 * Trade in a metafile object handle for a handle to the metafile memory.
1313 * hmf [I] metafile handle
1316 HGLOBAL16 WINAPI GetMetaFileBits16( HMETAFILE16 hmf )
1318 TRACE("hMem out: %04x\n", hmf);
1322 /******************************************************************
1323 * SetMetaFileBits (GDI.160)
1325 * Trade in a metafile memory handle for a handle to a metafile object.
1326 * The memory region should hold a proper metafile, otherwise
1327 * problems will occur when it is used. Validity of the memory is not
1328 * checked. The function is essentially just the identity function.
1331 * hMem [I] handle to a memory region holding a metafile
1334 * Handle to a metafile on success, NULL on failure..
1336 HMETAFILE16 WINAPI SetMetaFileBits16( HGLOBAL16 hMem )
1338 TRACE("hmf out: %04x\n", hMem);
1343 /******************************************************************
1344 * SetMetaFileBitsBetter (GDI.196)
1346 * Trade in a metafile memory handle for a handle to a metafile object,
1347 * making a cursory check (using IsValidMetaFile()) that the memory
1348 * handle points to a valid metafile.
1351 * Handle to a metafile on success, NULL on failure..
1353 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1355 if( IsValidMetaFile16( hMeta ) )
1356 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1357 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1358 return (HMETAFILE16)0;
1361 /******************************************************************
1362 * SetMetaFileBitsEx (GDI32.@)
1364 * Create a metafile from raw data. No checking of the data is performed.
1365 * Use GetMetaFileBitsEx() to get raw data from a metafile.
1368 * size [I] size of metafile, in bytes
1369 * lpData [I] pointer to metafile data
1372 * Success: Handle to metafile.
1375 HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData )
1377 METAHEADER *mh = (METAHEADER *)lpData;
1379 if (size & 1) return 0;
1381 if (!size || mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION ||
1382 mh->mtHeaderSize != sizeof(METAHEADER) / 2)
1384 SetLastError(ERROR_INVALID_DATA);
1388 mh = HeapAlloc( GetProcessHeap(), 0, size );
1391 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1395 memcpy(mh, lpData, size);
1396 mh->mtSize = size / 2;
1397 return MF_Create_HMETAFILE(mh);
1400 /*****************************************************************
1401 * GetMetaFileBitsEx (GDI32.@)
1403 * Get raw metafile data.
1405 * Copies the data from metafile _hmf_ into the buffer _buf_.
1409 * nSize [I] size of buf
1410 * buf [O] buffer to receive raw metafile data
1413 * If _buf_ is zero, returns size of buffer required. Otherwise,
1414 * returns number of bytes copied.
1416 UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf )
1418 METAHEADER *mh = MF_GetMetaHeader(hmf);
1421 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1422 if (!mh) return 0; /* FIXME: error code */
1423 if(mh->mtType == METAFILE_DISK)
1424 FIXME("Disk-based metafile?\n");
1425 mfSize = mh->mtSize * 2;
1427 TRACE("returning size %d\n", mfSize);
1430 if(mfSize > nSize) mfSize = nSize;
1431 memmove(buf, mh, mfSize);
1435 /******************************************************************
1436 * GetWinMetaFileBits [GDI32.@]
1438 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1439 UINT cbBuffer, LPBYTE lpbBuffer,
1440 INT fnMapMode, HDC hdcRef)
1448 GetClipBox(hdcRef, &rc);
1449 oldMapMode = SetMapMode(hdcRef, fnMapMode);
1451 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1452 fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1454 hdcmf = CreateMetaFileA(NULL);
1455 PlayEnhMetaFile(hdcmf, hemf, &rc);
1456 hmf = CloseMetaFile(hdcmf);
1457 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1458 DeleteMetaFile(hmf);
1460 SetMapMode(hdcRef, oldMapMode);
1465 /******************************************************************
1466 * MF_Play_MetaCreateRegion
1468 * Handles META_CREATEREGION for PlayMetaFileRecord().
1470 * The layout of the record looks something like this:
1475 * 2 Looks like a handle? - not constant
1477 * 4 Total number of bytes
1478 * 5 No. of separate bands = n [see below]
1479 * 6 Largest number of x co-ords in a band
1480 * 7-10 Bounding box x1 y1 x2 y2
1483 * Regions are divided into bands that are uniform in the
1484 * y-direction. Each band consists of pairs of on/off x-coords and is
1486 * m y0 y1 x1 x2 x3 ... xm m
1487 * into successive rdParm[]s.
1489 * This is probably just a dump of the internal RGNOBJ?
1495 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1500 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1502 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1503 band++, start = end + 1) {
1504 if(*start / 2 != (*start + 1) / 2) {
1505 WARN("Delimiter not even.\n");
1506 DeleteObject( hrgn2 );
1510 end = start + *start + 3;
1511 if(end > (WORD *)mr + mr->rdSize) {
1512 WARN("End points outside record.\n");
1513 DeleteObject( hrgn2 );
1517 if(*start != *end) {
1518 WARN("Mismatched delimiters.\n");
1519 DeleteObject( hrgn2 );
1523 y0 = *(INT16 *)(start + 1);
1524 y1 = *(INT16 *)(start + 2);
1525 for(pair = 0; pair < *start / 2; pair++) {
1526 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1527 *(INT16 *)(start + 4 + 2*pair), y1 );
1528 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1531 DeleteObject( hrgn2 );
1536 /******************************************************************
1537 * MF_Play_MetaExtTextOut
1539 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1542 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1551 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1553 s1 = mr->rdParm[2]; /* String length */
1554 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1555 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1556 /* rec len without dx array */
1558 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1561 rect.left = (SHORT)mr->rdParm[4];
1562 rect.top = (SHORT)mr->rdParm[5];
1563 rect.right = (SHORT)mr->rdParm[6];
1564 rect.bottom = (SHORT)mr->rdParm[7];
1565 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1568 if (mr->rdSize == len / 2)
1569 dxx = NULL; /* determine if array present */
1571 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1573 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1574 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1575 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1578 TRACE("%s len: %ld\n", sot, mr->rdSize);
1579 WARN("Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1580 len, s1, mr->rdSize, mr->rdParm[3]);
1581 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1584 (SHORT)mr->rdParm[1], /* X position */
1585 (SHORT)mr->rdParm[0], /* Y position */
1586 mr->rdParm[3], /* options */
1587 &rect, /* rectangle */
1589 s1, dx); /* length, dx array */
1592 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1593 HeapFree( GetProcessHeap(), 0, dx );