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