diff --git a/cucul/cucul.h b/cucul/cucul.h index 1644828..7efccbc 100644 --- a/cucul/cucul.h +++ b/cucul/cucul.h @@ -112,10 +112,10 @@ int cucul_blit(cucul_canvas_t *, int, int, cucul_canvas_t const *, cucul_canvas_ * These functions perform horizontal and vertical canvas flipping. * * @{ */ -void cucul_invert(cucul_canvas_t *); -void cucul_flip(cucul_canvas_t *); -void cucul_flop(cucul_canvas_t *); -void cucul_rotate(cucul_canvas_t *); +int cucul_invert(cucul_canvas_t *); +int cucul_flip(cucul_canvas_t *); +int cucul_flop(cucul_canvas_t *); +int cucul_rotate(cucul_canvas_t *); /* @} */ /** \defgroup prim libcucul primitives drawing @@ -150,9 +150,9 @@ int cucul_fill_triangle(cucul_canvas_t *, int, int, int, int, int, int, char con * * @{ */ unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *); -void cucul_set_canvas_frame(cucul_canvas_t *, unsigned int); -void cucul_create_canvas_frame(cucul_canvas_t *, unsigned int); -void cucul_free_canvas_frame(cucul_canvas_t *, unsigned int); +int cucul_set_canvas_frame(cucul_canvas_t *, unsigned int); +int cucul_create_canvas_frame(cucul_canvas_t *, unsigned int); +int cucul_free_canvas_frame(cucul_canvas_t *, unsigned int); /* @} */ /** \defgroup dither libcucul bitmap dithering @@ -165,24 +165,24 @@ cucul_dither_t *cucul_create_dither(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -void cucul_set_dither_palette(cucul_dither_t *, - unsigned int r[], unsigned int g[], - unsigned int b[], unsigned int a[]); -void cucul_set_dither_brightness(cucul_dither_t *, float); -void cucul_set_dither_gamma(cucul_dither_t *, float); -void cucul_set_dither_contrast(cucul_dither_t *, float); -void cucul_set_dither_invert(cucul_dither_t *, int); -void cucul_set_dither_antialias(cucul_dither_t *, char const *); +int cucul_set_dither_palette(cucul_dither_t *, + unsigned int r[], unsigned int g[], + unsigned int b[], unsigned int a[]); +int cucul_set_dither_brightness(cucul_dither_t *, float); +int cucul_set_dither_gamma(cucul_dither_t *, float); +int cucul_set_dither_contrast(cucul_dither_t *, float); +int cucul_set_dither_invert(cucul_dither_t *, int); +int cucul_set_dither_antialias(cucul_dither_t *, char const *); char const * const * cucul_get_dither_antialias_list(cucul_dither_t const *); -void cucul_set_dither_color(cucul_dither_t *, char const *); +int cucul_set_dither_color(cucul_dither_t *, char const *); char const * const * cucul_get_dither_color_list(cucul_dither_t const *); -void cucul_set_dither_charset(cucul_dither_t *, char const *); +int cucul_set_dither_charset(cucul_dither_t *, char const *); char const * const * cucul_get_dither_charset_list(cucul_dither_t const *); -void cucul_set_dither_mode(cucul_dither_t *, char const *); +int cucul_set_dither_mode(cucul_dither_t *, char const *); char const * const * cucul_get_dither_mode_list(cucul_dither_t const *); -void cucul_dither_bitmap(cucul_canvas_t *, int, int, int, int, +int cucul_dither_bitmap(cucul_canvas_t *, int, int, int, int, cucul_dither_t const *, void *); -void cucul_free_dither(cucul_dither_t *); +int cucul_free_dither(cucul_dither_t *); /* @} */ /** \defgroup font libcucul font handling @@ -195,9 +195,9 @@ cucul_font_t *cucul_load_font(void const *, unsigned int); char const * const * cucul_get_font_list(void); unsigned int cucul_get_font_width(cucul_font_t *); unsigned int cucul_get_font_height(cucul_font_t *); -void cucul_render_canvas(cucul_canvas_t *, cucul_font_t *, void *, +int cucul_render_canvas(cucul_canvas_t *, cucul_font_t *, void *, unsigned int, unsigned int, unsigned int); -void cucul_free_font(cucul_font_t *); +int cucul_free_font(cucul_font_t *); /* @} */ /** \defgroup importexport libcucul importers/exporters from/to various formats diff --git a/cucul/dither.c b/cucul/dither.c index 03a8dd0..e16717e 100644 --- a/cucul/dither.c +++ b/cucul/dither.c @@ -26,6 +26,9 @@ # include # include # include +# if defined(HAVE_ERRNO_H) +# include +# endif #endif #include "cucul.h" @@ -236,6 +239,11 @@ static inline void rgb2hsv_default(int r, int g, int b, * cucul_set_dither_palette() function. For depths greater than 8 bits per * pixel, a zero alpha mask causes the alpha values to be ignored. * + * If an error occurs, NULL is returned and \b errno is set accordingly: + * - \c EINVAL Requested width, height, pitch or bits per pixel value was + * invalid. + * - \c ENOMEM Not enough memory to allocate dither structure. + * * \param bpp Bitmap depth in bits per pixel. * \param w Bitmap width in pixels. * \param h Bitmap height in pixels. @@ -244,7 +252,7 @@ static inline void rgb2hsv_default(int r, int g, int b, * \param gmask Bitmask for green values. * \param bmask Bitmask for blue values. * \param amask Bitmask for alpha values. - * \return Dither object, or NULL upon error. + * \return Dither object upon success, NULL if an error occurred. */ cucul_dither_t *cucul_create_dither(unsigned int bpp, unsigned int w, unsigned int h, unsigned int pitch, @@ -256,11 +264,21 @@ cucul_dither_t *cucul_create_dither(unsigned int bpp, unsigned int w, /* Minor sanity test */ if(!w || !h || !pitch || bpp > 32 || bpp < 8) + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif return NULL; + } d = malloc(sizeof(cucul_dither_t)); if(!d) + { +#if defined(HAVE_ERRNO_H) + errno = ENOMEM; +#endif return NULL; + } d->bpp = bpp; d->has_palette = 0; @@ -325,99 +343,142 @@ cucul_dither_t *cucul_create_dither(unsigned int bpp, unsigned int w, * Set the palette of an 8 bits per pixel bitmap. Values should be between * 0 and 4095 (0xfff). * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Dither bits per pixel value is not 8, or one of the pixel + * values was outside the range 0 - 4095. + * * \param d Dither object. * \param red Array of 256 red values. * \param green Array of 256 green values. * \param blue Array of 256 blue values. * \param alpha Array of 256 alpha values. + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_dither_palette(cucul_dither_t *d, - unsigned int red[], unsigned int green[], - unsigned int blue[], unsigned int alpha[]) +int cucul_set_dither_palette(cucul_dither_t *d, + unsigned int red[], unsigned int green[], + unsigned int blue[], unsigned int alpha[]) { int i, has_alpha = 0; if(d->bpp != 8) - return; + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } for(i = 0; i < 256; i++) { - if(red[i] >= 0 && red[i] < 0x1000 && - green[i] >= 0 && green[i] < 0x1000 && - blue[i] >= 0 && blue[i] < 0x1000 && - alpha[i] >= 0 && alpha[i] < 0x1000) + if((red[i] | green[i] | blue[i] | alpha[i]) >= 0x1000) { - d->red[i] = red[i]; - d->green[i] = green[i]; - d->blue[i] = blue[i]; - if(alpha[i]) - { - d->alpha[i] = alpha[i]; - has_alpha = 1; - } +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } + } + + for(i = 0; i < 256; i++) + { + d->red[i] = red[i]; + d->green[i] = green[i]; + d->blue[i] = blue[i]; + if(alpha[i]) + { + d->alpha[i] = alpha[i]; + has_alpha = 1; } } d->has_alpha = has_alpha; + + return 0; } /** \brief Set the brightness of a dither object. * * Set the brightness of dither. * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Brightness value was out of range. + * * \param d Dither object. * \param brightness brightness value. + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_dither_brightness(cucul_dither_t *d, float brightness) +int cucul_set_dither_brightness(cucul_dither_t *d, float brightness) { /* FIXME */ + return 0; } /** \brief Set the gamma of a dither object. * * Set the gamma of dither. * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Gamma value was out of range. + * * \param d Dither object. * \param gamma Gamma value. + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_dither_gamma(cucul_dither_t *d, float gamma) +int cucul_set_dither_gamma(cucul_dither_t *d, float gamma) { - /* FIXME: we don't need 4096 calls to gammapow(), we can just compute + /* FIXME: we don't need 4096 calls to gammapow(), we could just compute * 128 of them and do linear interpolation for the rest. This will * probably speed up things a lot. */ int i; if(gamma <= 0.0) - return; + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } d->gamma = gamma; for(i = 0; i < 4096; i++) d->gammatab[i] = 4096.0 * gammapow((float)i / 4096.0, 1.0 / gamma); + + return 0; } /** \brief Invert colors of dither * - * Invert colors of dither + * Invert colors of dither. + * + * This function never fails. * * \param d Dither object. * \param value 0 for normal behaviour, 1 for invert + * \return This function always returns 0. */ -void cucul_set_dither_invert(cucul_dither_t *d, int value) +int cucul_set_dither_invert(cucul_dither_t *d, int value) { d->invert = value ? 1 : 0; + + return 0; } /** \brief Set the contrast of a dither object. * * Set the contrast of dither. * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Contrast value was out of range. + * * \param d Dither object. * \param contrast contrast value. + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_dither_contrast(cucul_dither_t *d, float contrast) +int cucul_set_dither_contrast(cucul_dither_t *d, float contrast) { /* FIXME */ + return 0; } /** \brief Set dither antialiasing @@ -427,19 +488,32 @@ void cucul_set_dither_contrast(cucul_dither_t *d, float contrast) * * \li \c "none": no antialiasing. * - * \li \c "prefilter": simple prefilter antialiasing. This is the default - * value. + * \li \c "prefilter" or \c "default": simple prefilter antialiasing. This + * is the default value. + * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Invalid antialiasing mode. * * \param d Dither object. * \param str A string describing the antialiasing method that will be used * for the dithering. + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_dither_antialias(cucul_dither_t *d, char const *str) +int cucul_set_dither_antialias(cucul_dither_t *d, char const *str) { if(!strcasecmp(str, "none")) d->antialias = 0; - else /* "prefilter" is the default */ + else if(!strcasecmp(str, "prefilter") || !strcasecmp(str, "default")) d->antialias = 1; + else + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } + + return 0; } /** \brief Get available antialiasing methods @@ -450,6 +524,8 @@ void cucul_set_dither_antialias(cucul_dither_t *d, char const *str) * cucul_set_dither_antialias(), and a string containing the natural * language description for that antialiasing method. * + * This function never fails. + * * \param d Dither object. * \return An array of strings. */ @@ -485,14 +561,18 @@ char const * const * * \li \c "full8": use the 8 ANSI colours for both the characters and the * background. * - * \li \c "full16": use the 16 ANSI colours for both the characters and the - * background. This is the default value. + * \li \c "full16" or \c "default": use the 16 ANSI colours for both the + * characters and the background. This is the default value. + * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Invalid colour set. * * \param d Dither object. * \param str A string describing the colour set that will be used * for the dithering. + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_dither_color(cucul_dither_t *d, char const *str) +int cucul_set_dither_color(cucul_dither_t *d, char const *str) { if(!strcasecmp(str, "mono")) d->color_mode = COLOR_MODE_MONO; @@ -506,8 +586,17 @@ void cucul_set_dither_color(cucul_dither_t *d, char const *str) d->color_mode = COLOR_MODE_FULLGRAY; else if(!strcasecmp(str, "full8")) d->color_mode = COLOR_MODE_FULL8; - else /* "full16" is the default */ + else if(!strcasecmp(str, "full16") || !strcasecmp(str, "default")) d->color_mode = COLOR_MODE_FULL16; + else + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } + + return 0; } /** \brief Get available colour modes @@ -518,6 +607,8 @@ void cucul_set_dither_color(cucul_dither_t *d, char const *str) * cucul_set_dither_color(), and a string containing the natural * language description for that colour mode. * + * This function never fails. + * * \param d Dither object. * \return An array of strings. */ @@ -544,7 +635,8 @@ char const * const * * Tell the renderer which characters should be used to render the * dither. Valid values for \c str are: * - * \li \c "ascii": use only ASCII characters. This is the default value. + * \li \c "ascii" or "default": use only ASCII characters. This is the + * default value. * * \li \c "shades": use Unicode characters "U+2591 LIGHT SHADE", "U+2592 * MEDIUM SHADE" and "U+2593 DARK SHADE". These characters are also @@ -553,11 +645,15 @@ char const * const * * \li \c "blocks": use Unicode quarter-cell block combinations. These * characters are only found in the Unicode set. * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Invalid character set. + * * \param d Dither object. * \param str A string describing the characters that need to be used * for the dithering. + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_dither_charset(cucul_dither_t *d, char const *str) +int cucul_set_dither_charset(cucul_dither_t *d, char const *str) { if(!strcasecmp(str, "shades")) { @@ -569,11 +665,20 @@ void cucul_set_dither_charset(cucul_dither_t *d, char const *str) d->glyphs = blocks_glyphs; d->glyph_count = sizeof(blocks_glyphs) / sizeof(*blocks_glyphs); } - else /* "ascii" is the default */ + else if(!strcasecmp(str, "ascii") || !strcasecmp(str, "default")) { d->glyphs = ascii_glyphs; d->glyph_count = sizeof(ascii_glyphs) / sizeof(*ascii_glyphs); } + else + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } + + return 0; } /** \brief Get available dither character sets @@ -584,6 +689,8 @@ void cucul_set_dither_charset(cucul_dither_t *d, char const *str) * cucul_set_dither_charset(), and a string containing the natural * language description for that character set. * + * This function never fails. + * * \param d Dither object. * \return An array of strings. */ @@ -618,11 +725,15 @@ char const * const * cucul_get_dither_charset_list(cucul_dither_t const *d) * * \li \c "fstein": use Floyd-Steinberg dithering. This is the default value. * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Unknown dithering mode. + * * \param d Dither object. * \param str A string describing the method that needs to be used * for the dithering. + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_dither_mode(cucul_dither_t *d, char const *str) +int cucul_set_dither_mode(cucul_dither_t *d, char const *str) { if(!strcasecmp(str, "none")) { @@ -654,12 +765,21 @@ void cucul_set_dither_mode(cucul_dither_t *d, char const *str) d->get_dither = get_random_dither; d->increment_dither = increment_random_dither; } - else /* "fstein" is the default */ + else if(!strcasecmp(str, "fstein") || !strcasecmp(str, "default")) { d->init_dither = init_fstein_dither; d->get_dither = get_fstein_dither; d->increment_dither = increment_fstein_dither; } + else + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } + + return 0; } /** \brief Get dithering methods @@ -670,6 +790,8 @@ void cucul_set_dither_mode(cucul_dither_t *d, char const *str) * cucul_set_dither_dithering(), and a string containing the natural * language description for that dithering method. * + * This function never fails. + * * \param d Dither object. * \return An array of strings. */ @@ -694,6 +816,8 @@ char const * const * cucul_get_dither_mode_list(cucul_dither_t const *d) * Dither a bitmap at the given coordinates. The dither can be of any size * and will be stretched to the text area. * + * This function never fails. + * * \param cv A handle to the libcucul canvas. * \param x X coordinate of the upper-left corner of the drawing area. * \param y Y coordinate of the upper-left corner of the drawing area. @@ -701,9 +825,10 @@ char const * const * cucul_get_dither_mode_list(cucul_dither_t const *d) * \param h Height of the drawing area. * \param d Dither object to be drawn. * \param pixels Bitmap's pixels. + * \return This function always returns 0. */ -void cucul_dither_bitmap(cucul_canvas_t *cv, int x, int y, int w, int h, - cucul_dither_t const *d, void *pixels) +int cucul_dither_bitmap(cucul_canvas_t *cv, int x, int y, int w, int h, + cucul_dither_t const *d, void *pixels) { int *floyd_steinberg, *fs_r, *fs_g, *fs_b; int fs_length; @@ -711,7 +836,7 @@ void cucul_dither_bitmap(cucul_canvas_t *cv, int x, int y, int w, int h, unsigned int dchmax; if(!d || !pixels) - return; + return 0; x1 = x; x2 = x + w - 1; y1 = y; y2 = y + h - 1; @@ -940,20 +1065,27 @@ void cucul_dither_bitmap(cucul_canvas_t *cv, int x, int y, int w, int h, } free(floyd_steinberg); + + return 0; } /** \brief Free the memory associated with a dither. * * Free the memory allocated by cucul_create_dither(). * + * This function never fails. + * * \param d Dither object. + * \return This function always returns 0. */ -void cucul_free_dither(cucul_dither_t *d) +int cucul_free_dither(cucul_dither_t *d) { if(!d) - return; + return 0; free(d); + + return 0; } /* diff --git a/cucul/export.c b/cucul/export.c index 00916cb..e4a4b8c 100644 --- a/cucul/export.c +++ b/cucul/export.c @@ -20,6 +20,9 @@ #include "common.h" #if !defined(__KERNEL__) +# if defined(HAVE_ERRNO_H) +# include +# endif # include # include # include @@ -63,14 +66,27 @@ static void export_tga(cucul_canvas_t *, cucul_buffer_t *); * * \li \c "tga": export a TGA image. * + * If an error occurs, NULL is returned and \b errno is set accordingly: + * - \c EINVAL Invalid format requested. + * - \c ENOMEM Not enough memory to allocate output buffer. + * * \param cv A libcucul canvas * \param format A string describing the requested output format. + * \return A libcucul buffer, or NULL in case of error. */ cucul_buffer_t * cucul_export_canvas(cucul_canvas_t *cv, char const *format) { cucul_buffer_t *ex; ex = malloc(sizeof(cucul_buffer_t)); + if(!ex) + { +#if defined(HAVE_ERRNO_H) + errno = ENOMEM; +#endif + return NULL; + } + ex->size = 0; ex->data = NULL; ex->user_data = 0; @@ -95,6 +111,9 @@ cucul_buffer_t * cucul_export_canvas(cucul_canvas_t *cv, char const *format) if(ex->size == 0) { free(ex); +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif return NULL; } @@ -108,6 +127,8 @@ cucul_buffer_t * cucul_export_canvas(cucul_canvas_t *cv, char const *format) * the export format, to be used with cucul_export_canvas(), and a string * containing the natural language description for that export format. * + * This function never fails. + * * \return An array of strings. */ char const * const * cucul_get_export_list(void) diff --git a/cucul/font.c b/cucul/font.c index b3f4411..b7b2e4e 100644 --- a/cucul/font.c +++ b/cucul/font.c @@ -27,6 +27,9 @@ # elif defined(HAVE_NETINET_IN_H) # include # endif +# if defined(HAVE_ERRNO_H) +# include +# endif # include # include # include @@ -108,6 +111,11 @@ DECLARE_UNPACKGLYPH(1) * are loaded as a font. This memory are must not be freed by the calling * program until the font handle has been freed with cucul_free_font(). * + * If an error occurs, NULL is returned and \b errno is set accordingly: + * - \c ENOENT Requested built-in font does not exist. + * - \c EINVAL Invalid font data in memory area. + * - \c ENOMEM Not enough memory to allocate font structure. + * * \param data The memory area containing the font or its name. * \param size The size of the memory area, or 0 if the font name is given. * \return A font handle or NULL in case of error. @@ -126,13 +134,29 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) return cucul_load_font(monobold12_data, monobold12_size); #endif +#if defined(HAVE_ERRNO_H) + errno = ENOENT; +#endif return NULL; } if(size < sizeof(struct font_header)) + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif return NULL; + } f = malloc(sizeof(cucul_font_t)); + if(!f) + { +#if defined(HAVE_ERRNO_H) + errno = ENOMEM; +#endif + return NULL; + } + f->private = (void *)(uintptr_t)data; memcpy(&f->header, f->private + 8, sizeof(struct font_header)); @@ -152,10 +176,22 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) || (f->header.flags & 1) == 0) { free(f); +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif return NULL; } f->block_list = malloc(f->header.blocks * sizeof(struct block_info)); + if(!f->block_list) + { + free(f); +#if defined(HAVE_ERRNO_H) + errno = ENOMEM; +#endif + return NULL; + } + memcpy(f->block_list, f->private + 8 + sizeof(struct font_header), f->header.blocks * sizeof(struct block_info)); @@ -171,11 +207,24 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) { free(f->block_list); free(f); +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif return NULL; } } f->glyph_list = malloc(f->header.glyphs * sizeof(struct glyph_info)); + if(!f->glyph_list) + { + free(f->block_list); + free(f); +#if defined(HAVE_ERRNO_H) + errno = ENOMEM; +#endif + return NULL; + } + memcpy(f->glyph_list, f->private + 8 + sizeof(struct font_header) + f->header.blocks * sizeof(struct block_info), @@ -194,6 +243,9 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) free(f->glyph_list); free(f->block_list); free(f); +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif return NULL; } } @@ -208,6 +260,8 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) * Return a list of available builtin fonts. The list is a NULL-terminated * array of strings. * + * This function never fails. + * * \return An array of strings. */ char const * const * cucul_get_font_list(void) @@ -226,6 +280,8 @@ char const * const * cucul_get_font_list(void) * * This function returns the maximum value for the current font's glyphs * + * This function never fails. + * * \param f The font, as returned by cucul_load_font() * \return The maximum glyph width. */ @@ -238,6 +294,8 @@ unsigned int cucul_get_font_width(cucul_font_t *f) * * This function returns the maximum value for the current font's glyphs * + * This function never fails. + * * \param f The font, as returned by cucul_load_font() * \return The maximum glyph height. */ @@ -253,13 +311,18 @@ unsigned int cucul_get_font_height(cucul_font_t *f) * this function has returned, the memory area that was given to * cucul_load_font() can be freed. * + * This function never fails. + * * \param f The font, as returned by cucul_load_font() + * \return This function always returns 0. */ -void cucul_free_font(cucul_font_t *f) +int cucul_free_font(cucul_font_t *f) { free(f->glyph_list); free(f->block_list); free(f); + + return 0; } /** \brief Render the canvas onto an image buffer. @@ -275,16 +338,19 @@ void cucul_free_font(cucul_font_t *f) * Glyphs that do not fit in the image buffer are currently not rendered at * all. They may be cropped instead in future versions. * + * This function never fails. + * * \param cv The canvas to render * \param f The font, as returned by cucul_load_font() * \param buf The image buffer * \param width The width (in pixels) of the image buffer * \param height The height (in pixels) of the image buffer * \param pitch The pitch (in bytes) of an image buffer line. + * \return This function always returns 0. */ -void cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f, - void *buf, unsigned int width, - unsigned int height, unsigned int pitch) +int cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f, + void *buf, unsigned int width, + unsigned int height, unsigned int pitch) { uint8_t *glyph = NULL; unsigned int x, y, xmax, ymax; @@ -379,6 +445,8 @@ void cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f, if(f->header.bpp != 8) free(glyph); + + return 0; } /* diff --git a/cucul/import.c b/cucul/import.c index 9c43790..dff0bfa 100644 --- a/cucul/import.c +++ b/cucul/import.c @@ -19,6 +19,9 @@ #include "common.h" #if !defined(__KERNEL__) +# if defined(HAVE_ERRNO_H) +# include +# endif # include # include # include @@ -43,8 +46,8 @@ static void ansi_parse_grcm(cucul_canvas_t *, struct ansi_grcm *, /** \brief Import a buffer into a canvas * - * This function imports a libcucul buffer (cucul_load_memory()/cucul_load_file()) - * into an internal libcucul canvas. + * This function imports a libcucul buffer as returned by cucul_load_memory() + * or cucul_load_file() into an internal libcucul canvas. * * Valid values for \c format are: * @@ -54,6 +57,10 @@ static void ansi_parse_grcm(cucul_canvas_t *, struct ansi_grcm *, * * \li \c "caca": import native libcaca files. * + * If an error occurs, NULL is returned and \b errno is set accordingly: + * - \c ENOMEM Not enough memory to allocate canvas. + * - \c EINVAL Invalid format requested. + * * \param buffer A \e libcucul buffer containing the data to be loaded * into a canvas. * \param format A string describing the input format. @@ -63,9 +70,6 @@ cucul_canvas_t * cucul_import_canvas(cucul_buffer_t *buffer, char const *format) { char const *buf = (char const*)buffer->data; - if(buffer->size == 0 || buffer->data == NULL) - return NULL; - if(!strcasecmp("caca", format)) return import_caca(buffer->data, buffer->size); if(!strcasecmp("text", format)) @@ -75,24 +79,26 @@ cucul_canvas_t * cucul_import_canvas(cucul_buffer_t *buffer, char const *format) /* Autodetection */ if(!strcasecmp("", format)) - { - unsigned int i=0; - /* if 4 first letters are CACA */ - if(buffer->size >= 4 && - buf[0] == 'C' && buf[1] == 'A' && buf[2] == 'C' && buf[3] != 'A') - return import_caca(buffer->data, buffer->size); - - /* If we find ESC[ argv, we guess it's an ANSI file */ - while(i < buffer->size - 1) - { - if((buf[i] == 0x1b) && (buf[i+1] == '[')) - return import_ansi(buffer->data, buffer->size); - i++; - } + { + unsigned int i; - /* Otherwise, import it as text */ - return import_text(buffer->data, buffer->size); - } + /* If 4 first letters are CACA */ + if(buffer->size >= 4 && + buf[0] == 'C' && buf[1] == 'A' && buf[2] == 'C' && buf[3] != 'A') + return import_caca(buffer->data, buffer->size); + + /* If we find ESC[ argv, we guess it's an ANSI file */ + for(i = 0; i < buffer->size - 1; i++) + if((buf[i] == 0x1b) && (buf[i + 1] == '[')) + return import_ansi(buffer->data, buffer->size); + + /* Otherwise, import it as text */ + return import_text(buffer->data, buffer->size); + } + +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif return NULL; } @@ -103,6 +109,8 @@ cucul_canvas_t * cucul_import_canvas(cucul_buffer_t *buffer, char const *format) * the import format, to be used with cucul_import_canvas(), and a string * containing the natural language description for that import format. * + * This function never fails. + * * \return An array of strings. */ char const * const * cucul_get_import_list(void) @@ -130,13 +138,13 @@ static cucul_canvas_t *import_caca(void const *data, unsigned int size) unsigned int width, height, n; if(size < 16) - return NULL; + goto invalid_caca; if(buf[0] != 'C' || buf[1] != 'A' || buf[2] != 'C' || buf[3] != 'A') - return NULL; + goto invalid_caca; if(buf[4] != 'C' || buf[5] != 'A' || buf[6] != 'N' || buf[7] != 'V') - return NULL; + goto invalid_caca; width = ((uint32_t)buf[8] << 24) | ((uint32_t)buf[9] << 16) | ((uint32_t)buf[10] << 8) | (uint32_t)buf[11]; @@ -144,15 +152,20 @@ static cucul_canvas_t *import_caca(void const *data, unsigned int size) | ((uint32_t)buf[14] << 8) | (uint32_t)buf[15]; if(!width || !height) - return NULL; + goto invalid_caca; if(size != 16 + width * height * 8) - return NULL; + goto invalid_caca; cv = cucul_create_canvas(width, height); if(!cv) + { +#if defined(HAVE_ERRNO_H) + errno = ENOMEM; +#endif return NULL; + } for(n = height * width; n--; ) { @@ -167,6 +180,12 @@ static cucul_canvas_t *import_caca(void const *data, unsigned int size) } return cv; + +invalid_caca: +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return NULL; } static cucul_canvas_t *import_text(void const *data, unsigned int size) @@ -176,37 +195,45 @@ static cucul_canvas_t *import_text(void const *data, unsigned int size) unsigned int width = 1, height = 1, x = 0, y = 0, i; cv = cucul_create_canvas(width, height); + if(!cv) + { +#if defined(HAVE_ERRNO_H) + errno = ENOMEM; +#endif + return NULL; + } + cucul_set_color(cv, CUCUL_COLOR_DEFAULT, CUCUL_COLOR_TRANSPARENT); for(i = 0; i < size; i++) - { - unsigned char ch = *text++; + { + unsigned char ch = *text++; - if(ch == '\r') - continue; + if(ch == '\r') + continue; - if(ch == '\n') - { - x = 0; - y++; - continue; - } - - if(x >= width || y >= height) - { - if(x >= width) - width = x + 1; + if(ch == '\n') + { + x = 0; + y++; + continue; + } - if(y >= height) - height = y + 1; + if(x >= width || y >= height) + { + if(x >= width) + width = x + 1; - cucul_set_canvas_size(cv, width, height); - } + if(y >= height) + height = y + 1; - cucul_putchar(cv, x, y, ch); - x++; + cucul_set_canvas_size(cv, width, height); } + cucul_putchar(cv, x, y, ch); + x++; + } + return cv; } @@ -220,158 +247,166 @@ static cucul_canvas_t *import_ansi(void const *data, unsigned int size) int x = 0, y = 0, save_x = 0, save_y = 0; cv = cucul_create_canvas(width, height); + if(!cv) + { +#if defined(HAVE_ERRNO_H) + errno = ENOMEM; +#endif + return NULL; + } + ansi_parse_grcm(cv, &grcm, 1, &dummy); for(i = 0; i < size; i += skip) + { + skip = 1; + + /* Wrap long lines */ + if((unsigned int)x >= width) { - skip = 1; + x = 0; + y++; + } - /* Wrap long lines */ - if((unsigned int)x >= width) - { - x = 0; - y++; - } + if(buffer[i] == '\x1a' && size - i >= 8 + && !memcmp(buffer + i + 1, "SAUCE00", 7)) + break; /* End before SAUCE data */ - if(buffer[i] == '\x1a' && size - i >= 8 - && !memcmp(buffer + i + 1, "SAUCE00", 7)) - break; /* End before SAUCE data */ + if(buffer[i] == '\r') + continue; /* DOS sucks */ - if(buffer[i] == '\r') - continue; /* DOS sucks */ + if(buffer[i] == '\n') + { + x = 0; + y++; + continue; + } - if(buffer[i] == '\n') - { - x = 0; - y++; - continue; - } + /* Interpret escape commands, as per Standard ECMA-48 "Control + * Functions for Coded Character Sets", 5.4. Control sequences. */ + if(buffer[i] == '\x1b' && buffer[i + 1] == '[') + { + unsigned int argc = 0, argv[101]; + unsigned int param, inter, final; + + /* Compute offsets to parameter bytes, intermediate bytes and + * to the final byte. Only the final byte is mandatory, there + * can be zero of the others. + * 0 param=2 inter final final+1 + * +-----+------------------+---------------------+-----------------+ + * | CSI | parameter bytes | intermediate bytes | final byte | + * | | 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e | + * | ^[[ | 0123456789:;<=>? | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ | + * +-----+------------------+---------------------+-----------------+ + */ + param = 2; + + for(inter = param; i + inter < size; inter++) + if(buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) + break; - /* Interpret escape commands, as per Standard ECMA-48 "Control - * Functions for Coded Character Sets", 5.4. Control sequences. */ - if(buffer[i] == '\x1b' && buffer[i + 1] == '[') - { - unsigned int argc = 0, argv[101]; - unsigned int param, inter, final; - - /* Compute offsets to parameter bytes, intermediate bytes and - * to the final byte. Only the final byte is mandatory, there - * can be zero of the others. - * 0 param=2 inter final final+1 - * +-----+------------------+---------------------+-----------------+ - * | CSI | parameter bytes | intermediate bytes | final byte | - * | | 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e | - * | ^[[ | 0123456789:;<=>? | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ | - * +-----+------------------+---------------------+-----------------+ - */ - param = 2; - - for(inter = param; i + inter < size; inter++) - if(buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) - break; - - for(final = inter; i + final < size; final++) - if(buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) - break; - - if(buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) - break; /* Invalid Final Byte */ - - skip += final; - - /* Sanity checks */ - if(param < inter && buffer[i + param] >= 0x3c) - { - fprintf(stderr, "private sequence \"^[[%.*s\"\n", - final - param + 1, buffer + i + param); - continue; /* Private sequence, skip it entirely */ - } - - if(final - param > 100) - continue; /* Suspiciously long sequence, skip it */ - - /* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string - * format */ - if(param < inter) - { - argv[0] = 0; - for(j = param; j < inter; j++) - { - if(buffer[i + j] == ';') - argv[++argc] = 0; - else if(buffer[i + j] >= '0' && buffer[i + j] <= '9') - argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); - } - argc++; - } - - /* Interpret final byte. The code representations are given in - * ECMA-48 5.4: Control sequences, and the code definitions are - * given in ECMA-48 8.3: Definition of control functions. */ - switch(buffer[i + final]) - { - case 'f': /* CUP - Cursor Position */ - case 'H': /* HVP - Character And Line Position */ - x = (argc > 1) ? argv[1] - 1 : 0; - y = (argc > 0) ? argv[0] - 1 : 0; - break; - case 'A': /* CUU - Cursor Up */ - y -= argc ? argv[0] : 1; - if(y < 0) - y = 0; - break; - case 'B': /* CUD - Cursor Down */ - y += argc ? argv[0] : 1; - break; - case 'C': /* CUF - Cursor Right */ - x += argc ? argv[0] : 1; - break; - case 'D': /* CUB - Cursor Left */ - x -= argc ? argv[0] : 1; - if(x < 0) - x = 0; - break; - case 's': /* Private (save cursor position) */ - save_x = x; - save_y = y; - break; - case 'u': /* Private (reload cursor positin) */ - x = save_x; - y = save_y; - break; - case 'J': /* ED - Erase In Page */ - if(argv[0] == 2) - x = y = 0; - break; - case 'K': /* EL - Erase In Line */ - for(j = x; j < width; j++) - _cucul_putchar32(cv, j, y, (uint32_t)' '); - x = width; - break; - case 'm': /* SGR - Select Graphic Rendition */ - ansi_parse_grcm(cv, &grcm, argc, argv); - break; - default: - fprintf(stderr, "unknown command %c\n", buffer[i + final]); - break; - } - - continue; - } + for(final = inter; i + final < size; final++) + if(buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) + break; + + if(buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) + break; /* Invalid Final Byte */ + + skip += final; + + /* Sanity checks */ + if(param < inter && buffer[i + param] >= 0x3c) + { + fprintf(stderr, "private sequence \"^[[%.*s\"\n", + final - param + 1, buffer + i + param); + continue; /* Private sequence, skip it entirely */ + } - /* We're going to paste a character. First make sure the canvas - * is big enough. */ - if((unsigned int)y >= height) + if(final - param > 100) + continue; /* Suspiciously long sequence, skip it */ + + /* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string + * format */ + if(param < inter) + { + argv[0] = 0; + for(j = param; j < inter; j++) { - height = y + 1; - cucul_set_canvas_size(cv, width, height); + if(buffer[i + j] == ';') + argv[++argc] = 0; + else if(buffer[i + j] >= '0' && buffer[i + j] <= '9') + argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); } + argc++; + } + + /* Interpret final byte. The code representations are given in + * ECMA-48 5.4: Control sequences, and the code definitions are + * given in ECMA-48 8.3: Definition of control functions. */ + switch(buffer[i + final]) + { + case 'f': /* CUP - Cursor Position */ + case 'H': /* HVP - Character And Line Position */ + x = (argc > 1) ? argv[1] - 1 : 0; + y = (argc > 0) ? argv[0] - 1 : 0; + break; + case 'A': /* CUU - Cursor Up */ + y -= argc ? argv[0] : 1; + if(y < 0) + y = 0; + break; + case 'B': /* CUD - Cursor Down */ + y += argc ? argv[0] : 1; + break; + case 'C': /* CUF - Cursor Right */ + x += argc ? argv[0] : 1; + break; + case 'D': /* CUB - Cursor Left */ + x -= argc ? argv[0] : 1; + if(x < 0) + x = 0; + break; + case 's': /* Private (save cursor position) */ + save_x = x; + save_y = y; + break; + case 'u': /* Private (reload cursor positin) */ + x = save_x; + y = save_y; + break; + case 'J': /* ED - Erase In Page */ + if(argv[0] == 2) + x = y = 0; + break; + case 'K': /* EL - Erase In Line */ + for(j = x; j < width; j++) + _cucul_putchar32(cv, j, y, (uint32_t)' '); + x = width; + break; + case 'm': /* SGR - Select Graphic Rendition */ + ansi_parse_grcm(cv, &grcm, argc, argv); + break; + default: + fprintf(stderr, "unknown command %c\n", buffer[i + final]); + break; + } + + continue; + } - /* Now paste our character */ - _cucul_putchar32(cv, x, y, _cucul_cp437_to_utf32(buffer[i])); - x++; + /* We're going to paste a character. First make sure the canvas + * is big enough. */ + if((unsigned int)y >= height) + { + height = y + 1; + cucul_set_canvas_size(cv, width, height); } + /* Now paste our character */ + _cucul_putchar32(cv, x, y, _cucul_cp437_to_utf32(buffer[i])); + x++; + } + return cv; } @@ -381,82 +416,82 @@ static void ansi_parse_grcm(cucul_canvas_t *cv, struct ansi_grcm *g, unsigned int argc, unsigned int const *argv) { static uint8_t const ansi2cucul[] = - { - CUCUL_COLOR_BLACK, CUCUL_COLOR_RED, - CUCUL_COLOR_GREEN, CUCUL_COLOR_BROWN, - CUCUL_COLOR_BLUE, CUCUL_COLOR_MAGENTA, - CUCUL_COLOR_CYAN, CUCUL_COLOR_LIGHTGRAY - }; + { + CUCUL_COLOR_BLACK, CUCUL_COLOR_RED, + CUCUL_COLOR_GREEN, CUCUL_COLOR_BROWN, + CUCUL_COLOR_BLUE, CUCUL_COLOR_MAGENTA, + CUCUL_COLOR_CYAN, CUCUL_COLOR_LIGHTGRAY + }; unsigned int j; uint8_t myfg, mybg; for(j = 0; j < argc; j++) + { + /* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */ + if(argv[j] >= 30 && argv[j] <= 37) + g->fg = ansi2cucul[argv[j] - 30]; + else if(argv[j] >= 40 && argv[j] <= 47) + g->bg = ansi2cucul[argv[j] - 40]; + else if(argv[j] >= 90 && argv[j] <= 97) + g->fg = ansi2cucul[argv[j] - 90] + 8; + else if(argv[j] >= 100 && argv[j] <= 107) + g->bg = ansi2cucul[argv[j] - 100] + 8; + else switch(argv[j]) { - /* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */ - if(argv[j] >= 30 && argv[j] <= 37) - g->fg = ansi2cucul[argv[j] - 30]; - else if(argv[j] >= 40 && argv[j] <= 47) - g->bg = ansi2cucul[argv[j] - 40]; - else if(argv[j] >= 90 && argv[j] <= 97) - g->fg = ansi2cucul[argv[j] - 90] + 8; - else if(argv[j] >= 100 && argv[j] <= 107) - g->bg = ansi2cucul[argv[j] - 100] + 8; - else switch(argv[j]) - { - case 0: /* default rendition */ - g->fg = CUCUL_COLOR_DEFAULT; - g->bg = CUCUL_COLOR_DEFAULT; - g->bold = g->negative = g->concealed = 0; - break; - case 1: /* bold or increased intensity */ - g->bold = 1; - break; - case 4: /* singly underlined */ - break; - case 5: /* slowly blinking (less then 150 per minute) */ - break; - case 7: /* negative image */ - g->negative = 1; - break; - case 8: /* concealed characters */ - g->concealed = 1; - break; - case 22: /* normal colour or normal intensity (neither bold nor faint) */ - g->bold = 0; - break; - case 28: /* revealed characters */ - g->concealed = 0; - break; - case 39: /* default display colour (implementation-defined) */ - g->fg = CUCUL_COLOR_DEFAULT; - break; - case 49: /* default background colour (implementation-defined) */ - g->bg = CUCUL_COLOR_DEFAULT; - break; - default: - fprintf(stderr, "unknown sgr %i\n", argv[j]); - break; - } + case 0: /* default rendition */ + g->fg = CUCUL_COLOR_DEFAULT; + g->bg = CUCUL_COLOR_DEFAULT; + g->bold = g->negative = g->concealed = 0; + break; + case 1: /* bold or increased intensity */ + g->bold = 1; + break; + case 4: /* singly underlined */ + break; + case 5: /* slowly blinking (less then 150 per minute) */ + break; + case 7: /* negative image */ + g->negative = 1; + break; + case 8: /* concealed characters */ + g->concealed = 1; + break; + case 22: /* normal colour or normal intensity (neither bold nor faint) */ + g->bold = 0; + break; + case 28: /* revealed characters */ + g->concealed = 0; + break; + case 39: /* default display colour (implementation-defined) */ + g->fg = CUCUL_COLOR_DEFAULT; + break; + case 49: /* default background colour (implementation-defined) */ + g->bg = CUCUL_COLOR_DEFAULT; + break; + default: + fprintf(stderr, "unknown sgr %i\n", argv[j]); + break; } + } if(g->concealed) - { - myfg = mybg = CUCUL_COLOR_TRANSPARENT; - } + { + myfg = mybg = CUCUL_COLOR_TRANSPARENT; + } else - { - myfg = g->negative ? g->bg : g->fg; - mybg = g->negative ? g->fg : g->bg; + { + myfg = g->negative ? g->bg : g->fg; + mybg = g->negative ? g->fg : g->bg; - if(g->bold) - { - if(myfg < 8) - myfg += 8; - else if(myfg == CUCUL_COLOR_DEFAULT) - myfg = CUCUL_COLOR_WHITE; - } + if(g->bold) + { + if(myfg < 8) + myfg += 8; + else if(myfg == CUCUL_COLOR_DEFAULT) + myfg = CUCUL_COLOR_WHITE; } + } cucul_set_color(cv, myfg, mybg); } diff --git a/cucul/sprite.c b/cucul/sprite.c index 18031a2..69476c9 100644 --- a/cucul/sprite.c +++ b/cucul/sprite.c @@ -22,6 +22,9 @@ # include # include # include +# if defined(HAVE_ERRNO_H) +# include +# endif #endif #include "cucul.h" @@ -31,6 +34,8 @@ * * This function returns the current canvas frame count. * + * This function never fails. + * * \param cv A libcucul canvas * \return The frame count */ @@ -47,18 +52,29 @@ unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *cv) * * If the frame index is outside the canvas' frame range, nothing happens. * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Requested frame is out of range. + * * \param cv A libcucul canvas * \param frame The canvas frame to activate + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) +int cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) { if(frame >= cv->framecount) - return; + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } cv->frame = frame; cv->chars = cv->allchars[cv->frame]; cv->attr = cv->allattr[cv->frame]; + + return 0; } /** \brief Add a frame to a canvas. @@ -74,10 +90,14 @@ void cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) * The active frame does not change, but its index may be renumbered due * to the insertion. * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c ENOMEM Not enough memory to allocate new frame. + * * \param cv A libcucul canvas * \param frame The index where to insert the new frame + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) +int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) { unsigned int size = cv->width * cv->height * sizeof(uint32_t); unsigned int f; @@ -105,6 +125,8 @@ void cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) cv->chars = cv->allchars[cv->frame]; cv->attr = cv->allattr[cv->frame]; + + return 0; } /** \brief Remove a frame from a canvas. @@ -123,18 +145,33 @@ void cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) * Otherwise, the active frame does not change, but its index may be * renumbered due to the deletion. * + * If an error occurs, -1 is returned and \b errno is set accordingly: + * - \c EINVAL Requested frame is out of range, or attempt to delete the + * last frame of the canvas. + * * \param cv A libcucul canvas * \param frame The index of the frame to delete + * \return 0 in case of success, -1 if an error occurred. */ -void cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame) +int cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame) { unsigned int f; if(frame >= cv->framecount) - return; + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } if(cv->framecount == 1) - return; + { +#if defined(HAVE_ERRNO_H) + errno = EINVAL; +#endif + return -1; + } free(cv->allchars[frame]); free(cv->allattr[frame]); @@ -156,5 +193,7 @@ void cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame) cv->chars = cv->allchars[cv->frame]; cv->attr = cv->allattr[cv->frame]; + + return 0; } diff --git a/cucul/transform.c b/cucul/transform.c index d4bc15f..1faad58 100644 --- a/cucul/transform.c +++ b/cucul/transform.c @@ -33,9 +33,12 @@ static uint32_t rotatechar(uint32_t ch); * This function inverts a canvas' colours (black becomes white, red * becomes cyan, etc.) without changing the characters in it. * + * This function never fails. + * * \param cv The canvas to invert. + * \return This function always returns 0. */ -void cucul_invert(cucul_canvas_t *cv) +int cucul_invert(cucul_canvas_t *cv) { uint32_t *attr = cv->attr; unsigned int i; @@ -45,6 +48,8 @@ void cucul_invert(cucul_canvas_t *cv) *attr = *attr ^ 0x000f000f; attr++; } + + return 0; } /** \brief Flip a canvas horizontally. @@ -52,9 +57,12 @@ void cucul_invert(cucul_canvas_t *cv) * This function flips a canvas horizontally, choosing characters that * look like the mirrored version wherever possible. * + * This function never fails. + * * \param cv The canvas to flip. + * \return This function always returns 0. */ -void cucul_flip(cucul_canvas_t *cv) +int cucul_flip(cucul_canvas_t *cv) { unsigned int y; @@ -82,6 +90,8 @@ void cucul_flip(cucul_canvas_t *cv) if(cleft == cright) *cleft = flipchar(*cleft); } + + return 0; } /** \brief Flip a canvas vertically. @@ -89,9 +99,12 @@ void cucul_flip(cucul_canvas_t *cv) * This function flips a canvas vertically, choosing characters that * look like the mirrored version wherever possible. * + * This function never fails. + * * \param cv The canvas to flop. + * \return This function always returns 0. */ -void cucul_flop(cucul_canvas_t *cv) +int cucul_flop(cucul_canvas_t *cv) { unsigned int x; @@ -120,6 +133,8 @@ void cucul_flop(cucul_canvas_t *cv) if(ctop == cbottom) *ctop = flopchar(*ctop); } + + return 0; } /** \brief Rotate a canvas. @@ -128,9 +143,12 @@ void cucul_flop(cucul_canvas_t *cv) * choosing characters that look like the mirrored version wherever * possible. * + * This function never fails. + * * \param cv The canvas to rotate. + * \return This function always returns 0. */ -void cucul_rotate(cucul_canvas_t *cv) +int cucul_rotate(cucul_canvas_t *cv) { uint32_t *cbegin = cv->chars; uint32_t *cend = cbegin + cv->width * cv->height - 1; @@ -153,6 +171,8 @@ void cucul_rotate(cucul_canvas_t *cv) if(cbegin == cend) *cbegin = rotatechar(*cbegin); + + return 0; } static uint32_t flipchar(uint32_t ch)