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
31 #include "ntgdi_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(gdi
);
36 /* GDI logical brush object */
39 struct gdi_obj_header obj
;
41 struct brush_pattern pattern
;
44 #define NB_HATCH_STYLES 6
46 static INT
BRUSH_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
);
47 static BOOL
BRUSH_DeleteObject( HGDIOBJ handle
);
49 static const struct gdi_obj_funcs brush_funcs
=
51 BRUSH_GetObject
, /* pGetObjectW */
52 NULL
, /* pUnrealizeObject */
53 BRUSH_DeleteObject
/* pDeleteObject */
57 static BOOL
copy_bitmap( struct brush_pattern
*brush
, HBITMAP bitmap
)
59 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256])];
60 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
61 struct gdi_image_bits bits
;
62 struct bitblt_coords src
;
63 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, NTGDI_OBJ_BITMAP
);
65 if (!bmp
) return FALSE
;
67 src
.visrect
.left
= src
.x
= 0;
68 src
.visrect
.top
= src
.y
= 0;
69 src
.visrect
.right
= src
.width
= bmp
->dib
.dsBm
.bmWidth
;
70 src
.visrect
.bottom
= src
.height
= bmp
->dib
.dsBm
.bmHeight
;
71 if (get_image_from_bitmap( bmp
, info
, &bits
, &src
)) goto done
;
76 if (!(brush
->bits
.ptr
= malloc( info
->bmiHeader
.biSizeImage
))) goto done
;
77 memcpy( brush
->bits
.ptr
, bits
.ptr
, info
->bmiHeader
.biSizeImage
);
78 brush
->bits
.free
= free_heap_bits
;
81 if (!(brush
->info
= malloc( get_dib_info_size( info
, DIB_RGB_COLORS
))))
83 if (brush
->bits
.free
) brush
->bits
.free( &brush
->bits
);
86 memcpy( brush
->info
, info
, get_dib_info_size( info
, DIB_RGB_COLORS
));
87 brush
->bits
.is_copy
= FALSE
; /* the bits can't be modified */
88 brush
->usage
= DIB_RGB_COLORS
;
91 GDI_ReleaseObj( bitmap
);
92 return brush
->info
!= NULL
;
95 BOOL
store_brush_pattern( LOGBRUSH
*brush
, struct brush_pattern
*pattern
)
98 pattern
->bits
.free
= NULL
;
100 switch (brush
->lbStyle
)
107 if (brush
->lbHatch
> HS_DIAGCROSS
)
109 if (brush
->lbHatch
>= HS_API_MAX
) return FALSE
;
110 brush
->lbStyle
= BS_SOLID
;
116 brush
->lbStyle
= BS_PATTERN
;
120 return copy_bitmap( pattern
, (HBITMAP
)brush
->lbHatch
);
122 case BS_DIBPATTERNPT
:
123 pattern
->usage
= brush
->lbColor
;
124 pattern
->info
= copy_packed_dib( (BITMAPINFO
*)brush
->lbHatch
, pattern
->usage
);
125 if (!pattern
->info
) return FALSE
;
126 pattern
->bits
.ptr
= (char *)pattern
->info
+ get_dib_info_size( pattern
->info
, pattern
->usage
);
127 brush
->lbStyle
= BS_DIBPATTERN
;
132 case BS_DIBPATTERN8X8
:
136 WARN( "invalid brush style %u\n", brush
->lbStyle
);
141 void free_brush_pattern( struct brush_pattern
*pattern
)
143 if (pattern
->bits
.free
) pattern
->bits
.free( &pattern
->bits
);
144 free( pattern
->info
);
147 /**********************************************************************
148 * __wine_get_brush_bitmap_info (win32u.@)
150 BOOL CDECL
__wine_get_brush_bitmap_info( HBRUSH handle
, BITMAPINFO
*info
, void *bits
, UINT
*usage
)
155 if (!(brush
= GDI_GetObjPtr( handle
, NTGDI_OBJ_BRUSH
))) return FALSE
;
157 if (brush
->pattern
.info
)
161 memcpy( info
, brush
->pattern
.info
,
162 get_dib_info_size( brush
->pattern
.info
, brush
->pattern
.usage
));
163 if (info
->bmiHeader
.biBitCount
<= 8 && !info
->bmiHeader
.biClrUsed
)
164 fill_default_color_table( info
);
165 if (info
->bmiHeader
.biHeight
< 0)
166 info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
170 /* always return a bottom-up DIB */
171 if (brush
->pattern
.info
->bmiHeader
.biHeight
< 0)
173 unsigned int i
, width_bytes
, height
= -brush
->pattern
.info
->bmiHeader
.biHeight
;
176 width_bytes
= get_dib_stride( brush
->pattern
.info
->bmiHeader
.biWidth
,
177 brush
->pattern
.info
->bmiHeader
.biBitCount
);
178 dst_ptr
= (char *)bits
+ (height
- 1) * width_bytes
;
179 for (i
= 0; i
< height
; i
++, dst_ptr
-= width_bytes
)
180 memcpy( dst_ptr
, (char *)brush
->pattern
.bits
.ptr
+ i
* width_bytes
,
183 else memcpy( bits
, brush
->pattern
.bits
.ptr
,
184 brush
->pattern
.info
->bmiHeader
.biSizeImage
);
186 if (usage
) *usage
= brush
->pattern
.usage
;
189 GDI_ReleaseObj( handle
);
194 HBRUSH
create_brush( const LOGBRUSH
*brush
)
199 if (!(ptr
= malloc( sizeof(*ptr
) ))) return 0;
201 ptr
->logbrush
= *brush
;
203 if (store_brush_pattern( &ptr
->logbrush
, &ptr
->pattern
) &&
204 (hbrush
= alloc_gdi_handle( &ptr
->obj
, NTGDI_OBJ_BRUSH
, &brush_funcs
)))
206 TRACE("%p\n", hbrush
);
210 free_brush_pattern( &ptr
->pattern
);
216 /***********************************************************************
217 * NtGdiCreateHatchBrushInternal (win32u.@)
219 * Create a logical brush with a hatched pattern.
221 HBRUSH WINAPI
NtGdiCreateHatchBrushInternal( INT style
, COLORREF color
, BOOL pen
)
225 TRACE( "%d %s\n", style
, debugstr_color(color
) );
227 logbrush
.lbStyle
= BS_HATCHED
;
228 logbrush
.lbColor
= color
;
229 logbrush
.lbHatch
= style
;
231 return create_brush( &logbrush
);
235 /***********************************************************************
236 * NtGdiCreatePatternBrushInternal (win32u.@)
238 * Create a logical brush with a pattern from a bitmap.
240 HBRUSH WINAPI
NtGdiCreatePatternBrushInternal( HBITMAP bitmap
, BOOL pen
, BOOL is_8x8
)
242 LOGBRUSH logbrush
= { BS_PATTERN
, 0, 0 };
244 TRACE( "%p\n", bitmap
);
246 logbrush
.lbHatch
= (ULONG_PTR
)bitmap
;
247 return create_brush( &logbrush
);
251 /***********************************************************************
252 * NtGdiCreateDIBBrush (win32u.@)
254 * Create a logical brush with a pattern from a DIB.
256 HBRUSH WINAPI
NtGdiCreateDIBBrush( const void *data
, UINT coloruse
, UINT size
,
257 BOOL is_8x8
, BOOL pen
, const void *client
)
259 const BITMAPINFO
*info
= data
;
265 TRACE( "%p %dx%d %dbpp\n", info
, (int)info
->bmiHeader
.biWidth
,
266 (int)info
->bmiHeader
.biHeight
, (int)info
->bmiHeader
.biBitCount
);
268 logbrush
.lbStyle
= BS_DIBPATTERNPT
;
269 logbrush
.lbColor
= coloruse
;
270 logbrush
.lbHatch
= (ULONG_PTR
)data
;
272 return create_brush( &logbrush
);
276 /***********************************************************************
277 * NtGdiCreateSolidBrush (win32u.@)
279 * Create a logical brush consisting of a single colour.
281 HBRUSH WINAPI
NtGdiCreateSolidBrush( COLORREF color
, HBRUSH brush
)
285 TRACE("%s\n", debugstr_color(color
) );
287 logbrush
.lbStyle
= BS_SOLID
;
288 logbrush
.lbColor
= color
;
289 logbrush
.lbHatch
= 0;
291 return create_brush( &logbrush
);
295 /***********************************************************************
296 * NtGdiSelectBrush (win32u.@)
298 HGDIOBJ WINAPI
NtGdiSelectBrush( HDC hdc
, HGDIOBJ handle
)
304 if (!(dc
= get_dc_ptr( hdc
))) return 0;
306 if ((brush
= GDI_GetObjPtr( handle
, NTGDI_OBJ_BRUSH
)))
308 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSelectBrush
);
309 struct brush_pattern
*pattern
= &brush
->pattern
;
311 if (!pattern
->info
) pattern
= NULL
;
313 GDI_inc_ref_count( handle
);
314 GDI_ReleaseObj( handle
);
316 if (!physdev
->funcs
->pSelectBrush( physdev
, handle
, pattern
))
318 GDI_dec_ref_count( handle
);
324 GDI_dec_ref_count( ret
);
327 release_dc_ptr( dc
);
332 /***********************************************************************
335 static BOOL
BRUSH_DeleteObject( HGDIOBJ handle
)
337 BRUSHOBJ
*brush
= free_gdi_handle( handle
);
339 if (!brush
) return FALSE
;
340 free_brush_pattern( &brush
->pattern
);
346 /***********************************************************************
349 static INT
BRUSH_GetObject( HGDIOBJ handle
, INT count
, LPVOID buffer
)
351 BRUSHOBJ
*brush
= GDI_GetObjPtr( handle
, NTGDI_OBJ_BRUSH
);
353 if (!brush
) return 0;
356 if (count
> sizeof(brush
->logbrush
)) count
= sizeof(brush
->logbrush
);
357 memcpy( buffer
, &brush
->logbrush
, count
);
359 else count
= sizeof(brush
->logbrush
);
360 GDI_ReleaseObj( handle
);