]> git.saurik.com Git - wxWidgets.git/blame - src/motif/colour.cpp
Someone need to make the clientdata be void* instead of this char*
[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{
2d120f83
JS
60 m_red = col.m_red;
61 m_green = col.m_green;
62 m_blue = col.m_blue;
63 m_isInit = col.m_isInit;
64 m_pixel = col.m_pixel;
65 return *this;
4bb6408c
JS
66}
67
e4a81a2e 68void wxColour::InitFromName(const wxString& col)
4bb6408c
JS
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
4bb6408c
JS
92void wxColour::Set (unsigned char r, unsigned char g, unsigned char b)
93{
94 m_red = r;
95 m_green = g;
96 m_blue = b;
97 m_isInit = TRUE;
e97f20a0 98 m_pixel = -1;
4bb6408c 99}
dfc54541
JS
100
101// Allocate a colour, or nearest colour, using the given display.
102// If realloc is TRUE, ignore the existing pixel, otherwise just return
103// the existing one.
16c1f7f3 104// Returns the old or allocated pixel.
dfc54541
JS
105
106// TODO: can this handle mono displays? If not, we should have an extra
107// flag to specify whether this should be black or white by default.
108
16c1f7f3 109int wxColour::AllocColour(WXDisplay* display, bool realloc)
dfc54541
JS
110{
111 if ((m_pixel != -1) && !realloc)
2d120f83
JS
112 return m_pixel;
113
dfc54541
JS
114 XColor color;
115 color.red = (unsigned short) Red ();
116 color.red |= color.red << 8;
117 color.green = (unsigned short) Green ();
118 color.green |= color.green << 8;
119 color.blue = (unsigned short) Blue ();
120 color.blue |= color.blue << 8;
2d120f83 121
dfc54541 122 color.flags = DoRed | DoGreen | DoBlue;
2d120f83 123
dfc54541 124 WXColormap cmap = wxTheApp->GetMainColormap(display);
2d120f83 125
dfc54541
JS
126 if (!XAllocColor ((Display*) display, (Colormap) cmap, &color))
127 {
2d120f83
JS
128 m_pixel = wxGetBestMatchingPixel((Display*) display, &color,(Colormap) cmap);
129 return m_pixel;
dfc54541
JS
130 }
131 else
132 {
2d120f83
JS
133 m_pixel = (int) color.pixel;
134 return m_pixel;
dfc54541
JS
135 }
136}
137
138/*-------------------------------------------
139Markus Emmenegger <mege@iqe.ethz.ch>
140Find the pixel value with an assigned color closest to the desired color
141Used if color cell allocation fails
142As the returned pixel value may be in use by another application,
143the color might change anytime.
144But in many cases, that is still better than always using black.
145--
146Chris Breeze <chris@hel.co.uk>
147Improvements:
1481) More efficient calculation of RGB distance of colour cell from
2d120f83
JS
149the desired colour. There is no need to take the sqrt of 'dist', and
150since we are only interested in the top 8-bits of R, G and B we
151can perform integer arithmetic.
dfc54541 1522) Attempt to allocate a read-only colour when a close match is found.
2d120f83 153A read-only colour will not change.
dfc54541
JS
1543) Fall back to the closest match if no read-only colours are available.
155
2d120f83
JS
156 Possible further improvements:
157 1) Scan the lookup table and sort the colour cells in order of
158 increasing
159 distance from the desired colour. Then attempt to allocate a
160 read-only
161 colour starting from the nearest match.
162 2) Linear RGB distance is not a particularly good method of colour
163 matching
164 (though it is quick). Converting the colour to HLS and then comparing
165 may give better matching.
dfc54541
JS
166-------------------------------------------*/
167
168int wxGetBestMatchingPixel(Display *display, XColor *desiredColor, Colormap cmap)
169{
170 if (cmap == (Colormap) NULL)
2d120f83
JS
171 cmap = (Colormap) wxTheApp->GetMainColormap(display);
172
dfc54541
JS
173 int numPixVals = XDisplayCells(display, DefaultScreen (display));
174 int mindist = 256 * 256 * 3;
175 int bestpixel = (int) BlackPixel (display, DefaultScreen (display));
176 int red = desiredColor->red >> 8;
177 int green = desiredColor->green >> 8;
178 int blue = desiredColor->blue >> 8;
179 const int threshold = 2 * 2 * 3; // allow an error of up to 2 in R,G & B
2d120f83 180
dfc54541
JS
181 for (int pixelcount = 0; pixelcount < numPixVals; pixelcount++)
182 {
183 XColor matching_color;
184 matching_color.pixel = pixelcount;
185 XQueryColor(display,cmap,&matching_color);
2d120f83 186
dfc54541
JS
187 int delta_red = red - (matching_color.red >> 8);
188 int delta_green = green - (matching_color.green >> 8);
189 int delta_blue = blue - (matching_color.blue >> 8);
2d120f83 190
dfc54541 191 int dist = delta_red * delta_red +
2d120f83
JS
192 delta_green * delta_green +
193 delta_blue * delta_blue;
194
dfc54541
JS
195 if (dist <= threshold)
196 {
197 // try to allocate a read-only colour...
198 if (XAllocColor (display, cmap, &matching_color))
199 {
200 return matching_color.pixel;
201 }
202 }
203 if (dist < mindist)
204 {
205 bestpixel = pixelcount;
206 mindist = dist;
207 }
208 }
209 return bestpixel;
210}