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 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
490 if (lpFilenameW.Buffer)
491 RtlFreeUnicodeString(&lpFilenameW);
496 /******************************************************************
497 * IsValidMetaFile (GDI.410)
499 * Attempts to check if a given metafile is correctly formatted.
500 * Currently, the only things verified are several properties of the
504 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
507 * This is not exactly what windows does, see _Undocumented_Windows_
510 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
513 METAHEADER *mh = MF_GetMetaHeader16(hmf);
515 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
516 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
517 if (mh->mtVersion == MFVERSION)
519 MF_ReleaseMetaHeader16(hmf);
521 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
526 /*******************************************************************
529 * Helper for PlayMetaFile
531 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
536 unsigned int offset = 0;
543 if (!mh) return FALSE;
544 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
545 mh = MF_LoadDiskBasedMetaFile(mh);
546 if(!mh) return FALSE;
550 /* save the current pen, brush and font */
551 hPen = GetCurrentObject(hdc, OBJ_PEN);
552 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
553 hFont = GetCurrentObject(hdc, OBJ_FONT);
555 /* create the handle table */
556 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
557 sizeof(HANDLETABLE) * mh->mtNoObjects);
558 if(!ht) return FALSE;
560 /* loop through metafile playing records */
561 offset = mh->mtHeaderSize * 2;
562 while (offset < mh->mtSize * 2)
564 mr = (METARECORD *)((char *)mh + offset);
565 TRACE("offset=%04x,size=%08lx\n",
569 "Entry got size 0 at offset %d, total mf length is %ld\n",
570 offset,mh->mtSize*2);
571 break; /* would loop endlessly otherwise */
573 offset += mr->rdSize * 2;
574 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
577 SelectObject(hdc, hBrush);
578 SelectObject(hdc, hPen);
579 SelectObject(hdc, hFont);
581 /* free objects in handle table */
582 for(i = 0; i < mh->mtNoObjects; i++)
583 if(*(ht->objectHandle + i) != 0)
584 DeleteObject(*(ht->objectHandle + i));
586 /* free handle table */
587 HeapFree( GetProcessHeap(), 0, ht );
589 HeapFree( GetProcessHeap(), 0, mh );
593 /******************************************************************
594 * PlayMetaFile (GDI.123)
597 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
600 METAHEADER *mh = MF_GetMetaHeader16( hmf );
601 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
602 MF_ReleaseMetaHeader16( hmf );
606 /******************************************************************
607 * PlayMetaFile (GDI32.@)
609 * Renders the metafile specified by hmf in the DC specified by
610 * hdc. Returns FALSE on failure, TRUE on success.
612 BOOL WINAPI PlayMetaFile(
613 HDC hdc, /* [in] handle of DC to render in */
614 HMETAFILE hmf /* [in] handle of metafile to render */
617 METAHEADER *mh = MF_GetMetaHeader( hmf );
618 return MF_PlayMetaFile( hdc, mh );
622 /******************************************************************
623 * EnumMetaFile (GDI.175)
626 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
627 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
629 METAHEADER *mh = MF_GetMetaHeader16(hmf);
632 HDC hdc = HDC_32(hdc16);
635 unsigned int offset = 0;
641 BOOL16 result = TRUE, loaded = FALSE;
643 TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
645 if(!mh) return FALSE;
646 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
647 mh = MF_LoadDiskBasedMetaFile(mh);
648 if(!mh) return FALSE;
652 /* save the current pen, brush and font */
653 hPen = GetCurrentObject(hdc, OBJ_PEN);
654 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
655 hFont = GetCurrentObject(hdc, OBJ_FONT);
657 /* create the handle table */
659 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
660 sizeof(HANDLETABLE16) * mh->mtNoObjects);
661 spht = K32WOWGlobalLock16(hHT);
664 offset = mh->mtHeaderSize * 2;
666 /* loop through metafile records */
669 args[6] = SELECTOROF(spht);
670 args[5] = OFFSETOF(spht);
671 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
672 args[3] = LOWORD(offset);
673 args[2] = mh->mtNoObjects;
674 args[1] = HIWORD(lpData);
675 args[0] = LOWORD(lpData);
677 while (offset < (mh->mtSize * 2))
681 mr = (METARECORD *)((char *)mh + offset);
683 WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
690 offset += (mr->rdSize * 2);
691 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
692 args[3] = LOWORD(offset);
695 SelectObject(hdc, hBrush);
696 SelectObject(hdc, hPen);
697 SelectObject(hdc, hFont);
699 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
701 /* free objects in handle table */
702 for(i = 0; i < mh->mtNoObjects; i++)
703 if(*(ht->objectHandle + i) != 0)
704 DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
706 /* free handle table */
709 HeapFree( GetProcessHeap(), 0, mh );
710 MF_ReleaseMetaHeader16(hmf);
714 /******************************************************************
715 * EnumMetaFile (GDI32.@)
717 * Loop through the metafile records in hmf, calling the user-specified
718 * function for each one, stopping when the user's function returns FALSE
719 * (which is considered to be failure)
720 * or when no records are left (which is considered to be success).
723 * TRUE on success, FALSE on failure.
726 * Niels de carpentier, april 1996
728 BOOL WINAPI EnumMetaFile(
731 MFENUMPROC lpEnumFunc,
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 if (mhTemp) 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:
1212 SelectClipRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1215 case META_DIBCREATEPATTERNBRUSH:
1216 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1217 but there's no difference */
1218 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1221 case META_DIBBITBLT:
1222 /* In practice I've found that there are two layouts for
1223 META_DIBBITBLT, one (the first here) is the usual one when a src
1224 dc is actually passed to it, the second occurs when the src dc is
1225 passed in as NULL to the creating BitBlt. As the second case has
1226 no dib, a size check will suffice to distinguish.
1228 Caolan.McNamara@ul.ie */
1230 if (mr->rdSize > 12) {
1231 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1232 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1234 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1235 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1236 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1237 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1239 else /* equivalent to a PatBlt */
1240 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1241 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1242 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1245 case META_SETTEXTCHAREXTRA:
1246 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1249 case META_SETTEXTJUSTIFICATION:
1250 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1253 case META_EXTFLOODFILL:
1254 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1255 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1259 case META_SETDIBTODEV:
1261 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1262 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1263 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1264 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1265 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1266 mr->rdParm[2], mr->rdParm[1], bits, info,
1271 #define META_UNIMP(x) case x: \
1272 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1274 META_UNIMP(META_DRAWTEXT)
1275 META_UNIMP(META_ANIMATEPALETTE)
1276 META_UNIMP(META_SETPALENTRIES)
1277 META_UNIMP(META_RESIZEPALETTE)
1278 META_UNIMP(META_RESETDC)
1279 META_UNIMP(META_STARTDOC)
1280 META_UNIMP(META_STARTPAGE)
1281 META_UNIMP(META_ENDPAGE)
1282 META_UNIMP(META_ABORTDOC)
1283 META_UNIMP(META_ENDDOC)
1284 META_UNIMP(META_CREATEBRUSH)
1285 META_UNIMP(META_CREATEBITMAPINDIRECT)
1286 META_UNIMP(META_CREATEBITMAP)
1290 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1296 /******************************************************************
1297 * GetMetaFileBits (GDI.159)
1299 * Trade in a metafile object handle for a handle to the metafile memory.
1303 HGLOBAL16 WINAPI GetMetaFileBits16(
1304 HMETAFILE16 hmf /* [in] metafile handle */
1307 TRACE("hMem out: %04x\n", hmf);
1311 /******************************************************************
1312 * SetMetaFileBits (GDI.160)
1314 * Trade in a metafile memory handle for a handle to a metafile object.
1315 * The memory region should hold a proper metafile, otherwise
1316 * problems will occur when it is used. Validity of the memory is not
1317 * checked. The function is essentially just the identity function.
1319 HMETAFILE16 WINAPI SetMetaFileBits16(
1321 /* [in] handle to a memory region holding a metafile */
1324 TRACE("hmf out: %04x\n", hMem);
1329 /******************************************************************
1330 * SetMetaFileBitsBetter (GDI.196)
1332 * Trade in a metafile memory handle for a handle to a metafile object,
1333 * making a cursory check (using IsValidMetaFile()) that the memory
1334 * handle points to a valid metafile.
1337 * Handle to a metafile on success, NULL on failure..
1339 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1341 if( IsValidMetaFile16( hMeta ) )
1342 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1343 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1344 return (HMETAFILE16)0;
1347 /******************************************************************
1348 * SetMetaFileBitsEx (GDI32.@)
1350 * Create a metafile from raw data. No checking of the data is performed.
1351 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1353 HMETAFILE WINAPI SetMetaFileBitsEx(
1354 UINT size, /* [in] size of metafile, in bytes */
1355 const BYTE *lpData /* [in] pointer to metafile data */
1358 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1360 memcpy(mh, lpData, size);
1361 return MF_Create_HMETAFILE(mh);
1364 /*****************************************************************
1365 * GetMetaFileBitsEx (GDI32.@)
1367 * Get raw metafile data.
1369 * Copies the data from metafile _hmf_ into the buffer _buf_.
1370 * If _buf_ is zero, returns size of buffer required. Otherwise,
1371 * returns number of bytes copied.
1373 UINT WINAPI GetMetaFileBitsEx(
1374 HMETAFILE hmf, /* [in] metafile */
1375 UINT nSize, /* [in] size of buf */
1376 LPVOID buf /* [out] buffer to receive raw metafile data */)
1378 METAHEADER *mh = MF_GetMetaHeader(hmf);
1381 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1382 if (!mh) return 0; /* FIXME: error code */
1383 if(mh->mtType == METAFILE_DISK)
1384 FIXME("Disk-based metafile?\n");
1385 mfSize = mh->mtSize * 2;
1387 TRACE("returning size %d\n", mfSize);
1390 if(mfSize > nSize) mfSize = nSize;
1391 memmove(buf, mh, mfSize);
1395 /******************************************************************
1396 * GetWinMetaFileBits [GDI32.@]
1398 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1399 UINT cbBuffer, LPBYTE lpbBuffer,
1400 INT fnMapMode, HDC hdcRef)
1408 GetClipBox(hdcRef, &rc);
1409 oldMapMode = SetMapMode(hdcRef, fnMapMode);
1411 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1412 fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1414 hdcmf = CreateMetaFileA(NULL);
1415 PlayEnhMetaFile(hdcmf, hemf, &rc);
1416 hmf = CloseMetaFile(hdcmf);
1417 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1418 DeleteMetaFile(hmf);
1420 SetMapMode(hdcRef, oldMapMode);
1425 /******************************************************************
1426 * MF_Play_MetaCreateRegion
1428 * Handles META_CREATEREGION for PlayMetaFileRecord().
1432 * The layout of the record looks something like this:
1437 * 2 Looks like a handle? - not constant
1439 * 4 Total number of bytes
1440 * 5 No. of separate bands = n [see below]
1441 * 6 Largest number of x co-ords in a band
1442 * 7-10 Bounding box x1 y1 x2 y2
1445 * Regions are divided into bands that are uniform in the
1446 * y-direction. Each band consists of pairs of on/off x-coords and is
1448 * m y0 y1 x1 x2 x3 ... xm m
1449 * into successive rdParm[]s.
1451 * This is probably just a dump of the internal RGNOBJ?
1457 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1462 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1464 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1465 band++, start = end + 1) {
1466 if(*start / 2 != (*start + 1) / 2) {
1467 WARN("Delimiter not even.\n");
1468 DeleteObject( hrgn2 );
1472 end = start + *start + 3;
1473 if(end > (WORD *)mr + mr->rdSize) {
1474 WARN("End points outside record.\n");
1475 DeleteObject( hrgn2 );
1479 if(*start != *end) {
1480 WARN("Mismatched delimiters.\n");
1481 DeleteObject( hrgn2 );
1485 y0 = *(INT16 *)(start + 1);
1486 y1 = *(INT16 *)(start + 2);
1487 for(pair = 0; pair < *start / 2; pair++) {
1488 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1489 *(INT16 *)(start + 4 + 2*pair), y1 );
1490 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1493 DeleteObject( hrgn2 );
1498 /******************************************************************
1499 * MF_Play_MetaExtTextOut
1501 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1504 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1513 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1515 s1 = mr->rdParm[2]; /* String length */
1516 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1517 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1518 /* rec len without dx array */
1520 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1523 rect.left = (SHORT)mr->rdParm[4];
1524 rect.top = (SHORT)mr->rdParm[5];
1525 rect.right = (SHORT)mr->rdParm[6];
1526 rect.bottom = (SHORT)mr->rdParm[7];
1527 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1530 if (mr->rdSize == len / 2)
1531 dxx = NULL; /* determine if array present */
1533 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1535 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1536 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1537 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1540 TRACE("%s len: %ld\n", sot, mr->rdSize);
1542 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1543 len, s1, mr->rdSize, mr->rdParm[3]);
1544 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1547 (SHORT)mr->rdParm[1], /* X position */
1548 (SHORT)mr->rdParm[0], /* Y position */
1549 mr->rdParm[3], /* options */
1550 &rect, /* rectangle */
1552 s1, dx); /* length, dx array */
1555 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1556 HeapFree( GetProcessHeap(), 0, dx );