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.

преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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. /* RGB colours for the ANSI palette. There is no real standard, so we
  25. * use the same values as gnome-terminal. The 7th colour (brown) is a bit
  26. * special. */
  27. static const uint16_t ansitab[16] =
  28. {
  29. 0xf000, 0xf00a, 0xf0a0, 0xf0aa, 0xfa00, 0xfa0a, 0xfa50, 0xfaaa,
  30. 0xf555, 0xf55f, 0xf5f5, 0xf5ff, 0xff55, 0xff5f, 0xfff5, 0xffff,
  31. };
  32. /** \brief Set the default colour pair.
  33. *
  34. * Set the default ANSI colour pair for drawing. String functions such as
  35. * caca_printf() and graphical primitive functions such as caca_draw_line()
  36. * will use these colours.
  37. *
  38. * Color values are those defined in cucul.h, such as CUCUL_COLOR_RED
  39. * or CUCUL_COLOR_TRANSPARENT.
  40. *
  41. * If an error occurs, -1 is returned and \b errno is set accordingly:
  42. * - \c EINVAL At least one of the colour values is invalid.
  43. *
  44. * \param cv A handle to the libcucul canvas.
  45. * \param fg The requested foreground colour.
  46. * \param bg The requested background colour.
  47. * \return 0 in case of success, -1 if an error occurred.
  48. */
  49. int cucul_set_color(cucul_canvas_t *cv, unsigned char fg, unsigned char bg)
  50. {
  51. if(fg > 0x20 || bg > 0x20)
  52. {
  53. #if defined(HAVE_ERRNO_H)
  54. errno = EINVAL;
  55. #endif
  56. return -1;
  57. }
  58. cv->fgcolor = fg;
  59. cv->bgcolor = bg;
  60. return 0;
  61. }
  62. /** \brief Set the default colour pair (truecolor version).
  63. *
  64. * Set the default colour pair for drawing. String functions such as
  65. * caca_printf() and graphical primitive functions such as caca_draw_line()
  66. * will use these colours.
  67. *
  68. * Colors are 16-bit ARGB values, each component being coded on 4 bits. For
  69. * instance, 0xf088 is solid dark cyan (A=15 R=0 G=8 B=8), and 0x8fff is
  70. * white with 50% alpha (A=8 R=15 G=15 B=15).
  71. *
  72. * If an error occurs, -1 is returned and \b errno is set accordingly:
  73. * - \c EINVAL At least one of the colour values is invalid.
  74. *
  75. * \param cv A handle to the libcucul canvas.
  76. * \param fg The requested foreground colour.
  77. * \param bg The requested background colour.
  78. * \return 0 in case of success, -1 if an error occurred.
  79. */
  80. int cucul_set_truecolor(cucul_canvas_t *cv, unsigned int fg, unsigned int bg)
  81. {
  82. if(fg > 0xffff || bg > 0xffff)
  83. {
  84. #if defined(HAVE_ERRNO_H)
  85. errno = EINVAL;
  86. #endif
  87. return -1;
  88. }
  89. if(fg < 0x100)
  90. fg += 0x100;
  91. if(bg < 0x100)
  92. bg += 0x100;
  93. cv->fgcolor = fg;
  94. cv->bgcolor = bg;
  95. return 0;
  96. }
  97. /** \brief Get the colour pair at the given coordinates.
  98. *
  99. * Get the internal \e libcucul colour pair value of the character at the
  100. * given coordinates. The colour pair value has 32 significant bits: the
  101. * lower 16 bits are for the foreground colour, the higher 16 bits are for
  102. * the background.
  103. *
  104. * If the coordinates are outside the canvas boundaries, the current colour
  105. * pair is returned.
  106. *
  107. * This function never fails.
  108. *
  109. * \param cv A handle to the libcucul canvas.
  110. * \param x X coordinate.
  111. * \param y Y coordinate.
  112. * \param ch The requested colour pair value.
  113. * \return The character always returns 0.
  114. */
  115. unsigned long int cucul_get_color(cucul_canvas_t *cv, int x, int y)
  116. {
  117. if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height)
  118. return ((uint32_t)cv->bgcolor << 16) | (uint32_t)cv->fgcolor;
  119. return (unsigned long int)cv->attr[x + y * cv->width];
  120. }
  121. /*
  122. * XXX: the following functions are local
  123. */
  124. static uint8_t nearest_ansi(uint16_t argb16, uint8_t def)
  125. {
  126. unsigned int i, best, dist;
  127. if(argb16 < CUCUL_COLOR_DEFAULT)
  128. return argb16;
  129. if(argb16 == CUCUL_COLOR_DEFAULT || argb16 == CUCUL_COLOR_TRANSPARENT)
  130. return def;
  131. if(argb16 < 0x5fff) /* too transparent, return default colour */
  132. return def;
  133. best = def;
  134. dist = 0xffff;
  135. for(i = 0; i < 16; i++)
  136. {
  137. unsigned int d = 0;
  138. int a, b;
  139. a = (ansitab[i] >> 8) & 0xf;
  140. b = (argb16 >> 8) & 0xf;
  141. d += (a - b) * (a - b);
  142. a = (ansitab[i] >> 4) & 0xf;
  143. b = (argb16 >> 4) & 0xf;
  144. d += (a - b) * (a - b);
  145. a = ansitab[i] & 0xf;
  146. b = argb16 & 0xf;
  147. d += (a - b) * (a - b);
  148. if(d < dist)
  149. {
  150. dist = d;
  151. best = i;
  152. }
  153. }
  154. return best;
  155. }
  156. uint8_t _cucul_argb32_to_ansi8(uint32_t ch)
  157. {
  158. uint16_t fg = ch & 0xffff;
  159. uint16_t bg = ch >> 16;
  160. return nearest_ansi(fg, CUCUL_COLOR_LIGHTGRAY)
  161. | (nearest_ansi(bg, CUCUL_COLOR_BLACK) << 4);
  162. }
  163. uint8_t _cucul_argb32_to_ansi4fg(uint32_t ch)
  164. {
  165. return nearest_ansi(ch & 0xffff, CUCUL_COLOR_LIGHTGRAY);
  166. }
  167. uint8_t _cucul_argb32_to_ansi4bg(uint32_t ch)
  168. {
  169. return nearest_ansi(ch >> 16, CUCUL_COLOR_BLACK);
  170. }
  171. uint16_t _cucul_argb32_to_rgb12fg(uint32_t ch)
  172. {
  173. uint16_t fg = ch & 0xffff;
  174. if(fg < CUCUL_COLOR_DEFAULT)
  175. return ansitab[fg] & 0x0fff;
  176. if(fg == CUCUL_COLOR_DEFAULT)
  177. return ansitab[CUCUL_COLOR_LIGHTGRAY] & 0x0fff;
  178. if(fg == CUCUL_COLOR_TRANSPARENT)
  179. return ansitab[CUCUL_COLOR_LIGHTGRAY] & 0x0fff;
  180. return fg & 0x0fff;
  181. }
  182. uint16_t _cucul_argb32_to_rgb12bg(uint32_t ch)
  183. {
  184. uint16_t bg = ch >> 16;
  185. if(bg < CUCUL_COLOR_DEFAULT)
  186. return ansitab[bg] & 0x0fff;
  187. if(bg == CUCUL_COLOR_DEFAULT)
  188. return ansitab[CUCUL_COLOR_BLACK] & 0x0fff;
  189. if(bg == CUCUL_COLOR_TRANSPARENT)
  190. return ansitab[CUCUL_COLOR_BLACK] & 0x0fff;
  191. return bg & 0x0fff;
  192. }
  193. #define RGB12TO24(i) \
  194. (((uint32_t)((i & 0xf00) >> 8) * 0x110000) \
  195. | ((uint32_t)((i & 0x0f0) >> 4) * 0x001100) \
  196. | ((uint32_t)(i & 0x00f) * 0x000011))
  197. uint32_t _cucul_argb32_to_rgb24fg(uint32_t ch)
  198. {
  199. return RGB12TO24(_cucul_argb32_to_rgb12fg(ch));
  200. }
  201. uint32_t _cucul_argb32_to_rgb24bg(uint32_t ch)
  202. {
  203. return RGB12TO24(_cucul_argb32_to_rgb12bg(ch));
  204. }
  205. void _cucul_argb32_to_argb4(uint32_t ch, uint8_t argb[8])
  206. {
  207. uint16_t fg = ch & 0xffff;
  208. uint16_t bg = ch >> 16;
  209. if(fg < CUCUL_COLOR_DEFAULT)
  210. fg = ansitab[fg];
  211. else if(fg == CUCUL_COLOR_DEFAULT)
  212. fg = ansitab[CUCUL_COLOR_LIGHTGRAY];
  213. else if(fg == CUCUL_COLOR_TRANSPARENT)
  214. fg = 0x0fff;
  215. if(bg < CUCUL_COLOR_DEFAULT)
  216. bg = ansitab[bg];
  217. else if(bg == CUCUL_COLOR_DEFAULT)
  218. bg = ansitab[CUCUL_COLOR_BLACK];
  219. else if(bg == CUCUL_COLOR_TRANSPARENT)
  220. bg = 0x0fff;
  221. argb[0] = bg >> 12;
  222. argb[1] = (bg >> 8) & 0xf;
  223. argb[2] = (bg >> 4) & 0xf;
  224. argb[3] = bg & 0xf;
  225. argb[4] = fg >> 12;
  226. argb[5] = (fg >> 8) & 0xf;
  227. argb[6] = (fg >> 4) & 0xf;
  228. argb[7] = fg & 0xf;
  229. }