]> git.saurik.com Git - wxWidgets.git/blame - src/motif/colour.cpp
Added wxRenderer method for drawing selection
[wxWidgets.git] / src / motif / colour.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
55034339 2// Name: src/motif/colour.cpp
4bb6408c
JS
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
55034339 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
dfc54541
JS
12//// TODO: make wxColour a ref-counted object,
13//// so pixel values get shared.
14
1248b41f
MB
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
4bb6408c 18#include "wx/colour.h"
40989e46
WS
19
20#include "wx/gdicmn.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 46wxColour::wxColour(const wxColour& col)
4bb6408c 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
aad6765c 61wxColour::~wxColour()
4bb6408c
JS
62{
63}
64
40989e46 65void wxColour::InitWith(unsigned char r, unsigned char g, unsigned char b)
4bb6408c
JS
66{
67 m_red = r;
68 m_green = g;
69 m_blue = b;
aad6765c 70 m_isInit = true;
e97f20a0 71 m_pixel = -1;
4bb6408c 72}
dfc54541
JS
73
74// Allocate a colour, or nearest colour, using the given display.
aad6765c 75// If realloc is true, ignore the existing pixel, otherwise just return
dfc54541 76// the existing one.
16c1f7f3 77// Returns the old or allocated pixel.
dfc54541
JS
78
79// TODO: can this handle mono displays? If not, we should have an extra
80// flag to specify whether this should be black or white by default.
81
16c1f7f3 82int wxColour::AllocColour(WXDisplay* display, bool realloc)
dfc54541
JS
83{
84 if ((m_pixel != -1) && !realloc)
2d120f83 85 return m_pixel;
aad6765c 86
dfc54541
JS
87 XColor color;
88 color.red = (unsigned short) Red ();
55034339 89 color.red |= (unsigned short)(color.red << 8);
dfc54541 90 color.green = (unsigned short) Green ();
55034339 91 color.green |= (unsigned short)(color.green << 8);
dfc54541 92 color.blue = (unsigned short) Blue ();
55034339 93 color.blue |= (unsigned short)(color.blue << 8);
aad6765c 94
dfc54541 95 color.flags = DoRed | DoGreen | DoBlue;
aad6765c 96
dfc54541 97 WXColormap cmap = wxTheApp->GetMainColormap(display);
aad6765c 98
dfc54541
JS
99 if (!XAllocColor ((Display*) display, (Colormap) cmap, &color))
100 {
2d120f83
JS
101 m_pixel = wxGetBestMatchingPixel((Display*) display, &color,(Colormap) cmap);
102 return m_pixel;
dfc54541
JS
103 }
104 else
105 {
2d120f83
JS
106 m_pixel = (int) color.pixel;
107 return m_pixel;
dfc54541
JS
108 }
109}
110
111/*-------------------------------------------
112Markus Emmenegger <mege@iqe.ethz.ch>
113Find the pixel value with an assigned color closest to the desired color
114Used if color cell allocation fails
115As the returned pixel value may be in use by another application,
116the color might change anytime.
117But in many cases, that is still better than always using black.
118--
119Chris Breeze <chris@hel.co.uk>
120Improvements:
1211) More efficient calculation of RGB distance of colour cell from
2d120f83
JS
122the desired colour. There is no need to take the sqrt of 'dist', and
123since we are only interested in the top 8-bits of R, G and B we
124can perform integer arithmetic.
dfc54541 1252) Attempt to allocate a read-only colour when a close match is found.
2d120f83 126A read-only colour will not change.
dfc54541
JS
1273) Fall back to the closest match if no read-only colours are available.
128
2d120f83
JS
129 Possible further improvements:
130 1) Scan the lookup table and sort the colour cells in order of
131 increasing
132 distance from the desired colour. Then attempt to allocate a
133 read-only
134 colour starting from the nearest match.
135 2) Linear RGB distance is not a particularly good method of colour
136 matching
137 (though it is quick). Converting the colour to HLS and then comparing
138 may give better matching.
dfc54541
JS
139-------------------------------------------*/
140
141int wxGetBestMatchingPixel(Display *display, XColor *desiredColor, Colormap cmap)
142{
143 if (cmap == (Colormap) NULL)
2d120f83 144 cmap = (Colormap) wxTheApp->GetMainColormap(display);
aad6765c 145
dfc54541
JS
146 int numPixVals = XDisplayCells(display, DefaultScreen (display));
147 int mindist = 256 * 256 * 3;
148 int bestpixel = (int) BlackPixel (display, DefaultScreen (display));
149 int red = desiredColor->red >> 8;
150 int green = desiredColor->green >> 8;
151 int blue = desiredColor->blue >> 8;
152 const int threshold = 2 * 2 * 3; // allow an error of up to 2 in R,G & B
aad6765c 153
dfc54541
JS
154 for (int pixelcount = 0; pixelcount < numPixVals; pixelcount++)
155 {
156 XColor matching_color;
157 matching_color.pixel = pixelcount;
158 XQueryColor(display,cmap,&matching_color);
aad6765c 159
dfc54541
JS
160 int delta_red = red - (matching_color.red >> 8);
161 int delta_green = green - (matching_color.green >> 8);
162 int delta_blue = blue - (matching_color.blue >> 8);
aad6765c 163
dfc54541 164 int dist = delta_red * delta_red +
2d120f83
JS
165 delta_green * delta_green +
166 delta_blue * delta_blue;
aad6765c 167
dfc54541
JS
168 if (dist <= threshold)
169 {
170 // try to allocate a read-only colour...
171 if (XAllocColor (display, cmap, &matching_color))
172 {
173 return matching_color.pixel;
174 }
175 }
176 if (dist < mindist)
177 {
178 bestpixel = pixelcount;
179 mindist = dist;
180 }
181 }
182 return bestpixel;
183}