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.

преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * makefont create libcaca font data
  3. * Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program 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. * Usage:
  14. * makefont
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <stdint.h>
  19. #include <arpa/inet.h>
  20. #include <pango/pango.h>
  21. #include <pango/pangoft2.h>
  22. static int const blocklist[] =
  23. {
  24. 0x0000, 0x0080, /* Basic latin: A, B, C, a, img, c */
  25. 0x0080, 0x0100, /* Latin-1 Supplement: Ä, Ç, å, ß */
  26. 0x0100, 0x0180, /* Latin Extended-A: Ā č Ō œ */
  27. 0x0180, 0x0250, /* Latin Extended-B: Ǝ Ƹ */
  28. 0x0250, 0x02b0, /* IPA Extensions: ɐ ɔ ɘ ʌ ʍ */
  29. 0x0370, 0x0400, /* Greek and Coptic: Λ α β */
  30. 0x0400, 0x0500, /* Cyrillic: И Я */
  31. 0x2000, 0x2070, /* General Punctuation: ‘’ “” */
  32. #if 0
  33. 0x2100, 0x2150, /* Letterlike Symbols: Ⅎ */
  34. #endif
  35. 0x2300, 0x2400, /* Miscellaneous Technical: ⌂ */
  36. 0x2500, 0x2580, /* Box Drawing: ═ ║ ╗ ╔ ╩ */
  37. 0x2580, 0x25a0, /* Block Elements: ▛ ▞ ░ ▒ ▓ */
  38. 0, 0
  39. };
  40. static int printf_hex(char const *, uint8_t *, int);
  41. static int printf_u32(char const *, uint32_t);
  42. static int printf_u16(char const *, uint16_t);
  43. int main(int argc, char *argv[])
  44. {
  45. PangoContext *cx;
  46. PangoFontDescription *fd;
  47. PangoFontMap *fm;
  48. PangoLayout *l;
  49. PangoRectangle r;
  50. FT_Bitmap img;
  51. int width, height, b, i, n, blocks, glyphs;
  52. unsigned int glyph_size, control_size, data_size;
  53. uint8_t *glyph_data;
  54. unsigned int bpp, dpi;
  55. char const *prefix, *font;
  56. if(argc != 5)
  57. {
  58. fprintf(stderr, "%s: wrong argument count\n", argv[0]);
  59. fprintf(stderr, "usage: %s <prefix> <font> <dpi> <bpp>\n", argv[0]);
  60. fprintf(stderr, "eg: %s monospace9 \"Monospace 9\" 96 4\n", argv[0]);
  61. return -1;
  62. }
  63. prefix = argv[1];
  64. font = argv[2];
  65. dpi = atoi(argv[3]);
  66. bpp = atoi(argv[4]);
  67. if(dpi == 0 || (bpp != 1 && bpp != 2 && bpp != 4 && bpp != 8))
  68. {
  69. fprintf(stderr, "%s: invalid argument\n", argv[0]);
  70. return -1;
  71. }
  72. fprintf(stderr, "Font \"%s\", %i dpi, %i bpp\n", font, dpi, bpp);
  73. /* Initialise Pango */
  74. fm = pango_ft2_font_map_new();
  75. pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fm), dpi, dpi);
  76. cx = pango_ft2_font_map_create_context(PANGO_FT2_FONT_MAP(fm));
  77. l = pango_layout_new(cx);
  78. if(!l)
  79. {
  80. fprintf(stderr, "%s: unable to initialise pango\n", argv[0]);
  81. g_object_unref(cx);
  82. return -1;
  83. }
  84. fd = pango_font_description_from_string(font);
  85. pango_layout_set_font_description(l, fd);
  86. pango_font_description_free(fd);
  87. /* Initialise our FreeType2 bitmap */
  88. img.width = 256;
  89. img.pitch = 256;
  90. img.rows = 256;
  91. img.buffer = malloc(256 * 256);
  92. img.num_grays = 256;
  93. img.pixel_mode = ft_pixel_mode_grays;
  94. /* Test rendering so that we know the glyph width */
  95. pango_layout_set_markup(l, "@", -1);
  96. pango_layout_get_extents(l, NULL, &r);
  97. width = PANGO_PIXELS(r.width);
  98. height = PANGO_PIXELS(r.height);
  99. glyph_size = ((width * height) + (8 / bpp) - 1) / (8 / bpp);
  100. glyph_data = malloc(glyph_size);
  101. /* Compute blocks and glyphs count */
  102. blocks = 0;
  103. glyphs = 0;
  104. for(b = 0; blocklist[b + 1]; b += 2)
  105. {
  106. blocks++;
  107. glyphs += blocklist[b + 1] - blocklist[b];
  108. }
  109. control_size = 24 + 12 * blocks + 8 * glyphs;
  110. data_size = glyph_size * glyphs;
  111. /* Let's go! */
  112. printf("/* libcucul font file\n");
  113. printf(" * \"%s\": %i dpi, %i bpp, %ix%i glyphs\n",
  114. font, dpi, bpp, width, height);
  115. printf(" * Automatically generated by tools/makefont.c:\n");
  116. printf(" * tools/makefont %s \"%s\" %i %i\n", prefix, font, dpi, bpp);
  117. printf(" */\n");
  118. printf("\n");
  119. printf("static unsigned int const %s_size = %i;\n",
  120. prefix, 8 + control_size + data_size);
  121. printf("static unsigned char const %s_data[] =\n", prefix);
  122. printf("/* file: */\n");
  123. printf("\"CACA\" /* caca_header */\n");
  124. printf("\"FONT\" /* caca_file_type */\n");
  125. printf("\n");
  126. printf("/* font_header: */\n");
  127. printf_u32("\"%s\" /* control_size */\n", control_size);
  128. printf_u32("\"%s\" /* data_size */\n", data_size);
  129. printf_u16("\"%s\" /* version */\n", 1);
  130. printf_u16("\"%s\" /* blocks */\n", blocks);
  131. printf_u32("\"%s\" /* glyphs */\n", glyphs);
  132. printf_u16("\"%s\" /* bpp */\n", bpp);
  133. printf_u16("\"%s\" /* width */\n", width);
  134. printf_u16("\"%s\" /* height */\n", height);
  135. printf_u16("\"%s\" /* flags */\n", 1);
  136. printf("\n");
  137. printf("/* block_info: */\n");
  138. n = 0;
  139. for(b = 0; blocklist[b + 1]; b += 2)
  140. {
  141. printf_u32("\"%s", blocklist[b]);
  142. printf_u32("%s", blocklist[b + 1]);
  143. printf_u32("%s\"\n", n);
  144. n += blocklist[b + 1] - blocklist[b];
  145. }
  146. printf("\n");
  147. printf("/* glyph_info: */\n");
  148. n = 0;
  149. for(b = 0; blocklist[b + 1]; b += 2)
  150. {
  151. for(i = blocklist[b]; i < blocklist[b + 1]; i++)
  152. {
  153. printf_u16("\"%s", width);
  154. printf_u16("%s", height);
  155. printf_u32("%s\"\n", n * glyph_size);
  156. n++;
  157. }
  158. }
  159. printf("\n");
  160. printf("/* font_data: */\n");
  161. for(b = 0; blocklist[b + 1]; b += 2)
  162. {
  163. for(i = blocklist[b]; i < blocklist[b + 1]; i++)
  164. {
  165. unsigned int ch = i;
  166. char buf[10], *parser;
  167. int x, y, bytes;
  168. if(ch < 0x80)
  169. {
  170. bytes = 1;
  171. buf[0] = ch;
  172. buf[1] = '\0';
  173. }
  174. else
  175. {
  176. static const unsigned char mark[7] =
  177. {
  178. 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
  179. };
  180. /* FIXME: use libcucul instead of this shit */
  181. bytes = (ch < 0x800) ? 2 : (ch < 0x10000) ? 3 : 4;
  182. buf[bytes] = '\0';
  183. parser = buf + bytes;
  184. switch(bytes)
  185. {
  186. case 4: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
  187. case 3: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
  188. case 2: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
  189. }
  190. *--parser = ch | mark[bytes];
  191. }
  192. /* Print glyph value in comment */
  193. printf("/* U+%.04X: \"", i);
  194. if(i < 0x20 || (i >= 0x80 && i <= 0xa0))
  195. printf("\\x%.02x\" */", i);
  196. else
  197. printf("%s\" */ ", buf);
  198. /* Render glyph on a bitmap */
  199. pango_layout_set_text(l, buf, -1);
  200. memset(glyph_data, 0, glyph_size);
  201. memset(img.buffer, 0, img.pitch * height);
  202. pango_ft2_render_layout(&img, l, 0, 0);
  203. /* Write bitmap as an escaped C string */
  204. n = 0;
  205. for(y = 0; y < height; y++)
  206. {
  207. for(x = 0; x < width; x++)
  208. {
  209. uint8_t pixel = img.buffer[y * img.pitch + x];
  210. pixel >>= (8 - bpp);
  211. glyph_data[n / 8] |= pixel << (8 - bpp - (n % 8));
  212. n += bpp;
  213. }
  214. }
  215. printf_hex("\"%s\"\n", glyph_data, glyph_size);
  216. }
  217. }
  218. printf(";\n");
  219. free(img.buffer);
  220. g_object_unref(l);
  221. g_object_unref(cx);
  222. return 0;
  223. }
  224. /*
  225. * XXX: the following functions are local
  226. */
  227. static int printf_u32(char const *fmt, uint32_t i)
  228. {
  229. uint32_t ni = htonl(i);
  230. return printf_hex(fmt, (uint8_t *)&ni, 4);
  231. }
  232. static int printf_u16(char const *fmt, uint16_t i)
  233. {
  234. uint16_t ni = htons(i);
  235. return printf_hex(fmt, (uint8_t *)&ni, 2);
  236. }
  237. static int printf_hex(char const *fmt, uint8_t *data, int bytes)
  238. {
  239. char buf[BUFSIZ];
  240. char *parser = buf;
  241. int rewind = 0; /* we use this variable to rewind 2 bytes after \000
  242. * was printed when the next char starts with "\", too. */
  243. while(bytes--)
  244. {
  245. uint8_t c = *data++;
  246. if(c == '\\' || c == '"')
  247. {
  248. parser -= rewind;
  249. parser += sprintf(parser, "\\%c", c);
  250. rewind = 0;
  251. }
  252. else if(c >= 0x20 && c < 0x7f)
  253. {
  254. parser += sprintf(parser, "%c", c);
  255. rewind = 0;
  256. }
  257. else
  258. {
  259. parser -= rewind;
  260. parser += sprintf(parser, "\\%.03o", c);
  261. rewind = c ? 0 : 2;
  262. }
  263. }
  264. parser -= rewind;
  265. parser[0] = '\0';
  266. return printf(fmt, buf);
  267. }