Correct tests involved with processing the LVIF_DI_SETITEM flag.
[wine] / objects / brush.c
1 /*
2  * GDI brush objects
3  *
4  * Copyright 1993, 1994  Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <string.h>
10
11 #include "winbase.h"
12 #include "wingdi.h"
13
14 #include "wine/wingdi16.h"
15 #include "bitmap.h"
16 #include "brush.h"
17
18 #include "debugtools.h"
19
20 DEFAULT_DEBUG_CHANNEL(gdi);
21
22 static HGLOBAL16 dib_copy(BITMAPINFO *info, UINT coloruse)
23 {
24     BITMAPINFO  *newInfo;
25     HGLOBAL16   hmem;
26     INT         size;
27
28     if (info->bmiHeader.biCompression)
29         size = info->bmiHeader.biSizeImage;
30     else
31         size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
32                                     info->bmiHeader.biHeight,
33                                     info->bmiHeader.biBitCount);
34     size += DIB_BitmapInfoSize( info, coloruse );
35
36     if (!(hmem = GlobalAlloc16( GMEM_MOVEABLE, size )))
37     {
38         return 0;
39     }
40     newInfo = (BITMAPINFO *) GlobalLock16( hmem );
41     memcpy( newInfo, info, size );
42     GlobalUnlock16( hmem );
43     return hmem;
44 }
45
46
47
48 static BOOL create_brush_indirect(BRUSHOBJ *brushPtr, BOOL v16)
49 {
50     LOGBRUSH *brush = &brushPtr->logbrush;
51
52     switch (brush->lbStyle)
53     {
54        case BS_PATTERN8X8:
55             brush->lbStyle = BS_PATTERN;
56        case BS_PATTERN:
57             brush->lbHatch = (LONG)BITMAP_CopyBitmap( (HBITMAP) brush->lbHatch );
58             if (! brush->lbHatch)
59                break;
60             return TRUE;
61
62        case BS_DIBPATTERNPT:
63             brush->lbStyle = BS_DIBPATTERN;
64             brush->lbHatch = (LONG)dib_copy( (BITMAPINFO *) brush->lbHatch,
65                                              brush->lbColor);
66             if (! brush->lbHatch)
67                break;
68             return TRUE;
69
70        case BS_DIBPATTERN8X8:
71        case BS_DIBPATTERN:
72        {
73             BITMAPINFO* bmi;
74             HGLOBAL     h = brush->lbHatch;
75
76             brush->lbStyle = BS_DIBPATTERN;
77             if (v16)
78             {
79                if (!(bmi = (BITMAPINFO *)GlobalLock16( h )))
80                   break;
81             }
82             else
83             {
84                if (!(bmi = (BITMAPINFO *)GlobalLock( h )))
85                   break;
86             }
87
88             brush->lbHatch = dib_copy( bmi, brush->lbColor);
89
90             if (v16)  GlobalUnlock16( h );
91             else      GlobalUnlock( h );
92
93             if (!brush->lbHatch)
94                break;
95
96             return TRUE;
97        }
98
99        default:
100           if( brush->lbStyle <= BS_MONOPATTERN)
101              return TRUE;
102     }
103
104     return FALSE;
105 }
106
107
108 /***********************************************************************
109  *           CreateBrushIndirect    (GDI.50)
110  */
111 HBRUSH16 WINAPI CreateBrushIndirect16( const LOGBRUSH16 * brush )
112 {
113     BOOL success;
114     BRUSHOBJ * brushPtr;
115     HBRUSH hbrush;
116
117     if (!(brushPtr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC, &hbrush ))) return 0;
118     brushPtr->logbrush.lbStyle = brush->lbStyle;
119     brushPtr->logbrush.lbColor = brush->lbColor;
120     brushPtr->logbrush.lbHatch = brush->lbHatch;
121     success = create_brush_indirect(brushPtr, TRUE);
122     if(!success)
123     {
124        GDI_FreeObject( hbrush, brushPtr );
125        hbrush = 0;
126     }
127     else GDI_ReleaseObj( hbrush );
128     TRACE("%04x\n", hbrush);
129     return hbrush;
130 }
131
132
133 /***********************************************************************
134  *           CreateBrushIndirect    (GDI32.@)
135  *
136  * BUGS
137  *      As for Windows 95 and Windows 98:
138  *      Creating brushes from bitmaps or DIBs larger than 8x8 pixels
139  *      is not supported. If a larger bitmap is given, only a portion
140  *      of the bitmap is used.
141  */
142 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
143 {
144     BOOL success;
145     BRUSHOBJ * brushPtr;
146     HBRUSH hbrush;
147     if (!(brushPtr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC, &hbrush ))) return 0;
148     brushPtr->logbrush.lbStyle = brush->lbStyle;
149     brushPtr->logbrush.lbColor = brush->lbColor;
150     brushPtr->logbrush.lbHatch = brush->lbHatch;
151     success = create_brush_indirect(brushPtr, FALSE);
152     if(!success)
153     {
154        GDI_FreeObject( hbrush, brushPtr );
155        hbrush = 0;
156     }
157     else GDI_ReleaseObj( hbrush );
158     TRACE("%08x\n", hbrush);
159     return hbrush;
160 }
161
162
163 /***********************************************************************
164  *           CreateHatchBrush    (GDI.58)
165  */
166 HBRUSH16 WINAPI CreateHatchBrush16( INT16 style, COLORREF color )
167 {
168     return CreateHatchBrush( style, color );
169 }
170
171
172 /***********************************************************************
173  *           CreateHatchBrush    (GDI32.@)
174  */
175 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
176 {
177     LOGBRUSH logbrush;
178
179     TRACE("%d %06lx\n", style, color );
180
181     logbrush.lbStyle = BS_HATCHED;
182     logbrush.lbColor = color;
183     logbrush.lbHatch = style;
184
185     return CreateBrushIndirect( &logbrush );
186 }
187
188
189 /***********************************************************************
190  *           CreatePatternBrush    (GDI.60)
191  */
192 HBRUSH16 WINAPI CreatePatternBrush16( HBITMAP16 hbitmap )
193 {
194     return (HBRUSH16)CreatePatternBrush( hbitmap );
195 }
196
197
198 /***********************************************************************
199  *           CreatePatternBrush    (GDI32.@)
200  */
201 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
202 {
203     LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
204     TRACE("%04x\n", hbitmap );
205
206     logbrush.lbHatch = hbitmap;
207         return CreateBrushIndirect( &logbrush );
208 }
209
210
211 /***********************************************************************
212  *           CreateDIBPatternBrush    (GDI.445)
213  */
214 HBRUSH16 WINAPI CreateDIBPatternBrush16( HGLOBAL16 hbitmap, UINT16 coloruse )
215 {
216     LOGBRUSH16 logbrush;
217
218     TRACE("%04x\n", hbitmap );
219
220     logbrush.lbStyle = BS_DIBPATTERN;
221     logbrush.lbColor = coloruse;
222     logbrush.lbHatch = hbitmap;
223
224     return CreateBrushIndirect16( &logbrush );
225     }
226
227
228 /***********************************************************************
229  *           CreateDIBPatternBrush    (GDI32.@)
230  *
231  *      Create a logical brush which has the pattern specified by the DIB
232  *
233  *      Function call is for compatibility only.  CreateDIBPatternBrushPt should be used.   
234  *
235  * RETURNS
236  *
237  *      Handle to a logical brush on success, NULL on failure.
238  *
239  * BUGS
240  *      
241  */
242 HBRUSH WINAPI CreateDIBPatternBrush( 
243                 HGLOBAL hbitmap, /* [in] Global object containg BITMAPINFO structure */
244                 UINT coloruse    /* [in] Specifies color format, if provided */
245 )
246 {
247     LOGBRUSH logbrush;
248     
249     TRACE("%04x\n", hbitmap );
250
251     logbrush.lbStyle = BS_DIBPATTERN;
252     logbrush.lbColor = coloruse;
253
254     logbrush.lbHatch = (LONG)hbitmap;
255
256     return CreateBrushIndirect( &logbrush );
257 }
258
259
260 /***********************************************************************
261  *           CreateDIBPatternBrushPt    (GDI32.@)
262  *
263  *      Create a logical brush which has the pattern specified by the DIB
264  *
265  * RETURNS
266  *
267  *      Handle to a logical brush on success, NULL on failure.
268  *
269  * BUGS
270  *      
271  */
272 HBRUSH WINAPI CreateDIBPatternBrushPt(
273                 const void* data, /* [in] Pointer to a BITMAPINFO structure followed by more data */ 
274                 UINT coloruse     /* [in] Specifies color format, if provided */
275 )
276 {
277     BITMAPINFO *info=(BITMAPINFO*)data;
278     LOGBRUSH logbrush;
279     
280     TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth,
281           info->bmiHeader.biHeight,  info->bmiHeader.biBitCount);
282
283     logbrush.lbStyle = BS_DIBPATTERNPT;
284     logbrush.lbColor = coloruse;
285     logbrush.lbHatch = (LONG) data;
286
287     return CreateBrushIndirect( &logbrush );
288 }
289
290
291 /***********************************************************************
292  *           CreateSolidBrush    (GDI.66)
293  */
294 HBRUSH16 WINAPI CreateSolidBrush16( COLORREF color )
295 {
296     return CreateSolidBrush( color );
297 }
298
299
300 /***********************************************************************
301  *           CreateSolidBrush    (GDI32.@)
302  */
303 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
304 {
305     LOGBRUSH logbrush;
306
307     TRACE("%06lx\n", color );
308
309     logbrush.lbStyle = BS_SOLID;
310     logbrush.lbColor = color;
311     logbrush.lbHatch = 0;
312
313     return CreateBrushIndirect( &logbrush );
314 }
315
316
317 /***********************************************************************
318  *           SetBrushOrg    (GDI.148)
319  */
320 DWORD WINAPI SetBrushOrg16( HDC16 hdc, INT16 x, INT16 y )
321 {
322     DWORD retval;
323     DC *dc = DC_GetDCPtr( hdc );
324     if (!dc) return FALSE;
325     retval = dc->brushOrgX | (dc->brushOrgY << 16);
326     dc->brushOrgX = x;
327     dc->brushOrgY = y;
328     GDI_ReleaseObj( hdc );
329     return retval;
330 }
331
332
333 /***********************************************************************
334  *           SetBrushOrgEx    (GDI32.@)
335  */
336 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
337 {
338     DC *dc = DC_GetDCPtr( hdc );
339
340     if (!dc) return FALSE;
341     if (oldorg)
342     {
343         oldorg->x = dc->brushOrgX;
344         oldorg->y = dc->brushOrgY;
345     }
346     dc->brushOrgX = x;
347     dc->brushOrgY = y;
348     GDI_ReleaseObj( hdc );
349     return TRUE;
350 }
351
352 /***********************************************************************
353  *           FixBrushOrgEx    (GDI32.@)
354  * SDK says discontinued, but in Win95 GDI32 this is the same as SetBrushOrgEx
355  */
356 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
357 {
358     return SetBrushOrgEx(hdc,x,y,oldorg);
359 }
360
361
362 /***********************************************************************
363  *           BRUSH_DeleteObject
364  */
365 BOOL BRUSH_DeleteObject( HBRUSH16 hbrush, BRUSHOBJ * brush )
366 {
367     switch(brush->logbrush.lbStyle)
368     {
369       case BS_PATTERN:
370           DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
371           break;
372       case BS_DIBPATTERN:
373           GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
374           break;
375     }
376     return GDI_FreeObject( hbrush, brush );
377 }
378
379
380 /***********************************************************************
381  *           BRUSH_GetObject16
382  */
383 INT16 BRUSH_GetObject16( BRUSHOBJ * brush, INT16 count, LPSTR buffer )
384 {
385     LOGBRUSH16 logbrush;
386
387     logbrush.lbStyle = brush->logbrush.lbStyle;
388     logbrush.lbColor = brush->logbrush.lbColor;
389     logbrush.lbHatch = brush->logbrush.lbHatch;
390     if (count > sizeof(logbrush)) count = sizeof(logbrush);
391     memcpy( buffer, &logbrush, count );
392     return count;
393 }
394
395
396 /***********************************************************************
397  *           BRUSH_GetObject
398  */
399 INT BRUSH_GetObject( BRUSHOBJ * brush, INT count, LPSTR buffer )
400 {
401     if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
402     memcpy( buffer, &brush->logbrush, count );
403     return count;
404 }
405
406
407 /***********************************************************************
408  *           SetSolidBrush   (GDI.604)
409  *
410  *  If hBrush is a solid brush, change its color to newColor.
411  *
412  *  RETURNS
413  *           TRUE on success, FALSE on failure.
414  *
415  *  FIXME: untested, not sure if correct.
416  */
417 BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
418 {
419     BRUSHOBJ * brushPtr;
420     BOOL16 res = FALSE;
421
422     TRACE("(hBrush %04x, newColor %08lx)\n", hBrush, (DWORD)newColor);
423     if (!(brushPtr = (BRUSHOBJ *) GDI_GetObjPtr( hBrush, BRUSH_MAGIC )))
424         return FALSE;
425
426     if (brushPtr->logbrush.lbStyle == BS_SOLID)
427     {
428         brushPtr->logbrush.lbColor = newColor;
429         res = TRUE;
430     }
431
432      GDI_ReleaseObj( hBrush );
433      return res;
434 }
435