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