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