* 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) | #if defined(HAVE_INTTYPES_H) | ||||
# include <inttypes.h> | # include <inttypes.h> | ||||
#endif | #endif | ||||
#include <string.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <cucul.h> | #include <cucul.h> | ||||
#include "toilet.h" | |||||
#include "filter.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 x, y, w, h; | ||||
unsigned int xmin, xmax, ymin, ymax; | unsigned int xmin, xmax, ymin, ymax; | ||||
@@ -58,7 +131,7 @@ void filter_autocrop(cucul_canvas_t *cv) | |||||
xmax - xmin + 1, ymax - ymin + 1); | 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[] = | 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[] = | 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. | * 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; | FILE *f; | ||||
}; | }; | ||||
TOIFILE *toiopen(const char *path, const char *mode) | |||||
TOIFILE *toiopen(char const *path, const char *mode) | |||||
{ | { | ||||
TOIFILE *toif = malloc(sizeof(*toif)); | TOIFILE *toif = malloc(sizeof(*toif)); | ||||
@@ -50,8 +50,6 @@ int main(int argc, char *argv[]) | |||||
int i, j, ret; | int i, j, ret; | ||||
unsigned int flag_gay = 0; | |||||
unsigned int flag_metal = 0; | |||||
int infocode = -1; | int infocode = -1; | ||||
cx->export = "utf8"; | cx->export = "utf8"; | ||||
@@ -60,6 +58,9 @@ int main(int argc, char *argv[]) | |||||
cx->term_width = 80; | cx->term_width = 80; | ||||
cx->filters = NULL; | |||||
cx->nfilters = 0; | |||||
#if defined(HAVE_GETOPT_H) | #if defined(HAVE_GETOPT_H) | ||||
for(;;) | for(;;) | ||||
{ | { | ||||
@@ -73,6 +74,7 @@ int main(int argc, char *argv[]) | |||||
{ "directory", 1, NULL, 'd' }, | { "directory", 1, NULL, 'd' }, | ||||
{ "width", 1, NULL, 'w' }, | { "width", 1, NULL, 'w' }, | ||||
{ "termwidth", 0, NULL, 't' }, | { "termwidth", 0, NULL, 't' }, | ||||
{ "filter", 1, NULL, 'F' }, | |||||
{ "gay", 0, NULL, 'g' }, | { "gay", 0, NULL, 'g' }, | ||||
{ "metal", 0, NULL, 'm' }, | { "metal", 0, NULL, 'm' }, | ||||
{ "irc", 0, NULL, 'i' }, | { "irc", 0, NULL, 'i' }, | ||||
@@ -82,11 +84,11 @@ int main(int argc, char *argv[]) | |||||
{ NULL, 0, NULL, 0 } | { 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); | long_options, &option_index); | ||||
# else | # else | ||||
# define MOREINFO "Try `%s -h' for more information.\n" | # 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 | # endif | ||||
if(c == -1) | if(c == -1) | ||||
break; | break; | ||||
@@ -108,11 +110,15 @@ int main(int argc, char *argv[]) | |||||
case 'd': /* --directory */ | case 'd': /* --directory */ | ||||
cx->dir = optarg; | cx->dir = optarg; | ||||
break; | break; | ||||
case 'F': /* --filter */ | |||||
if(filter_add(cx, optarg)) | |||||
return -1; | |||||
break; | |||||
case 'g': /* --gay */ | case 'g': /* --gay */ | ||||
flag_gay = 1; | |||||
filter_add(cx, "gay"); | |||||
break; | break; | ||||
case 'm': /* --metal */ | case 'm': /* --metal */ | ||||
flag_metal = 1; | |||||
filter_add(cx, "metal"); | |||||
break; | break; | ||||
case 'w': /* --width */ | case 'w': /* --width */ | ||||
cx->term_width = atoi(optarg); | cx->term_width = atoi(optarg); | ||||
@@ -220,12 +226,7 @@ int main(int argc, char *argv[]) | |||||
cx->end(cx); | cx->end(cx); | ||||
/* Apply optional effects to our string */ | /* 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 */ | /* Output char */ | ||||
buffer = cucul_export_canvas(cx->cv, cx->export); | buffer = cucul_export_canvas(cx->cv, cx->export); | ||||
@@ -240,7 +241,7 @@ int main(int argc, char *argv[]) | |||||
#if defined(HAVE_GETOPT_H) | #if defined(HAVE_GETOPT_H) | ||||
# define USAGE \ | # define USAGE \ | ||||
"Usage: toilet [ -ghimtv ] [ -d fontdirectory ]\n" \ | |||||
"Usage: toilet [ -ghimtvF ] [ -d fontdirectory ]\n" \ | |||||
" [ -f fontfile ] [ -w outputwidth ]\n" \ | " [ -f fontfile ] [ -w outputwidth ]\n" \ | ||||
" [ -I infocode ] [ message ]\n" | " [ -I infocode ] [ message ]\n" | ||||
#else | #else | ||||
@@ -274,6 +275,7 @@ static void usage(void) | |||||
printf(" -d, --directory <dir> specify font directory\n"); | printf(" -d, --directory <dir> specify font directory\n"); | ||||
printf(" -w, --width <width> set output width\n"); | printf(" -w, --width <width> set output width\n"); | ||||
printf(" -t, --termwidth adapt to terminal's 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(" -g, --gay add a rainbow effect to the text\n"); | ||||
printf(" -m, --metal add a metal effect to the text\n"); | printf(" -m, --metal add a metal effect to the text\n"); | ||||
printf(" -i, --irc output IRC colour codes\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(" -d <dir> specify font directory\n"); | ||||
printf(" -w <width> set output width\n"); | printf(" -w <width> set output width\n"); | ||||
printf(" -t adapt to terminal's 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(" -g add a rainbow effect to the text\n"); | ||||
printf(" -m add a metal effect to the text\n"); | printf(" -m add a metal effect to the text\n"); | ||||
printf(" -i output IRC colour codes\n"); | printf(" -i output IRC colour codes\n"); | ||||
@@ -26,7 +26,7 @@ struct toilet_context | |||||
cucul_canvas_t *cv; | cucul_canvas_t *cv; | ||||
unsigned int w, h, ew, eh, x, y; | unsigned int w, h, ew, eh, x, y; | ||||
/* Methods */ | |||||
/* Render methods */ | |||||
int (*feed)(struct toilet_context *, uint32_t); | int (*feed)(struct toilet_context *, uint32_t); | ||||
int (*end)(struct toilet_context *); | int (*end)(struct toilet_context *); | ||||
@@ -43,6 +43,10 @@ struct toilet_context | |||||
unsigned int glyphs; | unsigned int glyphs; | ||||
cucul_canvas_t *image; | cucul_canvas_t *image; | ||||
unsigned int *lookup; | unsigned int *lookup; | ||||
/* Render filters */ | |||||
void (**filters)(cucul_canvas_t *); | |||||
unsigned int nfilters; | |||||
}; | }; | ||||
typedef struct toilet_context context_t; | typedef struct toilet_context context_t; | ||||