Release 20010305.
[wine] / graphics / metafiledrv / init.c
1 /*
2  * Metafile driver initialisation functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include "windef.h"
8 #include "wine/winbase16.h"
9 #include "gdi.h"
10 #include "heap.h"
11 #include "metafile.h"
12 #include "metafiledrv.h"
13 #include "debugtools.h"
14
15 DEFAULT_DEBUG_CHANNEL(metafile);
16
17 #include <string.h>
18
19 static const DC_FUNCTIONS MFDRV_Funcs =
20 {
21     NULL,                            /* pAbortDoc */
22     MFDRV_AbortPath,                 /* pAbortPath */
23     NULL,                            /* pAngleArc */
24     MFDRV_Arc,                       /* pArc */
25     NULL,                            /* pArcTo */
26     MFDRV_BeginPath,                 /* pBeginPath */
27     MFDRV_BitBlt,                    /* pBitBlt */
28     NULL,                            /* pBitmapBits */  
29     NULL,                            /* pChoosePixelFormat */
30     MFDRV_Chord,                     /* pChord */
31     MFDRV_CloseFigure,               /* pCloseFigure */
32     NULL,                            /* pCreateBitmap */
33     NULL, /* no implementation */    /* pCreateDC */
34     NULL,                            /* pCreateDIBSection */
35     NULL,                            /* pCreateDIBSection16 */
36     NULL, /* no implementation */    /* pDeleteDC */
37     NULL,                            /* pDeleteObject */
38     NULL,                            /* pDescribePixelFormat */
39     NULL,                            /* pDeviceCapabilities */
40     MFDRV_Ellipse,                   /* pEllipse */
41     NULL,                            /* pEndDoc */
42     NULL,                            /* pEndPage */
43     MFDRV_EndPath,                   /* pEndPath */
44     NULL,                            /* pEnumDeviceFonts */
45     NULL,                            /* pEscape */
46     MFDRV_ExcludeClipRect,           /* pExcludeClipRect */
47     NULL,                            /* pExtDeviceMode */
48     MFDRV_ExtFloodFill,              /* pExtFloodFill */
49     MFDRV_ExtTextOut,                /* pExtTextOut */
50     MFDRV_FillPath,                  /* pFillPath */
51     MFDRV_FillRgn,                   /* pFillRgn */
52     MFDRV_FlattenPath,               /* pFlattenPath */
53     MFDRV_FrameRgn,                  /* pFrameRgn */
54     NULL,                            /* pGetCharWidth */
55     NULL,                            /* pGetDCOrgEx */
56     NULL, /* no implementation */    /* pGetPixel */
57     NULL,                            /* pGetPixelFormat */
58     NULL,                            /* pGetTextExtentPoint */
59     NULL,                            /* pGetTextMetrics */
60     MFDRV_IntersectClipRect,         /* pIntersectClipRect */
61     MFDRV_InvertRgn,                 /* pInvertRgn */
62     MFDRV_LineTo,                    /* pLineTo */
63     MFDRV_MoveTo,                    /* pMoveTo */
64     MFDRV_OffsetClipRgn,             /* pOffsetClipRgn */
65     MFDRV_OffsetViewportOrg,         /* pOffsetViewportOrg */
66     MFDRV_OffsetWindowOrg,           /* pOffsetWindowOrg */
67     MFDRV_PaintRgn,                  /* pPaintRgn */
68     MFDRV_PatBlt,                    /* pPatBlt */
69     MFDRV_Pie,                       /* pPie */
70     MFDRV_PolyBezier,                /* pPolyBezier */
71     MFDRV_PolyBezierTo,              /* pPolyBezierTo */
72     NULL,                            /* pPolyDraw */
73     MFDRV_PolyPolygon,               /* pPolyPolygon */
74     NULL,                            /* pPolyPolyline */
75     MFDRV_Polygon,                   /* pPolygon */
76     MFDRV_Polyline,                  /* pPolyline */
77     NULL,                            /* pPolylineTo */
78     NULL,                            /* pRealizePalette */
79     MFDRV_Rectangle,                 /* pRectangle */
80     MFDRV_RestoreDC,                 /* pRestoreDC */
81     MFDRV_RoundRect,                 /* pRoundRect */
82     MFDRV_SaveDC,                    /* pSaveDC */
83     MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
84     MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
85     MFDRV_SelectClipPath,            /* pSelectClipPath */
86     NULL,                            /* pSelectClipRgn */
87     MFDRV_SelectObject,              /* pSelectObject */
88     NULL,                            /* pSelectPalette */
89     MFDRV_SetBkColor,                /* pSetBkColor */
90     MFDRV_SetBkMode,                 /* pSetBkMode */
91     NULL,                            /* pSetDeviceClipping */
92     MFDRV_SetDIBitsToDevice,         /* pSetDIBitsToDevice */
93     MFDRV_SetMapMode,                /* pSetMapMode */
94     MFDRV_SetMapperFlags,            /* pSetMapperFlags */
95     MFDRV_SetPixel,                  /* pSetPixel */
96     NULL,                            /* pSetPixelFormat */
97     MFDRV_SetPolyFillMode,           /* pSetPolyFillMode */
98     MFDRV_SetROP2,                   /* pSetROP2 */
99     MFDRV_SetRelAbs,                 /* pSetRelAbs */
100     MFDRV_SetStretchBltMode,         /* pSetStretchBltMode */
101     MFDRV_SetTextAlign,              /* pSetTextAlign */
102     MFDRV_SetTextCharacterExtra,     /* pSetTextCharacterExtra */
103     MFDRV_SetTextColor,              /* pSetTextColor */
104     MFDRV_SetTextJustification,      /* pSetTextJustification */
105     MFDRV_SetViewportExt,            /* pSetViewportExt */
106     MFDRV_SetViewportOrg,            /* pSetViewportOrg */
107     MFDRV_SetWindowExt,              /* pSetWindowExt */
108     MFDRV_SetWindowOrg,              /* pSetWindowOrg */
109     NULL,                            /* pStartDoc */
110     NULL,                            /* pStartPage */
111     MFDRV_StretchBlt,                /* pStretchBlt */
112     MFDRV_StretchDIBits,             /* pStretchDIBits */
113     MFDRV_StrokeAndFillPath,         /* pStrokeAndFillPath */
114     MFDRV_StrokePath,                /* pStrokePath */
115     NULL,                            /* pSwapBuffers */
116     MFDRV_WidenPath                  /* pWidenPath */
117 };
118
119
120
121 /**********************************************************************
122  *           MFDRV_AllocMetaFile
123  */
124 static DC *MFDRV_AllocMetaFile(void)
125 {
126     DC *dc;
127     METAFILEDRV_PDEVICE *physDev;
128     
129     if (!(dc = DC_AllocDC( &MFDRV_Funcs ))) return NULL;
130     dc->header.wMagic = METAFILE_DC_MAGIC;
131
132     physDev = (METAFILEDRV_PDEVICE *)HeapAlloc(GetProcessHeap(),0,sizeof(*physDev));
133     if (!physDev)
134     {
135         GDI_FreeObject( dc->hSelf, dc );
136         return NULL;
137     }
138     dc->physDev = physDev;
139
140     if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) )))
141     {
142         HeapFree( GetProcessHeap(), 0, physDev );
143         GDI_FreeObject( dc->hSelf, dc );
144         return NULL;
145     }
146
147     physDev->nextHandle = 0;
148     physDev->hFile = 0;
149
150     physDev->mh->mtHeaderSize   = sizeof(METAHEADER) / sizeof(WORD);
151     physDev->mh->mtVersion      = 0x0300;
152     physDev->mh->mtSize         = physDev->mh->mtHeaderSize;
153     physDev->mh->mtNoObjects    = 0;
154     physDev->mh->mtMaxRecord    = 0;
155     physDev->mh->mtNoParameters = 0;
156
157     return dc;
158 }
159
160
161 /**********************************************************************
162  *           MFDRV_DeleteDC
163  */
164 static BOOL MFDRV_DeleteDC( DC *dc )
165 {
166     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
167     
168     if (physDev->mh) HeapFree( GetProcessHeap(), 0, physDev->mh );
169     HeapFree( GetProcessHeap(), 0, physDev );
170     dc->physDev = NULL;
171     GDI_FreeObject( dc->hSelf, dc );
172     return TRUE;
173 }
174
175 /**********************************************************************
176  *           CreateMetaFile16   (GDI.125)
177  *           CreateMetaFile16   (GDI32.@)
178  *
179  *  Create a new DC and associate it with a metafile. Pass a filename
180  *  to create a disk-based metafile, NULL to create a memory metafile.
181  *
182  * RETURNS
183  *  A handle to the metafile DC if successful, NULL on failure.
184  */
185 HDC16 WINAPI CreateMetaFile16( 
186                               LPCSTR filename /* [in] Filename of disk metafile */
187 )
188 {
189     HDC ret;
190     DC *dc;
191     METAFILEDRV_PDEVICE *physDev;
192     HFILE hFile;
193
194     TRACE("'%s'\n", filename );
195
196     if (!(dc = MFDRV_AllocMetaFile())) return 0;
197     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
198     
199     if (filename)  /* disk based metafile */
200     {
201         physDev->mh->mtType = METAFILE_DISK;
202         if ((hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
203                                 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
204             MFDRV_DeleteDC( dc );
205             return 0;
206         }
207         if (!WriteFile( hFile, (LPSTR)physDev->mh, sizeof(*physDev->mh), NULL,
208                         NULL )) {
209             MFDRV_DeleteDC( dc );
210             return 0;
211         }
212         physDev->hFile = hFile;
213
214         /* Grow METAHEADER to include filename */
215         physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename);
216     }
217     else  /* memory based metafile */
218         physDev->mh->mtType = METAFILE_MEMORY;
219         
220     TRACE("returning %04x\n", dc->hSelf);
221     ret = dc->hSelf;
222     GDI_ReleaseObj( dc->hSelf );
223     return ret;
224 }
225
226 /**********************************************************************
227  *           CreateMetaFileA   (GDI32.@)
228  */
229 HDC WINAPI CreateMetaFileA( 
230                               LPCSTR filename /* [in] Filename of disk metafile */
231 )
232 {
233   return CreateMetaFile16( filename );
234 }
235
236 /**********************************************************************
237  *          CreateMetaFileW   (GDI32.@)
238  */
239 HDC WINAPI CreateMetaFileW(LPCWSTR filename)
240 {
241     LPSTR filenameA;
242     HDC hReturnDC;
243
244     filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
245
246     hReturnDC = CreateMetaFileA(filenameA);
247
248     HeapFree( GetProcessHeap(), 0, filenameA );
249
250     return hReturnDC;
251 }
252
253
254 /**********************************************************************
255  *          MFDRV_CloseMetaFile
256  */
257 static DC *MFDRV_CloseMetaFile( HDC hdc ) 
258 {
259     DC *dc;
260     METAFILEDRV_PDEVICE *physDev;
261     
262     TRACE("(%04x)\n", hdc );
263
264     if (!(dc = (DC *) GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
265     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
266
267     /* Construct the end of metafile record - this is documented
268      * in SDK Knowledgebase Q99334.
269      */
270
271     if (!MFDRV_MetaParam0(dc, META_EOF))
272     {
273         MFDRV_DeleteDC( dc );
274         return 0;
275     }   
276
277     if (physDev->mh->mtType == METAFILE_DISK)  /* disk based metafile */
278     {
279         if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) {
280             MFDRV_DeleteDC( dc );
281             return 0;
282         }
283
284         physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */
285         if (!WriteFile(physDev->hFile, (LPSTR)physDev->mh,
286                        sizeof(*physDev->mh), NULL, NULL)) {
287             MFDRV_DeleteDC( dc );
288             return 0;
289         }
290         CloseHandle(physDev->hFile);
291         physDev->mh->mtType = METAFILE_DISK;
292     }
293
294     return dc;
295 }
296
297 /******************************************************************
298  *           CloseMetaFile16   (GDI.126)
299  *           CloseMetaFile16   (GDI32.@)
300  */
301 HMETAFILE16 WINAPI CloseMetaFile16( 
302                                    HDC16 hdc /* [in] Metafile DC to close */
303 )
304 {
305     HMETAFILE16 hmf;
306     METAFILEDRV_PDEVICE *physDev;
307     DC *dc = MFDRV_CloseMetaFile(hdc);
308     if (!dc) return 0;
309     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
310
311     /* Now allocate a global handle for the metafile */
312
313     hmf = MF_Create_HMETAFILE16( physDev->mh );
314
315     physDev->mh = NULL;  /* So it won't be deleted */
316     MFDRV_DeleteDC( dc );
317     return hmf;
318 }
319
320 /******************************************************************
321  *           CloseMetaFile   (GDI32.@)
322  *
323  *  Stop recording graphics operations in metafile associated with
324  *  hdc and retrieve metafile.
325  *
326  * RETURNS
327  *  Handle of newly created metafile on success, NULL on failure.
328  */
329 HMETAFILE WINAPI CloseMetaFile( 
330                                    HDC hdc /* [in] Metafile DC to close */
331 )
332 {
333     HMETAFILE hmf;
334     METAFILEDRV_PDEVICE *physDev;
335     DC *dc = MFDRV_CloseMetaFile(hdc);
336     if (!dc) return 0;
337     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
338
339     /* Now allocate a global handle for the metafile */
340
341     hmf = MF_Create_HMETAFILE( physDev->mh );
342
343     physDev->mh = NULL;  /* So it won't be deleted */
344     MFDRV_DeleteDC( dc );
345     return hmf;
346 }
347
348
349 /******************************************************************
350  *         MFDRV_WriteRecord
351  *
352  * Warning: this function can change the pointer to the metafile header.
353  */
354 BOOL MFDRV_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
355 {
356     DWORD len;
357     METAHEADER *mh;
358     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
359
360     switch(physDev->mh->mtType)
361     {
362     case METAFILE_MEMORY:
363         len = physDev->mh->mtSize * 2 + rlen;
364         mh = HeapReAlloc( GetProcessHeap(), 0, physDev->mh, len );
365         if (!mh) return FALSE;
366         physDev->mh = mh;
367         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
368         break;
369     case METAFILE_DISK:
370         TRACE("Writing record to disk\n");
371         if (!WriteFile(physDev->hFile, (char *)mr, rlen, NULL, NULL))
372             return FALSE;
373         break;
374     default:
375         ERR("Unknown metafile type %d\n", physDev->mh->mtType );
376         return FALSE;
377     }
378
379     physDev->mh->mtSize += rlen / 2;
380     physDev->mh->mtMaxRecord = max(physDev->mh->mtMaxRecord, rlen / 2);
381     return TRUE;
382 }
383
384
385 /******************************************************************
386  *         MFDRV_MetaParam0
387  */
388
389 BOOL MFDRV_MetaParam0(DC *dc, short func)
390 {
391     char buffer[8];
392     METARECORD *mr = (METARECORD *)&buffer;
393     
394     mr->rdSize = 3;
395     mr->rdFunction = func;
396     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
397 }
398
399
400 /******************************************************************
401  *         MFDRV_MetaParam1
402  */
403 BOOL MFDRV_MetaParam1(DC *dc, short func, short param1)
404 {
405     char buffer[8];
406     METARECORD *mr = (METARECORD *)&buffer;
407     
408     mr->rdSize = 4;
409     mr->rdFunction = func;
410     *(mr->rdParm) = param1;
411     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
412 }
413
414
415 /******************************************************************
416  *         MFDRV_MetaParam2
417  */
418 BOOL MFDRV_MetaParam2(DC *dc, short func, short param1, short param2)
419 {
420     char buffer[10];
421     METARECORD *mr = (METARECORD *)&buffer;
422     
423     mr->rdSize = 5;
424     mr->rdFunction = func;
425     *(mr->rdParm) = param2;
426     *(mr->rdParm + 1) = param1;
427     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
428 }
429
430
431 /******************************************************************
432  *         MFDRV_MetaParam4
433  */
434
435 BOOL MFDRV_MetaParam4(DC *dc, short func, short param1, short param2, 
436                       short param3, short param4)
437 {
438     char buffer[14];
439     METARECORD *mr = (METARECORD *)&buffer;
440     
441     mr->rdSize = 7;
442     mr->rdFunction = func;
443     *(mr->rdParm) = param4;
444     *(mr->rdParm + 1) = param3;
445     *(mr->rdParm + 2) = param2;
446     *(mr->rdParm + 3) = param1;
447     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
448 }
449
450
451 /******************************************************************
452  *         MFDRV_MetaParam6
453  */
454
455 BOOL MFDRV_MetaParam6(DC *dc, short func, short param1, short param2, 
456                       short param3, short param4, short param5, short param6)
457 {
458     char buffer[18];
459     METARECORD *mr = (METARECORD *)&buffer;
460     
461     mr->rdSize = 9;
462     mr->rdFunction = func;
463     *(mr->rdParm) = param6;
464     *(mr->rdParm + 1) = param5;
465     *(mr->rdParm + 2) = param4;
466     *(mr->rdParm + 3) = param3;
467     *(mr->rdParm + 4) = param2;
468     *(mr->rdParm + 5) = param1;
469     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
470 }
471
472
473 /******************************************************************
474  *         MFDRV_MetaParam8
475  */
476 BOOL MFDRV_MetaParam8(DC *dc, short func, short param1, short param2, 
477                       short param3, short param4, short param5,
478                       short param6, short param7, short param8)
479 {
480     char buffer[22];
481     METARECORD *mr = (METARECORD *)&buffer;
482     
483     mr->rdSize = 11;
484     mr->rdFunction = func;
485     *(mr->rdParm) = param8;
486     *(mr->rdParm + 1) = param7;
487     *(mr->rdParm + 2) = param6;
488     *(mr->rdParm + 3) = param5;
489     *(mr->rdParm + 4) = param4;
490     *(mr->rdParm + 5) = param3;
491     *(mr->rdParm + 6) = param2;
492     *(mr->rdParm + 7) = param1;
493     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
494 }
495
496
497 /******************************************************************
498  *         MFDRV_AddHandleDC
499  *
500  * Note: this function assumes that we never delete objects.
501  * If we do someday, we'll need to maintain a table to re-use deleted
502  * handles.
503  */
504 int MFDRV_AddHandleDC( DC *dc )
505 {
506     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
507     physDev->mh->mtNoObjects++;
508     return physDev->nextHandle++;
509 }
510
511