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
78 /* ### start build ### */
79 extern WORD CALLBACK MF_CallTo16_word_wllwl(MFENUMPROC16,WORD,LONG,LONG,WORD,LONG);
80 /* ### stop build ### */
82 /******************************************************************
85 * Add a handle to an external handle table and return the index
87 static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
91 for (i = 0; i < htlen; i++)
93 if (*(ht->objectHandle + i) == 0)
95 *(ht->objectHandle + i) = hobj;
103 /******************************************************************
104 * MF_Create_HMETATFILE
106 * Creates a (32 bit) HMETAFILE object from a METAHEADER
108 * HMETAFILEs are GDI objects.
110 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
113 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
114 (HGDIOBJ *)&hmf, NULL );
118 GDI_ReleaseObj( hmf );
123 /******************************************************************
124 * MF_Create_HMETATFILE16
126 * Creates a HMETAFILE16 object from a METAHEADER
128 * HMETAFILE16s are Global memory handles.
130 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
133 DWORD size = mh->mtSize * sizeof(WORD);
135 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
138 METAHEADER *mh_dest = GlobalLock16(hmf);
139 memcpy(mh_dest, mh, size);
142 HeapFree(GetProcessHeap(), 0, mh);
146 /******************************************************************
149 * Returns ptr to METAHEADER associated with HMETAFILE
151 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
153 METAHEADER *ret = NULL;
154 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
158 GDI_ReleaseObj( hmf );
163 /******************************************************************
166 * Returns ptr to METAHEADER associated with HMETAFILE16
167 * Should be followed by call to MF_ReleaseMetaHeader16
169 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
171 return GlobalLock16(hmf);
174 /******************************************************************
175 * MF_ReleaseMetaHeader16
177 * Releases METAHEADER associated with HMETAFILE16
179 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
181 return GlobalUnlock16( hmf );
185 /******************************************************************
188 * Convert an array of POINT16 to an array of POINT.
189 * Result must be freed by caller.
191 static POINT *convert_points( UINT count, POINT16 *pt16 )
194 POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
197 for (i = 0; i < count; i++)
199 ret[i].x = pt16[i].x;
200 ret[i].y = pt16[i].y;
207 /******************************************************************
208 * DeleteMetaFile (GDI.127)
210 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
212 return !GlobalFree16( hmf );
215 /******************************************************************
216 * DeleteMetaFile (GDI32.@)
218 * Delete a memory-based metafile.
221 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
223 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
224 if (!metaObj) return FALSE;
225 HeapFree( GetProcessHeap(), 0, metaObj->mh );
226 GDI_FreeObject( hmf, metaObj );
230 /******************************************************************
233 * Returns a pointer to a memory based METAHEADER read in from file HFILE
236 static METAHEADER *MF_ReadMetaFile(HANDLE hfile)
239 DWORD BytesRead, size;
241 size = sizeof(METAHEADER);
242 mh = HeapAlloc( GetProcessHeap(), 0, size );
244 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
246 HeapFree( GetProcessHeap(), 0, mh );
249 size = mh->mtSize * 2;
250 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
252 size -= sizeof(METAHEADER);
253 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
256 HeapFree( GetProcessHeap(), 0, mh );
260 if (mh->mtType != METAFILE_MEMORY) {
261 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
262 mh->mtType = METAFILE_MEMORY;
267 /******************************************************************
268 * GetMetaFile (GDI.124)
270 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
275 TRACE("%s\n", lpFilename);
280 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
281 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
284 mh = MF_ReadMetaFile(hFile);
287 return MF_Create_HMETAFILE16( mh );
290 /******************************************************************
291 * GetMetaFileA (GDI32.@)
293 * Read a metafile from a file. Returns handle to a memory-based metafile.
295 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
300 TRACE("%s\n", lpFilename);
305 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
306 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
309 mh = MF_ReadMetaFile(hFile);
312 return MF_Create_HMETAFILE( mh );
317 /******************************************************************
318 * GetMetaFileW (GDI32.@)
320 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
325 TRACE("%s\n", debugstr_w(lpFilename));
330 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
331 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
334 mh = MF_ReadMetaFile(hFile);
337 return MF_Create_HMETAFILE( mh );
341 /******************************************************************
342 * MF_LoadDiskBasedMetaFile
344 * Creates a new memory-based metafile from a disk-based one.
346 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
352 if(mh->mtType != METAFILE_DISK) {
353 ERR("Not a disk based metafile\n");
356 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
358 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
359 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
360 WARN("Can't open file of disk based metafile\n");
363 mh2 = MF_ReadMetaFile(hfile);
368 /******************************************************************
369 * MF_CreateMetaHeaderDisk
371 * Take a memory based METAHEADER and change it to a disk based METAHEADER
372 * assosiated with filename. Note: Trashes contents of old one.
374 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
379 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
380 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
381 mh->mtType = METAFILE_DISK;
382 size = HeapSize( GetProcessHeap(), 0, mh );
383 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
384 strcpy(mhd->filename, filename);
388 /******************************************************************
389 * CopyMetaFile (GDI.151)
391 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
393 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
394 METAHEADER *mh2 = NULL;
397 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
401 if(mh->mtType == METAFILE_DISK)
402 mh2 = MF_LoadDiskBasedMetaFile(mh);
404 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
405 memcpy( mh2, mh, mh->mtSize * 2 );
407 MF_ReleaseMetaHeader16( hSrcMetaFile );
409 if(lpFilename) { /* disk based metafile */
410 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
411 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
412 HeapFree( GetProcessHeap(), 0, mh2 );
415 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
417 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
420 return MF_Create_HMETAFILE16( mh2 );
424 /******************************************************************
425 * CopyMetaFileA (GDI32.@)
427 * Copies the metafile corresponding to hSrcMetaFile to either
428 * a disk file, if a filename is given, or to a new memory based
429 * metafile, if lpFileName is NULL.
433 * Handle to metafile copy on success, NULL on failure.
437 * Copying to disk returns NULL even if successful.
439 HMETAFILE WINAPI CopyMetaFileA(
440 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
441 LPCSTR lpFilename /* [in] filename if copying to a file */
443 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
444 METAHEADER *mh2 = NULL;
447 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
451 if(mh->mtType == METAFILE_DISK)
452 mh2 = MF_LoadDiskBasedMetaFile(mh);
454 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
455 memcpy( mh2, mh, mh->mtSize * 2 );
458 if(lpFilename) { /* disk based metafile */
459 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
460 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
461 HeapFree( GetProcessHeap(), 0, mh2 );
464 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
466 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
469 return MF_Create_HMETAFILE( mh2 );
473 /******************************************************************
474 * CopyMetaFileW (GDI32.@)
476 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
480 DWORD len = WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, NULL, 0, NULL, NULL );
481 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
485 WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, p, len, NULL, NULL );
486 ret = CopyMetaFileA( hSrcMetaFile, p );
487 HeapFree( GetProcessHeap(), 0, p );
493 /******************************************************************
494 * IsValidMetaFile (GDI.410)
496 * Attempts to check if a given metafile is correctly formatted.
497 * Currently, the only things verified are several properties of the
501 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
504 * This is not exactly what windows does, see _Undocumented_Windows_
507 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
510 METAHEADER *mh = MF_GetMetaHeader16(hmf);
512 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
513 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
514 if (mh->mtVersion == MFVERSION)
516 MF_ReleaseMetaHeader16(hmf);
518 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
523 /*******************************************************************
526 * Helper for PlayMetaFile
528 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
533 unsigned int offset = 0;
540 if (!mh) return FALSE;
541 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
542 mh = MF_LoadDiskBasedMetaFile(mh);
543 if(!mh) return FALSE;
547 /* save the current pen, brush and font */
548 hPen = GetCurrentObject(hdc, OBJ_PEN);
549 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
550 hFont = GetCurrentObject(hdc, OBJ_FONT);
552 /* create the handle table */
553 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
554 sizeof(HANDLETABLE) * mh->mtNoObjects);
555 if(!ht) return FALSE;
557 /* loop through metafile playing records */
558 offset = mh->mtHeaderSize * 2;
559 while (offset < mh->mtSize * 2)
561 mr = (METARECORD *)((char *)mh + offset);
562 TRACE("offset=%04x,size=%08lx\n",
566 "Entry got size 0 at offset %d, total mf length is %ld\n",
567 offset,mh->mtSize*2);
568 break; /* would loop endlessly otherwise */
570 offset += mr->rdSize * 2;
571 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
574 SelectObject(hdc, hBrush);
575 SelectObject(hdc, hPen);
576 SelectObject(hdc, hFont);
578 /* free objects in handle table */
579 for(i = 0; i < mh->mtNoObjects; i++)
580 if(*(ht->objectHandle + i) != 0)
581 DeleteObject(*(ht->objectHandle + i));
583 /* free handle table */
584 HeapFree( GetProcessHeap(), 0, ht );
586 HeapFree( GetProcessHeap(), 0, mh );
590 /******************************************************************
591 * PlayMetaFile (GDI.123)
594 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
597 METAHEADER *mh = MF_GetMetaHeader16( hmf );
598 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
599 MF_ReleaseMetaHeader16( hmf );
603 /******************************************************************
604 * PlayMetaFile (GDI32.@)
606 * Renders the metafile specified by hmf in the DC specified by
607 * hdc. Returns FALSE on failure, TRUE on success.
609 BOOL WINAPI PlayMetaFile(
610 HDC hdc, /* [in] handle of DC to render in */
611 HMETAFILE hmf /* [in] handle of metafile to render */
614 METAHEADER *mh = MF_GetMetaHeader( hmf );
615 return MF_PlayMetaFile( hdc, mh );
619 /******************************************************************
620 * EnumMetaFile (GDI.175)
623 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
624 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
626 METAHEADER *mh = MF_GetMetaHeader16(hmf);
629 HDC hdc = HDC_32(hdc16);
632 unsigned int offset = 0;
637 BOOL16 result = TRUE, loaded = FALSE;
639 TRACE("(%04x, %04x, %08lx, %08lx)\n",
640 hdc, hmf, (DWORD)lpEnumFunc, lpData);
643 if(!mh) return FALSE;
644 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
645 mh = MF_LoadDiskBasedMetaFile(mh);
646 if(!mh) return FALSE;
650 /* save the current pen, brush and font */
651 hPen = GetCurrentObject(hdc, OBJ_PEN);
652 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
653 hFont = GetCurrentObject(hdc, OBJ_FONT);
655 /* create the handle table */
657 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
658 sizeof(HANDLETABLE16) * mh->mtNoObjects);
659 spht = K32WOWGlobalLock16(hHT);
662 offset = mh->mtHeaderSize * 2;
664 /* loop through metafile records */
666 while (offset < (mh->mtSize * 2))
668 mr = (METARECORD *)((char *)mh + offset);
670 if (!MF_CallTo16_word_wllwl( lpEnumFunc, hdc16, spht,
671 MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
672 mh->mtNoObjects, (LONG)lpData ))
679 offset += (mr->rdSize * 2);
682 SelectObject(hdc, hBrush);
683 SelectObject(hdc, hPen);
684 SelectObject(hdc, hFont);
686 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
688 /* free objects in handle table */
689 for(i = 0; i < mh->mtNoObjects; i++)
690 if(*(ht->objectHandle + i) != 0)
691 DeleteObject(*(ht->objectHandle + i));
693 /* free handle table */
696 HeapFree( GetProcessHeap(), 0, mh );
697 MF_ReleaseMetaHeader16(hmf);
701 /******************************************************************
702 * EnumMetaFile (GDI32.@)
704 * Loop through the metafile records in hmf, calling the user-specified
705 * function for each one, stopping when the user's function returns FALSE
706 * (which is considered to be failure)
707 * or when no records are left (which is considered to be success).
710 * TRUE on success, FALSE on failure.
713 * Niels de carpentier, april 1996
715 BOOL WINAPI EnumMetaFile(
718 MFENUMPROC lpEnumFunc,
721 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
726 unsigned int offset = 0;
731 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
733 if(mh->mtType == METAFILE_DISK)
735 /* Create a memory-based copy */
736 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
740 /* save the current pen, brush and font */
741 hPen = GetCurrentObject(hdc, OBJ_PEN);
742 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
743 hFont = GetCurrentObject(hdc, OBJ_FONT);
745 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
746 sizeof(HANDLETABLE) * mh->mtNoObjects);
748 /* loop through metafile records */
749 offset = mh->mtHeaderSize * 2;
751 while (offset < (mh->mtSize * 2))
753 mr = (METARECORD *)((char *)mh + offset);
754 if(mr->rdFunction == META_EOF) {
755 TRACE("Got META_EOF so stopping\n");
758 TRACE("Calling EnumFunc with record type %x\n",
760 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
766 offset += (mr->rdSize * 2);
769 /* restore pen, brush and font */
770 SelectObject(hdc, hBrush);
771 SelectObject(hdc, hPen);
772 SelectObject(hdc, hFont);
774 /* free objects in handle table */
775 for(i = 0; i < mh->mtNoObjects; i++)
776 if(*(ht->objectHandle + i) != 0)
777 DeleteObject(*(ht->objectHandle + i));
779 /* free handle table */
780 HeapFree( GetProcessHeap(), 0, ht);
781 /* free a copy of metafile */
782 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
786 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
787 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
788 /******************************************************************
789 * PlayMetaFileRecord (GDI32.@)
791 * Render a single metafile record specified by *mr in the DC hdc, while
792 * using the handle table *ht, of length handles,
793 * to store metafile objects.
796 * The following metafile records are unimplemented:
798 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
799 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
800 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
802 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
806 BITMAPINFOHEADER *infohdr;
808 TRACE("(%04x %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
810 switch (mr->rdFunction)
815 case META_DELETEOBJECT:
816 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
817 *(ht->objectHandle + mr->rdParm[0]) = 0;
820 case META_SETBKCOLOR:
821 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
825 SetBkMode(hdc, mr->rdParm[0]);
828 case META_SETMAPMODE:
829 SetMapMode(hdc, mr->rdParm[0]);
833 SetROP2(hdc, mr->rdParm[0]);
837 SetRelAbs(hdc, mr->rdParm[0]);
840 case META_SETPOLYFILLMODE:
841 SetPolyFillMode(hdc, mr->rdParm[0]);
844 case META_SETSTRETCHBLTMODE:
845 SetStretchBltMode(hdc, mr->rdParm[0]);
848 case META_SETTEXTCOLOR:
849 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
852 case META_SETWINDOWORG:
853 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
856 case META_SETWINDOWEXT:
857 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
860 case META_SETVIEWPORTORG:
861 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
864 case META_SETVIEWPORTEXT:
865 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
868 case META_OFFSETWINDOWORG:
869 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
872 case META_SCALEWINDOWEXT:
873 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
874 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
877 case META_OFFSETVIEWPORTORG:
878 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
881 case META_SCALEVIEWPORTEXT:
882 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
883 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
887 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
891 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
894 case META_EXCLUDECLIPRECT:
895 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
896 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
899 case META_INTERSECTCLIPRECT:
900 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
901 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
905 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
906 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
907 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
908 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
912 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
913 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
917 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
918 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
922 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
923 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
924 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
925 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
929 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
930 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
934 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
935 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
936 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
940 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
941 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
942 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
950 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
951 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
954 case META_OFFSETCLIPRGN:
955 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
960 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
961 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
962 (char *)(mr->rdParm + 1), s1);
966 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
968 Polygon(hdc, pt, mr->rdParm[0]);
969 HeapFree( GetProcessHeap(), 0, pt );
973 case META_POLYPOLYGON:
976 SHORT *counts = (SHORT *)(mr->rdParm + 1);
978 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
979 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
982 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
985 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
986 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
987 HeapFree( GetProcessHeap(), 0, cnt32 );
990 HeapFree( GetProcessHeap(), 0, pt );
995 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
997 Polyline( hdc, pt, mr->rdParm[0] );
998 HeapFree( GetProcessHeap(), 0, pt );
1002 case META_RESTOREDC:
1003 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
1006 case META_SELECTOBJECT:
1007 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
1011 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1012 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1013 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1014 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1017 case META_CREATEPATTERNBRUSH:
1018 switch (mr->rdParm[0])
1021 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1022 MF_AddHandle(ht, handles,
1023 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
1026 infohdr->biBitCount,
1027 (LPSTR)(mr->rdParm +
1028 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
1032 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1033 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
1037 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1043 case META_CREATEPENINDIRECT:
1046 pen.lopnStyle = mr->rdParm[0];
1047 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
1048 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
1049 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
1050 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
1054 case META_CREATEFONTINDIRECT:
1057 font.lfHeight = (SHORT)mr->rdParm[0];
1058 font.lfWidth = (SHORT)mr->rdParm[1];
1059 font.lfEscapement = (SHORT)mr->rdParm[2];
1060 font.lfOrientation = (SHORT)mr->rdParm[3];
1061 font.lfWeight = (SHORT)mr->rdParm[4];
1062 font.lfItalic = LOBYTE(mr->rdParm[5]);
1063 font.lfUnderline = HIBYTE(mr->rdParm[5]);
1064 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
1065 font.lfCharSet = HIBYTE(mr->rdParm[6]);
1066 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
1067 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
1068 font.lfQuality = LOBYTE(mr->rdParm[8]);
1069 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
1070 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
1071 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
1075 case META_CREATEBRUSHINDIRECT:
1078 brush.lbStyle = mr->rdParm[0];
1079 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
1080 brush.lbHatch = mr->rdParm[3];
1081 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
1085 case META_CREATEPALETTE:
1086 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
1089 case META_SETTEXTALIGN:
1090 SetTextAlign(hdc, mr->rdParm[0]);
1093 case META_SELECTPALETTE:
1094 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
1097 case META_SETMAPPERFLAGS:
1098 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1101 case META_REALIZEPALETTE:
1102 GDIRealizePalette(hdc);
1106 FIXME("META_ESCAPE unimplemented.\n");
1109 case META_EXTTEXTOUT:
1110 MF_Play_MetaExtTextOut( hdc, mr );
1113 case META_STRETCHDIB:
1115 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1116 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1117 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1118 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1119 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
1120 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1124 case META_DIBSTRETCHBLT:
1126 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1127 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1128 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1129 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1130 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
1131 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1135 case META_STRETCHBLT:
1137 HDC hdcSrc = CreateCompatibleDC(hdc);
1138 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
1139 mr->rdParm[11], /*Height*/
1140 mr->rdParm[13], /*Planes*/
1141 mr->rdParm[14], /*BitsPixel*/
1142 (LPSTR)&mr->rdParm[15]); /*bits*/
1143 SelectObject(hdcSrc,hbitmap);
1144 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1145 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1146 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1147 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1148 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1155 HDC hdcSrc = CreateCompatibleDC(hdc);
1156 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
1157 mr->rdParm[8]/*Height*/,
1158 mr->rdParm[10]/*Planes*/,
1159 mr->rdParm[11]/*BitsPixel*/,
1160 (LPSTR)&mr->rdParm[12]/*bits*/);
1161 SelectObject(hdcSrc,hbitmap);
1162 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
1163 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
1164 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
1165 MAKELONG(0,mr->rdParm[0]));
1170 case META_CREATEREGION:
1172 HRGN hrgn = CreateRectRgn(0,0,0,0);
1174 MF_Play_MetaCreateRegion(mr, hrgn);
1175 MF_AddHandle(ht, handles, hrgn);
1179 case META_FILLREGION:
1180 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
1181 *(ht->objectHandle + mr->rdParm[0]));
1184 case META_FRAMEREGION:
1185 FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
1186 *(ht->objectHandle + mr->rdParm[2]),
1187 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1190 case META_INVERTREGION:
1191 InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1194 case META_PAINTREGION:
1195 PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1198 case META_SELECTCLIPREGION:
1199 SelectClipRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1202 case META_DIBCREATEPATTERNBRUSH:
1203 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1204 but there's no difference */
1205 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1208 case META_DIBBITBLT:
1209 /* In practice I've found that there are two layouts for
1210 META_DIBBITBLT, one (the first here) is the usual one when a src
1211 dc is actually passed to it, the second occurs when the src dc is
1212 passed in as NULL to the creating BitBlt. As the second case has
1213 no dib, a size check will suffice to distinguish.
1215 Caolan.McNamara@ul.ie */
1217 if (mr->rdSize > 12) {
1218 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1219 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1221 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1222 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1223 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1224 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1226 else /* equivalent to a PatBlt */
1227 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1228 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1229 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1232 case META_SETTEXTCHAREXTRA:
1233 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1236 case META_SETTEXTJUSTIFICATION:
1237 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1240 case META_EXTFLOODFILL:
1241 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1242 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1246 case META_SETDIBTODEV:
1248 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1249 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1250 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1251 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1252 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1253 mr->rdParm[2], mr->rdParm[1], bits, info,
1258 #define META_UNIMP(x) case x: \
1259 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1261 META_UNIMP(META_DRAWTEXT)
1262 META_UNIMP(META_ANIMATEPALETTE)
1263 META_UNIMP(META_SETPALENTRIES)
1264 META_UNIMP(META_RESIZEPALETTE)
1265 META_UNIMP(META_RESETDC)
1266 META_UNIMP(META_STARTDOC)
1267 META_UNIMP(META_STARTPAGE)
1268 META_UNIMP(META_ENDPAGE)
1269 META_UNIMP(META_ABORTDOC)
1270 META_UNIMP(META_ENDDOC)
1271 META_UNIMP(META_CREATEBRUSH)
1272 META_UNIMP(META_CREATEBITMAPINDIRECT)
1273 META_UNIMP(META_CREATEBITMAP)
1277 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1283 /******************************************************************
1284 * GetMetaFileBits (GDI.159)
1286 * Trade in a metafile object handle for a handle to the metafile memory.
1290 HGLOBAL16 WINAPI GetMetaFileBits16(
1291 HMETAFILE16 hmf /* [in] metafile handle */
1294 TRACE("hMem out: %04x\n", hmf);
1298 /******************************************************************
1299 * SetMetaFileBits (GDI.160)
1301 * Trade in a metafile memory handle for a handle to a metafile object.
1302 * The memory region should hold a proper metafile, otherwise
1303 * problems will occur when it is used. Validity of the memory is not
1304 * checked. The function is essentially just the identity function.
1306 HMETAFILE16 WINAPI SetMetaFileBits16(
1308 /* [in] handle to a memory region holding a metafile */
1311 TRACE("hmf out: %04x\n", hMem);
1316 /******************************************************************
1317 * SetMetaFileBitsBetter (GDI.196)
1319 * Trade in a metafile memory handle for a handle to a metafile object,
1320 * making a cursory check (using IsValidMetaFile()) that the memory
1321 * handle points to a valid metafile.
1324 * Handle to a metafile on success, NULL on failure..
1326 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1328 if( IsValidMetaFile16( hMeta ) )
1329 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1330 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1331 return (HMETAFILE16)0;
1334 /******************************************************************
1335 * SetMetaFileBitsEx (GDI32.@)
1337 * Create a metafile from raw data. No checking of the data is performed.
1338 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1340 HMETAFILE WINAPI SetMetaFileBitsEx(
1341 UINT size, /* [in] size of metafile, in bytes */
1342 const BYTE *lpData /* [in] pointer to metafile data */
1345 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1347 memcpy(mh, lpData, size);
1348 return MF_Create_HMETAFILE(mh);
1351 /*****************************************************************
1352 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1354 * Copies the data from metafile _hmf_ into the buffer _buf_.
1355 * If _buf_ is zero, returns size of buffer required. Otherwise,
1356 * returns number of bytes copied.
1358 UINT WINAPI GetMetaFileBitsEx(
1359 HMETAFILE hmf, /* [in] metafile */
1360 UINT nSize, /* [in] size of buf */
1361 LPVOID buf /* [out] buffer to receive raw metafile data */
1363 METAHEADER *mh = MF_GetMetaHeader(hmf);
1366 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1367 if (!mh) return 0; /* FIXME: error code */
1368 if(mh->mtType == METAFILE_DISK)
1369 FIXME("Disk-based metafile?\n");
1370 mfSize = mh->mtSize * 2;
1372 TRACE("returning size %d\n", mfSize);
1375 if(mfSize > nSize) mfSize = nSize;
1376 memmove(buf, mh, mfSize);
1380 /******************************************************************
1381 * GetWinMetaFileBits [GDI32.@]
1383 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1384 UINT cbBuffer, LPBYTE lpbBuffer,
1385 INT fnMapMode, HDC hdcRef)
1391 FIXME("(%d,%d,%p,%d,%d): stub\n",
1392 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1393 hdcmf = CreateMetaFileA(NULL);
1394 /* PlayEnhMetaFile(hdcmf, hemf, lpRect); where does the bounding rect come from? */
1395 hmf = CloseMetaFile(hdcmf);
1396 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1397 DeleteMetaFile(hmf);
1401 /******************************************************************
1402 * MF_Play_MetaCreateRegion
1404 * Handles META_CREATEREGION for PlayMetaFileRecord().
1408 * The layout of the record looks something like this:
1413 * 2 Looks like a handle? - not constant
1415 * 4 Total number of bytes
1416 * 5 No. of separate bands = n [see below]
1417 * 6 Largest number of x co-ords in a band
1418 * 7-10 Bounding box x1 y1 x2 y2
1421 * Regions are divided into bands that are uniform in the
1422 * y-direction. Each band consists of pairs of on/off x-coords and is
1424 * m y0 y1 x1 x2 x3 ... xm m
1425 * into successive rdParm[]s.
1427 * This is probably just a dump of the internal RGNOBJ?
1433 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1438 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1440 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1441 band++, start = end + 1) {
1442 if(*start / 2 != (*start + 1) / 2) {
1443 WARN("Delimiter not even.\n");
1444 DeleteObject( hrgn2 );
1448 end = start + *start + 3;
1449 if(end > (WORD *)mr + mr->rdSize) {
1450 WARN("End points outside record.\n");
1451 DeleteObject( hrgn2 );
1455 if(*start != *end) {
1456 WARN("Mismatched delimiters.\n");
1457 DeleteObject( hrgn2 );
1461 y0 = *(INT16 *)(start + 1);
1462 y1 = *(INT16 *)(start + 2);
1463 for(pair = 0; pair < *start / 2; pair++) {
1464 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1465 *(INT16 *)(start + 4 + 2*pair), y1 );
1466 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1469 DeleteObject( hrgn2 );
1474 /******************************************************************
1475 * MF_Play_MetaExtTextOut
1477 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1480 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1489 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1491 s1 = mr->rdParm[2]; /* String length */
1492 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1493 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1494 /* rec len without dx array */
1496 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1499 rect.left = (SHORT)mr->rdParm[4];
1500 rect.top = (SHORT)mr->rdParm[5];
1501 rect.right = (SHORT)mr->rdParm[6];
1502 rect.bottom = (SHORT)mr->rdParm[7];
1503 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1506 if (mr->rdSize == len / 2)
1507 dxx = NULL; /* determine if array present */
1509 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1511 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1512 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1513 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1516 TRACE("%s len: %ld\n", sot, mr->rdSize);
1518 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1519 len, s1, mr->rdSize, mr->rdParm[3]);
1520 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1523 (SHORT)mr->rdParm[1], /* X position */
1524 (SHORT)mr->rdParm[0], /* Y position */
1525 mr->rdParm[3], /* options */
1526 &rect, /* rectangle */
1528 s1, dx); /* length, dx array */
1531 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1532 HeapFree( GetProcessHeap(), 0, dx );