Clean up devenum and properly implement DllCanUnloadNow ref counting.
[wine/multimedia.git] / dlls / gdi / brush.c
blob72bb929e3197c9aa4003b258665c6cc9bd4c16f7
1 /*
2 * GDI brush objects
4 * Copyright 1993, 1994 Alexandre Julliard
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.
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.
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
21 #include "config.h"
23 #include <stdarg.h>
24 #include <string.h>
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"
35 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
37 /* GDI logical brush object */
38 typedef struct
40 GDIOBJHDR header;
41 LOGBRUSH logbrush;
42 } BRUSHOBJ;
44 #define NB_HATCH_STYLES 6
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 );
51 static const struct gdi_obj_funcs brush_funcs =
53 BRUSH_SelectObject, /* pSelectObject */
54 BRUSH_GetObject16, /* pGetObject16 */
55 BRUSH_GetObject, /* pGetObjectA */
56 BRUSH_GetObject, /* pGetObjectW */
57 NULL, /* pUnrealizeObject */
58 BRUSH_DeleteObject /* pDeleteObject */
61 static HGLOBAL16 dib_copy(BITMAPINFO *info, UINT coloruse)
63 BITMAPINFO *newInfo;
64 HGLOBAL16 hmem;
65 INT size;
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 );
75 if (!(hmem = GlobalAlloc16( GMEM_MOVEABLE, size )))
77 return 0;
79 newInfo = (BITMAPINFO *) GlobalLock16( hmem );
80 memcpy( newInfo, info, size );
81 GlobalUnlock16( hmem );
82 return hmem;
86 /***********************************************************************
87 * CreateBrushIndirect (GDI32.@)
89 * Create a logical brush with a given style, color or pattern.
91 * PARAMS
92 * brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
94 * RETURNS
95 * A handle to the created brush, or a NULL handle if the brush cannot be
96 * created.
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.
105 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
107 BRUSHOBJ * ptr;
108 HBRUSH hbrush;
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;
116 switch (ptr->logbrush.lbStyle)
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;
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;
133 case BS_DIBPATTERN8X8:
134 case BS_DIBPATTERN:
136 BITMAPINFO* bmi;
137 HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;
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;
147 default:
148 if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error;
149 break;
152 GDI_ReleaseObj( hbrush );
153 TRACE("%p\n", hbrush);
154 return hbrush;
156 error:
157 GDI_FreeObject( hbrush, ptr );
158 return 0;
162 /***********************************************************************
163 * CreateHatchBrush (GDI32.@)
165 * Create a logical brush with a hatched pattern.
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
171 * RETURNS
172 * A handle to the created brush, or a NULL handle if the brush cannot
173 * be created.
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.
180 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
182 LOGBRUSH logbrush;
184 TRACE("%d %06lx\n", style, color );
186 logbrush.lbStyle = BS_HATCHED;
187 logbrush.lbColor = color;
188 logbrush.lbHatch = style;
190 return CreateBrushIndirect( &logbrush );
194 /***********************************************************************
195 * CreatePatternBrush (GDI32.@)
197 * Create a logical brush with a pattern from a bitmap.
199 * PARAMS
200 * hbitmap [I] Bitmap containing pattern for the brush
202 * RETURNS
203 * A handle to the created brush, or a NULL handle if the brush cannot
204 * be created.
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.
211 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
213 LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
214 TRACE("%p\n", hbitmap );
216 logbrush.lbHatch = (ULONG_PTR)hbitmap;
217 return CreateBrushIndirect( &logbrush );
221 /***********************************************************************
222 * CreateDIBPatternBrush (GDI32.@)
224 * Create a logical brush with a pattern from a DIB.
226 * PARAMS
227 * hbitmap [I] Global object containing BITMAPINFO structure for the pattern
228 * coloruse [I] Specifies color format, if provided
230 * RETURNS
231 * A handle to the created brush, or a NULL handle if the brush cannot
232 * be created.
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.
241 HBRUSH WINAPI CreateDIBPatternBrush( HGLOBAL hbitmap, UINT coloruse )
243 LOGBRUSH logbrush;
245 TRACE("%p\n", hbitmap );
247 logbrush.lbStyle = BS_DIBPATTERN;
248 logbrush.lbColor = coloruse;
250 logbrush.lbHatch = (LONG)hbitmap;
252 return CreateBrushIndirect( &logbrush );
256 /***********************************************************************
257 * CreateDIBPatternBrushPt (GDI32.@)
259 * Create a logical brush with a pattern from a DIB.
261 * PARAMS
262 * data [I] Pointer to a BITMAPINFO structure and image data for the pattern
263 * coloruse [I] Specifies color format, if provided
265 * RETURNS
266 * A handle to the created brush, or a NULL handle if the brush cannot
267 * be created.
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.
274 HBRUSH WINAPI CreateDIBPatternBrushPt( const void* data, UINT coloruse )
276 BITMAPINFO *info=(BITMAPINFO*)data;
277 LOGBRUSH logbrush;
279 if (!data)
280 return NULL;
282 TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth,
283 info->bmiHeader.biHeight, info->bmiHeader.biBitCount);
285 logbrush.lbStyle = BS_DIBPATTERNPT;
286 logbrush.lbColor = coloruse;
287 logbrush.lbHatch = (LONG) data;
289 return CreateBrushIndirect( &logbrush );
293 /***********************************************************************
294 * CreateSolidBrush (GDI32.@)
296 * Create a logical brush consisting of a single colour.
298 * PARAMS
299 * color [I] Colour to make the solid brush
301 * RETURNS
302 * A handle to the newly created brush, or a NULL handle if the brush cannot
303 * be created.
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.
310 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
312 LOGBRUSH logbrush;
314 TRACE("%06lx\n", color );
316 logbrush.lbStyle = BS_SOLID;
317 logbrush.lbColor = color;
318 logbrush.lbHatch = 0;
320 return CreateBrushIndirect( &logbrush );
324 /***********************************************************************
325 * SetBrushOrgEx (GDI32.@)
327 * Set the brush origin for a device context.
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.
335 * RETURNS
336 * Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
338 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
340 DC *dc = DC_GetDCPtr( hdc );
342 if (!dc) return FALSE;
343 if (oldorg)
345 oldorg->x = dc->brushOrgX;
346 oldorg->y = dc->brushOrgY;
348 dc->brushOrgX = x;
349 dc->brushOrgY = y;
350 GDI_ReleaseObj( hdc );
351 return TRUE;
354 /***********************************************************************
355 * FixBrushOrgEx (GDI32.@)
357 * See SetBrushOrgEx.
359 * NOTES
360 * This function is no longer documented by MSDN, but in Win95 GDI32 it
361 * is the same as SetBrushOrgEx().
363 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
365 return SetBrushOrgEx(hdc,x,y,oldorg);
369 /***********************************************************************
370 * BRUSH_SelectObject
372 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
374 BRUSHOBJ *brush = obj;
375 HGDIOBJ ret;
376 DC *dc = DC_GetDCPtr( hdc );
378 if (!dc) return 0;
380 if (brush->logbrush.lbStyle == BS_PATTERN)
381 BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc );
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;
392 /***********************************************************************
393 * BRUSH_DeleteObject
395 static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj )
397 BRUSHOBJ *brush = obj;
399 switch(brush->logbrush.lbStyle)
401 case BS_PATTERN:
402 DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
403 break;
404 case BS_DIBPATTERN:
405 GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
406 break;
408 return GDI_FreeObject( handle, obj );
412 /***********************************************************************
413 * BRUSH_GetObject16
415 static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
417 BRUSHOBJ *brush = obj;
418 LOGBRUSH16 logbrush;
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;
429 /***********************************************************************
430 * BRUSH_GetObject
432 static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
434 BRUSHOBJ *brush = obj;
436 if( !buffer )
437 return sizeof(brush->logbrush);
439 if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
440 memcpy( buffer, &brush->logbrush, count );
441 return count;
445 /***********************************************************************
446 * SetSolidBrush (GDI.604)
448 * Change the color of a solid brush.
450 * PARAMS
451 * hBrush [I] Brush to change the color of
452 * newColor [I] New color for hBrush
454 * RETURNS
455 * Success: TRUE. The color of hBrush is set to newColor.
456 * Failure: FALSE.
458 * FIXME
459 * This function is undocumented and untested. The implementation may
460 * not be correct.
462 BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
464 BRUSHOBJ * brushPtr;
465 BOOL16 res = FALSE;
467 TRACE("(hBrush %04x, newColor %08lx)\n", hBrush, (DWORD)newColor);
468 if (!(brushPtr = (BRUSHOBJ *) GDI_GetObjPtr( HBRUSH_32(hBrush), BRUSH_MAGIC )))
469 return FALSE;
471 if (brushPtr->logbrush.lbStyle == BS_SOLID)
473 brushPtr->logbrush.lbColor = newColor;
474 res = TRUE;
477 GDI_ReleaseObj( HBRUSH_32(hBrush) );
478 return res;