Added support for non-deletable system brushes and pens created by
[wine/hacks.git] / objects / metafile.c
blob172c5787dff723d4abd73dffccb99945304e2f74
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
7 */
9 /*
10 * These functions are primarily involved with metafile playback or anything
11 * that touches a HMETAFILE.
12 * For recording of metafiles look in graphics/metafiledrv/
14 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
15 * global memory handles so these cannot be interchanged.
17 * Memory-based metafiles are just stored as a continuous block of memory with
18 * a METAHEADER at the head with METARECORDs appended to it. mtType is
19 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
20 * disk-based metafile - even mtType is METAFILE_MEMORY.
21 * 16bit HMETAFILE16s are global handles to this block
22 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
23 * the memory.
24 * Disk-based metafiles are rather different. HMETAFILE16s point to a
25 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
26 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
27 * more 0, then 2 which may be a time stamp of the file and then the path of
28 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
30 * HDMD - 14/4/1999
31 */
34 #include <string.h>
35 #include <fcntl.h>
36 #include "wine/winbase16.h"
37 #include "metafile.h"
38 #include "bitmap.h"
39 #include "heap.h"
40 #include "toolhelp.h"
41 #include "debugtools.h"
42 #include "global.h"
44 DEFAULT_DEBUG_CHANNEL(metafile)
46 /******************************************************************
47 * MF_AddHandle
49 * Add a handle to an external handle table and return the index
51 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
53 int i;
55 for (i = 0; i < htlen; i++)
57 if (*(ht->objectHandle + i) == 0)
59 *(ht->objectHandle + i) = hobj;
60 return i;
63 return -1;
67 /******************************************************************
68 * MF_Create_HMETATFILE
70 * Creates a (32 bit) HMETAFILE object from a METAHEADER
72 * HMETAFILEs are GDI objects.
74 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
76 HMETAFILE hmf = 0;
77 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
78 if (metaObj)
80 metaObj->mh = mh;
81 GDI_ReleaseObj( hmf );
83 return hmf;
86 /******************************************************************
87 * MF_Create_HMETATFILE16
89 * Creates a HMETAFILE16 object from a METAHEADER
91 * HMETAFILE16s are Global memory handles.
93 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
95 HMETAFILE16 hmf;
96 DWORD size;
98 if(mh->mtType == METAFILE_MEMORY)
99 size = mh->mtSize * sizeof(WORD);
100 else
101 size = sizeof(METAHEADER) + sizeof(METAHEADERDISK);
103 hmf = GLOBAL_CreateBlock( GMEM_MOVEABLE, mh, mh->mtSize * sizeof(WORD),
104 GetCurrentPDB16(), FALSE, FALSE, FALSE );
105 return hmf;
108 /******************************************************************
109 * MF_GetMetaHeader
111 * Returns ptr to METAHEADER associated with HMETAFILE
112 * Should be followed by call to MF_ReleaseMetaHeader
114 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
116 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
117 return metaObj ? metaObj->mh : 0;
120 /******************************************************************
121 * MF_GetMetaHeader16
123 * Returns ptr to METAHEADER associated with HMETAFILE16
124 * Should be followed by call to MF_ReleaseMetaHeader16
126 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
128 return GlobalLock16(hmf);
131 /******************************************************************
132 * MF_ReleaseMetaHeader
134 * Releases METAHEADER associated with HMETAFILE
136 static void MF_ReleaseMetaHeader( HMETAFILE hmf )
138 GDI_ReleaseObj( hmf );
141 /******************************************************************
142 * MF_ReleaseMetaHeader16
144 * Releases METAHEADER associated with HMETAFILE16
146 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
148 return GlobalUnlock16( hmf );
152 /******************************************************************
153 * DeleteMetaFile16 (GDI.127)
155 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
157 return !GlobalFree16( hmf );
160 /******************************************************************
161 * DeleteMetaFile (GDI32.69)
163 * Delete a memory-based metafile.
166 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
168 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
169 if (!metaObj) return FALSE;
170 HeapFree( GetProcessHeap(), 0, metaObj->mh );
171 GDI_FreeObject( hmf, metaObj );
172 return TRUE;
175 /******************************************************************
176 * MF_ReadMetaFile
178 * Returns a pointer to a memory based METAHEADER read in from file HFILE
181 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
183 METAHEADER *mh;
184 DWORD BytesRead, size;
186 size = sizeof(METAHEADER);
187 mh = HeapAlloc( GetProcessHeap(), 0, size );
188 if(!mh) return NULL;
189 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
190 BytesRead != size) {
191 HeapFree( GetProcessHeap(), 0, mh );
192 return NULL;
194 size = mh->mtSize * 2;
195 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
196 if(!mh) return NULL;
197 size -= sizeof(METAHEADER);
198 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
199 NULL) == 0 ||
200 BytesRead != size) {
201 HeapFree( GetProcessHeap(), 0, mh );
202 return NULL;
205 if (mh->mtType != METAFILE_MEMORY) {
206 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
207 mh->mtType = METAFILE_MEMORY;
209 return mh;
212 /******************************************************************
213 * GetMetaFile16 (GDI.124)
215 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
217 METAHEADER *mh;
218 HFILE hFile;
220 TRACE("%s\n", lpFilename);
222 if(!lpFilename)
223 return 0;
225 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
226 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
227 return 0;
229 mh = MF_ReadMetaFile(hFile);
230 CloseHandle(hFile);
231 if(!mh) return 0;
232 return MF_Create_HMETAFILE16( mh );
235 /******************************************************************
236 * GetMetaFileA (GDI32.197)
238 * Read a metafile from a file. Returns handle to a memory-based metafile.
240 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
242 METAHEADER *mh;
243 HFILE hFile;
245 TRACE("%s\n", lpFilename);
247 if(!lpFilename)
248 return 0;
250 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
251 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
252 return 0;
254 mh = MF_ReadMetaFile(hFile);
255 CloseHandle(hFile);
256 if(!mh) return 0;
257 return MF_Create_HMETAFILE( mh );
262 /******************************************************************
263 * GetMetaFileW (GDI32.199)
265 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
267 METAHEADER *mh;
268 HFILE hFile;
270 TRACE("%s\n", debugstr_w(lpFilename));
272 if(!lpFilename)
273 return 0;
275 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
276 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
277 return 0;
279 mh = MF_ReadMetaFile(hFile);
280 CloseHandle(hFile);
281 if(!mh) return 0;
282 return MF_Create_HMETAFILE( mh );
286 /******************************************************************
287 * MF_LoadDiskBasedMetaFile
289 * Creates a new memory-based metafile from a disk-based one.
291 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
293 METAHEADERDISK *mhd;
294 HFILE hfile;
295 METAHEADER *mh2;
297 if(mh->mtType != METAFILE_DISK) {
298 ERR("Not a disk based metafile\n");
299 return NULL;
301 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
303 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
304 OPEN_EXISTING, 0, -1)) == HFILE_ERROR) {
305 WARN("Can't open file of disk based metafile\n");
306 return NULL;
308 mh2 = MF_ReadMetaFile(hfile);
309 CloseHandle(hfile);
310 return mh2;
313 /******************************************************************
314 * MF_CreateMetaHeaderDisk
316 * Take a memory based METAHEADER and change it to a disk based METAHEADER
317 * assosiated with filename. Note: Trashes contents of old one.
319 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
321 METAHEADERDISK *mhd;
322 DWORD size;
324 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
325 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
326 mh->mtType = METAFILE_DISK;
327 size = HeapSize( GetProcessHeap(), 0, mh );
328 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
329 strcpy(mhd->filename, filename);
330 return mh;
333 /******************************************************************
334 * CopyMetaFile16 (GDI.151)
336 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
338 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
339 METAHEADER *mh2 = NULL;
340 HFILE hFile;
342 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
344 if(!mh) return 0;
346 if(mh->mtType == METAFILE_DISK)
347 mh2 = MF_LoadDiskBasedMetaFile(mh);
348 else {
349 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
350 memcpy( mh2, mh, mh->mtSize * 2 );
352 MF_ReleaseMetaHeader16( hSrcMetaFile );
354 if(lpFilename) { /* disk based metafile */
355 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
356 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
357 HeapFree( GetProcessHeap(), 0, mh2 );
358 return 0;
360 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
361 CloseHandle(hFile);
362 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
365 return MF_Create_HMETAFILE16( mh2 );
369 /******************************************************************
370 * CopyMetaFileA (GDI32.23)
372 * Copies the metafile corresponding to hSrcMetaFile to either
373 * a disk file, if a filename is given, or to a new memory based
374 * metafile, if lpFileName is NULL.
376 * RETURNS
378 * Handle to metafile copy on success, NULL on failure.
380 * BUGS
382 * Copying to disk returns NULL even if successful.
384 HMETAFILE WINAPI CopyMetaFileA(
385 HMETAFILE hSrcMetaFile, /* handle of metafile to copy */
386 LPCSTR lpFilename /* filename if copying to a file */
388 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
389 METAHEADER *mh2 = NULL;
390 HFILE hFile;
392 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
394 if(!mh) return 0;
396 if(mh->mtType == METAFILE_DISK)
397 mh2 = MF_LoadDiskBasedMetaFile(mh);
398 else {
399 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
400 memcpy( mh2, mh, mh->mtSize * 2 );
402 MF_ReleaseMetaHeader( hSrcMetaFile );
404 if(lpFilename) { /* disk based metafile */
405 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
406 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
407 HeapFree( GetProcessHeap(), 0, mh2 );
408 return 0;
410 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
411 CloseHandle(hFile);
412 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
415 return MF_Create_HMETAFILE( mh2 );
419 /******************************************************************
420 * CopyMetaFileW (GDI32.24)
422 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
423 LPCWSTR lpFilename )
425 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
426 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
427 HeapFree( GetProcessHeap(), 0, p );
428 return ret;
432 /******************************************************************
433 * IsValidMetaFile (GDI.410)
435 * Attempts to check if a given metafile is correctly formatted.
436 * Currently, the only things verified are several properties of the
437 * header.
439 * RETURNS
440 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
442 * BUGS
443 * This is not exactly what windows does, see _Undocumented_Windows_
444 * for details.
446 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
448 BOOL16 res=FALSE;
449 METAHEADER *mh = MF_GetMetaHeader16(hmf);
450 if (mh) {
451 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
452 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
453 if (mh->mtVersion == MFVERSION)
454 res=TRUE;
455 MF_ReleaseMetaHeader16(hmf);
457 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
458 return res;
462 /*******************************************************************
463 * MF_PlayMetaFile
465 * Helper for PlayMetaFile
467 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
470 METARECORD *mr;
471 HANDLETABLE16 *ht;
472 int offset = 0;
473 WORD i;
474 HPEN hPen;
475 HBRUSH hBrush;
476 HFONT hFont;
477 BOOL loaded = FALSE;
479 if (!mh) return FALSE;
480 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
481 mh = MF_LoadDiskBasedMetaFile(mh);
482 if(!mh) return FALSE;
483 loaded = TRUE;
486 /* save the current pen, brush and font */
487 hPen = GetCurrentObject(hdc, OBJ_PEN);
488 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
489 hFont = GetCurrentObject(hdc, OBJ_FONT);
491 /* create the handle table */
492 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
493 sizeof(HANDLETABLE16) * mh->mtNoObjects);
494 if(!ht) return FALSE;
496 /* loop through metafile playing records */
497 offset = mh->mtHeaderSize * 2;
498 while (offset < mh->mtSize * 2)
500 mr = (METARECORD *)((char *)mh + offset);
501 TRACE("offset=%04x,size=%08lx\n",
502 offset, mr->rdSize);
503 if (!mr->rdSize) {
504 TRACE(
505 "Entry got size 0 at offset %d, total mf length is %ld\n",
506 offset,mh->mtSize*2);
507 break; /* would loop endlessly otherwise */
509 offset += mr->rdSize * 2;
510 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
513 SelectObject(hdc, hBrush);
514 SelectObject(hdc, hPen);
515 SelectObject(hdc, hFont);
517 /* free objects in handle table */
518 for(i = 0; i < mh->mtNoObjects; i++)
519 if(*(ht->objectHandle + i) != 0)
520 DeleteObject(*(ht->objectHandle + i));
522 /* free handle table */
523 HeapFree( GetProcessHeap(), 0, ht );
524 if(loaded)
525 HeapFree( GetProcessHeap(), 0, mh );
526 return TRUE;
529 /******************************************************************
530 * PlayMetaFile16 (GDI.123)
533 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
535 BOOL16 ret;
536 METAHEADER *mh = MF_GetMetaHeader16( hmf );
537 ret = MF_PlayMetaFile( hdc, mh );
538 MF_ReleaseMetaHeader16( hmf );
539 return ret;
542 /******************************************************************
543 * PlayMetaFile (GDI32.265)
545 * Renders the metafile specified by hmf in the DC specified by
546 * hdc. Returns FALSE on failure, TRUE on success.
548 BOOL WINAPI PlayMetaFile(
549 HDC hdc, /* handle of DC to render in */
550 HMETAFILE hmf /* handle of metafile to render */
553 BOOL ret;
554 METAHEADER *mh = MF_GetMetaHeader( hmf );
555 ret = MF_PlayMetaFile( hdc, mh );
556 MF_ReleaseMetaHeader( hmf );
557 return ret;
561 /******************************************************************
562 * EnumMetaFile16 (GDI.175)
565 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
566 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
568 METAHEADER *mh = MF_GetMetaHeader16(hmf);
569 METARECORD *mr;
570 HANDLETABLE16 *ht;
571 HGLOBAL16 hHT;
572 SEGPTR spht;
573 int offset = 0;
574 WORD i, seg;
575 HPEN hPen;
576 HBRUSH hBrush;
577 HFONT hFont;
578 BOOL16 result = TRUE, loaded = FALSE;
580 TRACE("(%04x, %04x, %08lx, %08lx)\n",
581 hdc, hmf, (DWORD)lpEnumFunc, lpData);
584 if(!mh) return FALSE;
585 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
586 mh = MF_LoadDiskBasedMetaFile(mh);
587 if(!mh) return FALSE;
588 loaded = TRUE;
591 /* save the current pen, brush and font */
592 hPen = GetCurrentObject(hdc, OBJ_PEN);
593 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
594 hFont = GetCurrentObject(hdc, OBJ_FONT);
596 /* create the handle table */
598 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
599 sizeof(HANDLETABLE16) * mh->mtNoObjects);
600 spht = WIN16_GlobalLock16(hHT);
602 seg = GlobalHandleToSel16(hmf);
603 offset = mh->mtHeaderSize * 2;
605 /* loop through metafile records */
607 while (offset < (mh->mtSize * 2))
609 mr = (METARECORD *)((char *)mh + offset);
610 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
611 (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
612 mh->mtNoObjects, (LONG)lpData ))
614 result = FALSE;
615 break;
619 offset += (mr->rdSize * 2);
622 SelectObject(hdc, hBrush);
623 SelectObject(hdc, hPen);
624 SelectObject(hdc, hFont);
626 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
628 /* free objects in handle table */
629 for(i = 0; i < mh->mtNoObjects; i++)
630 if(*(ht->objectHandle + i) != 0)
631 DeleteObject(*(ht->objectHandle + i));
633 /* free handle table */
634 GlobalFree16(hHT);
635 if(loaded)
636 HeapFree( GetProcessHeap(), 0, mh );
637 MF_ReleaseMetaHeader16(hmf);
638 return result;
641 /******************************************************************
642 * EnumMetaFile (GDI32.88)
644 * Loop through the metafile records in hmf, calling the user-specified
645 * function for each one, stopping when the user's function returns FALSE
646 * (which is considered to be failure)
647 * or when no records are left (which is considered to be success).
649 * RETURNS
650 * TRUE on success, FALSE on failure.
652 * HISTORY
653 * Niels de carpentier, april 1996
655 BOOL WINAPI EnumMetaFile(
656 HDC hdc,
657 HMETAFILE hmf,
658 MFENUMPROC lpEnumFunc,
659 LPARAM lpData
661 METAHEADER *mh = MF_GetMetaHeader(hmf);
662 METARECORD *mr;
663 HANDLETABLE *ht;
664 BOOL result = TRUE, loaded = FALSE;
665 int i, offset = 0;
666 HPEN hPen;
667 HBRUSH hBrush;
668 HFONT hFont;
670 TRACE("(%08x,%08x,%p,%p)\n",
671 hdc, hmf, lpEnumFunc, (void*)lpData);
672 if (!mh) return 0;
673 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
674 mh = MF_LoadDiskBasedMetaFile(mh);
675 if(!mh) return 0;
676 loaded = TRUE;
679 /* save the current pen, brush and font */
680 hPen = GetCurrentObject(hdc, OBJ_PEN);
681 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
682 hFont = GetCurrentObject(hdc, OBJ_FONT);
684 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
685 sizeof(HANDLETABLE) * mh->mtNoObjects);
687 /* loop through metafile records */
688 offset = mh->mtHeaderSize * 2;
690 while (offset < (mh->mtSize * 2))
692 mr = (METARECORD *)((char *)mh + offset);
693 TRACE("Calling EnumFunc with record type %x\n",
694 mr->rdFunction);
695 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
697 result = FALSE;
698 break;
701 offset += (mr->rdSize * 2);
704 /* restore pen, brush and font */
705 SelectObject(hdc, hBrush);
706 SelectObject(hdc, hPen);
707 SelectObject(hdc, hFont);
709 /* free objects in handle table */
710 for(i = 0; i < mh->mtNoObjects; i++)
711 if(*(ht->objectHandle + i) != 0)
712 DeleteObject(*(ht->objectHandle + i));
714 /* free handle table */
715 HeapFree( GetProcessHeap(), 0, ht);
716 if(loaded)
717 HeapFree( GetProcessHeap(), 0, mh );
718 MF_ReleaseMetaHeader(hmf);
719 return result;
722 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
723 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
724 /******************************************************************
725 * PlayMetaFileRecord16 (GDI.176)
727 * Render a single metafile record specified by *mr in the DC hdc, while
728 * using the handle table *ht, of length nHandles,
729 * to store metafile objects.
731 * BUGS
732 * The following metafile records are unimplemented:
734 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
735 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
736 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
739 void WINAPI PlayMetaFileRecord16(
740 HDC16 hdc, /* DC to render metafile into */
741 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
742 METARECORD *mr, /* pointer to metafile record to render */
743 UINT16 nHandles /* size of handle table */
745 short s1;
746 HANDLE16 hndl;
747 char *ptr;
748 BITMAPINFOHEADER *infohdr;
750 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
751 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
753 switch (mr->rdFunction)
755 case META_EOF:
756 break;
758 case META_DELETEOBJECT:
759 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
760 *(ht->objectHandle + *(mr->rdParm)) = 0;
761 break;
763 case META_SETBKCOLOR:
764 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
765 break;
767 case META_SETBKMODE:
768 SetBkMode16(hdc, *(mr->rdParm));
769 break;
771 case META_SETMAPMODE:
772 SetMapMode16(hdc, *(mr->rdParm));
773 break;
775 case META_SETROP2:
776 SetROP216(hdc, *(mr->rdParm));
777 break;
779 case META_SETRELABS:
780 SetRelAbs16(hdc, *(mr->rdParm));
781 break;
783 case META_SETPOLYFILLMODE:
784 SetPolyFillMode16(hdc, *(mr->rdParm));
785 break;
787 case META_SETSTRETCHBLTMODE:
788 SetStretchBltMode16(hdc, *(mr->rdParm));
789 break;
791 case META_SETTEXTCOLOR:
792 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
793 break;
795 case META_SETWINDOWORG:
796 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
797 break;
799 case META_SETWINDOWEXT:
800 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
801 break;
803 case META_SETVIEWPORTORG:
804 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
805 break;
807 case META_SETVIEWPORTEXT:
808 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
809 break;
811 case META_OFFSETWINDOWORG:
812 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
813 break;
815 case META_SCALEWINDOWEXT:
816 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
817 *(mr->rdParm + 1), *(mr->rdParm));
818 break;
820 case META_OFFSETVIEWPORTORG:
821 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
822 break;
824 case META_SCALEVIEWPORTEXT:
825 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
826 *(mr->rdParm + 1), *(mr->rdParm));
827 break;
829 case META_LINETO:
830 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
831 break;
833 case META_MOVETO:
834 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
835 break;
837 case META_EXCLUDECLIPRECT:
838 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
839 *(mr->rdParm + 1), *(mr->rdParm) );
840 break;
842 case META_INTERSECTCLIPRECT:
843 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
844 *(mr->rdParm + 1), *(mr->rdParm) );
845 break;
847 case META_ARC:
848 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
849 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
850 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
851 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
852 break;
854 case META_ELLIPSE:
855 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
856 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
857 break;
859 case META_FLOODFILL:
860 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
861 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
862 break;
864 case META_PIE:
865 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
866 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
867 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
868 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
869 break;
871 case META_RECTANGLE:
872 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
873 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
874 break;
876 case META_ROUNDRECT:
877 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
878 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
879 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
880 break;
882 case META_PATBLT:
883 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
884 *(mr->rdParm + 3), *(mr->rdParm + 2),
885 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
886 break;
888 case META_SAVEDC:
889 SaveDC(hdc);
890 break;
892 case META_SETPIXEL:
893 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
894 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
895 break;
897 case META_OFFSETCLIPRGN:
898 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
899 break;
901 case META_TEXTOUT:
902 s1 = *(mr->rdParm);
903 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
904 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
905 (char *)(mr->rdParm + 1), s1);
906 break;
908 case META_POLYGON:
909 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
910 break;
912 case META_POLYPOLYGON:
913 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
914 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
915 break;
917 case META_POLYLINE:
918 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
919 break;
921 case META_RESTOREDC:
922 RestoreDC(hdc, (INT16)*(mr->rdParm));
923 break;
925 case META_SELECTOBJECT:
926 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
927 break;
929 case META_CHORD:
930 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
931 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
932 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
933 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
934 break;
936 case META_CREATEPATTERNBRUSH:
937 switch (*(mr->rdParm))
939 case BS_PATTERN:
940 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
941 MF_AddHandle(ht, nHandles,
942 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
943 infohdr->biHeight,
944 infohdr->biPlanes,
945 infohdr->biBitCount,
946 (LPSTR)(mr->rdParm +
947 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
948 break;
950 case BS_DIBPATTERN:
951 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
952 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
953 ptr = GlobalLock16(hndl);
954 memcpy(ptr, mr->rdParm + 2, s1);
955 GlobalUnlock16(hndl);
956 MF_AddHandle(ht, nHandles,
957 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
958 GlobalFree16(hndl);
959 break;
961 default:
962 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
963 mr->rdParm[0]);
964 break;
966 break;
968 case META_CREATEPENINDIRECT:
969 MF_AddHandle(ht, nHandles,
970 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
971 break;
973 case META_CREATEFONTINDIRECT:
974 MF_AddHandle(ht, nHandles,
975 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
976 break;
978 case META_CREATEBRUSHINDIRECT:
979 MF_AddHandle(ht, nHandles,
980 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
981 break;
983 case META_CREATEPALETTE:
984 MF_AddHandle(ht, nHandles,
985 CreatePalette16((LPLOGPALETTE)mr->rdParm));
986 break;
988 case META_SETTEXTALIGN:
989 SetTextAlign16(hdc, *(mr->rdParm));
990 break;
992 case META_SELECTPALETTE:
993 SelectPalette(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
994 *(mr->rdParm));
995 break;
997 case META_SETMAPPERFLAGS:
998 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
999 break;
1001 case META_REALIZEPALETTE:
1002 RealizePalette(hdc);
1003 break;
1005 case META_ESCAPE:
1006 FIXME("META_ESCAPE unimplemented.\n");
1007 break;
1009 case META_EXTTEXTOUT:
1010 MF_Play_MetaExtTextOut( hdc, mr );
1011 break;
1013 case META_STRETCHDIB:
1015 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1016 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1017 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1018 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1019 mr->rdParm[4],mr->rdParm[3],bits,info,
1020 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1022 break;
1024 case META_DIBSTRETCHBLT:
1026 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1027 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1028 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1029 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1030 mr->rdParm[3],mr->rdParm[2],bits,info,
1031 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1033 break;
1035 case META_STRETCHBLT:
1037 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1038 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1039 mr->rdParm[11], /*Height*/
1040 mr->rdParm[13], /*Planes*/
1041 mr->rdParm[14], /*BitsPixel*/
1042 (LPSTR)&mr->rdParm[15]); /*bits*/
1043 SelectObject(hdcSrc,hbitmap);
1044 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1045 mr->rdParm[7],mr->rdParm[6],
1046 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1047 mr->rdParm[3],mr->rdParm[2],
1048 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1049 DeleteDC(hdcSrc);
1051 break;
1053 case META_BITBLT:
1055 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1056 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1057 mr->rdParm[8]/*Height*/,
1058 mr->rdParm[10]/*Planes*/,
1059 mr->rdParm[11]/*BitsPixel*/,
1060 (LPSTR)&mr->rdParm[12]/*bits*/);
1061 SelectObject(hdcSrc,hbitmap);
1062 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1063 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1064 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1065 MAKELONG(0,mr->rdParm[0]));
1066 DeleteDC(hdcSrc);
1068 break;
1070 case META_CREATEREGION:
1072 HRGN hrgn = CreateRectRgn(0,0,0,0);
1074 MF_Play_MetaCreateRegion(mr, hrgn);
1075 MF_AddHandle(ht, nHandles, hrgn);
1077 break;
1079 case META_FILLREGION:
1080 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1081 *(ht->objectHandle + *(mr->rdParm)));
1082 break;
1084 case META_FRAMEREGION:
1085 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1086 *(ht->objectHandle + *(mr->rdParm+2)),
1087 *(mr->rdParm+1), *(mr->rdParm));
1088 break;
1090 case META_INVERTREGION:
1091 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1092 break;
1094 case META_PAINTREGION:
1095 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1096 break;
1098 case META_SELECTCLIPREGION:
1099 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1100 break;
1102 case META_DIBCREATEPATTERNBRUSH:
1103 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1104 but there's no difference */
1106 TRACE("%d\n",*(mr->rdParm));
1107 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1108 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1109 ptr = GlobalLock16(hndl);
1110 memcpy(ptr, mr->rdParm + 2, s1);
1111 GlobalUnlock16(hndl);
1112 MF_AddHandle(ht, nHandles,
1113 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1114 GlobalFree16(hndl);
1115 break;
1117 case META_DIBBITBLT:
1118 /* In practice I've found that there are two layouts for
1119 META_DIBBITBLT, one (the first here) is the usual one when a src
1120 dc is actually passed to it, the second occurs when the src dc is
1121 passed in as NULL to the creating BitBlt. As the second case has
1122 no dib, a size check will suffice to distinguish.
1124 Caolan.McNamara@ul.ie */
1126 if (mr->rdSize > 12) {
1127 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1128 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1130 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1131 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1132 mr->rdParm[5], mr->rdParm[4], bits, info,
1133 DIB_RGB_COLORS,
1134 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1135 } else { /* equivalent to a PatBlt */
1136 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1137 mr->rdParm[6], mr->rdParm[5],
1138 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1140 break;
1142 case META_SETTEXTCHAREXTRA:
1143 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1144 break;
1146 case META_SETTEXTJUSTIFICATION:
1147 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1148 break;
1150 case META_EXTFLOODFILL:
1151 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1152 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1153 *(mr->rdParm));
1154 break;
1156 case META_SETDIBTODEV:
1158 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1159 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1160 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1161 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1162 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1163 mr->rdParm[2], mr->rdParm[1], bits, info,
1164 mr->rdParm[0]);
1165 break;
1168 #define META_UNIMP(x) case x: \
1169 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1170 break;
1171 META_UNIMP(META_DRAWTEXT)
1172 META_UNIMP(META_ANIMATEPALETTE)
1173 META_UNIMP(META_SETPALENTRIES)
1174 META_UNIMP(META_RESIZEPALETTE)
1175 META_UNIMP(META_RESETDC)
1176 META_UNIMP(META_STARTDOC)
1177 META_UNIMP(META_STARTPAGE)
1178 META_UNIMP(META_ENDPAGE)
1179 META_UNIMP(META_ABORTDOC)
1180 META_UNIMP(META_ENDDOC)
1181 META_UNIMP(META_CREATEBRUSH)
1182 META_UNIMP(META_CREATEBITMAPINDIRECT)
1183 META_UNIMP(META_CREATEBITMAP)
1184 #undef META_UNIMP
1186 default:
1187 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1188 mr->rdFunction);
1192 /******************************************************************
1193 * PlayMetaFileRecord (GDI32.266)
1195 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1196 METARECORD *metarecord, UINT handles )
1198 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1199 handles*sizeof(HANDLETABLE16));
1200 int i = 0;
1201 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1202 handles);
1203 for (i=0; i<handles; i++)
1204 ht->objectHandle[i] = handletable->objectHandle[i];
1205 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1206 for (i=0; i<handles; i++)
1207 handletable->objectHandle[i] = ht->objectHandle[i];
1208 GlobalFree((HGLOBAL)ht);
1209 return TRUE;
1212 /******************************************************************
1213 * GetMetaFileBits (GDI.159)
1215 * Trade in a metafile object handle for a handle to the metafile memory.
1219 HGLOBAL16 WINAPI GetMetaFileBits16(
1220 HMETAFILE16 hmf /* metafile handle */
1223 TRACE("hMem out: %04x\n", hmf);
1224 return hmf;
1227 /******************************************************************
1228 * SetMetaFileBits (GDI.160)
1230 * Trade in a metafile memory handle for a handle to a metafile object.
1231 * The memory region should hold a proper metafile, otherwise
1232 * problems will occur when it is used. Validity of the memory is not
1233 * checked. The function is essentially just the identity function.
1235 HMETAFILE16 WINAPI SetMetaFileBits16(
1236 HGLOBAL16 hMem
1237 /* handle to a memory region holding a metafile */
1240 TRACE("hmf out: %04x\n", hMem);
1242 return hMem;
1245 /******************************************************************
1246 * SetMetaFileBitsBetter (GDI.196)
1248 * Trade in a metafile memory handle for a handle to a metafile object,
1249 * making a cursory check (using IsValidMetaFile()) that the memory
1250 * handle points to a valid metafile.
1252 * RETURNS
1253 * Handle to a metafile on success, NULL on failure..
1255 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1257 if( IsValidMetaFile16( hMeta ) )
1258 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1259 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1260 return (HMETAFILE16)0;
1263 /******************************************************************
1264 * SetMetaFileBitsEx (GDI32.323)
1266 * Create a metafile from raw data. No checking of the data is performed.
1267 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1269 HMETAFILE WINAPI SetMetaFileBitsEx(
1270 UINT size, /* size of metafile, in bytes */
1271 const BYTE *lpData /* pointer to metafile data */
1274 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1275 if (!mh) return 0;
1276 memcpy(mh, lpData, size);
1277 return MF_Create_HMETAFILE(mh);
1280 /*****************************************************************
1281 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1283 * Copies the data from metafile _hmf_ into the buffer _buf_.
1284 * If _buf_ is zero, returns size of buffer required. Otherwise,
1285 * returns number of bytes copied.
1287 UINT WINAPI GetMetaFileBitsEx(
1288 HMETAFILE hmf, /* metafile */
1289 UINT nSize, /* size of buf */
1290 LPVOID buf /* buffer to receive raw metafile data */
1292 METAHEADER *mh = MF_GetMetaHeader(hmf);
1293 UINT mfSize;
1295 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1296 if (!mh) return 0; /* FIXME: error code */
1297 if(mh->mtType == METAFILE_DISK)
1298 FIXME("Disk-based metafile?\n");
1299 mfSize = mh->mtSize * 2;
1300 if (!buf) {
1301 MF_ReleaseMetaHeader(hmf);
1302 TRACE("returning size %d\n", mfSize);
1303 return mfSize;
1305 if(mfSize > nSize) mfSize = nSize;
1306 memmove(buf, mh, mfSize);
1307 MF_ReleaseMetaHeader(hmf);
1308 return mfSize;
1311 /******************************************************************
1312 * GetWinMetaFileBits [GDI32.241]
1314 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1315 UINT cbBuffer, LPBYTE lpbBuffer,
1316 INT fnMapMode, HDC hdcRef)
1318 FIXME("(%d,%d,%p,%d,%d): stub\n",
1319 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1320 return 0;
1323 /******************************************************************
1324 * MF_Play_MetaCreateRegion
1326 * Handles META_CREATEREGION for PlayMetaFileRecord().
1330 * The layout of the record looks something like this:
1332 * rdParm meaning
1333 * 0 Always 0?
1334 * 1 Always 6?
1335 * 2 Looks like a handle? - not constant
1336 * 3 0 or 1 ??
1337 * 4 Total number of bytes
1338 * 5 No. of seperate bands = n [see below]
1339 * 6 Largest number of x co-ords in a band
1340 * 7-10 Bounding box x1 y1 x2 y2
1341 * 11-... n bands
1343 * Regions are divided into bands that are uniform in the
1344 * y-direction. Each band consists of pairs of on/off x-coords and is
1345 * written as
1346 * m y0 y1 x1 x2 x3 ... xm m
1347 * into successive rdParm[]s.
1349 * This is probably just a dump of the internal RGNOBJ?
1351 * HDMD - 18/12/97
1355 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1357 WORD band, pair;
1358 WORD *start, *end;
1359 INT16 y0, y1;
1360 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1362 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1363 band++, start = end + 1) {
1364 if(*start / 2 != (*start + 1) / 2) {
1365 WARN("Delimiter not even.\n");
1366 DeleteObject( hrgn2 );
1367 return FALSE;
1370 end = start + *start + 3;
1371 if(end > (WORD *)mr + mr->rdSize) {
1372 WARN("End points outside record.\n");
1373 DeleteObject( hrgn2 );
1374 return FALSE;
1377 if(*start != *end) {
1378 WARN("Mismatched delimiters.\n");
1379 DeleteObject( hrgn2 );
1380 return FALSE;
1383 y0 = *(INT16 *)(start + 1);
1384 y1 = *(INT16 *)(start + 2);
1385 for(pair = 0; pair < *start / 2; pair++) {
1386 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1387 *(INT16 *)(start + 4 + 2*pair), y1 );
1388 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1391 DeleteObject( hrgn2 );
1392 return TRUE;
1396 /******************************************************************
1397 * MF_Play_MetaExtTextOut
1399 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1402 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1404 LPINT16 dxx;
1405 LPSTR sot;
1406 DWORD len;
1407 WORD s1;
1409 s1 = mr->rdParm[2]; /* String length */
1410 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1411 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1412 /* rec len without dx array */
1414 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1415 if (mr->rdParm[3])
1416 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1418 if (mr->rdSize == len / 2)
1419 dxx = NULL; /* determine if array present */
1420 else
1421 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1422 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1423 else {
1424 TRACE("%s len: %ld\n", sot, mr->rdSize);
1425 WARN(
1426 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1427 len, s1, mr->rdSize, mr->rdParm[3]);
1428 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1430 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1431 mr->rdParm[0], /* Y position */
1432 mr->rdParm[3], /* options */
1433 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1434 /* rectangle */
1435 sot, /* string */
1436 s1, dxx); /* length, dx array */
1437 if (dxx)
1438 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1439 return TRUE;