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