diff --git a/src/Makefile.am b/src/Makefile.am index aa53ce2..2452327 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,7 @@ toilet_SOURCES = main.c \ io.c io.h \ render.c render.h \ filter.c filter.h \ - figlet.c figlet.h + term.c mono9.c figlet.c toilet_CFLAGS = `pkg-config --cflags cucul` toilet_LDFLAGS = `pkg-config --libs cucul` @GETOPT_LIBS@ @ZLIB_LIBS@ diff --git a/src/figlet.c b/src/figlet.c index 9599978..511f70d 100644 --- a/src/figlet.c +++ b/src/figlet.c @@ -26,13 +26,14 @@ #include #include "toilet.h" +#include "render.h" #include "io.h" -#include "figlet.h" #define STD_GLYPHS (127 - 32) #define EXT_GLYPHS (STD_GLYPHS + 7) static int feed_figlet(context_t *, uint32_t); +static int flush_figlet(context_t *); static int end_figlet(context_t *); static int open_font(context_t *cx); @@ -47,6 +48,7 @@ int init_figlet(context_t *cx) cx->cv = cucul_create_canvas(1, 1); cx->feed = feed_figlet; + cx->flush = flush_figlet; cx->end = end_figlet; return 0; @@ -108,9 +110,22 @@ static int feed_figlet(context_t *cx, uint32_t ch) return 0; } +static int flush_figlet(context_t *cx) +{ + cx->torender = cx->cv; + cucul_set_canvas_size(cx->torender, cx->w, cx->h); + + cx->x = cx->y = 0; + cx->w = cx->h = 0; + cx->cv = cucul_create_canvas(1, 1); + + return 0; +} + static int end_figlet(context_t *cx) { cucul_free_canvas(cx->image); + cucul_free_canvas(cx->cv); free(cx->lookup); return 0; diff --git a/src/figlet.h b/src/figlet.h deleted file mode 100644 index 3cee7e9..0000000 --- a/src/figlet.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * TOIlet The Other Implementation’s letters - * Copyright (c) 2006 Sam Hocevar - * 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. - */ - -/* - * This header defines functions for handling FIGlet fonts. - */ -extern int init_figlet(context_t *); - diff --git a/src/filter.c b/src/filter.c index 827ffed..8fb4a0d 100644 --- a/src/filter.c +++ b/src/filter.c @@ -92,7 +92,14 @@ int filter_do(context_t *cx) unsigned int i; for(i = 0; i < cx->nfilters; i++) - cx->filters[i](cx->cv); + cx->filters[i](cx->torender); + + return 0; +} + +int filter_end(context_t *cx) +{ + free(cx->filters); return 0; } diff --git a/src/filter.h b/src/filter.h index 86cc8fa..68ac306 100644 --- a/src/filter.h +++ b/src/filter.h @@ -17,4 +17,5 @@ extern int filter_add(context_t *, char const *); extern int filter_do(context_t *); +extern int filter_end(context_t *); diff --git a/src/main.c b/src/main.c index 801c4a6..44a7b23 100644 --- a/src/main.c +++ b/src/main.c @@ -27,13 +27,11 @@ # include #endif #include -#include #include #include #include "toilet.h" #include "render.h" -#include "figlet.h" #include "filter.h" static void version(void); @@ -46,10 +44,6 @@ int main(int argc, char *argv[]) context_t struct_cx; context_t *cx = &struct_cx; - cucul_buffer_t *buffer; - - int i, j, ret; - int infocode = -1; cx->export = "utf8"; @@ -183,66 +177,16 @@ int main(int argc, char *argv[]) return 0; } - if(!strcasecmp(cx->font, "mono9")) - ret = init_big(cx); - else if(!strcasecmp(cx->font, "term")) - ret = init_tiny(cx); - else - ret = init_figlet(cx); - - if(ret) + if(render_init(cx) < 0) return -1; if(optind >= argc) - { - char buf[10]; - unsigned int len; - uint32_t ch; - - i = 0; - - /* Read from stdin */ - while(!feof(stdin)) - { - buf[i++] = getchar(); - buf[i] = '\0'; - - ch = cucul_utf8_to_utf32(buf, &len); - - if(!len) - continue; - - cx->feed(cx, ch); - i = 0; - } - } - else for(i = optind; i < argc; i++) - { - /* Read from commandline */ - unsigned int len; - - if(i != optind) - cx->feed(cx, ' '); - - for(j = 0; argv[i][j];) - { - cx->feed(cx, cucul_utf8_to_utf32(argv[i] + j, &len)); - j += len; - } - } - - cx->end(cx); - - /* Apply optional effects to our string */ - filter_do(cx); - - /* Output char */ - buffer = cucul_export_canvas(cx->cv, cx->export); - fwrite(cucul_get_buffer_data(buffer), - cucul_get_buffer_size(buffer), 1, stdout); - cucul_free_buffer(buffer); + render_stdin(cx); + else + render_list(cx, argc - optind, argv + optind); - cucul_free_canvas(cx->cv); + render_end(cx); + filter_end(cx); return 0; } diff --git a/src/mono9.c b/src/mono9.c new file mode 100644 index 0000000..5db7dff --- /dev/null +++ b/src/mono9.c @@ -0,0 +1,136 @@ +/* + * TOIlet The Other Implementation’s letters + * Copyright (c) 2006 Sam Hocevar + * 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. + */ + +/* + * This file contains text to canvas rendering functions. + */ + +#include "config.h" + +#if defined(HAVE_INTTYPES_H) +# include +#endif +#include +#include + +#include "toilet.h" +#include "render.h" + +static int feed_big(context_t *, uint32_t); +static int flush_big(context_t *); +static int end_big(context_t *); + +int init_big(context_t *cx) +{ + char const * const * fonts; + + fonts = cucul_get_font_list(); + cx->f = cucul_load_font(fonts[0], 0); + cx->buf = malloc(4 * cucul_get_font_width(cx->f) + * cucul_get_font_height(cx->f)); + cx->onechar = cucul_create_canvas(1, 1); + cucul_set_color(cx->onechar, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK); + + cx->x = cx->y = 0; + cx->w = cx->h = 0; + cx->cv = cucul_create_canvas(1, 1); + + cx->feed = feed_big; + cx->flush = flush_big; + cx->end = end_big; + + return 0; +} + +static int feed_big(context_t *cx, uint32_t ch) +{ + unsigned int w = cucul_get_font_width(cx->f); + unsigned int h = cucul_get_font_height(cx->f); + unsigned int x, y; + + switch(ch) + { + case (uint32_t)'\r': + return 0; + case (uint32_t)'\n': + cx->x = 0; + cx->y += h; + return 0; + case (uint32_t)'\t': + cx->x = (((cx->x / w) & ~7) + 8) * w; + return 0; + } + + /* Check whether we reached the end of the screen */ + if(cx->x && cx->x + w > cx->term_width) + { + cx->x = 0; + cx->y += h; + } + + /* Check whether the current canvas is large enough */ + if(cx->x + w > cx->w) + cx->w = cx->x + w < cx->term_width ? cx->x + w : cx->term_width; + + if(cx->y + h > cx->h) + cx->h = cx->y + h; + + cucul_set_canvas_size(cx->cv, cx->w, cx->h); + + /* Render our char */ + cucul_putchar(cx->onechar, 0, 0, ch); + cucul_render_canvas(cx->onechar, cx->f, cx->buf, w, h, 4 * w); + + for(y = 0; y < h; y++) + for(x = 0; x < w; x++) + { + unsigned char c = cx->buf[4 * (x + y * w) + 2]; + + if(c >= 0xa0) + cucul_putstr(cx->cv, cx->x + x, cx->y + y, "█"); + else if(c >= 0x80) + cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▓"); + else if(c >= 0x40) + cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▒"); + else if(c >= 0x20) + cucul_putstr(cx->cv, cx->x + x, cx->y + y, "░"); + } + + /* Advance cursor */ + cx->x += w; + + return 0; +} + +static int flush_big(context_t *cx) +{ + cx->torender = cx->cv; + cucul_set_canvas_size(cx->torender, cx->w, cx->h); + + cx->x = cx->y = 0; + cx->w = cx->h = 0; + cx->cv = cucul_create_canvas(1, 1); + + return 0; +} + +static int end_big(context_t *cx) +{ + cucul_free_canvas(cx->onechar); + cucul_free_canvas(cx->cv); + free(cx->buf); + cucul_free_font(cx->f); + + return 0; +} + diff --git a/src/render.c b/src/render.c index 080565a..cb4dc56 100644 --- a/src/render.c +++ b/src/render.c @@ -21,169 +21,99 @@ # include #endif #include +#include +#include #include #include "toilet.h" #include "render.h" +#include "filter.h" -static int feed_tiny(context_t *, uint32_t); -static int end_tiny(context_t *); - -static int feed_big(context_t *, uint32_t); -static int end_big(context_t *); - -int init_tiny(context_t *cx) +int render_init(context_t *cx) { - cx->ew = 16; - cx->eh = 2; - cx->x = cx->y = 0; - cx->w = cx->h = 0; - cx->cv = cucul_create_canvas(cx->ew, cx->eh); + if(!strcasecmp(cx->font, "mono9")) + return init_big(cx); - cx->feed = feed_tiny; - cx->end = end_tiny; + if(!strcasecmp(cx->font, "term")) + return init_tiny(cx); - return 0; + return init_figlet(cx); } -static int feed_tiny(context_t *cx, uint32_t ch) +int render_stdin(context_t *cx) { - switch(ch) - { - case (uint32_t)'\r': - return 0; - case (uint32_t)'\n': - cx->x = 0; - cx->y++; - return 0; - case (uint32_t)'\t': - cx->x = (cx->x & ~7) + 8; - return 0; - } + char buf[10]; + unsigned int i = 0, len; + uint32_t ch; - /* Check whether we reached the end of the screen */ - if(cx->x && cx->x + 1 > cx->term_width) + /* Read from stdin */ + while(!feof(stdin)) { - cx->x = 0; - cx->y++; - } + buf[i++] = getchar(); + buf[i] = '\0'; - /* Check whether the current canvas is large enough */ - if(cx->x + 1 > cx->w) - { - cx->w = cx->x + 1 < cx->term_width ? cx->x + 1 : cx->term_width; - if(cx->w > cx->ew) - cx->ew = cx->ew + cx->ew / 2; - } + ch = cucul_utf8_to_utf32(buf, &len); - if(cx->y + 1 > cx->h) - { - cx->h = cx->y + 1; - if(cx->h > cx->eh) - cx->eh = cx->eh + cx->eh / 2; - } + if(!len) + continue; - cucul_set_canvas_size(cx->cv, cx->ew, cx->eh); + cx->feed(cx, ch); + i = 0; - cucul_putchar(cx->cv, cx->x, cx->y, ch); - cx->x++; + if(ch == '\n') + render_line(cx); + } return 0; } -static int end_tiny(context_t *cx) +int render_list(context_t *cx, unsigned int argc, char *argv[]) { - cucul_set_canvas_size(cx->cv, cx->w, cx->h); - - return 0; -} + unsigned int i, j; -int init_big(context_t *cx) -{ - char const * const * fonts; + for(i = 0; i < argc; i++) + { + /* Read from commandline */ + unsigned int len; - fonts = cucul_get_font_list(); - cx->f = cucul_load_font(fonts[0], 0); - cx->buf = malloc(4 * cucul_get_font_width(cx->f) - * cucul_get_font_height(cx->f)); - cx->onechar = cucul_create_canvas(1, 1); - cucul_set_color(cx->onechar, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK); + if(i) + cx->feed(cx, ' '); - cx->x = cx->y = 0; - cx->w = cx->h = 0; - cx->cv = cucul_create_canvas(1, 1); + for(j = 0; argv[i][j];) + { + cx->feed(cx, cucul_utf8_to_utf32(argv[i] + j, &len)); + j += len; + } + } - cx->feed = feed_big; - cx->end = end_big; + render_line(cx); return 0; } -static int feed_big(context_t *cx, uint32_t ch) +int render_line(context_t *cx) { - unsigned int w = cucul_get_font_width(cx->f); - unsigned int h = cucul_get_font_height(cx->f); - unsigned int x, y; - - switch(ch) - { - case (uint32_t)'\r': - return 0; - case (uint32_t)'\n': - cx->x = 0; - cx->y += h; - return 0; - case (uint32_t)'\t': - cx->x = (((cx->x / w) & ~7) + 8) * w; - return 0; - } - - /* Check whether we reached the end of the screen */ - if(cx->x && cx->x + w > cx->term_width) - { - cx->x = 0; - cx->y += h; - } - - /* Check whether the current canvas is large enough */ - if(cx->x + w > cx->w) - cx->w = cx->x + w < cx->term_width ? cx->x + w : cx->term_width; - - if(cx->y + h > cx->h) - cx->h = cx->y + h; + cucul_buffer_t *buffer; - cucul_set_canvas_size(cx->cv, cx->w, cx->h); + /* Flush current line */ + cx->flush(cx); - /* Render our char */ - cucul_putchar(cx->onechar, 0, 0, ch); - cucul_render_canvas(cx->onechar, cx->f, cx->buf, w, h, 4 * w); - - for(y = 0; y < h; y++) - for(x = 0; x < w; x++) - { - unsigned char c = cx->buf[4 * (x + y * w) + 2]; - - if(c >= 0xa0) - cucul_putstr(cx->cv, cx->x + x, cx->y + y, "█"); - else if(c >= 0x80) - cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▓"); - else if(c >= 0x40) - cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▒"); - else if(c >= 0x20) - cucul_putstr(cx->cv, cx->x + x, cx->y + y, "░"); - } + /* Apply optional effects to our string */ + filter_do(cx); - /* Advance cursor */ - cx->x += w; + /* Output line */ + buffer = cucul_export_canvas(cx->torender, cx->export); + fwrite(cucul_get_buffer_data(buffer), + cucul_get_buffer_size(buffer), 1, stdout); + cucul_free_buffer(buffer); + cucul_free_canvas(cx->torender); return 0; } -static int end_big(context_t *cx) +int render_end(context_t *cx) { - cucul_free_canvas(cx->onechar); - free(cx->buf); - cucul_free_font(cx->f); + cx->end(cx); return 0; } diff --git a/src/render.h b/src/render.h index a9d2aa6..ec311ec 100644 --- a/src/render.h +++ b/src/render.h @@ -17,4 +17,11 @@ extern int init_tiny(context_t *); extern int init_big(context_t *); +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_line(context_t *); +extern int render_end(context_t *); diff --git a/src/term.c b/src/term.c new file mode 100644 index 0000000..1859c01 --- /dev/null +++ b/src/term.c @@ -0,0 +1,113 @@ +/* + * TOIlet The Other Implementation’s letters + * Copyright (c) 2006 Sam Hocevar + * 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. + */ + +/* + * This file contains text to canvas rendering functions. + */ + +#include "config.h" + +#if defined(HAVE_INTTYPES_H) +# include +#endif +#include +#include + +#include "toilet.h" +#include "render.h" + +static int feed_tiny(context_t *, uint32_t); +static int flush_tiny(context_t *); +static int end_tiny(context_t *); + +int init_tiny(context_t *cx) +{ + cx->ew = 16; + cx->eh = 2; + cx->x = cx->y = 0; + cx->w = cx->h = 0; + cx->cv = cucul_create_canvas(cx->ew, cx->eh); + + cx->feed = feed_tiny; + cx->flush = flush_tiny; + cx->end = end_tiny; + + return 0; +} + +static int feed_tiny(context_t *cx, uint32_t ch) +{ + switch(ch) + { + case (uint32_t)'\r': + return 0; + case (uint32_t)'\n': + cx->x = 0; + cx->y++; + return 0; + case (uint32_t)'\t': + cx->x = (cx->x & ~7) + 8; + return 0; + } + + /* Check whether we reached the end of the screen */ + if(cx->x && cx->x + 1 > cx->term_width) + { + cx->x = 0; + cx->y++; + } + + /* Check whether the current canvas is large enough */ + if(cx->x + 1 > cx->w) + { + cx->w = cx->x + 1 < cx->term_width ? cx->x + 1 : cx->term_width; + if(cx->w > cx->ew) + cx->ew = cx->ew + cx->ew / 2; + } + + if(cx->y + 1 > cx->h) + { + cx->h = cx->y + 1; + if(cx->h > cx->eh) + cx->eh = cx->eh + cx->eh / 2; + } + + cucul_set_canvas_size(cx->cv, cx->ew, cx->eh); + + cucul_putchar(cx->cv, cx->x, cx->y, ch); + cx->x++; + + return 0; +} + +static int flush_tiny(context_t *cx) +{ + cx->torender = cx->cv; + cucul_set_canvas_size(cx->torender, cx->w, cx->h); + + cx->ew = 16; + cx->eh = 2; + cx->x = cx->y = 0; + cx->w = cx->h = 0; + cx->cv = cucul_create_canvas(cx->ew, cx->eh); + + return 0; +} + +static int end_tiny(context_t *cx) +{ + cucul_free_canvas(cx->cv); + + return 0; +} + diff --git a/src/toilet.h b/src/toilet.h index 6139c04..017c375 100644 --- a/src/toilet.h +++ b/src/toilet.h @@ -24,10 +24,12 @@ struct toilet_context unsigned int term_width; cucul_canvas_t *cv; + cucul_canvas_t *torender; unsigned int w, h, ew, eh, x, y; /* Render methods */ int (*feed)(struct toilet_context *, uint32_t); + int (*flush)(struct toilet_context *); int (*end)(struct toilet_context *); /* Used by the big driver */