Release 960506
[wine.git] / objects / metafile.c
blob6ca814ab4e2fb1549d1c6618b487b17fe8e1c50e
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, 1996
7 */
9 #include <string.h>
10 #include <fcntl.h>
11 #include "gdi.h"
12 #include "bitmap.h"
13 #include "file.h"
14 #include "metafile.h"
15 #include "stddebug.h"
16 #include "callback.h"
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 * GetMetafile GDI.124 By Kenny MacDonald 30 Nov 94
28 HMETAFILE GetMetaFile(LPSTR lpFilename)
30 HMETAFILE hmf;
31 METAHEADER *mh;
32 HFILE hFile;
33 DWORD size;
35 dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
37 if (!lpFilename)
38 return 0;
40 hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
41 mh = (METAHEADER *)GlobalLock16(hmf);
43 if (!mh) {
44 GlobalFree16(hmf);
45 return 0;
48 if ((hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) {
49 GlobalFree16(hmf);
50 return 0;
53 if (FILE_Read(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
54 GlobalFree16(hmf);
55 return 0;
58 size = mh->mtSize * 2; /* alloc memory for whole metafile */
59 GlobalUnlock16(hmf);
60 hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
61 mh = (METAHEADER *)GlobalLock16(hmf);
63 if (!mh) {
64 GlobalFree16(hmf);
65 return 0;
68 if (FILE_Read(hFile, (char*)mh + mh->mtHeaderSize * 2,
69 size - mh->mtHeaderSize * 2) == HFILE_ERROR) {
70 GlobalFree16(hmf);
71 return 0;
74 _lclose(hFile);
76 if (mh->mtType != 1) {
77 GlobalFree16(hmf);
78 return 0;
81 GlobalUnlock16(hmf);
82 return hmf;
86 /******************************************************************
87 * CreateMetafile GDI.125
90 HANDLE CreateMetaFile(LPCSTR lpFilename)
92 DC *dc;
93 HANDLE handle;
94 METAHEADER *mh;
95 int hFile;
97 dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
99 handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
101 if (!handle)
102 return 0;
104 dc = (DC *)GDI_HEAP_LIN_ADDR(handle);
106 if (!(dc->w.hMetaFile = GlobalAlloc16(GMEM_MOVEABLE, sizeof(METAHEADER)))) {
107 GDI_FreeObject(handle);
108 return 0;
111 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
113 mh->mtHeaderSize = MFHEADERSIZE / 2;
114 mh->mtVersion = MFVERSION;
115 mh->mtSize = MFHEADERSIZE / 2;
116 mh->mtNoObjects = 0;
117 mh->mtMaxRecord = 0;
118 mh->mtNoParameters = 0;
120 if (lpFilename) /* disk based metafile */
122 mh->mtType = 1; /* disk */
123 hFile = _lcreat(lpFilename, 0);
124 if (_lwrite(hFile, (char *)mh, MFHEADERSIZE) == -1)
126 GlobalFree16(dc->w.hMetaFile);
127 return 0;
129 mh->mtNoParameters = hFile; /* store file descriptor here */
130 /* windows probably uses this too*/
132 else /* memory based metafile */
133 mh->mtType = 0;
135 /* create the handle table */
136 HTLen = HTINCR;
137 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
138 sizeof(HANDLETABLE) * HTLen);
140 GlobalUnlock16(dc->w.hMetaFile);
141 dprintf_metafile(stddeb,"CreateMetaFile: returning %04x\n", handle);
142 return handle;
146 /******************************************************************
147 * CopyMetafile GDI.151 Niels de Carpentier, April 1996
150 HMETAFILE CopyMetaFile(HMETAFILE hSrcMetaFile, LPCSTR lpFilename)
152 HMETAFILE handle = 0;
153 METAHEADER *mh;
154 METAHEADER *mh2;
155 int hFile;
157 dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename);
159 mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
161 if (!mh)
162 return 0;
164 if (lpFilename) /* disk based metafile */
166 hFile = _lcreat(lpFilename, 0);
167 if (_lwrite(hFile, (char *)mh, mh->mtSize * 2) == -1)
169 _lclose(hFile);
170 return 0;
172 _lclose(hFile);
174 else /* memory based metafile */
176 handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
177 mh2 = (METAHEADER *)GlobalLock16(handle);
178 memcpy(mh2,mh, mh->mtSize * 2);
179 GlobalUnlock16(handle);
182 return handle;
186 /******************************************************************
187 * CloseMetafile GDI.126
190 HMETAFILE CloseMetaFile(HDC hdc)
192 DC *dc;
193 METAHEADER *mh;
194 HMETAFILE hmf;
195 HFILE hFile;
197 dprintf_metafile(stddeb,"CloseMetaFile\n");
199 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
201 if (!dc)
202 return 0;
204 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
206 /* Construct the end of metafile record - this is documented
207 * in SDK Knowledgebase Q99334.
210 if (!MF_MetaParam0(dc, META_EOF))
212 GlobalFree16(dc->w.hMetaFile);
213 return 0;
216 if (mh->mtType == 1) /* disk based metafile */
218 hFile = mh->mtNoParameters;
219 mh->mtNoParameters = 0;
220 if (_llseek(hFile, 0L, 0) == -1)
222 GlobalFree16(dc->w.hMetaFile);
223 return 0;
225 if (_lwrite(hFile, (char *)mh, MFHEADERSIZE) == -1)
227 GlobalFree16(dc->w.hMetaFile);
228 return 0;
230 _lclose(hFile);
233 /* delete the handle table */
234 GlobalFree16(hHT);
236 hmf = dc->w.hMetaFile;
237 GlobalUnlock16(hmf);
238 GDI_FreeObject(hdc);
239 return hmf;
243 /******************************************************************
244 * DeleteMetafile GDI.127
247 BOOL DeleteMetaFile(HMETAFILE hmf)
249 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
251 if (!mh)
252 return FALSE;
254 GlobalFree16(hmf);
255 return TRUE;
259 /******************************************************************
260 * PlayMetafile GDI.123
263 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
265 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
266 METARECORD *mr;
267 HANDLETABLE *ht;
268 int offset = 0;
269 WORD i;
271 dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf);
273 /* create the handle table */
274 hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
275 sizeof(HANDLETABLE) * mh->mtNoObjects);
276 ht = (HANDLETABLE *)GlobalLock16(hHT);
278 /* loop through metafile playing records */
279 offset = mh->mtHeaderSize * 2;
280 while (offset < mh->mtSize * 2)
282 mr = (METARECORD *)((char *)mh + offset);
283 dprintf_metafile(stddeb,"offset = %04x size = %08lx function = %04x\n",
284 offset,mr->rdSize,mr->rdFunction);
285 offset += mr->rdSize * 2;
286 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
289 /* free objects in handle table */
290 for(i = 0; i < mh->mtNoObjects; i++)
291 if(*(ht->objectHandle + i) != 0)
292 DeleteObject(*(ht->objectHandle + i));
294 /* free handle table */
295 GlobalFree16(hHT);
297 return TRUE;
301 /******************************************************************
302 * EnumMetafile GDI.175
303 * Niels de carpentier, april 1996
306 BOOL EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc,LPARAM lpData)
308 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
309 METARECORD *mr;
310 HANDLETABLE *ht;
311 int offset = 0;
313 dprintf_metafile(stddeb,"EnumMetaFile(%04x, %04x, %08lx, %08lx)\n",
314 hdc, hmf, (DWORD)lpEnumFunc, lpData);
316 /* create the handle table */
318 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
319 sizeof(HANDLETABLE) * mh->mtNoObjects);
320 ht = (HANDLETABLE *)GlobalLock16(hHT);
322 offset = mh->mtHeaderSize * 2;
324 /* loop through metafile records */
326 while (offset < (mh->mtSize * 2))
328 mr = (METARECORD *)((char *)mh + offset);
329 if (!CallEnumMetafileProc(lpEnumFunc, hdc, MAKE_SEGPTR(ht),
330 MAKE_SEGPTR(mr), mh->mtNoObjects,
331 (LONG)lpData))
332 break;
334 offset += (mr->rdSize * 2);
337 /* free handle table */
338 GlobalFree16(hHT);
340 return TRUE;
344 /******************************************************************
345 * PlayMetaFileRecord GDI.176
348 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
349 WORD nHandles)
351 short s1;
352 HANDLE hndl;
353 char *ptr;
354 BITMAPINFOHEADER *infohdr;
356 dprintf_metafile(stddeb,"PlayMetaFileRecord(%04x %08lx %08lx %04x)\n",
357 hdc,(LONG)ht, (LONG)mr, nHandles);
359 switch (mr->rdFunction)
361 case META_EOF:
362 break;
364 case META_DELETEOBJECT:
365 DeleteObject(*(ht->objectHandle + *(mr->rdParam)));
366 *(ht->objectHandle + *(mr->rdParam)) = 0;
367 break;
369 case META_SETBKCOLOR:
370 SetBkColor(hdc, *(mr->rdParam));
371 break;
373 case META_SETBKMODE:
374 SetBkMode(hdc, *(mr->rdParam));
375 break;
377 case META_SETMAPMODE:
378 SetMapMode(hdc, *(mr->rdParam));
379 break;
381 case META_SETROP2:
382 SetROP2(hdc, *(mr->rdParam));
383 break;
385 case META_SETRELABS:
386 SetRelAbs(hdc, *(mr->rdParam));
387 break;
389 case META_SETPOLYFILLMODE:
390 SetPolyFillMode(hdc, *(mr->rdParam));
391 break;
393 case META_SETSTRETCHBLTMODE:
394 SetStretchBltMode(hdc, *(mr->rdParam));
395 break;
397 case META_SETTEXTCOLOR:
398 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
399 break;
401 case META_SETWINDOWORG:
402 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
403 break;
405 case META_SETWINDOWEXT:
406 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
407 break;
409 case META_SETVIEWPORTORG:
410 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
411 break;
413 case META_SETVIEWPORTEXT:
414 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
415 break;
417 case META_OFFSETWINDOWORG:
418 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
419 break;
421 case META_SCALEWINDOWEXT:
422 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
423 *(mr->rdParam + 1), *(mr->rdParam));
424 break;
426 case META_OFFSETVIEWPORTORG:
427 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
428 break;
430 case META_SCALEVIEWPORTEXT:
431 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
432 *(mr->rdParam + 1), *(mr->rdParam));
433 break;
435 case META_LINETO:
436 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
437 break;
439 case META_MOVETO:
440 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
441 break;
443 case META_EXCLUDECLIPRECT:
444 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
445 *(mr->rdParam + 1), *(mr->rdParam));
446 break;
448 case META_INTERSECTCLIPRECT:
449 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
450 *(mr->rdParam + 1), *(mr->rdParam));
451 break;
453 case META_ARC:
454 Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
455 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
456 *(mr->rdParam + 1), *(mr->rdParam));
457 break;
459 case META_ELLIPSE:
460 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
461 *(mr->rdParam + 1), *(mr->rdParam));
462 break;
464 case META_FLOODFILL:
465 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
466 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
467 break;
469 case META_PIE:
470 Pie(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_RECTANGLE:
476 Rectangle(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
477 *(mr->rdParam + 1), *(mr->rdParam));
478 break;
480 case META_ROUNDRECT:
481 RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
482 *(mr->rdParam + 3), *(mr->rdParam + 2),
483 *(mr->rdParam + 1), *(mr->rdParam));
484 break;
486 case META_PATBLT:
487 PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
488 *(mr->rdParam + 3), *(mr->rdParam + 2),
489 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
490 break;
492 case META_SAVEDC:
493 SaveDC(hdc);
494 break;
496 case META_SETPIXEL:
497 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
498 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
499 break;
501 case META_OFFSETCLIPRGN:
502 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
503 break;
505 case META_TEXTOUT:
506 s1 = *(mr->rdParam);
507 TextOut(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
508 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
509 (char *)(mr->rdParam + 1), s1);
510 break;
512 case META_POLYGON:
513 Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
514 break;
516 case META_POLYPOLYGON:
517 PolyPolygon(hdc, (LPPOINT)(mr->rdParam + *(mr->rdParam) + 1),
518 (LPINT16)(mr->rdParam + 1), *(mr->rdParam));
519 break;
521 case META_POLYLINE:
522 Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
523 break;
525 case META_RESTOREDC:
526 RestoreDC(hdc, *(mr->rdParam));
527 break;
529 case META_SELECTOBJECT:
530 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
531 break;
533 case META_CHORD:
534 Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
535 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
536 *(mr->rdParam + 1), *(mr->rdParam));
537 break;
539 case META_CREATEPATTERNBRUSH:
540 switch (*(mr->rdParam))
542 case BS_PATTERN:
543 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
544 MF_AddHandle(ht, nHandles,
545 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
546 infohdr->biHeight,
547 infohdr->biPlanes,
548 infohdr->biBitCount,
549 (LPSTR)(mr->rdParam +
550 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
551 break;
553 case BS_DIBPATTERN:
554 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
555 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
556 ptr = GlobalLock16(hndl);
557 memcpy(ptr, mr->rdParam + 2, s1);
558 GlobalUnlock16(hndl);
559 MF_AddHandle(ht, nHandles,
560 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
561 GlobalFree16(hndl);
563 break;
565 case META_CREATEPENINDIRECT:
566 MF_AddHandle(ht, nHandles,
567 CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
568 break;
570 case META_CREATEFONTINDIRECT:
571 MF_AddHandle(ht, nHandles,
572 CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
573 break;
575 case META_CREATEBRUSHINDIRECT:
576 MF_AddHandle(ht, nHandles,
577 CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
578 break;
580 /* W. Magro: Some new metafile operations. Not all debugged. */
581 case META_CREATEPALETTE:
582 MF_AddHandle(ht, nHandles,
583 CreatePalette((LPLOGPALETTE)mr->rdParam));
584 break;
586 case META_SETTEXTALIGN:
587 SetTextAlign(hdc, *(mr->rdParam));
588 break;
590 case META_SELECTPALETTE:
591 SelectPalette(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
592 break;
594 case META_SETMAPPERFLAGS:
595 SetMapperFlags(hdc, *(mr->rdParam));
596 break;
598 case META_REALIZEPALETTE:
599 RealizePalette(hdc);
600 break;
602 case META_ESCAPE:
603 dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
604 break;
606 case META_EXTTEXTOUT: /* FIXME: don't know the exact parameters here */
608 short x,y,options,x5,x6,x7,x8;
609 y=mr->rdParam[0]; /* X position */
610 x=mr->rdParam[1]; /* Y position */
611 s1=mr->rdParam[2]; /* String length */
612 options=mr->rdParam[3];
613 x5=mr->rdParam[(s1+1)/2+4]; /* unknown meaning */
614 x6=mr->rdParam[(s1+1)/2+5]; /* unknown meaning */
615 x7=mr->rdParam[(s1+1)/2+6]; /* unknown meaning */
616 x8=mr->rdParam[(s1+1)/2+7]; /* unknown meaning */
617 ExtTextOut(hdc, x, y, options, (LPRECT) &mr->rdParam[(s1+1)/2+4], (char *)(mr->rdParam + 4), s1, NULL);
618 /* fprintf(stderr,"EXTTEXTOUT (len: %d) %hd : %hd %hd %hd %hd [%s].\n",
619 (mr->rdSize-s1),options,x5,x6,x7,x8,(char*) &(mr->rdParam[4]) );*/
621 break;
622 /* End new metafile operations. */
624 case META_STRETCHDIB:
626 LPSTR bits;
627 LPBITMAPINFO info;
628 int offset;
629 info = (LPBITMAPINFO) &(mr->rdParam[11]);
630 if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
632 if (info->bmiHeader.biClrUsed)
634 if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
635 offset = info->bmiHeader.biClrUsed * 4;
636 else
637 offset = (1 << info->bmiHeader.biBitCount) * 4;
639 else
640 offset = (1 << info->bmiHeader.biBitCount) * 4;
642 else if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
644 if (info->bmiHeader.biClrUsed)
646 if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
647 offset = info->bmiHeader.biClrUsed * 3;
648 else
649 offset = (1 << info->bmiHeader.biBitCount) * 3;
651 else
652 offset = (1 << info->bmiHeader.biBitCount) * 3;
654 else
656 fprintf(stderr,"Unknown size for BITMAPHEADER in PlayMetaRecord!\n");
657 break;
660 offset += info->bmiHeader.biSize;
661 bits = (LPSTR) info + offset;
662 StretchDIBits(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
663 mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
664 mr->rdParam[4],mr->rdParam[3],bits,info,
665 mr->rdParam[2],(DWORD)mr->rdParam[0]);
667 break;
669 default:
670 fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
671 mr->rdFunction);
675 /******************************************************************
676 * GetMetaFileBits by William Magro, 19 Sep 1995
678 * Trade in a meta file object handle for a handle to the meta file memory
681 HANDLE GetMetaFileBits(HMETAFILE hmf)
683 dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hmf);
685 return hmf;
688 /******************************************************************
689 * SetMetaFileBits by William Magro, 19 Sep 1995
691 * Trade in a meta file memory handle for a handle to a meta file object
694 HMETAFILE SetMetaFileBits(HANDLE hMem)
696 dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hMem);
698 return hMem;
701 /******************************************************************
702 * MF_WriteRecord
705 HMETAFILE MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
707 DWORD len;
708 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
710 if (mh->mtType == 0) /* memory based metafile */
712 len = mh->mtSize * 2 + rlen;
713 GlobalUnlock16(hmf);
714 hmf = GlobalReAlloc16(hmf, len, GMEM_MOVEABLE); /* hmf can change */
715 mh = (METAHEADER *)GlobalLock16(hmf);
716 memcpy((WORD *)mh + mh->mtSize, mr, rlen);
718 else if (mh->mtType == 1) /* disk based metafile */
720 dprintf_metafile(stddeb,"Writing record to disk\n");
721 if (_lwrite(mh->mtNoParameters, (char *)mr, rlen) == -1)
723 GlobalUnlock16(hmf);
724 return 0;
727 else
729 GlobalUnlock16(hmf);
730 return 0;
733 mh->mtSize += rlen / 2;
734 mh->mtMaxRecord = MAX(mh->mtMaxRecord, rlen / 2);
735 GlobalUnlock16(hmf);
736 return hmf;
740 /******************************************************************
741 * MF_AddHandle
743 * Add a handle to an external handle table and return the index
746 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
748 int i;
750 for (i = 0; i < htlen; i++)
752 if (*(ht->objectHandle + i) == 0)
754 *(ht->objectHandle + i) = hobj;
755 return i;
758 return -1;
762 /******************************************************************
763 * MF_AddHandleInternal
765 * Add a handle to the internal handle table and return the index
768 int MF_AddHandleInternal(HANDLE hobj)
770 int i;
771 HANDLETABLE *ht = (HANDLETABLE *)GlobalLock16(hHT);
773 for (i = 0; i < HTLen; i++)
775 if (*(ht->objectHandle + i) == 0)
777 *(ht->objectHandle + i) = hobj;
778 GlobalUnlock16(hHT);
779 return i;
782 GlobalUnlock16(hHT);
783 if (!(hHT = GlobalReAlloc16(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
784 return -1;
785 HTLen += HTINCR;
786 ht = (HANDLETABLE *)GlobalLock16(hHT);
787 *(ht->objectHandle + i) = hobj;
788 GlobalUnlock16(hHT);
789 return i;
793 /******************************************************************
794 * MF_MetaParam0
797 BOOL MF_MetaParam0(DC *dc, short func)
799 char buffer[8];
800 METARECORD *mr = (METARECORD *)&buffer;
801 HMETAFILE handle;
803 mr->rdSize = 3;
804 mr->rdFunction = func;
805 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
806 dc->w.hMetaFile = handle;
808 return handle;
812 /******************************************************************
813 * MF_MetaParam1
815 BOOL MF_MetaParam1(DC *dc, short func, short param1)
817 char buffer[8];
818 METARECORD *mr = (METARECORD *)&buffer;
819 HMETAFILE handle;
821 mr->rdSize = 4;
822 mr->rdFunction = func;
823 *(mr->rdParam) = param1;
824 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
825 dc->w.hMetaFile = handle;
827 return handle;
831 /******************************************************************
832 * MF_MetaParam2
834 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
836 char buffer[10];
837 METARECORD *mr = (METARECORD *)&buffer;
838 HMETAFILE handle;
840 mr->rdSize = 5;
841 mr->rdFunction = func;
842 *(mr->rdParam) = param2;
843 *(mr->rdParam + 1) = param1;
844 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
845 dc->w.hMetaFile = handle;
847 return handle;
851 /******************************************************************
852 * MF_MetaParam4
855 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
856 short param3, short param4)
858 char buffer[14];
859 METARECORD *mr = (METARECORD *)&buffer;
860 HMETAFILE handle;
862 mr->rdSize = 7;
863 mr->rdFunction = func;
864 *(mr->rdParam) = param4;
865 *(mr->rdParam + 1) = param3;
866 *(mr->rdParam + 2) = param2;
867 *(mr->rdParam + 3) = param1;
868 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
869 dc->w.hMetaFile = handle;
871 return handle;
875 /******************************************************************
876 * MF_MetaParam6
879 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
880 short param3, short param4, short param5, short param6)
882 char buffer[18];
883 METARECORD *mr = (METARECORD *)&buffer;
884 HMETAFILE handle;
886 mr->rdSize = 9;
887 mr->rdFunction = func;
888 *(mr->rdParam) = param6;
889 *(mr->rdParam + 1) = param5;
890 *(mr->rdParam + 2) = param4;
891 *(mr->rdParam + 3) = param3;
892 *(mr->rdParam + 4) = param2;
893 *(mr->rdParam + 5) = param1;
894 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
895 dc->w.hMetaFile = handle;
897 return handle;
901 /******************************************************************
902 * MF_MetaParam8
904 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
905 short param3, short param4, short param5,
906 short param6, short param7, short param8)
908 char buffer[22];
909 METARECORD *mr = (METARECORD *)&buffer;
910 HMETAFILE handle;
912 mr->rdSize = 11;
913 mr->rdFunction = func;
914 *(mr->rdParam) = param8;
915 *(mr->rdParam + 1) = param7;
916 *(mr->rdParam + 2) = param6;
917 *(mr->rdParam + 3) = param5;
918 *(mr->rdParam + 4) = param4;
919 *(mr->rdParam + 5) = param3;
920 *(mr->rdParam + 6) = param2;
921 *(mr->rdParam + 7) = param1;
922 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
923 dc->w.hMetaFile = handle;
925 return handle;
929 /******************************************************************
930 * MF_CreateBrushIndirect
933 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
935 int index;
936 HMETAFILE handle;
937 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
938 METARECORD *mr = (METARECORD *)&buffer;
939 METAHEADER *mh;
941 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
942 mr->rdFunction = META_CREATEBRUSHINDIRECT;
943 memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
944 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile,
945 mr, mr->rdSize * 2)))
946 return FALSE;
948 mr->rdSize = sizeof(METARECORD) / 2;
949 mr->rdFunction = META_SELECTOBJECT;
951 if ((index = MF_AddHandleInternal(hBrush)) == -1)
952 return FALSE;
954 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
955 *(mr->rdParam) = index;
956 if (index >= mh->mtNoObjects)
957 mh->mtNoObjects++;
959 GlobalUnlock16(dc->w.hMetaFile);
960 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
961 dc->w.hMetaFile = handle;
963 return handle;
967 /******************************************************************
968 * MF_CreatePatternBrush
971 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
973 DWORD len, bmSize, biSize;
974 HANDLE hmr;
975 METARECORD *mr;
976 BITMAPOBJ *bmp;
977 BITMAPINFO *info;
978 BITMAPINFOHEADER *infohdr;
979 int index;
980 HMETAFILE handle;
981 char buffer[sizeof(METARECORD)];
982 METAHEADER *mh;
984 switch (logbrush->lbStyle)
986 case BS_PATTERN:
987 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HANDLE)logbrush->lbHatch, BITMAP_MAGIC);
988 if (!bmp) return FALSE;
989 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
990 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
991 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
992 return FALSE;
993 mr = (METARECORD *)GlobalLock16(hmr);
994 memset(mr, 0, len);
995 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
996 mr->rdSize = len / 2;
997 *(mr->rdParam) = logbrush->lbStyle;
998 *(mr->rdParam + 1) = DIB_RGB_COLORS;
999 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
1000 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1001 infohdr->biWidth = bmp->bitmap.bmWidth;
1002 infohdr->biHeight = bmp->bitmap.bmHeight;
1003 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1004 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1005 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1006 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1007 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1008 break;
1010 case BS_DIBPATTERN:
1011 info = (BITMAPINFO *)GlobalLock16((HANDLE)logbrush->lbHatch);
1012 bmSize = info->bmiHeader.biSizeImage;
1013 if (!bmSize)
1014 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1015 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1016 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1017 len = sizeof(METARECORD) + biSize + bmSize + 2;
1018 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1019 return FALSE;
1020 mr = (METARECORD *)GlobalLock16(hmr);
1021 memset(mr, 0, len);
1022 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1023 mr->rdSize = len / 2;
1024 *(mr->rdParam) = logbrush->lbStyle;
1025 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
1026 memcpy(mr->rdParam + 2, info, biSize + bmSize);
1027 break;
1028 default:
1029 return FALSE;
1031 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, len)))
1033 GlobalFree16(hmr);
1034 return FALSE;
1037 GlobalFree16(hmr);
1039 mr = (METARECORD *)&buffer;
1040 mr->rdSize = sizeof(METARECORD) / 2;
1041 mr->rdFunction = META_SELECTOBJECT;
1042 if ((index = MF_AddHandleInternal(hBrush)) == -1)
1043 return FALSE;
1045 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1046 *(mr->rdParam) = index;
1047 if (index >= mh->mtNoObjects)
1048 mh->mtNoObjects++;
1049 GlobalUnlock16(dc->w.hMetaFile);
1050 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1051 dc->w.hMetaFile = handle;
1053 return handle;
1057 /******************************************************************
1058 * MF_CreatePenIndirect
1061 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
1063 int index;
1064 HMETAFILE handle;
1065 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
1066 METARECORD *mr = (METARECORD *)&buffer;
1067 METAHEADER *mh;
1069 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
1070 mr->rdFunction = META_CREATEPENINDIRECT;
1071 memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
1072 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr,
1073 mr->rdSize * 2)))
1074 return FALSE;
1076 mr->rdSize = sizeof(METARECORD) / 2;
1077 mr->rdFunction = META_SELECTOBJECT;
1079 if ((index = MF_AddHandleInternal(hPen)) == -1)
1080 return FALSE;
1082 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1083 *(mr->rdParam) = index;
1084 if (index >= mh->mtNoObjects)
1085 mh->mtNoObjects++;
1086 GlobalUnlock16(dc->w.hMetaFile);
1087 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1088 dc->w.hMetaFile = handle;
1090 return handle;
1094 /******************************************************************
1095 * MF_CreateFontIndirect
1098 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
1100 int index;
1101 HMETAFILE handle;
1102 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
1103 METARECORD *mr = (METARECORD *)&buffer;
1104 METAHEADER *mh;
1106 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
1107 mr->rdFunction = META_CREATEFONTINDIRECT;
1108 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
1109 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr,
1110 mr->rdSize * 2)))
1111 return FALSE;
1113 mr->rdSize = sizeof(METARECORD) / 2;
1114 mr->rdFunction = META_SELECTOBJECT;
1116 if ((index = MF_AddHandleInternal(hFont)) == -1)
1117 return FALSE;
1119 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1120 *(mr->rdParam) = index;
1121 if (index >= mh->mtNoObjects)
1122 mh->mtNoObjects++;
1123 GlobalUnlock16(dc->w.hMetaFile);
1124 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1125 dc->w.hMetaFile = handle;
1127 return handle;
1131 /******************************************************************
1132 * MF_TextOut
1134 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
1136 HMETAFILE handle;
1137 DWORD len;
1138 HANDLE hmr;
1139 METARECORD *mr;
1141 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1142 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1143 return FALSE;
1144 mr = (METARECORD *)GlobalLock16(hmr);
1145 memset(mr, 0, len);
1147 mr->rdSize = len / 2;
1148 mr->rdFunction = META_TEXTOUT;
1149 *(mr->rdParam) = count;
1150 memcpy(mr->rdParam + 1, str, count);
1151 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1152 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1153 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1154 dc->w.hMetaFile = handle;
1155 GlobalFree16(hmr);
1156 return handle;
1160 /******************************************************************
1161 * MF_MetaPoly - implements Polygon and Polyline
1163 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
1165 HMETAFILE handle;
1166 DWORD len;
1167 HANDLE hmr;
1168 METARECORD *mr;
1170 len = sizeof(METARECORD) + (count * 4);
1171 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1172 return FALSE;
1173 mr = (METARECORD *)GlobalLock16(hmr);
1174 memset(mr, 0, len);
1176 mr->rdSize = len / 2;
1177 mr->rdFunction = func;
1178 *(mr->rdParam) = count;
1179 memcpy(mr->rdParam + 1, pt, count * 4);
1180 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1181 dc->w.hMetaFile = handle;
1182 GlobalFree16(hmr);
1183 return handle;
1187 /******************************************************************
1188 * MF_BitBlt
1190 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1191 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
1193 fprintf(stdnimp,"MF_BitBlt: not implemented yet\n");
1194 return FALSE;
1198 /******************************************************************
1199 * MF_StretchBlt
1201 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1202 short heightDest, HDC hdcSrc, short xSrc, short ySrc,
1203 short widthSrc, short heightSrc, DWORD rop)
1205 fprintf(stdnimp,"MF_StretchBlt: not implemented yet\n");
1206 return FALSE;