]> git.saurik.com Git - wxWidgets.git/blame - src/motif/colour.cpp
wxRTC doc updates
[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 19
670f9935
WS
20#ifndef WX_PRECOMP
21 #include "wx/app.h"
dd05139a 22 #include "wx/gdicmn.h"
670f9935
WS
23#endif
24
338dd992
JJ
25#ifdef __VMS__
26#pragma message disable nosimpint
27#endif
dfc54541 28#include <Xm/Xm.h>
338dd992
JJ
29#ifdef __VMS__
30#pragma message enable nosimpint
31#endif
dfc54541
JS
32
33#include "wx/motif/private.h"
4bb6408c 34
3e0071d9
MB
35wxCOMPILE_TIME_ASSERT( sizeof(WXPixel) == sizeof(Pixel), PixelSizeIsOk );
36
4bb6408c
JS
37// Colour
38
aad6765c 39void wxColour::Init()
4bb6408c 40{
aad6765c 41 m_isInit = false;
3e0071d9 42 m_red = m_blue = 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
aea95b1c
VZ
65void wxColour::InitRGBA(unsigned char r, unsigned char g, unsigned char b,
66 unsigned char WXUNUSED(a))
4bb6408c
JS
67{
68 m_red = r;
69 m_green = g;
70 m_blue = b;
aad6765c 71 m_isInit = true;
e97f20a0 72 m_pixel = -1;
4bb6408c 73}
dfc54541
JS
74
75// Allocate a colour, or nearest colour, using the given display.
aad6765c 76// If realloc is true, ignore the existing pixel, otherwise just return
dfc54541 77// the existing one.
16c1f7f3 78// Returns the old or allocated pixel.
dfc54541
JS
79
80// TODO: can this handle mono displays? If not, we should have an extra
81// flag to specify whether this should be black or white by default.
82
3e0071d9 83WXPixel wxColour::AllocColour(WXDisplay* display, bool realloc)
dfc54541
JS
84{
85 if ((m_pixel != -1) && !realloc)
2d120f83 86 return m_pixel;
aad6765c 87
dfc54541
JS
88 XColor color;
89 color.red = (unsigned short) Red ();
55034339 90 color.red |= (unsigned short)(color.red << 8);
dfc54541 91 color.green = (unsigned short) Green ();
55034339 92 color.green |= (unsigned short)(color.green << 8);
dfc54541 93 color.blue = (unsigned short) Blue ();
55034339 94 color.blue |= (unsigned short)(color.blue << 8);
aad6765c 95
dfc54541 96 color.flags = DoRed | DoGreen | DoBlue;
aad6765c 97
dfc54541 98 WXColormap cmap = wxTheApp->GetMainColormap(display);
aad6765c 99
dfc54541
JS
100 if (!XAllocColor ((Display*) display, (Colormap) cmap, &color))
101 {
2d120f83
JS
102 m_pixel = wxGetBestMatchingPixel((Display*) display, &color,(Colormap) cmap);
103 return m_pixel;
dfc54541
JS
104 }
105 else
106 {
3e0071d9 107 m_pixel = (WXPixel) color.pixel;
2d120f83 108 return m_pixel;
dfc54541
JS
109 }
110}
111
112/*-------------------------------------------
113Markus Emmenegger <mege@iqe.ethz.ch>
114Find the pixel value with an assigned color closest to the desired color
115Used if color cell allocation fails
116As the returned pixel value may be in use by another application,
117the color might change anytime.
118But in many cases, that is still better than always using black.
119--
120Chris Breeze <chris@hel.co.uk>
121Improvements:
1221) More efficient calculation of RGB distance of colour cell from
2d120f83
JS
123the desired colour. There is no need to take the sqrt of 'dist', and
124since we are only interested in the top 8-bits of R, G and B we
125can perform integer arithmetic.
dfc54541 1262) Attempt to allocate a read-only colour when a close match is found.
2d120f83 127A read-only colour will not change.
dfc54541
JS
1283) Fall back to the closest match if no read-only colours are available.
129
2d120f83
JS
130 Possible further improvements:
131 1) Scan the lookup table and sort the colour cells in order of
132 increasing
133 distance from the desired colour. Then attempt to allocate a
134 read-only
135 colour starting from the nearest match.
136 2) Linear RGB distance is not a particularly good method of colour
137 matching
138 (though it is quick). Converting the colour to HLS and then comparing
139 may give better matching.
dfc54541
JS
140-------------------------------------------*/
141
3e0071d9 142WXPixel wxGetBestMatchingPixel(Display *display, XColor *desiredColor, Colormap cmap)
dfc54541
JS
143{
144 if (cmap == (Colormap) NULL)
2d120f83 145 cmap = (Colormap) wxTheApp->GetMainColormap(display);
aad6765c 146
dfc54541
JS
147 int numPixVals = XDisplayCells(display, DefaultScreen (display));
148 int mindist = 256 * 256 * 3;
3e0071d9 149 Pixel bestpixel = BlackPixel (display, DefaultScreen (display));
dfc54541
JS
150 int red = desiredColor->red >> 8;
151 int green = desiredColor->green >> 8;
152 int blue = desiredColor->blue >> 8;
153 const int threshold = 2 * 2 * 3; // allow an error of up to 2 in R,G & B
aad6765c 154
dfc54541
JS
155 for (int pixelcount = 0; pixelcount < numPixVals; pixelcount++)
156 {
157 XColor matching_color;
158 matching_color.pixel = pixelcount;
159 XQueryColor(display,cmap,&matching_color);
aad6765c 160
dfc54541
JS
161 int delta_red = red - (matching_color.red >> 8);
162 int delta_green = green - (matching_color.green >> 8);
163 int delta_blue = blue - (matching_color.blue >> 8);
aad6765c 164
dfc54541 165 int dist = delta_red * delta_red +
2d120f83
JS
166 delta_green * delta_green +
167 delta_blue * delta_blue;
aad6765c 168
dfc54541
JS
169 if (dist <= threshold)
170 {
171 // try to allocate a read-only colour...
172 if (XAllocColor (display, cmap, &matching_color))
173 {
174 return matching_color.pixel;
175 }
176 }
177 if (dist < mindist)
178 {
179 bestpixel = pixelcount;
180 mindist = dist;
181 }
182 }
183 return bestpixel;
184}