source: libcaca/trunk/cucul/transform.c @ 769

Last change on this file since 769 was 769, checked in by Sam Hocevar, 14 years ago
  • Removed \file directives from all files except caca.h and cucul.h, to remove redundencies in the Doxygen documentation.
  • Property svn:keywords set to Id
File size: 9.7 KB
Line 
1/*
2 *  libcucul      Canvas for ultrafast compositing of Unicode letters
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: transform.c 769 2006-04-14 07:30:53Z sam $
7 *
8 *  This library 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 horizontal and vertical flipping routines.
16 */
17
18#include "config.h"
19
20#if !defined(__KERNEL__)
21#endif
22
23#include "cucul.h"
24#include "cucul_internals.h"
25
26static uint32_t flipchar(uint32_t ch);
27static uint32_t flopchar(uint32_t ch);
28static uint32_t rotatechar(uint32_t ch);
29
30/** \brief Invert a canvas' colours.
31 *
32 *  This function inverts a canvas' colours (black becomes white, red
33 *  becomes cyan, etc.) without changing the characters in it.
34 *
35 *  \param qq The canvas to invert.
36 */
37void cucul_invert(cucul_t *qq)
38{
39    uint32_t *attr = qq->attr;
40    unsigned int i;
41
42    for(i = qq->height * qq->width; i--; )
43    {
44        *attr = *attr ^ 0x000f000f;
45        attr++;
46    }
47}
48
49/** \brief Flip a canvas horizontally.
50 *
51 *  This function flips a canvas horizontally, choosing characters that
52 *  look like the mirrored version wherever possible.
53 *
54 *  \param qq The canvas to flip.
55 */
56void cucul_flip(cucul_t *qq)
57{
58    unsigned int y;
59
60    for(y = 0; y < qq->height; y++)
61    {
62        uint32_t *cleft = qq->chars + y * qq->width;
63        uint32_t *cright = cleft + qq->width - 1;
64        uint32_t *aleft = qq->attr + y * qq->width;
65        uint32_t *aright = aleft + qq->width - 1;
66
67        while(cleft < cright)
68        {
69            uint32_t ch;
70            uint32_t attr;
71
72            /* Swap attributes */
73            attr = *aright; *aright = *aleft; *aleft = attr;
74
75            /* Swap characters */
76            ch = *cright; *cright = flipchar(*cleft); *cleft = flipchar(ch);
77
78            cleft++; cright--; aleft++; aright--;
79        }
80
81        if(cleft == cright)
82            *cleft = flipchar(*cleft);
83    }
84}
85
86/** \brief Flip a canvas vertically.
87 *
88 *  This function flips a canvas vertically, choosing characters that
89 *  look like the mirrored version wherever possible.
90 *
91 *  \param qq The canvas to flop.
92 */
93void cucul_flop(cucul_t *qq)
94{
95    unsigned int x;
96
97    for(x = 0; x < qq->width; x++)
98    {
99        uint32_t *ctop = qq->chars + x;
100        uint32_t *cbottom = ctop + qq->width * (qq->height - 1);
101        uint32_t *atop = qq->attr + x;
102        uint32_t *abottom = atop + qq->width * (qq->height - 1);
103
104        while(ctop < cbottom)
105        {
106            uint32_t ch;
107            uint32_t attr;
108
109            /* Swap attributes */
110            attr = *abottom; *abottom = *atop; *atop = attr;
111
112            /* Swap characters */
113            ch = *cbottom; *cbottom = flopchar(*ctop); *ctop = flopchar(ch);
114
115            ctop += qq->width; cbottom -= qq->width;
116            atop += qq->width; abottom -= qq->width;
117        }
118
119        if(ctop == cbottom)
120            *ctop = flopchar(*ctop);
121    }
122}
123
124/** \brief Rotate a canvas.
125 *
126 *  This function applies a 180 degrees transformation to a canvas,
127 *  choosing characters that look like the mirrored version wherever
128 *  possible.
129 *
130 *  \param qq The canvas to rotate.
131 */
132void cucul_rotate(cucul_t *qq)
133{
134    uint32_t *cbegin = qq->chars;
135    uint32_t *cend = cbegin + qq->width * qq->height - 1;
136    uint32_t *abegin = qq->attr;
137    uint32_t *aend = abegin + qq->width * qq->height - 1;
138
139    while(cbegin < cend)
140    {
141        uint32_t ch;
142        uint32_t attr;
143
144        /* Swap attributes */
145        attr = *aend; *aend = *abegin; *abegin = attr;
146
147        /* Swap characters */
148        ch = *cend; *cend = rotatechar(*cbegin); *cbegin = rotatechar(ch);
149
150        cbegin++; cend--; abegin++; aend--;
151    }
152
153    if(cbegin == cend)
154        *cbegin = rotatechar(*cbegin);
155}
156
157static uint32_t flipchar(uint32_t ch)
158{
159    int i;
160
161    static uint32_t const noflip[] =
162    {
163         /* ASCII */
164         (uint32_t)' ', (uint32_t)'"', (uint32_t)'#', (uint32_t)'\'',
165         (uint32_t)'-', (uint32_t)'.', (uint32_t)'*', (uint32_t)'+',
166         (uint32_t)':', (uint32_t)'=',
167         (uint32_t)'0', (uint32_t)'8', (uint32_t)'A', (uint32_t)'H',
168         (uint32_t)'I', (uint32_t)'M', (uint32_t)'O', (uint32_t)'T',
169         (uint32_t)'U', (uint32_t)'V', (uint32_t)'W', (uint32_t)'X',
170         (uint32_t)'Y', (uint32_t)'^', (uint32_t)'_', (uint32_t)'i',
171         (uint32_t)'o', (uint32_t)'v', (uint32_t)'w', (uint32_t)'x',
172         (uint32_t)'|',
173         /* Unicode */
174         0x2591, 0x2592, 0x2593, 0x2588, 0x2584, 0x2580, /* ░ ▒ ▓ █ ▄ ▀ */
175         0
176    };
177
178    static uint32_t const pairs[] =
179    {
180         /* ASCII */
181         (uint32_t)'(', (uint32_t)')', (uint32_t)'/', (uint32_t)'\\',
182         (uint32_t)'<', (uint32_t)'>', (uint32_t)'[', (uint32_t)']',
183         (uint32_t)'b', (uint32_t)'d', (uint32_t)'p', (uint32_t)'q',
184         (uint32_t)'{', (uint32_t)'}',
185         /* ASCII-Unicode */
186         (uint32_t)';', 0x204f, /* ; ⁏ */
187         (uint32_t)'`', 0x00b4, /* ` ´ */
188         (uint32_t)'E', 0x018e, /* E Ǝ */
189         (uint32_t)'N', 0x0418, /* N И */
190         (uint32_t)'R', 0x042f, /* R Я */
191         (uint32_t)'S', 0x01a7, /* S Ƨ */
192         (uint32_t)'c', 0x0254, /* c ɔ */
193         (uint32_t)'e', 0x0258, /* e ɘ */
194         /* Unicode only */
195         0x258c, 0x2590, /* ▌ ▐ */
196         0x2596, 0x2597, /* ▖ ▗ */
197         0x2598, 0x259d, /* ▘ ▝ */
198         0x2599, 0x259f, /* ▙ ▟ */
199         0x259a, 0x259e, /* ▚ ▞ */
200         0x259b, 0x259c, /* ▛ ▜ */
201         0
202    };
203
204    for(i = 0; noflip[i]; i++)
205        if(ch == noflip[i])
206            return ch;
207
208    for(i = 0; pairs[i]; i++)
209        if(ch == pairs[i])
210            return pairs[i ^ 1];
211
212    return ch;
213}
214
215static uint32_t flopchar(uint32_t ch)
216{
217    int i;
218
219    static uint32_t const noflop[] =
220    {
221         /* ASCII */
222         (uint32_t)' ', (uint32_t)'(', (uint32_t)')', (uint32_t)'*',
223         (uint32_t)'+', (uint32_t)'-',
224         (uint32_t)'0', (uint32_t)'3', (uint32_t)'8', (uint32_t)':',
225         (uint32_t)'<', (uint32_t)'=', (uint32_t)'>', (uint32_t)'B',
226         (uint32_t)'C', (uint32_t)'D', (uint32_t)'E', (uint32_t)'H',
227         (uint32_t)'I', (uint32_t)'K', (uint32_t)'O', (uint32_t)'X',
228         (uint32_t)'[', (uint32_t)']', (uint32_t)'c', (uint32_t)'o',
229         (uint32_t)'{', (uint32_t)'|', (uint32_t)'}',
230         /* Unicode */
231         0x2591, 0x2592, 0x2593, 0x2588, 0x258c, 0x2590, /* ░ ▒ ▓ █ ▌ ▐ */
232         0
233    };
234
235    static uint32_t const pairs[] =
236    {
237         /* ASCII */
238         (uint32_t)'/', (uint32_t)'\\', (uint32_t)'M', (uint32_t)'W',
239         (uint32_t)',', (uint32_t)'`', (uint32_t)'b', (uint32_t)'p',
240         (uint32_t)'d', (uint32_t)'q', (uint32_t)'p', (uint32_t)'q',
241         (uint32_t)'f', (uint32_t)'t', (uint32_t)'.', (uint32_t)'\'',
242         /* ASCII-Unicode */
243         (uint32_t)'_', 0x2594, /* _ ▔ */
244         (uint32_t)'`', 0x201a, /* ` ‚ */
245         (uint32_t)'!', 0x00a1, /* ! ¡ */
246         (uint32_t)'N', 0x0418, /* N И */
247         (uint32_t)'P', 0x042c, /* P Ь */
248         (uint32_t)'S', 0x01a7, /* S Ƨ */
249         (uint32_t)'v', 0x028c, /* v ʌ */
250         (uint32_t)'w', 0x028d, /* w ʍ */
251         /* Unicode only */
252         0x2584, 0x2580, /* ▄ ▀ */
253         0x2596, 0x2598, /* ▖ ▘ */
254         0x2597, 0x259d, /* ▗ ▝ */
255         0x2599, 0x259b, /* ▙ ▛ */
256         0x259f, 0x259c, /* ▟ ▜ */
257         0x259a, 0x259e, /* ▚ ▞ */
258         0
259    };
260
261    for(i = 0; noflop[i]; i++)
262        if(ch == noflop[i])
263            return ch;
264
265    for(i = 0; pairs[i]; i++)
266        if(ch == pairs[i])
267            return pairs[i ^ 1];
268
269    return ch;
270}
271
272static uint32_t rotatechar(uint32_t ch)
273{
274    int i;
275
276    static uint32_t const norotate[] =
277    {
278         /* ASCII - FIXME: a lot are missing */
279         (uint32_t)' ', (uint32_t)'*', (uint32_t)'+', (uint32_t)'-',
280         (uint32_t)'0', (uint32_t)'8', (uint32_t)':', (uint32_t)'=',
281         /* Unicode */
282         0x2591, 0x2592, 0x2593, 0x2588, 0x259a, 0x259e, /* ░ ▒ ▓ █ ▚ ▞ */
283         0
284    };
285
286    static uint32_t const pairs[] =
287    {
288         /* ASCII */
289         (uint32_t)'(', (uint32_t)')', (uint32_t)'<', (uint32_t)'>',
290         (uint32_t)'[', (uint32_t)']', (uint32_t)'{', (uint32_t)'}',
291         (uint32_t)'.', (uint32_t)'\'',
292         (uint32_t)'6', (uint32_t)'9',
293         (uint32_t)'M', (uint32_t)'W', (uint32_t)'b', (uint32_t)'q',
294         (uint32_t)'d', (uint32_t)'p', (uint32_t)'n', (uint32_t)'u',
295         /* ASCII-Unicode */
296         (uint32_t)'_', 0x2594, /* _ ▔ */
297         (uint32_t)',', 0x02bb, /* , ʻ */
298         (uint32_t)'!', 0x00a1, /* ! ¡ */
299         (uint32_t)'?', 0x00bf, /* ? ¿ */
300         (uint32_t)'E', 0x018e, /* E Ǝ */
301         (uint32_t)'F', 0x2132, /* F Ⅎ */
302         (uint32_t)'a', 0x0250, /* a ɐ */
303         (uint32_t)'c', 0x0254, /* c ɔ */
304         (uint32_t)'e', 0x0259, /* e ə */
305         (uint32_t)'f', 0x025f, /* f ɟ */
306         (uint32_t)'h', 0x0265, /* h ɥ */
307         (uint32_t)'k', 0x029e, /* k ʞ */
308         (uint32_t)'m', 0x026f, /* m ɯ */
309         (uint32_t)'r', 0x0279, /* r ɹ */
310         (uint32_t)'t', 0x0287, /* t ʇ */
311         (uint32_t)'v', 0x028c, /* v ʌ */
312         (uint32_t)'w', 0x028d, /* w ʍ */
313         (uint32_t)'y', 0x028e, /* y ʎ */
314         /* Unicode only */
315         0x258c, 0x2590, /* ▌ ▐ */
316         0x2584, 0x2580, /* ▄ ▀ */
317         0x2596, 0x259d, /* ▖ ▝ */
318         0x2597, 0x2598, /* ▗ ▘ */
319         0x2599, 0x259c, /* ▙ ▜ */
320         0x259f, 0x259b, /* ▟ ▛ */
321         0
322    };
323
324    for(i = 0; norotate[i]; i++)
325        if(ch == norotate[i])
326            return ch;
327
328    for(i = 0; pairs[i]; i++)
329        if(ch == pairs[i])
330            return pairs[i ^ 1];
331
332    return ch;
333}
334
Note: See TracBrowser for help on using the repository browser.