Changeset 1786 for libcaca


Ignore:
Timestamp:
Jun 28, 2007, 5:56:59 PM (13 years ago)
Author:
Sam Hocevar
Message:
  • Implemented cucul_left() and cucul_right() for 90-degree rotations.
Location:
libcaca/trunk/cucul
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/cucul/cucul.h

    r1773 r1786  
    122122int cucul_flop(cucul_canvas_t *);
    123123int cucul_rotate(cucul_canvas_t *);
     124int cucul_left(cucul_canvas_t *);
     125int cucul_right(cucul_canvas_t *);
    124126/*  @} */
    125127
  • libcaca/trunk/cucul/transform.c

    r1782 r1786  
    2121
    2222#if !defined(__KERNEL__)
     23#   include <stdlib.h>
    2324#endif
    2425
     
    2930static uint32_t flopchar(uint32_t ch);
    3031static uint32_t rotatechar(uint32_t ch);
     32static uint32_t leftchar(uint32_t ch);
     33static uint32_t rightchar(uint32_t ch);
    3134
    3235/** \brief Invert a canvas' colours.
     
    211214        }
    212215    }
     216
     217    return 0;
     218}
     219
     220/** \brief Rotate a canvas, 90 degrees counterclockwise.
     221 *
     222 *  Apply a 90-degree transformation to a canvas, choosing characters
     223 *  that look like the rotated version wherever possible. Some characters
     224 *  will stay unchanged by the process, some others will be replaced by
     225 *  close equivalents. Fullwidth characters will be lost. The operation is
     226 *  not guaranteed to be reversible at all.
     227 *
     228 *  Note that the width and height of the canvas are swapped.
     229 *
     230 *  If an error occurs, -1 is returned and \b errno is set accordingly:
     231 *  - \c EBUSY The canvas is in use by a display driver and cannot be rotated.
     232 *  - \c ENOMEM Not enough memory to allocate the new canvas size. If this
     233 *    happens, the previous canvas handle is still valid.
     234 *
     235 *  \param cv The canvas to rotate left.
     236 *  \return 0 in case of success, -1 if an error occurred.
     237 */
     238int cucul_left(cucul_canvas_t *cv)
     239{
     240    uint32_t *newchars, *newattrs;
     241    unsigned int x, y;
     242
     243    if(cv->refcount)
     244    {
     245        seterrno(EBUSY);
     246        return -1;
     247    }
     248
     249    /* Save the current frame shortcuts */
     250    _cucul_save_frame_info(cv);
     251
     252    newchars = malloc(cv->width * cv->height * sizeof(uint32_t));
     253    if(!newchars)
     254        return -1;
     255
     256    newattrs = malloc(cv->width * cv->height * sizeof(uint32_t));
     257    if(!newattrs)
     258    {
     259        free(newchars);
     260        return -1;
     261    }
     262
     263    for(y = 0; y < cv->height; y++)
     264    {
     265        for(x = 0; x < cv->width; x++)
     266        {
     267            uint32_t ch, attr;
     268
     269            ch = cv->chars[cv->width * y + x];
     270            attr = cv->attrs[cv->width * y + x];
     271
     272            /* FIXME: do something about fullwidth characters */
     273            ch = leftchar(ch);
     274
     275            newchars[cv->height * (cv->width - 1 - x) + y] = ch;
     276            newattrs[cv->height * (cv->width - 1 - x) + y] = attr;
     277        }
     278    }
     279
     280    free(cv->chars);
     281    free(cv->attrs);
     282
     283    /* Swap X and Y information */
     284    x = cv->frames[cv->frame].x;
     285    y = cv->frames[cv->frame].y;
     286    cv->frames[cv->frame].x = y;
     287    cv->frames[cv->frame].y = cv->width - 1 - x;
     288
     289    x = cv->frames[cv->frame].handlex;
     290    y = cv->frames[cv->frame].handley;
     291    cv->frames[cv->frame].handlex = y;
     292    cv->frames[cv->frame].handley = cv->width - 1 - x;
     293
     294    cv->frames[cv->frame].width = cv->height;
     295    cv->frames[cv->frame].height = cv->width;
     296
     297    cv->frames[cv->frame].chars = newchars;
     298    cv->frames[cv->frame].attrs = newattrs;
     299
     300    /* Reset the current frame shortcuts */
     301    _cucul_load_frame_info(cv);
     302
     303    return 0;
     304}
     305
     306/** \brief Rotate a canvas, 90 degrees clockwise.
     307 *
     308 *  Apply a 270-degree transformation to a canvas, choosing characters
     309 *  that look like the rotated version wherever possible. Some characters
     310 *  will stay unchanged by the process, some others will be replaced by
     311 *  close equivalents. Fullwidth characters will be lost. The operation is
     312 *  not guaranteed to be reversible at all.
     313 *
     314 *  Note that the width and height of the canvas are swapped.
     315 *
     316 *  If an error occurs, -1 is returned and \b errno is set accordingly:
     317 *  - \c EBUSY The canvas is in use by a display driver and cannot be rotated.
     318 *  - \c ENOMEM Not enough memory to allocate the new canvas size. If this
     319 *    happens, the previous canvas handle is still valid.
     320 *
     321 *  \param cv The canvas to rotate right.
     322 *  \return 0 in case of success, -1 if an error occurred.
     323 */
     324int cucul_right(cucul_canvas_t *cv)
     325{
     326    uint32_t *newchars, *newattrs;
     327    unsigned int x, y;
     328
     329    if(cv->refcount)
     330    {
     331        seterrno(EBUSY);
     332        return -1;
     333    }
     334
     335    /* Save the current frame shortcuts */
     336    _cucul_save_frame_info(cv);
     337
     338    newchars = malloc(cv->width * cv->height * sizeof(uint32_t));
     339    if(!newchars)
     340    {
     341        seterrno(ENOMEM);
     342        return -1;
     343    }
     344
     345    newattrs = malloc(cv->width * cv->height * sizeof(uint32_t));
     346    if(!newattrs)
     347    {
     348        free(newchars);
     349        seterrno(ENOMEM);
     350        return -1;
     351    }
     352
     353    for(y = 0; y < cv->height; y++)
     354    {
     355        for(x = 0; x < cv->width; x++)
     356        {
     357            uint32_t ch, attr;
     358
     359            ch = cv->chars[cv->width * y + x];
     360            attr = cv->attrs[cv->width * y + x];
     361
     362            /* FIXME: do something about fullwidth characters */
     363            ch = rightchar(ch);
     364
     365            newchars[cv->height * x + cv->height - 1 - y] = ch;
     366            newattrs[cv->height * x + cv->height - 1 - y] = attr;
     367        }
     368    }
     369
     370    free(cv->chars);
     371    free(cv->attrs);
     372
     373    /* Swap X and Y information */
     374    x = cv->frames[cv->frame].x;
     375    y = cv->frames[cv->frame].y;
     376    cv->frames[cv->frame].x = cv->height - 1 - y;
     377    cv->frames[cv->frame].y = x;
     378
     379    x = cv->frames[cv->frame].handlex;
     380    y = cv->frames[cv->frame].handley;
     381    cv->frames[cv->frame].handlex = cv->height - 1 - y;
     382    cv->frames[cv->frame].handley = x;
     383
     384    cv->frames[cv->frame].width = cv->height;
     385    cv->frames[cv->frame].height = cv->width;
     386
     387    cv->frames[cv->frame].chars = newchars;
     388    cv->frames[cv->frame].attrs = newattrs;
     389
     390    /* Reset the current frame shortcuts */
     391    _cucul_load_frame_info(cv);
    213392
    214393    return 0;
     
    497676}
    498677
     678static uint32_t const leftright2[] =
     679{
     680    /* ASCII */
     681    '/', '\\',
     682    '|', '-',
     683    '|', '_', /* This is all right because there was already a '|' before */
     684    /* ASCII-Unicode */
     685    '|', 0x203e, /* | ‾ */
     686    /* Misc Unicode */
     687    0x2571, 0x2572, /* ╱ ╲ */
     688    /* Box drawing */
     689    0x2500, 0x2502, /* ─ │ */
     690    0x2501, 0x2503, /* ━ ┃ */
     691    0x2550, 0x2551, /* ═ ║ */
     692    0, 0
     693};
     694
     695static uint32_t const leftright4[] =
     696{
     697    /* ASCII */
     698    '<', 'v', '>', '^',
     699    ',', '.', '\'', '`',
     700    /* Misc Unicode */
     701    0x256d, 0x2570, 0x256f, 0x256e, /* ╭ ╰ ╯ ╮ */
     702    /* CP437 */
     703    0x258c, 0x2584, 0x2590, 0x2580, /* ▌ ▄ ▐ ▀ */
     704    0x2596, 0x2597, 0x259d, 0x2598, /* ▖ ▗ ▝ ▘ */
     705    0x2599, 0x259f, 0x259c, 0x259b, /* ▙ ▟ ▜ ▛ */
     706    /* Box drawing */
     707    0x250c, 0x2514, 0x2518, 0x2510, /* ┌ └ ┘ ┐ */
     708    0x250f, 0x2517, 0x251b, 0x2513, /* ┏ ┗ ┛ ┓ */
     709    0x251c, 0x2534, 0x2524, 0x252c, /* ├ ┴ ┤ ┬ */
     710    0x2523, 0x253b, 0x252b, 0x2533, /* ┣ ┻ ┫ ┳ */
     711    0x2552, 0x2559, 0x255b, 0x2556, /* ╒ ╙ ╛ ╖ */
     712    0x2553, 0x2558, 0x255c, 0x2555, /* ╓ ╘ ╜ ╕ */
     713    0x2554, 0x255a, 0x255d, 0x2557, /* ╔ ╚ ╝ ╗ */
     714    0x255e, 0x2568, 0x2561, 0x2565, /* ╞ ╨ ╡ ╥ */
     715    0x255f, 0x2567, 0x2562, 0x2564, /* ╟ ╧ ╢ ╤ */
     716    0x2560, 0x2569, 0x2563, 0x2566, /* ╠ ╩ ╣ ╦ */
     717    0x2574, 0x2577, 0x2576, 0x2575, /* ╴ ╷ ╶ ╵ */
     718    0x2578, 0x257b, 0x257a, 0x2579, /* ╸ ╻ ╺ ╹ */
     719    0, 0, 0, 0
     720};
     721
     722static uint32_t leftchar(uint32_t ch)
     723{
     724    int i;
     725
     726    for(i = 0; leftright2[i]; i++)
     727        if(ch == leftright2[i])
     728            return leftright2[(i & ~1) | ((i + 1) & 1)];
     729
     730    for(i = 0; leftright4[i]; i++)
     731        if(ch == leftright4[i])
     732            return leftright4[(i & ~3) | ((i + 1) & 3)];
     733
     734    return ch;
     735}
     736
     737static uint32_t rightchar(uint32_t ch)
     738{
     739    int i;
     740
     741    for(i = 0; leftright2[i]; i++)
     742        if(ch == leftright2[i])
     743            return leftright2[(i & ~1) | ((i - 1) & 1)];
     744
     745    for(i = 0; leftright4[i]; i++)
     746        if(ch == leftright4[i])
     747            return leftright4[(i & ~3) | ((i - 1) & 3)];
     748
     749    return ch;
     750}
     751
Note: See TracChangeset for help on using the changeset viewer.