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 if(mh->mtVersion != MFVERSION || mh->mtHeaderSize != size / 2) {
249 HeapFree( GetProcessHeap(), 0, mh );
252 size = mh->mtSize * 2;
253 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
255 size -= sizeof(METAHEADER);
256 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
259 HeapFree( GetProcessHeap(), 0, mh );
263 if (mh->mtType != METAFILE_MEMORY) {
264 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
265 mh->mtType = METAFILE_MEMORY;
270 /******************************************************************
271 * GetMetaFile (GDI.124)
273 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
278 TRACE("%s\n", lpFilename);
283 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
284 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
287 mh = MF_ReadMetaFile(hFile);
290 return MF_Create_HMETAFILE16( mh );
293 /******************************************************************
294 * GetMetaFileA (GDI32.@)
296 * Read a metafile from a file. Returns handle to a memory-based metafile.
298 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
303 TRACE("%s\n", lpFilename);
308 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
309 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
312 mh = MF_ReadMetaFile(hFile);
315 return MF_Create_HMETAFILE( mh );
320 /******************************************************************
321 * GetMetaFileW (GDI32.@)
323 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
328 TRACE("%s\n", debugstr_w(lpFilename));
333 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
334 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
337 mh = MF_ReadMetaFile(hFile);
340 return MF_Create_HMETAFILE( mh );
344 /******************************************************************
345 * MF_LoadDiskBasedMetaFile
347 * Creates a new memory-based metafile from a disk-based one.
349 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
355 if(mh->mtType != METAFILE_DISK) {
356 ERR("Not a disk based metafile\n");
359 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
361 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
362 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
363 WARN("Can't open file of disk based metafile\n");
366 mh2 = MF_ReadMetaFile(hfile);
371 /******************************************************************
372 * MF_CreateMetaHeaderDisk
374 * Take a memory based METAHEADER and change it to a disk based METAHEADER
375 * assosiated with filename. Note: Trashes contents of old one.
377 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni )
382 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
383 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
384 mh->mtType = METAFILE_DISK;
385 size = HeapSize( GetProcessHeap(), 0, mh );
386 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
389 WideCharToMultiByte(CP_ACP, 0, filename, -1,
390 mhd->filename, sizeof mhd->filename, NULL, NULL);
392 lstrcpynA( mhd->filename, filename, sizeof mhd->filename );
396 /******************************************************************
397 * CopyMetaFile (GDI.151)
399 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
401 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
402 METAHEADER *mh2 = NULL;
405 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
409 if(mh->mtType == METAFILE_DISK)
410 mh2 = MF_LoadDiskBasedMetaFile(mh);
412 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
413 memcpy( mh2, mh, mh->mtSize * 2 );
415 MF_ReleaseMetaHeader16( hSrcMetaFile );
417 if(lpFilename) { /* disk based metafile */
419 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
420 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
421 HeapFree( GetProcessHeap(), 0, mh2 );
424 WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
426 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, FALSE);
429 return MF_Create_HMETAFILE16( mh2 );
433 /******************************************************************
434 * CopyMetaFileW (GDI32.@)
436 * Copies the metafile corresponding to hSrcMetaFile to either
437 * a disk file, if a filename is given, or to a new memory based
438 * metafile, if lpFileName is NULL.
442 * Handle to metafile copy on success, NULL on failure.
446 * Copying to disk returns NULL even if successful.
448 HMETAFILE WINAPI CopyMetaFileW(
449 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
450 LPCWSTR lpFilename /* [in] filename if copying to a file */)
452 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
453 METAHEADER *mh2 = NULL;
456 TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename));
460 if(mh->mtType == METAFILE_DISK)
461 mh2 = MF_LoadDiskBasedMetaFile(mh);
463 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
464 memcpy( mh2, mh, mh->mtSize * 2 );
467 if(lpFilename) { /* disk based metafile */
469 if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL,
470 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
471 HeapFree( GetProcessHeap(), 0, mh2 );
474 WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
476 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, TRUE);
479 return MF_Create_HMETAFILE( mh2 );
483 /******************************************************************
484 * CopyMetaFileA (GDI32.@)
486 HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile,
489 UNICODE_STRING lpFilenameW;
492 if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
493 else lpFilenameW.Buffer = NULL;
495 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
496 if (lpFilenameW.Buffer)
497 RtlFreeUnicodeString(&lpFilenameW);
502 /******************************************************************
503 * IsValidMetaFile (GDI.410)
505 * Attempts to check if a given metafile is correctly formatted.
506 * Currently, the only things verified are several properties of the
510 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
513 * This is not exactly what windows does, see _Undocumented_Windows_
516 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
519 METAHEADER *mh = MF_GetMetaHeader16(hmf);
521 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
522 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
523 if (mh->mtVersion == MFVERSION)
525 MF_ReleaseMetaHeader16(hmf);
527 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
532 /*******************************************************************
535 * Helper for PlayMetaFile
537 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
542 unsigned int offset = 0;
549 if (!mh) return FALSE;
550 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
551 mh = MF_LoadDiskBasedMetaFile(mh);
552 if(!mh) return FALSE;
556 /* save the current pen, brush and font */
557 hPen = GetCurrentObject(hdc, OBJ_PEN);
558 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
559 hFont = GetCurrentObject(hdc, OBJ_FONT);
561 /* create the handle table */
562 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
563 sizeof(HANDLETABLE) * mh->mtNoObjects);
564 if(!ht) return FALSE;
566 /* loop through metafile playing records */
567 offset = mh->mtHeaderSize * 2;
568 while (offset < mh->mtSize * 2)
570 mr = (METARECORD *)((char *)mh + offset);
571 TRACE("offset=%04x,size=%08lx\n",
575 "Entry got size 0 at offset %d, total mf length is %ld\n",
576 offset,mh->mtSize*2);
577 break; /* would loop endlessly otherwise */
579 offset += mr->rdSize * 2;
580 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
583 SelectObject(hdc, hBrush);
584 SelectObject(hdc, hPen);
585 SelectObject(hdc, hFont);
587 /* free objects in handle table */
588 for(i = 0; i < mh->mtNoObjects; i++)
589 if(*(ht->objectHandle + i) != 0)
590 DeleteObject(*(ht->objectHandle + i));
592 /* free handle table */
593 HeapFree( GetProcessHeap(), 0, ht );
595 HeapFree( GetProcessHeap(), 0, mh );
599 /******************************************************************
600 * PlayMetaFile (GDI.123)
603 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
606 METAHEADER *mh = MF_GetMetaHeader16( hmf );
607 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
608 MF_ReleaseMetaHeader16( hmf );
612 /******************************************************************
613 * PlayMetaFile (GDI32.@)
615 * Renders the metafile specified by hmf in the DC specified by
616 * hdc. Returns FALSE on failure, TRUE on success.
618 BOOL WINAPI PlayMetaFile(
619 HDC hdc, /* [in] handle of DC to render in */
620 HMETAFILE hmf /* [in] handle of metafile to render */
623 METAHEADER *mh = MF_GetMetaHeader( hmf );
624 return MF_PlayMetaFile( hdc, mh );
628 /******************************************************************
629 * EnumMetaFile (GDI.175)
632 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
633 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
635 METAHEADER *mh = MF_GetMetaHeader16(hmf);
638 HDC hdc = HDC_32(hdc16);
641 unsigned int offset = 0;
647 BOOL16 result = TRUE, loaded = FALSE;
649 TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
651 if(!mh) return FALSE;
652 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
653 mh = MF_LoadDiskBasedMetaFile(mh);
654 if(!mh) return FALSE;
658 /* save the current pen, brush and font */
659 hPen = GetCurrentObject(hdc, OBJ_PEN);
660 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
661 hFont = GetCurrentObject(hdc, OBJ_FONT);
663 /* create the handle table */
665 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
666 sizeof(HANDLETABLE16) * mh->mtNoObjects);
667 spht = K32WOWGlobalLock16(hHT);
670 offset = mh->mtHeaderSize * 2;
672 /* loop through metafile records */
675 args[6] = SELECTOROF(spht);
676 args[5] = OFFSETOF(spht);
677 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
678 args[3] = LOWORD(offset);
679 args[2] = mh->mtNoObjects;
680 args[1] = HIWORD(lpData);
681 args[0] = LOWORD(lpData);
683 while (offset < (mh->mtSize * 2))
687 mr = (METARECORD *)((char *)mh + offset);
689 WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
696 offset += (mr->rdSize * 2);
697 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
698 args[3] = LOWORD(offset);
701 SelectObject(hdc, hBrush);
702 SelectObject(hdc, hPen);
703 SelectObject(hdc, hFont);
705 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
707 /* free objects in handle table */
708 for(i = 0; i < mh->mtNoObjects; i++)
709 if(*(ht->objectHandle + i) != 0)
710 DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
712 /* free handle table */
715 HeapFree( GetProcessHeap(), 0, mh );
716 MF_ReleaseMetaHeader16(hmf);
720 /******************************************************************
721 * EnumMetaFile (GDI32.@)
723 * Loop through the metafile records in hmf, calling the user-specified
724 * function for each one, stopping when the user's function returns FALSE
725 * (which is considered to be failure)
726 * or when no records are left (which is considered to be success).
729 * TRUE on success, FALSE on failure.
732 * Niels de carpentier, april 1996
734 BOOL WINAPI EnumMetaFile(
737 MFENUMPROC lpEnumFunc,
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.
1314 HGLOBAL16 WINAPI GetMetaFileBits16(
1315 HMETAFILE16 hmf /* [in] metafile handle */
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.
1330 HMETAFILE16 WINAPI SetMetaFileBits16(
1332 /* [in] handle to a memory region holding a metafile */
1335 TRACE("hmf out: %04x\n", hMem);
1340 /******************************************************************
1341 * SetMetaFileBitsBetter (GDI.196)
1343 * Trade in a metafile memory handle for a handle to a metafile object,
1344 * making a cursory check (using IsValidMetaFile()) that the memory
1345 * handle points to a valid metafile.
1348 * Handle to a metafile on success, NULL on failure..
1350 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1352 if( IsValidMetaFile16( hMeta ) )
1353 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1354 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1355 return (HMETAFILE16)0;
1358 /******************************************************************
1359 * SetMetaFileBitsEx (GDI32.@)
1361 * Create a metafile from raw data. No checking of the data is performed.
1362 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1364 HMETAFILE WINAPI SetMetaFileBitsEx(
1365 UINT size, /* [in] size of metafile, in bytes */
1366 const BYTE *lpData /* [in] pointer to metafile data */
1369 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1371 memcpy(mh, lpData, size);
1372 return MF_Create_HMETAFILE(mh);
1375 /*****************************************************************
1376 * GetMetaFileBitsEx (GDI32.@)
1378 * Get raw metafile data.
1380 * Copies the data from metafile _hmf_ into the buffer _buf_.
1381 * If _buf_ is zero, returns size of buffer required. Otherwise,
1382 * returns number of bytes copied.
1384 UINT WINAPI GetMetaFileBitsEx(
1385 HMETAFILE hmf, /* [in] metafile */
1386 UINT nSize, /* [in] size of buf */
1387 LPVOID buf /* [out] buffer to receive raw metafile data */)
1389 METAHEADER *mh = MF_GetMetaHeader(hmf);
1392 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1393 if (!mh) return 0; /* FIXME: error code */
1394 if(mh->mtType == METAFILE_DISK)
1395 FIXME("Disk-based metafile?\n");
1396 mfSize = mh->mtSize * 2;
1398 TRACE("returning size %d\n", mfSize);
1401 if(mfSize > nSize) mfSize = nSize;
1402 memmove(buf, mh, mfSize);
1406 /******************************************************************
1407 * GetWinMetaFileBits [GDI32.@]
1409 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1410 UINT cbBuffer, LPBYTE lpbBuffer,
1411 INT fnMapMode, HDC hdcRef)
1419 GetClipBox(hdcRef, &rc);
1420 oldMapMode = SetMapMode(hdcRef, fnMapMode);
1422 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1423 fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1425 hdcmf = CreateMetaFileA(NULL);
1426 PlayEnhMetaFile(hdcmf, hemf, &rc);
1427 hmf = CloseMetaFile(hdcmf);
1428 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1429 DeleteMetaFile(hmf);
1431 SetMapMode(hdcRef, oldMapMode);
1436 /******************************************************************
1437 * MF_Play_MetaCreateRegion
1439 * Handles META_CREATEREGION for PlayMetaFileRecord().
1443 * The layout of the record looks something like this:
1448 * 2 Looks like a handle? - not constant
1450 * 4 Total number of bytes
1451 * 5 No. of separate bands = n [see below]
1452 * 6 Largest number of x co-ords in a band
1453 * 7-10 Bounding box x1 y1 x2 y2
1456 * Regions are divided into bands that are uniform in the
1457 * y-direction. Each band consists of pairs of on/off x-coords and is
1459 * m y0 y1 x1 x2 x3 ... xm m
1460 * into successive rdParm[]s.
1462 * This is probably just a dump of the internal RGNOBJ?
1468 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1473 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1475 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1476 band++, start = end + 1) {
1477 if(*start / 2 != (*start + 1) / 2) {
1478 WARN("Delimiter not even.\n");
1479 DeleteObject( hrgn2 );
1483 end = start + *start + 3;
1484 if(end > (WORD *)mr + mr->rdSize) {
1485 WARN("End points outside record.\n");
1486 DeleteObject( hrgn2 );
1490 if(*start != *end) {
1491 WARN("Mismatched delimiters.\n");
1492 DeleteObject( hrgn2 );
1496 y0 = *(INT16 *)(start + 1);
1497 y1 = *(INT16 *)(start + 2);
1498 for(pair = 0; pair < *start / 2; pair++) {
1499 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1500 *(INT16 *)(start + 4 + 2*pair), y1 );
1501 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1504 DeleteObject( hrgn2 );
1509 /******************************************************************
1510 * MF_Play_MetaExtTextOut
1512 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1515 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1524 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1526 s1 = mr->rdParm[2]; /* String length */
1527 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1528 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1529 /* rec len without dx array */
1531 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1534 rect.left = (SHORT)mr->rdParm[4];
1535 rect.top = (SHORT)mr->rdParm[5];
1536 rect.right = (SHORT)mr->rdParm[6];
1537 rect.bottom = (SHORT)mr->rdParm[7];
1538 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1541 if (mr->rdSize == len / 2)
1542 dxx = NULL; /* determine if array present */
1544 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1546 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1547 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1548 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1551 TRACE("%s len: %ld\n", sot, mr->rdSize);
1553 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1554 len, s1, mr->rdSize, mr->rdParm[3]);
1555 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1558 (SHORT)mr->rdParm[1], /* X position */
1559 (SHORT)mr->rdParm[0], /* Y position */
1560 mr->rdParm[3], /* options */
1561 &rect, /* rectangle */
1563 s1, dx); /* length, dx array */
1566 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1567 HeapFree( GetProcessHeap(), 0, dx );