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