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