Make use of digitalv.h file.
[wine.git] / objects / metafile.c
blob90cd9bf515b95210e595559558b56b8a9f0bac75
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 "heap.h"
16 #include "toolhelp.h"
17 #include "debug.h"
19 /******************************************************************
20 * MF_AddHandle
22 * Add a handle to an external handle table and return the index
25 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
27 int i;
29 for (i = 0; i < htlen; i++)
31 if (*(ht->objectHandle + i) == 0)
33 *(ht->objectHandle + i) = hobj;
34 return i;
37 return -1;
41 /******************************************************************
42 * MF_AddHandleDC
44 * Note: this function assumes that we never delete objects.
45 * If we do someday, we'll need to maintain a table to re-use deleted
46 * handles.
48 static int MF_AddHandleDC( DC *dc )
50 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
51 physDev->mh->mtNoObjects++;
52 return physDev->nextHandle++;
56 /******************************************************************
57 * GetMetaFile16 (GDI.124)
59 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
61 return GetMetaFileA( lpFilename );
65 /******************************************************************
66 * GetMetaFile32A (GDI32.197)
68 * Read a metafile from a file. Returns handle to a disk-based metafile.
70 HMETAFILE WINAPI GetMetaFileA(
71 LPCSTR lpFilename
72 /* pointer to string containing filename to read */
75 HMETAFILE16 hmf;
76 METAHEADER *mh;
77 HFILE hFile;
78 DWORD size;
80 TRACE(metafile,"%s\n", lpFilename);
82 if (!lpFilename)
83 return 0;
85 hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
86 mh = (METAHEADER *)GlobalLock16(hmf);
88 if (!mh)
90 GlobalFree16(hmf);
91 return 0;
94 if ((hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR)
96 GlobalFree16(hmf);
97 return 0;
100 if (_lread(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR)
102 _lclose( hFile );
103 GlobalFree16(hmf);
104 return 0;
107 size = mh->mtSize * 2; /* alloc memory for whole metafile */
108 GlobalUnlock16(hmf);
109 hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
110 mh = (METAHEADER *)GlobalLock16(hmf);
112 if (!mh)
114 _lclose( hFile );
115 GlobalFree16(hmf);
116 return 0;
119 if (_lread(hFile, (char*)mh + mh->mtHeaderSize * 2,
120 size - mh->mtHeaderSize * 2) == HFILE_ERROR)
122 _lclose( hFile );
123 GlobalFree16(hmf);
124 return 0;
127 _lclose(hFile);
129 if (mh->mtType != 1)
131 GlobalFree16(hmf);
132 return 0;
135 GlobalUnlock16(hmf);
136 return hmf;
141 /******************************************************************
142 * GetMetaFile32W (GDI32.199)
144 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
146 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
147 HMETAFILE ret = GetMetaFileA( p );
148 HeapFree( GetProcessHeap(), 0, p );
149 return ret;
153 /******************************************************************
154 * CopyMetaFile16 (GDI.151)
157 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename )
159 return CopyMetaFileA( hSrcMetaFile, lpFilename );
163 /******************************************************************
164 * CopyMetaFile32A (GDI32.23)
166 * Copies the metafile corresponding to hSrcMetaFile to either
167 * a disk file, if a filename is given, or to a new memory based
168 * metafile, if lpFileName is NULL.
170 * RETURNS
172 * Handle to metafile copy on success, NULL on failure.
174 * BUGS
176 * Copying to disk returns NULL even if successful.
178 HMETAFILE WINAPI CopyMetaFileA(
179 HMETAFILE hSrcMetaFile, /* handle of metafile to copy */
180 LPCSTR lpFilename /* filename if copying to a file */
182 HMETAFILE16 handle = 0;
183 METAHEADER *mh;
184 METAHEADER *mh2;
185 HFILE hFile;
187 TRACE(metafile,"(%08x,%s)\n", hSrcMetaFile, lpFilename);
189 mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
191 if (!mh)
192 return 0;
194 if (lpFilename) /* disk based metafile */
196 int i,j;
197 hFile = _lcreat(lpFilename, 0);
198 j=mh->mtType;
199 mh->mtType=1; /* disk file version stores 1 here */
200 i=_lwrite(hFile, (char *)mh, mh->mtSize * 2) ;
201 mh->mtType=j; /* restore old value [0 or 1] */
202 _lclose(hFile);
203 if (i == -1)
204 return 0;
205 /* FIXME: return value */
207 else /* memory based metafile */
209 handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
210 mh2 = (METAHEADER *)GlobalLock16(handle);
211 memcpy(mh2,mh, mh->mtSize * 2);
212 GlobalUnlock16(handle);
215 GlobalUnlock16(hSrcMetaFile);
216 return handle;
220 /******************************************************************
221 * CopyMetaFile32W (GDI32.24)
223 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
224 LPCWSTR lpFilename )
226 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
227 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
228 HeapFree( GetProcessHeap(), 0, p );
229 return ret;
233 /******************************************************************
234 * IsValidMetaFile (GDI.410)
236 * Attempts to check if a given metafile is correctly formatted.
237 * Currently, the only things verified are several properties of the
238 * header.
240 * RETURNS
241 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
243 * BUGS
244 * This is not exactly what windows does, see _Undocumented_Windows_
245 * for details.
248 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
250 BOOL16 resu=FALSE;
251 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
252 if (mh) {
253 if (mh->mtType == 1 || mh->mtType == 0)
254 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
255 if (mh->mtVersion == MFVERSION)
256 resu=TRUE;
257 GlobalUnlock16(hmf);
259 TRACE(metafile,"IsValidMetaFile %x => %d\n",hmf,resu);
260 return resu;
264 /******************************************************************
265 * PlayMetaFile16 (GDI.123)
268 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
270 return PlayMetaFile( hdc, hmf );
273 /******************************************************************
274 * PlayMetaFile32 (GDI32.265)
276 * Renders the metafile specified by hmf in the DC specified by
277 * hdc. Returns FALSE on failure, TRUE on success.
279 BOOL WINAPI PlayMetaFile(
280 HDC hdc, /* handle of DC to render in */
281 HMETAFILE hmf /* handle of metafile to render */
284 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
285 METARECORD *mr;
286 HANDLETABLE16 *ht;
287 HGLOBAL16 hHT;
288 int offset = 0;
289 WORD i;
290 HPEN hPen;
291 HBRUSH hBrush;
292 HFONT hFont;
293 DC *dc;
295 TRACE(metafile,"(%04x %04x)\n",hdc,hmf);
296 if (!mh) return FALSE;
298 /* save the current pen, brush and font */
299 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
300 hPen = dc->w.hPen;
301 hBrush = dc->w.hBrush;
302 hFont = dc->w.hFont;
303 GDI_HEAP_UNLOCK(hdc);
304 /* create the handle table */
305 hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
306 sizeof(HANDLETABLE16) * mh->mtNoObjects);
307 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
310 /* loop through metafile playing records */
311 offset = mh->mtHeaderSize * 2;
312 while (offset < mh->mtSize * 2)
314 mr = (METARECORD *)((char *)mh + offset);
315 TRACE(metafile,"offset=%04x,size=%08lx\n",
316 offset, mr->rdSize);
317 if (!mr->rdSize) {
318 TRACE(metafile,"Entry got size 0 at offset %d, total mf length is %ld\n",
319 offset,mh->mtSize*2);
320 break; /* would loop endlessly otherwise */
322 offset += mr->rdSize * 2;
323 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
326 SelectObject(hdc, hBrush);
327 SelectObject(hdc, hPen);
328 SelectObject(hdc, hFont);
330 /* free objects in handle table */
331 for(i = 0; i < mh->mtNoObjects; i++)
332 if(*(ht->objectHandle + i) != 0)
333 DeleteObject(*(ht->objectHandle + i));
335 /* free handle table */
336 GlobalFree16(hHT);
338 return TRUE;
342 /******************************************************************
343 * EnumMetaFile16 (GDI.175)
345 * Loop through the metafile records in hmf, calling the user-specified
346 * function for each one, stopping when the user's function returns FALSE
347 * (which is considered to be failure)
348 * or when no records are left (which is considered to be success).
350 * RETURNS
351 * TRUE on success, FALSE on failure.
353 * HISTORY
354 * Niels de carpentier, april 1996
356 BOOL16 WINAPI EnumMetaFile16(
357 HDC16 hdc,
358 HMETAFILE16 hmf,
359 MFENUMPROC16 lpEnumFunc,
360 LPARAM lpData
363 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
364 METARECORD *mr;
365 HANDLETABLE16 *ht;
366 HGLOBAL16 hHT;
367 SEGPTR spht;
368 int offset = 0;
369 WORD i, seg;
370 HPEN hPen;
371 HBRUSH hBrush;
372 HFONT hFont;
373 DC *dc;
374 BOOL16 result = TRUE;
376 TRACE(metafile,"(%04x, %04x, %08lx, %08lx)\n",
377 hdc, hmf, (DWORD)lpEnumFunc, lpData);
379 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
380 hPen = dc->w.hPen;
381 hBrush = dc->w.hBrush;
382 hFont = dc->w.hFont;
383 GDI_HEAP_UNLOCK(hdc);
385 /* create the handle table */
387 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
388 sizeof(HANDLETABLE16) * mh->mtNoObjects);
389 spht = WIN16_GlobalLock16(hHT);
391 seg = GlobalHandleToSel16(hmf);
392 offset = mh->mtHeaderSize * 2;
394 /* loop through metafile records */
396 while (offset < (mh->mtSize * 2))
398 mr = (METARECORD *)((char *)mh + offset);
399 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
400 (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
401 mh->mtNoObjects, (LONG)lpData ))
403 result = FALSE;
404 break;
408 offset += (mr->rdSize * 2);
411 SelectObject(hdc, hBrush);
412 SelectObject(hdc, hPen);
413 SelectObject(hdc, hFont);
415 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
417 /* free objects in handle table */
418 for(i = 0; i < mh->mtNoObjects; i++)
419 if(*(ht->objectHandle + i) != 0)
420 DeleteObject(*(ht->objectHandle + i));
422 /* free handle table */
423 GlobalFree16(hHT);
424 GlobalUnlock16(hmf);
425 return result;
428 BOOL WINAPI EnumMetaFile(
429 HDC hdc,
430 HMETAFILE hmf,
431 MFENUMPROC lpEnumFunc,
432 LPARAM lpData
434 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
435 METARECORD *mr;
436 HANDLETABLE *ht;
437 BOOL result = TRUE;
438 int i, offset = 0;
439 DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
440 HPEN hPen;
441 HBRUSH hBrush;
442 HFONT hFont;
444 TRACE(metafile,"(%08x,%08x,%p,%p)\n",
445 hdc, hmf, lpEnumFunc, (void*)lpData);
446 if (!mh) return 0;
448 /* save the current pen, brush and font */
449 if (!dc) return 0;
450 hPen = dc->w.hPen;
451 hBrush = dc->w.hBrush;
452 hFont = dc->w.hFont;
453 GDI_HEAP_UNLOCK(hdc);
456 ht = (HANDLETABLE *) GlobalAlloc(GPTR,
457 sizeof(HANDLETABLE) * mh->mtNoObjects);
459 /* loop through metafile records */
460 offset = mh->mtHeaderSize * 2;
462 while (offset < (mh->mtSize * 2))
464 mr = (METARECORD *)((char *)mh + offset);
465 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
467 result = FALSE;
468 break;
471 offset += (mr->rdSize * 2);
474 /* restore pen, brush and font */
475 SelectObject(hdc, hBrush);
476 SelectObject(hdc, hPen);
477 SelectObject(hdc, hFont);
479 /* free objects in handle table */
480 for(i = 0; i < mh->mtNoObjects; i++)
481 if(*(ht->objectHandle + i) != 0)
482 DeleteObject(*(ht->objectHandle + i));
484 /* free handle table */
485 GlobalFree((HGLOBAL)ht);
486 GlobalUnlock16(hmf);
487 return result;
490 static BOOL MF_Meta_CreateRegion( METARECORD *mr, HRGN hrgn );
492 /******************************************************************
493 * PlayMetaFileRecord16 (GDI.176)
495 * Render a single metafile record specified by *mr in the DC hdc, while
496 * using the handle table *ht, of length nHandles,
497 * to store metafile objects.
499 * BUGS
500 * The following metafile records are unimplemented:
502 * FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
503 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
504 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
507 void WINAPI PlayMetaFileRecord16(
508 HDC16 hdc, /* DC to render metafile into */
509 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
510 METARECORD *mr, /* pointer to metafile record to render */
511 UINT16 nHandles /* size of handle table */
513 short s1;
514 HANDLE16 hndl;
515 char *ptr;
516 BITMAPINFOHEADER *infohdr;
518 TRACE(metafile,"(%04x %08lx %08lx %04x) function %04x\n",
519 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
521 switch (mr->rdFunction)
523 case META_EOF:
524 break;
526 case META_DELETEOBJECT:
527 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
528 *(ht->objectHandle + *(mr->rdParm)) = 0;
529 break;
531 case META_SETBKCOLOR:
532 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
533 break;
535 case META_SETBKMODE:
536 SetBkMode16(hdc, *(mr->rdParm));
537 break;
539 case META_SETMAPMODE:
540 SetMapMode16(hdc, *(mr->rdParm));
541 break;
543 case META_SETROP2:
544 SetROP216(hdc, *(mr->rdParm));
545 break;
547 case META_SETRELABS:
548 SetRelAbs16(hdc, *(mr->rdParm));
549 break;
551 case META_SETPOLYFILLMODE:
552 SetPolyFillMode16(hdc, *(mr->rdParm));
553 break;
555 case META_SETSTRETCHBLTMODE:
556 SetStretchBltMode16(hdc, *(mr->rdParm));
557 break;
559 case META_SETTEXTCOLOR:
560 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
561 break;
563 case META_SETWINDOWORG:
564 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
565 break;
567 case META_SETWINDOWEXT:
568 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
569 break;
571 case META_SETVIEWPORTORG:
572 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
573 break;
575 case META_SETVIEWPORTEXT:
576 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
577 break;
579 case META_OFFSETWINDOWORG:
580 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
581 break;
583 case META_SCALEWINDOWEXT:
584 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
585 *(mr->rdParm + 1), *(mr->rdParm));
586 break;
588 case META_OFFSETVIEWPORTORG:
589 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
590 break;
592 case META_SCALEVIEWPORTEXT:
593 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
594 *(mr->rdParm + 1), *(mr->rdParm));
595 break;
597 case META_LINETO:
598 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
599 break;
601 case META_MOVETO:
602 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
603 break;
605 case META_EXCLUDECLIPRECT:
606 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
607 *(mr->rdParm + 1), *(mr->rdParm) );
608 break;
610 case META_INTERSECTCLIPRECT:
611 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
612 *(mr->rdParm + 1), *(mr->rdParm) );
613 break;
615 case META_ARC:
616 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
617 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
618 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
619 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
620 break;
622 case META_ELLIPSE:
623 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
624 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
625 break;
627 case META_FLOODFILL:
628 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
629 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
630 break;
632 case META_PIE:
633 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
634 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
635 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
636 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
637 break;
639 case META_RECTANGLE:
640 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
641 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
642 break;
644 case META_ROUNDRECT:
645 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
646 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
647 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
648 break;
650 case META_PATBLT:
651 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
652 *(mr->rdParm + 3), *(mr->rdParm + 2),
653 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
654 break;
656 case META_SAVEDC:
657 SaveDC(hdc);
658 break;
660 case META_SETPIXEL:
661 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
662 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
663 break;
665 case META_OFFSETCLIPRGN:
666 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
667 break;
669 case META_TEXTOUT:
670 s1 = *(mr->rdParm);
671 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
672 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
673 (char *)(mr->rdParm + 1), s1);
674 break;
676 case META_POLYGON:
677 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
678 break;
680 case META_POLYPOLYGON:
681 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
682 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
683 break;
685 case META_POLYLINE:
686 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
687 break;
689 case META_RESTOREDC:
690 RestoreDC(hdc, (INT16)*(mr->rdParm));
691 break;
693 case META_SELECTOBJECT:
694 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
695 break;
697 case META_CHORD:
698 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
699 (INT16)*(mr->rdParm+5), (INT16)*(mr->rdParm + 4),
700 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
701 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
702 break;
704 case META_CREATEPATTERNBRUSH:
705 switch (*(mr->rdParm))
707 case BS_PATTERN:
708 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
709 MF_AddHandle(ht, nHandles,
710 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
711 infohdr->biHeight,
712 infohdr->biPlanes,
713 infohdr->biBitCount,
714 (LPSTR)(mr->rdParm +
715 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
716 break;
718 case BS_DIBPATTERN:
719 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
720 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
721 ptr = GlobalLock16(hndl);
722 memcpy(ptr, mr->rdParm + 2, s1);
723 GlobalUnlock16(hndl);
724 MF_AddHandle(ht, nHandles,
725 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
726 GlobalFree16(hndl);
728 break;
730 case META_CREATEPENINDIRECT:
731 MF_AddHandle(ht, nHandles,
732 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
733 break;
735 case META_CREATEFONTINDIRECT:
736 MF_AddHandle(ht, nHandles,
737 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
738 break;
740 case META_CREATEBRUSHINDIRECT:
741 MF_AddHandle(ht, nHandles,
742 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
743 break;
745 /* W. Magro: Some new metafile operations. Not all debugged. */
746 case META_CREATEPALETTE:
747 MF_AddHandle(ht, nHandles,
748 CreatePalette16((LPLOGPALETTE)mr->rdParm));
749 break;
751 case META_SETTEXTALIGN:
752 SetTextAlign16(hdc, *(mr->rdParm));
753 break;
755 case META_SELECTPALETTE:
756 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),*(mr->rdParm));
757 break;
759 case META_SETMAPPERFLAGS:
760 SetMapperFlags16(hdc, *(mr->rdParm));
761 break;
763 case META_REALIZEPALETTE:
764 RealizePalette16(hdc);
765 break;
767 case META_ESCAPE:
768 FIXME(metafile, "META_ESCAPE unimplemented.\n");
769 break;
771 /* --- Begin of fixed or new metafile operations. July 1996 ----*/
772 case META_EXTTEXTOUT:
774 LPINT16 dxx;
775 LPSTR sot;
776 DWORD len;
778 s1 = mr->rdParm[2]; /* String length */
779 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
780 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0); /* rec len without dx array */
782 sot= (LPSTR)&mr->rdParm[4]; /* start_of_text */
783 if (mr->rdParm[3])
784 sot+=sizeof(RECT16); /* there is a rectangle, so add offset */
786 if (mr->rdSize == len / 2)
787 dxx = NULL; /* determine if array present */
788 else
789 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
790 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
791 else
793 TRACE(metafile,"%s len: %ld\n",
794 sot,mr->rdSize);
795 WARN(metafile,
796 "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
797 len,s1,mr->rdSize,mr->rdParm[3]);
798 dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
800 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
801 mr->rdParm[0], /* Y position */
802 mr->rdParm[3], /* options */
803 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL, /* rectangle */
804 sot, /* string */
805 s1, dxx); /* length, dx array */
806 if (dxx)
807 TRACE(metafile,"%s len: %ld dx0: %d\n",
808 sot,mr->rdSize,dxx[0]);
810 break;
812 case META_STRETCHDIB:
814 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
815 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
816 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
817 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
818 mr->rdParm[4],mr->rdParm[3],bits,info,
819 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
821 break;
823 case META_DIBSTRETCHBLT:
825 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
826 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
827 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
828 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
829 mr->rdParm[3],mr->rdParm[2],bits,info,
830 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
832 break;
834 case META_STRETCHBLT:
836 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
837 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
838 mr->rdParm[11], /*Height*/
839 mr->rdParm[13], /*Planes*/
840 mr->rdParm[14], /*BitsPixel*/
841 (LPSTR)&mr->rdParm[15]); /*bits*/
842 SelectObject(hdcSrc,hbitmap);
843 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
844 mr->rdParm[7],mr->rdParm[6],
845 hdcSrc,mr->rdParm[5],mr->rdParm[4],
846 mr->rdParm[3],mr->rdParm[2],
847 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
848 DeleteDC(hdcSrc);
850 break;
852 case META_BITBLT: /* <-- not yet debugged */
854 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
855 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
856 mr->rdParm[8]/*Height*/,
857 mr->rdParm[10]/*Planes*/,
858 mr->rdParm[11]/*BitsPixel*/,
859 (LPSTR)&mr->rdParm[12]/*bits*/);
860 SelectObject(hdcSrc,hbitmap);
861 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
862 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
863 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
864 MAKELONG(0,mr->rdParm[0]));
865 DeleteDC(hdcSrc);
867 break;
869 /* --- Begin of new metafile operations. April, 1997 (ak) ----*/
870 case META_CREATEREGION:
872 HRGN hrgn = CreateRectRgn(0,0,0,0);
874 MF_Meta_CreateRegion(mr, hrgn);
875 MF_AddHandle(ht, nHandles, hrgn);
877 break;
879 case META_FILLREGION:
880 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)),
881 *(ht->objectHandle + *(mr->rdParm+1)));
882 break;
884 case META_INVERTREGION:
885 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
886 break;
888 case META_PAINTREGION:
889 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
890 break;
892 case META_SELECTCLIPREGION:
893 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
894 break;
896 case META_DIBCREATEPATTERNBRUSH:
897 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
898 TRACE(metafile,"%d\n",*(mr->rdParm));
899 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
900 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
901 ptr = GlobalLock16(hndl);
902 memcpy(ptr, mr->rdParm + 2, s1);
903 GlobalUnlock16(hndl);
904 MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
905 GlobalFree16(hndl);
906 break;
908 case META_DIBBITBLT:
910 /*In practice ive found that theres two layout for META_DIBBITBLT,
911 one (the first here) is the usual one when a src dc is actually passed
912 int, the second occurs when the src dc is passed in as NULL to
913 the creating BitBlt.
914 as the second case has no dib, a size check will suffice to distinguish.
917 Caolan.McNamara@ul.ie
919 if (mr->rdSize > 12)
921 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
922 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
923 StretchDIBits16(hdc,mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
924 mr->rdParm[4],mr->rdParm[3],mr->rdParm[2],
925 mr->rdParm[5],mr->rdParm[4],bits,info,
926 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
928 else /*equivalent to a PatBlt*/
930 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
931 mr->rdParm[6], mr->rdParm[5],
932 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
935 break;
937 case META_SETTEXTCHAREXTRA:
938 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
939 break;
941 case META_SETTEXTJUSTIFICATION:
942 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
943 break;
945 case META_EXTFLOODFILL:
946 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
947 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),*(mr->rdParm));
948 break;
950 #define META_UNIMP(x) case x: FIXME(metafile, "PlayMetaFileRecord:record type "#x" not implemented.\n");break;
951 META_UNIMP(META_FRAMEREGION)
952 META_UNIMP(META_DRAWTEXT)
953 META_UNIMP(META_SETDIBTODEV)
954 META_UNIMP(META_ANIMATEPALETTE)
955 META_UNIMP(META_SETPALENTRIES)
956 META_UNIMP(META_RESIZEPALETTE)
957 META_UNIMP(META_RESETDC)
958 META_UNIMP(META_STARTDOC)
959 META_UNIMP(META_STARTPAGE)
960 META_UNIMP(META_ENDPAGE)
961 META_UNIMP(META_ABORTDOC)
962 META_UNIMP(META_ENDDOC)
963 META_UNIMP(META_CREATEBRUSH)
964 META_UNIMP(META_CREATEBITMAPINDIRECT)
965 META_UNIMP(META_CREATEBITMAP)
966 #undef META_UNIMP
968 default:
969 WARN(metafile, "PlayMetaFileRecord: Unknown record type %x\n",
970 mr->rdFunction);
975 BOOL WINAPI PlayMetaFileRecord(
976 HDC hdc,
977 HANDLETABLE *handletable,
978 METARECORD *metarecord,
979 UINT handles
982 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
983 handles*sizeof(HANDLETABLE16));
984 int i = 0;
985 TRACE(metafile, "(%08x,%p,%p,%d)\n", hdc, handletable, metarecord, handles);
986 for (i=0; i<handles; i++)
987 ht->objectHandle[i] = handletable->objectHandle[i];
988 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
989 for (i=0; i<handles; i++)
990 handletable->objectHandle[i] = ht->objectHandle[i];
991 GlobalFree((HGLOBAL)ht);
992 return TRUE;
995 /******************************************************************
996 * GetMetaFileBits (GDI.159)
998 * Trade in a metafile object handle for a handle to the metafile memory.
1002 HGLOBAL16 WINAPI GetMetaFileBits16(
1003 HMETAFILE16 hmf /* metafile handle */
1006 TRACE(metafile,"hMem out: %04x\n", hmf);
1007 return hmf;
1010 /******************************************************************
1011 * SetMetaFileBits (GDI.160)
1013 * Trade in a metafile memory handle for a handle to a metafile object.
1014 * The memory region should hold a proper metafile, otherwise
1015 * problems will occur when it is used. Validity of the memory is not
1016 * checked. The function is essentially just the identity function.
1018 HMETAFILE16 WINAPI SetMetaFileBits16(
1019 HGLOBAL16 hMem
1020 /* handle to a memory region holding a metafile */
1023 TRACE(metafile,"hmf out: %04x\n", hMem);
1025 return hMem;
1028 /******************************************************************
1029 * SetMetaFileBitsBetter (GDI.196)
1031 * Trade in a metafile memory handle for a handle to a metafile object,
1032 * making a cursory check (using IsValidMetaFile()) that the memory
1033 * handle points to a valid metafile.
1035 * RETURNS
1036 * Handle to a metafile on success, NULL on failure..
1038 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1040 if( IsValidMetaFile16( hMeta ) )
1041 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1042 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1043 return (HMETAFILE16)0;
1046 /******************************************************************
1047 * SetMetaFileBitsEx (GDI32.323)
1049 * Create a metafile from raw data. No checking of the data is performed.
1050 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1052 HMETAFILE WINAPI SetMetaFileBitsEx(
1053 UINT size, /* size of metafile, in bytes */
1054 const BYTE *lpData /* pointer to metafile data */
1057 HMETAFILE hmf = GlobalAlloc16(GHND, size);
1058 BYTE *p = GlobalLock16(hmf) ;
1059 TRACE(metafile, "(%d,%p) returning %08x\n", size, lpData, hmf);
1060 if (!hmf || !p) return 0;
1061 memcpy(p, lpData, size);
1062 GlobalUnlock16(hmf);
1063 return hmf;
1066 /*****************************************************************
1067 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1069 * Copies the data from metafile _hmf_ into the buffer _buf_.
1070 * If _buf_ is zero, returns size of buffer required. Otherwise,
1071 * returns number of bytes copied.
1073 UINT WINAPI GetMetaFileBitsEx(
1074 HMETAFILE hmf, /* metafile */
1075 UINT nSize, /* size of buf */
1076 LPVOID buf /* buffer to receive raw metafile data */
1078 METAHEADER *h = GlobalLock16(hmf);
1079 UINT mfSize;
1081 TRACE(metafile, "(%08x,%d,%p)\n", hmf, nSize, buf);
1082 if (!h) return 0; /* FIXME: error code */
1083 mfSize = h->mtSize * 2;
1084 if (!buf) {
1085 GlobalUnlock16(hmf);
1086 TRACE(metafile,"returning size %d\n", mfSize);
1087 return mfSize;
1089 if(mfSize > nSize) mfSize = nSize;
1090 memmove(buf, h, mfSize);
1091 GlobalUnlock16(hmf);
1092 return mfSize;
1095 /******************************************************************
1096 * GetWinMetaFileBits [GDI32.241]
1098 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1099 UINT cbBuffer, LPBYTE lpbBuffer,
1100 INT fnMapMode, HDC hdcRef)
1102 FIXME(metafile, "(%d,%d,%p,%d,%d): stub\n",
1103 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1104 return 0;
1107 /******************************************************************
1108 * MF_Meta_CreateRegion
1110 * Handles META_CREATEREGION for PlayMetaFileRecord().
1114 * The layout of the record looks something like this:
1116 * rdParm meaning
1117 * 0 Always 0?
1118 * 1 Always 6?
1119 * 2 Looks like a handle? - not constant
1120 * 3 0 or 1 ??
1121 * 4 Total number of bytes
1122 * 5 No. of seperate bands = n [see below]
1123 * 6 Largest number of x co-ords in a band
1124 * 7-10 Bounding box x1 y1 x2 y2
1125 * 11-... n bands
1127 * Regions are divided into bands that are uniform in the
1128 * y-direction. Each band consists of pairs of on/off x-coords and is
1129 * written as
1130 * m y0 y1 x1 x2 x3 ... xm m
1131 * into successive rdParm[]s.
1133 * This is probably just a dump of the internal RGNOBJ?
1135 * HDMD - 18/12/97
1139 static BOOL MF_Meta_CreateRegion( METARECORD *mr, HRGN hrgn )
1141 WORD band, pair;
1142 WORD *start, *end;
1143 INT16 y0, y1;
1144 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1146 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1147 band++, start = end + 1) {
1148 if(*start / 2 != (*start + 1) / 2) {
1149 WARN(metafile, "Delimiter not even.\n");
1150 DeleteObject( hrgn2 );
1151 return FALSE;
1154 end = start + *start + 3;
1155 if(end > (WORD *)mr + mr->rdSize) {
1156 WARN(metafile, "End points outside record.\n");
1157 DeleteObject( hrgn2 );
1158 return FALSE;
1161 if(*start != *end) {
1162 WARN(metafile, "Mismatched delimiters.\n");
1163 DeleteObject( hrgn2 );
1164 return FALSE;
1167 y0 = *(INT16 *)(start + 1);
1168 y1 = *(INT16 *)(start + 2);
1169 for(pair = 0; pair < *start / 2; pair++) {
1170 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1171 *(INT16 *)(start + 4 + 2*pair), y1 );
1172 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1175 DeleteObject( hrgn2 );
1176 return TRUE;
1180 /******************************************************************
1181 * MF_WriteRecord
1183 * Warning: this function can change the metafile handle.
1186 static BOOL MF_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
1188 DWORD len;
1189 METAHEADER *mh;
1190 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1192 switch(physDev->mh->mtType)
1194 case METAFILE_MEMORY:
1195 len = physDev->mh->mtSize * 2 + rlen;
1196 mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1197 if (!mh) return FALSE;
1198 physDev->mh = mh;
1199 memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1200 break;
1201 case METAFILE_DISK:
1202 TRACE(metafile,"Writing record to disk\n");
1203 if (_lwrite(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1204 return FALSE;
1205 break;
1206 default:
1207 ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
1208 return FALSE;
1211 physDev->mh->mtSize += rlen / 2;
1212 physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1213 return TRUE;
1217 /******************************************************************
1218 * MF_MetaParam0
1221 BOOL MF_MetaParam0(DC *dc, short func)
1223 char buffer[8];
1224 METARECORD *mr = (METARECORD *)&buffer;
1226 mr->rdSize = 3;
1227 mr->rdFunction = func;
1228 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1232 /******************************************************************
1233 * MF_MetaParam1
1235 BOOL MF_MetaParam1(DC *dc, short func, short param1)
1237 char buffer[8];
1238 METARECORD *mr = (METARECORD *)&buffer;
1240 mr->rdSize = 4;
1241 mr->rdFunction = func;
1242 *(mr->rdParm) = param1;
1243 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1247 /******************************************************************
1248 * MF_MetaParam2
1250 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
1252 char buffer[10];
1253 METARECORD *mr = (METARECORD *)&buffer;
1255 mr->rdSize = 5;
1256 mr->rdFunction = func;
1257 *(mr->rdParm) = param2;
1258 *(mr->rdParm + 1) = param1;
1259 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1263 /******************************************************************
1264 * MF_MetaParam4
1267 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
1268 short param3, short param4)
1270 char buffer[14];
1271 METARECORD *mr = (METARECORD *)&buffer;
1273 mr->rdSize = 7;
1274 mr->rdFunction = func;
1275 *(mr->rdParm) = param4;
1276 *(mr->rdParm + 1) = param3;
1277 *(mr->rdParm + 2) = param2;
1278 *(mr->rdParm + 3) = param1;
1279 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1283 /******************************************************************
1284 * MF_MetaParam6
1287 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
1288 short param3, short param4, short param5, short param6)
1290 char buffer[18];
1291 METARECORD *mr = (METARECORD *)&buffer;
1293 mr->rdSize = 9;
1294 mr->rdFunction = func;
1295 *(mr->rdParm) = param6;
1296 *(mr->rdParm + 1) = param5;
1297 *(mr->rdParm + 2) = param4;
1298 *(mr->rdParm + 3) = param3;
1299 *(mr->rdParm + 4) = param2;
1300 *(mr->rdParm + 5) = param1;
1301 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1305 /******************************************************************
1306 * MF_MetaParam8
1308 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
1309 short param3, short param4, short param5,
1310 short param6, short param7, short param8)
1312 char buffer[22];
1313 METARECORD *mr = (METARECORD *)&buffer;
1315 mr->rdSize = 11;
1316 mr->rdFunction = func;
1317 *(mr->rdParm) = param8;
1318 *(mr->rdParm + 1) = param7;
1319 *(mr->rdParm + 2) = param6;
1320 *(mr->rdParm + 3) = param5;
1321 *(mr->rdParm + 4) = param4;
1322 *(mr->rdParm + 5) = param3;
1323 *(mr->rdParm + 6) = param2;
1324 *(mr->rdParm + 7) = param1;
1325 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1329 /******************************************************************
1330 * MF_CreateBrushIndirect
1333 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1335 int index;
1336 char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1337 METARECORD *mr = (METARECORD *)&buffer;
1339 mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1340 mr->rdFunction = META_CREATEBRUSHINDIRECT;
1341 memcpy(&(mr->rdParm), logbrush, sizeof(*logbrush));
1342 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1344 mr->rdSize = sizeof(METARECORD) / 2;
1345 mr->rdFunction = META_SELECTOBJECT;
1347 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1348 *(mr->rdParm) = index;
1349 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1353 /******************************************************************
1354 * MF_CreatePatternBrush
1357 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1359 DWORD len, bmSize, biSize;
1360 HGLOBAL16 hmr;
1361 METARECORD *mr;
1362 BITMAPOBJ *bmp;
1363 BITMAPINFO *info;
1364 BITMAPINFOHEADER *infohdr;
1365 int index;
1366 char buffer[sizeof(METARECORD)];
1368 switch (logbrush->lbStyle)
1370 case BS_PATTERN:
1371 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1372 if (!bmp) return FALSE;
1373 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
1374 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1375 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1377 GDI_HEAP_UNLOCK((HGDIOBJ16)logbrush->lbHatch);
1378 return FALSE;
1380 mr = (METARECORD *)GlobalLock16(hmr);
1381 memset(mr, 0, len);
1382 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1383 mr->rdSize = len / 2;
1384 *(mr->rdParm) = logbrush->lbStyle;
1385 *(mr->rdParm + 1) = DIB_RGB_COLORS;
1386 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1387 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1388 infohdr->biWidth = bmp->bitmap.bmWidth;
1389 infohdr->biHeight = bmp->bitmap.bmHeight;
1390 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1391 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1392 memcpy(mr->rdParm + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1393 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1394 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1395 GDI_HEAP_UNLOCK(logbrush->lbHatch);
1396 break;
1398 case BS_DIBPATTERN:
1399 info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1400 if (info->bmiHeader.biCompression)
1401 bmSize = info->bmiHeader.biSizeImage;
1402 else
1403 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1404 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1405 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1406 len = sizeof(METARECORD) + biSize + bmSize + 2;
1407 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1408 return FALSE;
1409 mr = (METARECORD *)GlobalLock16(hmr);
1410 memset(mr, 0, len);
1411 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1412 mr->rdSize = len / 2;
1413 *(mr->rdParm) = logbrush->lbStyle;
1414 *(mr->rdParm + 1) = LOWORD(logbrush->lbColor);
1415 memcpy(mr->rdParm + 2, info, biSize + bmSize);
1416 break;
1417 default:
1418 return FALSE;
1420 if (!(MF_WriteRecord(dc, mr, len)))
1422 GlobalFree16(hmr);
1423 return FALSE;
1426 GlobalFree16(hmr);
1428 mr = (METARECORD *)&buffer;
1429 mr->rdSize = sizeof(METARECORD) / 2;
1430 mr->rdFunction = META_SELECTOBJECT;
1432 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1433 *(mr->rdParm) = index;
1434 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1438 /******************************************************************
1439 * MF_CreatePenIndirect
1442 BOOL MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1444 int index;
1445 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1446 METARECORD *mr = (METARECORD *)&buffer;
1448 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1449 mr->rdFunction = META_CREATEPENINDIRECT;
1450 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
1451 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1453 mr->rdSize = sizeof(METARECORD) / 2;
1454 mr->rdFunction = META_SELECTOBJECT;
1456 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1457 *(mr->rdParm) = index;
1458 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1462 /******************************************************************
1463 * MF_CreateFontIndirect
1466 BOOL MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1468 int index;
1469 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1470 METARECORD *mr = (METARECORD *)&buffer;
1472 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1473 mr->rdFunction = META_CREATEFONTINDIRECT;
1474 memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
1475 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1477 mr->rdSize = sizeof(METARECORD) / 2;
1478 mr->rdFunction = META_SELECTOBJECT;
1480 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1481 *(mr->rdParm) = index;
1482 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1486 /******************************************************************
1487 * MF_TextOut
1489 BOOL MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1491 BOOL ret;
1492 DWORD len;
1493 HGLOBAL16 hmr;
1494 METARECORD *mr;
1496 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
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_TEXTOUT;
1504 *(mr->rdParm) = count;
1505 memcpy(mr->rdParm + 1, str, count);
1506 *(mr->rdParm + ((count + 1) >> 1) + 1) = y;
1507 *(mr->rdParm + ((count + 1) >> 1) + 2) = x;
1508 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1509 GlobalFree16(hmr);
1510 return ret;
1513 /******************************************************************
1514 * MF_ExtTextOut
1516 BOOL MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1517 LPCSTR str, short count, const INT16 *lpDx)
1519 BOOL ret;
1520 DWORD len;
1521 HGLOBAL16 hmr;
1522 METARECORD *mr;
1524 if((!flags && rect) || (flags && !rect))
1525 WARN(metafile, "Inconsistent flags and rect\n");
1526 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1527 + sizeof(UINT16);
1528 if(rect)
1529 len += sizeof(RECT16);
1530 if (lpDx)
1531 len+=count*sizeof(INT16);
1532 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1533 return FALSE;
1534 mr = (METARECORD *)GlobalLock16(hmr);
1535 memset(mr, 0, len);
1537 mr->rdSize = len / 2;
1538 mr->rdFunction = META_EXTTEXTOUT;
1539 *(mr->rdParm) = y;
1540 *(mr->rdParm + 1) = x;
1541 *(mr->rdParm + 2) = count;
1542 *(mr->rdParm + 3) = flags;
1543 if (rect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
1544 memcpy(mr->rdParm + (rect ? 8 : 4), str, count);
1545 if (lpDx)
1546 memcpy(mr->rdParm + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1547 count*sizeof(INT16));
1548 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1549 GlobalFree16(hmr);
1550 return ret;
1553 /******************************************************************
1554 * MF_MetaPoly - implements Polygon and Polyline
1556 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1558 BOOL ret;
1559 DWORD len;
1560 HGLOBAL16 hmr;
1561 METARECORD *mr;
1563 len = sizeof(METARECORD) + (count * 4);
1564 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1565 return FALSE;
1566 mr = (METARECORD *)GlobalLock16(hmr);
1567 memset(mr, 0, len);
1569 mr->rdSize = len / 2;
1570 mr->rdFunction = func;
1571 *(mr->rdParm) = count;
1572 memcpy(mr->rdParm + 1, pt, count * 4);
1573 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1574 GlobalFree16(hmr);
1575 return ret;
1579 /******************************************************************
1580 * MF_BitBlt
1582 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1583 short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1585 BOOL ret;
1586 DWORD len;
1587 HGLOBAL16 hmr;
1588 METARECORD *mr;
1589 BITMAP16 BM;
1591 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1592 len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1593 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1594 return FALSE;
1595 mr = (METARECORD *)GlobalLock16(hmr);
1596 mr->rdFunction = META_BITBLT;
1597 *(mr->rdParm + 7) = BM.bmWidth;
1598 *(mr->rdParm + 8) = BM.bmHeight;
1599 *(mr->rdParm + 9) = BM.bmWidthBytes;
1600 *(mr->rdParm +10) = BM.bmPlanes;
1601 *(mr->rdParm +11) = BM.bmBitsPixel;
1602 TRACE(metafile,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1603 if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1604 mr->rdParm +12))
1606 mr->rdSize = len / sizeof(INT16);
1607 *(mr->rdParm) = HIWORD(rop);
1608 *(mr->rdParm + 1) = ySrc;
1609 *(mr->rdParm + 2) = xSrc;
1610 *(mr->rdParm + 3) = height;
1611 *(mr->rdParm + 4) = width;
1612 *(mr->rdParm + 5) = yDest;
1613 *(mr->rdParm + 6) = xDest;
1614 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1616 else
1617 ret = FALSE;
1618 GlobalFree16(hmr);
1619 return ret;
1623 /**********************************************************************
1624 * MF_StretchBlt
1625 * this function contains TWO ways for procesing StretchBlt in metafiles,
1626 * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT
1627 * via #define STRETCH_VIA_DIB
1629 #define STRETCH_VIA_DIB
1630 #undef STRETCH_VIA_DIB
1631 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1632 short heightDest, DC *dcSrc, short xSrc, short ySrc,
1633 short widthSrc, short heightSrc, DWORD rop)
1635 BOOL ret;
1636 DWORD len;
1637 HGLOBAL16 hmr;
1638 METARECORD *mr;
1639 BITMAP16 BM;
1640 #ifdef STRETCH_VIA_DIB
1641 LPBITMAPINFOHEADER lpBMI;
1642 WORD nBPP;
1643 #endif
1644 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1645 #ifdef STRETCH_VIA_DIB
1646 nBPP = BM.bmPlanes * BM.bmBitsPixel;
1647 len = sizeof(METARECORD) + 10 * sizeof(INT16)
1648 + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
1649 + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1650 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1651 return FALSE;
1652 mr = (METARECORD *)GlobalLock16(hmr);
1653 mr->rdFunction = META_DIBSTRETCHBLT;
1654 lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10);
1655 lpBMI->biSize = sizeof(BITMAPINFOHEADER);
1656 lpBMI->biWidth = BM.bmWidth;
1657 lpBMI->biHeight = BM.bmHeight;
1658 lpBMI->biPlanes = 1;
1659 lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */
1660 lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0;
1661 lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1662 lpBMI->biCompression = BI_RGB;
1663 lpBMI->biXPelsPerMeter = MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1664 lpBMI->biYPelsPerMeter = MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1665 lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */
1667 TRACE(metafile,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n",
1668 len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1669 if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT)lpBMI->biHeight,
1670 (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1671 DIB_RGB_COLORS ),
1672 (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1673 #else
1674 len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1675 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1676 return FALSE;
1677 mr = (METARECORD *)GlobalLock16(hmr);
1678 mr->rdFunction = META_STRETCHBLT;
1679 *(mr->rdParm +10) = BM.bmWidth;
1680 *(mr->rdParm +11) = BM.bmHeight;
1681 *(mr->rdParm +12) = BM.bmWidthBytes;
1682 *(mr->rdParm +13) = BM.bmPlanes;
1683 *(mr->rdParm +14) = BM.bmBitsPixel;
1684 TRACE(metafile,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1685 if (GetBitmapBits( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1686 mr->rdParm +15))
1687 #endif
1689 mr->rdSize = len / sizeof(INT16);
1690 *(mr->rdParm) = LOWORD(rop);
1691 *(mr->rdParm + 1) = HIWORD(rop);
1692 *(mr->rdParm + 2) = heightSrc;
1693 *(mr->rdParm + 3) = widthSrc;
1694 *(mr->rdParm + 4) = ySrc;
1695 *(mr->rdParm + 5) = xSrc;
1696 *(mr->rdParm + 6) = heightDest;
1697 *(mr->rdParm + 7) = widthDest;
1698 *(mr->rdParm + 8) = yDest;
1699 *(mr->rdParm + 9) = xDest;
1700 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1702 else
1703 ret = FALSE;
1704 GlobalFree16(hmr);
1705 return ret;
1709 /******************************************************************
1710 * MF_CreateRegion
1712 INT16 MF_CreateRegion(DC *dc, HRGN hrgn)
1714 DWORD len;
1715 METARECORD *mr;
1716 RGNDATA *rgndata;
1717 RECT *pCurRect, *pEndRect;
1718 WORD Bands = 0, MaxBands = 0;
1719 WORD *Param, *StartBand;
1720 BOOL ret;
1722 len = GetRegionData( hrgn, 0, NULL );
1723 if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1724 WARN(metafile, "MF_CreateRegion: can't alloc rgndata buffer\n");
1725 return -1;
1727 GetRegionData( hrgn, len, rgndata );
1729 /* Overestimate of length:
1730 * Assume every rect is a separate band -> 6 WORDs per rect
1732 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1733 if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1734 WARN(metafile, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1735 HeapFree( SystemHeap, 0, rgndata );
1736 return -1;
1739 memset(mr, 0, len);
1741 Param = mr->rdParm + 11;
1742 StartBand = NULL;
1744 pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
1745 for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1747 if( StartBand && pCurRect->top == *(StartBand + 1) )
1749 *Param++ = pCurRect->left;
1750 *Param++ = pCurRect->right;
1752 else
1754 if(StartBand)
1756 *StartBand = Param - StartBand - 3;
1757 *Param++ = *StartBand;
1758 if(*StartBand > MaxBands)
1759 MaxBands = *StartBand;
1760 Bands++;
1762 StartBand = Param++;
1763 *Param++ = pCurRect->top;
1764 *Param++ = pCurRect->bottom;
1765 *Param++ = pCurRect->left;
1766 *Param++ = pCurRect->right;
1769 len = Param - (WORD *)mr;
1771 mr->rdParm[0] = 0;
1772 mr->rdParm[1] = 6;
1773 mr->rdParm[2] = 0x1234;
1774 mr->rdParm[3] = 0;
1775 mr->rdParm[4] = len * 2;
1776 mr->rdParm[5] = Bands;
1777 mr->rdParm[6] = MaxBands;
1778 mr->rdParm[7] = rgndata->rdh.rcBound.left;
1779 mr->rdParm[8] = rgndata->rdh.rcBound.top;
1780 mr->rdParm[9] = rgndata->rdh.rcBound.right;
1781 mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
1782 mr->rdFunction = META_CREATEREGION;
1783 mr->rdSize = len / 2;
1784 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );
1785 HeapFree( SystemHeap, 0, mr );
1786 HeapFree( SystemHeap, 0, rgndata );
1787 if(!ret)
1789 WARN(metafile, "MF_CreateRegion: MF_WriteRecord failed\n");
1790 return -1;
1792 return MF_AddHandleDC( dc );