Release 980927
[wine.git] / objects / metafile.c
blob03086600d523988c9088363a01bb4a29713ca8f7
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 "windows.h"
12 #include "gdi.h"
13 #include "bitmap.h"
14 #include "file.h"
15 #include "heap.h"
16 #include "metafile.h"
17 #include "metafiledrv.h"
18 #include "toolhelp.h"
19 #include "debug.h"
21 /******************************************************************
22 * MF_AddHandle
24 * Add a handle to an external handle table and return the index
27 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
29 int i;
31 for (i = 0; i < htlen; i++)
33 if (*(ht->objectHandle + i) == 0)
35 *(ht->objectHandle + i) = hobj;
36 return i;
39 return -1;
43 /******************************************************************
44 * MF_AddHandleDC
46 * Note: this function assumes that we never delete objects.
47 * If we do someday, we'll need to maintain a table to re-use deleted
48 * handles.
50 static int MF_AddHandleDC( DC *dc )
52 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
53 physDev->mh->mtNoObjects++;
54 return physDev->nextHandle++;
58 /******************************************************************
59 * GetMetaFile16 (GDI.124)
61 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
63 return GetMetaFile32A( lpFilename );
67 /******************************************************************
68 * GetMetaFile32A (GDI32.197)
70 * Read a metafile from a file. Returns handle to a disk-based metafile.
72 HMETAFILE32 WINAPI GetMetaFile32A(
73 LPCSTR lpFilename
74 /* pointer to string containing filename to read */
77 HMETAFILE16 hmf;
78 METAHEADER *mh;
79 HFILE32 hFile;
80 DWORD size;
82 TRACE(metafile,"%s\n", lpFilename);
84 if (!lpFilename)
85 return 0;
87 hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
88 mh = (METAHEADER *)GlobalLock16(hmf);
90 if (!mh)
92 GlobalFree16(hmf);
93 return 0;
96 if ((hFile = _lopen32(lpFilename, OF_READ)) == HFILE_ERROR32)
98 GlobalFree16(hmf);
99 return 0;
102 if (_lread32(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR32)
104 _lclose32( hFile );
105 GlobalFree16(hmf);
106 return 0;
109 size = mh->mtSize * 2; /* alloc memory for whole metafile */
110 GlobalUnlock16(hmf);
111 hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
112 mh = (METAHEADER *)GlobalLock16(hmf);
114 if (!mh)
116 _lclose32( hFile );
117 GlobalFree16(hmf);
118 return 0;
121 if (_lread32(hFile, (char*)mh + mh->mtHeaderSize * 2,
122 size - mh->mtHeaderSize * 2) == HFILE_ERROR32)
124 _lclose32( hFile );
125 GlobalFree16(hmf);
126 return 0;
129 _lclose32(hFile);
131 if (mh->mtType != 1)
133 GlobalFree16(hmf);
134 return 0;
137 GlobalUnlock16(hmf);
138 return hmf;
143 /******************************************************************
144 * GetMetaFile32W (GDI32.199)
146 HMETAFILE32 WINAPI GetMetaFile32W( LPCWSTR lpFilename )
148 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
149 HMETAFILE32 ret = GetMetaFile32A( p );
150 HeapFree( GetProcessHeap(), 0, p );
151 return ret;
155 /******************************************************************
156 * CopyMetaFile16 (GDI.151)
159 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename )
161 return CopyMetaFile32A( hSrcMetaFile, lpFilename );
165 /******************************************************************
166 * CopyMetaFile32A (GDI32.23)
168 * Copies the metafile corresponding to hSrcMetaFile to either
169 * a disk file, if a filename is given, or to a new memory based
170 * metafile, if lpFileName is NULL.
172 * RETURNS
174 * Handle to metafile copy on success, NULL on failure.
176 * BUGS
178 * Copying to disk returns NULL even if successful.
180 HMETAFILE32 WINAPI CopyMetaFile32A(
181 HMETAFILE32 hSrcMetaFile, /* handle of metafile to copy */
182 LPCSTR lpFilename /* filename if copying to a file */
184 HMETAFILE16 handle = 0;
185 METAHEADER *mh;
186 METAHEADER *mh2;
187 HFILE32 hFile;
189 TRACE(metafile,"(%08x,%s)\n", hSrcMetaFile, lpFilename);
191 mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
193 if (!mh)
194 return 0;
196 if (lpFilename) /* disk based metafile */
198 int i,j;
199 hFile = _lcreat32(lpFilename, 0);
200 j=mh->mtType;
201 mh->mtType=1; /* disk file version stores 1 here */
202 i=_lwrite32(hFile, (char *)mh, mh->mtSize * 2) ;
203 mh->mtType=j; /* restore old value [0 or 1] */
204 _lclose32(hFile);
205 if (i == -1)
206 return 0;
207 /* FIXME: return value */
209 else /* memory based metafile */
211 handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
212 mh2 = (METAHEADER *)GlobalLock16(handle);
213 memcpy(mh2,mh, mh->mtSize * 2);
214 GlobalUnlock16(handle);
217 GlobalUnlock16(hSrcMetaFile);
218 return handle;
222 /******************************************************************
223 * CopyMetaFile32W (GDI32.24)
225 HMETAFILE32 WINAPI CopyMetaFile32W( HMETAFILE32 hSrcMetaFile,
226 LPCWSTR lpFilename )
228 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
229 HMETAFILE32 ret = CopyMetaFile32A( hSrcMetaFile, p );
230 HeapFree( GetProcessHeap(), 0, p );
231 return ret;
235 /******************************************************************
236 * IsValidMetaFile (GDI.410)
238 * Attempts to check if a given metafile is correctly formatted.
239 * Currently, the only things verified are several properties of the
240 * header.
242 * RETURNS
243 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
245 * BUGS
246 * This is not exactly what windows does, see _Undocumented_Windows_
247 * for details.
250 BOOL16 WINAPI IsValidMetaFile(HMETAFILE16 hmf)
252 BOOL16 resu=FALSE;
253 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
254 if (mh) {
255 if (mh->mtType == 1 || mh->mtType == 0)
256 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
257 if (mh->mtVersion == MFVERSION)
258 resu=TRUE;
259 GlobalUnlock16(hmf);
261 TRACE(metafile,"IsValidMetaFile %x => %d\n",hmf,resu);
262 return resu;
266 /******************************************************************
267 * PlayMetaFile16 (GDI.123)
270 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
272 return PlayMetaFile32( hdc, hmf );
275 /******************************************************************
276 * PlayMetaFile32 (GDI32.265)
278 * Renders the metafile specified by hmf in the DC specified by
279 * hdc. Returns FALSE on failure, TRUE on success.
281 BOOL32 WINAPI PlayMetaFile32(
282 HDC32 hdc, /* handle of DC to render in */
283 HMETAFILE32 hmf /* handle of metafile to render */
286 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
287 METARECORD *mr;
288 HANDLETABLE16 *ht;
289 HGLOBAL16 hHT;
290 int offset = 0;
291 WORD i;
292 HPEN32 hPen;
293 HBRUSH32 hBrush;
294 HFONT32 hFont;
295 DC *dc;
297 TRACE(metafile,"(%04x %04x)\n",hdc,hmf);
298 if (!mh) return FALSE;
300 /* save the current pen, brush and font */
301 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
302 hPen = dc->w.hPen;
303 hBrush = dc->w.hBrush;
304 hFont = dc->w.hFont;
305 GDI_HEAP_UNLOCK(hdc);
306 /* create the handle table */
307 hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
308 sizeof(HANDLETABLE16) * mh->mtNoObjects);
309 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
312 /* loop through metafile playing records */
313 offset = mh->mtHeaderSize * 2;
314 while (offset < mh->mtSize * 2)
316 mr = (METARECORD *)((char *)mh + offset);
317 TRACE(metafile,"offset=%04x,size=%08lx\n",
318 offset, mr->rdSize);
319 if (!mr->rdSize) {
320 TRACE(metafile,"Entry got size 0 at offset %d, total mf length is %ld\n",
321 offset,mh->mtSize*2);
322 break; /* would loop endlessly otherwise */
324 offset += mr->rdSize * 2;
325 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
328 SelectObject32(hdc, hBrush);
329 SelectObject32(hdc, hPen);
330 SelectObject32(hdc, hFont);
332 /* free objects in handle table */
333 for(i = 0; i < mh->mtNoObjects; i++)
334 if(*(ht->objectHandle + i) != 0)
335 DeleteObject32(*(ht->objectHandle + i));
337 /* free handle table */
338 GlobalFree16(hHT);
340 return TRUE;
344 /******************************************************************
345 * EnumMetaFile16 (GDI.175)
347 * Loop through the metafile records in hmf, calling the user-specified
348 * function for each one, stopping when the user's function returns FALSE
349 * (which is considered to be failure)
350 * or when no records are left (which is considered to be success).
352 * RETURNS
353 * TRUE on success, FALSE on failure.
355 * HISTORY
356 * Niels de carpentier, april 1996
358 BOOL16 WINAPI EnumMetaFile16(
359 HDC16 hdc,
360 HMETAFILE16 hmf,
361 MFENUMPROC16 lpEnumFunc,
362 LPARAM lpData
365 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
366 METARECORD *mr;
367 HANDLETABLE16 *ht;
368 HGLOBAL16 hHT;
369 SEGPTR spht;
370 int offset = 0;
371 WORD i, seg;
372 HPEN32 hPen;
373 HBRUSH32 hBrush;
374 HFONT32 hFont;
375 DC *dc;
376 BOOL16 result = TRUE;
378 TRACE(metafile,"(%04x, %04x, %08lx, %08lx)\n",
379 hdc, hmf, (DWORD)lpEnumFunc, lpData);
381 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
382 hPen = dc->w.hPen;
383 hBrush = dc->w.hBrush;
384 hFont = dc->w.hFont;
385 GDI_HEAP_UNLOCK(hdc);
387 /* create the handle table */
389 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
390 sizeof(HANDLETABLE16) * mh->mtNoObjects);
391 spht = WIN16_GlobalLock16(hHT);
393 seg = GlobalHandleToSel(hmf);
394 offset = mh->mtHeaderSize * 2;
396 /* loop through metafile records */
398 while (offset < (mh->mtSize * 2))
400 mr = (METARECORD *)((char *)mh + offset);
401 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
402 (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
403 mh->mtNoObjects, (LONG)lpData ))
405 result = FALSE;
406 break;
410 offset += (mr->rdSize * 2);
413 SelectObject32(hdc, hBrush);
414 SelectObject32(hdc, hPen);
415 SelectObject32(hdc, hFont);
417 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
419 /* free objects in handle table */
420 for(i = 0; i < mh->mtNoObjects; i++)
421 if(*(ht->objectHandle + i) != 0)
422 DeleteObject32(*(ht->objectHandle + i));
424 /* free handle table */
425 GlobalFree16(hHT);
426 GlobalUnlock16(hmf);
427 return result;
430 BOOL32 WINAPI EnumMetaFile32(
431 HDC32 hdc,
432 HMETAFILE32 hmf,
433 MFENUMPROC32 lpEnumFunc,
434 LPARAM lpData
436 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
437 METARECORD *mr;
438 HANDLETABLE32 *ht;
439 BOOL32 result = TRUE;
440 int i, offset = 0;
441 DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
442 HPEN32 hPen;
443 HBRUSH32 hBrush;
444 HFONT32 hFont;
446 TRACE(metafile,"(%08x,%08x,%p,%p)\n",
447 hdc, hmf, lpEnumFunc, (void*)lpData);
448 if (!mh) return 0;
450 /* save the current pen, brush and font */
451 if (!dc) return 0;
452 hPen = dc->w.hPen;
453 hBrush = dc->w.hBrush;
454 hFont = dc->w.hFont;
455 GDI_HEAP_UNLOCK(hdc);
458 ht = (HANDLETABLE32 *) GlobalAlloc32(GPTR,
459 sizeof(HANDLETABLE32) * mh->mtNoObjects);
461 /* loop through metafile records */
462 offset = mh->mtHeaderSize * 2;
464 while (offset < (mh->mtSize * 2))
466 mr = (METARECORD *)((char *)mh + offset);
467 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
469 result = FALSE;
470 break;
473 offset += (mr->rdSize * 2);
476 /* restore pen, brush and font */
477 SelectObject32(hdc, hBrush);
478 SelectObject32(hdc, hPen);
479 SelectObject32(hdc, hFont);
481 /* free objects in handle table */
482 for(i = 0; i < mh->mtNoObjects; i++)
483 if(*(ht->objectHandle + i) != 0)
484 DeleteObject32(*(ht->objectHandle + i));
486 /* free handle table */
487 GlobalFree32((HGLOBAL32)ht);
488 GlobalUnlock16(hmf);
489 return result;
492 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn );
494 /******************************************************************
495 * PlayMetaFileRecord16 (GDI.176)
497 * Render a single metafile record specified by *mr in the DC hdc, while
498 * using the handle table *ht, of length nHandles,
499 * to store metafile objects.
501 * BUGS
502 * The following metafile records are unimplemented:
504 * FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
505 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
506 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
509 void WINAPI PlayMetaFileRecord16(
510 HDC16 hdc, /* DC to render metafile into */
511 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
512 METARECORD *mr, /* pointer to metafile record to render */
513 UINT16 nHandles /* size of handle table */
515 short s1;
516 HANDLE16 hndl;
517 char *ptr;
518 BITMAPINFOHEADER *infohdr;
520 TRACE(metafile,"(%04x %08lx %08lx %04x) function %04x\n",
521 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
523 switch (mr->rdFunction)
525 case META_EOF:
526 break;
528 case META_DELETEOBJECT:
529 DeleteObject32(*(ht->objectHandle + *(mr->rdParam)));
530 *(ht->objectHandle + *(mr->rdParam)) = 0;
531 break;
533 case META_SETBKCOLOR:
534 SetBkColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
535 break;
537 case META_SETBKMODE:
538 SetBkMode16(hdc, *(mr->rdParam));
539 break;
541 case META_SETMAPMODE:
542 SetMapMode16(hdc, *(mr->rdParam));
543 break;
545 case META_SETROP2:
546 SetROP216(hdc, *(mr->rdParam));
547 break;
549 case META_SETRELABS:
550 SetRelAbs16(hdc, *(mr->rdParam));
551 break;
553 case META_SETPOLYFILLMODE:
554 SetPolyFillMode16(hdc, *(mr->rdParam));
555 break;
557 case META_SETSTRETCHBLTMODE:
558 SetStretchBltMode16(hdc, *(mr->rdParam));
559 break;
561 case META_SETTEXTCOLOR:
562 SetTextColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
563 break;
565 case META_SETWINDOWORG:
566 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
567 break;
569 case META_SETWINDOWEXT:
570 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
571 break;
573 case META_SETVIEWPORTORG:
574 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
575 break;
577 case META_SETVIEWPORTEXT:
578 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
579 break;
581 case META_OFFSETWINDOWORG:
582 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
583 break;
585 case META_SCALEWINDOWEXT:
586 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
587 *(mr->rdParam + 1), *(mr->rdParam));
588 break;
590 case META_OFFSETVIEWPORTORG:
591 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
592 break;
594 case META_SCALEVIEWPORTEXT:
595 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
596 *(mr->rdParam + 1), *(mr->rdParam));
597 break;
599 case META_LINETO:
600 LineTo32(hdc, (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
601 break;
603 case META_MOVETO:
604 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
605 break;
607 case META_EXCLUDECLIPRECT:
608 ExcludeClipRect16( hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
609 *(mr->rdParam + 1), *(mr->rdParam) );
610 break;
612 case META_INTERSECTCLIPRECT:
613 IntersectClipRect16( hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
614 *(mr->rdParam + 1), *(mr->rdParam) );
615 break;
617 case META_ARC:
618 Arc32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
619 (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
620 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
621 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
622 break;
624 case META_ELLIPSE:
625 Ellipse32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
626 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
627 break;
629 case META_FLOODFILL:
630 FloodFill32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
631 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
632 break;
634 case META_PIE:
635 Pie32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
636 (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
637 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
638 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
639 break;
641 case META_RECTANGLE:
642 Rectangle32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
643 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
644 break;
646 case META_ROUNDRECT:
647 RoundRect32(hdc, (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
648 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
649 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
650 break;
652 case META_PATBLT:
653 PatBlt16(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
654 *(mr->rdParam + 3), *(mr->rdParam + 2),
655 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
656 break;
658 case META_SAVEDC:
659 SaveDC32(hdc);
660 break;
662 case META_SETPIXEL:
663 SetPixel32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
664 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
665 break;
667 case META_OFFSETCLIPRGN:
668 OffsetClipRgn16( hdc, *(mr->rdParam + 1), *(mr->rdParam) );
669 break;
671 case META_TEXTOUT:
672 s1 = *(mr->rdParam);
673 TextOut16(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
674 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
675 (char *)(mr->rdParam + 1), s1);
676 break;
678 case META_POLYGON:
679 Polygon16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
680 break;
682 case META_POLYPOLYGON:
683 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParam + *(mr->rdParam) + 1),
684 (LPINT16)(mr->rdParam + 1), *(mr->rdParam));
685 break;
687 case META_POLYLINE:
688 Polyline16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
689 break;
691 case META_RESTOREDC:
692 RestoreDC32(hdc, (INT16)*(mr->rdParam));
693 break;
695 case META_SELECTOBJECT:
696 SelectObject32(hdc, *(ht->objectHandle + *(mr->rdParam)));
697 break;
699 case META_CHORD:
700 Chord32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
701 (INT16)*(mr->rdParam+5), (INT16)*(mr->rdParam + 4),
702 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
703 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
704 break;
706 case META_CREATEPATTERNBRUSH:
707 switch (*(mr->rdParam))
709 case BS_PATTERN:
710 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
711 MF_AddHandle(ht, nHandles,
712 CreatePatternBrush32(CreateBitmap32(infohdr->biWidth,
713 infohdr->biHeight,
714 infohdr->biPlanes,
715 infohdr->biBitCount,
716 (LPSTR)(mr->rdParam +
717 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
718 break;
720 case BS_DIBPATTERN:
721 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
722 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
723 ptr = GlobalLock16(hndl);
724 memcpy(ptr, mr->rdParam + 2, s1);
725 GlobalUnlock16(hndl);
726 MF_AddHandle(ht, nHandles,
727 CreateDIBPatternBrush32(hndl, *(mr->rdParam + 1)));
728 GlobalFree16(hndl);
730 break;
732 case META_CREATEPENINDIRECT:
733 MF_AddHandle(ht, nHandles,
734 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParam))));
735 break;
737 case META_CREATEFONTINDIRECT:
738 MF_AddHandle(ht, nHandles,
739 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParam))));
740 break;
742 case META_CREATEBRUSHINDIRECT:
743 MF_AddHandle(ht, nHandles,
744 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParam))));
745 break;
747 /* W. Magro: Some new metafile operations. Not all debugged. */
748 case META_CREATEPALETTE:
749 MF_AddHandle(ht, nHandles,
750 CreatePalette16((LPLOGPALETTE)mr->rdParam));
751 break;
753 case META_SETTEXTALIGN:
754 SetTextAlign16(hdc, *(mr->rdParam));
755 break;
757 case META_SELECTPALETTE:
758 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
759 break;
761 case META_SETMAPPERFLAGS:
762 SetMapperFlags16(hdc, *(mr->rdParam));
763 break;
765 case META_REALIZEPALETTE:
766 RealizePalette16(hdc);
767 break;
769 case META_ESCAPE:
770 FIXME(metafile, "META_ESCAPE unimplemented.\n");
771 break;
773 /* --- Begin of fixed or new metafile operations. July 1996 ----*/
774 case META_EXTTEXTOUT:
776 LPINT16 dxx;
777 LPSTR sot;
778 DWORD len;
780 s1 = mr->rdParam[2]; /* String length */
781 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
782 + sizeof(UINT16) + (mr->rdParam[3] ? sizeof(RECT16) : 0); /* rec len without dx array */
784 sot= (LPSTR)&mr->rdParam[4]; /* start_of_text */
785 if (mr->rdParam[3])
786 sot+=sizeof(RECT16); /* there is a rectangle, so add offset */
788 if (mr->rdSize == len / 2)
789 dxx = NULL; /* determine if array present */
790 else
791 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
792 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
793 else
795 TRACE(metafile,"%s len: %ld\n",
796 sot,mr->rdSize);
797 WARN(metafile,
798 "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
799 len,s1,mr->rdSize,mr->rdParam[3]);
800 dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
802 ExtTextOut16( hdc, mr->rdParam[1], /* X position */
803 mr->rdParam[0], /* Y position */
804 mr->rdParam[3], /* options */
805 mr->rdParam[3] ? (LPRECT16) &mr->rdParam[4]:NULL, /* rectangle */
806 sot, /* string */
807 s1, dxx); /* length, dx array */
808 if (dxx)
809 TRACE(metafile,"%s len: %ld dx0: %d\n",
810 sot,mr->rdSize,dxx[0]);
812 break;
814 case META_STRETCHDIB:
816 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]);
817 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
818 StretchDIBits16(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
819 mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
820 mr->rdParam[4],mr->rdParam[3],bits,info,
821 mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1]));
823 break;
825 case META_DIBSTRETCHBLT:
827 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]);
828 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
829 StretchDIBits16(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
830 mr->rdParam[6],mr->rdParam[5],mr->rdParam[4],
831 mr->rdParam[3],mr->rdParam[2],bits,info,
832 DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
834 break;
836 case META_STRETCHBLT:
838 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
839 HBITMAP32 hbitmap=CreateBitmap32(mr->rdParam[10], /*Width */
840 mr->rdParam[11], /*Height*/
841 mr->rdParam[13], /*Planes*/
842 mr->rdParam[14], /*BitsPixel*/
843 (LPSTR)&mr->rdParam[15]); /*bits*/
844 SelectObject32(hdcSrc,hbitmap);
845 StretchBlt16(hdc,mr->rdParam[9],mr->rdParam[8],
846 mr->rdParam[7],mr->rdParam[6],
847 hdcSrc,mr->rdParam[5],mr->rdParam[4],
848 mr->rdParam[3],mr->rdParam[2],
849 MAKELONG(mr->rdParam[0],mr->rdParam[1]));
850 DeleteDC32(hdcSrc);
852 break;
854 case META_BITBLT: /* <-- not yet debugged */
856 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
857 HBITMAP32 hbitmap=CreateBitmap32(mr->rdParam[7]/*Width */,
858 mr->rdParam[8]/*Height*/,
859 mr->rdParam[10]/*Planes*/,
860 mr->rdParam[11]/*BitsPixel*/,
861 (LPSTR)&mr->rdParam[12]/*bits*/);
862 SelectObject32(hdcSrc,hbitmap);
863 BitBlt32(hdc,(INT16)mr->rdParam[6],(INT16)mr->rdParam[5],
864 (INT16)mr->rdParam[4],(INT16)mr->rdParam[3],
865 hdcSrc, (INT16)mr->rdParam[2],(INT16)mr->rdParam[1],
866 MAKELONG(0,mr->rdParam[0]));
867 DeleteDC32(hdcSrc);
869 break;
871 /* --- Begin of new metafile operations. April, 1997 (ak) ----*/
872 case META_CREATEREGION:
874 HRGN32 hrgn = CreateRectRgn32(0,0,0,0);
876 MF_Meta_CreateRegion(mr, hrgn);
877 MF_AddHandle(ht, nHandles, hrgn);
879 break;
881 case META_FILLREGION:
882 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)),
883 *(ht->objectHandle + *(mr->rdParam+1)));
884 break;
886 case META_INVERTREGION:
887 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)));
888 break;
890 case META_PAINTREGION:
891 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)));
892 break;
894 case META_SELECTCLIPREGION:
895 SelectClipRgn32(hdc, *(ht->objectHandle + *(mr->rdParam)));
896 break;
898 case META_DIBCREATEPATTERNBRUSH:
899 /* *(mr->rdParam) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
900 TRACE(metafile,"%d\n",*(mr->rdParam));
901 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
902 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
903 ptr = GlobalLock16(hndl);
904 memcpy(ptr, mr->rdParam + 2, s1);
905 GlobalUnlock16(hndl);
906 MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParam + 1)));
907 GlobalFree16(hndl);
908 break;
910 case META_DIBBITBLT:
912 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[8]);
913 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[0] );
914 StretchDIBits16(hdc,mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
915 mr->rdParam[4],mr->rdParam[3],mr->rdParam[2],
916 mr->rdParam[5],mr->rdParam[4],bits,info,
917 DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
919 break;
921 case META_SETTEXTCHAREXTRA:
922 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParam));
923 break;
925 case META_SETTEXTJUSTIFICATION:
926 SetTextJustification32(hdc, *(mr->rdParam + 1), *(mr->rdParam));
927 break;
929 #define META_UNIMP(x) case x: FIXME(metafile, "PlayMetaFileRecord:record type "#x" not implemented.\n");break;
930 META_UNIMP(META_FRAMEREGION)
931 META_UNIMP(META_DRAWTEXT)
932 META_UNIMP(META_SETDIBTODEV)
933 META_UNIMP(META_ANIMATEPALETTE)
934 META_UNIMP(META_SETPALENTRIES)
935 META_UNIMP(META_RESIZEPALETTE)
936 META_UNIMP(META_EXTFLOODFILL)
937 META_UNIMP(META_RESETDC)
938 META_UNIMP(META_STARTDOC)
939 META_UNIMP(META_STARTPAGE)
940 META_UNIMP(META_ENDPAGE)
941 META_UNIMP(META_ABORTDOC)
942 META_UNIMP(META_ENDDOC)
943 META_UNIMP(META_CREATEBRUSH)
944 META_UNIMP(META_CREATEBITMAPINDIRECT)
945 META_UNIMP(META_CREATEBITMAP)
946 #undef META_UNIMP
948 default:
949 WARN(metafile, "PlayMetaFileRecord: Unknown record type %x\n",
950 mr->rdFunction);
955 BOOL32 WINAPI PlayMetaFileRecord32(
956 HDC32 hdc,
957 HANDLETABLE32 *handletable,
958 METARECORD *metarecord,
959 UINT32 handles
962 HANDLETABLE16 * ht = (void *)GlobalAlloc32(GPTR,
963 handles*sizeof(HANDLETABLE16));
964 int i = 0;
965 TRACE(metafile, "(%08x,%p,%p,%d)\n", hdc, handletable, metarecord, handles);
966 for (i=0; i<handles; i++)
967 ht->objectHandle[i] = handletable->objectHandle[i];
968 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
969 for (i=0; i<handles; i++)
970 handletable->objectHandle[i] = ht->objectHandle[i];
971 GlobalFree32((HGLOBAL32)ht);
972 return TRUE;
975 /******************************************************************
976 * GetMetaFileBits (GDI.159)
978 * Trade in a metafile object handle for a handle to the metafile memory.
982 HGLOBAL16 WINAPI GetMetaFileBits(
983 HMETAFILE16 hmf /* metafile handle */
986 TRACE(metafile,"hMem out: %04x\n", hmf);
987 return hmf;
990 /******************************************************************
991 * SetMetaFileBits (GDI.160)
993 * Trade in a metafile memory handle for a handle to a metafile object.
994 * The memory region should hold a proper metafile, otherwise
995 * problems will occur when it is used. Validity of the memory is not
996 * checked. The function is essentially just the identity function.
998 HMETAFILE16 WINAPI SetMetaFileBits(
999 HGLOBAL16 hMem
1000 /* handle to a memory region holding a metafile */
1003 TRACE(metafile,"hmf out: %04x\n", hMem);
1005 return hMem;
1008 /******************************************************************
1009 * SetMetaFileBitsBetter (GDI.196)
1011 * Trade in a metafile memory handle for a handle to a metafile object,
1012 * making a cursory check (using IsValidMetaFile()) that the memory
1013 * handle points to a valid metafile.
1015 * RETURNS
1016 * Handle to a metafile on success, NULL on failure..
1018 HMETAFILE16 WINAPI SetMetaFileBitsBetter( HMETAFILE16 hMeta )
1020 if( IsValidMetaFile( hMeta ) )
1021 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1022 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1023 return (HMETAFILE16)0;
1026 /******************************************************************
1027 * SetMetaFileBitsEx (GDI32.323)
1029 * Create a metafile from raw data. No checking of the data is performed.
1030 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1032 HMETAFILE32 WINAPI SetMetaFileBitsEx(
1033 UINT32 size, /* size of metafile, in bytes */
1034 const BYTE *lpData /* pointer to metafile data */
1037 HMETAFILE32 hmf = GlobalAlloc16(GHND, size);
1038 BYTE *p = GlobalLock16(hmf) ;
1039 TRACE(metafile, "(%d,%p) returning %08x\n", size, lpData, hmf);
1040 if (!hmf || !p) return 0;
1041 memcpy(p, lpData, size);
1042 GlobalUnlock16(hmf);
1043 return hmf;
1046 /*****************************************************************
1047 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1049 * Copies the data from metafile _hmf_ into the buffer _buf_.
1050 * If _buf_ is zero, returns size of buffer required. Otherwise,
1051 * returns number of bytes copied.
1053 UINT32 WINAPI GetMetaFileBitsEx(
1054 HMETAFILE32 hmf, /* metafile */
1055 UINT32 nSize, /* size of buf */
1056 LPVOID buf /* buffer to receive raw metafile data */
1058 METAHEADER *h = GlobalLock16(hmf);
1059 TRACE(metafile, "(%08x,%d,%p)\n", hmf, nSize, buf);
1060 if (!h) return 0; /* FIXME: error code */
1061 if (!buf) {
1062 GlobalUnlock16(hmf);
1063 TRACE(metafile,"returning size %ld\n", h->mtSize);
1064 return h->mtSize;
1066 memmove(buf, h, MIN(nSize, h->mtSize));
1067 GlobalUnlock16(hmf);
1068 return MIN(nSize, h->mtSize);
1072 /******************************************************************
1073 * MF_Meta_CreateRegion
1075 * Handles META_CREATEREGION for PlayMetaFileRecord().
1079 * The layout of the record looks something like this:
1081 * rdParam meaning
1082 * 0 Always 0?
1083 * 1 Always 6?
1084 * 2 Looks like a handle? - not constant
1085 * 3 0 or 1 ??
1086 * 4 Total number of bytes
1087 * 5 No. of seperate bands = n [see below]
1088 * 6 Largest number of x co-ords in a band
1089 * 7-10 Bounding box x1 y1 x2 y2
1090 * 11-... n bands
1092 * Regions are divided into bands that are uniform in the
1093 * y-direction. Each band consists of pairs of on/off x-coords and is
1094 * written as
1095 * m y0 y1 x1 x2 x3 ... xm m
1096 * into successive rdParam[]s.
1098 * This is probably just a dump of the internal RGNOBJ?
1100 * HDMD - 18/12/97
1104 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn )
1106 WORD band, pair;
1107 WORD *start, *end;
1108 INT16 y0, y1;
1109 HRGN32 hrgn2 = CreateRectRgn32( 0, 0, 0, 0 );
1111 for(band = 0, start = &(mr->rdParam[11]); band < mr->rdParam[5];
1112 band++, start = end + 1) {
1113 if(*start / 2 != (*start + 1) / 2) {
1114 WARN(metafile, "Delimiter not even.\n");
1115 DeleteObject32( hrgn2 );
1116 return FALSE;
1119 end = start + *start + 3;
1120 if(end > (WORD *)mr + mr->rdSize) {
1121 WARN(metafile, "End points outside record.\n");
1122 DeleteObject32( hrgn2 );
1123 return FALSE;
1126 if(*start != *end) {
1127 WARN(metafile, "Mismatched delimiters.\n");
1128 DeleteObject32( hrgn2 );
1129 return FALSE;
1132 y0 = *(INT16 *)(start + 1);
1133 y1 = *(INT16 *)(start + 2);
1134 for(pair = 0; pair < *start / 2; pair++) {
1135 SetRectRgn32( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1136 *(INT16 *)(start + 4 + 2*pair), y1 );
1137 CombineRgn32(hrgn, hrgn, hrgn2, RGN_OR);
1140 DeleteObject32( hrgn2 );
1141 return TRUE;
1145 /******************************************************************
1146 * MF_WriteRecord
1148 * Warning: this function can change the metafile handle.
1151 static BOOL32 MF_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
1153 DWORD len;
1154 METAHEADER *mh;
1155 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1157 switch(physDev->mh->mtType)
1159 case METAFILE_MEMORY:
1160 len = physDev->mh->mtSize * 2 + rlen;
1161 mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1162 if (!mh) return FALSE;
1163 physDev->mh = mh;
1164 memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1165 break;
1166 case METAFILE_DISK:
1167 TRACE(metafile,"Writing record to disk\n");
1168 if (_lwrite32(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1169 return FALSE;
1170 break;
1171 default:
1172 ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
1173 return FALSE;
1176 physDev->mh->mtSize += rlen / 2;
1177 physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1178 return TRUE;
1182 /******************************************************************
1183 * MF_MetaParam0
1186 BOOL32 MF_MetaParam0(DC *dc, short func)
1188 char buffer[8];
1189 METARECORD *mr = (METARECORD *)&buffer;
1191 mr->rdSize = 3;
1192 mr->rdFunction = func;
1193 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1197 /******************************************************************
1198 * MF_MetaParam1
1200 BOOL32 MF_MetaParam1(DC *dc, short func, short param1)
1202 char buffer[8];
1203 METARECORD *mr = (METARECORD *)&buffer;
1205 mr->rdSize = 4;
1206 mr->rdFunction = func;
1207 *(mr->rdParam) = param1;
1208 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1212 /******************************************************************
1213 * MF_MetaParam2
1215 BOOL32 MF_MetaParam2(DC *dc, short func, short param1, short param2)
1217 char buffer[10];
1218 METARECORD *mr = (METARECORD *)&buffer;
1220 mr->rdSize = 5;
1221 mr->rdFunction = func;
1222 *(mr->rdParam) = param2;
1223 *(mr->rdParam + 1) = param1;
1224 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1228 /******************************************************************
1229 * MF_MetaParam4
1232 BOOL32 MF_MetaParam4(DC *dc, short func, short param1, short param2,
1233 short param3, short param4)
1235 char buffer[14];
1236 METARECORD *mr = (METARECORD *)&buffer;
1238 mr->rdSize = 7;
1239 mr->rdFunction = func;
1240 *(mr->rdParam) = param4;
1241 *(mr->rdParam + 1) = param3;
1242 *(mr->rdParam + 2) = param2;
1243 *(mr->rdParam + 3) = param1;
1244 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1248 /******************************************************************
1249 * MF_MetaParam6
1252 BOOL32 MF_MetaParam6(DC *dc, short func, short param1, short param2,
1253 short param3, short param4, short param5, short param6)
1255 char buffer[18];
1256 METARECORD *mr = (METARECORD *)&buffer;
1258 mr->rdSize = 9;
1259 mr->rdFunction = func;
1260 *(mr->rdParam) = param6;
1261 *(mr->rdParam + 1) = param5;
1262 *(mr->rdParam + 2) = param4;
1263 *(mr->rdParam + 3) = param3;
1264 *(mr->rdParam + 4) = param2;
1265 *(mr->rdParam + 5) = param1;
1266 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1270 /******************************************************************
1271 * MF_MetaParam8
1273 BOOL32 MF_MetaParam8(DC *dc, short func, short param1, short param2,
1274 short param3, short param4, short param5,
1275 short param6, short param7, short param8)
1277 char buffer[22];
1278 METARECORD *mr = (METARECORD *)&buffer;
1280 mr->rdSize = 11;
1281 mr->rdFunction = func;
1282 *(mr->rdParam) = param8;
1283 *(mr->rdParam + 1) = param7;
1284 *(mr->rdParam + 2) = param6;
1285 *(mr->rdParam + 3) = param5;
1286 *(mr->rdParam + 4) = param4;
1287 *(mr->rdParam + 5) = param3;
1288 *(mr->rdParam + 6) = param2;
1289 *(mr->rdParam + 7) = param1;
1290 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1294 /******************************************************************
1295 * MF_CreateBrushIndirect
1298 BOOL32 MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1300 int index;
1301 char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1302 METARECORD *mr = (METARECORD *)&buffer;
1304 mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1305 mr->rdFunction = META_CREATEBRUSHINDIRECT;
1306 memcpy(&(mr->rdParam), logbrush, sizeof(*logbrush));
1307 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1309 mr->rdSize = sizeof(METARECORD) / 2;
1310 mr->rdFunction = META_SELECTOBJECT;
1312 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1313 *(mr->rdParam) = index;
1314 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1318 /******************************************************************
1319 * MF_CreatePatternBrush
1322 BOOL32 MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1324 DWORD len, bmSize, biSize;
1325 HGLOBAL16 hmr;
1326 METARECORD *mr;
1327 BITMAPOBJ *bmp;
1328 BITMAPINFO *info;
1329 BITMAPINFOHEADER *infohdr;
1330 int index;
1331 char buffer[sizeof(METARECORD)];
1333 switch (logbrush->lbStyle)
1335 case BS_PATTERN:
1336 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1337 if (!bmp) return FALSE;
1338 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
1339 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1340 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1342 GDI_HEAP_UNLOCK((HGDIOBJ16)logbrush->lbHatch);
1343 return FALSE;
1345 mr = (METARECORD *)GlobalLock16(hmr);
1346 memset(mr, 0, len);
1347 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1348 mr->rdSize = len / 2;
1349 *(mr->rdParam) = logbrush->lbStyle;
1350 *(mr->rdParam + 1) = DIB_RGB_COLORS;
1351 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
1352 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1353 infohdr->biWidth = bmp->bitmap.bmWidth;
1354 infohdr->biHeight = bmp->bitmap.bmHeight;
1355 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1356 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1357 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1358 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1359 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1360 GDI_HEAP_UNLOCK(logbrush->lbHatch);
1361 break;
1363 case BS_DIBPATTERN:
1364 info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1365 if (info->bmiHeader.biCompression)
1366 bmSize = info->bmiHeader.biSizeImage;
1367 else
1368 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1369 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1370 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1371 len = sizeof(METARECORD) + biSize + bmSize + 2;
1372 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1373 return FALSE;
1374 mr = (METARECORD *)GlobalLock16(hmr);
1375 memset(mr, 0, len);
1376 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1377 mr->rdSize = len / 2;
1378 *(mr->rdParam) = logbrush->lbStyle;
1379 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
1380 memcpy(mr->rdParam + 2, info, biSize + bmSize);
1381 break;
1382 default:
1383 return FALSE;
1385 if (!(MF_WriteRecord(dc, mr, len)))
1387 GlobalFree16(hmr);
1388 return FALSE;
1391 GlobalFree16(hmr);
1393 mr = (METARECORD *)&buffer;
1394 mr->rdSize = sizeof(METARECORD) / 2;
1395 mr->rdFunction = META_SELECTOBJECT;
1397 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1398 *(mr->rdParam) = index;
1399 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1403 /******************************************************************
1404 * MF_CreatePenIndirect
1407 BOOL32 MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1409 int index;
1410 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1411 METARECORD *mr = (METARECORD *)&buffer;
1413 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1414 mr->rdFunction = META_CREATEPENINDIRECT;
1415 memcpy(&(mr->rdParam), logpen, sizeof(*logpen));
1416 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1418 mr->rdSize = sizeof(METARECORD) / 2;
1419 mr->rdFunction = META_SELECTOBJECT;
1421 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1422 *(mr->rdParam) = index;
1423 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1427 /******************************************************************
1428 * MF_CreateFontIndirect
1431 BOOL32 MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1433 int index;
1434 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1435 METARECORD *mr = (METARECORD *)&buffer;
1437 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1438 mr->rdFunction = META_CREATEFONTINDIRECT;
1439 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT16));
1440 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1442 mr->rdSize = sizeof(METARECORD) / 2;
1443 mr->rdFunction = META_SELECTOBJECT;
1445 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1446 *(mr->rdParam) = index;
1447 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1451 /******************************************************************
1452 * MF_TextOut
1454 BOOL32 MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1456 BOOL32 ret;
1457 DWORD len;
1458 HGLOBAL16 hmr;
1459 METARECORD *mr;
1461 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1462 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1463 return FALSE;
1464 mr = (METARECORD *)GlobalLock16(hmr);
1465 memset(mr, 0, len);
1467 mr->rdSize = len / 2;
1468 mr->rdFunction = META_TEXTOUT;
1469 *(mr->rdParam) = count;
1470 memcpy(mr->rdParam + 1, str, count);
1471 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1472 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1473 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1474 GlobalFree16(hmr);
1475 return ret;
1478 /******************************************************************
1479 * MF_ExtTextOut
1481 BOOL32 MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1482 LPCSTR str, short count, const INT16 *lpDx)
1484 BOOL32 ret;
1485 DWORD len;
1486 HGLOBAL16 hmr;
1487 METARECORD *mr;
1489 if((!flags && rect) || (flags && !rect))
1490 WARN(metafile, "Inconsistent flags and rect\n");
1491 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1492 + sizeof(UINT16);
1493 if(rect)
1494 len += sizeof(RECT16);
1495 if (lpDx)
1496 len+=count*sizeof(INT16);
1497 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1498 return FALSE;
1499 mr = (METARECORD *)GlobalLock16(hmr);
1500 memset(mr, 0, len);
1502 mr->rdSize = len / 2;
1503 mr->rdFunction = META_EXTTEXTOUT;
1504 *(mr->rdParam) = y;
1505 *(mr->rdParam + 1) = x;
1506 *(mr->rdParam + 2) = count;
1507 *(mr->rdParam + 3) = flags;
1508 if (rect) memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
1509 memcpy(mr->rdParam + (rect ? 8 : 4), str, count);
1510 if (lpDx)
1511 memcpy(mr->rdParam + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1512 count*sizeof(INT16));
1513 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1514 GlobalFree16(hmr);
1515 return ret;
1518 /******************************************************************
1519 * MF_MetaPoly - implements Polygon and Polyline
1521 BOOL32 MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1523 BOOL32 ret;
1524 DWORD len;
1525 HGLOBAL16 hmr;
1526 METARECORD *mr;
1528 len = sizeof(METARECORD) + (count * 4);
1529 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1530 return FALSE;
1531 mr = (METARECORD *)GlobalLock16(hmr);
1532 memset(mr, 0, len);
1534 mr->rdSize = len / 2;
1535 mr->rdFunction = func;
1536 *(mr->rdParam) = count;
1537 memcpy(mr->rdParam + 1, pt, count * 4);
1538 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1539 GlobalFree16(hmr);
1540 return ret;
1544 /******************************************************************
1545 * MF_BitBlt
1547 BOOL32 MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1548 short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1550 BOOL32 ret;
1551 DWORD len;
1552 HGLOBAL16 hmr;
1553 METARECORD *mr;
1554 BITMAP16 BM;
1556 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1557 len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1558 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1559 return FALSE;
1560 mr = (METARECORD *)GlobalLock16(hmr);
1561 mr->rdFunction = META_BITBLT;
1562 *(mr->rdParam + 7) = BM.bmWidth;
1563 *(mr->rdParam + 8) = BM.bmHeight;
1564 *(mr->rdParam + 9) = BM.bmWidthBytes;
1565 *(mr->rdParam +10) = BM.bmPlanes;
1566 *(mr->rdParam +11) = BM.bmBitsPixel;
1567 TRACE(metafile,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1568 if (GetBitmapBits32(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1569 mr->rdParam +12))
1571 mr->rdSize = len / sizeof(INT16);
1572 *(mr->rdParam) = HIWORD(rop);
1573 *(mr->rdParam + 1) = ySrc;
1574 *(mr->rdParam + 2) = xSrc;
1575 *(mr->rdParam + 3) = height;
1576 *(mr->rdParam + 4) = width;
1577 *(mr->rdParam + 5) = yDest;
1578 *(mr->rdParam + 6) = xDest;
1579 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1581 else
1582 ret = FALSE;
1583 GlobalFree16(hmr);
1584 return ret;
1588 /**********************************************************************
1589 * MF_StretchBlt
1590 * this function contains TWO ways for procesing StretchBlt in metafiles,
1591 * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT
1592 * via #define STRETCH_VIA_DIB
1594 #define STRETCH_VIA_DIB
1595 #undef STRETCH_VIA_DIB
1596 BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1597 short heightDest, DC *dcSrc, short xSrc, short ySrc,
1598 short widthSrc, short heightSrc, DWORD rop)
1600 BOOL32 ret;
1601 DWORD len;
1602 HGLOBAL16 hmr;
1603 METARECORD *mr;
1604 BITMAP16 BM;
1605 #ifdef STRETCH_VIA_DIB
1606 LPBITMAPINFOHEADER lpBMI;
1607 WORD nBPP;
1608 #endif
1609 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1610 #ifdef STRETCH_VIA_DIB
1611 nBPP = BM.bmPlanes * BM.bmBitsPixel;
1612 len = sizeof(METARECORD) + 10 * sizeof(INT16)
1613 + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
1614 + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1615 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1616 return FALSE;
1617 mr = (METARECORD *)GlobalLock16(hmr);
1618 mr->rdFunction = META_DIBSTRETCHBLT;
1619 lpBMI=(LPBITMAPINFOHEADER)(mr->rdParam+10);
1620 lpBMI->biSize = sizeof(BITMAPINFOHEADER);
1621 lpBMI->biWidth = BM.bmWidth;
1622 lpBMI->biHeight = BM.bmHeight;
1623 lpBMI->biPlanes = 1;
1624 lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */
1625 lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0;
1626 lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1627 lpBMI->biCompression = BI_RGB;
1628 lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1629 lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1630 lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */
1632 TRACE(metafile,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n",
1633 len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1634 if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT32)lpBMI->biHeight,
1635 (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1636 DIB_RGB_COLORS ),
1637 (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1638 #else
1639 len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1640 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1641 return FALSE;
1642 mr = (METARECORD *)GlobalLock16(hmr);
1643 mr->rdFunction = META_STRETCHBLT;
1644 *(mr->rdParam +10) = BM.bmWidth;
1645 *(mr->rdParam +11) = BM.bmHeight;
1646 *(mr->rdParam +12) = BM.bmWidthBytes;
1647 *(mr->rdParam +13) = BM.bmPlanes;
1648 *(mr->rdParam +14) = BM.bmBitsPixel;
1649 TRACE(metafile,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1650 if (GetBitmapBits32( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1651 mr->rdParam +15))
1652 #endif
1654 mr->rdSize = len / sizeof(INT16);
1655 *(mr->rdParam) = LOWORD(rop);
1656 *(mr->rdParam + 1) = HIWORD(rop);
1657 *(mr->rdParam + 2) = heightSrc;
1658 *(mr->rdParam + 3) = widthSrc;
1659 *(mr->rdParam + 4) = ySrc;
1660 *(mr->rdParam + 5) = xSrc;
1661 *(mr->rdParam + 6) = heightDest;
1662 *(mr->rdParam + 7) = widthDest;
1663 *(mr->rdParam + 8) = yDest;
1664 *(mr->rdParam + 9) = xDest;
1665 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1667 else
1668 ret = FALSE;
1669 GlobalFree16(hmr);
1670 return ret;
1674 /******************************************************************
1675 * MF_CreateRegion
1677 INT16 MF_CreateRegion(DC *dc, HRGN32 hrgn)
1679 DWORD len;
1680 METARECORD *mr;
1681 RGNDATA *rgndata;
1682 RECT32 *pCurRect, *pEndRect;
1683 WORD Bands = 0, MaxBands = 0;
1684 WORD *Param, *StartBand;
1685 BOOL32 ret;
1687 len = GetRegionData( hrgn, 0, NULL );
1688 if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1689 WARN(metafile, "MF_CreateRegion: can't alloc rgndata buffer\n");
1690 return -1;
1692 GetRegionData( hrgn, len, rgndata );
1694 /* Overestimate of length:
1695 * Assume every rect is a separate band -> 6 WORDs per rect
1697 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1698 if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1699 WARN(metafile, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1700 HeapFree( SystemHeap, 0, rgndata );
1701 return -1;
1704 memset(mr, 0, len);
1706 Param = mr->rdParam + 11;
1707 StartBand = NULL;
1709 pEndRect = (RECT32 *)rgndata->Buffer + rgndata->rdh.nCount;
1710 for(pCurRect = (RECT32 *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1712 if( StartBand && pCurRect->top == *(StartBand + 1) )
1714 *Param++ = pCurRect->left;
1715 *Param++ = pCurRect->right;
1717 else
1719 if(StartBand)
1721 *StartBand = Param - StartBand - 3;
1722 *Param++ = *StartBand;
1723 if(*StartBand > MaxBands)
1724 MaxBands = *StartBand;
1725 Bands++;
1727 StartBand = Param++;
1728 *Param++ = pCurRect->top;
1729 *Param++ = pCurRect->bottom;
1730 *Param++ = pCurRect->left;
1731 *Param++ = pCurRect->right;
1734 len = Param - (WORD *)mr;
1736 mr->rdParam[0] = 0;
1737 mr->rdParam[1] = 6;
1738 mr->rdParam[2] = 0x1234;
1739 mr->rdParam[3] = 0;
1740 mr->rdParam[4] = len * 2;
1741 mr->rdParam[5] = Bands;
1742 mr->rdParam[6] = MaxBands;
1743 mr->rdParam[7] = rgndata->rdh.rcBound.left;
1744 mr->rdParam[8] = rgndata->rdh.rcBound.top;
1745 mr->rdParam[9] = rgndata->rdh.rcBound.right;
1746 mr->rdParam[10] = rgndata->rdh.rcBound.bottom;
1747 mr->rdFunction = META_CREATEREGION;
1748 mr->rdSize = len / 2;
1749 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );
1750 HeapFree( SystemHeap, 0, mr );
1751 HeapFree( SystemHeap, 0, rgndata );
1752 if(!ret)
1754 WARN(metafile, "MF_CreateRegion: MF_WriteRecord failed\n");
1755 return -1;
1757 return MF_AddHandleDC( dc );