Release 941210
[wine/multimedia.git] / objects / metafile.c
blobdebdf2348125e969d948911e01eff5c30bb9131c
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
6 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
7 */
9 #include <string.h>
10 #include "windows.h"
11 #include "gdi.h"
12 #include "metafile.h"
13 #include "prototypes.h"
14 #include "stddebug.h"
15 /* #define DEBUG_METAFILE */
16 #include "debug.h"
18 #define HTINCR 10 /* handle table allocation size increment */
20 static HANDLE hHT; /* handle of the handle table */
21 static int HTLen; /* allocated length of handle table */
23 /******************************************************************
24 * GetMetafile GDI.124 By Kenny MacDonald 30 Nov 94
26 HMETAFILE GetMetaFile(LPSTR lpFilename)
29 DC *dc;
30 HMETAFILE hmf;
31 METAFILE *mf;
32 METAHEADER *mh;
34 dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
36 if (!lpFilename)
37 return 0;
39 hmf = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE));
40 mf = (METAFILE *)GlobalLock(hmf);
41 if (!mf) {
42 GlobalFree(hmf);
43 return 0;
46 mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, MFHEADERSIZE);
47 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
48 if (!mh) {
49 GlobalFree(mf->hMetaHdr);
50 GlobalFree(hmf);
51 return 0;
53 strcpy(mf->Filename, lpFilename);
54 mf->wMagic = METAFILE_MAGIC;
55 if ((mf->hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) {
56 GlobalFree(hmf);
57 return 0;
59 if (_lread(mf->hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
60 GlobalFree(mf->hMetaHdr);
61 GlobalFree(hmf);
62 return 0;
64 _lclose(mf->hFile);
67 GlobalUnlock(mf->hMetaHdr);
68 GlobalUnlock(hmf);
69 if (mh->mtType != 1)
70 return 0;
71 else
72 return hmf;
75 /******************************************************************
76 * CreateMetafile GDI.125
78 HANDLE CreateMetaFile(LPSTR lpFilename)
80 DC *dc;
81 HANDLE handle;
82 METAFILE *mf;
83 METAHEADER *mh;
84 HANDLETABLE *ht;
86 dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
88 handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
89 if (!handle) return 0;
90 dc = (DC *)GDI_HEAP_ADDR(handle);
92 if (!(dc->w.hMetaFile = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE))))
93 return 0;
94 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
95 if (!(mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAHEADER))))
97 GlobalFree(dc->w.hMetaFile);
98 return 0;
100 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
102 mf->wMagic = METAFILE_MAGIC;
103 mh->mtHeaderSize = MFHEADERSIZE / 2;
104 mh->mtVersion = MFVERSION;
105 mh->mtSize = MFHEADERSIZE / 2;
106 mh->mtNoObjects = 0;
107 mh->mtMaxRecord = 0;
108 mh->mtNoParameters = 0;
110 if (lpFilename) /* disk based metafile */
112 mh->mtType = 1;
113 strcpy(mf->Filename, lpFilename);
114 mf->hFile = _lcreat(lpFilename, 0);
115 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
117 GlobalFree(mf->hMetaHdr);
118 GlobalFree(dc->w.hMetaFile);
119 return 0;
122 else /* memory based metafile */
123 mh->mtType = 0;
125 /* create the handle table */
126 HTLen = HTINCR;
127 hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
128 sizeof(HANDLETABLE) * HTLen);
129 ht = (HANDLETABLE *)GlobalLock(hHT);
131 GlobalUnlock(mf->hMetaHdr);
132 GlobalUnlock(dc->w.hMetaFile);
133 return handle;
137 /******************************************************************
138 * CloseMetafile GDI.126
140 HMETAFILE CloseMetaFile(HDC hdc)
142 DC *dc;
143 METAFILE *mf;
144 METAHEADER *mh;
145 HMETAFILE hmf;
146 char buffer[15];
147 /* METARECORD *mr = (METARECORD *)&buffer;*/
149 dprintf_metafile(stddeb,"CloseMetaFile\n");
151 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
152 if (!dc) return 0;
153 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
154 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
156 /* Construct the end of metafile record - this is documented
157 * in SDK Knowledgebase Q99334.
159 if (!MF_MetaParam0(dc, META_EOF))
161 GlobalFree(mf->hMetaHdr);
162 GlobalFree(dc->w.hMetaFile);
163 return 0;
166 if (mh->mtType == 1) /* disk based metafile */
168 if (_llseek(mf->hFile, 0L, 0) == -1)
170 GlobalFree(mf->hMetaHdr);
171 GlobalFree(dc->w.hMetaFile);
172 return 0;
174 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
176 GlobalFree(mf->hMetaHdr);
177 GlobalFree(dc->w.hMetaFile);
178 return 0;
180 _lclose(mf->hFile);
183 /* delete the handle table */
184 GlobalFree(hHT);
186 GlobalUnlock(mf->hMetaHdr);
187 hmf = dc->w.hMetaFile;
188 GlobalUnlock(hmf);
189 GDI_FreeObject(hdc);
190 return hmf;
194 /******************************************************************
195 * DeleteMetafile GDI.127
197 BOOL DeleteMetaFile(HMETAFILE hmf)
199 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
201 if (mf->wMagic != METAFILE_MAGIC)
202 return FALSE;
204 GlobalFree(mf->hMetaHdr);
205 GlobalFree(hmf);
206 return TRUE;
210 /******************************************************************
211 * PlayMetafile GDI.123
213 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
215 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
216 METAHEADER *mh;
217 METARECORD *mr;
218 HANDLETABLE *ht;
219 char *buffer;
221 if (mf->wMagic != METAFILE_MAGIC)
222 return FALSE;
224 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
225 if (mh->mtType == 1) /* disk based metafile */
227 mf->hFile = _lopen(mf->Filename, OF_READ);
228 mf->hBuffer = GlobalAlloc(GMEM_MOVEABLE, mh->mtMaxRecord * 2);
229 buffer = (char *)GlobalLock(mf->hBuffer);
230 _llseek(mf->hFile, mh->mtHeaderSize * 2, 0);
231 mf->MetaOffset = mh->mtHeaderSize * 2;
233 else if (mh->mtType == 0) /* memory based metafile */
234 mf->MetaOffset = mh->mtHeaderSize * 2;
235 else /* not a valid metafile type */
236 return FALSE;
238 /* create the handle table */
239 hHT = GlobalAlloc(GMEM_MOVEABLE, sizeof(HANDLETABLE) * mh->mtNoObjects);
240 ht = (HANDLETABLE *)GlobalLock(hHT);
242 /* loop through metafile playing records */
243 while (mf->MetaOffset < mh->mtSize * 2)
245 if (mh->mtType == 1) /* disk based metafile */
247 _lread(mf->hFile, buffer, sizeof(METARECORD));
248 mr = (METARECORD *)buffer;
249 _lread(mf->hFile, (char *)(mr->rdParam + 1), (mr->rdSize * 2) -
250 sizeof(METARECORD));
251 mf->MetaOffset += mr->rdSize * 2;
253 else /* memory based metafile */
255 mr = (METARECORD *)((char *)mh + mf->MetaOffset);
256 mf->MetaOffset += mr->rdSize * 2;
258 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
261 /* close disk based metafile and free buffer */
262 if (mh->mtType == 1)
264 GlobalFree(mf->hBuffer);
265 _lclose(mf->hFile);
268 /* free handle table */
269 GlobalFree(hHT);
271 return TRUE;
275 /******************************************************************
276 * PlayMetaFileRecord GDI.176
278 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
279 WORD nHandles)
281 short s1;
282 HANDLE hndl;
283 char *ptr;
284 BITMAPINFOHEADER *infohdr;
286 switch (mr->rdFunction)
288 case META_EOF:
289 break;
291 case META_DELETEOBJECT:
292 DeleteObject(*(ht->objectHandle + *(mr->rdParam)));
293 break;
295 case META_SETBKCOLOR:
296 SetBkColor(hdc, *(mr->rdParam));
297 break;
299 case META_SETBKMODE:
300 SetBkMode(hdc, *(mr->rdParam));
301 break;
303 case META_SETMAPMODE:
304 SetMapMode(hdc, *(mr->rdParam));
305 break;
307 case META_SETROP2:
308 SetROP2(hdc, *(mr->rdParam));
309 break;
311 case META_SETRELABS:
312 SetRelAbs(hdc, *(mr->rdParam));
313 break;
315 case META_SETPOLYFILLMODE:
316 SetPolyFillMode(hdc, *(mr->rdParam));
317 break;
319 case META_SETSTRETCHBLTMODE:
320 SetStretchBltMode(hdc, *(mr->rdParam));
321 break;
323 case META_SETTEXTCOLOR:
324 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
325 break;
327 case META_SETWINDOWORG:
328 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
329 break;
331 case META_SETWINDOWEXT:
332 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
333 break;
335 case META_SETVIEWPORTORG:
336 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
337 break;
339 case META_SETVIEWPORTEXT:
340 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
341 break;
343 case META_OFFSETWINDOWORG:
344 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
345 break;
347 case META_SCALEWINDOWEXT:
348 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
349 *(mr->rdParam + 1), *(mr->rdParam));
350 break;
352 case META_OFFSETVIEWPORTORG:
353 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
354 break;
356 case META_SCALEVIEWPORTEXT:
357 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
358 *(mr->rdParam + 1), *(mr->rdParam));
359 break;
361 case META_LINETO:
362 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
363 break;
365 case META_MOVETO:
366 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
367 break;
369 case META_EXCLUDECLIPRECT:
370 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
371 *(mr->rdParam + 1), *(mr->rdParam));
372 break;
374 case META_INTERSECTCLIPRECT:
375 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
376 *(mr->rdParam + 1), *(mr->rdParam));
377 break;
379 case META_ARC:
380 Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
381 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
382 *(mr->rdParam + 1), *(mr->rdParam));
383 break;
385 case META_ELLIPSE:
386 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
387 *(mr->rdParam + 1), *(mr->rdParam));
388 break;
390 case META_FLOODFILL:
391 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
392 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
393 break;
395 case META_PIE:
396 Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
397 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
398 *(mr->rdParam + 1), *(mr->rdParam));
399 break;
401 case META_RECTANGLE:
402 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
403 *(mr->rdParam + 1), *(mr->rdParam));
404 break;
406 case META_ROUNDRECT:
407 RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
408 *(mr->rdParam + 3), *(mr->rdParam + 2),
409 *(mr->rdParam + 1), *(mr->rdParam));
410 break;
412 case META_PATBLT:
413 PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
414 *(mr->rdParam + 3), *(mr->rdParam + 2),
415 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
416 break;
418 case META_SAVEDC:
419 SaveDC(hdc);
420 break;
422 case META_SETPIXEL:
423 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
424 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
425 break;
427 case META_OFFSETCLIPRGN:
428 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
429 break;
431 case META_TEXTOUT:
432 s1 = *(mr->rdParam);
433 TextOut(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
434 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
435 (char *)(mr->rdParam + 1), s1);
436 break;
438 case META_POLYGON:
439 Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
440 break;
442 case META_POLYPOLYGON:
443 PolyPolygon(hdc, (LPPOINT)(mr->rdParam + *(mr->rdParam) + 1),
444 (mr->rdParam + 1), *(mr->rdParam));
445 break;
447 case META_POLYLINE:
448 Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
449 break;
451 case META_RESTOREDC:
452 RestoreDC(hdc, *(mr->rdParam));
453 break;
455 case META_SELECTOBJECT:
456 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
457 break;
459 case META_CHORD:
460 Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
461 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
462 *(mr->rdParam + 1), *(mr->rdParam));
463 break;
465 case META_CREATEPATTERNBRUSH:
466 switch (*(mr->rdParam))
468 case BS_PATTERN:
469 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
470 MF_AddHandle(ht, nHandles,
471 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
472 infohdr->biHeight,
473 infohdr->biPlanes,
474 infohdr->biBitCount,
475 (LPSTR)(mr->rdParam +
476 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
477 break;
479 case BS_DIBPATTERN:
480 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
481 hndl = GlobalAlloc(GMEM_MOVEABLE, s1);
482 ptr = GlobalLock(hndl);
483 memcpy(ptr, mr->rdParam + 2, s1);
484 GlobalUnlock(hndl);
485 MF_AddHandle(ht, nHandles,
486 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
487 GlobalFree(hndl);
489 break;
491 case META_CREATEPENINDIRECT:
492 MF_AddHandle(ht, nHandles,
493 CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
494 break;
496 case META_CREATEFONTINDIRECT:
497 MF_AddHandle(ht, nHandles,
498 CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
499 break;
501 case META_CREATEBRUSHINDIRECT:
502 MF_AddHandle(ht, nHandles,
503 CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
504 break;
506 default:
507 fprintf(stderr,"PlayMetaFileRecord: Unknown record type %x\n",
508 mr->rdFunction);
513 /******************************************************************
514 * MF_WriteRecord
516 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
518 DWORD len;
519 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
520 METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
522 if (mh->mtType == 0) /* memory based metafile */
524 len = mh->mtSize * 2 + rlen;
525 GlobalUnlock(mf->hMetaHdr);
526 mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE);
527 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
528 memcpy(mh + mh->mtSize * 2, mr, rlen);
530 else if (mh->mtType == 1) /* disk based metafile */
532 if (_lwrite(mf->hFile, (char *)mr, rlen) == -1)
534 GlobalUnlock(mf->hMetaHdr);
535 return FALSE;
538 else
540 GlobalUnlock(mf->hMetaHdr);
541 return FALSE;
544 mh->mtSize += rlen / 2;
545 mh->mtMaxRecord = max(mh->mtMaxRecord, rlen / 2);
546 GlobalUnlock(mf->hMetaHdr);
547 return TRUE;
551 /******************************************************************
552 * MF_AddHandle
554 * Add a handle to an external handle table and return the index
556 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
558 int i;
560 for (i = 0; i < htlen; i++)
562 if (*(ht->objectHandle + i) == 0)
564 *(ht->objectHandle + i) = hobj;
565 return i;
568 return -1;
572 /******************************************************************
573 * MF_AddHandleInternal
575 * Add a handle to the internal handle table and return the index
577 int MF_AddHandleInternal(HANDLE hobj)
579 int i;
580 HANDLETABLE *ht = (HANDLETABLE *)GlobalLock(hHT);
582 for (i = 0; i < HTLen; i++)
584 if (*(ht->objectHandle + i) == 0)
586 *(ht->objectHandle + i) = hobj;
587 GlobalUnlock(hHT);
588 return i;
591 GlobalUnlock(hHT);
592 if (!(hHT = GlobalReAlloc(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
593 return -1;
594 HTLen += HTINCR;
595 ht = (HANDLETABLE *)GlobalLock(hHT);
596 *(ht->objectHandle + i) = hobj;
597 GlobalUnlock(hHT);
598 return i;
602 /******************************************************************
603 * MF_MetaParam0
605 BOOL MF_MetaParam0(DC *dc, short func)
607 char buffer[8];
608 METARECORD *mr = (METARECORD *)&buffer;
610 mr->rdSize = 3;
611 mr->rdFunction = func;
612 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
616 /******************************************************************
617 * MF_MetaParam1
619 BOOL MF_MetaParam1(DC *dc, short func, short param1)
621 char buffer[8];
622 METARECORD *mr = (METARECORD *)&buffer;
624 mr->rdSize = 4;
625 mr->rdFunction = func;
626 *(mr->rdParam) = param1;
627 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
631 /******************************************************************
632 * MF_MetaParam2
634 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
636 char buffer[10];
637 METARECORD *mr = (METARECORD *)&buffer;
639 mr->rdSize = 5;
640 mr->rdFunction = func;
641 *(mr->rdParam) = param2;
642 *(mr->rdParam + 1) = param1;
643 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
647 /******************************************************************
648 * MF_MetaParam4
650 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
651 short param3, short param4)
653 char buffer[14];
654 METARECORD *mr = (METARECORD *)&buffer;
656 mr->rdSize = 7;
657 mr->rdFunction = func;
658 *(mr->rdParam) = param4;
659 *(mr->rdParam + 1) = param3;
660 *(mr->rdParam + 2) = param2;
661 *(mr->rdParam + 3) = param1;
662 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
666 /******************************************************************
667 * MF_MetaParam6
669 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
670 short param3, short param4, short param5, short param6)
672 char buffer[18];
673 METARECORD *mr = (METARECORD *)&buffer;
675 mr->rdSize = 9;
676 mr->rdFunction = func;
677 *(mr->rdParam) = param6;
678 *(mr->rdParam + 1) = param5;
679 *(mr->rdParam + 2) = param4;
680 *(mr->rdParam + 3) = param3;
681 *(mr->rdParam + 4) = param2;
682 *(mr->rdParam + 5) = param1;
683 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
687 /******************************************************************
688 * MF_MetaParam8
690 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
691 short param3, short param4, short param5,
692 short param6, short param7, short param8)
694 char buffer[22];
695 METARECORD *mr = (METARECORD *)&buffer;
697 mr->rdSize = 11;
698 mr->rdFunction = func;
699 *(mr->rdParam) = param8;
700 *(mr->rdParam + 1) = param7;
701 *(mr->rdParam + 2) = param6;
702 *(mr->rdParam + 3) = param5;
703 *(mr->rdParam + 4) = param4;
704 *(mr->rdParam + 5) = param3;
705 *(mr->rdParam + 6) = param2;
706 *(mr->rdParam + 7) = param1;
707 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
711 /******************************************************************
712 * MF_CreateBrushIndirect
714 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
716 int index;
717 BOOL rc;
718 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
719 METARECORD *mr = (METARECORD *)&buffer;
720 METAFILE *mf;
721 METAHEADER *mh;
723 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
724 mr->rdFunction = META_CREATEBRUSHINDIRECT;
725 memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
726 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
727 return FALSE;
729 mr->rdSize = sizeof(METARECORD) / 2;
730 mr->rdFunction = META_SELECTOBJECT;
731 if ((index = MF_AddHandleInternal(hBrush)) == -1)
732 return FALSE;
734 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
735 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
736 *(mr->rdParam) = index;
737 if (index >= mh->mtNoObjects)
738 mh->mtNoObjects++;
739 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
740 GlobalUnlock(mf->hMetaHdr);
741 GlobalUnlock(dc->w.hMetaFile);
742 return rc;
746 /******************************************************************
747 * MF_CreatePatternBrush
749 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
751 DWORD len, bmSize, biSize;
752 HANDLE hmr;
753 METARECORD *mr;
754 BITMAPOBJ *bmp;
755 BITMAPINFO *info;
756 BITMAPINFOHEADER *infohdr;
757 int index;
758 BOOL rc;
759 char buffer[sizeof(METARECORD)];
760 METAFILE *mf;
761 METAHEADER *mh;
763 switch (logbrush->lbStyle)
765 case BS_PATTERN:
766 bmp = (BITMAPOBJ *)GDI_GetObjPtr(logbrush->lbHatch, BITMAP_MAGIC);
767 if (!bmp) return FALSE;
768 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
769 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
770 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
771 return FALSE;
772 mr = (METARECORD *)GlobalLock(hmr);
773 memset(mr, 0, len);
774 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
775 mr->rdSize = len / 2;
776 *(mr->rdParam) = logbrush->lbStyle;
777 *(mr->rdParam + 1) = DIB_RGB_COLORS;
778 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
779 infohdr->biSize = sizeof(BITMAPINFOHEADER);
780 infohdr->biWidth = bmp->bitmap.bmWidth;
781 infohdr->biHeight = bmp->bitmap.bmHeight;
782 infohdr->biPlanes = bmp->bitmap.bmPlanes;
783 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
784 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
785 bmp->bitmap.bmBits,
786 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
787 break;
789 case BS_DIBPATTERN:
790 info = (BITMAPINFO *)GlobalLock(logbrush->lbHatch);
791 bmSize = info->bmiHeader.biSizeImage;
792 if (!bmSize)
793 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
794 + 31) / 32 * 8 * info->bmiHeader.biHeight;
795 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
796 len = sizeof(METARECORD) + biSize + bmSize + 2;
797 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
798 return FALSE;
799 mr = (METARECORD *)GlobalLock(hmr);
800 memset(mr, 0, len);
801 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
802 mr->rdSize = len / 2;
803 *(mr->rdParam) = logbrush->lbStyle;
804 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
805 memcpy(mr->rdParam + 2, info, biSize + bmSize);
806 break;
808 if (!MF_WriteRecord(dc->w.hMetaFile, mr, len))
810 GlobalFree(hmr);
811 return FALSE;
814 GlobalFree(hmr);
815 mr = (METARECORD *)&buffer;
816 mr->rdSize = sizeof(METARECORD) / 2;
817 mr->rdFunction = META_SELECTOBJECT;
818 if ((index = MF_AddHandleInternal(hBrush)) == -1)
819 return FALSE;
821 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
822 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
823 *(mr->rdParam) = index;
824 if (index >= mh->mtNoObjects)
825 mh->mtNoObjects++;
826 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
827 GlobalUnlock(mf->hMetaHdr);
828 GlobalUnlock(dc->w.hMetaFile);
829 return rc;
833 /******************************************************************
834 * MF_CreatePenIndirect
836 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
838 int index;
839 BOOL rc;
840 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
841 METARECORD *mr = (METARECORD *)&buffer;
842 METAFILE *mf;
843 METAHEADER *mh;
845 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
846 mr->rdFunction = META_CREATEPENINDIRECT;
847 memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
848 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
849 return FALSE;
851 mr->rdSize = sizeof(METARECORD) / 2;
852 mr->rdFunction = META_SELECTOBJECT;
853 if ((index = MF_AddHandleInternal(hPen)) == -1)
854 return FALSE;
856 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
857 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
858 *(mr->rdParam) = index;
859 if (index >= mh->mtNoObjects)
860 mh->mtNoObjects++;
861 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
862 GlobalUnlock(mf->hMetaHdr);
863 GlobalUnlock(dc->w.hMetaFile);
864 return rc;
868 /******************************************************************
869 * MF_CreateFontIndirect
871 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
873 int index;
874 BOOL rc;
875 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
876 METARECORD *mr = (METARECORD *)&buffer;
877 METAFILE *mf;
878 METAHEADER *mh;
880 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
881 mr->rdFunction = META_CREATEFONTINDIRECT;
882 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
883 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
884 return FALSE;
886 mr->rdSize = sizeof(METARECORD) / 2;
887 mr->rdFunction = META_SELECTOBJECT;
888 if ((index = MF_AddHandleInternal(hFont)) == -1)
889 return FALSE;
891 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
892 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
893 *(mr->rdParam) = index;
894 if (index >= mh->mtNoObjects)
895 mh->mtNoObjects++;
896 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
897 GlobalUnlock(mf->hMetaHdr);
898 GlobalUnlock(dc->w.hMetaFile);
899 return rc;
903 /******************************************************************
904 * MF_TextOut
906 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
908 BOOL rc;
909 DWORD len;
910 HANDLE hmr;
911 METARECORD *mr;
913 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
914 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
915 return FALSE;
916 mr = (METARECORD *)GlobalLock(hmr);
917 memset(mr, 0, len);
919 mr->rdSize = len / 2;
920 mr->rdFunction = META_TEXTOUT;
921 *(mr->rdParam) = count;
922 memcpy(mr->rdParam + 1, str, count);
923 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
924 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
925 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
926 GlobalFree(hmr);
927 return rc;
931 /******************************************************************
932 * MF_MetaPoly - implements Polygon and Polyline
934 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
936 BOOL rc;
937 DWORD len;
938 HANDLE hmr;
939 METARECORD *mr;
941 len = sizeof(METARECORD) + (count * 4);
942 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
943 return FALSE;
944 mr = (METARECORD *)GlobalLock(hmr);
945 memset(mr, 0, len);
947 mr->rdSize = len / 2;
948 mr->rdFunction = func;
949 *(mr->rdParam) = count;
950 memcpy(mr->rdParam + 1, pt, count * 4);
951 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
952 GlobalFree(hmr);
953 return rc;
957 /******************************************************************
958 * MF_BitBlt
960 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
961 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
963 fprintf(stdnimp,"MF_BitBlt: not implemented yet\n");
967 /******************************************************************
968 * MF_StretchBlt
970 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
971 short heightDest, HDC hdcSrc, short xSrc, short ySrc,
972 short widthSrc, short heightSrc, DWORD rop)
974 fprintf(stdnimp,"MF_StretchBlt: not implemented yet\n");