msxml3: Basic refcount test for IMXNamespacePrefixes.
[wine.git] / dlls / gdi32 / mfdrv / objects.c
blob34a405d3a1ccac937267d1f1c635a19e98e2268e
1 /*
2 * GDI objects
4 * Copyright 1993 Alexandre Julliard
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.
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.
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
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdarg.h>
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"
34 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
36 /******************************************************************
37 * MFDRV_AddHandle
39 UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
41 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
42 UINT16 index;
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]));
52 physDev->handles[index] = obj;
54 physDev->cur_handles++;
55 if(physDev->cur_handles > physDev->mh->mtNoObjects)
56 physDev->mh->mtNoObjects++;
58 return index ; /* index 0 is not reserved for metafiles */
61 /******************************************************************
62 * MFDRV_RemoveHandle
64 BOOL MFDRV_RemoveHandle( PHYSDEV dev, UINT index )
66 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
67 BOOL ret = FALSE;
69 if (index < physDev->handles_size && physDev->handles[index])
71 physDev->handles[index] = 0;
72 physDev->cur_handles--;
73 ret = TRUE;
75 return ret;
78 /******************************************************************
79 * MFDRV_FindObject
81 static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
83 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
84 INT16 index;
86 for(index = 0; index < physDev->handles_size; index++)
87 if(physDev->handles[index] == obj) break;
89 if(index == physDev->handles_size) return -1;
91 return index ;
95 /******************************************************************
96 * MFDRV_DeleteObject
98 BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
100 METARECORD mr;
101 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
102 INT16 index;
103 BOOL ret = TRUE;
105 index = MFDRV_FindObject(dev, obj);
106 if( index < 0 )
107 return 0;
109 mr.rdSize = sizeof mr / 2;
110 mr.rdFunction = META_DELETEOBJECT;
111 mr.rdParm[0] = index;
113 if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
114 ret = FALSE;
116 physDev->handles[index] = 0;
117 physDev->cur_handles--;
118 return ret;
122 /***********************************************************************
123 * MFDRV_SelectObject
125 static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
127 METARECORD mr;
129 mr.rdSize = sizeof mr / 2;
130 mr.rdFunction = META_SELECTOBJECT;
131 mr.rdParm[0] = index;
133 return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
137 /***********************************************************************
138 * MFDRV_SelectBitmap
140 HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
142 return 0;
145 /******************************************************************
146 * MFDRV_CreateBrushIndirect
149 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
151 DWORD size;
152 METARECORD *mr;
153 LOGBRUSH logbrush;
154 BOOL r;
156 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
158 switch(logbrush.lbStyle)
160 case BS_SOLID:
161 case BS_NULL:
162 case BS_HATCHED:
164 LOGBRUSH16 lb16;
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;
176 case BS_PATTERN:
177 case BS_DIBPATTERN:
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;
186 if (!get_brush_bitmap_info( hBrush, src_info, &bits, &usage )) goto done;
188 info_size = get_dib_info_size( src_info, usage );
189 size = FIELD_OFFSET( METARECORD, rdParm[2] ) + info_size + src_info->bmiHeader.biSizeImage;
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;
202 /* always return a bottom-up DIB */
203 if (dst_info->bmiHeader.biHeight < 0)
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 );
212 else memcpy( dst_ptr, bits, src_info->bmiHeader.biSizeImage );
213 break;
216 default:
217 FIXME("Unknown brush style %x\n", logbrush.lbStyle);
218 return 0;
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 );
229 /***********************************************************************
230 * MFDRV_SelectBrush
232 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern )
234 INT16 index;
236 index = MFDRV_FindObject(dev, hbrush);
237 if( index < 0 )
239 index = MFDRV_CreateBrushIndirect( dev, hbrush );
240 if( index < 0 )
241 return 0;
242 GDI_hdc_using_object(hbrush, dev->hdc);
244 return MFDRV_SelectObject( dev, index ) ? hbrush : 0;
247 /******************************************************************
248 * MFDRV_CreateFontIndirect
251 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
253 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
254 METARECORD *mr = (METARECORD *)&buffer;
255 LOGFONT16 *font16;
256 INT written;
258 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
259 mr->rdFunction = META_CREATEFONTINDIRECT;
260 font16 = (LOGFONT16 *)&mr->rdParm;
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);
279 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
280 return 0;
281 return MFDRV_AddHandle( dev, hFont );
285 /***********************************************************************
286 * MFDRV_SelectFont
288 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont )
290 LOGFONTW font;
291 INT16 index;
293 index = MFDRV_FindObject(dev, hfont);
294 if( index < 0 )
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);
303 return MFDRV_SelectObject( dev, index ) ? hfont : 0;
306 /******************************************************************
307 * MFDRV_CreatePenIndirect
309 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
311 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
312 METARECORD *mr = (METARECORD *)&buffer;
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 );
323 /***********************************************************************
324 * MFDRV_SelectPen
326 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern )
328 LOGPEN16 logpen;
329 INT16 index;
331 index = MFDRV_FindObject(dev, hpen);
332 if( index < 0 )
334 /* must be an extended pen */
335 INT size = GetObjectW( hpen, 0, NULL );
337 if (!size) return 0;
339 if (size == sizeof(LOGPEN))
341 LOGPEN pen;
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;
349 else /* must be an extended pen */
351 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
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;
360 HeapFree( GetProcessHeap(), 0, elp );
363 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
364 if( index < 0 )
365 return 0;
366 GDI_hdc_using_object(hpen, dev->hdc);
368 return MFDRV_SelectObject( dev, index ) ? hpen : 0;
372 /******************************************************************
373 * MFDRV_CreatePalette
375 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
377 int index;
378 BOOL ret;
379 METARECORD *mr;
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))))
387 HeapFree(GetProcessHeap(), 0, mr);
388 return FALSE;
391 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
392 mr->rdFunction = META_SELECTPALETTE;
394 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
395 else
397 *(mr->rdParm) = index;
398 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
400 HeapFree(GetProcessHeap(), 0, mr);
401 return ret;
405 /***********************************************************************
406 * MFDRV_SelectPalette
408 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
410 #define PALVERSION 0x0300
412 PLOGPALETTE logPalette;
413 WORD wNumEntries = 0;
414 BOOL creationSucceed;
415 int sizeofPalette;
417 GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
419 if (wNumEntries == 0) return 0;
421 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
422 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
424 if (logPalette == NULL) return 0;
426 logPalette->palVersion = PALVERSION;
427 logPalette->palNumEntries = wNumEntries;
429 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
431 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
433 HeapFree( GetProcessHeap(), 0, logPalette );
435 if (creationSucceed)
436 return hPalette;
438 return 0;
441 /***********************************************************************
442 * MFDRV_RealizePalette
444 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
446 char buffer[sizeof(METARECORD) - sizeof(WORD)];
447 METARECORD *mr = (METARECORD *)&buffer;
449 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
450 mr->rdFunction = META_REALIZEPALETTE;
452 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
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;