1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/gtk/colour.cpp
3// Purpose:
4// Author:      Robert Roebling
5// Id:          $Id: colour.cpp 41598 2006-10-03 16:45:33Z SC $
6// Copyright:   (c) 1998 Robert Roebling
7// Licence:     wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
13#include "wx/colour.h"
14
15#include "wx/gtk/private.h"
16
17#include <gdk/gdk.h>
18
19//-----------------------------------------------------------------------------
20// wxColour
21//-----------------------------------------------------------------------------
22
23class wxColourRefData: public wxObjectRefData
24{
25public:
26    wxColourRefData(guint16 red, guint16 green, guint16 blue, guint16 alpha)
27    {
28        m_color.red =
29        m_red = red;
30        m_color.green =
31        m_green = green;
32        m_color.blue =
33        m_blue = blue;
34        m_alpha = alpha;
35        m_color.pixel = 0;
36        m_colormap = NULL;
37    }
38
39    virtual ~wxColourRefData()
40    {
41        FreeColour();
42    }
43
44    void FreeColour();
45    void AllocColour( GdkColormap* cmap );
46
47    GdkColor     m_color;
48    GdkColormap *m_colormap;
49    // gdk_colormap_alloc_color may change the RGB values in m_color, so we need separate copies
50    guint16 m_red;
51    guint16 m_green;
52    guint16 m_blue;
53    guint16 m_alpha;
54
55    DECLARE_NO_COPY_CLASS(wxColourRefData)
56};
57
58void wxColourRefData::FreeColour()
59{
60    if (m_colormap)
61    {
62        gdk_colormap_free_colors(m_colormap, &m_color, 1);
63        m_colormap = NULL;
64        m_color.pixel = 0;
65    }
66}
67
68void wxColourRefData::AllocColour( GdkColormap *cmap )
69{
70    if (m_colormap != cmap)
71    {
72        FreeColour();
73
74        m_color.red = m_red;
75        m_color.green = m_green;
76        m_color.blue = m_blue;
77        if (gdk_colormap_alloc_color(cmap, &m_color, FALSE, TRUE))
78        {
79            m_colormap = cmap;
80        }
81    }
82}
83
84//-----------------------------------------------------------------------------
85
86#define M_COLDATA wx_static_cast(wxColourRefData*, m_refData)
87
88// GDK's values are in 0..65535 range, ours are in 0..255
89#define SHIFT  8
90
91IMPLEMENT_DYNAMIC_CLASS(wxColour,wxGDIObject)
92
93wxColour::wxColour(const GdkColor& gdkColor)
94{
95    m_refData = new wxColourRefData(gdkColor.red, gdkColor.green, gdkColor.blue, 0xFFFF /*opaque alpha in 16 bit*/);
96}
97
98wxColour::~wxColour()
99{
100}
101
102bool wxColour::operator == ( const wxColour& col ) const
103{
104    if (m_refData == col.m_refData)
105        return true;
106
107    if (!m_refData || !col.m_refData)
108        return false;
109
110    wxColourRefData* refData = M_COLDATA;
111    wxColourRefData* that_refData = wx_static_cast(wxColourRefData*, col.m_refData);
112    return refData->m_red == that_refData->m_red &&
113           refData->m_green == that_refData->m_green &&
114           refData->m_blue == that_refData->m_blue &&
115           refData->m_alpha == that_refData->m_alpha;
116}
117
118void wxColour::InitRGBA(unsigned char red, unsigned char green, unsigned char blue,
119                        unsigned char alpha)
120{
121    UnRef();
122
123    m_refData = new wxColourRefData(
124        (guint16(red) << SHIFT) + red,
125        (guint16(green) << SHIFT) + green,
126        (guint16(blue) << SHIFT) + blue,
127        (guint16(alpha) << SHIFT) + alpha);
128}
129
130unsigned char wxColour::Red() const
131{
132    wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
133
134    return wxByte(M_COLDATA->m_red >> SHIFT);
135}
136
137unsigned char wxColour::Green() const
138{
139    wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
140
141    return wxByte(M_COLDATA->m_green >> SHIFT);
142}
143
144unsigned char wxColour::Blue() const
145{
146    wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
147
148    return wxByte(M_COLDATA->m_blue >> SHIFT);
149}
150
151unsigned char wxColour::Alpha() const
152{
153    wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
154
155    return wxByte(M_COLDATA->m_alpha >> SHIFT);
156}
157
158void wxColour::CalcPixel( GdkColormap *cmap )
159{
160    if (!Ok()) return;
161
162    M_COLDATA->AllocColour( cmap );
163}
164
165int wxColour::GetPixel() const
166{
167    wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
168
169    return M_COLDATA->m_color.pixel;
170}
171
172#ifdef __WXGTK24__
173const GdkColor *wxColour::GetColor() const
174#else
175      GdkColor *wxColour::GetColor() const
176#endif
177{
178    wxCHECK_MSG( Ok(), NULL, wxT("invalid colour") );
179
180    return &M_COLDATA->m_color;
181}
182
183bool wxColour::FromString(const wxChar *str)
184{
185    GdkColor colGDK;
186    if ( gdk_color_parse( wxGTK_CONV_SYS( str ), &colGDK ) )
187    {
188        *this = wxColour(colGDK);
189        return true;
190    }
191
192    return wxColourBase::FromString(str);
193}
194