4 * Copyright David W. Metcalfe, 1994
5 * Copyright Niels de Carpentier, 1996
6 * Copyright Albrecht Kleine, 1996
7 * Copyright Huw Davies, 1996
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 * These functions are primarily involved with metafile playback or anything
26 * that touches a HMETAFILE.
27 * For recording of metafiles look in graphics/metafiledrv/
29 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
30 * global memory handles so these cannot be interchanged.
32 * Memory-based metafiles are just stored as a continuous block of memory with
33 * a METAHEADER at the head with METARECORDs appended to it. mtType is
34 * METAFILE_MEMORY (1). Note this is identical to the disk image of a
35 * disk-based metafile - even mtType is METAFILE_MEMORY.
36 * 16bit HMETAFILE16s are global handles to this block
37 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
39 * Disk-based metafiles are rather different. HMETAFILE16s point to a
40 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
41 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
42 * more 0, then 2 which may be a time stamp of the file and then the path of
43 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
60 #include "gdi_private.h"
61 #include "wine/debug.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(metafile
);
75 /******************************************************************
78 * Add a handle to an external handle table and return the index
80 static int MF_AddHandle(HANDLETABLE
*ht
, UINT htlen
, HGDIOBJ hobj
)
84 for (i
= 0; i
< htlen
; i
++)
86 if (*(ht
->objectHandle
+ i
) == 0)
88 *(ht
->objectHandle
+ i
) = hobj
;
96 /******************************************************************
97 * MF_Create_HMETATFILE
99 * Creates a (32 bit) HMETAFILE object from a METAHEADER
101 * HMETAFILEs are GDI objects.
103 HMETAFILE
MF_Create_HMETAFILE(METAHEADER
*mh
)
105 return alloc_gdi_handle( mh
, OBJ_METAFILE
, NULL
);
108 /******************************************************************
111 * Convert an array of POINTS to an array of POINT.
112 * Result must be freed by caller.
114 static POINT
*convert_points( UINT count
, const POINTS
*pts
)
117 POINT
*ret
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*ret
) );
120 for (i
= 0; i
< count
; i
++)
129 /******************************************************************
130 * DeleteMetaFile (GDI32.@)
132 * Delete a memory-based metafile.
135 BOOL WINAPI
DeleteMetaFile( HMETAFILE hmf
)
137 METAHEADER
*mh
= free_gdi_handle( hmf
);
139 if (!mh
) return FALSE
;
140 HeapFree( GetProcessHeap(), 0, mh
);
144 /******************************************************************
147 * Returns a pointer to a memory based METAHEADER read in from file HFILE
150 static METAHEADER
*MF_ReadMetaFile(HANDLE hfile
)
153 DWORD BytesRead
, size
;
155 size
= sizeof(METAHEADER
);
156 mh
= HeapAlloc( GetProcessHeap(), 0, size
);
158 if(ReadFile( hfile
, mh
, size
, &BytesRead
, NULL
) == 0 ||
160 HeapFree( GetProcessHeap(), 0, mh
);
163 if (mh
->mtType
!= METAFILE_MEMORY
|| mh
->mtVersion
!= MFVERSION
||
164 mh
->mtHeaderSize
!= size
/ 2)
166 HeapFree( GetProcessHeap(), 0, mh
);
169 size
= mh
->mtSize
* 2;
170 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
, size
);
172 size
-= sizeof(METAHEADER
);
173 if(ReadFile( hfile
, (char *)mh
+ sizeof(METAHEADER
), size
, &BytesRead
,
176 HeapFree( GetProcessHeap(), 0, mh
);
180 if (mh
->mtType
!= METAFILE_MEMORY
) {
181 WARN("Disk metafile had mtType = %04x\n", mh
->mtType
);
182 mh
->mtType
= METAFILE_MEMORY
;
187 /******************************************************************
188 * GetMetaFileA (GDI32.@)
190 * Read a metafile from a file. Returns handle to a memory-based metafile.
192 HMETAFILE WINAPI
GetMetaFileA( LPCSTR lpFilename
)
197 TRACE("%s\n", lpFilename
);
202 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
203 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
206 mh
= MF_ReadMetaFile(hFile
);
209 return MF_Create_HMETAFILE( mh
);
212 /******************************************************************
213 * GetMetaFileW (GDI32.@)
215 HMETAFILE WINAPI
GetMetaFileW( LPCWSTR lpFilename
)
220 TRACE("%s\n", debugstr_w(lpFilename
));
225 if((hFile
= CreateFileW(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
226 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
229 mh
= MF_ReadMetaFile(hFile
);
232 return MF_Create_HMETAFILE( mh
);
236 /******************************************************************
237 * MF_LoadDiskBasedMetaFile
239 * Creates a new memory-based metafile from a disk-based one.
241 static METAHEADER
*MF_LoadDiskBasedMetaFile(METAHEADER
*mh
)
247 if(mh
->mtType
!= METAFILE_DISK
) {
248 ERR("Not a disk based metafile\n");
251 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
253 if((hfile
= CreateFileA(mhd
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
254 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
255 WARN("Can't open file of disk based metafile\n");
258 mh2
= MF_ReadMetaFile(hfile
);
263 /******************************************************************
264 * MF_CreateMetaHeaderDisk
266 * Take a memory based METAHEADER and change it to a disk based METAHEADER
267 * associated with filename. Note: Trashes contents of old one.
269 METAHEADER
*MF_CreateMetaHeaderDisk(METAHEADER
*mh
, LPCVOID filename
, BOOL uni
)
273 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
,
274 sizeof(METAHEADER
) + sizeof(METAHEADERDISK
));
275 mh
->mtType
= METAFILE_DISK
;
276 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
279 WideCharToMultiByte(CP_ACP
, 0, filename
, -1,
280 mhd
->filename
, sizeof mhd
->filename
, NULL
, NULL
);
282 lstrcpynA( mhd
->filename
, filename
, sizeof mhd
->filename
);
286 /* return a copy of the metafile bits, to be freed with HeapFree */
287 static METAHEADER
*get_metafile_bits( HMETAFILE hmf
)
289 METAHEADER
*ret
, *mh
= GDI_GetObjPtr( hmf
, OBJ_METAFILE
);
291 if (!mh
) return NULL
;
293 if (mh
->mtType
!= METAFILE_DISK
)
295 ret
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
296 if (ret
) memcpy( ret
, mh
, mh
->mtSize
* 2 );
298 else ret
= MF_LoadDiskBasedMetaFile( mh
);
300 GDI_ReleaseObj( hmf
);
304 /******************************************************************
305 * CopyMetaFileW (GDI32.@)
307 * Copies the metafile corresponding to hSrcMetaFile to either
308 * a disk file, if a filename is given, or to a new memory based
309 * metafile, if lpFileName is NULL.
312 * hSrcMetaFile [I] handle of metafile to copy
313 * lpFilename [I] filename if copying to a file
316 * Handle to metafile copy on success, NULL on failure.
319 * Copying to disk returns NULL even if successful.
321 HMETAFILE WINAPI
CopyMetaFileW( HMETAFILE hSrcMetaFile
, LPCWSTR lpFilename
)
323 METAHEADER
*mh
= get_metafile_bits( hSrcMetaFile
);
326 TRACE("(%p,%s)\n", hSrcMetaFile
, debugstr_w(lpFilename
));
330 if(lpFilename
) { /* disk based metafile */
332 if((hFile
= CreateFileW(lpFilename
, GENERIC_WRITE
, 0, NULL
,
333 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
334 HeapFree( GetProcessHeap(), 0, mh
);
337 WriteFile(hFile
, mh
, mh
->mtSize
* 2, &w
, NULL
);
341 return MF_Create_HMETAFILE( mh
);
345 /******************************************************************
346 * CopyMetaFileA (GDI32.@)
350 HMETAFILE WINAPI
CopyMetaFileA( HMETAFILE hSrcMetaFile
, LPCSTR lpFilename
)
352 UNICODE_STRING lpFilenameW
;
355 if (lpFilename
) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW
, lpFilename
);
356 else lpFilenameW
.Buffer
= NULL
;
358 ret
= CopyMetaFileW( hSrcMetaFile
, lpFilenameW
.Buffer
);
359 if (lpFilenameW
.Buffer
)
360 RtlFreeUnicodeString(&lpFilenameW
);
364 /******************************************************************
365 * PlayMetaFile (GDI32.@)
367 * Renders the metafile specified by hmf in the DC specified by
368 * hdc. Returns FALSE on failure, TRUE on success.
371 * hdc [I] handle of DC to render in
372 * hmf [I] handle of metafile to render
378 BOOL WINAPI
PlayMetaFile( HDC hdc
, HMETAFILE hmf
)
380 METAHEADER
*mh
= get_metafile_bits( hmf
);
383 unsigned int offset
= 0;
390 if (!mh
) return FALSE
;
393 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
394 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
395 hPal
= GetCurrentObject(hdc
, OBJ_PAL
);
397 hRgn
= CreateRectRgn(0, 0, 0, 0);
398 if (!GetClipRgn(hdc
, hRgn
))
404 /* create the handle table */
405 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
406 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
409 HeapFree( GetProcessHeap(), 0, mh
);
413 /* loop through metafile playing records */
414 offset
= mh
->mtHeaderSize
* 2;
415 while (offset
< mh
->mtSize
* 2)
417 mr
= (METARECORD
*)((char *)mh
+ offset
);
418 TRACE("offset=%04x,size=%08x\n",
420 if (mr
->rdSize
< 3) { /* catch illegal record sizes */
421 TRACE("Entry got size %d at offset %d, total mf length is %d\n",
422 mr
->rdSize
,offset
,mh
->mtSize
*2);
426 offset
+= mr
->rdSize
* 2;
427 if (mr
->rdFunction
== META_EOF
) {
428 TRACE("Got META_EOF so stopping\n");
431 PlayMetaFileRecord( hdc
, ht
, mr
, mh
->mtNoObjects
);
435 SelectObject(hdc
, hPen
);
436 SelectObject(hdc
, hBrush
);
437 SelectPalette(hdc
, hPal
, FALSE
);
438 ExtSelectClipRgn(hdc
, hRgn
, RGN_COPY
);
441 /* free objects in handle table */
442 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
443 if(*(ht
->objectHandle
+ i
) != 0)
444 DeleteObject(*(ht
->objectHandle
+ i
));
446 HeapFree( GetProcessHeap(), 0, ht
);
447 HeapFree( GetProcessHeap(), 0, mh
);
451 /******************************************************************
452 * EnumMetaFile (GDI32.@)
454 * Loop through the metafile records in hmf, calling the user-specified
455 * function for each one, stopping when the user's function returns FALSE
456 * (which is considered to be failure)
457 * or when no records are left (which is considered to be success).
460 * TRUE on success, FALSE on failure.
462 BOOL WINAPI
EnumMetaFile(HDC hdc
, HMETAFILE hmf
, MFENUMPROC lpEnumFunc
, LPARAM lpData
)
464 METAHEADER
*mh
= get_metafile_bits( hmf
);
469 unsigned int offset
= 0;
474 TRACE("(%p,%p,%p,%lx)\n", hdc
, hmf
, lpEnumFunc
, lpData
);
476 if (!mh
) return FALSE
;
478 /* save the current pen, brush and font */
479 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
480 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
481 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
483 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
484 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
486 /* loop through metafile records */
487 offset
= mh
->mtHeaderSize
* 2;
489 while (offset
< (mh
->mtSize
* 2))
491 mr
= (METARECORD
*)((char *)mh
+ offset
);
492 if(mr
->rdFunction
== META_EOF
) {
493 TRACE("Got META_EOF so stopping\n");
496 TRACE("Calling EnumFunc with record type %x\n",
498 if (!lpEnumFunc( hdc
, ht
, mr
, mh
->mtNoObjects
, lpData
))
504 offset
+= (mr
->rdSize
* 2);
507 /* restore pen, brush and font */
508 SelectObject(hdc
, hBrush
);
509 SelectObject(hdc
, hPen
);
510 SelectObject(hdc
, hFont
);
512 /* free objects in handle table */
513 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
514 if(*(ht
->objectHandle
+ i
) != 0)
515 DeleteObject(*(ht
->objectHandle
+ i
));
517 HeapFree( GetProcessHeap(), 0, ht
);
518 HeapFree( GetProcessHeap(), 0, mh
);
522 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
);
523 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
);
524 /******************************************************************
525 * PlayMetaFileRecord (GDI32.@)
527 * Render a single metafile record specified by *mr in the DC hdc, while
528 * using the handle table *ht, of length handles,
529 * to store metafile objects.
532 * The following metafile records are unimplemented:
534 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
535 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
536 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
538 BOOL WINAPI
PlayMetaFileRecord( HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
, UINT handles
)
542 BITMAPINFOHEADER
*infohdr
;
544 TRACE("(%p %p %p %u) function %04x\n", hdc
, ht
, mr
, handles
, mr
->rdFunction
);
546 switch (mr
->rdFunction
)
551 case META_DELETEOBJECT
:
552 DeleteObject(*(ht
->objectHandle
+ mr
->rdParm
[0]));
553 *(ht
->objectHandle
+ mr
->rdParm
[0]) = 0;
556 case META_SETBKCOLOR
:
557 SetBkColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
561 SetBkMode(hdc
, mr
->rdParm
[0]);
564 case META_SETMAPMODE
:
565 SetMapMode(hdc
, mr
->rdParm
[0]);
569 SetROP2(hdc
, mr
->rdParm
[0]);
573 SetRelAbs(hdc
, mr
->rdParm
[0]);
576 case META_SETPOLYFILLMODE
:
577 SetPolyFillMode(hdc
, mr
->rdParm
[0]);
580 case META_SETSTRETCHBLTMODE
:
581 SetStretchBltMode(hdc
, mr
->rdParm
[0]);
584 case META_SETTEXTCOLOR
:
585 SetTextColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
588 case META_SETWINDOWORG
:
589 SetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
592 case META_SETWINDOWEXT
:
593 SetWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
596 case META_SETVIEWPORTORG
:
597 SetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
600 case META_SETVIEWPORTEXT
:
601 SetViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
604 case META_OFFSETWINDOWORG
:
605 OffsetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
608 case META_SCALEWINDOWEXT
:
609 ScaleWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
610 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
613 case META_OFFSETVIEWPORTORG
:
614 OffsetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
617 case META_SCALEVIEWPORTEXT
:
618 ScaleViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
619 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
623 LineTo(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
627 MoveToEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
630 case META_EXCLUDECLIPRECT
:
631 ExcludeClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
632 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
635 case META_INTERSECTCLIPRECT
:
636 IntersectClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
637 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
641 Arc(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
642 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
643 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
644 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
648 Ellipse(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
649 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
653 FloodFill(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
654 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
658 Pie(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
659 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
660 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
661 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
665 Rectangle(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
666 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
670 RoundRect(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
671 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
672 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
676 PatBlt(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
677 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
678 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
686 SetPixel(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
687 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
690 case META_OFFSETCLIPRGN
:
691 OffsetClipRgn( hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
696 TextOutA(hdc
, (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 2],
697 (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 1],
698 (char *)(mr
->rdParm
+ 1), s1
);
702 if ((pt
= convert_points( mr
->rdParm
[0], (POINTS
*)(mr
->rdParm
+ 1))))
704 Polygon(hdc
, pt
, mr
->rdParm
[0]);
705 HeapFree( GetProcessHeap(), 0, pt
);
709 case META_POLYPOLYGON
:
712 SHORT
*counts
= (SHORT
*)(mr
->rdParm
+ 1);
714 for (i
= total
= 0; i
< mr
->rdParm
[0]; i
++) total
+= counts
[i
];
715 pt
= convert_points( total
, (POINTS
*)(counts
+ mr
->rdParm
[0]) );
718 INT
*cnt32
= HeapAlloc( GetProcessHeap(), 0, mr
->rdParm
[0] * sizeof(*cnt32
) );
721 for (i
= 0; i
< mr
->rdParm
[0]; i
++) cnt32
[i
] = counts
[i
];
722 PolyPolygon( hdc
, pt
, cnt32
, mr
->rdParm
[0]);
723 HeapFree( GetProcessHeap(), 0, cnt32
);
726 HeapFree( GetProcessHeap(), 0, pt
);
731 if ((pt
= convert_points( mr
->rdParm
[0], (POINTS
*)(mr
->rdParm
+ 1))))
733 Polyline( hdc
, pt
, mr
->rdParm
[0] );
734 HeapFree( GetProcessHeap(), 0, pt
);
739 RestoreDC(hdc
, (SHORT
)mr
->rdParm
[0]);
742 case META_SELECTOBJECT
:
743 SelectObject(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
747 Chord(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
748 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
749 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
750 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
753 case META_CREATEPATTERNBRUSH
:
754 switch (mr
->rdParm
[0])
757 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
758 MF_AddHandle(ht
, handles
,
759 CreatePatternBrush(CreateBitmap(infohdr
->biWidth
,
764 (sizeof(BITMAPINFOHEADER
) / 2) + 4)));
768 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
769 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( infohdr
, mr
->rdParm
[1] ));
773 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
779 case META_CREATEPENINDIRECT
:
782 pen
.lopnStyle
= mr
->rdParm
[0];
783 pen
.lopnWidth
.x
= (SHORT
)mr
->rdParm
[1];
784 pen
.lopnWidth
.y
= (SHORT
)mr
->rdParm
[2];
785 pen
.lopnColor
= MAKELONG( mr
->rdParm
[3], mr
->rdParm
[4] );
786 MF_AddHandle(ht
, handles
, CreatePenIndirect( &pen
));
790 case META_CREATEFONTINDIRECT
:
793 font
.lfHeight
= (SHORT
)mr
->rdParm
[0];
794 font
.lfWidth
= (SHORT
)mr
->rdParm
[1];
795 font
.lfEscapement
= (SHORT
)mr
->rdParm
[2];
796 font
.lfOrientation
= (SHORT
)mr
->rdParm
[3];
797 font
.lfWeight
= (SHORT
)mr
->rdParm
[4];
798 font
.lfItalic
= LOBYTE(mr
->rdParm
[5]);
799 font
.lfUnderline
= HIBYTE(mr
->rdParm
[5]);
800 font
.lfStrikeOut
= LOBYTE(mr
->rdParm
[6]);
801 font
.lfCharSet
= HIBYTE(mr
->rdParm
[6]);
802 font
.lfOutPrecision
= LOBYTE(mr
->rdParm
[7]);
803 font
.lfClipPrecision
= HIBYTE(mr
->rdParm
[7]);
804 font
.lfQuality
= LOBYTE(mr
->rdParm
[8]);
805 font
.lfPitchAndFamily
= HIBYTE(mr
->rdParm
[8]);
806 memcpy( font
.lfFaceName
, mr
->rdParm
+ 9, LF_FACESIZE
);
807 MF_AddHandle(ht
, handles
, CreateFontIndirectA( &font
));
811 case META_CREATEBRUSHINDIRECT
:
814 brush
.lbStyle
= mr
->rdParm
[0];
815 brush
.lbColor
= MAKELONG( mr
->rdParm
[1], mr
->rdParm
[2] );
816 brush
.lbHatch
= mr
->rdParm
[3];
817 MF_AddHandle(ht
, handles
, CreateBrushIndirect( &brush
));
821 case META_CREATEPALETTE
:
822 MF_AddHandle(ht
, handles
, CreatePalette((LPLOGPALETTE
)mr
->rdParm
));
825 case META_SETTEXTALIGN
:
826 SetTextAlign(hdc
, mr
->rdParm
[0]);
829 case META_SELECTPALETTE
:
830 GDISelectPalette(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]), mr
->rdParm
[0]);
833 case META_SETMAPPERFLAGS
:
834 SetMapperFlags(hdc
, MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
837 case META_REALIZEPALETTE
:
838 GDIRealizePalette(hdc
);
842 switch (mr
->rdParm
[0]) {
843 case GETSCALINGFACTOR
: /* get function ... would just NULL dereference */
844 case GETPHYSPAGESIZE
:
845 case GETPRINTINGOFFSET
:
848 FIXME("Filtering Escape(SETABORTPROC), possible virus?\n");
851 Escape(hdc
, mr
->rdParm
[0], mr
->rdParm
[1], (LPCSTR
)&mr
->rdParm
[2], NULL
);
854 case META_EXTTEXTOUT
:
855 MF_Play_MetaExtTextOut( hdc
, mr
);
858 case META_STRETCHDIB
:
860 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[11]);
861 LPSTR bits
= (LPSTR
)info
+ bitmap_info_size( info
, mr
->rdParm
[2] );
862 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[10], (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
863 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
864 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], bits
, info
,
865 mr
->rdParm
[2],MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
869 case META_DIBSTRETCHBLT
:
871 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[10]);
872 LPSTR bits
= (LPSTR
)info
+ bitmap_info_size( info
, DIB_RGB_COLORS
);
873 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
874 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
875 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2], bits
, info
,
876 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
880 case META_STRETCHBLT
:
882 HDC hdcSrc
= CreateCompatibleDC(hdc
);
883 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[10], /*Width */
884 mr
->rdParm
[11], /*Height*/
885 mr
->rdParm
[13], /*Planes*/
886 mr
->rdParm
[14], /*BitsPixel*/
887 &mr
->rdParm
[15]); /*bits*/
888 SelectObject(hdcSrc
,hbitmap
);
889 StretchBlt(hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
890 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
891 hdcSrc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
892 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
893 MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
900 HDC hdcSrc
= CreateCompatibleDC(hdc
);
901 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[7]/*Width */,
902 mr
->rdParm
[8]/*Height*/,
903 mr
->rdParm
[10]/*Planes*/,
904 mr
->rdParm
[11]/*BitsPixel*/,
905 &mr
->rdParm
[12]/*bits*/);
906 SelectObject(hdcSrc
,hbitmap
);
907 BitBlt(hdc
,(SHORT
)mr
->rdParm
[6],(SHORT
)mr
->rdParm
[5],
908 (SHORT
)mr
->rdParm
[4],(SHORT
)mr
->rdParm
[3],
909 hdcSrc
, (SHORT
)mr
->rdParm
[2],(SHORT
)mr
->rdParm
[1],
910 MAKELONG(0,mr
->rdParm
[0]));
915 case META_CREATEREGION
:
917 HRGN hrgn
= CreateRectRgn(0,0,0,0);
919 MF_Play_MetaCreateRegion(mr
, hrgn
);
920 MF_AddHandle(ht
, handles
, hrgn
);
924 case META_FILLREGION
:
925 FillRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]),
926 *(ht
->objectHandle
+ mr
->rdParm
[0]));
929 case META_FRAMEREGION
:
930 FrameRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[3]),
931 *(ht
->objectHandle
+ mr
->rdParm
[2]),
932 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
935 case META_INVERTREGION
:
936 InvertRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
939 case META_PAINTREGION
:
940 PaintRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
943 case META_SELECTCLIPREGION
:
947 if (mr
->rdParm
[0]) hrgn
= *(ht
->objectHandle
+ mr
->rdParm
[0]);
948 SelectClipRgn(hdc
, hrgn
);
952 case META_DIBCREATEPATTERNBRUSH
:
953 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
954 but there's no difference */
955 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( mr
->rdParm
+ 2, mr
->rdParm
[1] ));
959 /* In practice I've found that there are two layouts for
960 META_DIBBITBLT, one (the first here) is the usual one when a src
961 dc is actually passed to it, the second occurs when the src dc is
962 passed in as NULL to the creating BitBlt. As the second case has
963 no dib, a size check will suffice to distinguish.
965 Caolan.McNamara@ul.ie */
967 if (mr
->rdSize
> 12) {
968 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[8]);
969 LPSTR bits
= (LPSTR
)info
+ bitmap_info_size(info
, mr
->rdParm
[0]);
971 StretchDIBits(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
972 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
973 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4], bits
, info
,
974 DIB_RGB_COLORS
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
976 else /* equivalent to a PatBlt */
977 PatBlt(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
978 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
979 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
982 case META_SETTEXTCHAREXTRA
:
983 SetTextCharacterExtra(hdc
, (SHORT
)mr
->rdParm
[0]);
986 case META_SETTEXTJUSTIFICATION
:
987 SetTextJustification(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
990 case META_EXTFLOODFILL
:
991 ExtFloodFill(hdc
, (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
992 MAKELONG(mr
->rdParm
[1], mr
->rdParm
[2]),
996 case META_SETDIBTODEV
:
998 BITMAPINFO
*info
= (BITMAPINFO
*) &(mr
->rdParm
[9]);
999 char *bits
= (char *)info
+ bitmap_info_size( info
, mr
->rdParm
[0] );
1000 SetDIBitsToDevice(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1001 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1002 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1003 mr
->rdParm
[2], mr
->rdParm
[1], bits
, info
,
1008 #define META_UNIMP(x) case x: \
1009 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1011 META_UNIMP(META_DRAWTEXT
)
1012 META_UNIMP(META_ANIMATEPALETTE
)
1013 META_UNIMP(META_SETPALENTRIES
)
1014 META_UNIMP(META_RESIZEPALETTE
)
1015 META_UNIMP(META_RESETDC
)
1016 META_UNIMP(META_STARTDOC
)
1017 META_UNIMP(META_STARTPAGE
)
1018 META_UNIMP(META_ENDPAGE
)
1019 META_UNIMP(META_ABORTDOC
)
1020 META_UNIMP(META_ENDDOC
)
1021 META_UNIMP(META_CREATEBRUSH
)
1022 META_UNIMP(META_CREATEBITMAPINDIRECT
)
1023 META_UNIMP(META_CREATEBITMAP
)
1027 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr
->rdFunction
);
1033 /******************************************************************
1034 * SetMetaFileBitsEx (GDI32.@)
1036 * Create a metafile from raw data. No checking of the data is performed.
1037 * Use GetMetaFileBitsEx() to get raw data from a metafile.
1040 * size [I] size of metafile, in bytes
1041 * lpData [I] pointer to metafile data
1044 * Success: Handle to metafile.
1047 HMETAFILE WINAPI
SetMetaFileBitsEx( UINT size
, const BYTE
*lpData
)
1049 const METAHEADER
*mh_in
= (const METAHEADER
*)lpData
;
1052 if (size
& 1) return 0;
1054 if (!size
|| mh_in
->mtType
!= METAFILE_MEMORY
|| mh_in
->mtVersion
!= MFVERSION
||
1055 mh_in
->mtHeaderSize
!= sizeof(METAHEADER
) / 2)
1057 SetLastError(ERROR_INVALID_DATA
);
1061 mh_out
= HeapAlloc( GetProcessHeap(), 0, size
);
1064 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1068 memcpy(mh_out
, mh_in
, size
);
1069 mh_out
->mtSize
= size
/ 2;
1070 return MF_Create_HMETAFILE(mh_out
);
1073 /*****************************************************************
1074 * GetMetaFileBitsEx (GDI32.@)
1076 * Get raw metafile data.
1078 * Copies the data from metafile _hmf_ into the buffer _buf_.
1082 * nSize [I] size of buf
1083 * buf [O] buffer to receive raw metafile data
1086 * If _buf_ is zero, returns size of buffer required. Otherwise,
1087 * returns number of bytes copied.
1089 UINT WINAPI
GetMetaFileBitsEx( HMETAFILE hmf
, UINT nSize
, LPVOID buf
)
1091 METAHEADER
*mh
= GDI_GetObjPtr( hmf
, OBJ_METAFILE
);
1093 BOOL mf_copy
= FALSE
;
1095 TRACE("(%p,%d,%p)\n", hmf
, nSize
, buf
);
1096 if (!mh
) return 0; /* FIXME: error code */
1097 if(mh
->mtType
== METAFILE_DISK
)
1099 mh
= MF_LoadDiskBasedMetaFile( mh
);
1102 GDI_ReleaseObj( hmf
);
1107 mfSize
= mh
->mtSize
* 2;
1110 if(mfSize
> nSize
) mfSize
= nSize
;
1111 memmove(buf
, mh
, mfSize
);
1113 if (mf_copy
) HeapFree( GetProcessHeap(), 0, mh
);
1114 GDI_ReleaseObj( hmf
);
1115 TRACE("returning size %d\n", mfSize
);
1119 /******************************************************************
1122 * Helper for GetWinMetaFileBits
1124 * Add the MFCOMMENT record[s] which is essentially a copy
1125 * of the original emf.
1127 static BOOL
add_mf_comment(HDC hdc
, HENHMETAFILE emf
)
1129 DWORD size
= GetEnhMetaFileBits(emf
, 0, NULL
), i
;
1130 BYTE
*bits
, *chunk_data
;
1131 emf_in_wmf_comment
*chunk
= NULL
;
1133 static const DWORD max_chunk_size
= 0x2000;
1135 if(!size
) return FALSE
;
1136 chunk_data
= bits
= HeapAlloc(GetProcessHeap(), 0, size
);
1137 if(!bits
) return FALSE
;
1138 if(!GetEnhMetaFileBits(emf
, size
, bits
)) goto end
;
1140 chunk
= HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(emf_in_wmf_comment
, emf_data
[max_chunk_size
]));
1141 if(!chunk
) goto end
;
1143 chunk
->magic
= WMFC_MAGIC
;
1148 chunk
->checksum
= 0; /* We fixup the first chunk's checksum before returning from GetWinMetaFileBits */
1150 chunk
->num_chunks
= (size
+ max_chunk_size
- 1) / max_chunk_size
;
1151 chunk
->chunk_size
= max_chunk_size
;
1152 chunk
->remaining_size
= size
;
1153 chunk
->emf_size
= size
;
1155 for(i
= 0; i
< chunk
->num_chunks
; i
++)
1157 if(i
== chunk
->num_chunks
- 1) /* last chunk */
1158 chunk
->chunk_size
= chunk
->remaining_size
;
1160 chunk
->remaining_size
-= chunk
->chunk_size
;
1161 memcpy(chunk
->emf_data
, chunk_data
, chunk
->chunk_size
);
1162 chunk_data
+= chunk
->chunk_size
;
1164 if(!Escape(hdc
, MFCOMMENT
, FIELD_OFFSET(emf_in_wmf_comment
, emf_data
[chunk
->chunk_size
]), (char*)chunk
, NULL
))
1169 HeapFree(GetProcessHeap(), 0, chunk
);
1170 HeapFree(GetProcessHeap(), 0, bits
);
1174 /*******************************************************************
1177 * Behaves somewhat differently to MulDiv when the answer is -ve
1178 * and also rounds n.5 towards zero
1180 static INT
muldiv(INT m1
, INT m2
, INT d
)
1184 ret
= ((LONGLONG
)m1
* m2
+ d
/2) / d
; /* Always add d/2 even if ret will be -ve */
1186 if((LONGLONG
)m1
* m2
* 2 == (2 * ret
- 1) * d
) /* If the answer is exactly n.5 round towards zero */
1194 /******************************************************************
1197 * Helper for GetWinMetaFileBits
1199 * Add the SetWindowOrg and SetWindowExt records
1201 static BOOL
set_window(HDC hdc
, HENHMETAFILE emf
, HDC ref_dc
, INT map_mode
)
1203 ENHMETAHEADER header
;
1204 INT horz_res
, vert_res
, horz_size
, vert_size
;
1207 if(!GetEnhMetaFileHeader(emf
, sizeof(header
), &header
)) return FALSE
;
1209 horz_res
= GetDeviceCaps(ref_dc
, HORZRES
);
1210 vert_res
= GetDeviceCaps(ref_dc
, VERTRES
);
1211 horz_size
= GetDeviceCaps(ref_dc
, HORZSIZE
);
1212 vert_size
= GetDeviceCaps(ref_dc
, VERTSIZE
);
1218 case MM_ANISOTROPIC
:
1219 pt
.y
= muldiv(header
.rclFrame
.top
, vert_res
, vert_size
* 100);
1220 pt
.x
= muldiv(header
.rclFrame
.left
, horz_res
, horz_size
* 100);
1223 pt
.y
= muldiv(-header
.rclFrame
.top
, 1, 10) + 1;
1224 pt
.x
= muldiv( header
.rclFrame
.left
, 1, 10);
1227 pt
.y
= -header
.rclFrame
.top
+ 1;
1228 pt
.x
= (header
.rclFrame
.left
>= 0) ? header
.rclFrame
.left
: header
.rclFrame
.left
+ 1; /* See the tests */
1231 pt
.y
= muldiv(-header
.rclFrame
.top
, 10, 254) + 1;
1232 pt
.x
= muldiv( header
.rclFrame
.left
, 10, 254);
1235 pt
.y
= muldiv(-header
.rclFrame
.top
, 100, 254) + 1;
1236 pt
.x
= muldiv( header
.rclFrame
.left
, 100, 254);
1239 pt
.y
= muldiv(-header
.rclFrame
.top
, 72 * 20, 2540) + 1;
1240 pt
.x
= muldiv( header
.rclFrame
.left
, 72 * 20, 2540);
1243 WARN("Unknown map mode %d\n", map_mode
);
1246 SetWindowOrgEx(hdc
, pt
.x
, pt
.y
, NULL
);
1248 pt
.x
= muldiv(header
.rclFrame
.right
- header
.rclFrame
.left
, horz_res
, horz_size
* 100);
1249 pt
.y
= muldiv(header
.rclFrame
.bottom
- header
.rclFrame
.top
, vert_res
, vert_size
* 100);
1250 SetWindowExtEx(hdc
, pt
.x
, pt
.y
, NULL
);
1254 /******************************************************************
1255 * GetWinMetaFileBits [GDI32.@]
1257 UINT WINAPI
GetWinMetaFileBits(HENHMETAFILE hemf
,
1258 UINT cbBuffer
, LPBYTE lpbBuffer
,
1259 INT map_mode
, HDC hdcRef
)
1263 UINT ret
, full_size
;
1266 GetClipBox(hdcRef
, &rc
);
1268 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf
, cbBuffer
, lpbBuffer
,
1269 map_mode
, hdcRef
, wine_dbgstr_rect(&rc
));
1271 hdcmf
= CreateMetaFileW(NULL
);
1273 add_mf_comment(hdcmf
, hemf
);
1274 SetMapMode(hdcmf
, map_mode
);
1275 if(!set_window(hdcmf
, hemf
, hdcRef
, map_mode
))
1278 PlayEnhMetaFile(hdcmf
, hemf
, &rc
);
1279 hmf
= CloseMetaFile(hdcmf
);
1280 full_size
= GetMetaFileBitsEx(hmf
, 0, NULL
);
1281 ret
= GetMetaFileBitsEx(hmf
, cbBuffer
, lpbBuffer
);
1282 DeleteMetaFile(hmf
);
1284 if(ret
&& ret
== full_size
&& lpbBuffer
) /* fixup checksum, but only if retrieving all of the bits */
1287 METARECORD
*comment_rec
= (METARECORD
*)(lpbBuffer
+ sizeof(METAHEADER
));
1290 for(i
= 0; i
< full_size
/ 2; i
++)
1291 checksum
+= ((WORD
*)lpbBuffer
)[i
];
1292 comment_rec
->rdParm
[8] = ~checksum
+ 1;
1297 DeleteMetaFile(CloseMetaFile(hdcmf
));
1301 /******************************************************************
1302 * MF_Play_MetaCreateRegion
1304 * Handles META_CREATEREGION for PlayMetaFileRecord().
1306 * The layout of the record looks something like this:
1311 * 2 Looks like a handle? - not constant
1313 * 4 Total number of bytes
1314 * 5 No. of separate bands = n [see below]
1315 * 6 Largest number of x co-ords in a band
1316 * 7-10 Bounding box x1 y1 x2 y2
1319 * Regions are divided into bands that are uniform in the
1320 * y-direction. Each band consists of pairs of on/off x-coords and is
1322 * m y0 y1 x1 x2 x3 ... xm m
1323 * into successive rdParm[]s.
1325 * This is probably just a dump of the internal RGNOBJ?
1331 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
)
1336 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1338 for(band
= 0, start
= &(mr
->rdParm
[11]); band
< mr
->rdParm
[5];
1339 band
++, start
= end
+ 1) {
1340 if(*start
/ 2 != (*start
+ 1) / 2) {
1341 WARN("Delimiter not even.\n");
1342 DeleteObject( hrgn2
);
1346 end
= start
+ *start
+ 3;
1347 if(end
> (WORD
*)mr
+ mr
->rdSize
) {
1348 WARN("End points outside record.\n");
1349 DeleteObject( hrgn2
);
1353 if(*start
!= *end
) {
1354 WARN("Mismatched delimiters.\n");
1355 DeleteObject( hrgn2
);
1359 y0
= *(INT16
*)(start
+ 1);
1360 y1
= *(INT16
*)(start
+ 2);
1361 for(pair
= 0; pair
< *start
/ 2; pair
++) {
1362 SetRectRgn( hrgn2
, *(INT16
*)(start
+ 3 + 2*pair
), y0
,
1363 *(INT16
*)(start
+ 4 + 2*pair
), y1
);
1364 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
1367 DeleteObject( hrgn2
);
1372 /******************************************************************
1373 * MF_Play_MetaExtTextOut
1375 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1378 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
)
1387 BOOL isrect
= mr
->rdParm
[3] & (ETO_OPAQUE
| ETO_CLIPPED
);
1389 s1
= mr
->rdParm
[2]; /* String length */
1390 len
= sizeof(METARECORD
) + (((s1
+ 1) >> 1) * 2) + 2 * sizeof(short)
1391 + sizeof(UINT16
) + (isrect
? 4 * sizeof(SHORT
) : 0);
1392 /* rec len without dx array */
1394 sot
= (LPSTR
)&mr
->rdParm
[4]; /* start_of_text */
1397 rect
.left
= (SHORT
)mr
->rdParm
[4];
1398 rect
.top
= (SHORT
)mr
->rdParm
[5];
1399 rect
.right
= (SHORT
)mr
->rdParm
[6];
1400 rect
.bottom
= (SHORT
)mr
->rdParm
[7];
1401 sot
+= 4 * sizeof(SHORT
); /* there is a rectangle, so add offset */
1404 if (mr
->rdSize
== len
/ 2)
1405 dxx
= NULL
; /* determine if array is present */
1407 if (mr
->rdSize
== (len
+ s1
* sizeof(INT16
)) / 2)
1409 dxx
= (SHORT
*)(sot
+(((s1
+1)>>1)*2));
1410 dx
= HeapAlloc( GetProcessHeap(), 0, s1
*sizeof(INT
));
1411 if (dx
) for (i
= 0; i
< s1
; i
++) dx
[i
] = dxx
[i
];
1414 TRACE("%s len: %d\n", sot
, mr
->rdSize
);
1415 WARN("Please report: ExtTextOut len=%d slen=%d rdSize=%d opt=%04x\n",
1416 len
, s1
, mr
->rdSize
, mr
->rdParm
[3]);
1417 dxx
= NULL
; /* shouldn't happen -- but if, we continue with NULL */
1420 (SHORT
)mr
->rdParm
[1], /* X position */
1421 (SHORT
)mr
->rdParm
[0], /* Y position */
1422 mr
->rdParm
[3], /* options */
1423 &rect
, /* rectangle */
1425 s1
, dx
); /* length, dx array */
1428 TRACE("%s len: %d dx0: %d\n", sot
, mr
->rdSize
, dx
[0]);
1429 HeapFree( GetProcessHeap(), 0, dx
);