user32: When building linedefs prev can be less than 0 if the format width is less...
[wine.git] / dlls / gdi32 / mfdrv / objects.c
blob150fb22f383ce9d261d6f573c28444b927bc51d8
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:
178 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
179 BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer;
180 struct gdi_image_bits bits;
181 COLORREF cref;
183 if (!get_bitmap_image( (HANDLE)logbrush.lbHatch, src_info, &bits )) goto done;
184 if (src_info->bmiHeader.biBitCount != 1)
186 FIXME("Trying to store a colour pattern brush\n");
187 if (bits.free) bits.free( &bits );
188 goto done;
191 size = FIELD_OFFSET( METARECORD, rdParm[2] ) +
192 FIELD_OFFSET( BITMAPINFO, bmiColors[2] ) + src_info->bmiHeader.biSizeImage;
194 if (!(mr = HeapAlloc( GetProcessHeap(), 0, size )))
196 if (bits.free) bits.free( &bits );
197 goto done;
199 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
200 mr->rdSize = size / 2;
201 mr->rdParm[0] = BS_PATTERN;
202 mr->rdParm[1] = DIB_RGB_COLORS;
203 dst_info = (BITMAPINFO *)(mr->rdParm + 2);
204 dst_info->bmiHeader = src_info->bmiHeader;
205 dst_info->bmiHeader.biClrUsed = 0;
206 cref = GetTextColor( dev->hdc );
207 dst_info->bmiColors[0].rgbRed = GetRValue(cref);
208 dst_info->bmiColors[0].rgbGreen = GetGValue(cref);
209 dst_info->bmiColors[0].rgbBlue = GetBValue(cref);
210 dst_info->bmiColors[0].rgbReserved = 0;
211 cref = GetBkColor( dev->hdc );
212 dst_info->bmiColors[1].rgbRed = GetRValue(cref);
213 dst_info->bmiColors[1].rgbGreen = GetGValue(cref);
214 dst_info->bmiColors[1].rgbBlue = GetBValue(cref);
215 dst_info->bmiColors[1].rgbReserved = 0;
217 /* always return a bottom-up DIB */
218 if (dst_info->bmiHeader.biHeight < 0)
220 int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth,
221 dst_info->bmiHeader.biBitCount );
222 char *dst_ptr = (char *)&dst_info->bmiColors[2];
223 dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight;
224 dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes;
225 for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes)
226 memcpy( dst_ptr, (char *)bits.ptr + i * width_bytes, width_bytes );
228 else memcpy( &dst_info->bmiColors[2], bits.ptr, dst_info->bmiHeader.biSizeImage );
229 if (bits.free) bits.free( &bits );
230 break;
233 case BS_DIBPATTERN:
235 BITMAPINFO *info;
236 DWORD bmSize, biSize;
238 info = GlobalLock( (HGLOBAL)logbrush.lbHatch );
239 if (info->bmiHeader.biCompression)
240 bmSize = info->bmiHeader.biSizeImage;
241 else
242 bmSize = get_dib_image_size( info );
243 biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor));
244 size = sizeof(METARECORD) + biSize + bmSize + 2;
245 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
246 if (!mr)
248 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
249 goto done;
251 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
252 mr->rdSize = size / 2;
253 *(mr->rdParm) = logbrush.lbStyle;
254 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
255 memcpy(mr->rdParm + 2, info, biSize + bmSize);
256 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
257 break;
259 default:
260 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
261 return 0;
263 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
264 HeapFree(GetProcessHeap(), 0, mr);
265 if( !r )
266 return -1;
267 done:
268 return MFDRV_AddHandle( dev, hBrush );
272 /***********************************************************************
273 * MFDRV_SelectBrush
275 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
277 INT16 index;
279 index = MFDRV_FindObject(dev, hbrush);
280 if( index < 0 )
282 index = MFDRV_CreateBrushIndirect( dev, hbrush );
283 if( index < 0 )
284 return 0;
285 GDI_hdc_using_object(hbrush, dev->hdc);
287 return MFDRV_SelectObject( dev, index ) ? hbrush : 0;
290 /******************************************************************
291 * MFDRV_CreateFontIndirect
294 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
296 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
297 METARECORD *mr = (METARECORD *)&buffer;
298 LOGFONT16 *font16;
299 INT written;
301 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
302 mr->rdFunction = META_CREATEFONTINDIRECT;
303 font16 = (LOGFONT16 *)&mr->rdParm;
305 font16->lfHeight = logfont->lfHeight;
306 font16->lfWidth = logfont->lfWidth;
307 font16->lfEscapement = logfont->lfEscapement;
308 font16->lfOrientation = logfont->lfOrientation;
309 font16->lfWeight = logfont->lfWeight;
310 font16->lfItalic = logfont->lfItalic;
311 font16->lfUnderline = logfont->lfUnderline;
312 font16->lfStrikeOut = logfont->lfStrikeOut;
313 font16->lfCharSet = logfont->lfCharSet;
314 font16->lfOutPrecision = logfont->lfOutPrecision;
315 font16->lfClipPrecision = logfont->lfClipPrecision;
316 font16->lfQuality = logfont->lfQuality;
317 font16->lfPitchAndFamily = logfont->lfPitchAndFamily;
318 written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName, LF_FACESIZE - 1, NULL, NULL );
319 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
320 memset(font16->lfFaceName + written, 0, LF_FACESIZE - written);
322 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
323 return 0;
324 return MFDRV_AddHandle( dev, hFont );
328 /***********************************************************************
329 * MFDRV_SelectFont
331 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont )
333 LOGFONTW font;
334 INT16 index;
336 index = MFDRV_FindObject(dev, hfont);
337 if( index < 0 )
339 if (!GetObjectW( hfont, sizeof(font), &font ))
340 return 0;
341 index = MFDRV_CreateFontIndirect(dev, hfont, &font);
342 if( index < 0 )
343 return 0;
344 GDI_hdc_using_object(hfont, dev->hdc);
346 return MFDRV_SelectObject( dev, index ) ? hfont : 0;
349 /******************************************************************
350 * MFDRV_CreatePenIndirect
352 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
354 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
355 METARECORD *mr = (METARECORD *)&buffer;
357 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
358 mr->rdFunction = META_CREATEPENINDIRECT;
359 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
360 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
361 return 0;
362 return MFDRV_AddHandle( dev, hPen );
366 /***********************************************************************
367 * MFDRV_SelectPen
369 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
371 LOGPEN16 logpen;
372 INT16 index;
374 index = MFDRV_FindObject(dev, hpen);
375 if( index < 0 )
377 /* must be an extended pen */
378 INT size = GetObjectW( hpen, 0, NULL );
380 if (!size) return 0;
382 if (size == sizeof(LOGPEN))
384 LOGPEN pen;
386 GetObjectW( hpen, sizeof(pen), &pen );
387 logpen.lopnStyle = pen.lopnStyle;
388 logpen.lopnWidth.x = pen.lopnWidth.x;
389 logpen.lopnWidth.y = pen.lopnWidth.y;
390 logpen.lopnColor = pen.lopnColor;
392 else /* must be an extended pen */
394 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
396 GetObjectW( hpen, size, elp );
397 /* FIXME: add support for user style pens */
398 logpen.lopnStyle = elp->elpPenStyle;
399 logpen.lopnWidth.x = elp->elpWidth;
400 logpen.lopnWidth.y = 0;
401 logpen.lopnColor = elp->elpColor;
403 HeapFree( GetProcessHeap(), 0, elp );
406 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
407 if( index < 0 )
408 return 0;
409 GDI_hdc_using_object(hpen, dev->hdc);
411 return MFDRV_SelectObject( dev, index ) ? hpen : 0;
415 /******************************************************************
416 * MFDRV_CreatePalette
418 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
420 int index;
421 BOOL ret;
422 METARECORD *mr;
424 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
425 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
426 mr->rdFunction = META_CREATEPALETTE;
427 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
428 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
430 HeapFree(GetProcessHeap(), 0, mr);
431 return FALSE;
434 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
435 mr->rdFunction = META_SELECTPALETTE;
437 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
438 else
440 *(mr->rdParm) = index;
441 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
443 HeapFree(GetProcessHeap(), 0, mr);
444 return ret;
448 /***********************************************************************
449 * MFDRV_SelectPalette
451 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
453 #define PALVERSION 0x0300
455 PLOGPALETTE logPalette;
456 WORD wNumEntries = 0;
457 BOOL creationSucceed;
458 int sizeofPalette;
460 GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
462 if (wNumEntries == 0) return 0;
464 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
465 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
467 if (logPalette == NULL) return 0;
469 logPalette->palVersion = PALVERSION;
470 logPalette->palNumEntries = wNumEntries;
472 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
474 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
476 HeapFree( GetProcessHeap(), 0, logPalette );
478 if (creationSucceed)
479 return hPalette;
481 return 0;
484 /***********************************************************************
485 * MFDRV_RealizePalette
487 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
489 char buffer[sizeof(METARECORD) - sizeof(WORD)];
490 METARECORD *mr = (METARECORD *)&buffer;
492 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
493 mr->rdFunction = META_REALIZEPALETTE;
495 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
497 /* The return value is suppose to be the number of entries
498 in the logical palette mapped to the system palette or 0
499 if the function failed. Since it's not trivial here to
500 get that kind of information and since it's of little
501 use in the case of metafiles, we'll always return 1. */
502 return 1;