opengl32: Move checks of the context thread id to opengl32.
[wine] / dlls / gdi32 / mfdrv / objects.c
1 /*
2  * GDI objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "wine/wingdi16.h"
30 #include "mfdrv/metafiledrv.h"
31 #include "gdi_private.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
35
36 /******************************************************************
37  *         MFDRV_AddHandle
38  */
39 UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
40 {
41     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
42     UINT16 index;
43
44     for(index = 0; index < physDev->handles_size; index++)
45         if(physDev->handles[index] == 0) break; 
46     if(index == physDev->handles_size) {
47         physDev->handles_size += HANDLE_LIST_INC;
48         physDev->handles = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
49                                        physDev->handles,
50                                        physDev->handles_size * sizeof(physDev->handles[0]));
51     }
52     physDev->handles[index] = obj;
53
54     physDev->cur_handles++; 
55     if(physDev->cur_handles > physDev->mh->mtNoObjects)
56         physDev->mh->mtNoObjects++;
57
58     return index ; /* index 0 is not reserved for metafiles */
59 }
60
61 /******************************************************************
62  *         MFDRV_RemoveHandle
63  */
64 BOOL MFDRV_RemoveHandle( PHYSDEV dev, UINT index )
65 {
66     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
67     BOOL ret = FALSE;
68
69     if (index < physDev->handles_size && physDev->handles[index])
70     {
71         physDev->handles[index] = 0;
72         physDev->cur_handles--;
73         ret = TRUE;
74     }
75     return ret;
76 }
77
78 /******************************************************************
79  *         MFDRV_FindObject
80  */
81 static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
82 {
83     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
84     INT16 index;
85
86     for(index = 0; index < physDev->handles_size; index++)
87         if(physDev->handles[index] == obj) break;
88
89     if(index == physDev->handles_size) return -1;
90
91     return index ;
92 }
93
94
95 /******************************************************************
96  *         MFDRV_DeleteObject
97  */
98 BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
99 {
100     METARECORD mr;
101     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
102     INT16 index;
103     BOOL ret = TRUE;
104
105     index = MFDRV_FindObject(dev, obj);
106     if( index < 0 )
107         return 0;
108
109     mr.rdSize = sizeof mr / 2;
110     mr.rdFunction = META_DELETEOBJECT;
111     mr.rdParm[0] = index;
112
113     if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
114         ret = FALSE;
115
116     physDev->handles[index] = 0;
117     physDev->cur_handles--;
118     return ret;
119 }
120
121
122 /***********************************************************************
123  *           MFDRV_SelectObject
124  */
125 static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
126 {
127     METARECORD mr;
128
129     mr.rdSize = sizeof mr / 2;
130     mr.rdFunction = META_SELECTOBJECT;
131     mr.rdParm[0] = index;
132
133     return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
134 }
135
136
137 /***********************************************************************
138  *           MFDRV_SelectBitmap
139  */
140 HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
141 {
142     return 0;
143 }
144
145 /******************************************************************
146  *         MFDRV_CreateBrushIndirect
147  */
148
149 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
150 {
151     DWORD size;
152     METARECORD *mr;
153     LOGBRUSH logbrush;
154     BOOL r;
155
156     if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
157
158     switch(logbrush.lbStyle)
159     {
160     case BS_SOLID:
161     case BS_NULL:
162     case BS_HATCHED:
163         {
164             LOGBRUSH16 lb16;
165
166             lb16.lbStyle = logbrush.lbStyle;
167             lb16.lbColor = logbrush.lbColor;
168             lb16.lbHatch = logbrush.lbHatch;
169             size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
170             mr = HeapAlloc( GetProcessHeap(), 0, size );
171             mr->rdSize = size / 2;
172             mr->rdFunction = META_CREATEBRUSHINDIRECT;
173             memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
174             break;
175         }
176     case BS_PATTERN:
177     case BS_DIBPATTERN:
178         {
179             char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
180             BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer;
181             DWORD info_size;
182             char *dst_ptr;
183             void *bits;
184             UINT usage;
185
186             if (!get_brush_bitmap_info( hBrush, src_info, &bits, &usage )) goto done;
187
188             info_size = get_dib_info_size( src_info, usage );
189             size = FIELD_OFFSET( METARECORD, rdParm[2] ) + info_size + src_info->bmiHeader.biSizeImage;
190
191             if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) goto done;
192             mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
193             mr->rdSize = size / 2;
194             mr->rdParm[0] = logbrush.lbStyle;
195             mr->rdParm[1] = usage;
196             dst_info = (BITMAPINFO *)(mr->rdParm + 2);
197             memcpy( dst_info, src_info, info_size );
198             if (dst_info->bmiHeader.biClrUsed == 1 << dst_info->bmiHeader.biBitCount)
199                 dst_info->bmiHeader.biClrUsed = 0;
200             dst_ptr = (char *)dst_info + info_size;
201
202             /* always return a bottom-up DIB */
203             if (dst_info->bmiHeader.biHeight < 0)
204             {
205                 int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth,
206                                                      dst_info->bmiHeader.biBitCount );
207                 dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight;
208                 dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes;
209                 for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes)
210                     memcpy( dst_ptr, (char *)bits + i * width_bytes, width_bytes );
211             }
212             else memcpy( dst_ptr, bits, src_info->bmiHeader.biSizeImage );
213             break;
214         }
215
216         default:
217             FIXME("Unknown brush style %x\n", logbrush.lbStyle);
218             return 0;
219     }
220     r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
221     HeapFree(GetProcessHeap(), 0, mr);
222     if( !r )
223         return -1;
224 done:
225     return MFDRV_AddHandle( dev, hBrush );
226 }
227
228
229 /***********************************************************************
230  *           MFDRV_SelectBrush
231  */
232 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern )
233 {
234     INT16 index;
235
236     index = MFDRV_FindObject(dev, hbrush);
237     if( index < 0 )
238     {
239         index = MFDRV_CreateBrushIndirect( dev, hbrush );
240         if( index < 0 )
241             return 0;
242         GDI_hdc_using_object(hbrush, dev->hdc);
243     }
244     return MFDRV_SelectObject( dev, index ) ? hbrush : 0;
245 }
246
247 /******************************************************************
248  *         MFDRV_CreateFontIndirect
249  */
250
251 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
252 {
253     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
254     METARECORD *mr = (METARECORD *)&buffer;
255     LOGFONT16 *font16;
256     INT written;
257
258     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
259     mr->rdFunction = META_CREATEFONTINDIRECT;
260     font16 = (LOGFONT16 *)&mr->rdParm;
261
262     font16->lfHeight         = logfont->lfHeight;
263     font16->lfWidth          = logfont->lfWidth;
264     font16->lfEscapement     = logfont->lfEscapement;
265     font16->lfOrientation    = logfont->lfOrientation;
266     font16->lfWeight         = logfont->lfWeight;
267     font16->lfItalic         = logfont->lfItalic;
268     font16->lfUnderline      = logfont->lfUnderline;
269     font16->lfStrikeOut      = logfont->lfStrikeOut;
270     font16->lfCharSet        = logfont->lfCharSet;
271     font16->lfOutPrecision   = logfont->lfOutPrecision;
272     font16->lfClipPrecision  = logfont->lfClipPrecision;
273     font16->lfQuality        = logfont->lfQuality;
274     font16->lfPitchAndFamily = logfont->lfPitchAndFamily;
275     written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName, LF_FACESIZE - 1, NULL, NULL );
276     /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
277     memset(font16->lfFaceName + written, 0, LF_FACESIZE - written);
278
279     if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
280         return 0;
281     return MFDRV_AddHandle( dev, hFont );
282 }
283
284
285 /***********************************************************************
286  *           MFDRV_SelectFont
287  */
288 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont )
289 {
290     LOGFONTW font;
291     INT16 index;
292
293     index = MFDRV_FindObject(dev, hfont);
294     if( index < 0 )
295     {
296         if (!GetObjectW( hfont, sizeof(font), &font ))
297             return 0;
298         index = MFDRV_CreateFontIndirect(dev, hfont, &font);
299         if( index < 0 )
300             return 0;
301         GDI_hdc_using_object(hfont, dev->hdc);
302     }
303     return MFDRV_SelectObject( dev, index ) ? hfont : 0;
304 }
305
306 /******************************************************************
307  *         MFDRV_CreatePenIndirect
308  */
309 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
310 {
311     char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
312     METARECORD *mr = (METARECORD *)&buffer;
313
314     mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
315     mr->rdFunction = META_CREATEPENINDIRECT;
316     memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
317     if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
318         return 0;
319     return MFDRV_AddHandle( dev, hPen );
320 }
321
322
323 /***********************************************************************
324  *           MFDRV_SelectPen
325  */
326 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern )
327 {
328     LOGPEN16 logpen;
329     INT16 index;
330
331     index = MFDRV_FindObject(dev, hpen);
332     if( index < 0 )
333     {
334         /* must be an extended pen */
335         INT size = GetObjectW( hpen, 0, NULL );
336
337         if (!size) return 0;
338
339         if (size == sizeof(LOGPEN))
340         {
341             LOGPEN pen;
342
343             GetObjectW( hpen, sizeof(pen), &pen );
344             logpen.lopnStyle   = pen.lopnStyle;
345             logpen.lopnWidth.x = pen.lopnWidth.x;
346             logpen.lopnWidth.y = pen.lopnWidth.y;
347             logpen.lopnColor   = pen.lopnColor;
348         }
349         else  /* must be an extended pen */
350         {
351             EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
352
353             GetObjectW( hpen, size, elp );
354             /* FIXME: add support for user style pens */
355             logpen.lopnStyle = elp->elpPenStyle;
356             logpen.lopnWidth.x = elp->elpWidth;
357             logpen.lopnWidth.y = 0;
358             logpen.lopnColor = elp->elpColor;
359
360             HeapFree( GetProcessHeap(), 0, elp );
361         }
362
363         index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
364         if( index < 0 )
365             return 0;
366         GDI_hdc_using_object(hpen, dev->hdc);
367     }
368     return MFDRV_SelectObject( dev, index ) ? hpen : 0;
369 }
370
371
372 /******************************************************************
373  *         MFDRV_CreatePalette
374  */
375 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
376 {
377     int index;
378     BOOL ret;
379     METARECORD *mr;
380
381     mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
382     mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
383     mr->rdFunction = META_CREATEPALETTE;
384     memcpy(&(mr->rdParm), logPalette, sizeofPalette);
385     if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
386     {
387         HeapFree(GetProcessHeap(), 0, mr);
388         return FALSE;
389     }
390
391     mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
392     mr->rdFunction = META_SELECTPALETTE;
393
394     if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
395     else
396     {
397         *(mr->rdParm) = index;
398         ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
399     }
400     HeapFree(GetProcessHeap(), 0, mr);
401     return ret;
402 }
403
404
405 /***********************************************************************
406  *           MFDRV_SelectPalette
407  */
408 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
409 {
410 #define PALVERSION 0x0300
411
412     PLOGPALETTE logPalette;
413     WORD        wNumEntries = 0;
414     BOOL        creationSucceed;
415     int         sizeofPalette;
416
417     GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
418
419     if (wNumEntries == 0) return 0;
420
421     sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
422     logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
423
424     if (logPalette == NULL) return 0;
425
426     logPalette->palVersion = PALVERSION;
427     logPalette->palNumEntries = wNumEntries;
428
429     GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
430
431     creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
432
433     HeapFree( GetProcessHeap(), 0, logPalette );
434
435     if (creationSucceed)
436         return hPalette;
437
438     return 0;
439 }
440
441 /***********************************************************************
442  *           MFDRV_RealizePalette
443  */
444 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
445 {
446     char buffer[sizeof(METARECORD) - sizeof(WORD)];
447     METARECORD *mr = (METARECORD *)&buffer;
448
449     mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
450     mr->rdFunction = META_REALIZEPALETTE;
451
452     if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
453
454     /* The return value is suppose to be the number of entries
455        in the logical palette mapped to the system palette or 0
456        if the function failed. Since it's not trivial here to
457        get that kind of information and since it's of little
458        use in the case of metafiles, we'll always return 1. */
459     return 1;
460 }