* 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; | |||