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 */
39 struct brush_pattern pattern
;
42 #define NB_HATCH_STYLES 6
44 static HGDIOBJ
BRUSH_SelectObject( HGDIOBJ handle
, HDC hdc
);
45 static INT
BRUSH_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
46 static BOOL
BRUSH_DeleteObject( HGDIOBJ handle
);
48 static const struct gdi_obj_funcs brush_funcs
=
50 BRUSH_SelectObject
, /* pSelectObject */
51 BRUSH_GetObject
, /* pGetObjectA */
52 BRUSH_GetObject
, /* pGetObjectW */
53 NULL
, /* pUnrealizeObject */
54 BRUSH_DeleteObject
/* pDeleteObject */
58 /* fetch the contents of the brush bitmap and cache them in the brush pattern */
59 void cache_pattern_bits( PHYSDEV physdev
, struct brush_pattern
*pattern
)
61 struct gdi_image_bits bits
;
62 struct bitblt_coords src
;
66 if (pattern
->info
) return; /* already cached */
67 if (!(bmp
= GDI_GetObjPtr( pattern
->bitmap
, OBJ_BITMAP
))) return;
69 /* we don't need to cache if we are selecting into the same type of DC */
70 if (physdev
&& bmp
->funcs
== physdev
->funcs
) goto done
;
72 if (!(info
= HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )))) goto done
;
74 src
.visrect
.left
= src
.x
= 0;
75 src
.visrect
.top
= src
.y
= 0;
76 src
.visrect
.right
= src
.width
= bmp
->dib
.dsBm
.bmWidth
;
77 src
.visrect
.bottom
= src
.height
= bmp
->dib
.dsBm
.bmHeight
;
78 if (bmp
->funcs
->pGetImage( NULL
, pattern
->bitmap
, info
, &bits
, &src
))
80 HeapFree( GetProcessHeap(), 0, info
);
84 /* release the unneeded space */
85 HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY
, info
,
86 get_dib_info_size( info
, DIB_RGB_COLORS
));
89 pattern
->usage
= DIB_RGB_COLORS
;
92 GDI_ReleaseObj( pattern
->bitmap
);
95 static BOOL
copy_bitmap( struct brush_pattern
*brush
, HBITMAP bitmap
)
98 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
100 if (!bmp
) return FALSE
;
102 if (!is_bitmapobj_dib( bmp
))
104 if ((brush
->bitmap
= CreateBitmap( bmp
->dib
.dsBm
.bmWidth
, bmp
->dib
.dsBm
.bmHeight
,
105 bmp
->dib
.dsBm
.bmPlanes
, bmp
->dib
.dsBm
.bmBitsPixel
, NULL
)))
107 if (bmp
->funcs
->pCopyBitmap( bitmap
, brush
->bitmap
))
109 BITMAPOBJ
*copy
= GDI_GetObjPtr( brush
->bitmap
, OBJ_BITMAP
);
110 copy
->funcs
= bmp
->funcs
;
111 GDI_ReleaseObj( copy
);
115 DeleteObject( brush
->bitmap
);
119 GDI_ReleaseObj( bitmap
);
120 return brush
->bitmap
!= 0;
123 info
= HeapAlloc( GetProcessHeap(), 0,
124 get_dib_info_size( (BITMAPINFO
*)&bmp
->dib
.dsBmih
, DIB_RGB_COLORS
));
125 if (!info
) goto done
;
126 info
->bmiHeader
= bmp
->dib
.dsBmih
;
127 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
128 memcpy( &info
->bmiHeader
+ 1, bmp
->dib
.dsBitfields
, sizeof(bmp
->dib
.dsBitfields
) );
129 else if (info
->bmiHeader
.biClrUsed
)
130 memcpy( &info
->bmiHeader
+ 1, bmp
->color_table
, info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
131 if (!(brush
->bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, info
->bmiHeader
.biSizeImage
)))
133 HeapFree( GetProcessHeap(), 0, info
);
136 memcpy( brush
->bits
.ptr
, bmp
->dib
.dsBm
.bmBits
, info
->bmiHeader
.biSizeImage
);
137 brush
->bits
.is_copy
= TRUE
;
138 brush
->bits
.free
= free_heap_bits
;
140 brush
->usage
= DIB_RGB_COLORS
;
143 GDI_ReleaseObj( bitmap
);
144 return brush
->info
!= NULL
;
147 BOOL
store_brush_pattern( LOGBRUSH
*brush
, struct brush_pattern
*pattern
)
152 pattern
->info
= NULL
;
153 pattern
->bits
.free
= NULL
;
155 switch (brush
->lbStyle
)
162 if (brush
->lbHatch
> HS_DIAGCROSS
)
164 if (brush
->lbHatch
>= HS_API_MAX
) return FALSE
;
165 brush
->lbStyle
= BS_SOLID
;
171 brush
->lbStyle
= BS_PATTERN
;
175 return copy_bitmap( pattern
, (HBITMAP
)brush
->lbHatch
);
178 hmem
= (HGLOBAL
)brush
->lbHatch
;
179 if (!(brush
->lbHatch
= (ULONG_PTR
)GlobalLock( hmem
))) return FALSE
;
181 case BS_DIBPATTERNPT
:
182 pattern
->usage
= brush
->lbColor
;
183 pattern
->info
= copy_packed_dib( (BITMAPINFO
*)brush
->lbHatch
, pattern
->usage
);
184 if (hmem
) GlobalUnlock( hmem
);
185 if (!pattern
->info
) return FALSE
;
186 pattern
->bits
.ptr
= (char *)pattern
->info
+ get_dib_info_size( pattern
->info
, pattern
->usage
);
187 brush
->lbStyle
= BS_DIBPATTERN
;
191 case BS_DIBPATTERN8X8
:
195 WARN( "invalid brush style %u\n", brush
->lbStyle
);
200 void free_brush_pattern( struct brush_pattern
*pattern
)
202 if (pattern
->bits
.free
) pattern
->bits
.free( &pattern
->bits
);
203 if (pattern
->bitmap
) DeleteObject( pattern
->bitmap
);
204 HeapFree( GetProcessHeap(), 0, pattern
->info
);
207 BOOL
get_brush_bitmap_info( HBRUSH handle
, BITMAPINFO
*info
, void **bits
, UINT
*usage
)
212 if (!(brush
= GDI_GetObjPtr( handle
, OBJ_BRUSH
))) return FALSE
;
214 if (!brush
->pattern
.info
) cache_pattern_bits( NULL
, &brush
->pattern
);
216 if (brush
->pattern
.info
)
218 memcpy( info
, brush
->pattern
.info
, get_dib_info_size( brush
->pattern
.info
, brush
->pattern
.usage
));
219 if (info
->bmiHeader
.biBitCount
<= 8 && !info
->bmiHeader
.biClrUsed
)
220 fill_default_color_table( info
);
221 *bits
= brush
->pattern
.bits
.ptr
;
222 *usage
= brush
->pattern
.usage
;
225 GDI_ReleaseObj( handle
);
230 /***********************************************************************
231 * CreateBrushIndirect (GDI32.@)
233 * Create a logical brush with a given style, color or pattern.
236 * brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
239 * A handle to the created brush, or a NULL handle if the brush cannot be
243 * - The brush returned should be freed by the caller using DeleteObject()
244 * when it is no longer required.
245 * - Windows 95 and earlier cannot create brushes from bitmaps or DIBs larger
246 * than 8x8 pixels. If a larger bitmap is given, only a portion of the bitmap
249 HBRUSH WINAPI
CreateBrushIndirect( const LOGBRUSH
* brush
)
254 if (!(ptr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*ptr
) ))) return 0;
256 ptr
->logbrush
= *brush
;
258 if (store_brush_pattern( &ptr
->logbrush
, &ptr
->pattern
) &&
259 (hbrush
= alloc_gdi_handle( &ptr
->header
, OBJ_BRUSH
, &brush_funcs
)))
261 TRACE("%p\n", hbrush
);
265 free_brush_pattern( &ptr
->pattern
);
266 HeapFree( GetProcessHeap(), 0, ptr
);
271 /***********************************************************************
272 * CreateHatchBrush (GDI32.@)
274 * Create a logical brush with a hatched pattern.
277 * style [I] Direction of lines for the hatch pattern (HS_* values from "wingdi.h")
278 * color [I] Colour of the hatched pattern
281 * A handle to the created brush, or a NULL handle if the brush cannot
285 * - This function uses CreateBrushIndirect() to create the brush.
286 * - The brush returned should be freed by the caller using DeleteObject()
287 * when it is no longer required.
289 HBRUSH WINAPI
CreateHatchBrush( INT style
, COLORREF color
)
293 TRACE("%d %06x\n", style
, color
);
295 logbrush
.lbStyle
= BS_HATCHED
;
296 logbrush
.lbColor
= color
;
297 logbrush
.lbHatch
= style
;
299 return CreateBrushIndirect( &logbrush
);
303 /***********************************************************************
304 * CreatePatternBrush (GDI32.@)
306 * Create a logical brush with a pattern from a bitmap.
309 * hbitmap [I] Bitmap containing pattern for the brush
312 * A handle to the 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
CreatePatternBrush( HBITMAP hbitmap
)
322 LOGBRUSH logbrush
= { BS_PATTERN
, 0, 0 };
323 TRACE("%p\n", hbitmap
);
325 logbrush
.lbHatch
= (ULONG_PTR
)hbitmap
;
326 return CreateBrushIndirect( &logbrush
);
330 /***********************************************************************
331 * CreateDIBPatternBrush (GDI32.@)
333 * Create a logical brush with a pattern from a DIB.
336 * hbitmap [I] Global object containing BITMAPINFO structure for the pattern
337 * coloruse [I] Specifies color format, if provided
340 * A handle to the created brush, or a NULL handle if the brush cannot
344 * - This function uses CreateBrushIndirect() to create the brush.
345 * - The brush returned should be freed by the caller using DeleteObject()
346 * when it is no longer required.
347 * - This function is for compatibility only. CreateDIBPatternBrushPt() should
350 HBRUSH WINAPI
CreateDIBPatternBrush( HGLOBAL hbitmap
, UINT coloruse
)
354 TRACE("%p\n", hbitmap
);
356 logbrush
.lbStyle
= BS_DIBPATTERN
;
357 logbrush
.lbColor
= coloruse
;
359 logbrush
.lbHatch
= (ULONG_PTR
)hbitmap
;
361 return CreateBrushIndirect( &logbrush
);
365 /***********************************************************************
366 * CreateDIBPatternBrushPt (GDI32.@)
368 * Create a logical brush with a pattern from a DIB.
371 * data [I] Pointer to a BITMAPINFO structure and image data for the pattern
372 * coloruse [I] Specifies color format, if provided
375 * A handle to the created brush, or a NULL handle if the brush cannot
379 * - This function uses CreateBrushIndirect() to create the brush.
380 * - The brush returned should be freed by the caller using DeleteObject()
381 * when it is no longer required.
383 HBRUSH WINAPI
CreateDIBPatternBrushPt( const void* data
, UINT coloruse
)
385 const BITMAPINFO
*info
=data
;
391 TRACE("%p %dx%d %dbpp\n", info
, info
->bmiHeader
.biWidth
,
392 info
->bmiHeader
.biHeight
, info
->bmiHeader
.biBitCount
);
394 logbrush
.lbStyle
= BS_DIBPATTERNPT
;
395 logbrush
.lbColor
= coloruse
;
396 logbrush
.lbHatch
= (ULONG_PTR
)data
;
398 return CreateBrushIndirect( &logbrush
);
402 /***********************************************************************
403 * CreateSolidBrush (GDI32.@)
405 * Create a logical brush consisting of a single colour.
408 * color [I] Colour to make the solid brush
411 * A handle to the newly created brush, or a NULL handle if the brush cannot
415 * - This function uses CreateBrushIndirect() to create the brush.
416 * - The brush returned should be freed by the caller using DeleteObject()
417 * when it is no longer required.
419 HBRUSH WINAPI
CreateSolidBrush( COLORREF color
)
423 TRACE("%06x\n", color
);
425 logbrush
.lbStyle
= BS_SOLID
;
426 logbrush
.lbColor
= color
;
427 logbrush
.lbHatch
= 0;
429 return CreateBrushIndirect( &logbrush
);
433 /***********************************************************************
434 * SetBrushOrgEx (GDI32.@)
436 * Set the brush origin for a device context.
439 * hdc [I] Device context to set the brush origin for
442 * oldorg [O] If non NULL, destination for previously set brush origin.
445 * Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
447 BOOL WINAPI
SetBrushOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT oldorg
)
449 DC
*dc
= get_dc_ptr( hdc
);
451 if (!dc
) return FALSE
;
454 oldorg
->x
= dc
->brushOrgX
;
455 oldorg
->y
= dc
->brushOrgY
;
459 release_dc_ptr( dc
);
463 /***********************************************************************
464 * FixBrushOrgEx (GDI32.@)
469 * This function is no longer documented by MSDN, but in Win95 GDI32 it
470 * is the same as SetBrushOrgEx().
472 BOOL WINAPI
FixBrushOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT oldorg
)
474 return SetBrushOrgEx(hdc
,x
,y
,oldorg
);
478 /***********************************************************************
481 static HGDIOBJ
BRUSH_SelectObject( HGDIOBJ handle
, HDC hdc
)
485 DC
*dc
= get_dc_ptr( hdc
);
489 SetLastError( ERROR_INVALID_HANDLE
);
493 if ((brush
= GDI_GetObjPtr( handle
, OBJ_BRUSH
)))
495 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSelectBrush
);
496 struct brush_pattern
*pattern
= &brush
->pattern
;
500 if (pattern
->bitmap
) cache_pattern_bits( physdev
, pattern
);
504 GDI_inc_ref_count( handle
);
505 GDI_ReleaseObj( handle
);
507 if (!physdev
->funcs
->pSelectBrush( physdev
, handle
, pattern
))
509 GDI_dec_ref_count( handle
);
515 GDI_dec_ref_count( ret
);
518 release_dc_ptr( dc
);
523 /***********************************************************************
526 static BOOL
BRUSH_DeleteObject( HGDIOBJ handle
)
528 BRUSHOBJ
*brush
= free_gdi_handle( handle
);
530 if (!brush
) return FALSE
;
531 free_brush_pattern( &brush
->pattern
);
532 return HeapFree( GetProcessHeap(), 0, brush
);
536 /***********************************************************************
539 static INT
BRUSH_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
541 BRUSHOBJ
*brush
= GDI_GetObjPtr( handle
, OBJ_BRUSH
);
543 if (!brush
) return 0;
546 if (count
> sizeof(brush
->logbrush
)) count
= sizeof(brush
->logbrush
);
547 memcpy( buffer
, &brush
->logbrush
, count
);
549 else count
= sizeof(brush
->logbrush
);
550 GDI_ReleaseObj( handle
);