xref: /haiku/src/servers/app/SystemPalette.cpp (revision fef6144999c2fa611f59ee6ffe6dd7999501385c)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2005, Haiku, Inc.
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		SystemPalette.cpp
23 //	Authors:		DarkWyrm <bpmagic@columbus.rr.com>
24 //					Stefano Ceccherini <burton666@libero.it>
25 //	Description:	Methods to initialize and get the system color_map.
26 //
27 //------------------------------------------------------------------------------
28 #include <stdio.h>
29 
30 #include <SystemPalette.h>
31 
32 const static rgb_color kSystemPalette[] = {
33  {   0,   0,   0, 255 }, {   8,   8,   8, 255 }, {  16,  16,  16, 255 },
34  {  24,  24,  24, 255 }, {  32,  32,  32, 255 }, {  40,  40,  40, 255 },
35  {  48,  48,  48, 255 }, {  56,  56,  56, 255 }, {  64,  64,  64, 255 },
36  {  72,  72,  72, 255 }, {  80,  80,  80, 255 }, {  88,  88,  88, 255 },
37  {  96,  96,  96, 255 }, { 104, 104, 104, 255 }, { 112, 112, 112, 255 },
38  { 120, 120, 120, 255 }, { 128, 128, 128, 255 }, { 136, 136, 136, 255 },
39  { 144, 144, 144, 255 }, { 152, 152, 152, 255 }, { 160, 160, 160, 255 },
40  { 168, 168, 168, 255 }, { 176, 176, 176, 255 }, { 184, 184, 184, 255 },
41  { 192, 192, 192, 255 }, { 200, 200, 200, 255 }, { 208, 208, 208, 255 },
42  { 216, 216, 216, 255 }, { 224, 224, 224, 255 }, { 232, 232, 232, 255 },
43  { 240, 240, 240, 255 }, { 248, 248, 248, 255 }, {   0,   0, 255, 255 },
44  {   0,   0, 229, 255 }, {   0,   0, 204, 255 }, {   0,   0, 179, 255 },
45  {   0,   0, 154, 255 }, {   0,   0, 129, 255 }, {   0,   0, 105, 255 },
46  {   0,   0,  80, 255 }, {   0,   0,  55, 255 }, {   0,   0,  30, 255 },
47  { 255,   0,   0, 255 }, { 228,   0,   0, 255 }, { 203,   0,   0, 255 },
48  { 178,   0,   0, 255 }, { 153,   0,   0, 255 }, { 128,   0,   0, 255 },
49  { 105,   0,   0, 255 }, {  80,   0,   0, 255 }, {  55,   0,   0, 255 },
50  {  30,   0,   0, 255 }, {   0, 255,   0, 255 }, {   0, 228,   0, 255 },
51  {   0, 203,   0, 255 }, {   0, 178,   0, 255 }, {   0, 153,   0, 255 },
52  {   0, 128,   0, 255 }, {   0, 105,   0, 255 }, {   0,  80,   0, 255 },
53  {   0,  55,   0, 255 }, {   0,  30,   0, 255 }, {   0, 152,  51, 255 },
54  { 255, 255, 255, 255 }, { 203, 255, 255, 255 }, { 203, 255, 203, 255 },
55  { 203, 255, 152, 255 }, { 203, 255, 102, 255 }, { 203, 255,  51, 255 },
56  { 203, 255,   0, 255 }, { 152, 255, 255, 255 }, { 152, 255, 203, 255 },
57  { 152, 255, 152, 255 }, { 152, 255, 102, 255 }, { 152, 255,  51, 255 },
58  { 152, 255,   0, 255 }, { 102, 255, 255, 255 }, { 102, 255, 203, 255 },
59  { 102, 255, 152, 255 }, { 102, 255, 102, 255 }, { 102, 255,  51, 255 },
60  { 102, 255,   0, 255 }, {  51, 255, 255, 255 }, {  51, 255, 203, 255 },
61  {  51, 255, 152, 255 }, {  51, 255, 102, 255 }, {  51, 255,  51, 255 },
62  {  51, 255,   0, 255 }, { 255, 152, 255, 255 }, { 255, 152, 203, 255 },
63  { 255, 152, 152, 255 }, { 255, 152, 102, 255 }, { 255, 152,  51, 255 },
64  { 255, 152,   0, 255 }, {   0, 102, 255, 255 }, {   0, 102, 203, 255 },
65  { 203, 203, 255, 255 }, { 203, 203, 203, 255 }, { 203, 203, 152, 255 },
66  { 203, 203, 102, 255 }, { 203, 203,  51, 255 }, { 203, 203,   0, 255 },
67  { 152, 203, 255, 255 }, { 152, 203, 203, 255 }, { 152, 203, 152, 255 },
68  { 152, 203, 102, 255 }, { 152, 203,  51, 255 }, { 152, 203,   0, 255 },
69  { 102, 203, 255, 255 }, { 102, 203, 203, 255 }, { 102, 203, 152, 255 },
70  { 102, 203, 102, 255 }, { 102, 203,  51, 255 }, { 102, 203,   0, 255 },
71  {  51, 203, 255, 255 }, {  51, 203, 203, 255 }, {  51, 203, 152, 255 },
72  {  51, 203, 102, 255 }, {  51, 203,  51, 255 }, {  51, 203,   0, 255 },
73  { 255, 102, 255, 255 }, { 255, 102, 203, 255 }, { 255, 102, 152, 255 },
74  { 255, 102, 102, 255 }, { 255, 102,  51, 255 }, { 255, 102,   0, 255 },
75  {   0, 102, 152, 255 }, {   0, 102, 102, 255 }, { 203, 152, 255, 255 },
76  { 203, 152, 203, 255 }, { 203, 152, 152, 255 }, { 203, 152, 102, 255 },
77  { 203, 152,  51, 255 }, { 203, 152,   0, 255 }, { 152, 152, 255, 255 },
78  { 152, 152, 203, 255 }, { 152, 152, 152, 255 }, { 152, 152, 102, 255 },
79  { 152, 152,  51, 255 }, { 152, 152,   0, 255 }, { 102, 152, 255, 255 },
80  { 102, 152, 203, 255 }, { 102, 152, 152, 255 }, { 102, 152, 102, 255 },
81  { 102, 152,  51, 255 }, { 102, 152,   0, 255 }, {  51, 152, 255, 255 },
82  {  51, 152, 203, 255 }, {  51, 152, 152, 255 }, {  51, 152, 102, 255 },
83  {  51, 152,  51, 255 }, {  51, 152,   0, 255 }, { 230, 134,   0, 255 },
84  { 255,  51, 203, 255 }, { 255,  51, 152, 255 }, { 255,  51, 102, 255 },
85  { 255,  51,  51, 255 }, { 255,  51,   0, 255 }, {   0, 102,  51, 255 },
86  {   0, 102,   0, 255 }, { 203, 102, 255, 255 }, { 203, 102, 203, 255 },
87  { 203, 102, 152, 255 }, { 203, 102, 102, 255 }, { 203, 102,  51, 255 },
88  { 203, 102,   0, 255 }, { 152, 102, 255, 255 }, { 152, 102, 203, 255 },
89  { 152, 102, 152, 255 }, { 152, 102, 102, 255 }, { 152, 102,  51, 255 },
90  { 152, 102,   0, 255 }, { 102, 102, 255, 255 }, { 102, 102, 203, 255 },
91  { 102, 102, 152, 255 }, { 102, 102, 102, 255 }, { 102, 102,  51, 255 },
92  { 102, 102,   0, 255 }, {  51, 102, 255, 255 }, {  51, 102, 203, 255 },
93  {  51, 102, 152, 255 }, {  51, 102, 102, 255 }, {  51, 102,  51, 255 },
94  {  51, 102,   0, 255 }, { 255,   0, 255, 255 }, { 255,   0, 203, 255 },
95  { 255,   0, 152, 255 }, { 255,   0, 102, 255 }, { 255,   0,  51, 255 },
96  { 255, 175,  19, 255 }, {   0,  51, 255, 255 }, {   0,  51, 203, 255 },
97  { 203,  51, 255, 255 }, { 203,  51, 203, 255 }, { 203,  51, 152, 255 },
98  { 203,  51, 102, 255 }, { 203,  51,  51, 255 }, { 203,  51,   0, 255 },
99  { 152,  51, 255, 255 }, { 152,  51, 203, 255 }, { 152,  51, 152, 255 },
100  { 152,  51, 102, 255 }, { 152,  51,  51, 255 }, { 152,  51,   0, 255 },
101  { 102,  51, 255, 255 }, { 102,  51, 203, 255 }, { 102,  51, 152, 255 },
102  { 102,  51, 102, 255 }, { 102,  51,  51, 255 }, { 102,  51,   0, 255 },
103  {  51,  51, 255, 255 }, {  51,  51, 203, 255 }, {  51,  51, 152, 255 },
104  {  51,  51, 102, 255 }, {  51,  51,  51, 255 }, {  51,  51,   0, 255 },
105  { 255, 203, 102, 255 }, { 255, 203, 152, 255 }, { 255, 203, 203, 255 },
106  { 255, 203, 255, 255 }, {   0,  51, 152, 255 }, {   0,  51, 102, 255 },
107  {   0,  51,  51, 255 }, {   0,  51,   0, 255 }, { 203,   0, 255, 255 },
108  { 203,   0, 203, 255 }, { 203,   0, 152, 255 }, { 203,   0, 102, 255 },
109  { 203,   0,  51, 255 }, { 255, 227,  70, 255 }, { 152,   0, 255, 255 },
110  { 152,   0, 203, 255 }, { 152,   0, 152, 255 }, { 152,   0, 102, 255 },
111  { 152,   0,  51, 255 }, { 152,   0,   0, 255 }, { 102,   0, 255, 255 },
112  { 102,   0, 203, 255 }, { 102,   0, 152, 255 }, { 102,   0, 102, 255 },
113  { 102,   0,  51, 255 }, { 102,   0,   0, 255 }, {  51,   0, 255, 255 },
114  {  51,   0, 203, 255 }, {  51,   0, 152, 255 }, {  51,   0, 102, 255 },
115  {  51,   0,  51, 255 }, {  51,   0,   0, 255 }, { 255, 203,  51, 255 },
116  { 255, 203,   0, 255 }, { 255, 255,   0, 255 }, { 255, 255,  51, 255 },
117  { 255, 255, 102, 255 }, { 255, 255, 152, 255 }, { 255, 255, 203, 255 },
118  { 255, 255, 255, 0 } // B_TRANSPARENT_MAGIC_CMAP8
119 };
120 
121 
122 // TODO: BWindowScreen has a method to set the palette.
123 // maybe we should have a lock to protect this variable.
124 static color_map sColorMap;
125 
126 
127 // color_distance
128 /*!	\brief Returns the "distance" between two RGB colors.
129 
130 	This functions defines an metric on the RGB color space. The distance
131 	between two colors is 0, if and only if the colors are equal.
132 
133 	\param red1 Red component of the first color.
134 	\param green1 Green component of the first color.
135 	\param blue1 Blue component of the first color.
136 	\param red2 Red component of the second color.
137 	\param green2 Green component of the second color.
138 	\param blue2 Blue component of the second color.
139 	\return The distance between the given colors.
140 */
141 static inline
142 unsigned
143 color_distance(uint8 red1, uint8 green1, uint8 blue1,
144 			   uint8 red2, uint8 green2, uint8 blue2)
145 {
146 	int rd = (int)red1 - (int)red2;
147 	int gd = (int)green1 - (int)green2;
148 	int bd = (int)blue1 - (int)blue2;
149 
150 	// distance according to psycho-visual tests
151 	// algorithm taken from here:
152 	// http://www.stud.uni-hannover.de/~michaelt/juggle/Algorithms.pdf
153 	int rmean = ((int)red1 + (int)red2) / 2;
154 	return (((512 + rmean) * rd * rd) >> 8)
155 			+ 4 * gd * gd
156 			+ (((767 - rmean) * bd * bd) >> 8);
157 }
158 
159 
160 static inline uint8
161 FindClosestColor(const rgb_color &color, const rgb_color *palette)
162 {
163 	uint8 closestIndex = 0;
164 	unsigned closestDistance = UINT_MAX;
165 	for (int32 i = 0; i < 256; i++) {
166 		const rgb_color &c = palette[i];
167 		unsigned distance = color_distance(color.red, color.green, color.blue,
168 										   c.red, c.green, c.blue);
169 		if (distance < closestDistance) {
170 			closestIndex = (uint8)i;
171 			closestDistance = distance;
172 		}
173 	}
174 	return closestIndex;
175 }
176 
177 
178 static inline rgb_color
179 InvertColor(const rgb_color &color)
180 {
181 	// For some reason, Inverting (255, 255, 255) on beos
182 	// results in the same color.
183 	if (color.red == 255 && color.green == 255
184 		&& color.blue == 255)
185 		return color;
186 
187 	rgb_color inverted;
188 	inverted.red = 255 - color.red;
189 	inverted.green = 255 - color.green;
190 	inverted.blue = 255 - color.blue;
191 	inverted.alpha = 255;
192 
193 	return inverted;
194 }
195 
196 
197 static void
198 FillColorMap(const rgb_color *palette, color_map *map)
199 {
200 	memcpy(map->color_list, palette, sizeof(map->color_list));
201 
202 	// init index map
203 	for (int32 color = 0; color < 32768; color++) {
204 		// get components
205 		rgb_color rgbColor;
206 		rgbColor.red = (color & 0x7c00) >> 7;
207 		rgbColor.green = (color & 0x3e0) >> 2;
208 		rgbColor.blue = (color & 0x1f) << 3;
209 
210 		map->index_map[color] = FindClosestColor(rgbColor, palette);
211 	}
212 
213 	// init inversion map
214 	for (int32 index = 0; index < 256; index++) {
215 		rgb_color inverted = InvertColor(map->color_list[index]);
216 		map->inversion_map[index] = FindClosestColor(inverted, palette);
217 	}
218 }
219 
220 
221 /*!	\brief Initializes the system color_map.
222 */
223 void
224 InitializeColorMap()
225 {
226 	FillColorMap(kSystemPalette, &sColorMap);
227 }
228 
229 
230 /*!	\brief Returns a pointer to the system palette.
231 	\return A pointer to the system palette.
232 */
233 const rgb_color *
234 SystemPalette()
235 {
236 	return sColorMap.color_list;
237 }
238 
239 
240 /*!	\brief Returns a pointer to the system color_map structure.
241 	\return A pointer to the system color_map.
242 */
243 const color_map *
244 SystemColorMap()
245 {
246 	return &sColorMap;
247 }
248