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.

sortchars.c 6.7 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * sortchars analyse ASCII characters
  3. * Copyright (c) 2007 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program 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. #include "config.h"
  15. #include "common.h"
  16. #if !defined(__KERNEL__)
  17. # if defined(HAVE_INTTYPES_H)
  18. # include <inttypes.h>
  19. # endif
  20. # include <stdio.h>
  21. # include <string.h>
  22. # include <stdlib.h>
  23. #endif
  24. #include "cucul.h"
  25. #define GLYPHS 0x7f
  26. #define FONT 0 /* 0 or 1 */
  27. #define DX 2
  28. #define DY 3
  29. #define RANGEBITS 2
  30. #define RANGE (1 << RANGEBITS)
  31. #define FULLRANGE (1 << (RANGEBITS * DX * DY))
  32. int total[GLYPHS][DX][DY];
  33. int16_t allbits[GLYPHS];
  34. int bestchar[FULLRANGE];
  35. static int curve[17] = /* 17 instead of 16 */
  36. {
  37. 0, 4, 6, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15
  38. //0, 3, 5, 7, 8, 9, 10, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15
  39. //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15
  40. };
  41. static int distance(uint16_t, uint16_t);
  42. static void testcircle(void);
  43. int main(int argc, char *argv[])
  44. {
  45. int count[DX][DY];
  46. char utf8[7];
  47. cucul_canvas_t *cv;
  48. cucul_font_t *f;
  49. char const * const * fonts;
  50. uint8_t *img;
  51. unsigned int w, h, x, y;
  52. int ret, i, max;
  53. /* Load a libcucul internal font */
  54. fonts = cucul_get_font_list();
  55. if(fonts[FONT] == NULL)
  56. {
  57. fprintf(stderr, "error: libcucul was compiled without any fonts\n");
  58. return -1;
  59. }
  60. f = cucul_load_font(fonts[FONT], 0);
  61. if(f == NULL)
  62. {
  63. fprintf(stderr, "error: could not load font \"%s\"\n", fonts[0]);
  64. return -1;
  65. }
  66. cv = cucul_create_canvas(1, 1);
  67. cucul_set_color_ansi(cv, CUCUL_WHITE, CUCUL_BLACK);
  68. /* Create our bitmap buffer (32-bit ARGB) */
  69. w = cucul_get_font_width(f);
  70. h = cucul_get_font_height(f);
  71. img = malloc(4 * w * h);
  72. /* Zero our structures */
  73. for(y = 0; y < DY; y++)
  74. for(x = 0; x < DX; x++)
  75. count[x][y] = 0;
  76. for(y = 0; y < h; y++)
  77. for(x = 0; x < w; x++)
  78. count[x * DX / w][y * DY / h]++;
  79. for(i = 0x20; i < GLYPHS; i++)
  80. for(y = 0; y < DY; y++)
  81. for(x = 0; x < DX; x++)
  82. total[GLYPHS][x][y] = 0;
  83. /* Draw all glyphs and count their pixels */
  84. for(i = 0x20; i < GLYPHS; i++)
  85. {
  86. cucul_put_char(cv, 0, 0, i);
  87. /* Render the canvas onto our image buffer */
  88. cucul_render_canvas(cv, f, img, w, h, 4 * w);
  89. for(y = 0; y < h * DY; y++)
  90. for(x = 0; x < w * DX; x++)
  91. total[i][x / w][y / h]
  92. += img[(w * (y / DY) + (x / DX)) * 4 + 1];
  93. }
  94. /* Compute max pixel value */
  95. max = 0;
  96. for(i = 0x20; i < GLYPHS; i++)
  97. for(y = 0; y < DY; y++)
  98. for(x = 0; x < DX; x++)
  99. {
  100. int val = total[i][x][y] * 256 / count[x][y];
  101. if(val > max)
  102. max = val;
  103. }
  104. /* Compute bits for all glyphs */
  105. for(i = 0x20; i < GLYPHS; i++)
  106. {
  107. int bits = 0;
  108. if(i >= 0x7f && i <= 0x9f)
  109. {
  110. allbits[i] = 0;
  111. continue;
  112. }
  113. for(y = 0; y < DY; y++)
  114. {
  115. for(x = 0; x < DX; x++)
  116. {
  117. int t = total[i][x][y] * 16 * 256 / (count[x][y] * max);
  118. bits *= RANGE;
  119. bits |= curve[t] / (16 / RANGE);
  120. }
  121. }
  122. allbits[i] = bits;
  123. }
  124. /* Find a glyph for all combinations */
  125. for(i = 0; i < FULLRANGE; i++)
  126. {
  127. int j, mindist = 0x1000, best = 0;
  128. for(j = 0x20; j < GLYPHS; j++)
  129. {
  130. int d = distance(i, allbits[j]);
  131. if(d < mindist)
  132. {
  133. best = j;
  134. mindist = d;
  135. if(d == 0)
  136. break;
  137. }
  138. }
  139. bestchar[i] = best;
  140. }
  141. /* Print results */
  142. printf("/* Generated by sortchars.c */\n");
  143. printf("static char const cells_to_ascii[%i] =\n{\n ", FULLRANGE);
  144. for(i = 0; i < FULLRANGE; i++)
  145. {
  146. ret = cucul_utf32_to_utf8(utf8, bestchar[i]);
  147. utf8[ret] = '\0';
  148. printf("%i, ", bestchar[i]);
  149. if((i % 16) == 15 && i != FULLRANGE - 1)
  150. printf("\n ");
  151. }
  152. printf("\n};\n\n");
  153. printf("static uint16_t const ascii_to_cells[%i] =\n{\n ", GLYPHS);
  154. for(i = 0; i < GLYPHS; i++)
  155. {
  156. ret = cucul_utf32_to_utf8(utf8, bestchar[i]);
  157. utf8[ret] = '\0';
  158. printf("0x%03x, ", allbits[i]);
  159. if((i % 8) == 7 && i != GLYPHS - 1)
  160. printf("\n ");
  161. }
  162. printf("\n};\n");
  163. cucul_free_canvas(cv);
  164. testcircle();
  165. return 0;
  166. }
  167. static int distance(uint16_t mychar, uint16_t x)
  168. {
  169. int i, d = 0;
  170. for(i = 0; i < DX * DY; i++)
  171. {
  172. int t = (int)(mychar & (RANGE - 1)) - (int)(x & (RANGE - 1));
  173. d += t > 0 ? 1 * t : -2 * t;
  174. mychar /= RANGE;
  175. x /= RANGE;
  176. }
  177. return d;
  178. }
  179. #define WIDTH 40
  180. #define HEIGHT 18
  181. static void testcircle(void)
  182. {
  183. char utf8[7];
  184. uint8_t *buf = malloc(256 * 256);
  185. uint16_t *dst = malloc(WIDTH * DX * HEIGHT * DY * sizeof(uint16_t));
  186. int x, y, ret;
  187. memset(buf, 0, 256 * 256);
  188. memset(dst, 0, WIDTH * DX * HEIGHT * DY);
  189. /* Fill image */
  190. for(y = 0; y < 256; y++)
  191. for(x = 0; x < 256; x++)
  192. {
  193. int dist2 = (x - 128) * (x - 128) + (y - 128) * (y - 128);
  194. if(dist2 < 25000 && dist2 > 18000)
  195. buf[y * 256 + x] = 255;
  196. else if(dist2 < 14000 && dist2 > 9000)
  197. buf[y * 256 + x] = 204;
  198. else if(dist2 < 6000 && dist2 > 3000)
  199. buf[y * 256 + x] = 153;
  200. else if(dist2 < 1600 && dist2 > 300)
  201. buf[y * 256 + x] = 102;
  202. }
  203. /* Parse image */
  204. for(y = 0; y < HEIGHT * DY; y++)
  205. for(x = 0; x < WIDTH * DX; x++)
  206. dst[y * WIDTH * DX + x] = (int)buf[(y * 256 / (HEIGHT * DY)) * 256 + (x * 256 / (WIDTH * DX))] * RANGE / 256;
  207. printf("/* example:\n");
  208. for(y = 0; y < HEIGHT; y++)
  209. {
  210. for(x = 0; x < WIDTH; x++)
  211. {
  212. uint16_t bits = 0;
  213. int i, j;
  214. for(j = 0; j < DY; j++)
  215. for(i = 0; i < DX; i++)
  216. {
  217. bits *= RANGE;
  218. bits |= dst[(y * DY + j) * WIDTH * DX + x * DX + i];
  219. }
  220. ret = cucul_utf32_to_utf8(utf8, bestchar[bits]);
  221. utf8[ret] = '\0';
  222. printf("%s", utf8);
  223. }
  224. printf("\n");
  225. }
  226. printf("*/\n");
  227. }