blob: 4fe7c82fae964ce20fc656ab9684a6a9d6751862 [file] [log] [blame]
/*
* GDI brush objects
*
* Copyright 1993, 1994 Alexandre Julliard
*
* 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
*/
#include "config.h"
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "wine/wingdi16.h"
#include "gdi.h"
#include "wownt32.h"
#include "gdi_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(gdi);
/* 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 */
};
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;
}
/***********************************************************************
* CreateBrushIndirect (GDI32.@)
*
* 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.
*/
HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush )
{
BRUSHOBJ * ptr;
HBRUSH hbrush;
if (!(ptr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC,
(HGDIOBJ *)&hbrush, &brush_funcs ))) return 0;
ptr->logbrush.lbStyle = brush->lbStyle;
ptr->logbrush.lbColor = brush->lbColor;
ptr->logbrush.lbHatch = brush->lbHatch;
switch (ptr->logbrush.lbStyle)
{
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;
}
GDI_ReleaseObj( hbrush );
TRACE("%p\n", hbrush);
return hbrush;
error:
GDI_FreeObject( hbrush, ptr );
return 0;
}
/***********************************************************************
* CreateHatchBrush (GDI32.@)
*/
HBRUSH WINAPI CreateHatchBrush( INT style, COLORREF color )
{
LOGBRUSH logbrush;
TRACE("%d %06lx\n", style, color );
logbrush.lbStyle = BS_HATCHED;
logbrush.lbColor = color;
logbrush.lbHatch = style;
return CreateBrushIndirect( &logbrush );
}
/***********************************************************************
* CreatePatternBrush (GDI32.@)
*/
HBRUSH WINAPI CreatePatternBrush( HBITMAP hbitmap )
{
LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
TRACE("%p\n", hbitmap );
logbrush.lbHatch = (ULONG_PTR)hbitmap;
return CreateBrushIndirect( &logbrush );
}
/***********************************************************************
* CreateDIBPatternBrush (GDI32.@)
*
* Create a logical brush which has the pattern specified by the DIB
*
* Function call is for compatibility only. CreateDIBPatternBrushPt should be used.
*
* RETURNS
*
* Handle to a logical brush on success, NULL on failure.
*
* BUGS
*
*/
HBRUSH WINAPI CreateDIBPatternBrush(
HGLOBAL hbitmap, /* [in] Global object containg BITMAPINFO structure */
UINT coloruse /* [in] Specifies color format, if provided */
)
{
LOGBRUSH logbrush;
TRACE("%p\n", hbitmap );
logbrush.lbStyle = BS_DIBPATTERN;
logbrush.lbColor = coloruse;
logbrush.lbHatch = (LONG)hbitmap;
return CreateBrushIndirect( &logbrush );
}
/***********************************************************************
* CreateDIBPatternBrushPt (GDI32.@)
*
* Create a logical brush which has the pattern specified by the DIB
*
* RETURNS
*
* Handle to a logical brush on success, NULL on failure.
*
* BUGS
*
*/
HBRUSH WINAPI CreateDIBPatternBrushPt(
const void* data, /* [in] Pointer to a BITMAPINFO structure followed by more data */
UINT coloruse /* [in] Specifies color format, if provided */
)
{
BITMAPINFO *info=(BITMAPINFO*)data;
LOGBRUSH logbrush;
if (!data)
return NULL;
TRACE("%p %ldx%ld %dbpp\n", info, info->bmiHeader.biWidth,
info->bmiHeader.biHeight, info->bmiHeader.biBitCount);
logbrush.lbStyle = BS_DIBPATTERNPT;
logbrush.lbColor = coloruse;
logbrush.lbHatch = (LONG) data;
return CreateBrushIndirect( &logbrush );
}
/***********************************************************************
* CreateSolidBrush (GDI32.@)
*/
HBRUSH WINAPI CreateSolidBrush( COLORREF color )
{
LOGBRUSH logbrush;
TRACE("%06lx\n", color );
logbrush.lbStyle = BS_SOLID;
logbrush.lbColor = color;
logbrush.lbHatch = 0;
return CreateBrushIndirect( &logbrush );
}
/***********************************************************************
* SetBrushOrgEx (GDI32.@)
*/
BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
{
DC *dc = DC_GetDCPtr( hdc );
if (!dc) return FALSE;
if (oldorg)
{
oldorg->x = dc->brushOrgX;
oldorg->y = dc->brushOrgY;
}
dc->brushOrgX = x;
dc->brushOrgY = y;
GDI_ReleaseObj( hdc );
return TRUE;
}
/***********************************************************************
* FixBrushOrgEx (GDI32.@)
* SDK says discontinued, but in Win95 GDI32 this is the same as SetBrushOrgEx
*/
BOOL WINAPI FixBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg )
{
return SetBrushOrgEx(hdc,x,y,oldorg);
}
/***********************************************************************
* 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;
}
/***********************************************************************
* BRUSH_DeleteObject
*/
static BOOL BRUSH_DeleteObject( HGDIOBJ handle, void *obj )
{
BRUSHOBJ *brush = obj;
switch(brush->logbrush.lbStyle)
{
case BS_PATTERN:
DeleteObject( (HGDIOBJ)brush->logbrush.lbHatch );
break;
case BS_DIBPATTERN:
GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
break;
}
return GDI_FreeObject( handle, obj );
}
/***********************************************************************
* BRUSH_GetObject16
*/
static INT BRUSH_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
{
BRUSHOBJ *brush = obj;
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;
}
/***********************************************************************
* BRUSH_GetObject
*/
static INT BRUSH_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
{
BRUSHOBJ *brush = obj;
if( !buffer )
return sizeof(brush->logbrush);
if (count > sizeof(brush->logbrush)) count = sizeof(brush->logbrush);
memcpy( buffer, &brush->logbrush, count );
return count;
}
/***********************************************************************
* SetSolidBrush (GDI.604)
*
* If hBrush is a solid brush, change its color to newColor.
*
* RETURNS
* TRUE on success, FALSE on failure.
*
* FIXME: untested, not sure if correct.
*/
BOOL16 WINAPI SetSolidBrush16(HBRUSH16 hBrush, COLORREF newColor )
{
BRUSHOBJ * brushPtr;
BOOL16 res = FALSE;
TRACE("(hBrush %04x, newColor %08lx)\n", hBrush, (DWORD)newColor);
if (!(brushPtr = (BRUSHOBJ *) GDI_GetObjPtr( HBRUSH_32(hBrush), BRUSH_MAGIC )))
return FALSE;
if (brushPtr->logbrush.lbStyle == BS_SOLID)
{
brushPtr->logbrush.lbColor = newColor;
res = TRUE;
}
GDI_ReleaseObj( HBRUSH_32(hBrush) );
return res;
}