4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * These functions are primarily involved with metafile playback or anything
24 * that touches a HMETAFILE.
25 * For recording of metafiles look in graphics/metafiledrv/
27 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
28 * global memory handles so these cannot be interchanged.
30 * Memory-based metafiles are just stored as a continuous block of memory with
31 * a METAHEADER at the head with METARECORDs appended to it. mtType is
32 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
33 * disk-based metafile - even mtType is METAFILE_MEMORY.
34 * 16bit HMETAFILE16s are global handles to this block
35 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
37 * Disk-based metafiles are rather different. HMETAFILE16s point to a
38 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
39 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
40 * more 0, then 2 which may be a time stamp of the file and then the path of
41 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
51 #include "wine/winbase16.h"
52 #include "wine/wingdi16.h"
57 #include "gdi_private.h"
58 #include "wine/debug.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
77 #define MFHEADERSIZE (sizeof(METAHEADER))
78 #define MFVERSION 0x300
81 /******************************************************************
84 * Add a handle to an external handle table and return the index
86 static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
90 for (i = 0; i < htlen; i++)
92 if (*(ht->objectHandle + i) == 0)
94 *(ht->objectHandle + i) = hobj;
102 /******************************************************************
103 * MF_Create_HMETATFILE
105 * Creates a (32 bit) HMETAFILE object from a METAHEADER
107 * HMETAFILEs are GDI objects.
109 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
112 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
113 (HGDIOBJ *)&hmf, NULL );
117 GDI_ReleaseObj( hmf );
122 /******************************************************************
123 * MF_Create_HMETATFILE16
125 * Creates a HMETAFILE16 object from a METAHEADER
127 * HMETAFILE16s are Global memory handles.
129 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
132 DWORD size = mh->mtSize * sizeof(WORD);
134 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
137 METAHEADER *mh_dest = GlobalLock16(hmf);
138 memcpy(mh_dest, mh, size);
141 HeapFree(GetProcessHeap(), 0, mh);
145 /******************************************************************
148 * Returns ptr to METAHEADER associated with HMETAFILE
150 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
152 METAHEADER *ret = NULL;
153 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
157 GDI_ReleaseObj( hmf );
162 /******************************************************************
165 * Returns ptr to METAHEADER associated with HMETAFILE16
166 * Should be followed by call to MF_ReleaseMetaHeader16
168 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
170 return GlobalLock16(hmf);
173 /******************************************************************
174 * MF_ReleaseMetaHeader16
176 * Releases METAHEADER associated with HMETAFILE16
178 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
180 return GlobalUnlock16( hmf );
184 /******************************************************************
187 * Convert an array of POINT16 to an array of POINT.
188 * Result must be freed by caller.
190 static POINT *convert_points( UINT count, POINT16 *pt16 )
193 POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
196 for (i = 0; i < count; i++)
198 ret[i].x = pt16[i].x;
199 ret[i].y = pt16[i].y;
206 /******************************************************************
207 * DeleteMetaFile (GDI.127)
209 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
211 return !GlobalFree16( hmf );
214 /******************************************************************
215 * DeleteMetaFile (GDI32.@)
217 * Delete a memory-based metafile.
220 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
222 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
223 if (!metaObj) return FALSE;
224 HeapFree( GetProcessHeap(), 0, metaObj->mh );
225 GDI_FreeObject( hmf, metaObj );
229 /******************************************************************
232 * Returns a pointer to a memory based METAHEADER read in from file HFILE
235 static METAHEADER *MF_ReadMetaFile(HANDLE hfile)
238 DWORD BytesRead, size;
240 size = sizeof(METAHEADER);
241 mh = HeapAlloc( GetProcessHeap(), 0, size );
243 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
245 HeapFree( GetProcessHeap(), 0, mh );
248 size = mh->mtSize * 2;
249 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
251 size -= sizeof(METAHEADER);
252 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
255 HeapFree( GetProcessHeap(), 0, mh );
259 if (mh->mtType != METAFILE_MEMORY) {
260 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
261 mh->mtType = METAFILE_MEMORY;
266 /******************************************************************
267 * GetMetaFile (GDI.124)
269 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
274 TRACE("%s\n", lpFilename);
279 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
280 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
283 mh = MF_ReadMetaFile(hFile);
286 return MF_Create_HMETAFILE16( mh );
289 /******************************************************************
290 * GetMetaFileA (GDI32.@)
292 * Read a metafile from a file. Returns handle to a memory-based metafile.
294 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
299 TRACE("%s\n", lpFilename);
304 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
305 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
308 mh = MF_ReadMetaFile(hFile);
311 return MF_Create_HMETAFILE( mh );
316 /******************************************************************
317 * GetMetaFileW (GDI32.@)
319 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
324 TRACE("%s\n", debugstr_w(lpFilename));
329 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
330 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
333 mh = MF_ReadMetaFile(hFile);
336 return MF_Create_HMETAFILE( mh );
340 /******************************************************************
341 * MF_LoadDiskBasedMetaFile
343 * Creates a new memory-based metafile from a disk-based one.
345 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
351 if(mh->mtType != METAFILE_DISK) {
352 ERR("Not a disk based metafile\n");
355 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
357 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
358 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
359 WARN("Can't open file of disk based metafile\n");
362 mh2 = MF_ReadMetaFile(hfile);
367 /******************************************************************
368 * MF_CreateMetaHeaderDisk
370 * Take a memory based METAHEADER and change it to a disk based METAHEADER
371 * assosiated with filename. Note: Trashes contents of old one.
373 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni )
378 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
379 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
380 mh->mtType = METAFILE_DISK;
381 size = HeapSize( GetProcessHeap(), 0, mh );
382 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
385 WideCharToMultiByte(CP_ACP, 0, filename, -1,
386 mhd->filename, sizeof mhd->filename, NULL, NULL);
388 lstrcpynA( mhd->filename, filename, sizeof mhd->filename );
392 /******************************************************************
393 * CopyMetaFile (GDI.151)
395 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
397 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
398 METAHEADER *mh2 = NULL;
401 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
405 if(mh->mtType == METAFILE_DISK)
406 mh2 = MF_LoadDiskBasedMetaFile(mh);
408 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
409 memcpy( mh2, mh, mh->mtSize * 2 );
411 MF_ReleaseMetaHeader16( hSrcMetaFile );
413 if(lpFilename) { /* disk based metafile */
414 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
415 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
416 HeapFree( GetProcessHeap(), 0, mh2 );
419 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
421 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, FALSE);
424 return MF_Create_HMETAFILE16( mh2 );
428 /******************************************************************
429 * CopyMetaFileW (GDI32.@)
431 * Copies the metafile corresponding to hSrcMetaFile to either
432 * a disk file, if a filename is given, or to a new memory based
433 * metafile, if lpFileName is NULL.
437 * Handle to metafile copy on success, NULL on failure.
441 * Copying to disk returns NULL even if successful.
443 HMETAFILE WINAPI CopyMetaFileW(
444 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
445 LPCWSTR lpFilename /* [in] filename if copying to a file */)
447 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
448 METAHEADER *mh2 = NULL;
451 TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename));
455 if(mh->mtType == METAFILE_DISK)
456 mh2 = MF_LoadDiskBasedMetaFile(mh);
458 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
459 memcpy( mh2, mh, mh->mtSize * 2 );
462 if(lpFilename) { /* disk based metafile */
463 if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL,
464 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
465 HeapFree( GetProcessHeap(), 0, mh2 );
468 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
470 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, TRUE);
473 return MF_Create_HMETAFILE( mh2 );
477 /******************************************************************
478 * CopyMetaFileA (GDI32.@)
480 HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile,
483 UNICODE_STRING lpFilenameW;
486 if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
487 else lpFilenameW.Buffer = NULL;
489 if (lpFilenameW.Buffer) {
490 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
492 RtlFreeUnicodeString(&lpFilenameW);
497 /******************************************************************
498 * IsValidMetaFile (GDI.410)
500 * Attempts to check if a given metafile is correctly formatted.
501 * Currently, the only things verified are several properties of the
505 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
508 * This is not exactly what windows does, see _Undocumented_Windows_
511 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
514 METAHEADER *mh = MF_GetMetaHeader16(hmf);
516 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
517 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
518 if (mh->mtVersion == MFVERSION)
520 MF_ReleaseMetaHeader16(hmf);
522 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
527 /*******************************************************************
530 * Helper for PlayMetaFile
532 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
537 unsigned int offset = 0;
544 if (!mh) return FALSE;
545 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
546 mh = MF_LoadDiskBasedMetaFile(mh);
547 if(!mh) return FALSE;
551 /* save the current pen, brush and font */
552 hPen = GetCurrentObject(hdc, OBJ_PEN);
553 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
554 hFont = GetCurrentObject(hdc, OBJ_FONT);
556 /* create the handle table */
557 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
558 sizeof(HANDLETABLE) * mh->mtNoObjects);
559 if(!ht) return FALSE;
561 /* loop through metafile playing records */
562 offset = mh->mtHeaderSize * 2;
563 while (offset < mh->mtSize * 2)
565 mr = (METARECORD *)((char *)mh + offset);
566 TRACE("offset=%04x,size=%08lx\n",
570 "Entry got size 0 at offset %d, total mf length is %ld\n",
571 offset,mh->mtSize*2);
572 break; /* would loop endlessly otherwise */
574 offset += mr->rdSize * 2;
575 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
578 SelectObject(hdc, hBrush);
579 SelectObject(hdc, hPen);
580 SelectObject(hdc, hFont);
582 /* free objects in handle table */
583 for(i = 0; i < mh->mtNoObjects; i++)
584 if(*(ht->objectHandle + i) != 0)
585 DeleteObject(*(ht->objectHandle + i));
587 /* free handle table */
588 HeapFree( GetProcessHeap(), 0, ht );
590 HeapFree( GetProcessHeap(), 0, mh );
594 /******************************************************************
595 * PlayMetaFile (GDI.123)
598 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
601 METAHEADER *mh = MF_GetMetaHeader16( hmf );
602 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
603 MF_ReleaseMetaHeader16( hmf );
607 /******************************************************************
608 * PlayMetaFile (GDI32.@)
610 * Renders the metafile specified by hmf in the DC specified by
611 * hdc. Returns FALSE on failure, TRUE on success.
613 BOOL WINAPI PlayMetaFile(
614 HDC hdc, /* [in] handle of DC to render in */
615 HMETAFILE hmf /* [in] handle of metafile to render */
618 METAHEADER *mh = MF_GetMetaHeader( hmf );
619 return MF_PlayMetaFile( hdc, mh );
623 /******************************************************************
624 * EnumMetaFile (GDI.175)
627 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
628 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
630 METAHEADER *mh = MF_GetMetaHeader16(hmf);
633 HDC hdc = HDC_32(hdc16);
636 unsigned int offset = 0;
642 BOOL16 result = TRUE, loaded = FALSE;
644 TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
646 if(!mh) return FALSE;
647 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
648 mh = MF_LoadDiskBasedMetaFile(mh);
649 if(!mh) return FALSE;
653 /* save the current pen, brush and font */
654 hPen = GetCurrentObject(hdc, OBJ_PEN);
655 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
656 hFont = GetCurrentObject(hdc, OBJ_FONT);
658 /* create the handle table */
660 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
661 sizeof(HANDLETABLE16) * mh->mtNoObjects);
662 spht = K32WOWGlobalLock16(hHT);
665 offset = mh->mtHeaderSize * 2;
667 /* loop through metafile records */
670 args[6] = SELECTOROF(spht);
671 args[5] = OFFSETOF(spht);
672 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
673 args[3] = LOWORD(offset);
674 args[2] = mh->mtNoObjects;
675 args[1] = HIWORD(lpData);
676 args[0] = LOWORD(lpData);
678 while (offset < (mh->mtSize * 2))
682 mr = (METARECORD *)((char *)mh + offset);
684 WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
691 offset += (mr->rdSize * 2);
692 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
693 args[3] = LOWORD(offset);
696 SelectObject(hdc, hBrush);
697 SelectObject(hdc, hPen);
698 SelectObject(hdc, hFont);
700 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
702 /* free objects in handle table */
703 for(i = 0; i < mh->mtNoObjects; i++)
704 if(*(ht->objectHandle + i) != 0)
705 DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
707 /* free handle table */
710 HeapFree( GetProcessHeap(), 0, mh );
711 MF_ReleaseMetaHeader16(hmf);
715 /******************************************************************
716 * EnumMetaFile (GDI32.@)
718 * Loop through the metafile records in hmf, calling the user-specified
719 * function for each one, stopping when the user's function returns FALSE
720 * (which is considered to be failure)
721 * or when no records are left (which is considered to be success).
724 * TRUE on success, FALSE on failure.
727 * Niels de carpentier, april 1996
729 BOOL WINAPI EnumMetaFile(
732 MFENUMPROC lpEnumFunc,
735 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
740 unsigned int offset = 0;
745 TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
747 if(mh->mtType == METAFILE_DISK)
749 /* Create a memory-based copy */
750 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
754 /* save the current pen, brush and font */
755 hPen = GetCurrentObject(hdc, OBJ_PEN);
756 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
757 hFont = GetCurrentObject(hdc, OBJ_FONT);
759 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
760 sizeof(HANDLETABLE) * mh->mtNoObjects);
762 /* loop through metafile records */
763 offset = mh->mtHeaderSize * 2;
765 while (offset < (mh->mtSize * 2))
767 mr = (METARECORD *)((char *)mh + offset);
768 if(mr->rdFunction == META_EOF) {
769 TRACE("Got META_EOF so stopping\n");
772 TRACE("Calling EnumFunc with record type %x\n",
774 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
780 offset += (mr->rdSize * 2);
783 /* restore pen, brush and font */
784 SelectObject(hdc, hBrush);
785 SelectObject(hdc, hPen);
786 SelectObject(hdc, hFont);
788 /* free objects in handle table */
789 for(i = 0; i < mh->mtNoObjects; i++)
790 if(*(ht->objectHandle + i) != 0)
791 DeleteObject(*(ht->objectHandle + i));
793 /* free handle table */
794 HeapFree( GetProcessHeap(), 0, ht);
795 /* free a copy of metafile */
796 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
800 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
801 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
802 /******************************************************************
803 * PlayMetaFileRecord (GDI32.@)
805 * Render a single metafile record specified by *mr in the DC hdc, while
806 * using the handle table *ht, of length handles,
807 * to store metafile objects.
810 * The following metafile records are unimplemented:
812 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
813 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
814 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
816 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
820 BITMAPINFOHEADER *infohdr;
822 TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
824 switch (mr->rdFunction)
829 case META_DELETEOBJECT:
830 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
831 *(ht->objectHandle + mr->rdParm[0]) = 0;
834 case META_SETBKCOLOR:
835 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
839 SetBkMode(hdc, mr->rdParm[0]);
842 case META_SETMAPMODE:
843 SetMapMode(hdc, mr->rdParm[0]);
847 SetROP2(hdc, mr->rdParm[0]);
851 SetRelAbs(hdc, mr->rdParm[0]);
854 case META_SETPOLYFILLMODE:
855 SetPolyFillMode(hdc, mr->rdParm[0]);
858 case META_SETSTRETCHBLTMODE:
859 SetStretchBltMode(hdc, mr->rdParm[0]);
862 case META_SETTEXTCOLOR:
863 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
866 case META_SETWINDOWORG:
867 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
870 case META_SETWINDOWEXT:
871 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
874 case META_SETVIEWPORTORG:
875 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
878 case META_SETVIEWPORTEXT:
879 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
882 case META_OFFSETWINDOWORG:
883 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
886 case META_SCALEWINDOWEXT:
887 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
888 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
891 case META_OFFSETVIEWPORTORG:
892 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
895 case META_SCALEVIEWPORTEXT:
896 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
897 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
901 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
905 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
908 case META_EXCLUDECLIPRECT:
909 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
910 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
913 case META_INTERSECTCLIPRECT:
914 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
915 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
919 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
920 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
921 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
922 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
926 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
927 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
931 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
932 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
936 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
937 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
938 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
939 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
943 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
944 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
948 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
949 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
950 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
954 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
955 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
956 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
964 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
965 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
968 case META_OFFSETCLIPRGN:
969 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
974 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
975 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
976 (char *)(mr->rdParm + 1), s1);
980 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
982 Polygon(hdc, pt, mr->rdParm[0]);
983 HeapFree( GetProcessHeap(), 0, pt );
987 case META_POLYPOLYGON:
990 SHORT *counts = (SHORT *)(mr->rdParm + 1);
992 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
993 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
996 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
999 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
1000 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
1001 HeapFree( GetProcessHeap(), 0, cnt32 );
1004 HeapFree( GetProcessHeap(), 0, pt );
1009 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
1011 Polyline( hdc, pt, mr->rdParm[0] );
1012 HeapFree( GetProcessHeap(), 0, pt );
1016 case META_RESTOREDC:
1017 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
1020 case META_SELECTOBJECT:
1021 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
1025 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1026 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1027 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1028 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1031 case META_CREATEPATTERNBRUSH:
1032 switch (mr->rdParm[0])
1035 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1036 MF_AddHandle(ht, handles,
1037 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
1040 infohdr->biBitCount,
1041 (LPSTR)(mr->rdParm +
1042 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
1046 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1047 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
1051 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1057 case META_CREATEPENINDIRECT:
1060 pen.lopnStyle = mr->rdParm[0];
1061 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
1062 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
1063 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
1064 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
1068 case META_CREATEFONTINDIRECT:
1071 font.lfHeight = (SHORT)mr->rdParm[0];
1072 font.lfWidth = (SHORT)mr->rdParm[1];
1073 font.lfEscapement = (SHORT)mr->rdParm[2];
1074 font.lfOrientation = (SHORT)mr->rdParm[3];
1075 font.lfWeight = (SHORT)mr->rdParm[4];
1076 font.lfItalic = LOBYTE(mr->rdParm[5]);
1077 font.lfUnderline = HIBYTE(mr->rdParm[5]);
1078 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
1079 font.lfCharSet = HIBYTE(mr->rdParm[6]);
1080 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
1081 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
1082 font.lfQuality = LOBYTE(mr->rdParm[8]);
1083 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
1084 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
1085 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
1089 case META_CREATEBRUSHINDIRECT:
1092 brush.lbStyle = mr->rdParm[0];
1093 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
1094 brush.lbHatch = mr->rdParm[3];
1095 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
1099 case META_CREATEPALETTE:
1100 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
1103 case META_SETTEXTALIGN:
1104 SetTextAlign(hdc, mr->rdParm[0]);
1107 case META_SELECTPALETTE:
1108 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
1111 case META_SETMAPPERFLAGS:
1112 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1115 case META_REALIZEPALETTE:
1116 GDIRealizePalette(hdc);
1120 Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
1123 case META_EXTTEXTOUT:
1124 MF_Play_MetaExtTextOut( hdc, mr );
1127 case META_STRETCHDIB:
1129 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1130 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1131 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1132 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1133 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
1134 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1138 case META_DIBSTRETCHBLT:
1140 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1141 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1142 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1143 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1144 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
1145 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1149 case META_STRETCHBLT:
1151 HDC hdcSrc = CreateCompatibleDC(hdc);
1152 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
1153 mr->rdParm[11], /*Height*/
1154 mr->rdParm[13], /*Planes*/
1155 mr->rdParm[14], /*BitsPixel*/
1156 (LPSTR)&mr->rdParm[15]); /*bits*/
1157 SelectObject(hdcSrc,hbitmap);
1158 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1159 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1160 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1161 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1162 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1169 HDC hdcSrc = CreateCompatibleDC(hdc);
1170 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
1171 mr->rdParm[8]/*Height*/,
1172 mr->rdParm[10]/*Planes*/,
1173 mr->rdParm[11]/*BitsPixel*/,
1174 (LPSTR)&mr->rdParm[12]/*bits*/);
1175 SelectObject(hdcSrc,hbitmap);
1176 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
1177 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
1178 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
1179 MAKELONG(0,mr->rdParm[0]));
1184 case META_CREATEREGION:
1186 HRGN hrgn = CreateRectRgn(0,0,0,0);
1188 MF_Play_MetaCreateRegion(mr, hrgn);
1189 MF_AddHandle(ht, handles, hrgn);
1193 case META_FILLREGION:
1194 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
1195 *(ht->objectHandle + mr->rdParm[0]));
1198 case META_FRAMEREGION:
1199 FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
1200 *(ht->objectHandle + mr->rdParm[2]),
1201 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1204 case META_INVERTREGION:
1205 InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1208 case META_PAINTREGION:
1209 PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1212 case META_SELECTCLIPREGION:
1213 SelectClipRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1216 case META_DIBCREATEPATTERNBRUSH:
1217 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1218 but there's no difference */
1219 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1222 case META_DIBBITBLT:
1223 /* In practice I've found that there are two layouts for
1224 META_DIBBITBLT, one (the first here) is the usual one when a src
1225 dc is actually passed to it, the second occurs when the src dc is
1226 passed in as NULL to the creating BitBlt. As the second case has
1227 no dib, a size check will suffice to distinguish.
1229 Caolan.McNamara@ul.ie */
1231 if (mr->rdSize > 12) {
1232 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1233 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1235 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1236 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1237 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1238 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1240 else /* equivalent to a PatBlt */
1241 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1242 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1243 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1246 case META_SETTEXTCHAREXTRA:
1247 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1250 case META_SETTEXTJUSTIFICATION:
1251 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1254 case META_EXTFLOODFILL:
1255 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1256 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1260 case META_SETDIBTODEV:
1262 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1263 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1264 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1265 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1266 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1267 mr->rdParm[2], mr->rdParm[1], bits, info,
1272 #define META_UNIMP(x) case x: \
1273 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1275 META_UNIMP(META_DRAWTEXT)
1276 META_UNIMP(META_ANIMATEPALETTE)
1277 META_UNIMP(META_SETPALENTRIES)
1278 META_UNIMP(META_RESIZEPALETTE)
1279 META_UNIMP(META_RESETDC)
1280 META_UNIMP(META_STARTDOC)
1281 META_UNIMP(META_STARTPAGE)
1282 META_UNIMP(META_ENDPAGE)
1283 META_UNIMP(META_ABORTDOC)
1284 META_UNIMP(META_ENDDOC)
1285 META_UNIMP(META_CREATEBRUSH)
1286 META_UNIMP(META_CREATEBITMAPINDIRECT)
1287 META_UNIMP(META_CREATEBITMAP)
1291 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1297 /******************************************************************
1298 * GetMetaFileBits (GDI.159)
1300 * Trade in a metafile object handle for a handle to the metafile memory.
1304 HGLOBAL16 WINAPI GetMetaFileBits16(
1305 HMETAFILE16 hmf /* [in] metafile handle */
1308 TRACE("hMem out: %04x\n", hmf);
1312 /******************************************************************
1313 * SetMetaFileBits (GDI.160)
1315 * Trade in a metafile memory handle for a handle to a metafile object.
1316 * The memory region should hold a proper metafile, otherwise
1317 * problems will occur when it is used. Validity of the memory is not
1318 * checked. The function is essentially just the identity function.
1320 HMETAFILE16 WINAPI SetMetaFileBits16(
1322 /* [in] handle to a memory region holding a metafile */
1325 TRACE("hmf out: %04x\n", hMem);
1330 /******************************************************************
1331 * SetMetaFileBitsBetter (GDI.196)
1333 * Trade in a metafile memory handle for a handle to a metafile object,
1334 * making a cursory check (using IsValidMetaFile()) that the memory
1335 * handle points to a valid metafile.
1338 * Handle to a metafile on success, NULL on failure..
1340 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1342 if( IsValidMetaFile16( hMeta ) )
1343 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1344 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1345 return (HMETAFILE16)0;
1348 /******************************************************************
1349 * SetMetaFileBitsEx (GDI32.@)
1351 * Create a metafile from raw data. No checking of the data is performed.
1352 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1354 HMETAFILE WINAPI SetMetaFileBitsEx(
1355 UINT size, /* [in] size of metafile, in bytes */
1356 const BYTE *lpData /* [in] pointer to metafile data */
1359 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1361 memcpy(mh, lpData, size);
1362 return MF_Create_HMETAFILE(mh);
1365 /*****************************************************************
1366 * GetMetaFileBitsEx (GDI32.@)
1368 * Get raw metafile data.
1370 * Copies the data from metafile _hmf_ into the buffer _buf_.
1371 * If _buf_ is zero, returns size of buffer required. Otherwise,
1372 * returns number of bytes copied.
1374 UINT WINAPI GetMetaFileBitsEx(
1375 HMETAFILE hmf, /* [in] metafile */
1376 UINT nSize, /* [in] size of buf */
1377 LPVOID buf /* [out] buffer to receive raw metafile data */)
1379 METAHEADER *mh = MF_GetMetaHeader(hmf);
1382 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1383 if (!mh) return 0; /* FIXME: error code */
1384 if(mh->mtType == METAFILE_DISK)
1385 FIXME("Disk-based metafile?\n");
1386 mfSize = mh->mtSize * 2;
1388 TRACE("returning size %d\n", mfSize);
1391 if(mfSize > nSize) mfSize = nSize;
1392 memmove(buf, mh, mfSize);
1396 /******************************************************************
1397 * GetWinMetaFileBits [GDI32.@]
1399 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1400 UINT cbBuffer, LPBYTE lpbBuffer,
1401 INT fnMapMode, HDC hdcRef)
1409 GetClipBox(hdcRef, &rc);
1410 oldMapMode = SetMapMode(hdcRef, fnMapMode);
1412 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1413 fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1415 hdcmf = CreateMetaFileA(NULL);
1416 PlayEnhMetaFile(hdcmf, hemf, &rc);
1417 hmf = CloseMetaFile(hdcmf);
1418 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1419 DeleteMetaFile(hmf);
1421 SetMapMode(hdcRef, oldMapMode);
1426 /******************************************************************
1427 * MF_Play_MetaCreateRegion
1429 * Handles META_CREATEREGION for PlayMetaFileRecord().
1433 * The layout of the record looks something like this:
1438 * 2 Looks like a handle? - not constant
1440 * 4 Total number of bytes
1441 * 5 No. of separate bands = n [see below]
1442 * 6 Largest number of x co-ords in a band
1443 * 7-10 Bounding box x1 y1 x2 y2
1446 * Regions are divided into bands that are uniform in the
1447 * y-direction. Each band consists of pairs of on/off x-coords and is
1449 * m y0 y1 x1 x2 x3 ... xm m
1450 * into successive rdParm[]s.
1452 * This is probably just a dump of the internal RGNOBJ?
1458 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1463 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1465 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1466 band++, start = end + 1) {
1467 if(*start / 2 != (*start + 1) / 2) {
1468 WARN("Delimiter not even.\n");
1469 DeleteObject( hrgn2 );
1473 end = start + *start + 3;
1474 if(end > (WORD *)mr + mr->rdSize) {
1475 WARN("End points outside record.\n");
1476 DeleteObject( hrgn2 );
1480 if(*start != *end) {
1481 WARN("Mismatched delimiters.\n");
1482 DeleteObject( hrgn2 );
1486 y0 = *(INT16 *)(start + 1);
1487 y1 = *(INT16 *)(start + 2);
1488 for(pair = 0; pair < *start / 2; pair++) {
1489 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1490 *(INT16 *)(start + 4 + 2*pair), y1 );
1491 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1494 DeleteObject( hrgn2 );
1499 /******************************************************************
1500 * MF_Play_MetaExtTextOut
1502 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1505 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1514 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1516 s1 = mr->rdParm[2]; /* String length */
1517 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1518 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1519 /* rec len without dx array */
1521 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1524 rect.left = (SHORT)mr->rdParm[4];
1525 rect.top = (SHORT)mr->rdParm[5];
1526 rect.right = (SHORT)mr->rdParm[6];
1527 rect.bottom = (SHORT)mr->rdParm[7];
1528 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1531 if (mr->rdSize == len / 2)
1532 dxx = NULL; /* determine if array present */
1534 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1536 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1537 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1538 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1541 TRACE("%s len: %ld\n", sot, mr->rdSize);
1543 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1544 len, s1, mr->rdSize, mr->rdParm[3]);
1545 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1548 (SHORT)mr->rdParm[1], /* X position */
1549 (SHORT)mr->rdParm[0], /* Y position */
1550 mr->rdParm[3], /* options */
1551 &rect, /* rectangle */
1553 s1, dx); /* length, dx array */
1556 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1557 HeapFree( GetProcessHeap(), 0, dx );