Fixed message filtering check.
[wine/testsucceed.git] / objects / metafile.c
blob1da0384dada6512a485f530ae009acfb79a071f0
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
7 */
9 #include <string.h>
10 #include <fcntl.h>
11 #include "wine/winbase16.h"
12 #include "metafiledrv.h"
13 #include "metafile.h"
14 #include "bitmap.h"
15 #include "file.h"
16 #include "heap.h"
17 #include "toolhelp.h"
18 #include "debug.h"
20 /******************************************************************
21 * MF_AddHandle
23 * Add a handle to an external handle table and return the index
26 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
28 int i;
30 for (i = 0; i < htlen; i++)
32 if (*(ht->objectHandle + i) == 0)
34 *(ht->objectHandle + i) = hobj;
35 return i;
38 return -1;
42 /******************************************************************
43 * MF_AddHandleDC
45 * Note: this function assumes that we never delete objects.
46 * If we do someday, we'll need to maintain a table to re-use deleted
47 * handles.
49 static int MF_AddHandleDC( DC *dc )
51 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
52 physDev->mh->mtNoObjects++;
53 return physDev->nextHandle++;
57 /******************************************************************
58 * GetMetaFile16 (GDI.124)
60 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
62 return GetMetaFile32A( lpFilename );
66 /******************************************************************
67 * GetMetaFile32A (GDI32.197)
69 * Read a metafile from a file. Returns handle to a disk-based metafile.
71 HMETAFILE32 WINAPI GetMetaFile32A(
72 LPCSTR lpFilename
73 /* pointer to string containing filename to read */
76 HMETAFILE16 hmf;
77 METAHEADER *mh;
78 HFILE32 hFile;
79 DWORD size;
81 TRACE(metafile,"%s\n", lpFilename);
83 if (!lpFilename)
84 return 0;
86 hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
87 mh = (METAHEADER *)GlobalLock16(hmf);
89 if (!mh)
91 GlobalFree16(hmf);
92 return 0;
95 if ((hFile = _lopen32(lpFilename, OF_READ)) == HFILE_ERROR32)
97 GlobalFree16(hmf);
98 return 0;
101 if (_lread32(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR32)
103 _lclose32( hFile );
104 GlobalFree16(hmf);
105 return 0;
108 size = mh->mtSize * 2; /* alloc memory for whole metafile */
109 GlobalUnlock16(hmf);
110 hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
111 mh = (METAHEADER *)GlobalLock16(hmf);
113 if (!mh)
115 _lclose32( hFile );
116 GlobalFree16(hmf);
117 return 0;
120 if (_lread32(hFile, (char*)mh + mh->mtHeaderSize * 2,
121 size - mh->mtHeaderSize * 2) == HFILE_ERROR32)
123 _lclose32( hFile );
124 GlobalFree16(hmf);
125 return 0;
128 _lclose32(hFile);
130 if (mh->mtType != 1)
132 GlobalFree16(hmf);
133 return 0;
136 GlobalUnlock16(hmf);
137 return hmf;
142 /******************************************************************
143 * GetMetaFile32W (GDI32.199)
145 HMETAFILE32 WINAPI GetMetaFile32W( LPCWSTR lpFilename )
147 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
148 HMETAFILE32 ret = GetMetaFile32A( p );
149 HeapFree( GetProcessHeap(), 0, p );
150 return ret;
154 /******************************************************************
155 * CopyMetaFile16 (GDI.151)
158 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename )
160 return CopyMetaFile32A( hSrcMetaFile, lpFilename );
164 /******************************************************************
165 * CopyMetaFile32A (GDI32.23)
167 * Copies the metafile corresponding to hSrcMetaFile to either
168 * a disk file, if a filename is given, or to a new memory based
169 * metafile, if lpFileName is NULL.
171 * RETURNS
173 * Handle to metafile copy on success, NULL on failure.
175 * BUGS
177 * Copying to disk returns NULL even if successful.
179 HMETAFILE32 WINAPI CopyMetaFile32A(
180 HMETAFILE32 hSrcMetaFile, /* handle of metafile to copy */
181 LPCSTR lpFilename /* filename if copying to a file */
183 HMETAFILE16 handle = 0;
184 METAHEADER *mh;
185 METAHEADER *mh2;
186 HFILE32 hFile;
188 TRACE(metafile,"(%08x,%s)\n", hSrcMetaFile, lpFilename);
190 mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
192 if (!mh)
193 return 0;
195 if (lpFilename) /* disk based metafile */
197 int i,j;
198 hFile = _lcreat32(lpFilename, 0);
199 j=mh->mtType;
200 mh->mtType=1; /* disk file version stores 1 here */
201 i=_lwrite32(hFile, (char *)mh, mh->mtSize * 2) ;
202 mh->mtType=j; /* restore old value [0 or 1] */
203 _lclose32(hFile);
204 if (i == -1)
205 return 0;
206 /* FIXME: return value */
208 else /* memory based metafile */
210 handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
211 mh2 = (METAHEADER *)GlobalLock16(handle);
212 memcpy(mh2,mh, mh->mtSize * 2);
213 GlobalUnlock16(handle);
216 GlobalUnlock16(hSrcMetaFile);
217 return handle;
221 /******************************************************************
222 * CopyMetaFile32W (GDI32.24)
224 HMETAFILE32 WINAPI CopyMetaFile32W( HMETAFILE32 hSrcMetaFile,
225 LPCWSTR lpFilename )
227 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
228 HMETAFILE32 ret = CopyMetaFile32A( hSrcMetaFile, p );
229 HeapFree( GetProcessHeap(), 0, p );
230 return ret;
234 /******************************************************************
235 * IsValidMetaFile (GDI.410)
237 * Attempts to check if a given metafile is correctly formatted.
238 * Currently, the only things verified are several properties of the
239 * header.
241 * RETURNS
242 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
244 * BUGS
245 * This is not exactly what windows does, see _Undocumented_Windows_
246 * for details.
249 BOOL16 WINAPI IsValidMetaFile(HMETAFILE16 hmf)
251 BOOL16 resu=FALSE;
252 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
253 if (mh) {
254 if (mh->mtType == 1 || mh->mtType == 0)
255 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
256 if (mh->mtVersion == MFVERSION)
257 resu=TRUE;
258 GlobalUnlock16(hmf);
260 TRACE(metafile,"IsValidMetaFile %x => %d\n",hmf,resu);
261 return resu;
265 /******************************************************************
266 * PlayMetaFile16 (GDI.123)
269 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
271 return PlayMetaFile32( hdc, hmf );
274 /******************************************************************
275 * PlayMetaFile32 (GDI32.265)
277 * Renders the metafile specified by hmf in the DC specified by
278 * hdc. Returns FALSE on failure, TRUE on success.
280 BOOL32 WINAPI PlayMetaFile32(
281 HDC32 hdc, /* handle of DC to render in */
282 HMETAFILE32 hmf /* handle of metafile to render */
285 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
286 METARECORD *mr;
287 HANDLETABLE16 *ht;
288 HGLOBAL16 hHT;
289 int offset = 0;
290 WORD i;
291 HPEN32 hPen;
292 HBRUSH32 hBrush;
293 HFONT32 hFont;
294 DC *dc;
296 TRACE(metafile,"(%04x %04x)\n",hdc,hmf);
297 if (!mh) return FALSE;
299 /* save the current pen, brush and font */
300 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
301 hPen = dc->w.hPen;
302 hBrush = dc->w.hBrush;
303 hFont = dc->w.hFont;
304 GDI_HEAP_UNLOCK(hdc);
305 /* create the handle table */
306 hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
307 sizeof(HANDLETABLE16) * mh->mtNoObjects);
308 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
311 /* loop through metafile playing records */
312 offset = mh->mtHeaderSize * 2;
313 while (offset < mh->mtSize * 2)
315 mr = (METARECORD *)((char *)mh + offset);
316 TRACE(metafile,"offset=%04x,size=%08lx\n",
317 offset, mr->rdSize);
318 if (!mr->rdSize) {
319 TRACE(metafile,"Entry got size 0 at offset %d, total mf length is %ld\n",
320 offset,mh->mtSize*2);
321 break; /* would loop endlessly otherwise */
323 offset += mr->rdSize * 2;
324 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
327 SelectObject32(hdc, hBrush);
328 SelectObject32(hdc, hPen);
329 SelectObject32(hdc, hFont);
331 /* free objects in handle table */
332 for(i = 0; i < mh->mtNoObjects; i++)
333 if(*(ht->objectHandle + i) != 0)
334 DeleteObject32(*(ht->objectHandle + i));
336 /* free handle table */
337 GlobalFree16(hHT);
339 return TRUE;
343 /******************************************************************
344 * EnumMetaFile16 (GDI.175)
346 * Loop through the metafile records in hmf, calling the user-specified
347 * function for each one, stopping when the user's function returns FALSE
348 * (which is considered to be failure)
349 * or when no records are left (which is considered to be success).
351 * RETURNS
352 * TRUE on success, FALSE on failure.
354 * HISTORY
355 * Niels de carpentier, april 1996
357 BOOL16 WINAPI EnumMetaFile16(
358 HDC16 hdc,
359 HMETAFILE16 hmf,
360 MFENUMPROC16 lpEnumFunc,
361 LPARAM lpData
364 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
365 METARECORD *mr;
366 HANDLETABLE16 *ht;
367 HGLOBAL16 hHT;
368 SEGPTR spht;
369 int offset = 0;
370 WORD i, seg;
371 HPEN32 hPen;
372 HBRUSH32 hBrush;
373 HFONT32 hFont;
374 DC *dc;
375 BOOL16 result = TRUE;
377 TRACE(metafile,"(%04x, %04x, %08lx, %08lx)\n",
378 hdc, hmf, (DWORD)lpEnumFunc, lpData);
380 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
381 hPen = dc->w.hPen;
382 hBrush = dc->w.hBrush;
383 hFont = dc->w.hFont;
384 GDI_HEAP_UNLOCK(hdc);
386 /* create the handle table */
388 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
389 sizeof(HANDLETABLE16) * mh->mtNoObjects);
390 spht = WIN16_GlobalLock16(hHT);
392 seg = GlobalHandleToSel(hmf);
393 offset = mh->mtHeaderSize * 2;
395 /* loop through metafile records */
397 while (offset < (mh->mtSize * 2))
399 mr = (METARECORD *)((char *)mh + offset);
400 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
401 (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
402 mh->mtNoObjects, (LONG)lpData ))
404 result = FALSE;
405 break;
409 offset += (mr->rdSize * 2);
412 SelectObject32(hdc, hBrush);
413 SelectObject32(hdc, hPen);
414 SelectObject32(hdc, hFont);
416 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
418 /* free objects in handle table */
419 for(i = 0; i < mh->mtNoObjects; i++)
420 if(*(ht->objectHandle + i) != 0)
421 DeleteObject32(*(ht->objectHandle + i));
423 /* free handle table */
424 GlobalFree16(hHT);
425 GlobalUnlock16(hmf);
426 return result;
429 BOOL32 WINAPI EnumMetaFile32(
430 HDC32 hdc,
431 HMETAFILE32 hmf,
432 MFENUMPROC32 lpEnumFunc,
433 LPARAM lpData
435 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
436 METARECORD *mr;
437 HANDLETABLE32 *ht;
438 BOOL32 result = TRUE;
439 int i, offset = 0;
440 DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
441 HPEN32 hPen;
442 HBRUSH32 hBrush;
443 HFONT32 hFont;
445 TRACE(metafile,"(%08x,%08x,%p,%p)\n",
446 hdc, hmf, lpEnumFunc, (void*)lpData);
447 if (!mh) return 0;
449 /* save the current pen, brush and font */
450 if (!dc) return 0;
451 hPen = dc->w.hPen;
452 hBrush = dc->w.hBrush;
453 hFont = dc->w.hFont;
454 GDI_HEAP_UNLOCK(hdc);
457 ht = (HANDLETABLE32 *) GlobalAlloc32(GPTR,
458 sizeof(HANDLETABLE32) * mh->mtNoObjects);
460 /* loop through metafile records */
461 offset = mh->mtHeaderSize * 2;
463 while (offset < (mh->mtSize * 2))
465 mr = (METARECORD *)((char *)mh + offset);
466 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
468 result = FALSE;
469 break;
472 offset += (mr->rdSize * 2);
475 /* restore pen, brush and font */
476 SelectObject32(hdc, hBrush);
477 SelectObject32(hdc, hPen);
478 SelectObject32(hdc, hFont);
480 /* free objects in handle table */
481 for(i = 0; i < mh->mtNoObjects; i++)
482 if(*(ht->objectHandle + i) != 0)
483 DeleteObject32(*(ht->objectHandle + i));
485 /* free handle table */
486 GlobalFree32((HGLOBAL32)ht);
487 GlobalUnlock16(hmf);
488 return result;
491 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn );
493 /******************************************************************
494 * PlayMetaFileRecord16 (GDI.176)
496 * Render a single metafile record specified by *mr in the DC hdc, while
497 * using the handle table *ht, of length nHandles,
498 * to store metafile objects.
500 * BUGS
501 * The following metafile records are unimplemented:
503 * FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
504 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
505 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
508 void WINAPI PlayMetaFileRecord16(
509 HDC16 hdc, /* DC to render metafile into */
510 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
511 METARECORD *mr, /* pointer to metafile record to render */
512 UINT16 nHandles /* size of handle table */
514 short s1;
515 HANDLE16 hndl;
516 char *ptr;
517 BITMAPINFOHEADER *infohdr;
519 TRACE(metafile,"(%04x %08lx %08lx %04x) function %04x\n",
520 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
522 switch (mr->rdFunction)
524 case META_EOF:
525 break;
527 case META_DELETEOBJECT:
528 DeleteObject32(*(ht->objectHandle + *(mr->rdParm)));
529 *(ht->objectHandle + *(mr->rdParm)) = 0;
530 break;
532 case META_SETBKCOLOR:
533 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
534 break;
536 case META_SETBKMODE:
537 SetBkMode16(hdc, *(mr->rdParm));
538 break;
540 case META_SETMAPMODE:
541 SetMapMode16(hdc, *(mr->rdParm));
542 break;
544 case META_SETROP2:
545 SetROP216(hdc, *(mr->rdParm));
546 break;
548 case META_SETRELABS:
549 SetRelAbs16(hdc, *(mr->rdParm));
550 break;
552 case META_SETPOLYFILLMODE:
553 SetPolyFillMode16(hdc, *(mr->rdParm));
554 break;
556 case META_SETSTRETCHBLTMODE:
557 SetStretchBltMode16(hdc, *(mr->rdParm));
558 break;
560 case META_SETTEXTCOLOR:
561 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
562 break;
564 case META_SETWINDOWORG:
565 SetWindowOrg(hdc, *(mr->rdParm + 1), *(mr->rdParm));
566 break;
568 case META_SETWINDOWEXT:
569 SetWindowExt(hdc, *(mr->rdParm + 1), *(mr->rdParm));
570 break;
572 case META_SETVIEWPORTORG:
573 SetViewportOrg(hdc, *(mr->rdParm + 1), *(mr->rdParm));
574 break;
576 case META_SETVIEWPORTEXT:
577 SetViewportExt(hdc, *(mr->rdParm + 1), *(mr->rdParm));
578 break;
580 case META_OFFSETWINDOWORG:
581 OffsetWindowOrg(hdc, *(mr->rdParm + 1), *(mr->rdParm));
582 break;
584 case META_SCALEWINDOWEXT:
585 ScaleWindowExt(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
586 *(mr->rdParm + 1), *(mr->rdParm));
587 break;
589 case META_OFFSETVIEWPORTORG:
590 OffsetViewportOrg(hdc, *(mr->rdParm + 1), *(mr->rdParm));
591 break;
593 case META_SCALEVIEWPORTEXT:
594 ScaleViewportExt(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
595 *(mr->rdParm + 1), *(mr->rdParm));
596 break;
598 case META_LINETO:
599 LineTo32(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
600 break;
602 case META_MOVETO:
603 MoveTo(hdc, *(mr->rdParm + 1), *(mr->rdParm));
604 break;
606 case META_EXCLUDECLIPRECT:
607 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
608 *(mr->rdParm + 1), *(mr->rdParm) );
609 break;
611 case META_INTERSECTCLIPRECT:
612 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
613 *(mr->rdParm + 1), *(mr->rdParm) );
614 break;
616 case META_ARC:
617 Arc32(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
618 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
619 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
620 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
621 break;
623 case META_ELLIPSE:
624 Ellipse32(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
625 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
626 break;
628 case META_FLOODFILL:
629 FloodFill32(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
630 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
631 break;
633 case META_PIE:
634 Pie32(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
635 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
636 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
637 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
638 break;
640 case META_RECTANGLE:
641 Rectangle32(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
642 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
643 break;
645 case META_ROUNDRECT:
646 RoundRect32(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
647 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
648 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
649 break;
651 case META_PATBLT:
652 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
653 *(mr->rdParm + 3), *(mr->rdParm + 2),
654 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
655 break;
657 case META_SAVEDC:
658 SaveDC32(hdc);
659 break;
661 case META_SETPIXEL:
662 SetPixel32(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
663 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
664 break;
666 case META_OFFSETCLIPRGN:
667 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
668 break;
670 case META_TEXTOUT:
671 s1 = *(mr->rdParm);
672 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
673 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
674 (char *)(mr->rdParm + 1), s1);
675 break;
677 case META_POLYGON:
678 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
679 break;
681 case META_POLYPOLYGON:
682 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
683 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
684 break;
686 case META_POLYLINE:
687 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
688 break;
690 case META_RESTOREDC:
691 RestoreDC32(hdc, (INT16)*(mr->rdParm));
692 break;
694 case META_SELECTOBJECT:
695 SelectObject32(hdc, *(ht->objectHandle + *(mr->rdParm)));
696 break;
698 case META_CHORD:
699 Chord32(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
700 (INT16)*(mr->rdParm+5), (INT16)*(mr->rdParm + 4),
701 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
702 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
703 break;
705 case META_CREATEPATTERNBRUSH:
706 switch (*(mr->rdParm))
708 case BS_PATTERN:
709 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
710 MF_AddHandle(ht, nHandles,
711 CreatePatternBrush32(CreateBitmap32(infohdr->biWidth,
712 infohdr->biHeight,
713 infohdr->biPlanes,
714 infohdr->biBitCount,
715 (LPSTR)(mr->rdParm +
716 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
717 break;
719 case BS_DIBPATTERN:
720 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
721 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
722 ptr = GlobalLock16(hndl);
723 memcpy(ptr, mr->rdParm + 2, s1);
724 GlobalUnlock16(hndl);
725 MF_AddHandle(ht, nHandles,
726 CreateDIBPatternBrush32(hndl, *(mr->rdParm + 1)));
727 GlobalFree16(hndl);
729 break;
731 case META_CREATEPENINDIRECT:
732 MF_AddHandle(ht, nHandles,
733 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
734 break;
736 case META_CREATEFONTINDIRECT:
737 MF_AddHandle(ht, nHandles,
738 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
739 break;
741 case META_CREATEBRUSHINDIRECT:
742 MF_AddHandle(ht, nHandles,
743 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
744 break;
746 /* W. Magro: Some new metafile operations. Not all debugged. */
747 case META_CREATEPALETTE:
748 MF_AddHandle(ht, nHandles,
749 CreatePalette16((LPLOGPALETTE)mr->rdParm));
750 break;
752 case META_SETTEXTALIGN:
753 SetTextAlign16(hdc, *(mr->rdParm));
754 break;
756 case META_SELECTPALETTE:
757 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),*(mr->rdParm));
758 break;
760 case META_SETMAPPERFLAGS:
761 SetMapperFlags16(hdc, *(mr->rdParm));
762 break;
764 case META_REALIZEPALETTE:
765 RealizePalette16(hdc);
766 break;
768 case META_ESCAPE:
769 FIXME(metafile, "META_ESCAPE unimplemented.\n");
770 break;
772 /* --- Begin of fixed or new metafile operations. July 1996 ----*/
773 case META_EXTTEXTOUT:
775 LPINT16 dxx;
776 LPSTR sot;
777 DWORD len;
779 s1 = mr->rdParm[2]; /* String length */
780 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
781 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0); /* rec len without dx array */
783 sot= (LPSTR)&mr->rdParm[4]; /* start_of_text */
784 if (mr->rdParm[3])
785 sot+=sizeof(RECT16); /* there is a rectangle, so add offset */
787 if (mr->rdSize == len / 2)
788 dxx = NULL; /* determine if array present */
789 else
790 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
791 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
792 else
794 TRACE(metafile,"%s len: %ld\n",
795 sot,mr->rdSize);
796 WARN(metafile,
797 "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
798 len,s1,mr->rdSize,mr->rdParm[3]);
799 dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
801 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
802 mr->rdParm[0], /* Y position */
803 mr->rdParm[3], /* options */
804 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL, /* rectangle */
805 sot, /* string */
806 s1, dxx); /* length, dx array */
807 if (dxx)
808 TRACE(metafile,"%s len: %ld dx0: %d\n",
809 sot,mr->rdSize,dxx[0]);
811 break;
813 case META_STRETCHDIB:
815 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
816 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
817 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
818 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
819 mr->rdParm[4],mr->rdParm[3],bits,info,
820 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
822 break;
824 case META_DIBSTRETCHBLT:
826 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
827 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
828 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
829 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
830 mr->rdParm[3],mr->rdParm[2],bits,info,
831 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
833 break;
835 case META_STRETCHBLT:
837 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
838 HBITMAP32 hbitmap=CreateBitmap32(mr->rdParm[10], /*Width */
839 mr->rdParm[11], /*Height*/
840 mr->rdParm[13], /*Planes*/
841 mr->rdParm[14], /*BitsPixel*/
842 (LPSTR)&mr->rdParm[15]); /*bits*/
843 SelectObject32(hdcSrc,hbitmap);
844 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
845 mr->rdParm[7],mr->rdParm[6],
846 hdcSrc,mr->rdParm[5],mr->rdParm[4],
847 mr->rdParm[3],mr->rdParm[2],
848 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
849 DeleteDC32(hdcSrc);
851 break;
853 case META_BITBLT: /* <-- not yet debugged */
855 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
856 HBITMAP32 hbitmap=CreateBitmap32(mr->rdParm[7]/*Width */,
857 mr->rdParm[8]/*Height*/,
858 mr->rdParm[10]/*Planes*/,
859 mr->rdParm[11]/*BitsPixel*/,
860 (LPSTR)&mr->rdParm[12]/*bits*/);
861 SelectObject32(hdcSrc,hbitmap);
862 BitBlt32(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
863 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
864 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
865 MAKELONG(0,mr->rdParm[0]));
866 DeleteDC32(hdcSrc);
868 break;
870 /* --- Begin of new metafile operations. April, 1997 (ak) ----*/
871 case META_CREATEREGION:
873 HRGN32 hrgn = CreateRectRgn32(0,0,0,0);
875 MF_Meta_CreateRegion(mr, hrgn);
876 MF_AddHandle(ht, nHandles, hrgn);
878 break;
880 case META_FILLREGION:
881 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)),
882 *(ht->objectHandle + *(mr->rdParm+1)));
883 break;
885 case META_INVERTREGION:
886 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
887 break;
889 case META_PAINTREGION:
890 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
891 break;
893 case META_SELECTCLIPREGION:
894 SelectClipRgn32(hdc, *(ht->objectHandle + *(mr->rdParm)));
895 break;
897 case META_DIBCREATEPATTERNBRUSH:
898 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
899 TRACE(metafile,"%d\n",*(mr->rdParm));
900 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
901 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
902 ptr = GlobalLock16(hndl);
903 memcpy(ptr, mr->rdParm + 2, s1);
904 GlobalUnlock16(hndl);
905 MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
906 GlobalFree16(hndl);
907 break;
909 case META_DIBBITBLT:
911 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
912 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
913 StretchDIBits16(hdc,mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
914 mr->rdParm[4],mr->rdParm[3],mr->rdParm[2],
915 mr->rdParm[5],mr->rdParm[4],bits,info,
916 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
918 break;
920 case META_SETTEXTCHAREXTRA:
921 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
922 break;
924 case META_SETTEXTJUSTIFICATION:
925 SetTextJustification32(hdc, *(mr->rdParm + 1), *(mr->rdParm));
926 break;
928 #define META_UNIMP(x) case x: FIXME(metafile, "PlayMetaFileRecord:record type "#x" not implemented.\n");break;
929 META_UNIMP(META_FRAMEREGION)
930 META_UNIMP(META_DRAWTEXT)
931 META_UNIMP(META_SETDIBTODEV)
932 META_UNIMP(META_ANIMATEPALETTE)
933 META_UNIMP(META_SETPALENTRIES)
934 META_UNIMP(META_RESIZEPALETTE)
935 META_UNIMP(META_EXTFLOODFILL)
936 META_UNIMP(META_RESETDC)
937 META_UNIMP(META_STARTDOC)
938 META_UNIMP(META_STARTPAGE)
939 META_UNIMP(META_ENDPAGE)
940 META_UNIMP(META_ABORTDOC)
941 META_UNIMP(META_ENDDOC)
942 META_UNIMP(META_CREATEBRUSH)
943 META_UNIMP(META_CREATEBITMAPINDIRECT)
944 META_UNIMP(META_CREATEBITMAP)
945 #undef META_UNIMP
947 default:
948 WARN(metafile, "PlayMetaFileRecord: Unknown record type %x\n",
949 mr->rdFunction);
954 BOOL32 WINAPI PlayMetaFileRecord32(
955 HDC32 hdc,
956 HANDLETABLE32 *handletable,
957 METARECORD *metarecord,
958 UINT32 handles
961 HANDLETABLE16 * ht = (void *)GlobalAlloc32(GPTR,
962 handles*sizeof(HANDLETABLE16));
963 int i = 0;
964 TRACE(metafile, "(%08x,%p,%p,%d)\n", hdc, handletable, metarecord, handles);
965 for (i=0; i<handles; i++)
966 ht->objectHandle[i] = handletable->objectHandle[i];
967 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
968 for (i=0; i<handles; i++)
969 handletable->objectHandle[i] = ht->objectHandle[i];
970 GlobalFree32((HGLOBAL32)ht);
971 return TRUE;
974 /******************************************************************
975 * GetMetaFileBits (GDI.159)
977 * Trade in a metafile object handle for a handle to the metafile memory.
981 HGLOBAL16 WINAPI GetMetaFileBits(
982 HMETAFILE16 hmf /* metafile handle */
985 TRACE(metafile,"hMem out: %04x\n", hmf);
986 return hmf;
989 /******************************************************************
990 * SetMetaFileBits (GDI.160)
992 * Trade in a metafile memory handle for a handle to a metafile object.
993 * The memory region should hold a proper metafile, otherwise
994 * problems will occur when it is used. Validity of the memory is not
995 * checked. The function is essentially just the identity function.
997 HMETAFILE16 WINAPI SetMetaFileBits(
998 HGLOBAL16 hMem
999 /* handle to a memory region holding a metafile */
1002 TRACE(metafile,"hmf out: %04x\n", hMem);
1004 return hMem;
1007 /******************************************************************
1008 * SetMetaFileBitsBetter (GDI.196)
1010 * Trade in a metafile memory handle for a handle to a metafile object,
1011 * making a cursory check (using IsValidMetaFile()) that the memory
1012 * handle points to a valid metafile.
1014 * RETURNS
1015 * Handle to a metafile on success, NULL on failure..
1017 HMETAFILE16 WINAPI SetMetaFileBitsBetter( HMETAFILE16 hMeta )
1019 if( IsValidMetaFile( hMeta ) )
1020 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1021 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1022 return (HMETAFILE16)0;
1025 /******************************************************************
1026 * SetMetaFileBitsEx (GDI32.323)
1028 * Create a metafile from raw data. No checking of the data is performed.
1029 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1031 HMETAFILE32 WINAPI SetMetaFileBitsEx(
1032 UINT32 size, /* size of metafile, in bytes */
1033 const BYTE *lpData /* pointer to metafile data */
1036 HMETAFILE32 hmf = GlobalAlloc16(GHND, size);
1037 BYTE *p = GlobalLock16(hmf) ;
1038 TRACE(metafile, "(%d,%p) returning %08x\n", size, lpData, hmf);
1039 if (!hmf || !p) return 0;
1040 memcpy(p, lpData, size);
1041 GlobalUnlock16(hmf);
1042 return hmf;
1045 /*****************************************************************
1046 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1048 * Copies the data from metafile _hmf_ into the buffer _buf_.
1049 * If _buf_ is zero, returns size of buffer required. Otherwise,
1050 * returns number of bytes copied.
1052 UINT32 WINAPI GetMetaFileBitsEx(
1053 HMETAFILE32 hmf, /* metafile */
1054 UINT32 nSize, /* size of buf */
1055 LPVOID buf /* buffer to receive raw metafile data */
1057 METAHEADER *h = GlobalLock16(hmf);
1058 UINT32 mfSize;
1060 TRACE(metafile, "(%08x,%d,%p)\n", hmf, nSize, buf);
1061 if (!h) return 0; /* FIXME: error code */
1062 mfSize = h->mtSize * 2;
1063 if (!buf) {
1064 GlobalUnlock16(hmf);
1065 TRACE(metafile,"returning size %d\n", mfSize);
1066 return mfSize;
1068 if(mfSize > nSize) mfSize = nSize;
1069 memmove(buf, h, mfSize);
1070 GlobalUnlock16(hmf);
1071 return mfSize;
1074 /******************************************************************
1075 * GetWinMetaFileBits [GDI32.241]
1077 UINT32 WINAPI GetWinMetaFileBits(HENHMETAFILE32 hemf,
1078 UINT32 cbBuffer, LPBYTE lpbBuffer,
1079 INT32 fnMapMode, HDC32 hdcRef)
1081 FIXME(metafile, "(%d,%d,%p,%d,%d): stub\n",
1082 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1083 return 0;
1086 /******************************************************************
1087 * MF_Meta_CreateRegion
1089 * Handles META_CREATEREGION for PlayMetaFileRecord().
1093 * The layout of the record looks something like this:
1095 * rdParm meaning
1096 * 0 Always 0?
1097 * 1 Always 6?
1098 * 2 Looks like a handle? - not constant
1099 * 3 0 or 1 ??
1100 * 4 Total number of bytes
1101 * 5 No. of seperate bands = n [see below]
1102 * 6 Largest number of x co-ords in a band
1103 * 7-10 Bounding box x1 y1 x2 y2
1104 * 11-... n bands
1106 * Regions are divided into bands that are uniform in the
1107 * y-direction. Each band consists of pairs of on/off x-coords and is
1108 * written as
1109 * m y0 y1 x1 x2 x3 ... xm m
1110 * into successive rdParm[]s.
1112 * This is probably just a dump of the internal RGNOBJ?
1114 * HDMD - 18/12/97
1118 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn )
1120 WORD band, pair;
1121 WORD *start, *end;
1122 INT16 y0, y1;
1123 HRGN32 hrgn2 = CreateRectRgn32( 0, 0, 0, 0 );
1125 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1126 band++, start = end + 1) {
1127 if(*start / 2 != (*start + 1) / 2) {
1128 WARN(metafile, "Delimiter not even.\n");
1129 DeleteObject32( hrgn2 );
1130 return FALSE;
1133 end = start + *start + 3;
1134 if(end > (WORD *)mr + mr->rdSize) {
1135 WARN(metafile, "End points outside record.\n");
1136 DeleteObject32( hrgn2 );
1137 return FALSE;
1140 if(*start != *end) {
1141 WARN(metafile, "Mismatched delimiters.\n");
1142 DeleteObject32( hrgn2 );
1143 return FALSE;
1146 y0 = *(INT16 *)(start + 1);
1147 y1 = *(INT16 *)(start + 2);
1148 for(pair = 0; pair < *start / 2; pair++) {
1149 SetRectRgn32( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1150 *(INT16 *)(start + 4 + 2*pair), y1 );
1151 CombineRgn32(hrgn, hrgn, hrgn2, RGN_OR);
1154 DeleteObject32( hrgn2 );
1155 return TRUE;
1159 /******************************************************************
1160 * MF_WriteRecord
1162 * Warning: this function can change the metafile handle.
1165 static BOOL32 MF_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
1167 DWORD len;
1168 METAHEADER *mh;
1169 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1171 switch(physDev->mh->mtType)
1173 case METAFILE_MEMORY:
1174 len = physDev->mh->mtSize * 2 + rlen;
1175 mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1176 if (!mh) return FALSE;
1177 physDev->mh = mh;
1178 memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1179 break;
1180 case METAFILE_DISK:
1181 TRACE(metafile,"Writing record to disk\n");
1182 if (_lwrite32(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1183 return FALSE;
1184 break;
1185 default:
1186 ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
1187 return FALSE;
1190 physDev->mh->mtSize += rlen / 2;
1191 physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1192 return TRUE;
1196 /******************************************************************
1197 * MF_MetaParam0
1200 BOOL32 MF_MetaParam0(DC *dc, short func)
1202 char buffer[8];
1203 METARECORD *mr = (METARECORD *)&buffer;
1205 mr->rdSize = 3;
1206 mr->rdFunction = func;
1207 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1211 /******************************************************************
1212 * MF_MetaParam1
1214 BOOL32 MF_MetaParam1(DC *dc, short func, short param1)
1216 char buffer[8];
1217 METARECORD *mr = (METARECORD *)&buffer;
1219 mr->rdSize = 4;
1220 mr->rdFunction = func;
1221 *(mr->rdParm) = param1;
1222 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1226 /******************************************************************
1227 * MF_MetaParam2
1229 BOOL32 MF_MetaParam2(DC *dc, short func, short param1, short param2)
1231 char buffer[10];
1232 METARECORD *mr = (METARECORD *)&buffer;
1234 mr->rdSize = 5;
1235 mr->rdFunction = func;
1236 *(mr->rdParm) = param2;
1237 *(mr->rdParm + 1) = param1;
1238 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1242 /******************************************************************
1243 * MF_MetaParam4
1246 BOOL32 MF_MetaParam4(DC *dc, short func, short param1, short param2,
1247 short param3, short param4)
1249 char buffer[14];
1250 METARECORD *mr = (METARECORD *)&buffer;
1252 mr->rdSize = 7;
1253 mr->rdFunction = func;
1254 *(mr->rdParm) = param4;
1255 *(mr->rdParm + 1) = param3;
1256 *(mr->rdParm + 2) = param2;
1257 *(mr->rdParm + 3) = param1;
1258 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1262 /******************************************************************
1263 * MF_MetaParam6
1266 BOOL32 MF_MetaParam6(DC *dc, short func, short param1, short param2,
1267 short param3, short param4, short param5, short param6)
1269 char buffer[18];
1270 METARECORD *mr = (METARECORD *)&buffer;
1272 mr->rdSize = 9;
1273 mr->rdFunction = func;
1274 *(mr->rdParm) = param6;
1275 *(mr->rdParm + 1) = param5;
1276 *(mr->rdParm + 2) = param4;
1277 *(mr->rdParm + 3) = param3;
1278 *(mr->rdParm + 4) = param2;
1279 *(mr->rdParm + 5) = param1;
1280 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1284 /******************************************************************
1285 * MF_MetaParam8
1287 BOOL32 MF_MetaParam8(DC *dc, short func, short param1, short param2,
1288 short param3, short param4, short param5,
1289 short param6, short param7, short param8)
1291 char buffer[22];
1292 METARECORD *mr = (METARECORD *)&buffer;
1294 mr->rdSize = 11;
1295 mr->rdFunction = func;
1296 *(mr->rdParm) = param8;
1297 *(mr->rdParm + 1) = param7;
1298 *(mr->rdParm + 2) = param6;
1299 *(mr->rdParm + 3) = param5;
1300 *(mr->rdParm + 4) = param4;
1301 *(mr->rdParm + 5) = param3;
1302 *(mr->rdParm + 6) = param2;
1303 *(mr->rdParm + 7) = param1;
1304 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1308 /******************************************************************
1309 * MF_CreateBrushIndirect
1312 BOOL32 MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1314 int index;
1315 char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1316 METARECORD *mr = (METARECORD *)&buffer;
1318 mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1319 mr->rdFunction = META_CREATEBRUSHINDIRECT;
1320 memcpy(&(mr->rdParm), logbrush, sizeof(*logbrush));
1321 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1323 mr->rdSize = sizeof(METARECORD) / 2;
1324 mr->rdFunction = META_SELECTOBJECT;
1326 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1327 *(mr->rdParm) = index;
1328 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1332 /******************************************************************
1333 * MF_CreatePatternBrush
1336 BOOL32 MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1338 DWORD len, bmSize, biSize;
1339 HGLOBAL16 hmr;
1340 METARECORD *mr;
1341 BITMAPOBJ *bmp;
1342 BITMAPINFO *info;
1343 BITMAPINFOHEADER *infohdr;
1344 int index;
1345 char buffer[sizeof(METARECORD)];
1347 switch (logbrush->lbStyle)
1349 case BS_PATTERN:
1350 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1351 if (!bmp) return FALSE;
1352 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
1353 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1354 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1356 GDI_HEAP_UNLOCK((HGDIOBJ16)logbrush->lbHatch);
1357 return FALSE;
1359 mr = (METARECORD *)GlobalLock16(hmr);
1360 memset(mr, 0, len);
1361 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1362 mr->rdSize = len / 2;
1363 *(mr->rdParm) = logbrush->lbStyle;
1364 *(mr->rdParm + 1) = DIB_RGB_COLORS;
1365 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1366 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1367 infohdr->biWidth = bmp->bitmap.bmWidth;
1368 infohdr->biHeight = bmp->bitmap.bmHeight;
1369 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1370 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1371 memcpy(mr->rdParm + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1372 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1373 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1374 GDI_HEAP_UNLOCK(logbrush->lbHatch);
1375 break;
1377 case BS_DIBPATTERN:
1378 info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1379 if (info->bmiHeader.biCompression)
1380 bmSize = info->bmiHeader.biSizeImage;
1381 else
1382 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1383 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1384 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1385 len = sizeof(METARECORD) + biSize + bmSize + 2;
1386 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1387 return FALSE;
1388 mr = (METARECORD *)GlobalLock16(hmr);
1389 memset(mr, 0, len);
1390 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1391 mr->rdSize = len / 2;
1392 *(mr->rdParm) = logbrush->lbStyle;
1393 *(mr->rdParm + 1) = LOWORD(logbrush->lbColor);
1394 memcpy(mr->rdParm + 2, info, biSize + bmSize);
1395 break;
1396 default:
1397 return FALSE;
1399 if (!(MF_WriteRecord(dc, mr, len)))
1401 GlobalFree16(hmr);
1402 return FALSE;
1405 GlobalFree16(hmr);
1407 mr = (METARECORD *)&buffer;
1408 mr->rdSize = sizeof(METARECORD) / 2;
1409 mr->rdFunction = META_SELECTOBJECT;
1411 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1412 *(mr->rdParm) = index;
1413 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1417 /******************************************************************
1418 * MF_CreatePenIndirect
1421 BOOL32 MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1423 int index;
1424 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1425 METARECORD *mr = (METARECORD *)&buffer;
1427 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1428 mr->rdFunction = META_CREATEPENINDIRECT;
1429 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
1430 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1432 mr->rdSize = sizeof(METARECORD) / 2;
1433 mr->rdFunction = META_SELECTOBJECT;
1435 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1436 *(mr->rdParm) = index;
1437 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1441 /******************************************************************
1442 * MF_CreateFontIndirect
1445 BOOL32 MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1447 int index;
1448 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1449 METARECORD *mr = (METARECORD *)&buffer;
1451 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1452 mr->rdFunction = META_CREATEFONTINDIRECT;
1453 memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
1454 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1456 mr->rdSize = sizeof(METARECORD) / 2;
1457 mr->rdFunction = META_SELECTOBJECT;
1459 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1460 *(mr->rdParm) = index;
1461 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1465 /******************************************************************
1466 * MF_TextOut
1468 BOOL32 MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1470 BOOL32 ret;
1471 DWORD len;
1472 HGLOBAL16 hmr;
1473 METARECORD *mr;
1475 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1476 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1477 return FALSE;
1478 mr = (METARECORD *)GlobalLock16(hmr);
1479 memset(mr, 0, len);
1481 mr->rdSize = len / 2;
1482 mr->rdFunction = META_TEXTOUT;
1483 *(mr->rdParm) = count;
1484 memcpy(mr->rdParm + 1, str, count);
1485 *(mr->rdParm + ((count + 1) >> 1) + 1) = y;
1486 *(mr->rdParm + ((count + 1) >> 1) + 2) = x;
1487 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1488 GlobalFree16(hmr);
1489 return ret;
1492 /******************************************************************
1493 * MF_ExtTextOut
1495 BOOL32 MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1496 LPCSTR str, short count, const INT16 *lpDx)
1498 BOOL32 ret;
1499 DWORD len;
1500 HGLOBAL16 hmr;
1501 METARECORD *mr;
1503 if((!flags && rect) || (flags && !rect))
1504 WARN(metafile, "Inconsistent flags and rect\n");
1505 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1506 + sizeof(UINT16);
1507 if(rect)
1508 len += sizeof(RECT16);
1509 if (lpDx)
1510 len+=count*sizeof(INT16);
1511 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1512 return FALSE;
1513 mr = (METARECORD *)GlobalLock16(hmr);
1514 memset(mr, 0, len);
1516 mr->rdSize = len / 2;
1517 mr->rdFunction = META_EXTTEXTOUT;
1518 *(mr->rdParm) = y;
1519 *(mr->rdParm + 1) = x;
1520 *(mr->rdParm + 2) = count;
1521 *(mr->rdParm + 3) = flags;
1522 if (rect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
1523 memcpy(mr->rdParm + (rect ? 8 : 4), str, count);
1524 if (lpDx)
1525 memcpy(mr->rdParm + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1526 count*sizeof(INT16));
1527 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1528 GlobalFree16(hmr);
1529 return ret;
1532 /******************************************************************
1533 * MF_MetaPoly - implements Polygon and Polyline
1535 BOOL32 MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1537 BOOL32 ret;
1538 DWORD len;
1539 HGLOBAL16 hmr;
1540 METARECORD *mr;
1542 len = sizeof(METARECORD) + (count * 4);
1543 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1544 return FALSE;
1545 mr = (METARECORD *)GlobalLock16(hmr);
1546 memset(mr, 0, len);
1548 mr->rdSize = len / 2;
1549 mr->rdFunction = func;
1550 *(mr->rdParm) = count;
1551 memcpy(mr->rdParm + 1, pt, count * 4);
1552 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1553 GlobalFree16(hmr);
1554 return ret;
1558 /******************************************************************
1559 * MF_BitBlt
1561 BOOL32 MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1562 short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1564 BOOL32 ret;
1565 DWORD len;
1566 HGLOBAL16 hmr;
1567 METARECORD *mr;
1568 BITMAP16 BM;
1570 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1571 len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1572 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1573 return FALSE;
1574 mr = (METARECORD *)GlobalLock16(hmr);
1575 mr->rdFunction = META_BITBLT;
1576 *(mr->rdParm + 7) = BM.bmWidth;
1577 *(mr->rdParm + 8) = BM.bmHeight;
1578 *(mr->rdParm + 9) = BM.bmWidthBytes;
1579 *(mr->rdParm +10) = BM.bmPlanes;
1580 *(mr->rdParm +11) = BM.bmBitsPixel;
1581 TRACE(metafile,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1582 if (GetBitmapBits32(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1583 mr->rdParm +12))
1585 mr->rdSize = len / sizeof(INT16);
1586 *(mr->rdParm) = HIWORD(rop);
1587 *(mr->rdParm + 1) = ySrc;
1588 *(mr->rdParm + 2) = xSrc;
1589 *(mr->rdParm + 3) = height;
1590 *(mr->rdParm + 4) = width;
1591 *(mr->rdParm + 5) = yDest;
1592 *(mr->rdParm + 6) = xDest;
1593 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1595 else
1596 ret = FALSE;
1597 GlobalFree16(hmr);
1598 return ret;
1602 /**********************************************************************
1603 * MF_StretchBlt
1604 * this function contains TWO ways for procesing StretchBlt in metafiles,
1605 * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT
1606 * via #define STRETCH_VIA_DIB
1608 #define STRETCH_VIA_DIB
1609 #undef STRETCH_VIA_DIB
1610 BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1611 short heightDest, DC *dcSrc, short xSrc, short ySrc,
1612 short widthSrc, short heightSrc, DWORD rop)
1614 BOOL32 ret;
1615 DWORD len;
1616 HGLOBAL16 hmr;
1617 METARECORD *mr;
1618 BITMAP16 BM;
1619 #ifdef STRETCH_VIA_DIB
1620 LPBITMAPINFOHEADER lpBMI;
1621 WORD nBPP;
1622 #endif
1623 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1624 #ifdef STRETCH_VIA_DIB
1625 nBPP = BM.bmPlanes * BM.bmBitsPixel;
1626 len = sizeof(METARECORD) + 10 * sizeof(INT16)
1627 + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
1628 + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1629 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1630 return FALSE;
1631 mr = (METARECORD *)GlobalLock16(hmr);
1632 mr->rdFunction = META_DIBSTRETCHBLT;
1633 lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10);
1634 lpBMI->biSize = sizeof(BITMAPINFOHEADER);
1635 lpBMI->biWidth = BM.bmWidth;
1636 lpBMI->biHeight = BM.bmHeight;
1637 lpBMI->biPlanes = 1;
1638 lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */
1639 lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0;
1640 lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1641 lpBMI->biCompression = BI_RGB;
1642 lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1643 lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1644 lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */
1646 TRACE(metafile,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n",
1647 len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1648 if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT32)lpBMI->biHeight,
1649 (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1650 DIB_RGB_COLORS ),
1651 (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1652 #else
1653 len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1654 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1655 return FALSE;
1656 mr = (METARECORD *)GlobalLock16(hmr);
1657 mr->rdFunction = META_STRETCHBLT;
1658 *(mr->rdParm +10) = BM.bmWidth;
1659 *(mr->rdParm +11) = BM.bmHeight;
1660 *(mr->rdParm +12) = BM.bmWidthBytes;
1661 *(mr->rdParm +13) = BM.bmPlanes;
1662 *(mr->rdParm +14) = BM.bmBitsPixel;
1663 TRACE(metafile,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1664 if (GetBitmapBits32( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1665 mr->rdParm +15))
1666 #endif
1668 mr->rdSize = len / sizeof(INT16);
1669 *(mr->rdParm) = LOWORD(rop);
1670 *(mr->rdParm + 1) = HIWORD(rop);
1671 *(mr->rdParm + 2) = heightSrc;
1672 *(mr->rdParm + 3) = widthSrc;
1673 *(mr->rdParm + 4) = ySrc;
1674 *(mr->rdParm + 5) = xSrc;
1675 *(mr->rdParm + 6) = heightDest;
1676 *(mr->rdParm + 7) = widthDest;
1677 *(mr->rdParm + 8) = yDest;
1678 *(mr->rdParm + 9) = xDest;
1679 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1681 else
1682 ret = FALSE;
1683 GlobalFree16(hmr);
1684 return ret;
1688 /******************************************************************
1689 * MF_CreateRegion
1691 INT16 MF_CreateRegion(DC *dc, HRGN32 hrgn)
1693 DWORD len;
1694 METARECORD *mr;
1695 RGNDATA *rgndata;
1696 RECT32 *pCurRect, *pEndRect;
1697 WORD Bands = 0, MaxBands = 0;
1698 WORD *Param, *StartBand;
1699 BOOL32 ret;
1701 len = GetRegionData32( hrgn, 0, NULL );
1702 if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1703 WARN(metafile, "MF_CreateRegion: can't alloc rgndata buffer\n");
1704 return -1;
1706 GetRegionData32( hrgn, len, rgndata );
1708 /* Overestimate of length:
1709 * Assume every rect is a separate band -> 6 WORDs per rect
1711 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1712 if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1713 WARN(metafile, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1714 HeapFree( SystemHeap, 0, rgndata );
1715 return -1;
1718 memset(mr, 0, len);
1720 Param = mr->rdParm + 11;
1721 StartBand = NULL;
1723 pEndRect = (RECT32 *)rgndata->Buffer + rgndata->rdh.nCount;
1724 for(pCurRect = (RECT32 *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1726 if( StartBand && pCurRect->top == *(StartBand + 1) )
1728 *Param++ = pCurRect->left;
1729 *Param++ = pCurRect->right;
1731 else
1733 if(StartBand)
1735 *StartBand = Param - StartBand - 3;
1736 *Param++ = *StartBand;
1737 if(*StartBand > MaxBands)
1738 MaxBands = *StartBand;
1739 Bands++;
1741 StartBand = Param++;
1742 *Param++ = pCurRect->top;
1743 *Param++ = pCurRect->bottom;
1744 *Param++ = pCurRect->left;
1745 *Param++ = pCurRect->right;
1748 len = Param - (WORD *)mr;
1750 mr->rdParm[0] = 0;
1751 mr->rdParm[1] = 6;
1752 mr->rdParm[2] = 0x1234;
1753 mr->rdParm[3] = 0;
1754 mr->rdParm[4] = len * 2;
1755 mr->rdParm[5] = Bands;
1756 mr->rdParm[6] = MaxBands;
1757 mr->rdParm[7] = rgndata->rdh.rcBound.left;
1758 mr->rdParm[8] = rgndata->rdh.rcBound.top;
1759 mr->rdParm[9] = rgndata->rdh.rcBound.right;
1760 mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
1761 mr->rdFunction = META_CREATEREGION;
1762 mr->rdSize = len / 2;
1763 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );
1764 HeapFree( SystemHeap, 0, mr );
1765 HeapFree( SystemHeap, 0, rgndata );
1766 if(!ret)
1768 WARN(metafile, "MF_CreateRegion: MF_WriteRecord failed\n");
1769 return -1;
1771 return MF_AddHandleDC( dc );