Release 960928
[wine/multimedia.git] / objects / metafile.c
blob3d38d3aedd4ce649b07f0ac233a718488055dcd2
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 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 /******************************************************************
21 * GetMetafile GDI.124 By Kenny MacDonald 30 Nov 94
24 HMETAFILE16 GetMetaFile(LPSTR lpFilename)
26 HMETAFILE16 hmf;
27 METAHEADER *mh;
28 HFILE hFile;
29 DWORD size;
31 dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
33 if (!lpFilename)
34 return 0;
36 hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
37 mh = (METAHEADER *)GlobalLock16(hmf);
39 if (!mh) {
40 GlobalFree16(hmf);
41 return 0;
44 if ((hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) {
45 GlobalFree16(hmf);
46 return 0;
49 if (_lread32(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
50 GlobalFree16(hmf);
51 return 0;
54 size = mh->mtSize * 2; /* alloc memory for whole metafile */
55 GlobalUnlock16(hmf);
56 hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
57 mh = (METAHEADER *)GlobalLock16(hmf);
59 if (!mh) {
60 GlobalFree16(hmf);
61 return 0;
64 if (_lread32(hFile, (char*)mh + mh->mtHeaderSize * 2,
65 size - mh->mtHeaderSize * 2) == HFILE_ERROR) {
66 GlobalFree16(hmf);
67 return 0;
70 _lclose(hFile);
72 if (mh->mtType != 1) {
73 GlobalFree16(hmf);
74 return 0;
77 GlobalUnlock16(hmf);
78 return hmf;
82 /******************************************************************
83 * CreateMetafile GDI.125
86 HANDLE CreateMetaFile(LPCSTR lpFilename)
88 DC *dc;
89 HANDLE handle;
90 METAHEADER *mh;
91 HFILE hFile;
93 dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
95 handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
97 if (!handle)
98 return 0;
100 dc = (DC *)GDI_HEAP_LIN_ADDR(handle);
102 if (!(dc->w.hMetaFile = GlobalAlloc16(GMEM_MOVEABLE, sizeof(METAHEADER)))) {
103 GDI_FreeObject(handle);
104 return 0;
106 if (!(dc->w.hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
107 sizeof(HANDLETABLE16) * HTINCR))) {
108 GlobalFree16(dc->w.hMetaFile);
109 GDI_FreeObject(handle);
110 return 0;
112 dc->w.HTLen = HTINCR;
113 dc->w.bitsPerPixel = screenDepth;
114 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
116 mh->mtHeaderSize = MFHEADERSIZE / 2;
117 mh->mtVersion = MFVERSION;
118 mh->mtSize = MFHEADERSIZE / 2;
119 mh->mtNoObjects = 0;
120 mh->mtMaxRecord = 0;
121 mh->mtNoParameters = 0;
123 if (lpFilename) /* disk based metafile */
125 mh->mtType = 1; /* disk */
126 hFile = _lcreat(lpFilename, 0);
127 if (_lwrite32(hFile, (char *)mh, MFHEADERSIZE) == -1)
129 GlobalFree16(dc->w.hHT);
130 GlobalFree16(dc->w.hMetaFile);
131 GDI_FreeObject(handle);
132 return 0;
134 mh->mtNoParameters = hFile; /* store file descriptor here */
135 /* windows probably uses this too*/
137 else /* memory based metafile */
138 mh->mtType = 0;
140 GlobalUnlock16(dc->w.hMetaFile);
141 dprintf_metafile(stddeb,"CreateMetaFile: returning %04x\n", handle);
142 return handle;
145 /******************************************************************
146 * CopyMetafile GDI.151 Niels de Carpentier, April 1996
149 HMETAFILE16 CopyMetaFile(HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
151 HMETAFILE16 handle = 0;
152 METAHEADER *mh;
153 METAHEADER *mh2;
154 HFILE hFile;
156 dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename);
158 mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
160 if (!mh)
161 return 0;
163 if (lpFilename) /* disk based metafile */
165 int i,j;
166 hFile = _lcreat(lpFilename, 0);
167 j=mh->mtType;
168 mh->mtType=1; /* disk file version stores 1 here */
169 i=_lwrite32(hFile, (char *)mh, mh->mtSize * 2) ;
170 mh->mtType=j; /* restore old value [0 or 1] */
171 _lclose(hFile);
172 if (i == -1)
173 return 0;
175 else /* memory based metafile */
177 handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
178 mh2 = (METAHEADER *)GlobalLock16(handle);
179 memcpy(mh2,mh, mh->mtSize * 2);
180 GlobalUnlock16(handle);
183 return handle;
186 /******************************************************************
187 * IsValidMetaFile (GDI.410)
188 * (This is not exactly what windows does, see "Undoc Win")
191 BOOL IsValidMetaFile(HMETAFILE16 hmf)
193 BOOL resu=FALSE;
194 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
195 if (mh) {
196 if (mh->mtType == 1 || mh->mtType == 0)
197 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
198 if (mh->mtVersion == MFVERSION)
199 resu=TRUE;
200 GlobalUnlock16(hmf);
202 dprintf_metafile(stddeb,"IsValidMetaFile %x => %d\n",hmf,resu);
203 return resu;
207 /******************************************************************
208 * CloseMetafile GDI.126
211 HMETAFILE16 CloseMetaFile(HDC hdc)
213 DC *dc;
214 METAHEADER *mh;
215 HMETAFILE16 hmf;
216 HFILE hFile;
218 dprintf_metafile(stddeb,"CloseMetaFile\n");
220 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
222 if (!dc)
223 return 0;
225 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
227 /* Construct the end of metafile record - this is documented
228 * in SDK Knowledgebase Q99334.
231 if (!MF_MetaParam0(dc, META_EOF))
233 GlobalFree16(dc->w.hHT);
234 GlobalFree16(dc->w.hMetaFile);
235 GDI_FreeObject(hdc);
236 return 0;
239 if (mh->mtType == 1) /* disk based metafile */
241 hFile = mh->mtNoParameters;
242 mh->mtNoParameters = 0;
243 if (_llseek(hFile, 0L, 0) == -1)
245 GlobalFree16(dc->w.hHT);
246 GlobalFree16(dc->w.hMetaFile);
247 GDI_FreeObject(hdc);
248 return 0;
250 if (_lwrite32(hFile, (char *)mh, MFHEADERSIZE) == -1)
252 GlobalFree16(dc->w.hHT);
253 GlobalFree16(dc->w.hMetaFile);
254 GDI_FreeObject(hdc);
255 return 0;
257 _lclose(hFile);
260 GlobalFree16(dc->w.hHT);
261 hmf = dc->w.hMetaFile;
262 GlobalUnlock16(hmf);
263 GDI_FreeObject(hdc);
264 return hmf;
268 /******************************************************************
269 * DeleteMetafile GDI.127
272 BOOL DeleteMetaFile(HMETAFILE16 hmf)
274 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
276 if (!mh)
277 return FALSE;
279 GlobalFree16(hmf);
280 return TRUE;
284 /******************************************************************
285 * PlayMetafile GDI.123
288 BOOL PlayMetaFile(HDC hdc, HMETAFILE16 hmf)
290 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
291 METARECORD *mr;
292 HANDLETABLE16 *ht;
293 HGLOBAL16 hHT;
294 int offset = 0;
295 WORD i;
297 dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf);
299 /* create the handle table */
300 hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
301 sizeof(HANDLETABLE16) * mh->mtNoObjects);
302 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
304 /* loop through metafile playing records */
305 offset = mh->mtHeaderSize * 2;
306 while (offset < mh->mtSize * 2)
308 mr = (METARECORD *)((char *)mh + offset);
309 dprintf_metafile(stddeb,"offset = %04x size = %08lx function = %04x\n",
310 offset,mr->rdSize,mr->rdFunction);
311 offset += mr->rdSize * 2;
312 PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
315 /* free objects in handle table */
316 for(i = 0; i < mh->mtNoObjects; i++)
317 if(*(ht->objectHandle + i) != 0)
318 DeleteObject(*(ht->objectHandle + i));
320 /* free handle table */
321 GlobalFree16(hHT);
323 return TRUE;
327 /******************************************************************
328 * EnumMetafile GDI.175
329 * Niels de carpentier, april 1996
332 BOOL EnumMetaFile(HDC hdc, HMETAFILE16 hmf, MFENUMPROC16 lpEnumFunc,LPARAM lpData)
334 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
335 METARECORD *mr;
336 HGLOBAL16 hHT;
337 SEGPTR ht, spRecord;
338 int offset = 0;
340 dprintf_metafile(stddeb,"EnumMetaFile(%04x, %04x, %08lx, %08lx)\n",
341 hdc, hmf, (DWORD)lpEnumFunc, lpData);
343 /* create the handle table */
345 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
346 sizeof(HANDLETABLE16) * mh->mtNoObjects);
347 ht = WIN16_GlobalLock16(hHT);
349 offset = mh->mtHeaderSize * 2;
351 /* loop through metafile records */
353 spRecord = WIN16_GlobalLock16(hmf);
354 while (offset < (mh->mtSize * 2))
356 mr = (METARECORD *)((char *)mh + offset);
357 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)ht,
358 (METARECORD *)((UINT32)spRecord + offset),
359 mh->mtNoObjects, (LONG)lpData))
360 break;
362 offset += (mr->rdSize * 2);
365 /* free handle table */
366 GlobalFree16(hHT);
368 return TRUE;
371 /*******************************************************************
372 * MF_GetDIBitsPointer [internal helper for e.g. PlayMetaFileRecord]
374 * Returns offset to DIB bits or 0 if error
375 * (perhaps should be moved to (objects/dib.c ?)
377 static LPSTR MF_GetDIBitsPointer(LPBITMAPINFO info)
379 int offset;
380 if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
382 if (info->bmiHeader.biClrUsed)
384 if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
385 offset = info->bmiHeader.biClrUsed * 4;
386 else
387 offset = (1 << info->bmiHeader.biBitCount) * 4;
389 else
390 offset = (1 << info->bmiHeader.biBitCount) * 4;
392 else if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
394 if (info->bmiHeader.biClrUsed)
396 if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
397 offset = info->bmiHeader.biClrUsed * 3;
398 else
399 offset = (1 << info->bmiHeader.biBitCount) * 3;
401 else
402 offset = (1 << info->bmiHeader.biBitCount) * 3;
404 else
406 fprintf(stderr,"Unknown size for BITMAPHEADER in MetaFile!\n");
407 return NULL;
409 return (LPSTR)info + info->bmiHeader.biSize + offset;
413 /******************************************************************
414 * PlayMetaFileRecord GDI.176
417 void PlayMetaFileRecord(HDC hdc, HANDLETABLE16 *ht, METARECORD *mr,
418 WORD nHandles)
420 short s1;
421 HANDLE hndl;
422 char *ptr;
423 BITMAPINFOHEADER *infohdr;
425 dprintf_metafile(stddeb,"PlayMetaFileRecord(%04x %08lx %08lx %04x)\n",
426 hdc,(LONG)ht, (LONG)mr, nHandles);
428 switch (mr->rdFunction)
430 case META_EOF:
431 break;
433 case META_DELETEOBJECT:
434 DeleteObject(*(ht->objectHandle + *(mr->rdParam)));
435 *(ht->objectHandle + *(mr->rdParam)) = 0;
436 break;
438 case META_SETBKCOLOR:
439 SetBkColor(hdc, *(mr->rdParam));
440 break;
442 case META_SETBKMODE:
443 SetBkMode(hdc, *(mr->rdParam));
444 break;
446 case META_SETMAPMODE:
447 SetMapMode(hdc, *(mr->rdParam));
448 break;
450 case META_SETROP2:
451 SetROP2(hdc, *(mr->rdParam));
452 break;
454 case META_SETRELABS:
455 SetRelAbs(hdc, *(mr->rdParam));
456 break;
458 case META_SETPOLYFILLMODE:
459 SetPolyFillMode(hdc, *(mr->rdParam));
460 break;
462 case META_SETSTRETCHBLTMODE:
463 SetStretchBltMode(hdc, *(mr->rdParam));
464 break;
466 case META_SETTEXTCOLOR:
467 SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
468 break;
470 case META_SETWINDOWORG:
471 SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
472 break;
474 case META_SETWINDOWEXT:
475 SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
476 break;
478 case META_SETVIEWPORTORG:
479 SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
480 break;
482 case META_SETVIEWPORTEXT:
483 SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
484 break;
486 case META_OFFSETWINDOWORG:
487 OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
488 break;
490 case META_SCALEWINDOWEXT:
491 ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
492 *(mr->rdParam + 1), *(mr->rdParam));
493 break;
495 case META_OFFSETVIEWPORTORG:
496 OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
497 break;
499 case META_SCALEVIEWPORTEXT:
500 ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
501 *(mr->rdParam + 1), *(mr->rdParam));
502 break;
504 case META_LINETO:
505 LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
506 break;
508 case META_MOVETO:
509 MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
510 break;
512 case META_EXCLUDECLIPRECT:
513 ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
514 *(mr->rdParam + 1), *(mr->rdParam));
515 break;
517 case META_INTERSECTCLIPRECT:
518 IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
519 *(mr->rdParam + 1), *(mr->rdParam));
520 break;
522 case META_ARC:
523 Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
524 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
525 *(mr->rdParam + 1), *(mr->rdParam));
526 break;
528 case META_ELLIPSE:
529 Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
530 *(mr->rdParam + 1), *(mr->rdParam));
531 break;
533 case META_FLOODFILL:
534 FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
535 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
536 break;
538 case META_PIE:
539 Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
540 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
541 *(mr->rdParam + 1), *(mr->rdParam));
542 break;
544 case META_RECTANGLE:
545 Rectangle(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
546 *(mr->rdParam + 1), *(mr->rdParam));
547 break;
549 case META_ROUNDRECT:
550 RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
551 *(mr->rdParam + 3), *(mr->rdParam + 2),
552 *(mr->rdParam + 1), *(mr->rdParam));
553 break;
555 case META_PATBLT:
556 PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
557 *(mr->rdParam + 3), *(mr->rdParam + 2),
558 MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
559 break;
561 case META_SAVEDC:
562 SaveDC(hdc);
563 break;
565 case META_SETPIXEL:
566 SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
567 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
568 break;
570 case META_OFFSETCLIPRGN:
571 OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
572 break;
574 case META_TEXTOUT:
575 s1 = *(mr->rdParam);
576 TextOut16(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
577 *(mr->rdParam + ((s1 + 1) >> 1) + 1),
578 (char *)(mr->rdParam + 1), s1);
579 break;
581 case META_POLYGON:
582 Polygon16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
583 break;
585 case META_POLYPOLYGON:
586 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParam + *(mr->rdParam) + 1),
587 (LPINT16)(mr->rdParam + 1), *(mr->rdParam));
588 break;
590 case META_POLYLINE:
591 Polyline16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
592 break;
594 case META_RESTOREDC:
595 RestoreDC(hdc, *(mr->rdParam));
596 break;
598 case META_SELECTOBJECT:
599 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
600 break;
602 case META_CHORD:
603 Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
604 *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
605 *(mr->rdParam + 1), *(mr->rdParam));
606 break;
608 case META_CREATEPATTERNBRUSH:
609 switch (*(mr->rdParam))
611 case BS_PATTERN:
612 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
613 MF_AddHandle(ht, nHandles,
614 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
615 infohdr->biHeight,
616 infohdr->biPlanes,
617 infohdr->biBitCount,
618 (LPSTR)(mr->rdParam +
619 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
620 break;
622 case BS_DIBPATTERN:
623 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
624 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
625 ptr = GlobalLock16(hndl);
626 memcpy(ptr, mr->rdParam + 2, s1);
627 GlobalUnlock16(hndl);
628 MF_AddHandle(ht, nHandles,
629 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
630 GlobalFree16(hndl);
632 break;
634 case META_CREATEPENINDIRECT:
635 MF_AddHandle(ht, nHandles,
636 CreatePenIndirect((LOGPEN16 *)(&(mr->rdParam))));
637 break;
639 case META_CREATEFONTINDIRECT:
640 MF_AddHandle(ht, nHandles,
641 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParam))));
642 break;
644 case META_CREATEBRUSHINDIRECT:
645 MF_AddHandle(ht, nHandles,
646 CreateBrushIndirect((LOGBRUSH16 *)(&(mr->rdParam))));
647 break;
649 /* W. Magro: Some new metafile operations. Not all debugged. */
650 case META_CREATEPALETTE:
651 MF_AddHandle(ht, nHandles,
652 CreatePalette((LPLOGPALETTE)mr->rdParam));
653 break;
655 case META_SETTEXTALIGN:
656 SetTextAlign(hdc, *(mr->rdParam));
657 break;
659 case META_SELECTPALETTE:
660 SelectPalette(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
661 break;
663 case META_SETMAPPERFLAGS:
664 SetMapperFlags(hdc, *(mr->rdParam));
665 break;
667 case META_REALIZEPALETTE:
668 RealizePalette(hdc);
669 break;
671 case META_ESCAPE:
672 dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
673 break;
675 /* --- Begin of fixed or new metafile operations. July 1996 ----*/
676 case META_EXTTEXTOUT:
678 LPINT16 dxx;
679 DWORD len;
681 s1 = mr->rdParam[2]; /* String length */
682 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
683 + sizeof(UINT16) + sizeof(RECT16);
684 if (mr->rdSize == len / 2)
685 dxx = NULL; /* No array present */
686 else if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
687 dxx = &mr->rdParam[8+(s1+1)/2]; /* start of array */
688 else {
689 fprintf(stderr,
690 "PlayMetaFileRecord ExtTextOut mr->rdSize = %08lx, count = %x\n",
691 mr->rdSize, s1);
692 dxx = NULL;
694 ExtTextOut16( hdc, mr->rdParam[1], /* X position */
695 mr->rdParam[0], /* Y position */
696 mr->rdParam[3], /* options */
697 (LPRECT16) &mr->rdParam[4], /* rectangle */
698 (char *)(mr->rdParam + 8), /* string */
699 s1, dxx); /* length, dx array */
700 if (dxx)
701 dprintf_metafile(stddeb,"EXTTEXTOUT len: %ld (%hd %hd) [%s].\n",
702 mr->rdSize,dxx[0],dxx[1],(char*) &(mr->rdParam[8]) );
704 break;
706 case META_STRETCHDIB:
708 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]);
709 LPSTR bits = MF_GetDIBitsPointer(info);
710 if (bits)
711 StretchDIBits(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
712 mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
713 mr->rdParam[4],mr->rdParam[3],bits,info,
714 mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1]));
716 break;
718 case META_DIBSTRETCHBLT:
720 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]);
721 LPSTR bits = MF_GetDIBitsPointer(info);
722 if (bits)
723 StretchDIBits(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
724 mr->rdParam[6],mr->rdParam[5],mr->rdParam[4],
725 mr->rdParam[3],mr->rdParam[2],bits,info,
726 DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
728 break;
730 case META_STRETCHBLT:
732 HDC hdcSrc=CreateCompatibleDC(hdc);
733 HBITMAP16 hbitmap=CreateBitmap(mr->rdParam[10], /*Width */
734 mr->rdParam[11], /*Height*/
735 mr->rdParam[13], /*Planes*/
736 mr->rdParam[14], /*BitsPixel*/
737 (LPSTR)&mr->rdParam[15]); /*bits*/
738 SelectObject(hdcSrc,hbitmap);
739 StretchBlt(hdc,mr->rdParam[9],mr->rdParam[8],
740 mr->rdParam[7],mr->rdParam[6],
741 hdcSrc,mr->rdParam[5],mr->rdParam[4],
742 mr->rdParam[3],mr->rdParam[2],
743 MAKELONG(mr->rdParam[0],mr->rdParam[1]));
744 DeleteDC(hdcSrc);
746 break;
748 case META_BITBLT: /* <-- not yet debugged */
750 HDC hdcSrc=CreateCompatibleDC(hdc);
751 HBITMAP16 hbitmap=CreateBitmap(mr->rdParam[7]/*Width */,mr->rdParam[8]/*Height*/,
752 mr->rdParam[10]/*Planes*/,mr->rdParam[11]/*BitsPixel*/,
753 (LPSTR)&mr->rdParam[12]/*bits*/);
754 SelectObject(hdcSrc,hbitmap);
755 BitBlt(hdc,mr->rdParam[6],mr->rdParam[5],
756 mr->rdParam[4],mr->rdParam[3],
757 hdcSrc,
758 mr->rdParam[2],mr->rdParam[1],
759 MAKELONG(0,mr->rdParam[0]));
760 DeleteDC(hdcSrc);
762 break;
764 default:
765 fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
766 mr->rdFunction);
771 /******************************************************************
772 * GetMetaFileBits by William Magro, 19 Sep 1995
774 * Trade in a meta file object handle for a handle to the meta file memory
777 HANDLE GetMetaFileBits(HMETAFILE16 hmf)
779 dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hmf);
781 return hmf;
784 /******************************************************************
785 * SetMetaFileBits by William Magro, 19 Sep 1995
787 * Trade in a meta file memory handle for a handle to a meta file object
790 HMETAFILE16 SetMetaFileBits(HANDLE hMem)
792 dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hMem);
794 return hMem;
797 /******************************************************************
798 * MF_WriteRecord
801 HMETAFILE16 MF_WriteRecord(HMETAFILE16 hmf, METARECORD *mr, WORD rlen)
803 DWORD len;
804 METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
806 if (mh->mtType == 0) /* memory based metafile */
808 len = mh->mtSize * 2 + rlen;
809 GlobalUnlock16(hmf);
810 hmf = GlobalReAlloc16(hmf, len, GMEM_MOVEABLE); /* hmf can change */
811 mh = (METAHEADER *)GlobalLock16(hmf);
812 memcpy((WORD *)mh + mh->mtSize, mr, rlen);
814 else if (mh->mtType == 1) /* disk based metafile */
816 dprintf_metafile(stddeb,"Writing record to disk\n");
817 if (_lwrite32(mh->mtNoParameters, (char *)mr, rlen) == -1)
819 GlobalUnlock16(hmf);
820 return 0;
823 else
825 GlobalUnlock16(hmf);
826 return 0;
829 mh->mtSize += rlen / 2;
830 mh->mtMaxRecord = MAX(mh->mtMaxRecord, rlen / 2);
831 GlobalUnlock16(hmf);
832 return hmf;
836 /******************************************************************
837 * MF_AddHandle
839 * Add a handle to an external handle table and return the index
842 int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HANDLE hobj)
844 int i;
846 for (i = 0; i < htlen; i++)
848 if (*(ht->objectHandle + i) == 0)
850 *(ht->objectHandle + i) = hobj;
851 return i;
854 return -1;
858 /******************************************************************
859 * MF_AddHandleDC
861 * Add a handle to the handle table in the DC, growing table if
862 * necessary. Return the index
865 int MF_AddHandleDC(DC *dc, HANDLE hobj)
867 int i;
868 HANDLETABLE16 *ht = (HANDLETABLE16 *)GlobalLock16(dc->w.hHT);
870 if((i = MF_AddHandle(ht, dc->w.HTLen, hobj)) == -1) {
871 GlobalUnlock16(dc->w.hHT);
872 if(!(dc->w.hHT = GlobalReAlloc16(dc->w.hHT, (dc->w.HTLen + HTINCR) *
873 sizeof(HANDLETABLE16), GMEM_MOVEABLE | GMEM_ZEROINIT)))
874 return -1;
875 dc->w.HTLen += HTINCR;
876 ht = (HANDLETABLE16 *)GlobalLock16(dc->w.hHT);
877 i = MF_AddHandle(ht, dc->w.HTLen, hobj);
879 GlobalUnlock16(dc->w.hHT);
880 return i;
884 /******************************************************************
885 * MF_MetaParam0
888 BOOL MF_MetaParam0(DC *dc, short func)
890 char buffer[8];
891 METARECORD *mr = (METARECORD *)&buffer;
892 HMETAFILE16 handle;
894 mr->rdSize = 3;
895 mr->rdFunction = func;
896 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
897 dc->w.hMetaFile = handle;
899 return handle;
903 /******************************************************************
904 * MF_MetaParam1
906 BOOL MF_MetaParam1(DC *dc, short func, short param1)
908 char buffer[8];
909 METARECORD *mr = (METARECORD *)&buffer;
910 HMETAFILE16 handle;
912 mr->rdSize = 4;
913 mr->rdFunction = func;
914 *(mr->rdParam) = param1;
915 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
916 dc->w.hMetaFile = handle;
918 return handle;
922 /******************************************************************
923 * MF_MetaParam2
925 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
927 char buffer[10];
928 METARECORD *mr = (METARECORD *)&buffer;
929 HMETAFILE16 handle;
931 mr->rdSize = 5;
932 mr->rdFunction = func;
933 *(mr->rdParam) = param2;
934 *(mr->rdParam + 1) = param1;
935 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
936 dc->w.hMetaFile = handle;
938 return handle;
942 /******************************************************************
943 * MF_MetaParam4
946 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2,
947 short param3, short param4)
949 char buffer[14];
950 METARECORD *mr = (METARECORD *)&buffer;
951 HMETAFILE16 handle;
953 mr->rdSize = 7;
954 mr->rdFunction = func;
955 *(mr->rdParam) = param4;
956 *(mr->rdParam + 1) = param3;
957 *(mr->rdParam + 2) = param2;
958 *(mr->rdParam + 3) = param1;
959 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
960 dc->w.hMetaFile = handle;
962 return handle;
966 /******************************************************************
967 * MF_MetaParam6
970 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2,
971 short param3, short param4, short param5, short param6)
973 char buffer[18];
974 METARECORD *mr = (METARECORD *)&buffer;
975 HMETAFILE16 handle;
977 mr->rdSize = 9;
978 mr->rdFunction = func;
979 *(mr->rdParam) = param6;
980 *(mr->rdParam + 1) = param5;
981 *(mr->rdParam + 2) = param4;
982 *(mr->rdParam + 3) = param3;
983 *(mr->rdParam + 4) = param2;
984 *(mr->rdParam + 5) = param1;
985 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
986 dc->w.hMetaFile = handle;
988 return handle;
992 /******************************************************************
993 * MF_MetaParam8
995 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
996 short param3, short param4, short param5,
997 short param6, short param7, short param8)
999 char buffer[22];
1000 METARECORD *mr = (METARECORD *)&buffer;
1001 HMETAFILE16 handle;
1003 mr->rdSize = 11;
1004 mr->rdFunction = func;
1005 *(mr->rdParam) = param8;
1006 *(mr->rdParam + 1) = param7;
1007 *(mr->rdParam + 2) = param6;
1008 *(mr->rdParam + 3) = param5;
1009 *(mr->rdParam + 4) = param4;
1010 *(mr->rdParam + 5) = param3;
1011 *(mr->rdParam + 6) = param2;
1012 *(mr->rdParam + 7) = param1;
1013 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1014 dc->w.hMetaFile = handle;
1016 return handle;
1020 /******************************************************************
1021 * MF_CreateBrushIndirect
1024 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH16 *logbrush)
1026 int index;
1027 HMETAFILE16 handle;
1028 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH16)];
1029 METARECORD *mr = (METARECORD *)&buffer;
1030 METAHEADER *mh;
1032 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2) / 2;
1033 mr->rdFunction = META_CREATEBRUSHINDIRECT;
1034 memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH16));
1035 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile,
1036 mr, mr->rdSize * 2)))
1037 return FALSE;
1039 mr->rdSize = sizeof(METARECORD) / 2;
1040 mr->rdFunction = META_SELECTOBJECT;
1042 if ((index = MF_AddHandleDC(dc, hBrush)) == -1)
1043 return FALSE;
1045 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1046 *(mr->rdParam) = index;
1047 if (index >= mh->mtNoObjects)
1048 mh->mtNoObjects++;
1050 GlobalUnlock16(dc->w.hMetaFile);
1051 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1052 dc->w.hMetaFile = handle;
1054 return handle;
1058 /******************************************************************
1059 * MF_CreatePatternBrush
1062 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH16 *logbrush)
1064 DWORD len, bmSize, biSize;
1065 HANDLE hmr;
1066 METARECORD *mr;
1067 BITMAPOBJ *bmp;
1068 BITMAPINFO *info;
1069 BITMAPINFOHEADER *infohdr;
1070 int index;
1071 HMETAFILE16 handle;
1072 char buffer[sizeof(METARECORD)];
1073 METAHEADER *mh;
1075 switch (logbrush->lbStyle)
1077 case BS_PATTERN:
1078 bmp = (BITMAPOBJ *)GDI_GetObjPtr((HANDLE)logbrush->lbHatch, BITMAP_MAGIC);
1079 if (!bmp) return FALSE;
1080 len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) +
1081 (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1082 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1083 return FALSE;
1084 mr = (METARECORD *)GlobalLock16(hmr);
1085 memset(mr, 0, len);
1086 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1087 mr->rdSize = len / 2;
1088 *(mr->rdParam) = logbrush->lbStyle;
1089 *(mr->rdParam + 1) = DIB_RGB_COLORS;
1090 infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
1091 infohdr->biSize = sizeof(BITMAPINFOHEADER);
1092 infohdr->biWidth = bmp->bitmap.bmWidth;
1093 infohdr->biHeight = bmp->bitmap.bmHeight;
1094 infohdr->biPlanes = bmp->bitmap.bmPlanes;
1095 infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1096 memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1097 PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1098 bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1099 break;
1101 case BS_DIBPATTERN:
1102 info = (BITMAPINFO *)GlobalLock16((HANDLE)logbrush->lbHatch);
1103 if (info->bmiHeader.biCompression)
1104 bmSize = info->bmiHeader.biSizeImage;
1105 else
1106 bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount
1107 + 31) / 32 * 8 * info->bmiHeader.biHeight;
1108 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor));
1109 len = sizeof(METARECORD) + biSize + bmSize + 2;
1110 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1111 return FALSE;
1112 mr = (METARECORD *)GlobalLock16(hmr);
1113 memset(mr, 0, len);
1114 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1115 mr->rdSize = len / 2;
1116 *(mr->rdParam) = logbrush->lbStyle;
1117 *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
1118 memcpy(mr->rdParam + 2, info, biSize + bmSize);
1119 break;
1120 default:
1121 return FALSE;
1123 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, len)))
1125 GlobalFree16(hmr);
1126 return FALSE;
1129 GlobalFree16(hmr);
1131 mr = (METARECORD *)&buffer;
1132 mr->rdSize = sizeof(METARECORD) / 2;
1133 mr->rdFunction = META_SELECTOBJECT;
1134 if ((index = MF_AddHandleDC(dc, hBrush)) == -1)
1135 return FALSE;
1137 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1138 *(mr->rdParam) = index;
1139 if (index >= mh->mtNoObjects)
1140 mh->mtNoObjects++;
1141 GlobalUnlock16(dc->w.hMetaFile);
1142 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1143 dc->w.hMetaFile = handle;
1145 return handle;
1149 /******************************************************************
1150 * MF_CreatePenIndirect
1153 BOOL MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1155 int index;
1156 HMETAFILE16 handle;
1157 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN16)];
1158 METARECORD *mr = (METARECORD *)&buffer;
1159 METAHEADER *mh;
1161 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN16) - 2) / 2;
1162 mr->rdFunction = META_CREATEPENINDIRECT;
1163 memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN16));
1164 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr,
1165 mr->rdSize * 2)))
1166 return FALSE;
1168 mr->rdSize = sizeof(METARECORD) / 2;
1169 mr->rdFunction = META_SELECTOBJECT;
1171 if ((index = MF_AddHandleDC(dc, hPen)) == -1)
1172 return FALSE;
1174 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1175 *(mr->rdParam) = index;
1176 if (index >= mh->mtNoObjects)
1177 mh->mtNoObjects++;
1178 GlobalUnlock16(dc->w.hMetaFile);
1179 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1180 dc->w.hMetaFile = handle;
1182 return handle;
1186 /******************************************************************
1187 * MF_CreateFontIndirect
1190 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT16 *logfont)
1192 int index;
1193 HMETAFILE16 handle;
1194 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1195 METARECORD *mr = (METARECORD *)&buffer;
1196 METAHEADER *mh;
1198 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1199 mr->rdFunction = META_CREATEFONTINDIRECT;
1200 memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT16));
1201 if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr,
1202 mr->rdSize * 2)))
1203 return FALSE;
1205 mr->rdSize = sizeof(METARECORD) / 2;
1206 mr->rdFunction = META_SELECTOBJECT;
1208 if ((index = MF_AddHandleDC(dc, hFont)) == -1)
1209 return FALSE;
1211 mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
1212 *(mr->rdParam) = index;
1213 if (index >= mh->mtNoObjects)
1214 mh->mtNoObjects++;
1215 GlobalUnlock16(dc->w.hMetaFile);
1216 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1217 dc->w.hMetaFile = handle;
1219 return handle;
1223 /******************************************************************
1224 * MF_TextOut
1226 BOOL MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1228 HMETAFILE16 handle;
1229 DWORD len;
1230 HANDLE hmr;
1231 METARECORD *mr;
1233 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1234 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1235 return FALSE;
1236 mr = (METARECORD *)GlobalLock16(hmr);
1237 memset(mr, 0, len);
1239 mr->rdSize = len / 2;
1240 mr->rdFunction = META_TEXTOUT;
1241 *(mr->rdParam) = count;
1242 memcpy(mr->rdParam + 1, str, count);
1243 *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1244 *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1245 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1246 dc->w.hMetaFile = handle;
1247 GlobalFree16(hmr);
1248 return handle;
1251 /******************************************************************
1252 * MF_ExtTextOut
1254 BOOL MF_ExtTextOut(DC *dc, short x, short y, UINT16 flags, const RECT16 *rect,
1255 LPCSTR str, short count, const INT16 *lpDx)
1257 HMETAFILE16 handle;
1258 DWORD len;
1259 HANDLE hmr;
1260 METARECORD *mr;
1262 len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1263 + sizeof(UINT16) + sizeof(RECT16);
1264 if (lpDx)
1265 len+=count*sizeof(INT16);
1266 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1267 return FALSE;
1268 mr = (METARECORD *)GlobalLock16(hmr);
1269 memset(mr, 0, len);
1271 mr->rdSize = len / 2;
1272 mr->rdFunction = META_EXTTEXTOUT;
1273 *(mr->rdParam) = y;
1274 *(mr->rdParam + 1) = x;
1275 *(mr->rdParam + 2) = count;
1276 *(mr->rdParam + 3) = flags;
1277 if (rect) memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
1278 memcpy(mr->rdParam + 8, str, count);
1279 if (lpDx)
1280 memcpy(mr->rdParam + 8+ ((count + 1) >> 1),lpDx,count*sizeof(INT16));
1281 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1282 dc->w.hMetaFile = handle;
1283 GlobalFree16(hmr);
1284 return handle;
1287 /******************************************************************
1288 * MF_MetaPoly - implements Polygon and Polyline
1290 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1292 HMETAFILE16 handle;
1293 DWORD len;
1294 HANDLE hmr;
1295 METARECORD *mr;
1297 len = sizeof(METARECORD) + (count * 4);
1298 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1299 return FALSE;
1300 mr = (METARECORD *)GlobalLock16(hmr);
1301 memset(mr, 0, len);
1303 mr->rdSize = len / 2;
1304 mr->rdFunction = func;
1305 *(mr->rdParam) = count;
1306 memcpy(mr->rdParam + 1, pt, count * 4);
1307 handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
1308 dc->w.hMetaFile = handle;
1309 GlobalFree16(hmr);
1310 return handle;
1314 /******************************************************************
1315 * MF_BitBlt
1317 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1318 short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
1320 HMETAFILE16 handle;
1321 DWORD len;
1322 HANDLE hmr;
1323 METARECORD *mr;
1324 DC *dcSrc;
1325 BITMAP16 BM;
1327 if (!(dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC ))) return 0;
1328 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1329 len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1330 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1331 return FALSE;
1332 mr = (METARECORD *)GlobalLock16(hmr);
1333 mr->rdFunction = META_BITBLT;
1334 *(mr->rdParam + 7) = BM.bmWidth;
1335 *(mr->rdParam + 8) = BM.bmHeight;
1336 *(mr->rdParam + 9) = BM.bmWidthBytes;
1337 *(mr->rdParam +10) = BM.bmPlanes;
1338 *(mr->rdParam +11) = BM.bmBitsPixel;
1339 dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1340 if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,mr->rdParam +12))
1342 mr->rdSize = len / sizeof(INT16);
1343 *(mr->rdParam) = HIWORD(rop);
1344 *(mr->rdParam + 1) = ySrc;
1345 *(mr->rdParam + 2) = xSrc;
1346 *(mr->rdParam + 3) = height;
1347 *(mr->rdParam + 4) = width;
1348 *(mr->rdParam + 5) = yDest;
1349 *(mr->rdParam + 6) = xDest;
1350 handle = MF_WriteRecord(dcDest->w.hMetaFile, mr, mr->rdSize * 2);
1352 else
1353 handle = 0;
1354 dcDest->w.hMetaFile = handle;
1355 GlobalFree16(hmr);
1356 return handle;
1360 /**********************************************************************
1361 * MF_StretchBlt
1362 * this function contains TWO ways for procesing StretchBlt in metafiles,
1363 * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT
1364 * via #define STRETCH_VIA_DIB
1366 #define STRETCH_VIA_DIB
1367 #undef STRETCH_VIA_DIB
1368 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1369 short heightDest, HDC hdcSrc, short xSrc, short ySrc,
1370 short widthSrc, short heightSrc, DWORD rop)
1372 HMETAFILE16 handle;
1373 DWORD len;
1374 HANDLE hmr;
1375 METARECORD *mr;
1376 DC *dcSrc;
1377 BITMAP16 BM;
1378 #ifdef STRETCH_VIA_DIB
1379 LPBITMAPINFOHEADER lpBMI;
1380 WORD nBPP;
1381 #endif
1382 if (!(dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC ))) return 0;
1383 GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1384 #ifdef STRETCH_VIA_DIB
1385 nBPP = BM.bmPlanes * BM.bmBitsPixel;
1386 len = sizeof(METARECORD) + 10 * sizeof(INT16)
1387 + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
1388 + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1389 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1390 return FALSE;
1391 mr = (METARECORD *)GlobalLock16(hmr);
1392 mr->rdFunction = META_DIBSTRETCHBLT;
1393 lpBMI=(LPBITMAPINFOHEADER)(mr->rdParam+10);
1394 lpBMI->biSize = sizeof(BITMAPINFOHEADER);
1395 lpBMI->biWidth = BM.bmWidth;
1396 lpBMI->biHeight = BM.bmHeight;
1397 lpBMI->biPlanes = 1;
1398 lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */
1399 lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0;
1400 lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1401 lpBMI->biCompression = BI_RGB;
1402 lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(hdcSrc,LOGPIXELSX),3937,100);
1403 lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(hdcSrc,LOGPIXELSY),3937,100);
1404 lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */
1406 dprintf_metafile(stddeb,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n",
1407 len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1408 if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT)lpBMI->biHeight,
1409 MF_GetDIBitsPointer((LPBITMAPINFO)lpBMI), /* DIB bits */
1410 (LPBITMAPINFO)lpBMI,DIB_RGB_COLORS)) /* DIB info structure */
1411 #else
1412 len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1413 if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1414 return FALSE;
1415 mr = (METARECORD *)GlobalLock16(hmr);
1416 mr->rdFunction = META_STRETCHBLT;
1417 *(mr->rdParam +10) = BM.bmWidth;
1418 *(mr->rdParam +11) = BM.bmHeight;
1419 *(mr->rdParam +12) = BM.bmWidthBytes;
1420 *(mr->rdParam +13) = BM.bmPlanes;
1421 *(mr->rdParam +14) = BM.bmBitsPixel;
1422 dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop);
1423 if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,mr->rdParam +15))
1424 #endif
1426 mr->rdSize = len / sizeof(INT16);
1427 *(mr->rdParam) = LOWORD(rop);
1428 *(mr->rdParam + 1) = HIWORD(rop);
1429 *(mr->rdParam + 2) = heightSrc;
1430 *(mr->rdParam + 3) = widthSrc;
1431 *(mr->rdParam + 4) = ySrc;
1432 *(mr->rdParam + 5) = xSrc;
1433 *(mr->rdParam + 6) = heightDest;
1434 *(mr->rdParam + 7) = widthDest;
1435 *(mr->rdParam + 8) = yDest;
1436 *(mr->rdParam + 9) = xDest;
1437 handle = MF_WriteRecord(dcDest->w.hMetaFile, mr, mr->rdSize * 2);
1439 else
1440 handle = 0;
1441 dcDest->w.hMetaFile = handle;
1442 GlobalFree16(hmr);
1443 return handle;