source: toilet/trunk/src/main.c @ 1087

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