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
29 #include "gdi_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
34 /* GDI logical brush object */
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)
62 if (info->bmiHeader.biCompression != BI_RGB && info->bmiHeader.biCompression != BI_BITFIELDS)
63 size = info->bmiHeader.biSizeImage;
65 size = get_dib_image_size(info);
66 size += bitmap_info_size( info, coloruse );
68 if (!(hmem = GlobalAlloc( GMEM_MOVEABLE, size )))
72 newInfo = GlobalLock( hmem );
73 memcpy( newInfo, info, size );
79 /***********************************************************************
80 * CreateBrushIndirect (GDI32.@)
82 * Create a logical brush with a given style, color or pattern.
85 * brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
88 * A handle to the created brush, or a NULL handle if the brush cannot be
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
98 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
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)
117 ptr->logbrush.lbStyle = BS_PATTERN;
120 ptr->logbrush.lbHatch = (ULONG_PTR)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch );
121 ptr->logbrush.lbColor = 0;
122 if (!ptr->logbrush.lbHatch) goto error;
125 case BS_DIBPATTERNPT:
126 ptr->logbrush.lbStyle = BS_DIBPATTERN;
127 ptr->logbrush.lbHatch = (ULONG_PTR)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch,
128 ptr->logbrush.lbColor);
129 if (!ptr->logbrush.lbHatch) goto error;
135 HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;
137 ptr->logbrush.lbStyle = BS_DIBPATTERN;
138 if (!(bmi = GlobalLock( h ))) goto error;
139 ptr->logbrush.lbHatch = (ULONG_PTR)dib_copy( bmi, ptr->logbrush.lbColor);
141 if (!ptr->logbrush.lbHatch) goto error;
145 case BS_DIBPATTERN8X8:
149 WARN( "invalid brush style %u\n", ptr->logbrush.lbStyle );
153 if ((hbrush = alloc_gdi_handle( &ptr->header, OBJ_BRUSH, &brush_funcs )))
155 TRACE("%p\n", hbrush);
160 if (ptr->logbrush.lbHatch)
162 if (ptr->logbrush.lbStyle == BS_PATTERN)
163 DeleteObject( (HGDIOBJ)ptr->logbrush.lbHatch );
164 else if (ptr->logbrush.lbStyle == BS_DIBPATTERN)
165 GlobalFree( (HGLOBAL)ptr->logbrush.lbHatch );
167 HeapFree( GetProcessHeap(), 0, ptr );
172 /***********************************************************************
173 * CreateHatchBrush (GDI32.@)
175 * Create a logical brush with a hatched pattern.
178 * style [I] Direction of lines for the hatch pattern (HS_* values from "wingdi.h")
179 * color [I] Colour of the hatched pattern
182 * A handle to the created brush, or a NULL handle if the brush cannot
186 * - This function uses CreateBrushIndirect() to create the brush.
187 * - The brush returned should be freed by the caller using DeleteObject()
188 * when it is no longer required.
190 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
194 TRACE("%d %06x\n", style, color );
196 logbrush.lbStyle = BS_HATCHED;
197 logbrush.lbColor = color;
198 logbrush.lbHatch = style;
200 return CreateBrushIndirect( &logbrush );
204 /***********************************************************************
205 * CreatePatternBrush (GDI32.@)
207 * Create a logical brush with a pattern from a bitmap.
210 * hbitmap [I] Bitmap containing pattern for the brush
213 * A handle to the created brush, or a NULL handle if the brush cannot
217 * - This function uses CreateBrushIndirect() to create the brush.
218 * - The brush returned should be freed by the caller using DeleteObject()
219 * when it is no longer required.
221 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
223 LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
224 TRACE("%p\n", hbitmap );
226 logbrush.lbHatch = (ULONG_PTR)hbitmap;
227 return CreateBrushIndirect( &logbrush );
231 /***********************************************************************
232 * CreateDIBPatternBrush (GDI32.@)
234 * Create a logical brush with a pattern from a DIB.
237 * hbitmap [I] Global object containing BITMAPINFO structure for the pattern
238 * coloruse [I] Specifies color format, if provided
241 * A handle to the created brush, or a NULL handle if the brush cannot
245 * - This function uses CreateBrushIndirect() to create the brush.
246 * - The brush returned should be freed by the caller using DeleteObject()
247 * when it is no longer required.
248 * - This function is for compatibility only. CreateDIBPatternBrushPt() should
251 HBRUSH WINAPI CreateDIBPatternBrush( HGLOBAL hbitmap, UINT coloruse )
255 TRACE("%p\n", hbitmap );
257 logbrush.lbStyle = BS_DIBPATTERN;
258 logbrush.lbColor = coloruse;
260 logbrush.lbHatch = (ULONG_PTR)hbitmap;
262 return CreateBrushIndirect( &logbrush );
266 /***********************************************************************
267 * CreateDIBPatternBrushPt (GDI32.@)
269 * Create a logical brush with a pattern from a DIB.
272 * data [I] Pointer to a BITMAPINFO structure and image data for the pattern
273 * coloruse [I] Specifies color format, if provided
276 * A handle to the created brush, or a NULL handle if the brush cannot
280 * - This function uses CreateBrushIndirect() to create the brush.
281 * - The brush returned should be freed by the caller using DeleteObject()
282 * when it is no longer required.
284 HBRUSH WINAPI CreateDIBPatternBrushPt( const void* data, UINT coloruse )
286 const BITMAPINFO *info=data;
292 TRACE("%p %dx%d %dbpp\n", info, info->bmiHeader.biWidth,
293 info->bmiHeader.biHeight, info->bmiHeader.biBitCount);
295 logbrush.lbStyle = BS_DIBPATTERNPT;
296 logbrush.lbColor = coloruse;
297 logbrush.lbHatch = (ULONG_PTR)data;
299 return CreateBrushIndirect( &logbrush );
303 /***********************************************************************
304 * CreateSolidBrush (GDI32.@)
306 * Create a logical brush consisting of a single colour.
309 * color [I] Colour to make the solid brush
312 * A handle to the newly created brush, or a NULL handle if the brush cannot
316 * - This function uses CreateBrushIndirect() to create the brush.
317 * - The brush returned should be freed by the caller using DeleteObject()
318 * when it is no longer required.
320 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
324 TRACE("%06x\n", color );
326 logbrush.lbStyle = BS_SOLID;
327 logbrush.lbColor = color;
328 logbrush.lbHatch = 0;
330 return CreateBrushIndirect( &logbrush );
334 /***********************************************************************
335 * SetBrushOrgEx (GDI32.@)
337 * Set the brush origin for a device context.
340 * hdc [I] Device context to set the brush origin for
343 * oldorg [O] If non NULL, destination for previously set brush origin.
346 * Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
348 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
350 DC *dc = get_dc_ptr( hdc );
352 if (!dc) return FALSE;
355 oldorg->x = dc->brushOrgX;
356 oldorg->y = dc->brushOrgY;
360 release_dc_ptr( dc );
364 /***********************************************************************
365 * FixBrushOrgEx (GDI32.@)
370 * This function is no longer documented by MSDN, but in Win95 GDI32 it
371 * is the same as SetBrushOrgEx().
373 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
375 return SetBrushOrgEx(hdc,x,y,oldorg);
379 /***********************************************************************
382 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc )
386 DC *dc = get_dc_ptr( hdc );
390 SetLastError( ERROR_INVALID_HANDLE );
394 if ((brush = GDI_GetObjPtr( handle, OBJ_BRUSH )))
396 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectBrush );
398 if (brush->logbrush.lbStyle == BS_PATTERN)
400 PHYSDEV pattern_dev = physdev;
401 /* FIXME: This will go away once the dib driver implements
403 if(pattern_dev == dc->dibdrv)
404 pattern_dev = GET_NEXT_PHYSDEV( physdev, pSelectBrush );
406 BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, pattern_dev );
409 GDI_inc_ref_count( handle );
410 GDI_ReleaseObj( handle );
412 if (!physdev->funcs->pSelectBrush( physdev, handle ))
414 GDI_dec_ref_count( handle );
420 GDI_dec_ref_count( ret );
423 release_dc_ptr( dc );
428 /***********************************************************************
431 static BOOL BRUSH_DeleteObject( HGDIOBJ handle )
433 BRUSHOBJ *brush = free_gdi_handle( handle );
435 if (!brush) return FALSE;
436 switch(brush->logbrush.lbStyle)
439 DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
442 GlobalFree( (HGLOBAL)brush->logbrush.lbHatch );
445 return HeapFree( GetProcessHeap(), 0, brush );
449 /***********************************************************************
452 static INT BRUSH_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
454 BRUSHOBJ *brush = GDI_GetObjPtr( handle, OBJ_BRUSH );
456 if (!brush) return 0;
459 if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
460 memcpy( buffer, &brush->logbrush, count );
462 else count = sizeof(brush->logbrush);
463 GDI_ReleaseObj( handle );