Release 980201
[wine/multimedia.git] / objects / metafile.c
blobb390b04a55d8bde27eeef68e642599ebf72ff0ad
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 "stddebug.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 dprintf_metafile(stddeb,"GetMetaFile: %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,
182 /* handle of metafile to copy */
183 LPCSTR lpFilename
184 /* filename if copying to a file */
187 HMETAFILE16 handle = 0;
188 METAHEADER *mh;
189 METAHEADER *mh2;
190 HFILE32 hFile;
192 dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename);
194 mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
196 if (!mh)
197 return 0;
199 if (lpFilename) /* disk based metafile */
201 int i,j;
202 hFile = _lcreat32(lpFilename, 0);
203 j=mh->mtType;
204 mh->mtType=1; /* disk file version stores 1 here */
205 i=_lwrite32(hFile, (char *)mh, mh->mtSize * 2) ;
206 mh->mtType=j; /* restore old value [0 or 1] */
207 _lclose32(hFile);
208 if (i == -1)
209 return 0;
210 /* FIXME: return value */
212 else /* memory based metafile */
214 handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
215 mh2 = (METAHEADER *)GlobalLock16(handle);
216 memcpy(mh2,mh, mh->mtSize * 2);
217 GlobalUnlock16(handle);
220 return handle;
224 /******************************************************************
225 * CopyMetaFile32W (GDI32.24)
227 HMETAFILE32 WINAPI CopyMetaFile32W( HMETAFILE32 hSrcMetaFile,
228 LPCWSTR lpFilename )
230 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
231 HMETAFILE32 ret = CopyMetaFile32A( hSrcMetaFile, p );
232 HeapFree( GetProcessHeap(), 0, p );
233 return ret;
237 /******************************************************************
238 * IsValidMetaFile (GDI.410)
240 * Attempts to check if a given metafile is correctly formatted.
241 * Currently, the only things verified are several properties of the
242 * header.
244 * RETURNS
245 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
247 * BUGS
248 * This is not exactly what windows does, see _Undocumented_Windows_
249 * for details.
252 BOOL16 WINAPI IsValidMetaFile(HMETAFILE16 hmf)
254 BOOL16 resu=FALSE;
255 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
256 if (mh) {
257 if (mh->mtType == 1 || mh->mtType == 0)
258 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
259 if (mh->mtVersion == MFVERSION)
260 resu=TRUE;
261 GlobalUnlock16(hmf);
263 dprintf_metafile(stddeb,"IsValidMetaFile %x => %d\n",hmf,resu);
264 return resu;
268 /******************************************************************
269 * PlayMetaFile16 (GDI.123)
272 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
274 return PlayMetaFile32( hdc, hmf );
277 /******************************************************************
278 * PlayMetaFile32 (GDI32.265)
280 * Renders the metafile specified by hmf in the DC specified by
281 * hdc. Returns FALSE on failure, TRUE on success.
283 BOOL32 WINAPI PlayMetaFile32(
284 HDC32 hdc, /* handle of DC to render in */
285 HMETAFILE32 hmf /* handle of metafile to render */
288 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
289 METARECORD *mr;
290 HANDLETABLE16 *ht;
291 HGLOBAL16 hHT;
292 int offset = 0;
293 WORD i;
294 HPEN32 hPen;
295 HBRUSH32 hBrush;
296 HFONT32 hFont;
297 DC *dc;
299 dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf);
300 if (!mh) return FALSE;
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 dprintf_metafile(stddeb,"offset = %04x size = %08lx\n",
318 offset, mr->rdSize);
319 if (!mr->rdSize) {
320 fprintf(stderr,"METAFILE entry got size 0 at offset %d, total mf length is %ld\n",offset,mh->mtSize*2);
321 break; /* would loop endlessly otherwise */
323 offset += mr->rdSize * 2;
324 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
327 SelectObject32(hdc, hBrush);
328 SelectObject32(hdc, hPen);
329 SelectObject32(hdc, hFont);
331 /* free objects in handle table */
332 for(i = 0; i < mh->mtNoObjects; i++)
333 if(*(ht->objectHandle + i) != 0)
334 DeleteObject32(*(ht->objectHandle + i));
336 /* free handle table */
337 GlobalFree16(hHT);
339 return TRUE;
343 /******************************************************************
344 * EnumMetaFile16 (GDI.175)
346 * Loop through the metafile records in hmf, calling the user-specified
347 * function for each one, stopping when the user's function returns FALSE
348 * (which is considered to be failure)
349 * or when no records are left (which is considered to be success).
351 * RETURNS
352 * TRUE on success, FALSE on failure.
354 * HISTORY
355 * Niels de carpentier, april 1996
357 BOOL16 WINAPI EnumMetaFile16(
358 HDC16 hdc,
359 HMETAFILE16 hmf,
360 MFENUMPROC16 lpEnumFunc,
361 LPARAM lpData
364 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
365 METARECORD *mr;
366 HANDLETABLE16 *ht;
367 HGLOBAL16 hHT;
368 SEGPTR spht, spRecord;
369 int offset = 0;
370 WORD i;
371 HPEN32 hPen;
372 HBRUSH32 hBrush;
373 HFONT32 hFont;
374 DC *dc;
375 BOOL16 result = TRUE;
377 dprintf_metafile(stddeb,"EnumMetaFile(%04x, %04x, %08lx, %08lx)\n",
378 hdc, hmf, (DWORD)lpEnumFunc, lpData);
380 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
381 hPen = dc->w.hPen;
382 hBrush = dc->w.hBrush;
383 hFont = dc->w.hFont;
384 GDI_HEAP_UNLOCK(hdc);
386 /* create the handle table */
388 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
389 sizeof(HANDLETABLE16) * mh->mtNoObjects);
390 spht = WIN16_GlobalLock16(hHT);
392 offset = mh->mtHeaderSize * 2;
394 /* loop through metafile records */
396 spRecord = WIN16_GlobalLock16(hmf);
397 while (offset < (mh->mtSize * 2))
399 mr = (METARECORD *)((char *)mh + offset);
400 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
401 (METARECORD *)((UINT32)spRecord + offset),
402 mh->mtNoObjects, (LONG)lpData)) {
403 result = FALSE;
404 break;
408 offset += (mr->rdSize * 2);
411 SelectObject32(hdc, hBrush);
412 SelectObject32(hdc, hPen);
413 SelectObject32(hdc, hFont);
415 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
417 /* free objects in handle table */
418 for(i = 0; i < mh->mtNoObjects; i++)
419 if(*(ht->objectHandle + i) != 0)
420 DeleteObject32(*(ht->objectHandle + i));
422 /* free handle table */
423 GlobalFree16(hHT);
425 return result;
428 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn );
430 /******************************************************************
431 * PlayMetaFileRecord16 (GDI.176)
433 * Render a single metafile record specified by *mr in the DC hdc, while
434 * using the handle table *ht, of length nHandles,
435 * to store metafile objects.
437 * BUGS
438 * The following metafile records are unimplemented:
440 * FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
441 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
442 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
446 void WINAPI PlayMetaFileRecord16(
447 HDC16 hdc,
448 /* DC to render metafile into */
449 HANDLETABLE16 *ht,
450 /* pointer to handle table for metafile objects */
451 METARECORD *mr,
452 /* pointer to metafile record to render */
453 UINT16 nHandles
454 /* size of handle table */
457 short s1;
458 HANDLE16 hndl;
459 char *ptr;
460 BITMAPINFOHEADER *infohdr;
462 dprintf_metafile(stddeb,
463 "PlayMetaFileRecord(%04x %08lx %08lx %04x) function %04x\n",
464 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
466 switch (mr->rdFunction)
468 case META_EOF:
469 break;
471 case META_DELETEOBJECT:
472 DeleteObject32(*(ht->objectHandle + *(mr->rdParam)));
473 *(ht->objectHandle + *(mr->rdParam)) = 0;
474 break;
476 case META_SETBKCOLOR:
477 SetBkColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
478 break;
480 case META_SETBKMODE:
481 SetBkMode16(hdc, *(mr->rdParam));
482 break;
484 case META_SETMAPMODE:
485 SetMapMode16(hdc, *(mr->rdParam));
486 break;
488 case META_SETROP2:
489 SetROP216(hdc, *(mr->rdParam));
490 break;
492 case META_SETRELABS:
493 SetRelAbs16(hdc, *(mr->rdParam));
494 break;
496 case META_SETPOLYFILLMODE:
497 SetPolyFillMode16(hdc, *(mr->rdParam));
498 break;
500 case META_SETSTRETCHBLTMODE:
501 SetStretchBltMode16(hdc, *(mr->rdParam));
502 break;
504 case META_SETTEXTCOLOR:
505 SetTextColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
506 break;
508 case META_SETWINDOWORG:
509 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
510 break;
512 case META_SETWINDOWEXT:
513 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
514 break;
516 case META_SETVIEWPORTORG:
517 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
518 break;
520 case META_SETVIEWPORTEXT:
521 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
522 break;
524 case META_OFFSETWINDOWORG:
525 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
526 break;
528 case META_SCALEWINDOWEXT:
529 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
530 *(mr->rdParam + 1), *(mr->rdParam));
531 break;
533 case META_OFFSETVIEWPORTORG:
534 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
535 break;
537 case META_SCALEVIEWPORTEXT:
538 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
539 *(mr->rdParam + 1), *(mr->rdParam));
540 break;
542 case META_LINETO:
543 LineTo32(hdc, (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
544 break;
546 case META_MOVETO:
547 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
548 break;
550 case META_EXCLUDECLIPRECT:
551 ExcludeClipRect16( hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
552 *(mr->rdParam + 1), *(mr->rdParam) );
553 break;
555 case META_INTERSECTCLIPRECT:
556 IntersectClipRect16( hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
557 *(mr->rdParam + 1), *(mr->rdParam) );
558 break;
560 case META_ARC:
561 Arc32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
562 (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
563 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
564 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
565 break;
567 case META_ELLIPSE:
568 Ellipse32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
569 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
570 break;
572 case META_FLOODFILL:
573 FloodFill32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
574 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
575 break;
577 case META_PIE:
578 Pie32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
579 (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
580 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
581 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
582 break;
584 case META_RECTANGLE:
585 Rectangle32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
586 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
587 break;
589 case META_ROUNDRECT:
590 RoundRect32(hdc, (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
591 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
592 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
593 break;
595 case META_PATBLT:
596 PatBlt16(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
597 *(mr->rdParam + 3), *(mr->rdParam + 2),
598 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
599 break;
601 case META_SAVEDC:
602 SaveDC32(hdc);
603 break;
605 case META_SETPIXEL:
606 SetPixel32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
607 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
608 break;
610 case META_OFFSETCLIPRGN:
611 OffsetClipRgn16( hdc, *(mr->rdParam + 1), *(mr->rdParam) );
612 break;
614 case META_TEXTOUT:
615 s1 = *(mr->rdParam);
616 TextOut16(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
617 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
618 (char *)(mr->rdParam + 1), s1);
619 break;
621 case META_POLYGON:
622 Polygon16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
623 break;
625 case META_POLYPOLYGON:
626 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParam + *(mr->rdParam) + 1),
627 (LPINT16)(mr->rdParam + 1), *(mr->rdParam));
628 break;
630 case META_POLYLINE:
631 Polyline16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
632 break;
634 case META_RESTOREDC:
635 RestoreDC32(hdc, (INT16)*(mr->rdParam));
636 break;
638 case META_SELECTOBJECT:
639 SelectObject32(hdc, *(ht->objectHandle + *(mr->rdParam)));
640 break;
642 case META_CHORD:
643 Chord32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
644 (INT16)*(mr->rdParam+5), (INT16)*(mr->rdParam + 4),
645 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
646 (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
647 break;
649 case META_CREATEPATTERNBRUSH:
650 switch (*(mr->rdParam))
652 case BS_PATTERN:
653 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
654 MF_AddHandle(ht, nHandles,
655 CreatePatternBrush32(CreateBitmap32(infohdr->biWidth,
656 infohdr->biHeight,
657 infohdr->biPlanes,
658 infohdr->biBitCount,
659 (LPSTR)(mr->rdParam +
660 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
661 break;
663 case BS_DIBPATTERN:
664 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
665 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
666 ptr = GlobalLock16(hndl);
667 memcpy(ptr, mr->rdParam + 2, s1);
668 GlobalUnlock16(hndl);
669 MF_AddHandle(ht, nHandles,
670 CreateDIBPatternBrush32(hndl, *(mr->rdParam + 1)));
671 GlobalFree16(hndl);
673 break;
675 case META_CREATEPENINDIRECT:
676 MF_AddHandle(ht, nHandles,
677 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParam))));
678 break;
680 case META_CREATEFONTINDIRECT:
681 MF_AddHandle(ht, nHandles,
682 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParam))));
683 break;
685 case META_CREATEBRUSHINDIRECT:
686 MF_AddHandle(ht, nHandles,
687 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParam))));
688 break;
690 /* W. Magro: Some new metafile operations. Not all debugged. */
691 case META_CREATEPALETTE:
692 MF_AddHandle(ht, nHandles,
693 CreatePalette16((LPLOGPALETTE)mr->rdParam));
694 break;
696 case META_SETTEXTALIGN:
697 SetTextAlign16(hdc, *(mr->rdParam));
698 break;
700 case META_SELECTPALETTE:
701 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
702 break;
704 case META_SETMAPPERFLAGS:
705 SetMapperFlags16(hdc, *(mr->rdParam));
706 break;
708 case META_REALIZEPALETTE:
709 RealizePalette16(hdc);
710 break;
712 case META_ESCAPE:
713 dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
714 break;
716 /* --- Begin of fixed or new metafile operations. July 1996 ----*/
717 case META_EXTTEXTOUT:
719 LPINT16 dxx;
720 LPSTR sot;
721 DWORD len;
723 s1 = mr->rdParam[2]; /* String length */
724 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
725 + sizeof(UINT16) + (mr->rdParam[3] ? sizeof(RECT16) : 0); /* rec len without dx array */
727 sot= (LPSTR)&mr->rdParam[4]; /* start_of_text */
728 if (mr->rdParam[3])
729 sot+=sizeof(RECT16); /* there is a rectangle, so add offset */
731 if (mr->rdSize == len / 2)
732 dxx = NULL; /* determine if array present */
733 else
734 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
735 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
736 else
738 dprintf_metafile(stddeb,"EXTTEXTOUT: %s len: %ld\n",
739 sot,mr->rdSize);
740 fprintf(stderr,
741 "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
742 len,s1,mr->rdSize,mr->rdParam[3]);
743 dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
745 ExtTextOut16( hdc, mr->rdParam[1], /* X position */
746 mr->rdParam[0], /* Y position */
747 mr->rdParam[3], /* options */
748 mr->rdParam[3] ? (LPRECT16) &mr->rdParam[4]:NULL, /* rectangle */
749 sot, /* string */
750 s1, dxx); /* length, dx array */
751 if (dxx)
752 dprintf_metafile(stddeb,"EXTTEXTOUT: %s len: %ld dx0: %d\n",
753 sot,mr->rdSize,dxx[0]);
755 break;
757 case META_STRETCHDIB:
759 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]);
760 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
761 StretchDIBits16(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
762 mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
763 mr->rdParam[4],mr->rdParam[3],bits,info,
764 mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1]));
766 break;
768 case META_DIBSTRETCHBLT:
770 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]);
771 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
772 StretchDIBits16(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
773 mr->rdParam[6],mr->rdParam[5],mr->rdParam[4],
774 mr->rdParam[3],mr->rdParam[2],bits,info,
775 DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
777 break;
779 case META_STRETCHBLT:
781 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
782 HBITMAP32 hbitmap=CreateBitmap32(mr->rdParam[10], /*Width */
783 mr->rdParam[11], /*Height*/
784 mr->rdParam[13], /*Planes*/
785 mr->rdParam[14], /*BitsPixel*/
786 (LPSTR)&mr->rdParam[15]); /*bits*/
787 SelectObject32(hdcSrc,hbitmap);
788 StretchBlt16(hdc,mr->rdParam[9],mr->rdParam[8],
789 mr->rdParam[7],mr->rdParam[6],
790 hdcSrc,mr->rdParam[5],mr->rdParam[4],
791 mr->rdParam[3],mr->rdParam[2],
792 MAKELONG(mr->rdParam[0],mr->rdParam[1]));
793 DeleteDC32(hdcSrc);
795 break;
797 case META_BITBLT: /* <-- not yet debugged */
799 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
800 HBITMAP32 hbitmap=CreateBitmap32(mr->rdParam[7]/*Width */,
801 mr->rdParam[8]/*Height*/,
802 mr->rdParam[10]/*Planes*/,
803 mr->rdParam[11]/*BitsPixel*/,
804 (LPSTR)&mr->rdParam[12]/*bits*/);
805 SelectObject32(hdcSrc,hbitmap);
806 BitBlt32(hdc,(INT16)mr->rdParam[6],(INT16)mr->rdParam[5],
807 (INT16)mr->rdParam[4],(INT16)mr->rdParam[3],
808 hdcSrc, (INT16)mr->rdParam[2],(INT16)mr->rdParam[1],
809 MAKELONG(0,mr->rdParam[0]));
810 DeleteDC32(hdcSrc);
812 break;
814 /* --- Begin of new metafile operations. April, 1997 (ak) ----*/
815 case META_CREATEREGION:
817 HRGN32 hrgn = CreateRectRgn32(0,0,0,0);
819 MF_Meta_CreateRegion(mr, hrgn);
820 MF_AddHandle(ht, nHandles, hrgn);
822 break;
824 case META_FILLREGION:
825 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)),
826 *(ht->objectHandle + *(mr->rdParam+1)));
827 break;
829 case META_INVERTREGION:
830 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)));
831 break;
833 case META_PAINTREGION:
834 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)));
835 break;
837 case META_SELECTCLIPREGION:
838 SelectClipRgn32(hdc, *(ht->objectHandle + *(mr->rdParam)));
839 break;
841 case META_DIBCREATEPATTERNBRUSH:
842 /* *(mr->rdParam) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
843 dprintf_metafile(stddeb,"META_DIBCREATEPATTERNBRUSH: %d\n",*(mr->rdParam));
844 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
845 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
846 ptr = GlobalLock16(hndl);
847 memcpy(ptr, mr->rdParam + 2, s1);
848 GlobalUnlock16(hndl);
849 MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParam + 1)));
850 GlobalFree16(hndl);
851 break;
853 case META_DIBBITBLT:
855 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[8]);
856 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[0] );
857 StretchDIBits16(hdc,mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
858 mr->rdParam[4],mr->rdParam[3],mr->rdParam[2],
859 mr->rdParam[5],mr->rdParam[4],bits,info,
860 DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
862 break;
864 case META_SETTEXTCHAREXTRA:
865 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParam));
866 break;
868 case META_SETTEXTJUSTIFICATION:
869 SetTextJustification32(hdc, *(mr->rdParam + 1), *(mr->rdParam));
870 break;
872 #define META_UNIMP(x) case x: fprintf(stderr,"PlayMetaFileRecord:record type "#x" not implemented.\n");break;
873 META_UNIMP(META_FRAMEREGION)
874 META_UNIMP(META_DRAWTEXT)
875 META_UNIMP(META_SETDIBTODEV)
876 META_UNIMP(META_ANIMATEPALETTE)
877 META_UNIMP(META_SETPALENTRIES)
878 META_UNIMP(META_RESIZEPALETTE)
879 META_UNIMP(META_EXTFLOODFILL)
880 META_UNIMP(META_RESETDC)
881 META_UNIMP(META_STARTDOC)
882 META_UNIMP(META_STARTPAGE)
883 META_UNIMP(META_ENDPAGE)
884 META_UNIMP(META_ABORTDOC)
885 META_UNIMP(META_ENDDOC)
886 META_UNIMP(META_CREATEBRUSH)
887 META_UNIMP(META_CREATEBITMAPINDIRECT)
888 META_UNIMP(META_CREATEBITMAP)
889 #undef META_UNIMP
891 default:
892 fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
893 mr->rdFunction);
898 /******************************************************************
899 * GetMetaFileBits (GDI.159)
901 * Trade in a metafile object handle for a handle to the metafile memory.
905 HGLOBAL16 WINAPI GetMetaFileBits(
906 HMETAFILE16 hmf /* metafile handle */
909 dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hmf);
910 return hmf;
913 /******************************************************************
914 * SetMetaFileBits (GDI.160)
916 * Trade in a metafile memory handle for a handle to a metafile object.
917 * The memory region should hold a proper metafile, otherwise
918 * problems will occur when it is used. Validity of the memory is not
919 * checked. The function is essentially just the identity function.
921 HMETAFILE16 WINAPI SetMetaFileBits(
922 HGLOBAL16 hMem
923 /* handle to a memory region holding a metafile */
926 dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hMem);
928 return hMem;
931 /******************************************************************
932 * SetMetaFileBitsBetter (GDI.196)
934 * Trade in a metafile memory handle for a handle to a metafile object,
935 * making a cursory check (using IsValidMetaFile()) that the memory
936 * handle points to a valid metafile.
938 * RETURNS
939 * Handle to a metafile on success, NULL on failure..
941 HMETAFILE16 WINAPI SetMetaFileBitsBetter( HMETAFILE16 hMeta )
943 if( IsValidMetaFile( hMeta ) )
944 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
945 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
946 return (HMETAFILE16)0;
949 /******************************************************************
950 * MF_Meta_CreateRegion
952 * Handles META_CREATEREGION for PlayMetaFileRecord().
956 * The layout of the record looks something like this:
958 * rdParam meaning
959 * 0 Always 0?
960 * 1 Always 6?
961 * 2 Looks like a handle? - not constant
962 * 3 0 or 1 ??
963 * 4 Total number of bytes
964 * 5 No. of seperate bands = n [see below]
965 * 6 Largest number of x co-ords in a band
966 * 7-10 Bounding box x1 y1 x2 y2
967 * 11-... n bands
969 * Regions are divided into bands that are uniform in the
970 * y-direction. Each band consists of pairs of on/off x-coords and is
971 * written as
972 * m y0 y1 x1 x2 x3 ... xm m
973 * into successive rdParam[]s.
975 * This is probably just a dump of the internal RGNOBJ?
977 * HDMD - 18/12/97
981 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn )
983 WORD band, pair;
984 WORD *start, *end;
985 INT16 y0, y1;
986 HRGN32 hrgn2 = CreateRectRgn32( 0, 0, 0, 0 );
988 for(band = 0, start = &(mr->rdParam[11]); band < mr->rdParam[5];
989 band++, start = end + 1) {
990 if(*start / 2 != (*start + 1) / 2) {
991 fprintf(stderr, "META_CREATEREGION: delimiter not even.\n");
992 DeleteObject32( hrgn2 );
993 return FALSE;
996 end = start + *start + 3;
997 if(end > (WORD *)mr + mr->rdSize) {
998 fprintf(stderr, "META_CREATEREGION: end points outside record.\n");
999 DeleteObject32( hrgn2 );
1000 return FALSE;
1003 if(*start != *end) {
1004 fprintf(stderr, "META_CREATEREGION: mismatched delimiters.\n");
1005 DeleteObject32( hrgn2 );
1006 return FALSE;
1009 y0 = *(INT16 *)(start + 1);
1010 y1 = *(INT16 *)(start + 2);
1011 for(pair = 0; pair < *start / 2; pair++) {
1012 SetRectRgn32( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1013 *(INT16 *)(start + 4 + 2*pair), y1 );
1014 CombineRgn32(hrgn, hrgn, hrgn2, RGN_OR);
1017 DeleteObject32( hrgn2 );
1018 return TRUE;
1022 /******************************************************************
1023 * MF_WriteRecord
1025 * Warning: this function can change the metafile handle.
1028 static BOOL32 MF_WriteRecord( DC *dc, METARECORD *mr, WORD rlen)
1030 DWORD len;
1031 METAHEADER *mh;
1032 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1034 switch(physDev->mh->mtType)
1036 case METAFILE_MEMORY:
1037 len = physDev->mh->mtSize * 2 + rlen;
1038 mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1039 if (!mh) return FALSE;
1040 physDev->mh = mh;
1041 memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1042 break;
1043 case METAFILE_DISK:
1044 dprintf_metafile(stddeb,"Writing record to disk\n");
1045 if (_lwrite32(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1046 return FALSE;
1047 break;
1048 default:
1049 fprintf( stderr, "Unknown metafile type %d\n", physDev->mh->mtType );
1050 return FALSE;
1053 physDev->mh->mtSize += rlen / 2;
1054 physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1055 return TRUE;
1059 /******************************************************************
1060 * MF_MetaParam0
1063 BOOL32 MF_MetaParam0(DC *dc, short func)
1065 char buffer[8];
1066 METARECORD *mr = (METARECORD *)&buffer;
1068 mr->rdSize = 3;
1069 mr->rdFunction = func;
1070 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1074 /******************************************************************
1075 * MF_MetaParam1
1077 BOOL32 MF_MetaParam1(DC *dc, short func, short param1)
1079 char buffer[8];
1080 METARECORD *mr = (METARECORD *)&buffer;
1082 mr->rdSize = 4;
1083 mr->rdFunction = func;
1084 *(mr->rdParam) = param1;
1085 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1089 /******************************************************************
1090 * MF_MetaParam2
1092 BOOL32 MF_MetaParam2(DC *dc, short func, short param1, short param2)
1094 char buffer[10];
1095 METARECORD *mr = (METARECORD *)&buffer;
1097 mr->rdSize = 5;
1098 mr->rdFunction = func;
1099 *(mr->rdParam) = param2;
1100 *(mr->rdParam + 1) = param1;
1101 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1105 /******************************************************************
1106 * MF_MetaParam4
1109 BOOL32 MF_MetaParam4(DC *dc, short func, short param1, short param2,
1110 short param3, short param4)
1112 char buffer[14];
1113 METARECORD *mr = (METARECORD *)&buffer;
1115 mr->rdSize = 7;
1116 mr->rdFunction = func;
1117 *(mr->rdParam) = param4;
1118 *(mr->rdParam + 1) = param3;
1119 *(mr->rdParam + 2) = param2;
1120 *(mr->rdParam + 3) = param1;
1121 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1125 /******************************************************************
1126 * MF_MetaParam6
1129 BOOL32 MF_MetaParam6(DC *dc, short func, short param1, short param2,
1130 short param3, short param4, short param5, short param6)
1132 char buffer[18];
1133 METARECORD *mr = (METARECORD *)&buffer;
1135 mr->rdSize = 9;
1136 mr->rdFunction = func;
1137 *(mr->rdParam) = param6;
1138 *(mr->rdParam + 1) = param5;
1139 *(mr->rdParam + 2) = param4;
1140 *(mr->rdParam + 3) = param3;
1141 *(mr->rdParam + 4) = param2;
1142 *(mr->rdParam + 5) = param1;
1143 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1147 /******************************************************************
1148 * MF_MetaParam8
1150 BOOL32 MF_MetaParam8(DC *dc, short func, short param1, short param2,
1151 short param3, short param4, short param5,
1152 short param6, short param7, short param8)
1154 char buffer[22];
1155 METARECORD *mr = (METARECORD *)&buffer;
1157 mr->rdSize = 11;
1158 mr->rdFunction = func;
1159 *(mr->rdParam) = param8;
1160 *(mr->rdParam + 1) = param7;
1161 *(mr->rdParam + 2) = param6;
1162 *(mr->rdParam + 3) = param5;
1163 *(mr->rdParam + 4) = param4;
1164 *(mr->rdParam + 5) = param3;
1165 *(mr->rdParam + 6) = param2;
1166 *(mr->rdParam + 7) = param1;
1167 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1171 /******************************************************************
1172 * MF_CreateBrushIndirect
1175 BOOL32 MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1177 int index;
1178 char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1179 METARECORD *mr = (METARECORD *)&buffer;
1181 mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1182 mr->rdFunction = META_CREATEBRUSHINDIRECT;
1183 memcpy(&(mr->rdParam), logbrush, sizeof(*logbrush));
1184 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1186 mr->rdSize = sizeof(METARECORD) / 2;
1187 mr->rdFunction = META_SELECTOBJECT;
1189 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1190 *(mr->rdParam) = index;
1191 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1195 /******************************************************************
1196 * MF_CreatePatternBrush
1199 BOOL32 MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1201 DWORD len, bmSize, biSize;
1202 HGLOBAL16 hmr;
1203 METARECORD *mr;
1204 BITMAPOBJ *bmp;
1205 BITMAPINFO *info;
1206 BITMAPINFOHEADER *infohdr;
1207 int index;
1208 char buffer[sizeof(METARECORD)];
1210 switch (logbrush->lbStyle)
1212 case BS_PATTERN:
1213 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1214 if (!bmp) return FALSE;
1215 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
1216 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1217 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1219 GDI_HEAP_UNLOCK((HGDIOBJ16)logbrush->lbHatch);
1220 return FALSE;
1222 mr = (METARECORD *)GlobalLock16(hmr);
1223 memset(mr, 0, len);
1224 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1225 mr->rdSize = len / 2;
1226 *(mr->rdParam) = logbrush->lbStyle;
1227 *(mr->rdParam + 1) = DIB_RGB_COLORS;
1228 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
1229 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1230 infohdr->biWidth = bmp->bitmap.bmWidth;
1231 infohdr->biHeight = bmp->bitmap.bmHeight;
1232 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1233 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1234 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1235 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1236 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1237 GDI_HEAP_UNLOCK(logbrush->lbHatch);
1238 break;
1240 case BS_DIBPATTERN:
1241 info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1242 if (info->bmiHeader.biCompression)
1243 bmSize = info->bmiHeader.biSizeImage;
1244 else
1245 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1246 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1247 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1248 len = sizeof(METARECORD) + biSize + bmSize + 2;
1249 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1250 return FALSE;
1251 mr = (METARECORD *)GlobalLock16(hmr);
1252 memset(mr, 0, len);
1253 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1254 mr->rdSize = len / 2;
1255 *(mr->rdParam) = logbrush->lbStyle;
1256 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
1257 memcpy(mr->rdParam + 2, info, biSize + bmSize);
1258 break;
1259 default:
1260 return FALSE;
1262 if (!(MF_WriteRecord(dc, mr, len)))
1264 GlobalFree16(hmr);
1265 return FALSE;
1268 GlobalFree16(hmr);
1270 mr = (METARECORD *)&buffer;
1271 mr->rdSize = sizeof(METARECORD) / 2;
1272 mr->rdFunction = META_SELECTOBJECT;
1274 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1275 *(mr->rdParam) = index;
1276 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1280 /******************************************************************
1281 * MF_CreatePenIndirect
1284 BOOL32 MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1286 int index;
1287 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1288 METARECORD *mr = (METARECORD *)&buffer;
1290 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1291 mr->rdFunction = META_CREATEPENINDIRECT;
1292 memcpy(&(mr->rdParam), logpen, sizeof(*logpen));
1293 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1295 mr->rdSize = sizeof(METARECORD) / 2;
1296 mr->rdFunction = META_SELECTOBJECT;
1298 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1299 *(mr->rdParam) = index;
1300 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1304 /******************************************************************
1305 * MF_CreateFontIndirect
1308 BOOL32 MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1310 int index;
1311 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1312 METARECORD *mr = (METARECORD *)&buffer;
1314 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1315 mr->rdFunction = META_CREATEFONTINDIRECT;
1316 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT16));
1317 if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1319 mr->rdSize = sizeof(METARECORD) / 2;
1320 mr->rdFunction = META_SELECTOBJECT;
1322 if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1323 *(mr->rdParam) = index;
1324 return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1328 /******************************************************************
1329 * MF_TextOut
1331 BOOL32 MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1333 BOOL32 ret;
1334 DWORD len;
1335 HGLOBAL16 hmr;
1336 METARECORD *mr;
1338 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1339 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1340 return FALSE;
1341 mr = (METARECORD *)GlobalLock16(hmr);
1342 memset(mr, 0, len);
1344 mr->rdSize = len / 2;
1345 mr->rdFunction = META_TEXTOUT;
1346 *(mr->rdParam) = count;
1347 memcpy(mr->rdParam + 1, str, count);
1348 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1349 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1350 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1351 GlobalFree16(hmr);
1352 return ret;
1355 /******************************************************************
1356 * MF_ExtTextOut
1358 BOOL32 MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1359 LPCSTR str, short count, const INT16 *lpDx)
1361 BOOL32 ret;
1362 DWORD len;
1363 HGLOBAL16 hmr;
1364 METARECORD *mr;
1366 if((!flags && rect) || (flags && !rect))
1367 fprintf(stderr, "MF_ExtTextOut: Inconsistent flags and rect\n");
1368 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1369 + sizeof(UINT16);
1370 if(rect)
1371 len += sizeof(RECT16);
1372 if (lpDx)
1373 len+=count*sizeof(INT16);
1374 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1375 return FALSE;
1376 mr = (METARECORD *)GlobalLock16(hmr);
1377 memset(mr, 0, len);
1379 mr->rdSize = len / 2;
1380 mr->rdFunction = META_EXTTEXTOUT;
1381 *(mr->rdParam) = y;
1382 *(mr->rdParam + 1) = x;
1383 *(mr->rdParam + 2) = count;
1384 *(mr->rdParam + 3) = flags;
1385 if (rect) memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
1386 memcpy(mr->rdParam + (rect ? 8 : 4), str, count);
1387 if (lpDx)
1388 memcpy(mr->rdParam + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1389 count*sizeof(INT16));
1390 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1391 GlobalFree16(hmr);
1392 return ret;
1395 /******************************************************************
1396 * MF_MetaPoly - implements Polygon and Polyline
1398 BOOL32 MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1400 BOOL32 ret;
1401 DWORD len;
1402 HGLOBAL16 hmr;
1403 METARECORD *mr;
1405 len = sizeof(METARECORD) + (count * 4);
1406 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1407 return FALSE;
1408 mr = (METARECORD *)GlobalLock16(hmr);
1409 memset(mr, 0, len);
1411 mr->rdSize = len / 2;
1412 mr->rdFunction = func;
1413 *(mr->rdParam) = count;
1414 memcpy(mr->rdParam + 1, pt, count * 4);
1415 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1416 GlobalFree16(hmr);
1417 return ret;
1421 /******************************************************************
1422 * MF_BitBlt
1424 BOOL32 MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1425 short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1427 BOOL32 ret;
1428 DWORD len;
1429 HGLOBAL16 hmr;
1430 METARECORD *mr;
1431 BITMAP16 BM;
1433 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1434 len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1435 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1436 return FALSE;
1437 mr = (METARECORD *)GlobalLock16(hmr);
1438 mr->rdFunction = META_BITBLT;
1439 *(mr->rdParam + 7) = BM.bmWidth;
1440 *(mr->rdParam + 8) = BM.bmHeight;
1441 *(mr->rdParam + 9) = BM.bmWidthBytes;
1442 *(mr->rdParam +10) = BM.bmPlanes;
1443 *(mr->rdParam +11) = BM.bmBitsPixel;
1444 dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1445 if (GetBitmapBits32(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1446 mr->rdParam +12))
1448 mr->rdSize = len / sizeof(INT16);
1449 *(mr->rdParam) = HIWORD(rop);
1450 *(mr->rdParam + 1) = ySrc;
1451 *(mr->rdParam + 2) = xSrc;
1452 *(mr->rdParam + 3) = height;
1453 *(mr->rdParam + 4) = width;
1454 *(mr->rdParam + 5) = yDest;
1455 *(mr->rdParam + 6) = xDest;
1456 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1458 else
1459 ret = FALSE;
1460 GlobalFree16(hmr);
1461 return ret;
1465 /**********************************************************************
1466 * MF_StretchBlt
1467 * this function contains TWO ways for procesing StretchBlt in metafiles,
1468 * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT
1469 * via #define STRETCH_VIA_DIB
1471 #define STRETCH_VIA_DIB
1472 #undef STRETCH_VIA_DIB
1473 BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1474 short heightDest, DC *dcSrc, short xSrc, short ySrc,
1475 short widthSrc, short heightSrc, DWORD rop)
1477 BOOL32 ret;
1478 DWORD len;
1479 HGLOBAL16 hmr;
1480 METARECORD *mr;
1481 BITMAP16 BM;
1482 #ifdef STRETCH_VIA_DIB
1483 LPBITMAPINFOHEADER lpBMI;
1484 WORD nBPP;
1485 #endif
1486 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1487 #ifdef STRETCH_VIA_DIB
1488 nBPP = BM.bmPlanes * BM.bmBitsPixel;
1489 len = sizeof(METARECORD) + 10 * sizeof(INT16)
1490 + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
1491 + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1492 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1493 return FALSE;
1494 mr = (METARECORD *)GlobalLock16(hmr);
1495 mr->rdFunction = META_DIBSTRETCHBLT;
1496 lpBMI=(LPBITMAPINFOHEADER)(mr->rdParam+10);
1497 lpBMI->biSize = sizeof(BITMAPINFOHEADER);
1498 lpBMI->biWidth = BM.bmWidth;
1499 lpBMI->biHeight = BM.bmHeight;
1500 lpBMI->biPlanes = 1;
1501 lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */
1502 lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0;
1503 lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1504 lpBMI->biCompression = BI_RGB;
1505 lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1506 lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1507 lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */
1509 dprintf_metafile(stddeb,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n",
1510 len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1511 if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT32)lpBMI->biHeight,
1512 (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1513 DIB_RGB_COLORS ),
1514 (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1515 #else
1516 len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1517 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1518 return FALSE;
1519 mr = (METARECORD *)GlobalLock16(hmr);
1520 mr->rdFunction = META_STRETCHBLT;
1521 *(mr->rdParam +10) = BM.bmWidth;
1522 *(mr->rdParam +11) = BM.bmHeight;
1523 *(mr->rdParam +12) = BM.bmWidthBytes;
1524 *(mr->rdParam +13) = BM.bmPlanes;
1525 *(mr->rdParam +14) = BM.bmBitsPixel;
1526 dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1527 if (GetBitmapBits32( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1528 mr->rdParam +15))
1529 #endif
1531 mr->rdSize = len / sizeof(INT16);
1532 *(mr->rdParam) = LOWORD(rop);
1533 *(mr->rdParam + 1) = HIWORD(rop);
1534 *(mr->rdParam + 2) = heightSrc;
1535 *(mr->rdParam + 3) = widthSrc;
1536 *(mr->rdParam + 4) = ySrc;
1537 *(mr->rdParam + 5) = xSrc;
1538 *(mr->rdParam + 6) = heightDest;
1539 *(mr->rdParam + 7) = widthDest;
1540 *(mr->rdParam + 8) = yDest;
1541 *(mr->rdParam + 9) = xDest;
1542 ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1544 else
1545 ret = FALSE;
1546 GlobalFree16(hmr);
1547 return ret;
1551 /******************************************************************
1552 * MF_CreateRegion
1554 INT16 MF_CreateRegion(DC *dc, HRGN32 hrgn)
1556 DWORD len;
1557 METARECORD *mr;
1558 RGNDATA *rgndata;
1559 RECT32 *pCurRect, *pEndRect;
1560 WORD Bands = 0, MaxBands = 0;
1561 WORD *Param, *StartBand;
1562 BOOL32 ret;
1564 len = GetRegionData( hrgn, 0, NULL );
1565 if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1566 fprintf(stderr, "MF_CreateRegion: can't alloc rgndata buffer\n");
1567 return -1;
1569 GetRegionData( hrgn, len, rgndata );
1571 /* Overestimate of length:
1572 * Assume every rect is a separate band -> 6 WORDs per rect
1574 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1575 if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1576 fprintf(stderr, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1577 HeapFree( SystemHeap, 0, rgndata );
1578 return -1;
1581 memset(mr, 0, len);
1583 Param = mr->rdParam + 11;
1584 StartBand = NULL;
1586 pEndRect = (RECT32 *)rgndata->Buffer + rgndata->rdh.nCount;
1587 for(pCurRect = (RECT32 *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1589 if( StartBand && pCurRect->top == *(StartBand + 1) )
1591 *Param++ = pCurRect->left;
1592 *Param++ = pCurRect->right;
1594 else
1596 if(StartBand)
1598 *StartBand = Param - StartBand - 3;
1599 *Param++ = *StartBand;
1600 if(*StartBand > MaxBands)
1601 MaxBands = *StartBand;
1602 Bands++;
1604 StartBand = Param++;
1605 *Param++ = pCurRect->top;
1606 *Param++ = pCurRect->bottom;
1607 *Param++ = pCurRect->left;
1608 *Param++ = pCurRect->right;
1611 len = Param - (WORD *)mr;
1613 mr->rdParam[0] = 0;
1614 mr->rdParam[1] = 6;
1615 mr->rdParam[2] = 0x1234;
1616 mr->rdParam[3] = 0;
1617 mr->rdParam[4] = len * 2;
1618 mr->rdParam[5] = Bands;
1619 mr->rdParam[6] = MaxBands;
1620 mr->rdParam[7] = rgndata->rdh.rcBound.left;
1621 mr->rdParam[8] = rgndata->rdh.rcBound.top;
1622 mr->rdParam[9] = rgndata->rdh.rcBound.right;
1623 mr->rdParam[10] = rgndata->rdh.rcBound.bottom;
1624 mr->rdFunction = META_CREATEREGION;
1625 mr->rdSize = len / 2;
1626 ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );
1627 HeapFree( SystemHeap, 0, mr );
1628 HeapFree( SystemHeap, 0, rgndata );
1629 if(!ret)
1631 fprintf(stderr, "MF_CreateRegion: MF_WriteRecord failed\n");
1632 return -1;
1634 return MF_AddHandleDC( dc );