- mostly cleanup after the renaming
[wine/wine64.git] / objects / metafile.c
blob0f335d9e86ae9bd856b977a117d3b3fa2ba89cdf
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 #define META_UNIMP(x) case x: FIXME(metafile, "PlayMetaFileRecord:record type "#x" not implemented.\n");break;
946 META_UNIMP(META_FRAMEREGION)
947 META_UNIMP(META_DRAWTEXT)
948 META_UNIMP(META_SETDIBTODEV)
949 META_UNIMP(META_ANIMATEPALETTE)
950 META_UNIMP(META_SETPALENTRIES)
951 META_UNIMP(META_RESIZEPALETTE)
952 META_UNIMP(META_EXTFLOODFILL)
953 META_UNIMP(META_RESETDC)
954 META_UNIMP(META_STARTDOC)
955 META_UNIMP(META_STARTPAGE)
956 META_UNIMP(META_ENDPAGE)
957 META_UNIMP(META_ABORTDOC)
958 META_UNIMP(META_ENDDOC)
959 META_UNIMP(META_CREATEBRUSH)
960 META_UNIMP(META_CREATEBITMAPINDIRECT)
961 META_UNIMP(META_CREATEBITMAP)
962 #undef META_UNIMP
964 default:
965 WARN(metafile, "PlayMetaFileRecord: Unknown record type %x\n",
966 mr->rdFunction);
971 BOOL WINAPI PlayMetaFileRecord(
972 HDC hdc,
973 HANDLETABLE *handletable,
974 METARECORD *metarecord,
975 UINT handles
978 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
979 handles*sizeof(HANDLETABLE16));
980 int i = 0;
981 TRACE(metafile, "(%08x,%p,%p,%d)\n", hdc, handletable, metarecord, handles);
982 for (i=0; i<handles; i++)
983 ht->objectHandle[i] = handletable->objectHandle[i];
984 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
985 for (i=0; i<handles; i++)
986 handletable->objectHandle[i] = ht->objectHandle[i];
987 GlobalFree((HGLOBAL)ht);
988 return TRUE;
991 /******************************************************************
992 * GetMetaFileBits (GDI.159)
994 * Trade in a metafile object handle for a handle to the metafile memory.
998 HGLOBAL16 WINAPI GetMetaFileBits16(
999 HMETAFILE16 hmf /* metafile handle */
1002 TRACE(metafile,"hMem out: %04x\n", hmf);
1003 return hmf;
1006 /******************************************************************
1007 * SetMetaFileBits (GDI.160)
1009 * Trade in a metafile memory handle for a handle to a metafile object.
1010 * The memory region should hold a proper metafile, otherwise
1011 * problems will occur when it is used. Validity of the memory is not
1012 * checked. The function is essentially just the identity function.
1014 HMETAFILE16 WINAPI SetMetaFileBits16(
1015 HGLOBAL16 hMem
1016 /* handle to a memory region holding a metafile */
1019 TRACE(metafile,"hmf out: %04x\n", hMem);
1021 return hMem;
1024 /******************************************************************
1025 * SetMetaFileBitsBetter (GDI.196)
1027 * Trade in a metafile memory handle for a handle to a metafile object,
1028 * making a cursory check (using IsValidMetaFile()) that the memory
1029 * handle points to a valid metafile.
1031 * RETURNS
1032 * Handle to a metafile on success, NULL on failure..
1034 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1036 if( IsValidMetaFile16( hMeta ) )
1037 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1038 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1039 return (HMETAFILE16)0;
1042 /******************************************************************
1043 * SetMetaFileBitsEx (GDI32.323)
1045 * Create a metafile from raw data. No checking of the data is performed.
1046 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1048 HMETAFILE WINAPI SetMetaFileBitsEx(
1049 UINT size, /* size of metafile, in bytes */
1050 const BYTE *lpData /* pointer to metafile data */
1053 HMETAFILE hmf = GlobalAlloc16(GHND, size);
1054 BYTE *p = GlobalLock16(hmf) ;
1055 TRACE(metafile, "(%d,%p) returning %08x\n", size, lpData, hmf);
1056 if (!hmf || !p) return 0;
1057 memcpy(p, lpData, size);
1058 GlobalUnlock16(hmf);
1059 return hmf;
1062 /*****************************************************************
1063 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1065 * Copies the data from metafile _hmf_ into the buffer _buf_.
1066 * If _buf_ is zero, returns size of buffer required. Otherwise,
1067 * returns number of bytes copied.
1069 UINT WINAPI GetMetaFileBitsEx(
1070 HMETAFILE hmf, /* metafile */
1071 UINT nSize, /* size of buf */
1072 LPVOID buf /* buffer to receive raw metafile data */
1074 METAHEADER *h = GlobalLock16(hmf);
1075 UINT mfSize;
1077 TRACE(metafile, "(%08x,%d,%p)\n", hmf, nSize, buf);
1078 if (!h) return 0; /* FIXME: error code */
1079 mfSize = h->mtSize * 2;
1080 if (!buf) {
1081 GlobalUnlock16(hmf);
1082 TRACE(metafile,"returning size %d\n", mfSize);
1083 return mfSize;
1085 if(mfSize > nSize) mfSize = nSize;
1086 memmove(buf, h, mfSize);
1087 GlobalUnlock16(hmf);
1088 return mfSize;
1091 /******************************************************************
1092 * GetWinMetaFileBits [GDI32.241]
1094 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1095 UINT cbBuffer, LPBYTE lpbBuffer,
1096 INT fnMapMode, HDC hdcRef)
1098 FIXME(metafile, "(%d,%d,%p,%d,%d): stub\n",
1099 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1100 return 0;
1103 /******************************************************************
1104 * MF_Meta_CreateRegion
1106 * Handles META_CREATEREGION for PlayMetaFileRecord().
1110 * The layout of the record looks something like this:
1112 * rdParm meaning
1113 * 0 Always 0?
1114 * 1 Always 6?
1115 * 2 Looks like a handle? - not constant
1116 * 3 0 or 1 ??
1117 * 4 Total number of bytes
1118 * 5 No. of seperate bands = n [see below]
1119 * 6 Largest number of x co-ords in a band
1120 * 7-10 Bounding box x1 y1 x2 y2
1121 * 11-... n bands
1123 * Regions are divided into bands that are uniform in the
1124 * y-direction. Each band consists of pairs of on/off x-coords and is
1125 * written as
1126 * m y0 y1 x1 x2 x3 ... xm m
1127 * into successive rdParm[]s.
1129 * This is probably just a dump of the internal RGNOBJ?
1131 * HDMD - 18/12/97
1135 static BOOL MF_Meta_CreateRegion( METARECORD *mr, HRGN hrgn )
1137 WORD band, pair;
1138 WORD *start, *end;
1139 INT16 y0, y1;
1140 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1142 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1143 band++, start = end + 1) {
1144 if(*start / 2 != (*start + 1) / 2) {
1145 WARN(metafile, "Delimiter not even.\n");
1146 DeleteObject( hrgn2 );
1147 return FALSE;
1150 end = start + *start + 3;
1151 if(end > (WORD *)mr + mr->rdSize) {
1152 WARN(metafile, "End points outside record.\n");
1153 DeleteObject( hrgn2 );
1154 return FALSE;
1157 if(*start != *end) {
1158 WARN(metafile, "Mismatched delimiters.\n");
1159 DeleteObject( hrgn2 );
1160 return FALSE;
1163 y0 = *(INT16 *)(start + 1);
1164 y1 = *(INT16 *)(start + 2);
1165 for(pair = 0; pair < *start / 2; pair++) {
1166 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1167 *(INT16 *)(start + 4 + 2*pair), y1 );
1168 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1171 DeleteObject( hrgn2 );
1172 return TRUE;
1176 /******************************************************************
1177 * MF_WriteRecord
1179 * Warning: this function can change the metafile handle.
1182 static BOOL MF_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
1184 DWORD len;
1185 METAHEADER *mh;
1186 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1188 switch(physDev->mh->mtType)
1190 case METAFILE_MEMORY:
1191 len = physDev->mh->mtSize * 2 + rlen;
1192 mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1193 if (!mh) return FALSE;
1194 physDev->mh = mh;
1195 memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1196 break;
1197 case METAFILE_DISK:
1198 TRACE(metafile,"Writing record to disk\n");
1199 if (_lwrite(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1200 return FALSE;
1201 break;
1202 default:
1203 ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
1204 return FALSE;
1207 physDev->mh->mtSize += rlen / 2;
1208 physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1209 return TRUE;
1213 /******************************************************************
1214 * MF_MetaParam0
1217 BOOL MF_MetaParam0(DC *dc, short func)
1219 char buffer[8];
1220 METARECORD *mr = (METARECORD *)&buffer;
1222 mr->rdSize = 3;
1223 mr->rdFunction = func;
1224 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1228 /******************************************************************
1229 * MF_MetaParam1
1231 BOOL MF_MetaParam1(DC *dc, short func, short param1)
1233 char buffer[8];
1234 METARECORD *mr = (METARECORD *)&buffer;
1236 mr->rdSize = 4;
1237 mr->rdFunction = func;
1238 *(mr->rdParm) = param1;
1239 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1243 /******************************************************************
1244 * MF_MetaParam2
1246 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
1248 char buffer[10];
1249 METARECORD *mr = (METARECORD *)&buffer;
1251 mr->rdSize = 5;
1252 mr->rdFunction = func;
1253 *(mr->rdParm) = param2;
1254 *(mr->rdParm + 1) = param1;
1255 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1259 /******************************************************************
1260 * MF_MetaParam4
1263 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
1264 short param3, short param4)
1266 char buffer[14];
1267 METARECORD *mr = (METARECORD *)&buffer;
1269 mr->rdSize = 7;
1270 mr->rdFunction = func;
1271 *(mr->rdParm) = param4;
1272 *(mr->rdParm + 1) = param3;
1273 *(mr->rdParm + 2) = param2;
1274 *(mr->rdParm + 3) = param1;
1275 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1279 /******************************************************************
1280 * MF_MetaParam6
1283 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
1284 short param3, short param4, short param5, short param6)
1286 char buffer[18];
1287 METARECORD *mr = (METARECORD *)&buffer;
1289 mr->rdSize = 9;
1290 mr->rdFunction = func;
1291 *(mr->rdParm) = param6;
1292 *(mr->rdParm + 1) = param5;
1293 *(mr->rdParm + 2) = param4;
1294 *(mr->rdParm + 3) = param3;
1295 *(mr->rdParm + 4) = param2;
1296 *(mr->rdParm + 5) = param1;
1297 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1301 /******************************************************************
1302 * MF_MetaParam8
1304 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
1305 short param3, short param4, short param5,
1306 short param6, short param7, short param8)
1308 char buffer[22];
1309 METARECORD *mr = (METARECORD *)&buffer;
1311 mr->rdSize = 11;
1312 mr->rdFunction = func;
1313 *(mr->rdParm) = param8;
1314 *(mr->rdParm + 1) = param7;
1315 *(mr->rdParm + 2) = param6;
1316 *(mr->rdParm + 3) = param5;
1317 *(mr->rdParm + 4) = param4;
1318 *(mr->rdParm + 5) = param3;
1319 *(mr->rdParm + 6) = param2;
1320 *(mr->rdParm + 7) = param1;
1321 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1325 /******************************************************************
1326 * MF_CreateBrushIndirect
1329 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1331 int index;
1332 char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1333 METARECORD *mr = (METARECORD *)&buffer;
1335 mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1336 mr->rdFunction = META_CREATEBRUSHINDIRECT;
1337 memcpy(&(mr->rdParm), logbrush, sizeof(*logbrush));
1338 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1340 mr->rdSize = sizeof(METARECORD) / 2;
1341 mr->rdFunction = META_SELECTOBJECT;
1343 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1344 *(mr->rdParm) = index;
1345 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1349 /******************************************************************
1350 * MF_CreatePatternBrush
1353 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1355 DWORD len, bmSize, biSize;
1356 HGLOBAL16 hmr;
1357 METARECORD *mr;
1358 BITMAPOBJ *bmp;
1359 BITMAPINFO *info;
1360 BITMAPINFOHEADER *infohdr;
1361 int index;
1362 char buffer[sizeof(METARECORD)];
1364 switch (logbrush->lbStyle)
1366 case BS_PATTERN:
1367 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1368 if (!bmp) return FALSE;
1369 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
1370 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1371 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1373 GDI_HEAP_UNLOCK((HGDIOBJ16)logbrush->lbHatch);
1374 return FALSE;
1376 mr = (METARECORD *)GlobalLock16(hmr);
1377 memset(mr, 0, len);
1378 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1379 mr->rdSize = len / 2;
1380 *(mr->rdParm) = logbrush->lbStyle;
1381 *(mr->rdParm + 1) = DIB_RGB_COLORS;
1382 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1383 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1384 infohdr->biWidth = bmp->bitmap.bmWidth;
1385 infohdr->biHeight = bmp->bitmap.bmHeight;
1386 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1387 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1388 memcpy(mr->rdParm + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1389 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1390 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1391 GDI_HEAP_UNLOCK(logbrush->lbHatch);
1392 break;
1394 case BS_DIBPATTERN:
1395 info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1396 if (info->bmiHeader.biCompression)
1397 bmSize = info->bmiHeader.biSizeImage;
1398 else
1399 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1400 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1401 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1402 len = sizeof(METARECORD) + biSize + bmSize + 2;
1403 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1404 return FALSE;
1405 mr = (METARECORD *)GlobalLock16(hmr);
1406 memset(mr, 0, len);
1407 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1408 mr->rdSize = len / 2;
1409 *(mr->rdParm) = logbrush->lbStyle;
1410 *(mr->rdParm + 1) = LOWORD(logbrush->lbColor);
1411 memcpy(mr->rdParm + 2, info, biSize + bmSize);
1412 break;
1413 default:
1414 return FALSE;
1416 if (!(MF_WriteRecord(dc, mr, len)))
1418 GlobalFree16(hmr);
1419 return FALSE;
1422 GlobalFree16(hmr);
1424 mr = (METARECORD *)&buffer;
1425 mr->rdSize = sizeof(METARECORD) / 2;
1426 mr->rdFunction = META_SELECTOBJECT;
1428 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1429 *(mr->rdParm) = index;
1430 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1434 /******************************************************************
1435 * MF_CreatePenIndirect
1438 BOOL MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1440 int index;
1441 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1442 METARECORD *mr = (METARECORD *)&buffer;
1444 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1445 mr->rdFunction = META_CREATEPENINDIRECT;
1446 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
1447 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1449 mr->rdSize = sizeof(METARECORD) / 2;
1450 mr->rdFunction = META_SELECTOBJECT;
1452 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1453 *(mr->rdParm) = index;
1454 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1458 /******************************************************************
1459 * MF_CreateFontIndirect
1462 BOOL MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1464 int index;
1465 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1466 METARECORD *mr = (METARECORD *)&buffer;
1468 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1469 mr->rdFunction = META_CREATEFONTINDIRECT;
1470 memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
1471 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1473 mr->rdSize = sizeof(METARECORD) / 2;
1474 mr->rdFunction = META_SELECTOBJECT;
1476 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1477 *(mr->rdParm) = index;
1478 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1482 /******************************************************************
1483 * MF_TextOut
1485 BOOL MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1487 BOOL ret;
1488 DWORD len;
1489 HGLOBAL16 hmr;
1490 METARECORD *mr;
1492 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1493 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1494 return FALSE;
1495 mr = (METARECORD *)GlobalLock16(hmr);
1496 memset(mr, 0, len);
1498 mr->rdSize = len / 2;
1499 mr->rdFunction = META_TEXTOUT;
1500 *(mr->rdParm) = count;
1501 memcpy(mr->rdParm + 1, str, count);
1502 *(mr->rdParm + ((count + 1) >> 1) + 1) = y;
1503 *(mr->rdParm + ((count + 1) >> 1) + 2) = x;
1504 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1505 GlobalFree16(hmr);
1506 return ret;
1509 /******************************************************************
1510 * MF_ExtTextOut
1512 BOOL MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1513 LPCSTR str, short count, const INT16 *lpDx)
1515 BOOL ret;
1516 DWORD len;
1517 HGLOBAL16 hmr;
1518 METARECORD *mr;
1520 if((!flags && rect) || (flags && !rect))
1521 WARN(metafile, "Inconsistent flags and rect\n");
1522 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1523 + sizeof(UINT16);
1524 if(rect)
1525 len += sizeof(RECT16);
1526 if (lpDx)
1527 len+=count*sizeof(INT16);
1528 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1529 return FALSE;
1530 mr = (METARECORD *)GlobalLock16(hmr);
1531 memset(mr, 0, len);
1533 mr->rdSize = len / 2;
1534 mr->rdFunction = META_EXTTEXTOUT;
1535 *(mr->rdParm) = y;
1536 *(mr->rdParm + 1) = x;
1537 *(mr->rdParm + 2) = count;
1538 *(mr->rdParm + 3) = flags;
1539 if (rect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
1540 memcpy(mr->rdParm + (rect ? 8 : 4), str, count);
1541 if (lpDx)
1542 memcpy(mr->rdParm + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1543 count*sizeof(INT16));
1544 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1545 GlobalFree16(hmr);
1546 return ret;
1549 /******************************************************************
1550 * MF_MetaPoly - implements Polygon and Polyline
1552 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1554 BOOL ret;
1555 DWORD len;
1556 HGLOBAL16 hmr;
1557 METARECORD *mr;
1559 len = sizeof(METARECORD) + (count * 4);
1560 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1561 return FALSE;
1562 mr = (METARECORD *)GlobalLock16(hmr);
1563 memset(mr, 0, len);
1565 mr->rdSize = len / 2;
1566 mr->rdFunction = func;
1567 *(mr->rdParm) = count;
1568 memcpy(mr->rdParm + 1, pt, count * 4);
1569 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1570 GlobalFree16(hmr);
1571 return ret;
1575 /******************************************************************
1576 * MF_BitBlt
1578 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1579 short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1581 BOOL ret;
1582 DWORD len;
1583 HGLOBAL16 hmr;
1584 METARECORD *mr;
1585 BITMAP16 BM;
1587 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1588 len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1589 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1590 return FALSE;
1591 mr = (METARECORD *)GlobalLock16(hmr);
1592 mr->rdFunction = META_BITBLT;
1593 *(mr->rdParm + 7) = BM.bmWidth;
1594 *(mr->rdParm + 8) = BM.bmHeight;
1595 *(mr->rdParm + 9) = BM.bmWidthBytes;
1596 *(mr->rdParm +10) = BM.bmPlanes;
1597 *(mr->rdParm +11) = BM.bmBitsPixel;
1598 TRACE(metafile,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1599 if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1600 mr->rdParm +12))
1602 mr->rdSize = len / sizeof(INT16);
1603 *(mr->rdParm) = HIWORD(rop);
1604 *(mr->rdParm + 1) = ySrc;
1605 *(mr->rdParm + 2) = xSrc;
1606 *(mr->rdParm + 3) = height;
1607 *(mr->rdParm + 4) = width;
1608 *(mr->rdParm + 5) = yDest;
1609 *(mr->rdParm + 6) = xDest;
1610 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1612 else
1613 ret = FALSE;
1614 GlobalFree16(hmr);
1615 return ret;
1619 /**********************************************************************
1620 * MF_StretchBlt
1621 * this function contains TWO ways for procesing StretchBlt in metafiles,
1622 * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT
1623 * via #define STRETCH_VIA_DIB
1625 #define STRETCH_VIA_DIB
1626 #undef STRETCH_VIA_DIB
1627 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1628 short heightDest, DC *dcSrc, short xSrc, short ySrc,
1629 short widthSrc, short heightSrc, DWORD rop)
1631 BOOL ret;
1632 DWORD len;
1633 HGLOBAL16 hmr;
1634 METARECORD *mr;
1635 BITMAP16 BM;
1636 #ifdef STRETCH_VIA_DIB
1637 LPBITMAPINFOHEADER lpBMI;
1638 WORD nBPP;
1639 #endif
1640 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1641 #ifdef STRETCH_VIA_DIB
1642 nBPP = BM.bmPlanes * BM.bmBitsPixel;
1643 len = sizeof(METARECORD) + 10 * sizeof(INT16)
1644 + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
1645 + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1646 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1647 return FALSE;
1648 mr = (METARECORD *)GlobalLock16(hmr);
1649 mr->rdFunction = META_DIBSTRETCHBLT;
1650 lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10);
1651 lpBMI->biSize = sizeof(BITMAPINFOHEADER);
1652 lpBMI->biWidth = BM.bmWidth;
1653 lpBMI->biHeight = BM.bmHeight;
1654 lpBMI->biPlanes = 1;
1655 lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */
1656 lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0;
1657 lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1658 lpBMI->biCompression = BI_RGB;
1659 lpBMI->biXPelsPerMeter = MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1660 lpBMI->biYPelsPerMeter = MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1661 lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */
1663 TRACE(metafile,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n",
1664 len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1665 if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT)lpBMI->biHeight,
1666 (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1667 DIB_RGB_COLORS ),
1668 (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1669 #else
1670 len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1671 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1672 return FALSE;
1673 mr = (METARECORD *)GlobalLock16(hmr);
1674 mr->rdFunction = META_STRETCHBLT;
1675 *(mr->rdParm +10) = BM.bmWidth;
1676 *(mr->rdParm +11) = BM.bmHeight;
1677 *(mr->rdParm +12) = BM.bmWidthBytes;
1678 *(mr->rdParm +13) = BM.bmPlanes;
1679 *(mr->rdParm +14) = BM.bmBitsPixel;
1680 TRACE(metafile,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1681 if (GetBitmapBits( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1682 mr->rdParm +15))
1683 #endif
1685 mr->rdSize = len / sizeof(INT16);
1686 *(mr->rdParm) = LOWORD(rop);
1687 *(mr->rdParm + 1) = HIWORD(rop);
1688 *(mr->rdParm + 2) = heightSrc;
1689 *(mr->rdParm + 3) = widthSrc;
1690 *(mr->rdParm + 4) = ySrc;
1691 *(mr->rdParm + 5) = xSrc;
1692 *(mr->rdParm + 6) = heightDest;
1693 *(mr->rdParm + 7) = widthDest;
1694 *(mr->rdParm + 8) = yDest;
1695 *(mr->rdParm + 9) = xDest;
1696 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1698 else
1699 ret = FALSE;
1700 GlobalFree16(hmr);
1701 return ret;
1705 /******************************************************************
1706 * MF_CreateRegion
1708 INT16 MF_CreateRegion(DC *dc, HRGN hrgn)
1710 DWORD len;
1711 METARECORD *mr;
1712 RGNDATA *rgndata;
1713 RECT *pCurRect, *pEndRect;
1714 WORD Bands = 0, MaxBands = 0;
1715 WORD *Param, *StartBand;
1716 BOOL ret;
1718 len = GetRegionData( hrgn, 0, NULL );
1719 if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1720 WARN(metafile, "MF_CreateRegion: can't alloc rgndata buffer\n");
1721 return -1;
1723 GetRegionData( hrgn, len, rgndata );
1725 /* Overestimate of length:
1726 * Assume every rect is a separate band -> 6 WORDs per rect
1728 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1729 if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1730 WARN(metafile, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1731 HeapFree( SystemHeap, 0, rgndata );
1732 return -1;
1735 memset(mr, 0, len);
1737 Param = mr->rdParm + 11;
1738 StartBand = NULL;
1740 pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
1741 for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1743 if( StartBand && pCurRect->top == *(StartBand + 1) )
1745 *Param++ = pCurRect->left;
1746 *Param++ = pCurRect->right;
1748 else
1750 if(StartBand)
1752 *StartBand = Param - StartBand - 3;
1753 *Param++ = *StartBand;
1754 if(*StartBand > MaxBands)
1755 MaxBands = *StartBand;
1756 Bands++;
1758 StartBand = Param++;
1759 *Param++ = pCurRect->top;
1760 *Param++ = pCurRect->bottom;
1761 *Param++ = pCurRect->left;
1762 *Param++ = pCurRect->right;
1765 len = Param - (WORD *)mr;
1767 mr->rdParm[0] = 0;
1768 mr->rdParm[1] = 6;
1769 mr->rdParm[2] = 0x1234;
1770 mr->rdParm[3] = 0;
1771 mr->rdParm[4] = len * 2;
1772 mr->rdParm[5] = Bands;
1773 mr->rdParm[6] = MaxBands;
1774 mr->rdParm[7] = rgndata->rdh.rcBound.left;
1775 mr->rdParm[8] = rgndata->rdh.rcBound.top;
1776 mr->rdParm[9] = rgndata->rdh.rcBound.right;
1777 mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
1778 mr->rdFunction = META_CREATEREGION;
1779 mr->rdSize = len / 2;
1780 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );
1781 HeapFree( SystemHeap, 0, mr );
1782 HeapFree( SystemHeap, 0, rgndata );
1783 if(!ret)
1785 WARN(metafile, "MF_CreateRegion: MF_WriteRecord failed\n");
1786 return -1;
1788 return MF_AddHandleDC( dc );