* Get rid of all the FIGlet font handling: everything is moving into

libcucul.
This commit is contained in:
Sam Hocevar 2008-06-15 14:46:54 +00:00 committed by sam
parent 98d4ddf5c9
commit f3cdb2921c
3 changed files with 14 additions and 423 deletions

View file

@ -37,49 +37,14 @@ static int feed_figlet(context_t *, uint32_t, uint32_t);
static int flush_figlet(context_t *);
static int end_figlet(context_t *);
static int open_font(context_t *cx);
static uint32_t hsmush(uint32_t, uint32_t, unsigned int);
int init_figlet(context_t *cx)
{
if(open_font(cx))
char path[2048];
snprintf(path, 2047, "%s/%s", cx->dir, cx->font);
if(cucul_canvas_set_figfont(cx->cv, path))
return -1;
if(cx->full_layout & 0x3f)
cx->hsmushrule = cx->full_layout & 0x3f;
else if(cx->old_layout > 0)
cx->hsmushrule = cx->old_layout;
switch(cx->hmode)
{
case H_DEFAULT:
if(cx->old_layout == -1)
cx->hmode = H_NONE;
else if(cx->old_layout == 0 && (cx->full_layout & 0xc0) == 0x40)
cx->hmode = H_KERN;
else if((cx->old_layout & 0x3f) && (cx->full_layout & 0x3f)
&& (cx->full_layout & 0x80))
{
cx->hmode = H_SMUSH;
cx->hsmushrule = cx->full_layout & 0x3f;
}
else if(cx->old_layout == 0 && (cx->full_layout & 0xbf) == 0x80)
{
cx->hmode = H_SMUSH;
cx->hsmushrule = 0x3f;
}
else
cx->hmode = H_OVERLAP;
break;
default:
break;
}
cx->charcv = cucul_create_canvas(cx->max_length - 2, cx->height);
cx->left = malloc(cx->height * sizeof(int));
cx->right = malloc(cx->height * sizeof(int));
cx->feed = feed_figlet;
cx->flush = flush_figlet;
cx->end = end_figlet;
@ -89,389 +54,16 @@ int init_figlet(context_t *cx)
static int feed_figlet(context_t *cx, uint32_t ch, uint32_t attr)
{
unsigned int c, w, h, x, y, overlap, extra, xleft, xright;
switch(ch)
{
case (uint32_t)'\r':
return 0;
case (uint32_t)'\n':
cx->x = 0;
cx->y += cx->height;
return 0;
/* FIXME: handle '\t' */
}
/* Look whether our glyph is available */
for(c = 0; c < cx->glyphs; c++)
if(cx->lookup[c * 2] == ch)
break;
if(c == cx->glyphs)
return 0;
w = cx->lookup[c * 2 + 1];
h = cx->height;
cucul_set_canvas_handle(cx->fontcv, 0, c * cx->height);
cucul_blit(cx->charcv, 0, 0, cx->fontcv, NULL);
/* Check whether we reached the end of the screen */
if(cx->x && cx->x + w > cx->term_width)
{
cx->x = 0;
cx->y += h;
}
/* Compute how much the next character will overlap */
switch(cx->hmode)
{
case H_SMUSH:
case H_KERN:
case H_OVERLAP:
extra = (cx->hmode == H_OVERLAP);
overlap = w;
for(y = 0; y < h; y++)
{
/* Compute how much spaces we can eat from the new glyph */
for(xright = 0; xright < overlap; xright++)
if(cucul_get_char(cx->charcv, xright, y) != ' ')
break;
/* Compute how much spaces we can eat from the previous glyph */
for(xleft = 0; xright + xleft < overlap && xleft < cx->x; xleft++)
if(cucul_get_char(cx->cv, cx->x - 1 - xleft, cx->y + y) != ' ')
break;
/* Handle overlapping */
if(cx->hmode == H_OVERLAP && xleft < cx->x)
xleft++;
/* Handle smushing */
if(cx->hmode == H_SMUSH)
{
if(xleft < cx->x &&
hsmush(cucul_get_char(cx->cv, cx->x - 1 - xleft, cx->y + y),
cucul_get_char(cx->charcv, xright, y),
cx->hsmushrule))
xleft++;
}
if(xleft + xright < overlap)
overlap = xleft + xright;
}
break;
case H_NONE:
overlap = 0;
break;
default:
return -1;
}
/* Check whether the current canvas is large enough */
if(cx->x + w - overlap > cx->w)
cx->w = cx->x + w - overlap < cx->term_width
? cx->x + w - overlap : cx->term_width;
if(cx->y + h > cx->h)
cx->h = cx->y + h;
if(attr)
cucul_set_attr(cx->cv, attr);
cucul_set_canvas_size(cx->cv, cx->w, cx->h);
/* Render our char (FIXME: create a rect-aware cucul_blit_canvas?) */
for(y = 0; y < h; y++)
for(x = 0; x < w; x++)
{
uint32_t ch1, ch2;
//uint32_t tmpat = cucul_get_attr(cx->fontcv, x, y + c * cx->height);
ch2 = cucul_get_char(cx->charcv, x, y);
if(ch2 == ' ')
continue;
ch1 = cucul_get_char(cx->cv, cx->x + x - overlap, cx->y + y);
/* FIXME: this could be changed to cucul_put_attr() when the
* function is fixed in libcucul */
//cucul_set_attr(cx->cv, tmpat);
if(ch1 == ' ' || cx->hmode != H_SMUSH)
cucul_put_char(cx->cv, cx->x + x - overlap, cx->y + y, ch2);
else
cucul_put_char(cx->cv, cx->x + x - overlap, cx->y + y,
hsmush(ch1, ch2, cx->hsmushrule));
//cucul_put_attr(cx->cv, cx->x + x, cx->y + y, tmpat);
}
/* Advance cursor */
cx->x += w - overlap;
return 0;
return cucul_put_figchar(cx->cv, ch);
}
static int flush_figlet(context_t *cx)
{
unsigned int x, y;
cx->torender = cx->cv;
cucul_set_canvas_size(cx->torender, cx->w, cx->h);
/* FIXME: do this somewhere else, or record hardblank positions */
for(y = 0; y < cx->h; y++)
for(x = 0; x < cx->w; x++)
if(cucul_get_char(cx->torender, x, y) == 0xa0)
{
uint32_t attr = cucul_get_attr(cx->torender, x, y);
cucul_put_char(cx->torender, x, y, ' ');
cucul_put_attr(cx->torender, x, y, attr);
}
cx->x = cx->y = 0;
cx->w = cx->h = 0;
cx->cv = cucul_create_canvas(1, 1);
return 0;
return cucul_flush_figlet(cx->cv);
}
static int end_figlet(context_t *cx)
{
free(cx->left);
free(cx->right);
cucul_free_canvas(cx->charcv);
cucul_free_canvas(cx->fontcv);
free(cx->lookup);
return 0;
}
static int open_font(context_t *cx)
{
char *data = NULL;
char path[2048];
char buf[2048];
char hardblank[10];
TOIFILE *f;
unsigned int i, j, size, comment_lines;
/* Open font: try .tlf, then .flf */
snprintf(path, 2047, "%s/%s.tlf", cx->dir, cx->font);
path[2047] = '\0';
f = toiopen(path, "r");
if(!f)
{
snprintf(path, 2047, "%s/%s.flf", cx->dir, cx->font);
path[2047] = '\0';
f = toiopen(path, "r");
if(!f)
{
fprintf(stderr, "font `%s' not found\n", path);
return -1;
}
}
/* Read header */
cx->print_direction = 0;
cx->full_layout = 0;
cx->codetag_count = 0;
toigets(buf, 2048, f);
if(sscanf(buf, "%*[ft]lf2a%6s %u %u %u %i %u %u %u %u\n", hardblank,
&cx->height, &cx->baseline, &cx->max_length,
&cx->old_layout, &comment_lines, &cx->print_direction,
&cx->full_layout, &cx->codetag_count) < 6)
{
fprintf(stderr, "font `%s' has invalid header: %s\n", path, buf);
toiclose(f);
return -1;
}
if(cx->old_layout < -1 || cx->old_layout > 63 || cx->full_layout > 32767
|| ((cx->full_layout & 0x80) && (cx->full_layout & 0x3f) == 0
&& cx->old_layout))
{
fprintf(stderr, "font `%s' has invalid layout %i/%u\n",
path, cx->old_layout, cx->full_layout);
toiclose(f);
return -1;
}
cx->hardblank = cucul_utf8_to_utf32(hardblank, NULL);
/* Skip comment lines */
for(i = 0; i < comment_lines; i++)
toigets(buf, 2048, f);
/* Read mandatory characters (32-127, 196, 214, 220, 228, 246, 252, 223)
* then read additional characters. */
cx->glyphs = 0;
cx->lookup = NULL;
for(i = 0, size = 0; !toieof(f); cx->glyphs++)
{
if((cx->glyphs % 2048) == 0)
cx->lookup = realloc(cx->lookup,
(cx->glyphs + 2048) * 2 * sizeof(int));
if(cx->glyphs < STD_GLYPHS)
{
cx->lookup[cx->glyphs * 2] = 32 + cx->glyphs;
}
else if(cx->glyphs < EXT_GLYPHS)
{
static int const tab[7] = { 196, 214, 220, 228, 246, 252, 223 };
cx->lookup[cx->glyphs * 2] = tab[cx->glyphs - STD_GLYPHS];
}
else
{
if(toigets(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 < cx->height; j++)
toigets(buf, 2048, f);
continue;
}
if(!buf[0] || buf[0] < '0' || buf[0] > '9')
{
free(data);
free(cx->lookup);
fprintf(stderr, "read error at glyph #%u in `%s'\n",
cx->glyphs, path);
return -1;
}
if(buf[1] == 'x')
sscanf(buf, "%x", &cx->lookup[cx->glyphs * 2]);
else
sscanf(buf, "%u", &cx->lookup[cx->glyphs * 2]);
}
cx->lookup[cx->glyphs * 2 + 1] = 0;
for(j = 0; j < cx->height; j++)
{
if(i + 2048 >= size)
data = realloc(data, size += 2048);
toigets(data + i, 2048, f);
i = (uintptr_t)strchr(data + i, 0) - (uintptr_t)data;
}
}
toiclose(f);
if(cx->glyphs < EXT_GLYPHS)
{
free(data);
free(cx->lookup);
fprintf(stderr, "only %u glyphs in `%s', expected at least %u\n",
cx->glyphs, path, EXT_GLYPHS);
return -1;
}
/* Import buffer into canvas */
cx->fontcv = cucul_create_canvas(0, 0);
cucul_import_memory(cx->fontcv, data, i, "utf8");
free(data);
/* Remove EOL characters. For now we ignore hardblanks, dont do any
* smushing, nor any kind of error checking. */
for(j = 0; j < cx->height * cx->glyphs; j++)
{
unsigned long int ch, oldch = 0;
for(i = cx->max_length; i--;)
{
ch = cucul_get_char(cx->fontcv, i, j);
/* Replace hardblanks with U+00A0 NO-BREAK SPACE */
if(ch == cx->hardblank)
cucul_put_char(cx->fontcv, i, j, ch = 0xa0);
if(oldch && ch != oldch)
{
if(!cx->lookup[j / cx->height * 2 + 1])
cx->lookup[j / cx->height * 2 + 1] = i + 1;
}
else if(oldch && ch == oldch)
cucul_put_char(cx->fontcv, i, j, ' ');
else if(ch != ' ')
{
oldch = ch;
cucul_put_char(cx->fontcv, i, j, ' ');
}
}
}
return 0;
}
static uint32_t hsmush(uint32_t ch1, uint32_t ch2, unsigned int rule)
{
/* Rule 1 */
if((rule & 0x01) && ch1 == ch2 && ch1 != 0xa0)
return ch2;
if(ch1 < 0x80 && ch2 < 0x80)
{
char const charlist[] = "|/\\[]{}()<>";
char *tmp1, *tmp2;
/* Rule 2 */
if(rule & 0x02)
{
if(ch1 == '_' && strchr(charlist, ch2))
return ch2;
if(ch2 == '_' && strchr(charlist, ch1))
return ch1;
}
/* Rule 3 */
if((rule & 0x04) &&
(tmp1 = strchr(charlist, ch1)) && (tmp2 = strchr(charlist, ch2)))
{
int cl1 = (tmp1 + 1 - charlist) / 2;
int cl2 = (tmp2 + 1 - charlist) / 2;
if(cl1 < cl2)
return ch2;
if(cl1 > cl2)
return ch1;
}
/* Rule 4 */
if(rule & 0x08)
{
uint16_t s = ch1 + ch2;
uint16_t p = ch1 * ch2;
if(p == 15375 /* '{' * '}' */
|| p == 8463 /* '[' * ']' */
|| (p == 1640 && s == 81)) /* '(' *|+ ')' */
return '|';
}
/* Rule 5 */
if(rule & 0x10)
{
switch((ch1 << 8) | ch2)
{
case 0x2f5c: return '|'; /* /\ */
case 0x5c2f: return 'Y'; /* \/ */
case 0x3e3c: return 'X'; /* >< */
}
}
/* Rule 6 */
if((rule & 0x20) && ch1 == ch2 && ch1 == 0xa0)
return 0xa0;
}
return 0;
return cucul_canvas_set_figfont(cx->cv, NULL);
}

View file

@ -49,7 +49,7 @@ int render_stdin(context_t *cx)
{
cucul_canvas_t *cv;
char *line;
unsigned int i, len;
int i, len;
/* FIXME: we can't read longer lines */
len = 1024;
@ -80,10 +80,10 @@ int render_stdin(context_t *cx)
return 0;
}
int render_list(context_t *cx, unsigned int argc, char *argv[])
int render_list(context_t *cx, int argc, char *argv[])
{
cucul_canvas_t *cv;
unsigned int i, j, len;
int i, j, len;
char *parser = NULL;
cv = cucul_create_canvas(0, 0);
@ -129,6 +129,8 @@ int render_list(context_t *cx, unsigned int argc, char *argv[])
render_flush(cx);
cucul_free_canvas(cv);
return 0;
}
@ -153,15 +155,12 @@ static int render_flush(context_t *cx)
/* Apply optional effects to our string */
filter_do(cx);
cx->lines += cucul_get_canvas_height(cx->torender);
/* Output line */
buffer = cucul_export_memory(cx->torender, cx->export, &len);
buffer = cucul_export_memory(cx->cv, cx->export, &len);
if(!buffer)
return -1;
fwrite(buffer, len, 1, stdout);
free(buffer);
cucul_free_canvas(cx->torender);
return 0;
}

View file

@ -21,6 +21,6 @@ extern int init_figlet(context_t *);
extern int render_init(context_t *);
extern int render_stdin(context_t *);
extern int render_list(context_t *, unsigned int, char *[]);
extern int render_list(context_t *, int, char *[]);
extern int render_end(context_t *);