gdi32: Correct the font family values returned in the text metrics.
[wine] / dlls / gdi32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "wine/wingdi16.h"
30 #include "wownt32.h"
31 #include "gdi_private.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
35
36 /* GDI logical brush object */
37 typedef struct
38 {
39     GDIOBJHDR header;
40     LOGBRUSH  logbrush;
41 } BRUSHOBJ;
42
43 #define NB_HATCH_STYLES  6
44
45 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc );
46 static INT BRUSH_GetObject( HGDIOBJ handle, INT count, LPVOID buffer );
47 static BOOL BRUSH_DeleteObject( HGDIOBJ handle );
48
49 static const struct gdi_obj_funcs brush_funcs =
50 {
51     BRUSH_SelectObject,  /* pSelectObject */
52     BRUSH_GetObject,     /* pGetObjectA */
53     BRUSH_GetObject,     /* pGetObjectW */
54     NULL,                /* pUnrealizeObject */
55     BRUSH_DeleteObject   /* pDeleteObject */
56 };
57
58 static HGLOBAL16 dib_copy(const BITMAPINFO *info, UINT coloruse)
59 {
60     BITMAPINFO  *newInfo;
61     HGLOBAL16   hmem;
62     INT         size;
63
64     if (info->bmiHeader.biCompression != BI_RGB && info->bmiHeader.biCompression != BI_BITFIELDS)
65         size = info->bmiHeader.biSizeImage;
66     else
67         size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
68                                     info->bmiHeader.biHeight,
69                                     info->bmiHeader.biBitCount);
70     size += bitmap_info_size( info, coloruse );
71
72     if (!(hmem = GlobalAlloc16( GMEM_MOVEABLE, size )))
73     {
74         return 0;
75     }
76     newInfo = GlobalLock16( hmem );
77     memcpy( newInfo, info, size );
78     GlobalUnlock16( hmem );
79     return hmem;
80 }
81
82
83 /***********************************************************************
84  *           CreateBrushIndirect    (GDI32.@)
85  *
86  * Create a logical brush with a given style, color or pattern.
87  *
88  * PARAMS
89  *  brush [I] Pointer to a LOGBRUSH structure describing the desired brush.
90  *
91  * RETURNS
92  *  A handle to the created brush, or a NULL handle if the brush cannot be 
93  *  created.
94  *
95  * NOTES
96  * - The brush returned should be freed by the caller using DeleteObject()
97  *   when it is no longer required.
98  * - Windows 95 and earlier cannot create brushes from bitmaps or DIBs larger
99  *   than 8x8 pixels. If a larger bitmap is given, only a portion of the bitmap
100  *   is used.
101  */
102 HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
103 {
104     BRUSHOBJ * ptr;
105     HBRUSH hbrush;
106
107     if (!(ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(*ptr) ))) return 0;
108
109     ptr->logbrush.lbStyle = brush->lbStyle;
110     ptr->logbrush.lbColor = brush->lbColor;
111     ptr->logbrush.lbHatch = brush->lbHatch;
112
113     switch (ptr->logbrush.lbStyle)
114     {
115     case BS_PATTERN8X8:
116         ptr->logbrush.lbStyle = BS_PATTERN;
117         /* fall through */
118     case BS_PATTERN:
119         ptr->logbrush.lbHatch = (ULONG_PTR)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch );
120         if (!ptr->logbrush.lbHatch) goto error;
121         break;
122
123     case BS_DIBPATTERNPT:
124         ptr->logbrush.lbStyle = BS_DIBPATTERN;
125         ptr->logbrush.lbHatch = (ULONG_PTR)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch,
126                                                      ptr->logbrush.lbColor);
127         if (!ptr->logbrush.lbHatch) goto error;
128         break;
129
130     case BS_DIBPATTERN8X8:
131     case BS_DIBPATTERN:
132        {
133             BITMAPINFO* bmi;
134             HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;
135
136             ptr->logbrush.lbStyle = BS_DIBPATTERN;
137             if (!(bmi = GlobalLock( h ))) goto error;
138             ptr->logbrush.lbHatch = dib_copy( bmi, ptr->logbrush.lbColor);
139             GlobalUnlock( h );
140             if (!ptr->logbrush.lbHatch) goto error;
141             break;
142        }
143
144     default:
145         if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error;
146         break;
147     }
148
149     if ((hbrush = alloc_gdi_handle( &ptr->header, OBJ_BRUSH, &brush_funcs )))
150     {
151         TRACE("%p\n", hbrush);
152         return hbrush;
153     }
154
155  error:
156     if (ptr->logbrush.lbHatch)
157     {
158         if (ptr->logbrush.lbStyle == BS_PATTERN)
159             DeleteObject( (HGDIOBJ)ptr->logbrush.lbHatch );
160         else if (ptr->logbrush.lbStyle == BS_DIBPATTERN)
161             GlobalFree16( (HGLOBAL16)ptr->logbrush.lbHatch );
162     }
163     HeapFree( GetProcessHeap(), 0, ptr );
164     return 0;
165 }
166
167
168 /***********************************************************************
169  *           CreateHatchBrush    (GDI32.@)
170  *
171  * Create a logical brush with a hatched pattern.
172  *
173  * PARAMS
174  *  style [I] Direction of lines for the hatch pattern (HS_* values from "wingdi.h")
175  *  color [I] Colour of the hatched pattern
176  *
177  * RETURNS
178  *  A handle to the created brush, or a NULL handle if the brush cannot
179  *  be created.
180  *
181  * NOTES
182  * - This function uses CreateBrushIndirect() to create the brush.
183  * - The brush returned should be freed by the caller using DeleteObject()
184  *   when it is no longer required.
185  */
186 HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
187 {
188     LOGBRUSH logbrush;
189
190     TRACE("%d %06x\n", style, color );
191
192     logbrush.lbStyle = BS_HATCHED;
193     logbrush.lbColor = color;
194     logbrush.lbHatch = style;
195
196     return CreateBrushIndirect( &logbrush );
197 }
198
199
200 /***********************************************************************
201  *           CreatePatternBrush    (GDI32.@)
202  *
203  * Create a logical brush with a pattern from a bitmap.
204  *
205  * PARAMS
206  *  hbitmap  [I] Bitmap containing pattern for the brush
207  *
208  * RETURNS
209  *  A handle to the created brush, or a NULL handle if the brush cannot 
210  *  be created.
211  *
212  * NOTES
213  * - This function uses CreateBrushIndirect() to create the brush.
214  * - The brush returned should be freed by the caller using DeleteObject()
215  *   when it is no longer required.
216  */
217 HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
218 {
219     LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
220     TRACE("%p\n", hbitmap );
221
222     logbrush.lbHatch = (ULONG_PTR)hbitmap;
223     return CreateBrushIndirect( &logbrush );
224 }
225
226
227 /***********************************************************************
228  *           CreateDIBPatternBrush    (GDI32.@)
229  *
230  * Create a logical brush with a pattern from a DIB.
231  *
232  * PARAMS
233  *  hbitmap  [I] Global object containing BITMAPINFO structure for the pattern
234  *  coloruse [I] Specifies color format, if provided
235  *
236  * RETURNS
237  *  A handle to the created brush, or a NULL handle if the brush cannot 
238  *  be created.
239  *
240  * NOTES
241  * - This function uses CreateBrushIndirect() to create the brush.
242  * - The brush returned should be freed by the caller using DeleteObject()
243  *   when it is no longer required.
244  * - This function is for compatibility only. CreateDIBPatternBrushPt() should 
245  *   be used instead.
246  */
247 HBRUSH WINAPI CreateDIBPatternBrush( HGLOBAL hbitmap, UINT coloruse )
248 {
249     LOGBRUSH logbrush;
250
251     TRACE("%p\n", hbitmap );
252
253     logbrush.lbStyle = BS_DIBPATTERN;
254     logbrush.lbColor = coloruse;
255
256     logbrush.lbHatch = (ULONG_PTR)hbitmap;
257
258     return CreateBrushIndirect( &logbrush );
259 }
260
261
262 /***********************************************************************
263  *           CreateDIBPatternBrushPt    (GDI32.@)
264  *
265  * Create a logical brush with a pattern from a DIB.
266  *
267  * PARAMS
268  *  data     [I] Pointer to a BITMAPINFO structure and image data  for the pattern
269  *  coloruse [I] Specifies color format, if provided
270  *
271  * RETURNS
272  *  A handle to the created brush, or a NULL handle if the brush cannot
273  *  be created.
274  *
275  * NOTES
276  * - This function uses CreateBrushIndirect() to create the brush.
277  * - The brush returned should be freed by the caller using DeleteObject()
278  *   when it is no longer required.
279  */
280 HBRUSH WINAPI CreateDIBPatternBrushPt( const void* data, UINT coloruse )
281 {
282     const BITMAPINFO *info=data;
283     LOGBRUSH logbrush;
284
285     if (!data)
286         return NULL;
287
288     TRACE("%p %dx%d %dbpp\n", info, info->bmiHeader.biWidth,
289           info->bmiHeader.biHeight,  info->bmiHeader.biBitCount);
290
291     logbrush.lbStyle = BS_DIBPATTERNPT;
292     logbrush.lbColor = coloruse;
293     logbrush.lbHatch = (ULONG_PTR)data;
294
295     return CreateBrushIndirect( &logbrush );
296 }
297
298
299 /***********************************************************************
300  *           CreateSolidBrush    (GDI32.@)
301  *
302  * Create a logical brush consisting of a single colour.
303  *
304  * PARAMS
305  *  color [I] Colour to make the solid brush
306  *
307  * RETURNS
308  *  A handle to the newly created brush, or a NULL handle if the brush cannot
309  *  be created.
310  *
311  * NOTES
312  * - This function uses CreateBrushIndirect() to create the brush.
313  * - The brush returned should be freed by the caller using DeleteObject()
314  *   when it is no longer required.
315  */
316 HBRUSH WINAPI CreateSolidBrush( COLORREF color )
317 {
318     LOGBRUSH logbrush;
319
320     TRACE("%06x\n", color );
321
322     logbrush.lbStyle = BS_SOLID;
323     logbrush.lbColor = color;
324     logbrush.lbHatch = 0;
325
326     return CreateBrushIndirect( &logbrush );
327 }
328
329
330 /***********************************************************************
331  *           SetBrushOrgEx    (GDI32.@)
332  *
333  * Set the brush origin for a device context.
334  *
335  * PARAMS
336  *  hdc    [I] Device context to set the brush origin for 
337  *  x      [I] New x origin
338  *  y      [I] Ney y origin
339  *  oldorg [O] If non NULL, destination for previously set brush origin.
340  *
341  * RETURNS
342  *  Success: TRUE. The origin is set to (x,y), and oldorg is updated if given.
343  */
344 BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
345 {
346     DC *dc = get_dc_ptr( hdc );
347
348     if (!dc) return FALSE;
349     if (oldorg)
350     {
351         oldorg->x = dc->brushOrgX;
352         oldorg->y = dc->brushOrgY;
353     }
354     dc->brushOrgX = x;
355     dc->brushOrgY = y;
356     release_dc_ptr( dc );
357     return TRUE;
358 }
359
360 /***********************************************************************
361  *           FixBrushOrgEx    (GDI32.@)
362  *
363  * See SetBrushOrgEx.
364  *
365  * NOTES
366  *  This function is no longer documented by MSDN, but in Win95 GDI32 it
367  *  is the same as SetBrushOrgEx().
368  */
369 BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
370 {
371     return SetBrushOrgEx(hdc,x,y,oldorg);
372 }
373
374
375 /***********************************************************************
376  *           BRUSH_SelectObject
377  */
378 static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc )
379 {
380     BRUSHOBJ *brush;
381     HGDIOBJ ret = 0;
382     DC *dc = get_dc_ptr( hdc );
383
384     if (!dc)
385     {
386         SetLastError( ERROR_INVALID_HANDLE );
387         return 0;
388     }
389
390     if ((brush = GDI_GetObjPtr( handle, OBJ_BRUSH )))
391     {
392         if (brush->logbrush.lbStyle == BS_PATTERN)
393             BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc );
394
395         GDI_inc_ref_count( handle );
396         GDI_ReleaseObj( handle );
397
398         if (dc->funcs->pSelectBrush && !dc->funcs->pSelectBrush( dc->physDev, handle ))
399         {
400             GDI_dec_ref_count( handle );
401         }
402         else
403         {
404             ret = dc->hBrush;
405             dc->hBrush = handle;
406             GDI_dec_ref_count( ret );
407         }
408     }
409     release_dc_ptr( dc );
410     return ret;
411 }
412
413
414 /***********************************************************************
415  *           BRUSH_DeleteObject
416  */
417 static BOOL BRUSH_DeleteObject( HGDIOBJ handle )
418 {
419     BRUSHOBJ *brush = free_gdi_handle( handle );
420
421     if (!brush) return FALSE;
422     switch(brush->logbrush.lbStyle)
423     {
424       case BS_PATTERN:
425           DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
426           break;
427       case BS_DIBPATTERN:
428           GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
429           break;
430     }
431     return HeapFree( GetProcessHeap(), 0, brush );
432 }
433
434
435 /***********************************************************************
436  *           BRUSH_GetObject
437  */
438 static INT BRUSH_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
439 {
440     BRUSHOBJ *brush = GDI_GetObjPtr( handle, OBJ_BRUSH );
441
442     if (!brush) return 0;
443     if (buffer)
444     {
445         if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
446         memcpy( buffer, &brush->logbrush, count );
447     }
448     else count = sizeof(brush->logbrush);
449     GDI_ReleaseObj( handle );
450     return count;
451 }
452
453
454 /***********************************************************************
455  *           SetSolidBrush   (GDI.604)
456  *
457  * Change the color of a solid brush.
458  *
459  * PARAMS
460  *  hBrush   [I] Brush to change the color of
461  *  newColor [I] New color for hBrush
462  *
463  * RETURNS
464  *  Success: TRUE. The color of hBrush is set to newColor.
465  *  Failure: FALSE.
466  *
467  * FIXME
468  *  This function is undocumented and untested. The implementation may
469  *  not be correct.
470  */
471 BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
472 {
473     BRUSHOBJ * brushPtr;
474     BOOL16 res = FALSE;
475
476     TRACE("(hBrush %04x, newColor %08x)\n", hBrush, newColor);
477     if (!(brushPtr = GDI_GetObjPtr( HBRUSH_32(hBrush), OBJ_BRUSH )))
478         return FALSE;
479
480     if (brushPtr->logbrush.lbStyle == BS_SOLID)
481     {
482         brushPtr->logbrush.lbColor = newColor;
483         res = TRUE;
484     }
485
486      GDI_ReleaseObj( HBRUSH_32(hBrush) );
487      return res;
488 }