include: Assorted spelling fixes.
[wine] / dlls / gdi32 / brush.c
1 /*
2  * GDI brush objects
3  *
4  * Copyright 1993, 1994  Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "gdi_private.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
33
34 /* GDI logical brush object */
35 typedef struct
36 {
37     LOGBRUSH              logbrush;
38     struct brush_pattern  pattern;
39 } BRUSHOBJ;
40
41 #define NB_HATCH_STYLES  6
42
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 );
46
47 static const struct gdi_obj_funcs brush_funcs =
48 {
49     BRUSH_SelectObject,  /* pSelectObject */
50     BRUSH_GetObject,     /* pGetObjectA */
51     BRUSH_GetObject,     /* pGetObjectW */
52     NULL,                /* pUnrealizeObject */
53     BRUSH_DeleteObject   /* pDeleteObject */
54 };
55
56
57 static BOOL copy_bitmap( struct brush_pattern *brush, HBITMAP bitmap )
58 {
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, OBJ_BITMAP );
64
65     if (!bmp) return FALSE;
66
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;
72
73     brush->bits = bits;
74     if (!bits.free)
75     {
76         if (!(brush->bits.ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ))) goto done;
77         memcpy( brush->bits.ptr, bits.ptr, info->bmiHeader.biSizeImage );
78         brush->bits.free = free_heap_bits;
79     }
80
81     if (!(brush->info = HeapAlloc( GetProcessHeap(), 0, get_dib_info_size( info, DIB_RGB_COLORS ))))
82     {
83         if (brush->bits.free) brush->bits.free( &brush->bits );
84         goto done;
85     }
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;
89
90 done:
91     GDI_ReleaseObj( bitmap );
92     return brush->info != NULL;
93 }
94
95 BOOL store_brush_pattern( LOGBRUSH *brush, struct brush_pattern *pattern )
96 {
97     HGLOBAL hmem = 0;
98
99     pattern->info = NULL;
100     pattern->bits.free = NULL;
101
102     switch (brush->lbStyle)
103     {
104     case BS_SOLID:
105     case BS_HOLLOW:
106         return TRUE;
107
108     case BS_HATCHED:
109         if (brush->lbHatch > HS_DIAGCROSS)
110         {
111             if (brush->lbHatch >= HS_API_MAX) return FALSE;
112             brush->lbStyle = BS_SOLID;
113             brush->lbHatch = 0;
114         }
115         return TRUE;
116
117     case BS_PATTERN8X8:
118         brush->lbStyle = BS_PATTERN;
119         /* fall through */
120     case BS_PATTERN:
121         brush->lbColor = 0;
122         return copy_bitmap( pattern, (HBITMAP)brush->lbHatch );
123
124     case BS_DIBPATTERN:
125         hmem = (HGLOBAL)brush->lbHatch;
126         if (!(brush->lbHatch = (ULONG_PTR)GlobalLock( hmem ))) return FALSE;
127         /* fall through */
128     case BS_DIBPATTERNPT:
129         pattern->usage = brush->lbColor;
130         pattern->info = copy_packed_dib( (BITMAPINFO *)brush->lbHatch, pattern->usage );
131         if (hmem) GlobalUnlock( hmem );
132         if (!pattern->info) return FALSE;
133         pattern->bits.ptr = (char *)pattern->info + get_dib_info_size( pattern->info, pattern->usage );
134         brush->lbStyle = BS_DIBPATTERN;
135         brush->lbColor = 0;
136         return TRUE;
137
138     case BS_DIBPATTERN8X8:
139     case BS_MONOPATTERN:
140     case BS_INDEXED:
141     default:
142         WARN( "invalid brush style %u\n", brush->lbStyle );
143         return FALSE;
144     }
145 }
146
147 void free_brush_pattern( struct brush_pattern *pattern )
148 {
149     if (pattern->bits.free) pattern->bits.free( &pattern->bits );
150     HeapFree( GetProcessHeap(), 0, pattern->info );
151 }
152
153 BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage )
154 {
155     BRUSHOBJ *brush;
156     BOOL ret = FALSE;
157
158     if (!(brush = GDI_GetObjPtr( handle, OBJ_BRUSH ))) return FALSE;
159
160     if (brush->pattern.info)
161     {
162         memcpy( info, brush->pattern.info, 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         *bits = brush->pattern.bits.ptr;
166         *usage = brush->pattern.usage;
167         ret = TRUE;
168     }
169     GDI_ReleaseObj( handle );
170     return ret;
171 }
172
173
174 /***********************************************************************
175  *           CreateBrushIndirect    (GDI32.@)
176  *
177  * Create a logical brush with a given style, color or pattern.
178  *
179  * PARAMS
180  *  brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
181  *
182  * RETURNS
183  *  A handle to the created brush, or a NULL handle if the brush cannot be 
184  *  created.
185  *
186  * NOTES
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
191  *   is used.
192  */
193 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
194 {
195     BRUSHOBJ * ptr;
196     HBRUSH hbrush;
197
198     if (!(ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(*ptr) ))) return 0;
199
200     ptr->logbrush = *brush;
201
202     if (store_brush_pattern( &ptr->logbrush, &ptr->pattern ) &&
203         (hbrush = alloc_gdi_handle( ptr, OBJ_BRUSH, &brush_funcs )))
204     {
205         TRACE("%p\n", hbrush);
206         return hbrush;
207     }
208
209     free_brush_pattern( &ptr->pattern );
210     HeapFree( GetProcessHeap(), 0, ptr );
211     return 0;
212 }
213
214
215 /***********************************************************************
216  *           CreateHatchBrush    (GDI32.@)
217  *
218  * Create a logical brush with a hatched pattern.
219  *
220  * PARAMS
221  *  style [I] Direction of lines for the hatch pattern (HS_* values from "wingdi.h")
222  *  color [I] Colour of the hatched pattern
223  *
224  * RETURNS
225  *  A handle to the created brush, or a NULL handle if the brush cannot
226  *  be created.
227  *
228  * NOTES
229  * - This function uses CreateBrushIndirect() to create the brush.
230  * - The brush returned should be freed by the caller using DeleteObject()
231  *   when it is no longer required.
232  */
233 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
234 {
235     LOGBRUSH logbrush;
236
237     TRACE("%d %06x\n", style, color );
238
239     logbrush.lbStyle = BS_HATCHED;
240     logbrush.lbColor = color;
241     logbrush.lbHatch = style;
242
243     return CreateBrushIndirect( &logbrush );
244 }
245
246
247 /***********************************************************************
248  *           CreatePatternBrush    (GDI32.@)
249  *
250  * Create a logical brush with a pattern from a bitmap.
251  *
252  * PARAMS
253  *  hbitmap  [I] Bitmap containing pattern for the brush
254  *
255  * RETURNS
256  *  A handle to the created brush, or a NULL handle if the brush cannot 
257  *  be created.
258  *
259  * NOTES
260  * - This function uses CreateBrushIndirect() to create the brush.
261  * - The brush returned should be freed by the caller using DeleteObject()
262  *   when it is no longer required.
263  */
264 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
265 {
266     LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
267     TRACE("%p\n", hbitmap );
268
269     logbrush.lbHatch = (ULONG_PTR)hbitmap;
270     return CreateBrushIndirect( &logbrush );
271 }
272
273
274 /***********************************************************************
275  *           CreateDIBPatternBrush    (GDI32.@)
276  *
277  * Create a logical brush with a pattern from a DIB.
278  *
279  * PARAMS
280  *  hbitmap  [I] Global object containing BITMAPINFO structure for the pattern
281  *  coloruse [I] Specifies color format, if provided
282  *
283  * RETURNS
284  *  A handle to the created brush, or a NULL handle if the brush cannot 
285  *  be created.
286  *
287  * NOTES
288  * - This function uses CreateBrushIndirect() to create the brush.
289  * - The brush returned should be freed by the caller using DeleteObject()
290  *   when it is no longer required.
291  * - This function is for compatibility only. CreateDIBPatternBrushPt() should 
292  *   be used instead.
293  */
294 HBRUSH WINAPI CreateDIBPatternBrush( HGLOBAL hbitmap, UINT coloruse )
295 {
296     LOGBRUSH logbrush;
297
298     TRACE("%p\n", hbitmap );
299
300     logbrush.lbStyle = BS_DIBPATTERN;
301     logbrush.lbColor = coloruse;
302
303     logbrush.lbHatch = (ULONG_PTR)hbitmap;
304
305     return CreateBrushIndirect( &logbrush );
306 }
307
308
309 /***********************************************************************
310  *           CreateDIBPatternBrushPt    (GDI32.@)
311  *
312  * Create a logical brush with a pattern from a DIB.
313  *
314  * PARAMS
315  *  data     [I] Pointer to a BITMAPINFO structure and image data  for the pattern
316  *  coloruse [I] Specifies color format, if provided
317  *
318  * RETURNS
319  *  A handle to the created brush, or a NULL handle if the brush cannot
320  *  be created.
321  *
322  * NOTES
323  * - This function uses CreateBrushIndirect() to create the brush.
324  * - The brush returned should be freed by the caller using DeleteObject()
325  *   when it is no longer required.
326  */
327 HBRUSH WINAPI CreateDIBPatternBrushPt( const void* data, UINT coloruse )
328 {
329     const BITMAPINFO *info=data;
330     LOGBRUSH logbrush;
331
332     if (!data)
333         return NULL;
334
335     TRACE("%p %dx%d %dbpp\n", info, info->bmiHeader.biWidth,
336           info->bmiHeader.biHeight,  info->bmiHeader.biBitCount);
337
338     logbrush.lbStyle = BS_DIBPATTERNPT;
339     logbrush.lbColor = coloruse;
340     logbrush.lbHatch = (ULONG_PTR)data;
341
342     return CreateBrushIndirect( &logbrush );
343 }
344
345
346 /***********************************************************************
347  *           CreateSolidBrush    (GDI32.@)
348  *
349  * Create a logical brush consisting of a single colour.
350  *
351  * PARAMS
352  *  color [I] Colour to make the solid brush
353  *
354  * RETURNS
355  *  A handle to the newly created brush, or a NULL handle if the brush cannot
356  *  be created.
357  *
358  * NOTES
359  * - This function uses CreateBrushIndirect() to create the brush.
360  * - The brush returned should be freed by the caller using DeleteObject()
361  *   when it is no longer required.
362  */
363 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
364 {
365     LOGBRUSH logbrush;
366
367     TRACE("%06x\n", color );
368
369     logbrush.lbStyle = BS_SOLID;
370     logbrush.lbColor = color;
371     logbrush.lbHatch = 0;
372
373     return CreateBrushIndirect( &logbrush );
374 }
375
376
377 /***********************************************************************
378  *           SetBrushOrgEx    (GDI32.@)
379  *
380  * Set the brush origin for a device context.
381  *
382  * PARAMS
383  *  hdc    [I] Device context to set the brush origin for
384  *  x      [I] New x origin
385  *  y      [I] New y origin
386  *  oldorg [O] If non NULL, destination for previously set brush origin.
387  *
388  * RETURNS
389  *  Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
390  */
391 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
392 {
393     DC *dc = get_dc_ptr( hdc );
394
395     if (!dc) return FALSE;
396     if (oldorg)
397     {
398         oldorg->x = dc->brushOrgX;
399         oldorg->y = dc->brushOrgY;
400     }
401     dc->brushOrgX = x;
402     dc->brushOrgY = y;
403     release_dc_ptr( dc );
404     return TRUE;
405 }
406
407 /***********************************************************************
408  *           FixBrushOrgEx    (GDI32.@)
409  *
410  * See SetBrushOrgEx.
411  *
412  * NOTES
413  *  This function is no longer documented by MSDN, but in Win95 GDI32 it
414  *  is the same as SetBrushOrgEx().
415  */
416 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
417 {
418     return SetBrushOrgEx(hdc,x,y,oldorg);
419 }
420
421
422 /***********************************************************************
423  *           BRUSH_SelectObject
424  */
425 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc )
426 {
427     BRUSHOBJ *brush;
428     HGDIOBJ ret = 0;
429     DC *dc = get_dc_ptr( hdc );
430
431     if (!dc)
432     {
433         SetLastError( ERROR_INVALID_HANDLE );
434         return 0;
435     }
436
437     if ((brush = GDI_GetObjPtr( handle, OBJ_BRUSH )))
438     {
439         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectBrush );
440         struct brush_pattern *pattern = &brush->pattern;
441
442         if (!pattern->info) pattern = NULL;
443
444         GDI_inc_ref_count( handle );
445         GDI_ReleaseObj( handle );
446
447         if (!physdev->funcs->pSelectBrush( physdev, handle, pattern ))
448         {
449             GDI_dec_ref_count( handle );
450         }
451         else
452         {
453             ret = dc->hBrush;
454             dc->hBrush = handle;
455             GDI_dec_ref_count( ret );
456         }
457     }
458     release_dc_ptr( dc );
459     return ret;
460 }
461
462
463 /***********************************************************************
464  *           BRUSH_DeleteObject
465  */
466 static BOOL BRUSH_DeleteObject( HGDIOBJ handle )
467 {
468     BRUSHOBJ *brush = free_gdi_handle( handle );
469
470     if (!brush) return FALSE;
471     free_brush_pattern( &brush->pattern );
472     return HeapFree( GetProcessHeap(), 0, brush );
473 }
474
475
476 /***********************************************************************
477  *           BRUSH_GetObject
478  */
479 static INT BRUSH_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
480 {
481     BRUSHOBJ *brush = GDI_GetObjPtr( handle, OBJ_BRUSH );
482
483     if (!brush) return 0;
484     if (buffer)
485     {
486         if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
487         memcpy( buffer, &brush->logbrush, count );
488     }
489     else count = sizeof(brush->logbrush);
490     GDI_ReleaseObj( handle );
491     return count;
492 }