1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk/colour.cpp
3 // Purpose:
4 // Author:      Robert Roebling
5 // Copyright:   (c) 1998 Robert Roebling
6 // Licence:     wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8 
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
11 
12 #include "wx/colour.h"
13 
14 #include <gdk/gdk.h>
15 #include "wx/gtk/private.h"
16 
17 //-----------------------------------------------------------------------------
18 // wxColour
19 //-----------------------------------------------------------------------------
20 
21 class wxColourRefData : public wxGDIRefData
22 {
23 public:
24 #ifdef __WXGTK3__
wxColourRefData(const GdkRGBA & gdkRGBA)25     wxColourRefData(const GdkRGBA& gdkRGBA)
26         : m_gdkRGBA(gdkRGBA)
27     {
28         m_gdkColor.red = guint16(gdkRGBA.red * 65535);
29         m_gdkColor.green = guint16(gdkRGBA.green * 65535);
30         m_gdkColor.blue = guint16(gdkRGBA.blue * 65535);
31         m_alpha = wxByte(gdkRGBA.alpha * 255 + 0.5);
32     }
wxColourRefData(const GdkColor & gdkColor)33     wxColourRefData(const GdkColor& gdkColor)
34         : m_gdkColor(gdkColor)
35     {
36         m_gdkRGBA.red = gdkColor.red / 65535.0;
37         m_gdkRGBA.green = gdkColor.green / 65535.0;
38         m_gdkRGBA.blue = gdkColor.blue / 65535.0;
39         m_gdkRGBA.alpha = 1;
40         m_alpha = 255;
41     }
wxColourRefData(guchar red,guchar green,guchar blue,guchar alpha)42     wxColourRefData(guchar red, guchar green, guchar blue, guchar alpha)
43     {
44         m_gdkRGBA.red = red / 255.0;
45         m_gdkRGBA.green = green / 255.0;
46         m_gdkRGBA.blue = blue / 255.0;
47         m_gdkRGBA.alpha = alpha / 255.0;
48         m_gdkColor.red = (guint16(red) << 8) + red;
49         m_gdkColor.green = (guint16(green) << 8) + green;
50         m_gdkColor.blue = (guint16(blue) << 8) + blue;
51         m_alpha = alpha;
52     }
53     GdkRGBA m_gdkRGBA;
54     GdkColor m_gdkColor;
55 #else
56     wxColourRefData(guint16 red, guint16 green, guint16 blue, wxByte alpha = 0xff)
57     {
58         m_color.red =
59         m_red = red;
60         m_color.green =
61         m_green = green;
62         m_color.blue =
63         m_blue = blue;
64         m_alpha = alpha;
65         m_color.pixel = 0;
66         m_colormap = NULL;
67     }
68 
69     virtual ~wxColourRefData()
70     {
71         FreeColour();
72     }
73 
74     void FreeColour();
75     void AllocColour( GdkColormap* cmap );
76 
77     GdkColor     m_color;
78     GdkColormap *m_colormap;
79     // gdk_colormap_alloc_color may change the RGB values in m_color, so we need separate copies
80     guint16 m_red;
81     guint16 m_green;
82     guint16 m_blue;
83 #endif
84     wxByte m_alpha;
85 
86     wxDECLARE_NO_COPY_CLASS(wxColourRefData);
87 };
88 
89 #ifndef __WXGTK3__
FreeColour()90 void wxColourRefData::FreeColour()
91 {
92     if (m_colormap)
93     {
94         gdk_colormap_free_colors(m_colormap, &m_color, 1);
95         m_colormap = NULL;
96         m_color.pixel = 0;
97     }
98 }
99 
AllocColour(GdkColormap * cmap)100 void wxColourRefData::AllocColour( GdkColormap *cmap )
101 {
102     if (m_colormap != cmap)
103     {
104         FreeColour();
105 
106         m_color.red = m_red;
107         m_color.green = m_green;
108         m_color.blue = m_blue;
109         if (gdk_colormap_alloc_color(cmap, &m_color, FALSE, TRUE))
110         {
111             m_colormap = cmap;
112         }
113     }
114 }
115 #endif
116 
117 //-----------------------------------------------------------------------------
118 
119 #define M_COLDATA static_cast<wxColourRefData*>(m_refData)
120 
121 // GDK's values are in 0..65535 range, ours are in 0..255
122 #define SHIFT  8
123 
124 #ifdef __WXGTK3__
wxColour(const GdkRGBA & gdkRGBA)125 wxColour::wxColour(const GdkRGBA& gdkRGBA)
126 {
127     m_refData = new wxColourRefData(gdkRGBA);
128 }
129 
wxColour(const GdkColor & gdkColor)130 wxColour::wxColour(const GdkColor& gdkColor)
131 {
132     m_refData = new wxColourRefData(gdkColor);
133 }
134 #else
wxColour(const GdkColor & gdkColor)135 wxColour::wxColour(const GdkColor& gdkColor)
136 {
137     m_refData = new wxColourRefData(gdkColor.red, gdkColor.green, gdkColor.blue);
138 }
139 #endif
140 
~wxColour()141 wxColour::~wxColour()
142 {
143 }
144 
operator ==(const wxColour & col) const145 bool wxColour::operator == ( const wxColour& col ) const
146 {
147     if (m_refData == col.m_refData)
148         return true;
149 
150     if (!m_refData || !col.m_refData)
151         return false;
152 
153     wxColourRefData* refData = M_COLDATA;
154     wxColourRefData* that_refData = static_cast<wxColourRefData*>(col.m_refData);
155 #ifdef __WXGTK3__
156     return refData->m_gdkColor.red == that_refData->m_gdkColor.red &&
157            refData->m_gdkColor.green == that_refData->m_gdkColor.green &&
158            refData->m_gdkColor.blue == that_refData->m_gdkColor.blue &&
159 #else
160     return refData->m_red == that_refData->m_red &&
161            refData->m_green == that_refData->m_green &&
162            refData->m_blue == that_refData->m_blue &&
163 #endif
164            refData->m_alpha == that_refData->m_alpha;
165 }
166 
InitRGBA(unsigned char red,unsigned char green,unsigned char blue,unsigned char alpha)167 void wxColour::InitRGBA(unsigned char red, unsigned char green, unsigned char blue,
168                         unsigned char alpha)
169 {
170     UnRef();
171 
172 #ifdef __WXGTK3__
173     m_refData = new wxColourRefData(red, green, blue, alpha);
174 #else
175     m_refData = new wxColourRefData(
176         (guint16(red) << SHIFT) + red,
177         (guint16(green) << SHIFT) + green,
178         (guint16(blue) << SHIFT) + blue,
179         alpha);
180 #endif
181 }
182 
Red() const183 unsigned char wxColour::Red() const
184 {
185     wxCHECK_MSG( IsOk(), 0, wxT("invalid colour") );
186 
187 #ifdef __WXGTK3__
188     return wxByte(M_COLDATA->m_gdkColor.red >> 8);
189 #else
190     return wxByte(M_COLDATA->m_red >> SHIFT);
191 #endif
192 }
193 
Green() const194 unsigned char wxColour::Green() const
195 {
196     wxCHECK_MSG( IsOk(), 0, wxT("invalid colour") );
197 
198 #ifdef __WXGTK3__
199     return wxByte(M_COLDATA->m_gdkColor.green >> 8);
200 #else
201     return wxByte(M_COLDATA->m_green >> SHIFT);
202 #endif
203 }
204 
Blue() const205 unsigned char wxColour::Blue() const
206 {
207     wxCHECK_MSG( IsOk(), 0, wxT("invalid colour") );
208 
209 #ifdef __WXGTK3__
210     return wxByte(M_COLDATA->m_gdkColor.blue >> 8);
211 #else
212     return wxByte(M_COLDATA->m_blue >> SHIFT);
213 #endif
214 }
215 
Alpha() const216 unsigned char wxColour::Alpha() const
217 {
218     wxCHECK_MSG( IsOk(), 0, wxT("invalid colour") );
219 
220     return M_COLDATA->m_alpha;
221 }
222 
223 #ifndef __WXGTK3__
CalcPixel(GdkColormap * cmap)224 void wxColour::CalcPixel( GdkColormap *cmap )
225 {
226     if (!IsOk()) return;
227 
228     M_COLDATA->AllocColour( cmap );
229 }
230 
GetPixel() const231 int wxColour::GetPixel() const
232 {
233     wxCHECK_MSG( IsOk(), 0, wxT("invalid colour") );
234 
235     return M_COLDATA->m_color.pixel;
236 }
237 #endif
238 
GetColor() const239 const GdkColor *wxColour::GetColor() const
240 {
241     wxCHECK_MSG( IsOk(), NULL, wxT("invalid colour") );
242 
243 #ifdef __WXGTK3__
244     return &M_COLDATA->m_gdkColor;
245 #else
246     return &M_COLDATA->m_color;
247 #endif
248 }
249 
250 #ifdef __WXGTK3__
operator const GdkRGBA*() const251 wxColour::operator const GdkRGBA*() const
252 {
253     const GdkRGBA* c = NULL;
254     if (IsOk())
255         c = &M_COLDATA->m_gdkRGBA;
256     return c;
257 }
258 #endif
259 
FromString(const wxString & str)260 bool wxColour::FromString(const wxString& str)
261 {
262 #ifdef __WXGTK3__
263     GdkRGBA gdkRGBA;
264     if (gdk_rgba_parse(&gdkRGBA, wxGTK_CONV_SYS(str)))
265     {
266         *this = wxColour(gdkRGBA);
267         return true;
268     }
269 #else
270     GdkColor colGDK;
271     if ( gdk_color_parse( wxGTK_CONV_SYS( str ), &colGDK ) )
272     {
273         *this = wxColour(colGDK);
274         return true;
275     }
276 #endif
277 
278     return wxColourBase::FromString(str);
279 }
280