Browse Source

* Added a font creator that uses pango to render glyphs.

tags/v0.99.beta14
Sam Hocevar sam 19 years ago
parent
commit
fed62ed798
3 changed files with 296 additions and 2 deletions
  1. +9
    -1
      configure.ac
  2. +10
    -1
      tools/Makefile.am
  3. +277
    -0
      tools/makefont.c

+ 9
- 1
configure.ac View File

@@ -21,8 +21,10 @@ AC_C_INLINE
AC_TYPE_SIGNAL

dnl AC_PROG_EGREP only exists in autoconf 2.54+, so we use AC_EGREP_CPP right
dnl now otherwise it might be set in an obscure if statement.
dnl now otherwise it might be set in an obscure if statement. Same thing for
dnl PKG_PROG_PKG_CONFIG which needs to be called first.
AC_EGREP_CPP(foo, foo)
PKG_PROG_PKG_CONFIG()

dnl output driver features
AC_ARG_ENABLE(slang,
@@ -257,6 +259,12 @@ if test "${enable_imlib2}" != "no"; then
fi
AM_CONDITIONAL(USE_IMLIB2, test "${ac_cv_my_have_imlib2}" = "yes")

# Build development tools?
PANGOFT2="no"
PKG_CHECK_MODULES(pangoft2, pangoft2,
[PANGOFT2="yes"])
AM_CONDITIONAL(USE_PANGO, test "${PANGO}" != "no")

# Build documentation?
DOXYGEN="no"
LATEX="no"


+ 10
- 1
tools/Makefile.am View File

@@ -2,7 +2,16 @@

AM_CPPFLAGS = -I$(top_srcdir)/cucul -I$(top_srcdir)/caca -DDATADIR=\"$(pkgdatadir)\"

noinst_PROGRAMS = optipal
noinst_PROGRAMS = optipal $(pango_programs)

optipal_SOURCES = optipal.c

makefont_SOURCES = makefont.c
makefont_CFLAGS = `pkg-config --cflags pangoft2`
makefont_LDFLAGS = `pkg-config --libs pangoft2`

if USE_PANGO
pango_programs = makefont
else
pango_programs =
endif

+ 277
- 0
tools/makefont.c View File

@@ -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;
}


Loading…
Cancel
Save