gdi32: Introduce a unified function to perform COLORREF to pixel color mapping.
[wine.git] / dlls / gdi32 / brush.c
blobca95f2089acddced178bffd9c3dbc2b17333c5e5
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "gdi_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
34 /* GDI logical brush object */
35 typedef struct
37 GDIOBJHDR header;
38 LOGBRUSH logbrush;
39 } BRUSHOBJ;
41 #define NB_HATCH_STYLES 6
43 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc );
44 static INT BRUSH_GetObject( HGDIOBJ handle, INT count, LPVOID buffer );
45 static BOOL BRUSH_DeleteObject( HGDIOBJ handle );
47 static const struct gdi_obj_funcs brush_funcs =
49 BRUSH_SelectObject, /* pSelectObject */
50 BRUSH_GetObject, /* pGetObjectA */
51 BRUSH_GetObject, /* pGetObjectW */
52 NULL, /* pUnrealizeObject */
53 BRUSH_DeleteObject /* pDeleteObject */
56 static HGLOBAL dib_copy(const BITMAPINFO *info, UINT coloruse)
58 BITMAPINFO *newInfo;
59 HGLOBAL hmem;
60 INT size;
62 if (info->bmiHeader.biCompression != BI_RGB && info->bmiHeader.biCompression != BI_BITFIELDS)
63 size = info->bmiHeader.biSizeImage;
64 else
65 size = get_dib_image_size(info);
66 size += bitmap_info_size( info, coloruse );
68 if (!(hmem = GlobalAlloc( GMEM_MOVEABLE, size )))
70 return 0;
72 newInfo = GlobalLock( hmem );
73 memcpy( newInfo, info, size );
74 GlobalUnlock( hmem );
75 return hmem;
79 /***********************************************************************
80 * CreateBrushIndirect (GDI32.@)
82 * Create a logical brush with a given style, color or pattern.
84 * PARAMS
85 * brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
87 * RETURNS
88 * A handle to the created brush, or a NULL handle if the brush cannot be
89 * created.
91 * NOTES
92 * - The brush returned should be freed by the caller using DeleteObject()
93 * when it is no longer required.
94 * - Windows 95 and earlier cannot create brushes from bitmaps or DIBs larger
95 * than 8x8 pixels. If a larger bitmap is given, only a portion of the bitmap
96 * is used.
98 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
100 BRUSHOBJ * ptr;
101 HBRUSH hbrush;
103 if (!(ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(*ptr) ))) return 0;
105 ptr->logbrush.lbStyle = brush->lbStyle;
106 ptr->logbrush.lbColor = brush->lbColor;
107 ptr->logbrush.lbHatch = brush->lbHatch;
109 switch (ptr->logbrush.lbStyle)
111 case BS_PATTERN8X8:
112 ptr->logbrush.lbStyle = BS_PATTERN;
113 /* fall through */
114 case BS_PATTERN:
115 ptr->logbrush.lbHatch = (ULONG_PTR)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch );
116 if (!ptr->logbrush.lbHatch) goto error;
117 break;
119 case BS_DIBPATTERNPT:
120 ptr->logbrush.lbStyle = BS_DIBPATTERN;
121 ptr->logbrush.lbHatch = (ULONG_PTR)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch,
122 ptr->logbrush.lbColor);
123 if (!ptr->logbrush.lbHatch) goto error;
124 break;
126 case BS_DIBPATTERN8X8:
127 case BS_DIBPATTERN:
129 BITMAPINFO* bmi;
130 HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;
132 ptr->logbrush.lbStyle = BS_DIBPATTERN;
133 if (!(bmi = GlobalLock( h ))) goto error;
134 ptr->logbrush.lbHatch = (ULONG_PTR)dib_copy( bmi, ptr->logbrush.lbColor);
135 GlobalUnlock( h );
136 if (!ptr->logbrush.lbHatch) goto error;
137 break;
140 default:
141 if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error;
142 break;
145 if ((hbrush = alloc_gdi_handle( &ptr->header, OBJ_BRUSH, &brush_funcs )))
147 TRACE("%p\n", hbrush);
148 return hbrush;
151 error:
152 if (ptr->logbrush.lbHatch)
154 if (ptr->logbrush.lbStyle == BS_PATTERN)
155 DeleteObject( (HGDIOBJ)ptr->logbrush.lbHatch );
156 else if (ptr->logbrush.lbStyle == BS_DIBPATTERN)
157 GlobalFree( (HGLOBAL)ptr->logbrush.lbHatch );
159 HeapFree( GetProcessHeap(), 0, ptr );
160 return 0;
164 /***********************************************************************
165 * CreateHatchBrush (GDI32.@)
167 * Create a logical brush with a hatched pattern.
169 * PARAMS
170 * style [I] Direction of lines for the hatch pattern (HS_* values from "wingdi.h")
171 * color [I] Colour of the hatched pattern
173 * RETURNS
174 * A handle to the created brush, or a NULL handle if the brush cannot
175 * be created.
177 * NOTES
178 * - This function uses CreateBrushIndirect() to create the brush.
179 * - The brush returned should be freed by the caller using DeleteObject()
180 * when it is no longer required.
182 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
184 LOGBRUSH logbrush;
186 TRACE("%d %06x\n", style, color );
188 logbrush.lbStyle = BS_HATCHED;
189 logbrush.lbColor = color;
190 logbrush.lbHatch = style;
192 return CreateBrushIndirect( &logbrush );
196 /***********************************************************************
197 * CreatePatternBrush (GDI32.@)
199 * Create a logical brush with a pattern from a bitmap.
201 * PARAMS
202 * hbitmap [I] Bitmap containing pattern for the brush
204 * RETURNS
205 * A handle to the created brush, or a NULL handle if the brush cannot
206 * be created.
208 * NOTES
209 * - This function uses CreateBrushIndirect() to create the brush.
210 * - The brush returned should be freed by the caller using DeleteObject()
211 * when it is no longer required.
213 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
215 LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
216 TRACE("%p\n", hbitmap );
218 logbrush.lbHatch = (ULONG_PTR)hbitmap;
219 return CreateBrushIndirect( &logbrush );
223 /***********************************************************************
224 * CreateDIBPatternBrush (GDI32.@)
226 * Create a logical brush with a pattern from a DIB.
228 * PARAMS
229 * hbitmap [I] Global object containing BITMAPINFO structure for the pattern
230 * coloruse [I] Specifies color format, if provided
232 * RETURNS
233 * A handle to the created brush, or a NULL handle if the brush cannot
234 * be created.
236 * NOTES
237 * - This function uses CreateBrushIndirect() to create the brush.
238 * - The brush returned should be freed by the caller using DeleteObject()
239 * when it is no longer required.
240 * - This function is for compatibility only. CreateDIBPatternBrushPt() should
241 * be used instead.
243 HBRUSH WINAPI CreateDIBPatternBrush( HGLOBAL hbitmap, UINT coloruse )
245 LOGBRUSH logbrush;
247 TRACE("%p\n", hbitmap );
249 logbrush.lbStyle = BS_DIBPATTERN;
250 logbrush.lbColor = coloruse;
252 logbrush.lbHatch = (ULONG_PTR)hbitmap;
254 return CreateBrushIndirect( &logbrush );
258 /***********************************************************************
259 * CreateDIBPatternBrushPt (GDI32.@)
261 * Create a logical brush with a pattern from a DIB.
263 * PARAMS
264 * data [I] Pointer to a BITMAPINFO structure and image data for the pattern
265 * coloruse [I] Specifies color format, if provided
267 * RETURNS
268 * A handle to the created brush, or a NULL handle if the brush cannot
269 * be created.
271 * NOTES
272 * - This function uses CreateBrushIndirect() to create the brush.
273 * - The brush returned should be freed by the caller using DeleteObject()
274 * when it is no longer required.
276 HBRUSH WINAPI CreateDIBPatternBrushPt( const void* data, UINT coloruse )
278 const BITMAPINFO *info=data;
279 LOGBRUSH logbrush;
281 if (!data)
282 return NULL;
284 TRACE("%p %dx%d %dbpp\n", info, info->bmiHeader.biWidth,
285 info->bmiHeader.biHeight, info->bmiHeader.biBitCount);
287 logbrush.lbStyle = BS_DIBPATTERNPT;
288 logbrush.lbColor = coloruse;
289 logbrush.lbHatch = (ULONG_PTR)data;
291 return CreateBrushIndirect( &logbrush );
295 /***********************************************************************
296 * CreateSolidBrush (GDI32.@)
298 * Create a logical brush consisting of a single colour.
300 * PARAMS
301 * color [I] Colour to make the solid brush
303 * RETURNS
304 * A handle to the newly created brush, or a NULL handle if the brush cannot
305 * be created.
307 * NOTES
308 * - This function uses CreateBrushIndirect() to create the brush.
309 * - The brush returned should be freed by the caller using DeleteObject()
310 * when it is no longer required.
312 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
314 LOGBRUSH logbrush;
316 TRACE("%06x\n", color );
318 logbrush.lbStyle = BS_SOLID;
319 logbrush.lbColor = color;
320 logbrush.lbHatch = 0;
322 return CreateBrushIndirect( &logbrush );
326 /***********************************************************************
327 * SetBrushOrgEx (GDI32.@)
329 * Set the brush origin for a device context.
331 * PARAMS
332 * hdc [I] Device context to set the brush origin for
333 * x [I] New x origin
334 * y [I] New y origin
335 * oldorg [O] If non NULL, destination for previously set brush origin.
337 * RETURNS
338 * Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
340 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
342 DC *dc = get_dc_ptr( hdc );
344 if (!dc) return FALSE;
345 if (oldorg)
347 oldorg->x = dc->brushOrgX;
348 oldorg->y = dc->brushOrgY;
350 dc->brushOrgX = x;
351 dc->brushOrgY = y;
352 release_dc_ptr( dc );
353 return TRUE;
356 /***********************************************************************
357 * FixBrushOrgEx (GDI32.@)
359 * See SetBrushOrgEx.
361 * NOTES
362 * This function is no longer documented by MSDN, but in Win95 GDI32 it
363 * is the same as SetBrushOrgEx().
365 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
367 return SetBrushOrgEx(hdc,x,y,oldorg);
371 /***********************************************************************
372 * BRUSH_SelectObject
374 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc )
376 BRUSHOBJ *brush;
377 HGDIOBJ ret = 0;
378 DC *dc = get_dc_ptr( hdc );
380 if (!dc)
382 SetLastError( ERROR_INVALID_HANDLE );
383 return 0;
386 if ((brush = GDI_GetObjPtr( handle, OBJ_BRUSH )))
388 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectBrush );
390 if (brush->logbrush.lbStyle == BS_PATTERN)
392 PHYSDEV pattern_dev = physdev;
393 /* FIXME: This will go away once the dib driver implements
394 pattern brushes */
395 if(pattern_dev == dc->dibdrv)
396 pattern_dev = GET_NEXT_PHYSDEV( physdev, pSelectBrush );
398 BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, pattern_dev );
401 GDI_inc_ref_count( handle );
402 GDI_ReleaseObj( handle );
404 if (!physdev->funcs->pSelectBrush( physdev, handle ))
406 GDI_dec_ref_count( handle );
408 else
410 ret = dc->hBrush;
411 dc->hBrush = handle;
412 GDI_dec_ref_count( ret );
415 release_dc_ptr( dc );
416 return ret;
420 /***********************************************************************
421 * BRUSH_DeleteObject
423 static BOOL BRUSH_DeleteObject( HGDIOBJ handle )
425 BRUSHOBJ *brush = free_gdi_handle( handle );
427 if (!brush) return FALSE;
428 switch(brush->logbrush.lbStyle)
430 case BS_PATTERN:
431 DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
432 break;
433 case BS_DIBPATTERN:
434 GlobalFree( (HGLOBAL)brush->logbrush.lbHatch );
435 break;
437 return HeapFree( GetProcessHeap(), 0, brush );
441 /***********************************************************************
442 * BRUSH_GetObject
444 static INT BRUSH_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
446 BRUSHOBJ *brush = GDI_GetObjPtr( handle, OBJ_BRUSH );
448 if (!brush) return 0;
449 if (buffer)
451 if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
452 memcpy( buffer, &brush->logbrush, count );
454 else count = sizeof(brush->logbrush);
455 GDI_ReleaseObj( handle );
456 return count;