Release 960114
[wine.git] / objects / metafile.c
blobab0b7dfb858038ada13003d5cf4b524aa8407afa
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 <fcntl.h>
11 #include "gdi.h"
12 #include "bitmap.h"
13 #include "metafile.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)
28 HMETAFILE hmf;
29 METAFILE *mf;
30 METAHEADER *mh;
32 dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
34 if (!lpFilename)
35 return 0;
37 hmf = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE));
38 mf = (METAFILE *)GlobalLock(hmf);
39 if (!mf) {
40 GlobalFree(hmf);
41 return 0;
44 mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, MFHEADERSIZE);
45 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
46 if (!mh) {
47 GlobalFree(mf->hMetaHdr);
48 GlobalFree(hmf);
49 return 0;
51 strcpy(mf->Filename, lpFilename);
52 mf->wMagic = METAFILE_MAGIC;
53 if ((mf->hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) {
54 GlobalFree(mf->hMetaHdr);
55 GlobalFree(hmf);
56 return 0;
58 if (_lread(mf->hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
59 GlobalFree(mf->hMetaHdr);
60 GlobalFree(hmf);
61 return 0;
63 _lclose(mf->hFile);
65 if (mh->mtType != 1) {
66 GlobalFree(mf->hMetaHdr);
67 GlobalFree(hmf);
68 return 0;
71 GlobalUnlock(mf->hMetaHdr);
72 GlobalUnlock(hmf);
73 return hmf;
77 /******************************************************************
78 * CreateMetafile GDI.125
80 HANDLE CreateMetaFile(LPSTR lpFilename)
82 DC *dc;
83 HANDLE handle;
84 METAFILE *mf;
85 METAHEADER *mh;
86 HANDLETABLE *ht;
88 dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
90 handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
91 if (!handle) return 0;
92 dc = (DC *)GDI_HEAP_LIN_ADDR(handle);
94 if (!(dc->w.hMetaFile = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE)))) {
95 GDI_FreeObject(handle);
96 return 0;
98 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
99 if (!(mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAHEADER))))
101 GDI_FreeObject(handle);
102 GlobalFree(dc->w.hMetaFile);
103 return 0;
105 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
107 mf->wMagic = METAFILE_MAGIC;
108 mh->mtHeaderSize = MFHEADERSIZE / 2;
109 mh->mtVersion = MFVERSION;
110 mh->mtSize = MFHEADERSIZE / 2;
111 mh->mtNoObjects = 0;
112 mh->mtMaxRecord = 0;
113 mh->mtNoParameters = 0;
115 if (lpFilename) /* disk based metafile */
117 mh->mtType = 1;
118 strcpy(mf->Filename, lpFilename);
119 #ifndef WINELIB
120 mf->hFile = _lcreat(lpFilename, 0);
121 #else
122 /* temporary fix until _lcreate works under WINELIB */
123 mf->hFile = creat(lpFilename, 0666);
124 #endif
125 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
127 GlobalFree(mf->hMetaHdr);
128 GlobalFree(dc->w.hMetaFile);
129 return 0;
132 else /* memory based metafile */
133 mh->mtType = 0;
135 /* create the handle table */
136 HTLen = HTINCR;
137 hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
138 sizeof(HANDLETABLE) * HTLen);
139 ht = (HANDLETABLE *)GlobalLock(hHT);
141 GlobalUnlock(mf->hMetaHdr);
142 GlobalUnlock(dc->w.hMetaFile);
143 return handle;
147 /******************************************************************
148 * CloseMetafile GDI.126
150 HMETAFILE CloseMetaFile(HDC hdc)
152 DC *dc;
153 METAFILE *mf;
154 METAHEADER *mh;
155 HMETAFILE hmf;
156 /* METARECORD *mr = (METARECORD *)&buffer;*/
158 dprintf_metafile(stddeb,"CloseMetaFile\n");
160 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
161 if (!dc) return 0;
162 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
163 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
165 /* Construct the end of metafile record - this is documented
166 * in SDK Knowledgebase Q99334.
168 if (!MF_MetaParam0(dc, META_EOF))
170 GlobalFree(mf->hMetaHdr);
171 GlobalFree(dc->w.hMetaFile);
172 return 0;
175 if (mh->mtType == 1) /* disk based metafile */
177 if (_llseek(mf->hFile, 0L, 0) == -1)
179 GlobalFree(mf->hMetaHdr);
180 GlobalFree(dc->w.hMetaFile);
181 return 0;
183 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
185 GlobalFree(mf->hMetaHdr);
186 GlobalFree(dc->w.hMetaFile);
187 return 0;
189 _lclose(mf->hFile);
192 /* delete the handle table */
193 GlobalFree(hHT);
195 GlobalUnlock(mf->hMetaHdr);
196 hmf = dc->w.hMetaFile;
197 GlobalUnlock(hmf);
198 GDI_FreeObject(hdc);
199 return hmf;
203 /******************************************************************
204 * DeleteMetafile GDI.127
206 BOOL DeleteMetaFile(HMETAFILE hmf)
208 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
210 if (!mf || mf->wMagic != METAFILE_MAGIC)
211 return FALSE;
213 GlobalFree(mf->hMetaHdr);
214 GlobalFree(hmf);
215 return TRUE;
219 /******************************************************************
220 * PlayMetafile GDI.123
222 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
224 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
225 METAHEADER *mh;
226 METARECORD *mr;
227 HANDLETABLE *ht;
228 char *buffer = (char *)NULL;
230 if (mf->wMagic != METAFILE_MAGIC)
231 return FALSE;
233 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
234 if (mh->mtType == 1) /* disk based metafile */
236 mf->hFile = _lopen(mf->Filename, OF_READ);
237 mf->hBuffer = GlobalAlloc(GMEM_MOVEABLE, mh->mtMaxRecord * 2);
238 buffer = (char *)GlobalLock(mf->hBuffer);
239 _llseek(mf->hFile, mh->mtHeaderSize * 2, 0);
240 mf->MetaOffset = mh->mtHeaderSize * 2;
242 else if (mh->mtType == 0) /* memory based metafile */
243 mf->MetaOffset = mh->mtHeaderSize * 2;
244 else /* not a valid metafile type */
245 return FALSE;
247 /* create the handle table */
248 hHT = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,
249 sizeof(HANDLETABLE) * mh->mtNoObjects);
250 ht = (HANDLETABLE *)GlobalLock(hHT);
252 /* loop through metafile playing records */
253 while (mf->MetaOffset < mh->mtSize * 2)
255 if (mh->mtType == 1) /* disk based metafile */
257 _lread(mf->hFile, buffer, sizeof(METARECORD));
258 mr = (METARECORD *)buffer;
259 _lread(mf->hFile, (char *)(mr->rdParam + 1), (mr->rdSize * 2) -
260 sizeof(METARECORD));
261 mf->MetaOffset += mr->rdSize * 2;
263 else /* memory based metafile */
265 mr = (METARECORD *)((char *)mh + mf->MetaOffset);
266 mf->MetaOffset += mr->rdSize * 2;
268 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
271 /* close disk based metafile and free buffer */
272 if (mh->mtType == 1)
274 GlobalFree(mf->hBuffer);
275 _lclose(mf->hFile);
278 /* free handle table */
279 GlobalFree(hHT);
281 return TRUE;
285 /******************************************************************
286 * PlayMetaFileRecord GDI.176
288 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
289 WORD nHandles)
291 short s1;
292 HANDLE hndl;
293 char *ptr;
294 BITMAPINFOHEADER *infohdr;
296 switch (mr->rdFunction)
298 case META_EOF:
299 break;
301 case META_DELETEOBJECT:
302 DeleteObject(*(ht->objectHandle + *(mr->rdParam)));
303 break;
305 case META_SETBKCOLOR:
306 SetBkColor(hdc, *(mr->rdParam));
307 break;
309 case META_SETBKMODE:
310 SetBkMode(hdc, *(mr->rdParam));
311 break;
313 case META_SETMAPMODE:
314 SetMapMode(hdc, *(mr->rdParam));
315 break;
317 case META_SETROP2:
318 SetROP2(hdc, *(mr->rdParam));
319 break;
321 case META_SETRELABS:
322 SetRelAbs(hdc, *(mr->rdParam));
323 break;
325 case META_SETPOLYFILLMODE:
326 SetPolyFillMode(hdc, *(mr->rdParam));
327 break;
329 case META_SETSTRETCHBLTMODE:
330 SetStretchBltMode(hdc, *(mr->rdParam));
331 break;
333 case META_SETTEXTCOLOR:
334 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
335 break;
337 case META_SETWINDOWORG:
338 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
339 break;
341 case META_SETWINDOWEXT:
342 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
343 break;
345 case META_SETVIEWPORTORG:
346 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
347 break;
349 case META_SETVIEWPORTEXT:
350 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
351 break;
353 case META_OFFSETWINDOWORG:
354 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
355 break;
357 case META_SCALEWINDOWEXT:
358 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
359 *(mr->rdParam + 1), *(mr->rdParam));
360 break;
362 case META_OFFSETVIEWPORTORG:
363 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
364 break;
366 case META_SCALEVIEWPORTEXT:
367 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
368 *(mr->rdParam + 1), *(mr->rdParam));
369 break;
371 case META_LINETO:
372 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
373 break;
375 case META_MOVETO:
376 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
377 break;
379 case META_EXCLUDECLIPRECT:
380 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
381 *(mr->rdParam + 1), *(mr->rdParam));
382 break;
384 case META_INTERSECTCLIPRECT:
385 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
386 *(mr->rdParam + 1), *(mr->rdParam));
387 break;
389 case META_ARC:
390 Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
391 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
392 *(mr->rdParam + 1), *(mr->rdParam));
393 break;
395 case META_ELLIPSE:
396 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
397 *(mr->rdParam + 1), *(mr->rdParam));
398 break;
400 case META_FLOODFILL:
401 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
402 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
403 break;
405 case META_PIE:
406 Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
407 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
408 *(mr->rdParam + 1), *(mr->rdParam));
409 break;
411 case META_RECTANGLE:
412 Rectangle(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
413 *(mr->rdParam + 1), *(mr->rdParam));
414 break;
416 case META_ROUNDRECT:
417 RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
418 *(mr->rdParam + 3), *(mr->rdParam + 2),
419 *(mr->rdParam + 1), *(mr->rdParam));
420 break;
422 case META_PATBLT:
423 PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
424 *(mr->rdParam + 3), *(mr->rdParam + 2),
425 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
426 break;
428 case META_SAVEDC:
429 SaveDC(hdc);
430 break;
432 case META_SETPIXEL:
433 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
434 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
435 break;
437 case META_OFFSETCLIPRGN:
438 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
439 break;
441 case META_TEXTOUT:
442 s1 = *(mr->rdParam);
443 TextOut(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
444 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
445 (char *)(mr->rdParam + 1), s1);
446 break;
448 case META_POLYGON:
449 Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
450 break;
452 case META_POLYPOLYGON:
453 PolyPolygon(hdc, (LPPOINT)(mr->rdParam + *(mr->rdParam) + 1),
454 (LPINT)(mr->rdParam + 1), *(mr->rdParam));
455 break;
457 case META_POLYLINE:
458 Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
459 break;
461 case META_RESTOREDC:
462 RestoreDC(hdc, *(mr->rdParam));
463 break;
465 case META_SELECTOBJECT:
466 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
467 break;
469 case META_CHORD:
470 Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
471 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
472 *(mr->rdParam + 1), *(mr->rdParam));
473 break;
475 case META_CREATEPATTERNBRUSH:
476 switch (*(mr->rdParam))
478 case BS_PATTERN:
479 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
480 MF_AddHandle(ht, nHandles,
481 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
482 infohdr->biHeight,
483 infohdr->biPlanes,
484 infohdr->biBitCount,
485 (LPSTR)(mr->rdParam +
486 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
487 break;
489 case BS_DIBPATTERN:
490 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
491 hndl = GlobalAlloc(GMEM_MOVEABLE, s1);
492 ptr = GlobalLock(hndl);
493 memcpy(ptr, mr->rdParam + 2, s1);
494 GlobalUnlock(hndl);
495 MF_AddHandle(ht, nHandles,
496 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
497 GlobalFree(hndl);
499 break;
501 case META_CREATEPENINDIRECT:
502 MF_AddHandle(ht, nHandles,
503 CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
504 break;
506 case META_CREATEFONTINDIRECT:
507 MF_AddHandle(ht, nHandles,
508 CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
509 break;
511 case META_CREATEBRUSHINDIRECT:
512 MF_AddHandle(ht, nHandles,
513 CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
514 break;
516 /* W. Magro: Some new metafile operations. Not all debugged. */
517 case META_CREATEPALETTE:
518 MF_AddHandle(ht, nHandles,
519 CreatePalette((LPLOGPALETTE)mr->rdParam));
520 break;
522 case META_SETTEXTALIGN:
523 fprintf(stderr,"PlayMetaFileRecord: SETTEXTALIGN: %hd\n",mr->rdParam[0]);
524 SetTextAlign(hdc, *(mr->rdParam));
525 break;
527 case META_SELECTPALETTE:
528 SelectPalette(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
529 break;
531 case META_SETMAPPERFLAGS:
532 SetMapperFlags(hdc, *(mr->rdParam));
533 break;
535 case META_REALIZEPALETTE:
536 RealizePalette(hdc);
537 break;
539 case META_ESCAPE:
540 dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
541 break;
543 case META_EXTTEXTOUT: /* FIXME: don't know the exact parameters here */
545 short x,y,options,x5,x6,x7,x8;
546 y=mr->rdParam[0]; /* X position */
547 x=mr->rdParam[1]; /* Y position */
548 s1=mr->rdParam[2]; /* String length */
549 options=mr->rdParam[3];
550 x5=mr->rdParam[(s1+1)/2+4]; /* unknown meaning */
551 x6=mr->rdParam[(s1+1)/2+5]; /* unknown meaning */
552 x7=mr->rdParam[(s1+1)/2+6]; /* unknown meaning */
553 x8=mr->rdParam[(s1+1)/2+7]; /* unknown meaning */
554 ExtTextOut(hdc, x, y, options, (LPRECT) &mr->rdParam[(s1+1)/2+4], (char *)(mr->rdParam + 4), s1, NULL);
555 /* fprintf(stderr,"EXTTEXTOUT (len: %d) %hd : %hd %hd %hd %hd [%s].\n",
556 (mr->rdSize-s1),options,x5,x6,x7,x8,(char*) &(mr->rdParam[4]) );*/
558 break;
559 /* End new metafile operations. */
561 default:
562 fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
563 mr->rdFunction);
567 /******************************************************************
568 * GetMetaFileBits by William Magro, 19 Sep 1995
570 * Trade in a meta file object handle for a handle to the meta file memory
572 HANDLE GetMetaFileBits(HMETAFILE hmf)
575 /* save away the meta file bits handle */
576 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
577 HANDLE hMem = mf->hMetaHdr;
578 METAHEADER *mh = (METAHEADER *)GlobalLock(hMem);
580 dprintf_metafile(stddeb,"GetMetaFileBits: hmf in: "NPFMT"\n", hmf);
582 /* can't get bits of disk based metafile */
583 /* FIXME: should the disk file be loaded in this case? */
584 if(mh->mtType == 1) {
585 fprintf(stderr,
586 "GetMetaFileBits: application requested bits of disk meta file.\n");
587 GlobalUnlock(hMem);
588 GlobalUnlock(hmf);
589 return FALSE;
592 /* unlock the memory and invalidate the metafile handle */
593 GlobalUnlock(hMem);
594 GlobalFree(hmf);
596 dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: "NPFMT"\n", hMem);
598 return hMem;
601 /******************************************************************
602 * SetMetaFileBits by William Magro, 19 Sep 1995
604 * Trade in a meta file memory handle for a handle to a meta file object
606 HMETAFILE SetMetaFileBits(HANDLE hMem)
608 HMETAFILE hmf;
609 METAFILE *mf;
610 METAHEADER *mh = (METAHEADER *)GlobalLock(hMem);
612 dprintf_metafile(stddeb,"SetMetaFileBits: hMem in: "NPFMT"\n", hMem);
614 if (!mh) return FALSE;
616 /* now it is a memory meta file */
617 mh->mtType = 0;
619 hmf = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE));
620 mf = (METAFILE *)GlobalLock(hmf);
621 if (!mf) {
622 GlobalUnlock(hMem);
623 GlobalFree(hmf);
624 return FALSE;
627 /* use the supplied memory handle */
628 mf->hMetaHdr = hMem;
629 mf->wMagic = METAFILE_MAGIC;
630 mf->MetaOffset = mh->mtHeaderSize * 2;
631 mf->hFile = (int) (mf->hBuffer = (HANDLE) NULL);
633 GlobalUnlock(hMem);
634 GlobalUnlock(hmf);
636 dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: "NPFMT"\n", hmf);
638 return hmf;
641 /******************************************************************
642 * MF_WriteRecord
644 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
646 DWORD len;
647 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
648 METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
650 if (mh->mtType == 0) /* memory based metafile */
652 len = mh->mtSize * 2 + rlen;
653 GlobalUnlock(mf->hMetaHdr);
654 mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE);
655 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
656 memcpy(mh + mh->mtSize * 2, mr, rlen);
658 else if (mh->mtType == 1) /* disk based metafile */
660 if (_lwrite(mf->hFile, (char *)mr, rlen) == -1)
662 GlobalUnlock(mf->hMetaHdr);
663 return FALSE;
666 else
668 GlobalUnlock(mf->hMetaHdr);
669 return FALSE;
672 mh->mtSize += rlen / 2;
673 mh->mtMaxRecord = MAX(mh->mtMaxRecord, rlen / 2);
674 GlobalUnlock(mf->hMetaHdr);
675 return TRUE;
679 /******************************************************************
680 * MF_AddHandle
682 * Add a handle to an external handle table and return the index
684 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
686 int i;
688 for (i = 0; i < htlen; i++)
690 if (*(ht->objectHandle + i) == 0)
692 *(ht->objectHandle + i) = hobj;
693 return i;
696 return -1;
700 /******************************************************************
701 * MF_AddHandleInternal
703 * Add a handle to the internal handle table and return the index
705 int MF_AddHandleInternal(HANDLE hobj)
707 int i;
708 HANDLETABLE *ht = (HANDLETABLE *)GlobalLock(hHT);
710 for (i = 0; i < HTLen; i++)
712 if (*(ht->objectHandle + i) == 0)
714 *(ht->objectHandle + i) = hobj;
715 GlobalUnlock(hHT);
716 return i;
719 GlobalUnlock(hHT);
720 if (!(hHT = GlobalReAlloc(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
721 return -1;
722 HTLen += HTINCR;
723 ht = (HANDLETABLE *)GlobalLock(hHT);
724 *(ht->objectHandle + i) = hobj;
725 GlobalUnlock(hHT);
726 return i;
730 /******************************************************************
731 * MF_MetaParam0
733 BOOL MF_MetaParam0(DC *dc, short func)
735 char buffer[8];
736 METARECORD *mr = (METARECORD *)&buffer;
738 mr->rdSize = 3;
739 mr->rdFunction = func;
740 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
744 /******************************************************************
745 * MF_MetaParam1
747 BOOL MF_MetaParam1(DC *dc, short func, short param1)
749 char buffer[8];
750 METARECORD *mr = (METARECORD *)&buffer;
752 mr->rdSize = 4;
753 mr->rdFunction = func;
754 *(mr->rdParam) = param1;
755 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
759 /******************************************************************
760 * MF_MetaParam2
762 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
764 char buffer[10];
765 METARECORD *mr = (METARECORD *)&buffer;
767 mr->rdSize = 5;
768 mr->rdFunction = func;
769 *(mr->rdParam) = param2;
770 *(mr->rdParam + 1) = param1;
771 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
775 /******************************************************************
776 * MF_MetaParam4
778 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
779 short param3, short param4)
781 char buffer[14];
782 METARECORD *mr = (METARECORD *)&buffer;
784 mr->rdSize = 7;
785 mr->rdFunction = func;
786 *(mr->rdParam) = param4;
787 *(mr->rdParam + 1) = param3;
788 *(mr->rdParam + 2) = param2;
789 *(mr->rdParam + 3) = param1;
790 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
794 /******************************************************************
795 * MF_MetaParam6
797 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
798 short param3, short param4, short param5, short param6)
800 char buffer[18];
801 METARECORD *mr = (METARECORD *)&buffer;
803 mr->rdSize = 9;
804 mr->rdFunction = func;
805 *(mr->rdParam) = param6;
806 *(mr->rdParam + 1) = param5;
807 *(mr->rdParam + 2) = param4;
808 *(mr->rdParam + 3) = param3;
809 *(mr->rdParam + 4) = param2;
810 *(mr->rdParam + 5) = param1;
811 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
815 /******************************************************************
816 * MF_MetaParam8
818 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
819 short param3, short param4, short param5,
820 short param6, short param7, short param8)
822 char buffer[22];
823 METARECORD *mr = (METARECORD *)&buffer;
825 mr->rdSize = 11;
826 mr->rdFunction = func;
827 *(mr->rdParam) = param8;
828 *(mr->rdParam + 1) = param7;
829 *(mr->rdParam + 2) = param6;
830 *(mr->rdParam + 3) = param5;
831 *(mr->rdParam + 4) = param4;
832 *(mr->rdParam + 5) = param3;
833 *(mr->rdParam + 6) = param2;
834 *(mr->rdParam + 7) = param1;
835 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
839 /******************************************************************
840 * MF_CreateBrushIndirect
842 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
844 int index;
845 BOOL rc;
846 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
847 METARECORD *mr = (METARECORD *)&buffer;
848 METAFILE *mf;
849 METAHEADER *mh;
851 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
852 mr->rdFunction = META_CREATEBRUSHINDIRECT;
853 memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
854 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
855 return FALSE;
857 mr->rdSize = sizeof(METARECORD) / 2;
858 mr->rdFunction = META_SELECTOBJECT;
859 if ((index = MF_AddHandleInternal(hBrush)) == -1)
860 return FALSE;
862 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
863 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
864 *(mr->rdParam) = index;
865 if (index >= mh->mtNoObjects)
866 mh->mtNoObjects++;
867 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
868 GlobalUnlock(mf->hMetaHdr);
869 GlobalUnlock(dc->w.hMetaFile);
870 return rc;
874 /******************************************************************
875 * MF_CreatePatternBrush
877 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
879 DWORD len, bmSize, biSize;
880 HANDLE hmr;
881 METARECORD *mr;
882 BITMAPOBJ *bmp;
883 BITMAPINFO *info;
884 BITMAPINFOHEADER *infohdr;
885 int index;
886 BOOL rc;
887 char buffer[sizeof(METARECORD)];
888 METAFILE *mf;
889 METAHEADER *mh;
891 switch (logbrush->lbStyle)
893 case BS_PATTERN:
894 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HANDLE)logbrush->lbHatch, BITMAP_MAGIC);
895 if (!bmp) return FALSE;
896 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
897 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
898 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
899 return FALSE;
900 mr = (METARECORD *)GlobalLock(hmr);
901 memset(mr, 0, len);
902 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
903 mr->rdSize = len / 2;
904 *(mr->rdParam) = logbrush->lbStyle;
905 *(mr->rdParam + 1) = DIB_RGB_COLORS;
906 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
907 infohdr->biSize = sizeof(BITMAPINFOHEADER);
908 infohdr->biWidth = bmp->bitmap.bmWidth;
909 infohdr->biHeight = bmp->bitmap.bmHeight;
910 infohdr->biPlanes = bmp->bitmap.bmPlanes;
911 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
912 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
913 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
914 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
915 break;
917 case BS_DIBPATTERN:
918 info = (BITMAPINFO *)GlobalLock((HANDLE)logbrush->lbHatch);
919 bmSize = info->bmiHeader.biSizeImage;
920 if (!bmSize)
921 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
922 + 31) / 32 * 8 * info->bmiHeader.biHeight;
923 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
924 len = sizeof(METARECORD) + biSize + bmSize + 2;
925 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
926 return FALSE;
927 mr = (METARECORD *)GlobalLock(hmr);
928 memset(mr, 0, len);
929 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
930 mr->rdSize = len / 2;
931 *(mr->rdParam) = logbrush->lbStyle;
932 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
933 memcpy(mr->rdParam + 2, info, biSize + bmSize);
934 break;
935 default:
936 return FALSE;
938 if (!MF_WriteRecord(dc->w.hMetaFile, mr, len))
940 GlobalFree(hmr);
941 return FALSE;
944 GlobalFree(hmr);
945 mr = (METARECORD *)&buffer;
946 mr->rdSize = sizeof(METARECORD) / 2;
947 mr->rdFunction = META_SELECTOBJECT;
948 if ((index = MF_AddHandleInternal(hBrush)) == -1)
949 return FALSE;
951 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
952 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
953 *(mr->rdParam) = index;
954 if (index >= mh->mtNoObjects)
955 mh->mtNoObjects++;
956 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
957 GlobalUnlock(mf->hMetaHdr);
958 GlobalUnlock(dc->w.hMetaFile);
959 return rc;
963 /******************************************************************
964 * MF_CreatePenIndirect
966 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
968 int index;
969 BOOL rc;
970 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
971 METARECORD *mr = (METARECORD *)&buffer;
972 METAFILE *mf;
973 METAHEADER *mh;
975 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
976 mr->rdFunction = META_CREATEPENINDIRECT;
977 memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
978 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
979 return FALSE;
981 mr->rdSize = sizeof(METARECORD) / 2;
982 mr->rdFunction = META_SELECTOBJECT;
983 if ((index = MF_AddHandleInternal(hPen)) == -1)
984 return FALSE;
986 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
987 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
988 *(mr->rdParam) = index;
989 if (index >= mh->mtNoObjects)
990 mh->mtNoObjects++;
991 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
992 GlobalUnlock(mf->hMetaHdr);
993 GlobalUnlock(dc->w.hMetaFile);
994 return rc;
998 /******************************************************************
999 * MF_CreateFontIndirect
1001 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
1003 int index;
1004 BOOL rc;
1005 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
1006 METARECORD *mr = (METARECORD *)&buffer;
1007 METAFILE *mf;
1008 METAHEADER *mh;
1010 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
1011 mr->rdFunction = META_CREATEFONTINDIRECT;
1012 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
1013 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
1014 return FALSE;
1016 mr->rdSize = sizeof(METARECORD) / 2;
1017 mr->rdFunction = META_SELECTOBJECT;
1018 if ((index = MF_AddHandleInternal(hFont)) == -1)
1019 return FALSE;
1021 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
1022 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
1023 *(mr->rdParam) = index;
1024 if (index >= mh->mtNoObjects)
1025 mh->mtNoObjects++;
1026 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1027 GlobalUnlock(mf->hMetaHdr);
1028 GlobalUnlock(dc->w.hMetaFile);
1029 return rc;
1033 /******************************************************************
1034 * MF_TextOut
1036 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
1038 BOOL rc;
1039 DWORD len;
1040 HANDLE hmr;
1041 METARECORD *mr;
1043 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1044 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
1045 return FALSE;
1046 mr = (METARECORD *)GlobalLock(hmr);
1047 memset(mr, 0, len);
1049 mr->rdSize = len / 2;
1050 mr->rdFunction = META_TEXTOUT;
1051 *(mr->rdParam) = count;
1052 memcpy(mr->rdParam + 1, str, count);
1053 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1054 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1055 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1056 GlobalFree(hmr);
1057 return rc;
1061 /******************************************************************
1062 * MF_MetaPoly - implements Polygon and Polyline
1064 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
1066 BOOL rc;
1067 DWORD len;
1068 HANDLE hmr;
1069 METARECORD *mr;
1071 len = sizeof(METARECORD) + (count * 4);
1072 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
1073 return FALSE;
1074 mr = (METARECORD *)GlobalLock(hmr);
1075 memset(mr, 0, len);
1077 mr->rdSize = len / 2;
1078 mr->rdFunction = func;
1079 *(mr->rdParam) = count;
1080 memcpy(mr->rdParam + 1, pt, count * 4);
1081 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1082 GlobalFree(hmr);
1083 return rc;
1087 /******************************************************************
1088 * MF_BitBlt
1090 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1091 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
1093 fprintf(stdnimp,"MF_BitBlt: not implemented yet\n");
1094 return FALSE;
1098 /******************************************************************
1099 * MF_StretchBlt
1101 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1102 short heightDest, HDC hdcSrc, short xSrc, short ySrc,
1103 short widthSrc, short heightSrc, DWORD rop)
1105 fprintf(stdnimp,"MF_StretchBlt: not implemented yet\n");
1106 return FALSE;