Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

278 righe
7.6 KiB

  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 8
  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 *fmt, uint8_t *data, int bytes)
  44. {
  45. char buf[BUFSIZ];
  46. char *parser = buf;
  47. int rewind = 0; /* we use this variable to rewind 2 bytes after \000
  48. * was printed when the next char starts with "\", too. */
  49. while(bytes--)
  50. {
  51. uint8_t c = *data++;
  52. if(c == '\\' || c == '"')
  53. {
  54. parser -= rewind;
  55. parser += sprintf(parser, "\\%c", c);
  56. rewind = 0;
  57. }
  58. else if(c >= 0x20 && c < 0x7f)
  59. {
  60. parser += sprintf(parser, "%c", c);
  61. rewind = 0;
  62. }
  63. else
  64. {
  65. parser -= rewind;
  66. parser += sprintf(parser, "\\%.03o", c);
  67. rewind = c ? 0 : 2;
  68. }
  69. }
  70. parser -= rewind;
  71. parser[0] = '\0';
  72. return printf(fmt, buf);
  73. }
  74. static int printf_u32(char const *fmt, uint32_t i)
  75. {
  76. uint32_t ni = htonl(i);
  77. return printf_hex(fmt, (uint8_t *)&ni, 4);
  78. }
  79. static int printf_u16(char const *fmt, uint16_t i)
  80. {
  81. uint16_t ni = htons(i);
  82. return printf_hex(fmt, (uint8_t *)&ni, 2);
  83. }
  84. int main(void)
  85. {
  86. PangoContext *cx;
  87. PangoFontDescription *fd;
  88. PangoFontMap *fm;
  89. PangoLayout *l;
  90. PangoRectangle r;
  91. FT_Bitmap img;
  92. int width, height, b, i, n, blocks, glyphs, data_bytes;
  93. uint8_t *glyph_data;
  94. /* Initialise Pango */
  95. fm = pango_ft2_font_map_new();
  96. pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fm), DPI, DPI);
  97. cx = pango_ft2_font_map_create_context(PANGO_FT2_FONT_MAP(fm));
  98. l = pango_layout_new(cx);
  99. if(!l)
  100. {
  101. g_object_unref(cx);
  102. return -1;
  103. }
  104. fd = pango_font_description_from_string(FONT);
  105. pango_layout_set_font_description(l, fd);
  106. pango_font_description_free(fd);
  107. /* Initialise our FreeType2 bitmap */
  108. img.width = 256;
  109. img.pitch = 256;
  110. img.rows = 256;
  111. img.buffer = malloc(256 * 256);
  112. img.num_grays = 256;
  113. img.pixel_mode = ft_pixel_mode_grays;
  114. /* Test rendering so that we know the glyph width */
  115. pango_layout_set_markup(l, "@", -1);
  116. pango_layout_get_extents(l, NULL, &r);
  117. width = PANGO_PIXELS(r.width);
  118. height = PANGO_PIXELS(r.height);
  119. data_bytes = ((width * height) + (8 / BPP) - 1) / (8 / BPP);
  120. glyph_data = malloc(data_bytes);
  121. /* Compute blocks and glyphs count */
  122. blocks = 0;
  123. glyphs = 0;
  124. for(b = 0; blocklist[b + 1]; b += 2)
  125. {
  126. blocks++;
  127. glyphs += blocklist[b + 1] - blocklist[b];
  128. }
  129. /* Let's go! */
  130. printf("/* libcucul font file\n");
  131. printf(" * \"%s\": %i dpi, %i bpp, %ix%i glyphs\n",
  132. FONT, DPI, BPP, width, height);
  133. printf(" * Automatically generated by tools/makefont.c */\n");
  134. printf("\n");
  135. printf("/* file: */\n");
  136. printf("\"CACA\" /* caca_header */\n");
  137. printf("\"FONT\" /* caca_file_type */\n");
  138. printf("\n");
  139. printf("/* font_header: */\n");
  140. printf_u32("\"%s\" /* header_size */\n", 24 + 12 * blocks + 8 * glyphs);
  141. printf_u32("\"%s\" /* data_size */\n", data_bytes * glyphs);
  142. printf_u16("\"%s\" /* version */\n", 1);
  143. printf_u16("\"%s\" /* blocks */\n", blocks);
  144. printf_u32("\"%s\" /* glyphs */\n", glyphs);
  145. printf_u16("\"%s\" /* bpp */\n", BPP);
  146. printf_u16("\"%s\" /* width */\n", width);
  147. printf_u16("\"%s\" /* height */\n", height);
  148. printf_u16("\"%s\" /* flags */\n", 1);
  149. printf("\n");
  150. printf("/* block_info: */\n");
  151. n = 0;
  152. for(b = 0; blocklist[b + 1]; b += 2)
  153. {
  154. printf_u32("\"%s", blocklist[b]);
  155. printf_u32("%s", blocklist[b + 1]);
  156. printf_u32("%s\"\n", n);
  157. n += blocklist[b + 1] - blocklist[b];
  158. }
  159. printf("\n");
  160. printf("/* glyph_info: */\n");
  161. n = 0;
  162. for(b = 0; blocklist[b + 1]; b += 2)
  163. {
  164. for(i = blocklist[b]; i < blocklist[b + 1]; i++)
  165. {
  166. printf_u16("\"%s", width);
  167. printf_u16("%s", height);
  168. printf_u32("%s\"\n", n * data_bytes);
  169. n++;
  170. }
  171. }
  172. printf("\n");
  173. printf("/* font_data: */\n");
  174. for(b = 0; blocklist[b + 1]; b += 2)
  175. {
  176. for(i = blocklist[b]; i < blocklist[b + 1]; i++)
  177. {
  178. unsigned int ch = i;
  179. char buf[10], *parser;
  180. int x, y, bytes;
  181. if(ch < 0x80)
  182. {
  183. bytes = 1;
  184. buf[0] = ch;
  185. buf[1] = '\0';
  186. }
  187. else
  188. {
  189. static const unsigned char mark[7] =
  190. {
  191. 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
  192. };
  193. /* FIXME: use libcucul instead of this shit */
  194. bytes = (ch < 0x800) ? 2 : (ch < 0x10000) ? 3 : 4;
  195. buf[bytes] = '\0';
  196. parser = buf + bytes;
  197. switch(bytes)
  198. {
  199. case 4: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
  200. case 3: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
  201. case 2: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
  202. }
  203. *--parser = ch | mark[bytes];
  204. }
  205. /* Print glyph value in comment */
  206. printf("/* U+%.04X: \"", i);
  207. if(i < 0x20 || (i >= 0x80 && i <= 0xa0))
  208. printf("\\x%.02x\" (", i);
  209. else
  210. printf("%s\" (", buf);
  211. for(x = 0; x < bytes; x++)
  212. printf("%s0x%.02X", x ? " " : "", (unsigned char)buf[x]);
  213. printf(") */\n");
  214. /* Render glyph on a bitmap */
  215. pango_layout_set_text(l, buf, -1);
  216. memset(glyph_data, 0, data_bytes);
  217. memset(img.buffer, 0, img.pitch * height);
  218. pango_ft2_render_layout(&img, l, 0, 0);
  219. /* Write bitmap as an escaped C string */
  220. n = 0;
  221. for(y = 0; y < height; y++)
  222. {
  223. for(x = 0; x < width; x++)
  224. {
  225. uint8_t pixel = img.buffer[y * img.pitch + x];
  226. pixel >>= (8 - BPP);
  227. /* FIXME: BPP should appear here */
  228. glyph_data[n / 8] |= (pixel << (n % 8));
  229. n += BPP;
  230. }
  231. }
  232. printf_hex("\"%s\"\n", glyph_data, data_bytes);
  233. }
  234. }
  235. free(img.buffer);
  236. g_object_unref(l);
  237. g_object_unref(cx);
  238. return 0;
  239. }