@@ -29,6 +29,7 @@ libcucul_la_SOURCES = \ | |||||
import.c \ | import.c \ | ||||
export.c \ | export.c \ | ||||
file.c \ | file.c \ | ||||
figfont.c \ | |||||
$(NULL) | $(NULL) | ||||
libcucul_la_DEPENDENCIES = \ | libcucul_la_DEPENDENCIES = \ | ||||
mono9.data \ | mono9.data \ | ||||
@@ -490,7 +490,7 @@ int cucul_set_canvas_boundaries(cucul_canvas_t *cv, int x, int y, | |||||
} | } | ||||
free(cv->frames); | free(cv->frames); | ||||
memcpy(cv, new, sizeof(cucul_canvas_t)); | |||||
cv->frames = new->frames; | |||||
free(new); | free(new); | ||||
cucul_set_frame(cv, saved_f); | cucul_set_frame(cv, saved_f); | ||||
@@ -85,6 +85,8 @@ cucul_canvas_t * cucul_create_canvas(unsigned int width, unsigned int height) | |||||
_cucul_load_frame_info(cv); | _cucul_load_frame_info(cv); | ||||
cucul_set_color_ansi(cv, CUCUL_DEFAULT, CUCUL_TRANSPARENT); | cucul_set_color_ansi(cv, CUCUL_DEFAULT, CUCUL_TRANSPARENT); | ||||
cv->ff = NULL; | |||||
if(cucul_resize(cv, width, height) < 0) | if(cucul_resize(cv, width, height) < 0) | ||||
{ | { | ||||
int saved_errno = geterrno(); | int saved_errno = geterrno(); | ||||
@@ -306,6 +308,9 @@ int cucul_free_canvas(cucul_canvas_t *cv) | |||||
free(cv->frames[f].name); | free(cv->frames[f].name); | ||||
} | } | ||||
if(cv->ff) | |||||
_cucul_free_figfont(cv->ff); | |||||
free(cv->frames); | free(cv->frames); | ||||
free(cv); | free(cv); | ||||
@@ -280,6 +280,14 @@ __extern int cucul_render_canvas(cucul_canvas_t const *, cucul_font_t const *, | |||||
__extern int cucul_free_font(cucul_font_t *); | __extern int cucul_free_font(cucul_font_t *); | ||||
/* @} */ | /* @} */ | ||||
/** \defgroup cucul_figfont libcucul FIGfont handling | |||||
* | |||||
* These functions provide FIGlet and TOIlet font handling routines. | |||||
* | |||||
* @{ */ | |||||
__extern int cucul_canvas_set_figfont(cucul_canvas_t *, char const *); | |||||
/* @} */ | |||||
/** \defgroup cucul_importexport libcucul importers/exporters from/to various | /** \defgroup cucul_importexport libcucul importers/exporters from/to various | ||||
* formats | * formats | ||||
* | * | ||||
@@ -19,6 +19,8 @@ | |||||
# include <inttypes.h> | # include <inttypes.h> | ||||
#endif | #endif | ||||
typedef struct cucul_figfont cucul_figfont_t; | |||||
struct cucul_frame | struct cucul_frame | ||||
{ | { | ||||
/* Frame size */ | /* Frame size */ | ||||
@@ -39,6 +41,9 @@ struct cucul_frame | |||||
struct cucul_canvas | struct cucul_canvas | ||||
{ | { | ||||
/* XXX: look at cucul_set_canvas_boundaries() before adding anything | |||||
* to this structure. The function is quite hacky. */ | |||||
/* Frame information */ | /* Frame information */ | ||||
unsigned int frame, framecount; | unsigned int frame, framecount; | ||||
struct cucul_frame *frames; | struct cucul_frame *frames; | ||||
@@ -54,6 +59,9 @@ struct cucul_canvas | |||||
uint32_t *chars; | uint32_t *chars; | ||||
uint32_t *attrs; | uint32_t *attrs; | ||||
uint32_t curattr; | uint32_t curattr; | ||||
/* FIGfont management */ | |||||
cucul_figfont_t *ff; | |||||
}; | }; | ||||
struct cucul_buffer | struct cucul_buffer | ||||
@@ -77,4 +85,8 @@ extern int _cucul_file_close(cucul_file_t *); | |||||
extern int _cucul_file_eof(cucul_file_t *); | extern int _cucul_file_eof(cucul_file_t *); | ||||
extern char *_cucul_file_gets(char *, int, cucul_file_t *); | extern char *_cucul_file_gets(char *, int, cucul_file_t *); | ||||
/* FIGfont functions */ | |||||
extern cucul_figfont_t * _cucul_open_figfont(char const *); | |||||
extern int _cucul_free_figfont(cucul_figfont_t *); | |||||
#endif /* __CUCUL_INTERNALS_H__ */ | #endif /* __CUCUL_INTERNALS_H__ */ |
@@ -0,0 +1,261 @@ | |||||
/* | |||||
* libcucul Canvas for ultrafast compositing of Unicode letters | |||||
* Copyright (c) 2006-2007 Sam Hocevar <sam@zoy.org> | |||||
* All Rights Reserved | |||||
* | |||||
* $Id$ | |||||
* | |||||
* This library is free software. It comes without any warranty, to | |||||
* the extent permitted by applicable law. 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. | |||||
*/ | |||||
/* | |||||
* This file contains FIGlet and TOIlet font handling functions. | |||||
*/ | |||||
#include "config.h" | |||||
#include "common.h" | |||||
#if !defined(__KERNEL__) | |||||
# include <stdio.h> | |||||
# include <stdlib.h> | |||||
# include <string.h> | |||||
#endif | |||||
#include "cucul.h" | |||||
#include "cucul_internals.h" | |||||
struct cucul_figfont | |||||
{ | |||||
/* Used by the FIGlet driver */ | |||||
unsigned long int hardblank; | |||||
unsigned int height, baseline, max_length; | |||||
int old_layout; | |||||
unsigned int print_direction, full_layout, codetag_count; | |||||
unsigned int glyphs; | |||||
cucul_canvas_t *fontcv; | |||||
unsigned int *lookup; | |||||
}; | |||||
int cucul_canvas_set_figfont(cucul_canvas_t *cv, char const *path) | |||||
{ | |||||
cucul_figfont_t *ff = NULL; | |||||
if(path) | |||||
{ | |||||
ff = _cucul_open_figfont(path); | |||||
if(!ff) | |||||
return -1; | |||||
} | |||||
if(cv->ff) | |||||
_cucul_free_figfont(cv->ff); | |||||
cv->ff = ff; | |||||
return 0; | |||||
} | |||||
#define STD_GLYPHS (127 - 32) | |||||
#define EXT_GLYPHS (STD_GLYPHS + 7) | |||||
cucul_figfont_t * _cucul_open_figfont(char const *path) | |||||
{ | |||||
char altpath[2048]; | |||||
char buf[2048]; | |||||
char hardblank[10]; | |||||
cucul_figfont_t *ff; | |||||
char *data = NULL; | |||||
cucul_file_t *f; | |||||
unsigned int i, j, size, comment_lines; | |||||
ff = malloc(sizeof(cucul_figfont_t)); | |||||
if(!ff) | |||||
{ | |||||
seterrno(ENOMEM); | |||||
return NULL; | |||||
} | |||||
/* Open font: if not found, try .tlf, then .flf */ | |||||
f = _cucul_file_open(path, "r"); | |||||
if(!f) | |||||
{ | |||||
snprintf(altpath, 2047, "%s.tlf", path); | |||||
altpath[2047] = '\0'; | |||||
f = _cucul_file_open(altpath, "r"); | |||||
} | |||||
if(!f) | |||||
{ | |||||
snprintf(altpath, 2047, "%s.flf", path); | |||||
altpath[2047] = '\0'; | |||||
f = _cucul_file_open(altpath, "r"); | |||||
} | |||||
if(!f) | |||||
{ | |||||
free(ff); | |||||
seterrno(ENOENT); | |||||
return NULL; | |||||
} | |||||
/* Read header */ | |||||
ff->print_direction = 0; | |||||
ff->full_layout = 0; | |||||
ff->codetag_count = 0; | |||||
_cucul_file_gets(buf, 2048, f); | |||||
if(sscanf(buf, "%*[ft]lf2a%6s %u %u %u %i %u %u %u %u\n", hardblank, | |||||
&ff->height, &ff->baseline, &ff->max_length, | |||||
&ff->old_layout, &comment_lines, &ff->print_direction, | |||||
&ff->full_layout, &ff->codetag_count) < 6) | |||||
{ | |||||
debug("figfont error: `%s' has invalid header: %s", path, buf); | |||||
_cucul_file_close(f); | |||||
free(ff); | |||||
seterrno(EINVAL); | |||||
return NULL; | |||||
} | |||||
if(ff->old_layout < -1 || ff->old_layout > 63 || ff->full_layout > 32767 | |||||
|| ((ff->full_layout & 0x80) && (ff->full_layout & 0x3f) == 0 | |||||
&& ff->old_layout)) | |||||
{ | |||||
debug("figfont error: `%s' has invalid layout %i/%u", | |||||
path, ff->old_layout, ff->full_layout); | |||||
_cucul_file_close(f); | |||||
free(ff); | |||||
seterrno(EINVAL); | |||||
return NULL; | |||||
} | |||||
ff->hardblank = cucul_utf8_to_utf32(hardblank, NULL); | |||||
/* Skip comment lines */ | |||||
for(i = 0; i < comment_lines; i++) | |||||
_cucul_file_gets(buf, 2048, f); | |||||
/* Read mandatory characters (32-127, 196, 214, 220, 228, 246, 252, 223) | |||||
* then read additional characters. */ | |||||
ff->glyphs = 0; | |||||
ff->lookup = NULL; | |||||
for(i = 0, size = 0; !_cucul_file_eof(f); ff->glyphs++) | |||||
{ | |||||
if((ff->glyphs % 2048) == 0) | |||||
ff->lookup = realloc(ff->lookup, | |||||
(ff->glyphs + 2048) * 2 * sizeof(int)); | |||||
if(ff->glyphs < STD_GLYPHS) | |||||
{ | |||||
ff->lookup[ff->glyphs * 2] = 32 + ff->glyphs; | |||||
} | |||||
else if(ff->glyphs < EXT_GLYPHS) | |||||
{ | |||||
static int const tab[7] = { 196, 214, 220, 228, 246, 252, 223 }; | |||||
ff->lookup[ff->glyphs * 2] = tab[ff->glyphs - STD_GLYPHS]; | |||||
} | |||||
else | |||||
{ | |||||
if(_cucul_file_gets(buf, 2048, f) == NULL) | |||||
break; | |||||
/* Ignore blank lines, as in jacky.flf */ | |||||
if(buf[0] == '\n' || buf[0] == '\r') | |||||
continue; | |||||
/* Ignore negative indices for now, as in ivrit.flf */ | |||||
if(buf[0] == '-') | |||||
{ | |||||
for(j = 0; j < ff->height; j++) | |||||
_cucul_file_gets(buf, 2048, f); | |||||
continue; | |||||
} | |||||
if(!buf[0] || buf[0] < '0' || buf[0] > '9') | |||||
{ | |||||
debug("figfont error: glyph #%u in `%s'", ff->glyphs, path); | |||||
free(data); | |||||
free(ff->lookup); | |||||
free(ff); | |||||
seterrno(EINVAL); | |||||
return NULL; | |||||
} | |||||
if(buf[1] == 'x') | |||||
sscanf(buf, "%x", &ff->lookup[ff->glyphs * 2]); | |||||
else | |||||
sscanf(buf, "%u", &ff->lookup[ff->glyphs * 2]); | |||||
} | |||||
ff->lookup[ff->glyphs * 2 + 1] = 0; | |||||
for(j = 0; j < ff->height; j++) | |||||
{ | |||||
if(i + 2048 >= size) | |||||
data = realloc(data, size += 2048); | |||||
_cucul_file_gets(data + i, 2048, f); | |||||
i = (uintptr_t)strchr(data + i, 0) - (uintptr_t)data; | |||||
} | |||||
} | |||||
_cucul_file_close(f); | |||||
if(ff->glyphs < EXT_GLYPHS) | |||||
{ | |||||
debug("figfont error: only %u glyphs in `%s', expected at least %u", | |||||
ff->glyphs, path, EXT_GLYPHS); | |||||
free(data); | |||||
free(ff->lookup); | |||||
free(ff); | |||||
seterrno(EINVAL); | |||||
return NULL; | |||||
} | |||||
/* Import buffer into canvas */ | |||||
ff->fontcv = cucul_create_canvas(0, 0); | |||||
cucul_import_memory(ff->fontcv, data, i, "utf8"); | |||||
free(data); | |||||
/* Remove EOL characters. For now we ignore hardblanks, don’t do any | |||||
* smushing, nor any kind of error checking. */ | |||||
for(j = 0; j < ff->height * ff->glyphs; j++) | |||||
{ | |||||
unsigned long int ch, oldch = 0; | |||||
for(i = ff->max_length; i--;) | |||||
{ | |||||
ch = cucul_get_char(ff->fontcv, i, j); | |||||
/* Replace hardblanks with U+00A0 NO-BREAK SPACE */ | |||||
if(ch == ff->hardblank) | |||||
cucul_put_char(ff->fontcv, i, j, ch = 0xa0); | |||||
if(oldch && ch != oldch) | |||||
{ | |||||
if(!ff->lookup[j / ff->height * 2 + 1]) | |||||
ff->lookup[j / ff->height * 2 + 1] = i + 1; | |||||
} | |||||
else if(oldch && ch == oldch) | |||||
cucul_put_char(ff->fontcv, i, j, ' '); | |||||
else if(ch != ' ') | |||||
{ | |||||
oldch = ch; | |||||
cucul_put_char(ff->fontcv, i, j, ' '); | |||||
} | |||||
} | |||||
} | |||||
return ff; | |||||
} | |||||
int _cucul_free_figfont(cucul_figfont_t *ff) | |||||
{ | |||||
cucul_free_canvas(ff->fontcv); | |||||
free(ff->lookup); | |||||
free(ff); | |||||
return 0; | |||||
} | |||||
@@ -6,6 +6,7 @@ demo0 | |||||
dithering | dithering | ||||
event | event | ||||
export | export | ||||
figfont | |||||
font | font | ||||
font2tga | font2tga | ||||
frames | frames | ||||
@@ -2,7 +2,7 @@ | |||||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/cucul -I$(top_srcdir)/caca -DDATADIR=\"$(pkgdatadir)\" | AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/cucul -I$(top_srcdir)/caca -DDATADIR=\"$(pkgdatadir)\" | ||||
noinst_PROGRAMS = blit colors cucul demo demo0 dithering event export font font2tga frames fullwidth gamma hsv input spritedit swallow text transform truecolor unicode import | |||||
noinst_PROGRAMS = blit colors cucul demo demo0 dithering event export figfont font font2tga frames fullwidth gamma hsv input spritedit swallow text transform truecolor unicode import | |||||
blit_SOURCES = blit.c | blit_SOURCES = blit.c | ||||
blit_LDADD = ../caca/libcaca.la ../cucul/libcucul.la | blit_LDADD = ../caca/libcaca.la ../cucul/libcucul.la | ||||
@@ -30,6 +30,9 @@ event_LDADD = ../caca/libcaca.la ../cucul/libcucul.la | |||||
export_SOURCES = export.c | export_SOURCES = export.c | ||||
export_LDADD = ../cucul/libcucul.la | export_LDADD = ../cucul/libcucul.la | ||||
figfont_SOURCES = figfont.c | |||||
figfont_LDADD = ../cucul/libcucul.la | |||||
font_SOURCES = font.c | font_SOURCES = font.c | ||||
font_LDADD = ../caca/libcaca.la ../cucul/libcucul.la | font_LDADD = ../caca/libcaca.la ../cucul/libcucul.la | ||||
@@ -0,0 +1,45 @@ | |||||
/* | |||||
* figfont libcucul FIGfont test program | |||||
* Copyright (c) 2007 Sam Hocevar <sam@zoy.org> | |||||
* All Rights Reserved | |||||
* | |||||
* $Id$ | |||||
* | |||||
* This program is free software. It comes without any warranty, to | |||||
* the extent permitted by applicable law. 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. | |||||
*/ | |||||
#include "config.h" | |||||
#include "common.h" | |||||
#if !defined(__KERNEL__) | |||||
# include <stdio.h> | |||||
#endif | |||||
#include "cucul.h" | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
cucul_canvas_t *cv; | |||||
if(argc < 2) | |||||
{ | |||||
fprintf(stderr, "Too few arguments\n"); | |||||
return -1; | |||||
} | |||||
cv = cucul_create_canvas(0, 0); | |||||
if(cucul_canvas_set_figfont(cv, argv[1])) | |||||
{ | |||||
fprintf(stderr, "Could not open font\n"); | |||||
return -1; | |||||
} | |||||
cucul_free_canvas(cv); | |||||
return 0; | |||||
} | |||||