Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

499 lignes
14 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. It comes without any warranty, to
  9. * the extent permitted by applicable law. You can redistribute it
  10. * and/or modify it under the terms of the Do What The Fuck You Want
  11. * To Public License, Version 2, as published by Sam Hocevar. See
  12. * http://sam.zoy.org/wtfpl/COPYING for more details.
  13. */
  14. /*
  15. * This file contains horizontal and vertical flipping routines.
  16. */
  17. #include "config.h"
  18. #include "common.h"
  19. #if !defined(__KERNEL__)
  20. #endif
  21. #include "cucul.h"
  22. #include "cucul_internals.h"
  23. static uint32_t flipchar(uint32_t ch);
  24. static uint32_t flopchar(uint32_t ch);
  25. static uint32_t rotatechar(uint32_t ch);
  26. /** \brief Invert a canvas' colours.
  27. *
  28. * Invert a canvas' colours (black becomes white, red becomes cyan, etc.)
  29. * without changing the characters in it.
  30. *
  31. * This function never fails.
  32. *
  33. * \param cv The canvas to invert.
  34. * \return This function always returns 0.
  35. */
  36. int cucul_invert(cucul_canvas_t *cv)
  37. {
  38. uint32_t *attrs = cv->attrs;
  39. unsigned int i;
  40. for(i = cv->height * cv->width; i--; )
  41. {
  42. *attrs = *attrs ^ 0x000f000f;
  43. attrs++;
  44. }
  45. return 0;
  46. }
  47. /** \brief Flip a canvas horizontally.
  48. *
  49. * Flip a canvas horizontally, choosing characters that look like the
  50. * mirrored version wherever possible. Some characters will stay
  51. * unchanged by the process, but the operation is guaranteed to be
  52. * involutive: performing it again gives back the original canvas.
  53. *
  54. * This function never fails.
  55. *
  56. * \param cv The canvas to flip.
  57. * \return This function always returns 0.
  58. */
  59. int cucul_flip(cucul_canvas_t *cv)
  60. {
  61. unsigned int y;
  62. for(y = 0; y < cv->height; y++)
  63. {
  64. uint32_t *cleft = cv->chars + y * cv->width;
  65. uint32_t *cright = cleft + cv->width - 1;
  66. uint32_t *aleft = cv->attrs + y * cv->width;
  67. uint32_t *aright = aleft + cv->width - 1;
  68. while(cleft < cright)
  69. {
  70. uint32_t ch;
  71. uint32_t attr;
  72. /* Swap attributes */
  73. attr = *aright;
  74. *aright-- = *aleft;
  75. *aleft++ = attr;
  76. /* Swap characters */
  77. ch = *cright;
  78. *cright-- = flipchar(*cleft);
  79. *cleft++ = flipchar(ch);
  80. }
  81. if(cleft == cright)
  82. *cleft = flipchar(*cleft);
  83. /* Fix fullwidth characters. Could it be done in one loop? */
  84. cleft = cv->chars + y * cv->width;
  85. cright = cleft + cv->width - 1;
  86. for( ; cleft < cright; cleft++)
  87. {
  88. if(cleft[0] == CUCUL_MAGIC_FULLWIDTH)
  89. {
  90. cleft[0] = cleft[1];
  91. cleft[1] = CUCUL_MAGIC_FULLWIDTH;
  92. cleft++;
  93. }
  94. }
  95. }
  96. return 0;
  97. }
  98. /** \brief Flip a canvas vertically.
  99. *
  100. * Flip a canvas vertically, choosing characters that look like the
  101. * mirrored version wherever possible. Some characters will stay
  102. * unchanged by the process, but the operation is guaranteed to be
  103. * involutive: performing it again gives back the original canvas.
  104. *
  105. * This function never fails.
  106. *
  107. * \param cv The canvas to flop.
  108. * \return This function always returns 0.
  109. */
  110. int cucul_flop(cucul_canvas_t *cv)
  111. {
  112. unsigned int x;
  113. for(x = 0; x < cv->width; x++)
  114. {
  115. uint32_t *ctop = cv->chars + x;
  116. uint32_t *cbottom = ctop + cv->width * (cv->height - 1);
  117. uint32_t *atop = cv->attrs + x;
  118. uint32_t *abottom = atop + cv->width * (cv->height - 1);
  119. while(ctop < cbottom)
  120. {
  121. uint32_t ch;
  122. uint32_t attr;
  123. /* Swap attributes */
  124. attr = *abottom; *abottom = *atop; *atop = attr;
  125. /* Swap characters */
  126. ch = *cbottom; *cbottom = flopchar(*ctop); *ctop = flopchar(ch);
  127. ctop += cv->width; cbottom -= cv->width;
  128. atop += cv->width; abottom -= cv->width;
  129. }
  130. if(ctop == cbottom)
  131. *ctop = flopchar(*ctop);
  132. }
  133. return 0;
  134. }
  135. /** \brief Rotate a canvas.
  136. *
  137. * Apply a 180-degree transformation to a canvas, choosing characters
  138. * that look like the upside-down version wherever possible. Some
  139. * characters will stay unchanged by the process, but the operation is
  140. * guaranteed to be involutive: performing it again gives back the
  141. * original canvas.
  142. *
  143. * This function never fails.
  144. *
  145. * \param cv The canvas to rotate.
  146. * \return This function always returns 0.
  147. */
  148. int cucul_rotate(cucul_canvas_t *cv)
  149. {
  150. uint32_t *cbegin = cv->chars;
  151. uint32_t *cend = cbegin + cv->width * cv->height - 1;
  152. uint32_t *abegin = cv->attrs;
  153. uint32_t *aend = abegin + cv->width * cv->height - 1;
  154. unsigned int y;
  155. while(cbegin < cend)
  156. {
  157. uint32_t ch;
  158. uint32_t attr;
  159. /* Swap attributes */
  160. attr = *aend; *aend = *abegin; *abegin = attr;
  161. /* Swap characters */
  162. ch = *cend; *cend = rotatechar(*cbegin); *cbegin = rotatechar(ch);
  163. cbegin++; cend--; abegin++; aend--;
  164. }
  165. if(cbegin == cend)
  166. *cbegin = rotatechar(*cbegin);
  167. /* Fix fullwidth characters. Could it be done in one loop? */
  168. for(y = 0; y < cv->height; y++)
  169. {
  170. cbegin = cv->chars + y * cv->width;
  171. cend = cbegin + cv->width - 1;
  172. for( ; cbegin < cend; cbegin++)
  173. {
  174. if(cbegin[0] == CUCUL_MAGIC_FULLWIDTH)
  175. {
  176. cbegin[0] = cbegin[1];
  177. cbegin[1] = CUCUL_MAGIC_FULLWIDTH;
  178. cbegin++;
  179. }
  180. }
  181. }
  182. return 0;
  183. }
  184. /* FIXME: as the lookup tables grow bigger, use a log(n) lookup instead
  185. * of linear lookup. */
  186. static uint32_t flipchar(uint32_t ch)
  187. {
  188. int i;
  189. static uint32_t const noflip[] =
  190. {
  191. /* ASCII */
  192. ' ', '"', '#', '\'', '-', '.', '*', '+', ':', '=', '0', '8',
  193. 'A', 'H', 'I', 'M', 'O', 'T', 'U', 'V', 'W', 'X', 'Y', '^',
  194. '_', 'i', 'o', 'v', 'w', 'x', '|',
  195. /* CP437 and box drawing */
  196. 0x2591, 0x2592, 0x2593, 0x2588, 0x2584, 0x2580, /* ░ ▒ ▓ █ ▄ ▀ */
  197. 0x2500, 0x2501, 0x2503, 0x2503, 0x253c, 0x254b, /* ─ ━ │ ┃ ┼ ╋ */
  198. 0x252c, 0x2534, 0x2533, 0x253b, 0x2566, 0x2569, /* ┬ ┴ ┳ ┻ ╦ ╩ */
  199. 0x2550, 0x2551, 0x256c, /* ═ ║ ╬ */
  200. 0x2575, 0x2577, 0x2579, 0x257b, /* ╵ ╷ ╹ ╻ */
  201. 0
  202. };
  203. static uint32_t const pairs[] =
  204. {
  205. /* ASCII */
  206. '(', ')',
  207. '/', '\\',
  208. '<', '>',
  209. '[', ']',
  210. 'b', 'd',
  211. 'p', 'q',
  212. '{', '}',
  213. /* ASCII-Unicode */
  214. ';', 0x204f, /* ; ⁏ */
  215. '`', 0x00b4, /* ` ´ */
  216. ',', 0x02ce, /* , ˎ */
  217. 'C', 0x03fd, /* C Ͻ */
  218. 'E', 0x018e, /* E Ǝ */
  219. 'L', 0x2143, /* L ⅃ */
  220. 'N', 0x0418, /* N И */
  221. 'R', 0x042f, /* R Я */
  222. 'S', 0x01a7, /* S Ƨ */
  223. 'c', 0x0254, /* c ɔ */
  224. 'e', 0x0258, /* e ɘ */
  225. /* CP437 */
  226. 0x258c, 0x2590, /* ▌ ▐ */
  227. 0x2596, 0x2597, /* ▖ ▗ */
  228. 0x2598, 0x259d, /* ▘ ▝ */
  229. 0x2599, 0x259f, /* ▙ ▟ */
  230. 0x259a, 0x259e, /* ▚ ▞ */
  231. 0x259b, 0x259c, /* ▛ ▜ */
  232. 0x25ba, 0x25c4, /* ► ◄ */
  233. 0x2192, 0x2190, /* → ← */
  234. 0x2310, 0xac, /* ⌐ ¬ */
  235. /* Box drawing */
  236. 0x250c, 0x2510, /* ┌ ┐ */
  237. 0x2514, 0x2518, /* └ ┘ */
  238. 0x251c, 0x2524, /* ├ ┤ */
  239. 0x250f, 0x2513, /* ┏ ┓ */
  240. 0x2517, 0x251b, /* ┗ ┛ */
  241. 0x2523, 0x252b, /* ┣ ┫ */
  242. 0x2552, 0x2555, /* ╒ ╕ */
  243. 0x2558, 0x255b, /* ╘ ╛ */
  244. 0x2553, 0x2556, /* ╓ ╖ */
  245. 0x2559, 0x255c, /* ╙ ╜ */
  246. 0x2554, 0x2557, /* ╔ ╗ */
  247. 0x255a, 0x255d, /* ╚ ╝ */
  248. 0x255e, 0x2561, /* ╞ ╡ */
  249. 0x255f, 0x2562, /* ╟ ╢ */
  250. 0x2560, 0x2563, /* ╠ ╣ */
  251. 0x2574, 0x2576, /* ╴ ╶ */
  252. 0x2578, 0x257a, /* ╸ ╺ */
  253. 0
  254. };
  255. for(i = 0; noflip[i]; i++)
  256. if(ch == noflip[i])
  257. return ch;
  258. for(i = 0; pairs[i]; i++)
  259. if(ch == pairs[i])
  260. return pairs[i ^ 1];
  261. return ch;
  262. }
  263. static uint32_t flopchar(uint32_t ch)
  264. {
  265. int i;
  266. static uint32_t const noflop[] =
  267. {
  268. /* ASCII */
  269. ' ', '(', ')', '*', '+', '-', '0', '3', '8', ':', '<', '=',
  270. '>', 'B', 'C', 'D', 'E', 'H', 'I', 'K', 'O', 'X', '[', ']',
  271. 'c', 'o', '{', '|', '}',
  272. /* CP437 and box drawing */
  273. 0x2591, 0x2592, 0x2593, 0x2588, 0x258c, 0x2590, /* ░ ▒ ▓ █ ▌ ▐ */
  274. 0x2500, 0x2501, 0x2503, 0x2503, 0x253c, 0x254b, /* ─ ━ │ ┃ ┼ ╋ */
  275. 0x251c, 0x2524, 0x2523, 0x252b, 0x2560, 0x2563, /* ├ ┤ ┣ ┫ ╠ ╣ */
  276. 0x2550, 0x2551, 0x256c, /* ═ ║ ╬ */
  277. 0x2574, 0x2576, 0x2578, 0x257a, /* ╴ ╶ ╸ ╺ */
  278. 0
  279. };
  280. static uint32_t const pairs[] =
  281. {
  282. /* ASCII */
  283. '/', '\\',
  284. 'M', 'W',
  285. ',', '`',
  286. 'b', 'p',
  287. 'd', 'q',
  288. 'p', 'q',
  289. 'f', 't',
  290. '.', '\'',
  291. /* ASCII-Unicode */
  292. '_', 0x203e, /* _ ‾ */
  293. '!', 0x00a1, /* ! ¡ */
  294. 'L', 0x0413, /* L Г */
  295. 'N', 0x0418, /* N И */
  296. 'P', 0x042c, /* P Ь */
  297. 'R', 0x0281, /* R ʁ */
  298. 'S', 0x01a7, /* S Ƨ */
  299. 'U', 0x0548, /* U Ո */
  300. 'V', 0x039b, /* V Λ */
  301. 'Y', 0x2144, /* Y ⅄ */
  302. 'h', 0x03bc, /* h μ */
  303. 'i', 0x1d09, /* i ᴉ */
  304. 'v', 0x028c, /* v ʌ */
  305. 'w', 0x028d, /* w ʍ */
  306. 'y', 0x03bb, /* y λ */
  307. /* Not perfect, but better than nothing */
  308. '"', 0x201e, /* " „ */
  309. 'm', 0x026f, /* m ɯ */
  310. 'n', 'u',
  311. /* CP437 */
  312. 0x2584, 0x2580, /* ▄ ▀ */
  313. 0x2596, 0x2598, /* ▖ ▘ */
  314. 0x2597, 0x259d, /* ▗ ▝ */
  315. 0x2599, 0x259b, /* ▙ ▛ */
  316. 0x259f, 0x259c, /* ▟ ▜ */
  317. 0x259a, 0x259e, /* ▚ ▞ */
  318. /* Box drawing */
  319. 0x250c, 0x2514, /* ┌ └ */
  320. 0x2510, 0x2518, /* ┐ ┘ */
  321. 0x252c, 0x2534, /* ┬ ┴ */
  322. 0x250f, 0x2517, /* ┏ ┗ */
  323. 0x2513, 0x251b, /* ┓ ┛ */
  324. 0x2533, 0x253b, /* ┳ ┻ */
  325. 0x2554, 0x255a, /* ╔ ╚ */
  326. 0x2557, 0x255d, /* ╗ ╝ */
  327. 0x2566, 0x2569, /* ╦ ╩ */
  328. 0x2552, 0x2558, /* ╒ ╘ */
  329. 0x2555, 0x255b, /* ╕ ╛ */
  330. 0x2564, 0x2567, /* ╤ ╧ */
  331. 0x2553, 0x2559, /* ╓ ╙ */
  332. 0x2556, 0x255c, /* ╖ ╜ */
  333. 0x2565, 0x2568, /* ╥ ╨ */
  334. 0x2575, 0x2577, /* ╵ ╷ */
  335. 0x2579, 0x257b, /* ╹ ╻ */
  336. 0
  337. };
  338. for(i = 0; noflop[i]; i++)
  339. if(ch == noflop[i])
  340. return ch;
  341. for(i = 0; pairs[i]; i++)
  342. if(ch == pairs[i])
  343. return pairs[i ^ 1];
  344. return ch;
  345. }
  346. static uint32_t rotatechar(uint32_t ch)
  347. {
  348. int i;
  349. static uint32_t const norotate[] =
  350. {
  351. /* ASCII */
  352. ' ', '*', '+', '-', '/', '0', '8', ':', '=', 'H', 'I', 'N',
  353. 'O', 'S', 'X', 'Z', '\\', 'l', 'o', 's', 'x', 'z', '|',
  354. /* Unicode */
  355. 0x2591, 0x2592, 0x2593, 0x2588, 0x259a, 0x259e, /* ░ ▒ ▓ █ ▚ ▞ */
  356. 0x2500, 0x2501, 0x2503, 0x2503, 0x253c, 0x254b, /* ─ ━ │ ┃ ┼ ╋ */
  357. 0x2550, 0x2551, 0x256c, /* ═ ║ ╬ */
  358. 0
  359. };
  360. static uint32_t const pairs[] =
  361. {
  362. /* ASCII */
  363. '(', ')',
  364. '<', '>',
  365. '[', ']',
  366. '{', '}',
  367. '.', '\'',
  368. '6', '9',
  369. 'M', 'W',
  370. 'b', 'q',
  371. 'd', 'p',
  372. 'n', 'u',
  373. /* ASCII-Unicode */
  374. '_', 0x203e, /* _ ‾ */
  375. ',', 0x00b4, /* , ´ */
  376. '`', 0x02ce, /* ` ˎ */
  377. '&', 0x214b, /* & ⅋ */
  378. '!', 0x00a1, /* ! ¡ */
  379. '?', 0x00bf, /* ? ¿ */
  380. 'C', 0x03fd, /* C Ͻ */
  381. 'E', 0x018e, /* E Ǝ */
  382. 'F', 0x2132, /* F Ⅎ */
  383. 'L', 0x2142, /* L ⅂ */
  384. 'U', 0x0548, /* U Ո */
  385. 'V', 0x039b, /* V Λ */
  386. 'Y', 0x2144, /* Y ⅄ */
  387. 'a', 0x0250, /* a ɐ */
  388. 'c', 0x0254, /* c ɔ */
  389. 'e', 0x0259, /* e ə */
  390. 'f', 0x025f, /* f ɟ */
  391. 'g', 0x1d77, /* g ᵷ */
  392. 'h', 0x0265, /* h ɥ */
  393. 'i', 0x1d09, /* i ᴉ */
  394. 'k', 0x029e, /* k ʞ */
  395. 'm', 0x026f, /* m ɯ */
  396. 'r', 0x0279, /* r ɹ */
  397. 't', 0x0287, /* t ʇ */
  398. 'v', 0x028c, /* v ʌ */
  399. 'w', 0x028d, /* w ʍ */
  400. 'y', 0x028e, /* y ʎ */
  401. /* Not perfect, but better than nothing */
  402. '"', 0x201e, /* " „ */
  403. /* Misc Unicode */
  404. 0x00e6, 0x1d02, /* æ ᴂ */
  405. 0x0153, 0x1d14, /* œ ᴔ */
  406. /* CP437 */
  407. 0x258c, 0x2590, /* ▌ ▐ */
  408. 0x2584, 0x2580, /* ▄ ▀ */
  409. 0x2596, 0x259d, /* ▖ ▝ */
  410. 0x2597, 0x2598, /* ▗ ▘ */
  411. 0x2599, 0x259c, /* ▙ ▜ */
  412. 0x259f, 0x259b, /* ▟ ▛ */
  413. /* Box drawing */
  414. 0x250c, 0x2518, /* ┌ ┘ */
  415. 0x2510, 0x2514, /* ┐ └ */
  416. 0x251c, 0x2524, /* ├ ┤ */
  417. 0x252c, 0x2534, /* ┬ ┴ */
  418. 0x250f, 0x251b, /* ┏ ┛ */
  419. 0x2513, 0x2517, /* ┓ ┗ */
  420. 0x2523, 0x252b, /* ┣ ┫ */
  421. 0x2533, 0x253b, /* ┳ ┻ */
  422. 0x2554, 0x255d, /* ╔ ╝ */
  423. 0x2557, 0x255a, /* ╗ ╚ */
  424. 0x2560, 0x2563, /* ╠ ╣ */
  425. 0x2566, 0x2569, /* ╦ ╩ */
  426. 0x2552, 0x255b, /* ╒ ╛ */
  427. 0x2555, 0x2558, /* ╕ ╘ */
  428. 0x255e, 0x2561, /* ╞ ╡ */
  429. 0x2564, 0x2567, /* ╤ ╧ */
  430. 0x2553, 0x255c, /* ╓ ╜ */
  431. 0x2556, 0x2559, /* ╖ ╙ */
  432. 0x255f, 0x2562, /* ╟ ╢ */
  433. 0x2565, 0x2568, /* ╥ ╨ */
  434. 0x2574, 0x2576, /* ╴ ╶ */
  435. 0x2575, 0x2577, /* ╵ ╷ */
  436. 0x2578, 0x257a, /* ╸ ╺ */
  437. 0x2579, 0x257b, /* ╹ ╻ */
  438. 0
  439. };
  440. for(i = 0; norotate[i]; i++)
  441. if(ch == norotate[i])
  442. return ch;
  443. for(i = 0; pairs[i]; i++)
  444. if(ch == pairs[i])
  445. return pairs[i ^ 1];
  446. return ch;
  447. }