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