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.

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