gdi32: Simplify computation of the DIB header size for internal BITMAPINFO structures.
[wine/multimedia.git] / dlls / gdi32 / mfdrv / objects.c
blob1489f4ed6a6986f3150c52e8c082bd23f40afb12
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("Unkonwn 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, HBITMAP bitmap,
233 const BITMAPINFO *info, void *bits, UINT usage )
235 INT16 index;
237 index = MFDRV_FindObject(dev, hbrush);
238 if( index < 0 )
240 index = MFDRV_CreateBrushIndirect( dev, hbrush );
241 if( index < 0 )
242 return 0;
243 GDI_hdc_using_object(hbrush, dev->hdc);
245 return MFDRV_SelectObject( dev, index ) ? hbrush : 0;
248 /******************************************************************
249 * MFDRV_CreateFontIndirect
252 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
254 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
255 METARECORD *mr = (METARECORD *)&buffer;
256 LOGFONT16 *font16;
257 INT written;
259 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
260 mr->rdFunction = META_CREATEFONTINDIRECT;
261 font16 = (LOGFONT16 *)&mr->rdParm;
263 font16->lfHeight = logfont->lfHeight;
264 font16->lfWidth = logfont->lfWidth;
265 font16->lfEscapement = logfont->lfEscapement;
266 font16->lfOrientation = logfont->lfOrientation;
267 font16->lfWeight = logfont->lfWeight;
268 font16->lfItalic = logfont->lfItalic;
269 font16->lfUnderline = logfont->lfUnderline;
270 font16->lfStrikeOut = logfont->lfStrikeOut;
271 font16->lfCharSet = logfont->lfCharSet;
272 font16->lfOutPrecision = logfont->lfOutPrecision;
273 font16->lfClipPrecision = logfont->lfClipPrecision;
274 font16->lfQuality = logfont->lfQuality;
275 font16->lfPitchAndFamily = logfont->lfPitchAndFamily;
276 written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName, LF_FACESIZE - 1, NULL, NULL );
277 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
278 memset(font16->lfFaceName + written, 0, LF_FACESIZE - written);
280 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
281 return 0;
282 return MFDRV_AddHandle( dev, hFont );
286 /***********************************************************************
287 * MFDRV_SelectFont
289 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont )
291 LOGFONTW font;
292 INT16 index;
294 index = MFDRV_FindObject(dev, hfont);
295 if( index < 0 )
297 if (!GetObjectW( hfont, sizeof(font), &font ))
298 return 0;
299 index = MFDRV_CreateFontIndirect(dev, hfont, &font);
300 if( index < 0 )
301 return 0;
302 GDI_hdc_using_object(hfont, dev->hdc);
304 return MFDRV_SelectObject( dev, index ) ? hfont : 0;
307 /******************************************************************
308 * MFDRV_CreatePenIndirect
310 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
312 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
313 METARECORD *mr = (METARECORD *)&buffer;
315 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
316 mr->rdFunction = META_CREATEPENINDIRECT;
317 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
318 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
319 return 0;
320 return MFDRV_AddHandle( dev, hPen );
324 /***********************************************************************
325 * MFDRV_SelectPen
327 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
329 LOGPEN16 logpen;
330 INT16 index;
332 index = MFDRV_FindObject(dev, hpen);
333 if( index < 0 )
335 /* must be an extended pen */
336 INT size = GetObjectW( hpen, 0, NULL );
338 if (!size) return 0;
340 if (size == sizeof(LOGPEN))
342 LOGPEN pen;
344 GetObjectW( hpen, sizeof(pen), &pen );
345 logpen.lopnStyle = pen.lopnStyle;
346 logpen.lopnWidth.x = pen.lopnWidth.x;
347 logpen.lopnWidth.y = pen.lopnWidth.y;
348 logpen.lopnColor = pen.lopnColor;
350 else /* must be an extended pen */
352 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
354 GetObjectW( hpen, size, elp );
355 /* FIXME: add support for user style pens */
356 logpen.lopnStyle = elp->elpPenStyle;
357 logpen.lopnWidth.x = elp->elpWidth;
358 logpen.lopnWidth.y = 0;
359 logpen.lopnColor = elp->elpColor;
361 HeapFree( GetProcessHeap(), 0, elp );
364 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
365 if( index < 0 )
366 return 0;
367 GDI_hdc_using_object(hpen, dev->hdc);
369 return MFDRV_SelectObject( dev, index ) ? hpen : 0;
373 /******************************************************************
374 * MFDRV_CreatePalette
376 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
378 int index;
379 BOOL ret;
380 METARECORD *mr;
382 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
383 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
384 mr->rdFunction = META_CREATEPALETTE;
385 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
386 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
388 HeapFree(GetProcessHeap(), 0, mr);
389 return FALSE;
392 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
393 mr->rdFunction = META_SELECTPALETTE;
395 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
396 else
398 *(mr->rdParm) = index;
399 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
401 HeapFree(GetProcessHeap(), 0, mr);
402 return ret;
406 /***********************************************************************
407 * MFDRV_SelectPalette
409 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
411 #define PALVERSION 0x0300
413 PLOGPALETTE logPalette;
414 WORD wNumEntries = 0;
415 BOOL creationSucceed;
416 int sizeofPalette;
418 GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
420 if (wNumEntries == 0) return 0;
422 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
423 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
425 if (logPalette == NULL) return 0;
427 logPalette->palVersion = PALVERSION;
428 logPalette->palNumEntries = wNumEntries;
430 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
432 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
434 HeapFree( GetProcessHeap(), 0, logPalette );
436 if (creationSucceed)
437 return hPalette;
439 return 0;
442 /***********************************************************************
443 * MFDRV_RealizePalette
445 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
447 char buffer[sizeof(METARECORD) - sizeof(WORD)];
448 METARECORD *mr = (METARECORD *)&buffer;
450 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
451 mr->rdFunction = META_REALIZEPALETTE;
453 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
455 /* The return value is suppose to be the number of entries
456 in the logical palette mapped to the system palette or 0
457 if the function failed. Since it's not trivial here to
458 get that kind of information and since it's of little
459 use in the case of metafiles, we'll always return 1. */
460 return 1;