1 /*
2 * Metafile functions
3 *
4 * Copyright David W. Metcalfe, 1994
5 * Copyright Niels de Carpentier, 1996
6 * Copyright Albrecht Kleine, 1996
7 * Copyright Huw Davies, 1996
8 *
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.
13 *
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.
18 *
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
22 *
23 * NOTES
24 *
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/
28 *
29 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
30 * global memory handles so these cannot be interchanged.
31 *
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
38 * the memory.
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.
44 *
45 * HDMD - 14/4/1999
46 */
47
48 #include "config.h"
49
50 #include <stdarg.h>
51 #include <string.h>
52 #include <fcntl.h>
53
54 #include "windef.h"
55 #include "winbase.h"
56 #include "wingdi.h"
57 #include "winreg.h"
58 #include "winternl.h"
59 #include "gdi_private.h"
60 #include "wine/debug.h"
61
62 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
63
64 #include "pshpack1.h"
65 typedef struct
66 {
67 DWORD dw1, dw2, dw3;
68 WORD w4;
69 CHAR filename[0x100];
70 } METAHEADERDISK;
71 #include "poppack.h"
72
73 typedef struct
74 {
75 GDIOBJHDR header;
76 METAHEADER *mh;
77 } METAFILEOBJ;
78
79
80 /******************************************************************
81 * MF_AddHandle
82 *
83 * Add a handle to an external handle table and return the index
84 */
85 static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
86 {
87 int i;
88
89 for (i = 0; i < htlen; i++)
90 {
91 if (*(ht->objectHandle + i) == 0)
92 {
93 *(ht->objectHandle + i) = hobj;
94 return i;
95 }
96 }
97 return -1;
98 }
99
100
101 /******************************************************************
102 * MF_Create_HMETATFILE
103 *
104 * Creates a (32 bit) HMETAFILE object from a METAHEADER
105 *
106 * HMETAFILEs are GDI objects.
107 */
108 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
109 {
110 HMETAFILE hmf = 0;
111 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
112 (HGDIOBJ *)&hmf, NULL );
113 if (metaObj)
114 {
115 metaObj->mh = mh;
116 GDI_ReleaseObj( hmf );
117 }
118 return hmf;
119 }
120
121 /******************************************************************
122 * MF_GetMetaHeader
123 *
124 * Returns ptr to METAHEADER associated with HMETAFILE
125 */
126 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
127 {
128 METAHEADER *ret = NULL;
129 METAFILEOBJ * metaObj = GDI_GetObjPtr( hmf, METAFILE_MAGIC );
130 if (metaObj)
131 {
132 ret = metaObj->mh;
133 GDI_ReleaseObj( hmf );
134 }
135 return ret;
136 }
137
138 /******************************************************************
139 * convert_points
140 *
141 * Convert an array of POINT16 to an array of POINT.
142 * Result must be freed by caller.
143 */
144 static POINT *convert_points( UINT count, POINT16 *pt16 )
145 {
146 UINT i;
147 POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
148 if (ret)
149 {
150 for (i = 0; i < count; i++)
151 {
152 ret[i].x = pt16[i].x;
153 ret[i].y = pt16[i].y;
154 }
155 }
156 return ret;
157 }
158
159 /******************************************************************
160 * DeleteMetaFile (GDI32.@)
161 *
162 * Delete a memory-based metafile.
163 */
164
165 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
166 {
167 METAFILEOBJ * metaObj = GDI_GetObjPtr( hmf, METAFILE_MAGIC );
168 if (!metaObj) return FALSE;
169 HeapFree( GetProcessHeap(), 0, metaObj->mh );
170 GDI_FreeObject( hmf, metaObj );
171 return TRUE;
172 }
173
174 /******************************************************************
175 * MF_ReadMetaFile
176 *
177 * Returns a pointer to a memory based METAHEADER read in from file HFILE
178 *
179 */
180 METAHEADER *MF_ReadMetaFile(HANDLE hfile)
181 {
182 METAHEADER *mh;
183 DWORD BytesRead, size;
184
185 size = sizeof(METAHEADER);
186 mh = HeapAlloc( GetProcessHeap(), 0, size );
187 if(!mh) return NULL;
188 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
189 BytesRead != size) {
190 HeapFree( GetProcessHeap(), 0, mh );
191 return NULL;
192 }
193 if (mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION ||
194 mh->mtHeaderSize != size / 2)
195 {
196 HeapFree( GetProcessHeap(), 0, mh );
197 return NULL;
198 }
199 size = mh->mtSize * 2;
200 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
201 if(!mh) return NULL;
202 size -= sizeof(METAHEADER);
203 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
204 NULL) == 0 ||
205 BytesRead != size) {
206 HeapFree( GetProcessHeap(), 0, mh );
207 return NULL;
208 }
209
210 if (mh->mtType != METAFILE_MEMORY) {
211 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
212 mh->mtType = METAFILE_MEMORY;
213 }
214 return mh;
215 }
216
217 /******************************************************************
218 * GetMetaFileA (GDI32.@)
219 *
220 * Read a metafile from a file. Returns handle to a memory-based metafile.
221 */
222 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
223 {
224 METAHEADER *mh;
225 HANDLE hFile;
226
227 TRACE("%s\n", lpFilename);
228
229 if(!lpFilename)
230 return 0;
231
232 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
233 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
234 return 0;
235
236 mh = MF_ReadMetaFile(hFile);
237 CloseHandle(hFile);
238 if(!mh) return 0;
239 return MF_Create_HMETAFILE( mh );
240 }
241
242 /******************************************************************
243 * GetMetaFileW (GDI32.@)
244 */
245 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
246 {
247 METAHEADER *mh;
248 HANDLE hFile;
249
250 TRACE("%s\n", debugstr_w(lpFilename));
251
252 if(!lpFilename)
253 return 0;
254
255 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
256 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
257 return 0;
258
259 mh = MF_ReadMetaFile(hFile);
260 CloseHandle(hFile);
261 if(!mh) return 0;
262 return MF_Create_HMETAFILE( mh );
263 }
264
265
266 /******************************************************************
267 * MF_LoadDiskBasedMetaFile
268 *
269 * Creates a new memory-based metafile from a disk-based one.
270 */
271 METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
272 {
273 METAHEADERDISK *mhd;
274 HANDLE hfile;
275 METAHEADER *mh2;
276
277 if(mh->mtType != METAFILE_DISK) {
278 ERR("Not a disk based metafile\n");
279 return NULL;
280 }
281 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
282
283 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
284 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
285 WARN("Can't open file of disk based metafile\n");
286 return NULL;
287 }
288 mh2 = MF_ReadMetaFile(hfile);
289 CloseHandle(hfile);
290 return mh2;
291 }
292
293 /******************************************************************
294 * MF_CreateMetaHeaderDisk
295 *
296 * Take a memory based METAHEADER and change it to a disk based METAHEADER
297 * associated with filename. Note: Trashes contents of old one.
298 */
299 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni )
300 {
301 METAHEADERDISK *mhd;
302
303 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
304 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
305 mh->mtType = METAFILE_DISK;
306 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
307
308 if( uni )
309 WideCharToMultiByte(CP_ACP, 0, filename, -1,
310 mhd->filename, sizeof mhd->filename, NULL, NULL);
311 else
312 lstrcpynA( mhd->filename, filename, sizeof mhd->filename );
313 return mh;
314 }
315
316 /******************************************************************
317 * CopyMetaFileW (GDI32.@)
318 *
319 * Copies the metafile corresponding to hSrcMetaFile to either
320 * a disk file, if a filename is given, or to a new memory based
321 * metafile, if lpFileName is NULL.
322 *
323 * PARAMS
324 * hSrcMetaFile [I] handle of metafile to copy
325 * lpFilename [I] filename if copying to a file
326 *
327 * RETURNS
328 * Handle to metafile copy on success, NULL on failure.
329 *
330 * BUGS
331 * Copying to disk returns NULL even if successful.
332 */
333 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile, LPCWSTR lpFilename )
334 {
335 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
336 METAHEADER *mh2 = NULL;
337 HANDLE hFile;
338
339 TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename));
340
341 if(!mh) return 0;
342
343 if(mh->mtType == METAFILE_DISK)
344 mh2 = MF_LoadDiskBasedMetaFile(mh);
345 else {
346 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
347 memcpy( mh2, mh, mh->mtSize * 2 );
348 }
349
350 if(lpFilename) { /* disk based metafile */
351 DWORD w;
352 if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL,
353 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
354 HeapFree( GetProcessHeap(), 0, mh2 );
355 return 0;
356 }
357 WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
358 CloseHandle(hFile);
359 }
360
361 return MF_Create_HMETAFILE( mh2 );
362 }
363
364
365 /******************************************************************
366 * CopyMetaFileA (GDI32.@)
367 *
368 * See CopyMetaFileW.
369 */
370 HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile, LPCSTR lpFilename )
371 {
372 UNICODE_STRING lpFilenameW;
373 HMETAFILE ret = 0;
374
375 if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
376 else lpFilenameW.Buffer = NULL;
377
378 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
379 if (lpFilenameW.Buffer)
380 RtlFreeUnicodeString(&lpFilenameW);
381 return ret;
382 }
383
384 /*******************************************************************
385 * MF_PlayMetaFile
386 *
387 * Helper for PlayMetaFile
388 */
389 BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
390 {
391
392 METARECORD *mr;
393 HANDLETABLE *ht;
394 unsigned int offset = 0;
395 WORD i;
396 HPEN hPen;
397 HBRUSH hBrush;
398 HFONT hFont;
399 HPALETTE hPal;
400 HRGN hRgn;
401 BOOL loaded = FALSE;
402
403 if (!mh) return FALSE;
404 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
405 mh = MF_LoadDiskBasedMetaFile(mh);
406 if(!mh) return FALSE;
407 loaded = TRUE;
408 }
409
410 /* save DC */
411 hPen = GetCurrentObject(hdc, OBJ_PEN);
412 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
413 hFont = GetCurrentObject(hdc, OBJ_FONT);
414 hPal = GetCurrentObject(hdc, OBJ_PAL);
415
416 hRgn = CreateRectRgn(0, 0, 0, 0);
417 if (!GetClipRgn(hdc, hRgn))
418 {
419 DeleteObject(hRgn);
420 hRgn = 0;
421 }
422
423 /* create the handle table */
424 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
425 sizeof(HANDLETABLE) * mh->mtNoObjects);
426 if(!ht) return FALSE;
427
428 /* loop through metafile playing records */
429 offset = mh->mtHeaderSize * 2;
430 while (offset < mh->mtSize * 2)
431 {
432 mr = (METARECORD *)((char *)mh + offset);
433 TRACE("offset=%04x,size=%08x\n",
434 offset, mr->rdSize);
435 if (mr->rdSize < 3) { /* catch illegal record sizes */
436 TRACE("Entry got size %d at offset %d, total mf length is %d\n",
437 mr->rdSize,offset,mh->mtSize*2);
438 break;
439 }
440
441 offset += mr->rdSize * 2;
442 if (mr->rdFunction == META_EOF) {
443 TRACE("Got META_EOF so stopping\n");
444 break;
445 }
446 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
447 }
448
449 /* restore DC */
450 SelectObject(hdc, hPen);
451 SelectObject(hdc, hBrush);
452 SelectPalette(hdc, hPal, FALSE);
453 ExtSelectClipRgn(hdc, hRgn, RGN_COPY);
454 DeleteObject(hRgn);
455
456 /* free objects in handle table */
457 for(i = 0; i < mh->mtNoObjects; i++)
458 if(*(ht->objectHandle + i) != 0)
459 DeleteObject(*(ht->objectHandle + i));
460
461 /* free handle table */
462 HeapFree( GetProcessHeap(), 0, ht );
463 if(loaded)
464 HeapFree( GetProcessHeap(), 0, mh );
465 return TRUE;
466 }
467
468 /******************************************************************
469 * PlayMetaFile (GDI32.@)
470 *
471 * Renders the metafile specified by hmf in the DC specified by
472 * hdc. Returns FALSE on failure, TRUE on success.
473 *
474 * PARAMS
475 * hdc [I] handle of DC to render in
476 * hmf [I] handle of metafile to render
477 *
478 * RETURNS
479 * Success: TRUE
480 * Failure: FALSE
481 */
482 BOOL WINAPI PlayMetaFile( HDC hdc, HMETAFILE hmf )
483 {
484 METAHEADER *mh = MF_GetMetaHeader( hmf );
485 return MF_PlayMetaFile( hdc, mh );
486 }
487
488 /******************************************************************
489 * EnumMetaFile (GDI32.@)
490 *
491 * Loop through the metafile records in hmf, calling the user-specified
492 * function for each one, stopping when the user's function returns FALSE
493 * (which is considered to be failure)
494 * or when no records are left (which is considered to be success).
495 *
496 * RETURNS
497 * TRUE on success, FALSE on failure.
498 */
499 BOOL WINAPI EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc, LPARAM lpData)
500 {
501 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
502 METARECORD *mr;
503 HANDLETABLE *ht;
504 BOOL result = TRUE;
505 int i;
506 unsigned int offset = 0;
507 HPEN hPen;
508 HBRUSH hBrush;
509 HFONT hFont;
510
511 TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
512 if (!mh) return 0;
513 if(mh->mtType == METAFILE_DISK)
514 {
515 /* Create a memory-based copy */
516 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
517 mh = mhTemp;
518 }
519
520 /* save the current pen, brush and font */
521 hPen = GetCurrentObject(hdc, OBJ_PEN);
522 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
523 hFont = GetCurrentObject(hdc, OBJ_FONT);
524
525 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
526 sizeof(HANDLETABLE) * mh->mtNoObjects);
527
528 /* loop through metafile records */
529 offset = mh->mtHeaderSize * 2;
530
531 while (offset < (mh->mtSize * 2))
532 {
533 mr = (METARECORD *)((char *)mh + offset);
534 if(mr->rdFunction == META_EOF) {
535 TRACE("Got META_EOF so stopping\n");
536 break;
537 }
538 TRACE("Calling EnumFunc with record type %x\n",
539 mr->rdFunction);
540 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
541 {
542 result = FALSE;
543 break;
544 }
545
546 offset += (mr->rdSize * 2);
547 }
548
549 /* restore pen, brush and font */
550 SelectObject(hdc, hBrush);
551 SelectObject(hdc, hPen);
552 SelectObject(hdc, hFont);
553
554 /* free objects in handle table */
555 for(i = 0; i < mh->mtNoObjects; i++)
556 if(*(ht->objectHandle + i) != 0)
557 DeleteObject(*(ht->objectHandle + i));
558
559 /* free handle table */
560 HeapFree( GetProcessHeap(), 0, ht);
561 /* free a copy of metafile */
562 HeapFree( GetProcessHeap(), 0, mhTemp );
563 return result;
564 }
565
566 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
567 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
568 /******************************************************************
569 * PlayMetaFileRecord (GDI32.@)
570 *
571 * Render a single metafile record specified by *mr in the DC hdc, while
572 * using the handle table *ht, of length handles,
573 * to store metafile objects.
574 *
575 * BUGS
576 * The following metafile records are unimplemented:
577 *
578 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
579 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
580 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
581 */
582 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
583 {
584 short s1;
585 POINT *pt;
586 BITMAPINFOHEADER *infohdr;
587
588 TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
589
590 switch (mr->rdFunction)
591 {
592 case META_EOF:
593 break;
594
595 case META_DELETEOBJECT:
596 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
597 *(ht->objectHandle + mr->rdParm[0]) = 0;
598 break;
599
600 case META_SETBKCOLOR:
601 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
602 break;
603
604 case META_SETBKMODE:
605 SetBkMode(hdc, mr->rdParm[0]);
606 break;
607
608 case META_SETMAPMODE:
609 SetMapMode(hdc, mr->rdParm[0]);
610 break;
611
612 case META_SETROP2:
613 SetROP2(hdc, mr->rdParm[0]);
614 break;
615
616 case META_SETRELABS:
617 SetRelAbs(hdc, mr->rdParm[0]);
618 break;
619
620 case META_SETPOLYFILLMODE:
621 SetPolyFillMode(hdc, mr->rdParm[0]);
622 break;
623
624 case META_SETSTRETCHBLTMODE:
625 SetStretchBltMode(hdc, mr->rdParm[0]);
626 break;
627
628 case META_SETTEXTCOLOR:
629 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
630 break;
631
632 case META_SETWINDOWORG:
633 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
634 break;
635
636 case META_SETWINDOWEXT:
637 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
638 break;
639
640 case META_SETVIEWPORTORG:
641 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
642 break;
643
644 case META_SETVIEWPORTEXT:
645 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
646 break;
647
648 case META_OFFSETWINDOWORG:
649 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
650 break;
651
652 case META_SCALEWINDOWEXT:
653 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
654 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
655 break;
656
657 case META_OFFSETVIEWPORTORG:
658 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
659 break;
660
661 case META_SCALEVIEWPORTEXT:
662 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
663 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
664 break;
665
666 case META_LINETO:
667 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
668 break;
669
670 case META_MOVETO:
671 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
672 break;
673
674 case META_EXCLUDECLIPRECT:
675 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
676 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
677 break;
678
679 case META_INTERSECTCLIPRECT:
680 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
681 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
682 break;
683
684 case META_ARC:
685 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
686 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
687 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
688 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
689 break;
690
691 case META_ELLIPSE:
692 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
693 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
694 break;
695
696 case META_FLOODFILL:
697 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
698 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
699 break;
700
701 case META_PIE:
702 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
703 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
704 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
705 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
706 break;
707
708 case META_RECTANGLE:
709 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
710 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
711 break;
712
713 case META_ROUNDRECT:
714 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
715 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
716 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
717 break;
718
719 case META_PATBLT:
720 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
721 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
722 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
723 break;
724
725 case META_SAVEDC:
726 SaveDC(hdc);
727 break;
728
729 case META_SETPIXEL:
730 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
731 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
732 break;
733
734 case META_OFFSETCLIPRGN:
735 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
736 break;
737
738 case META_TEXTOUT:
739 s1 = mr->rdParm[0];
740 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
741 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
742 (char *)(mr->rdParm + 1), s1);
743 break;
744
745 case META_POLYGON:
746 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
747 {
748 Polygon(hdc, pt, mr->rdParm[0]);
749 HeapFree( GetProcessHeap(), 0, pt );
750 }
751 break;
752
753 case META_POLYPOLYGON:
754 {
755 UINT i, total;
756 SHORT *counts = (SHORT *)(mr->rdParm + 1);
757
758 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
759 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
760 if (pt)
761 {
762 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
763 if (cnt32)
764 {
765 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
766 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
767 HeapFree( GetProcessHeap(), 0, cnt32 );
768 }
769 }
770 HeapFree( GetProcessHeap(), 0, pt );
771 }
772 break;
773
774 case META_POLYLINE:
775 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
776 {
777 Polyline( hdc, pt, mr->rdParm[0] );
778 HeapFree( GetProcessHeap(), 0, pt );
779 }
780 break;
781
782 case META_RESTOREDC:
783 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
784 break;
785
786 case META_SELECTOBJECT:
787 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
788 break;
789
790 case META_CHORD:
791 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
792 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
793 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
794 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
795 break;
796
797 case META_CREATEPATTERNBRUSH:
798 switch (mr->rdParm[0])
799 {
800 case BS_PATTERN:
801 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
802 MF_AddHandle(ht, handles,
803 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
804 infohdr->biHeight,
805 infohdr->biPlanes,
806 infohdr->biBitCount,
807 (LPSTR)(mr->rdParm +
808 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
809 break;
810
811 case BS_DIBPATTERN:
812 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
813 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
814 break;
815
816 default:
817 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
818 mr->rdParm[0]);
819 break;
820 }
821 break;
822
823 case META_CREATEPENINDIRECT:
824 {
825 LOGPEN pen;
826 pen.lopnStyle = mr->rdParm[0];
827 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
828 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
829 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
830 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
831 }
832 break;
833
834 case META_CREATEFONTINDIRECT:
835 {
836 LOGFONTA font;
837 font.lfHeight = (SHORT)mr->rdParm[0];
838 font.lfWidth = (SHORT)mr->rdParm[1];
839 font.lfEscapement = (SHORT)mr->rdParm[2];
840 font.lfOrientation = (SHORT)mr->rdParm[3];
841 font.lfWeight = (SHORT)mr->rdParm[4];
842 font.lfItalic = LOBYTE(mr->rdParm[5]);
843 font.lfUnderline = HIBYTE(mr->rdParm[5]);
844 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
845 font.lfCharSet = HIBYTE(mr->rdParm[6]);
846 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
847 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
848 font.lfQuality = LOBYTE(mr->rdParm[8]);
849 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
850 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
851 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
852 }
853 break;
854
855 case META_CREATEBRUSHINDIRECT:
856 {
857 LOGBRUSH brush;
858 brush.lbStyle = mr->rdParm[0];
859 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
860 brush.lbHatch = mr->rdParm[3];
861 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
862 }
863 break;
864
865 case META_CREATEPALETTE:
866 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
867 break;
868
869 case META_SETTEXTALIGN:
870 SetTextAlign(hdc, mr->rdParm[0]);
871 break;
872
873 case META_SELECTPALETTE:
874 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
875 break;
876
877 case META_SETMAPPERFLAGS:
878 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
879 break;
880
881 case META_REALIZEPALETTE:
882 GDIRealizePalette(hdc);
883 break;
884
885 case META_ESCAPE:
886 switch (mr->rdParm[0]) {
887 case GETSCALINGFACTOR: /* get function ... would just NULL dereference */
888 case GETPHYSPAGESIZE:
889 case GETPRINTINGOFFSET:
890 return FALSE;
891 case SETABORTPROC:
892 FIXME("Filtering Escape(SETABORTPROC), possible virus?\n");
893 return FALSE;
894 }
895 Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
896 break;
897
898 case META_EXTTEXTOUT:
899 MF_Play_MetaExtTextOut( hdc, mr );
900 break;
901
902 case META_STRETCHDIB:
903 {
904 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
905 LPSTR bits = (LPSTR)info + bitmap_info_size( info, mr->rdParm[2] );
906 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
907 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
908 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
909 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
910 }
911 break;
912
913 case META_DIBSTRETCHBLT:
914 {
915 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
916 LPSTR bits = (LPSTR)info + bitmap_info_size( info, DIB_RGB_COLORS );
917 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
918 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
919 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
920 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
921 }
922 break;
923
924 case META_STRETCHBLT:
925 {
926 HDC hdcSrc = CreateCompatibleDC(hdc);
927 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
928 mr->rdParm[11], /*Height*/
929 mr->rdParm[13], /*Planes*/
930 mr->rdParm[14], /*BitsPixel*/
931 (LPSTR)&mr->rdParm[15]); /*bits*/
932 SelectObject(hdcSrc,hbitmap);
933 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
934 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
935 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
936 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
937 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
938 DeleteDC(hdcSrc);
939 }
940 break;
941
942 case META_BITBLT:
943 {
944 HDC hdcSrc = CreateCompatibleDC(hdc);
945 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
946 mr->rdParm[8]/*Height*/,
947 mr->rdParm[10]/*Planes*/,
948 mr->rdParm[11]/*BitsPixel*/,
949 (LPSTR)&mr->rdParm[12]/*bits*/);
950 SelectObject(hdcSrc,hbitmap);
951 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
952 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
953 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
954 MAKELONG(0,mr->rdParm[0]));
955 DeleteDC(hdcSrc);
956 }
957 break;
958
959 case META_CREATEREGION:
960 {
961 HRGN hrgn = CreateRectRgn(0,0,0,0);
962
963 MF_Play_MetaCreateRegion(mr, hrgn);
964 MF_AddHandle(ht, handles, hrgn);
965 }
966 break;
967
968 case META_FILLREGION:
969 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
970 *(ht->objectHandle + mr->rdParm[0]));
971 break;
972
973 case META_FRAMEREGION:
974 FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
975 *(ht->objectHandle + mr->rdParm[2]),
976 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
977 break;
978
979 case META_INVERTREGION:
980 InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
981 break;
982
983 case META_PAINTREGION:
984 PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
985 break;
986
987 case META_SELECTCLIPREGION:
988 {
989 HRGN hrgn = 0;
990
991 if (mr->rdParm[0]) hrgn = *(ht->objectHandle + mr->rdParm[0]);
992 SelectClipRgn(hdc, hrgn);
993 }
994 break;
995
996 case META_DIBCREATEPATTERNBRUSH:
997 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
998 but there's no difference */
999 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1000 break;
1001
1002 case META_DIBBITBLT:
1003 /* In practice I've found that there are two layouts for
1004 META_DIBBITBLT, one (the first here) is the usual one when a src
1005 dc is actually passed to it, the second occurs when the src dc is
1006 passed in as NULL to the creating BitBlt. As the second case has
1007 no dib, a size check will suffice to distinguish.
1008
1009 Caolan.McNamara@ul.ie */
1010
1011 if (mr->rdSize > 12) {
1012 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1013 LPSTR bits = (LPSTR)info + bitmap_info_size(info, mr->rdParm[0]);
1014
1015 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1016 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1017 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1018 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1019 }
1020 else /* equivalent to a PatBlt */
1021 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1022 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1023 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1024 break;
1025
1026 case META_SETTEXTCHAREXTRA:
1027 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1028 break;
1029
1030 case META_SETTEXTJUSTIFICATION:
1031 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1032 break;
1033
1034 case META_EXTFLOODFILL:
1035 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1036 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1037 mr->rdParm[0]);
1038 break;
1039
1040 case META_SETDIBTODEV:
1041 {
1042 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1043 char *bits = (char *)info + bitmap_info_size( info, mr->rdParm[0] );
1044 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1045 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1046 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1047 mr->rdParm[2], mr->rdParm[1], bits, info,
1048 mr->rdParm[0]);
1049 break;
1050 }
1051
1052 #define META_UNIMP(x) case x: \
1053 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1054 break;
1055 META_UNIMP(META_DRAWTEXT)
1056 META_UNIMP(META_ANIMATEPALETTE)
1057 META_UNIMP(META_SETPALENTRIES)
1058 META_UNIMP(META_RESIZEPALETTE)
1059 META_UNIMP(META_RESETDC)
1060 META_UNIMP(META_STARTDOC)
1061 META_UNIMP(META_STARTPAGE)
1062 META_UNIMP(META_ENDPAGE)
1063 META_UNIMP(META_ABORTDOC)
1064 META_UNIMP(META_ENDDOC)
1065 META_UNIMP(META_CREATEBRUSH)
1066 META_UNIMP(META_CREATEBITMAPINDIRECT)
1067 META_UNIMP(META_CREATEBITMAP)
1068 #undef META_UNIMP
1069
1070 default:
1071 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1072 return FALSE;
1073 }
1074 return TRUE;
1075 }
1076
1077 /******************************************************************
1078 * SetMetaFileBitsEx (GDI32.@)
1079 *
1080 * Create a metafile from raw data. No checking of the data is performed.
1081 * Use GetMetaFileBitsEx() to get raw data from a metafile.
1082 *
1083 * PARAMS
1084 * size [I] size of metafile, in bytes
1085 * lpData [I] pointer to metafile data
1086 *
1087 * RETURNS
1088 * Success: Handle to metafile.
1089 * Failure: NULL.
1090 */
1091 HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData )
1092 {
1093 const METAHEADER *mh_in = (const METAHEADER *)lpData;
1094 METAHEADER *mh_out;
1095
1096 if (size & 1) return 0;
1097
1098 if (!size || mh_in->mtType != METAFILE_MEMORY || mh_in->mtVersion != MFVERSION ||
1099 mh_in->mtHeaderSize != sizeof(METAHEADER) / 2)
1100 {
1101 SetLastError(ERROR_INVALID_DATA);
1102 return 0;
1103 }
1104
1105 mh_out = HeapAlloc( GetProcessHeap(), 0, size );
1106 if (!mh_out)
1107 {
1108 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1109 return 0;
1110 }
1111
1112 memcpy(mh_out, mh_in, size);
1113 mh_out->mtSize = size / 2;
1114 return MF_Create_HMETAFILE(mh_out);
1115 }
1116
1117 /*****************************************************************
1118 * GetMetaFileBitsEx (GDI32.@)
1119 *
1120 * Get raw metafile data.
1121 *
1122 * Copies the data from metafile _hmf_ into the buffer _buf_.
1123 *
1124 * PARAMS
1125 * hmf [I] metafile
1126 * nSize [I] size of buf
1127 * buf [O] buffer to receive raw metafile data
1128 *
1129 * RETURNS
1130 * If _buf_ is zero, returns size of buffer required. Otherwise,
1131 * returns number of bytes copied.
1132 */
1133 UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf )
1134 {
1135 METAHEADER *mh = MF_GetMetaHeader(hmf);
1136 UINT mfSize;
1137
1138 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1139 if (!mh) return 0; /* FIXME: error code */
1140 if(mh->mtType == METAFILE_DISK)
1141 FIXME("Disk-based metafile?\n");
1142 mfSize = mh->mtSize * 2;
1143 if (!buf) {
1144 TRACE("returning size %d\n", mfSize);
1145 return mfSize;
1146 }
1147 if(mfSize > nSize) mfSize = nSize;
1148 memmove(buf, mh, mfSize);
1149 return mfSize;
1150 }
1151
1152 /******************************************************************
1153 * GetWinMetaFileBits [GDI32.@]
1154 */
1155 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1156 UINT cbBuffer, LPBYTE lpbBuffer,
1157 INT fnMapMode, HDC hdcRef)
1158 {
1159 HDC hdcmf;
1160 HMETAFILE hmf;
1161 UINT ret;
1162 RECT rc;
1163 INT oldMapMode;
1164
1165 GetClipBox(hdcRef, &rc);
1166 oldMapMode = SetMapMode(hdcRef, fnMapMode);
1167
1168 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1169 fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1170
1171 hdcmf = CreateMetaFileA(NULL);
1172 PlayEnhMetaFile(hdcmf, hemf, &rc);
1173 hmf = CloseMetaFile(hdcmf);
1174 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1175 DeleteMetaFile(hmf);
1176
1177 SetMapMode(hdcRef, oldMapMode);
1178
1179 return ret;
1180 }
1181
1182 /******************************************************************
1183 * MF_Play_MetaCreateRegion
1184 *
1185 * Handles META_CREATEREGION for PlayMetaFileRecord().
1186 *
1187 * The layout of the record looks something like this:
1188 *
1189 * rdParm meaning
1190 * 0 Always 0?
1191 * 1 Always 6?
1192 * 2 Looks like a handle? - not constant
1193 * 3 0 or 1 ??
1194 * 4 Total number of bytes
1195 * 5 No. of separate bands = n [see below]
1196 * 6 Largest number of x co-ords in a band
1197 * 7-10 Bounding box x1 y1 x2 y2
1198 * 11-... n bands
1199 *
1200 * Regions are divided into bands that are uniform in the
1201 * y-direction. Each band consists of pairs of on/off x-coords and is
1202 * written as
1203 * m y0 y1 x1 x2 x3 ... xm m
1204 * into successive rdParm[]s.
1205 *
1206 * This is probably just a dump of the internal RGNOBJ?
1207 *
1208 * HDMD - 18/12/97
1209 *
1210 */
1211
1212 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1213 {
1214 WORD band, pair;
1215 WORD *start, *end;
1216 INT16 y0, y1;
1217 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1218
1219 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1220 band++, start = end + 1) {
1221 if(*start / 2 != (*start + 1) / 2) {
1222 WARN("Delimiter not even.\n");
1223 DeleteObject( hrgn2 );
1224 return FALSE;
1225 }
1226
1227 end = start + *start + 3;
1228 if(end > (WORD *)mr + mr->rdSize) {
1229 WARN("End points outside record.\n");
1230 DeleteObject( hrgn2 );
1231 return FALSE;
1232 }
1233
1234 if(*start != *end) {
1235 WARN("Mismatched delimiters.\n");
1236 DeleteObject( hrgn2 );
1237 return FALSE;
1238 }
1239
1240 y0 = *(INT16 *)(start + 1);
1241 y1 = *(INT16 *)(start + 2);
1242 for(pair = 0; pair < *start / 2; pair++) {
1243 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1244 *(INT16 *)(start + 4 + 2*pair), y1 );
1245 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1246 }
1247 }
1248 DeleteObject( hrgn2 );
1249 return TRUE;
1250 }
1251
1252
1253 /******************************************************************
1254 * MF_Play_MetaExtTextOut
1255 *
1256 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1257 */
1258
1259 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1260 {
1261 INT *dx = NULL;
1262 int i;
1263 LPINT16 dxx;
1264 LPSTR sot;
1265 DWORD len;
1266 WORD s1;
1267 RECT rect;
1268 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1269
1270 s1 = mr->rdParm[2]; /* String length */
1271 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1272 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1273 /* rec len without dx array */
1274
1275 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1276 if (isrect)
1277 {
1278 rect.left = (SHORT)mr->rdParm[4];
1279 rect.top = (SHORT)mr->rdParm[5];
1280 rect.right = (SHORT)mr->rdParm[6];
1281 rect.bottom = (SHORT)mr->rdParm[7];
1282 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1283 }
1284
1285 if (mr->rdSize == len / 2)
1286 dxx = NULL; /* determine if array is present */
1287 else
1288 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1289 {
1290 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1291 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1292 if (dx) for (i = 0; i < s1; i++) dx[i] = dxx[i];
1293 }
1294 else {
1295 TRACE("%s len: %d\n", sot, mr->rdSize);
1296 WARN("Please report: ExtTextOut len=%d slen=%d rdSize=%d opt=%04x\n",
1297 len, s1, mr->rdSize, mr->rdParm[3]);
1298 dxx = NULL; /* shouldn't happen -- but if, we continue with NULL */
1299 }
1300 ExtTextOutA( hdc,
1301 (SHORT)mr->rdParm[1], /* X position */
1302 (SHORT)mr->rdParm[0], /* Y position */
1303 mr->rdParm[3], /* options */
1304 &rect, /* rectangle */
1305 sot, /* string */
1306 s1, dx); /* length, dx array */
1307 if (dx)
1308 {
1309 TRACE("%s len: %d dx0: %d\n", sot, mr->rdSize, dx[0]);
1310 HeapFree( GetProcessHeap(), 0, dx );
1311 }
1312 return TRUE;
1313 }
1314
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.