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