Ignore:
Timestamp:
Apr 18, 2006, 5:54:33 PM (14 years ago)
Author:
Sam Hocevar
Message:
  • Renamed main canvas-related functions so that they have "canvas" in their name, eg. cucul_create() -> cucul_create_canvas() etc.
  • Moved buffer-related functions to cucul/buffer.c.
File:
1 copied

Legend:

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

    r811 r813  
    1313
    1414/*
    15  *  This file contains the main functions used by \e libcucul applications
    16  *  to initialise a drawing context.
     15 *  This file contains buffer handling functions.
    1716 */
    1817
     
    2726#include "cucul.h"
    2827#include "cucul_internals.h"
    29 
    30 /** \brief Initialise a \e libcucul canvas.
    31  *
    32  *  This function initialises internal \e libcucul structures and the backend
    33  *  that will be used for subsequent graphical operations. It must be the
    34  *  first \e libcucul function to be called in a function. cucul_free() should
    35  *  be called at the end of the program to free all allocated resources.
    36  *
    37  *  If one of the desired canvas coordinates is zero, a default canvas size
    38  *  of 80x32 is used instead.
    39  *
    40  *  \param width The desired canvas width
    41  *  \param height The desired canvas height
    42  *  \return A libcucul canvas handle upon success, NULL if an error occurred.
    43  */
    44 cucul_canvas_t * cucul_create(unsigned int width, unsigned int height)
    45 {
    46     cucul_canvas_t *cv = malloc(sizeof(cucul_canvas_t));
    47 
    48     cv->refcount = 0;
    49 
    50     cv->fgcolor = CUCUL_COLOR_LIGHTGRAY;
    51     cv->bgcolor = CUCUL_COLOR_BLACK;
    52 
    53     cv->width = cv->height = 0;
    54     cv->chars = NULL;
    55     cv->attr = NULL;
    56     cv->empty_line = cv->scratch_line = NULL;
    57 
    58     /* Initialise to a default size. 80x32 is arbitrary but matches AAlib's
    59      * default X11 window. When a graphic driver attaches to us, it can set
    60      * a different size. */
    61     if(width && height)
    62         _cucul_set_size(cv, width, height);
    63     else
    64         _cucul_set_size(cv, 80, 32);
    65 
    66     if(_cucul_init_dither())
    67     {
    68         free(cv);
    69         return NULL;
    70     }
    71 
    72     return cv;
    73 }
    74 
    75 /** \brief Load a memory area into a canvas.
    76  *
    77  *  This function loads a memory area containing an exported canvas into
    78  *  a new \e libcucul canvas.
    79  *
    80  *  \param data The memory area to be loaded into a canvas.
    81  *  \param size The length of the memory area.
    82  *  \return A libcucul canvas, or NULL in case of error.
    83  */
    84 cucul_canvas_t *cucul_load(void *data, unsigned int size)
    85 {
    86     cucul_canvas_t *cv;
    87     uint8_t *buf = (uint8_t *)data;
    88     unsigned int width, height, n;
    89 
    90     if(size < 12)
    91         return NULL;
    92 
    93     if(buf[0] != 'C' || buf[1] != 'A' || buf[2] != 'C' || buf[3] != 'A')
    94         return NULL;
    95 
    96     width = ((uint32_t)buf[4] << 24) | ((uint32_t)buf[5] << 16)
    97           | ((uint32_t)buf[6] << 8) | (uint32_t)buf[7];
    98     height = ((uint32_t)buf[8] << 24) | ((uint32_t)buf[9] << 16)
    99            | ((uint32_t)buf[10] << 8) | (uint32_t)buf[11];
    100 
    101     if(!width || !height)
    102         return NULL;
    103 
    104     if(size != 12 + width * height * 8 + 4)
    105         return NULL;
    106 
    107     if(buf[size - 4] != 'A' || buf[size - 3] != 'C'
    108         || buf[size - 2] != 'A' || buf[size - 1] != 'C')
    109         return NULL;
    110 
    111     cv = cucul_create(width, height);
    112 
    113     if(!cv)
    114         return NULL;
    115 
    116     for(n = height * width; n--; )
    117     {
    118         cv->chars[n] = ((uint32_t)buf[12 + 8 * n] << 24)
    119                      | ((uint32_t)buf[13 + 8 * n] << 16)
    120                      | ((uint32_t)buf[14 + 8 * n] << 8)
    121                      | (uint32_t)buf[15 + 8 * n];
    122         cv->attr[n] = ((uint32_t)buf[16 + 8 * n] << 24)
    123                     | ((uint32_t)buf[17 + 8 * n] << 16)
    124                     | ((uint32_t)buf[18 + 8 * n] << 8)
    125                     | (uint32_t)buf[19 + 8 * n];
    126     }
    127 
    128     return cv;
    129 }
    130 
    131 /** \brief Resize a canvas.
    132  *
    133  *  This function sets the canvas width and height, in character cells.
    134  *
    135  *  The contents of the canvas are preserved to the extent of the new
    136  *  canvas size. Newly allocated character cells at the right and/or at
    137  *  the bottom of the canvas are filled with spaces.
    138  *
    139  *  It is an error to try to resize the canvas if an output driver has
    140  *  been attached to the canvas using caca_attach(). You need to remove
    141  *  the output driver using caca_detach() before you can change the
    142  *  canvas size again. However, the caca output driver can cause a canvas
    143  *  resize through user interaction. See the caca_event() documentation
    144  *  for more about this.
    145  *
    146  *  \param cv A libcucul canvas
    147  *  \param width The desired canvas width
    148  *  \param height The desired canvas height
    149  */
    150 void cucul_set_size(cucul_canvas_t *cv, unsigned int width, unsigned int height)
    151 {
    152     if(cv->refcount)
    153         return;
    154 
    155     _cucul_set_size(cv, width, height);
    156 }
    157 
    158 /** \brief Get the canvas width.
    159  *
    160  *  This function returns the current canvas width, in character cells.
    161  *
    162  *  \param cv A libcucul canvas
    163  *  \return The canvas width.
    164  */
    165 unsigned int cucul_get_width(cucul_canvas_t *cv)
    166 {
    167     return cv->width;
    168 }
    169 
    170 /** \brief Get the canvas height.
    171  *
    172  *  This function returns the current canvas height, in character cells.
    173  *
    174  *  \param cv A libcucul canvas
    175  *  \return The canvas height.
    176  */
    177 unsigned int cucul_get_height(cucul_canvas_t *cv)
    178 {
    179     return cv->height;
    180 }
    181 
    182 /** \brief Translate a colour index into the colour's name.
    183  *
    184  *  This function translates a cucul_color enum into a human-readable
    185  *  description string of the associated colour.
    186  *
    187  *  \param color The colour value.
    188  *  \return A static string containing the colour's name.
    189  */
    190 char const *cucul_get_color_name(unsigned int color)
    191 {
    192     static char const *color_names[] =
    193     {
    194         "black",
    195         "blue",
    196         "green",
    197         "cyan",
    198         "red",
    199         "magenta",
    200         "brown",
    201         "light gray",
    202         "dark gray",
    203         "light blue",
    204         "light green",
    205         "light cyan",
    206         "light red",
    207         "light magenta",
    208         "yellow",
    209         "white",
    210     };
    211 
    212     if(color < 0 || color > 15)
    213         return "unknown";
    214 
    215     return color_names[color];
    216 }
    217 
    218 /** \brief Uninitialise \e libcucul.
    219  *
    220  *  This function frees all resources allocated by cucul_create(). After
    221  *  cucul_free() has been called, no other \e libcucul functions may be used
    222  *  unless a new call to cucul_create() is done.
    223  *
    224  *  \param cv A libcucul canvas
    225  */
    226 void cucul_free(cucul_canvas_t *cv)
    227 {
    228     _cucul_end_dither();
    229 
    230     free(cv->empty_line);
    231     free(cv->scratch_line);
    232 
    233     free(cv->chars);
    234     free(cv->attr);
    235 
    236     free(cv);
    237 }
    238 
    239 /** \brief Generate a random integer within a range.
    240  *
    241  *  \param min The lower bound of the integer range.
    242  *  \param max The upper bound of the integer range.
    243  *  \return A random integer comprised between \p min and \p max, inclusive.
    244  */
    245 int cucul_rand(int min, int max)
    246 {
    247     return min + (int)((1.0*(max-min+1)) * rand() / (RAND_MAX+1.0));
    248 }
    24928
    25029/** \brief Get the buffer size.
     
    28766}
    28867
    289 /*
    290  * XXX: The following functions are local.
    291  */
    292 
    293 void _cucul_set_size(cucul_canvas_t *cv, unsigned int width,
    294                                          unsigned int height)
    295 {
    296     unsigned int x, y, old_width, old_height, new_size, old_size;
    297 
    298     old_width = cv->width;
    299     old_height = cv->height;
    300     old_size = old_width * old_height;
    301 
    302     cv->width = width;
    303     cv->height = height;
    304     new_size = width * height;
    305 
    306     /* Step 1: if new area is bigger, resize the memory area now. */
    307     if(new_size > old_size)
    308     {
    309         cv->chars = realloc(cv->chars, new_size * sizeof(uint32_t));
    310         cv->attr = realloc(cv->attr, new_size * sizeof(uint32_t));
    311     }
    312 
    313     /* Step 2: move line data if necessary. */
    314     if(width == old_width)
    315     {
    316         /* Width did not change, which means we do not need to move data. */
    317         ;
    318     }
    319     else if(width > old_width)
    320     {
    321         /* New width is bigger than old width, which means we need to
    322          * copy lines starting from the bottom of the screen otherwise
    323          * we will overwrite information. */
    324         for(y = height < old_height ? height : old_height; y--; )
    325         {
    326             for(x = old_width; x--; )
    327             {
    328                 cv->chars[y * width + x] = cv->chars[y * old_width + x];
    329                 cv->attr[y * width + x] = cv->attr[y * old_width + x];
    330             }
    331 
    332             /* Zero the end of the line */
    333             for(x = width - old_width; x--; )
    334                 cv->chars[y * width + old_width + x] = (uint32_t)' ';
    335             memset(cv->attr + y * width + old_width, 0,
    336                    (width - old_width) * 4);
    337         }
    338     }
    339     else
    340     {
    341         /* New width is smaller. Copy as many lines as possible. Ignore
    342          * the first line, it is already in place. */
    343         unsigned int lines = height < old_height ? height : old_height;
    344 
    345         for(y = 1; y < lines; y++)
    346         {
    347             for(x = 0; x < width; x++)
    348             {
    349                 cv->chars[y * width + x] = cv->chars[y * old_width + x];
    350                 cv->attr[y * width + x] = cv->attr[y * old_width + x];
    351             }
    352         }
    353     }
    354 
    355     /* Step 3: fill the bottom of the new screen if necessary. */
    356     if(height > old_height)
    357     {
    358         /* Zero the bottom of the screen */
    359         for(x = (height - old_height) * width; x--; )
    360             cv->chars[old_height * width + x] = (uint32_t)' ';
    361         memset(cv->attr + old_height * width, 0,
    362                (height - old_height) * width * 4);
    363     }
    364 
    365     /* Step 4: if new area is smaller, resize memory area now. */
    366     if(new_size <= old_size)
    367     {
    368         cv->chars = realloc(cv->chars, new_size * sizeof(uint32_t));
    369         cv->attr = realloc(cv->attr, new_size * sizeof(uint32_t));
    370     }
    371 
    372     /* Recompute the scratch line and the empty line */
    373     if(width != old_width)
    374     {
    375         cv->empty_line = realloc(cv->empty_line, width + 1);
    376         memset(cv->empty_line, ' ', width);
    377         cv->empty_line[width] = '\0';
    378 
    379         cv->scratch_line = realloc(cv->scratch_line, width + 1);
    380     }
    381 }
    382 
Note: See TracChangeset for help on using the changeset viewer.