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