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