Release 960824
[wine/multimedia.git] / objects / metafile.c
blobb273a549a28d7128bfd264327ff95c7a16e08319
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine 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 "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
27 HMETAFILE16 GetMetaFile(LPSTR lpFilename)
29 HMETAFILE16 hmf;
30 METAHEADER *mh;
31 HFILE hFile;
32 DWORD size;
34 dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
36 if (!lpFilename)
37 return 0;
39 hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
40 mh = (METAHEADER *)GlobalLock16(hmf);
42 if (!mh) {
43 GlobalFree16(hmf);
44 return 0;
47 if ((hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) {
48 GlobalFree16(hmf);
49 return 0;
52 if (FILE_Read(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
53 GlobalFree16(hmf);
54 return 0;
57 size = mh->mtSize * 2; /* alloc memory for whole metafile */
58 GlobalUnlock16(hmf);
59 hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
60 mh = (METAHEADER *)GlobalLock16(hmf);
62 if (!mh) {
63 GlobalFree16(hmf);
64 return 0;
67 if (FILE_Read(hFile, (char*)mh + mh->mtHeaderSize * 2,
68 size - mh->mtHeaderSize * 2) == HFILE_ERROR) {
69 GlobalFree16(hmf);
70 return 0;
73 _lclose(hFile);
75 if (mh->mtType != 1) {
76 GlobalFree16(hmf);
77 return 0;
80 GlobalUnlock16(hmf);
81 return hmf;
85 /******************************************************************
86 * CreateMetafile GDI.125
89 HANDLE CreateMetaFile(LPCSTR lpFilename)
91 DC *dc;
92 HANDLE handle;
93 METAHEADER *mh;
94 int hFile;
96 dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
98 handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
100 if (!handle)
101 return 0;
103 dc = (DC *)GDI_HEAP_LIN_ADDR(handle);
105 if (!(dc->w.hMetaFile = GlobalAlloc16(GMEM_MOVEABLE, sizeof(METAHEADER)))) {
106 GDI_FreeObject(handle);
107 return 0;
109 dc->w.bitsPerPixel = screenDepth;
110 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
112 mh->mtHeaderSize = MFHEADERSIZE / 2;
113 mh->mtVersion = MFVERSION;
114 mh->mtSize = MFHEADERSIZE / 2;
115 mh->mtNoObjects = 0;
116 mh->mtMaxRecord = 0;
117 mh->mtNoParameters = 0;
119 if (lpFilename) /* disk based metafile */
121 mh->mtType = 1; /* disk */
122 hFile = _lcreat(lpFilename, 0);
123 if (_lwrite(hFile, (char *)mh, MFHEADERSIZE) == -1)
125 GlobalFree16(dc->w.hMetaFile);
126 return 0;
128 mh->mtNoParameters = hFile; /* store file descriptor here */
129 /* windows probably uses this too*/
131 else /* memory based metafile */
132 mh->mtType = 0;
134 /* create the handle table */
135 HTLen = HTINCR;
136 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
137 sizeof(HANDLETABLE16) * HTLen);
139 GlobalUnlock16(dc->w.hMetaFile);
140 dprintf_metafile(stddeb,"CreateMetaFile: returning %04x\n", handle);
141 return handle;
144 /******************************************************************
145 * CopyMetafile GDI.151 Niels de Carpentier, April 1996
148 HMETAFILE16 CopyMetaFile(HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
150 HMETAFILE16 handle = 0;
151 METAHEADER *mh;
152 METAHEADER *mh2;
153 int hFile;
155 dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename);
157 mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
159 if (!mh)
160 return 0;
162 if (lpFilename) /* disk based metafile */
164 int i,j;
165 hFile = _lcreat(lpFilename, 0);
166 j=mh->mtType;
167 mh->mtType=1; /* disk file version stores 1 here */
168 i=_lwrite(hFile, (char *)mh, mh->mtSize * 2) ;
169 mh->mtType=j; /* restore old value [0 or 1] */
170 _lclose(hFile);
171 if (i == -1)
172 return 0;
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;
185 /******************************************************************
186 * IsValidMetaFile (GDI.410)
187 * (This is not exactly what windows does, see "Undoc Win")
190 BOOL IsValidMetaFile(HMETAFILE16 hmf)
192 BOOL resu=FALSE;
193 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
194 if (mh)
195 if (mh->mtType == 1 || mh->mtType == 0)
196 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
197 if (mh->mtVersion == MFVERSION)
198 resu=TRUE;
199 GlobalUnlock16(hmf);
200 dprintf_metafile(stddeb,"IsValidMetaFile %x => %d\n",hmf,resu);
201 return resu;
205 /******************************************************************
206 * CloseMetafile GDI.126
209 HMETAFILE16 CloseMetaFile(HDC hdc)
211 DC *dc;
212 METAHEADER *mh;
213 HMETAFILE16 hmf;
214 HFILE hFile;
216 dprintf_metafile(stddeb,"CloseMetaFile\n");
218 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
220 if (!dc)
221 return 0;
223 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
225 /* Construct the end of metafile record - this is documented
226 * in SDK Knowledgebase Q99334.
229 if (!MF_MetaParam0(dc, META_EOF))
231 GlobalFree16(dc->w.hMetaFile);
232 return 0;
235 if (mh->mtType == 1) /* disk based metafile */
237 hFile = mh->mtNoParameters;
238 mh->mtNoParameters = 0;
239 if (_llseek(hFile, 0L, 0) == -1)
241 GlobalFree16(dc->w.hMetaFile);
242 return 0;
244 if (_lwrite(hFile, (char *)mh, MFHEADERSIZE) == -1)
246 GlobalFree16(dc->w.hMetaFile);
247 return 0;
249 _lclose(hFile);
252 /* delete the handle table */
253 GlobalFree16(hHT);
255 hmf = dc->w.hMetaFile;
256 GlobalUnlock16(hmf);
257 GDI_FreeObject(hdc);
258 return hmf;
262 /******************************************************************
263 * DeleteMetafile GDI.127
266 BOOL DeleteMetaFile(HMETAFILE16 hmf)
268 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
270 if (!mh)
271 return FALSE;
273 GlobalFree16(hmf);
274 return TRUE;
278 /******************************************************************
279 * PlayMetafile GDI.123
282 BOOL PlayMetaFile(HDC hdc, HMETAFILE16 hmf)
284 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
285 METARECORD *mr;
286 HANDLETABLE16 *ht;
287 int offset = 0;
288 WORD i;
290 dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf);
292 /* create the handle table */
293 hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
294 sizeof(HANDLETABLE16) * mh->mtNoObjects);
295 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
297 /* loop through metafile playing records */
298 offset = mh->mtHeaderSize * 2;
299 while (offset < mh->mtSize * 2)
301 mr = (METARECORD *)((char *)mh + offset);
302 dprintf_metafile(stddeb,"offset = %04x size = %08lx function = %04x\n",
303 offset,mr->rdSize,mr->rdFunction);
304 offset += mr->rdSize * 2;
305 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
308 /* free objects in handle table */
309 for(i = 0; i < mh->mtNoObjects; i++)
310 if(*(ht->objectHandle + i) != 0)
311 DeleteObject(*(ht->objectHandle + i));
313 /* free handle table */
314 GlobalFree16(hHT);
316 return TRUE;
320 /******************************************************************
321 * EnumMetafile GDI.175
322 * Niels de carpentier, april 1996
325 BOOL EnumMetaFile(HDC hdc, HMETAFILE16 hmf, MFENUMPROC16 lpEnumFunc,LPARAM lpData)
327 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
328 METARECORD *mr;
329 SEGPTR ht, spRecord;
330 int offset = 0;
332 dprintf_metafile(stddeb,"EnumMetaFile(%04x, %04x, %08lx, %08lx)\n",
333 hdc, hmf, (DWORD)lpEnumFunc, lpData);
335 /* create the handle table */
337 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
338 sizeof(HANDLETABLE16) * mh->mtNoObjects);
339 ht = WIN16_GlobalLock16(hHT);
341 offset = mh->mtHeaderSize * 2;
343 /* loop through metafile records */
345 spRecord = WIN16_GlobalLock16(hmf);
346 while (offset < (mh->mtSize * 2))
348 mr = (METARECORD *)((char *)mh + offset);
349 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)ht,
350 (METARECORD *)((UINT32)spRecord + offset),
351 mh->mtNoObjects, (LONG)lpData))
352 break;
354 offset += (mr->rdSize * 2);
357 /* free handle table */
358 GlobalFree16(hHT);
360 return TRUE;
363 /*******************************************************************
364 * MF_GetDIBitsPointer [internal helper for e.g. PlayMetaFileRecord]
366 * Returns offset to DIB bits or 0 if error
367 * (perhaps should be moved to (objects/dib.c ?)
369 static LPSTR MF_GetDIBitsPointer(LPBITMAPINFO info)
371 int offset;
372 if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
374 if (info->bmiHeader.biClrUsed)
376 if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
377 offset = info->bmiHeader.biClrUsed * 4;
378 else
379 offset = (1 << info->bmiHeader.biBitCount) * 4;
381 else
382 offset = (1 << info->bmiHeader.biBitCount) * 4;
384 else if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
386 if (info->bmiHeader.biClrUsed)
388 if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
389 offset = info->bmiHeader.biClrUsed * 3;
390 else
391 offset = (1 << info->bmiHeader.biBitCount) * 3;
393 else
394 offset = (1 << info->bmiHeader.biBitCount) * 3;
396 else
398 fprintf(stderr,"Unknown size for BITMAPHEADER in MetaFile!\n");
399 return NULL;
401 return (LPSTR)info + info->bmiHeader.biSize + offset;
405 /******************************************************************
406 * PlayMetaFileRecord GDI.176
409 void PlayMetaFileRecord(HDC hdc, HANDLETABLE16 *ht, METARECORD *mr,
410 WORD nHandles)
412 short s1;
413 HANDLE hndl;
414 char *ptr;
415 BITMAPINFOHEADER *infohdr;
417 dprintf_metafile(stddeb,"PlayMetaFileRecord(%04x %08lx %08lx %04x)\n",
418 hdc,(LONG)ht, (LONG)mr, nHandles);
420 switch (mr->rdFunction)
422 case META_EOF:
423 break;
425 case META_DELETEOBJECT:
426 DeleteObject(*(ht->objectHandle + *(mr->rdParam)));
427 *(ht->objectHandle + *(mr->rdParam)) = 0;
428 break;
430 case META_SETBKCOLOR:
431 SetBkColor(hdc, *(mr->rdParam));
432 break;
434 case META_SETBKMODE:
435 SetBkMode(hdc, *(mr->rdParam));
436 break;
438 case META_SETMAPMODE:
439 SetMapMode(hdc, *(mr->rdParam));
440 break;
442 case META_SETROP2:
443 SetROP2(hdc, *(mr->rdParam));
444 break;
446 case META_SETRELABS:
447 SetRelAbs(hdc, *(mr->rdParam));
448 break;
450 case META_SETPOLYFILLMODE:
451 SetPolyFillMode(hdc, *(mr->rdParam));
452 break;
454 case META_SETSTRETCHBLTMODE:
455 SetStretchBltMode(hdc, *(mr->rdParam));
456 break;
458 case META_SETTEXTCOLOR:
459 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
460 break;
462 case META_SETWINDOWORG:
463 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
464 break;
466 case META_SETWINDOWEXT:
467 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
468 break;
470 case META_SETVIEWPORTORG:
471 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
472 break;
474 case META_SETVIEWPORTEXT:
475 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
476 break;
478 case META_OFFSETWINDOWORG:
479 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
480 break;
482 case META_SCALEWINDOWEXT:
483 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
484 *(mr->rdParam + 1), *(mr->rdParam));
485 break;
487 case META_OFFSETVIEWPORTORG:
488 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
489 break;
491 case META_SCALEVIEWPORTEXT:
492 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
493 *(mr->rdParam + 1), *(mr->rdParam));
494 break;
496 case META_LINETO:
497 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
498 break;
500 case META_MOVETO:
501 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
502 break;
504 case META_EXCLUDECLIPRECT:
505 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
506 *(mr->rdParam + 1), *(mr->rdParam));
507 break;
509 case META_INTERSECTCLIPRECT:
510 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
511 *(mr->rdParam + 1), *(mr->rdParam));
512 break;
514 case META_ARC:
515 Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
516 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
517 *(mr->rdParam + 1), *(mr->rdParam));
518 break;
520 case META_ELLIPSE:
521 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
522 *(mr->rdParam + 1), *(mr->rdParam));
523 break;
525 case META_FLOODFILL:
526 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
527 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
528 break;
530 case META_PIE:
531 Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
532 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
533 *(mr->rdParam + 1), *(mr->rdParam));
534 break;
536 case META_RECTANGLE:
537 Rectangle(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
538 *(mr->rdParam + 1), *(mr->rdParam));
539 break;
541 case META_ROUNDRECT:
542 RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
543 *(mr->rdParam + 3), *(mr->rdParam + 2),
544 *(mr->rdParam + 1), *(mr->rdParam));
545 break;
547 case META_PATBLT:
548 PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
549 *(mr->rdParam + 3), *(mr->rdParam + 2),
550 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
551 break;
553 case META_SAVEDC:
554 SaveDC(hdc);
555 break;
557 case META_SETPIXEL:
558 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
559 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
560 break;
562 case META_OFFSETCLIPRGN:
563 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
564 break;
566 case META_TEXTOUT:
567 s1 = *(mr->rdParam);
568 TextOut16(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
569 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
570 (char *)(mr->rdParam + 1), s1);
571 break;
573 case META_POLYGON:
574 Polygon16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
575 break;
577 case META_POLYPOLYGON:
578 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParam + *(mr->rdParam) + 1),
579 (LPINT16)(mr->rdParam + 1), *(mr->rdParam));
580 break;
582 case META_POLYLINE:
583 Polyline16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
584 break;
586 case META_RESTOREDC:
587 RestoreDC(hdc, *(mr->rdParam));
588 break;
590 case META_SELECTOBJECT:
591 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
592 break;
594 case META_CHORD:
595 Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
596 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
597 *(mr->rdParam + 1), *(mr->rdParam));
598 break;
600 case META_CREATEPATTERNBRUSH:
601 switch (*(mr->rdParam))
603 case BS_PATTERN:
604 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
605 MF_AddHandle(ht, nHandles,
606 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
607 infohdr->biHeight,
608 infohdr->biPlanes,
609 infohdr->biBitCount,
610 (LPSTR)(mr->rdParam +
611 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
612 break;
614 case BS_DIBPATTERN:
615 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
616 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
617 ptr = GlobalLock16(hndl);
618 memcpy(ptr, mr->rdParam + 2, s1);
619 GlobalUnlock16(hndl);
620 MF_AddHandle(ht, nHandles,
621 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
622 GlobalFree16(hndl);
624 break;
626 case META_CREATEPENINDIRECT:
627 MF_AddHandle(ht, nHandles,
628 CreatePenIndirect((LOGPEN16 *)(&(mr->rdParam))));
629 break;
631 case META_CREATEFONTINDIRECT:
632 MF_AddHandle(ht, nHandles,
633 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParam))));
634 break;
636 case META_CREATEBRUSHINDIRECT:
637 MF_AddHandle(ht, nHandles,
638 CreateBrushIndirect((LOGBRUSH16 *)(&(mr->rdParam))));
639 break;
641 /* W. Magro: Some new metafile operations. Not all debugged. */
642 case META_CREATEPALETTE:
643 MF_AddHandle(ht, nHandles,
644 CreatePalette((LPLOGPALETTE)mr->rdParam));
645 break;
647 case META_SETTEXTALIGN:
648 SetTextAlign(hdc, *(mr->rdParam));
649 break;
651 case META_SELECTPALETTE:
652 SelectPalette(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
653 break;
655 case META_SETMAPPERFLAGS:
656 SetMapperFlags(hdc, *(mr->rdParam));
657 break;
659 case META_REALIZEPALETTE:
660 RealizePalette(hdc);
661 break;
663 case META_ESCAPE:
664 dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
665 break;
667 /* --- Begin of fixed or new metafile operations. July 1996 ----*/
668 case META_EXTTEXTOUT:
670 LPINT16 dxx;
671 s1=mr->rdParam[2]; /* String length */
672 if (mr->rdSize-(s1+1))
673 dxx=&mr->rdParam[8+(s1+1)/2]; /* start of array */
674 else
675 dxx=NULL; /* NO array present */
677 ExtTextOut16( hdc, mr->rdParam[1], /* X position */
678 mr->rdParam[0], /* Y position */
679 mr->rdParam[3], /* options */
680 (LPRECT16) &mr->rdParam[4], /* rectangle */
681 (char *)(mr->rdParam + 8), /* string */
682 s1, dxx); /* length, dx array */
683 if (dxx)
684 dprintf_metafile(stddeb,"EXTTEXTOUT len: %ld (%hd %hd) [%s].\n",
685 mr->rdSize,dxx[0],dxx[1],(char*) &(mr->rdParam[8]) );
687 break;
689 case META_STRETCHDIB:
691 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]);
692 LPSTR bits = MF_GetDIBitsPointer(info);
693 if (bits)
694 StretchDIBits(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
695 mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
696 mr->rdParam[4],mr->rdParam[3],bits,info,
697 mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1]));
699 break;
701 case META_DIBSTRETCHBLT:
703 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]);
704 LPSTR bits = MF_GetDIBitsPointer(info);
705 if (bits)
706 StretchDIBits(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
707 mr->rdParam[6],mr->rdParam[5],mr->rdParam[4],
708 mr->rdParam[3],mr->rdParam[2],bits,info,
709 DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
711 break;
713 case META_STRETCHBLT:
715 HDC hdcSrc=CreateCompatibleDC(hdc);
716 HBITMAP16 hbitmap=CreateBitmap(mr->rdParam[10], /*Width */
717 mr->rdParam[11], /*Height*/
718 mr->rdParam[13], /*Planes*/
719 mr->rdParam[14], /*BitsPixel*/
720 (LPSTR)&mr->rdParam[15]); /*bits*/
721 SelectObject(hdcSrc,hbitmap);
722 StretchBlt(hdc,mr->rdParam[9],mr->rdParam[8],
723 mr->rdParam[7],mr->rdParam[6],
724 hdcSrc,mr->rdParam[5],mr->rdParam[4],
725 mr->rdParam[3],mr->rdParam[2],
726 MAKELONG(mr->rdParam[0],mr->rdParam[1]));
727 DeleteDC(hdcSrc);
729 break;
731 case META_BITBLT: /* <-- not yet debugged */
733 HDC hdcSrc=CreateCompatibleDC(hdc);
734 HBITMAP16 hbitmap=CreateBitmap(mr->rdParam[7]/*Width */,mr->rdParam[8]/*Height*/,
735 mr->rdParam[10]/*Planes*/,mr->rdParam[11]/*BitsPixel*/,
736 (LPSTR)&mr->rdParam[12]/*bits*/);
737 SelectObject(hdcSrc,hbitmap);
738 BitBlt(hdc,mr->rdParam[6],mr->rdParam[5],
739 mr->rdParam[4],mr->rdParam[3],
740 hdcSrc,
741 mr->rdParam[2],mr->rdParam[1],
742 MAKELONG(0,mr->rdParam[0]));
743 DeleteDC(hdcSrc);
745 break;
747 default:
748 fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
749 mr->rdFunction);
754 /******************************************************************
755 * GetMetaFileBits by William Magro, 19 Sep 1995
757 * Trade in a meta file object handle for a handle to the meta file memory
760 HANDLE GetMetaFileBits(HMETAFILE16 hmf)
762 dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hmf);
764 return hmf;
767 /******************************************************************
768 * SetMetaFileBits by William Magro, 19 Sep 1995
770 * Trade in a meta file memory handle for a handle to a meta file object
773 HMETAFILE16 SetMetaFileBits(HANDLE hMem)
775 dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hMem);
777 return hMem;
780 /******************************************************************
781 * MF_WriteRecord
784 HMETAFILE16 MF_WriteRecord(HMETAFILE16 hmf, METARECORD *mr, WORD rlen)
786 DWORD len;
787 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
789 if (mh->mtType == 0) /* memory based metafile */
791 len = mh->mtSize * 2 + rlen;
792 GlobalUnlock16(hmf);
793 hmf = GlobalReAlloc16(hmf, len, GMEM_MOVEABLE); /* hmf can change */
794 mh = (METAHEADER *)GlobalLock16(hmf);
795 memcpy((WORD *)mh + mh->mtSize, mr, rlen);
797 else if (mh->mtType == 1) /* disk based metafile */
799 dprintf_metafile(stddeb,"Writing record to disk\n");
800 if (_lwrite(mh->mtNoParameters, (char *)mr, rlen) == -1)
802 GlobalUnlock16(hmf);
803 return 0;
806 else
808 GlobalUnlock16(hmf);
809 return 0;
812 mh->mtSize += rlen / 2;
813 mh->mtMaxRecord = MAX(mh->mtMaxRecord, rlen / 2);
814 GlobalUnlock16(hmf);
815 return hmf;
819 /******************************************************************
820 * MF_AddHandle
822 * Add a handle to an external handle table and return the index
825 int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HANDLE hobj)
827 int i;
829 for (i = 0; i < htlen; i++)
831 if (*(ht->objectHandle + i) == 0)
833 *(ht->objectHandle + i) = hobj;
834 return i;
837 return -1;
841 /******************************************************************
842 * MF_AddHandleInternal
844 * Add a handle to the internal handle table and return the index
847 int MF_AddHandleInternal(HANDLE hobj)
849 int i;
850 HANDLETABLE16 *ht = (HANDLETABLE16 *)GlobalLock16(hHT);
852 for (i = 0; i < HTLen; i++)
854 if (*(ht->objectHandle + i) == 0)
856 *(ht->objectHandle + i) = hobj;
857 GlobalUnlock16(hHT);
858 return i;
861 GlobalUnlock16(hHT);
862 if (!(hHT = GlobalReAlloc16(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
863 return -1;
864 HTLen += HTINCR;
865 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
866 *(ht->objectHandle + i) = hobj;
867 GlobalUnlock16(hHT);
868 return i;
872 /******************************************************************
873 * MF_MetaParam0
876 BOOL MF_MetaParam0(DC *dc, short func)
878 char buffer[8];
879 METARECORD *mr = (METARECORD *)&buffer;
880 HMETAFILE16 handle;
882 mr->rdSize = 3;
883 mr->rdFunction = func;
884 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
885 dc->w.hMetaFile = handle;
887 return handle;
891 /******************************************************************
892 * MF_MetaParam1
894 BOOL MF_MetaParam1(DC *dc, short func, short param1)
896 char buffer[8];
897 METARECORD *mr = (METARECORD *)&buffer;
898 HMETAFILE16 handle;
900 mr->rdSize = 4;
901 mr->rdFunction = func;
902 *(mr->rdParam) = param1;
903 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
904 dc->w.hMetaFile = handle;
906 return handle;
910 /******************************************************************
911 * MF_MetaParam2
913 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
915 char buffer[10];
916 METARECORD *mr = (METARECORD *)&buffer;
917 HMETAFILE16 handle;
919 mr->rdSize = 5;
920 mr->rdFunction = func;
921 *(mr->rdParam) = param2;
922 *(mr->rdParam + 1) = param1;
923 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
924 dc->w.hMetaFile = handle;
926 return handle;
930 /******************************************************************
931 * MF_MetaParam4
934 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
935 short param3, short param4)
937 char buffer[14];
938 METARECORD *mr = (METARECORD *)&buffer;
939 HMETAFILE16 handle;
941 mr->rdSize = 7;
942 mr->rdFunction = func;
943 *(mr->rdParam) = param4;
944 *(mr->rdParam + 1) = param3;
945 *(mr->rdParam + 2) = param2;
946 *(mr->rdParam + 3) = param1;
947 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
948 dc->w.hMetaFile = handle;
950 return handle;
954 /******************************************************************
955 * MF_MetaParam6
958 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
959 short param3, short param4, short param5, short param6)
961 char buffer[18];
962 METARECORD *mr = (METARECORD *)&buffer;
963 HMETAFILE16 handle;
965 mr->rdSize = 9;
966 mr->rdFunction = func;
967 *(mr->rdParam) = param6;
968 *(mr->rdParam + 1) = param5;
969 *(mr->rdParam + 2) = param4;
970 *(mr->rdParam + 3) = param3;
971 *(mr->rdParam + 4) = param2;
972 *(mr->rdParam + 5) = param1;
973 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
974 dc->w.hMetaFile = handle;
976 return handle;
980 /******************************************************************
981 * MF_MetaParam8
983 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
984 short param3, short param4, short param5,
985 short param6, short param7, short param8)
987 char buffer[22];
988 METARECORD *mr = (METARECORD *)&buffer;
989 HMETAFILE16 handle;
991 mr->rdSize = 11;
992 mr->rdFunction = func;
993 *(mr->rdParam) = param8;
994 *(mr->rdParam + 1) = param7;
995 *(mr->rdParam + 2) = param6;
996 *(mr->rdParam + 3) = param5;
997 *(mr->rdParam + 4) = param4;
998 *(mr->rdParam + 5) = param3;
999 *(mr->rdParam + 6) = param2;
1000 *(mr->rdParam + 7) = param1;
1001 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1002 dc->w.hMetaFile = handle;
1004 return handle;
1008 /******************************************************************
1009 * MF_CreateBrushIndirect
1012 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH16 *logbrush)
1014 int index;
1015 HMETAFILE16 handle;
1016 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH16)];
1017 METARECORD *mr = (METARECORD *)&buffer;
1018 METAHEADER *mh;
1020 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2) / 2;
1021 mr->rdFunction = META_CREATEBRUSHINDIRECT;
1022 memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH16));
1023 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile,
1024 mr, mr->rdSize * 2)))
1025 return FALSE;
1027 mr->rdSize = sizeof(METARECORD) / 2;
1028 mr->rdFunction = META_SELECTOBJECT;
1030 if ((index = MF_AddHandleInternal(hBrush)) == -1)
1031 return FALSE;
1033 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1034 *(mr->rdParam) = index;
1035 if (index >= mh->mtNoObjects)
1036 mh->mtNoObjects++;
1038 GlobalUnlock16(dc->w.hMetaFile);
1039 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1040 dc->w.hMetaFile = handle;
1042 return handle;
1046 /******************************************************************
1047 * MF_CreatePatternBrush
1050 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH16 *logbrush)
1052 DWORD len, bmSize, biSize;
1053 HANDLE hmr;
1054 METARECORD *mr;
1055 BITMAPOBJ *bmp;
1056 BITMAPINFO *info;
1057 BITMAPINFOHEADER *infohdr;
1058 int index;
1059 HMETAFILE16 handle;
1060 char buffer[sizeof(METARECORD)];
1061 METAHEADER *mh;
1063 switch (logbrush->lbStyle)
1065 case BS_PATTERN:
1066 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HANDLE)logbrush->lbHatch, BITMAP_MAGIC);
1067 if (!bmp) return FALSE;
1068 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
1069 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1070 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1071 return FALSE;
1072 mr = (METARECORD *)GlobalLock16(hmr);
1073 memset(mr, 0, len);
1074 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1075 mr->rdSize = len / 2;
1076 *(mr->rdParam) = logbrush->lbStyle;
1077 *(mr->rdParam + 1) = DIB_RGB_COLORS;
1078 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
1079 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1080 infohdr->biWidth = bmp->bitmap.bmWidth;
1081 infohdr->biHeight = bmp->bitmap.bmHeight;
1082 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1083 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1084 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1085 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1086 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1087 break;
1089 case BS_DIBPATTERN:
1090 info = (BITMAPINFO *)GlobalLock16((HANDLE)logbrush->lbHatch);
1091 if (info->bmiHeader.biCompression)
1092 bmSize = info->bmiHeader.biSizeImage;
1093 else
1094 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1095 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1096 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1097 len = sizeof(METARECORD) + biSize + bmSize + 2;
1098 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1099 return FALSE;
1100 mr = (METARECORD *)GlobalLock16(hmr);
1101 memset(mr, 0, len);
1102 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1103 mr->rdSize = len / 2;
1104 *(mr->rdParam) = logbrush->lbStyle;
1105 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
1106 memcpy(mr->rdParam + 2, info, biSize + bmSize);
1107 break;
1108 default:
1109 return FALSE;
1111 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, len)))
1113 GlobalFree16(hmr);
1114 return FALSE;
1117 GlobalFree16(hmr);
1119 mr = (METARECORD *)&buffer;
1120 mr->rdSize = sizeof(METARECORD) / 2;
1121 mr->rdFunction = META_SELECTOBJECT;
1122 if ((index = MF_AddHandleInternal(hBrush)) == -1)
1123 return FALSE;
1125 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1126 *(mr->rdParam) = index;
1127 if (index >= mh->mtNoObjects)
1128 mh->mtNoObjects++;
1129 GlobalUnlock16(dc->w.hMetaFile);
1130 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1131 dc->w.hMetaFile = handle;
1133 return handle;
1137 /******************************************************************
1138 * MF_CreatePenIndirect
1141 BOOL MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1143 int index;
1144 HMETAFILE16 handle;
1145 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN16)];
1146 METARECORD *mr = (METARECORD *)&buffer;
1147 METAHEADER *mh;
1149 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN16) - 2) / 2;
1150 mr->rdFunction = META_CREATEPENINDIRECT;
1151 memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN16));
1152 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr,
1153 mr->rdSize * 2)))
1154 return FALSE;
1156 mr->rdSize = sizeof(METARECORD) / 2;
1157 mr->rdFunction = META_SELECTOBJECT;
1159 if ((index = MF_AddHandleInternal(hPen)) == -1)
1160 return FALSE;
1162 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1163 *(mr->rdParam) = index;
1164 if (index >= mh->mtNoObjects)
1165 mh->mtNoObjects++;
1166 GlobalUnlock16(dc->w.hMetaFile);
1167 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1168 dc->w.hMetaFile = handle;
1170 return handle;
1174 /******************************************************************
1175 * MF_CreateFontIndirect
1178 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT16 *logfont)
1180 int index;
1181 HMETAFILE16 handle;
1182 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1183 METARECORD *mr = (METARECORD *)&buffer;
1184 METAHEADER *mh;
1186 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1187 mr->rdFunction = META_CREATEFONTINDIRECT;
1188 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT16));
1189 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr,
1190 mr->rdSize * 2)))
1191 return FALSE;
1193 mr->rdSize = sizeof(METARECORD) / 2;
1194 mr->rdFunction = META_SELECTOBJECT;
1196 if ((index = MF_AddHandleInternal(hFont)) == -1)
1197 return FALSE;
1199 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1200 *(mr->rdParam) = index;
1201 if (index >= mh->mtNoObjects)
1202 mh->mtNoObjects++;
1203 GlobalUnlock16(dc->w.hMetaFile);
1204 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1205 dc->w.hMetaFile = handle;
1207 return handle;
1211 /******************************************************************
1212 * MF_TextOut
1214 BOOL MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1216 HMETAFILE16 handle;
1217 DWORD len;
1218 HANDLE hmr;
1219 METARECORD *mr;
1221 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1222 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1223 return FALSE;
1224 mr = (METARECORD *)GlobalLock16(hmr);
1225 memset(mr, 0, len);
1227 mr->rdSize = len / 2;
1228 mr->rdFunction = META_TEXTOUT;
1229 *(mr->rdParam) = count;
1230 memcpy(mr->rdParam + 1, str, count);
1231 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1232 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1233 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1234 dc->w.hMetaFile = handle;
1235 GlobalFree16(hmr);
1236 return handle;
1239 /******************************************************************
1240 * MF_ExtTextOut
1242 BOOL MF_ExtTextOut(DC *dc, short x, short y, UINT16 flags, const RECT16 *rect,
1243 LPCSTR str, short count, const INT16 *lpDx)
1245 HMETAFILE16 handle;
1246 DWORD len;
1247 HANDLE hmr;
1248 METARECORD *mr;
1250 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4 + sizeof(RECT16);
1251 if (lpDx)
1252 len+=count*sizeof(INT16);
1253 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1254 return FALSE;
1255 mr = (METARECORD *)GlobalLock16(hmr);
1256 memset(mr, 0, len);
1258 mr->rdSize = len / 2;
1259 mr->rdFunction = META_EXTTEXTOUT;
1260 *(mr->rdParam) = y;
1261 *(mr->rdParam + 1) = x;
1262 *(mr->rdParam + 2) = count;
1263 *(mr->rdParam + 3) = flags;
1264 if (rect) memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
1265 memcpy(mr->rdParam + 8, str, count);
1266 if (lpDx)
1267 memcpy(mr->rdParam + 8+ ((count + 1) >> 1),lpDx,count*sizeof(INT16));
1268 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1269 dc->w.hMetaFile = handle;
1270 GlobalFree16(hmr);
1271 return handle;
1274 /******************************************************************
1275 * MF_MetaPoly - implements Polygon and Polyline
1277 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1279 HMETAFILE16 handle;
1280 DWORD len;
1281 HANDLE hmr;
1282 METARECORD *mr;
1284 len = sizeof(METARECORD) + (count * 4);
1285 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1286 return FALSE;
1287 mr = (METARECORD *)GlobalLock16(hmr);
1288 memset(mr, 0, len);
1290 mr->rdSize = len / 2;
1291 mr->rdFunction = func;
1292 *(mr->rdParam) = count;
1293 memcpy(mr->rdParam + 1, pt, count * 4);
1294 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1295 dc->w.hMetaFile = handle;
1296 GlobalFree16(hmr);
1297 return handle;
1301 /******************************************************************
1302 * MF_BitBlt
1304 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1305 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
1307 HMETAFILE16 handle;
1308 DWORD len;
1309 HANDLE hmr;
1310 METARECORD *mr;
1311 DC *dcSrc;
1312 BITMAP16 BM;
1314 if (!(dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC ))) return 0;
1315 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1316 len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1317 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1318 return FALSE;
1319 mr = (METARECORD *)GlobalLock16(hmr);
1320 mr->rdFunction = META_BITBLT;
1321 *(mr->rdParam + 7) = BM.bmWidth;
1322 *(mr->rdParam + 8) = BM.bmHeight;
1323 *(mr->rdParam + 9) = BM.bmWidthBytes;
1324 *(mr->rdParam +10) = BM.bmPlanes;
1325 *(mr->rdParam +11) = BM.bmBitsPixel;
1326 dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1327 if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,mr->rdParam +12))
1329 mr->rdSize = len / sizeof(INT16);
1330 *(mr->rdParam) = HIWORD(rop);
1331 *(mr->rdParam + 1) = ySrc;
1332 *(mr->rdParam + 2) = xSrc;
1333 *(mr->rdParam + 3) = height;
1334 *(mr->rdParam + 4) = width;
1335 *(mr->rdParam + 5) = yDest;
1336 *(mr->rdParam + 6) = xDest;
1337 handle = MF_WriteRecord(dcDest->w.hMetaFile, mr, mr->rdSize * 2);
1339 else
1340 handle = 0;
1341 dcDest->w.hMetaFile = handle;
1342 GlobalFree16(hmr);
1343 return handle;
1347 /**********************************************************************
1348 * MF_StretchBlt
1349 * this function contains TWO ways for procesing StretchBlt in metafiles,
1350 * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT
1351 * via #define STRETCH_VIA_DIB
1353 #define STRETCH_VIA_DIB
1354 #undef STRETCH_VIA_DIB
1355 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1356 short heightDest, HDC hdcSrc, short xSrc, short ySrc,
1357 short widthSrc, short heightSrc, DWORD rop)
1359 HMETAFILE16 handle;
1360 DWORD len;
1361 HANDLE hmr;
1362 METARECORD *mr;
1363 DC *dcSrc;
1364 BITMAP16 BM;
1365 #ifdef STRETCH_VIA_DIB
1366 LPBITMAPINFOHEADER lpBMI;
1367 WORD nBPP;
1368 #endif
1369 if (!(dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC ))) return 0;
1370 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1371 #ifdef STRETCH_VIA_DIB
1372 nBPP = BM.bmPlanes * BM.bmBitsPixel;
1373 len = sizeof(METARECORD) + 10 * sizeof(INT16)
1374 + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
1375 + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1376 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1377 return FALSE;
1378 mr = (METARECORD *)GlobalLock16(hmr);
1379 mr->rdFunction = META_DIBSTRETCHBLT;
1380 lpBMI=(LPBITMAPINFOHEADER)(mr->rdParam+10);
1381 lpBMI->biSize = sizeof(BITMAPINFOHEADER);
1382 lpBMI->biWidth = BM.bmWidth;
1383 lpBMI->biHeight = BM.bmHeight;
1384 lpBMI->biPlanes = 1;
1385 lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */
1386 lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0;
1387 lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1388 lpBMI->biCompression = BI_RGB;
1389 lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(hdcSrc,LOGPIXELSX),3937,100);
1390 lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(hdcSrc,LOGPIXELSY),3937,100);
1391 lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */
1393 dprintf_metafile(stddeb,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n",
1394 len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1395 if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT)lpBMI->biHeight,
1396 MF_GetDIBitsPointer((LPBITMAPINFO)lpBMI), /* DIB bits */
1397 (LPBITMAPINFO)lpBMI,DIB_RGB_COLORS)) /* DIB info structure */
1398 #else
1399 len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1400 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1401 return FALSE;
1402 mr = (METARECORD *)GlobalLock16(hmr);
1403 mr->rdFunction = META_STRETCHBLT;
1404 *(mr->rdParam +10) = BM.bmWidth;
1405 *(mr->rdParam +11) = BM.bmHeight;
1406 *(mr->rdParam +12) = BM.bmWidthBytes;
1407 *(mr->rdParam +13) = BM.bmPlanes;
1408 *(mr->rdParam +14) = BM.bmBitsPixel;
1409 dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1410 if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,mr->rdParam +15))
1411 #endif
1413 mr->rdSize = len / sizeof(INT16);
1414 *(mr->rdParam) = LOWORD(rop);
1415 *(mr->rdParam + 1) = HIWORD(rop);
1416 *(mr->rdParam + 2) = heightSrc;
1417 *(mr->rdParam + 3) = widthSrc;
1418 *(mr->rdParam + 4) = ySrc;
1419 *(mr->rdParam + 5) = xSrc;
1420 *(mr->rdParam + 6) = heightDest;
1421 *(mr->rdParam + 7) = widthDest;
1422 *(mr->rdParam + 8) = yDest;
1423 *(mr->rdParam + 9) = xDest;
1424 handle = MF_WriteRecord(dcDest->w.hMetaFile, mr, mr->rdSize * 2);
1426 else
1427 handle = 0;
1428 dcDest->w.hMetaFile = handle;
1429 GlobalFree16(hmr);
1430 return handle;