59fe08a71d4881307ac91f0513450550739a4686
[reactos.git] / reactos / win32ss / gdi / gdi32 / wine / 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] = get_full_gdi_handle( 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 FALSE;
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[sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD)]; // ros
180 //char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
181 BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer;
182 DWORD info_size;
183 char *dst_ptr;
184 void *bits;
185 UINT usage;
186
187 if (!get_brush_bitmap_info( hBrush, src_info, &bits, &usage )) goto done;
188
189 info_size = get_dib_info_size( src_info, usage );
190 size = FIELD_OFFSET( METARECORD, rdParm[2] ) + info_size + src_info->bmiHeader.biSizeImage;
191
192 if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) goto done;
193 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
194 mr->rdSize = size / 2;
195 mr->rdParm[0] = logbrush.lbStyle;
196 mr->rdParm[1] = usage;
197 dst_info = (BITMAPINFO *)(mr->rdParm + 2);
198 memcpy( dst_info, src_info, info_size );
199 if (dst_info->bmiHeader.biClrUsed == 1 << dst_info->bmiHeader.biBitCount)
200 dst_info->bmiHeader.biClrUsed = 0;
201 dst_ptr = (char *)dst_info + info_size;
202
203 /* always return a bottom-up DIB */
204 if (dst_info->bmiHeader.biHeight < 0)
205 {
206 int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth,
207 dst_info->bmiHeader.biBitCount );
208 dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight;
209 dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes;
210 for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes)
211 memcpy( dst_ptr, (char *)bits + i * width_bytes, width_bytes );
212 }
213 else memcpy( dst_ptr, bits, src_info->bmiHeader.biSizeImage );
214 break;
215 }
216
217 default:
218 FIXME("Unknown brush style %x\n", logbrush.lbStyle);
219 return 0;
220 }
221 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
222 HeapFree(GetProcessHeap(), 0, mr);
223 if( !r )
224 return -1;
225 done:
226 return MFDRV_AddHandle( dev, hBrush );
227 }
228
229
230 /***********************************************************************
231 * MFDRV_SelectBrush
232 */
233 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern )
234 {
235 INT16 index;
236
237 index = MFDRV_FindObject(dev, hbrush);
238 if( index < 0 )
239 {
240 index = MFDRV_CreateBrushIndirect( dev, hbrush );
241 if( index < 0 )
242 return 0;
243 GDI_hdc_using_object(hbrush, dev->hdc);
244 }
245 return MFDRV_SelectObject( dev, index ) ? hbrush : 0;
246 }
247
248 /******************************************************************
249 * MFDRV_CreateFontIndirect
250 */
251
252 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
253 {
254 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
255 METARECORD *mr = (METARECORD *)&buffer;
256 LOGFONT16 *font16;
257 INT written;
258
259 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
260 mr->rdFunction = META_CREATEFONTINDIRECT;
261 font16 = (LOGFONT16 *)&mr->rdParm;
262
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);
279
280 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
281 return 0;
282 return MFDRV_AddHandle( dev, hFont );
283 }
284
285
286 /***********************************************************************
287 * MFDRV_SelectFont
288 */
289 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
290 {
291 LOGFONTW font;
292 INT16 index;
293
294 *aa_flags = GGO_BITMAP; /* no point in anti-aliasing on metafiles */
295 index = MFDRV_FindObject(dev, hfont);
296 if( index < 0 )
297 {
298 if (!GetObjectW( hfont, sizeof(font), &font ))
299 return 0;
300 index = MFDRV_CreateFontIndirect(dev, hfont, &font);
301 if( index < 0 )
302 return 0;
303 GDI_hdc_using_object(hfont, dev->hdc);
304 }
305 return MFDRV_SelectObject( dev, index ) ? hfont : 0;
306 }
307
308 /******************************************************************
309 * MFDRV_CreatePenIndirect
310 */
311 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
312 {
313 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
314 METARECORD *mr = (METARECORD *)&buffer;
315
316 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
317 mr->rdFunction = META_CREATEPENINDIRECT;
318 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
319 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
320 return 0;
321 return MFDRV_AddHandle( dev, hPen );
322 }
323
324
325 /***********************************************************************
326 * MFDRV_SelectPen
327 */
328 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern )
329 {
330 LOGPEN16 logpen;
331 INT16 index;
332
333 index = MFDRV_FindObject(dev, hpen);
334 if( index < 0 )
335 {
336 /* must be an extended pen */
337 INT size = GetObjectW( hpen, 0, NULL );
338
339 if (!size) return 0;
340
341 if (size == sizeof(LOGPEN))
342 {
343 LOGPEN pen;
344
345 GetObjectW( hpen, sizeof(pen), &pen );
346 logpen.lopnStyle = pen.lopnStyle;
347 logpen.lopnWidth.x = pen.lopnWidth.x;
348 logpen.lopnWidth.y = pen.lopnWidth.y;
349 logpen.lopnColor = pen.lopnColor;
350 }
351 else /* must be an extended pen */
352 {
353 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
354
355 GetObjectW( hpen, size, elp );
356 /* FIXME: add support for user style pens */
357 logpen.lopnStyle = elp->elpPenStyle;
358 logpen.lopnWidth.x = elp->elpWidth;
359 logpen.lopnWidth.y = 0;
360 logpen.lopnColor = elp->elpColor;
361
362 HeapFree( GetProcessHeap(), 0, elp );
363 }
364
365 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
366 if( index < 0 )
367 return 0;
368 GDI_hdc_using_object(hpen, dev->hdc);
369 }
370 return MFDRV_SelectObject( dev, index ) ? hpen : 0;
371 }
372
373
374 /******************************************************************
375 * MFDRV_CreatePalette
376 */
377 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
378 {
379 int index;
380 BOOL ret;
381 METARECORD *mr;
382
383 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
384 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
385 mr->rdFunction = META_CREATEPALETTE;
386 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
387 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
388 {
389 HeapFree(GetProcessHeap(), 0, mr);
390 return FALSE;
391 }
392
393 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
394 mr->rdFunction = META_SELECTPALETTE;
395
396 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
397 else
398 {
399 *(mr->rdParm) = index;
400 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
401 }
402 HeapFree(GetProcessHeap(), 0, mr);
403 return ret;
404 }
405
406
407 /***********************************************************************
408 * MFDRV_SelectPalette
409 */
410 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
411 {
412 #define PALVERSION 0x0300
413
414 PLOGPALETTE logPalette;
415 WORD wNumEntries = 0;
416 BOOL creationSucceed;
417 int sizeofPalette;
418
419 GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
420
421 if (wNumEntries == 0) return 0;
422
423 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
424 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
425
426 if (logPalette == NULL) return 0;
427
428 logPalette->palVersion = PALVERSION;
429 logPalette->palNumEntries = wNumEntries;
430
431 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
432
433 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
434
435 HeapFree( GetProcessHeap(), 0, logPalette );
436
437 if (creationSucceed)
438 return hPalette;
439
440 return 0;
441 }
442
443 /***********************************************************************
444 * MFDRV_RealizePalette
445 */
446 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
447 {
448 char buffer[sizeof(METARECORD) - sizeof(WORD)];
449 METARECORD *mr = (METARECORD *)&buffer;
450
451 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
452 mr->rdFunction = META_REALIZEPALETTE;
453
454 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
455
456 /* The return value is suppose to be the number of entries
457 in the logical palette mapped to the system palette or 0
458 if the function failed. Since it's not trivial here to
459 get that kind of information and since it's of little
460 use in the case of metafiles, we'll always return 1. */
461 return 1;
462 }