Changeset 842


Ignore:
Timestamp:
Apr 22, 2006, 9:11:25 PM (15 years ago)
Author:
Sam Hocevar
Message:
  • Support for multiple frames in canvases.
Location:
libcaca/trunk/cucul
Files:
4 edited

Legend:

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

    r834 r842  
    5454    cv->chars = NULL;
    5555    cv->attr = NULL;
     56
     57    cv->frame = 0;
     58    cv->framecount = 1;
     59    cv->allchars = malloc(sizeof(uint32_t *));
     60    cv->allattr = malloc(sizeof(uint32_t *));
     61    cv->allchars[0] = NULL;
     62    cv->allattr[0] = NULL;
    5663
    5764    /* Initialise to a default size. 80x32 is arbitrary but matches AAlib's
     
    170177void cucul_free_canvas(cucul_canvas_t *cv)
    171178{
     179    unsigned int f;
     180
    172181    _cucul_end_dither();
    173182
    174     free(cv->chars);
    175     free(cv->attr);
     183    for(f = 0; f < cv->framecount; f++)
     184    {
     185        free(cv->allchars[f]);
     186        free(cv->allattr[f]);
     187    }
    176188
    177189    free(cv);
     
    197209                                                unsigned int height)
    198210{
    199     unsigned int x, y, old_width, old_height, new_size, old_size;
     211    unsigned int x, y, f, old_width, old_height, new_size, old_size;
    200212
    201213    old_width = cv->width;
     
    210222    if(new_size > old_size)
    211223    {
    212         cv->chars = realloc(cv->chars, new_size * sizeof(uint32_t));
    213         cv->attr = realloc(cv->attr, new_size * sizeof(uint32_t));
     224        for(f = 0; f < cv->framecount; f++)
     225        {
     226            cv->allchars[f] = realloc(cv->allchars[f],
     227                                      new_size * sizeof(uint32_t));
     228            cv->allattr[f] = realloc(cv->allattr[f],
     229                                     new_size * sizeof(uint32_t));
     230        }
    214231    }
    215232
     
    225242         * copy lines starting from the bottom of the screen otherwise
    226243         * we will overwrite information. */
    227         for(y = height < old_height ? height : old_height; y--; )
    228         {
    229             for(x = old_width; x--; )
     244        for(f = 0; f < cv->framecount; f++)
     245        {
     246            uint32_t *chars = cv->allchars[f];
     247            uint32_t *attr = cv->allattr[f];
     248
     249            for(y = height < old_height ? height : old_height; y--; )
    230250            {
    231                 cv->chars[y * width + x] = cv->chars[y * old_width + x];
    232                 cv->attr[y * width + x] = cv->attr[y * old_width + x];
     251                for(x = old_width; x--; )
     252                {
     253                    chars[y * width + x] = chars[y * old_width + x];
     254                    attr[y * width + x] = attr[y * old_width + x];
     255                }
     256
     257                /* Zero the end of the line */
     258                for(x = width - old_width; x--; )
     259                    chars[y * width + old_width + x] = (uint32_t)' ';
     260                memset(attr + y * width + old_width, 0,
     261                       (width - old_width) * 4);
    233262            }
    234 
    235             /* Zero the end of the line */
    236             for(x = width - old_width; x--; )
    237                 cv->chars[y * width + old_width + x] = (uint32_t)' ';
    238             memset(cv->attr + y * width + old_width, 0,
    239                    (width - old_width) * 4);
    240263        }
    241264    }
     
    246269        unsigned int lines = height < old_height ? height : old_height;
    247270
    248         for(y = 1; y < lines; y++)
    249         {
    250             for(x = 0; x < width; x++)
     271        for(f = 0; f < cv->framecount; f++)
     272        {
     273            uint32_t *chars = cv->allchars[f];
     274            uint32_t *attr = cv->allattr[f];
     275
     276            for(y = 1; y < lines; y++)
    251277            {
    252                 cv->chars[y * width + x] = cv->chars[y * old_width + x];
    253                 cv->attr[y * width + x] = cv->attr[y * old_width + x];
     278                for(x = 0; x < width; x++)
     279                {
     280                    chars[y * width + x] = chars[y * old_width + x];
     281                    attr[y * width + x] = attr[y * old_width + x];
     282                }
    254283            }
    255284        }
     
    259288    if(height > old_height)
    260289    {
    261         /* Zero the bottom of the screen */
    262         for(x = (height - old_height) * width; x--; )
    263             cv->chars[old_height * width + x] = (uint32_t)' ';
    264         memset(cv->attr + old_height * width, 0,
    265                (height - old_height) * width * 4);
     290        for(f = 0; f < cv->framecount; f++)
     291        {
     292            uint32_t *chars = cv->allchars[f];
     293            uint32_t *attr = cv->allattr[f];
     294
     295            /* Zero the bottom of the screen */
     296            for(x = (height - old_height) * width; x--; )
     297                chars[old_height * width + x] = (uint32_t)' ';
     298            memset(attr + old_height * width, 0,
     299                   (height - old_height) * width * 4);
     300        }
    266301    }
    267302
     
    269304    if(new_size <= old_size)
    270305    {
    271         cv->chars = realloc(cv->chars, new_size * sizeof(uint32_t));
    272         cv->attr = realloc(cv->attr, new_size * sizeof(uint32_t));
    273     }
    274 }
    275 
     306        for(f = 0; f < cv->framecount; f++)
     307        {
     308            cv->allchars[f] = realloc(cv->allchars[f],
     309                                      new_size * sizeof(uint32_t));
     310            cv->allattr[f] = realloc(cv->allattr[f],
     311                                     new_size * sizeof(uint32_t));
     312        }
     313    }
     314
     315    /* Reset the current frame shortcut */
     316    cv->chars = cv->allchars[cv->frame];
     317    cv->attr = cv->allattr[cv->frame];
     318}
     319
  • libcaca/trunk/cucul/cucul.h

    r832 r842  
    3434/** \e libcucul context */
    3535typedef struct cucul_canvas cucul_canvas_t;
    36 /** sprite structure */
    37 typedef struct cucul_sprite cucul_sprite_t;
    3836/** dither structure */
    3937typedef struct cucul_dither cucul_dither_t;
     
    144142/*  @} */
    145143
    146 /** \defgroup sprite libcucul sprite handling
    147  *
    148  *  These functions provide high level routines for sprite loading, animation
    149  *  and rendering.
    150  *
    151  *  @{ */
    152 cucul_sprite_t * cucul_load_sprite(char const *);
    153 int cucul_get_sprite_frames(cucul_sprite_t const *);
    154 int cucul_get_sprite_width(cucul_sprite_t const *, int);
    155 int cucul_get_sprite_height(cucul_sprite_t const *, int);
    156 int cucul_get_sprite_dx(cucul_sprite_t const *, int);
    157 int cucul_get_sprite_dy(cucul_sprite_t const *, int);
    158 void cucul_draw_sprite(cucul_canvas_t *, int, int, cucul_sprite_t const *, int);
    159 void cucul_free_sprite(cucul_sprite_t *);
     144/** \defgroup frame libcucul canvas frame handling
     145 *
     146 *  These functions provide high level routines for canvas frame insertion,
     147 *  removal, copying etc.
     148 *
     149 *  @{ */
     150unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *);
     151void cucul_set_canvas_frame(cucul_canvas_t *, unsigned int);
     152void cucul_create_canvas_frame(cucul_canvas_t *, unsigned int);
     153void cucul_free_canvas_frame(cucul_canvas_t *, unsigned int);
    160154/*  @} */
    161155
     
    167161 *  @{ */
    168162cucul_dither_t *cucul_create_dither(unsigned int, unsigned int,
    169                                          unsigned int, unsigned int,
    170                                          unsigned int, unsigned int,
    171                                          unsigned int, unsigned int);
     163                                    unsigned int, unsigned int,
     164                                    unsigned int, unsigned int,
     165                                    unsigned int, unsigned int);
    172166void cucul_set_dither_palette(cucul_dither_t *,
    173167                              unsigned int r[], unsigned int g[],
  • libcaca/trunk/cucul/cucul_internals.h

    r834 r842  
    2828struct cucul_canvas
    2929{
    30     /* Context size */
     30    /* Canvas size */
    3131    unsigned int width, height;
    3232
     33    /* Shortcut to the active frame */
    3334    uint32_t *chars;
    3435    uint32_t *attr;
    3536
     37    /* Frame information */
     38    unsigned int frame, framecount;
     39    uint32_t **allchars;
     40    uint32_t **allattr;
     41
     42    /* Painting context */
    3643    uint16_t fgcolor;
    3744    uint16_t bgcolor;
  • libcaca/trunk/cucul/sprite.c

    r811 r842  
    1313
    1414/*
    15  *  This file contains a small framework for sprite loading and blitting.
     15 *  This file contains a small framework for canvas frame management.
    1616 */
    1717
     
    2727#include "cucul_internals.h"
    2828
    29 #if !defined(_DOXYGEN_SKIP_ME)
    30 struct cucul_frame
     29/** \brief Get the number of frames in a canvas.
     30 *
     31 *  This function returns the current canvas frame count.
     32 *
     33 *  \param cv A libcucul canvas
     34 *  \return The frame count
     35 */
     36unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *cv)
    3137{
    32     int w, h;
    33     int dx, dy;
    34     char *chars;
    35     int *color;
    36 };
     38    return cv->framecount;
     39}
    3740
    38 struct cucul_sprite
     41/** \brief Activate a given canvas frame.
     42 *
     43 *  This function sets the active canvas frame. All subsequent drawing
     44 *  operations will be performed on that frame. The current painting
     45 *  context set by cucul_set_color() or cucul_set_truecolor() is inherited.
     46 *
     47 *  If the frame index is outside the canvas' frame range, nothing happens.
     48 *
     49 *  \param cv A libcucul canvas
     50 *  \param frame The canvas frame to activate
     51 */
     52void cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
    3953{
    40     int nf;
    41     struct cucul_frame *frames;
    42 };
    43 #endif
     54    if(frame >= cv->framecount)
     55        return;
    4456
    45 /** \brief Allocate a sprite loaded from a file.
     57    cv->frame = frame;
     58
     59    cv->chars = cv->allchars[cv->frame];
     60    cv->attr = cv->allattr[cv->frame];
     61}
     62
     63/** \brief Add a frame to a canvas.
    4664 *
    47  *  \param file The filename.
    48  *  \return The sprite, or NULL if an error occured.
     65 *  This function creates a new frame within the given canvas. Its contents
     66 *  are copied from the currently active frame.
     67 *
     68 *  The frame index indicates where the frame should be inserted. Valid
     69 *  values range from 0 to the current canvas frame count. If the frame
     70 *  index is greater the or equals the current canvas frame count, the new
     71 *  frame is appended at the end of the canvas.
     72 *
     73 *  The active frame does not change, but its index may be renumbered due
     74 *  to the insertion.
     75 *
     76 *  \param cv A libcucul canvas
     77 *  \param frame The index where to insert the new frame
    4978 */
    50 cucul_sprite_t *cucul_load_sprite(char const *file)
     79void cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
    5180{
    52     char buf[BUFSIZ];
    53     cucul_sprite_t *sprite;
    54     FILE *fd;
     81    unsigned int size = cv->width * cv->height * sizeof(uint32_t);
     82    unsigned int f;
    5583
    56     fd = fopen(file, "r");
    57     if(fd == NULL)
    58         return NULL;
     84    if(frame > cv->framecount)
     85        frame = cv->framecount;
    5986
    60     sprite = malloc(sizeof(cucul_sprite_t));
    61     if(sprite == NULL)
    62         goto sprite_alloc_failed;
     87    cv->framecount++;
     88    cv->allchars = realloc(cv->allchars, sizeof(uint32_t *) * cv->framecount);
     89    cv->allattr = realloc(cv->allattr, sizeof(uint32_t *) * cv->framecount);
    6390
    64     sprite->nf = 0;
    65     sprite->frames = NULL;
    66 
    67     while(!feof(fd))
     91    for(f = cv->framecount - 1; f > frame; f--)
    6892    {
    69         int x, y;
    70         int w = 0, h = 0, dx = 0, dy = 0;
    71         struct cucul_frame *frame;
    72 
    73         /* Get width and height */
    74         if(!fgets(buf, BUFSIZ, fd))
    75             break;
    76 
    77         sscanf(buf, "%i %i %i %i", &w, &h, &dx, &dy);
    78         if(w <= 0 || h <= 0 || w > BUFSIZ / 2)
    79             break;
    80 
    81         if(sprite->nf)
    82         {
    83             void *tmp = realloc(sprite->frames,
    84                                 (sprite->nf + 1) * sizeof(struct cucul_frame));
    85             if(tmp == NULL)
    86                 goto frame_failed;
    87             sprite->frames = tmp;
    88             sprite->nf++;
    89         }
    90         else
    91         {
    92             sprite->frames = malloc((sprite->nf + 1) * sizeof(struct cucul_frame));
    93             if(sprite->frames == NULL)
    94                 goto sprite_failed;
    95             sprite->nf++;
    96         }
    97 
    98         frame = &sprite->frames[sprite->nf - 1];
    99 
    100         frame->w = w;
    101         frame->h = h;
    102         frame->dx = dx;
    103         frame->dy = dy;
    104         frame->chars = malloc(w * h * sizeof(char));
    105         if(frame->chars == NULL)
    106         {
    107             sprite->nf--;
    108             goto frame_failed;
    109         }
    110         frame->color = malloc(w * h * sizeof(int));
    111         if(frame->color == NULL)
    112         {
    113             free(frame->chars);
    114             sprite->nf--;
    115             goto frame_failed;
    116         }
    117 
    118         for(y = 0; y < h; y++)
    119         {
    120             if(!fgets(buf, BUFSIZ, fd))
    121                 goto frame_failed;
    122 
    123             for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
    124                 frame->chars[w * y + x] = buf[x];
    125 
    126             for(; x < w; x++)
    127                 frame->chars[w * y + x] = ' ';
    128         }
    129 
    130         for(y = 0; y < h; y++)
    131         {
    132             if(!fgets(buf, BUFSIZ, fd))
    133                 goto frame_failed;
    134 
    135             for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
    136                 frame->color[w * y + x] = buf[x] - 'a';
    137 
    138             for(; x < w; x++)
    139                 frame->color[w * y + x] = ' ' - 'a';
    140         }
    141 
    142         continue;
     93        cv->allchars[f] = cv->allchars[f - 1];
     94        cv->allattr[f] = cv->allattr[f - 1];
    14395    }
    14496
    145     if(sprite->nf == 0)
    146         goto sprite_failed;
     97    cv->allchars[frame] = malloc(size);
     98    memcpy(cv->allchars[frame], cv->chars, size);
     99    cv->allattr[frame] = malloc(size);
     100    memcpy(cv->allattr[frame], cv->attr, size);
    147101
    148     fclose(fd);
    149     return sprite;
     102    if(cv->frame >= frame)
     103        cv->frame++;
    150104
    151 frame_failed:
    152     while(sprite->nf)
    153     {
    154         free(sprite->frames[sprite->nf - 1].color);
    155         free(sprite->frames[sprite->nf - 1].chars);
    156         sprite->nf--;
    157     }
    158 sprite_failed:
    159     free(sprite);
    160 sprite_alloc_failed:
    161     fclose(fd);
    162     return NULL;
     105    cv->chars = cv->allchars[cv->frame];
     106    cv->attr = cv->allattr[cv->frame];
    163107}
    164108
    165 /** \brief Return the number of frames in a sprite.
     109/** \brief Remove a frame from a canvas.
    166110 *
    167  *  \param sprite The sprite.
    168  *  \return The number of frames.
     111 *  This function deletes a frame from a given canvas.
     112 *
     113 *  It is not legal to remove the last frame from a canvas. Such a request
     114 *  will be ignored by cucul_free_canvas_frame().
     115 *
     116 *  The frame index indicates the frame to delete. Valid values range from
     117 *  0 to the current canvas frame count minus 1. If the frame index is
     118 *  greater the or equals the current canvas frame count, the last frame
     119 *  is deleted.
     120 *
     121 *  If the active frame is deleted, frame 0 becomes the new active frame.
     122 *  Otherwise, the active frame does not change, but its index may be
     123 *  renumbered due to the deletion.
     124 *
     125 *  \param cv A libcucul canvas
     126 *  \param frame The index of the frame to delete
    169127 */
    170 int cucul_get_sprite_frames(cucul_sprite_t const *sprite)
     128void cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
    171129{
    172     if(sprite == NULL)
    173         return 0;
     130    unsigned int f;
    174131
    175     return sprite->nf;
     132    if(frame >= cv->framecount)
     133        return;
     134
     135    if(cv->framecount == 1)
     136        return;
     137
     138    free(cv->allchars[frame]);
     139    free(cv->allattr[frame]);
     140
     141    for(f = frame + 1; f < cv->framecount; f++)
     142    {
     143        cv->allchars[f - 1] = cv->allchars[f];
     144        cv->allattr[f - 1] = cv->allattr[f];
     145    }
     146
     147    cv->framecount--;
     148    cv->allchars = realloc(cv->allchars, sizeof(uint32_t *) * cv->framecount);
     149    cv->allattr = realloc(cv->allattr, sizeof(uint32_t *) * cv->framecount);
     150
     151    if(cv->frame > frame)
     152        cv->frame--;
     153    else if(cv->frame == frame)
     154        cv->frame = 0;
     155
     156    cv->chars = cv->allchars[cv->frame];
     157    cv->attr = cv->allattr[cv->frame];
    176158}
    177159
    178 /** \brief Return the width of a sprite.
    179  *
    180  *  \param sprite The sprite.
    181  *  \param f The frame index.
    182  *  \return The width of the given frame of the sprite.
    183  */
    184 int cucul_get_sprite_width(cucul_sprite_t const *sprite, int f)
    185 {
    186     if(sprite == NULL)
    187         return 0;
    188 
    189     if(f < 0 || f >= sprite->nf)
    190         return 0;
    191 
    192     return sprite->frames[f].w;
    193 }
    194 
    195 /** \brief Return the height of a sprite.
    196  *
    197  *  \param sprite The sprite.
    198  *  \param f The frame index.
    199  *  \return The height of the given frame of the sprite.
    200  */
    201 int cucul_get_sprite_height(cucul_sprite_t const *sprite, int f)
    202 {
    203     if(sprite == NULL)
    204         return 0;
    205 
    206     if(f < 0 || f >= sprite->nf)
    207         return 0;
    208 
    209     return sprite->frames[f].h;
    210 }
    211 
    212 /** \brief Return the X coordinate of a sprite's handle.
    213  *
    214  *  \param sprite The sprite.
    215  *  \param f The frame index.
    216  *  \return The X coordinate of the given frame's handle.
    217  */
    218 int cucul_get_sprite_dx(cucul_sprite_t const *sprite, int f)
    219 {
    220     if(sprite == NULL)
    221         return 0;
    222 
    223     if(f < 0 || f >= sprite->nf)
    224         return 0;
    225 
    226     return sprite->frames[f].dx;
    227 }
    228 
    229 /** \brief Return the Y coordinate of a sprite's handle.
    230  *
    231  *  \param sprite The sprite.
    232  *  \param f The frame index.
    233  *  \return The Y coordinate of the given frame's handle.
    234  */
    235 int cucul_get_sprite_dy(cucul_sprite_t const *sprite, int f)
    236 {
    237     if(sprite == NULL)
    238         return 0;
    239 
    240     if(f < 0 || f >= sprite->nf)
    241         return 0;
    242 
    243     return sprite->frames[f].dy;
    244 }
    245 
    246 /** \brief Draw a sprite's specific frame at the given coordinates. If the
    247  *         frame does not exist, nothing is displayed.
    248  *
    249  *  \param cv A libcucul canvas
    250  *  \param x The X coordinate.
    251  *  \param y The Y coordinate.
    252  *  \param sprite The sprite.
    253  *  \param f The frame index.
    254  *  \return void
    255  */
    256 void cucul_draw_sprite(cucul_canvas_t *cv, int x, int y,
    257                        cucul_sprite_t const *sprite, int f)
    258 {
    259     int i, j;
    260     unsigned int oldfg, oldbg;
    261     struct cucul_frame *frame;
    262 
    263     if(sprite == NULL)
    264         return;
    265 
    266     if(f < 0 || f >= sprite->nf)
    267         return;
    268 
    269     frame = &sprite->frames[f];
    270 
    271     oldfg = cv->fgcolor;
    272     oldbg = cv->bgcolor;
    273 
    274     for(j = 0; j < frame->h; j++)
    275     {
    276         for(i = 0; i < frame->w; i++)
    277         {
    278             int col = frame->color[frame->w * j + i];
    279             if(col >= 0)
    280             {
    281                 cucul_set_color(cv, col, CUCUL_COLOR_BLACK);
    282                 cucul_putchar(cv, x + i - frame->dx, y + j - frame->dy,
    283                               frame->chars[frame->w * j + i]);
    284             }
    285         }
    286     }
    287 
    288     cucul_set_color(cv, oldfg, oldbg);
    289 }
    290 
    291 /** \brief Free the memory associated with a sprite.
    292  *
    293  *  \param sprite The sprite to be freed.
    294  *  \return void
    295  */
    296 void cucul_free_sprite(cucul_sprite_t *sprite)
    297 {
    298     int i;
    299 
    300     if(sprite == NULL)
    301         return;
    302 
    303     for(i = sprite->nf; i--;)
    304     {
    305         struct cucul_frame *frame = &sprite->frames[i];
    306         free(frame->chars);
    307         free(frame->color);
    308     }
    309 
    310     free(sprite->frames);
    311     free(sprite);
    312 }
    313 
Note: See TracChangeset for help on using the changeset viewer.