source: libcaca/trunk/test/toilet.c @ 1080

Last change on this file since 1080 was 1080, checked in by Sam Hocevar, 15 years ago
  • Autocrop toilet output.
  • Property svn:keywords set to Id
File size: 7.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: toilet.c 1080 2006-09-22 00:27: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#include "config.h"
15#include "common.h"
16
17#if !defined(__KERNEL__)
18#   if defined(HAVE_INTTYPES_H)
19#      include <inttypes.h>
20#   endif
21#   if defined(HAVE_GETOPT_H)
22#      include <getopt.h>
23#   endif
24#   include <stdio.h>
25#   include <string.h>
26#   include <stdlib.h>
27#endif
28
29#include "cucul.h"
30#include "caca.h"
31
32/* String to canvas transformations */
33static cucul_canvas_t *cuculize_big(uint32_t const *, unsigned int);
34static cucul_canvas_t *cuculize_tiny(uint32_t const *, unsigned int);
35
36/* Canvas special effects */
37static void filter_autocrop(cucul_canvas_t *);
38static void filter_gay(cucul_canvas_t *);
39
40int main(int argc, char *argv[])
41{
42    cucul_canvas_t *cv;
43    cucul_buffer_t *buffer;
44
45    uint32_t *string = NULL;
46    unsigned int length;
47
48    int i;
49
50    char const *export = "utf8";
51    unsigned flag_gay = 0;
52
53#if defined(HAVE_GETOPT_H)
54    for(;;)
55    {
56#   ifdef HAVE_GETOPT_LONG
57#       define MOREINFO "Try `%s --help' for more information.\n"
58        int option_index = 0;
59        static struct option long_options[] =
60        {
61            /* Long option, needs arg, flag, short option */
62            { "gay", 0, NULL, 'g' },
63            { "irc", 0, NULL, 'i' },
64            { "help", 0, NULL, 'h' },
65            { "version", 0, NULL, 'v' },
66            { NULL, 0, NULL, 0 }
67        };
68
69        int c = getopt_long(argc, argv, "gihv", long_options, &option_index);
70#   else
71#       define MOREINFO "Try `%s -h' for more information.\n"
72        int c = getopt(argc, argv, "gihv");
73#   endif
74        if(c == -1)
75            break;
76
77        switch(c)
78        {
79        case 'h': /* --help */
80            printf("Usage: %s [ -gihv ] [ message ]\n", argv[0]);
81#   ifdef HAVE_GETOPT_LONG
82            printf("  -g, --gay        add a rainbow effect to the text\n");
83            printf("  -i, --irc        output IRC colour codes\n");
84            printf("  -h, --help       display this help and exit\n");
85            printf("  -v, --version    output version information and exit\n");
86#   else
87            printf("  -g    add a rainbow effect to the text\n");
88            printf("  -i    output IRC colour codes\n");
89            printf("  -h    display this help and exit\n");
90            printf("  -v    output version information and exit\n");
91#   endif
92            return 0;
93        case 'g': /* --gay */
94            flag_gay = 1;
95            break;
96        case 'i': /* --irc */
97            export = "irc";
98            break;
99        case 'v': /* --version */
100            printf("TOIlet Copyright 2006 Sam Hocevar %s\n", VERSION);
101            printf("Internet: <sam@zoy.org> Version: 0, date: 21 Sep 2006\n");
102            printf("\n");
103            return 0;
104        case '?':
105            printf(MOREINFO, argv[0]);
106            return 1;
107        default:
108            printf("%s: invalid option -- %i\n", argv[0], c);
109            printf(MOREINFO, argv[0]);
110            return 1;
111        }
112    }
113#else
114#   define MOREINFO "Usage: %s message...\n"
115    int optind = 1;
116#endif
117
118    if(optind >= argc)
119    {
120        printf("%s: too few arguments\n", argv[0]);
121        printf(MOREINFO, argv[0]);
122        return 1;
123    }
124
125    /* Load rest of commandline into a UTF-32 string */
126    for(i = optind, length = 0; i < argc; i++)
127    {
128        unsigned int k, guessed_len, real_len;
129
130        guessed_len = strlen(argv[i]);
131
132        if(i > optind)
133            string[length++] = (uint32_t)' ';
134
135        string = realloc(string, (length + guessed_len + 1) * 4);
136
137        for(k = 0, real_len = 0; k < guessed_len; real_len++)
138        {
139            unsigned int char_len;
140
141            string[length + real_len] =
142                cucul_utf8_to_utf32(argv[i] + k, &char_len);
143
144            k += char_len;
145        }
146
147        length += real_len;
148    }
149
150    /* Do gay stuff with our string (léopard) */
151    cv = cuculize_big(string, length);
152    filter_autocrop(cv);
153    if(flag_gay)
154        filter_gay(cv);
155
156    /* Output char */
157    buffer = cucul_export_canvas(cv, export);
158    fwrite(cucul_get_buffer_data(buffer),
159           cucul_get_buffer_size(buffer), 1, stdout);
160    cucul_free_buffer(buffer);
161
162    cucul_free_canvas(cv);
163
164    return 0;
165}
166
167static cucul_canvas_t *cuculize_big(uint32_t const *string,
168                                    unsigned int length)
169{
170    cucul_canvas_t *cv;
171    cucul_font_t *f;
172    char const * const * fonts;
173    unsigned char *buf;
174    unsigned int w, h, x, y, miny, maxy;
175
176    cv = cucul_create_canvas(length, 1);
177    for(x = 0; x < length; x++)
178        cucul_putchar(cv, x, 0, string[x]);
179
180    fonts = cucul_get_font_list();
181    f = cucul_load_font(fonts[0], 0);
182
183    /* Create our bitmap buffer (32-bit ARGB) */
184    w = cucul_get_canvas_width(cv) * cucul_get_font_width(f);
185    h = cucul_get_canvas_height(cv) * cucul_get_font_height(f);
186    buf = malloc(4 * w * h);
187
188    /* Render the canvas onto our image buffer */
189    cucul_render_canvas(cv, f, buf, w, h, 4 * w);
190
191    /* Free our canvas, and allocate a bigger one */
192    cucul_free_font(f);
193    cucul_free_canvas(cv);
194    cv = cucul_create_canvas(w, h);
195
196    /* Render the image buffer on the canvas */
197    cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_TRANSPARENT);
198    cucul_clear_canvas(cv);
199
200    miny = h; maxy = 0;
201
202    for(y = 0; y < h; y++)
203       for(x = 0; x < w; x++)
204    {
205        unsigned char c = buf[4 * (x + y * w) + 2];
206
207        if(c >= 0xa0)
208            cucul_putstr(cv, x, y, "█");
209        else if(c >= 0x80)
210            cucul_putstr(cv, x, y, "▓");
211        else if(c >= 0x40)
212            cucul_putstr(cv, x, y, "▒");
213        else if(c >= 0x20)
214            cucul_putstr(cv, x, y, "░");
215    }
216
217    free(buf);
218
219    return cv;
220}
221
222static cucul_canvas_t *cuculize_tiny(uint32_t const *string,
223                                     unsigned int length)
224{
225    unsigned int x;
226    cucul_canvas_t *cv = cucul_create_canvas(length, 1);
227
228    for(x = 0; x < length; x++)
229        cucul_putchar(cv, x, 0, string[x]);
230
231    return cv;
232}
233
234static void filter_autocrop(cucul_canvas_t *cv)
235{
236    unsigned int x, y, w, h;
237    unsigned int xmin, xmax, ymin, ymax;
238
239    xmin = w = cucul_get_canvas_width(cv);
240    xmax = 0;
241    ymin = h = cucul_get_canvas_height(cv);
242    ymax = 0;
243
244    for(y = 0; y < h; y++)
245        for(x = 0; x < w; x++)
246    {
247        unsigned long int ch = cucul_getchar(cv, x, y);
248        if(ch != (unsigned char)' ')
249        {
250            if(x < xmin)
251                xmin = x;
252            if(x > xmax)
253                xmax = x;
254            if(y < ymin)
255                ymin = y;
256            if(y > ymax)
257                ymax = y;
258        }
259    }
260
261    cucul_set_canvas_boundaries(cv, xmin, ymin,
262                                xmax - xmin + 1, ymax - ymin + 1);
263}
264
265static void filter_gay(cucul_canvas_t *cv)
266{
267    static unsigned char const rainbow[] =
268    {
269        CUCUL_COLOR_LIGHTMAGENTA,
270        CUCUL_COLOR_LIGHTRED,
271        CUCUL_COLOR_YELLOW,
272        CUCUL_COLOR_LIGHTGREEN,
273        CUCUL_COLOR_LIGHTCYAN,
274        CUCUL_COLOR_LIGHTBLUE,
275    };
276    unsigned int x, y, w, h;
277
278    w = cucul_get_canvas_width(cv);
279    h = cucul_get_canvas_height(cv);
280
281    for(y = 0; y < h; y++)
282        for(x = 0; x < w; x++)
283    {
284        unsigned long int ch = cucul_getchar(cv, x, y);
285        if(ch != (unsigned char)' ')
286        {
287            cucul_set_color(cv, rainbow[(x / 2 + y) % 6],
288                                CUCUL_COLOR_TRANSPARENT);
289            cucul_putchar(cv, x, y, ch);
290        }
291    }
292}
293
Note: See TracBrowser for help on using the repository browser.