Release 950122
[wine/multimedia.git] / objects / metafile.c
blob1ad135e59d27ed3b2790c5406b98511f71aeeefb
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 "gdi.h"
11 #include "bitmap.h"
12 #include "metafile.h"
13 #include "stddebug.h"
14 /* #define DEBUG_METAFILE */
15 #include "debug.h"
17 #define HTINCR 10 /* handle table allocation size increment */
19 static HANDLE hHT; /* handle of the handle table */
20 static int HTLen; /* allocated length of handle table */
22 /******************************************************************
23 * GetMetafile GDI.124 By Kenny MacDonald 30 Nov 94
25 HMETAFILE GetMetaFile(LPSTR lpFilename)
27 HMETAFILE hmf;
28 METAFILE *mf;
29 METAHEADER *mh;
31 dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
33 if (!lpFilename)
34 return 0;
36 hmf = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE));
37 mf = (METAFILE *)GlobalLock(hmf);
38 if (!mf) {
39 GlobalFree(hmf);
40 return 0;
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;
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;
56 if (_lread(mf->hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
57 GlobalFree(mf->hMetaHdr);
58 GlobalFree(hmf);
59 return 0;
61 _lclose(mf->hFile);
64 GlobalUnlock(mf->hMetaHdr);
65 GlobalUnlock(hmf);
66 if (mh->mtType != 1)
67 return 0;
68 else
69 return hmf;
72 /******************************************************************
73 * CreateMetafile GDI.125
75 HANDLE CreateMetaFile(LPSTR lpFilename)
77 DC *dc;
78 HANDLE handle;
79 METAFILE *mf;
80 METAHEADER *mh;
81 HANDLETABLE *ht;
83 dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
85 handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
86 if (!handle) return 0;
87 dc = (DC *)GDI_HEAP_ADDR(handle);
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))))
94 GlobalFree(dc->w.hMetaFile);
95 return 0;
97 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
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;
107 if (lpFilename) /* disk based metafile */
109 mh->mtType = 1;
110 strcpy(mf->Filename, lpFilename);
111 mf->hFile = _lcreat(lpFilename, 0);
112 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
114 GlobalFree(mf->hMetaHdr);
115 GlobalFree(dc->w.hMetaFile);
116 return 0;
119 else /* memory based metafile */
120 mh->mtType = 0;
122 /* create the handle table */
123 HTLen = HTINCR;
124 hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
125 sizeof(HANDLETABLE) * HTLen);
126 ht = (HANDLETABLE *)GlobalLock(hHT);
128 GlobalUnlock(mf->hMetaHdr);
129 GlobalUnlock(dc->w.hMetaFile);
130 return handle;
134 /******************************************************************
135 * CloseMetafile GDI.126
137 HMETAFILE CloseMetaFile(HDC hdc)
139 DC *dc;
140 METAFILE *mf;
141 METAHEADER *mh;
142 HMETAFILE hmf;
143 /* METARECORD *mr = (METARECORD *)&buffer;*/
145 dprintf_metafile(stddeb,"CloseMetaFile\n");
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);
152 /* Construct the end of metafile record - this is documented
153 * in SDK Knowledgebase Q99334.
155 if (!MF_MetaParam0(dc, META_EOF))
157 GlobalFree(mf->hMetaHdr);
158 GlobalFree(dc->w.hMetaFile);
159 return 0;
162 if (mh->mtType == 1) /* disk based metafile */
164 if (_llseek(mf->hFile, 0L, 0) == -1)
166 GlobalFree(mf->hMetaHdr);
167 GlobalFree(dc->w.hMetaFile);
168 return 0;
170 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
172 GlobalFree(mf->hMetaHdr);
173 GlobalFree(dc->w.hMetaFile);
174 return 0;
176 _lclose(mf->hFile);
179 /* delete the handle table */
180 GlobalFree(hHT);
182 GlobalUnlock(mf->hMetaHdr);
183 hmf = dc->w.hMetaFile;
184 GlobalUnlock(hmf);
185 GDI_FreeObject(hdc);
186 return hmf;
190 /******************************************************************
191 * DeleteMetafile GDI.127
193 BOOL DeleteMetaFile(HMETAFILE hmf)
195 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
197 if (mf->wMagic != METAFILE_MAGIC)
198 return FALSE;
200 GlobalFree(mf->hMetaHdr);
201 GlobalFree(hmf);
202 return TRUE;
206 /******************************************************************
207 * PlayMetafile GDI.123
209 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
211 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
212 METAHEADER *mh;
213 METARECORD *mr;
214 HANDLETABLE *ht;
215 char *buffer;
217 if (mf->wMagic != METAFILE_MAGIC)
218 return FALSE;
220 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
221 if (mh->mtType == 1) /* disk based metafile */
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;
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;
234 /* create the handle table */
235 hHT = GlobalAlloc(GMEM_MOVEABLE, sizeof(HANDLETABLE) * mh->mtNoObjects);
236 ht = (HANDLETABLE *)GlobalLock(hHT);
238 /* loop through metafile playing records */
239 while (mf->MetaOffset < mh->mtSize * 2)
241 if (mh->mtType == 1) /* disk based metafile */
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;
249 else /* memory based metafile */
251 mr = (METARECORD *)((char *)mh + mf->MetaOffset);
252 mf->MetaOffset += mr->rdSize * 2;
254 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
257 /* close disk based metafile and free buffer */
258 if (mh->mtType == 1)
260 GlobalFree(mf->hBuffer);
261 _lclose(mf->hFile);
264 /* free handle table */
265 GlobalFree(hHT);
267 return TRUE;
271 /******************************************************************
272 * PlayMetaFileRecord GDI.176
274 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
275 WORD nHandles)
277 short s1;
278 HANDLE hndl;
279 char *ptr;
280 BITMAPINFOHEADER *infohdr;
282 switch (mr->rdFunction)
284 case META_EOF:
285 break;
287 case META_DELETEOBJECT:
288 DeleteObject(*(ht->objectHandle + *(mr->rdParam)));
289 break;
291 case META_SETBKCOLOR:
292 SetBkColor(hdc, *(mr->rdParam));
293 break;
295 case META_SETBKMODE:
296 SetBkMode(hdc, *(mr->rdParam));
297 break;
299 case META_SETMAPMODE:
300 SetMapMode(hdc, *(mr->rdParam));
301 break;
303 case META_SETROP2:
304 SetROP2(hdc, *(mr->rdParam));
305 break;
307 case META_SETRELABS:
308 SetRelAbs(hdc, *(mr->rdParam));
309 break;
311 case META_SETPOLYFILLMODE:
312 SetPolyFillMode(hdc, *(mr->rdParam));
313 break;
315 case META_SETSTRETCHBLTMODE:
316 SetStretchBltMode(hdc, *(mr->rdParam));
317 break;
319 case META_SETTEXTCOLOR:
320 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
321 break;
323 case META_SETWINDOWORG:
324 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
325 break;
327 case META_SETWINDOWEXT:
328 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
329 break;
331 case META_SETVIEWPORTORG:
332 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
333 break;
335 case META_SETVIEWPORTEXT:
336 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
337 break;
339 case META_OFFSETWINDOWORG:
340 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
341 break;
343 case META_SCALEWINDOWEXT:
344 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
345 *(mr->rdParam + 1), *(mr->rdParam));
346 break;
348 case META_OFFSETVIEWPORTORG:
349 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
350 break;
352 case META_SCALEVIEWPORTEXT:
353 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
354 *(mr->rdParam + 1), *(mr->rdParam));
355 break;
357 case META_LINETO:
358 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
359 break;
361 case META_MOVETO:
362 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
363 break;
365 case META_EXCLUDECLIPRECT:
366 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
367 *(mr->rdParam + 1), *(mr->rdParam));
368 break;
370 case META_INTERSECTCLIPRECT:
371 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
372 *(mr->rdParam + 1), *(mr->rdParam));
373 break;
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;
381 case META_ELLIPSE:
382 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
383 *(mr->rdParam + 1), *(mr->rdParam));
384 break;
386 case META_FLOODFILL:
387 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
388 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
389 break;
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;
397 case META_RECTANGLE:
398 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
399 *(mr->rdParam + 1), *(mr->rdParam));
400 break;
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;
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;
414 case META_SAVEDC:
415 SaveDC(hdc);
416 break;
418 case META_SETPIXEL:
419 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
420 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
421 break;
423 case META_OFFSETCLIPRGN:
424 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
425 break;
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;
434 case META_POLYGON:
435 Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
436 break;
438 case META_POLYPOLYGON:
439 PolyPolygon(hdc, (LPPOINT)(mr->rdParam + *(mr->rdParam) + 1),
440 (mr->rdParam + 1), *(mr->rdParam));
441 break;
443 case META_POLYLINE:
444 Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
445 break;
447 case META_RESTOREDC:
448 RestoreDC(hdc, *(mr->rdParam));
449 break;
451 case META_SELECTOBJECT:
452 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
453 break;
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;
461 case META_CREATEPATTERNBRUSH:
462 switch (*(mr->rdParam))
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;
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);
485 break;
487 case META_CREATEPENINDIRECT:
488 MF_AddHandle(ht, nHandles,
489 CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
490 break;
492 case META_CREATEFONTINDIRECT:
493 MF_AddHandle(ht, nHandles,
494 CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
495 break;
497 case META_CREATEBRUSHINDIRECT:
498 MF_AddHandle(ht, nHandles,
499 CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
500 break;
502 default:
503 fprintf(stderr,"PlayMetaFileRecord: Unknown record type %x\n",
504 mr->rdFunction);
509 /******************************************************************
510 * MF_WriteRecord
512 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
514 DWORD len;
515 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
516 METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
518 if (mh->mtType == 0) /* memory based metafile */
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);
526 else if (mh->mtType == 1) /* disk based metafile */
528 if (_lwrite(mf->hFile, (char *)mr, rlen) == -1)
530 GlobalUnlock(mf->hMetaHdr);
531 return FALSE;
534 else
536 GlobalUnlock(mf->hMetaHdr);
537 return FALSE;
540 mh->mtSize += rlen / 2;
541 mh->mtMaxRecord = max(mh->mtMaxRecord, rlen / 2);
542 GlobalUnlock(mf->hMetaHdr);
543 return TRUE;
547 /******************************************************************
548 * MF_AddHandle
550 * Add a handle to an external handle table and return the index
552 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
554 int i;
556 for (i = 0; i < htlen; i++)
558 if (*(ht->objectHandle + i) == 0)
560 *(ht->objectHandle + i) = hobj;
561 return i;
564 return -1;
568 /******************************************************************
569 * MF_AddHandleInternal
571 * Add a handle to the internal handle table and return the index
573 int MF_AddHandleInternal(HANDLE hobj)
575 int i;
576 HANDLETABLE *ht = (HANDLETABLE *)GlobalLock(hHT);
578 for (i = 0; i < HTLen; i++)
580 if (*(ht->objectHandle + i) == 0)
582 *(ht->objectHandle + i) = hobj;
583 GlobalUnlock(hHT);
584 return i;
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;
598 /******************************************************************
599 * MF_MetaParam0
601 BOOL MF_MetaParam0(DC *dc, short func)
603 char buffer[8];
604 METARECORD *mr = (METARECORD *)&buffer;
606 mr->rdSize = 3;
607 mr->rdFunction = func;
608 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
612 /******************************************************************
613 * MF_MetaParam1
615 BOOL MF_MetaParam1(DC *dc, short func, short param1)
617 char buffer[8];
618 METARECORD *mr = (METARECORD *)&buffer;
620 mr->rdSize = 4;
621 mr->rdFunction = func;
622 *(mr->rdParam) = param1;
623 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
627 /******************************************************************
628 * MF_MetaParam2
630 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
632 char buffer[10];
633 METARECORD *mr = (METARECORD *)&buffer;
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);
643 /******************************************************************
644 * MF_MetaParam4
646 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
647 short param3, short param4)
649 char buffer[14];
650 METARECORD *mr = (METARECORD *)&buffer;
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);
662 /******************************************************************
663 * MF_MetaParam6
665 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
666 short param3, short param4, short param5, short param6)
668 char buffer[18];
669 METARECORD *mr = (METARECORD *)&buffer;
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);
683 /******************************************************************
684 * MF_MetaParam8
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)
690 char buffer[22];
691 METARECORD *mr = (METARECORD *)&buffer;
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);
707 /******************************************************************
708 * MF_CreateBrushIndirect
710 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
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;
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;
725 mr->rdSize = sizeof(METARECORD) / 2;
726 mr->rdFunction = META_SELECTOBJECT;
727 if ((index = MF_AddHandleInternal(hBrush)) == -1)
728 return FALSE;
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;
742 /******************************************************************
743 * MF_CreatePatternBrush
745 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
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;
759 switch (logbrush->lbStyle)
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;
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;
806 if (!MF_WriteRecord(dc->w.hMetaFile, mr, len))
808 GlobalFree(hmr);
809 return FALSE;
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;
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;
831 /******************************************************************
832 * MF_CreatePenIndirect
834 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
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;
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;
849 mr->rdSize = sizeof(METARECORD) / 2;
850 mr->rdFunction = META_SELECTOBJECT;
851 if ((index = MF_AddHandleInternal(hPen)) == -1)
852 return FALSE;
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;
866 /******************************************************************
867 * MF_CreateFontIndirect
869 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
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;
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;
884 mr->rdSize = sizeof(METARECORD) / 2;
885 mr->rdFunction = META_SELECTOBJECT;
886 if ((index = MF_AddHandleInternal(hFont)) == -1)
887 return FALSE;
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;
901 /******************************************************************
902 * MF_TextOut
904 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
906 BOOL rc;
907 DWORD len;
908 HANDLE hmr;
909 METARECORD *mr;
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);
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;
929 /******************************************************************
930 * MF_MetaPoly - implements Polygon and Polyline
932 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
934 BOOL rc;
935 DWORD len;
936 HANDLE hmr;
937 METARECORD *mr;
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);
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;
955 /******************************************************************
956 * MF_BitBlt
958 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
959 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
961 fprintf(stdnimp,"MF_BitBlt: not implemented yet\n");
962 return FALSE;
966 /******************************************************************
967 * MF_StretchBlt
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)
973 fprintf(stdnimp,"MF_StretchBlt: not implemented yet\n");
974 return FALSE;