colors.nim 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #
  2. # Nim's Runtime Library
  3. # (c) Copyright 2010 Andreas Rumpf
  4. #
  5. # See the file "copying.txt", included in this
  6. # distribution, for details about the copyright.
  7. #
  8. ## This module implements color handling for Nim. It is used by
  9. ## the ``graphics`` module.
  10. import strutils
  11. from algorithm import binarySearch
  12. type
  13. Color* = distinct int ## a color stored as RGB
  14. proc `==` *(a, b: Color): bool {.borrow.}
  15. ## compares two colors.
  16. template extract(a: Color, r, g, b: untyped) =
  17. var r = a.int shr 16 and 0xff
  18. var g = a.int shr 8 and 0xff
  19. var b = a.int and 0xff
  20. template rawRGB(r, g, b: int): Color =
  21. Color(r shl 16 or g shl 8 or b)
  22. template colorOp(op): Color =
  23. extract(a, ar, ag, ab)
  24. extract(b, br, bg, bb)
  25. rawRGB(op(ar, br), op(ag, bg), op(ab, bb))
  26. proc satPlus(a, b: int): int {.inline.} =
  27. result = a +% b
  28. if result > 255: result = 255
  29. proc satMinus(a, b: int): int {.inline.} =
  30. result = a -% b
  31. if result < 0: result = 0
  32. proc `+`*(a, b: Color): Color =
  33. ## adds two colors: This uses saturated artithmetic, so that each color
  34. ## component cannot overflow (255 is used as a maximum).
  35. colorOp(satPlus)
  36. proc `-`*(a, b: Color): Color =
  37. ## subtracts two colors: This uses saturated artithmetic, so that each color
  38. ## component cannot overflow (255 is used as a maximum).
  39. colorOp(satMinus)
  40. proc extractRGB*(a: Color): tuple[r, g, b: range[0..255]] =
  41. ## extracts the red/green/blue components of the color `a`.
  42. result.r = a.int shr 16 and 0xff
  43. result.g = a.int shr 8 and 0xff
  44. result.b = a.int and 0xff
  45. proc intensity*(a: Color, f: float): Color =
  46. ## returns `a` with intensity `f`. `f` should be a float from 0.0 (completely
  47. ## dark) to 1.0 (full color intensity).
  48. var r = toInt(toFloat(a.int shr 16 and 0xff) * f)
  49. var g = toInt(toFloat(a.int shr 8 and 0xff) * f)
  50. var b = toInt(toFloat(a.int and 0xff) * f)
  51. if r >% 255: r = 255
  52. if g >% 255: g = 255
  53. if b >% 255: b = 255
  54. result = rawRGB(r, g, b)
  55. template mix*(a, b: Color, fn: untyped): untyped =
  56. ## uses `fn` to mix the colors `a` and `b`. `fn` is invoked for each component
  57. ## R, G, and B. This is a template because `fn` should be inlined and the
  58. ## compiler cannot inline proc pointers yet. If `fn`'s result is not in the
  59. ## range[0..255], it will be saturated to be so.
  60. template `><` (x: untyped): untyped =
  61. # keep it in the range 0..255
  62. block:
  63. var y = x # eval only once
  64. if y >% 255:
  65. y = if y < 0: 0 else: 255
  66. y
  67. (bind extract)(a, ar, ag, ab)
  68. (bind extract)(b, br, bg, bb)
  69. (bind rawRGB)(><fn(ar, br), ><fn(ag, bg), ><fn(ab, bb))
  70. const
  71. colAliceBlue* = Color(0xF0F8FF)
  72. colAntiqueWhite* = Color(0xFAEBD7)
  73. colAqua* = Color(0x00FFFF)
  74. colAquamarine* = Color(0x7FFFD4)
  75. colAzure* = Color(0xF0FFFF)
  76. colBeige* = Color(0xF5F5DC)
  77. colBisque* = Color(0xFFE4C4)
  78. colBlack* = Color(0x000000)
  79. colBlanchedAlmond* = Color(0xFFEBCD)
  80. colBlue* = Color(0x0000FF)
  81. colBlueViolet* = Color(0x8A2BE2)
  82. colBrown* = Color(0xA52A2A)
  83. colBurlyWood* = Color(0xDEB887)
  84. colCadetBlue* = Color(0x5F9EA0)
  85. colChartreuse* = Color(0x7FFF00)
  86. colChocolate* = Color(0xD2691E)
  87. colCoral* = Color(0xFF7F50)
  88. colCornflowerBlue* = Color(0x6495ED)
  89. colCornsilk* = Color(0xFFF8DC)
  90. colCrimson* = Color(0xDC143C)
  91. colCyan* = Color(0x00FFFF)
  92. colDarkBlue* = Color(0x00008B)
  93. colDarkCyan* = Color(0x008B8B)
  94. colDarkGoldenRod* = Color(0xB8860B)
  95. colDarkGray* = Color(0xA9A9A9)
  96. colDarkGreen* = Color(0x006400)
  97. colDarkKhaki* = Color(0xBDB76B)
  98. colDarkMagenta* = Color(0x8B008B)
  99. colDarkOliveGreen* = Color(0x556B2F)
  100. colDarkorange* = Color(0xFF8C00)
  101. colDarkOrchid* = Color(0x9932CC)
  102. colDarkRed* = Color(0x8B0000)
  103. colDarkSalmon* = Color(0xE9967A)
  104. colDarkSeaGreen* = Color(0x8FBC8F)
  105. colDarkSlateBlue* = Color(0x483D8B)
  106. colDarkSlateGray* = Color(0x2F4F4F)
  107. colDarkTurquoise* = Color(0x00CED1)
  108. colDarkViolet* = Color(0x9400D3)
  109. colDeepPink* = Color(0xFF1493)
  110. colDeepSkyBlue* = Color(0x00BFFF)
  111. colDimGray* = Color(0x696969)
  112. colDodgerBlue* = Color(0x1E90FF)
  113. colFireBrick* = Color(0xB22222)
  114. colFloralWhite* = Color(0xFFFAF0)
  115. colForestGreen* = Color(0x228B22)
  116. colFuchsia* = Color(0xFF00FF)
  117. colGainsboro* = Color(0xDCDCDC)
  118. colGhostWhite* = Color(0xF8F8FF)
  119. colGold* = Color(0xFFD700)
  120. colGoldenRod* = Color(0xDAA520)
  121. colGray* = Color(0x808080)
  122. colGreen* = Color(0x008000)
  123. colGreenYellow* = Color(0xADFF2F)
  124. colHoneyDew* = Color(0xF0FFF0)
  125. colHotPink* = Color(0xFF69B4)
  126. colIndianRed* = Color(0xCD5C5C)
  127. colIndigo* = Color(0x4B0082)
  128. colIvory* = Color(0xFFFFF0)
  129. colKhaki* = Color(0xF0E68C)
  130. colLavender* = Color(0xE6E6FA)
  131. colLavenderBlush* = Color(0xFFF0F5)
  132. colLawnGreen* = Color(0x7CFC00)
  133. colLemonChiffon* = Color(0xFFFACD)
  134. colLightBlue* = Color(0xADD8E6)
  135. colLightCoral* = Color(0xF08080)
  136. colLightCyan* = Color(0xE0FFFF)
  137. colLightGoldenRodYellow* = Color(0xFAFAD2)
  138. colLightGrey* = Color(0xD3D3D3)
  139. colLightGreen* = Color(0x90EE90)
  140. colLightPink* = Color(0xFFB6C1)
  141. colLightSalmon* = Color(0xFFA07A)
  142. colLightSeaGreen* = Color(0x20B2AA)
  143. colLightSkyBlue* = Color(0x87CEFA)
  144. colLightSlateGray* = Color(0x778899)
  145. colLightSteelBlue* = Color(0xB0C4DE)
  146. colLightYellow* = Color(0xFFFFE0)
  147. colLime* = Color(0x00FF00)
  148. colLimeGreen* = Color(0x32CD32)
  149. colLinen* = Color(0xFAF0E6)
  150. colMagenta* = Color(0xFF00FF)
  151. colMaroon* = Color(0x800000)
  152. colMediumAquaMarine* = Color(0x66CDAA)
  153. colMediumBlue* = Color(0x0000CD)
  154. colMediumOrchid* = Color(0xBA55D3)
  155. colMediumPurple* = Color(0x9370D8)
  156. colMediumSeaGreen* = Color(0x3CB371)
  157. colMediumSlateBlue* = Color(0x7B68EE)
  158. colMediumSpringGreen* = Color(0x00FA9A)
  159. colMediumTurquoise* = Color(0x48D1CC)
  160. colMediumVioletRed* = Color(0xC71585)
  161. colMidnightBlue* = Color(0x191970)
  162. colMintCream* = Color(0xF5FFFA)
  163. colMistyRose* = Color(0xFFE4E1)
  164. colMoccasin* = Color(0xFFE4B5)
  165. colNavajoWhite* = Color(0xFFDEAD)
  166. colNavy* = Color(0x000080)
  167. colOldLace* = Color(0xFDF5E6)
  168. colOlive* = Color(0x808000)
  169. colOliveDrab* = Color(0x6B8E23)
  170. colOrange* = Color(0xFFA500)
  171. colOrangeRed* = Color(0xFF4500)
  172. colOrchid* = Color(0xDA70D6)
  173. colPaleGoldenRod* = Color(0xEEE8AA)
  174. colPaleGreen* = Color(0x98FB98)
  175. colPaleTurquoise* = Color(0xAFEEEE)
  176. colPaleVioletRed* = Color(0xD87093)
  177. colPapayaWhip* = Color(0xFFEFD5)
  178. colPeachPuff* = Color(0xFFDAB9)
  179. colPeru* = Color(0xCD853F)
  180. colPink* = Color(0xFFC0CB)
  181. colPlum* = Color(0xDDA0DD)
  182. colPowderBlue* = Color(0xB0E0E6)
  183. colPurple* = Color(0x800080)
  184. colRed* = Color(0xFF0000)
  185. colRosyBrown* = Color(0xBC8F8F)
  186. colRoyalBlue* = Color(0x4169E1)
  187. colSaddleBrown* = Color(0x8B4513)
  188. colSalmon* = Color(0xFA8072)
  189. colSandyBrown* = Color(0xF4A460)
  190. colSeaGreen* = Color(0x2E8B57)
  191. colSeaShell* = Color(0xFFF5EE)
  192. colSienna* = Color(0xA0522D)
  193. colSilver* = Color(0xC0C0C0)
  194. colSkyBlue* = Color(0x87CEEB)
  195. colSlateBlue* = Color(0x6A5ACD)
  196. colSlateGray* = Color(0x708090)
  197. colSnow* = Color(0xFFFAFA)
  198. colSpringGreen* = Color(0x00FF7F)
  199. colSteelBlue* = Color(0x4682B4)
  200. colTan* = Color(0xD2B48C)
  201. colTeal* = Color(0x008080)
  202. colThistle* = Color(0xD8BFD8)
  203. colTomato* = Color(0xFF6347)
  204. colTurquoise* = Color(0x40E0D0)
  205. colViolet* = Color(0xEE82EE)
  206. colWheat* = Color(0xF5DEB3)
  207. colWhite* = Color(0xFFFFFF)
  208. colWhiteSmoke* = Color(0xF5F5F5)
  209. colYellow* = Color(0xFFFF00)
  210. colYellowGreen* = Color(0x9ACD32)
  211. colorNames = [
  212. ("aliceblue", colAliceBlue),
  213. ("antiquewhite", colAntiqueWhite),
  214. ("aqua", colAqua),
  215. ("aquamarine", colAquamarine),
  216. ("azure", colAzure),
  217. ("beige", colBeige),
  218. ("bisque", colBisque),
  219. ("black", colBlack),
  220. ("blanchedalmond", colBlanchedAlmond),
  221. ("blue", colBlue),
  222. ("blueviolet", colBlueViolet),
  223. ("brown", colBrown),
  224. ("burlywood", colBurlyWood),
  225. ("cadetblue", colCadetBlue),
  226. ("chartreuse", colChartreuse),
  227. ("chocolate", colChocolate),
  228. ("coral", colCoral),
  229. ("cornflowerblue", colCornflowerBlue),
  230. ("cornsilk", colCornsilk),
  231. ("crimson", colCrimson),
  232. ("cyan", colCyan),
  233. ("darkblue", colDarkBlue),
  234. ("darkcyan", colDarkCyan),
  235. ("darkgoldenrod", colDarkGoldenRod),
  236. ("darkgray", colDarkGray),
  237. ("darkgreen", colDarkGreen),
  238. ("darkkhaki", colDarkKhaki),
  239. ("darkmagenta", colDarkMagenta),
  240. ("darkolivegreen", colDarkOliveGreen),
  241. ("darkorange", colDarkorange),
  242. ("darkorchid", colDarkOrchid),
  243. ("darkred", colDarkRed),
  244. ("darksalmon", colDarkSalmon),
  245. ("darkseagreen", colDarkSeaGreen),
  246. ("darkslateblue", colDarkSlateBlue),
  247. ("darkslategray", colDarkSlateGray),
  248. ("darkturquoise", colDarkTurquoise),
  249. ("darkviolet", colDarkViolet),
  250. ("deeppink", colDeepPink),
  251. ("deepskyblue", colDeepSkyBlue),
  252. ("dimgray", colDimGray),
  253. ("dodgerblue", colDodgerBlue),
  254. ("firebrick", colFireBrick),
  255. ("floralwhite", colFloralWhite),
  256. ("forestgreen", colForestGreen),
  257. ("fuchsia", colFuchsia),
  258. ("gainsboro", colGainsboro),
  259. ("ghostwhite", colGhostWhite),
  260. ("gold", colGold),
  261. ("goldenrod", colGoldenRod),
  262. ("gray", colGray),
  263. ("green", colGreen),
  264. ("greenyellow", colGreenYellow),
  265. ("honeydew", colHoneyDew),
  266. ("hotpink", colHotPink),
  267. ("indianred", colIndianRed),
  268. ("indigo", colIndigo),
  269. ("ivory", colIvory),
  270. ("khaki", colKhaki),
  271. ("lavender", colLavender),
  272. ("lavenderblush", colLavenderBlush),
  273. ("lawngreen", colLawnGreen),
  274. ("lemonchiffon", colLemonChiffon),
  275. ("lightblue", colLightBlue),
  276. ("lightcoral", colLightCoral),
  277. ("lightcyan", colLightCyan),
  278. ("lightgoldenrodyellow", colLightGoldenRodYellow),
  279. ("lightgrey", colLightGrey),
  280. ("lightgreen", colLightGreen),
  281. ("lightpink", colLightPink),
  282. ("lightsalmon", colLightSalmon),
  283. ("lightseagreen", colLightSeaGreen),
  284. ("lightskyblue", colLightSkyBlue),
  285. ("lightslategray", colLightSlateGray),
  286. ("lightsteelblue", colLightSteelBlue),
  287. ("lightyellow", colLightYellow),
  288. ("lime", colLime),
  289. ("limegreen", colLimeGreen),
  290. ("linen", colLinen),
  291. ("magenta", colMagenta),
  292. ("maroon", colMaroon),
  293. ("mediumaquamarine", colMediumAquaMarine),
  294. ("mediumblue", colMediumBlue),
  295. ("mediumorchid", colMediumOrchid),
  296. ("mediumpurple", colMediumPurple),
  297. ("mediumseagreen", colMediumSeaGreen),
  298. ("mediumslateblue", colMediumSlateBlue),
  299. ("mediumspringgreen", colMediumSpringGreen),
  300. ("mediumturquoise", colMediumTurquoise),
  301. ("mediumvioletred", colMediumVioletRed),
  302. ("midnightblue", colMidnightBlue),
  303. ("mintcream", colMintCream),
  304. ("mistyrose", colMistyRose),
  305. ("moccasin", colMoccasin),
  306. ("navajowhite", colNavajoWhite),
  307. ("navy", colNavy),
  308. ("oldlace", colOldLace),
  309. ("olive", colOlive),
  310. ("olivedrab", colOliveDrab),
  311. ("orange", colOrange),
  312. ("orangered", colOrangeRed),
  313. ("orchid", colOrchid),
  314. ("palegoldenrod", colPaleGoldenRod),
  315. ("palegreen", colPaleGreen),
  316. ("paleturquoise", colPaleTurquoise),
  317. ("palevioletred", colPaleVioletRed),
  318. ("papayawhip", colPapayaWhip),
  319. ("peachpuff", colPeachPuff),
  320. ("peru", colPeru),
  321. ("pink", colPink),
  322. ("plum", colPlum),
  323. ("powderblue", colPowderBlue),
  324. ("purple", colPurple),
  325. ("red", colRed),
  326. ("rosybrown", colRosyBrown),
  327. ("royalblue", colRoyalBlue),
  328. ("saddlebrown", colSaddleBrown),
  329. ("salmon", colSalmon),
  330. ("sandybrown", colSandyBrown),
  331. ("seagreen", colSeaGreen),
  332. ("seashell", colSeaShell),
  333. ("sienna", colSienna),
  334. ("silver", colSilver),
  335. ("skyblue", colSkyBlue),
  336. ("slateblue", colSlateBlue),
  337. ("slategray", colSlateGray),
  338. ("snow", colSnow),
  339. ("springgreen", colSpringGreen),
  340. ("steelblue", colSteelBlue),
  341. ("tan", colTan),
  342. ("teal", colTeal),
  343. ("thistle", colThistle),
  344. ("tomato", colTomato),
  345. ("turquoise", colTurquoise),
  346. ("violet", colViolet),
  347. ("wheat", colWheat),
  348. ("white", colWhite),
  349. ("whitesmoke", colWhiteSmoke),
  350. ("yellow", colYellow),
  351. ("yellowgreen", colYellowGreen)]
  352. proc `$`*(c: Color): string =
  353. ## converts a color into its textual representation. Example: ``#00FF00``.
  354. result = '#' & toHex(int(c), 6)
  355. proc colorNameCmp(x: tuple[name: string, col: Color], y: string): int =
  356. result = cmpIgnoreCase(x.name, y)
  357. proc parseColor*(name: string): Color =
  358. ## parses `name` to a color value. If no valid color could be
  359. ## parsed ``ValueError`` is raised. Case insensitive.
  360. if name[0] == '#':
  361. result = Color(parseHexInt(name))
  362. else:
  363. var idx = binarySearch(colorNames, name, colorNameCmp)
  364. if idx < 0: raise newException(ValueError, "unknown color: " & name)
  365. result = colorNames[idx][1]
  366. proc isColor*(name: string): bool =
  367. ## returns true if `name` is a known color name or a hexadecimal color
  368. ## prefixed with ``#``. Case insensitive.
  369. if name[0] == '#':
  370. for i in 1 .. name.len-1:
  371. if name[i] notin {'0'..'9', 'a'..'f', 'A'..'F'}: return false
  372. result = true
  373. else:
  374. result = binarySearch(colorNames, name, colorNameCmp) >= 0
  375. proc rgb*(r, g, b: range[0..255]): Color =
  376. ## constructs a color from RGB values.
  377. result = rawRGB(r, g, b)