Release 960414
[wine.git] / objects / metafile.c
blobb68373ab0c0cdf3dae1327161e7ad382fe1bf925
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
6 */
8 #include <string.h>
9 #include <fcntl.h>
10 #include "gdi.h"
11 #include "bitmap.h"
12 #include "file.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 (FILE_Read(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(LPCTSTR 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 mf->hFile = _lcreat(lpFilename, 0);
120 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
122 GlobalFree(mf->hMetaHdr);
123 GlobalFree(dc->w.hMetaFile);
124 return 0;
127 else /* memory based metafile */
128 mh->mtType = 0;
130 /* create the handle table */
131 HTLen = HTINCR;
132 hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
133 sizeof(HANDLETABLE) * HTLen);
134 ht = (HANDLETABLE *)GlobalLock(hHT);
136 GlobalUnlock(mf->hMetaHdr);
137 GlobalUnlock(dc->w.hMetaFile);
138 return handle;
142 /******************************************************************
143 * CloseMetafile GDI.126
145 HMETAFILE CloseMetaFile(HDC hdc)
147 DC *dc;
148 METAFILE *mf;
149 METAHEADER *mh;
150 HMETAFILE hmf;
151 /* METARECORD *mr = (METARECORD *)&buffer;*/
153 dprintf_metafile(stddeb,"CloseMetaFile\n");
155 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
156 if (!dc) return 0;
157 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
158 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
160 /* Construct the end of metafile record - this is documented
161 * in SDK Knowledgebase Q99334.
163 if (!MF_MetaParam0(dc, META_EOF))
165 GlobalFree(mf->hMetaHdr);
166 GlobalFree(dc->w.hMetaFile);
167 return 0;
170 if (mh->mtType == 1) /* disk based metafile */
172 if (_llseek(mf->hFile, 0L, 0) == -1)
174 GlobalFree(mf->hMetaHdr);
175 GlobalFree(dc->w.hMetaFile);
176 return 0;
178 if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
180 GlobalFree(mf->hMetaHdr);
181 GlobalFree(dc->w.hMetaFile);
182 return 0;
184 _lclose(mf->hFile);
187 /* delete the handle table */
188 GlobalFree(hHT);
190 GlobalUnlock(mf->hMetaHdr);
191 hmf = dc->w.hMetaFile;
192 GlobalUnlock(hmf);
193 GDI_FreeObject(hdc);
194 return hmf;
198 /******************************************************************
199 * DeleteMetafile GDI.127
201 BOOL DeleteMetaFile(HMETAFILE hmf)
203 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
205 if (!mf || mf->wMagic != METAFILE_MAGIC)
206 return FALSE;
208 GlobalFree(mf->hMetaHdr);
209 GlobalFree(hmf);
210 return TRUE;
214 /******************************************************************
215 * PlayMetafile GDI.123
217 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
219 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
220 METAHEADER *mh;
221 METARECORD *mr;
222 HANDLETABLE *ht;
223 char *buffer = (char *)NULL;
225 if (mf->wMagic != METAFILE_MAGIC)
226 return FALSE;
228 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
229 if (mh->mtType == 1) /* disk based metafile */
231 mf->hFile = _lopen(mf->Filename, OF_READ);
232 mf->hBuffer = GlobalAlloc(GMEM_MOVEABLE, mh->mtMaxRecord * 2);
233 buffer = (char *)GlobalLock(mf->hBuffer);
234 _llseek(mf->hFile, mh->mtHeaderSize * 2, 0);
235 mf->MetaOffset = mh->mtHeaderSize * 2;
237 else if (mh->mtType == 0) /* memory based metafile */
238 mf->MetaOffset = mh->mtHeaderSize * 2;
239 else /* not a valid metafile type */
240 return FALSE;
242 /* create the handle table */
243 hHT = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,
244 sizeof(HANDLETABLE) * mh->mtNoObjects);
245 ht = (HANDLETABLE *)GlobalLock(hHT);
247 /* loop through metafile playing records */
248 while (mf->MetaOffset < mh->mtSize * 2)
250 if (mh->mtType == 1) /* disk based metafile */
252 FILE_Read(mf->hFile, buffer, sizeof(METARECORD));
253 mr = (METARECORD *)buffer;
254 FILE_Read(mf->hFile, (char *)(mr->rdParam + 1), (mr->rdSize * 2) -
255 sizeof(METARECORD));
256 mf->MetaOffset += mr->rdSize * 2;
258 else /* memory based metafile */
260 mr = (METARECORD *)((char *)mh + mf->MetaOffset);
261 mf->MetaOffset += mr->rdSize * 2;
263 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
266 /* close disk based metafile and free buffer */
267 if (mh->mtType == 1)
269 GlobalFree(mf->hBuffer);
270 _lclose(mf->hFile);
273 /* free handle table */
274 GlobalFree(hHT);
276 return TRUE;
280 /******************************************************************
281 * PlayMetaFileRecord GDI.176
283 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
284 WORD nHandles)
286 short s1;
287 HANDLE hndl;
288 char *ptr;
289 BITMAPINFOHEADER *infohdr;
291 switch (mr->rdFunction)
293 case META_EOF:
294 break;
296 case META_DELETEOBJECT:
297 DeleteObject(*(ht->objectHandle + *(mr->rdParam)));
298 break;
300 case META_SETBKCOLOR:
301 SetBkColor(hdc, *(mr->rdParam));
302 break;
304 case META_SETBKMODE:
305 SetBkMode(hdc, *(mr->rdParam));
306 break;
308 case META_SETMAPMODE:
309 SetMapMode(hdc, *(mr->rdParam));
310 break;
312 case META_SETROP2:
313 SetROP2(hdc, *(mr->rdParam));
314 break;
316 case META_SETRELABS:
317 SetRelAbs(hdc, *(mr->rdParam));
318 break;
320 case META_SETPOLYFILLMODE:
321 SetPolyFillMode(hdc, *(mr->rdParam));
322 break;
324 case META_SETSTRETCHBLTMODE:
325 SetStretchBltMode(hdc, *(mr->rdParam));
326 break;
328 case META_SETTEXTCOLOR:
329 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
330 break;
332 case META_SETWINDOWORG:
333 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
334 break;
336 case META_SETWINDOWEXT:
337 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
338 break;
340 case META_SETVIEWPORTORG:
341 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
342 break;
344 case META_SETVIEWPORTEXT:
345 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
346 break;
348 case META_OFFSETWINDOWORG:
349 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
350 break;
352 case META_SCALEWINDOWEXT:
353 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
354 *(mr->rdParam + 1), *(mr->rdParam));
355 break;
357 case META_OFFSETVIEWPORTORG:
358 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
359 break;
361 case META_SCALEVIEWPORTEXT:
362 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
363 *(mr->rdParam + 1), *(mr->rdParam));
364 break;
366 case META_LINETO:
367 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
368 break;
370 case META_MOVETO:
371 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
372 break;
374 case META_EXCLUDECLIPRECT:
375 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
376 *(mr->rdParam + 1), *(mr->rdParam));
377 break;
379 case META_INTERSECTCLIPRECT:
380 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
381 *(mr->rdParam + 1), *(mr->rdParam));
382 break;
384 case META_ARC:
385 Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
386 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
387 *(mr->rdParam + 1), *(mr->rdParam));
388 break;
390 case META_ELLIPSE:
391 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
392 *(mr->rdParam + 1), *(mr->rdParam));
393 break;
395 case META_FLOODFILL:
396 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
397 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
398 break;
400 case META_PIE:
401 Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
402 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
403 *(mr->rdParam + 1), *(mr->rdParam));
404 break;
406 case META_RECTANGLE:
407 Rectangle(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
408 *(mr->rdParam + 1), *(mr->rdParam));
409 break;
411 case META_ROUNDRECT:
412 RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
413 *(mr->rdParam + 3), *(mr->rdParam + 2),
414 *(mr->rdParam + 1), *(mr->rdParam));
415 break;
417 case META_PATBLT:
418 PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
419 *(mr->rdParam + 3), *(mr->rdParam + 2),
420 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
421 break;
423 case META_SAVEDC:
424 SaveDC(hdc);
425 break;
427 case META_SETPIXEL:
428 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
429 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
430 break;
432 case META_OFFSETCLIPRGN:
433 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
434 break;
436 case META_TEXTOUT:
437 s1 = *(mr->rdParam);
438 TextOut(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
439 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
440 (char *)(mr->rdParam + 1), s1);
441 break;
443 case META_POLYGON:
444 Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
445 break;
447 case META_POLYPOLYGON:
448 PolyPolygon(hdc, (LPPOINT)(mr->rdParam + *(mr->rdParam) + 1),
449 (LPINT)(mr->rdParam + 1), *(mr->rdParam));
450 break;
452 case META_POLYLINE:
453 Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
454 break;
456 case META_RESTOREDC:
457 RestoreDC(hdc, *(mr->rdParam));
458 break;
460 case META_SELECTOBJECT:
461 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
462 break;
464 case META_CHORD:
465 Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
466 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
467 *(mr->rdParam + 1), *(mr->rdParam));
468 break;
470 case META_CREATEPATTERNBRUSH:
471 switch (*(mr->rdParam))
473 case BS_PATTERN:
474 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
475 MF_AddHandle(ht, nHandles,
476 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
477 infohdr->biHeight,
478 infohdr->biPlanes,
479 infohdr->biBitCount,
480 (LPSTR)(mr->rdParam +
481 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
482 break;
484 case BS_DIBPATTERN:
485 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
486 hndl = GlobalAlloc(GMEM_MOVEABLE, s1);
487 ptr = GlobalLock(hndl);
488 memcpy(ptr, mr->rdParam + 2, s1);
489 GlobalUnlock(hndl);
490 MF_AddHandle(ht, nHandles,
491 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
492 GlobalFree(hndl);
494 break;
496 case META_CREATEPENINDIRECT:
497 MF_AddHandle(ht, nHandles,
498 CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
499 break;
501 case META_CREATEFONTINDIRECT:
502 MF_AddHandle(ht, nHandles,
503 CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
504 break;
506 case META_CREATEBRUSHINDIRECT:
507 MF_AddHandle(ht, nHandles,
508 CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
509 break;
511 /* W. Magro: Some new metafile operations. Not all debugged. */
512 case META_CREATEPALETTE:
513 MF_AddHandle(ht, nHandles,
514 CreatePalette((LPLOGPALETTE)mr->rdParam));
515 break;
517 case META_SETTEXTALIGN:
518 fprintf(stderr,"PlayMetaFileRecord: SETTEXTALIGN: %hd\n",mr->rdParam[0]);
519 SetTextAlign(hdc, *(mr->rdParam));
520 break;
522 case META_SELECTPALETTE:
523 SelectPalette(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
524 break;
526 case META_SETMAPPERFLAGS:
527 SetMapperFlags(hdc, *(mr->rdParam));
528 break;
530 case META_REALIZEPALETTE:
531 RealizePalette(hdc);
532 break;
534 case META_ESCAPE:
535 dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
536 break;
538 case META_EXTTEXTOUT: /* FIXME: don't know the exact parameters here */
540 short x,y,options,x5,x6,x7,x8;
541 y=mr->rdParam[0]; /* X position */
542 x=mr->rdParam[1]; /* Y position */
543 s1=mr->rdParam[2]; /* String length */
544 options=mr->rdParam[3];
545 x5=mr->rdParam[(s1+1)/2+4]; /* unknown meaning */
546 x6=mr->rdParam[(s1+1)/2+5]; /* unknown meaning */
547 x7=mr->rdParam[(s1+1)/2+6]; /* unknown meaning */
548 x8=mr->rdParam[(s1+1)/2+7]; /* unknown meaning */
549 ExtTextOut(hdc, x, y, options, (LPRECT) &mr->rdParam[(s1+1)/2+4], (char *)(mr->rdParam + 4), s1, NULL);
550 /* fprintf(stderr,"EXTTEXTOUT (len: %d) %hd : %hd %hd %hd %hd [%s].\n",
551 (mr->rdSize-s1),options,x5,x6,x7,x8,(char*) &(mr->rdParam[4]) );*/
553 break;
554 /* End new metafile operations. */
556 default:
557 fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
558 mr->rdFunction);
562 /******************************************************************
563 * GetMetaFileBits by William Magro, 19 Sep 1995
565 * Trade in a meta file object handle for a handle to the meta file memory
567 HANDLE GetMetaFileBits(HMETAFILE hmf)
570 /* save away the meta file bits handle */
571 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
572 HANDLE hMem = mf->hMetaHdr;
573 METAHEADER *mh = (METAHEADER *)GlobalLock(hMem);
575 dprintf_metafile(stddeb,"GetMetaFileBits: hmf in: %04x\n", hmf);
577 /* can't get bits of disk based metafile */
578 /* FIXME: should the disk file be loaded in this case? */
579 if(mh->mtType == 1) {
580 fprintf(stderr,
581 "GetMetaFileBits: application requested bits of disk meta file.\n");
582 GlobalUnlock(hMem);
583 GlobalUnlock(hmf);
584 return FALSE;
587 /* unlock the memory and invalidate the metafile handle */
588 GlobalUnlock(hMem);
589 GlobalFree(hmf);
591 dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hMem);
593 return hMem;
596 /******************************************************************
597 * SetMetaFileBits by William Magro, 19 Sep 1995
599 * Trade in a meta file memory handle for a handle to a meta file object
601 HMETAFILE SetMetaFileBits(HANDLE hMem)
603 HMETAFILE hmf;
604 METAFILE *mf;
605 METAHEADER *mh = (METAHEADER *)GlobalLock(hMem);
607 dprintf_metafile(stddeb,"SetMetaFileBits: hMem in: %04x\n", hMem);
609 if (!mh) return FALSE;
611 /* now it is a memory meta file */
612 mh->mtType = 0;
614 hmf = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE));
615 mf = (METAFILE *)GlobalLock(hmf);
616 if (!mf) {
617 GlobalUnlock(hMem);
618 GlobalFree(hmf);
619 return FALSE;
622 /* use the supplied memory handle */
623 mf->hMetaHdr = hMem;
624 mf->wMagic = METAFILE_MAGIC;
625 mf->MetaOffset = mh->mtHeaderSize * 2;
626 mf->hFile = (int) (mf->hBuffer = (HANDLE) NULL);
628 GlobalUnlock(hMem);
629 GlobalUnlock(hmf);
631 dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hmf);
633 return hmf;
636 /******************************************************************
637 * MF_WriteRecord
639 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
641 DWORD len;
642 METAFILE *mf = (METAFILE *)GlobalLock(hmf);
643 METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
645 if (mh->mtType == 0) /* memory based metafile */
647 len = mh->mtSize * 2 + rlen;
648 GlobalUnlock(mf->hMetaHdr);
649 mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE);
650 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
651 memcpy((WORD *)mh + mh->mtSize, mr, rlen);
653 else if (mh->mtType == 1) /* disk based metafile */
655 if (_lwrite(mf->hFile, (char *)mr, rlen) == -1)
657 GlobalUnlock(mf->hMetaHdr);
658 return FALSE;
661 else
663 GlobalUnlock(mf->hMetaHdr);
664 return FALSE;
667 mh->mtSize += rlen / 2;
668 mh->mtMaxRecord = MAX(mh->mtMaxRecord, rlen / 2);
669 GlobalUnlock(mf->hMetaHdr);
670 return TRUE;
674 /******************************************************************
675 * MF_AddHandle
677 * Add a handle to an external handle table and return the index
679 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
681 int i;
683 for (i = 0; i < htlen; i++)
685 if (*(ht->objectHandle + i) == 0)
687 *(ht->objectHandle + i) = hobj;
688 return i;
691 return -1;
695 /******************************************************************
696 * MF_AddHandleInternal
698 * Add a handle to the internal handle table and return the index
700 int MF_AddHandleInternal(HANDLE hobj)
702 int i;
703 HANDLETABLE *ht = (HANDLETABLE *)GlobalLock(hHT);
705 for (i = 0; i < HTLen; i++)
707 if (*(ht->objectHandle + i) == 0)
709 *(ht->objectHandle + i) = hobj;
710 GlobalUnlock(hHT);
711 return i;
714 GlobalUnlock(hHT);
715 if (!(hHT = GlobalReAlloc(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
716 return -1;
717 HTLen += HTINCR;
718 ht = (HANDLETABLE *)GlobalLock(hHT);
719 *(ht->objectHandle + i) = hobj;
720 GlobalUnlock(hHT);
721 return i;
725 /******************************************************************
726 * MF_MetaParam0
728 BOOL MF_MetaParam0(DC *dc, short func)
730 char buffer[8];
731 METARECORD *mr = (METARECORD *)&buffer;
733 mr->rdSize = 3;
734 mr->rdFunction = func;
735 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
739 /******************************************************************
740 * MF_MetaParam1
742 BOOL MF_MetaParam1(DC *dc, short func, short param1)
744 char buffer[8];
745 METARECORD *mr = (METARECORD *)&buffer;
747 mr->rdSize = 4;
748 mr->rdFunction = func;
749 *(mr->rdParam) = param1;
750 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
754 /******************************************************************
755 * MF_MetaParam2
757 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
759 char buffer[10];
760 METARECORD *mr = (METARECORD *)&buffer;
762 mr->rdSize = 5;
763 mr->rdFunction = func;
764 *(mr->rdParam) = param2;
765 *(mr->rdParam + 1) = param1;
766 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
770 /******************************************************************
771 * MF_MetaParam4
773 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
774 short param3, short param4)
776 char buffer[14];
777 METARECORD *mr = (METARECORD *)&buffer;
779 mr->rdSize = 7;
780 mr->rdFunction = func;
781 *(mr->rdParam) = param4;
782 *(mr->rdParam + 1) = param3;
783 *(mr->rdParam + 2) = param2;
784 *(mr->rdParam + 3) = param1;
785 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
789 /******************************************************************
790 * MF_MetaParam6
792 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
793 short param3, short param4, short param5, short param6)
795 char buffer[18];
796 METARECORD *mr = (METARECORD *)&buffer;
798 mr->rdSize = 9;
799 mr->rdFunction = func;
800 *(mr->rdParam) = param6;
801 *(mr->rdParam + 1) = param5;
802 *(mr->rdParam + 2) = param4;
803 *(mr->rdParam + 3) = param3;
804 *(mr->rdParam + 4) = param2;
805 *(mr->rdParam + 5) = param1;
806 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
810 /******************************************************************
811 * MF_MetaParam8
813 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
814 short param3, short param4, short param5,
815 short param6, short param7, short param8)
817 char buffer[22];
818 METARECORD *mr = (METARECORD *)&buffer;
820 mr->rdSize = 11;
821 mr->rdFunction = func;
822 *(mr->rdParam) = param8;
823 *(mr->rdParam + 1) = param7;
824 *(mr->rdParam + 2) = param6;
825 *(mr->rdParam + 3) = param5;
826 *(mr->rdParam + 4) = param4;
827 *(mr->rdParam + 5) = param3;
828 *(mr->rdParam + 6) = param2;
829 *(mr->rdParam + 7) = param1;
830 return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
834 /******************************************************************
835 * MF_CreateBrushIndirect
837 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
839 int index;
840 BOOL rc;
841 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
842 METARECORD *mr = (METARECORD *)&buffer;
843 METAFILE *mf;
844 METAHEADER *mh;
846 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
847 mr->rdFunction = META_CREATEBRUSHINDIRECT;
848 memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
849 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
850 return FALSE;
852 mr->rdSize = sizeof(METARECORD) / 2;
853 mr->rdFunction = META_SELECTOBJECT;
854 if ((index = MF_AddHandleInternal(hBrush)) == -1)
855 return FALSE;
857 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
858 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
859 *(mr->rdParam) = index;
860 if (index >= mh->mtNoObjects)
861 mh->mtNoObjects++;
862 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
863 GlobalUnlock(mf->hMetaHdr);
864 GlobalUnlock(dc->w.hMetaFile);
865 return rc;
869 /******************************************************************
870 * MF_CreatePatternBrush
872 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
874 DWORD len, bmSize, biSize;
875 HANDLE hmr;
876 METARECORD *mr;
877 BITMAPOBJ *bmp;
878 BITMAPINFO *info;
879 BITMAPINFOHEADER *infohdr;
880 int index;
881 BOOL rc;
882 char buffer[sizeof(METARECORD)];
883 METAFILE *mf;
884 METAHEADER *mh;
886 switch (logbrush->lbStyle)
888 case BS_PATTERN:
889 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HANDLE)logbrush->lbHatch, BITMAP_MAGIC);
890 if (!bmp) return FALSE;
891 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
892 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
893 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
894 return FALSE;
895 mr = (METARECORD *)GlobalLock(hmr);
896 memset(mr, 0, len);
897 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
898 mr->rdSize = len / 2;
899 *(mr->rdParam) = logbrush->lbStyle;
900 *(mr->rdParam + 1) = DIB_RGB_COLORS;
901 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
902 infohdr->biSize = sizeof(BITMAPINFOHEADER);
903 infohdr->biWidth = bmp->bitmap.bmWidth;
904 infohdr->biHeight = bmp->bitmap.bmHeight;
905 infohdr->biPlanes = bmp->bitmap.bmPlanes;
906 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
907 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
908 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
909 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
910 break;
912 case BS_DIBPATTERN:
913 info = (BITMAPINFO *)GlobalLock((HANDLE)logbrush->lbHatch);
914 bmSize = info->bmiHeader.biSizeImage;
915 if (!bmSize)
916 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
917 + 31) / 32 * 8 * info->bmiHeader.biHeight;
918 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
919 len = sizeof(METARECORD) + biSize + bmSize + 2;
920 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
921 return FALSE;
922 mr = (METARECORD *)GlobalLock(hmr);
923 memset(mr, 0, len);
924 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
925 mr->rdSize = len / 2;
926 *(mr->rdParam) = logbrush->lbStyle;
927 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
928 memcpy(mr->rdParam + 2, info, biSize + bmSize);
929 break;
930 default:
931 return FALSE;
933 if (!MF_WriteRecord(dc->w.hMetaFile, mr, len))
935 GlobalFree(hmr);
936 return FALSE;
939 GlobalFree(hmr);
940 mr = (METARECORD *)&buffer;
941 mr->rdSize = sizeof(METARECORD) / 2;
942 mr->rdFunction = META_SELECTOBJECT;
943 if ((index = MF_AddHandleInternal(hBrush)) == -1)
944 return FALSE;
946 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
947 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
948 *(mr->rdParam) = index;
949 if (index >= mh->mtNoObjects)
950 mh->mtNoObjects++;
951 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
952 GlobalUnlock(mf->hMetaHdr);
953 GlobalUnlock(dc->w.hMetaFile);
954 return rc;
958 /******************************************************************
959 * MF_CreatePenIndirect
961 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
963 int index;
964 BOOL rc;
965 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
966 METARECORD *mr = (METARECORD *)&buffer;
967 METAFILE *mf;
968 METAHEADER *mh;
970 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
971 mr->rdFunction = META_CREATEPENINDIRECT;
972 memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
973 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
974 return FALSE;
976 mr->rdSize = sizeof(METARECORD) / 2;
977 mr->rdFunction = META_SELECTOBJECT;
978 if ((index = MF_AddHandleInternal(hPen)) == -1)
979 return FALSE;
981 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
982 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
983 *(mr->rdParam) = index;
984 if (index >= mh->mtNoObjects)
985 mh->mtNoObjects++;
986 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
987 GlobalUnlock(mf->hMetaHdr);
988 GlobalUnlock(dc->w.hMetaFile);
989 return rc;
993 /******************************************************************
994 * MF_CreateFontIndirect
996 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
998 int index;
999 BOOL rc;
1000 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
1001 METARECORD *mr = (METARECORD *)&buffer;
1002 METAFILE *mf;
1003 METAHEADER *mh;
1005 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
1006 mr->rdFunction = META_CREATEFONTINDIRECT;
1007 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
1008 if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
1009 return FALSE;
1011 mr->rdSize = sizeof(METARECORD) / 2;
1012 mr->rdFunction = META_SELECTOBJECT;
1013 if ((index = MF_AddHandleInternal(hFont)) == -1)
1014 return FALSE;
1016 mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
1017 mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
1018 *(mr->rdParam) = index;
1019 if (index >= mh->mtNoObjects)
1020 mh->mtNoObjects++;
1021 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1022 GlobalUnlock(mf->hMetaHdr);
1023 GlobalUnlock(dc->w.hMetaFile);
1024 return rc;
1028 /******************************************************************
1029 * MF_TextOut
1031 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
1033 BOOL rc;
1034 DWORD len;
1035 HANDLE hmr;
1036 METARECORD *mr;
1038 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1039 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
1040 return FALSE;
1041 mr = (METARECORD *)GlobalLock(hmr);
1042 memset(mr, 0, len);
1044 mr->rdSize = len / 2;
1045 mr->rdFunction = META_TEXTOUT;
1046 *(mr->rdParam) = count;
1047 memcpy(mr->rdParam + 1, str, count);
1048 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1049 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1050 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1051 GlobalFree(hmr);
1052 return rc;
1056 /******************************************************************
1057 * MF_MetaPoly - implements Polygon and Polyline
1059 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
1061 BOOL rc;
1062 DWORD len;
1063 HANDLE hmr;
1064 METARECORD *mr;
1066 len = sizeof(METARECORD) + (count * 4);
1067 if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
1068 return FALSE;
1069 mr = (METARECORD *)GlobalLock(hmr);
1070 memset(mr, 0, len);
1072 mr->rdSize = len / 2;
1073 mr->rdFunction = func;
1074 *(mr->rdParam) = count;
1075 memcpy(mr->rdParam + 1, pt, count * 4);
1076 rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1077 GlobalFree(hmr);
1078 return rc;
1082 /******************************************************************
1083 * MF_BitBlt
1085 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1086 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
1088 fprintf(stdnimp,"MF_BitBlt: not implemented yet\n");
1089 return FALSE;
1093 /******************************************************************
1094 * MF_StretchBlt
1096 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1097 short heightDest, HDC hdcSrc, short xSrc, short ySrc,
1098 short widthSrc, short heightSrc, DWORD rop)
1100 fprintf(stdnimp,"MF_StretchBlt: not implemented yet\n");
1101 return FALSE;