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"
56 #include "wine/debug.h"
58 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
75 #define MFHEADERSIZE (sizeof(METAHEADER))
76 #define MFVERSION 0x300
79 /******************************************************************
82 * Add a handle to an external handle table and return the index
84 static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
88 for (i = 0; i < htlen; i++)
90 if (*(ht->objectHandle + i) == 0)
92 *(ht->objectHandle + i) = hobj;
100 /******************************************************************
101 * MF_Create_HMETATFILE
103 * Creates a (32 bit) HMETAFILE object from a METAHEADER
105 * HMETAFILEs are GDI objects.
107 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
110 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
111 (HGDIOBJ *)&hmf, NULL );
115 GDI_ReleaseObj( hmf );
120 /******************************************************************
121 * MF_Create_HMETATFILE16
123 * Creates a HMETAFILE16 object from a METAHEADER
125 * HMETAFILE16s are Global memory handles.
127 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
130 DWORD size = mh->mtSize * sizeof(WORD);
132 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
135 METAHEADER *mh_dest = GlobalLock16(hmf);
136 memcpy(mh_dest, mh, size);
139 HeapFree(GetProcessHeap(), 0, mh);
143 /******************************************************************
146 * Returns ptr to METAHEADER associated with HMETAFILE
148 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
150 METAHEADER *ret = NULL;
151 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
155 GDI_ReleaseObj( hmf );
160 /******************************************************************
163 * Returns ptr to METAHEADER associated with HMETAFILE16
164 * Should be followed by call to MF_ReleaseMetaHeader16
166 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
168 return GlobalLock16(hmf);
171 /******************************************************************
172 * MF_ReleaseMetaHeader16
174 * Releases METAHEADER associated with HMETAFILE16
176 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
178 return GlobalUnlock16( hmf );
182 /******************************************************************
185 * Convert an array of POINT16 to an array of POINT.
186 * Result must be freed by caller.
188 static POINT *convert_points( UINT count, POINT16 *pt16 )
191 POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
194 for (i = 0; i < count; i++)
196 ret[i].x = pt16[i].x;
197 ret[i].y = pt16[i].y;
204 /******************************************************************
205 * DeleteMetaFile (GDI.127)
207 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
209 return !GlobalFree16( hmf );
212 /******************************************************************
213 * DeleteMetaFile (GDI32.@)
215 * Delete a memory-based metafile.
218 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
220 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
221 if (!metaObj) return FALSE;
222 HeapFree( GetProcessHeap(), 0, metaObj->mh );
223 GDI_FreeObject( hmf, metaObj );
227 /******************************************************************
230 * Returns a pointer to a memory based METAHEADER read in from file HFILE
233 static METAHEADER *MF_ReadMetaFile(HANDLE hfile)
236 DWORD BytesRead, size;
238 size = sizeof(METAHEADER);
239 mh = HeapAlloc( GetProcessHeap(), 0, size );
241 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
243 HeapFree( GetProcessHeap(), 0, mh );
246 size = mh->mtSize * 2;
247 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
249 size -= sizeof(METAHEADER);
250 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
253 HeapFree( GetProcessHeap(), 0, mh );
257 if (mh->mtType != METAFILE_MEMORY) {
258 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
259 mh->mtType = METAFILE_MEMORY;
264 /******************************************************************
265 * GetMetaFile (GDI.124)
267 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
272 TRACE("%s\n", lpFilename);
277 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
278 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
281 mh = MF_ReadMetaFile(hFile);
284 return MF_Create_HMETAFILE16( mh );
287 /******************************************************************
288 * GetMetaFileA (GDI32.@)
290 * Read a metafile from a file. Returns handle to a memory-based metafile.
292 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
297 TRACE("%s\n", lpFilename);
302 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
303 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
306 mh = MF_ReadMetaFile(hFile);
309 return MF_Create_HMETAFILE( mh );
314 /******************************************************************
315 * GetMetaFileW (GDI32.@)
317 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
322 TRACE("%s\n", debugstr_w(lpFilename));
327 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
328 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
331 mh = MF_ReadMetaFile(hFile);
334 return MF_Create_HMETAFILE( mh );
338 /******************************************************************
339 * MF_LoadDiskBasedMetaFile
341 * Creates a new memory-based metafile from a disk-based one.
343 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
349 if(mh->mtType != METAFILE_DISK) {
350 ERR("Not a disk based metafile\n");
353 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
355 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
356 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
357 WARN("Can't open file of disk based metafile\n");
360 mh2 = MF_ReadMetaFile(hfile);
365 /******************************************************************
366 * MF_CreateMetaHeaderDisk
368 * Take a memory based METAHEADER and change it to a disk based METAHEADER
369 * assosiated with filename. Note: Trashes contents of old one.
371 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
376 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
377 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
378 mh->mtType = METAFILE_DISK;
379 size = HeapSize( GetProcessHeap(), 0, mh );
380 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
381 strcpy(mhd->filename, filename);
385 /******************************************************************
386 * CopyMetaFile (GDI.151)
388 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
390 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
391 METAHEADER *mh2 = NULL;
394 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
398 if(mh->mtType == METAFILE_DISK)
399 mh2 = MF_LoadDiskBasedMetaFile(mh);
401 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
402 memcpy( mh2, mh, mh->mtSize * 2 );
404 MF_ReleaseMetaHeader16( hSrcMetaFile );
406 if(lpFilename) { /* disk based metafile */
407 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
408 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
409 HeapFree( GetProcessHeap(), 0, mh2 );
412 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
414 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
417 return MF_Create_HMETAFILE16( mh2 );
421 /******************************************************************
422 * CopyMetaFileA (GDI32.@)
424 * Copies the metafile corresponding to hSrcMetaFile to either
425 * a disk file, if a filename is given, or to a new memory based
426 * metafile, if lpFileName is NULL.
430 * Handle to metafile copy on success, NULL on failure.
434 * Copying to disk returns NULL even if successful.
436 HMETAFILE WINAPI CopyMetaFileA(
437 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
438 LPCSTR lpFilename /* [in] filename if copying to a file */
440 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
441 METAHEADER *mh2 = NULL;
444 TRACE("(%p,%s)\n", hSrcMetaFile, lpFilename);
448 if(mh->mtType == METAFILE_DISK)
449 mh2 = MF_LoadDiskBasedMetaFile(mh);
451 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
452 memcpy( mh2, mh, mh->mtSize * 2 );
455 if(lpFilename) { /* disk based metafile */
456 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
457 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
458 HeapFree( GetProcessHeap(), 0, mh2 );
461 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
463 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
466 return MF_Create_HMETAFILE( mh2 );
470 /******************************************************************
471 * CopyMetaFileW (GDI32.@)
473 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
477 DWORD len = WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, NULL, 0, NULL, NULL );
478 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
482 WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, p, len, NULL, NULL );
483 ret = CopyMetaFileA( hSrcMetaFile, p );
484 HeapFree( GetProcessHeap(), 0, p );
490 /******************************************************************
491 * IsValidMetaFile (GDI.410)
493 * Attempts to check if a given metafile is correctly formatted.
494 * Currently, the only things verified are several properties of the
498 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
501 * This is not exactly what windows does, see _Undocumented_Windows_
504 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
507 METAHEADER *mh = MF_GetMetaHeader16(hmf);
509 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
510 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
511 if (mh->mtVersion == MFVERSION)
513 MF_ReleaseMetaHeader16(hmf);
515 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
520 /*******************************************************************
523 * Helper for PlayMetaFile
525 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
530 unsigned int offset = 0;
537 if (!mh) return FALSE;
538 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
539 mh = MF_LoadDiskBasedMetaFile(mh);
540 if(!mh) return FALSE;
544 /* save the current pen, brush and font */
545 hPen = GetCurrentObject(hdc, OBJ_PEN);
546 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
547 hFont = GetCurrentObject(hdc, OBJ_FONT);
549 /* create the handle table */
550 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
551 sizeof(HANDLETABLE) * mh->mtNoObjects);
552 if(!ht) return FALSE;
554 /* loop through metafile playing records */
555 offset = mh->mtHeaderSize * 2;
556 while (offset < mh->mtSize * 2)
558 mr = (METARECORD *)((char *)mh + offset);
559 TRACE("offset=%04x,size=%08lx\n",
563 "Entry got size 0 at offset %d, total mf length is %ld\n",
564 offset,mh->mtSize*2);
565 break; /* would loop endlessly otherwise */
567 offset += mr->rdSize * 2;
568 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
571 SelectObject(hdc, hBrush);
572 SelectObject(hdc, hPen);
573 SelectObject(hdc, hFont);
575 /* free objects in handle table */
576 for(i = 0; i < mh->mtNoObjects; i++)
577 if(*(ht->objectHandle + i) != 0)
578 DeleteObject(*(ht->objectHandle + i));
580 /* free handle table */
581 HeapFree( GetProcessHeap(), 0, ht );
583 HeapFree( GetProcessHeap(), 0, mh );
587 /******************************************************************
588 * PlayMetaFile (GDI.123)
591 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
594 METAHEADER *mh = MF_GetMetaHeader16( hmf );
595 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
596 MF_ReleaseMetaHeader16( hmf );
600 /******************************************************************
601 * PlayMetaFile (GDI32.@)
603 * Renders the metafile specified by hmf in the DC specified by
604 * hdc. Returns FALSE on failure, TRUE on success.
606 BOOL WINAPI PlayMetaFile(
607 HDC hdc, /* [in] handle of DC to render in */
608 HMETAFILE hmf /* [in] handle of metafile to render */
611 METAHEADER *mh = MF_GetMetaHeader( hmf );
612 return MF_PlayMetaFile( hdc, mh );
616 /******************************************************************
617 * EnumMetaFile (GDI.175)
620 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
621 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
623 METAHEADER *mh = MF_GetMetaHeader16(hmf);
626 HDC hdc = HDC_32(hdc16);
629 unsigned int offset = 0;
635 BOOL16 result = TRUE, loaded = FALSE;
637 TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
639 if(!mh) return FALSE;
640 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
641 mh = MF_LoadDiskBasedMetaFile(mh);
642 if(!mh) return FALSE;
646 /* save the current pen, brush and font */
647 hPen = GetCurrentObject(hdc, OBJ_PEN);
648 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
649 hFont = GetCurrentObject(hdc, OBJ_FONT);
651 /* create the handle table */
653 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
654 sizeof(HANDLETABLE16) * mh->mtNoObjects);
655 spht = K32WOWGlobalLock16(hHT);
658 offset = mh->mtHeaderSize * 2;
660 /* loop through metafile records */
663 args[6] = SELECTOROF(spht);
664 args[5] = OFFSETOF(spht);
665 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
666 args[3] = LOWORD(offset);
667 args[2] = mh->mtNoObjects;
668 args[1] = HIWORD(lpData);
669 args[0] = LOWORD(lpData);
671 while (offset < (mh->mtSize * 2))
675 mr = (METARECORD *)((char *)mh + offset);
677 WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
684 offset += (mr->rdSize * 2);
685 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
686 args[3] = LOWORD(offset);
689 SelectObject(hdc, hBrush);
690 SelectObject(hdc, hPen);
691 SelectObject(hdc, hFont);
693 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
695 /* free objects in handle table */
696 for(i = 0; i < mh->mtNoObjects; i++)
697 if(*(ht->objectHandle + i) != 0)
698 DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
700 /* free handle table */
703 HeapFree( GetProcessHeap(), 0, mh );
704 MF_ReleaseMetaHeader16(hmf);
708 /******************************************************************
709 * EnumMetaFile (GDI32.@)
711 * Loop through the metafile records in hmf, calling the user-specified
712 * function for each one, stopping when the user's function returns FALSE
713 * (which is considered to be failure)
714 * or when no records are left (which is considered to be success).
717 * TRUE on success, FALSE on failure.
720 * Niels de carpentier, april 1996
722 BOOL WINAPI EnumMetaFile(
725 MFENUMPROC lpEnumFunc,
728 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
733 unsigned int offset = 0;
738 TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
740 if(mh->mtType == METAFILE_DISK)
742 /* Create a memory-based copy */
743 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
747 /* save the current pen, brush and font */
748 hPen = GetCurrentObject(hdc, OBJ_PEN);
749 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
750 hFont = GetCurrentObject(hdc, OBJ_FONT);
752 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
753 sizeof(HANDLETABLE) * mh->mtNoObjects);
755 /* loop through metafile records */
756 offset = mh->mtHeaderSize * 2;
758 while (offset < (mh->mtSize * 2))
760 mr = (METARECORD *)((char *)mh + offset);
761 if(mr->rdFunction == META_EOF) {
762 TRACE("Got META_EOF so stopping\n");
765 TRACE("Calling EnumFunc with record type %x\n",
767 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
773 offset += (mr->rdSize * 2);
776 /* restore pen, brush and font */
777 SelectObject(hdc, hBrush);
778 SelectObject(hdc, hPen);
779 SelectObject(hdc, hFont);
781 /* free objects in handle table */
782 for(i = 0; i < mh->mtNoObjects; i++)
783 if(*(ht->objectHandle + i) != 0)
784 DeleteObject(*(ht->objectHandle + i));
786 /* free handle table */
787 HeapFree( GetProcessHeap(), 0, ht);
788 /* free a copy of metafile */
789 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
793 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
794 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
795 /******************************************************************
796 * PlayMetaFileRecord (GDI32.@)
798 * Render a single metafile record specified by *mr in the DC hdc, while
799 * using the handle table *ht, of length handles,
800 * to store metafile objects.
803 * The following metafile records are unimplemented:
805 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
806 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
807 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
809 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
813 BITMAPINFOHEADER *infohdr;
815 TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
817 switch (mr->rdFunction)
822 case META_DELETEOBJECT:
823 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
824 *(ht->objectHandle + mr->rdParm[0]) = 0;
827 case META_SETBKCOLOR:
828 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
832 SetBkMode(hdc, mr->rdParm[0]);
835 case META_SETMAPMODE:
836 SetMapMode(hdc, mr->rdParm[0]);
840 SetROP2(hdc, mr->rdParm[0]);
844 SetRelAbs(hdc, mr->rdParm[0]);
847 case META_SETPOLYFILLMODE:
848 SetPolyFillMode(hdc, mr->rdParm[0]);
851 case META_SETSTRETCHBLTMODE:
852 SetStretchBltMode(hdc, mr->rdParm[0]);
855 case META_SETTEXTCOLOR:
856 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
859 case META_SETWINDOWORG:
860 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
863 case META_SETWINDOWEXT:
864 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
867 case META_SETVIEWPORTORG:
868 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
871 case META_SETVIEWPORTEXT:
872 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
875 case META_OFFSETWINDOWORG:
876 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
879 case META_SCALEWINDOWEXT:
880 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
881 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
884 case META_OFFSETVIEWPORTORG:
885 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
888 case META_SCALEVIEWPORTEXT:
889 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
890 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
894 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
898 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
901 case META_EXCLUDECLIPRECT:
902 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
903 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
906 case META_INTERSECTCLIPRECT:
907 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
908 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
912 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
913 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
914 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
915 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
919 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
920 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
924 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
925 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
929 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
930 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
931 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
932 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
936 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
937 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
941 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
942 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
943 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
947 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
948 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
949 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
957 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
958 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
961 case META_OFFSETCLIPRGN:
962 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
967 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
968 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
969 (char *)(mr->rdParm + 1), s1);
973 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
975 Polygon(hdc, pt, mr->rdParm[0]);
976 HeapFree( GetProcessHeap(), 0, pt );
980 case META_POLYPOLYGON:
983 SHORT *counts = (SHORT *)(mr->rdParm + 1);
985 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
986 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
989 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
992 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
993 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
994 HeapFree( GetProcessHeap(), 0, cnt32 );
997 HeapFree( GetProcessHeap(), 0, pt );
1002 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
1004 Polyline( hdc, pt, mr->rdParm[0] );
1005 HeapFree( GetProcessHeap(), 0, pt );
1009 case META_RESTOREDC:
1010 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
1013 case META_SELECTOBJECT:
1014 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
1018 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1019 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1020 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1021 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1024 case META_CREATEPATTERNBRUSH:
1025 switch (mr->rdParm[0])
1028 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1029 MF_AddHandle(ht, handles,
1030 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
1033 infohdr->biBitCount,
1034 (LPSTR)(mr->rdParm +
1035 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
1039 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1040 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
1044 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1050 case META_CREATEPENINDIRECT:
1053 pen.lopnStyle = mr->rdParm[0];
1054 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
1055 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
1056 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
1057 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
1061 case META_CREATEFONTINDIRECT:
1064 font.lfHeight = (SHORT)mr->rdParm[0];
1065 font.lfWidth = (SHORT)mr->rdParm[1];
1066 font.lfEscapement = (SHORT)mr->rdParm[2];
1067 font.lfOrientation = (SHORT)mr->rdParm[3];
1068 font.lfWeight = (SHORT)mr->rdParm[4];
1069 font.lfItalic = LOBYTE(mr->rdParm[5]);
1070 font.lfUnderline = HIBYTE(mr->rdParm[5]);
1071 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
1072 font.lfCharSet = HIBYTE(mr->rdParm[6]);
1073 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
1074 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
1075 font.lfQuality = LOBYTE(mr->rdParm[8]);
1076 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
1077 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
1078 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
1082 case META_CREATEBRUSHINDIRECT:
1085 brush.lbStyle = mr->rdParm[0];
1086 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
1087 brush.lbHatch = mr->rdParm[3];
1088 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
1092 case META_CREATEPALETTE:
1093 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
1096 case META_SETTEXTALIGN:
1097 SetTextAlign(hdc, mr->rdParm[0]);
1100 case META_SELECTPALETTE:
1101 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
1104 case META_SETMAPPERFLAGS:
1105 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1108 case META_REALIZEPALETTE:
1109 GDIRealizePalette(hdc);
1113 Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
1116 case META_EXTTEXTOUT:
1117 MF_Play_MetaExtTextOut( hdc, mr );
1120 case META_STRETCHDIB:
1122 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1123 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1124 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1125 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1126 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
1127 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1131 case META_DIBSTRETCHBLT:
1133 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1134 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1135 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1136 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1137 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
1138 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1142 case META_STRETCHBLT:
1144 HDC hdcSrc = CreateCompatibleDC(hdc);
1145 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
1146 mr->rdParm[11], /*Height*/
1147 mr->rdParm[13], /*Planes*/
1148 mr->rdParm[14], /*BitsPixel*/
1149 (LPSTR)&mr->rdParm[15]); /*bits*/
1150 SelectObject(hdcSrc,hbitmap);
1151 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1152 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1153 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1154 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1155 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1162 HDC hdcSrc = CreateCompatibleDC(hdc);
1163 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
1164 mr->rdParm[8]/*Height*/,
1165 mr->rdParm[10]/*Planes*/,
1166 mr->rdParm[11]/*BitsPixel*/,
1167 (LPSTR)&mr->rdParm[12]/*bits*/);
1168 SelectObject(hdcSrc,hbitmap);
1169 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
1170 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
1171 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
1172 MAKELONG(0,mr->rdParm[0]));
1177 case META_CREATEREGION:
1179 HRGN hrgn = CreateRectRgn(0,0,0,0);
1181 MF_Play_MetaCreateRegion(mr, hrgn);
1182 MF_AddHandle(ht, handles, hrgn);
1186 case META_FILLREGION:
1187 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
1188 *(ht->objectHandle + mr->rdParm[0]));
1191 case META_FRAMEREGION:
1192 FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
1193 *(ht->objectHandle + mr->rdParm[2]),
1194 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1197 case META_INVERTREGION:
1198 InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1201 case META_PAINTREGION:
1202 PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1205 case META_SELECTCLIPREGION:
1206 SelectClipRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1209 case META_DIBCREATEPATTERNBRUSH:
1210 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1211 but there's no difference */
1212 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1215 case META_DIBBITBLT:
1216 /* In practice I've found that there are two layouts for
1217 META_DIBBITBLT, one (the first here) is the usual one when a src
1218 dc is actually passed to it, the second occurs when the src dc is
1219 passed in as NULL to the creating BitBlt. As the second case has
1220 no dib, a size check will suffice to distinguish.
1222 Caolan.McNamara@ul.ie */
1224 if (mr->rdSize > 12) {
1225 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1226 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1228 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1229 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1230 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1231 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1233 else /* equivalent to a PatBlt */
1234 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1235 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1236 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1239 case META_SETTEXTCHAREXTRA:
1240 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1243 case META_SETTEXTJUSTIFICATION:
1244 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1247 case META_EXTFLOODFILL:
1248 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1249 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1253 case META_SETDIBTODEV:
1255 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1256 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1257 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1258 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1259 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1260 mr->rdParm[2], mr->rdParm[1], bits, info,
1265 #define META_UNIMP(x) case x: \
1266 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1268 META_UNIMP(META_DRAWTEXT)
1269 META_UNIMP(META_ANIMATEPALETTE)
1270 META_UNIMP(META_SETPALENTRIES)
1271 META_UNIMP(META_RESIZEPALETTE)
1272 META_UNIMP(META_RESETDC)
1273 META_UNIMP(META_STARTDOC)
1274 META_UNIMP(META_STARTPAGE)
1275 META_UNIMP(META_ENDPAGE)
1276 META_UNIMP(META_ABORTDOC)
1277 META_UNIMP(META_ENDDOC)
1278 META_UNIMP(META_CREATEBRUSH)
1279 META_UNIMP(META_CREATEBITMAPINDIRECT)
1280 META_UNIMP(META_CREATEBITMAP)
1284 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1290 /******************************************************************
1291 * GetMetaFileBits (GDI.159)
1293 * Trade in a metafile object handle for a handle to the metafile memory.
1297 HGLOBAL16 WINAPI GetMetaFileBits16(
1298 HMETAFILE16 hmf /* [in] metafile handle */
1301 TRACE("hMem out: %04x\n", hmf);
1305 /******************************************************************
1306 * SetMetaFileBits (GDI.160)
1308 * Trade in a metafile memory handle for a handle to a metafile object.
1309 * The memory region should hold a proper metafile, otherwise
1310 * problems will occur when it is used. Validity of the memory is not
1311 * checked. The function is essentially just the identity function.
1313 HMETAFILE16 WINAPI SetMetaFileBits16(
1315 /* [in] handle to a memory region holding a metafile */
1318 TRACE("hmf out: %04x\n", hMem);
1323 /******************************************************************
1324 * SetMetaFileBitsBetter (GDI.196)
1326 * Trade in a metafile memory handle for a handle to a metafile object,
1327 * making a cursory check (using IsValidMetaFile()) that the memory
1328 * handle points to a valid metafile.
1331 * Handle to a metafile on success, NULL on failure..
1333 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1335 if( IsValidMetaFile16( hMeta ) )
1336 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1337 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1338 return (HMETAFILE16)0;
1341 /******************************************************************
1342 * SetMetaFileBitsEx (GDI32.@)
1344 * Create a metafile from raw data. No checking of the data is performed.
1345 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1347 HMETAFILE WINAPI SetMetaFileBitsEx(
1348 UINT size, /* [in] size of metafile, in bytes */
1349 const BYTE *lpData /* [in] pointer to metafile data */
1352 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1354 memcpy(mh, lpData, size);
1355 return MF_Create_HMETAFILE(mh);
1358 /*****************************************************************
1359 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1361 * Copies the data from metafile _hmf_ into the buffer _buf_.
1362 * If _buf_ is zero, returns size of buffer required. Otherwise,
1363 * returns number of bytes copied.
1365 UINT WINAPI GetMetaFileBitsEx(
1366 HMETAFILE hmf, /* [in] metafile */
1367 UINT nSize, /* [in] size of buf */
1368 LPVOID buf /* [out] buffer to receive raw metafile data */
1370 METAHEADER *mh = MF_GetMetaHeader(hmf);
1373 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1374 if (!mh) return 0; /* FIXME: error code */
1375 if(mh->mtType == METAFILE_DISK)
1376 FIXME("Disk-based metafile?\n");
1377 mfSize = mh->mtSize * 2;
1379 TRACE("returning size %d\n", mfSize);
1382 if(mfSize > nSize) mfSize = nSize;
1383 memmove(buf, mh, mfSize);
1387 /******************************************************************
1388 * GetWinMetaFileBits [GDI32.@]
1390 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1391 UINT cbBuffer, LPBYTE lpbBuffer,
1392 INT fnMapMode, HDC hdcRef)
1398 FIXME("(%p,%d,%p,%d,%p): stub\n", hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1399 hdcmf = CreateMetaFileA(NULL);
1400 /* PlayEnhMetaFile(hdcmf, hemf, lpRect); where does the bounding rect come from? */
1401 hmf = CloseMetaFile(hdcmf);
1402 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1403 DeleteMetaFile(hmf);
1407 /******************************************************************
1408 * MF_Play_MetaCreateRegion
1410 * Handles META_CREATEREGION for PlayMetaFileRecord().
1414 * The layout of the record looks something like this:
1419 * 2 Looks like a handle? - not constant
1421 * 4 Total number of bytes
1422 * 5 No. of separate bands = n [see below]
1423 * 6 Largest number of x co-ords in a band
1424 * 7-10 Bounding box x1 y1 x2 y2
1427 * Regions are divided into bands that are uniform in the
1428 * y-direction. Each band consists of pairs of on/off x-coords and is
1430 * m y0 y1 x1 x2 x3 ... xm m
1431 * into successive rdParm[]s.
1433 * This is probably just a dump of the internal RGNOBJ?
1439 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1444 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1446 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1447 band++, start = end + 1) {
1448 if(*start / 2 != (*start + 1) / 2) {
1449 WARN("Delimiter not even.\n");
1450 DeleteObject( hrgn2 );
1454 end = start + *start + 3;
1455 if(end > (WORD *)mr + mr->rdSize) {
1456 WARN("End points outside record.\n");
1457 DeleteObject( hrgn2 );
1461 if(*start != *end) {
1462 WARN("Mismatched delimiters.\n");
1463 DeleteObject( hrgn2 );
1467 y0 = *(INT16 *)(start + 1);
1468 y1 = *(INT16 *)(start + 2);
1469 for(pair = 0; pair < *start / 2; pair++) {
1470 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1471 *(INT16 *)(start + 4 + 2*pair), y1 );
1472 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1475 DeleteObject( hrgn2 );
1480 /******************************************************************
1481 * MF_Play_MetaExtTextOut
1483 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1486 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1495 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1497 s1 = mr->rdParm[2]; /* String length */
1498 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1499 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1500 /* rec len without dx array */
1502 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1505 rect.left = (SHORT)mr->rdParm[4];
1506 rect.top = (SHORT)mr->rdParm[5];
1507 rect.right = (SHORT)mr->rdParm[6];
1508 rect.bottom = (SHORT)mr->rdParm[7];
1509 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1512 if (mr->rdSize == len / 2)
1513 dxx = NULL; /* determine if array present */
1515 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1517 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1518 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1519 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1522 TRACE("%s len: %ld\n", sot, mr->rdSize);
1524 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1525 len, s1, mr->rdSize, mr->rdParm[3]);
1526 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1529 (SHORT)mr->rdParm[1], /* X position */
1530 (SHORT)mr->rdParm[0], /* Y position */
1531 mr->rdParm[3], /* options */
1532 &rect, /* rectangle */
1534 s1, dx); /* length, dx array */
1537 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1538 HeapFree( GetProcessHeap(), 0, dx );