You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 19 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * libcucul Canvas for ultrafast compositing of Unicode letters
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. /*
  14. * This file contains functions for converting colour values between
  15. * various colourspaces.
  16. */
  17. #include "config.h"
  18. #include "common.h"
  19. #if defined(HAVE_ERRNO_H)
  20. # include <errno.h>
  21. #endif
  22. #include "cucul.h"
  23. #include "cucul_internals.h"
  24. /* Legacy stuff from old versions */
  25. int cucul_set_color(cucul_canvas_t *, unsigned char, unsigned char);
  26. int cucul_set_truecolor(cucul_canvas_t *, unsigned int, unsigned int);
  27. /* RGB colours for the ANSI palette. There is no real standard, so we
  28. * use the same values as gnome-terminal. The 7th colour (brown) is a bit
  29. * special: 0xfa50 instead of 0xfaa0. */
  30. static const uint16_t ansitab[16] =
  31. {
  32. 0xf000, 0xf00a, 0xf0a0, 0xf0aa, 0xfa00, 0xfa0a, 0xfa50, 0xfaaa,
  33. 0xf555, 0xf55f, 0xf5f5, 0xf5ff, 0xff55, 0xff5f, 0xfff5, 0xffff,
  34. };
  35. /** \brief Set the default character attribute.
  36. *
  37. * Set the default character attribute for drawing. Attributes define
  38. * foreground and background colour, transparency, bold, italics and
  39. * underline styles, as well as blink. String functions such as
  40. * caca_printf() and graphical primitive functions such as caca_draw_line()
  41. * will use this attribute.
  42. *
  43. * The attribute value is a 32-bit integer as returned by cucul_get_attr().
  44. * For more user-friendly versions of this function, see cucul_set_attr_ansi()
  45. * and cucul_set_attr_argb().
  46. *
  47. * If an error occurs, -1 is returned and \b errno is set accordingly:
  48. * - \c EINVAL The attribute value is out of the 32-bit range.
  49. *
  50. * \param cv A handle to the libcucul canvas.
  51. * \param attr The requested attribute value.
  52. * \return 0 in case of success, -1 if an error occurred.
  53. */
  54. int cucul_set_attr(cucul_canvas_t *cv, unsigned long int attr)
  55. {
  56. if(sizeof(unsigned long int) > sizeof(uint32_t) && attr > 0xffffffff)
  57. {
  58. #if defined(HAVE_ERRNO_H)
  59. errno = EINVAL;
  60. #endif
  61. return -1;
  62. }
  63. cv->curattr = attr;
  64. return 0;
  65. }
  66. /** \brief Set the default colour pair and text style (ANSI version).
  67. *
  68. * Set the default ANSI colour pair and text style for drawing. String
  69. * functions such as caca_printf() and graphical primitive functions such as
  70. * caca_draw_line() will use these attributes.
  71. *
  72. * Color values are those defined in cucul.h, such as CUCUL_COLOR_RED
  73. * or CUCUL_COLOR_TRANSPARENT.
  74. *
  75. * Style values are those defined in cucul.h, such as CUCUL_STYLE_UNDERLINE
  76. * or CUCUL_STYLE_BLINK. The values can be ORed to set several styles at
  77. * the same time.
  78. *
  79. * If an error occurs, -1 is returned and \b errno is set accordingly:
  80. * - \c EINVAL The colour values and/or the style mask are invalid.
  81. *
  82. * \param cv A handle to the libcucul canvas.
  83. * \param fg The requested foreground colour.
  84. * \param bg The requested background colour.
  85. * \param style The requested text styles.
  86. * \return 0 in case of success, -1 if an error occurred.
  87. */
  88. int cucul_set_attr_ansi(cucul_canvas_t *cv, unsigned char fg, unsigned char bg,
  89. unsigned char style)
  90. {
  91. uint32_t attr;
  92. if(fg > 0x20 || bg > 0x20 || style > 0x0f)
  93. {
  94. #if defined(HAVE_ERRNO_H)
  95. errno = EINVAL;
  96. #endif
  97. return -1;
  98. }
  99. attr = ((uint32_t)bg << 20) | ((uint32_t)fg << 4);
  100. if(style)
  101. attr |= (0x02004801 * style) & 0x10011001;
  102. cv->curattr = attr;
  103. return 0;
  104. }
  105. /* Legacy function for old programs */
  106. int cucul_set_color(cucul_canvas_t *cv, unsigned char fg, unsigned char bg)
  107. {
  108. return cucul_set_attr_ansi(cv, fg, bg, 0);
  109. }
  110. /** \brief Set the default colour pair and text style (truecolor version).
  111. *
  112. * Set the default colour pair and text style for drawing. String
  113. * functions such as caca_printf() and graphical primitive functions such as
  114. * caca_draw_line() will use these attributes.
  115. *
  116. * Colors are 16-bit ARGB values, each component being coded on 4 bits. For
  117. * instance, 0xf088 is solid dark cyan (A=15 R=0 G=8 B=8), and 0x8fff is
  118. * white with 50% alpha (A=8 R=15 G=15 B=15).
  119. *
  120. * Style values are those defined in cucul.h, such as CUCUL_STYLE_UNDERLINE
  121. * or CUCUL_STYLE_BLINK. The values can be ORed to set several styles at
  122. * the same time.
  123. *
  124. * If an error occurs, -1 is returned and \b errno is set accordingly:
  125. * - \c EINVAL At least one of the colour values is invalid.
  126. *
  127. * \param cv A handle to the libcucul canvas.
  128. * \param fg The requested foreground colour.
  129. * \param bg The requested background colour.
  130. * \param style The requested text styles.
  131. * \return 0 in case of success, -1 if an error occurred.
  132. */
  133. int cucul_set_attr_argb(cucul_canvas_t *cv, unsigned int fg, unsigned int bg,
  134. unsigned char style)
  135. {
  136. uint32_t attr;
  137. if(fg > 0xffff || bg > 0xffff || style > 0x0f)
  138. {
  139. #if defined(HAVE_ERRNO_H)
  140. errno = EINVAL;
  141. #endif
  142. return -1;
  143. }
  144. if(fg < 0x100)
  145. fg += 0x100;
  146. if(bg < 0x100)
  147. bg += 0x100;
  148. attr = (((uint32_t)bg << 16) | (uint32_t)fg) & 0xeffeeffe;
  149. if(style)
  150. attr |= (0x02004801 * style) & 0x10011001;
  151. cv->curattr = attr;
  152. return 0;
  153. }
  154. /* Legacy function for old programs */
  155. int cucul_set_truecolor(cucul_canvas_t *cv, unsigned int fg, unsigned int bg)
  156. {
  157. return cucul_set_attr_argb(cv, fg, bg, 0);
  158. }
  159. /** \brief Get the text attribute at the given coordinates.
  160. *
  161. * Get the internal \e libcucul attribute value of the character at the
  162. * given coordinates. The attribute value has 32 significant bits,
  163. * organised as follows from MSB to LSB:
  164. * - 3 bits for the background alpha
  165. * - 1 bit for the blink flag
  166. * - 4 bits for the background red component
  167. * - 4 bits for the background green component
  168. * - 3 bits for the background blue component
  169. * - 1 bit for the underline flag
  170. * - 3 bits for the foreground alpha
  171. * - 1 bit for the italics flag
  172. * - 4 bits for the foreground red component
  173. * - 4 bits for the foreground green component
  174. * - 3 bits for the foreground blue component
  175. * - 1 bit for the bold flag
  176. *
  177. * If the coordinates are outside the canvas boundaries, the current
  178. * attribute is returned.
  179. *
  180. * This function never fails.
  181. *
  182. * \param cv A handle to the libcucul canvas.
  183. * \param x X coordinate.
  184. * \param y Y coordinate.
  185. * \return The requested attribute.
  186. */
  187. unsigned long int cucul_get_attr(cucul_canvas_t *cv, int x, int y)
  188. {
  189. if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height)
  190. return (unsigned long int)cv->curattr;
  191. return (unsigned long int)cv->attrs[x + y * cv->width];
  192. }
  193. /*
  194. * XXX: the following functions are local
  195. */
  196. static uint8_t nearest_ansi(uint16_t argb16, uint8_t def)
  197. {
  198. unsigned int i, best, dist;
  199. if(argb16 == (argb16 & 0x00f0))
  200. return argb16 >> 4;
  201. if(argb16 == (CUCUL_COLOR_DEFAULT << 4)
  202. || argb16 == (CUCUL_COLOR_TRANSPARENT << 4))
  203. return def;
  204. if(argb16 < 0x6fff) /* too transparent, return default colour */
  205. return def;
  206. best = def;
  207. dist = 0xffff;
  208. for(i = 0; i < 16; i++)
  209. {
  210. unsigned int d = 0;
  211. int a, b;
  212. a = (ansitab[i] >> 8) & 0xf;
  213. b = (argb16 >> 8) & 0xf;
  214. d += (a - b) * (a - b);
  215. a = (ansitab[i] >> 4) & 0xf;
  216. b = (argb16 >> 4) & 0xf;
  217. d += (a - b) * (a - b);
  218. a = ansitab[i] & 0xf;
  219. b = argb16 & 0xf;
  220. d += (a - b) * (a - b);
  221. if(d < dist)
  222. {
  223. dist = d;
  224. best = i;
  225. }
  226. }
  227. return best;
  228. }
  229. uint8_t _cucul_attr_to_ansi8(uint32_t attr)
  230. {
  231. uint16_t fg = attr & 0xeffe;
  232. uint16_t bg = (attr >> 16) & 0xeffe;
  233. return nearest_ansi(fg, CUCUL_COLOR_LIGHTGRAY)
  234. | (nearest_ansi(bg, CUCUL_COLOR_BLACK) << 4);
  235. }
  236. uint8_t _cucul_attr_to_ansi4fg(uint32_t attr)
  237. {
  238. return nearest_ansi(attr & 0xeffe, CUCUL_COLOR_LIGHTGRAY);
  239. }
  240. uint8_t _cucul_attr_to_ansi4bg(uint32_t attr)
  241. {
  242. return nearest_ansi((attr >> 16) & 0xeffe, CUCUL_COLOR_BLACK);
  243. }
  244. uint16_t _cucul_attr_to_rgb12fg(uint32_t attr)
  245. {
  246. uint16_t fg = attr & 0xeffe;
  247. if(fg == (fg & 0x00f0))
  248. return ansitab[fg >> 4] & 0x0fff;
  249. if(fg == (CUCUL_COLOR_DEFAULT << 4))
  250. return ansitab[CUCUL_COLOR_LIGHTGRAY] & 0x0fff;
  251. if(fg == (CUCUL_COLOR_TRANSPARENT << 4))
  252. return ansitab[CUCUL_COLOR_LIGHTGRAY] & 0x0fff;
  253. return fg & 0x0fff;
  254. }
  255. uint16_t _cucul_attr_to_rgb12bg(uint32_t attr)
  256. {
  257. uint16_t bg = (attr >> 16) & 0xeffe;
  258. if(bg == (bg & 0x00f0))
  259. return ansitab[bg >> 4] & 0x0fff;
  260. if(bg == (CUCUL_COLOR_DEFAULT << 4))
  261. return ansitab[CUCUL_COLOR_BLACK] & 0x0fff;
  262. if(bg == (CUCUL_COLOR_TRANSPARENT << 4))
  263. return ansitab[CUCUL_COLOR_BLACK] & 0x0fff;
  264. return bg & 0x0fff;
  265. }
  266. #define RGB12TO24(i) \
  267. (((uint32_t)((i & 0xf00) >> 8) * 0x110000) \
  268. | ((uint32_t)((i & 0x0f0) >> 4) * 0x001100) \
  269. | ((uint32_t)(i & 0x00f) * 0x000011))
  270. uint32_t _cucul_attr_to_rgb24fg(uint32_t attr)
  271. {
  272. return RGB12TO24(_cucul_attr_to_rgb12fg(attr));
  273. }
  274. uint32_t _cucul_attr_to_rgb24bg(uint32_t attr)
  275. {
  276. return RGB12TO24(_cucul_attr_to_rgb12bg(attr));
  277. }
  278. void _cucul_attr_to_argb4(uint32_t attr, uint8_t argb[8])
  279. {
  280. uint16_t fg = attr & 0xeffe;
  281. uint16_t bg = (attr >> 16) & 0xeffe;
  282. if(fg == (fg & 0x00f0))
  283. fg = ansitab[fg >> 4];
  284. else if(fg == (CUCUL_COLOR_DEFAULT << 4))
  285. fg = ansitab[CUCUL_COLOR_LIGHTGRAY];
  286. else if(fg == (CUCUL_COLOR_TRANSPARENT << 4))
  287. fg = 0x0fff;
  288. if(bg == (bg & 0x00f0))
  289. bg = ansitab[bg >> 4];
  290. else if(bg == (CUCUL_COLOR_DEFAULT << 4))
  291. bg = ansitab[CUCUL_COLOR_BLACK];
  292. else if(bg == (CUCUL_COLOR_TRANSPARENT << 4))
  293. bg = 0x0fff;
  294. argb[0] = bg >> 12;
  295. argb[1] = (bg >> 8) & 0xf;
  296. argb[2] = (bg >> 4) & 0xf;
  297. argb[3] = bg & 0xf;
  298. argb[4] = fg >> 12;
  299. argb[5] = (fg >> 8) & 0xf;
  300. argb[6] = (fg >> 4) & 0xf;
  301. argb[7] = fg & 0xf;
  302. }