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