Release 950901
[wine] / objects / metafile.c
1 /*
2  * Metafile functions
3  *
4  * Copyright  David W. Metcalfe, 1994
5  *
6 static char Copyright[] = "Copyright  David W. Metcalfe, 1994";
7 */
8
9 #include <string.h>
10 #include "gdi.h"
11 #include "bitmap.h"
12 #include "metafile.h"
13 #include "stddebug.h"
14 /* #define DEBUG_METAFILE */
15 #include "debug.h"
16
17 #define HTINCR  10      /* handle table allocation size increment */
18
19 static HANDLE hHT;      /* handle of the handle table */
20 static int HTLen;       /* allocated length of handle table */
21
22 /******************************************************************
23  *         GetMetafile         GDI.124 By Kenny MacDonald 30 Nov 94
24  */
25 HMETAFILE GetMetaFile(LPSTR lpFilename)
26 {
27   HMETAFILE hmf;
28   METAFILE *mf;
29   METAHEADER *mh;
30
31   dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
32
33   if (!lpFilename)
34     return 0;
35
36   hmf = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE));
37   mf = (METAFILE *)GlobalLock(hmf);
38   if (!mf) {
39     GlobalFree(hmf);
40     return 0;
41   }
42
43   mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, MFHEADERSIZE);
44   mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
45   if (!mh) {
46     GlobalFree(mf->hMetaHdr);
47     GlobalFree(hmf);
48     return 0;
49   }
50   strcpy(mf->Filename, lpFilename);
51   mf->wMagic = METAFILE_MAGIC;
52   if ((mf->hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) {
53     GlobalFree(hmf);
54     return 0;
55   }
56   if (_lread(mf->hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
57     GlobalFree(mf->hMetaHdr);
58     GlobalFree(hmf);
59     return 0;
60   }
61   _lclose(mf->hFile);
62
63
64   GlobalUnlock(mf->hMetaHdr);
65   GlobalUnlock(hmf);
66   if (mh->mtType != 1)
67     return 0;
68   else
69     return hmf;
70 }
71
72 /******************************************************************
73  *         CreateMetafile         GDI.125
74  */
75 HANDLE CreateMetaFile(LPSTR lpFilename)
76 {
77     DC *dc;
78     HANDLE handle;
79     METAFILE *mf;
80     METAHEADER *mh;
81     HANDLETABLE *ht;
82
83     dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
84
85     handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
86     if (!handle) return 0;
87     dc = (DC *)GDI_HEAP_LIN_ADDR(handle);
88
89     if (!(dc->w.hMetaFile = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE))))
90         return 0;
91     mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
92     if (!(mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAHEADER))))
93     {
94         GlobalFree(dc->w.hMetaFile);
95         return 0;
96     }
97     mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
98
99     mf->wMagic = METAFILE_MAGIC;
100     mh->mtHeaderSize = MFHEADERSIZE / 2;
101     mh->mtVersion = MFVERSION;
102     mh->mtSize = MFHEADERSIZE / 2;
103     mh->mtNoObjects = 0;
104     mh->mtMaxRecord = 0;
105     mh->mtNoParameters = 0;
106
107     if (lpFilename)          /* disk based metafile */
108     {
109         mh->mtType = 1;
110         strcpy(mf->Filename, lpFilename);
111         mf->hFile = _lcreat(lpFilename, 0);
112         if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
113         {
114             GlobalFree(mf->hMetaHdr);
115             GlobalFree(dc->w.hMetaFile);
116             return 0;
117         }
118     }
119     else                     /* memory based metafile */
120         mh->mtType = 0;
121
122     /* create the handle table */
123     HTLen = HTINCR;
124     hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 
125                       sizeof(HANDLETABLE) * HTLen);
126     ht = (HANDLETABLE *)GlobalLock(hHT);
127
128     GlobalUnlock(mf->hMetaHdr);
129     GlobalUnlock(dc->w.hMetaFile);
130     return handle;
131 }
132
133
134 /******************************************************************
135  *         CloseMetafile         GDI.126
136  */
137 HMETAFILE CloseMetaFile(HDC hdc)
138 {
139     DC *dc;
140     METAFILE *mf;
141     METAHEADER *mh;
142     HMETAFILE hmf;
143 /*    METARECORD *mr = (METARECORD *)&buffer;*/
144
145     dprintf_metafile(stddeb,"CloseMetaFile\n");
146
147     dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
148     if (!dc) return 0;
149     mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
150     mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
151
152     /* Construct the end of metafile record - this is documented
153      * in SDK Knowledgebase Q99334.
154      */
155     if (!MF_MetaParam0(dc, META_EOF))
156     {
157         GlobalFree(mf->hMetaHdr);
158         GlobalFree(dc->w.hMetaFile);
159         return 0;
160     }   
161
162     if (mh->mtType == 1)        /* disk based metafile */
163     {
164         if (_llseek(mf->hFile, 0L, 0) == -1)
165         {
166             GlobalFree(mf->hMetaHdr);
167             GlobalFree(dc->w.hMetaFile);
168             return 0;
169         }
170         if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
171         {
172             GlobalFree(mf->hMetaHdr);
173             GlobalFree(dc->w.hMetaFile);
174             return 0;
175         }
176         _lclose(mf->hFile);
177     }
178
179     /* delete the handle table */
180     GlobalFree(hHT);
181
182     GlobalUnlock(mf->hMetaHdr);
183     hmf = dc->w.hMetaFile;
184     GlobalUnlock(hmf);
185     GDI_FreeObject(hdc);
186     return hmf;
187 }
188
189
190 /******************************************************************
191  *         DeleteMetafile         GDI.127
192  */
193 BOOL DeleteMetaFile(HMETAFILE hmf)
194 {
195     METAFILE *mf = (METAFILE *)GlobalLock(hmf);
196
197     if (mf->wMagic != METAFILE_MAGIC)
198         return FALSE;
199
200     GlobalFree(mf->hMetaHdr);
201     GlobalFree(hmf);
202     return TRUE;
203 }
204
205
206 /******************************************************************
207  *         PlayMetafile         GDI.123
208  */
209 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
210 {
211     METAFILE *mf = (METAFILE *)GlobalLock(hmf);
212     METAHEADER *mh;
213     METARECORD *mr;
214     HANDLETABLE *ht;
215     char *buffer = (char *)NULL;
216
217     if (mf->wMagic != METAFILE_MAGIC)
218         return FALSE;
219
220     mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
221     if (mh->mtType == 1)       /* disk based metafile */
222     {
223         mf->hFile = _lopen(mf->Filename, OF_READ);
224         mf->hBuffer = GlobalAlloc(GMEM_MOVEABLE, mh->mtMaxRecord * 2);
225         buffer = (char *)GlobalLock(mf->hBuffer);
226         _llseek(mf->hFile, mh->mtHeaderSize * 2, 0);
227         mf->MetaOffset = mh->mtHeaderSize * 2;
228     }
229     else if (mh->mtType == 0)   /* memory based metafile */
230         mf->MetaOffset = mh->mtHeaderSize * 2;
231     else                       /* not a valid metafile type */
232         return FALSE;
233
234     /* create the handle table */
235     hHT = GlobalAlloc(GMEM_MOVEABLE, sizeof(HANDLETABLE) * mh->mtNoObjects);
236     ht = (HANDLETABLE *)GlobalLock(hHT);
237
238     /* loop through metafile playing records */
239     while (mf->MetaOffset < mh->mtSize * 2)
240     {
241         if (mh->mtType == 1)   /* disk based metafile */
242         {
243             _lread(mf->hFile, buffer, sizeof(METARECORD));
244             mr = (METARECORD *)buffer;
245             _lread(mf->hFile, (char *)(mr->rdParam + 1), (mr->rdSize * 2) -
246                                                        sizeof(METARECORD));
247             mf->MetaOffset += mr->rdSize * 2;
248         }
249         else                   /* memory based metafile */
250         {
251             mr = (METARECORD *)((char *)mh + mf->MetaOffset);
252             mf->MetaOffset += mr->rdSize * 2;
253         }
254         PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
255     }
256
257     /* close disk based metafile and free buffer */
258     if (mh->mtType == 1)
259     {
260         GlobalFree(mf->hBuffer);
261         _lclose(mf->hFile);
262     }
263
264     /* free handle table */
265     GlobalFree(hHT);
266
267     return TRUE;
268 }
269
270
271 /******************************************************************
272  *         PlayMetaFileRecord      GDI.176
273  */
274 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
275                                                    WORD nHandles)
276 {
277     short s1;
278     HANDLE hndl;
279     char *ptr;
280     BITMAPINFOHEADER *infohdr;
281
282     switch (mr->rdFunction)
283     {
284     case META_EOF:
285       break;
286
287     case META_DELETEOBJECT:
288       DeleteObject(*(ht->objectHandle + *(mr->rdParam)));
289       break;
290
291     case META_SETBKCOLOR:
292         SetBkColor(hdc, *(mr->rdParam));
293         break;
294
295     case META_SETBKMODE:
296         SetBkMode(hdc, *(mr->rdParam));
297         break;
298
299     case META_SETMAPMODE:
300         SetMapMode(hdc, *(mr->rdParam));
301         break;
302
303     case META_SETROP2:
304         SetROP2(hdc, *(mr->rdParam));
305         break;
306
307     case META_SETRELABS:
308         SetRelAbs(hdc, *(mr->rdParam));
309         break;
310
311     case META_SETPOLYFILLMODE:
312         SetPolyFillMode(hdc, *(mr->rdParam));
313         break;
314
315     case META_SETSTRETCHBLTMODE:
316         SetStretchBltMode(hdc, *(mr->rdParam));
317         break;
318
319     case META_SETTEXTCOLOR:
320         SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
321         break;
322
323     case META_SETWINDOWORG:
324         SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
325         break;
326
327     case META_SETWINDOWEXT:
328         SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
329         break;
330
331     case META_SETVIEWPORTORG:
332         SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
333         break;
334
335     case META_SETVIEWPORTEXT:
336         SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
337         break;
338
339     case META_OFFSETWINDOWORG:
340         OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
341         break;
342
343     case META_SCALEWINDOWEXT:
344         ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
345                        *(mr->rdParam + 1), *(mr->rdParam));
346         break;
347
348     case META_OFFSETVIEWPORTORG:
349         OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
350         break;
351
352     case META_SCALEVIEWPORTEXT:
353         ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
354                          *(mr->rdParam + 1), *(mr->rdParam));
355         break;
356
357     case META_LINETO:
358         LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
359         break;
360
361     case META_MOVETO:
362         MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
363         break;
364
365     case META_EXCLUDECLIPRECT:
366         ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
367                         *(mr->rdParam + 1), *(mr->rdParam));
368         break;
369
370     case META_INTERSECTCLIPRECT:
371         IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
372                         *(mr->rdParam + 1), *(mr->rdParam));
373         break;
374
375     case META_ARC:
376         Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
377             *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
378             *(mr->rdParam + 1), *(mr->rdParam));
379         break;
380
381     case META_ELLIPSE:
382         Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
383                 *(mr->rdParam + 1), *(mr->rdParam));
384         break;
385
386     case META_FLOODFILL:
387         FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
388                   MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
389         break;
390
391     case META_PIE:
392         Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
393             *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
394             *(mr->rdParam + 1), *(mr->rdParam));
395         break;
396
397     case META_RECTANGLE:
398         Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
399                 *(mr->rdParam + 1), *(mr->rdParam));
400         break;
401
402     case META_ROUNDRECT:
403         RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
404                   *(mr->rdParam + 3), *(mr->rdParam + 2),
405                   *(mr->rdParam + 1), *(mr->rdParam));
406         break;
407
408     case META_PATBLT:
409         PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
410                *(mr->rdParam + 3), *(mr->rdParam + 2),
411                MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
412         break;
413
414     case META_SAVEDC:
415         SaveDC(hdc);
416         break;
417
418     case META_SETPIXEL:
419         SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
420                  MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
421         break;
422
423     case META_OFFSETCLIPRGN:
424         OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
425         break;
426
427     case META_TEXTOUT:
428         s1 = *(mr->rdParam);
429         TextOut(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
430                 *(mr->rdParam + ((s1 + 1) >> 1) + 1), 
431                 (char *)(mr->rdParam + 1), s1);
432         break;
433
434     case META_POLYGON:
435         Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
436         break;
437
438     case META_POLYPOLYGON:
439       PolyPolygon(hdc, (LPPOINT)(mr->rdParam + *(mr->rdParam) + 1),
440                   (mr->rdParam + 1), *(mr->rdParam)); 
441       break;
442
443     case META_POLYLINE:
444         Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
445         break;
446
447     case META_RESTOREDC:
448         RestoreDC(hdc, *(mr->rdParam));
449         break;
450
451     case META_SELECTOBJECT:
452         SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
453         break;
454
455     case META_CHORD:
456         Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
457               *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
458               *(mr->rdParam + 1), *(mr->rdParam));
459         break;
460
461     case META_CREATEPATTERNBRUSH:
462         switch (*(mr->rdParam))
463         {
464         case BS_PATTERN:
465             infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
466             MF_AddHandle(ht, nHandles,
467                          CreatePatternBrush(CreateBitmap(infohdr->biWidth, 
468                                       infohdr->biHeight, 
469                                       infohdr->biPlanes, 
470                                       infohdr->biBitCount,
471                                       (LPSTR)(mr->rdParam + 
472                                       (sizeof(BITMAPINFOHEADER) / 2) + 4))));
473             break;
474
475         case BS_DIBPATTERN:
476             s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
477             hndl = GlobalAlloc(GMEM_MOVEABLE, s1);
478             ptr = GlobalLock(hndl);
479             memcpy(ptr, mr->rdParam + 2, s1);
480             GlobalUnlock(hndl);
481             MF_AddHandle(ht, nHandles,
482                          CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
483             GlobalFree(hndl);
484         }
485         break;
486         
487     case META_CREATEPENINDIRECT:
488         MF_AddHandle(ht, nHandles, 
489                      CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
490         break;
491
492     case META_CREATEFONTINDIRECT:
493         MF_AddHandle(ht, nHandles, 
494                      CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
495         break;
496
497     case META_CREATEBRUSHINDIRECT:
498         MF_AddHandle(ht, nHandles, 
499                      CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
500         break;
501
502     default:
503         fprintf(stderr,"PlayMetaFileRecord: Unknown record type %x\n",
504                                               mr->rdFunction);
505     }
506 }
507
508
509 /******************************************************************
510  *         MF_WriteRecord
511  */
512 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
513 {
514     DWORD len;
515     METAFILE *mf = (METAFILE *)GlobalLock(hmf);
516     METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
517
518     if (mh->mtType == 0)          /* memory based metafile */
519     {
520         len = mh->mtSize * 2 + rlen;
521         GlobalUnlock(mf->hMetaHdr);
522         mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE);
523         mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
524         memcpy(mh + mh->mtSize * 2, mr, rlen);
525     }
526     else if (mh->mtType == 1)     /* disk based metafile */
527     {
528         if (_lwrite(mf->hFile, (char *)mr, rlen) == -1)
529         {
530             GlobalUnlock(mf->hMetaHdr);
531             return FALSE;
532         }
533     }
534     else
535     {
536         GlobalUnlock(mf->hMetaHdr);
537         return FALSE;
538     }
539
540     mh->mtSize += rlen / 2;
541     mh->mtMaxRecord = max(mh->mtMaxRecord, rlen / 2);
542     GlobalUnlock(mf->hMetaHdr);
543     return TRUE;
544 }
545
546
547 /******************************************************************
548  *         MF_AddHandle
549  *
550  *    Add a handle to an external handle table and return the index
551  */
552 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
553 {
554     int i;
555
556     for (i = 0; i < htlen; i++)
557     {
558         if (*(ht->objectHandle + i) == 0)
559         {
560             *(ht->objectHandle + i) = hobj;
561             return i;
562         }
563     }
564     return -1;
565 }
566
567
568 /******************************************************************
569  *         MF_AddHandleInternal
570  *
571  *    Add a handle to the internal handle table and return the index
572  */
573 int MF_AddHandleInternal(HANDLE hobj)
574 {
575     int i;
576     HANDLETABLE *ht = (HANDLETABLE *)GlobalLock(hHT);
577
578     for (i = 0; i < HTLen; i++)
579     {
580         if (*(ht->objectHandle + i) == 0)
581         {
582             *(ht->objectHandle + i) = hobj;
583             GlobalUnlock(hHT);
584             return i;
585         }
586     }
587     GlobalUnlock(hHT);
588     if (!(hHT = GlobalReAlloc(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
589         return -1;
590     HTLen += HTINCR;
591     ht = (HANDLETABLE *)GlobalLock(hHT);
592     *(ht->objectHandle + i) = hobj;
593     GlobalUnlock(hHT);
594     return i;
595 }
596
597
598 /******************************************************************
599  *         MF_MetaParam0
600  */
601 BOOL MF_MetaParam0(DC *dc, short func)
602 {
603     char buffer[8];
604     METARECORD *mr = (METARECORD *)&buffer;
605
606     mr->rdSize = 3;
607     mr->rdFunction = func;
608     return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
609 }
610
611
612 /******************************************************************
613  *         MF_MetaParam1
614  */
615 BOOL MF_MetaParam1(DC *dc, short func, short param1)
616 {
617     char buffer[8];
618     METARECORD *mr = (METARECORD *)&buffer;
619
620     mr->rdSize = 4;
621     mr->rdFunction = func;
622     *(mr->rdParam) = param1;
623     return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
624 }
625
626
627 /******************************************************************
628  *         MF_MetaParam2
629  */
630 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
631 {
632     char buffer[10];
633     METARECORD *mr = (METARECORD *)&buffer;
634
635     mr->rdSize = 5;
636     mr->rdFunction = func;
637     *(mr->rdParam) = param2;
638     *(mr->rdParam + 1) = param1;
639     return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
640 }
641
642
643 /******************************************************************
644  *         MF_MetaParam4
645  */
646 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2, 
647                    short param3, short param4)
648 {
649     char buffer[14];
650     METARECORD *mr = (METARECORD *)&buffer;
651
652     mr->rdSize = 7;
653     mr->rdFunction = func;
654     *(mr->rdParam) = param4;
655     *(mr->rdParam + 1) = param3;
656     *(mr->rdParam + 2) = param2;
657     *(mr->rdParam + 3) = param1;
658     return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
659 }
660
661
662 /******************************************************************
663  *         MF_MetaParam6
664  */
665 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2, 
666                    short param3, short param4, short param5, short param6)
667 {
668     char buffer[18];
669     METARECORD *mr = (METARECORD *)&buffer;
670
671     mr->rdSize = 9;
672     mr->rdFunction = func;
673     *(mr->rdParam) = param6;
674     *(mr->rdParam + 1) = param5;
675     *(mr->rdParam + 2) = param4;
676     *(mr->rdParam + 3) = param3;
677     *(mr->rdParam + 4) = param2;
678     *(mr->rdParam + 5) = param1;
679     return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
680 }
681
682
683 /******************************************************************
684  *         MF_MetaParam8
685  */
686 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2, 
687                    short param3, short param4, short param5,
688                    short param6, short param7, short param8)
689 {
690     char buffer[22];
691     METARECORD *mr = (METARECORD *)&buffer;
692
693     mr->rdSize = 11;
694     mr->rdFunction = func;
695     *(mr->rdParam) = param8;
696     *(mr->rdParam + 1) = param7;
697     *(mr->rdParam + 2) = param6;
698     *(mr->rdParam + 3) = param5;
699     *(mr->rdParam + 4) = param4;
700     *(mr->rdParam + 5) = param3;
701     *(mr->rdParam + 6) = param2;
702     *(mr->rdParam + 7) = param1;
703     return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
704 }
705
706
707 /******************************************************************
708  *         MF_CreateBrushIndirect
709  */
710 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
711 {
712     int index;
713     BOOL rc;
714     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
715     METARECORD *mr = (METARECORD *)&buffer;
716     METAFILE *mf;
717     METAHEADER *mh;
718
719     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
720     mr->rdFunction = META_CREATEBRUSHINDIRECT;
721     memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
722     if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
723         return FALSE;
724
725     mr->rdSize = sizeof(METARECORD) / 2;
726     mr->rdFunction = META_SELECTOBJECT;
727     if ((index = MF_AddHandleInternal(hBrush)) == -1)
728         return FALSE;
729
730     mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
731     mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
732     *(mr->rdParam) = index;
733     if (index >= mh->mtNoObjects)
734         mh->mtNoObjects++;
735     rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
736     GlobalUnlock(mf->hMetaHdr);
737     GlobalUnlock(dc->w.hMetaFile);
738     return rc;
739 }
740
741
742 /******************************************************************
743  *         MF_CreatePatternBrush
744  */
745 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
746 {
747     DWORD len, bmSize, biSize;
748     HANDLE hmr;
749     METARECORD *mr;
750     BITMAPOBJ *bmp;
751     BITMAPINFO *info;
752     BITMAPINFOHEADER *infohdr;
753     int index;
754     BOOL rc;
755     char buffer[sizeof(METARECORD)];
756     METAFILE *mf;
757     METAHEADER *mh;
758
759     switch (logbrush->lbStyle)
760     {
761     case BS_PATTERN:
762         bmp = (BITMAPOBJ *)GDI_GetObjPtr(logbrush->lbHatch, BITMAP_MAGIC);
763         if (!bmp) return FALSE;
764         len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) + 
765               (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
766         if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
767             return FALSE;
768         mr = (METARECORD *)GlobalLock(hmr);
769         memset(mr, 0, len);
770         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
771         mr->rdSize = len / 2;
772         *(mr->rdParam) = logbrush->lbStyle;
773         *(mr->rdParam + 1) = DIB_RGB_COLORS;
774         infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
775         infohdr->biSize = sizeof(BITMAPINFOHEADER);
776         infohdr->biWidth = bmp->bitmap.bmWidth;
777         infohdr->biHeight = bmp->bitmap.bmHeight;
778         infohdr->biPlanes = bmp->bitmap.bmPlanes;
779         infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
780         memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
781                bmp->bitmap.bmBits, 
782                bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
783         break;
784
785     case BS_DIBPATTERN:
786         info = (BITMAPINFO *)GlobalLock(logbrush->lbHatch);
787         bmSize = info->bmiHeader.biSizeImage;
788         if (!bmSize)
789             bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount 
790                     + 31) / 32 * 8 * info->bmiHeader.biHeight;
791         biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor)); 
792         len = sizeof(METARECORD) + biSize + bmSize + 2;
793         if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
794             return FALSE;
795         mr = (METARECORD *)GlobalLock(hmr);
796         memset(mr, 0, len);
797         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
798         mr->rdSize = len / 2;
799         *(mr->rdParam) = logbrush->lbStyle;
800         *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
801         memcpy(mr->rdParam + 2, info, biSize + bmSize);
802         break;
803     default:
804         return FALSE;
805     }
806     if (!MF_WriteRecord(dc->w.hMetaFile, mr, len))
807     {
808         GlobalFree(hmr);
809         return FALSE;
810     }
811
812     GlobalFree(hmr);
813     mr = (METARECORD *)&buffer;
814     mr->rdSize = sizeof(METARECORD) / 2;
815     mr->rdFunction = META_SELECTOBJECT;
816     if ((index = MF_AddHandleInternal(hBrush)) == -1)
817         return FALSE;
818
819     mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
820     mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
821     *(mr->rdParam) = index;
822     if (index >= mh->mtNoObjects)
823         mh->mtNoObjects++;
824     rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
825     GlobalUnlock(mf->hMetaHdr);
826     GlobalUnlock(dc->w.hMetaFile);
827     return rc;
828 }
829
830
831 /******************************************************************
832  *         MF_CreatePenIndirect
833  */
834 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
835 {
836     int index;
837     BOOL rc;
838     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
839     METARECORD *mr = (METARECORD *)&buffer;
840     METAFILE *mf;
841     METAHEADER *mh;
842
843     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
844     mr->rdFunction = META_CREATEPENINDIRECT;
845     memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
846     if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
847         return FALSE;
848
849     mr->rdSize = sizeof(METARECORD) / 2;
850     mr->rdFunction = META_SELECTOBJECT;
851     if ((index = MF_AddHandleInternal(hPen)) == -1)
852         return FALSE;
853
854     mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
855     mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
856     *(mr->rdParam) = index;
857     if (index >= mh->mtNoObjects)
858         mh->mtNoObjects++;
859     rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
860     GlobalUnlock(mf->hMetaHdr);
861     GlobalUnlock(dc->w.hMetaFile);
862     return rc;
863 }
864
865
866 /******************************************************************
867  *         MF_CreateFontIndirect
868  */
869 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
870 {
871     int index;
872     BOOL rc;
873     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
874     METARECORD *mr = (METARECORD *)&buffer;
875     METAFILE *mf;
876     METAHEADER *mh;
877
878     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
879     mr->rdFunction = META_CREATEFONTINDIRECT;
880     memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
881     if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
882         return FALSE;
883
884     mr->rdSize = sizeof(METARECORD) / 2;
885     mr->rdFunction = META_SELECTOBJECT;
886     if ((index = MF_AddHandleInternal(hFont)) == -1)
887         return FALSE;
888
889     mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
890     mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
891     *(mr->rdParam) = index;
892     if (index >= mh->mtNoObjects)
893         mh->mtNoObjects++;
894     rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
895     GlobalUnlock(mf->hMetaHdr);
896     GlobalUnlock(dc->w.hMetaFile);
897     return rc;
898 }
899
900
901 /******************************************************************
902  *         MF_TextOut
903  */
904 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
905 {
906     BOOL rc;
907     DWORD len;
908     HANDLE hmr;
909     METARECORD *mr;
910
911     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
912     if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
913         return FALSE;
914     mr = (METARECORD *)GlobalLock(hmr);
915     memset(mr, 0, len);
916
917     mr->rdSize = len / 2;
918     mr->rdFunction = META_TEXTOUT;
919     *(mr->rdParam) = count;
920     memcpy(mr->rdParam + 1, str, count);
921     *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
922     *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
923     rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
924     GlobalFree(hmr);
925     return rc;
926 }
927
928
929 /******************************************************************
930  *         MF_MetaPoly - implements Polygon and Polyline
931  */
932 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
933 {
934     BOOL rc;
935     DWORD len;
936     HANDLE hmr;
937     METARECORD *mr;
938
939     len = sizeof(METARECORD) + (count * 4); 
940     if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
941         return FALSE;
942     mr = (METARECORD *)GlobalLock(hmr);
943     memset(mr, 0, len);
944
945     mr->rdSize = len / 2;
946     mr->rdFunction = func;
947     *(mr->rdParam) = count;
948     memcpy(mr->rdParam + 1, pt, count * 4);
949     rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
950     GlobalFree(hmr);
951     return rc;
952 }
953
954
955 /******************************************************************
956  *         MF_BitBlt
957  */
958 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
959                short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
960 {
961     fprintf(stdnimp,"MF_BitBlt: not implemented yet\n");
962     return FALSE;
963 }
964
965
966 /******************************************************************
967  *         MF_StretchBlt
968  */
969 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
970                    short heightDest, HDC hdcSrc, short xSrc, short ySrc, 
971                    short widthSrc, short heightSrc, DWORD rop)
972 {
973     fprintf(stdnimp,"MF_StretchBlt: not implemented yet\n");
974     return FALSE;
975 }