xref: /haiku/src/servers/app/SystemPalette.cpp (revision 5412911f7f8ca41340b0f5cb928ed9726322ab44)
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 #include <string.h>
30 
31 #include <SystemPalette.h>
32 
33 const static rgb_color kSystemPalette[] = {
34  {   0,   0,   0, 255 }, {   8,   8,   8, 255 }, {  16,  16,  16, 255 },
35  {  24,  24,  24, 255 }, {  32,  32,  32, 255 }, {  40,  40,  40, 255 },
36  {  48,  48,  48, 255 }, {  56,  56,  56, 255 }, {  64,  64,  64, 255 },
37  {  72,  72,  72, 255 }, {  80,  80,  80, 255 }, {  88,  88,  88, 255 },
38  {  96,  96,  96, 255 }, { 104, 104, 104, 255 }, { 112, 112, 112, 255 },
39  { 120, 120, 120, 255 }, { 128, 128, 128, 255 }, { 136, 136, 136, 255 },
40  { 144, 144, 144, 255 }, { 152, 152, 152, 255 }, { 160, 160, 160, 255 },
41  { 168, 168, 168, 255 }, { 176, 176, 176, 255 }, { 184, 184, 184, 255 },
42  { 192, 192, 192, 255 }, { 200, 200, 200, 255 }, { 208, 208, 208, 255 },
43  { 216, 216, 216, 255 }, { 224, 224, 224, 255 }, { 232, 232, 232, 255 },
44  { 240, 240, 240, 255 }, { 248, 248, 248, 255 }, {   0,   0, 255, 255 },
45  {   0,   0, 229, 255 }, {   0,   0, 204, 255 }, {   0,   0, 179, 255 },
46  {   0,   0, 154, 255 }, {   0,   0, 129, 255 }, {   0,   0, 105, 255 },
47  {   0,   0,  80, 255 }, {   0,   0,  55, 255 }, {   0,   0,  30, 255 },
48  { 255,   0,   0, 255 }, { 228,   0,   0, 255 }, { 203,   0,   0, 255 },
49  { 178,   0,   0, 255 }, { 153,   0,   0, 255 }, { 128,   0,   0, 255 },
50  { 105,   0,   0, 255 }, {  80,   0,   0, 255 }, {  55,   0,   0, 255 },
51  {  30,   0,   0, 255 }, {   0, 255,   0, 255 }, {   0, 228,   0, 255 },
52  {   0, 203,   0, 255 }, {   0, 178,   0, 255 }, {   0, 153,   0, 255 },
53  {   0, 128,   0, 255 }, {   0, 105,   0, 255 }, {   0,  80,   0, 255 },
54  {   0,  55,   0, 255 }, {   0,  30,   0, 255 }, {   0, 152,  51, 255 },
55  { 255, 255, 255, 255 }, { 203, 255, 255, 255 }, { 203, 255, 203, 255 },
56  { 203, 255, 152, 255 }, { 203, 255, 102, 255 }, { 203, 255,  51, 255 },
57  { 203, 255,   0, 255 }, { 152, 255, 255, 255 }, { 152, 255, 203, 255 },
58  { 152, 255, 152, 255 }, { 152, 255, 102, 255 }, { 152, 255,  51, 255 },
59  { 152, 255,   0, 255 }, { 102, 255, 255, 255 }, { 102, 255, 203, 255 },
60  { 102, 255, 152, 255 }, { 102, 255, 102, 255 }, { 102, 255,  51, 255 },
61  { 102, 255,   0, 255 }, {  51, 255, 255, 255 }, {  51, 255, 203, 255 },
62  {  51, 255, 152, 255 }, {  51, 255, 102, 255 }, {  51, 255,  51, 255 },
63  {  51, 255,   0, 255 }, { 255, 152, 255, 255 }, { 255, 152, 203, 255 },
64  { 255, 152, 152, 255 }, { 255, 152, 102, 255 }, { 255, 152,  51, 255 },
65  { 255, 152,   0, 255 }, {   0, 102, 255, 255 }, {   0, 102, 203, 255 },
66  { 203, 203, 255, 255 }, { 203, 203, 203, 255 }, { 203, 203, 152, 255 },
67  { 203, 203, 102, 255 }, { 203, 203,  51, 255 }, { 203, 203,   0, 255 },
68  { 152, 203, 255, 255 }, { 152, 203, 203, 255 }, { 152, 203, 152, 255 },
69  { 152, 203, 102, 255 }, { 152, 203,  51, 255 }, { 152, 203,   0, 255 },
70  { 102, 203, 255, 255 }, { 102, 203, 203, 255 }, { 102, 203, 152, 255 },
71  { 102, 203, 102, 255 }, { 102, 203,  51, 255 }, { 102, 203,   0, 255 },
72  {  51, 203, 255, 255 }, {  51, 203, 203, 255 }, {  51, 203, 152, 255 },
73  {  51, 203, 102, 255 }, {  51, 203,  51, 255 }, {  51, 203,   0, 255 },
74  { 255, 102, 255, 255 }, { 255, 102, 203, 255 }, { 255, 102, 152, 255 },
75  { 255, 102, 102, 255 }, { 255, 102,  51, 255 }, { 255, 102,   0, 255 },
76  {   0, 102, 152, 255 }, {   0, 102, 102, 255 }, { 203, 152, 255, 255 },
77  { 203, 152, 203, 255 }, { 203, 152, 152, 255 }, { 203, 152, 102, 255 },
78  { 203, 152,  51, 255 }, { 203, 152,   0, 255 }, { 152, 152, 255, 255 },
79  { 152, 152, 203, 255 }, { 152, 152, 152, 255 }, { 152, 152, 102, 255 },
80  { 152, 152,  51, 255 }, { 152, 152,   0, 255 }, { 102, 152, 255, 255 },
81  { 102, 152, 203, 255 }, { 102, 152, 152, 255 }, { 102, 152, 102, 255 },
82  { 102, 152,  51, 255 }, { 102, 152,   0, 255 }, {  51, 152, 255, 255 },
83  {  51, 152, 203, 255 }, {  51, 152, 152, 255 }, {  51, 152, 102, 255 },
84  {  51, 152,  51, 255 }, {  51, 152,   0, 255 }, { 230, 134,   0, 255 },
85  { 255,  51, 203, 255 }, { 255,  51, 152, 255 }, { 255,  51, 102, 255 },
86  { 255,  51,  51, 255 }, { 255,  51,   0, 255 }, {   0, 102,  51, 255 },
87  {   0, 102,   0, 255 }, { 203, 102, 255, 255 }, { 203, 102, 203, 255 },
88  { 203, 102, 152, 255 }, { 203, 102, 102, 255 }, { 203, 102,  51, 255 },
89  { 203, 102,   0, 255 }, { 152, 102, 255, 255 }, { 152, 102, 203, 255 },
90  { 152, 102, 152, 255 }, { 152, 102, 102, 255 }, { 152, 102,  51, 255 },
91  { 152, 102,   0, 255 }, { 102, 102, 255, 255 }, { 102, 102, 203, 255 },
92  { 102, 102, 152, 255 }, { 102, 102, 102, 255 }, { 102, 102,  51, 255 },
93  { 102, 102,   0, 255 }, {  51, 102, 255, 255 }, {  51, 102, 203, 255 },
94  {  51, 102, 152, 255 }, {  51, 102, 102, 255 }, {  51, 102,  51, 255 },
95  {  51, 102,   0, 255 }, { 255,   0, 255, 255 }, { 255,   0, 203, 255 },
96  { 255,   0, 152, 255 }, { 255,   0, 102, 255 }, { 255,   0,  51, 255 },
97  { 255, 175,  19, 255 }, {   0,  51, 255, 255 }, {   0,  51, 203, 255 },
98  { 203,  51, 255, 255 }, { 203,  51, 203, 255 }, { 203,  51, 152, 255 },
99  { 203,  51, 102, 255 }, { 203,  51,  51, 255 }, { 203,  51,   0, 255 },
100  { 152,  51, 255, 255 }, { 152,  51, 203, 255 }, { 152,  51, 152, 255 },
101  { 152,  51, 102, 255 }, { 152,  51,  51, 255 }, { 152,  51,   0, 255 },
102  { 102,  51, 255, 255 }, { 102,  51, 203, 255 }, { 102,  51, 152, 255 },
103  { 102,  51, 102, 255 }, { 102,  51,  51, 255 }, { 102,  51,   0, 255 },
104  {  51,  51, 255, 255 }, {  51,  51, 203, 255 }, {  51,  51, 152, 255 },
105  {  51,  51, 102, 255 }, {  51,  51,  51, 255 }, {  51,  51,   0, 255 },
106  { 255, 203, 102, 255 }, { 255, 203, 152, 255 }, { 255, 203, 203, 255 },
107  { 255, 203, 255, 255 }, {   0,  51, 152, 255 }, {   0,  51, 102, 255 },
108  {   0,  51,  51, 255 }, {   0,  51,   0, 255 }, { 203,   0, 255, 255 },
109  { 203,   0, 203, 255 }, { 203,   0, 152, 255 }, { 203,   0, 102, 255 },
110  { 203,   0,  51, 255 }, { 255, 227,  70, 255 }, { 152,   0, 255, 255 },
111  { 152,   0, 203, 255 }, { 152,   0, 152, 255 }, { 152,   0, 102, 255 },
112  { 152,   0,  51, 255 }, { 152,   0,   0, 255 }, { 102,   0, 255, 255 },
113  { 102,   0, 203, 255 }, { 102,   0, 152, 255 }, { 102,   0, 102, 255 },
114  { 102,   0,  51, 255 }, { 102,   0,   0, 255 }, {  51,   0, 255, 255 },
115  {  51,   0, 203, 255 }, {  51,   0, 152, 255 }, {  51,   0, 102, 255 },
116  {  51,   0,  51, 255 }, {  51,   0,   0, 255 }, { 255, 203,  51, 255 },
117  { 255, 203,   0, 255 }, { 255, 255,   0, 255 }, { 255, 255,  51, 255 },
118  { 255, 255, 102, 255 }, { 255, 255, 152, 255 }, { 255, 255, 203, 255 },
119  { 255, 255, 255, 0 } // B_TRANSPARENT_MAGIC_CMAP8
120 };
121 
122 
123 // TODO: BWindowScreen has a method to set the palette.
124 // maybe we should have a lock to protect this variable.
125 static color_map sColorMap;
126 
127 
128 // color_distance
129 /*!	\brief Returns the "distance" between two RGB colors.
130 
131 	This functions defines an metric on the RGB color space. The distance
132 	between two colors is 0, if and only if the colors are equal.
133 
134 	\param red1 Red component of the first color.
135 	\param green1 Green component of the first color.
136 	\param blue1 Blue component of the first color.
137 	\param red2 Red component of the second color.
138 	\param green2 Green component of the second color.
139 	\param blue2 Blue component of the second color.
140 	\return The distance between the given colors.
141 */
142 static inline
143 unsigned
144 color_distance(uint8 red1, uint8 green1, uint8 blue1,
145 			   uint8 red2, uint8 green2, uint8 blue2)
146 {
147 	int rd = (int)red1 - (int)red2;
148 	int gd = (int)green1 - (int)green2;
149 	int bd = (int)blue1 - (int)blue2;
150 
151 	// distance according to psycho-visual tests
152 	// algorithm taken from here:
153 	// http://www.stud.uni-hannover.de/~michaelt/juggle/Algorithms.pdf
154 	int rmean = ((int)red1 + (int)red2) / 2;
155 	return (((512 + rmean) * rd * rd) >> 8)
156 			+ 4 * gd * gd
157 			+ (((767 - rmean) * bd * bd) >> 8);
158 }
159 
160 
161 static inline uint8
162 FindClosestColor(const rgb_color &color, const rgb_color *palette)
163 {
164 	uint8 closestIndex = 0;
165 	unsigned closestDistance = UINT_MAX;
166 	for (int32 i = 0; i < 256; i++) {
167 		const rgb_color &c = palette[i];
168 		unsigned distance = color_distance(color.red, color.green, color.blue,
169 										   c.red, c.green, c.blue);
170 		if (distance < closestDistance) {
171 			closestIndex = (uint8)i;
172 			closestDistance = distance;
173 		}
174 	}
175 	return closestIndex;
176 }
177 
178 
179 static inline rgb_color
180 InvertColor(const rgb_color &color)
181 {
182 	// For some reason, Inverting (255, 255, 255) on beos
183 	// results in the same color.
184 	if (color.red == 255 && color.green == 255
185 		&& color.blue == 255)
186 		return color;
187 
188 	rgb_color inverted;
189 	inverted.red = 255 - color.red;
190 	inverted.green = 255 - color.green;
191 	inverted.blue = 255 - color.blue;
192 	inverted.alpha = 255;
193 
194 	return inverted;
195 }
196 
197 
198 static void
199 FillColorMap(const rgb_color *palette, color_map *map)
200 {
201 	memcpy(map->color_list, palette, sizeof(map->color_list));
202 
203 	// init index map
204 	for (int32 color = 0; color < 32768; color++) {
205 		// get components
206 		rgb_color rgbColor;
207 		rgbColor.red = (color & 0x7c00) >> 7;
208 		rgbColor.green = (color & 0x3e0) >> 2;
209 		rgbColor.blue = (color & 0x1f) << 3;
210 
211 		map->index_map[color] = FindClosestColor(rgbColor, palette);
212 	}
213 
214 	// init inversion map
215 	for (int32 index = 0; index < 256; index++) {
216 		rgb_color inverted = InvertColor(map->color_list[index]);
217 		map->inversion_map[index] = FindClosestColor(inverted, palette);
218 	}
219 }
220 
221 
222 /*!	\brief Initializes the system color_map.
223 */
224 void
225 InitializeColorMap()
226 {
227 	FillColorMap(kSystemPalette, &sColorMap);
228 }
229 
230 
231 /*!	\brief Returns a pointer to the system palette.
232 	\return A pointer to the system palette.
233 */
234 const rgb_color *
235 SystemPalette()
236 {
237 	return sColorMap.color_list;
238 }
239 
240 
241 /*!	\brief Returns a pointer to the system color_map structure.
242 	\return A pointer to the system color_map.
243 */
244 const color_map *
245 SystemColorMap()
246 {
247 	return &sColorMap;
248 }
249