source: toilet/trunk/src/filter.c @ 1461

Last change on this file since 1461 was 1461, checked in by sam, 7 years ago
  • Bwarf, typo in the no warranty clause.
  • Property svn:keywords set to Id
File size: 5.2 KB
Line 
1/*
2 *  TOIlet        The Other Implementation’s letters
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 * This file contains post-processing filter functions.
17 */
18
19#include "config.h"
20
21#if defined(HAVE_INTTYPES_H)
22#   include <inttypes.h>
23#endif
24#include <string.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <cucul.h>
28
29#include "toilet.h"
30#include "filter.h"
31
32static void filter_crop(context_t *);
33static void filter_gay(context_t *);
34static void filter_metal(context_t *);
35static void filter_flip(context_t *);
36static void filter_flop(context_t *);
37static void filter_rotate(context_t *);
38
39struct
40{
41    char const *name;
42    void (*function)(context_t *);
43    char const *description;
44}
45const lookup[] =
46{
47    { "crop", filter_crop, "crop unused blanks" },
48    { "gay", filter_gay, "add a rainbow colour effect" },
49    { "metal", filter_metal, "add a metallic colour effect" },
50    { "flip", filter_flip, "flip horizontally" },
51    { "flop", filter_flop, "flip vertically" },
52    { "rotate", filter_rotate, "perform a 180 degrees rotation" },
53};
54
55int filter_list(void)
56{
57    unsigned int i;
58
59    printf("Available filters:\n");
60    for(i = 0; i < sizeof(lookup) / sizeof(lookup[0]); i++)
61        printf("\"%s\": %s\n", lookup[i].name, lookup[i].description);
62
63    return 0;
64}
65
66int filter_add(context_t *cx, char const *filter)
67{
68    unsigned int n;
69    int i;
70
71    for(;;)
72    {
73        while(*filter == ':')
74            filter++;
75
76        if(*filter == '\0')
77            break;
78
79        for(i = sizeof(lookup) / sizeof(lookup[0]); i--; )
80            if(!strncmp(filter, lookup[i].name, strlen(lookup[i].name)))
81            {
82                n = strlen(lookup[i].name);
83                break;
84            }
85
86        if(i == -1 || (filter[n] != ':' && filter[n] != '\0'))
87        {
88            fprintf(stderr, "unknown filter near `%s'\n", filter);
89            return -1;
90        }
91
92        if((cx->nfilters % 16) == 0)
93            cx->filters = realloc(cx->filters, (cx->nfilters + 16)
94                                                 * sizeof(lookup[0].function));
95        cx->filters[cx->nfilters] = lookup[i].function;
96        cx->nfilters++;
97
98        filter += n;
99    }
100
101    return 0;
102}
103
104int filter_do(context_t *cx)
105{
106    unsigned int i;
107
108    for(i = 0; i < cx->nfilters; i++)
109        cx->filters[i](cx);
110
111    return 0;
112}
113
114int filter_end(context_t *cx)
115{
116    free(cx->filters);
117
118    return 0;
119}
120
121static void filter_crop(context_t *cx)
122{
123    unsigned int x, y, w, h;
124    unsigned int xmin, xmax, ymin, ymax;
125
126    xmin = w = cucul_get_canvas_width(cx->torender);
127    xmax = 0;
128    ymin = h = cucul_get_canvas_height(cx->torender);
129    ymax = 0;
130
131    for(y = 0; y < h; y++)
132        for(x = 0; x < w; x++)
133    {
134        unsigned long int ch = cucul_get_char(cx->torender, x, y);
135        if(ch != (unsigned char)' ')
136        {
137            if(x < xmin)
138                xmin = x;
139            if(x > xmax)
140                xmax = x;
141            if(y < ymin)
142                ymin = y;
143            if(y > ymax)
144                ymax = y;
145        }
146    }
147
148    if(xmax < xmin || ymax < ymin)
149        return;
150
151    cucul_set_canvas_boundaries(cx->torender, xmin, ymin,
152                                xmax - xmin + 1, ymax - ymin + 1);
153}
154
155static void filter_metal(context_t *cx)
156{
157    static unsigned char const palette[] =
158    {
159        CUCUL_LIGHTBLUE, CUCUL_BLUE, CUCUL_LIGHTGRAY, CUCUL_DARKGRAY,
160    };
161
162    unsigned int x, y, w, h;
163
164    w = cucul_get_canvas_width(cx->torender);
165    h = cucul_get_canvas_height(cx->torender);
166
167    for(y = 0; y < h; y++)
168        for(x = 0; x < w; x++)
169    {
170        unsigned long int ch = cucul_get_char(cx->torender, x, y);
171        int i;
172
173        if(ch == (unsigned char)' ')
174            continue;
175
176        i = ((cx->lines + y + x / 8) / 2) % 4;
177        cucul_set_color_ansi(cx->torender, palette[i], CUCUL_TRANSPARENT);
178        cucul_put_char(cx->torender, x, y, ch);
179    }
180}
181
182static void filter_gay(context_t *cx)
183{
184    static unsigned char const rainbow[] =
185    {
186        CUCUL_LIGHTMAGENTA, CUCUL_LIGHTRED, CUCUL_YELLOW,
187        CUCUL_LIGHTGREEN, CUCUL_LIGHTCYAN, CUCUL_LIGHTBLUE,
188    };
189    unsigned int x, y, w, h;
190
191    w = cucul_get_canvas_width(cx->torender);
192    h = cucul_get_canvas_height(cx->torender);
193
194    for(y = 0; y < h; y++)
195        for(x = 0; x < w; x++)
196    {
197        unsigned long int ch = cucul_get_char(cx->torender, x, y);
198        if(ch != (unsigned char)' ')
199        {
200            cucul_set_color_ansi(cx->torender,
201                                 rainbow[(x / 2 + y + cx->lines) % 6],
202                                 CUCUL_TRANSPARENT);
203            cucul_put_char(cx->torender, x, y, ch);
204        }
205    }
206}
207
208static void filter_flip(context_t *cx)
209{
210    cucul_flip(cx->torender);
211}
212
213static void filter_flop(context_t *cx)
214{
215    cucul_flop(cx->torender);
216}
217
218static void filter_rotate(context_t *cx)
219{
220    cucul_rotate(cx->torender);
221}
222
Note: See TracBrowser for help on using the repository browser.