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