Fixed a couple of crashes.
[wine.git] / objects / brush.c
blob4fe7c82fae964ce20fc656ab9684a6a9d6751862
1 /*
2 * GDI brush objects
4 * Copyright 1993, 1994 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <stdarg.h>
24 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "wine/wingdi16.h"
30 #include "gdi.h"
31 #include "wownt32.h"
32 #include "gdi_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
37 /* GDI logical brush object */
38 typedef struct
40 GDIOBJHDR header;
41 LOGBRUSH logbrush;
42 } BRUSHOBJ;
44 #define NB_HATCH_STYLES 6
46 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
47 static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
48 static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
49 static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj );
51 static const struct gdi_obj_funcs brush_funcs =
53 BRUSH_SelectObject, /* pSelectObject */
54 BRUSH_GetObject16, /* pGetObject16 */
55 BRUSH_GetObject, /* pGetObjectA */
56 BRUSH_GetObject, /* pGetObjectW */
57 NULL, /* pUnrealizeObject */
58 BRUSH_DeleteObject /* pDeleteObject */
61 static HGLOBAL16 dib_copy(BITMAPINFO *info, UINT coloruse)
63 BITMAPINFO *newInfo;
64 HGLOBAL16 hmem;
65 INT size;
67 if (info->bmiHeader.biCompression)
68 size = info->bmiHeader.biSizeImage;
69 else
70 size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
71 info->bmiHeader.biHeight,
72 info->bmiHeader.biBitCount);
73 size += DIB_BitmapInfoSize( info, coloruse );
75 if (!(hmem = GlobalAlloc16( GMEM_MOVEABLE, size )))
77 return 0;
79 newInfo = (BITMAPINFO *) GlobalLock16( hmem );
80 memcpy( newInfo, info, size );
81 GlobalUnlock16( hmem );
82 return hmem;
86 /***********************************************************************
87 * CreateBrushIndirect (GDI32.@)
89 * BUGS
90 * As for Windows 95 and Windows 98:
91 * Creating brushes from bitmaps or DIBs larger than 8x8 pixels
92 * is not supported. If a larger bitmap is given, only a portion
93 * of the bitmap is used.
95 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
97 BRUSHOBJ * ptr;
98 HBRUSH hbrush;
100 if (!(ptr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC,
101 (HGDIOBJ *)&hbrush, &brush_funcs ))) return 0;
102 ptr->logbrush.lbStyle = brush->lbStyle;
103 ptr->logbrush.lbColor = brush->lbColor;
104 ptr->logbrush.lbHatch = brush->lbHatch;
106 switch (ptr->logbrush.lbStyle)
108 case BS_PATTERN8X8:
109 ptr->logbrush.lbStyle = BS_PATTERN;
110 /* fall through */
111 case BS_PATTERN:
112 ptr->logbrush.lbHatch = (LONG)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch );
113 if (!ptr->logbrush.lbHatch) goto error;
114 break;
116 case BS_DIBPATTERNPT:
117 ptr->logbrush.lbStyle = BS_DIBPATTERN;
118 ptr->logbrush.lbHatch = (LONG)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch,
119 ptr->logbrush.lbColor);
120 if (!ptr->logbrush.lbHatch) goto error;
121 break;
123 case BS_DIBPATTERN8X8:
124 case BS_DIBPATTERN:
126 BITMAPINFO* bmi;
127 HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;
129 ptr->logbrush.lbStyle = BS_DIBPATTERN;
130 if (!(bmi = (BITMAPINFO *)GlobalLock( h ))) goto error;
131 ptr->logbrush.lbHatch = dib_copy( bmi, ptr->logbrush.lbColor);
132 GlobalUnlock( h );
133 if (!ptr->logbrush.lbHatch) goto error;
134 break;
137 default:
138 if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error;
139 break;
142 GDI_ReleaseObj( hbrush );
143 TRACE("%p\n", hbrush);
144 return hbrush;
146 error:
147 GDI_FreeObject( hbrush, ptr );
148 return 0;
152 /***********************************************************************
153 * CreateHatchBrush (GDI32.@)
155 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
157 LOGBRUSH logbrush;
159 TRACE("%d %06lx\n", style, color );
161 logbrush.lbStyle = BS_HATCHED;
162 logbrush.lbColor = color;
163 logbrush.lbHatch = style;
165 return CreateBrushIndirect( &logbrush );
169 /***********************************************************************
170 * CreatePatternBrush (GDI32.@)
172 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
174 LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
175 TRACE("%p\n", hbitmap );
177 logbrush.lbHatch = (ULONG_PTR)hbitmap;
178 return CreateBrushIndirect( &logbrush );
182 /***********************************************************************
183 * CreateDIBPatternBrush (GDI32.@)
185 * Create a logical brush which has the pattern specified by the DIB
187 * Function call is for compatibility only. CreateDIBPatternBrushPt should be used.
189 * RETURNS
191 * Handle to a logical brush on success, NULL on failure.
193 * BUGS
196 HBRUSH WINAPI CreateDIBPatternBrush(
197 HGLOBAL hbitmap, /* [in] Global object containg BITMAPINFO structure */
198 UINT coloruse /* [in] Specifies color format, if provided */
201 LOGBRUSH logbrush;
203 TRACE("%p\n", hbitmap );
205 logbrush.lbStyle = BS_DIBPATTERN;
206 logbrush.lbColor = coloruse;
208 logbrush.lbHatch = (LONG)hbitmap;
210 return CreateBrushIndirect( &logbrush );
214 /***********************************************************************
215 * CreateDIBPatternBrushPt (GDI32.@)
217 * Create a logical brush which has the pattern specified by the DIB
219 * RETURNS
221 * Handle to a logical brush on success, NULL on failure.
223 * BUGS
226 HBRUSH WINAPI CreateDIBPatternBrushPt(
227 const void* data, /* [in] Pointer to a BITMAPINFO structure followed by more data */
228 UINT coloruse /* [in] Specifies color format, if provided */
231 BITMAPINFO *info=(BITMAPINFO*)data;
232 LOGBRUSH logbrush;
234 if (!data)
235 return NULL;
237 TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth,
238 info->bmiHeader.biHeight, info->bmiHeader.biBitCount);
240 logbrush.lbStyle = BS_DIBPATTERNPT;
241 logbrush.lbColor = coloruse;
242 logbrush.lbHatch = (LONG) data;
244 return CreateBrushIndirect( &logbrush );
248 /***********************************************************************
249 * CreateSolidBrush (GDI32.@)
251 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
253 LOGBRUSH logbrush;
255 TRACE("%06lx\n", color );
257 logbrush.lbStyle = BS_SOLID;
258 logbrush.lbColor = color;
259 logbrush.lbHatch = 0;
261 return CreateBrushIndirect( &logbrush );
265 /***********************************************************************
266 * SetBrushOrgEx (GDI32.@)
268 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
270 DC *dc = DC_GetDCPtr( hdc );
272 if (!dc) return FALSE;
273 if (oldorg)
275 oldorg->x = dc->brushOrgX;
276 oldorg->y = dc->brushOrgY;
278 dc->brushOrgX = x;
279 dc->brushOrgY = y;
280 GDI_ReleaseObj( hdc );
281 return TRUE;
284 /***********************************************************************
285 * FixBrushOrgEx (GDI32.@)
286 * SDK says discontinued, but in Win95 GDI32 this is the same as SetBrushOrgEx
288 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
290 return SetBrushOrgEx(hdc,x,y,oldorg);
294 /***********************************************************************
295 * BRUSH_SelectObject
297 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
299 BRUSHOBJ *brush = obj;
300 HGDIOBJ ret;
301 DC *dc = DC_GetDCPtr( hdc );
303 if (!dc) return 0;
305 if (brush->logbrush.lbStyle == BS_PATTERN)
306 BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc );
308 ret = dc->hBrush;
309 if (dc->funcs->pSelectBrush) handle = dc->funcs->pSelectBrush( dc->physDev, handle );
310 if (handle) dc->hBrush = handle;
311 else ret = 0;
312 GDI_ReleaseObj( hdc );
313 return ret;
317 /***********************************************************************
318 * BRUSH_DeleteObject
320 static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj )
322 BRUSHOBJ *brush = obj;
324 switch(brush->logbrush.lbStyle)
326 case BS_PATTERN:
327 DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
328 break;
329 case BS_DIBPATTERN:
330 GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
331 break;
333 return GDI_FreeObject( handle, obj );
337 /***********************************************************************
338 * BRUSH_GetObject16
340 static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
342 BRUSHOBJ *brush = obj;
343 LOGBRUSH16 logbrush;
345 logbrush.lbStyle = brush->logbrush.lbStyle;
346 logbrush.lbColor = brush->logbrush.lbColor;
347 logbrush.lbHatch = brush->logbrush.lbHatch;
348 if (count > sizeof(logbrush)) count = sizeof(logbrush);
349 memcpy( buffer, &logbrush, count );
350 return count;
354 /***********************************************************************
355 * BRUSH_GetObject
357 static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
359 BRUSHOBJ *brush = obj;
361 if( !buffer )
362 return sizeof(brush->logbrush);
364 if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
365 memcpy( buffer, &brush->logbrush, count );
366 return count;
370 /***********************************************************************
371 * SetSolidBrush (GDI.604)
373 * If hBrush is a solid brush, change its color to newColor.
375 * RETURNS
376 * TRUE on success, FALSE on failure.
378 * FIXME: untested, not sure if correct.
380 BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
382 BRUSHOBJ * brushPtr;
383 BOOL16 res = FALSE;
385 TRACE("(hBrush %04x, newColor %08lx)\n", hBrush, (DWORD)newColor);
386 if (!(brushPtr = (BRUSHOBJ *) GDI_GetObjPtr( HBRUSH_32(hBrush), BRUSH_MAGIC )))
387 return FALSE;
389 if (brushPtr->logbrush.lbStyle == BS_SOLID)
391 brushPtr->logbrush.lbColor = newColor;
392 res = TRUE;
395 GDI_ReleaseObj( HBRUSH_32(hBrush) );
396 return res;