|
|
@@ -0,0 +1,277 @@ |
|
|
|
/* |
|
|
|
* makefont create libcaca font data |
|
|
|
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org> |
|
|
|
* All Rights Reserved |
|
|
|
* |
|
|
|
* $Id$ |
|
|
|
* |
|
|
|
* This program is free software; you can redistribute it and/or |
|
|
|
* modify it under the terms of the Do What The Fuck You Want To |
|
|
|
* Public License, Version 2, as published by Sam Hocevar. See |
|
|
|
* http://sam.zoy.org/wtfpl/COPYING for more details. |
|
|
|
* |
|
|
|
* Usage: |
|
|
|
* makefont |
|
|
|
*/ |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
#include <arpa/inet.h> |
|
|
|
|
|
|
|
#include <pango/pango.h> |
|
|
|
#include <pango/pangoft2.h> |
|
|
|
|
|
|
|
#define FONT "Monospace 9" |
|
|
|
#define DPI 96 |
|
|
|
#define BPP 8 |
|
|
|
|
|
|
|
static int const blocklist[] = |
|
|
|
{ |
|
|
|
0x0000, 0x0080, /* Basic latin: A, B, C, a, img, c */ |
|
|
|
0x0080, 0x0100, /* Latin-1 Supplement: Ä, Ç, å, ß */ |
|
|
|
0x0100, 0x0180, /* Latin Extended-A: Ā č Ō œ */ |
|
|
|
0x0180, 0x0250, /* Latin Extended-B: Ǝ Ƹ */ |
|
|
|
0x0250, 0x02b0, /* IPA Extensions: ɐ ɔ ɘ ʌ ʍ */ |
|
|
|
0x0370, 0x0400, /* Greek and Coptic: Λ α β */ |
|
|
|
0x0400, 0x0500, /* Cyrillic: И Я */ |
|
|
|
0x2000, 0x2070, /* General Punctuation: ‘’ “” */ |
|
|
|
#if 0 |
|
|
|
0x2100, 0x2150, /* Letterlike Symbols: Ⅎ */ |
|
|
|
#endif |
|
|
|
0x2300, 0x2400, /* Miscellaneous Technical: ⌂ */ |
|
|
|
0x2500, 0x2580, /* Box Drawing: ═ ║ ╗ ╔ ╩ */ |
|
|
|
0x2580, 0x25a0, /* Block Elements: ▛ ▞ ░ ▒ ▓ */ |
|
|
|
0, 0 |
|
|
|
}; |
|
|
|
|
|
|
|
static int printf_hex(char const *fmt, uint8_t *data, int bytes) |
|
|
|
{ |
|
|
|
char buf[BUFSIZ]; |
|
|
|
char *parser = buf; |
|
|
|
int rewind = 0; /* we use this variable to rewind 2 bytes after \000 |
|
|
|
* was printed when the next char starts with "\", too. */ |
|
|
|
|
|
|
|
while(bytes--) |
|
|
|
{ |
|
|
|
uint8_t c = *data++; |
|
|
|
if(c == '\\' || c == '"') |
|
|
|
{ |
|
|
|
parser -= rewind; |
|
|
|
parser += sprintf(parser, "\\%c", c); |
|
|
|
rewind = 0; |
|
|
|
} |
|
|
|
else if(c >= 0x20 && c < 0x7f) |
|
|
|
{ |
|
|
|
parser += sprintf(parser, "%c", c); |
|
|
|
rewind = 0; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
parser -= rewind; |
|
|
|
parser += sprintf(parser, "\\%.03o", c); |
|
|
|
rewind = c ? 0 : 2; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
parser -= rewind; |
|
|
|
parser[0] = '\0'; |
|
|
|
|
|
|
|
return printf(fmt, buf); |
|
|
|
} |
|
|
|
|
|
|
|
static int printf_u32(char const *fmt, uint32_t i) |
|
|
|
{ |
|
|
|
uint32_t ni = htonl(i); |
|
|
|
return printf_hex(fmt, (uint8_t *)&ni, 4); |
|
|
|
} |
|
|
|
|
|
|
|
static int printf_u16(char const *fmt, uint16_t i) |
|
|
|
{ |
|
|
|
uint16_t ni = htons(i); |
|
|
|
return printf_hex(fmt, (uint8_t *)&ni, 2); |
|
|
|
} |
|
|
|
|
|
|
|
int main(void) |
|
|
|
{ |
|
|
|
PangoContext *cx; |
|
|
|
PangoFontDescription *fd; |
|
|
|
PangoFontMap *fm; |
|
|
|
PangoLayout *l; |
|
|
|
PangoRectangle r; |
|
|
|
|
|
|
|
FT_Bitmap img; |
|
|
|
int width, height, b, i, n, blocks, glyphs, data_bytes; |
|
|
|
uint8_t *glyph_data; |
|
|
|
|
|
|
|
/* Initialise Pango */ |
|
|
|
fm = pango_ft2_font_map_new(); |
|
|
|
pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fm), DPI, DPI); |
|
|
|
cx = pango_ft2_font_map_create_context(PANGO_FT2_FONT_MAP(fm)); |
|
|
|
|
|
|
|
l = pango_layout_new(cx); |
|
|
|
if(!l) |
|
|
|
{ |
|
|
|
g_object_unref(cx); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
fd = pango_font_description_from_string(FONT); |
|
|
|
pango_layout_set_font_description(l, fd); |
|
|
|
pango_font_description_free(fd); |
|
|
|
|
|
|
|
/* Initialise our FreeType2 bitmap */ |
|
|
|
img.width = 256; |
|
|
|
img.pitch = 256; |
|
|
|
img.rows = 256; |
|
|
|
img.buffer = malloc(256 * 256); |
|
|
|
img.num_grays = 256; |
|
|
|
img.pixel_mode = ft_pixel_mode_grays; |
|
|
|
|
|
|
|
/* Test rendering so that we know the glyph width */ |
|
|
|
pango_layout_set_markup(l, "@", -1); |
|
|
|
pango_layout_get_extents(l, NULL, &r); |
|
|
|
width = PANGO_PIXELS(r.width); |
|
|
|
height = PANGO_PIXELS(r.height); |
|
|
|
data_bytes = ((width * height) + (8 / BPP) - 1) / (8 / BPP); |
|
|
|
glyph_data = malloc(data_bytes); |
|
|
|
|
|
|
|
/* Compute blocks and glyphs count */ |
|
|
|
blocks = 0; |
|
|
|
glyphs = 0; |
|
|
|
for(b = 0; blocklist[b + 1]; b += 2) |
|
|
|
{ |
|
|
|
blocks++; |
|
|
|
glyphs += blocklist[b + 1] - blocklist[b]; |
|
|
|
} |
|
|
|
|
|
|
|
/* Let's go! */ |
|
|
|
printf("/* libcucul font file\n"); |
|
|
|
printf(" * \"%s\": %i dpi, %i bpp, %ix%i glyphs\n", |
|
|
|
FONT, DPI, BPP, width, height); |
|
|
|
printf(" * Automatically generated by tools/makefont.c */\n"); |
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
printf("/* file: */\n"); |
|
|
|
printf("\"CACA\" /* caca_header */\n"); |
|
|
|
printf("\"FONT\" /* caca_file_type */\n"); |
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
printf("/* font_header: */\n"); |
|
|
|
printf_u32("\"%s\" /* header_size */\n", 24 + 12 * blocks + 8 * glyphs); |
|
|
|
printf_u32("\"%s\" /* data_size */\n", data_bytes * glyphs); |
|
|
|
printf_u16("\"%s\" /* version */\n", 1); |
|
|
|
printf_u16("\"%s\" /* blocks */\n", blocks); |
|
|
|
printf_u32("\"%s\" /* glyphs */\n", glyphs); |
|
|
|
printf_u16("\"%s\" /* bpp */\n", BPP); |
|
|
|
printf_u16("\"%s\" /* width */\n", width); |
|
|
|
printf_u16("\"%s\" /* height */\n", height); |
|
|
|
printf_u16("\"%s\" /* flags */\n", 1); |
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
printf("/* block_info: */\n"); |
|
|
|
n = 0; |
|
|
|
for(b = 0; blocklist[b + 1]; b += 2) |
|
|
|
{ |
|
|
|
printf_u32("\"%s", blocklist[b]); |
|
|
|
printf_u32("%s", blocklist[b + 1]); |
|
|
|
printf_u32("%s\"\n", n); |
|
|
|
n += blocklist[b + 1] - blocklist[b]; |
|
|
|
} |
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
printf("/* glyph_info: */\n"); |
|
|
|
n = 0; |
|
|
|
for(b = 0; blocklist[b + 1]; b += 2) |
|
|
|
{ |
|
|
|
for(i = blocklist[b]; i < blocklist[b + 1]; i++) |
|
|
|
{ |
|
|
|
printf_u16("\"%s", width); |
|
|
|
printf_u16("%s", height); |
|
|
|
printf_u32("%s\"\n", n * data_bytes); |
|
|
|
n++; |
|
|
|
} |
|
|
|
} |
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
printf("/* font_data: */\n"); |
|
|
|
for(b = 0; blocklist[b + 1]; b += 2) |
|
|
|
{ |
|
|
|
for(i = blocklist[b]; i < blocklist[b + 1]; i++) |
|
|
|
{ |
|
|
|
unsigned int ch = i; |
|
|
|
char buf[10], *parser; |
|
|
|
int x, y, bytes; |
|
|
|
|
|
|
|
if(ch < 0x80) |
|
|
|
{ |
|
|
|
bytes = 1; |
|
|
|
buf[0] = ch; |
|
|
|
buf[1] = '\0'; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
static const unsigned char mark[7] = |
|
|
|
{ |
|
|
|
0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC |
|
|
|
}; |
|
|
|
|
|
|
|
/* FIXME: use libcucul instead of this shit */ |
|
|
|
bytes = (ch < 0x800) ? 2 : (ch < 0x10000) ? 3 : 4; |
|
|
|
buf[bytes] = '\0'; |
|
|
|
parser = buf + bytes; |
|
|
|
|
|
|
|
switch(bytes) |
|
|
|
{ |
|
|
|
case 4: *--parser = (ch | 0x80) & 0xbf; ch >>= 6; |
|
|
|
case 3: *--parser = (ch | 0x80) & 0xbf; ch >>= 6; |
|
|
|
case 2: *--parser = (ch | 0x80) & 0xbf; ch >>= 6; |
|
|
|
} |
|
|
|
*--parser = ch | mark[bytes]; |
|
|
|
} |
|
|
|
|
|
|
|
/* Print glyph value in comment */ |
|
|
|
printf("/* U+%.04X: \"", i); |
|
|
|
|
|
|
|
if(i < 0x20 || (i >= 0x80 && i <= 0xa0)) |
|
|
|
printf("\\x%.02x\" (", i); |
|
|
|
else |
|
|
|
printf("%s\" (", buf); |
|
|
|
|
|
|
|
for(x = 0; x < bytes; x++) |
|
|
|
printf("%s0x%.02X", x ? " " : "", (unsigned char)buf[x]); |
|
|
|
|
|
|
|
printf(") */\n"); |
|
|
|
|
|
|
|
/* Render glyph on a bitmap */ |
|
|
|
pango_layout_set_text(l, buf, -1); |
|
|
|
memset(glyph_data, 0, data_bytes); |
|
|
|
memset(img.buffer, 0, img.pitch * height); |
|
|
|
pango_ft2_render_layout(&img, l, 0, 0); |
|
|
|
|
|
|
|
/* Write bitmap as an escaped C string */ |
|
|
|
n = 0; |
|
|
|
for(y = 0; y < height; y++) |
|
|
|
{ |
|
|
|
for(x = 0; x < width; x++) |
|
|
|
{ |
|
|
|
uint8_t pixel = img.buffer[y * img.pitch + x]; |
|
|
|
|
|
|
|
pixel >>= (8 - BPP); |
|
|
|
/* FIXME: BPP should appear here */ |
|
|
|
glyph_data[n / 8] |= (pixel << (n % 8)); |
|
|
|
n += BPP; |
|
|
|
} |
|
|
|
} |
|
|
|
printf_hex("\"%s\"\n", glyph_data, data_bytes); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
free(img.buffer); |
|
|
|
g_object_unref(l); |
|
|
|
g_object_unref(cx); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|