Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

336 рядки
9.7 KiB

  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 horizontal and vertical flipping routines.
  15. */
  16. #include "config.h"
  17. #include "common.h"
  18. #if !defined(__KERNEL__)
  19. #endif
  20. #include "cucul.h"
  21. #include "cucul_internals.h"
  22. static uint32_t flipchar(uint32_t ch);
  23. static uint32_t flopchar(uint32_t ch);
  24. static uint32_t rotatechar(uint32_t ch);
  25. /** \brief Invert a canvas' colours.
  26. *
  27. * This function inverts a canvas' colours (black becomes white, red
  28. * becomes cyan, etc.) without changing the characters in it.
  29. *
  30. * \param cv The canvas to invert.
  31. */
  32. void cucul_invert(cucul_canvas_t *cv)
  33. {
  34. uint32_t *attr = cv->attr;
  35. unsigned int i;
  36. for(i = cv->height * cv->width; i--; )
  37. {
  38. *attr = *attr ^ 0x000f000f;
  39. attr++;
  40. }
  41. }
  42. /** \brief Flip a canvas horizontally.
  43. *
  44. * This function flips a canvas horizontally, choosing characters that
  45. * look like the mirrored version wherever possible.
  46. *
  47. * \param cv The canvas to flip.
  48. */
  49. void cucul_flip(cucul_canvas_t *cv)
  50. {
  51. unsigned int y;
  52. for(y = 0; y < cv->height; y++)
  53. {
  54. uint32_t *cleft = cv->chars + y * cv->width;
  55. uint32_t *cright = cleft + cv->width - 1;
  56. uint32_t *aleft = cv->attr + y * cv->width;
  57. uint32_t *aright = aleft + cv->width - 1;
  58. while(cleft < cright)
  59. {
  60. uint32_t ch;
  61. uint32_t attr;
  62. /* Swap attributes */
  63. attr = *aright; *aright = *aleft; *aleft = attr;
  64. /* Swap characters */
  65. ch = *cright; *cright = flipchar(*cleft); *cleft = flipchar(ch);
  66. cleft++; cright--; aleft++; aright--;
  67. }
  68. if(cleft == cright)
  69. *cleft = flipchar(*cleft);
  70. }
  71. }
  72. /** \brief Flip a canvas vertically.
  73. *
  74. * This function flips a canvas vertically, choosing characters that
  75. * look like the mirrored version wherever possible.
  76. *
  77. * \param cv The canvas to flop.
  78. */
  79. void cucul_flop(cucul_canvas_t *cv)
  80. {
  81. unsigned int x;
  82. for(x = 0; x < cv->width; x++)
  83. {
  84. uint32_t *ctop = cv->chars + x;
  85. uint32_t *cbottom = ctop + cv->width * (cv->height - 1);
  86. uint32_t *atop = cv->attr + x;
  87. uint32_t *abottom = atop + cv->width * (cv->height - 1);
  88. while(ctop < cbottom)
  89. {
  90. uint32_t ch;
  91. uint32_t attr;
  92. /* Swap attributes */
  93. attr = *abottom; *abottom = *atop; *atop = attr;
  94. /* Swap characters */
  95. ch = *cbottom; *cbottom = flopchar(*ctop); *ctop = flopchar(ch);
  96. ctop += cv->width; cbottom -= cv->width;
  97. atop += cv->width; abottom -= cv->width;
  98. }
  99. if(ctop == cbottom)
  100. *ctop = flopchar(*ctop);
  101. }
  102. }
  103. /** \brief Rotate a canvas.
  104. *
  105. * This function applies a 180 degrees transformation to a canvas,
  106. * choosing characters that look like the mirrored version wherever
  107. * possible.
  108. *
  109. * \param cv The canvas to rotate.
  110. */
  111. void cucul_rotate(cucul_canvas_t *cv)
  112. {
  113. uint32_t *cbegin = cv->chars;
  114. uint32_t *cend = cbegin + cv->width * cv->height - 1;
  115. uint32_t *abegin = cv->attr;
  116. uint32_t *aend = abegin + cv->width * cv->height - 1;
  117. while(cbegin < cend)
  118. {
  119. uint32_t ch;
  120. uint32_t attr;
  121. /* Swap attributes */
  122. attr = *aend; *aend = *abegin; *abegin = attr;
  123. /* Swap characters */
  124. ch = *cend; *cend = rotatechar(*cbegin); *cbegin = rotatechar(ch);
  125. cbegin++; cend--; abegin++; aend--;
  126. }
  127. if(cbegin == cend)
  128. *cbegin = rotatechar(*cbegin);
  129. }
  130. static uint32_t flipchar(uint32_t ch)
  131. {
  132. int i;
  133. static uint32_t const noflip[] =
  134. {
  135. /* ASCII */
  136. (uint32_t)' ', (uint32_t)'"', (uint32_t)'#', (uint32_t)'\'',
  137. (uint32_t)'-', (uint32_t)'.', (uint32_t)'*', (uint32_t)'+',
  138. (uint32_t)':', (uint32_t)'=',
  139. (uint32_t)'0', (uint32_t)'8', (uint32_t)'A', (uint32_t)'H',
  140. (uint32_t)'I', (uint32_t)'M', (uint32_t)'O', (uint32_t)'T',
  141. (uint32_t)'U', (uint32_t)'V', (uint32_t)'W', (uint32_t)'X',
  142. (uint32_t)'Y', (uint32_t)'^', (uint32_t)'_', (uint32_t)'i',
  143. (uint32_t)'o', (uint32_t)'v', (uint32_t)'w', (uint32_t)'x',
  144. (uint32_t)'|',
  145. /* Unicode */
  146. 0x2591, 0x2592, 0x2593, 0x2588, 0x2584, 0x2580, /* ░ ▒ ▓ █ ▄ ▀ */
  147. 0
  148. };
  149. static uint32_t const pairs[] =
  150. {
  151. /* ASCII */
  152. (uint32_t)'(', (uint32_t)')', (uint32_t)'/', (uint32_t)'\\',
  153. (uint32_t)'<', (uint32_t)'>', (uint32_t)'[', (uint32_t)']',
  154. (uint32_t)'b', (uint32_t)'d', (uint32_t)'p', (uint32_t)'q',
  155. (uint32_t)'{', (uint32_t)'}',
  156. /* ASCII-Unicode */
  157. (uint32_t)';', 0x204f, /* ; ⁏ */
  158. (uint32_t)'`', 0x00b4, /* ` ´ */
  159. (uint32_t)'E', 0x018e, /* E Ǝ */
  160. (uint32_t)'N', 0x0418, /* N И */
  161. (uint32_t)'R', 0x042f, /* R Я */
  162. (uint32_t)'S', 0x01a7, /* S Ƨ */
  163. (uint32_t)'c', 0x0254, /* c ɔ */
  164. (uint32_t)'e', 0x0258, /* e ɘ */
  165. /* Unicode only */
  166. 0x258c, 0x2590, /* ▌ ▐ */
  167. 0x2596, 0x2597, /* ▖ ▗ */
  168. 0x2598, 0x259d, /* ▘ ▝ */
  169. 0x2599, 0x259f, /* ▙ ▟ */
  170. 0x259a, 0x259e, /* ▚ ▞ */
  171. 0x259b, 0x259c, /* ▛ ▜ */
  172. 0
  173. };
  174. for(i = 0; noflip[i]; i++)
  175. if(ch == noflip[i])
  176. return ch;
  177. for(i = 0; pairs[i]; i++)
  178. if(ch == pairs[i])
  179. return pairs[i ^ 1];
  180. return ch;
  181. }
  182. static uint32_t flopchar(uint32_t ch)
  183. {
  184. int i;
  185. static uint32_t const noflop[] =
  186. {
  187. /* ASCII */
  188. (uint32_t)' ', (uint32_t)'(', (uint32_t)')', (uint32_t)'*',
  189. (uint32_t)'+', (uint32_t)'-',
  190. (uint32_t)'0', (uint32_t)'3', (uint32_t)'8', (uint32_t)':',
  191. (uint32_t)'<', (uint32_t)'=', (uint32_t)'>', (uint32_t)'B',
  192. (uint32_t)'C', (uint32_t)'D', (uint32_t)'E', (uint32_t)'H',
  193. (uint32_t)'I', (uint32_t)'K', (uint32_t)'O', (uint32_t)'X',
  194. (uint32_t)'[', (uint32_t)']', (uint32_t)'c', (uint32_t)'o',
  195. (uint32_t)'{', (uint32_t)'|', (uint32_t)'}',
  196. /* Unicode */
  197. 0x2591, 0x2592, 0x2593, 0x2588, 0x258c, 0x2590, /* ░ ▒ ▓ █ ▌ ▐ */
  198. 0
  199. };
  200. static uint32_t const pairs[] =
  201. {
  202. /* ASCII */
  203. (uint32_t)'/', (uint32_t)'\\', (uint32_t)'M', (uint32_t)'W',
  204. (uint32_t)',', (uint32_t)'`', (uint32_t)'b', (uint32_t)'p',
  205. (uint32_t)'d', (uint32_t)'q', (uint32_t)'p', (uint32_t)'q',
  206. (uint32_t)'f', (uint32_t)'t', (uint32_t)'.', (uint32_t)'\'',
  207. /* ASCII-Unicode */
  208. (uint32_t)'_', 0x2594, /* _ ▔ */
  209. (uint32_t)'`', 0x201a, /* ` ‚ */
  210. (uint32_t)'!', 0x00a1, /* ! ¡ */
  211. (uint32_t)'N', 0x0418, /* N И */
  212. (uint32_t)'P', 0x042c, /* P Ь */
  213. (uint32_t)'S', 0x01a7, /* S Ƨ */
  214. (uint32_t)'v', 0x028c, /* v ʌ */
  215. (uint32_t)'w', 0x028d, /* w ʍ */
  216. /* Unicode only */
  217. 0x2584, 0x2580, /* ▄ ▀ */
  218. 0x2596, 0x2598, /* ▖ ▘ */
  219. 0x2597, 0x259d, /* ▗ ▝ */
  220. 0x2599, 0x259b, /* ▙ ▛ */
  221. 0x259f, 0x259c, /* ▟ ▜ */
  222. 0x259a, 0x259e, /* ▚ ▞ */
  223. 0
  224. };
  225. for(i = 0; noflop[i]; i++)
  226. if(ch == noflop[i])
  227. return ch;
  228. for(i = 0; pairs[i]; i++)
  229. if(ch == pairs[i])
  230. return pairs[i ^ 1];
  231. return ch;
  232. }
  233. static uint32_t rotatechar(uint32_t ch)
  234. {
  235. int i;
  236. static uint32_t const norotate[] =
  237. {
  238. /* ASCII - FIXME: a lot are missing */
  239. (uint32_t)' ', (uint32_t)'*', (uint32_t)'+', (uint32_t)'-',
  240. (uint32_t)'0', (uint32_t)'8', (uint32_t)':', (uint32_t)'=',
  241. /* Unicode */
  242. 0x2591, 0x2592, 0x2593, 0x2588, 0x259a, 0x259e, /* ░ ▒ ▓ █ ▚ ▞ */
  243. 0
  244. };
  245. static uint32_t const pairs[] =
  246. {
  247. /* ASCII */
  248. (uint32_t)'(', (uint32_t)')', (uint32_t)'<', (uint32_t)'>',
  249. (uint32_t)'[', (uint32_t)']', (uint32_t)'{', (uint32_t)'}',
  250. (uint32_t)'.', (uint32_t)'\'',
  251. (uint32_t)'6', (uint32_t)'9',
  252. (uint32_t)'M', (uint32_t)'W', (uint32_t)'b', (uint32_t)'q',
  253. (uint32_t)'d', (uint32_t)'p', (uint32_t)'n', (uint32_t)'u',
  254. /* ASCII-Unicode */
  255. (uint32_t)'_', 0x2594, /* _ ▔ */
  256. (uint32_t)',', 0x02bb, /* , ʻ */
  257. (uint32_t)'!', 0x00a1, /* ! ¡ */
  258. (uint32_t)'?', 0x00bf, /* ? ¿ */
  259. (uint32_t)'E', 0x018e, /* E Ǝ */
  260. (uint32_t)'F', 0x2132, /* F Ⅎ */
  261. (uint32_t)'a', 0x0250, /* a ɐ */
  262. (uint32_t)'c', 0x0254, /* c ɔ */
  263. (uint32_t)'e', 0x0259, /* e ə */
  264. (uint32_t)'f', 0x025f, /* f ɟ */
  265. (uint32_t)'h', 0x0265, /* h ɥ */
  266. (uint32_t)'k', 0x029e, /* k ʞ */
  267. (uint32_t)'m', 0x026f, /* m ɯ */
  268. (uint32_t)'r', 0x0279, /* r ɹ */
  269. (uint32_t)'t', 0x0287, /* t ʇ */
  270. (uint32_t)'v', 0x028c, /* v ʌ */
  271. (uint32_t)'w', 0x028d, /* w ʍ */
  272. (uint32_t)'y', 0x028e, /* y ʎ */
  273. /* Unicode only */
  274. 0x258c, 0x2590, /* ▌ ▐ */
  275. 0x2584, 0x2580, /* ▄ ▀ */
  276. 0x2596, 0x259d, /* ▖ ▝ */
  277. 0x2597, 0x2598, /* ▗ ▘ */
  278. 0x2599, 0x259c, /* ▙ ▜ */
  279. 0x259f, 0x259b, /* ▟ ▛ */
  280. 0
  281. };
  282. for(i = 0; norotate[i]; i++)
  283. if(ch == norotate[i])
  284. return ch;
  285. for(i = 0; pairs[i]; i++)
  286. if(ch == pairs[i])
  287. return pairs[i ^ 1];
  288. return ch;
  289. }