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

Last change on this file since 1148 was 1011, checked in by Sam Hocevar, 14 years ago
  • U+214B TURNED AMPERSAND
  • Property svn:keywords set to Id
File size: 11.0 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 1011 2006-08-30 21:30:29Z 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#include "common.h"
20
21#if !defined(__KERNEL__)
22#endif
23
24#include "cucul.h"
25#include "cucul_internals.h"
26
27static uint32_t flipchar(uint32_t ch);
28static uint32_t flopchar(uint32_t ch);
29static uint32_t rotatechar(uint32_t ch);
30
31/** \brief Invert a canvas' colours.
32 *
33 *  This function inverts a canvas' colours (black becomes white, red
34 *  becomes cyan, etc.) without changing the characters in it.
35 *
36 *  This function never fails.
37 *
38 *  \param cv The canvas to invert.
39 *  \return This function always returns 0.
40 */
41int cucul_invert(cucul_canvas_t *cv)
42{
43    uint32_t *attr = cv->attr;
44    unsigned int i;
45
46    for(i = cv->height * cv->width; i--; )
47    {
48        *attr = *attr ^ 0x000f000f;
49        attr++;
50    }
51
52    return 0;
53}
54
55/** \brief Flip a canvas horizontally.
56 *
57 *  This function flips a canvas horizontally, choosing characters that
58 *  look like the mirrored version wherever possible.
59 *
60 *  This function never fails.
61 *
62 *  \param cv The canvas to flip.
63 *  \return This function always returns 0.
64 */
65int cucul_flip(cucul_canvas_t *cv)
66{
67    unsigned int y;
68
69    for(y = 0; y < cv->height; y++)
70    {
71        uint32_t *cleft = cv->chars + y * cv->width;
72        uint32_t *cright = cleft + cv->width - 1;
73        uint32_t *aleft = cv->attr + y * cv->width;
74        uint32_t *aright = aleft + cv->width - 1;
75
76        while(cleft < cright)
77        {
78            uint32_t ch;
79            uint32_t attr;
80
81            /* Swap attributes */
82            attr = *aright; *aright = *aleft; *aleft = attr;
83
84            /* Swap characters */
85            ch = *cright; *cright = flipchar(*cleft); *cleft = flipchar(ch);
86
87            cleft++; cright--; aleft++; aright--;
88        }
89
90        if(cleft == cright)
91            *cleft = flipchar(*cleft);
92    }
93
94    return 0;
95}
96
97/** \brief Flip a canvas vertically.
98 *
99 *  This function flips a canvas vertically, choosing characters that
100 *  look like the mirrored version wherever possible.
101 *
102 *  This function never fails.
103 *
104 *  \param cv The canvas to flop.
105 *  \return This function always returns 0.
106 */
107int cucul_flop(cucul_canvas_t *cv)
108{
109    unsigned int x;
110
111    for(x = 0; x < cv->width; x++)
112    {
113        uint32_t *ctop = cv->chars + x;
114        uint32_t *cbottom = ctop + cv->width * (cv->height - 1);
115        uint32_t *atop = cv->attr + x;
116        uint32_t *abottom = atop + cv->width * (cv->height - 1);
117
118        while(ctop < cbottom)
119        {
120            uint32_t ch;
121            uint32_t attr;
122
123            /* Swap attributes */
124            attr = *abottom; *abottom = *atop; *atop = attr;
125
126            /* Swap characters */
127            ch = *cbottom; *cbottom = flopchar(*ctop); *ctop = flopchar(ch);
128
129            ctop += cv->width; cbottom -= cv->width;
130            atop += cv->width; abottom -= cv->width;
131        }
132
133        if(ctop == cbottom)
134            *ctop = flopchar(*ctop);
135    }
136
137    return 0;
138}
139
140/** \brief Rotate a canvas.
141 *
142 *  This function applies a 180 degrees transformation to a canvas,
143 *  choosing characters that look like the mirrored version wherever
144 *  possible.
145 *
146 *  This function never fails.
147 *
148 *  \param cv The canvas to rotate.
149 *  \return This function always returns 0.
150 */
151int cucul_rotate(cucul_canvas_t *cv)
152{
153    uint32_t *cbegin = cv->chars;
154    uint32_t *cend = cbegin + cv->width * cv->height - 1;
155    uint32_t *abegin = cv->attr;
156    uint32_t *aend = abegin + cv->width * cv->height - 1;
157
158    while(cbegin < cend)
159    {
160        uint32_t ch;
161        uint32_t attr;
162
163        /* Swap attributes */
164        attr = *aend; *aend = *abegin; *abegin = attr;
165
166        /* Swap characters */
167        ch = *cend; *cend = rotatechar(*cbegin); *cbegin = rotatechar(ch);
168
169        cbegin++; cend--; abegin++; aend--;
170    }
171
172    if(cbegin == cend)
173        *cbegin = rotatechar(*cbegin);
174
175    return 0;
176}
177
178static uint32_t flipchar(uint32_t ch)
179{
180    int i;
181
182    static uint32_t const noflip[] =
183    {
184         /* ASCII */
185         (uint32_t)' ', (uint32_t)'"', (uint32_t)'#', (uint32_t)'\'',
186         (uint32_t)'-', (uint32_t)'.', (uint32_t)'*', (uint32_t)'+',
187         (uint32_t)':', (uint32_t)'=',
188         (uint32_t)'0', (uint32_t)'8', (uint32_t)'A', (uint32_t)'H',
189         (uint32_t)'I', (uint32_t)'M', (uint32_t)'O', (uint32_t)'T',
190         (uint32_t)'U', (uint32_t)'V', (uint32_t)'W', (uint32_t)'X',
191         (uint32_t)'Y', (uint32_t)'^', (uint32_t)'_', (uint32_t)'i',
192         (uint32_t)'o', (uint32_t)'v', (uint32_t)'w', (uint32_t)'x',
193         (uint32_t)'|',
194         /* CP437 */
195         0x2591, 0x2592, 0x2593, 0x2588, 0x2584, 0x2580, /* ░ ▒ ▓ █ ▄ ▀ */
196         0
197    };
198
199    static uint32_t const pairs[] =
200    {
201         /* ASCII */
202         (uint32_t)'(', (uint32_t)')',
203         (uint32_t)'/', (uint32_t)'\\',
204         (uint32_t)'<', (uint32_t)'>',
205         (uint32_t)'[', (uint32_t)']',
206         (uint32_t)'b', (uint32_t)'d',
207         (uint32_t)'p', (uint32_t)'q',
208         (uint32_t)'{', (uint32_t)'}',
209         /* ASCII-Unicode */
210         (uint32_t)';', 0x204f, /* ; ⁏ */
211         (uint32_t)'`', 0x00b4, /* ` ´ */
212         (uint32_t)',', 0x02ce, /* , ˎ */
213         (uint32_t)'C', 0x03fd, /* C Ͻ */
214         (uint32_t)'E', 0x018e, /* E Ǝ */
215         (uint32_t)'N', 0x0418, /* N И */
216         (uint32_t)'R', 0x042f, /* R Я */
217         (uint32_t)'S', 0x01a7, /* S Ƨ */
218         (uint32_t)'c', 0x0254, /* c ɔ */
219         (uint32_t)'e', 0x0258, /* e ɘ */
220         /* CP437 */
221         0x258c, 0x2590, /* ▌ ▐ */
222         0x2596, 0x2597, /* ▖ ▗ */
223         0x2598, 0x259d, /* ▘ ▝ */
224         0x2599, 0x259f, /* ▙ ▟ */
225         0x259a, 0x259e, /* ▚ ▞ */
226         0x259b, 0x259c, /* ▛ ▜ */
227         0x25ba, 0x25c4, /* ► ◄ */
228         0x2192, 0x2190, /* → ← */
229         0x2310, 0xac,   /* ⌐ ¬ */
230         0
231    };
232
233    for(i = 0; noflip[i]; i++)
234        if(ch == noflip[i])
235            return ch;
236
237    for(i = 0; pairs[i]; i++)
238        if(ch == pairs[i])
239            return pairs[i ^ 1];
240
241    return ch;
242}
243
244static uint32_t flopchar(uint32_t ch)
245{
246    int i;
247
248    static uint32_t const noflop[] =
249    {
250         /* ASCII */
251         (uint32_t)' ', (uint32_t)'(', (uint32_t)')', (uint32_t)'*',
252         (uint32_t)'+', (uint32_t)'-',
253         (uint32_t)'0', (uint32_t)'3', (uint32_t)'8', (uint32_t)':',
254         (uint32_t)'<', (uint32_t)'=', (uint32_t)'>', (uint32_t)'B',
255         (uint32_t)'C', (uint32_t)'D', (uint32_t)'E', (uint32_t)'H',
256         (uint32_t)'I', (uint32_t)'K', (uint32_t)'O', (uint32_t)'X',
257         (uint32_t)'[', (uint32_t)']', (uint32_t)'c', (uint32_t)'o',
258         (uint32_t)'{', (uint32_t)'|', (uint32_t)'}',
259         /* CP437 */
260         0x2591, 0x2592, 0x2593, 0x2588, 0x258c, 0x2590, /* ░ ▒ ▓ █ ▌ ▐ */
261         0
262    };
263
264    static uint32_t const pairs[] =
265    {
266         /* ASCII */
267         (uint32_t)'/', (uint32_t)'\\',
268         (uint32_t)'M', (uint32_t)'W',
269         (uint32_t)',', (uint32_t)'`',
270         (uint32_t)'b', (uint32_t)'p',
271         (uint32_t)'d', (uint32_t)'q',
272         (uint32_t)'p', (uint32_t)'q',
273         (uint32_t)'f', (uint32_t)'t',
274         (uint32_t)'.', (uint32_t)'\'',
275         /* ASCII-Unicode */
276         (uint32_t)'_', 0x203e, /* _ ‾ */
277         (uint32_t)'!', 0x00a1, /* ! ¡ */
278         (uint32_t)'L', 0x0413, /* L Г */
279         (uint32_t)'N', 0x0418, /* N И */
280         (uint32_t)'P', 0x042c, /* P Ь */
281         (uint32_t)'R', 0x0281, /* R ʁ */
282         (uint32_t)'S', 0x01a7, /* S Ƨ */
283         (uint32_t)'U', 0x0548, /* U Ո */
284         (uint32_t)'V', 0x039b, /* V Λ */
285         (uint32_t)'h', 0x03bc, /* h μ */
286         (uint32_t)'i', 0x1d09, /* i ᴉ */
287         (uint32_t)'v', 0x028c, /* v ʌ */
288         (uint32_t)'w', 0x028d, /* w ʍ */
289         (uint32_t)'y', 0x03bb, /* y λ */
290         /* Not perfect, but better than nothing */
291         (uint32_t)'m', 0x026f, /* m ɯ */
292         (uint32_t)'n', (uint32_t)'u',
293         /* CP437 */
294         0x2584, 0x2580, /* ▄ ▀ */
295         0x2596, 0x2598, /* ▖ ▘ */
296         0x2597, 0x259d, /* ▗ ▝ */
297         0x2599, 0x259b, /* ▙ ▛ */
298         0x259f, 0x259c, /* ▟ ▜ */
299         0x259a, 0x259e, /* ▚ ▞ */
300         0
301    };
302
303    for(i = 0; noflop[i]; i++)
304        if(ch == noflop[i])
305            return ch;
306
307    for(i = 0; pairs[i]; i++)
308        if(ch == pairs[i])
309            return pairs[i ^ 1];
310
311    return ch;
312}
313
314static uint32_t rotatechar(uint32_t ch)
315{
316    int i;
317
318    static uint32_t const norotate[] =
319    {
320         /* ASCII - FIXME: a lot are missing */
321         (uint32_t)' ', (uint32_t)'*', (uint32_t)'+', (uint32_t)'-',
322         (uint32_t)'0', (uint32_t)'8', (uint32_t)':', (uint32_t)'=',
323         /* Unicode */
324         0x2591, 0x2592, 0x2593, 0x2588, 0x259a, 0x259e, /* ░ ▒ ▓ █ ▚ ▞ */
325         0
326    };
327
328    static uint32_t const pairs[] =
329    {
330         /* ASCII */
331         (uint32_t)'(', (uint32_t)')',
332         (uint32_t)'<', (uint32_t)'>',
333         (uint32_t)'[', (uint32_t)']',
334         (uint32_t)'{', (uint32_t)'}',
335         (uint32_t)'.', (uint32_t)'\'',
336         (uint32_t)'6', (uint32_t)'9',
337         (uint32_t)'M', (uint32_t)'W',
338         (uint32_t)'b', (uint32_t)'q',
339         (uint32_t)'d', (uint32_t)'p',
340         (uint32_t)'n', (uint32_t)'u',
341         /* ASCII-Unicode */
342         (uint32_t)'_', 0x203e, /* _ ‾ */
343         (uint32_t)',', 0x00b4, /* , ´ */
344         (uint32_t)'`', 0x02ce, /* ` ˎ */
345         (uint32_t)'&', 0x214b, /* & ⅋ */
346         (uint32_t)'!', 0x00a1, /* ! ¡ */
347         (uint32_t)'?', 0x00bf, /* ? ¿ */
348         (uint32_t)'C', 0x03fd, /* C Ͻ */
349         (uint32_t)'E', 0x018e, /* E Ǝ */
350         (uint32_t)'F', 0x2132, /* F Ⅎ */
351         (uint32_t)'U', 0x0548, /* U Ո */
352         (uint32_t)'V', 0x039b, /* V Λ */
353         (uint32_t)'a', 0x0250, /* a ɐ */
354         (uint32_t)'c', 0x0254, /* c ɔ */
355         (uint32_t)'e', 0x0259, /* e ə */
356         (uint32_t)'f', 0x025f, /* f ɟ */
357         (uint32_t)'g', 0x1d77, /* g ᵷ */
358         (uint32_t)'h', 0x0265, /* h ɥ */
359         (uint32_t)'i', 0x1d09, /* i ᴉ */
360         (uint32_t)'k', 0x029e, /* k ʞ */
361         (uint32_t)'m', 0x026f, /* m ɯ */
362         (uint32_t)'r', 0x0279, /* r ɹ */
363         (uint32_t)'t', 0x0287, /* t ʇ */
364         (uint32_t)'v', 0x028c, /* v ʌ */
365         (uint32_t)'w', 0x028d, /* w ʍ */
366         (uint32_t)'y', 0x028e, /* y ʎ */
367         /* CP437 */
368         0x258c, 0x2590, /* ▌ ▐ */
369         0x2584, 0x2580, /* ▄ ▀ */
370         0x2596, 0x259d, /* ▖ ▝ */
371         0x2597, 0x2598, /* ▗ ▘ */
372         0x2599, 0x259c, /* ▙ ▜ */
373         0x259f, 0x259b, /* ▟ ▛ */
374         0
375    };
376
377    for(i = 0; norotate[i]; i++)
378        if(ch == norotate[i])
379            return ch;
380
381    for(i = 0; pairs[i]; i++)
382        if(ch == pairs[i])
383            return pairs[i ^ 1];
384
385    return ch;
386}
387
Note: See TracBrowser for help on using the repository browser.