Release 980215
[wine.git] / objects / metafile.c
blob4d426d7126904cf4f94ba547802f7b925d06c281
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 "stddebug.h"
20 #include "debug.h"
22 /******************************************************************
23 * MF_AddHandle
25 * Add a handle to an external handle table and return the index
28 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
30 int i;
32 for (i = 0; i < htlen; i++)
34 if (*(ht->objectHandle + i) == 0)
36 *(ht->objectHandle + i) = hobj;
37 return i;
40 return -1;
44 /******************************************************************
45 * MF_AddHandleDC
47 * Note: this function assumes that we never delete objects.
48 * If we do someday, we'll need to maintain a table to re-use deleted
49 * handles.
51 static int MF_AddHandleDC( DC *dc )
53 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
54 physDev->mh->mtNoObjects++;
55 return physDev->nextHandle++;
59 /******************************************************************
60 * GetMetaFile16 (GDI.124)
62 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
64 return GetMetaFile32A( lpFilename );
68 /******************************************************************
69 * GetMetaFile32A (GDI32.197)
71 * Read a metafile from a file. Returns handle to a disk-based metafile.
73 HMETAFILE32 WINAPI GetMetaFile32A(
74 LPCSTR lpFilename
75 /* pointer to string containing filename to read */
78 HMETAFILE16 hmf;
79 METAHEADER *mh;
80 HFILE32 hFile;
81 DWORD size;
83 dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
85 if (!lpFilename)
86 return 0;
88 hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
89 mh = (METAHEADER *)GlobalLock16(hmf);
91 if (!mh)
93 GlobalFree16(hmf);
94 return 0;
97 if ((hFile = _lopen32(lpFilename, OF_READ)) == HFILE_ERROR32)
99 GlobalFree16(hmf);
100 return 0;
103 if (_lread32(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR32)
105 _lclose32( hFile );
106 GlobalFree16(hmf);
107 return 0;
110 size = mh->mtSize * 2; /* alloc memory for whole metafile */
111 GlobalUnlock16(hmf);
112 hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
113 mh = (METAHEADER *)GlobalLock16(hmf);
115 if (!mh)
117 _lclose32( hFile );
118 GlobalFree16(hmf);
119 return 0;
122 if (_lread32(hFile, (char*)mh + mh->mtHeaderSize * 2,
123 size - mh->mtHeaderSize * 2) == HFILE_ERROR32)
125 _lclose32( hFile );
126 GlobalFree16(hmf);
127 return 0;
130 _lclose32(hFile);
132 if (mh->mtType != 1)
134 GlobalFree16(hmf);
135 return 0;
138 GlobalUnlock16(hmf);
139 return hmf;
144 /******************************************************************
145 * GetMetaFile32W (GDI32.199)
147 HMETAFILE32 WINAPI GetMetaFile32W( LPCWSTR lpFilename )
149 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
150 HMETAFILE32 ret = GetMetaFile32A( p );
151 HeapFree( GetProcessHeap(), 0, p );
152 return ret;
156 /******************************************************************
157 * CopyMetaFile16 (GDI.151)
160 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename )
162 return CopyMetaFile32A( hSrcMetaFile, lpFilename );
166 /******************************************************************
167 * CopyMetaFile32A (GDI32.23)
169 * Copies the metafile corresponding to hSrcMetaFile to either
170 * a disk file, if a filename is given, or to a new memory based
171 * metafile, if lpFileName is NULL.
173 * RETURNS
175 * Handle to metafile copy on success, NULL on failure.
177 * BUGS
179 * Copying to disk returns NULL even if successful.
181 HMETAFILE32 WINAPI CopyMetaFile32A(
182 HMETAFILE32 hSrcMetaFile,
183 /* handle of metafile to copy */
184 LPCSTR lpFilename
185 /* filename if copying to a file */
188 HMETAFILE16 handle = 0;
189 METAHEADER *mh;
190 METAHEADER *mh2;
191 HFILE32 hFile;
193 dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename);
195 mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
197 if (!mh)
198 return 0;
200 if (lpFilename) /* disk based metafile */
202 int i,j;
203 hFile = _lcreat32(lpFilename, 0);
204 j=mh->mtType;
205 mh->mtType=1; /* disk file version stores 1 here */
206 i=_lwrite32(hFile, (char *)mh, mh->mtSize * 2) ;
207 mh->mtType=j; /* restore old value [0 or 1] */
208 _lclose32(hFile);
209 if (i == -1)
210 return 0;
211 /* FIXME: return value */
213 else /* memory based metafile */
215 handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
216 mh2 = (METAHEADER *)GlobalLock16(handle);
217 memcpy(mh2,mh, mh->mtSize * 2);
218 GlobalUnlock16(handle);
221 return handle;
225 /******************************************************************
226 * CopyMetaFile32W (GDI32.24)
228 HMETAFILE32 WINAPI CopyMetaFile32W( HMETAFILE32 hSrcMetaFile,
229 LPCWSTR lpFilename )
231 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
232 HMETAFILE32 ret = CopyMetaFile32A( hSrcMetaFile, p );
233 HeapFree( GetProcessHeap(), 0, p );
234 return ret;
238 /******************************************************************
239 * IsValidMetaFile (GDI.410)
241 * Attempts to check if a given metafile is correctly formatted.
242 * Currently, the only things verified are several properties of the
243 * header.
245 * RETURNS
246 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
248 * BUGS
249 * This is not exactly what windows does, see _Undocumented_Windows_
250 * for details.
253 BOOL16 WINAPI IsValidMetaFile(HMETAFILE16 hmf)
255 BOOL16 resu=FALSE;
256 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
257 if (mh) {
258 if (mh->mtType == 1 || mh->mtType == 0)
259 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
260 if (mh->mtVersion == MFVERSION)
261 resu=TRUE;
262 GlobalUnlock16(hmf);
264 dprintf_metafile(stddeb,"IsValidMetaFile %x => %d\n",hmf,resu);
265 return resu;
269 /******************************************************************
270 * PlayMetaFile16 (GDI.123)
273 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
275 return PlayMetaFile32( hdc, hmf );
278 /******************************************************************
279 * PlayMetaFile32 (GDI32.265)
281 * Renders the metafile specified by hmf in the DC specified by
282 * hdc. Returns FALSE on failure, TRUE on success.
284 BOOL32 WINAPI PlayMetaFile32(
285 HDC32 hdc, /* handle of DC to render in */
286 HMETAFILE32 hmf /* handle of metafile to render */
289 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
290 METARECORD *mr;
291 HANDLETABLE16 *ht;
292 HGLOBAL16 hHT;
293 int offset = 0;
294 WORD i;
295 HPEN32 hPen;
296 HBRUSH32 hBrush;
297 HFONT32 hFont;
298 DC *dc;
300 dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf);
301 if (!mh) return FALSE;
302 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
303 hPen = dc->w.hPen;
304 hBrush = dc->w.hBrush;
305 hFont = dc->w.hFont;
306 GDI_HEAP_UNLOCK(hdc);
307 /* create the handle table */
308 hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
309 sizeof(HANDLETABLE16) * mh->mtNoObjects);
310 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
313 /* loop through metafile playing records */
314 offset = mh->mtHeaderSize * 2;
315 while (offset < mh->mtSize * 2)
317 mr = (METARECORD *)((char *)mh + offset);
318 dprintf_metafile(stddeb,"offset = %04x size = %08lx\n",
319 offset, mr->rdSize);
320 if (!mr->rdSize) {
321 fprintf(stderr,"METAFILE entry got size 0 at offset %d, total mf length is %ld\n",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 dprintf_metafile(stddeb,"EnumMetaFile(%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 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn );
432 /******************************************************************
433 * PlayMetaFileRecord16 (GDI.176)
435 * Render a single metafile record specified by *mr in the DC hdc, while
436 * using the handle table *ht, of length nHandles,
437 * to store metafile objects.
439 * BUGS
440 * The following metafile records are unimplemented:
442 * FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
443 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
444 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
448 void WINAPI PlayMetaFileRecord16(
449 HDC16 hdc,
450 /* DC to render metafile into */
451 HANDLETABLE16 *ht,
452 /* pointer to handle table for metafile objects */
453 METARECORD *mr,
454 /* pointer to metafile record to render */
455 UINT16 nHandles
456 /* size of handle table */
459 short s1;
460 HANDLE16 hndl;
461 char *ptr;
462 BITMAPINFOHEADER *infohdr;
464 dprintf_metafile(stddeb,
465 "PlayMetaFileRecord(%04x %08lx %08lx %04x) function %04x\n",
466 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
468 switch (mr->rdFunction)
470 case META_EOF:
471 break;
473 case META_DELETEOBJECT:
474 DeleteObject32(*(ht->objectHandle + *(mr->rdParam)));
475 *(ht->objectHandle + *(mr->rdParam)) = 0;
476 break;
478 case META_SETBKCOLOR:
479 SetBkColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
480 break;
482 case META_SETBKMODE:
483 SetBkMode16(hdc, *(mr->rdParam));
484 break;
486 case META_SETMAPMODE:
487 SetMapMode16(hdc, *(mr->rdParam));
488 break;
490 case META_SETROP2:
491 SetROP216(hdc, *(mr->rdParam));
492 break;
494 case META_SETRELABS:
495 SetRelAbs16(hdc, *(mr->rdParam));
496 break;
498 case META_SETPOLYFILLMODE:
499 SetPolyFillMode16(hdc, *(mr->rdParam));
500 break;
502 case META_SETSTRETCHBLTMODE:
503 SetStretchBltMode16(hdc, *(mr->rdParam));
504 break;
506 case META_SETTEXTCOLOR:
507 SetTextColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
508 break;
510 case META_SETWINDOWORG:
511 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
512 break;
514 case META_SETWINDOWEXT:
515 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
516 break;
518 case META_SETVIEWPORTORG:
519 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
520 break;
522 case META_SETVIEWPORTEXT:
523 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
524 break;
526 case META_OFFSETWINDOWORG:
527 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
528 break;
530 case META_SCALEWINDOWEXT:
531 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
532 *(mr->rdParam + 1), *(mr->rdParam));
533 break;
535 case META_OFFSETVIEWPORTORG:
536 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
537 break;
539 case META_SCALEVIEWPORTEXT:
540 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
541 *(mr->rdParam + 1), *(mr->rdParam));
542 break;
544 case META_LINETO:
545 LineTo32(hdc, (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
546 break;
548 case META_MOVETO:
549 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
550 break;
552 case META_EXCLUDECLIPRECT:
553 ExcludeClipRect16( hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
554 *(mr->rdParam + 1), *(mr->rdParam) );
555 break;
557 case META_INTERSECTCLIPRECT:
558 IntersectClipRect16( hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
559 *(mr->rdParam + 1), *(mr->rdParam) );
560 break;
562 case META_ARC:
563 Arc32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
564 (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
565 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
566 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
567 break;
569 case META_ELLIPSE:
570 Ellipse32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
571 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
572 break;
574 case META_FLOODFILL:
575 FloodFill32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
576 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
577 break;
579 case META_PIE:
580 Pie32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
581 (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
582 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
583 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
584 break;
586 case META_RECTANGLE:
587 Rectangle32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
588 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
589 break;
591 case META_ROUNDRECT:
592 RoundRect32(hdc, (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
593 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
594 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
595 break;
597 case META_PATBLT:
598 PatBlt16(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
599 *(mr->rdParam + 3), *(mr->rdParam + 2),
600 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
601 break;
603 case META_SAVEDC:
604 SaveDC32(hdc);
605 break;
607 case META_SETPIXEL:
608 SetPixel32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
609 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
610 break;
612 case META_OFFSETCLIPRGN:
613 OffsetClipRgn16( hdc, *(mr->rdParam + 1), *(mr->rdParam) );
614 break;
616 case META_TEXTOUT:
617 s1 = *(mr->rdParam);
618 TextOut16(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
619 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
620 (char *)(mr->rdParam + 1), s1);
621 break;
623 case META_POLYGON:
624 Polygon16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
625 break;
627 case META_POLYPOLYGON:
628 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParam + *(mr->rdParam) + 1),
629 (LPINT16)(mr->rdParam + 1), *(mr->rdParam));
630 break;
632 case META_POLYLINE:
633 Polyline16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
634 break;
636 case META_RESTOREDC:
637 RestoreDC32(hdc, (INT16)*(mr->rdParam));
638 break;
640 case META_SELECTOBJECT:
641 SelectObject32(hdc, *(ht->objectHandle + *(mr->rdParam)));
642 break;
644 case META_CHORD:
645 Chord32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
646 (INT16)*(mr->rdParam+5), (INT16)*(mr->rdParam + 4),
647 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
648 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
649 break;
651 case META_CREATEPATTERNBRUSH:
652 switch (*(mr->rdParam))
654 case BS_PATTERN:
655 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
656 MF_AddHandle(ht, nHandles,
657 CreatePatternBrush32(CreateBitmap32(infohdr->biWidth,
658 infohdr->biHeight,
659 infohdr->biPlanes,
660 infohdr->biBitCount,
661 (LPSTR)(mr->rdParam +
662 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
663 break;
665 case BS_DIBPATTERN:
666 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
667 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
668 ptr = GlobalLock16(hndl);
669 memcpy(ptr, mr->rdParam + 2, s1);
670 GlobalUnlock16(hndl);
671 MF_AddHandle(ht, nHandles,
672 CreateDIBPatternBrush32(hndl, *(mr->rdParam + 1)));
673 GlobalFree16(hndl);
675 break;
677 case META_CREATEPENINDIRECT:
678 MF_AddHandle(ht, nHandles,
679 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParam))));
680 break;
682 case META_CREATEFONTINDIRECT:
683 MF_AddHandle(ht, nHandles,
684 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParam))));
685 break;
687 case META_CREATEBRUSHINDIRECT:
688 MF_AddHandle(ht, nHandles,
689 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParam))));
690 break;
692 /* W. Magro: Some new metafile operations. Not all debugged. */
693 case META_CREATEPALETTE:
694 MF_AddHandle(ht, nHandles,
695 CreatePalette16((LPLOGPALETTE)mr->rdParam));
696 break;
698 case META_SETTEXTALIGN:
699 SetTextAlign16(hdc, *(mr->rdParam));
700 break;
702 case META_SELECTPALETTE:
703 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
704 break;
706 case META_SETMAPPERFLAGS:
707 SetMapperFlags16(hdc, *(mr->rdParam));
708 break;
710 case META_REALIZEPALETTE:
711 RealizePalette16(hdc);
712 break;
714 case META_ESCAPE:
715 dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
716 break;
718 /* --- Begin of fixed or new metafile operations. July 1996 ----*/
719 case META_EXTTEXTOUT:
721 LPINT16 dxx;
722 LPSTR sot;
723 DWORD len;
725 s1 = mr->rdParam[2]; /* String length */
726 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
727 + sizeof(UINT16) + (mr->rdParam[3] ? sizeof(RECT16) : 0); /* rec len without dx array */
729 sot= (LPSTR)&mr->rdParam[4]; /* start_of_text */
730 if (mr->rdParam[3])
731 sot+=sizeof(RECT16); /* there is a rectangle, so add offset */
733 if (mr->rdSize == len / 2)
734 dxx = NULL; /* determine if array present */
735 else
736 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
737 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
738 else
740 dprintf_metafile(stddeb,"EXTTEXTOUT: %s len: %ld\n",
741 sot,mr->rdSize);
742 fprintf(stderr,
743 "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
744 len,s1,mr->rdSize,mr->rdParam[3]);
745 dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
747 ExtTextOut16( hdc, mr->rdParam[1], /* X position */
748 mr->rdParam[0], /* Y position */
749 mr->rdParam[3], /* options */
750 mr->rdParam[3] ? (LPRECT16) &mr->rdParam[4]:NULL, /* rectangle */
751 sot, /* string */
752 s1, dxx); /* length, dx array */
753 if (dxx)
754 dprintf_metafile(stddeb,"EXTTEXTOUT: %s len: %ld dx0: %d\n",
755 sot,mr->rdSize,dxx[0]);
757 break;
759 case META_STRETCHDIB:
761 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]);
762 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
763 StretchDIBits16(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
764 mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
765 mr->rdParam[4],mr->rdParam[3],bits,info,
766 mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1]));
768 break;
770 case META_DIBSTRETCHBLT:
772 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]);
773 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
774 StretchDIBits16(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
775 mr->rdParam[6],mr->rdParam[5],mr->rdParam[4],
776 mr->rdParam[3],mr->rdParam[2],bits,info,
777 DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
779 break;
781 case META_STRETCHBLT:
783 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
784 HBITMAP32 hbitmap=CreateBitmap32(mr->rdParam[10], /*Width */
785 mr->rdParam[11], /*Height*/
786 mr->rdParam[13], /*Planes*/
787 mr->rdParam[14], /*BitsPixel*/
788 (LPSTR)&mr->rdParam[15]); /*bits*/
789 SelectObject32(hdcSrc,hbitmap);
790 StretchBlt16(hdc,mr->rdParam[9],mr->rdParam[8],
791 mr->rdParam[7],mr->rdParam[6],
792 hdcSrc,mr->rdParam[5],mr->rdParam[4],
793 mr->rdParam[3],mr->rdParam[2],
794 MAKELONG(mr->rdParam[0],mr->rdParam[1]));
795 DeleteDC32(hdcSrc);
797 break;
799 case META_BITBLT: /* <-- not yet debugged */
801 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
802 HBITMAP32 hbitmap=CreateBitmap32(mr->rdParam[7]/*Width */,
803 mr->rdParam[8]/*Height*/,
804 mr->rdParam[10]/*Planes*/,
805 mr->rdParam[11]/*BitsPixel*/,
806 (LPSTR)&mr->rdParam[12]/*bits*/);
807 SelectObject32(hdcSrc,hbitmap);
808 BitBlt32(hdc,(INT16)mr->rdParam[6],(INT16)mr->rdParam[5],
809 (INT16)mr->rdParam[4],(INT16)mr->rdParam[3],
810 hdcSrc, (INT16)mr->rdParam[2],(INT16)mr->rdParam[1],
811 MAKELONG(0,mr->rdParam[0]));
812 DeleteDC32(hdcSrc);
814 break;
816 /* --- Begin of new metafile operations. April, 1997 (ak) ----*/
817 case META_CREATEREGION:
819 HRGN32 hrgn = CreateRectRgn32(0,0,0,0);
821 MF_Meta_CreateRegion(mr, hrgn);
822 MF_AddHandle(ht, nHandles, hrgn);
824 break;
826 case META_FILLREGION:
827 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)),
828 *(ht->objectHandle + *(mr->rdParam+1)));
829 break;
831 case META_INVERTREGION:
832 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)));
833 break;
835 case META_PAINTREGION:
836 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)));
837 break;
839 case META_SELECTCLIPREGION:
840 SelectClipRgn32(hdc, *(ht->objectHandle + *(mr->rdParam)));
841 break;
843 case META_DIBCREATEPATTERNBRUSH:
844 /* *(mr->rdParam) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
845 dprintf_metafile(stddeb,"META_DIBCREATEPATTERNBRUSH: %d\n",*(mr->rdParam));
846 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
847 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
848 ptr = GlobalLock16(hndl);
849 memcpy(ptr, mr->rdParam + 2, s1);
850 GlobalUnlock16(hndl);
851 MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParam + 1)));
852 GlobalFree16(hndl);
853 break;
855 case META_DIBBITBLT:
857 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[8]);
858 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[0] );
859 StretchDIBits16(hdc,mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
860 mr->rdParam[4],mr->rdParam[3],mr->rdParam[2],
861 mr->rdParam[5],mr->rdParam[4],bits,info,
862 DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
864 break;
866 case META_SETTEXTCHAREXTRA:
867 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParam));
868 break;
870 case META_SETTEXTJUSTIFICATION:
871 SetTextJustification32(hdc, *(mr->rdParam + 1), *(mr->rdParam));
872 break;
874 #define META_UNIMP(x) case x: fprintf(stderr,"PlayMetaFileRecord:record type "#x" not implemented.\n");break;
875 META_UNIMP(META_FRAMEREGION)
876 META_UNIMP(META_DRAWTEXT)
877 META_UNIMP(META_SETDIBTODEV)
878 META_UNIMP(META_ANIMATEPALETTE)
879 META_UNIMP(META_SETPALENTRIES)
880 META_UNIMP(META_RESIZEPALETTE)
881 META_UNIMP(META_EXTFLOODFILL)
882 META_UNIMP(META_RESETDC)
883 META_UNIMP(META_STARTDOC)
884 META_UNIMP(META_STARTPAGE)
885 META_UNIMP(META_ENDPAGE)
886 META_UNIMP(META_ABORTDOC)
887 META_UNIMP(META_ENDDOC)
888 META_UNIMP(META_CREATEBRUSH)
889 META_UNIMP(META_CREATEBITMAPINDIRECT)
890 META_UNIMP(META_CREATEBITMAP)
891 #undef META_UNIMP
893 default:
894 fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
895 mr->rdFunction);
900 /******************************************************************
901 * GetMetaFileBits (GDI.159)
903 * Trade in a metafile object handle for a handle to the metafile memory.
907 HGLOBAL16 WINAPI GetMetaFileBits(
908 HMETAFILE16 hmf /* metafile handle */
911 dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hmf);
912 return hmf;
915 /******************************************************************
916 * SetMetaFileBits (GDI.160)
918 * Trade in a metafile memory handle for a handle to a metafile object.
919 * The memory region should hold a proper metafile, otherwise
920 * problems will occur when it is used. Validity of the memory is not
921 * checked. The function is essentially just the identity function.
923 HMETAFILE16 WINAPI SetMetaFileBits(
924 HGLOBAL16 hMem
925 /* handle to a memory region holding a metafile */
928 dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hMem);
930 return hMem;
933 /******************************************************************
934 * SetMetaFileBitsBetter (GDI.196)
936 * Trade in a metafile memory handle for a handle to a metafile object,
937 * making a cursory check (using IsValidMetaFile()) that the memory
938 * handle points to a valid metafile.
940 * RETURNS
941 * Handle to a metafile on success, NULL on failure..
943 HMETAFILE16 WINAPI SetMetaFileBitsBetter( HMETAFILE16 hMeta )
945 if( IsValidMetaFile( hMeta ) )
946 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
947 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
948 return (HMETAFILE16)0;
951 /******************************************************************
952 * MF_Meta_CreateRegion
954 * Handles META_CREATEREGION for PlayMetaFileRecord().
958 * The layout of the record looks something like this:
960 * rdParam meaning
961 * 0 Always 0?
962 * 1 Always 6?
963 * 2 Looks like a handle? - not constant
964 * 3 0 or 1 ??
965 * 4 Total number of bytes
966 * 5 No. of seperate bands = n [see below]
967 * 6 Largest number of x co-ords in a band
968 * 7-10 Bounding box x1 y1 x2 y2
969 * 11-... n bands
971 * Regions are divided into bands that are uniform in the
972 * y-direction. Each band consists of pairs of on/off x-coords and is
973 * written as
974 * m y0 y1 x1 x2 x3 ... xm m
975 * into successive rdParam[]s.
977 * This is probably just a dump of the internal RGNOBJ?
979 * HDMD - 18/12/97
983 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn )
985 WORD band, pair;
986 WORD *start, *end;
987 INT16 y0, y1;
988 HRGN32 hrgn2 = CreateRectRgn32( 0, 0, 0, 0 );
990 for(band = 0, start = &(mr->rdParam[11]); band < mr->rdParam[5];
991 band++, start = end + 1) {
992 if(*start / 2 != (*start + 1) / 2) {
993 fprintf(stderr, "META_CREATEREGION: delimiter not even.\n");
994 DeleteObject32( hrgn2 );
995 return FALSE;
998 end = start + *start + 3;
999 if(end > (WORD *)mr + mr->rdSize) {
1000 fprintf(stderr, "META_CREATEREGION: end points outside record.\n");
1001 DeleteObject32( hrgn2 );
1002 return FALSE;
1005 if(*start != *end) {
1006 fprintf(stderr, "META_CREATEREGION: mismatched delimiters.\n");
1007 DeleteObject32( hrgn2 );
1008 return FALSE;
1011 y0 = *(INT16 *)(start + 1);
1012 y1 = *(INT16 *)(start + 2);
1013 for(pair = 0; pair < *start / 2; pair++) {
1014 SetRectRgn32( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1015 *(INT16 *)(start + 4 + 2*pair), y1 );
1016 CombineRgn32(hrgn, hrgn, hrgn2, RGN_OR);
1019 DeleteObject32( hrgn2 );
1020 return TRUE;
1024 /******************************************************************
1025 * MF_WriteRecord
1027 * Warning: this function can change the metafile handle.
1030 static BOOL32 MF_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
1032 DWORD len;
1033 METAHEADER *mh;
1034 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1036 switch(physDev->mh->mtType)
1038 case METAFILE_MEMORY:
1039 len = physDev->mh->mtSize * 2 + rlen;
1040 mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1041 if (!mh) return FALSE;
1042 physDev->mh = mh;
1043 memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1044 break;
1045 case METAFILE_DISK:
1046 dprintf_metafile(stddeb,"Writing record to disk\n");
1047 if (_lwrite32(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1048 return FALSE;
1049 break;
1050 default:
1051 fprintf( stderr, "Unknown metafile type %d\n", physDev->mh->mtType );
1052 return FALSE;
1055 physDev->mh->mtSize += rlen / 2;
1056 physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1057 return TRUE;
1061 /******************************************************************
1062 * MF_MetaParam0
1065 BOOL32 MF_MetaParam0(DC *dc, short func)
1067 char buffer[8];
1068 METARECORD *mr = (METARECORD *)&buffer;
1070 mr->rdSize = 3;
1071 mr->rdFunction = func;
1072 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1076 /******************************************************************
1077 * MF_MetaParam1
1079 BOOL32 MF_MetaParam1(DC *dc, short func, short param1)
1081 char buffer[8];
1082 METARECORD *mr = (METARECORD *)&buffer;
1084 mr->rdSize = 4;
1085 mr->rdFunction = func;
1086 *(mr->rdParam) = param1;
1087 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1091 /******************************************************************
1092 * MF_MetaParam2
1094 BOOL32 MF_MetaParam2(DC *dc, short func, short param1, short param2)
1096 char buffer[10];
1097 METARECORD *mr = (METARECORD *)&buffer;
1099 mr->rdSize = 5;
1100 mr->rdFunction = func;
1101 *(mr->rdParam) = param2;
1102 *(mr->rdParam + 1) = param1;
1103 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1107 /******************************************************************
1108 * MF_MetaParam4
1111 BOOL32 MF_MetaParam4(DC *dc, short func, short param1, short param2,
1112 short param3, short param4)
1114 char buffer[14];
1115 METARECORD *mr = (METARECORD *)&buffer;
1117 mr->rdSize = 7;
1118 mr->rdFunction = func;
1119 *(mr->rdParam) = param4;
1120 *(mr->rdParam + 1) = param3;
1121 *(mr->rdParam + 2) = param2;
1122 *(mr->rdParam + 3) = param1;
1123 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1127 /******************************************************************
1128 * MF_MetaParam6
1131 BOOL32 MF_MetaParam6(DC *dc, short func, short param1, short param2,
1132 short param3, short param4, short param5, short param6)
1134 char buffer[18];
1135 METARECORD *mr = (METARECORD *)&buffer;
1137 mr->rdSize = 9;
1138 mr->rdFunction = func;
1139 *(mr->rdParam) = param6;
1140 *(mr->rdParam + 1) = param5;
1141 *(mr->rdParam + 2) = param4;
1142 *(mr->rdParam + 3) = param3;
1143 *(mr->rdParam + 4) = param2;
1144 *(mr->rdParam + 5) = param1;
1145 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1149 /******************************************************************
1150 * MF_MetaParam8
1152 BOOL32 MF_MetaParam8(DC *dc, short func, short param1, short param2,
1153 short param3, short param4, short param5,
1154 short param6, short param7, short param8)
1156 char buffer[22];
1157 METARECORD *mr = (METARECORD *)&buffer;
1159 mr->rdSize = 11;
1160 mr->rdFunction = func;
1161 *(mr->rdParam) = param8;
1162 *(mr->rdParam + 1) = param7;
1163 *(mr->rdParam + 2) = param6;
1164 *(mr->rdParam + 3) = param5;
1165 *(mr->rdParam + 4) = param4;
1166 *(mr->rdParam + 5) = param3;
1167 *(mr->rdParam + 6) = param2;
1168 *(mr->rdParam + 7) = param1;
1169 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1173 /******************************************************************
1174 * MF_CreateBrushIndirect
1177 BOOL32 MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1179 int index;
1180 char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1181 METARECORD *mr = (METARECORD *)&buffer;
1183 mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1184 mr->rdFunction = META_CREATEBRUSHINDIRECT;
1185 memcpy(&(mr->rdParam), logbrush, sizeof(*logbrush));
1186 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1188 mr->rdSize = sizeof(METARECORD) / 2;
1189 mr->rdFunction = META_SELECTOBJECT;
1191 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1192 *(mr->rdParam) = index;
1193 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1197 /******************************************************************
1198 * MF_CreatePatternBrush
1201 BOOL32 MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1203 DWORD len, bmSize, biSize;
1204 HGLOBAL16 hmr;
1205 METARECORD *mr;
1206 BITMAPOBJ *bmp;
1207 BITMAPINFO *info;
1208 BITMAPINFOHEADER *infohdr;
1209 int index;
1210 char buffer[sizeof(METARECORD)];
1212 switch (logbrush->lbStyle)
1214 case BS_PATTERN:
1215 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1216 if (!bmp) return FALSE;
1217 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
1218 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1219 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1221 GDI_HEAP_UNLOCK((HGDIOBJ16)logbrush->lbHatch);
1222 return FALSE;
1224 mr = (METARECORD *)GlobalLock16(hmr);
1225 memset(mr, 0, len);
1226 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1227 mr->rdSize = len / 2;
1228 *(mr->rdParam) = logbrush->lbStyle;
1229 *(mr->rdParam + 1) = DIB_RGB_COLORS;
1230 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
1231 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1232 infohdr->biWidth = bmp->bitmap.bmWidth;
1233 infohdr->biHeight = bmp->bitmap.bmHeight;
1234 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1235 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1236 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1237 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1238 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1239 GDI_HEAP_UNLOCK(logbrush->lbHatch);
1240 break;
1242 case BS_DIBPATTERN:
1243 info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1244 if (info->bmiHeader.biCompression)
1245 bmSize = info->bmiHeader.biSizeImage;
1246 else
1247 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1248 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1249 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1250 len = sizeof(METARECORD) + biSize + bmSize + 2;
1251 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1252 return FALSE;
1253 mr = (METARECORD *)GlobalLock16(hmr);
1254 memset(mr, 0, len);
1255 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1256 mr->rdSize = len / 2;
1257 *(mr->rdParam) = logbrush->lbStyle;
1258 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
1259 memcpy(mr->rdParam + 2, info, biSize + bmSize);
1260 break;
1261 default:
1262 return FALSE;
1264 if (!(MF_WriteRecord(dc, mr, len)))
1266 GlobalFree16(hmr);
1267 return FALSE;
1270 GlobalFree16(hmr);
1272 mr = (METARECORD *)&buffer;
1273 mr->rdSize = sizeof(METARECORD) / 2;
1274 mr->rdFunction = META_SELECTOBJECT;
1276 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1277 *(mr->rdParam) = index;
1278 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1282 /******************************************************************
1283 * MF_CreatePenIndirect
1286 BOOL32 MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1288 int index;
1289 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1290 METARECORD *mr = (METARECORD *)&buffer;
1292 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1293 mr->rdFunction = META_CREATEPENINDIRECT;
1294 memcpy(&(mr->rdParam), logpen, sizeof(*logpen));
1295 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1297 mr->rdSize = sizeof(METARECORD) / 2;
1298 mr->rdFunction = META_SELECTOBJECT;
1300 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1301 *(mr->rdParam) = index;
1302 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1306 /******************************************************************
1307 * MF_CreateFontIndirect
1310 BOOL32 MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1312 int index;
1313 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1314 METARECORD *mr = (METARECORD *)&buffer;
1316 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1317 mr->rdFunction = META_CREATEFONTINDIRECT;
1318 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT16));
1319 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1321 mr->rdSize = sizeof(METARECORD) / 2;
1322 mr->rdFunction = META_SELECTOBJECT;
1324 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1325 *(mr->rdParam) = index;
1326 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1330 /******************************************************************
1331 * MF_TextOut
1333 BOOL32 MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1335 BOOL32 ret;
1336 DWORD len;
1337 HGLOBAL16 hmr;
1338 METARECORD *mr;
1340 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1341 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1342 return FALSE;
1343 mr = (METARECORD *)GlobalLock16(hmr);
1344 memset(mr, 0, len);
1346 mr->rdSize = len / 2;
1347 mr->rdFunction = META_TEXTOUT;
1348 *(mr->rdParam) = count;
1349 memcpy(mr->rdParam + 1, str, count);
1350 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1351 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1352 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1353 GlobalFree16(hmr);
1354 return ret;
1357 /******************************************************************
1358 * MF_ExtTextOut
1360 BOOL32 MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1361 LPCSTR str, short count, const INT16 *lpDx)
1363 BOOL32 ret;
1364 DWORD len;
1365 HGLOBAL16 hmr;
1366 METARECORD *mr;
1368 if((!flags && rect) || (flags && !rect))
1369 fprintf(stderr, "MF_ExtTextOut: Inconsistent flags and rect\n");
1370 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1371 + sizeof(UINT16);
1372 if(rect)
1373 len += sizeof(RECT16);
1374 if (lpDx)
1375 len+=count*sizeof(INT16);
1376 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1377 return FALSE;
1378 mr = (METARECORD *)GlobalLock16(hmr);
1379 memset(mr, 0, len);
1381 mr->rdSize = len / 2;
1382 mr->rdFunction = META_EXTTEXTOUT;
1383 *(mr->rdParam) = y;
1384 *(mr->rdParam + 1) = x;
1385 *(mr->rdParam + 2) = count;
1386 *(mr->rdParam + 3) = flags;
1387 if (rect) memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
1388 memcpy(mr->rdParam + (rect ? 8 : 4), str, count);
1389 if (lpDx)
1390 memcpy(mr->rdParam + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1391 count*sizeof(INT16));
1392 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1393 GlobalFree16(hmr);
1394 return ret;
1397 /******************************************************************
1398 * MF_MetaPoly - implements Polygon and Polyline
1400 BOOL32 MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1402 BOOL32 ret;
1403 DWORD len;
1404 HGLOBAL16 hmr;
1405 METARECORD *mr;
1407 len = sizeof(METARECORD) + (count * 4);
1408 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1409 return FALSE;
1410 mr = (METARECORD *)GlobalLock16(hmr);
1411 memset(mr, 0, len);
1413 mr->rdSize = len / 2;
1414 mr->rdFunction = func;
1415 *(mr->rdParam) = count;
1416 memcpy(mr->rdParam + 1, pt, count * 4);
1417 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1418 GlobalFree16(hmr);
1419 return ret;
1423 /******************************************************************
1424 * MF_BitBlt
1426 BOOL32 MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1427 short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1429 BOOL32 ret;
1430 DWORD len;
1431 HGLOBAL16 hmr;
1432 METARECORD *mr;
1433 BITMAP16 BM;
1435 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1436 len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1437 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1438 return FALSE;
1439 mr = (METARECORD *)GlobalLock16(hmr);
1440 mr->rdFunction = META_BITBLT;
1441 *(mr->rdParam + 7) = BM.bmWidth;
1442 *(mr->rdParam + 8) = BM.bmHeight;
1443 *(mr->rdParam + 9) = BM.bmWidthBytes;
1444 *(mr->rdParam +10) = BM.bmPlanes;
1445 *(mr->rdParam +11) = BM.bmBitsPixel;
1446 dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1447 if (GetBitmapBits32(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1448 mr->rdParam +12))
1450 mr->rdSize = len / sizeof(INT16);
1451 *(mr->rdParam) = HIWORD(rop);
1452 *(mr->rdParam + 1) = ySrc;
1453 *(mr->rdParam + 2) = xSrc;
1454 *(mr->rdParam + 3) = height;
1455 *(mr->rdParam + 4) = width;
1456 *(mr->rdParam + 5) = yDest;
1457 *(mr->rdParam + 6) = xDest;
1458 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1460 else
1461 ret = FALSE;
1462 GlobalFree16(hmr);
1463 return ret;
1467 /**********************************************************************
1468 * MF_StretchBlt
1469 * this function contains TWO ways for procesing StretchBlt in metafiles,
1470 * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT
1471 * via #define STRETCH_VIA_DIB
1473 #define STRETCH_VIA_DIB
1474 #undef STRETCH_VIA_DIB
1475 BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1476 short heightDest, DC *dcSrc, short xSrc, short ySrc,
1477 short widthSrc, short heightSrc, DWORD rop)
1479 BOOL32 ret;
1480 DWORD len;
1481 HGLOBAL16 hmr;
1482 METARECORD *mr;
1483 BITMAP16 BM;
1484 #ifdef STRETCH_VIA_DIB
1485 LPBITMAPINFOHEADER lpBMI;
1486 WORD nBPP;
1487 #endif
1488 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1489 #ifdef STRETCH_VIA_DIB
1490 nBPP = BM.bmPlanes * BM.bmBitsPixel;
1491 len = sizeof(METARECORD) + 10 * sizeof(INT16)
1492 + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
1493 + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1494 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1495 return FALSE;
1496 mr = (METARECORD *)GlobalLock16(hmr);
1497 mr->rdFunction = META_DIBSTRETCHBLT;
1498 lpBMI=(LPBITMAPINFOHEADER)(mr->rdParam+10);
1499 lpBMI->biSize = sizeof(BITMAPINFOHEADER);
1500 lpBMI->biWidth = BM.bmWidth;
1501 lpBMI->biHeight = BM.bmHeight;
1502 lpBMI->biPlanes = 1;
1503 lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */
1504 lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0;
1505 lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1506 lpBMI->biCompression = BI_RGB;
1507 lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1508 lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1509 lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */
1511 dprintf_metafile(stddeb,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n",
1512 len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1513 if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT32)lpBMI->biHeight,
1514 (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1515 DIB_RGB_COLORS ),
1516 (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1517 #else
1518 len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1519 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1520 return FALSE;
1521 mr = (METARECORD *)GlobalLock16(hmr);
1522 mr->rdFunction = META_STRETCHBLT;
1523 *(mr->rdParam +10) = BM.bmWidth;
1524 *(mr->rdParam +11) = BM.bmHeight;
1525 *(mr->rdParam +12) = BM.bmWidthBytes;
1526 *(mr->rdParam +13) = BM.bmPlanes;
1527 *(mr->rdParam +14) = BM.bmBitsPixel;
1528 dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1529 if (GetBitmapBits32( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1530 mr->rdParam +15))
1531 #endif
1533 mr->rdSize = len / sizeof(INT16);
1534 *(mr->rdParam) = LOWORD(rop);
1535 *(mr->rdParam + 1) = HIWORD(rop);
1536 *(mr->rdParam + 2) = heightSrc;
1537 *(mr->rdParam + 3) = widthSrc;
1538 *(mr->rdParam + 4) = ySrc;
1539 *(mr->rdParam + 5) = xSrc;
1540 *(mr->rdParam + 6) = heightDest;
1541 *(mr->rdParam + 7) = widthDest;
1542 *(mr->rdParam + 8) = yDest;
1543 *(mr->rdParam + 9) = xDest;
1544 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1546 else
1547 ret = FALSE;
1548 GlobalFree16(hmr);
1549 return ret;
1553 /******************************************************************
1554 * MF_CreateRegion
1556 INT16 MF_CreateRegion(DC *dc, HRGN32 hrgn)
1558 DWORD len;
1559 METARECORD *mr;
1560 RGNDATA *rgndata;
1561 RECT32 *pCurRect, *pEndRect;
1562 WORD Bands = 0, MaxBands = 0;
1563 WORD *Param, *StartBand;
1564 BOOL32 ret;
1566 len = GetRegionData( hrgn, 0, NULL );
1567 if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1568 fprintf(stderr, "MF_CreateRegion: can't alloc rgndata buffer\n");
1569 return -1;
1571 GetRegionData( hrgn, len, rgndata );
1573 /* Overestimate of length:
1574 * Assume every rect is a separate band -> 6 WORDs per rect
1576 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1577 if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1578 fprintf(stderr, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1579 HeapFree( SystemHeap, 0, rgndata );
1580 return -1;
1583 memset(mr, 0, len);
1585 Param = mr->rdParam + 11;
1586 StartBand = NULL;
1588 pEndRect = (RECT32 *)rgndata->Buffer + rgndata->rdh.nCount;
1589 for(pCurRect = (RECT32 *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1591 if( StartBand && pCurRect->top == *(StartBand + 1) )
1593 *Param++ = pCurRect->left;
1594 *Param++ = pCurRect->right;
1596 else
1598 if(StartBand)
1600 *StartBand = Param - StartBand - 3;
1601 *Param++ = *StartBand;
1602 if(*StartBand > MaxBands)
1603 MaxBands = *StartBand;
1604 Bands++;
1606 StartBand = Param++;
1607 *Param++ = pCurRect->top;
1608 *Param++ = pCurRect->bottom;
1609 *Param++ = pCurRect->left;
1610 *Param++ = pCurRect->right;
1613 len = Param - (WORD *)mr;
1615 mr->rdParam[0] = 0;
1616 mr->rdParam[1] = 6;
1617 mr->rdParam[2] = 0x1234;
1618 mr->rdParam[3] = 0;
1619 mr->rdParam[4] = len * 2;
1620 mr->rdParam[5] = Bands;
1621 mr->rdParam[6] = MaxBands;
1622 mr->rdParam[7] = rgndata->rdh.rcBound.left;
1623 mr->rdParam[8] = rgndata->rdh.rcBound.top;
1624 mr->rdParam[9] = rgndata->rdh.rcBound.right;
1625 mr->rdParam[10] = rgndata->rdh.rcBound.bottom;
1626 mr->rdFunction = META_CREATEREGION;
1627 mr->rdSize = len / 2;
1628 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );
1629 HeapFree( SystemHeap, 0, mr );
1630 HeapFree( SystemHeap, 0, rgndata );
1631 if(!ret)
1633 fprintf(stderr, "MF_CreateRegion: MF_WriteRecord failed\n");
1634 return -1;
1636 return MF_AddHandleDC( dc );