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