1 /** 2 * Color module for dcell. 3 * 4 * Copyright: Copyright 2025 Garrett D'Amore 5 * Authors: Garrett D'Amore 6 * License: 7 * Distributed under the Boost Software License, Version 1.0. 8 * (See accompanying file LICENSE or https://www.boost.org/LICENSE_1_0.txt) 9 * SPDX-License-Identifier: BSL-1.0 10 */ 11 module dcell.color; 12 13 import std.format; 14 import std.typecons; 15 16 /** 17 * Color is a what you think, almost. 18 * However, the upper bits of the color are used to indicate special behaviors. 19 * If the value upper 24-bits are clear, then the value is an index into a 20 * palette (typically it should be less than 256). If the isRGB bit is 21 * set, then the lower 24 bits are a 24-bit direct color (RGB). 22 */ 23 enum Color : uint 24 { 25 invalid = 1 << 24, /// not a color (also means do not change color) 26 reset = invalid + 1, /// reset color to terminal defaults 27 isRGB = 1 << 31, /// indicates that the low 24-bits are red, green blue 28 black = 0, 29 maroon = 1, 30 green = 2, 31 olive = 3, 32 navy = 4, 33 purple = 5, 34 teal = 6, 35 silver = 7, 36 gray = 8, 37 red = 9, 38 lime = 10, 39 yellow = 11, 40 blue = 12, 41 fuchsia = 13, 42 aqua = 14, 43 white = 15, 44 // following colors are web named colors 45 aliceBlue = isRGB | 0xF0F8FF, 46 antiqueWhite = isRGB | 0xFAEBD7, 47 aquamarine = isRGB | 0x7FFFD4, 48 azure = isRGB | 0xF0FFFF, 49 beige = isRGB | 0xF5F5DC, 50 bisque = isRGB | 0xFFE4C4, 51 blanchedAlmond = isRGB | 0xFFEBCD, 52 blueViolet = isRGB | 0x8A2BE2, 53 brown = isRGB | 0xA52A2A, 54 burlyWood = isRGB | 0xDEB887, 55 cadetBlue = isRGB | 0x5F9EA0, 56 chartreuse = isRGB | 0x7FFF00, 57 chocolate = isRGB | 0xD2691E, 58 coral = isRGB | 0xFF7F50, 59 cornflowerBlue = isRGB | 0x6495ED, 60 cornsilk = isRGB | 0xFFF8DC, 61 crimson = isRGB | 0xDC143C, 62 darkBlue = isRGB | 0x00008B, 63 darkCyan = isRGB | 0x008B8B, 64 darkGoldenrod = isRGB | 0xB8860B, 65 darkGray = isRGB | 0xA9A9A9, 66 darkGreen = isRGB | 0x006400, 67 darkKhaki = isRGB | 0xBDB76B, 68 darkMagenta = isRGB | 0x8B008B, 69 darkOliveGreen = isRGB | 0x556B2F, 70 darkOrange = isRGB | 0xFF8C00, 71 darkOrchid = isRGB | 0x9932CC, 72 darkRed = isRGB | 0x8B0000, 73 darkSalmon = isRGB | 0xE9967A, 74 darkSeaGreen = isRGB | 0x8FBC8F, 75 darkSlateBlue = isRGB | 0x483D8B, 76 darkSlateGray = isRGB | 0x2F4F4F, 77 darkTurquoise = isRGB | 0x00CED1, 78 darkViolet = isRGB | 0x9400D3, 79 deepPink = isRGB | 0xFF1493, 80 deepSkyBlue = isRGB | 0x00BFFF, 81 dimGray = isRGB | 0x696969, 82 dodgerBlue = isRGB | 0x1E90FF, 83 fireBrick = isRGB | 0xB22222, 84 floralWhite = isRGB | 0xFFFAF0, 85 forestGreen = isRGB | 0x228B22, 86 gainsboro = isRGB | 0xDCDCDC, 87 ghostWhite = isRGB | 0xF8F8FF, 88 gold = isRGB | 0xFFD700, 89 goldenrod = isRGB | 0xDAA520, 90 greenYellow = isRGB | 0xADFF2F, 91 honeydew = isRGB | 0xF0FFF0, 92 hotPink = isRGB | 0xFF69B4, 93 indianRed = isRGB | 0xCD5C5C, 94 indigo = isRGB | 0x4B0082, 95 ivory = isRGB | 0xFFFFF0, 96 khaki = isRGB | 0xF0E68C, 97 lavender = isRGB | 0xE6E6FA, 98 lavenderBlush = isRGB | 0xFFF0F5, 99 lawnGreen = isRGB | 0x7CFC00, 100 lemonChiffon = isRGB | 0xFFFACD, 101 lightBlue = isRGB | 0xADD8E6, 102 lightCoral = isRGB | 0xF08080, 103 lightCyan = isRGB | 0xE0FFFF, 104 lightGoldenrodYellow = isRGB | 0xFAFAD2, 105 lightGray = isRGB | 0xD3D3D3, 106 lightGreen = isRGB | 0x90EE90, 107 lightPink = isRGB | 0xFFB6C1, 108 lightSalmon = isRGB | 0xFFA07A, 109 lightSeaGreen = isRGB | 0x20B2AA, 110 lightSkyBlue = isRGB | 0x87CEFA, 111 lightSlateGray = isRGB | 0x778899, 112 lightSteelBlue = isRGB | 0xB0C4DE, 113 lightYellow = isRGB | 0xFFFFE0, 114 limeGreen = isRGB | 0x32CD32, 115 linen = isRGB | 0xFAF0E6, 116 mediumAquamarine = isRGB | 0x66CDAA, 117 mediumBlue = isRGB | 0x0000CD, 118 mediumOrchid = isRGB | 0xBA55D3, 119 mediumPurple = isRGB | 0x9370DB, 120 mediumSeaGreen = isRGB | 0x3CB371, 121 mediumSlateBlue = isRGB | 0x7B68EE, 122 mediumSpringGreen = isRGB | 0x00FA9A, 123 mediumTurquoise = isRGB | 0x48D1CC, 124 mediumVioletRed = isRGB | 0xC71585, 125 midnightBlue = isRGB | 0x191970, 126 mintCream = isRGB | 0xF5FFFA, 127 mistyRose = isRGB | 0xFFE4E1, 128 moccasin = isRGB | 0xFFE4B5, 129 navajoWhite = isRGB | 0xFFDEAD, 130 oldLace = isRGB | 0xFDF5E6, 131 oliveDrab = isRGB | 0x6B8E23, 132 orange = isRGB | 0xFFA500, 133 orangeRed = isRGB | 0xFF4500, 134 orchid = isRGB | 0xDA70D6, 135 paleGoldenrod = isRGB | 0xEEE8AA, 136 paleGreen = isRGB | 0x98FB98, 137 paleTurquoise = isRGB | 0xAFEEEE, 138 paleVioletRed = isRGB | 0xDB7093, 139 papayaWhip = isRGB | 0xFFEFD5, 140 peachPuff = isRGB | 0xFFDAB9, 141 peru = isRGB | 0xCD853F, 142 pink = isRGB | 0xFFC0CB, 143 plum = isRGB | 0xDDA0DD, 144 powderBlue = isRGB | 0xB0E0E6, 145 rebeccaPurple = isRGB | 0x663399, 146 rosyBrown = isRGB | 0xBC8F8F, 147 royalBlue = isRGB | 0x4169E1, 148 saddleBrown = isRGB | 0x8B4513, 149 salmon = isRGB | 0xFA8072, 150 sandyBrown = isRGB | 0xF4A460, 151 seaGreen = isRGB | 0x2E8B57, 152 seashell = isRGB | 0xFFF5EE, 153 sienna = isRGB | 0xA0522D, 154 skyBlue = isRGB | 0x87CEEB, 155 slateBlue = isRGB | 0x6A5ACD, 156 slateGray = isRGB | 0x708090, 157 snow = isRGB | 0xFFFAFA, 158 springGreen = isRGB | 0x00FF7F, 159 steelBlue = isRGB | 0x4682B4, 160 tan = isRGB | 0xD2B48C, 161 thistle = isRGB | 0xD8BFD8, 162 tomato = isRGB | 0xFF6347, 163 turquoise = isRGB | 0x40E0D0, 164 violet = isRGB | 0xEE82EE, 165 wheat = isRGB | 0xF5DEB3, 166 whiteSmoke = isRGB | 0xF5F5F5, 167 yellowGreen = isRGB | 0x9ACD32, 168 init = invalid, 169 } 170 171 private static immutable uint[Color] rgbValues; 172 private static immutable Color[uint] palValues; 173 174 shared static this() @safe 175 { 176 rgbValues[Color.black] = 0x000000; 177 rgbValues[Color.maroon] = 0x800000; 178 rgbValues[Color.green] = 0x008000; 179 rgbValues[Color.olive] = 0x808000; 180 rgbValues[Color.navy] = 0x000080; 181 rgbValues[Color.purple] = 0x800080; 182 rgbValues[Color.teal] = 0x008080; 183 rgbValues[Color.silver] = 0xC0C0C0; 184 rgbValues[Color.gray] = 0x808080; 185 rgbValues[Color.red] = 0xFF0000; 186 rgbValues[Color.lime] = 0x00FF00; 187 rgbValues[Color.yellow] = 0xFFFF00; 188 rgbValues[Color.blue] = 0x0000FF; 189 rgbValues[Color.fuchsia] = 0xFF00FF; 190 rgbValues[Color.aqua] = 0x00FFFF; 191 rgbValues[Color.white] = 0xFFFFFF; 192 // 256 color extended palette 193 rgbValues[cast(Color) 16] = 0x000000; // black 194 rgbValues[cast(Color) 17] = 0x00005F; 195 rgbValues[cast(Color) 18] = 0x000087; 196 rgbValues[cast(Color) 19] = 0x0000AF; 197 rgbValues[cast(Color) 20] = 0x0000D7; 198 rgbValues[cast(Color) 21] = 0x0000FF; // blue 199 rgbValues[cast(Color) 22] = 0x005F00; 200 rgbValues[cast(Color) 23] = 0x005F5F; 201 rgbValues[cast(Color) 24] = 0x005F87; 202 rgbValues[cast(Color) 25] = 0x005FAF; 203 rgbValues[cast(Color) 26] = 0x005FD7; 204 rgbValues[cast(Color) 27] = 0x005FFF; 205 rgbValues[cast(Color) 28] = 0x008700; 206 rgbValues[cast(Color) 29] = 0x00875F; 207 rgbValues[cast(Color) 30] = 0x008787; 208 rgbValues[cast(Color) 31] = 0x0087Af; 209 rgbValues[cast(Color) 32] = 0x0087D7; 210 rgbValues[cast(Color) 33] = 0x0087FF; 211 rgbValues[cast(Color) 34] = 0x00AF00; 212 rgbValues[cast(Color) 35] = 0x00AF5F; 213 rgbValues[cast(Color) 36] = 0x00AF87; 214 rgbValues[cast(Color) 37] = 0x00AFAF; 215 rgbValues[cast(Color) 38] = 0x00AFD7; 216 rgbValues[cast(Color) 39] = 0x00AFFF; 217 rgbValues[cast(Color) 40] = 0x00D700; 218 rgbValues[cast(Color) 41] = 0x00D75F; 219 rgbValues[cast(Color) 42] = 0x00D787; 220 rgbValues[cast(Color) 43] = 0x00D7AF; 221 rgbValues[cast(Color) 44] = 0x00D7D7; 222 rgbValues[cast(Color) 45] = 0x00D7FF; 223 rgbValues[cast(Color) 46] = 0x00FF00; // lime 224 rgbValues[cast(Color) 47] = 0x00FF5F; 225 rgbValues[cast(Color) 48] = 0x00FF87; 226 rgbValues[cast(Color) 49] = 0x00FFAF; 227 rgbValues[cast(Color) 50] = 0x00FFd7; 228 rgbValues[cast(Color) 51] = 0x00FFFF; // aqua 229 rgbValues[cast(Color) 52] = 0x5F0000; 230 rgbValues[cast(Color) 53] = 0x5F005F; 231 rgbValues[cast(Color) 54] = 0x5F0087; 232 rgbValues[cast(Color) 55] = 0x5F00AF; 233 rgbValues[cast(Color) 56] = 0x5F00D7; 234 rgbValues[cast(Color) 57] = 0x5F00FF; 235 rgbValues[cast(Color) 58] = 0x5F5F00; 236 rgbValues[cast(Color) 59] = 0x5F5F5F; 237 rgbValues[cast(Color) 60] = 0x5F5F87; 238 rgbValues[cast(Color) 61] = 0x5F5FAF; 239 rgbValues[cast(Color) 62] = 0x5F5FD7; 240 rgbValues[cast(Color) 63] = 0x5F5FFF; 241 rgbValues[cast(Color) 64] = 0x5F8700; 242 rgbValues[cast(Color) 65] = 0x5F875F; 243 rgbValues[cast(Color) 66] = 0x5F8787; 244 rgbValues[cast(Color) 67] = 0x5F87AF; 245 rgbValues[cast(Color) 68] = 0x5F87D7; 246 rgbValues[cast(Color) 69] = 0x5F87FF; 247 rgbValues[cast(Color) 70] = 0x5FAF00; 248 rgbValues[cast(Color) 71] = 0x5FAF5F; 249 rgbValues[cast(Color) 72] = 0x5FAF87; 250 rgbValues[cast(Color) 73] = 0x5FAFAF; 251 rgbValues[cast(Color) 74] = 0x5FAFD7; 252 rgbValues[cast(Color) 75] = 0x5FAFFF; 253 rgbValues[cast(Color) 76] = 0x5FD700; 254 rgbValues[cast(Color) 77] = 0x5FD75F; 255 rgbValues[cast(Color) 78] = 0x5FD787; 256 rgbValues[cast(Color) 79] = 0x5FD7AF; 257 rgbValues[cast(Color) 80] = 0x5FD7D7; 258 rgbValues[cast(Color) 81] = 0x5FD7FF; 259 rgbValues[cast(Color) 82] = 0x5FFF00; 260 rgbValues[cast(Color) 83] = 0x5FFF5F; 261 rgbValues[cast(Color) 84] = 0x5FFF87; 262 rgbValues[cast(Color) 85] = 0x5FFFAF; 263 rgbValues[cast(Color) 86] = 0x5FFFD7; 264 rgbValues[cast(Color) 87] = 0x5FFFFF; 265 rgbValues[cast(Color) 88] = 0x870000; 266 rgbValues[cast(Color) 89] = 0x87005F; 267 rgbValues[cast(Color) 90] = 0x870087; 268 rgbValues[cast(Color) 91] = 0x8700AF; 269 rgbValues[cast(Color) 92] = 0x8700D7; 270 rgbValues[cast(Color) 93] = 0x8700FF; 271 rgbValues[cast(Color) 94] = 0x875F00; 272 rgbValues[cast(Color) 95] = 0x875F5F; 273 rgbValues[cast(Color) 96] = 0x875F87; 274 rgbValues[cast(Color) 97] = 0x875FAF; 275 rgbValues[cast(Color) 98] = 0x875FD7; 276 rgbValues[cast(Color) 99] = 0x875FFF; 277 rgbValues[cast(Color) 100] = 0x878700; 278 rgbValues[cast(Color) 101] = 0x87875F; 279 rgbValues[cast(Color) 102] = 0x878787; 280 rgbValues[cast(Color) 103] = 0x8787AF; 281 rgbValues[cast(Color) 104] = 0x8787D7; 282 rgbValues[cast(Color) 105] = 0x8787FF; 283 rgbValues[cast(Color) 106] = 0x87AF00; 284 rgbValues[cast(Color) 107] = 0x87AF5F; 285 rgbValues[cast(Color) 108] = 0x87AF87; 286 rgbValues[cast(Color) 109] = 0x87AFAF; 287 rgbValues[cast(Color) 110] = 0x87AFD7; 288 rgbValues[cast(Color) 111] = 0x87AFFF; 289 rgbValues[cast(Color) 112] = 0x87D700; 290 rgbValues[cast(Color) 113] = 0x87D75F; 291 rgbValues[cast(Color) 114] = 0x87D787; 292 rgbValues[cast(Color) 115] = 0x87D7AF; 293 rgbValues[cast(Color) 116] = 0x87D7D7; 294 rgbValues[cast(Color) 117] = 0x87D7FF; 295 rgbValues[cast(Color) 118] = 0x87FF00; 296 rgbValues[cast(Color) 119] = 0x87FF5F; 297 rgbValues[cast(Color) 120] = 0x87FF87; 298 rgbValues[cast(Color) 121] = 0x87FFAF; 299 rgbValues[cast(Color) 122] = 0x87FFD7; 300 rgbValues[cast(Color) 123] = 0x87FFFF; 301 rgbValues[cast(Color) 124] = 0xAF0000; 302 rgbValues[cast(Color) 125] = 0xAF005F; 303 rgbValues[cast(Color) 126] = 0xAF0087; 304 rgbValues[cast(Color) 127] = 0xAF00AF; 305 rgbValues[cast(Color) 128] = 0xAF00D7; 306 rgbValues[cast(Color) 129] = 0xAF00FF; 307 rgbValues[cast(Color) 130] = 0xAF5F00; 308 rgbValues[cast(Color) 131] = 0xAF5F5F; 309 rgbValues[cast(Color) 132] = 0xAF5F87; 310 rgbValues[cast(Color) 133] = 0xAF5FAF; 311 rgbValues[cast(Color) 134] = 0xAF5FD7; 312 rgbValues[cast(Color) 135] = 0xAF5FFF; 313 rgbValues[cast(Color) 136] = 0xAF8700; 314 rgbValues[cast(Color) 137] = 0xAF875F; 315 rgbValues[cast(Color) 138] = 0xAF8787; 316 rgbValues[cast(Color) 139] = 0xAF87AF; 317 rgbValues[cast(Color) 140] = 0xAF87D7; 318 rgbValues[cast(Color) 141] = 0xAF87FF; 319 rgbValues[cast(Color) 142] = 0xAFAF00; 320 rgbValues[cast(Color) 143] = 0xAFAF5F; 321 rgbValues[cast(Color) 144] = 0xAFAF87; 322 rgbValues[cast(Color) 145] = 0xAFAFAF; 323 rgbValues[cast(Color) 146] = 0xAFAFD7; 324 rgbValues[cast(Color) 147] = 0xAFAFFF; 325 rgbValues[cast(Color) 148] = 0xAFD700; 326 rgbValues[cast(Color) 149] = 0xAFD75F; 327 rgbValues[cast(Color) 150] = 0xAFD787; 328 rgbValues[cast(Color) 151] = 0xAFD7AF; 329 rgbValues[cast(Color) 152] = 0xAFD7D7; 330 rgbValues[cast(Color) 153] = 0xAFD7FF; 331 rgbValues[cast(Color) 154] = 0xAFFF00; 332 rgbValues[cast(Color) 155] = 0xAFFF5F; 333 rgbValues[cast(Color) 156] = 0xAFFF87; 334 rgbValues[cast(Color) 157] = 0xAFFFAF; 335 rgbValues[cast(Color) 158] = 0xAFFFD7; 336 rgbValues[cast(Color) 159] = 0xAFFFFF; 337 rgbValues[cast(Color) 160] = 0xD70000; 338 rgbValues[cast(Color) 161] = 0xD7005F; 339 rgbValues[cast(Color) 162] = 0xD70087; 340 rgbValues[cast(Color) 163] = 0xD700AF; 341 rgbValues[cast(Color) 164] = 0xD700D7; 342 rgbValues[cast(Color) 165] = 0xD700FF; 343 rgbValues[cast(Color) 166] = 0xD75F00; 344 rgbValues[cast(Color) 167] = 0xD75F5F; 345 rgbValues[cast(Color) 168] = 0xD75F87; 346 rgbValues[cast(Color) 169] = 0xD75FAF; 347 rgbValues[cast(Color) 170] = 0xD75FD7; 348 rgbValues[cast(Color) 171] = 0xD75FFF; 349 rgbValues[cast(Color) 172] = 0xD78700; 350 rgbValues[cast(Color) 173] = 0xD7875F; 351 rgbValues[cast(Color) 174] = 0xD78787; 352 rgbValues[cast(Color) 175] = 0xD787AF; 353 rgbValues[cast(Color) 176] = 0xD787D7; 354 rgbValues[cast(Color) 177] = 0xD787FF; 355 rgbValues[cast(Color) 178] = 0xD7AF00; 356 rgbValues[cast(Color) 179] = 0xD7AF5F; 357 rgbValues[cast(Color) 180] = 0xD7AF87; 358 rgbValues[cast(Color) 181] = 0xD7AFAF; 359 rgbValues[cast(Color) 182] = 0xD7AFD7; 360 rgbValues[cast(Color) 183] = 0xD7AFFF; 361 rgbValues[cast(Color) 184] = 0xD7D700; 362 rgbValues[cast(Color) 185] = 0xD7D75F; 363 rgbValues[cast(Color) 186] = 0xD7D787; 364 rgbValues[cast(Color) 187] = 0xD7D7AF; 365 rgbValues[cast(Color) 188] = 0xD7D7D7; 366 rgbValues[cast(Color) 189] = 0xD7D7FF; 367 rgbValues[cast(Color) 190] = 0xD7FF00; 368 rgbValues[cast(Color) 191] = 0xD7FF5F; 369 rgbValues[cast(Color) 192] = 0xD7FF87; 370 rgbValues[cast(Color) 193] = 0xD7FFAF; 371 rgbValues[cast(Color) 194] = 0xD7FFD7; 372 rgbValues[cast(Color) 195] = 0xD7FFFF; 373 rgbValues[cast(Color) 196] = 0xFF0000; // red 374 rgbValues[cast(Color) 197] = 0xFF005F; 375 rgbValues[cast(Color) 198] = 0xFF0087; 376 rgbValues[cast(Color) 199] = 0xFF00AF; 377 rgbValues[cast(Color) 200] = 0xFF00D7; 378 rgbValues[cast(Color) 201] = 0xFF00FF; // fuchsia 379 rgbValues[cast(Color) 202] = 0xFF5F00; 380 rgbValues[cast(Color) 203] = 0xFF5F5F; 381 rgbValues[cast(Color) 204] = 0xFF5F87; 382 rgbValues[cast(Color) 205] = 0xFF5FAF; 383 rgbValues[cast(Color) 206] = 0xFF5FD7; 384 rgbValues[cast(Color) 207] = 0xFF5FFF; 385 rgbValues[cast(Color) 208] = 0xFF8700; 386 rgbValues[cast(Color) 209] = 0xFF875F; 387 rgbValues[cast(Color) 210] = 0xFF8787; 388 rgbValues[cast(Color) 211] = 0xFF87AF; 389 rgbValues[cast(Color) 212] = 0xFF87D7; 390 rgbValues[cast(Color) 213] = 0xFF87FF; 391 rgbValues[cast(Color) 214] = 0xFFAF00; 392 rgbValues[cast(Color) 215] = 0xFFAF5F; 393 rgbValues[cast(Color) 216] = 0xFFAF87; 394 rgbValues[cast(Color) 217] = 0xFFAFAF; 395 rgbValues[cast(Color) 218] = 0xFFAFD7; 396 rgbValues[cast(Color) 219] = 0xFFAFFF; 397 rgbValues[cast(Color) 220] = 0xFFD700; 398 rgbValues[cast(Color) 221] = 0xFFD75F; 399 rgbValues[cast(Color) 222] = 0xFFD787; 400 rgbValues[cast(Color) 223] = 0xFFD7AF; 401 rgbValues[cast(Color) 224] = 0xFFD7D7; 402 rgbValues[cast(Color) 225] = 0xFFD7FF; 403 rgbValues[cast(Color) 226] = 0xFFFF00; // yellow 404 rgbValues[cast(Color) 227] = 0xFFFF5F; 405 rgbValues[cast(Color) 228] = 0xFFFF87; 406 rgbValues[cast(Color) 229] = 0xFFFFAF; 407 rgbValues[cast(Color) 230] = 0xFFFFD7; 408 rgbValues[cast(Color) 231] = 0xFFFFFF; // white 409 rgbValues[cast(Color) 232] = 0x080808; 410 rgbValues[cast(Color) 233] = 0x121212; 411 rgbValues[cast(Color) 234] = 0x1C1C1C; 412 rgbValues[cast(Color) 235] = 0x262626; 413 rgbValues[cast(Color) 236] = 0x303030; 414 rgbValues[cast(Color) 237] = 0x3A3A3A; 415 rgbValues[cast(Color) 238] = 0x444444; 416 rgbValues[cast(Color) 239] = 0x4E4E4E; 417 rgbValues[cast(Color) 240] = 0x585858; 418 rgbValues[cast(Color) 241] = 0x626262; 419 rgbValues[cast(Color) 242] = 0x6C6C6C; 420 rgbValues[cast(Color) 243] = 0x767676; 421 rgbValues[cast(Color) 244] = 0x808080; // grey 422 rgbValues[cast(Color) 245] = 0x8A8A8A; 423 rgbValues[cast(Color) 246] = 0x949494; 424 rgbValues[cast(Color) 247] = 0x9E9E9E; 425 rgbValues[cast(Color) 248] = 0xA8A8A8; 426 rgbValues[cast(Color) 249] = 0xB2B2B2; 427 rgbValues[cast(Color) 250] = 0xBCBCBC; 428 rgbValues[cast(Color) 251] = 0xC6C6C6; 429 rgbValues[cast(Color) 252] = 0xD0D0D0; 430 rgbValues[cast(Color) 253] = 0xDADADA; 431 rgbValues[cast(Color) 254] = 0xE4E4E4; 432 rgbValues[cast(Color) 255] = 0xEEEEEE; 433 434 palValues[0x000000] = Color.black; 435 palValues[0x800000] = Color.maroon; 436 palValues[0x008000] = Color.green; 437 palValues[0x808000] = Color.olive; 438 palValues[0x000080] = Color.navy; 439 palValues[0x800080] = Color.purple; 440 palValues[0x008080] = Color.teal; 441 palValues[0xC0C0C0] = Color.silver; 442 palValues[0x808080] = Color.gray; 443 palValues[0xFF0000] = Color.red; 444 palValues[0x00FF00] = Color.lime; 445 palValues[0xFFFF00] = Color.yellow; 446 palValues[0x0000FF] = Color.blue; 447 palValues[0xFF00FF] = Color.fuchsia; 448 palValues[0x00FFFF] = Color.aqua; 449 palValues[0xFFFFFF] = Color.white; 450 // palValues[0x000000] = cast(Color) 16; // black 451 palValues[0x00005F] = cast(Color) 17; 452 palValues[0x000087] = cast(Color) 18; 453 palValues[0x0000AF] = cast(Color) 19; 454 palValues[0x0000D7] = cast(Color) 20; 455 // palValues[0x0000FF] = cast(Color) 21; // blue 456 palValues[0x005F00] = cast(Color) 22; 457 palValues[0x005F5F] = cast(Color) 23; 458 palValues[0x005F87] = cast(Color) 24; 459 palValues[0x005FAF] = cast(Color) 25; 460 palValues[0x005FD7] = cast(Color) 26; 461 palValues[0x005FFF] = cast(Color) 27; 462 palValues[0x008700] = cast(Color) 28; 463 palValues[0x00875F] = cast(Color) 29; 464 palValues[0x008787] = cast(Color) 30; 465 palValues[0x0087Af] = cast(Color) 31; 466 palValues[0x0087D7] = cast(Color) 32; 467 palValues[0x0087FF] = cast(Color) 33; 468 palValues[0x00AF00] = cast(Color) 34; 469 palValues[0x00AF5F] = cast(Color) 35; 470 palValues[0x00AF87] = cast(Color) 36; 471 palValues[0x00AFAF] = cast(Color) 37; 472 palValues[0x00AFD7] = cast(Color) 38; 473 palValues[0x00AFFF] = cast(Color) 39; 474 palValues[0x00D700] = cast(Color) 40; 475 palValues[0x00D75F] = cast(Color) 41; 476 palValues[0x00D787] = cast(Color) 42; 477 palValues[0x00D7AF] = cast(Color) 43; 478 palValues[0x00D7D7] = cast(Color) 44; 479 palValues[0x00D7FF] = cast(Color) 45; 480 // palValues[0x00FF00] = cast(Color) 46; // lime 481 palValues[0x00FF5F] = cast(Color) 47; 482 palValues[0x00FF87] = cast(Color) 48; 483 palValues[0x00FFAF] = cast(Color) 49; 484 palValues[0x00FFd7] = cast(Color) 50; 485 // palValues[0x00FFFF] = cast(Color) 51; // aqua 486 palValues[0x5F0000] = cast(Color) 52; 487 palValues[0x5F005F] = cast(Color) 53; 488 palValues[0x5F0087] = cast(Color) 54; 489 palValues[0x5F00AF] = cast(Color) 55; 490 palValues[0x5F00D7] = cast(Color) 56; 491 palValues[0x5F00FF] = cast(Color) 57; 492 palValues[0x5F5F00] = cast(Color) 58; 493 palValues[0x5F5F5F] = cast(Color) 59; 494 palValues[0x5F5F87] = cast(Color) 60; 495 palValues[0x5F5FAF] = cast(Color) 61; 496 palValues[0x5F5FD7] = cast(Color) 62; 497 palValues[0x5F5FFF] = cast(Color) 63; 498 palValues[0x5F8700] = cast(Color) 64; 499 palValues[0x5F875F] = cast(Color) 65; 500 palValues[0x5F8787] = cast(Color) 66; 501 palValues[0x5F87AF] = cast(Color) 67; 502 palValues[0x5F87D7] = cast(Color) 68; 503 palValues[0x5F87FF] = cast(Color) 69; 504 palValues[0x5FAF00] = cast(Color) 70; 505 palValues[0x5FAF5F] = cast(Color) 71; 506 palValues[0x5FAF87] = cast(Color) 72; 507 palValues[0x5FAFAF] = cast(Color) 73; 508 palValues[0x5FAFD7] = cast(Color) 74; 509 palValues[0x5FAFFF] = cast(Color) 75; 510 palValues[0x5FD700] = cast(Color) 76; 511 palValues[0x5FD75F] = cast(Color) 77; 512 palValues[0x5FD787] = cast(Color) 78; 513 palValues[0x5FD7AF] = cast(Color) 79; 514 palValues[0x5FD7D7] = cast(Color) 80; 515 palValues[0x5FD7FF] = cast(Color) 81; 516 palValues[0x5FFF00] = cast(Color) 82; 517 palValues[0x5FFF5F] = cast(Color) 83; 518 palValues[0x5FFF87] = cast(Color) 84; 519 palValues[0x5FFFAF] = cast(Color) 85; 520 palValues[0x5FFFD7] = cast(Color) 86; 521 palValues[0x5FFFFF] = cast(Color) 87; 522 palValues[0x870000] = cast(Color) 88; 523 palValues[0x87005F] = cast(Color) 89; 524 palValues[0x870087] = cast(Color) 90; 525 palValues[0x8700AF] = cast(Color) 91; 526 palValues[0x8700D7] = cast(Color) 92; 527 palValues[0x8700FF] = cast(Color) 93; 528 palValues[0x875F00] = cast(Color) 94; 529 palValues[0x875F5F] = cast(Color) 95; 530 palValues[0x875F87] = cast(Color) 96; 531 palValues[0x875FAF] = cast(Color) 97; 532 palValues[0x875FD7] = cast(Color) 98; 533 palValues[0x875FFF] = cast(Color) 99; 534 palValues[0x878700] = cast(Color) 100; 535 palValues[0x87875F] = cast(Color) 101; 536 palValues[0x878787] = cast(Color) 102; 537 palValues[0x8787AF] = cast(Color) 103; 538 palValues[0x8787D7] = cast(Color) 104; 539 palValues[0x8787FF] = cast(Color) 105; 540 palValues[0x87AF00] = cast(Color) 106; 541 palValues[0x87AF5F] = cast(Color) 107; 542 palValues[0x87AF87] = cast(Color) 108; 543 palValues[0x87AFAF] = cast(Color) 109; 544 palValues[0x87AFD7] = cast(Color) 110; 545 palValues[0x87AFFF] = cast(Color) 111; 546 palValues[0x87D700] = cast(Color) 112; 547 palValues[0x87D75F] = cast(Color) 113; 548 palValues[0x87D787] = cast(Color) 114; 549 palValues[0x87D7AF] = cast(Color) 115; 550 palValues[0x87D7D7] = cast(Color) 116; 551 palValues[0x87D7FF] = cast(Color) 117; 552 palValues[0x87FF00] = cast(Color) 118; 553 palValues[0x87FF5F] = cast(Color) 119; 554 palValues[0x87FF87] = cast(Color) 120; 555 palValues[0x87FFAF] = cast(Color) 121; 556 palValues[0x87FFD7] = cast(Color) 122; 557 palValues[0x87FFFF] = cast(Color) 123; 558 palValues[0xAF0000] = cast(Color) 124; 559 palValues[0xAF005F] = cast(Color) 125; 560 palValues[0xAF0087] = cast(Color) 126; 561 palValues[0xAF00AF] = cast(Color) 127; 562 palValues[0xAF00D7] = cast(Color) 128; 563 palValues[0xAF00FF] = cast(Color) 129; 564 palValues[0xAF5F00] = cast(Color) 130; 565 palValues[0xAF5F5F] = cast(Color) 131; 566 palValues[0xAF5F87] = cast(Color) 132; 567 palValues[0xAF5FAF] = cast(Color) 133; 568 palValues[0xAF5FD7] = cast(Color) 134; 569 palValues[0xAF5FFF] = cast(Color) 135; 570 palValues[0xAF8700] = cast(Color) 136; 571 palValues[0xAF875F] = cast(Color) 137; 572 palValues[0xAF8787] = cast(Color) 138; 573 palValues[0xAF87AF] = cast(Color) 139; 574 palValues[0xAF87D7] = cast(Color) 140; 575 palValues[0xAF87FF] = cast(Color) 141; 576 palValues[0xAFAF00] = cast(Color) 142; 577 palValues[0xAFAF5F] = cast(Color) 143; 578 palValues[0xAFAF87] = cast(Color) 144; 579 palValues[0xAFAFAF] = cast(Color) 145; 580 palValues[0xAFAFD7] = cast(Color) 146; 581 palValues[0xAFAFFF] = cast(Color) 147; 582 palValues[0xAFD700] = cast(Color) 148; 583 palValues[0xAFD75F] = cast(Color) 149; 584 palValues[0xAFD787] = cast(Color) 150; 585 palValues[0xAFD7AF] = cast(Color) 151; 586 palValues[0xAFD7D7] = cast(Color) 152; 587 palValues[0xAFD7FF] = cast(Color) 153; 588 palValues[0xAFFF00] = cast(Color) 154; 589 palValues[0xAFFF5F] = cast(Color) 155; 590 palValues[0xAFFF87] = cast(Color) 156; 591 palValues[0xAFFFAF] = cast(Color) 157; 592 palValues[0xAFFFD7] = cast(Color) 158; 593 palValues[0xAFFFFF] = cast(Color) 159; 594 palValues[0xD70000] = cast(Color) 160; 595 palValues[0xD7005F] = cast(Color) 161; 596 palValues[0xD70087] = cast(Color) 162; 597 palValues[0xD700AF] = cast(Color) 163; 598 palValues[0xD700D7] = cast(Color) 164; 599 palValues[0xD700FF] = cast(Color) 165; 600 palValues[0xD75F00] = cast(Color) 166; 601 palValues[0xD75F5F] = cast(Color) 167; 602 palValues[0xD75F87] = cast(Color) 168; 603 palValues[0xD75FAF] = cast(Color) 169; 604 palValues[0xD75FD7] = cast(Color) 170; 605 palValues[0xD75FFF] = cast(Color) 171; 606 palValues[0xD78700] = cast(Color) 172; 607 palValues[0xD7875F] = cast(Color) 173; 608 palValues[0xD78787] = cast(Color) 174; 609 palValues[0xD787AF] = cast(Color) 175; 610 palValues[0xD787D7] = cast(Color) 176; 611 palValues[0xD787FF] = cast(Color) 177; 612 palValues[0xD7AF00] = cast(Color) 178; 613 palValues[0xD7AF5F] = cast(Color) 179; 614 palValues[0xD7AF87] = cast(Color) 180; 615 palValues[0xD7AFAF] = cast(Color) 181; 616 palValues[0xD7AFD7] = cast(Color) 182; 617 palValues[0xD7AFFF] = cast(Color) 183; 618 palValues[0xD7D700] = cast(Color) 184; 619 palValues[0xD7D75F] = cast(Color) 185; 620 palValues[0xD7D787] = cast(Color) 186; 621 palValues[0xD7D7AF] = cast(Color) 187; 622 palValues[0xD7D7D7] = cast(Color) 188; 623 palValues[0xD7D7FF] = cast(Color) 189; 624 palValues[0xD7FF00] = cast(Color) 190; 625 palValues[0xD7FF5F] = cast(Color) 191; 626 palValues[0xD7FF87] = cast(Color) 192; 627 palValues[0xD7FFAF] = cast(Color) 193; 628 palValues[0xD7FFD7] = cast(Color) 194; 629 palValues[0xD7FFFF] = cast(Color) 195; 630 // palValues[0xFF0000] = cast(Color) 196; // red 631 palValues[0xFF005F] = cast(Color) 197; 632 palValues[0xFF0087] = cast(Color) 198; 633 palValues[0xFF00AF] = cast(Color) 199; 634 palValues[0xFF00D7] = cast(Color) 200; 635 // palValues[0xFF00FF] = cast(Color) 201; // fuchsia 636 palValues[0xFF5F00] = cast(Color) 202; 637 palValues[0xFF5F5F] = cast(Color) 203; 638 palValues[0xFF5F87] = cast(Color) 204; 639 palValues[0xFF5FAF] = cast(Color) 205; 640 palValues[0xFF5FD7] = cast(Color) 206; 641 palValues[0xFF5FFF] = cast(Color) 207; 642 palValues[0xFF8700] = cast(Color) 208; 643 palValues[0xFF875F] = cast(Color) 209; 644 palValues[0xFF8787] = cast(Color) 210; 645 palValues[0xFF87AF] = cast(Color) 211; 646 palValues[0xFF87D7] = cast(Color) 212; 647 palValues[0xFF87FF] = cast(Color) 213; 648 palValues[0xFFAF00] = cast(Color) 214; 649 palValues[0xFFAF5F] = cast(Color) 215; 650 palValues[0xFFAF87] = cast(Color) 216; 651 palValues[0xFFAFAF] = cast(Color) 217; 652 palValues[0xFFAFD7] = cast(Color) 218; 653 palValues[0xFFAFFF] = cast(Color) 219; 654 palValues[0xFFD700] = cast(Color) 220; 655 palValues[0xFFD75F] = cast(Color) 221; 656 palValues[0xFFD787] = cast(Color) 222; 657 palValues[0xFFD7AF] = cast(Color) 223; 658 palValues[0xFFD7D7] = cast(Color) 224; 659 palValues[0xFFD7FF] = cast(Color) 225; 660 // palValues[0xFFFF00] = cast(Color) 226; // yellow 661 palValues[0xFFFF5F] = cast(Color) 227; 662 palValues[0xFFFF87] = cast(Color) 228; 663 palValues[0xFFFFAF] = cast(Color) 229; 664 palValues[0xFFFFD7] = cast(Color) 230; 665 // palValues[0xFFFFFF] = cast(Color) 231; // white 666 palValues[0x080808] = cast(Color) 232; 667 palValues[0x121212] = cast(Color) 233; 668 palValues[0x1C1C1C] = cast(Color) 234; 669 palValues[0x262626] = cast(Color) 235; 670 palValues[0x303030] = cast(Color) 236; 671 palValues[0x3A3A3A] = cast(Color) 237; 672 palValues[0x444444] = cast(Color) 238; 673 palValues[0x4E4E4E] = cast(Color) 239; 674 palValues[0x585858] = cast(Color) 240; 675 palValues[0x626262] = cast(Color) 241; 676 palValues[0x6C6C6C] = cast(Color) 242; 677 palValues[0x767676] = cast(Color) 243; 678 // palValues[0x808080] = cast(Color) 244; // grey 679 palValues[0x8A8A8A] = cast(Color) 245; 680 palValues[0x949494] = cast(Color) 246; 681 palValues[0x9E9E9E] = cast(Color) 247; 682 palValues[0xA8A8A8] = cast(Color) 248; 683 palValues[0xB2B2B2] = cast(Color) 249; 684 palValues[0xBCBCBC] = cast(Color) 250; 685 palValues[0xC6C6C6] = cast(Color) 251; 686 palValues[0xD0D0D0] = cast(Color) 252; 687 palValues[0xDADADA] = cast(Color) 253; 688 palValues[0xE4E4E4] = cast(Color) 254; 689 palValues[0xEEEEEE] = cast(Color) 255; 690 } 691 692 /** 693 * Obtain the numeric value of the RGB for the color. 694 * 695 * Params: 696 * c = a Color 697 * Returns: Numeric RGB value for color, or -1 if it cannot be represented. 698 */ 699 int toHex(Color c) pure @safe 700 { 701 if ((c & Color.isRGB) != 0) 702 { 703 return (c & 0xffffff); 704 } 705 if (c in rgbValues) 706 { 707 return rgbValues[c]; 708 } 709 return (-1); 710 } 711 712 /** 713 * Create a color from RGB values. 714 * 715 * Params: 716 * rgb = hex value, red << 16 | green << 8 | blue 717 * Returns: The associated Color, or Color.invalid if a bad value for rgb was supplied. 718 */ 719 Color fromHex(int rgb) pure @safe 720 { 721 if (rgb < 1 << 24) 722 { 723 return cast(Color) rgb | Color.isRGB; 724 } 725 return Color.invalid; 726 } 727 728 /** 729 * Convert a color to RGB form. This is useful to convert 730 * palette based colors to their full RGB values, which will provide 731 * fidelity when the terminal supports it, but consequently does not 732 * honor terminal preferences for color palettes. 733 * 734 * Params: 735 * c = a valid Color 736 * Returns: An RGB format Color, Color.invalid if it cannot be determined. 737 */ 738 Color toRGB(Color c) pure @safe 739 { 740 if ((c & Color.isRGB) != 0) 741 { 742 return c; 743 } 744 if (c in rgbValues) 745 { 746 return cast(Color) rgbValues[c] | Color.isRGB; 747 } 748 return Color.invalid; 749 } 750 751 /** 752 * Is the color in RGB format? RGB format colors will try to be accurate 753 * on the terminal, and will not honor user preferences. 754 * Params: 755 * c = a valid color 756 * Returns: true if the color is an RGB format color 757 */ 758 bool isRGB(Color c) pure @safe 759 { 760 return (c & Color.isRGB) != 0; 761 } 762 763 /// Return true if the color is valid. 764 bool isValid(Color c) pure @safe 765 { 766 return (c != Color.invalid); 767 } 768 769 /** 770 * Given a color, try to find an associated palette entry for it. 771 * This will try to find the lowest numbered palette entry. 772 * The palette entry might be a higher numbered color than the 773 * terminal can support, if it does not support a 256 color palette. 774 * 775 * Params: 776 * c = a valid Color 777 * numColors = the size of the palette 778 * 779 * Returns: the palette Color closest matching c 780 */ 781 Color toPalette(Color c, int numColors) @safe 782 { 783 import std.functional; 784 785 switch (c) 786 { 787 case Color.reset, Color.invalid: 788 return c; 789 default: 790 return memoize!bestColor(c, numColors); 791 } 792 } 793 794 /// Return true if c1 is darker than c2. 795 bool darker(Color c1, Color c2) @safe 796 { 797 import std.functional; 798 799 auto d1 = memoize!redMean(c1, Color.black); 800 auto d2 = memoize!redMean(c2, Color.black); 801 return (d1 < d2); 802 } 803 804 /** 805 * decompose a color into red, green, and blue values. 806 */ 807 auto decompose(Color c) pure @safe 808 { 809 c = toRGB(c); 810 return Tuple!(int, int, int)((c & 0xff0000) >> 16, ((c & 0xff00) >> 8), (c & 0xff)); 811 } 812 813 /** 814 * decompose a color into red, green, and blue values. 815 */ 816 void decompose(Color c, ref int r, ref int g, ref int b) pure @safe 817 { 818 c = toRGB(c); 819 r = int(c & 0xff0000) >> 16; 820 g = int(c & 0xff00) >> 8; 821 b = int(c & 0xff); 822 } 823 824 /** 825 * Name returns W3C name or an empty string if no arguments 826 * if passed true as an argument it will falls back to 827 * the CSS hex string if no W3C name found '#ABCDEF' 828 */ 829 string name(Color c, bool css = false) pure @safe 830 { 831 foreach (name, color; colorsByName) 832 { 833 if (c == color) 834 { 835 return name; 836 } 837 } 838 if (css) 839 { 840 return c.css(); 841 } 842 return ""; 843 } 844 845 string css(Color c) pure @safe 846 { 847 if (!c.isValid) 848 { 849 return ""; 850 } 851 return format("#%06X", c.toHex()); 852 } 853 854 unittest 855 { 856 assert(toPalette(Color.red, 16) == Color.red); 857 assert(toPalette(cast(Color) 0x00FF00 | Color.isRGB, 16) == Color.lime); 858 assert(toHex(Color.invalid) == -1); 859 assert(toRGB(cast(Color) 512) == Color.invalid); 860 assert(toRGB(Color.reset) == Color.invalid); 861 assert(fromHex(cast(int) Color.reset) == Color.invalid); 862 for (int i = 0; i < 256; i++) 863 { 864 auto r = toHex(cast(Color) i); 865 assert(r >= 0); 866 auto c = fromHex(r); 867 assert(toRGB(c) == c); 868 assert(c != Color.invalid); 869 auto p = toPalette(c, 256); 870 assert(p != Color.invalid); 871 if (i < 16) 872 { 873 assert(p == i); 874 } 875 else 876 { 877 assert(p < 256); 878 if (p > 15) // sometimes we map to a lower palette color 879 { 880 assert(p == i); 881 } 882 } 883 } 884 for (Color c = Color.black; c <= Color.white; c++) 885 { 886 assert(toPalette(toRGB(c), 256) == c); 887 } 888 assert(decompose(Color.yellowGreen)[0] == 0x9a); 889 assert(decompose(Color.yellowGreen)[1] == 0xcd); 890 assert(decompose(Color.yellowGreen)[2] == 0x32); 891 assert(decompose(Color.red)[0] == 0xff); 892 assert(decompose(Color.red)[1] == 0); 893 assert(decompose(Color.red)[2] == 0); 894 895 assert(Color.red.name == "red"); 896 assert(Color.darkKhaki.name == "darkkhaki"); 897 assert(Color.red.css == "#FF0000"); 898 assert(Color.red.toRGB.name(true) == "#FF0000"); 899 } 900 901 private long redMean(Color c1, Color c2) pure @safe 902 { 903 int r1, r2, g1, g2, b1, b2; 904 decompose(c1, r1, g1, b1); 905 decompose(c2, r2, g2, b2); 906 long ar = (r1 + r2) / 2; 907 long dr = (r1 - r2); 908 long dg = (g1 - g2); 909 long db = (b1 - b2); 910 911 long dist; 912 913 // see https://en.wikipedia.org/wiki/Color_difference 914 dist = ((2 + ar / 256) * dr * dr) + (4 * dg * dg) + ((2 + ((255 - ar) / 256)) * db * db); 915 916 // not bothering with the square root, since we are just comparing values 917 return dist; 918 } 919 920 private Color bestColor(Color c, int numColors) pure @safe 921 { 922 // this is an expensive operation, so you really want 923 // to memoize it. 924 long abs(long a) pure 925 { 926 return a >= 0 ? a : -a; 927 } 928 929 c = toRGB(c); 930 if (c == Color.invalid) 931 { 932 return c; 933 } 934 935 // look for a perfect fit first before we start doing hard math 936 auto hex = toHex(c); 937 if ((hex in palValues) && (palValues[hex] <= numColors)) 938 { 939 return (palValues[hex]); 940 } 941 942 if (numColors == 0) 943 { 944 auto d1 = redMean(c, Color.black); 945 auto d2 = redMean(c, Color.white); 946 return abs(d1) < abs(d2) ? Color.black : Color.white; 947 } 948 if (numColors > 256) 949 { 950 numColors = 256; 951 } 952 auto bestDist = long.max; 953 auto bestColor = Color.invalid; 954 for (Color pal = Color.black; pal < numColors; pal++) 955 { 956 auto d = redMean(c, toRGB(pal)); 957 if (d < bestDist) 958 { 959 bestDist = d; 960 bestColor = pal; 961 } 962 } 963 964 return (bestColor); 965 } 966 967 unittest 968 { 969 import std.stdio; 970 971 Color v; 972 assert(v == Color.invalid); 973 assert(bestColor(Color.red, 16) == Color.red); 974 assert(bestColor(Color.red, 256) == Color.red); 975 assert(bestColor(Color.paleGreen, 256) == cast(Color) 120); 976 assert(bestColor(Color.darkSlateBlue, 256) == cast(Color) 60); 977 assert(bestColor(fromHex(0xfe0000), 16) == Color.red); 978 } 979 980 unittest 981 { 982 import std.stdio; 983 984 assert(toPalette(Color.red, 16) == Color.red); 985 assert(toPalette(Color.red, 256) == Color.red); 986 assert(toPalette(Color.paleGreen, 256) == cast(Color) 120); 987 assert(toPalette(Color.darkSlateBlue, 256) == cast(Color) 60); 988 assert(toPalette(fromHex(0xfe0000), 16) == Color.red); 989 } 990 991 // ColorNames holds the written names of colors. Useful to present a list of 992 // recognized named colors. 993 static immutable Color[string] colorsByName; 994 995 shared static this() @safe 996 { 997 colorsByName = [ 998 "black": Color.black, 999 "maroon": Color.maroon, 1000 "green": Color.green, 1001 "olive": Color.olive, 1002 "navy": Color.navy, 1003 "purple": Color.purple, 1004 "teal": Color.teal, 1005 "silver": Color.silver, 1006 "gray": Color.gray, 1007 "red": Color.red, 1008 "lime": Color.lime, 1009 "yellow": Color.yellow, 1010 "blue": Color.blue, 1011 "fuchsia": Color.fuchsia, 1012 "aqua": Color.aqua, 1013 "white": Color.white, 1014 "aliceblue": Color.aliceBlue, 1015 "antiquewhite": Color.antiqueWhite, 1016 "aquamarine": Color.aquamarine, 1017 "azure": Color.azure, 1018 "beige": Color.beige, 1019 "bisque": Color.bisque, 1020 "blanchedalmond": Color.blanchedAlmond, 1021 "blueviolet": Color.blueViolet, 1022 "brown": Color.brown, 1023 "burlywood": Color.burlyWood, 1024 "cadetblue": Color.cadetBlue, 1025 "chartreuse": Color.chartreuse, 1026 "chocolate": Color.chocolate, 1027 "coral": Color.coral, 1028 "cornflowerblue": Color.cornflowerBlue, 1029 "cornsilk": Color.cornsilk, 1030 "crimson": Color.crimson, 1031 "darkblue": Color.darkBlue, 1032 "darkcyan": Color.darkCyan, 1033 "darkgoldenrod": Color.darkGoldenrod, 1034 "darkgray": Color.darkGray, 1035 "darkgreen": Color.darkGreen, 1036 "darkkhaki": Color.darkKhaki, 1037 "darkmagenta": Color.darkMagenta, 1038 "darkolivegreen": Color.darkOliveGreen, 1039 "darkorange": Color.darkOrange, 1040 "darkorchid": Color.darkOrchid, 1041 "darkred": Color.darkRed, 1042 "darksalmon": Color.darkSalmon, 1043 "darkseagreen": Color.darkSeaGreen, 1044 "darkslateblue": Color.darkSlateBlue, 1045 "darkslategray": Color.darkSlateGray, 1046 "darkturquoise": Color.darkTurquoise, 1047 "darkviolet": Color.darkViolet, 1048 "deeppink": Color.deepPink, 1049 "deepskyblue": Color.deepSkyBlue, 1050 "dimgray": Color.dimGray, 1051 "dodgerblue": Color.dodgerBlue, 1052 "firebrick": Color.fireBrick, 1053 "floralwhite": Color.floralWhite, 1054 "forestgreen": Color.forestGreen, 1055 "gainsboro": Color.gainsboro, 1056 "ghostwhite": Color.ghostWhite, 1057 "gold": Color.gold, 1058 "goldenrod": Color.goldenrod, 1059 "greenyellow": Color.greenYellow, 1060 "honeydew": Color.honeydew, 1061 "hotpink": Color.hotPink, 1062 "indianred": Color.indianRed, 1063 "indigo": Color.indigo, 1064 "ivory": Color.ivory, 1065 "khaki": Color.khaki, 1066 "lavender": Color.lavender, 1067 "lavenderblush": Color.lavenderBlush, 1068 "lawngreen": Color.lawnGreen, 1069 "lemonchiffon": Color.lemonChiffon, 1070 "lightblue": Color.lightBlue, 1071 "lightcoral": Color.lightCoral, 1072 "lightcyan": Color.lightCyan, 1073 "lightgoldenrodyellow": Color.lightGoldenrodYellow, 1074 "lightgray": Color.lightGray, 1075 "lightgreen": Color.lightGreen, 1076 "lightpink": Color.lightPink, 1077 "lightsalmon": Color.lightSalmon, 1078 "lightseagreen": Color.lightSeaGreen, 1079 "lightskyblue": Color.lightSkyBlue, 1080 "lightslategray": Color.lightSlateGray, 1081 "lightsteelblue": Color.lightSteelBlue, 1082 "lightyellow": Color.lightYellow, 1083 "limegreen": Color.limeGreen, 1084 "linen": Color.linen, 1085 "mediumaquamarine": Color.mediumAquamarine, 1086 "mediumblue": Color.mediumBlue, 1087 "mediumorchid": Color.mediumOrchid, 1088 "mediumpurple": Color.mediumPurple, 1089 "mediumseagreen": Color.mediumSeaGreen, 1090 "mediumslateblue": Color.mediumSlateBlue, 1091 "mediumspringgreen": Color.mediumSpringGreen, 1092 "mediumturquoise": Color.mediumTurquoise, 1093 "mediumvioletred": Color.mediumVioletRed, 1094 "midnightblue": Color.midnightBlue, 1095 "mintcream": Color.mintCream, 1096 "mistyrose": Color.mistyRose, 1097 "moccasin": Color.moccasin, 1098 "navajowhite": Color.navajoWhite, 1099 "oldlace": Color.oldLace, 1100 "olivedrab": Color.oliveDrab, 1101 "orange": Color.orange, 1102 "orangered": Color.orangeRed, 1103 "orchid": Color.orchid, 1104 "palegoldenrod": Color.paleGoldenrod, 1105 "palegreen": Color.paleGreen, 1106 "paleturquoise": Color.paleTurquoise, 1107 "palevioletred": Color.paleVioletRed, 1108 "papayawhip": Color.papayaWhip, 1109 "peachpuff": Color.peachPuff, 1110 "peru": Color.peru, 1111 "pink": Color.pink, 1112 "plum": Color.plum, 1113 "powderblue": Color.powderBlue, 1114 "rebeccapurple": Color.rebeccaPurple, 1115 "rosybrown": Color.rosyBrown, 1116 "royalblue": Color.royalBlue, 1117 "saddlebrown": Color.saddleBrown, 1118 "salmon": Color.salmon, 1119 "sandybrown": Color.sandyBrown, 1120 "seagreen": Color.seaGreen, 1121 "seashell": Color.seashell, 1122 "sienna": Color.sienna, 1123 "skyblue": Color.skyBlue, 1124 "slateblue": Color.slateBlue, 1125 "slategray": Color.slateGray, 1126 "snow": Color.snow, 1127 "springgreen": Color.springGreen, 1128 "steelblue": Color.steelBlue, 1129 "tan": Color.tan, 1130 "thistle": Color.thistle, 1131 "tomato": Color.tomato, 1132 "turquoise": Color.turquoise, 1133 "violet": Color.violet, 1134 "wheat": Color.wheat, 1135 "whitesmoke": Color.whiteSmoke, 1136 "yellowgreen": Color.yellowGreen, 1137 "grey": Color.gray, 1138 "dimgrey": Color.dimGray, 1139 "darkgrey": Color.darkGray, 1140 "darkslategrey": Color.darkSlateGray, 1141 "lightgrey": Color.lightGray, 1142 "lightslategrey": Color.lightSlateGray, 1143 "slategrey": Color.slateGray, 1144 1145 "reset": Color.reset, // actually the terminal default 1146 ]; 1147 }