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.
 
 
 
 
 
 

387 lines
11 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. * 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. /* CP437 */
  162. 0x2591, 0x2592, 0x2593, 0x2588, 0x2584, 0x2580, /* ░ ▒ ▓ █ ▄ ▀ */
  163. 0
  164. };
  165. static uint32_t const pairs[] =
  166. {
  167. /* ASCII */
  168. (uint32_t)'(', (uint32_t)')',
  169. (uint32_t)'/', (uint32_t)'\\',
  170. (uint32_t)'<', (uint32_t)'>',
  171. (uint32_t)'[', (uint32_t)']',
  172. (uint32_t)'b', (uint32_t)'d',
  173. (uint32_t)'p', (uint32_t)'q',
  174. (uint32_t)'{', (uint32_t)'}',
  175. /* ASCII-Unicode */
  176. (uint32_t)';', 0x204f, /* ; ⁏ */
  177. (uint32_t)'`', 0x00b4, /* ` ´ */
  178. (uint32_t)',', 0x02ce, /* , ˎ */
  179. (uint32_t)'C', 0x03fd, /* C Ͻ */
  180. (uint32_t)'E', 0x018e, /* E Ǝ */
  181. (uint32_t)'N', 0x0418, /* N И */
  182. (uint32_t)'R', 0x042f, /* R Я */
  183. (uint32_t)'S', 0x01a7, /* S Ƨ */
  184. (uint32_t)'c', 0x0254, /* c ɔ */
  185. (uint32_t)'e', 0x0258, /* e ɘ */
  186. /* CP437 */
  187. 0x258c, 0x2590, /* ▌ ▐ */
  188. 0x2596, 0x2597, /* ▖ ▗ */
  189. 0x2598, 0x259d, /* ▘ ▝ */
  190. 0x2599, 0x259f, /* ▙ ▟ */
  191. 0x259a, 0x259e, /* ▚ ▞ */
  192. 0x259b, 0x259c, /* ▛ ▜ */
  193. 0x25ba, 0x25c4, /* ► ◄ */
  194. 0x2192, 0x2190, /* → ← */
  195. 0x2310, 0xac, /* ⌐ ¬ */
  196. 0
  197. };
  198. for(i = 0; noflip[i]; i++)
  199. if(ch == noflip[i])
  200. return ch;
  201. for(i = 0; pairs[i]; i++)
  202. if(ch == pairs[i])
  203. return pairs[i ^ 1];
  204. return ch;
  205. }
  206. static uint32_t flopchar(uint32_t ch)
  207. {
  208. int i;
  209. static uint32_t const noflop[] =
  210. {
  211. /* ASCII */
  212. (uint32_t)' ', (uint32_t)'(', (uint32_t)')', (uint32_t)'*',
  213. (uint32_t)'+', (uint32_t)'-',
  214. (uint32_t)'0', (uint32_t)'3', (uint32_t)'8', (uint32_t)':',
  215. (uint32_t)'<', (uint32_t)'=', (uint32_t)'>', (uint32_t)'B',
  216. (uint32_t)'C', (uint32_t)'D', (uint32_t)'E', (uint32_t)'H',
  217. (uint32_t)'I', (uint32_t)'K', (uint32_t)'O', (uint32_t)'X',
  218. (uint32_t)'[', (uint32_t)']', (uint32_t)'c', (uint32_t)'o',
  219. (uint32_t)'{', (uint32_t)'|', (uint32_t)'}',
  220. /* CP437 */
  221. 0x2591, 0x2592, 0x2593, 0x2588, 0x258c, 0x2590, /* ░ ▒ ▓ █ ▌ ▐ */
  222. 0
  223. };
  224. static uint32_t const pairs[] =
  225. {
  226. /* ASCII */
  227. (uint32_t)'/', (uint32_t)'\\',
  228. (uint32_t)'M', (uint32_t)'W',
  229. (uint32_t)',', (uint32_t)'`',
  230. (uint32_t)'b', (uint32_t)'p',
  231. (uint32_t)'d', (uint32_t)'q',
  232. (uint32_t)'p', (uint32_t)'q',
  233. (uint32_t)'f', (uint32_t)'t',
  234. (uint32_t)'.', (uint32_t)'\'',
  235. /* ASCII-Unicode */
  236. (uint32_t)'_', 0x203e, /* _ ‾ */
  237. (uint32_t)'!', 0x00a1, /* ! ¡ */
  238. (uint32_t)'L', 0x0413, /* L Г */
  239. (uint32_t)'N', 0x0418, /* N И */
  240. (uint32_t)'P', 0x042c, /* P Ь */
  241. (uint32_t)'R', 0x0281, /* R ʁ */
  242. (uint32_t)'S', 0x01a7, /* S Ƨ */
  243. (uint32_t)'U', 0x0548, /* U Ո */
  244. (uint32_t)'V', 0x039b, /* V Λ */
  245. (uint32_t)'h', 0x03bc, /* h μ */
  246. (uint32_t)'i', 0x1d09, /* i ᴉ */
  247. (uint32_t)'v', 0x028c, /* v ʌ */
  248. (uint32_t)'w', 0x028d, /* w ʍ */
  249. (uint32_t)'y', 0x03bb, /* y λ */
  250. /* Not perfect, but better than nothing */
  251. (uint32_t)'m', 0x026f, /* m ɯ */
  252. (uint32_t)'n', (uint32_t)'u',
  253. /* CP437 */
  254. 0x2584, 0x2580, /* ▄ ▀ */
  255. 0x2596, 0x2598, /* ▖ ▘ */
  256. 0x2597, 0x259d, /* ▗ ▝ */
  257. 0x2599, 0x259b, /* ▙ ▛ */
  258. 0x259f, 0x259c, /* ▟ ▜ */
  259. 0x259a, 0x259e, /* ▚ ▞ */
  260. 0
  261. };
  262. for(i = 0; noflop[i]; i++)
  263. if(ch == noflop[i])
  264. return ch;
  265. for(i = 0; pairs[i]; i++)
  266. if(ch == pairs[i])
  267. return pairs[i ^ 1];
  268. return ch;
  269. }
  270. static uint32_t rotatechar(uint32_t ch)
  271. {
  272. int i;
  273. static uint32_t const norotate[] =
  274. {
  275. /* ASCII - FIXME: a lot are missing */
  276. (uint32_t)' ', (uint32_t)'*', (uint32_t)'+', (uint32_t)'-',
  277. (uint32_t)'0', (uint32_t)'8', (uint32_t)':', (uint32_t)'=',
  278. /* Unicode */
  279. 0x2591, 0x2592, 0x2593, 0x2588, 0x259a, 0x259e, /* ░ ▒ ▓ █ ▚ ▞ */
  280. 0
  281. };
  282. static uint32_t const pairs[] =
  283. {
  284. /* ASCII */
  285. (uint32_t)'(', (uint32_t)')',
  286. (uint32_t)'<', (uint32_t)'>',
  287. (uint32_t)'[', (uint32_t)']',
  288. (uint32_t)'{', (uint32_t)'}',
  289. (uint32_t)'.', (uint32_t)'\'',
  290. (uint32_t)'6', (uint32_t)'9',
  291. (uint32_t)'M', (uint32_t)'W',
  292. (uint32_t)'b', (uint32_t)'q',
  293. (uint32_t)'d', (uint32_t)'p',
  294. (uint32_t)'n', (uint32_t)'u',
  295. /* ASCII-Unicode */
  296. (uint32_t)'_', 0x203e, /* _ ‾ */
  297. (uint32_t)',', 0x00b4, /* , ´ */
  298. (uint32_t)'`', 0x02ce, /* ` ˎ */
  299. (uint32_t)'!', 0x00a1, /* ! ¡ */
  300. (uint32_t)'?', 0x00bf, /* ? ¿ */
  301. (uint32_t)'C', 0x03fd, /* C Ͻ */
  302. (uint32_t)'E', 0x018e, /* E Ǝ */
  303. (uint32_t)'F', 0x2132, /* F Ⅎ */
  304. (uint32_t)'U', 0x0548, /* U Ո */
  305. (uint32_t)'V', 0x039b, /* V Λ */
  306. (uint32_t)'a', 0x0250, /* a ɐ */
  307. (uint32_t)'c', 0x0254, /* c ɔ */
  308. (uint32_t)'e', 0x0259, /* e ə */
  309. (uint32_t)'f', 0x025f, /* f ɟ */
  310. (uint32_t)'g', 0x1d77, /* g ᵷ */
  311. (uint32_t)'h', 0x0265, /* h ɥ */
  312. (uint32_t)'i', 0x1d09, /* i ᴉ */
  313. (uint32_t)'k', 0x029e, /* k ʞ */
  314. (uint32_t)'m', 0x026f, /* m ɯ */
  315. (uint32_t)'r', 0x0279, /* r ɹ */
  316. (uint32_t)'t', 0x0287, /* t ʇ */
  317. (uint32_t)'v', 0x028c, /* v ʌ */
  318. (uint32_t)'w', 0x028d, /* w ʍ */
  319. (uint32_t)'y', 0x028e, /* y ʎ */
  320. /* CP437 */
  321. 0x258c, 0x2590, /* ▌ ▐ */
  322. 0x2584, 0x2580, /* ▄ ▀ */
  323. 0x2596, 0x259d, /* ▖ ▝ */
  324. 0x2597, 0x2598, /* ▗ ▘ */
  325. 0x2599, 0x259c, /* ▙ ▜ */
  326. 0x259f, 0x259b, /* ▟ ▛ */
  327. 0
  328. };
  329. for(i = 0; norotate[i]; i++)
  330. if(ch == norotate[i])
  331. return ch;
  332. for(i = 0; pairs[i]; i++)
  333. if(ch == pairs[i])
  334. return pairs[i ^ 1];
  335. return ch;
  336. }