1. more accurate conversion from 8-bit wx color to 16-bit GDK color
[wxWidgets.git] / src / gtk / colour.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/colour.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
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
23 class wxColourRefData: public wxObjectRefData
24 {
25 public:
26 wxColourRefData(guint16 red, guint16 green, guint16 blue)
27 {
28 m_red = red;
29 m_green = green;
30 m_blue = blue;
31 m_color.pixel = 0;
32 m_colormap = NULL;
33 }
34
35 ~wxColourRefData()
36 {
37 FreeColour();
38 }
39
40 void FreeColour();
41 void AllocColour( GdkColormap* cmap );
42
43 GdkColor m_color;
44 GdkColormap *m_colormap;
45 // gdk_colormap_alloc_color may change the RGB values in m_color, so we need separate copies
46 guint16 m_red;
47 guint16 m_green;
48 guint16 m_blue;
49
50 DECLARE_NO_COPY_CLASS(wxColourRefData)
51 };
52
53 void wxColourRefData::FreeColour()
54 {
55 if (m_colormap)
56 {
57 gdk_colormap_free_colors(m_colormap, &m_color, 1);
58 m_colormap = NULL;
59 m_color.pixel = 0;
60 }
61 }
62
63 void wxColourRefData::AllocColour( GdkColormap *cmap )
64 {
65 if (m_colormap != cmap)
66 {
67 FreeColour();
68
69 m_color.red = m_red;
70 m_color.green = m_green;
71 m_color.blue = m_blue;
72 if (gdk_colormap_alloc_color(cmap, &m_color, FALSE, TRUE))
73 {
74 m_colormap = cmap;
75 }
76 }
77 }
78
79 //-----------------------------------------------------------------------------
80
81 #define M_COLDATA wx_static_cast(wxColourRefData*, m_refData)
82
83 // GDK's values are in 0..65535 range, ours are in 0..255
84 #define SHIFT 8
85
86 IMPLEMENT_DYNAMIC_CLASS(wxColour,wxGDIObject)
87
88 wxColour::wxColour(const GdkColor& gdkColor)
89 {
90 m_refData = new wxColourRefData(gdkColor.red, gdkColor.green, gdkColor.blue);
91 }
92
93 wxColour::~wxColour()
94 {
95 }
96
97 bool wxColour::operator == ( const wxColour& col ) const
98 {
99 if (m_refData == col.m_refData)
100 return true;
101
102 if (!m_refData || !col.m_refData)
103 return false;
104
105 wxColourRefData* refData = M_COLDATA;
106 wxColourRefData* that_refData = wx_static_cast(wxColourRefData*, col.m_refData);
107 return refData->m_red == that_refData->m_red &&
108 refData->m_green == that_refData->m_green &&
109 refData->m_blue == that_refData->m_blue;
110 }
111
112 void wxColour::InitWith( unsigned char red, unsigned char green, unsigned char blue )
113 {
114 UnRef();
115
116 m_refData = new wxColourRefData(
117 (guint16(red) << SHIFT) + red,
118 (guint16(green) << SHIFT) + green,
119 (guint16(blue) << SHIFT) + blue);
120 }
121
122 unsigned char wxColour::Red() const
123 {
124 wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
125
126 return wxByte(M_COLDATA->m_red >> SHIFT);
127 }
128
129 unsigned char wxColour::Green() const
130 {
131 wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
132
133 return wxByte(M_COLDATA->m_green >> SHIFT);
134 }
135
136 unsigned char wxColour::Blue() const
137 {
138 wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
139
140 return wxByte(M_COLDATA->m_blue >> SHIFT);
141 }
142
143 void wxColour::CalcPixel( GdkColormap *cmap )
144 {
145 if (!Ok()) return;
146
147 M_COLDATA->AllocColour( cmap );
148 }
149
150 int wxColour::GetPixel() const
151 {
152 wxCHECK_MSG( Ok(), 0, wxT("invalid colour") );
153
154 return M_COLDATA->m_color.pixel;
155 }
156
157 const GdkColor *wxColour::GetColor() const
158 {
159 wxCHECK_MSG( Ok(), NULL, wxT("invalid colour") );
160
161 return &M_COLDATA->m_color;
162 }
163
164 bool wxColour::FromString(const wxChar *str)
165 {
166 GdkColor colGDK;
167 if ( gdk_color_parse( wxGTK_CONV_SYS( str ), &colGDK ) )
168 {
169 *this = wxColour(colGDK);
170 return true;
171 }
172
173 return wxColourBase::FromString(str);
174 }