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