diff --git a/src/figlet.c b/src/figlet.c index 6206578..0b08443 100644 --- a/src/figlet.c +++ b/src/figlet.c @@ -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, don’t 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); } diff --git a/src/render.c b/src/render.c index 3bbd64f..d01d2e0 100644 --- a/src/render.c +++ b/src/render.c @@ -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; } diff --git a/src/render.h b/src/render.h index 17c8b03..068a3a0 100644 --- a/src/render.h +++ b/src/render.h @@ -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 *);