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