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 HBITMAP bitmap
; /* bitmap handle for DDB pattern brushes */
40 BITMAPINFO
*info
; /* DIB info for pattern brushes */
41 struct gdi_image_bits bits
; /* DIB bits for pattern brushes */
42 UINT usage
; /* color usage for DIB info */
45 #define NB_HATCH_STYLES 6
47 static HGDIOBJ
BRUSH_SelectObject( HGDIOBJ handle
, HDC hdc
);
48 static INT
BRUSH_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
49 static BOOL
BRUSH_DeleteObject( HGDIOBJ handle
);
51 static const struct gdi_obj_funcs brush_funcs
=
53 BRUSH_SelectObject
, /* pSelectObject */
54 BRUSH_GetObject
, /* pGetObjectA */
55 BRUSH_GetObject
, /* pGetObjectW */
56 NULL
, /* pUnrealizeObject */
57 BRUSH_DeleteObject
/* pDeleteObject */
61 /* fetch the contents of the brush bitmap and cache them in the brush object */
62 static BOOL
store_bitmap_bits( BRUSHOBJ
*brush
, BITMAPOBJ
*bmp
)
64 const struct gdi_dc_funcs
*funcs
= get_bitmap_funcs( bmp
);
65 struct gdi_image_bits bits
;
66 struct bitblt_coords src
;
69 if (!(info
= HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] ))))
72 src
.visrect
.left
= src
.x
= 0;
73 src
.visrect
.top
= src
.y
= 0;
74 src
.visrect
.right
= src
.width
= bmp
->bitmap
.bmWidth
;
75 src
.visrect
.bottom
= src
.height
= bmp
->bitmap
.bmHeight
;
76 if (funcs
->pGetImage( NULL
, brush
->bitmap
, info
, &bits
, &src
))
78 HeapFree( GetProcessHeap(), 0, info
);
82 /* release the unneeded space */
83 HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY
, info
,
84 get_dib_info_size( info
, DIB_RGB_COLORS
));
87 brush
->usage
= DIB_RGB_COLORS
;
91 static BOOL
copy_bitmap( BRUSHOBJ
*brush
, HBITMAP bitmap
)
94 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
96 if (!bmp
) return FALSE
;
100 if ((brush
->bitmap
= CreateBitmap( bmp
->bitmap
.bmWidth
, bmp
->bitmap
.bmHeight
,
101 bmp
->bitmap
.bmPlanes
, bmp
->bitmap
.bmBitsPixel
, NULL
)))
103 if (bmp
->funcs
->pCopyBitmap( bitmap
, brush
->bitmap
))
105 BITMAPOBJ
*copy
= GDI_GetObjPtr( brush
->bitmap
, OBJ_BITMAP
);
106 copy
->funcs
= bmp
->funcs
;
107 GDI_ReleaseObj( copy
);
111 DeleteObject( brush
->bitmap
);
115 GDI_ReleaseObj( bitmap
);
116 return brush
->bitmap
!= 0;
119 info
= HeapAlloc( GetProcessHeap(), 0,
120 get_dib_info_size( (BITMAPINFO
*)&bmp
->dib
->dsBmih
, DIB_RGB_COLORS
));
121 if (!info
) goto done
;
122 info
->bmiHeader
= bmp
->dib
->dsBmih
;
123 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
124 memcpy( &info
->bmiHeader
+ 1, bmp
->dib
->dsBitfields
, sizeof(bmp
->dib
->dsBitfields
) );
125 else if (info
->bmiHeader
.biClrUsed
)
126 memcpy( &info
->bmiHeader
+ 1, bmp
->color_table
, info
->bmiHeader
.biClrUsed
* sizeof(RGBQUAD
) );
127 if (!(brush
->bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, info
->bmiHeader
.biSizeImage
)))
129 HeapFree( GetProcessHeap(), 0, info
);
132 memcpy( brush
->bits
.ptr
, bmp
->dib
->dsBm
.bmBits
, info
->bmiHeader
.biSizeImage
);
133 brush
->bits
.is_copy
= TRUE
;
134 brush
->bits
.free
= free_heap_bits
;
136 brush
->usage
= DIB_RGB_COLORS
;
139 GDI_ReleaseObj( bitmap
);
140 return brush
->info
!= NULL
;
143 BOOL
get_brush_bitmap_info( HBRUSH handle
, BITMAPINFO
*info
, void **bits
, UINT
*usage
)
148 if (!(brush
= GDI_GetObjPtr( handle
, OBJ_BRUSH
))) return FALSE
;
152 BITMAPOBJ
*bmp
= GDI_GetObjPtr( brush
->bitmap
, OBJ_BITMAP
);
156 store_bitmap_bits( brush
, bmp
);
157 GDI_ReleaseObj( brush
->bitmap
);
162 memcpy( info
, brush
->info
, get_dib_info_size( brush
->info
, brush
->usage
));
163 if (info
->bmiHeader
.biBitCount
<= 8 && !info
->bmiHeader
.biClrUsed
)
164 fill_default_color_table( info
);
165 *bits
= brush
->bits
.ptr
;
166 *usage
= brush
->usage
;
169 GDI_ReleaseObj( handle
);
174 /***********************************************************************
175 * CreateBrushIndirect (GDI32.@)
177 * Create a logical brush with a given style, color or pattern.
180 * brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
183 * A handle to the created brush, or a NULL handle if the brush cannot be
187 * - The brush returned should be freed by the caller using DeleteObject()
188 * when it is no longer required.
189 * - Windows 95 and earlier cannot create brushes from bitmaps or DIBs larger
190 * than 8x8 pixels. If a larger bitmap is given, only a portion of the bitmap
193 HBRUSH WINAPI
CreateBrushIndirect( const LOGBRUSH
* brush
)
199 if (!(ptr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ptr
) ))) return 0;
201 ptr
->logbrush
= *brush
;
203 switch (ptr
->logbrush
.lbStyle
)
211 ptr
->logbrush
.lbStyle
= BS_PATTERN
;
214 if (!copy_bitmap( ptr
, (HBITMAP
)ptr
->logbrush
.lbHatch
)) goto error
;
215 ptr
->logbrush
.lbColor
= 0;
219 hmem
= (HGLOBAL
)ptr
->logbrush
.lbHatch
;
220 if (!(ptr
->logbrush
.lbHatch
= (ULONG_PTR
)GlobalLock( hmem
))) goto error
;
222 case BS_DIBPATTERNPT
:
223 ptr
->usage
= ptr
->logbrush
.lbColor
;
224 ptr
->info
= copy_packed_dib( (BITMAPINFO
*)ptr
->logbrush
.lbHatch
, ptr
->usage
);
225 if (hmem
) GlobalUnlock( hmem
);
226 if (!ptr
->info
) goto error
;
227 ptr
->bits
.ptr
= (char *)ptr
->info
+ get_dib_info_size( ptr
->info
, ptr
->usage
);
228 ptr
->logbrush
.lbStyle
= BS_DIBPATTERN
;
229 ptr
->logbrush
.lbColor
= 0;
232 case BS_DIBPATTERN8X8
:
236 WARN( "invalid brush style %u\n", ptr
->logbrush
.lbStyle
);
240 if ((hbrush
= alloc_gdi_handle( &ptr
->header
, OBJ_BRUSH
, &brush_funcs
)))
242 TRACE("%p\n", hbrush
);
247 if (ptr
->bitmap
) DeleteObject( ptr
->bitmap
);
248 HeapFree( GetProcessHeap(), 0, ptr
->info
);
249 HeapFree( GetProcessHeap(), 0, ptr
);
254 /***********************************************************************
255 * CreateHatchBrush (GDI32.@)
257 * Create a logical brush with a hatched pattern.
260 * style [I] Direction of lines for the hatch pattern (HS_* values from "wingdi.h")
261 * color [I] Colour of the hatched pattern
264 * A handle to the created brush, or a NULL handle if the brush cannot
268 * - This function uses CreateBrushIndirect() to create the brush.
269 * - The brush returned should be freed by the caller using DeleteObject()
270 * when it is no longer required.
272 HBRUSH WINAPI
CreateHatchBrush( INT style
, COLORREF color
)
276 TRACE("%d %06x\n", style
, color
);
278 logbrush
.lbStyle
= BS_HATCHED
;
279 logbrush
.lbColor
= color
;
280 logbrush
.lbHatch
= style
;
282 return CreateBrushIndirect( &logbrush
);
286 /***********************************************************************
287 * CreatePatternBrush (GDI32.@)
289 * Create a logical brush with a pattern from a bitmap.
292 * hbitmap [I] Bitmap containing pattern for the brush
295 * A handle to the created brush, or a NULL handle if the brush cannot
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
CreatePatternBrush( HBITMAP hbitmap
)
305 LOGBRUSH logbrush
= { BS_PATTERN
, 0, 0 };
306 TRACE("%p\n", hbitmap
);
308 logbrush
.lbHatch
= (ULONG_PTR
)hbitmap
;
309 return CreateBrushIndirect( &logbrush
);
313 /***********************************************************************
314 * CreateDIBPatternBrush (GDI32.@)
316 * Create a logical brush with a pattern from a DIB.
319 * hbitmap [I] Global object containing BITMAPINFO structure for the pattern
320 * coloruse [I] Specifies color format, if provided
323 * A handle to the created brush, or a NULL handle if the brush cannot
327 * - This function uses CreateBrushIndirect() to create the brush.
328 * - The brush returned should be freed by the caller using DeleteObject()
329 * when it is no longer required.
330 * - This function is for compatibility only. CreateDIBPatternBrushPt() should
333 HBRUSH WINAPI
CreateDIBPatternBrush( HGLOBAL hbitmap
, UINT coloruse
)
337 TRACE("%p\n", hbitmap
);
339 logbrush
.lbStyle
= BS_DIBPATTERN
;
340 logbrush
.lbColor
= coloruse
;
342 logbrush
.lbHatch
= (ULONG_PTR
)hbitmap
;
344 return CreateBrushIndirect( &logbrush
);
348 /***********************************************************************
349 * CreateDIBPatternBrushPt (GDI32.@)
351 * Create a logical brush with a pattern from a DIB.
354 * data [I] Pointer to a BITMAPINFO structure and image data for the pattern
355 * coloruse [I] Specifies color format, if provided
358 * A handle to the created brush, or a NULL handle if the brush cannot
362 * - This function uses CreateBrushIndirect() to create the brush.
363 * - The brush returned should be freed by the caller using DeleteObject()
364 * when it is no longer required.
366 HBRUSH WINAPI
CreateDIBPatternBrushPt( const void* data
, UINT coloruse
)
368 const BITMAPINFO
*info
=data
;
374 TRACE("%p %dx%d %dbpp\n", info
, info
->bmiHeader
.biWidth
,
375 info
->bmiHeader
.biHeight
, info
->bmiHeader
.biBitCount
);
377 logbrush
.lbStyle
= BS_DIBPATTERNPT
;
378 logbrush
.lbColor
= coloruse
;
379 logbrush
.lbHatch
= (ULONG_PTR
)data
;
381 return CreateBrushIndirect( &logbrush
);
385 /***********************************************************************
386 * CreateSolidBrush (GDI32.@)
388 * Create a logical brush consisting of a single colour.
391 * color [I] Colour to make the solid brush
394 * A handle to the newly created brush, or a NULL handle if the brush cannot
398 * - This function uses CreateBrushIndirect() to create the brush.
399 * - The brush returned should be freed by the caller using DeleteObject()
400 * when it is no longer required.
402 HBRUSH WINAPI
CreateSolidBrush( COLORREF color
)
406 TRACE("%06x\n", color
);
408 logbrush
.lbStyle
= BS_SOLID
;
409 logbrush
.lbColor
= color
;
410 logbrush
.lbHatch
= 0;
412 return CreateBrushIndirect( &logbrush
);
416 /***********************************************************************
417 * SetBrushOrgEx (GDI32.@)
419 * Set the brush origin for a device context.
422 * hdc [I] Device context to set the brush origin for
425 * oldorg [O] If non NULL, destination for previously set brush origin.
428 * Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
430 BOOL WINAPI
SetBrushOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT oldorg
)
432 DC
*dc
= get_dc_ptr( hdc
);
434 if (!dc
) return FALSE
;
437 oldorg
->x
= dc
->brushOrgX
;
438 oldorg
->y
= dc
->brushOrgY
;
442 release_dc_ptr( dc
);
446 /***********************************************************************
447 * FixBrushOrgEx (GDI32.@)
452 * This function is no longer documented by MSDN, but in Win95 GDI32 it
453 * is the same as SetBrushOrgEx().
455 BOOL WINAPI
FixBrushOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT oldorg
)
457 return SetBrushOrgEx(hdc
,x
,y
,oldorg
);
461 /***********************************************************************
464 static HGDIOBJ
BRUSH_SelectObject( HGDIOBJ handle
, HDC hdc
)
468 DC
*dc
= get_dc_ptr( hdc
);
472 SetLastError( ERROR_INVALID_HANDLE
);
476 if ((brush
= GDI_GetObjPtr( handle
, OBJ_BRUSH
)))
478 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSelectBrush
);
479 HBITMAP bitmap
= brush
->bitmap
;
484 if (bitmap
&& !brush
->info
)
486 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
487 /* fetch the bitmap bits if we are selecting into a different type of DC */
488 if (bmp
&& bmp
->funcs
!= physdev
->funcs
) store_bitmap_bits( brush
, bmp
);
489 GDI_ReleaseObj( bitmap
);
493 bits
= brush
->bits
.ptr
;
494 usage
= brush
->usage
;
495 GDI_inc_ref_count( handle
);
496 GDI_ReleaseObj( handle
);
498 if (!physdev
->funcs
->pSelectBrush( physdev
, handle
, bitmap
, info
, bits
, usage
))
500 GDI_dec_ref_count( handle
);
506 GDI_dec_ref_count( ret
);
509 release_dc_ptr( dc
);
514 /***********************************************************************
517 static BOOL
BRUSH_DeleteObject( HGDIOBJ handle
)
519 BRUSHOBJ
*brush
= free_gdi_handle( handle
);
521 if (!brush
) return FALSE
;
522 if (brush
->bits
.free
) brush
->bits
.free( &brush
->bits
);
523 if (brush
->bitmap
) DeleteObject( brush
->bitmap
);
524 HeapFree( GetProcessHeap(), 0, brush
->info
);
525 return HeapFree( GetProcessHeap(), 0, brush
);
529 /***********************************************************************
532 static INT
BRUSH_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
534 BRUSHOBJ
*brush
= GDI_GetObjPtr( handle
, OBJ_BRUSH
);
536 if (!brush
) return 0;
539 if (count
> sizeof(brush
->logbrush
)) count
= sizeof(brush
->logbrush
);
540 memcpy( buffer
, &brush
->logbrush
, count
);
542 else count
= sizeof(brush
->logbrush
);
543 GDI_ReleaseObj( handle
);