Dillo v3.2.0-151-g90488cbf
Loading...
Searching...
No Matches
colors.c
Go to the documentation of this file.
1/*
2 * File: colors.c
3 *
4 * Copyright (C) 2000-2007 Jorge Arellano Cid <jcid@dillo.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <string.h>
13#include <stdlib.h>
14#include "colors.h"
15
16#include "msg.h"
17
18#include "dlib/dlib.h" /* dIsspace */
19
20/*
21 * If EXTENDED_COLOR is defined, the extended set of named colors is supported.
22 * These colors're not standard but they're supported in most browsers.
23 * NOTE: The colors MUST be in alphabetical order and lower case because the
24 * code uses a binary search.
25 */
26
27#define EXTENDED_COLOR
28
29static const struct key {
30 char *key;
31 int32_t val;
32} color_keyword [] = {
33#ifdef EXTENDED_COLOR
34 { "aliceblue", 0xf0f8ff},
35 { "antiquewhite", 0xfaebd7},
36#endif
37 { "aqua", 0x00ffff},
38#ifdef EXTENDED_COLOR
39 { "aquamarine", 0x7fffd4},
40 { "azure", 0xf0ffff},
41 { "beige", 0xf5f5dc},
42 { "bisque", 0xffe4c4},
43#endif
44 { "black", 0x000000},
45#ifdef EXTENDED_COLOR
46 { "blanchedalmond", 0xffebcd},
47#endif
48 {"blue", 0x0000ff},
49#ifdef EXTENDED_COLOR
50 { "blueviolet", 0x8a2be2},
51 { "brown", 0xa52a2a},
52 { "burlywood", 0xdeb887},
53 { "cadetblue", 0x5f9ea0},
54 { "chartreuse", 0x7fff00},
55 { "chocolate", 0xd2691e},
56 { "coral", 0xff7f50},
57 { "cornflowerblue", 0x6495ed},
58 { "cornsilk", 0xfff8dc},
59 { "crimson", 0xdc1436},
60 { "cyan", 0x00ffff},
61 { "darkblue", 0x00008b},
62 { "darkcyan", 0x008b8b},
63 { "darkgoldenrod", 0xb8860b},
64 { "darkgray", 0xa9a9a9},
65 { "darkgreen", 0x006400},
66 { "darkgrey", 0xa9a9a9},
67 { "darkkhaki", 0xbdb76b},
68 { "darkmagenta", 0x8b008b},
69 { "darkolivegreen", 0x556b2f},
70 { "darkorange", 0xff8c00},
71 { "darkorchid", 0x9932cc},
72 { "darkred", 0x8b0000},
73 { "darksalmon", 0xe9967a},
74 { "darkseagreen", 0x8fbc8f},
75 { "darkslateblue", 0x483d8b},
76 { "darkslategray", 0x2f4f4f},
77 { "darkslategrey", 0x2f4f4f},
78 { "darkturquoise", 0x00ced1},
79 { "darkviolet", 0x9400d3},
80 { "deeppink", 0xff1493},
81 { "deepskyblue", 0x00bfff},
82 { "dimgray", 0x696969},
83 { "dimgrey", 0x696969},
84 { "dodgerblue", 0x1e90ff},
85 { "firebrick", 0xb22222},
86 { "floralwhite", 0xfffaf0},
87 { "forestgreen", 0x228b22},
88#endif
89 { "fuchsia", 0xff00ff},
90#ifdef EXTENDED_COLOR
91 { "gainsboro", 0xdcdcdc},
92 { "ghostwhite", 0xf8f8ff},
93 { "gold", 0xffd700},
94 { "goldenrod", 0xdaa520},
95#endif
96 { "gray", 0x808080},
97 { "green", 0x008000},
98#ifdef EXTENDED_COLOR
99 { "greenyellow", 0xadff2f},
100 { "grey", 0x808080},
101 { "honeydew", 0xf0fff0},
102 { "hotpink", 0xff69b4},
103 { "indianred", 0xcd5c5c},
104 { "indigo", 0x4b0082},
105 { "ivory", 0xfffff0},
106 { "khaki", 0xf0e68c},
107 { "lavender", 0xe6e6fa},
108 { "lavenderblush", 0xfff0f5},
109 { "lawngreen", 0x7cfc00},
110 { "lemonchiffon", 0xfffacd},
111 { "lightblue", 0xadd8e6},
112 { "lightcoral", 0xf08080},
113 { "lightcyan", 0xe0ffff},
114 { "lightgoldenrodyellow", 0xfafad2},
115 { "lightgray", 0xd3d3d3},
116 { "lightgreen", 0x90ee90},
117 { "lightgrey", 0xd3d3d3},
118 { "lightpink", 0xffb6c1},
119 { "lightsalmon", 0xffa07a},
120 { "lightseagreen", 0x20b2aa},
121 { "lightskyblue", 0x87cefa},
122 { "lightslategray", 0x778899},
123 { "lightslategrey", 0x778899},
124 { "lightsteelblue", 0xb0c4de},
125 { "lightyellow", 0xffffe0},
126#endif
127 { "lime", 0x00ff00},
128#ifdef EXTENDED_COLOR
129 { "limegreen", 0x32cd32},
130 { "linen", 0xfaf0e6},
131 { "magenta", 0xff00ff},
132#endif
133 { "maroon", 0x800000},
134#ifdef EXTENDED_COLOR
135 { "mediumaquamarine", 0x66cdaa},
136 { "mediumblue", 0x0000cd},
137 { "mediumorchid", 0xba55d3},
138 { "mediumpurple", 0x9370db},
139 { "mediumseagreen", 0x3cb371},
140 { "mediumslateblue", 0x7b68ee},
141 { "mediumspringgreen", 0x00fa9a},
142 { "mediumturquoise", 0x48d1cc},
143 { "mediumvioletred", 0xc71585},
144 { "midnightblue", 0x191970},
145 { "mintcream", 0xf5fffa},
146 { "mistyrose", 0xffe4e1},
147 { "moccasin", 0xffe4b5},
148 { "navajowhite", 0xffdead},
149#endif
150 { "navy", 0x000080},
151#ifdef EXTENDED_COLOR
152 { "oldlace", 0xfdf5e6},
153#endif
154 { "olive", 0x808000},
155#ifdef EXTENDED_COLOR
156 { "olivedrab", 0x6b8e23},
157 { "orange", 0xffa500},
158 { "orangered", 0xff4500},
159 { "orchid", 0xda70d6},
160 { "palegoldenrod", 0xeee8aa},
161 { "palegreen", 0x98fb98},
162 { "paleturquoise", 0xafeeee},
163 { "palevioletred", 0xdb7093},
164 { "papayawhip", 0xffefd5},
165 { "peachpuff", 0xffdab9},
166 { "peru", 0xcd853f},
167 { "pink", 0xffc0cb},
168 { "plum", 0xdda0dd},
169 { "powderblue", 0xb0e0e6},
170#endif
171 { "purple", 0x800080},
172 { "red", 0xff0000},
173#ifdef EXTENDED_COLOR
174 { "rosybrown", 0xbc8f8f},
175 { "royalblue", 0x4169e1},
176 { "saddlebrown", 0x8b4513},
177 { "salmon", 0xfa8072},
178 { "sandybrown", 0xf4a460},
179 { "seagreen", 0x2e8b57},
180 { "seashell", 0xfff5ee},
181 { "sienna", 0xa0522d},
182#endif
183 { "silver", 0xc0c0c0},
184#ifdef EXTENDED_COLOR
185 { "skyblue", 0x87ceeb},
186 { "slateblue", 0x6a5acd},
187 { "slategray", 0x708090},
188 { "slategrey", 0x708090},
189 { "snow", 0xfffafa},
190 { "springgreen", 0x00ff7f},
191 { "steelblue", 0x4682b4},
192 { "tan", 0xd2b48c},
193#endif
194 { "teal", 0x008080},
195#ifdef EXTENDED_COLOR
196 { "thistle", 0xd8bfd8},
197 { "tomato", 0xff6347},
198 { "turquoise", 0x40e0d0},
199 { "violet", 0xee82ee},
200 { "wheat", 0xf5deb3},
201#endif
202 { "white", 0xffffff},
203#ifdef EXTENDED_COLOR
204 { "whitesmoke", 0xf5f5f5},
205#endif
206 { "yellow", 0xffff00},
207#ifdef EXTENDED_COLOR
208 { "yellowgreen", 0x9acd32},
209#endif
211
212#define NCOLORS (sizeof(color_keyword) / sizeof(color_keyword[0]))
213
221static int32_t Color_parse_hex (const char *s, int32_t default_color, int *err)
222{
223 int32_t ret_color;
224 char *tail;
225
226 *err = 1;
227 ret_color = strtol(s, &tail, 16);
228 if (tail - s == 6)
229 *err = 0;
230 else if (tail - s == 3) { /* #RGB as allowed by CSS */
231 *err = 0;
232 ret_color = ((ret_color & 0xf00) << 12) | ((ret_color & 0xf00) << 8) |
233 ((ret_color & 0x0f0) << 8) | ((ret_color & 0x0f0) << 4) |
234 ((ret_color & 0x00f) << 4) | ((ret_color & 0x00f) << 0);
235 } else
236 ret_color = default_color;
237
238 return ret_color;
239}
240
259int32_t a_Color_parse (const char *str, int32_t default_color, int *err)
260{
261 const char *cp;
262 int32_t ret_color;
263 int ret, low, mid, high, st = 1;
264
265 /* skip leading spaces */
266 for (cp = str; dIsspace(*cp); cp++);
267
268 ret_color = default_color;
269 if (*cp == '#') {
270 ret_color = Color_parse_hex(cp + 1, default_color, &st);
271
272 } else if (*cp == '0' && (cp[1] == 'x' || cp[1] == 'X') ) {
273 ret_color = Color_parse_hex(cp + 2, default_color, &st);
274 if (!st)
275 st = 2;
276 } else {
277 /* Binary search */
278 low = 0;
279 high = NCOLORS - 1;
280 while (low <= high) {
281 mid = (low + high) / 2;
282 if ((ret = dStrAsciiCasecmp(cp, color_keyword[mid].key)) < 0)
283 high = mid - 1;
284 else if (ret > 0)
285 low = mid + 1;
286 else {
287 ret_color = color_keyword[mid].val;
288 st = 0;
289 break;
290 }
291 }
292
293 if (low > high) {
294 /* try for RRGGBB lacking the leading '#' */
295 ret_color = Color_parse_hex(cp, default_color, &st);
296 st = 1;
297 }
298 }
299
300 _MSG("color string: %s\n", str);
301 _MSG("color : %X\n", ret_color);
302
303 *err = st;
304 return ret_color;
305}
306
307#if 0
308/*
309 * Return a "distance" measure (between [0, 10])
310 */
311static int Color_distance(long c1, long c2)
312{
313 return (labs((c1 & 0x0000ff) - (c2 & 0x0000ff)) +
314 labs(((c1 & 0x00ff00) - (c2 & 0x00ff00)) >> 8) +
315 labs(((c1 & 0xff0000) - (c2 & 0xff0000)) >> 16)) / 75;
316}
317#endif
318
319/*
320 * Return: [0-3]
321 */
322static int Color_distance2(long c1, long c2)
323{
324 return (labs((c1 & 0x0000ff) - (c2 & 0x0000ff)) >= 0x000060) +
325 (labs((c1 & 0x00ff00) - (c2 & 0x00ff00)) >= 0x006000) +
326 (labs((c1 & 0xff0000) - (c2 & 0xff0000)) >= 0x600000);
327}
328
329/*
330 * Return: [0-3] (requires less contrast than distance2)
331 */
332static int Color_distance3(long c1, long c2)
333{
334 return (labs((c1 & 0x0000ff) - (c2 & 0x0000ff)) >= 0x000040) +
335 (labs((c1 & 0x00ff00) - (c2 & 0x00ff00)) >= 0x004000) +
336 (labs((c1 & 0xff0000) - (c2 & 0xff0000)) >= 0x400000);
337}
338
345int32_t a_Color_vc(int32_t candidate,
346 int32_t C_txt, int32_t C_lnk, int32_t C_bg)
347{
348 /* candidate purple darkcyan darkmagenta olive */
349 static int32_t v[] = {0x000000, 0x800080, 0x008b8b, 0x8b008b, 0x808000,
350 /* darkred coral black */
351 0x8b0000, 0xff7f50, 0x000000};
352 int v_size = sizeof(v) / sizeof(v[0]);
353 int i, max_i, score, max_score, d_bg, d_txt, d_lnk;
354
355
356 /* set candidate in the list */
357 v[0] = candidate;
358
359 /* Try to get good overall and individual contrast */
360 max_i = max_score = 0;
361 for (i = 0; i < v_size; ++i) {
362 _MSG("a_Color_vc: [%d]%.6x: %d %d %d\n", i, v[i],
363 Color_distance2(C_txt, v[i]),
364 Color_distance2(C_lnk, v[i]),
365 Color_distance2(C_bg, v[i]));
366
367 /* Tuned with: slashdot.org, paulgraham.com, newsforge.com,
368 * linuxjournal.com
369 */
370 d_txt = Color_distance2(C_txt, v[i]);
371 d_lnk = Color_distance2(C_lnk, v[i]);
372 d_bg = Color_distance2(C_bg, v[i]);
373 score = (d_bg >= 2 ? 4 : 2 * d_bg) +
374 (d_txt + d_lnk >= 2 ? 2 : d_txt + d_lnk) +
375 (Color_distance3(C_lnk, v[i]) >= 1 ? 1 : 0);
376 if (score >= 7) {
377 /* enough distance, use this color */
378 max_i = i;
379 break;
380 } else if (score > max_score) {
381 /* keep track of the best candidate so far */
382 max_score = score;
383 max_i = i;
384 }
385 }
386 return v[max_i];
387}
#define _MSG(...)
Definition bookmarks.c:44
static int Color_distance2(long c1, long c2)
Definition colors.c:322
static int Color_distance3(long c1, long c2)
Definition colors.c:332
static int32_t Color_parse_hex(const char *s, int32_t default_color, int *err)
Parse a color in hex (RRGGBB) or (RGB).
Definition colors.c:221
int32_t a_Color_parse(const char *str, int32_t default_color, int *err)
Parse a color string.
Definition colors.c:259
static const struct key color_keyword[]
#define NCOLORS
Definition colors.c:212
int32_t a_Color_vc(int32_t candidate, int32_t C_txt, int32_t C_lnk, int32_t C_bg)
Return a suitable "visited link" color.
Definition colors.c:345
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:202
static int dIsspace(unsigned char c)
Definition dlib.h:53