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 "wine/winternl.h"
64 #include "gdi_private.h"
65 #include "wine/debug.h"
67 WINE_DEFAULT_DEBUG_CHANNEL(metafile
);
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
)
109 return alloc_gdi_handle( mh
, OBJ_METAFILE
, NULL
);
112 /******************************************************************
115 * Convert an array of POINTS to an array of POINT.
116 * Result must be freed by caller.
118 static POINT
*convert_points( UINT count
, const POINTS
*pts
)
121 POINT
*ret
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*ret
) );
124 for (i
= 0; i
< count
; i
++)
133 /******************************************************************
134 * DeleteMetaFile (GDI32.@)
136 * Delete a memory-based metafile.
139 BOOL WINAPI
DeleteMetaFile( HMETAFILE hmf
)
141 METAHEADER
*mh
= free_gdi_handle( hmf
);
142 if (!mh
) return FALSE
;
143 return HeapFree( GetProcessHeap(), 0, mh
);
146 /******************************************************************
149 * Returns a pointer to a memory based METAHEADER read in from file HFILE
152 static METAHEADER
*MF_ReadMetaFile(HANDLE hfile
)
155 DWORD BytesRead
, size
;
157 size
= sizeof(METAHEADER
);
158 mh
= HeapAlloc( GetProcessHeap(), 0, size
);
160 if(ReadFile( hfile
, mh
, size
, &BytesRead
, NULL
) == 0 ||
162 HeapFree( GetProcessHeap(), 0, mh
);
165 if (mh
->mtType
!= METAFILE_MEMORY
|| mh
->mtVersion
!= MFVERSION
||
166 mh
->mtHeaderSize
!= size
/ 2)
168 HeapFree( GetProcessHeap(), 0, mh
);
171 size
= mh
->mtSize
* 2;
172 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
, size
);
174 size
-= sizeof(METAHEADER
);
175 if(ReadFile( hfile
, (char *)mh
+ sizeof(METAHEADER
), size
, &BytesRead
,
178 HeapFree( GetProcessHeap(), 0, mh
);
182 if (mh
->mtType
!= METAFILE_MEMORY
) {
183 WARN("Disk metafile had mtType = %04x\n", mh
->mtType
);
184 mh
->mtType
= METAFILE_MEMORY
;
189 /******************************************************************
190 * GetMetaFileA (GDI32.@)
192 * Read a metafile from a file. Returns handle to a memory-based metafile.
194 HMETAFILE WINAPI
GetMetaFileA( LPCSTR lpFilename
)
199 TRACE("%s\n", lpFilename
);
204 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
205 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
208 mh
= MF_ReadMetaFile(hFile
);
211 return MF_Create_HMETAFILE( mh
);
214 /******************************************************************
215 * GetMetaFileW (GDI32.@)
217 HMETAFILE WINAPI
GetMetaFileW( LPCWSTR lpFilename
)
222 TRACE("%s\n", debugstr_w(lpFilename
));
227 if((hFile
= CreateFileW(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
228 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
231 mh
= MF_ReadMetaFile(hFile
);
234 return MF_Create_HMETAFILE( mh
);
238 /******************************************************************
239 * MF_LoadDiskBasedMetaFile
241 * Creates a new memory-based metafile from a disk-based one.
243 static METAHEADER
*MF_LoadDiskBasedMetaFile(METAHEADER
*mh
)
249 if(mh
->mtType
!= METAFILE_DISK
) {
250 ERR("Not a disk based metafile\n");
253 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
255 if((hfile
= CreateFileA(mhd
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
256 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
257 WARN("Can't open file of disk based metafile\n");
260 mh2
= MF_ReadMetaFile(hfile
);
265 /******************************************************************
266 * MF_CreateMetaHeaderDisk
268 * Take a memory based METAHEADER and change it to a disk based METAHEADER
269 * associated with filename. Note: Trashes contents of old one.
271 METAHEADER
*MF_CreateMetaHeaderDisk(METAHEADER
*mh
, LPCVOID filename
, BOOL uni
)
275 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
,
276 sizeof(METAHEADER
) + sizeof(METAHEADERDISK
));
277 mh
->mtType
= METAFILE_DISK
;
278 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
281 WideCharToMultiByte(CP_ACP
, 0, filename
, -1,
282 mhd
->filename
, sizeof mhd
->filename
, NULL
, NULL
);
284 lstrcpynA( mhd
->filename
, filename
, sizeof mhd
->filename
);
288 /* return a copy of the metafile bits, to be freed with HeapFree */
289 static METAHEADER
*get_metafile_bits( HMETAFILE hmf
)
291 METAHEADER
*ret
, *mh
= GDI_GetObjPtr( hmf
, OBJ_METAFILE
);
293 if (!mh
) return NULL
;
295 if (mh
->mtType
!= METAFILE_DISK
)
297 ret
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
298 if (ret
) memcpy( ret
, mh
, mh
->mtSize
* 2 );
300 else ret
= MF_LoadDiskBasedMetaFile( mh
);
302 GDI_ReleaseObj( hmf
);
306 /******************************************************************
307 * CopyMetaFileW (GDI32.@)
309 * Copies the metafile corresponding to hSrcMetaFile to either
310 * a disk file, if a filename is given, or to a new memory based
311 * metafile, if lpFileName is NULL.
314 * hSrcMetaFile [I] handle of metafile to copy
315 * lpFilename [I] filename if copying to a file
318 * Handle to metafile copy on success, NULL on failure.
321 * Copying to disk returns NULL even if successful.
323 HMETAFILE WINAPI
CopyMetaFileW( HMETAFILE hSrcMetaFile
, LPCWSTR lpFilename
)
325 METAHEADER
*mh
= get_metafile_bits( hSrcMetaFile
);
328 TRACE("(%p,%s)\n", hSrcMetaFile
, debugstr_w(lpFilename
));
332 if(lpFilename
) { /* disk based metafile */
334 if((hFile
= CreateFileW(lpFilename
, GENERIC_WRITE
, 0, NULL
,
335 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
336 HeapFree( GetProcessHeap(), 0, mh
);
339 WriteFile(hFile
, mh
, mh
->mtSize
* 2, &w
, NULL
);
343 return MF_Create_HMETAFILE( mh
);
347 /******************************************************************
348 * CopyMetaFileA (GDI32.@)
352 HMETAFILE WINAPI
CopyMetaFileA( HMETAFILE hSrcMetaFile
, LPCSTR lpFilename
)
354 UNICODE_STRING lpFilenameW
;
357 if (lpFilename
) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW
, lpFilename
);
358 else lpFilenameW
.Buffer
= NULL
;
360 ret
= CopyMetaFileW( hSrcMetaFile
, lpFilenameW
.Buffer
);
361 if (lpFilenameW
.Buffer
)
362 RtlFreeUnicodeString(&lpFilenameW
);
366 /******************************************************************
367 * PlayMetaFile (GDI32.@)
369 * Renders the metafile specified by hmf in the DC specified by
370 * hdc. Returns FALSE on failure, TRUE on success.
373 * hdc [I] handle of DC to render in
374 * hmf [I] handle of metafile to render
380 BOOL WINAPI
PlayMetaFile( HDC hdc
, HMETAFILE hmf
)
382 METAHEADER
*mh
= get_metafile_bits( hmf
);
385 unsigned int offset
= 0;
392 if (!mh
) return FALSE
;
395 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
396 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
397 hPal
= GetCurrentObject(hdc
, OBJ_PAL
);
399 hRgn
= CreateRectRgn(0, 0, 0, 0);
400 if (!GetClipRgn(hdc
, hRgn
))
406 /* create the handle table */
407 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
408 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
411 HeapFree( GetProcessHeap(), 0, mh
);
415 /* loop through metafile playing records */
416 offset
= mh
->mtHeaderSize
* 2;
417 while (offset
< mh
->mtSize
* 2)
419 mr
= (METARECORD
*)((char *)mh
+ offset
);
420 TRACE("offset=%04x,size=%08x\n",
422 if (mr
->rdSize
< 3) { /* catch illegal record sizes */
423 TRACE("Entry got size %d at offset %d, total mf length is %d\n",
424 mr
->rdSize
,offset
,mh
->mtSize
*2);
428 offset
+= mr
->rdSize
* 2;
429 if (mr
->rdFunction
== META_EOF
) {
430 TRACE("Got META_EOF so stopping\n");
433 PlayMetaFileRecord( hdc
, ht
, mr
, mh
->mtNoObjects
);
437 SelectObject(hdc
, hPen
);
438 SelectObject(hdc
, hBrush
);
439 SelectPalette(hdc
, hPal
, FALSE
);
440 ExtSelectClipRgn(hdc
, hRgn
, RGN_COPY
);
443 /* free objects in handle table */
444 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
445 if(*(ht
->objectHandle
+ i
) != 0)
446 DeleteObject(*(ht
->objectHandle
+ i
));
448 HeapFree( GetProcessHeap(), 0, ht
);
449 HeapFree( GetProcessHeap(), 0, mh
);
453 /******************************************************************
454 * EnumMetaFile (GDI32.@)
456 * Loop through the metafile records in hmf, calling the user-specified
457 * function for each one, stopping when the user's function returns FALSE
458 * (which is considered to be failure)
459 * or when no records are left (which is considered to be success).
462 * TRUE on success, FALSE on failure.
464 BOOL WINAPI
EnumMetaFile(HDC hdc
, HMETAFILE hmf
, MFENUMPROC lpEnumFunc
, LPARAM lpData
)
466 METAHEADER
*mh
= get_metafile_bits( hmf
);
471 unsigned int offset
= 0;
476 TRACE("(%p,%p,%p,%lx)\n", hdc
, hmf
, lpEnumFunc
, lpData
);
478 if (!mh
) return FALSE
;
480 /* save the current pen, brush and font */
481 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
482 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
483 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
485 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
486 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
488 /* loop through metafile records */
489 offset
= mh
->mtHeaderSize
* 2;
491 while (offset
< (mh
->mtSize
* 2))
493 mr
= (METARECORD
*)((char *)mh
+ offset
);
494 if(mr
->rdFunction
== META_EOF
) {
495 TRACE("Got META_EOF so stopping\n");
498 TRACE("Calling EnumFunc with record type %x\n",
500 if (!lpEnumFunc( hdc
, ht
, mr
, mh
->mtNoObjects
, lpData
))
506 offset
+= (mr
->rdSize
* 2);
509 /* restore pen, brush and font */
510 SelectObject(hdc
, hBrush
);
511 SelectObject(hdc
, hPen
);
512 SelectObject(hdc
, hFont
);
514 /* free objects in handle table */
515 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
516 if(*(ht
->objectHandle
+ i
) != 0)
517 DeleteObject(*(ht
->objectHandle
+ i
));
519 HeapFree( GetProcessHeap(), 0, ht
);
520 HeapFree( GetProcessHeap(), 0, mh
);
524 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
);
525 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
);
526 /******************************************************************
527 * PlayMetaFileRecord (GDI32.@)
529 * Render a single metafile record specified by *mr in the DC hdc, while
530 * using the handle table *ht, of length handles,
531 * to store metafile objects.
534 * The following metafile records are unimplemented:
536 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
537 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
538 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
540 BOOL WINAPI
PlayMetaFileRecord( HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
, UINT handles
)
544 BITMAPINFOHEADER
*infohdr
;
546 TRACE("(%p %p %p %u) function %04x\n", hdc
, ht
, mr
, handles
, mr
->rdFunction
);
548 switch (mr
->rdFunction
)
553 case META_DELETEOBJECT
:
554 DeleteObject(*(ht
->objectHandle
+ mr
->rdParm
[0]));
555 *(ht
->objectHandle
+ mr
->rdParm
[0]) = 0;
558 case META_SETBKCOLOR
:
559 SetBkColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
563 SetBkMode(hdc
, mr
->rdParm
[0]);
566 case META_SETMAPMODE
:
567 SetMapMode(hdc
, mr
->rdParm
[0]);
571 SetROP2(hdc
, mr
->rdParm
[0]);
575 SetRelAbs(hdc
, mr
->rdParm
[0]);
578 case META_SETPOLYFILLMODE
:
579 SetPolyFillMode(hdc
, mr
->rdParm
[0]);
582 case META_SETSTRETCHBLTMODE
:
583 SetStretchBltMode(hdc
, mr
->rdParm
[0]);
586 case META_SETTEXTCOLOR
:
587 SetTextColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
590 case META_SETWINDOWORG
:
591 SetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
594 case META_SETWINDOWEXT
:
595 SetWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
598 case META_SETVIEWPORTORG
:
599 SetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
602 case META_SETVIEWPORTEXT
:
603 SetViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
606 case META_OFFSETWINDOWORG
:
607 OffsetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
610 case META_SCALEWINDOWEXT
:
611 ScaleWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
612 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
615 case META_OFFSETVIEWPORTORG
:
616 OffsetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
619 case META_SCALEVIEWPORTEXT
:
620 ScaleViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
621 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
625 LineTo(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
629 MoveToEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
632 case META_EXCLUDECLIPRECT
:
633 ExcludeClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
634 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
637 case META_INTERSECTCLIPRECT
:
638 IntersectClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
639 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
643 Arc(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
644 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
645 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
646 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
650 Ellipse(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
651 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
655 FloodFill(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
656 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
660 Pie(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
661 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
662 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
663 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
667 Rectangle(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
668 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
672 RoundRect(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
673 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
674 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
678 PatBlt(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
679 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
680 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
688 SetPixel(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
689 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
692 case META_OFFSETCLIPRGN
:
693 OffsetClipRgn( hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
698 TextOutA(hdc
, (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 2],
699 (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 1],
700 (char *)(mr
->rdParm
+ 1), s1
);
704 if ((pt
= convert_points( mr
->rdParm
[0], (POINTS
*)(mr
->rdParm
+ 1))))
706 Polygon(hdc
, pt
, mr
->rdParm
[0]);
707 HeapFree( GetProcessHeap(), 0, pt
);
711 case META_POLYPOLYGON
:
714 SHORT
*counts
= (SHORT
*)(mr
->rdParm
+ 1);
716 for (i
= total
= 0; i
< mr
->rdParm
[0]; i
++) total
+= counts
[i
];
717 pt
= convert_points( total
, (POINTS
*)(counts
+ mr
->rdParm
[0]) );
720 INT
*cnt32
= HeapAlloc( GetProcessHeap(), 0, mr
->rdParm
[0] * sizeof(*cnt32
) );
723 for (i
= 0; i
< mr
->rdParm
[0]; i
++) cnt32
[i
] = counts
[i
];
724 PolyPolygon( hdc
, pt
, cnt32
, mr
->rdParm
[0]);
725 HeapFree( GetProcessHeap(), 0, cnt32
);
728 HeapFree( GetProcessHeap(), 0, pt
);
733 if ((pt
= convert_points( mr
->rdParm
[0], (POINTS
*)(mr
->rdParm
+ 1))))
735 Polyline( hdc
, pt
, mr
->rdParm
[0] );
736 HeapFree( GetProcessHeap(), 0, pt
);
741 RestoreDC(hdc
, (SHORT
)mr
->rdParm
[0]);
744 case META_SELECTOBJECT
:
745 SelectObject(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
749 Chord(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
750 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
751 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
752 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
755 case META_CREATEPATTERNBRUSH
:
756 switch (mr
->rdParm
[0])
759 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
760 MF_AddHandle(ht
, handles
,
761 CreatePatternBrush(CreateBitmap(infohdr
->biWidth
,
766 (sizeof(BITMAPINFOHEADER
) / 2) + 4)));
770 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
771 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( infohdr
, mr
->rdParm
[1] ));
775 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
781 case META_CREATEPENINDIRECT
:
784 pen
.lopnStyle
= mr
->rdParm
[0];
785 pen
.lopnWidth
.x
= (SHORT
)mr
->rdParm
[1];
786 pen
.lopnWidth
.y
= (SHORT
)mr
->rdParm
[2];
787 pen
.lopnColor
= MAKELONG( mr
->rdParm
[3], mr
->rdParm
[4] );
788 MF_AddHandle(ht
, handles
, CreatePenIndirect( &pen
));
792 case META_CREATEFONTINDIRECT
:
795 font
.lfHeight
= (SHORT
)mr
->rdParm
[0];
796 font
.lfWidth
= (SHORT
)mr
->rdParm
[1];
797 font
.lfEscapement
= (SHORT
)mr
->rdParm
[2];
798 font
.lfOrientation
= (SHORT
)mr
->rdParm
[3];
799 font
.lfWeight
= (SHORT
)mr
->rdParm
[4];
800 font
.lfItalic
= LOBYTE(mr
->rdParm
[5]);
801 font
.lfUnderline
= HIBYTE(mr
->rdParm
[5]);
802 font
.lfStrikeOut
= LOBYTE(mr
->rdParm
[6]);
803 font
.lfCharSet
= HIBYTE(mr
->rdParm
[6]);
804 font
.lfOutPrecision
= LOBYTE(mr
->rdParm
[7]);
805 font
.lfClipPrecision
= HIBYTE(mr
->rdParm
[7]);
806 font
.lfQuality
= LOBYTE(mr
->rdParm
[8]);
807 font
.lfPitchAndFamily
= HIBYTE(mr
->rdParm
[8]);
808 memcpy( font
.lfFaceName
, mr
->rdParm
+ 9, LF_FACESIZE
);
809 MF_AddHandle(ht
, handles
, CreateFontIndirectA( &font
));
813 case META_CREATEBRUSHINDIRECT
:
816 brush
.lbStyle
= mr
->rdParm
[0];
817 brush
.lbColor
= MAKELONG( mr
->rdParm
[1], mr
->rdParm
[2] );
818 brush
.lbHatch
= mr
->rdParm
[3];
819 MF_AddHandle(ht
, handles
, CreateBrushIndirect( &brush
));
823 case META_CREATEPALETTE
:
824 MF_AddHandle(ht
, handles
, CreatePalette((LPLOGPALETTE
)mr
->rdParm
));
827 case META_SETTEXTALIGN
:
828 SetTextAlign(hdc
, mr
->rdParm
[0]);
831 case META_SELECTPALETTE
:
832 GDISelectPalette(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]), mr
->rdParm
[0]);
835 case META_SETMAPPERFLAGS
:
836 SetMapperFlags(hdc
, MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
839 case META_REALIZEPALETTE
:
840 GDIRealizePalette(hdc
);
844 switch (mr
->rdParm
[0]) {
845 case GETSCALINGFACTOR
: /* get function ... would just NULL dereference */
846 case GETPHYSPAGESIZE
:
847 case GETPRINTINGOFFSET
:
850 FIXME("Filtering Escape(SETABORTPROC), possible virus?\n");
853 Escape(hdc
, mr
->rdParm
[0], mr
->rdParm
[1], (LPCSTR
)&mr
->rdParm
[2], NULL
);
856 case META_EXTTEXTOUT
:
857 MF_Play_MetaExtTextOut( hdc
, mr
);
860 case META_STRETCHDIB
:
862 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[11]);
863 LPSTR bits
= (LPSTR
)info
+ bitmap_info_size( info
, mr
->rdParm
[2] );
864 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[10], (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
865 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
866 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], bits
, info
,
867 mr
->rdParm
[2],MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
871 case META_DIBSTRETCHBLT
:
873 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[10]);
874 LPSTR bits
= (LPSTR
)info
+ bitmap_info_size( info
, DIB_RGB_COLORS
);
875 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
876 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
877 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2], bits
, info
,
878 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
882 case META_STRETCHBLT
:
884 HDC hdcSrc
= CreateCompatibleDC(hdc
);
885 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[10], /*Width */
886 mr
->rdParm
[11], /*Height*/
887 mr
->rdParm
[13], /*Planes*/
888 mr
->rdParm
[14], /*BitsPixel*/
889 &mr
->rdParm
[15]); /*bits*/
890 SelectObject(hdcSrc
,hbitmap
);
891 StretchBlt(hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
892 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
893 hdcSrc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
894 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
895 MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
902 HDC hdcSrc
= CreateCompatibleDC(hdc
);
903 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[7]/*Width */,
904 mr
->rdParm
[8]/*Height*/,
905 mr
->rdParm
[10]/*Planes*/,
906 mr
->rdParm
[11]/*BitsPixel*/,
907 &mr
->rdParm
[12]/*bits*/);
908 SelectObject(hdcSrc
,hbitmap
);
909 BitBlt(hdc
,(SHORT
)mr
->rdParm
[6],(SHORT
)mr
->rdParm
[5],
910 (SHORT
)mr
->rdParm
[4],(SHORT
)mr
->rdParm
[3],
911 hdcSrc
, (SHORT
)mr
->rdParm
[2],(SHORT
)mr
->rdParm
[1],
912 MAKELONG(0,mr
->rdParm
[0]));
917 case META_CREATEREGION
:
919 HRGN hrgn
= CreateRectRgn(0,0,0,0);
921 MF_Play_MetaCreateRegion(mr
, hrgn
);
922 MF_AddHandle(ht
, handles
, hrgn
);
926 case META_FILLREGION
:
927 FillRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]),
928 *(ht
->objectHandle
+ mr
->rdParm
[0]));
931 case META_FRAMEREGION
:
932 FrameRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[3]),
933 *(ht
->objectHandle
+ mr
->rdParm
[2]),
934 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
937 case META_INVERTREGION
:
938 InvertRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
941 case META_PAINTREGION
:
942 PaintRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
945 case META_SELECTCLIPREGION
:
949 if (mr
->rdParm
[0]) hrgn
= *(ht
->objectHandle
+ mr
->rdParm
[0]);
950 SelectClipRgn(hdc
, hrgn
);
954 case META_DIBCREATEPATTERNBRUSH
:
955 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
956 but there's no difference */
957 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( mr
->rdParm
+ 2, mr
->rdParm
[1] ));
961 /* In practice I've found that there are two layouts for
962 META_DIBBITBLT, one (the first here) is the usual one when a src
963 dc is actually passed to it, the second occurs when the src dc is
964 passed in as NULL to the creating BitBlt. As the second case has
965 no dib, a size check will suffice to distinguish.
967 Caolan.McNamara@ul.ie */
969 if (mr
->rdSize
> 12) {
970 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[8]);
971 LPSTR bits
= (LPSTR
)info
+ bitmap_info_size(info
, mr
->rdParm
[0]);
973 StretchDIBits(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
974 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
975 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4], bits
, info
,
976 DIB_RGB_COLORS
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
978 else /* equivalent to a PatBlt */
979 PatBlt(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
980 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
981 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
984 case META_SETTEXTCHAREXTRA
:
985 SetTextCharacterExtra(hdc
, (SHORT
)mr
->rdParm
[0]);
988 case META_SETTEXTJUSTIFICATION
:
989 SetTextJustification(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
992 case META_EXTFLOODFILL
:
993 ExtFloodFill(hdc
, (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
994 MAKELONG(mr
->rdParm
[1], mr
->rdParm
[2]),
998 case META_SETDIBTODEV
:
1000 BITMAPINFO
*info
= (BITMAPINFO
*) &(mr
->rdParm
[9]);
1001 char *bits
= (char *)info
+ bitmap_info_size( info
, mr
->rdParm
[0] );
1002 SetDIBitsToDevice(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1003 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1004 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1005 mr
->rdParm
[2], mr
->rdParm
[1], bits
, info
,
1010 #define META_UNIMP(x) case x: \
1011 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1013 META_UNIMP(META_DRAWTEXT
)
1014 META_UNIMP(META_ANIMATEPALETTE
)
1015 META_UNIMP(META_SETPALENTRIES
)
1016 META_UNIMP(META_RESIZEPALETTE
)
1017 META_UNIMP(META_RESETDC
)
1018 META_UNIMP(META_STARTDOC
)
1019 META_UNIMP(META_STARTPAGE
)
1020 META_UNIMP(META_ENDPAGE
)
1021 META_UNIMP(META_ABORTDOC
)
1022 META_UNIMP(META_ENDDOC
)
1023 META_UNIMP(META_CREATEBRUSH
)
1024 META_UNIMP(META_CREATEBITMAPINDIRECT
)
1025 META_UNIMP(META_CREATEBITMAP
)
1029 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr
->rdFunction
);
1035 /******************************************************************
1036 * SetMetaFileBitsEx (GDI32.@)
1038 * Create a metafile from raw data. No checking of the data is performed.
1039 * Use GetMetaFileBitsEx() to get raw data from a metafile.
1042 * size [I] size of metafile, in bytes
1043 * lpData [I] pointer to metafile data
1046 * Success: Handle to metafile.
1049 HMETAFILE WINAPI
SetMetaFileBitsEx( UINT size
, const BYTE
*lpData
)
1051 const METAHEADER
*mh_in
= (const METAHEADER
*)lpData
;
1054 if (size
& 1) return 0;
1056 if (!size
|| mh_in
->mtType
!= METAFILE_MEMORY
|| mh_in
->mtVersion
!= MFVERSION
||
1057 mh_in
->mtHeaderSize
!= sizeof(METAHEADER
) / 2)
1059 SetLastError(ERROR_INVALID_DATA
);
1063 mh_out
= HeapAlloc( GetProcessHeap(), 0, size
);
1066 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1070 memcpy(mh_out
, mh_in
, size
);
1071 mh_out
->mtSize
= size
/ 2;
1072 return MF_Create_HMETAFILE(mh_out
);
1075 /*****************************************************************
1076 * GetMetaFileBitsEx (GDI32.@)
1078 * Get raw metafile data.
1080 * Copies the data from metafile _hmf_ into the buffer _buf_.
1084 * nSize [I] size of buf
1085 * buf [O] buffer to receive raw metafile data
1088 * If _buf_ is zero, returns size of buffer required. Otherwise,
1089 * returns number of bytes copied.
1091 UINT WINAPI
GetMetaFileBitsEx( HMETAFILE hmf
, UINT nSize
, LPVOID buf
)
1093 METAHEADER
*mh
= GDI_GetObjPtr( hmf
, OBJ_METAFILE
);
1095 BOOL mf_copy
= FALSE
;
1097 TRACE("(%p,%d,%p)\n", hmf
, nSize
, buf
);
1098 if (!mh
) return 0; /* FIXME: error code */
1099 if(mh
->mtType
== METAFILE_DISK
)
1101 mh
= MF_LoadDiskBasedMetaFile( mh
);
1104 GDI_ReleaseObj( hmf
);
1109 mfSize
= mh
->mtSize
* 2;
1112 if(mfSize
> nSize
) mfSize
= nSize
;
1113 memmove(buf
, mh
, mfSize
);
1115 if (mf_copy
) HeapFree( GetProcessHeap(), 0, mh
);
1116 GDI_ReleaseObj( hmf
);
1117 TRACE("returning size %d\n", mfSize
);
1121 /******************************************************************
1124 * Helper for GetWinMetaFileBits
1126 * Add the MFCOMMENT record[s] which is essentially a copy
1127 * of the original emf.
1129 static BOOL
add_mf_comment(HDC hdc
, HENHMETAFILE emf
)
1131 DWORD size
= GetEnhMetaFileBits(emf
, 0, NULL
), i
;
1132 BYTE
*bits
, *chunk_data
;
1133 emf_in_wmf_comment
*chunk
= NULL
;
1135 static const DWORD max_chunk_size
= 0x2000;
1137 if(!size
) return FALSE
;
1138 chunk_data
= bits
= HeapAlloc(GetProcessHeap(), 0, size
);
1139 if(!bits
) return FALSE
;
1140 if(!GetEnhMetaFileBits(emf
, size
, bits
)) goto end
;
1142 chunk
= HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(emf_in_wmf_comment
, emf_data
[max_chunk_size
]));
1143 if(!chunk
) goto end
;
1145 chunk
->magic
= WMFC_MAGIC
;
1150 chunk
->checksum
= 0; /* We fixup the first chunk's checksum before returning from GetWinMetaFileBits */
1152 chunk
->num_chunks
= (size
+ max_chunk_size
- 1) / max_chunk_size
;
1153 chunk
->chunk_size
= max_chunk_size
;
1154 chunk
->remaining_size
= size
;
1155 chunk
->emf_size
= size
;
1157 for(i
= 0; i
< chunk
->num_chunks
; i
++)
1159 if(i
== chunk
->num_chunks
- 1) /* last chunk */
1160 chunk
->chunk_size
= chunk
->remaining_size
;
1162 chunk
->remaining_size
-= chunk
->chunk_size
;
1163 memcpy(chunk
->emf_data
, chunk_data
, chunk
->chunk_size
);
1164 chunk_data
+= chunk
->chunk_size
;
1166 if(!Escape(hdc
, MFCOMMENT
, FIELD_OFFSET(emf_in_wmf_comment
, emf_data
[chunk
->chunk_size
]), (char*)chunk
, NULL
))
1171 HeapFree(GetProcessHeap(), 0, chunk
);
1172 HeapFree(GetProcessHeap(), 0, bits
);
1176 /*******************************************************************
1179 * Behaves somewhat differently to MulDiv when the answer is -ve
1180 * and also rounds n.5 towards zero
1182 static INT
muldiv(INT m1
, INT m2
, INT d
)
1186 ret
= ((LONGLONG
)m1
* m2
+ d
/2) / d
; /* Always add d/2 even if ret will be -ve */
1188 if((LONGLONG
)m1
* m2
* 2 == (2 * ret
- 1) * d
) /* If the answer is exactly n.5 round towards zero */
1196 /******************************************************************
1199 * Helper for GetWinMetaFileBits
1201 * Add the SetWindowOrg and SetWindowExt records
1203 static BOOL
set_window(HDC hdc
, HENHMETAFILE emf
, HDC ref_dc
, INT map_mode
)
1205 ENHMETAHEADER header
;
1206 INT horz_res
, vert_res
, horz_size
, vert_size
;
1209 if(!GetEnhMetaFileHeader(emf
, sizeof(header
), &header
)) return FALSE
;
1211 horz_res
= GetDeviceCaps(ref_dc
, HORZRES
);
1212 vert_res
= GetDeviceCaps(ref_dc
, VERTRES
);
1213 horz_size
= GetDeviceCaps(ref_dc
, HORZSIZE
);
1214 vert_size
= GetDeviceCaps(ref_dc
, VERTSIZE
);
1220 case MM_ANISOTROPIC
:
1221 pt
.y
= muldiv(header
.rclFrame
.top
, vert_res
, vert_size
* 100);
1222 pt
.x
= muldiv(header
.rclFrame
.left
, horz_res
, horz_size
* 100);
1225 pt
.y
= muldiv(-header
.rclFrame
.top
, 1, 10) + 1;
1226 pt
.x
= muldiv( header
.rclFrame
.left
, 1, 10);
1229 pt
.y
= -header
.rclFrame
.top
+ 1;
1230 pt
.x
= (header
.rclFrame
.left
>= 0) ? header
.rclFrame
.left
: header
.rclFrame
.left
+ 1; /* See the tests */
1233 pt
.y
= muldiv(-header
.rclFrame
.top
, 10, 254) + 1;
1234 pt
.x
= muldiv( header
.rclFrame
.left
, 10, 254);
1237 pt
.y
= muldiv(-header
.rclFrame
.top
, 100, 254) + 1;
1238 pt
.x
= muldiv( header
.rclFrame
.left
, 100, 254);
1241 pt
.y
= muldiv(-header
.rclFrame
.top
, 72 * 20, 2540) + 1;
1242 pt
.x
= muldiv( header
.rclFrame
.left
, 72 * 20, 2540);
1245 WARN("Unknown map mode %d\n", map_mode
);
1248 SetWindowOrgEx(hdc
, pt
.x
, pt
.y
, NULL
);
1250 pt
.x
= muldiv(header
.rclFrame
.right
- header
.rclFrame
.left
, horz_res
, horz_size
* 100);
1251 pt
.y
= muldiv(header
.rclFrame
.bottom
- header
.rclFrame
.top
, vert_res
, vert_size
* 100);
1252 SetWindowExtEx(hdc
, pt
.x
, pt
.y
, NULL
);
1256 /******************************************************************
1257 * GetWinMetaFileBits [GDI32.@]
1259 UINT WINAPI
GetWinMetaFileBits(HENHMETAFILE hemf
,
1260 UINT cbBuffer
, LPBYTE lpbBuffer
,
1261 INT map_mode
, HDC hdcRef
)
1265 UINT ret
, full_size
;
1268 GetClipBox(hdcRef
, &rc
);
1270 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf
, cbBuffer
, lpbBuffer
,
1271 map_mode
, hdcRef
, wine_dbgstr_rect(&rc
));
1273 hdcmf
= CreateMetaFileW(NULL
);
1275 add_mf_comment(hdcmf
, hemf
);
1276 SetMapMode(hdcmf
, map_mode
);
1277 if(!set_window(hdcmf
, hemf
, hdcRef
, map_mode
))
1280 PlayEnhMetaFile(hdcmf
, hemf
, &rc
);
1281 hmf
= CloseMetaFile(hdcmf
);
1282 full_size
= GetMetaFileBitsEx(hmf
, 0, NULL
);
1283 ret
= GetMetaFileBitsEx(hmf
, cbBuffer
, lpbBuffer
);
1284 DeleteMetaFile(hmf
);
1286 if(ret
&& ret
== full_size
&& lpbBuffer
) /* fixup checksum, but only if retrieving all of the bits */
1289 METARECORD
*comment_rec
= (METARECORD
*)(lpbBuffer
+ sizeof(METAHEADER
));
1292 for(i
= 0; i
< full_size
/ 2; i
++)
1293 checksum
+= ((WORD
*)lpbBuffer
)[i
];
1294 comment_rec
->rdParm
[8] = ~checksum
+ 1;
1299 DeleteMetaFile(CloseMetaFile(hdcmf
));
1303 /******************************************************************
1304 * MF_Play_MetaCreateRegion
1306 * Handles META_CREATEREGION for PlayMetaFileRecord().
1308 * The layout of the record looks something like this:
1313 * 2 Looks like a handle? - not constant
1315 * 4 Total number of bytes
1316 * 5 No. of separate bands = n [see below]
1317 * 6 Largest number of x co-ords in a band
1318 * 7-10 Bounding box x1 y1 x2 y2
1321 * Regions are divided into bands that are uniform in the
1322 * y-direction. Each band consists of pairs of on/off x-coords and is
1324 * m y0 y1 x1 x2 x3 ... xm m
1325 * into successive rdParm[]s.
1327 * This is probably just a dump of the internal RGNOBJ?
1333 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
)
1338 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1340 for(band
= 0, start
= &(mr
->rdParm
[11]); band
< mr
->rdParm
[5];
1341 band
++, start
= end
+ 1) {
1342 if(*start
/ 2 != (*start
+ 1) / 2) {
1343 WARN("Delimiter not even.\n");
1344 DeleteObject( hrgn2
);
1348 end
= start
+ *start
+ 3;
1349 if(end
> (WORD
*)mr
+ mr
->rdSize
) {
1350 WARN("End points outside record.\n");
1351 DeleteObject( hrgn2
);
1355 if(*start
!= *end
) {
1356 WARN("Mismatched delimiters.\n");
1357 DeleteObject( hrgn2
);
1361 y0
= *(INT16
*)(start
+ 1);
1362 y1
= *(INT16
*)(start
+ 2);
1363 for(pair
= 0; pair
< *start
/ 2; pair
++) {
1364 SetRectRgn( hrgn2
, *(INT16
*)(start
+ 3 + 2*pair
), y0
,
1365 *(INT16
*)(start
+ 4 + 2*pair
), y1
);
1366 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
1369 DeleteObject( hrgn2
);
1374 /******************************************************************
1375 * MF_Play_MetaExtTextOut
1377 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1380 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
)
1389 BOOL isrect
= mr
->rdParm
[3] & (ETO_OPAQUE
| ETO_CLIPPED
);
1391 s1
= mr
->rdParm
[2]; /* String length */
1392 len
= sizeof(METARECORD
) + (((s1
+ 1) >> 1) * 2) + 2 * sizeof(short)
1393 + sizeof(UINT16
) + (isrect
? 4 * sizeof(SHORT
) : 0);
1394 /* rec len without dx array */
1396 sot
= (LPSTR
)&mr
->rdParm
[4]; /* start_of_text */
1399 rect
.left
= (SHORT
)mr
->rdParm
[4];
1400 rect
.top
= (SHORT
)mr
->rdParm
[5];
1401 rect
.right
= (SHORT
)mr
->rdParm
[6];
1402 rect
.bottom
= (SHORT
)mr
->rdParm
[7];
1403 sot
+= 4 * sizeof(SHORT
); /* there is a rectangle, so add offset */
1406 if (mr
->rdSize
== len
/ 2)
1407 dxx
= NULL
; /* determine if array is present */
1409 if (mr
->rdSize
== (len
+ s1
* sizeof(INT16
)) / 2)
1411 dxx
= (SHORT
*)(sot
+(((s1
+1)>>1)*2));
1412 dx
= HeapAlloc( GetProcessHeap(), 0, s1
*sizeof(INT
));
1413 if (dx
) for (i
= 0; i
< s1
; i
++) dx
[i
] = dxx
[i
];
1416 TRACE("%s len: %d\n", sot
, mr
->rdSize
);
1417 WARN("Please report: ExtTextOut len=%d slen=%d rdSize=%d opt=%04x\n",
1418 len
, s1
, mr
->rdSize
, mr
->rdParm
[3]);
1419 dxx
= NULL
; /* shouldn't happen -- but if, we continue with NULL */
1422 (SHORT
)mr
->rdParm
[1], /* X position */
1423 (SHORT
)mr
->rdParm
[0], /* Y position */
1424 mr
->rdParm
[3], /* options */
1425 &rect
, /* rectangle */
1427 s1
, dx
); /* length, dx array */
1430 TRACE("%s len: %d dx0: %d\n", sot
, mr
->rdSize
, dx
[0]);
1431 HeapFree( GetProcessHeap(), 0, dx
);