Return error from low level driver when necessary.
[wine.git] / dlls / gdi / brush.c
blob6776bb9a07dc46d184e9cd2a482944fd44b81f3c
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 * Create a logical brush with a given style, color or pattern.
91 * PARAMS
92 * brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
94 * RETURNS
95 * A handle to the created brush, or a NULL handle if the brush cannot be
96 * created.
98 * NOTES
99 * - The brush returned should be freed by the caller using DeleteObject()
100 * when it is no longer required.
101 * - Windows 95 and earlier cannot create brushes from bitmaps or DIBs larger
102 * than 8x8 pixels. If a larger bitmap is given, only a portion of the bitmap
103 * is used.
104 * - If the brush to be created matches a stock brush, a stock brush will be
105 * returned. This behaviour is undocumented.
107 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
109 static const DWORD stockMap[] = { /* Map of RGB colors of stock brushes */
110 RGB(255,255,255), WHITE_BRUSH,
111 RGB(192,192,192), LTGRAY_BRUSH,
112 RGB(128,128,128), GRAY_BRUSH,
113 RGB(0,0,0), BLACK_BRUSH
115 BRUSHOBJ * ptr;
116 HBRUSH hbrush;
118 if (brush->lbStyle == BS_SOLID)
120 size_t i;
122 /* If a solid brush is created in a color matching one of the
123 * stock brushes, native returns the stock object (GDI heap
124 * optimisation). Some apps rely on this as they otherwise
125 * would leak their brushes.
127 for (i = 0; i < (sizeof(stockMap)/sizeof(stockMap[0])) / 2; i += 2)
129 if (brush->lbColor == stockMap[i])
131 HBRUSH hBr = GetStockObject(stockMap[i + 1]);
132 if (hBr)
133 return hBr; /* Return stock brush */
134 break; /* Being called to create a stock brush, fall through */
139 if (!(ptr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC,
140 (HGDIOBJ *)&hbrush, &brush_funcs ))) return 0;
141 ptr->logbrush.lbStyle = brush->lbStyle;
142 ptr->logbrush.lbColor = brush->lbColor;
143 ptr->logbrush.lbHatch = brush->lbHatch;
145 switch (ptr->logbrush.lbStyle)
147 case BS_PATTERN8X8:
148 ptr->logbrush.lbStyle = BS_PATTERN;
149 /* fall through */
150 case BS_PATTERN:
151 ptr->logbrush.lbHatch = (LONG)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch );
152 if (!ptr->logbrush.lbHatch) goto error;
153 break;
155 case BS_DIBPATTERNPT:
156 ptr->logbrush.lbStyle = BS_DIBPATTERN;
157 ptr->logbrush.lbHatch = (LONG)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch,
158 ptr->logbrush.lbColor);
159 if (!ptr->logbrush.lbHatch) goto error;
160 break;
162 case BS_DIBPATTERN8X8:
163 case BS_DIBPATTERN:
165 BITMAPINFO* bmi;
166 HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;
168 ptr->logbrush.lbStyle = BS_DIBPATTERN;
169 if (!(bmi = (BITMAPINFO *)GlobalLock( h ))) goto error;
170 ptr->logbrush.lbHatch = dib_copy( bmi, ptr->logbrush.lbColor);
171 GlobalUnlock( h );
172 if (!ptr->logbrush.lbHatch) goto error;
173 break;
176 default:
177 if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error;
178 break;
181 GDI_ReleaseObj( hbrush );
182 TRACE("%p\n", hbrush);
183 return hbrush;
185 error:
186 GDI_FreeObject( hbrush, ptr );
187 return 0;
191 /***********************************************************************
192 * CreateHatchBrush (GDI32.@)
194 * Create a logical brush with a hatched pattern.
196 * PARAMS
197 * style [I] Direction of lines for the hatch pattern (HS_* values from "wingdi.h")
198 * color [I] Colour of the hatched pattern
200 * RETURNS
201 * A handle to the created brush, or a NULL handle if the brush cannot
202 * be created.
204 * NOTES
205 * - This function uses CreateBrushIndirect() to create the brush.
206 * - The brush returned should be freed by the caller using DeleteObject()
207 * when it is no longer required.
209 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
211 LOGBRUSH logbrush;
213 TRACE("%d %06lx\n", style, color );
215 logbrush.lbStyle = BS_HATCHED;
216 logbrush.lbColor = color;
217 logbrush.lbHatch = style;
219 return CreateBrushIndirect( &logbrush );
223 /***********************************************************************
224 * CreatePatternBrush (GDI32.@)
226 * Create a logical brush with a pattern from a bitmap.
228 * PARAMS
229 * hbitmap [I] Bitmap containing pattern for the brush
231 * RETURNS
232 * A handle to the created brush, or a NULL handle if the brush cannot
233 * be created.
235 * NOTES
236 * - This function uses CreateBrushIndirect() to create the brush.
237 * - The brush returned should be freed by the caller using DeleteObject()
238 * when it is no longer required.
240 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
242 LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
243 TRACE("%p\n", hbitmap );
245 logbrush.lbHatch = (ULONG_PTR)hbitmap;
246 return CreateBrushIndirect( &logbrush );
250 /***********************************************************************
251 * CreateDIBPatternBrush (GDI32.@)
253 * Create a logical brush with a pattern from a DIB.
255 * PARAMS
256 * hbitmap [I] Global object containing BITMAPINFO structure for the pattern
257 * coloruse [I] Specifies color format, if provided
259 * RETURNS
260 * A handle to the created brush, or a NULL handle if the brush cannot
261 * be created.
263 * NOTES
264 * - This function uses CreateBrushIndirect() to create the brush.
265 * - The brush returned should be freed by the caller using DeleteObject()
266 * when it is no longer required.
267 * - This function is for compatibility only. CreateDIBPatternBrushPt() should
268 * be used instead.
270 HBRUSH WINAPI CreateDIBPatternBrush( HGLOBAL hbitmap, UINT coloruse )
272 LOGBRUSH logbrush;
274 TRACE("%p\n", hbitmap );
276 logbrush.lbStyle = BS_DIBPATTERN;
277 logbrush.lbColor = coloruse;
279 logbrush.lbHatch = (LONG)hbitmap;
281 return CreateBrushIndirect( &logbrush );
285 /***********************************************************************
286 * CreateDIBPatternBrushPt (GDI32.@)
288 * Create a logical brush with a pattern from a DIB.
290 * PARAMS
291 * data [I] Pointer to a BITMAPINFO structure and image data for the pattern
292 * coloruse [I] Specifies color format, if provided
294 * RETURNS
295 * A handle to the created brush, or a NULL handle if the brush cannot
296 * be created.
298 * NOTES
299 * - This function uses CreateBrushIndirect() to create the brush.
300 * - The brush returned should be freed by the caller using DeleteObject()
301 * when it is no longer required.
303 HBRUSH WINAPI CreateDIBPatternBrushPt( const void* data, UINT coloruse )
305 BITMAPINFO *info=(BITMAPINFO*)data;
306 LOGBRUSH logbrush;
308 if (!data)
309 return NULL;
311 TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth,
312 info->bmiHeader.biHeight, info->bmiHeader.biBitCount);
314 logbrush.lbStyle = BS_DIBPATTERNPT;
315 logbrush.lbColor = coloruse;
316 logbrush.lbHatch = (LONG) data;
318 return CreateBrushIndirect( &logbrush );
322 /***********************************************************************
323 * CreateSolidBrush (GDI32.@)
325 * Create a logical brush consisting of a single colour.
327 * PARAMS
328 * color [I] Colour to make the solid brush
330 * RETURNS
331 * A handle to the newly created brush, or a NULL handle if the brush cannot
332 * be created.
334 * NOTES
335 * - This function uses CreateBrushIndirect() to create the brush.
336 * - The brush returned should be freed by the caller using DeleteObject()
337 * when it is no longer required.
339 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
341 LOGBRUSH logbrush;
343 TRACE("%06lx\n", color );
345 logbrush.lbStyle = BS_SOLID;
346 logbrush.lbColor = color;
347 logbrush.lbHatch = 0;
349 return CreateBrushIndirect( &logbrush );
353 /***********************************************************************
354 * SetBrushOrgEx (GDI32.@)
356 * Set the brush origin for a device context.
358 * PARAMS
359 * hdc [I] Device context to set the brush origin for
360 * x [I] New x origin
361 * y [I] Ney y origin
362 * oldorg [O] If non NULL, destination for previously set brush origin.
364 * RETURNS
365 * Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
367 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
369 DC *dc = DC_GetDCPtr( hdc );
371 if (!dc) return FALSE;
372 if (oldorg)
374 oldorg->x = dc->brushOrgX;
375 oldorg->y = dc->brushOrgY;
377 dc->brushOrgX = x;
378 dc->brushOrgY = y;
379 GDI_ReleaseObj( hdc );
380 return TRUE;
383 /***********************************************************************
384 * FixBrushOrgEx (GDI32.@)
386 * See SetBrushOrgEx.
388 * NOTES
389 * This function is no longer documented by MSDN, but in Win95 GDI32 it
390 * is the same as SetBrushOrgEx().
392 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
394 return SetBrushOrgEx(hdc,x,y,oldorg);
398 /***********************************************************************
399 * BRUSH_SelectObject
401 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
403 BRUSHOBJ *brush = obj;
404 HGDIOBJ ret;
405 DC *dc = DC_GetDCPtr( hdc );
407 if (!dc) return 0;
409 if (brush->logbrush.lbStyle == BS_PATTERN)
410 BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc );
412 ret = dc->hBrush;
413 if (dc->funcs->pSelectBrush) handle = dc->funcs->pSelectBrush( dc->physDev, handle );
414 if (handle) dc->hBrush = handle;
415 else ret = 0;
416 GDI_ReleaseObj( hdc );
417 return ret;
421 /***********************************************************************
422 * BRUSH_DeleteObject
424 static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj )
426 BRUSHOBJ *brush = obj;
428 switch(brush->logbrush.lbStyle)
430 case BS_PATTERN:
431 DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
432 break;
433 case BS_DIBPATTERN:
434 GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
435 break;
437 return GDI_FreeObject( handle, obj );
441 /***********************************************************************
442 * BRUSH_GetObject16
444 static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
446 BRUSHOBJ *brush = obj;
447 LOGBRUSH16 logbrush;
449 logbrush.lbStyle = brush->logbrush.lbStyle;
450 logbrush.lbColor = brush->logbrush.lbColor;
451 logbrush.lbHatch = brush->logbrush.lbHatch;
452 if (count > sizeof(logbrush)) count = sizeof(logbrush);
453 memcpy( buffer, &logbrush, count );
454 return count;
458 /***********************************************************************
459 * BRUSH_GetObject
461 static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
463 BRUSHOBJ *brush = obj;
465 if( !buffer )
466 return sizeof(brush->logbrush);
468 if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
469 memcpy( buffer, &brush->logbrush, count );
470 return count;
474 /***********************************************************************
475 * SetSolidBrush (GDI.604)
477 * Change the color of a solid brush.
479 * PARAMS
480 * hBrush [I] Brush to change the color of
481 * newColor [I] New color for hBrush
483 * RETURNS
484 * Success: TRUE. The color of hBrush is set to newColor.
485 * Failure: FALSE.
487 * FIXME
488 * This function is undocumented and untested. The implementation may
489 * not be correct.
491 BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
493 BRUSHOBJ * brushPtr;
494 BOOL16 res = FALSE;
496 TRACE("(hBrush %04x, newColor %08lx)\n", hBrush, (DWORD)newColor);
497 if (!(brushPtr = (BRUSHOBJ *) GDI_GetObjPtr( HBRUSH_32(hBrush), BRUSH_MAGIC )))
498 return FALSE;
500 if (brushPtr->logbrush.lbStyle == BS_SOLID)
502 brushPtr->logbrush.lbColor = newColor;
503 res = TRUE;
506 GDI_ReleaseObj( HBRUSH_32(hBrush) );
507 return res;