Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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