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