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

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