brush.c 10.3 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 * GDI brush objects
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
4
 * Copyright 1993, 1994  Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Alexandre Julliard's avatar
Alexandre Julliard committed
19
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
20

21 22
#include "config.h"

23
#include <string.h>
24

25
#include "winbase.h"
26 27
#include "wingdi.h"
#include "wine/wingdi16.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
28
#include "bitmap.h"
29
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
30

31
WINE_DEFAULT_DEBUG_CHANNEL(gdi);
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
/* GDI logical brush object */
typedef struct
{
    GDIOBJHDR header;
    LOGBRUSH  logbrush;
} BRUSHOBJ;

#define NB_HATCH_STYLES  6

static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj );

static const struct gdi_obj_funcs brush_funcs =
{
    BRUSH_SelectObject,  /* pSelectObject */
    BRUSH_GetObject16,   /* pGetObject16 */
    BRUSH_GetObject,     /* pGetObjectA */
    BRUSH_GetObject,     /* pGetObjectW */
    NULL,                /* pUnrealizeObject */
    BRUSH_DeleteObject   /* pDeleteObject */
};

Ulrich Czekalla's avatar
Ulrich Czekalla committed
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
static HGLOBAL16 dib_copy(BITMAPINFO *info, UINT coloruse)
{
    BITMAPINFO  *newInfo;
    HGLOBAL16   hmem;
    INT         size;

    if (info->bmiHeader.biCompression)
        size = info->bmiHeader.biSizeImage;
    else
        size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
                                    info->bmiHeader.biHeight,
                                    info->bmiHeader.biBitCount);
    size += DIB_BitmapInfoSize( info, coloruse );

    if (!(hmem = GlobalAlloc16( GMEM_MOVEABLE, size )))
    {
        return 0;
    }
    newInfo = (BITMAPINFO *) GlobalLock16( hmem );
    memcpy( newInfo, info, size );
    GlobalUnlock16( hmem );
    return hmem;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
82
/***********************************************************************
83
 *           CreateBrushIndirect    (GDI32.@)
Ulrich Czekalla's avatar
Ulrich Czekalla committed
84 85 86 87 88 89
 *
 * BUGS
 *      As for Windows 95 and Windows 98:
 *      Creating brushes from bitmaps or DIBs larger than 8x8 pixels
 *      is not supported. If a larger bitmap is given, only a portion
 *      of the bitmap is used.
Alexandre Julliard's avatar
Alexandre Julliard committed
90
 */
91
HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
Alexandre Julliard's avatar
Alexandre Julliard committed
92
{
93
    BRUSHOBJ * ptr;
94
    HBRUSH hbrush;
95 96 97 98 99 100 101

    if (!(ptr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC, &hbrush, &brush_funcs ))) return 0;
    ptr->logbrush.lbStyle = brush->lbStyle;
    ptr->logbrush.lbColor = brush->lbColor;
    ptr->logbrush.lbHatch = brush->lbHatch;

    switch (ptr->logbrush.lbStyle)
Ulrich Czekalla's avatar
Ulrich Czekalla committed
102
    {
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    case BS_PATTERN8X8:
        ptr->logbrush.lbStyle = BS_PATTERN;
        /* fall through */
    case BS_PATTERN:
        ptr->logbrush.lbHatch = (LONG)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch );
        if (!ptr->logbrush.lbHatch) goto error;
        break;

    case BS_DIBPATTERNPT:
        ptr->logbrush.lbStyle = BS_DIBPATTERN;
        ptr->logbrush.lbHatch = (LONG)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch,
                                                ptr->logbrush.lbColor);
        if (!ptr->logbrush.lbHatch) goto error;
        break;

    case BS_DIBPATTERN8X8:
    case BS_DIBPATTERN:
       {
            BITMAPINFO* bmi;
            HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch;

            ptr->logbrush.lbStyle = BS_DIBPATTERN;
            if (!(bmi = (BITMAPINFO *)GlobalLock( h ))) goto error;
            ptr->logbrush.lbHatch = dib_copy( bmi, ptr->logbrush.lbColor);
            GlobalUnlock( h );
            if (!ptr->logbrush.lbHatch) goto error;
            break;
       }

    default:
        if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error;
        break;
Ulrich Czekalla's avatar
Ulrich Czekalla committed
135
    }
136 137

    GDI_ReleaseObj( hbrush );
138
    TRACE("%08x\n", hbrush);
Alexandre Julliard's avatar
Alexandre Julliard committed
139
    return hbrush;
140 141 142 143

 error:
    GDI_FreeObject( hbrush, ptr );
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
144 145 146 147
}


/***********************************************************************
148
 *           CreateHatchBrush    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
149
 */
150
HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
Alexandre Julliard's avatar
Alexandre Julliard committed
151
{
152 153
    LOGBRUSH logbrush;

154
    TRACE("%d %06lx\n", style, color );
155 156 157 158 159

    logbrush.lbStyle = BS_HATCHED;
    logbrush.lbColor = color;
    logbrush.lbHatch = style;

160
    return CreateBrushIndirect( &logbrush );
Alexandre Julliard's avatar
Alexandre Julliard committed
161 162 163
}


Alexandre Julliard's avatar
Alexandre Julliard committed
164
/***********************************************************************
165
 *           CreatePatternBrush    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
166
 */
167
HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
Alexandre Julliard's avatar
Alexandre Julliard committed
168
{
169
    LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
170
    TRACE("%04x\n", hbitmap );
Alexandre Julliard's avatar
Alexandre Julliard committed
171

172
    logbrush.lbHatch = (ULONG_PTR)hbitmap;
173
    return CreateBrushIndirect( &logbrush );
Alexandre Julliard's avatar
Alexandre Julliard committed
174 175 176
}


Alexandre Julliard's avatar
Alexandre Julliard committed
177
/***********************************************************************
178
 *           CreateDIBPatternBrush    (GDI32.@)
179 180 181
 *
 *	Create a logical brush which has the pattern specified by the DIB
 *
182
 *	Function call is for compatibility only.  CreateDIBPatternBrushPt should be used.
183 184 185 186 187 188
 *
 * RETURNS
 *
 *	Handle to a logical brush on success, NULL on failure.
 *
 * BUGS
189
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
190
 */
191
HBRUSH WINAPI CreateDIBPatternBrush(
192 193
		HGLOBAL hbitmap, /* [in] Global object containg BITMAPINFO structure */
		UINT coloruse 	 /* [in] Specifies color format, if provided */
194
)
Alexandre Julliard's avatar
Alexandre Julliard committed
195
{
196
    LOGBRUSH logbrush;
197

198
    TRACE("%04x\n", hbitmap );
Alexandre Julliard's avatar
Alexandre Julliard committed
199

200 201
    logbrush.lbStyle = BS_DIBPATTERN;
    logbrush.lbColor = coloruse;
Alexandre Julliard's avatar
Alexandre Julliard committed
202

Ulrich Czekalla's avatar
Ulrich Czekalla committed
203
    logbrush.lbHatch = (LONG)hbitmap;
Alexandre Julliard's avatar
Alexandre Julliard committed
204

205
    return CreateBrushIndirect( &logbrush );
206 207 208 209
}


/***********************************************************************
210
 *           CreateDIBPatternBrushPt    (GDI32.@)
211 212 213 214 215 216 217 218
 *
 *	Create a logical brush which has the pattern specified by the DIB
 *
 * RETURNS
 *
 *	Handle to a logical brush on success, NULL on failure.
 *
 * BUGS
219
 *
220
 */
221
HBRUSH WINAPI CreateDIBPatternBrushPt(
222
		const void* data, /* [in] Pointer to a BITMAPINFO structure followed by more data */
223
		UINT coloruse 	  /* [in] Specifies color format, if provided */
224 225
)
{
226
    BITMAPINFO *info=(BITMAPINFO*)data;
Patrik Stridvall's avatar
Patrik Stridvall committed
227
    LOGBRUSH logbrush;
228

229
    TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth,
230
	  info->bmiHeader.biHeight,  info->bmiHeader.biBitCount);
231

Ulrich Czekalla's avatar
Ulrich Czekalla committed
232
    logbrush.lbStyle = BS_DIBPATTERNPT;
Patrik Stridvall's avatar
Patrik Stridvall committed
233
    logbrush.lbColor = coloruse;
Ulrich Czekalla's avatar
Ulrich Czekalla committed
234
    logbrush.lbHatch = (LONG) data;
235

236
    return CreateBrushIndirect( &logbrush );
Alexandre Julliard's avatar
Alexandre Julliard committed
237 238 239
}


Alexandre Julliard's avatar
Alexandre Julliard committed
240
/***********************************************************************
241
 *           CreateSolidBrush    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
242
 */
243
HBRUSH WINAPI CreateSolidBrush( COLORREF color )
Alexandre Julliard's avatar
Alexandre Julliard committed
244
{
245 246
    LOGBRUSH logbrush;

247
    TRACE("%06lx\n", color );
248 249 250 251 252

    logbrush.lbStyle = BS_SOLID;
    logbrush.lbColor = color;
    logbrush.lbHatch = 0;

253
    return CreateBrushIndirect( &logbrush );
Alexandre Julliard's avatar
Alexandre Julliard committed
254 255 256
}


Alexandre Julliard's avatar
Alexandre Julliard committed
257
/***********************************************************************
258
 *           SetBrushOrgEx    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
259
 */
260
BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
Alexandre Julliard's avatar
Alexandre Julliard committed
261
{
262
    DC *dc = DC_GetDCPtr( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
263 264 265 266

    if (!dc) return FALSE;
    if (oldorg)
    {
267 268
        oldorg->x = dc->brushOrgX;
        oldorg->y = dc->brushOrgY;
Alexandre Julliard's avatar
Alexandre Julliard committed
269
    }
270 271
    dc->brushOrgX = x;
    dc->brushOrgY = y;
272
    GDI_ReleaseObj( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
273 274 275
    return TRUE;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
276
/***********************************************************************
277
 *           FixBrushOrgEx    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
278 279
 * SDK says discontinued, but in Win95 GDI32 this is the same as SetBrushOrgEx
 */
280
BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
Alexandre Julliard's avatar
Alexandre Julliard committed
281 282 283 284
{
    return SetBrushOrgEx(hdc,x,y,oldorg);
}

Alexandre Julliard's avatar
Alexandre Julliard committed
285

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
/***********************************************************************
 *           BRUSH_SelectObject
 */
static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
{
    BRUSHOBJ *brush = obj;
    HGDIOBJ ret;
    DC *dc = DC_GetDCPtr( hdc );

    if (!dc) return 0;

    if (brush->logbrush.lbStyle == BS_PATTERN)
        BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc );

    ret = dc->hBrush;
    if (dc->funcs->pSelectBrush) handle = dc->funcs->pSelectBrush( dc->physDev, handle );
    if (handle) dc->hBrush = handle;
    else ret = 0;
    GDI_ReleaseObj( hdc );
    return ret;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
309 310 311
/***********************************************************************
 *           BRUSH_DeleteObject
 */
312
static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
313
{
314 315
    BRUSHOBJ *brush = obj;

Alexandre Julliard's avatar
Alexandre Julliard committed
316 317 318
    switch(brush->logbrush.lbStyle)
    {
      case BS_PATTERN:
319
	  DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
Alexandre Julliard's avatar
Alexandre Julliard committed
320 321
	  break;
      case BS_DIBPATTERN:
Alexandre Julliard's avatar
Alexandre Julliard committed
322
	  GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
Alexandre Julliard's avatar
Alexandre Julliard committed
323 324
	  break;
    }
325
    return GDI_FreeObject( handle, obj );
Alexandre Julliard's avatar
Alexandre Julliard committed
326 327 328 329
}


/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
330
 *           BRUSH_GetObject16
Alexandre Julliard's avatar
Alexandre Julliard committed
331
 */
332
static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
Alexandre Julliard's avatar
Alexandre Julliard committed
333
{
334
    BRUSHOBJ *brush = obj;
Alexandre Julliard's avatar
Alexandre Julliard committed
335 336 337 338 339 340 341 342 343 344 345 346
    LOGBRUSH16 logbrush;

    logbrush.lbStyle = brush->logbrush.lbStyle;
    logbrush.lbColor = brush->logbrush.lbColor;
    logbrush.lbHatch = brush->logbrush.lbHatch;
    if (count > sizeof(logbrush)) count = sizeof(logbrush);
    memcpy( buffer, &logbrush, count );
    return count;
}


/***********************************************************************
347
 *           BRUSH_GetObject
Alexandre Julliard's avatar
Alexandre Julliard committed
348
 */
349
static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
Alexandre Julliard's avatar
Alexandre Julliard committed
350
{
351 352
    BRUSHOBJ *brush = obj;

Alexandre Julliard's avatar
Alexandre Julliard committed
353
    if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
Alexandre Julliard's avatar
Alexandre Julliard committed
354 355 356
    memcpy( buffer, &brush->logbrush, count );
    return count;
}
357 358 359


/***********************************************************************
360
 *           SetSolidBrush   (GDI.604)
361
 *
362
 *  If hBrush is a solid brush, change its color to newColor.
363 364 365
 *
 *  RETURNS
 *           TRUE on success, FALSE on failure.
366 367
 *
 *  FIXME: untested, not sure if correct.
368 369 370
 */
BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
{
371 372 373 374 375 376 377 378 379 380 381 382
    BRUSHOBJ * brushPtr;
    BOOL16 res = FALSE;

    TRACE("(hBrush %04x, newColor %08lx)\n", hBrush, (DWORD)newColor);
    if (!(brushPtr = (BRUSHOBJ *) GDI_GetObjPtr( hBrush, BRUSH_MAGIC )))
	return FALSE;

    if (brushPtr->logbrush.lbStyle == BS_SOLID)
    {
        brushPtr->logbrush.lbColor = newColor;
	res = TRUE;
    }
383

384 385
     GDI_ReleaseObj( hBrush );
     return res;
386
}