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