Release 940804
[wine/gsoc-2012-control.git] / objects / metafile.c
blob544e6e48272e4d173bbeba06dc1d1d70d9a0c92d
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 */
7 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
9 #include "windows.h"
10 #include "gdi.h"
11 #include "metafile.h"
12 #include "prototypes.h"
14 #define DEBUG_METAFILE
16 #define HTINCR 10 /* handle table allocation size increment */
18 static HANDLE hHT; /* handle of the handle table */
19 static int HTLen; /* allocated length of handle table */
21 /******************************************************************
22 * CreateMetafile GDI.125
24 HANDLE CreateMetaFile(LPSTR lpFilename)
26 DC *dc;
27 HANDLE handle;
28 METAFILE *mf;
29 METAHEADER *mh;
30 HANDLETABLE *ht;
32 #ifdef DEBUG_METAFILE
33 printf("CreateMetaFile: %s\n", lpFilename);
34 #endif
36 handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
37 if (!handle) return 0;
38 dc = (DC *)GDI_HEAP_ADDR(handle);
40 if (!(dc->w.hMetaFile = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE))))
41 return 0;
42 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
43 if (!(mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAHEADER))))
45 GlobalFree(dc->w.hMetaFile);
46 return 0;
48 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
50 mf->wMagic = METAFILE_MAGIC;
51 mh->mtHeaderSize = MFHEADERSIZE / 2;
52 mh->mtVersion = MFVERSION;
53 mh->mtSize = MFHEADERSIZE / 2;
54 mh->mtNoObjects = 0;
55 mh->mtMaxRecord = 0;
56 mh->mtNoParameters = 0;
58 if (lpFilename) /* disk based metafile */
60 mh->mtType = 1;
61 strcpy(mf->Filename, lpFilename);
62 mf->hFile = _lcreat(lpFilename, 0);
63 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
65 GlobalFree(mf->hMetaHdr);
66 GlobalFree(dc->w.hMetaFile);
67 return 0;
70 else /* memory based metafile */
71 mh->mtType = 0;
73 /* create the handle table */
74 HTLen = HTINCR;
75 hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
76 sizeof(HANDLETABLE) * HTLen);
77 ht = (HANDLETABLE *)GlobalLock(hHT);
79 GlobalUnlock(mf->hMetaHdr);
80 GlobalUnlock(dc->w.hMetaFile);
81 return handle;
85 /******************************************************************
86 * CloseMetafile GDI.126
88 HMETAFILE CloseMetaFile(HDC hdc)
90 DC *dc;
91 METAFILE *mf;
92 METAHEADER *mh;
93 HMETAFILE hmf;
94 char buffer[15];
95 METARECORD *mr = (METARECORD *)&buffer;
97 #ifdef DEBUG_METAFILE
98 printf("CloseMetaFile\n");
99 #endif
101 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
102 if (!dc) return 0;
103 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
104 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
106 /* Construct the end of metafile record - this is undocumented
107 * but is created by MS Windows 3.1.
109 if (!MF_MetaParam0(dc, META_EOF))
111 GlobalFree(mf->hMetaHdr);
112 GlobalFree(dc->w.hMetaFile);
113 return 0;
116 if (mh->mtType == 1) /* disk based metafile */
118 if (_llseek(mf->hFile, 0L, 0) == -1)
120 GlobalFree(mf->hMetaHdr);
121 GlobalFree(dc->w.hMetaFile);
122 return 0;
124 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
126 GlobalFree(mf->hMetaHdr);
127 GlobalFree(dc->w.hMetaFile);
128 return 0;
130 _lclose(mf->hFile);
133 /* delete the handle table */
134 GlobalFree(hHT);
136 GlobalUnlock(mf->hMetaHdr);
137 hmf = dc->w.hMetaFile;
138 GlobalUnlock(hmf);
139 GDI_FreeObject(hdc);
140 return hmf;
144 /******************************************************************
145 * DeleteMetafile GDI.127
147 BOOL DeleteMetaFile(HMETAFILE hmf)
149 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
151 if (mf->wMagic != METAFILE_MAGIC)
152 return FALSE;
154 GlobalFree(mf->hMetaHdr);
155 GlobalFree(hmf);
156 return TRUE;
160 /******************************************************************
161 * PlayMetafile GDI.123
163 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
165 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
166 METAHEADER *mh;
167 METARECORD *mr;
168 HANDLETABLE *ht;
169 char *buffer;
171 if (mf->wMagic != METAFILE_MAGIC)
172 return FALSE;
174 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
175 if (mh->mtType == 1) /* disk based metafile */
177 mf->hFile = _lopen(mf->Filename, OF_READ);
178 mf->hBuffer = GlobalAlloc(GMEM_MOVEABLE, mh->mtMaxRecord * 2);
179 buffer = (char *)GlobalLock(mf->hBuffer);
180 _llseek(mf->hFile, mh->mtHeaderSize * 2, 0);
181 mf->MetaOffset = mh->mtHeaderSize * 2;
183 else if (mh->mtType == 0) /* memory based metafile */
184 mf->MetaOffset = mh->mtHeaderSize * 2;
185 else /* not a valid metafile type */
186 return FALSE;
188 /* create the handle table */
189 hHT = GlobalAlloc(GMEM_MOVEABLE, sizeof(HANDLETABLE) * mh->mtNoObjects);
190 ht = (HANDLETABLE *)GlobalLock(hHT);
192 /* loop through metafile playing records */
193 while (mf->MetaOffset < mh->mtSize * 2)
195 if (mh->mtType == 1) /* disk based metafile */
197 _lread(mf->hFile, buffer, sizeof(METARECORD));
198 mr = (METARECORD *)&buffer;
199 _lread(mf->hFile, (char *)(mr->rdParam + 1), (mr->rdSize * 2) -
200 sizeof(METARECORD));
201 mf->MetaOffset += mr->rdSize * 2;
203 else /* memory based metafile */
205 mr = (METARECORD *)((char *)mh + mf->MetaOffset);
206 mf->MetaOffset += mr->rdSize * 2;
208 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
211 /* close disk based metafile and free buffer */
212 if (mh->mtType == 1)
214 GlobalFree(mf->hBuffer);
215 _lclose(mf->hFile);
218 /* free handle table */
219 GlobalFree(hHT);
221 return TRUE;
225 /******************************************************************
226 * PlayMetaFileRecord GDI.176
228 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
229 WORD nHandles)
231 short s1;
232 HANDLE hndl;
233 char *ptr;
234 BITMAPINFOHEADER *infohdr;
236 switch (mr->rdFunction)
238 case META_SETBKCOLOR:
239 SetBkColor(hdc, *(mr->rdParam));
240 break;
242 case META_SETBKMODE:
243 SetBkMode(hdc, *(mr->rdParam));
244 break;
246 case META_SETMAPMODE:
247 SetMapMode(hdc, *(mr->rdParam));
248 break;
250 case META_SETROP2:
251 SetROP2(hdc, *(mr->rdParam));
252 break;
254 case META_SETRELABS:
255 SetRelAbs(hdc, *(mr->rdParam));
256 break;
258 case META_SETPOLYFILLMODE:
259 SetPolyFillMode(hdc, *(mr->rdParam));
260 break;
262 case META_SETSTRETCHBLTMODE:
263 SetStretchBltMode(hdc, *(mr->rdParam));
264 break;
266 case META_SETTEXTCOLOR:
267 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
268 break;
270 case META_SETWINDOWORG:
271 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
272 break;
274 case META_SETWINDOWEXT:
275 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
276 break;
278 case META_SETVIEWPORTORG:
279 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
280 break;
282 case META_SETVIEWPORTEXT:
283 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
284 break;
286 case META_OFFSETWINDOWORG:
287 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
288 break;
290 case META_SCALEWINDOWEXT:
291 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
292 *(mr->rdParam + 1), *(mr->rdParam));
293 break;
295 case META_OFFSETVIEWPORTORG:
296 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
297 break;
299 case META_SCALEVIEWPORTEXT:
300 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
301 *(mr->rdParam + 1), *(mr->rdParam));
302 break;
304 case META_LINETO:
305 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
306 break;
308 case META_MOVETO:
309 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
310 break;
312 case META_EXCLUDECLIPRECT:
313 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
314 *(mr->rdParam + 1), *(mr->rdParam));
315 break;
317 case META_INTERSECTCLIPRECT:
318 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
319 *(mr->rdParam + 1), *(mr->rdParam));
320 break;
322 case META_ARC:
323 Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
324 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
325 *(mr->rdParam + 1), *(mr->rdParam));
326 break;
328 case META_ELLIPSE:
329 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
330 *(mr->rdParam + 1), *(mr->rdParam));
331 break;
333 case META_FLOODFILL:
334 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
335 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
336 break;
338 case META_PIE:
339 Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
340 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
341 *(mr->rdParam + 1), *(mr->rdParam));
342 break;
344 case META_RECTANGLE:
345 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
346 *(mr->rdParam + 1), *(mr->rdParam));
347 break;
349 case META_ROUNDRECT:
350 RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
351 *(mr->rdParam + 3), *(mr->rdParam + 2),
352 *(mr->rdParam + 1), *(mr->rdParam));
353 break;
355 case META_PATBLT:
356 PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
357 *(mr->rdParam + 3), *(mr->rdParam + 2),
358 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
359 break;
361 case META_SAVEDC:
362 SaveDC(hdc);
363 break;
365 case META_SETPIXEL:
366 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
367 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
368 break;
370 case META_OFFSETCLIPRGN:
371 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
372 break;
374 case META_TEXTOUT:
375 s1 = *(mr->rdParam);
376 TextOut(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
377 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
378 (char *)(mr->rdParam + 1), s1);
379 break;
381 case META_POLYGON:
382 Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
383 break;
385 case META_POLYLINE:
386 Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
387 break;
389 case META_RESTOREDC:
390 RestoreDC(hdc, *(mr->rdParam));
391 break;
393 case META_SELECTOBJECT:
394 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
395 break;
397 case META_CHORD:
398 Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
399 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
400 *(mr->rdParam + 1), *(mr->rdParam));
401 break;
403 case META_CREATEPATTERNBRUSH:
404 switch (*(mr->rdParam))
406 case BS_PATTERN:
407 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
408 MF_AddHandle(ht, nHandles,
409 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
410 infohdr->biHeight,
411 infohdr->biPlanes,
412 infohdr->biBitCount,
413 (LPSTR)(mr->rdParam +
414 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
415 break;
417 case BS_DIBPATTERN:
418 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
419 hndl = GlobalAlloc(GMEM_MOVEABLE, s1);
420 ptr = GlobalLock(hndl);
421 memcpy(ptr, mr->rdParam + 2, s1);
422 GlobalUnlock(hndl);
423 MF_AddHandle(ht, nHandles,
424 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
425 GlobalFree(hndl);
427 break;
429 case META_CREATEPENINDIRECT:
430 MF_AddHandle(ht, nHandles,
431 CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
432 break;
434 case META_CREATEFONTINDIRECT:
435 MF_AddHandle(ht, nHandles,
436 CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
437 break;
439 case META_CREATEBRUSHINDIRECT:
440 MF_AddHandle(ht, nHandles,
441 CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
442 break;
444 default:
445 printf("PlayMetaFileRecord: Unknown record type %x\n",
446 mr->rdFunction);
451 /******************************************************************
452 * MF_WriteRecord
454 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
456 DWORD len;
457 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
458 METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
460 if (mh->mtType == 0) /* memory based metafile */
462 len = mh->mtSize * 2 + rlen;
463 GlobalUnlock(mf->hMetaHdr);
464 mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE);
465 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
466 memcpy(mh + mh->mtSize * 2, mr, rlen);
468 else if (mh->mtType == 1) /* disk based metafile */
470 if (_lwrite(mf->hFile, (char *)mr, rlen) == -1)
472 GlobalUnlock(mf->hMetaHdr);
473 return FALSE;
476 else
478 GlobalUnlock(mf->hMetaHdr);
479 return FALSE;
482 mh->mtSize += rlen / 2;
483 mh->mtMaxRecord = max(mh->mtMaxRecord, rlen / 2);
484 GlobalUnlock(mf->hMetaHdr);
485 return TRUE;
489 /******************************************************************
490 * MF_AddHandle
492 * Add a handle to an external handle table and return the index
494 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
496 int i;
498 for (i = 0; i < htlen; i++)
500 if (*(ht->objectHandle + i) == 0)
502 *(ht->objectHandle + i) = hobj;
503 return i;
506 return -1;
510 /******************************************************************
511 * MF_AddHandleInternal
513 * Add a handle to the internal handle table and return the index
515 int MF_AddHandleInternal(HANDLE hobj)
517 int i;
518 HANDLETABLE *ht = (HANDLETABLE *)GlobalLock(hHT);
520 for (i = 0; i < HTLen; i++)
522 if (*(ht->objectHandle + i) == 0)
524 *(ht->objectHandle + i) = hobj;
525 GlobalUnlock(hHT);
526 return i;
529 GlobalUnlock(hHT);
530 if (!(hHT = GlobalReAlloc(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
531 return -1;
532 HTLen += HTINCR;
533 ht = (HANDLETABLE *)GlobalLock(hHT);
534 *(ht->objectHandle + i) = hobj;
535 GlobalUnlock(hHT);
536 return i;
540 /******************************************************************
541 * MF_MetaParam0
543 BOOL MF_MetaParam0(DC *dc, short func)
545 char buffer[8];
546 METARECORD *mr = (METARECORD *)&buffer;
548 mr->rdSize = 3;
549 mr->rdFunction = func;
550 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
554 /******************************************************************
555 * MF_MetaParam1
557 BOOL MF_MetaParam1(DC *dc, short func, short param1)
559 char buffer[8];
560 METARECORD *mr = (METARECORD *)&buffer;
562 mr->rdSize = 4;
563 mr->rdFunction = func;
564 *(mr->rdParam) = param1;
565 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
569 /******************************************************************
570 * MF_MetaParam2
572 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
574 char buffer[10];
575 METARECORD *mr = (METARECORD *)&buffer;
577 mr->rdSize = 5;
578 mr->rdFunction = func;
579 *(mr->rdParam) = param2;
580 *(mr->rdParam + 1) = param1;
581 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
585 /******************************************************************
586 * MF_MetaParam4
588 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
589 short param3, short param4)
591 char buffer[14];
592 METARECORD *mr = (METARECORD *)&buffer;
594 mr->rdSize = 7;
595 mr->rdFunction = func;
596 *(mr->rdParam) = param4;
597 *(mr->rdParam + 1) = param3;
598 *(mr->rdParam + 2) = param2;
599 *(mr->rdParam + 3) = param1;
600 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
604 /******************************************************************
605 * MF_MetaParam6
607 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
608 short param3, short param4, short param5, short param6)
610 char buffer[18];
611 METARECORD *mr = (METARECORD *)&buffer;
613 mr->rdSize = 9;
614 mr->rdFunction = func;
615 *(mr->rdParam) = param6;
616 *(mr->rdParam + 1) = param5;
617 *(mr->rdParam + 2) = param4;
618 *(mr->rdParam + 3) = param3;
619 *(mr->rdParam + 4) = param2;
620 *(mr->rdParam + 5) = param1;
621 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
625 /******************************************************************
626 * MF_MetaParam8
628 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
629 short param3, short param4, short param5,
630 short param6, short param7, short param8)
632 char buffer[22];
633 METARECORD *mr = (METARECORD *)&buffer;
635 mr->rdSize = 11;
636 mr->rdFunction = func;
637 *(mr->rdParam) = param8;
638 *(mr->rdParam + 1) = param7;
639 *(mr->rdParam + 2) = param6;
640 *(mr->rdParam + 3) = param5;
641 *(mr->rdParam + 4) = param4;
642 *(mr->rdParam + 5) = param3;
643 *(mr->rdParam + 6) = param2;
644 *(mr->rdParam + 7) = param1;
645 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
649 /******************************************************************
650 * MF_CreateBrushIndirect
652 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
654 int index;
655 BOOL rc;
656 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
657 METARECORD *mr = (METARECORD *)&buffer;
658 METAFILE *mf;
659 METAHEADER *mh;
661 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
662 mr->rdFunction = META_CREATEBRUSHINDIRECT;
663 memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
664 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
665 return FALSE;
667 mr->rdSize = sizeof(METARECORD) / 2;
668 mr->rdFunction = META_SELECTOBJECT;
669 if ((index = MF_AddHandleInternal(hBrush)) == -1)
670 return FALSE;
672 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
673 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
674 *(mr->rdParam) = index;
675 if (index >= mh->mtNoObjects)
676 mh->mtNoObjects++;
677 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
678 GlobalUnlock(mf->hMetaHdr);
679 GlobalUnlock(dc->w.hMetaFile);
680 return rc;
684 /******************************************************************
685 * MF_CreatePatternBrush
687 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
689 DWORD len, bmSize, biSize;
690 HANDLE hmr;
691 METARECORD *mr;
692 BITMAPOBJ *bmp;
693 BITMAPINFO *info;
694 BITMAPINFOHEADER *infohdr;
695 int index;
696 BOOL rc;
697 char buffer[sizeof(METARECORD)];
698 METAFILE *mf;
699 METAHEADER *mh;
701 switch (logbrush->lbStyle)
703 case BS_PATTERN:
704 bmp = (BITMAPOBJ *)GDI_GetObjPtr(logbrush->lbHatch, BITMAP_MAGIC);
705 if (!bmp) return FALSE;
706 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
707 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
708 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
709 return FALSE;
710 mr = (METARECORD *)GlobalLock(hmr);
711 memset(mr, 0, len);
712 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
713 mr->rdSize = len / 2;
714 *(mr->rdParam) = logbrush->lbStyle;
715 *(mr->rdParam + 1) = DIB_RGB_COLORS;
716 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
717 infohdr->biSize = sizeof(BITMAPINFOHEADER);
718 infohdr->biWidth = bmp->bitmap.bmWidth;
719 infohdr->biHeight = bmp->bitmap.bmHeight;
720 infohdr->biPlanes = bmp->bitmap.bmPlanes;
721 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
722 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
723 bmp->bitmap.bmBits,
724 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
725 break;
727 case BS_DIBPATTERN:
728 info = (BITMAPINFO *)GlobalLock(logbrush->lbHatch);
729 bmSize = info->bmiHeader.biSizeImage;
730 if (!bmSize)
731 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
732 + 31) / 32 * 8 * info->bmiHeader.biHeight;
733 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
734 len = sizeof(METARECORD) + biSize + bmSize + 2;
735 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
736 return FALSE;
737 mr = (METARECORD *)GlobalLock(hmr);
738 memset(mr, 0, len);
739 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
740 mr->rdSize = len / 2;
741 *(mr->rdParam) = logbrush->lbStyle;
742 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
743 memcpy(mr->rdParam + 2, info, biSize + bmSize);
744 break;
746 if (!MF_WriteRecord(dc->w.hMetaFile, mr, len))
748 GlobalFree(hmr);
749 return FALSE;
752 GlobalFree(hmr);
753 mr = (METARECORD *)&buffer;
754 mr->rdSize = sizeof(METARECORD) / 2;
755 mr->rdFunction = META_SELECTOBJECT;
756 if ((index = MF_AddHandleInternal(hBrush)) == -1)
757 return FALSE;
759 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
760 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
761 *(mr->rdParam) = index;
762 if (index >= mh->mtNoObjects)
763 mh->mtNoObjects++;
764 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
765 GlobalUnlock(mf->hMetaHdr);
766 GlobalUnlock(dc->w.hMetaFile);
767 return rc;
771 /******************************************************************
772 * MF_CreatePenIndirect
774 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
776 int index;
777 BOOL rc;
778 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
779 METARECORD *mr = (METARECORD *)&buffer;
780 METAFILE *mf;
781 METAHEADER *mh;
783 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
784 mr->rdFunction = META_CREATEPENINDIRECT;
785 memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
786 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
787 return FALSE;
789 mr->rdSize = sizeof(METARECORD) / 2;
790 mr->rdFunction = META_SELECTOBJECT;
791 if ((index = MF_AddHandleInternal(hPen)) == -1)
792 return FALSE;
794 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
795 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
796 *(mr->rdParam) = index;
797 if (index >= mh->mtNoObjects)
798 mh->mtNoObjects++;
799 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
800 GlobalUnlock(mf->hMetaHdr);
801 GlobalUnlock(dc->w.hMetaFile);
802 return rc;
806 /******************************************************************
807 * MF_CreateFontIndirect
809 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
811 int index;
812 BOOL rc;
813 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
814 METARECORD *mr = (METARECORD *)&buffer;
815 METAFILE *mf;
816 METAHEADER *mh;
818 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
819 mr->rdFunction = META_CREATEFONTINDIRECT;
820 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
821 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
822 return FALSE;
824 mr->rdSize = sizeof(METARECORD) / 2;
825 mr->rdFunction = META_SELECTOBJECT;
826 if ((index = MF_AddHandleInternal(hFont)) == -1)
827 return FALSE;
829 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
830 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
831 *(mr->rdParam) = index;
832 if (index >= mh->mtNoObjects)
833 mh->mtNoObjects++;
834 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
835 GlobalUnlock(mf->hMetaHdr);
836 GlobalUnlock(dc->w.hMetaFile);
837 return rc;
841 /******************************************************************
842 * MF_TextOut
844 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
846 BOOL rc;
847 DWORD len;
848 HANDLE hmr;
849 METARECORD *mr;
851 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
852 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
853 return FALSE;
854 mr = (METARECORD *)GlobalLock(hmr);
855 memset(mr, 0, len);
857 mr->rdSize = len / 2;
858 mr->rdFunction = META_TEXTOUT;
859 *(mr->rdParam) = count;
860 memcpy(mr->rdParam + 1, str, count);
861 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
862 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
863 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
864 GlobalFree(hmr);
865 return rc;
869 /******************************************************************
870 * MF_MetaPoly - implements Polygon and Polyline
872 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
874 BOOL rc;
875 DWORD len;
876 HANDLE hmr;
877 METARECORD *mr;
879 len = sizeof(METARECORD) + (count * 4);
880 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
881 return FALSE;
882 mr = (METARECORD *)GlobalLock(hmr);
883 memset(mr, 0, len);
885 mr->rdSize = len / 2;
886 mr->rdFunction = func;
887 *(mr->rdParam) = count;
888 memcpy(mr->rdParam + 1, pt, count * 4);
889 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
890 GlobalFree(hmr);
891 return rc;
895 /******************************************************************
896 * MF_BitBlt
898 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
899 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
901 printf("MF_BitBlt: not implemented yet\n");
905 /******************************************************************
906 * MF_StretchBlt
908 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
909 short heightDest, HDC hdcSrc, short xSrc, short ySrc,
910 short widthSrc, short heightSrc, DWORD rop)
912 printf("MF_StretchBlt: not implemented yet\n");