* Add a -F flag to specify filters to apply. Can be specified more than
once, and filters can be chained using ":", eg. "-F flip:gay".
pull/1/head
| @@ -20,11 +20,84 @@ | |||
| #if defined(HAVE_INTTYPES_H) | |||
| # include <inttypes.h> | |||
| #endif | |||
| #include <string.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <cucul.h> | |||
| #include "toilet.h" | |||
| #include "filter.h" | |||
| void filter_autocrop(cucul_canvas_t *cv) | |||
| static void filter_crop(cucul_canvas_t *); | |||
| static void filter_gay(cucul_canvas_t *); | |||
| static void filter_metal(cucul_canvas_t *); | |||
| static void filter_flip(cucul_canvas_t *); | |||
| static void filter_flop(cucul_canvas_t *); | |||
| static void filter_rotate(cucul_canvas_t *); | |||
| struct | |||
| { | |||
| char const *name; | |||
| void (*function)(cucul_canvas_t *); | |||
| } | |||
| const lookup[] = | |||
| { | |||
| { "crop", filter_crop }, | |||
| { "gay", filter_gay }, | |||
| { "metal", filter_metal }, | |||
| { "flip", filter_flip }, | |||
| { "flop", filter_flop }, | |||
| { "rotate", filter_rotate }, | |||
| }; | |||
| int filter_add(context_t *cx, char const *filter) | |||
| { | |||
| unsigned int n; | |||
| int i; | |||
| for(;;) | |||
| { | |||
| while(*filter == ':') | |||
| filter++; | |||
| if(*filter == '\0') | |||
| break; | |||
| for(i = sizeof(lookup) / sizeof(lookup[0]); i--; ) | |||
| if(!strncmp(filter, lookup[i].name, strlen(lookup[i].name))) | |||
| break; | |||
| n = strlen(lookup[i].name); | |||
| if(i == -1 || (filter[n] != ':' && filter[n] != '\0')) | |||
| { | |||
| fprintf(stderr, "unknown filter near `%s'\n", filter); | |||
| return -1; | |||
| } | |||
| if((cx->nfilters % 16) == 0) | |||
| cx->filters = realloc(cx->filters, (cx->nfilters + 16) | |||
| * sizeof(lookup[0].function)); | |||
| cx->filters[cx->nfilters] = lookup[i].function; | |||
| cx->nfilters++; | |||
| filter += n; | |||
| } | |||
| return 0; | |||
| } | |||
| int filter_do(context_t *cx) | |||
| { | |||
| unsigned int i; | |||
| for(i = 0; i < cx->nfilters; i++) | |||
| cx->filters[i](cx->cv); | |||
| return 0; | |||
| } | |||
| static void filter_crop(cucul_canvas_t *cv) | |||
| { | |||
| unsigned int x, y, w, h; | |||
| unsigned int xmin, xmax, ymin, ymax; | |||
| @@ -58,7 +131,7 @@ void filter_autocrop(cucul_canvas_t *cv) | |||
| xmax - xmin + 1, ymax - ymin + 1); | |||
| } | |||
| void filter_metal(cucul_canvas_t *cv) | |||
| static void filter_metal(cucul_canvas_t *cv) | |||
| { | |||
| static unsigned char const palette[] = | |||
| { | |||
| @@ -88,7 +161,7 @@ void filter_metal(cucul_canvas_t *cv) | |||
| } | |||
| } | |||
| void filter_gay(cucul_canvas_t *cv) | |||
| static void filter_gay(cucul_canvas_t *cv) | |||
| { | |||
| static unsigned char const rainbow[] = | |||
| { | |||
| @@ -117,3 +190,18 @@ void filter_gay(cucul_canvas_t *cv) | |||
| } | |||
| } | |||
| static void filter_flip(cucul_canvas_t *cv) | |||
| { | |||
| cucul_flip(cv); | |||
| } | |||
| static void filter_flop(cucul_canvas_t *cv) | |||
| { | |||
| cucul_flop(cv); | |||
| } | |||
| static void filter_rotate(cucul_canvas_t *cv) | |||
| { | |||
| cucul_rotate(cv); | |||
| } | |||
| @@ -15,7 +15,6 @@ | |||
| * This header defines post-processing filter functions. | |||
| */ | |||
| extern void filter_autocrop(cucul_canvas_t *); | |||
| extern void filter_metal(cucul_canvas_t *); | |||
| extern void filter_gay(cucul_canvas_t *); | |||
| extern int filter_add(context_t *, char const *); | |||
| extern int filter_do(context_t *); | |||
| @@ -45,7 +45,7 @@ struct toifile | |||
| FILE *f; | |||
| }; | |||
| TOIFILE *toiopen(const char *path, const char *mode) | |||
| TOIFILE *toiopen(char const *path, const char *mode) | |||
| { | |||
| TOIFILE *toif = malloc(sizeof(*toif)); | |||
| @@ -50,8 +50,6 @@ int main(int argc, char *argv[]) | |||
| int i, j, ret; | |||
| unsigned int flag_gay = 0; | |||
| unsigned int flag_metal = 0; | |||
| int infocode = -1; | |||
| cx->export = "utf8"; | |||
| @@ -60,6 +58,9 @@ int main(int argc, char *argv[]) | |||
| cx->term_width = 80; | |||
| cx->filters = NULL; | |||
| cx->nfilters = 0; | |||
| #if defined(HAVE_GETOPT_H) | |||
| for(;;) | |||
| { | |||
| @@ -73,6 +74,7 @@ int main(int argc, char *argv[]) | |||
| { "directory", 1, NULL, 'd' }, | |||
| { "width", 1, NULL, 'w' }, | |||
| { "termwidth", 0, NULL, 't' }, | |||
| { "filter", 1, NULL, 'F' }, | |||
| { "gay", 0, NULL, 'g' }, | |||
| { "metal", 0, NULL, 'm' }, | |||
| { "irc", 0, NULL, 'i' }, | |||
| @@ -82,11 +84,11 @@ int main(int argc, char *argv[]) | |||
| { NULL, 0, NULL, 0 } | |||
| }; | |||
| int c = getopt_long(argc, argv, "d:f:I:w:ghimtv", | |||
| int c = getopt_long(argc, argv, "f:d:w:tF:gmihI:v", | |||
| long_options, &option_index); | |||
| # else | |||
| # define MOREINFO "Try `%s -h' for more information.\n" | |||
| int c = getopt(argc, argv, "d:f:I:w:ghimtv"); | |||
| int c = getopt(argc, argv, "f:d:w:tF:gmihI:v"); | |||
| # endif | |||
| if(c == -1) | |||
| break; | |||
| @@ -108,11 +110,15 @@ int main(int argc, char *argv[]) | |||
| case 'd': /* --directory */ | |||
| cx->dir = optarg; | |||
| break; | |||
| case 'F': /* --filter */ | |||
| if(filter_add(cx, optarg)) | |||
| return -1; | |||
| break; | |||
| case 'g': /* --gay */ | |||
| flag_gay = 1; | |||
| filter_add(cx, "gay"); | |||
| break; | |||
| case 'm': /* --metal */ | |||
| flag_metal = 1; | |||
| filter_add(cx, "metal"); | |||
| break; | |||
| case 'w': /* --width */ | |||
| cx->term_width = atoi(optarg); | |||
| @@ -220,12 +226,7 @@ int main(int argc, char *argv[]) | |||
| cx->end(cx); | |||
| /* Apply optional effects to our string */ | |||
| if(!strcasecmp(cx->font, "mono9")) | |||
| filter_autocrop(cx->cv); | |||
| if(flag_metal) | |||
| filter_metal(cx->cv); | |||
| if(flag_gay) | |||
| filter_gay(cx->cv); | |||
| filter_do(cx); | |||
| /* Output char */ | |||
| buffer = cucul_export_canvas(cx->cv, cx->export); | |||
| @@ -240,7 +241,7 @@ int main(int argc, char *argv[]) | |||
| #if defined(HAVE_GETOPT_H) | |||
| # define USAGE \ | |||
| "Usage: toilet [ -ghimtv ] [ -d fontdirectory ]\n" \ | |||
| "Usage: toilet [ -ghimtvF ] [ -d fontdirectory ]\n" \ | |||
| " [ -f fontfile ] [ -w outputwidth ]\n" \ | |||
| " [ -I infocode ] [ message ]\n" | |||
| #else | |||
| @@ -274,6 +275,7 @@ static void usage(void) | |||
| printf(" -d, --directory <dir> specify font directory\n"); | |||
| printf(" -w, --width <width> set output width\n"); | |||
| printf(" -t, --termwidth adapt to terminal's width\n"); | |||
| printf(" -F, --filter apply one or several filters to the text\n"); | |||
| printf(" -g, --gay add a rainbow effect to the text\n"); | |||
| printf(" -m, --metal add a metal effect to the text\n"); | |||
| printf(" -i, --irc output IRC colour codes\n"); | |||
| @@ -285,6 +287,7 @@ static void usage(void) | |||
| printf(" -d <dir> specify font directory\n"); | |||
| printf(" -w <width> set output width\n"); | |||
| printf(" -t adapt to terminal's width\n"); | |||
| printf(" -F apply one or several filters to the text\n"); | |||
| printf(" -g add a rainbow effect to the text\n"); | |||
| printf(" -m add a metal effect to the text\n"); | |||
| printf(" -i output IRC colour codes\n"); | |||
| @@ -26,7 +26,7 @@ struct toilet_context | |||
| cucul_canvas_t *cv; | |||
| unsigned int w, h, ew, eh, x, y; | |||
| /* Methods */ | |||
| /* Render methods */ | |||
| int (*feed)(struct toilet_context *, uint32_t); | |||
| int (*end)(struct toilet_context *); | |||
| @@ -43,6 +43,10 @@ struct toilet_context | |||
| unsigned int glyphs; | |||
| cucul_canvas_t *image; | |||
| unsigned int *lookup; | |||
| /* Render filters */ | |||
| void (**filters)(cucul_canvas_t *); | |||
| unsigned int nfilters; | |||
| }; | |||
| typedef struct toilet_context context_t; | |||