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