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

Last change on this file since 1317 was 1317, checked in by Sam Hocevar, 14 years ago
  • Updated code to the beta9 API.
  • Property svn:keywords set to Id
File size: 4.7 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 1317 2006-11-09 21:58:43Z 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_LIGHTBLUE, CUCUL_BLUE, CUCUL_LIGHTGRAY, CUCUL_DARKGRAY,
147    };
148
149    unsigned int x, y, w, h;
150
151    w = cucul_get_canvas_width(cx->torender);
152    h = cucul_get_canvas_height(cx->torender);
153
154    for(y = 0; y < h; y++)
155        for(x = 0; x < w; x++)
156    {
157        unsigned long int ch = cucul_getchar(cx->torender, x, y);
158        int i;
159
160        if(ch == (unsigned char)' ')
161            continue;
162
163        i = ((cx->lines + y + x / 8) / 2) % 4;
164        cucul_set_color_ansi(cx->torender, palette[i], CUCUL_TRANSPARENT);
165        cucul_putchar(cx->torender, x, y, ch);
166    }
167}
168
169static void filter_gay(context_t *cx)
170{
171    static unsigned char const rainbow[] =
172    {
173        CUCUL_LIGHTMAGENTA, CUCUL_LIGHTRED, CUCUL_YELLOW,
174        CUCUL_LIGHTGREEN, CUCUL_LIGHTCYAN, CUCUL_LIGHTBLUE,
175    };
176    unsigned int x, y, w, h;
177
178    w = cucul_get_canvas_width(cx->torender);
179    h = cucul_get_canvas_height(cx->torender);
180
181    for(y = 0; y < h; y++)
182        for(x = 0; x < w; x++)
183    {
184        unsigned long int ch = cucul_getchar(cx->torender, x, y);
185        if(ch != (unsigned char)' ')
186        {
187            cucul_set_color_ansi(cx->torender,
188                                 rainbow[(x / 2 + y + cx->lines) % 6],
189                                 CUCUL_TRANSPARENT);
190            cucul_putchar(cx->torender, x, y, ch);
191        }
192    }
193}
194
195static void filter_flip(context_t *cx)
196{
197    cucul_flip(cx->torender);
198}
199
200static void filter_flop(context_t *cx)
201{
202    cucul_flop(cx->torender);
203}
204
205static void filter_rotate(context_t *cx)
206{
207    cucul_rotate(cx->torender);
208}
209
Note: See TracBrowser for help on using the repository browser.