Fix strncpyWtoA to actually act as advertised (and not overflow the
[wine/multimedia.git] / objects / brush.c
blob3b54fbbac7ce646c0667ec0deaeb51220dc0dbfe
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 "bitmap.h"
31 #include "wownt32.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
36 /* GDI logical brush object */
37 typedef struct
39 GDIOBJHDR header;
40 LOGBRUSH logbrush;
41 } BRUSHOBJ;
43 #define NB_HATCH_STYLES 6
45 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, 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 );
50 static const struct gdi_obj_funcs brush_funcs =
52 BRUSH_SelectObject, /* pSelectObject */
53 BRUSH_GetObject16, /* pGetObject16 */
54 BRUSH_GetObject, /* pGetObjectA */
55 BRUSH_GetObject, /* pGetObjectW */
56 NULL, /* pUnrealizeObject */
57 BRUSH_DeleteObject /* pDeleteObject */
60 static HGLOBAL16 dib_copy(BITMAPINFO *info, UINT coloruse)
62 BITMAPINFO *newInfo;
63 HGLOBAL16 hmem;
64 INT size;
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 );
74 if (!(hmem = GlobalAlloc16( GMEM_MOVEABLE, size )))
76 return 0;
78 newInfo = (BITMAPINFO *) GlobalLock16( hmem );
79 memcpy( newInfo, info, size );
80 GlobalUnlock16( hmem );
81 return hmem;
85 /***********************************************************************
86 * CreateBrushIndirect (GDI32.@)
88 * BUGS
89 * As for Windows 95 and Windows 98:
90 * Creating brushes from bitmaps or DIBs larger than 8x8 pixels
91 * is not supported. If a larger bitmap is given, only a portion
92 * of the bitmap is used.
94 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
96 BRUSHOBJ * ptr;
97 HBRUSH hbrush;
99 if (!(ptr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC,
100 (HGDIOBJ *)&hbrush, &brush_funcs ))) return 0;
101 ptr->logbrush.lbStyle = brush->lbStyle;
102 ptr->logbrush.lbColor = brush->lbColor;
103 ptr->logbrush.lbHatch = brush->lbHatch;
105 switch (ptr->logbrush.lbStyle)
107 case BS_PATTERN8X8:
108 ptr->logbrush.lbStyle = BS_PATTERN;
109 /* fall through */
110 case BS_PATTERN:
111 ptr->logbrush.lbHatch = (LONG)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch );
112 if (!ptr->logbrush.lbHatch) goto error;
113 break;
115 case BS_DIBPATTERNPT:
116 ptr->logbrush.lbStyle = BS_DIBPATTERN;
117 ptr->logbrush.lbHatch = (LONG)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch,
118 ptr->logbrush.lbColor);
119 if (!ptr->logbrush.lbHatch) goto error;
120 break;
122 case BS_DIBPATTERN8X8:
123 case BS_DIBPATTERN:
125 BITMAPINFO* bmi;
126 HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;
128 ptr->logbrush.lbStyle = BS_DIBPATTERN;
129 if (!(bmi = (BITMAPINFO *)GlobalLock( h ))) goto error;
130 ptr->logbrush.lbHatch = dib_copy( bmi, ptr->logbrush.lbColor);
131 GlobalUnlock( h );
132 if (!ptr->logbrush.lbHatch) goto error;
133 break;
136 default:
137 if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error;
138 break;
141 GDI_ReleaseObj( hbrush );
142 TRACE("%p\n", hbrush);
143 return hbrush;
145 error:
146 GDI_FreeObject( hbrush, ptr );
147 return 0;
151 /***********************************************************************
152 * CreateHatchBrush (GDI32.@)
154 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
156 LOGBRUSH logbrush;
158 TRACE("%d %06lx\n", style, color );
160 logbrush.lbStyle = BS_HATCHED;
161 logbrush.lbColor = color;
162 logbrush.lbHatch = style;
164 return CreateBrushIndirect( &logbrush );
168 /***********************************************************************
169 * CreatePatternBrush (GDI32.@)
171 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
173 LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
174 TRACE("%p\n", hbitmap );
176 logbrush.lbHatch = (ULONG_PTR)hbitmap;
177 return CreateBrushIndirect( &logbrush );
181 /***********************************************************************
182 * CreateDIBPatternBrush (GDI32.@)
184 * Create a logical brush which has the pattern specified by the DIB
186 * Function call is for compatibility only. CreateDIBPatternBrushPt should be used.
188 * RETURNS
190 * Handle to a logical brush on success, NULL on failure.
192 * BUGS
195 HBRUSH WINAPI CreateDIBPatternBrush(
196 HGLOBAL hbitmap, /* [in] Global object containg BITMAPINFO structure */
197 UINT coloruse /* [in] Specifies color format, if provided */
200 LOGBRUSH logbrush;
202 TRACE("%p\n", hbitmap );
204 logbrush.lbStyle = BS_DIBPATTERN;
205 logbrush.lbColor = coloruse;
207 logbrush.lbHatch = (LONG)hbitmap;
209 return CreateBrushIndirect( &logbrush );
213 /***********************************************************************
214 * CreateDIBPatternBrushPt (GDI32.@)
216 * Create a logical brush which has the pattern specified by the DIB
218 * RETURNS
220 * Handle to a logical brush on success, NULL on failure.
222 * BUGS
225 HBRUSH WINAPI CreateDIBPatternBrushPt(
226 const void* data, /* [in] Pointer to a BITMAPINFO structure followed by more data */
227 UINT coloruse /* [in] Specifies color format, if provided */
230 BITMAPINFO *info=(BITMAPINFO*)data;
231 LOGBRUSH logbrush;
233 TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth,
234 info->bmiHeader.biHeight, info->bmiHeader.biBitCount);
236 logbrush.lbStyle = BS_DIBPATTERNPT;
237 logbrush.lbColor = coloruse;
238 logbrush.lbHatch = (LONG) data;
240 return CreateBrushIndirect( &logbrush );
244 /***********************************************************************
245 * CreateSolidBrush (GDI32.@)
247 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
249 LOGBRUSH logbrush;
251 TRACE("%06lx\n", color );
253 logbrush.lbStyle = BS_SOLID;
254 logbrush.lbColor = color;
255 logbrush.lbHatch = 0;
257 return CreateBrushIndirect( &logbrush );
261 /***********************************************************************
262 * SetBrushOrgEx (GDI32.@)
264 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
266 DC *dc = DC_GetDCPtr( hdc );
268 if (!dc) return FALSE;
269 if (oldorg)
271 oldorg->x = dc->brushOrgX;
272 oldorg->y = dc->brushOrgY;
274 dc->brushOrgX = x;
275 dc->brushOrgY = y;
276 GDI_ReleaseObj( hdc );
277 return TRUE;
280 /***********************************************************************
281 * FixBrushOrgEx (GDI32.@)
282 * SDK says discontinued, but in Win95 GDI32 this is the same as SetBrushOrgEx
284 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
286 return SetBrushOrgEx(hdc,x,y,oldorg);
290 /***********************************************************************
291 * BRUSH_SelectObject
293 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
295 BRUSHOBJ *brush = obj;
296 HGDIOBJ ret;
297 DC *dc = DC_GetDCPtr( hdc );
299 if (!dc) return 0;
301 if (brush->logbrush.lbStyle == BS_PATTERN)
302 BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc );
304 ret = dc->hBrush;
305 if (dc->funcs->pSelectBrush) handle = dc->funcs->pSelectBrush( dc->physDev, handle );
306 if (handle) dc->hBrush = handle;
307 else ret = 0;
308 GDI_ReleaseObj( hdc );
309 return ret;
313 /***********************************************************************
314 * BRUSH_DeleteObject
316 static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj )
318 BRUSHOBJ *brush = obj;
320 switch(brush->logbrush.lbStyle)
322 case BS_PATTERN:
323 DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
324 break;
325 case BS_DIBPATTERN:
326 GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
327 break;
329 return GDI_FreeObject( handle, obj );
333 /***********************************************************************
334 * BRUSH_GetObject16
336 static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
338 BRUSHOBJ *brush = obj;
339 LOGBRUSH16 logbrush;
341 logbrush.lbStyle = brush->logbrush.lbStyle;
342 logbrush.lbColor = brush->logbrush.lbColor;
343 logbrush.lbHatch = brush->logbrush.lbHatch;
344 if (count > sizeof(logbrush)) count = sizeof(logbrush);
345 memcpy( buffer, &logbrush, count );
346 return count;
350 /***********************************************************************
351 * BRUSH_GetObject
353 static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
355 BRUSHOBJ *brush = obj;
357 if( !buffer )
358 return sizeof(brush->logbrush);
360 if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
361 memcpy( buffer, &brush->logbrush, count );
362 return count;
366 /***********************************************************************
367 * SetSolidBrush (GDI.604)
369 * If hBrush is a solid brush, change its color to newColor.
371 * RETURNS
372 * TRUE on success, FALSE on failure.
374 * FIXME: untested, not sure if correct.
376 BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
378 BRUSHOBJ * brushPtr;
379 BOOL16 res = FALSE;
381 TRACE("(hBrush %04x, newColor %08lx)\n", hBrush, (DWORD)newColor);
382 if (!(brushPtr = (BRUSHOBJ *) GDI_GetObjPtr( HBRUSH_32(hBrush), BRUSH_MAGIC )))
383 return FALSE;
385 if (brushPtr->logbrush.lbStyle == BS_SOLID)
387 brushPtr->logbrush.lbColor = newColor;
388 res = TRUE;
391 GDI_ReleaseObj( HBRUSH_32(hBrush) );
392 return res;