source: libcaca/trunk/tools/makefont.c @ 755

Last change on this file since 755 was 755, checked in by Sam Hocevar, 14 years ago
  • Some cleaning up in makefont.c.
  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1/*
2 *  makefont       create libcaca font data
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: makefont.c 755 2006-04-13 12:44:55Z sam $
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
17#include <stdio.h>
18#include <stdlib.h>
19#include <stdint.h>
20
21#include <arpa/inet.h>
22
23#include <pango/pango.h>
24#include <pango/pangoft2.h>
25
26#define FONT "Monospace 9"
27#define DPI 96
28#define BPP 4
29
30static int const blocklist[] =
31{
32    0x0000, 0x0080, /* Basic latin: A, B, C, a, img, 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    0x2300, 0x2400, /* Miscellaneous Technical: ⌂ */
44    0x2500, 0x2580, /* Box Drawing: ═ ║ ╗ ╔ ╩ */
45    0x2580, 0x25a0, /* Block Elements: ▛ ▞ ░ ▒ ▓ */
46    0, 0
47};
48
49static int printf_hex(char const *, uint8_t *, int);
50static int printf_u32(char const *, uint32_t);
51static int printf_u16(char const *, uint16_t);
52
53int main(void)
54{
55    PangoContext *cx;
56    PangoFontDescription *fd;
57    PangoFontMap *fm;
58    PangoLayout *l;
59    PangoRectangle r;
60
61    FT_Bitmap img;
62    int width, height, b, i, n, blocks, glyphs, data_bytes;
63    uint8_t *glyph_data;
64
65    int bpp = BPP;
66    int dpi = DPI;
67    char const *font = FONT;
68
69    fprintf(stderr, "Font \"%s\", %i dpi, %i bpp\n", font, dpi, bpp);
70
71    /* Initialise Pango */
72    fm = pango_ft2_font_map_new();
73    pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fm), dpi, dpi);
74    cx = pango_ft2_font_map_create_context(PANGO_FT2_FONT_MAP(fm));
75
76    l = pango_layout_new(cx);
77    if(!l)
78    {
79        g_object_unref(cx);
80        return -1;
81    }
82
83    fd = pango_font_description_from_string(font);
84    pango_layout_set_font_description(l, fd);
85    pango_font_description_free(fd);
86
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
95    /* Test rendering so that we know the glyph width */
96    pango_layout_set_markup(l, "@", -1);
97    pango_layout_get_extents(l, NULL, &r);
98    width = PANGO_PIXELS(r.width);
99    height = PANGO_PIXELS(r.height);
100    data_bytes = ((width * height) + (8 / bpp) - 1) / (8 / bpp);
101    glyph_data = malloc(data_bytes);
102
103    /* Compute blocks and glyphs count */
104    blocks = 0;
105    glyphs = 0;
106    for(b = 0; blocklist[b + 1]; b += 2)
107    {
108        blocks++;
109        glyphs += blocklist[b + 1] - blocklist[b];
110    }
111
112    /* Let's go! */
113    printf("/* libcucul font file\n");
114    printf(" * \"%s\": %i dpi, %i bpp, %ix%i glyphs\n",
115           font, dpi, bpp, width, height);
116    printf(" * Automatically generated by tools/makefont.c */\n");
117    printf("\n");
118
119    printf("/* file: */\n");
120    printf("\"CACA\" /* caca_header */\n");
121    printf("\"FONT\" /* caca_file_type */\n");
122    printf("\n");
123
124    printf("/* font_header: */\n");
125    printf_u32("\"%s\" /* header_size */\n", 24 + 12 * blocks + 8 * glyphs);
126    printf_u32("\"%s\" /* data_size */\n", data_bytes * glyphs);
127    printf_u16("\"%s\" /* version */\n", 1);
128    printf_u16("\"%s\" /* blocks */\n", blocks);
129    printf_u32("\"%s\" /* glyphs */\n", glyphs);
130    printf_u16("\"%s\" /* bpp */\n", bpp);
131    printf_u16("\"%s\" /* width */\n", width);
132    printf_u16("\"%s\" /* height */\n", height);
133    printf_u16("\"%s\" /* flags */\n", 1);
134    printf("\n");
135
136    printf("/* block_info: */\n");
137    n = 0;
138    for(b = 0; blocklist[b + 1]; b += 2)
139    {
140        printf_u32("\"%s", blocklist[b]);
141        printf_u32("%s", blocklist[b + 1]);
142        printf_u32("%s\"\n", n);
143        n += blocklist[b + 1] - blocklist[b];
144    }
145    printf("\n");
146
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 * data_bytes);
156            n++;
157        }
158    }
159    printf("\n");
160
161    printf("/* font_data: */\n");
162    for(b = 0; blocklist[b + 1]; b += 2)
163    {
164        for(i = blocklist[b]; i < blocklist[b + 1]; i++)
165        {
166            unsigned int ch = i;
167            char buf[10], *parser;
168            int x, y, bytes;
169
170            if(ch < 0x80)
171            {
172                bytes = 1;
173                buf[0] = ch;
174                buf[1] = '\0';
175            }
176            else
177            {
178                static const unsigned char mark[7] =
179                {
180                    0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
181                };
182
183                /* FIXME: use libcucul instead of this shit */
184                bytes = (ch < 0x800) ? 2 : (ch < 0x10000) ? 3 : 4;
185                buf[bytes] = '\0';
186                parser = buf + bytes;
187
188                switch(bytes)
189                {
190                    case 4: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
191                    case 3: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
192                    case 2: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
193                }
194                *--parser = ch | mark[bytes];
195            }
196
197            /* Print glyph value in comment */
198            printf("/* U+%.04X: \"", i);
199
200            if(i < 0x20 || (i >= 0x80 && i <= 0xa0))
201                printf("\\x%.02x\" */", i);
202            else
203                printf("%s\" */ ", buf);
204
205            /* Render glyph on a bitmap */
206            pango_layout_set_text(l, buf, -1);
207            memset(glyph_data, 0, data_bytes);
208            memset(img.buffer, 0, img.pitch * height);
209            pango_ft2_render_layout(&img, l, 0, 0);
210
211            /* Write bitmap as an escaped C string */
212            n = 0;
213            for(y = 0; y < height; y++)
214            {
215                for(x = 0; x < width; x++)
216                {
217                    uint8_t pixel = img.buffer[y * img.pitch + x];
218
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, data_bytes);
225        }
226    }
227
228    free(img.buffer);
229    g_object_unref(l);
230    g_object_unref(cx);
231
232    return 0;
233}
234
235/*
236 * XXX: the following functions are local
237 */
238
239static int printf_u32(char const *fmt, uint32_t i)
240{
241    uint32_t ni = htonl(i);
242    return printf_hex(fmt, (uint8_t *)&ni, 4);
243}
244
245static int printf_u16(char const *fmt, uint16_t i)
246{
247    uint16_t ni = htons(i);
248    return printf_hex(fmt, (uint8_t *)&ni, 2);
249}
250
251static int printf_hex(char const *fmt, uint8_t *data, int bytes)
252{
253    char buf[BUFSIZ];
254    char *parser = buf;
255    int rewind = 0; /* we use this variable to rewind 2 bytes after \000
256                     * was printed when the next char starts with "\", too. */
257
258    while(bytes--)
259    {
260        uint8_t c = *data++;
261        if(c == '\\' || c == '"')
262        {
263            parser -= rewind;
264            parser += sprintf(parser, "\\%c", c);
265            rewind = 0;
266        }
267        else if(c >= 0x20 && c < 0x7f)
268        {
269            parser += sprintf(parser, "%c", c);
270            rewind = 0;
271        }
272        else
273        {
274            parser -= rewind;
275            parser += sprintf(parser, "\\%.03o", c);
276            rewind = c ? 0 : 2;
277        }
278    }
279
280    parser -= rewind;
281    parser[0] = '\0';
282
283    return printf(fmt, buf);
284}
285
Note: See TracBrowser for help on using the repository browser.