X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/04ef50df3a0fa3c343800c554e609f98fc7575cc..43c42c18d36c703a88b1b7b697bac27fe5608eca:/src/msw/brush.cpp diff --git a/src/msw/brush.cpp b/src/msw/brush.cpp index 83f9652783..2d266918b7 100644 --- a/src/msw/brush.cpp +++ b/src/msw/brush.cpp @@ -1,253 +1,336 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: brush.cpp +// Name: src/msw/brush.cpp // Purpose: wxBrush // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Julian Smart +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "brush.h" -#endif +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif -#ifndef WX_PRECOMP -#include -#include "wx/setup.h" -#include "wx/list.h" -#include "wx/utils.h" -#include "wx/app.h" #include "wx/brush.h" -#endif + +#ifndef WX_PRECOMP + #include "wx/list.h" + #include "wx/utils.h" + #include "wx/app.h" + #include "wx/bitmap.h" +#endif // WX_PRECOMP #include "wx/msw/private.h" -#include "assert.h" +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxBrushRefData: public wxGDIRefData +{ +public: + wxBrushRefData(const wxColour& colour = wxNullColour, wxBrushStyle style = wxBRUSHSTYLE_SOLID); + wxBrushRefData(const wxBitmap& stipple); + wxBrushRefData(const wxBrushRefData& data); + virtual ~wxBrushRefData(); + + bool operator==(const wxBrushRefData& data) const; + + HBRUSH GetHBRUSH(); + void Free(); + + const wxColour& GetColour() const { return m_colour; } + wxBrushStyle GetStyle() const { return m_style; } + wxBitmap *GetStipple() { return &m_stipple; } + + void SetColour(const wxColour& colour) { Free(); m_colour = colour; } + void SetStyle(wxBrushStyle style) { Free(); m_style = style; } + void SetStipple(const wxBitmap& stipple) { Free(); DoSetStipple(stipple); } + +private: + void DoSetStipple(const wxBitmap& stipple); + + wxBrushStyle m_style; + wxBitmap m_stipple; + wxColour m_colour; + HBRUSH m_hBrush; + + // no assignment operator, the objects of this class are shared and never + // assigned after being created once + wxBrushRefData& operator=(const wxBrushRefData&); +}; + +#define M_BRUSHDATA ((wxBrushRefData *)m_refData) + +// ============================================================================ +// wxBrushRefData implementation +// ============================================================================ IMPLEMENT_DYNAMIC_CLASS(wxBrush, wxGDIObject) -wxBrushRefData::wxBrushRefData(void) +// ---------------------------------------------------------------------------- +// wxBrushRefData ctors/dtor +// ---------------------------------------------------------------------------- + +wxBrushRefData::wxBrushRefData(const wxColour& colour, wxBrushStyle style) + : m_colour(colour) { - m_style = wxSOLID; - m_hBrush = 0; + m_style = style; + + m_hBrush = NULL; } -wxBrushRefData::wxBrushRefData(const wxBrushRefData& data) +wxBrushRefData::wxBrushRefData(const wxBitmap& stipple) { - m_style = data.m_style; - m_stipple = data.m_stipple; - m_colour = data.m_colour; - m_hBrush = 0; + DoSetStipple(stipple); + + m_hBrush = NULL; } -wxBrushRefData::~wxBrushRefData(void) +wxBrushRefData::wxBrushRefData(const wxBrushRefData& data) + : wxGDIRefData(), + m_stipple(data.m_stipple), + m_colour(data.m_colour) { - if ( m_hBrush ) - ::DeleteObject((HBRUSH) m_hBrush); + m_style = data.m_style; + + // we can't share HBRUSH, we'd need to create another one ourselves + m_hBrush = NULL; } -// Brushes -wxBrush::wxBrush(void) +wxBrushRefData::~wxBrushRefData() { - if ( wxTheBrushList ) - wxTheBrushList->AddBrush(this); + Free(); } -wxBrush::~wxBrush() +// ---------------------------------------------------------------------------- +// wxBrushRefData accesors +// ---------------------------------------------------------------------------- + +bool wxBrushRefData::operator==(const wxBrushRefData& data) const { - if (wxTheBrushList) - wxTheBrushList->RemoveBrush(this); + // don't compare HBRUSHes + return m_style == data.m_style && + m_colour == data.m_colour && + m_stipple.IsSameAs(data.m_stipple); } -wxBrush::wxBrush(const wxColour& col, int Style) +void wxBrushRefData::DoSetStipple(const wxBitmap& stipple) { - m_refData = new wxBrushRefData; + m_stipple = stipple; + m_style = stipple.GetMask() ? wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE + : wxBRUSHSTYLE_STIPPLE; +} - M_BRUSHDATA->m_colour = col; - M_BRUSHDATA->m_style = Style; - M_BRUSHDATA->m_hBrush = 0; +// ---------------------------------------------------------------------------- +// wxBrushRefData resource handling +// ---------------------------------------------------------------------------- - RealizeResource(); +void wxBrushRefData::Free() +{ + if ( m_hBrush ) + { + ::DeleteObject(m_hBrush); - if ( wxTheBrushList ) - wxTheBrushList->AddBrush(this); + m_hBrush = NULL; + } } -wxBrush::wxBrush(const wxBitmap& stipple) +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) + +static int TranslateHatchStyle(int style) { - m_refData = new wxBrushRefData; + switch ( style ) + { + case wxBRUSHSTYLE_BDIAGONAL_HATCH: return HS_BDIAGONAL; + case wxBRUSHSTYLE_CROSSDIAG_HATCH: return HS_DIAGCROSS; + case wxBRUSHSTYLE_FDIAGONAL_HATCH: return HS_FDIAGONAL; + case wxBRUSHSTYLE_CROSS_HATCH: return HS_CROSS; + case wxBRUSHSTYLE_HORIZONTAL_HATCH:return HS_HORIZONTAL; + case wxBRUSHSTYLE_VERTICAL_HATCH: return HS_VERTICAL; + default: return -1; + } +} - M_BRUSHDATA->m_stipple = stipple; - if (M_BRUSHDATA->m_stipple.GetMask()) - M_BRUSHDATA->m_style = wxSTIPPLE_MASK_OPAQUE; - else - M_BRUSHDATA->m_style = wxSTIPPLE; +#endif // !__WXMICROWIN__ && !__WXWINCE__ - M_BRUSHDATA->m_hBrush = 0; +HBRUSH wxBrushRefData::GetHBRUSH() +{ + if ( !m_hBrush ) + { +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) + int hatchStyle = TranslateHatchStyle(m_style); + if ( hatchStyle == -1 ) +#endif // !__WXMICROWIN__ && !__WXWINCE__ + { + switch ( m_style ) + { + case wxBRUSHSTYLE_TRANSPARENT: + m_hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH); + break; + + case wxBRUSHSTYLE_STIPPLE: + m_hBrush = ::CreatePatternBrush(GetHbitmapOf(m_stipple)); + break; + + case wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE: + m_hBrush = ::CreatePatternBrush((HBITMAP)m_stipple.GetMask() + ->GetMaskBitmap()); + break; + + default: + wxFAIL_MSG( wxT("unknown brush style") ); + // fall through + + case wxBRUSHSTYLE_SOLID: + m_hBrush = ::CreateSolidBrush(m_colour.GetPixel()); + break; + } + } +#ifndef __WXWINCE__ + else // create a hatched brush + { + m_hBrush = ::CreateHatchBrush(hatchStyle, m_colour.GetPixel()); + } +#endif - RealizeResource(); + if ( !m_hBrush ) + { + wxLogLastError(wxT("CreateXXXBrush()")); + } + } - if ( wxTheBrushList ) - wxTheBrushList->AddBrush(this); + return m_hBrush; } -bool wxBrush::RealizeResource(void) +// ============================================================================ +// wxBrush implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxBrush ctors/dtor +// ---------------------------------------------------------------------------- + +wxBrush::wxBrush() { - if (M_BRUSHDATA && (M_BRUSHDATA->m_hBrush == 0)) - { - if (M_BRUSHDATA->m_style==wxTRANSPARENT) - { - M_BRUSHDATA->m_hBrush = (WXHBRUSH) ::GetStockObject(NULL_BRUSH); - return TRUE; - } - COLORREF ms_colour = 0 ; +} - ms_colour = M_BRUSHDATA->m_colour.GetPixel() ; +wxBrush::wxBrush(const wxColour& col, wxBrushStyle style) +{ + m_refData = new wxBrushRefData(col, style); +} - switch (M_BRUSHDATA->m_style) - { -/**** - // Don't reset cbrush, wxTRANSPARENT is handled by wxBrush::SelectBrush() - // this could save (many) time if frequently switching from - // wxSOLID to wxTRANSPARENT, because Create... is not always called!! - // - // NB August 95: now create and select a Null brush instead. - // This could be optimized as above. - case wxTRANSPARENT: - M_BRUSHDATA->m_hBrush = NULL; // Must always select a suitable background brush - // - could choose white always for a quick solution - break; -***/ -#ifndef __WXMICROWIN__ - case wxBDIAGONAL_HATCH: - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateHatchBrush(HS_BDIAGONAL,ms_colour) ; - break ; - case wxCROSSDIAG_HATCH: - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateHatchBrush(HS_DIAGCROSS,ms_colour) ; - break ; - case wxFDIAGONAL_HATCH: - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateHatchBrush(HS_FDIAGONAL,ms_colour) ; - break ; - case wxCROSS_HATCH: - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateHatchBrush(HS_CROSS,ms_colour) ; - break ; - case wxHORIZONTAL_HATCH: - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateHatchBrush(HS_HORIZONTAL,ms_colour) ; - break ; - case wxVERTICAL_HATCH: - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateHatchBrush(HS_VERTICAL,ms_colour) ; - break ; - case wxSTIPPLE: - if (M_BRUSHDATA->m_stipple.Ok()) - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreatePatternBrush((HBITMAP) M_BRUSHDATA->m_stipple.GetHBITMAP()) ; - else - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateSolidBrush(ms_colour) ; - break ; - case wxSTIPPLE_MASK_OPAQUE: - if (M_BRUSHDATA->m_stipple.Ok() && M_BRUSHDATA->m_stipple.GetMask()) - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreatePatternBrush((HBITMAP) M_BRUSHDATA->m_stipple.GetMask()->GetMaskBitmap()); - else - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateSolidBrush(ms_colour) ; - break ; -#endif - case wxSOLID: - default: - M_BRUSHDATA->m_hBrush = (WXHBRUSH) CreateSolidBrush(ms_colour) ; - break; - } -#ifdef WXDEBUG_CREATE - if (M_BRUSHDATA->m_hBrush==NULL) wxError("Cannot create brush","Internal error") ; +#if FUTURE_WXWIN_COMPATIBILITY_3_0 +wxBrush::wxBrush(const wxColour& col, int style) +{ + m_refData = new wxBrushRefData(col, (wxBrushStyle)style); +} #endif - return TRUE; - } - else - return FALSE; + +wxBrush::wxBrush(const wxBitmap& stipple) +{ + m_refData = new wxBrushRefData(stipple); } -WXHANDLE wxBrush::GetResourceHandle(void) +wxBrush::~wxBrush() { - return (WXHANDLE) M_BRUSHDATA->m_hBrush; } -bool wxBrush::FreeResource(bool WXUNUSED(force)) +// ---------------------------------------------------------------------------- +// wxBrush house keeping stuff +// ---------------------------------------------------------------------------- + +bool wxBrush::operator==(const wxBrush& brush) const { - if (M_BRUSHDATA && (M_BRUSHDATA->m_hBrush != 0)) - { - DeleteObject((HBRUSH) M_BRUSHDATA->m_hBrush); - M_BRUSHDATA->m_hBrush = 0; - return TRUE; - } - else return FALSE; + const wxBrushRefData *brushData = (wxBrushRefData *)brush.m_refData; + + // an invalid brush is considered to be only equal to another invalid brush + return m_refData ? (brushData && *M_BRUSHDATA == *brushData) : !brushData; } -bool wxBrush::IsFree() const +wxGDIRefData *wxBrush::CreateGDIRefData() const { - return (M_BRUSHDATA && (M_BRUSHDATA->m_hBrush == 0)); + return new wxBrushRefData; } -void wxBrush::Unshare() +wxGDIRefData *wxBrush::CloneGDIRefData(const wxGDIRefData *data) const { - // Don't change shared data - if (!m_refData) - { - m_refData = new wxBrushRefData(); - } - else - { - wxBrushRefData* ref = new wxBrushRefData(*(wxBrushRefData*)m_refData); - UnRef(); - m_refData = ref; - } + return new wxBrushRefData(*(const wxBrushRefData *)data); } +// ---------------------------------------------------------------------------- +// wxBrush accessors +// ---------------------------------------------------------------------------- -void wxBrush::SetColour(const wxColour& col) +wxColour wxBrush::GetColour() const { - Unshare(); - - M_BRUSHDATA->m_colour = col; + wxCHECK_MSG( IsOk(), wxNullColour, wxT("invalid brush") ); - RealizeResource(); + return M_BRUSHDATA->GetColour(); } -void wxBrush::SetColour(unsigned char r, unsigned char g, unsigned char b) +wxBrushStyle wxBrush::GetStyle() const { - Unshare(); + wxCHECK_MSG( IsOk(), wxBRUSHSTYLE_INVALID, wxT("invalid brush") ); - M_BRUSHDATA->m_colour.Set(r, g, b); + return M_BRUSHDATA->GetStyle(); +} - RealizeResource(); +wxBitmap *wxBrush::GetStipple() const +{ + wxCHECK_MSG( IsOk(), NULL, wxT("invalid brush") ); + + return M_BRUSHDATA->GetStipple(); } -void wxBrush::SetStyle(int Style) +WXHANDLE wxBrush::GetResourceHandle() const { - Unshare(); + wxCHECK_MSG( IsOk(), FALSE, wxT("invalid brush") ); + + return (WXHANDLE)M_BRUSHDATA->GetHBRUSH(); +} - M_BRUSHDATA->m_style = Style; +// ---------------------------------------------------------------------------- +// wxBrush setters +// ---------------------------------------------------------------------------- - RealizeResource(); +void wxBrush::SetColour(const wxColour& col) +{ + AllocExclusive(); + + M_BRUSHDATA->SetColour(col); } -void wxBrush::SetStipple(const wxBitmap& Stipple) +void wxBrush::SetColour(unsigned char r, unsigned char g, unsigned char b) { - Unshare(); + AllocExclusive(); - M_BRUSHDATA->m_stipple = Stipple; - if (M_BRUSHDATA->m_stipple.GetMask()) - M_BRUSHDATA->m_style = wxSTIPPLE_MASK_OPAQUE; - else - M_BRUSHDATA->m_style = wxSTIPPLE; + M_BRUSHDATA->SetColour(wxColour(r, g, b)); +} - RealizeResource(); +void wxBrush::SetStyle(wxBrushStyle style) +{ + AllocExclusive(); + + M_BRUSHDATA->SetStyle(style); } +void wxBrush::SetStipple(const wxBitmap& stipple) +{ + AllocExclusive(); + M_BRUSHDATA->SetStipple(stipple); +}