Release 941030
[wine/hacks.git] / objects / metafile.c
blob8715bf72e06e74dd4e4c0b4c7c1b1b18d308f45f
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 */
7 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
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 /* #undef DEBUG_METAFILE /* */
17 #include "debug.h"
19 #define HTINCR 10 /* handle table allocation size increment */
21 static HANDLE hHT; /* handle of the handle table */
22 static int HTLen; /* allocated length of handle table */
24 /******************************************************************
25 * CreateMetafile GDI.125
27 HANDLE CreateMetaFile(LPSTR lpFilename)
29 DC *dc;
30 HANDLE handle;
31 METAFILE *mf;
32 METAHEADER *mh;
33 HANDLETABLE *ht;
35 dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
37 handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
38 if (!handle) return 0;
39 dc = (DC *)GDI_HEAP_ADDR(handle);
41 if (!(dc->w.hMetaFile = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE))))
42 return 0;
43 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
44 if (!(mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAHEADER))))
46 GlobalFree(dc->w.hMetaFile);
47 return 0;
49 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
51 mf->wMagic = METAFILE_MAGIC;
52 mh->mtHeaderSize = MFHEADERSIZE / 2;
53 mh->mtVersion = MFVERSION;
54 mh->mtSize = MFHEADERSIZE / 2;
55 mh->mtNoObjects = 0;
56 mh->mtMaxRecord = 0;
57 mh->mtNoParameters = 0;
59 if (lpFilename) /* disk based metafile */
61 mh->mtType = 1;
62 strcpy(mf->Filename, lpFilename);
63 mf->hFile = _lcreat(lpFilename, 0);
64 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
66 GlobalFree(mf->hMetaHdr);
67 GlobalFree(dc->w.hMetaFile);
68 return 0;
71 else /* memory based metafile */
72 mh->mtType = 0;
74 /* create the handle table */
75 HTLen = HTINCR;
76 hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
77 sizeof(HANDLETABLE) * HTLen);
78 ht = (HANDLETABLE *)GlobalLock(hHT);
80 GlobalUnlock(mf->hMetaHdr);
81 GlobalUnlock(dc->w.hMetaFile);
82 return handle;
86 /******************************************************************
87 * CloseMetafile GDI.126
89 HMETAFILE CloseMetaFile(HDC hdc)
91 DC *dc;
92 METAFILE *mf;
93 METAHEADER *mh;
94 HMETAFILE hmf;
95 char buffer[15];
96 METARECORD *mr = (METARECORD *)&buffer;
98 dprintf_metafile(stddeb,"CloseMetaFile\n");
100 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
101 if (!dc) return 0;
102 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
103 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
105 /* Construct the end of metafile record - this is documented
106 * in SDK Knowledgebase Q99334.
108 if (!MF_MetaParam0(dc, META_EOF))
110 GlobalFree(mf->hMetaHdr);
111 GlobalFree(dc->w.hMetaFile);
112 return 0;
115 if (mh->mtType == 1) /* disk based metafile */
117 if (_llseek(mf->hFile, 0L, 0) == -1)
119 GlobalFree(mf->hMetaHdr);
120 GlobalFree(dc->w.hMetaFile);
121 return 0;
123 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
125 GlobalFree(mf->hMetaHdr);
126 GlobalFree(dc->w.hMetaFile);
127 return 0;
129 _lclose(mf->hFile);
132 /* delete the handle table */
133 GlobalFree(hHT);
135 GlobalUnlock(mf->hMetaHdr);
136 hmf = dc->w.hMetaFile;
137 GlobalUnlock(hmf);
138 GDI_FreeObject(hdc);
139 return hmf;
143 /******************************************************************
144 * DeleteMetafile GDI.127
146 BOOL DeleteMetaFile(HMETAFILE hmf)
148 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
150 if (mf->wMagic != METAFILE_MAGIC)
151 return FALSE;
153 GlobalFree(mf->hMetaHdr);
154 GlobalFree(hmf);
155 return TRUE;
159 /******************************************************************
160 * PlayMetafile GDI.123
162 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
164 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
165 METAHEADER *mh;
166 METARECORD *mr;
167 HANDLETABLE *ht;
168 char *buffer;
170 if (mf->wMagic != METAFILE_MAGIC)
171 return FALSE;
173 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
174 if (mh->mtType == 1) /* disk based metafile */
176 mf->hFile = _lopen(mf->Filename, OF_READ);
177 mf->hBuffer = GlobalAlloc(GMEM_MOVEABLE, mh->mtMaxRecord * 2);
178 buffer = (char *)GlobalLock(mf->hBuffer);
179 _llseek(mf->hFile, mh->mtHeaderSize * 2, 0);
180 mf->MetaOffset = mh->mtHeaderSize * 2;
182 else if (mh->mtType == 0) /* memory based metafile */
183 mf->MetaOffset = mh->mtHeaderSize * 2;
184 else /* not a valid metafile type */
185 return FALSE;
187 /* create the handle table */
188 hHT = GlobalAlloc(GMEM_MOVEABLE, sizeof(HANDLETABLE) * mh->mtNoObjects);
189 ht = (HANDLETABLE *)GlobalLock(hHT);
191 /* loop through metafile playing records */
192 while (mf->MetaOffset < mh->mtSize * 2)
194 if (mh->mtType == 1) /* disk based metafile */
196 _lread(mf->hFile, buffer, sizeof(METARECORD));
197 mr = (METARECORD *)&buffer;
198 _lread(mf->hFile, (char *)(mr->rdParam + 1), (mr->rdSize * 2) -
199 sizeof(METARECORD));
200 mf->MetaOffset += mr->rdSize * 2;
202 else /* memory based metafile */
204 mr = (METARECORD *)((char *)mh + mf->MetaOffset);
205 mf->MetaOffset += mr->rdSize * 2;
207 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
210 /* close disk based metafile and free buffer */
211 if (mh->mtType == 1)
213 GlobalFree(mf->hBuffer);
214 _lclose(mf->hFile);
217 /* free handle table */
218 GlobalFree(hHT);
220 return TRUE;
224 /******************************************************************
225 * PlayMetaFileRecord GDI.176
227 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
228 WORD nHandles)
230 short s1;
231 HANDLE hndl;
232 char *ptr;
233 BITMAPINFOHEADER *infohdr;
235 switch (mr->rdFunction)
237 case META_SETBKCOLOR:
238 SetBkColor(hdc, *(mr->rdParam));
239 break;
241 case META_SETBKMODE:
242 SetBkMode(hdc, *(mr->rdParam));
243 break;
245 case META_SETMAPMODE:
246 SetMapMode(hdc, *(mr->rdParam));
247 break;
249 case META_SETROP2:
250 SetROP2(hdc, *(mr->rdParam));
251 break;
253 case META_SETRELABS:
254 SetRelAbs(hdc, *(mr->rdParam));
255 break;
257 case META_SETPOLYFILLMODE:
258 SetPolyFillMode(hdc, *(mr->rdParam));
259 break;
261 case META_SETSTRETCHBLTMODE:
262 SetStretchBltMode(hdc, *(mr->rdParam));
263 break;
265 case META_SETTEXTCOLOR:
266 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
267 break;
269 case META_SETWINDOWORG:
270 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
271 break;
273 case META_SETWINDOWEXT:
274 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
275 break;
277 case META_SETVIEWPORTORG:
278 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
279 break;
281 case META_SETVIEWPORTEXT:
282 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
283 break;
285 case META_OFFSETWINDOWORG:
286 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
287 break;
289 case META_SCALEWINDOWEXT:
290 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
291 *(mr->rdParam + 1), *(mr->rdParam));
292 break;
294 case META_OFFSETVIEWPORTORG:
295 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
296 break;
298 case META_SCALEVIEWPORTEXT:
299 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
300 *(mr->rdParam + 1), *(mr->rdParam));
301 break;
303 case META_LINETO:
304 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
305 break;
307 case META_MOVETO:
308 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
309 break;
311 case META_EXCLUDECLIPRECT:
312 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
313 *(mr->rdParam + 1), *(mr->rdParam));
314 break;
316 case META_INTERSECTCLIPRECT:
317 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
318 *(mr->rdParam + 1), *(mr->rdParam));
319 break;
321 case META_ARC:
322 Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
323 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
324 *(mr->rdParam + 1), *(mr->rdParam));
325 break;
327 case META_ELLIPSE:
328 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
329 *(mr->rdParam + 1), *(mr->rdParam));
330 break;
332 case META_FLOODFILL:
333 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
334 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
335 break;
337 case META_PIE:
338 Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
339 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
340 *(mr->rdParam + 1), *(mr->rdParam));
341 break;
343 case META_RECTANGLE:
344 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
345 *(mr->rdParam + 1), *(mr->rdParam));
346 break;
348 case META_ROUNDRECT:
349 RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
350 *(mr->rdParam + 3), *(mr->rdParam + 2),
351 *(mr->rdParam + 1), *(mr->rdParam));
352 break;
354 case META_PATBLT:
355 PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
356 *(mr->rdParam + 3), *(mr->rdParam + 2),
357 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
358 break;
360 case META_SAVEDC:
361 SaveDC(hdc);
362 break;
364 case META_SETPIXEL:
365 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
366 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
367 break;
369 case META_OFFSETCLIPRGN:
370 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
371 break;
373 case META_TEXTOUT:
374 s1 = *(mr->rdParam);
375 TextOut(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
376 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
377 (char *)(mr->rdParam + 1), s1);
378 break;
380 case META_POLYGON:
381 Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
382 break;
384 case META_POLYLINE:
385 Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
386 break;
388 case META_RESTOREDC:
389 RestoreDC(hdc, *(mr->rdParam));
390 break;
392 case META_SELECTOBJECT:
393 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
394 break;
396 case META_CHORD:
397 Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
398 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
399 *(mr->rdParam + 1), *(mr->rdParam));
400 break;
402 case META_CREATEPATTERNBRUSH:
403 switch (*(mr->rdParam))
405 case BS_PATTERN:
406 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
407 MF_AddHandle(ht, nHandles,
408 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
409 infohdr->biHeight,
410 infohdr->biPlanes,
411 infohdr->biBitCount,
412 (LPSTR)(mr->rdParam +
413 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
414 break;
416 case BS_DIBPATTERN:
417 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
418 hndl = GlobalAlloc(GMEM_MOVEABLE, s1);
419 ptr = GlobalLock(hndl);
420 memcpy(ptr, mr->rdParam + 2, s1);
421 GlobalUnlock(hndl);
422 MF_AddHandle(ht, nHandles,
423 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
424 GlobalFree(hndl);
426 break;
428 case META_CREATEPENINDIRECT:
429 MF_AddHandle(ht, nHandles,
430 CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
431 break;
433 case META_CREATEFONTINDIRECT:
434 MF_AddHandle(ht, nHandles,
435 CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
436 break;
438 case META_CREATEBRUSHINDIRECT:
439 MF_AddHandle(ht, nHandles,
440 CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
441 break;
443 default:
444 fprintf(stderr,"PlayMetaFileRecord: Unknown record type %x\n",
445 mr->rdFunction);
450 /******************************************************************
451 * MF_WriteRecord
453 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
455 DWORD len;
456 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
457 METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
459 if (mh->mtType == 0) /* memory based metafile */
461 len = mh->mtSize * 2 + rlen;
462 GlobalUnlock(mf->hMetaHdr);
463 mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE);
464 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
465 memcpy(mh + mh->mtSize * 2, mr, rlen);
467 else if (mh->mtType == 1) /* disk based metafile */
469 if (_lwrite(mf->hFile, (char *)mr, rlen) == -1)
471 GlobalUnlock(mf->hMetaHdr);
472 return FALSE;
475 else
477 GlobalUnlock(mf->hMetaHdr);
478 return FALSE;
481 mh->mtSize += rlen / 2;
482 mh->mtMaxRecord = max(mh->mtMaxRecord, rlen / 2);
483 GlobalUnlock(mf->hMetaHdr);
484 return TRUE;
488 /******************************************************************
489 * MF_AddHandle
491 * Add a handle to an external handle table and return the index
493 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
495 int i;
497 for (i = 0; i < htlen; i++)
499 if (*(ht->objectHandle + i) == 0)
501 *(ht->objectHandle + i) = hobj;
502 return i;
505 return -1;
509 /******************************************************************
510 * MF_AddHandleInternal
512 * Add a handle to the internal handle table and return the index
514 int MF_AddHandleInternal(HANDLE hobj)
516 int i;
517 HANDLETABLE *ht = (HANDLETABLE *)GlobalLock(hHT);
519 for (i = 0; i < HTLen; i++)
521 if (*(ht->objectHandle + i) == 0)
523 *(ht->objectHandle + i) = hobj;
524 GlobalUnlock(hHT);
525 return i;
528 GlobalUnlock(hHT);
529 if (!(hHT = GlobalReAlloc(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
530 return -1;
531 HTLen += HTINCR;
532 ht = (HANDLETABLE *)GlobalLock(hHT);
533 *(ht->objectHandle + i) = hobj;
534 GlobalUnlock(hHT);
535 return i;
539 /******************************************************************
540 * MF_MetaParam0
542 BOOL MF_MetaParam0(DC *dc, short func)
544 char buffer[8];
545 METARECORD *mr = (METARECORD *)&buffer;
547 mr->rdSize = 3;
548 mr->rdFunction = func;
549 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
553 /******************************************************************
554 * MF_MetaParam1
556 BOOL MF_MetaParam1(DC *dc, short func, short param1)
558 char buffer[8];
559 METARECORD *mr = (METARECORD *)&buffer;
561 mr->rdSize = 4;
562 mr->rdFunction = func;
563 *(mr->rdParam) = param1;
564 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
568 /******************************************************************
569 * MF_MetaParam2
571 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
573 char buffer[10];
574 METARECORD *mr = (METARECORD *)&buffer;
576 mr->rdSize = 5;
577 mr->rdFunction = func;
578 *(mr->rdParam) = param2;
579 *(mr->rdParam + 1) = param1;
580 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
584 /******************************************************************
585 * MF_MetaParam4
587 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
588 short param3, short param4)
590 char buffer[14];
591 METARECORD *mr = (METARECORD *)&buffer;
593 mr->rdSize = 7;
594 mr->rdFunction = func;
595 *(mr->rdParam) = param4;
596 *(mr->rdParam + 1) = param3;
597 *(mr->rdParam + 2) = param2;
598 *(mr->rdParam + 3) = param1;
599 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
603 /******************************************************************
604 * MF_MetaParam6
606 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
607 short param3, short param4, short param5, short param6)
609 char buffer[18];
610 METARECORD *mr = (METARECORD *)&buffer;
612 mr->rdSize = 9;
613 mr->rdFunction = func;
614 *(mr->rdParam) = param6;
615 *(mr->rdParam + 1) = param5;
616 *(mr->rdParam + 2) = param4;
617 *(mr->rdParam + 3) = param3;
618 *(mr->rdParam + 4) = param2;
619 *(mr->rdParam + 5) = param1;
620 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
624 /******************************************************************
625 * MF_MetaParam8
627 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
628 short param3, short param4, short param5,
629 short param6, short param7, short param8)
631 char buffer[22];
632 METARECORD *mr = (METARECORD *)&buffer;
634 mr->rdSize = 11;
635 mr->rdFunction = func;
636 *(mr->rdParam) = param8;
637 *(mr->rdParam + 1) = param7;
638 *(mr->rdParam + 2) = param6;
639 *(mr->rdParam + 3) = param5;
640 *(mr->rdParam + 4) = param4;
641 *(mr->rdParam + 5) = param3;
642 *(mr->rdParam + 6) = param2;
643 *(mr->rdParam + 7) = param1;
644 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
648 /******************************************************************
649 * MF_CreateBrushIndirect
651 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
653 int index;
654 BOOL rc;
655 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
656 METARECORD *mr = (METARECORD *)&buffer;
657 METAFILE *mf;
658 METAHEADER *mh;
660 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
661 mr->rdFunction = META_CREATEBRUSHINDIRECT;
662 memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
663 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
664 return FALSE;
666 mr->rdSize = sizeof(METARECORD) / 2;
667 mr->rdFunction = META_SELECTOBJECT;
668 if ((index = MF_AddHandleInternal(hBrush)) == -1)
669 return FALSE;
671 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
672 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
673 *(mr->rdParam) = index;
674 if (index >= mh->mtNoObjects)
675 mh->mtNoObjects++;
676 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
677 GlobalUnlock(mf->hMetaHdr);
678 GlobalUnlock(dc->w.hMetaFile);
679 return rc;
683 /******************************************************************
684 * MF_CreatePatternBrush
686 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
688 DWORD len, bmSize, biSize;
689 HANDLE hmr;
690 METARECORD *mr;
691 BITMAPOBJ *bmp;
692 BITMAPINFO *info;
693 BITMAPINFOHEADER *infohdr;
694 int index;
695 BOOL rc;
696 char buffer[sizeof(METARECORD)];
697 METAFILE *mf;
698 METAHEADER *mh;
700 switch (logbrush->lbStyle)
702 case BS_PATTERN:
703 bmp = (BITMAPOBJ *)GDI_GetObjPtr(logbrush->lbHatch, BITMAP_MAGIC);
704 if (!bmp) return FALSE;
705 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
706 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
707 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
708 return FALSE;
709 mr = (METARECORD *)GlobalLock(hmr);
710 memset(mr, 0, len);
711 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
712 mr->rdSize = len / 2;
713 *(mr->rdParam) = logbrush->lbStyle;
714 *(mr->rdParam + 1) = DIB_RGB_COLORS;
715 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
716 infohdr->biSize = sizeof(BITMAPINFOHEADER);
717 infohdr->biWidth = bmp->bitmap.bmWidth;
718 infohdr->biHeight = bmp->bitmap.bmHeight;
719 infohdr->biPlanes = bmp->bitmap.bmPlanes;
720 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
721 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
722 bmp->bitmap.bmBits,
723 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
724 break;
726 case BS_DIBPATTERN:
727 info = (BITMAPINFO *)GlobalLock(logbrush->lbHatch);
728 bmSize = info->bmiHeader.biSizeImage;
729 if (!bmSize)
730 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
731 + 31) / 32 * 8 * info->bmiHeader.biHeight;
732 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
733 len = sizeof(METARECORD) + biSize + bmSize + 2;
734 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
735 return FALSE;
736 mr = (METARECORD *)GlobalLock(hmr);
737 memset(mr, 0, len);
738 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
739 mr->rdSize = len / 2;
740 *(mr->rdParam) = logbrush->lbStyle;
741 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
742 memcpy(mr->rdParam + 2, info, biSize + bmSize);
743 break;
745 if (!MF_WriteRecord(dc->w.hMetaFile, mr, len))
747 GlobalFree(hmr);
748 return FALSE;
751 GlobalFree(hmr);
752 mr = (METARECORD *)&buffer;
753 mr->rdSize = sizeof(METARECORD) / 2;
754 mr->rdFunction = META_SELECTOBJECT;
755 if ((index = MF_AddHandleInternal(hBrush)) == -1)
756 return FALSE;
758 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
759 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
760 *(mr->rdParam) = index;
761 if (index >= mh->mtNoObjects)
762 mh->mtNoObjects++;
763 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
764 GlobalUnlock(mf->hMetaHdr);
765 GlobalUnlock(dc->w.hMetaFile);
766 return rc;
770 /******************************************************************
771 * MF_CreatePenIndirect
773 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
775 int index;
776 BOOL rc;
777 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
778 METARECORD *mr = (METARECORD *)&buffer;
779 METAFILE *mf;
780 METAHEADER *mh;
782 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
783 mr->rdFunction = META_CREATEPENINDIRECT;
784 memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
785 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
786 return FALSE;
788 mr->rdSize = sizeof(METARECORD) / 2;
789 mr->rdFunction = META_SELECTOBJECT;
790 if ((index = MF_AddHandleInternal(hPen)) == -1)
791 return FALSE;
793 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
794 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
795 *(mr->rdParam) = index;
796 if (index >= mh->mtNoObjects)
797 mh->mtNoObjects++;
798 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
799 GlobalUnlock(mf->hMetaHdr);
800 GlobalUnlock(dc->w.hMetaFile);
801 return rc;
805 /******************************************************************
806 * MF_CreateFontIndirect
808 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
810 int index;
811 BOOL rc;
812 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
813 METARECORD *mr = (METARECORD *)&buffer;
814 METAFILE *mf;
815 METAHEADER *mh;
817 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
818 mr->rdFunction = META_CREATEFONTINDIRECT;
819 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
820 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
821 return FALSE;
823 mr->rdSize = sizeof(METARECORD) / 2;
824 mr->rdFunction = META_SELECTOBJECT;
825 if ((index = MF_AddHandleInternal(hFont)) == -1)
826 return FALSE;
828 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
829 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
830 *(mr->rdParam) = index;
831 if (index >= mh->mtNoObjects)
832 mh->mtNoObjects++;
833 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
834 GlobalUnlock(mf->hMetaHdr);
835 GlobalUnlock(dc->w.hMetaFile);
836 return rc;
840 /******************************************************************
841 * MF_TextOut
843 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
845 BOOL rc;
846 DWORD len;
847 HANDLE hmr;
848 METARECORD *mr;
850 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
851 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
852 return FALSE;
853 mr = (METARECORD *)GlobalLock(hmr);
854 memset(mr, 0, len);
856 mr->rdSize = len / 2;
857 mr->rdFunction = META_TEXTOUT;
858 *(mr->rdParam) = count;
859 memcpy(mr->rdParam + 1, str, count);
860 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
861 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
862 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
863 GlobalFree(hmr);
864 return rc;
868 /******************************************************************
869 * MF_MetaPoly - implements Polygon and Polyline
871 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
873 BOOL rc;
874 DWORD len;
875 HANDLE hmr;
876 METARECORD *mr;
878 len = sizeof(METARECORD) + (count * 4);
879 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
880 return FALSE;
881 mr = (METARECORD *)GlobalLock(hmr);
882 memset(mr, 0, len);
884 mr->rdSize = len / 2;
885 mr->rdFunction = func;
886 *(mr->rdParam) = count;
887 memcpy(mr->rdParam + 1, pt, count * 4);
888 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
889 GlobalFree(hmr);
890 return rc;
894 /******************************************************************
895 * MF_BitBlt
897 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
898 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
900 fprintf(stdnimp,"MF_BitBlt: not implemented yet\n");
904 /******************************************************************
905 * MF_StretchBlt
907 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
908 short heightDest, HDC hdcSrc, short xSrc, short ySrc,
909 short widthSrc, short heightSrc, DWORD rop)
911 fprintf(stdnimp,"MF_StretchBlt: not implemented yet\n");