Store a bitmap of active hooks on the client side to try to avoid
[wine] / dlls / gdi / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "wine/wingdi16.h"
30 #include "gdi.h"
31 #include "wownt32.h"
32 #include "gdi_private.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
36
37 /* GDI logical brush object */
38 typedef struct
39 {
40     GDIOBJHDR header;
41     LOGBRUSH  logbrush;
42 } BRUSHOBJ;
43
44 #define NB_HATCH_STYLES  6
45
46 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
47 static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
48 static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
49 static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj );
50
51 static const struct gdi_obj_funcs brush_funcs =
52 {
53     BRUSH_SelectObject,  /* pSelectObject */
54     BRUSH_GetObject16,   /* pGetObject16 */
55     BRUSH_GetObject,     /* pGetObjectA */
56     BRUSH_GetObject,     /* pGetObjectW */
57     NULL,                /* pUnrealizeObject */
58     BRUSH_DeleteObject   /* pDeleteObject */
59 };
60
61 static HGLOBAL16 dib_copy(BITMAPINFO *info, UINT coloruse)
62 {
63     BITMAPINFO  *newInfo;
64     HGLOBAL16   hmem;
65     INT         size;
66
67     if (info->bmiHeader.biCompression)
68         size = info->bmiHeader.biSizeImage;
69     else
70         size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
71                                     info->bmiHeader.biHeight,
72                                     info->bmiHeader.biBitCount);
73     size += DIB_BitmapInfoSize( info, coloruse );
74
75     if (!(hmem = GlobalAlloc16( GMEM_MOVEABLE, size )))
76     {
77         return 0;
78     }
79     newInfo = (BITMAPINFO *) GlobalLock16( hmem );
80     memcpy( newInfo, info, size );
81     GlobalUnlock16( hmem );
82     return hmem;
83 }
84
85
86 /***********************************************************************
87  *           CreateBrushIndirect    (GDI32.@)
88  *
89  * Create a logical brush with a given style, color or pattern.
90  *
91  * PARAMS
92  *  brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
93  *
94  * RETURNS
95  *  A handle to the created brush, or a NULL handle if the brush cannot be 
96  *  created.
97  *
98  * NOTES
99  * - The brush returned should be freed by the caller using DeleteObject()
100  *   when it is no longer required.
101  * - Windows 95 and earlier cannot create brushes from bitmaps or DIBs larger
102  *   than 8x8 pixels. If a larger bitmap is given, only a portion of the bitmap
103  *   is used.
104  */
105 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
106 {
107     BRUSHOBJ * ptr;
108     HBRUSH hbrush;
109
110     if (!(ptr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC,
111                                 (HGDIOBJ *)&hbrush, &brush_funcs ))) return 0;
112     ptr->logbrush.lbStyle = brush->lbStyle;
113     ptr->logbrush.lbColor = brush->lbColor;
114     ptr->logbrush.lbHatch = brush->lbHatch;
115
116     switch (ptr->logbrush.lbStyle)
117     {
118     case BS_PATTERN8X8:
119         ptr->logbrush.lbStyle = BS_PATTERN;
120         /* fall through */
121     case BS_PATTERN:
122         ptr->logbrush.lbHatch = (LONG)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch );
123         if (!ptr->logbrush.lbHatch) goto error;
124         break;
125
126     case BS_DIBPATTERNPT:
127         ptr->logbrush.lbStyle = BS_DIBPATTERN;
128         ptr->logbrush.lbHatch = (LONG)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch,
129                                                 ptr->logbrush.lbColor);
130         if (!ptr->logbrush.lbHatch) goto error;
131         break;
132
133     case BS_DIBPATTERN8X8:
134     case BS_DIBPATTERN:
135        {
136             BITMAPINFO* bmi;
137             HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;
138
139             ptr->logbrush.lbStyle = BS_DIBPATTERN;
140             if (!(bmi = (BITMAPINFO *)GlobalLock( h ))) goto error;
141             ptr->logbrush.lbHatch = dib_copy( bmi, ptr->logbrush.lbColor);
142             GlobalUnlock( h );
143             if (!ptr->logbrush.lbHatch) goto error;
144             break;
145        }
146
147     default:
148         if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error;
149         break;
150     }
151
152     GDI_ReleaseObj( hbrush );
153     TRACE("%p\n", hbrush);
154     return hbrush;
155
156  error:
157     GDI_FreeObject( hbrush, ptr );
158     return 0;
159 }
160
161
162 /***********************************************************************
163  *           CreateHatchBrush    (GDI32.@)
164  *
165  * Create a logical brush with a hatched pattern.
166  *
167  * PARAMS
168  *  style [I] Direction of lines for the hatch pattern (HS_* values from "wingdi.h")
169  *  color [I] Colour of the hatched pattern
170  *
171  * RETURNS
172  *  A handle to the created brush, or a NULL handle if the brush cannot
173  *  be created.
174  *
175  * NOTES
176  * - This function uses CreateBrushIndirect() to create the brush.
177  * - The brush returned should be freed by the caller using DeleteObject()
178  *   when it is no longer required.
179  */
180 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
181 {
182     LOGBRUSH logbrush;
183
184     TRACE("%d %06lx\n", style, color );
185
186     logbrush.lbStyle = BS_HATCHED;
187     logbrush.lbColor = color;
188     logbrush.lbHatch = style;
189
190     return CreateBrushIndirect( &logbrush );
191 }
192
193
194 /***********************************************************************
195  *           CreatePatternBrush    (GDI32.@)
196  *
197  * Create a logical brush with a pattern from a bitmap.
198  *
199  * PARAMS
200  *  hbitmap  [I] Bitmap containing pattern for the brush
201  *
202  * RETURNS
203  *  A handle to the created brush, or a NULL handle if the brush cannot 
204  *  be created.
205  *
206  * NOTES
207  * - This function uses CreateBrushIndirect() to create the brush.
208  * - The brush returned should be freed by the caller using DeleteObject()
209  *   when it is no longer required.
210  */
211 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
212 {
213     LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
214     TRACE("%p\n", hbitmap );
215
216     logbrush.lbHatch = (ULONG_PTR)hbitmap;
217     return CreateBrushIndirect( &logbrush );
218 }
219
220
221 /***********************************************************************
222  *           CreateDIBPatternBrush    (GDI32.@)
223  *
224  * Create a logical brush with a pattern from a DIB.
225  *
226  * PARAMS
227  *  hbitmap  [I] Global object containing BITMAPINFO structure for the pattern
228  *  coloruse [I] Specifies color format, if provided
229  *
230  * RETURNS
231  *  A handle to the created brush, or a NULL handle if the brush cannot 
232  *  be created.
233  *
234  * NOTES
235  * - This function uses CreateBrushIndirect() to create the brush.
236  * - The brush returned should be freed by the caller using DeleteObject()
237  *   when it is no longer required.
238  * - This function is for compatibility only. CreateDIBPatternBrushPt() should 
239  *   be used instead.
240  */
241 HBRUSH WINAPI CreateDIBPatternBrush( HGLOBAL hbitmap, UINT coloruse )
242 {
243     LOGBRUSH logbrush;
244
245     TRACE("%p\n", hbitmap );
246
247     logbrush.lbStyle = BS_DIBPATTERN;
248     logbrush.lbColor = coloruse;
249
250     logbrush.lbHatch = (LONG)hbitmap;
251
252     return CreateBrushIndirect( &logbrush );
253 }
254
255
256 /***********************************************************************
257  *           CreateDIBPatternBrushPt    (GDI32.@)
258  *
259  * Create a logical brush with a pattern from a DIB.
260  *
261  * PARAMS
262  *  data     [I] Pointer to a BITMAPINFO structure and image data  for the pattern
263  *  coloruse [I] Specifies color format, if provided
264  *
265  * RETURNS
266  *  A handle to the created brush, or a NULL handle if the brush cannot
267  *  be created.
268  *
269  * NOTES
270  * - This function uses CreateBrushIndirect() to create the brush.
271  * - The brush returned should be freed by the caller using DeleteObject()
272  *   when it is no longer required.
273  */
274 HBRUSH WINAPI CreateDIBPatternBrushPt( const void* data, UINT coloruse )
275 {
276     BITMAPINFO *info=(BITMAPINFO*)data;
277     LOGBRUSH logbrush;
278
279     if (!data)
280         return NULL;
281
282     TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth,
283           info->bmiHeader.biHeight,  info->bmiHeader.biBitCount);
284
285     logbrush.lbStyle = BS_DIBPATTERNPT;
286     logbrush.lbColor = coloruse;
287     logbrush.lbHatch = (LONG) data;
288
289     return CreateBrushIndirect( &logbrush );
290 }
291
292
293 /***********************************************************************
294  *           CreateSolidBrush    (GDI32.@)
295  *
296  * Create a logical brush consisting of a single colour.
297  *
298  * PARAMS
299  *  color [I] Colour to make the solid brush
300  *
301  * RETURNS
302  *  A handle to the newly created brush, or a NULL handle if the brush cannot
303  *  be created.
304  *
305  * NOTES
306  * - This function uses CreateBrushIndirect() to create the brush.
307  * - The brush returned should be freed by the caller using DeleteObject()
308  *   when it is no longer required.
309  */
310 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
311 {
312     LOGBRUSH logbrush;
313
314     TRACE("%06lx\n", color );
315
316     logbrush.lbStyle = BS_SOLID;
317     logbrush.lbColor = color;
318     logbrush.lbHatch = 0;
319
320     return CreateBrushIndirect( &logbrush );
321 }
322
323
324 /***********************************************************************
325  *           SetBrushOrgEx    (GDI32.@)
326  *
327  * Set the brush origin for a device context.
328  *
329  * PARAMS
330  *  hdc    [I] Device context to set the brush origin for 
331  *  x      [I] New x origin
332  *  y      [I] Ney y origin
333  *  oldorg [O] If non NULL, destination for previously set brush origin.
334  *
335  * RETURNS
336  *  Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
337  */
338 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
339 {
340     DC *dc = DC_GetDCPtr( hdc );
341
342     if (!dc) return FALSE;
343     if (oldorg)
344     {
345         oldorg->x = dc->brushOrgX;
346         oldorg->y = dc->brushOrgY;
347     }
348     dc->brushOrgX = x;
349     dc->brushOrgY = y;
350     GDI_ReleaseObj( hdc );
351     return TRUE;
352 }
353
354 /***********************************************************************
355  *           FixBrushOrgEx    (GDI32.@)
356  *
357  * See SetBrushOrgEx.
358  *
359  * NOTES
360  *  This function is no longer documented by MSDN, but in Win95 GDI32 it
361  *  is the same as SetBrushOrgEx().
362  */
363 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
364 {
365     return SetBrushOrgEx(hdc,x,y,oldorg);
366 }
367
368
369 /***********************************************************************
370  *           BRUSH_SelectObject
371  */
372 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
373 {
374     BRUSHOBJ *brush = obj;
375     HGDIOBJ ret;
376     DC *dc = DC_GetDCPtr( hdc );
377
378     if (!dc) return 0;
379
380     if (brush->logbrush.lbStyle == BS_PATTERN)
381         BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc );
382
383     ret = dc->hBrush;
384     if (dc->funcs->pSelectBrush) handle = dc->funcs->pSelectBrush( dc->physDev, handle );
385     if (handle) dc->hBrush = handle;
386     else ret = 0;
387     GDI_ReleaseObj( hdc );
388     return ret;
389 }
390
391
392 /***********************************************************************
393  *           BRUSH_DeleteObject
394  */
395 static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj )
396 {
397     BRUSHOBJ *brush = obj;
398
399     switch(brush->logbrush.lbStyle)
400     {
401       case BS_PATTERN:
402           DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
403           break;
404       case BS_DIBPATTERN:
405           GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
406           break;
407     }
408     return GDI_FreeObject( handle, obj );
409 }
410
411
412 /***********************************************************************
413  *           BRUSH_GetObject16
414  */
415 static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
416 {
417     BRUSHOBJ *brush = obj;
418     LOGBRUSH16 logbrush;
419
420     logbrush.lbStyle = brush->logbrush.lbStyle;
421     logbrush.lbColor = brush->logbrush.lbColor;
422     logbrush.lbHatch = brush->logbrush.lbHatch;
423     if (count > sizeof(logbrush)) count = sizeof(logbrush);
424     memcpy( buffer, &logbrush, count );
425     return count;
426 }
427
428
429 /***********************************************************************
430  *           BRUSH_GetObject
431  */
432 static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
433 {
434     BRUSHOBJ *brush = obj;
435
436     if( !buffer )
437         return sizeof(brush->logbrush);
438
439     if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
440     memcpy( buffer, &brush->logbrush, count );
441     return count;
442 }
443
444
445 /***********************************************************************
446  *           SetSolidBrush   (GDI.604)
447  *
448  * Change the color of a solid brush.
449  *
450  * PARAMS
451  *  hBrush   [I] Brush to change the color of
452  *  newColor [I] New color for hBrush
453  *
454  * RETURNS
455  *  Success: TRUE. The color of hBrush is set to newColor.
456  *  Failure: FALSE.
457  *
458  * FIXME
459  *  This function is undocumented and untested. The implementation may
460  *  not be correct.
461  */
462 BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
463 {
464     BRUSHOBJ * brushPtr;
465     BOOL16 res = FALSE;
466
467     TRACE("(hBrush %04x, newColor %08lx)\n", hBrush, (DWORD)newColor);
468     if (!(brushPtr = (BRUSHOBJ *) GDI_GetObjPtr( HBRUSH_32(hBrush), BRUSH_MAGIC )))
469         return FALSE;
470
471     if (brushPtr->logbrush.lbStyle == BS_SOLID)
472     {
473         brushPtr->logbrush.lbColor = newColor;
474         res = TRUE;
475     }
476
477      GDI_ReleaseObj( HBRUSH_32(hBrush) );
478      return res;
479 }