]> git.saurik.com Git - wxWidgets.git/blame - src/motif/colour.cpp
More Motif additions: mdi and sashtest samples now just about work!
[wxWidgets.git] / src / motif / colour.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: colour.cpp
3// Purpose: wxColour class
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
dfc54541
JS
12//// TODO: make wxColour a ref-counted object,
13//// so pixel values get shared.
14
4bb6408c
JS
15#ifdef __GNUG__
16#pragma implementation "colour.h"
17#endif
18
19#include "wx/gdicmn.h"
20#include "wx/colour.h"
dfc54541
JS
21#include "wx/app.h"
22
23#include <Xm/Xm.h>
24
25#include "wx/motif/private.h"
4bb6408c
JS
26
27#if !USE_SHARED_LIBRARY
28IMPLEMENT_DYNAMIC_CLASS(wxColour, wxObject)
29#endif
30
31// Colour
32
33wxColour::wxColour ()
34{
35 m_isInit = FALSE;
36 m_red = m_blue = m_green = 0;
dfc54541 37 m_pixel = -1;
4bb6408c
JS
38}
39
40wxColour::wxColour (unsigned char r, unsigned char g, unsigned char b)
41{
42 m_red = r;
43 m_green = g;
44 m_blue = b;
45 m_isInit = TRUE;
dfc54541 46 m_pixel = -1;
4bb6408c
JS
47}
48
49wxColour::wxColour (const wxColour& col)
50{
51 m_red = col.m_red;
52 m_green = col.m_green;
53 m_blue = col.m_blue;
54 m_isInit = col.m_isInit;
4bb6408c 55 m_pixel = col.m_pixel;
4bb6408c
JS
56}
57
58wxColour& wxColour::operator =(const wxColour& col)
59{
60 m_red = col.m_red;
61 m_green = col.m_green;
62 m_blue = col.m_blue;
63 m_isInit = col.m_isInit;
4bb6408c 64 m_pixel = col.m_pixel;
4bb6408c
JS
65 return *this;
66}
67
68wxColour::wxColour (const wxString& col)
69{
70 wxColour *the_colour = wxTheColourDatabase->FindColour (col);
71 if (the_colour)
72 {
73 m_red = the_colour->Red ();
74 m_green = the_colour->Green ();
75 m_blue = the_colour->Blue ();
e97f20a0 76 m_pixel = the_colour->m_pixel;
4bb6408c
JS
77 m_isInit = TRUE;
78 }
79 else
80 {
81 m_red = 0;
82 m_green = 0;
83 m_blue = 0;
84 m_isInit = FALSE;
85 }
4bb6408c
JS
86}
87
88wxColour::~wxColour ()
89{
90}
91
92wxColour& wxColour::operator = (const wxString& col)
93{
94 wxColour *the_colour = wxTheColourDatabase->FindColour (col);
95 if (the_colour)
96 {
97 m_red = the_colour->Red ();
98 m_green = the_colour->Green ();
99 m_blue = the_colour->Blue ();
e97f20a0 100 m_pixel = the_colour->m_pixel;
4bb6408c
JS
101 m_isInit = TRUE;
102 }
103 else
104 {
105 m_red = 0;
106 m_green = 0;
107 m_blue = 0;
108 m_isInit = FALSE;
109 }
e97f20a0 110
4bb6408c
JS
111 return (*this);
112}
113
114void wxColour::Set (unsigned char r, unsigned char g, unsigned char b)
115{
116 m_red = r;
117 m_green = g;
118 m_blue = b;
119 m_isInit = TRUE;
e97f20a0 120 m_pixel = -1;
4bb6408c 121}
dfc54541
JS
122
123// Allocate a colour, or nearest colour, using the given display.
124// If realloc is TRUE, ignore the existing pixel, otherwise just return
125// the existing one.
16c1f7f3 126// Returns the old or allocated pixel.
dfc54541
JS
127
128// TODO: can this handle mono displays? If not, we should have an extra
129// flag to specify whether this should be black or white by default.
130
16c1f7f3 131int wxColour::AllocColour(WXDisplay* display, bool realloc)
dfc54541
JS
132{
133 if ((m_pixel != -1) && !realloc)
16c1f7f3 134 return m_pixel;
dfc54541
JS
135
136 XColor color;
137 color.red = (unsigned short) Red ();
138 color.red |= color.red << 8;
139 color.green = (unsigned short) Green ();
140 color.green |= color.green << 8;
141 color.blue = (unsigned short) Blue ();
142 color.blue |= color.blue << 8;
143
144 color.flags = DoRed | DoGreen | DoBlue;
145
146 WXColormap cmap = wxTheApp->GetMainColormap(display);
147
148 if (!XAllocColor ((Display*) display, (Colormap) cmap, &color))
149 {
150 m_pixel = wxGetBestMatchingPixel((Display*) display, &color,(Colormap) cmap);
16c1f7f3 151 return m_pixel;
dfc54541
JS
152 }
153 else
154 {
155 m_pixel = (int) color.pixel;
16c1f7f3 156 return m_pixel;
dfc54541
JS
157 }
158}
159
160/*-------------------------------------------
161Markus Emmenegger <mege@iqe.ethz.ch>
162Find the pixel value with an assigned color closest to the desired color
163Used if color cell allocation fails
164As the returned pixel value may be in use by another application,
165the color might change anytime.
166But in many cases, that is still better than always using black.
167--
168Chris Breeze <chris@hel.co.uk>
169Improvements:
1701) More efficient calculation of RGB distance of colour cell from
171 the desired colour. There is no need to take the sqrt of 'dist', and
172 since we are only interested in the top 8-bits of R, G and B we
173 can perform integer arithmetic.
1742) Attempt to allocate a read-only colour when a close match is found.
175 A read-only colour will not change.
1763) Fall back to the closest match if no read-only colours are available.
177
178Possible further improvements:
1791) Scan the lookup table and sort the colour cells in order of
180increasing
181 distance from the desired colour. Then attempt to allocate a
182read-only
183 colour starting from the nearest match.
1842) Linear RGB distance is not a particularly good method of colour
185matching
186 (though it is quick). Converting the colour to HLS and then comparing
187 may give better matching.
188-------------------------------------------*/
189
190int wxGetBestMatchingPixel(Display *display, XColor *desiredColor, Colormap cmap)
191{
192 if (cmap == (Colormap) NULL)
193 cmap = (Colormap) wxTheApp->GetMainColormap(display);
194
195 int numPixVals = XDisplayCells(display, DefaultScreen (display));
196 int mindist = 256 * 256 * 3;
197 int bestpixel = (int) BlackPixel (display, DefaultScreen (display));
198 int red = desiredColor->red >> 8;
199 int green = desiredColor->green >> 8;
200 int blue = desiredColor->blue >> 8;
201 const int threshold = 2 * 2 * 3; // allow an error of up to 2 in R,G & B
202
203 for (int pixelcount = 0; pixelcount < numPixVals; pixelcount++)
204 {
205 XColor matching_color;
206 matching_color.pixel = pixelcount;
207 XQueryColor(display,cmap,&matching_color);
208
209 int delta_red = red - (matching_color.red >> 8);
210 int delta_green = green - (matching_color.green >> 8);
211 int delta_blue = blue - (matching_color.blue >> 8);
212
213 int dist = delta_red * delta_red +
214 delta_green * delta_green +
215 delta_blue * delta_blue;
216
217 if (dist <= threshold)
218 {
219 // try to allocate a read-only colour...
220 if (XAllocColor (display, cmap, &matching_color))
221 {
222 return matching_color.pixel;
223 }
224 }
225 if (dist < mindist)
226 {
227 bestpixel = pixelcount;
228 mindist = dist;
229 }
230 }
231 return bestpixel;
232}