Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/svg/svg-color.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 // Copyright (C) 2004-2021 Artifex Software, Inc. | |
| 2 // | |
| 3 // This file is part of MuPDF. | |
| 4 // | |
| 5 // MuPDF is free software: you can redistribute it and/or modify it under the | |
| 6 // terms of the GNU Affero General Public License as published by the Free | |
| 7 // Software Foundation, either version 3 of the License, or (at your option) | |
| 8 // any later version. | |
| 9 // | |
| 10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | |
| 13 // details. | |
| 14 // | |
| 15 // You should have received a copy of the GNU Affero General Public License | |
| 16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> | |
| 17 // | |
| 18 // Alternative licensing terms are available from the licensor. | |
| 19 // For commercial licensing, see <https://www.artifex.com/> or contact | |
| 20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, | |
| 21 // CA 94129, USA, for further information. | |
| 22 | |
| 23 #include "mupdf/fitz.h" | |
| 24 #include "svg-imp.h" | |
| 25 | |
| 26 #include <string.h> | |
| 27 | |
| 28 /* Color keywords (white, blue, fuchsia) | |
| 29 * System color keywords (ActiveBorder, ButtonFace -- need to find reasonable defaults) | |
| 30 * #fb0 (expand to #ffbb00) | |
| 31 * #ffbb00 | |
| 32 * rgb(255,255,255) | |
| 33 * rgb(100%,100%,100%) | |
| 34 * | |
| 35 * "red icc-color(profileName,255,0,0)" (not going to support for now) | |
| 36 */ | |
| 37 | |
| 38 struct | |
| 39 { | |
| 40 const char *name; | |
| 41 float red, green, blue; | |
| 42 } | |
| 43 svg_predefined_colors[] = | |
| 44 { | |
| 45 { "aliceblue", 240, 248, 255 }, | |
| 46 { "antiquewhite", 250, 235, 215 }, | |
| 47 { "aqua", 0, 255, 255 }, | |
| 48 { "aquamarine", 127, 255, 212 }, | |
| 49 { "azure", 240, 255, 255 }, | |
| 50 { "beige", 245, 245, 220 }, | |
| 51 { "bisque", 255, 228, 196 }, | |
| 52 { "black", 0, 0, 0 }, | |
| 53 { "blanchedalmond", 255, 235, 205 }, | |
| 54 { "blue", 0, 0, 255 }, | |
| 55 { "blueviolet", 138, 43, 226 }, | |
| 56 { "brown", 165, 42, 42 }, | |
| 57 { "burlywood", 222, 184, 135 }, | |
| 58 { "cadetblue", 95, 158, 160 }, | |
| 59 { "chartreuse", 127, 255, 0 }, | |
| 60 { "chocolate", 210, 105, 30 }, | |
| 61 { "coral", 255, 127, 80 }, | |
| 62 { "cornflowerblue", 100, 149, 237 }, | |
| 63 { "cornsilk", 255, 248, 220 }, | |
| 64 { "crimson", 220, 20, 60 }, | |
| 65 { "cyan", 0, 255, 255 }, | |
| 66 { "darkblue", 0, 0, 139 }, | |
| 67 { "darkcyan", 0, 139, 139 }, | |
| 68 { "darkgoldenrod", 184, 134, 11 }, | |
| 69 { "darkgray", 169, 169, 169 }, | |
| 70 { "darkgreen", 0, 100, 0 }, | |
| 71 { "darkgrey", 169, 169, 169 }, | |
| 72 { "darkkhaki", 189, 183, 107 }, | |
| 73 { "darkmagenta", 139, 0, 139 }, | |
| 74 { "darkolivegreen", 85, 107, 47 }, | |
| 75 { "darkorange", 255, 140, 0 }, | |
| 76 { "darkorchid", 153, 50, 204 }, | |
| 77 { "darkred", 139, 0, 0 }, | |
| 78 { "darksalmon", 233, 150, 122 }, | |
| 79 { "darkseagreen", 143, 188, 143 }, | |
| 80 { "darkslateblue", 72, 61, 139 }, | |
| 81 { "darkslategray", 47, 79, 79 }, | |
| 82 { "darkslategrey", 47, 79, 79 }, | |
| 83 { "darkturquoise", 0, 206, 209 }, | |
| 84 { "darkviolet", 148, 0, 211 }, | |
| 85 { "deeppink", 255, 20, 147 }, | |
| 86 { "deepskyblue", 0, 191, 255 }, | |
| 87 { "dimgray", 105, 105, 105 }, | |
| 88 { "dimgrey", 105, 105, 105 }, | |
| 89 { "dodgerblue", 30, 144, 255 }, | |
| 90 { "firebrick", 178, 34, 34 }, | |
| 91 { "floralwhite", 255, 250, 240 }, | |
| 92 { "forestgreen", 34, 139, 34 }, | |
| 93 { "fuchsia", 255, 0, 255 }, | |
| 94 { "gainsboro", 220, 220, 220 }, | |
| 95 { "ghostwhite", 248, 248, 255 }, | |
| 96 { "gold", 255, 215, 0 }, | |
| 97 { "goldenrod", 218, 165, 32 }, | |
| 98 { "gray", 128, 128, 128 }, | |
| 99 { "green", 0, 128, 0 }, | |
| 100 { "greenyellow", 173, 255, 47 }, | |
| 101 { "grey", 128, 128, 128 }, | |
| 102 { "honeydew", 240, 255, 240 }, | |
| 103 { "hotpink", 255, 105, 180 }, | |
| 104 { "indianred", 205, 92, 92 }, | |
| 105 { "indigo", 75, 0, 130 }, | |
| 106 { "ivory", 255, 255, 240 }, | |
| 107 { "khaki", 240, 230, 140 }, | |
| 108 { "lavender", 230, 230, 250 }, | |
| 109 { "lavenderblush", 255, 240, 245 }, | |
| 110 { "lawngreen", 124, 252, 0 }, | |
| 111 { "lemonchiffon", 255, 250, 205 }, | |
| 112 { "lightblue", 173, 216, 230 }, | |
| 113 { "lightcoral", 240, 128, 128 }, | |
| 114 { "lightcyan", 224, 255, 255 }, | |
| 115 { "lightgoldenrodyellow", 250, 250, 210 }, | |
| 116 { "lightgray", 211, 211, 211 }, | |
| 117 { "lightgreen", 144, 238, 144 }, | |
| 118 { "lightgrey", 211, 211, 211 }, | |
| 119 { "lightpink", 255, 182, 193 }, | |
| 120 { "lightsalmon", 255, 160, 122 }, | |
| 121 { "lightseagreen", 32, 178, 170 }, | |
| 122 { "lightskyblue", 135, 206, 250 }, | |
| 123 { "lightslategray", 119, 136, 153 }, | |
| 124 { "lightslategrey", 119, 136, 153 }, | |
| 125 { "lightsteelblue", 176, 196, 222 }, | |
| 126 { "lightyellow", 255, 255, 224 }, | |
| 127 { "lime", 0, 255, 0 }, | |
| 128 { "limegreen", 50, 205, 50 }, | |
| 129 { "linen", 250, 240, 230 }, | |
| 130 { "magenta", 255, 0, 255 }, | |
| 131 { "maroon", 128, 0, 0 }, | |
| 132 { "mediumaquamarine", 102, 205, 170 }, | |
| 133 { "mediumblue", 0, 0, 205 }, | |
| 134 { "mediumorchid", 186, 85, 211 }, | |
| 135 { "mediumpurple", 147, 112, 219 }, | |
| 136 { "mediumseagreen", 60, 179, 113 }, | |
| 137 { "mediumslateblue", 123, 104, 238 }, | |
| 138 { "mediumspringgreen", 0, 250, 154 }, | |
| 139 { "mediumturquoise", 72, 209, 204 }, | |
| 140 { "mediumvioletred", 199, 21, 133 }, | |
| 141 { "midnightblue", 25, 25, 112 }, | |
| 142 { "mintcream", 245, 255, 250 }, | |
| 143 { "mistyrose", 255, 228, 225 }, | |
| 144 { "moccasin", 255, 228, 181 }, | |
| 145 { "navajowhite", 255, 222, 173 }, | |
| 146 { "navy", 0, 0, 128 }, | |
| 147 { "oldlace", 253, 245, 230 }, | |
| 148 { "olive", 128, 128, 0 }, | |
| 149 { "olivedrab", 107, 142, 35 }, | |
| 150 { "orange", 255, 165, 0 }, | |
| 151 { "orangered", 255, 69, 0 }, | |
| 152 { "orchid", 218, 112, 214 }, | |
| 153 { "palegoldenrod", 238, 232, 170 }, | |
| 154 { "palegreen", 152, 251, 152 }, | |
| 155 { "paleturquoise", 175, 238, 238 }, | |
| 156 { "palevioletred", 219, 112, 147 }, | |
| 157 { "papayawhip", 255, 239, 213 }, | |
| 158 { "peachpuff", 255, 218, 185 }, | |
| 159 { "peru", 205, 133, 63 }, | |
| 160 { "pink", 255, 192, 203 }, | |
| 161 { "plum", 221, 160, 221 }, | |
| 162 { "powderblue", 176, 224, 230 }, | |
| 163 { "purple", 128, 0, 128 }, | |
| 164 { "red", 255, 0, 0 }, | |
| 165 { "rosybrown", 188, 143, 143 }, | |
| 166 { "royalblue", 65, 105, 225 }, | |
| 167 { "saddlebrown", 139, 69, 19 }, | |
| 168 { "salmon", 250, 128, 114 }, | |
| 169 { "sandybrown", 244, 164, 96 }, | |
| 170 { "seagreen", 46, 139, 87 }, | |
| 171 { "seashell", 255, 245, 238 }, | |
| 172 { "sienna", 160, 82, 45 }, | |
| 173 { "silver", 192, 192, 192 }, | |
| 174 { "skyblue", 135, 206, 235 }, | |
| 175 { "slateblue", 106, 90, 205 }, | |
| 176 { "slategray", 112, 128, 144 }, | |
| 177 { "slategrey", 112, 128, 144 }, | |
| 178 { "snow", 255, 250, 250 }, | |
| 179 { "springgreen", 0, 255, 127 }, | |
| 180 { "steelblue", 70, 130, 180 }, | |
| 181 { "tan", 210, 180, 140 }, | |
| 182 { "teal", 0, 128, 128 }, | |
| 183 { "thistle", 216, 191, 216 }, | |
| 184 { "tomato", 255, 99, 71 }, | |
| 185 { "turquoise", 64, 224, 208 }, | |
| 186 { "violet", 238, 130, 238 }, | |
| 187 { "wheat", 245, 222, 179 }, | |
| 188 { "white", 255, 255, 255 }, | |
| 189 { "whitesmoke", 245, 245, 245 }, | |
| 190 { "yellow", 255, 255, 0 }, | |
| 191 { "yellowgreen", 154, 205, 50 }, | |
| 192 }; | |
| 193 | |
| 194 static int unhex(int chr) | |
| 195 { | |
| 196 const char *hextable = "0123456789abcdef"; | |
| 197 return strchr(hextable, (chr|32)) - hextable; | |
| 198 } | |
| 199 | |
| 200 static int ishex(int chr) | |
| 201 { | |
| 202 if (chr >= '0' && chr <= '9') return 1; | |
| 203 if (chr >= 'A' && chr <= 'F') return 1; | |
| 204 if (chr >= 'a' && chr <= 'f') return 1; | |
| 205 return 0; | |
| 206 } | |
| 207 | |
| 208 void | |
| 209 svg_parse_color(fz_context *ctx, svg_document *doc, const char *str, float *rgb) | |
| 210 { | |
| 211 int i, l, m, r, cmp; | |
| 212 size_t n; | |
| 213 | |
| 214 rgb[0] = 0.0f; | |
| 215 rgb[1] = 0.0f; | |
| 216 rgb[2] = 0.0f; | |
| 217 | |
| 218 /* Crack hex-coded RGB */ | |
| 219 | |
| 220 if (str[0] == '#') | |
| 221 { | |
| 222 str ++; | |
| 223 | |
| 224 n = strlen(str); | |
| 225 if (n == 3 || (n > 3 && !ishex(str[3]))) | |
| 226 { | |
| 227 rgb[0] = (unhex(str[0]) * 16 + unhex(str[0])) / 255.0f; | |
| 228 rgb[1] = (unhex(str[1]) * 16 + unhex(str[1])) / 255.0f; | |
| 229 rgb[2] = (unhex(str[2]) * 16 + unhex(str[2])) / 255.0f; | |
| 230 return; | |
| 231 } | |
| 232 | |
| 233 if (n >= 6) | |
| 234 { | |
| 235 rgb[0] = (unhex(str[0]) * 16 + unhex(str[1])) / 255.0f; | |
| 236 rgb[1] = (unhex(str[2]) * 16 + unhex(str[3])) / 255.0f; | |
| 237 rgb[2] = (unhex(str[4]) * 16 + unhex(str[5])) / 255.0f; | |
| 238 return; | |
| 239 } | |
| 240 | |
| 241 return; | |
| 242 } | |
| 243 | |
| 244 /* rgb(X,Y,Z) -- whitespace allowed around numbers */ | |
| 245 | |
| 246 else if (strstr(str, "rgb(")) | |
| 247 { | |
| 248 int numberlen = 0; | |
| 249 char numberbuf[50]; | |
| 250 | |
| 251 str = str + 4; | |
| 252 | |
| 253 for (i = 0; i < 3; i++) | |
| 254 { | |
| 255 while (svg_is_whitespace_or_comma(*str)) | |
| 256 str ++; | |
| 257 | |
| 258 if (svg_is_digit(*str)) | |
| 259 { | |
| 260 numberlen = 0; | |
| 261 while (svg_is_digit(*str) && numberlen < (int)sizeof(numberbuf) - 1) | |
| 262 numberbuf[numberlen++] = *str++; | |
| 263 numberbuf[numberlen] = 0; | |
| 264 | |
| 265 if (*str == '%') | |
| 266 { | |
| 267 str ++; | |
| 268 rgb[i] = fz_atof(numberbuf) / 100.0f; | |
| 269 } | |
| 270 else | |
| 271 { | |
| 272 rgb[i] = fz_atof(numberbuf) / 255.0f; | |
| 273 } | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 return; | |
| 278 } | |
| 279 | |
| 280 /* TODO: parse icc-profile(X,Y,Z,W) syntax */ | |
| 281 | |
| 282 /* Search for a pre-defined color */ | |
| 283 | |
| 284 else | |
| 285 { | |
| 286 char keyword[50], *p; | |
| 287 fz_strlcpy(keyword, str, sizeof keyword); | |
| 288 p = keyword; | |
| 289 while (*p && *p >= 'a' && *p <= 'z') | |
| 290 ++p; | |
| 291 *p = 0; | |
| 292 | |
| 293 l = 0; | |
| 294 r = nelem(svg_predefined_colors) - 1; | |
| 295 | |
| 296 while (l <= r) | |
| 297 { | |
| 298 m = (l + r) / 2; | |
| 299 cmp = strcmp(svg_predefined_colors[m].name, keyword); | |
| 300 if (cmp > 0) | |
| 301 r = m - 1; | |
| 302 else if (cmp < 0) | |
| 303 l = m + 1; | |
| 304 else | |
| 305 { | |
| 306 rgb[0] = svg_predefined_colors[m].red / 255.0f; | |
| 307 rgb[1] = svg_predefined_colors[m].green / 255.0f; | |
| 308 rgb[2] = svg_predefined_colors[m].blue / 255.0f; | |
| 309 return; | |
| 310 } | |
| 311 } | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 static int | |
| 316 svg_parse_color_from_style_string(fz_context *ctx, svg_document *doc, const char *p, float color[3]) | |
| 317 { | |
| 318 char buf[100], *e; | |
| 319 while (*p && svg_is_whitespace(*p)) | |
| 320 ++p; | |
| 321 fz_strlcpy(buf, p, sizeof buf); | |
| 322 e = strchr(buf, ';'); | |
| 323 if (e) | |
| 324 *e = 0; | |
| 325 if (!strcmp(buf, "none")) | |
| 326 return 0; | |
| 327 svg_parse_color(ctx, doc, buf, color); | |
| 328 return 1; | |
| 329 } | |
| 330 | |
| 331 void | |
| 332 svg_parse_color_from_style(fz_context *ctx, svg_document *doc, const char *str, | |
| 333 int *fill_is_set, float fill[3], | |
| 334 int *stroke_is_set, float stroke[3]) | |
| 335 { | |
| 336 const char *p; | |
| 337 | |
| 338 p = strstr(str, "fill:"); | |
| 339 if (p) | |
| 340 *fill_is_set = svg_parse_color_from_style_string(ctx, doc, p+5, fill); | |
| 341 | |
| 342 p = strstr(str, "stroke:"); | |
| 343 if (p) | |
| 344 *stroke_is_set = svg_parse_color_from_style_string(ctx, doc, p+7, stroke); | |
| 345 } |
