From cfadd8b64d04623746ce517de669cad031002039 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 1 Apr 2006 15:02:05 +0000 Subject: [PATCH] * Removed CUCUL_BACKGROUND, CUCUL_ANTIALIASING and CUCUL_DITHERING environment variables handling. Replaced that with three per-bitmap functions: cucul_set_bitmap_antialias(), cucul_set_bitmap_color() and cucul_set_bitmap_dithering(). * Added cucul_set_bitmap_brightness() and cucul_set_bitmap_contrast() prototypes (but did not implement them yet). * Added cucul_set_bitmap_charset() to choose what characters are going to be used for the bitmap rendering. * Removed the now useless cucul_get_feature(), cucul_set_feature() etc. --- caca/caca.h | 34 +- cucul/bitmap.c | 972 ++++++++++++++++++++++++++-------------- cucul/cucul.c | 147 ------ cucul/cucul.h | 98 ++-- cucul/cucul_internals.h | 3 - test/demo.c | 6 +- 6 files changed, 673 insertions(+), 587 deletions(-) diff --git a/caca/caca.h b/caca/caca.h index b2a6d5a..fc9abf8 100644 --- a/caca/caca.h +++ b/caca/caca.h @@ -30,8 +30,8 @@ * using the conio library, and on Windows systems using either slang or * ncurses (through Cygwin emulation) or conio. There is also a native X11 * driver, and an OpenGL driver (through freeglut) that does not require a - * text terminal. For machines without a screen, and with a valid tcp stack, - * the network driver (BSD sockets) should perfectly fit your needs. + * text terminal. For machines without a screen, the raw driver can be used + * to send the output to another machine, using for instance cacaserver. * * \e libcaca is free software, released under the Do What The Fuck You * Want To Public License. This ensures that no one, not even the \e libcaca @@ -51,8 +51,8 @@ * \section env Environment variables * * Some environment variables can be used to change the behaviour of - * \e libcaca or \e libcucul without having to modify the program which - * uses them. These variables are: + * \e libcaca without having to modify the program which uses them. These + * variables are: * * \li \b CACA_DRIVER: set the backend video driver. In order of preference: * - \c conio uses the DOS conio.h interface. @@ -60,30 +60,8 @@ * - \c slang uses the S-Lang library. * - \c x11 uses the native X11 driver. * - \c gl uses freeglut and opengl libraries. - * - \c network uses BSD sockets calls. - * - * \li \b CUCUL_BACKGROUND: set the background type. - * - \c solid uses solid coloured backgrounds for all characters. This - * feature does not work with all terminal emulators. This is the - * default choice. - * - \c black uses only black backgrounds to render characters. - * - * \li \b CUCUL_ANTIALIASING: set the antialiasing mode. Antialiasing - * smoothens the rendered image and avoids the commonly seen staircase - * effect. - * - \c none disables antialiasing. - * - \c prefilter uses a simple prefilter antialiasing method. This is - * the default choice. - * - * \li \b CUCUL_DITHERING: set the dithering mode. Dithering is necessary - * when rendering a picture that has more colours than the usually - * available palette. - * - \c none disables dithering. - * - \c ordered2 uses a 2x2 Bayer matrix for dithering. - * - \c ordered4 uses a 4x4 Bayer matrix for dithering. This is the - * default choice. - * - \c ordered8 uses a 8x8 Bayer matrix for dithering. - * - \c random uses random dithering. + * - \c raw outputs to the standard output instead of rendering the + * canvas. This is can be used together with cacaserver. * * \li \b CACA_GEOMETRY: set the video display size. The format of this * variable must be XxY, with X and Y being integer values. This option diff --git a/cucul/bitmap.c b/cucul/bitmap.c index d74e29d..6ce42fc 100644 --- a/cucul/bitmap.c +++ b/cucul/bitmap.c @@ -85,7 +85,62 @@ static int const rgb_weight[] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; +/* List of glyphs */ +static char const * ascii_glyphs[] = +{ + " ", ".", ":", ";", "t", "%", "S", "X", "@", "8", "?" +}; + +static char const * shades_glyphs[] = +{ + " ", ":", "░", "▒", "?" +}; + +static char const * blocks_glyphs[] = +{ + " ", "▘", "▚", "?" +}; + #if !defined(_DOXYGEN_SKIP_ME) +enum color_mode +{ + COLOR_MODE_MONO, + COLOR_MODE_GRAY, + COLOR_MODE_8, + COLOR_MODE_16, + COLOR_MODE_FULLGRAY, + COLOR_MODE_FULL8, + COLOR_MODE_FULL16, +}; + +struct cucul_bitmap +{ + int bpp, has_palette, has_alpha; + int w, h, pitch; + int rmask, gmask, bmask, amask; + int rright, gright, bright, aright; + int rleft, gleft, bleft, aleft; + void (*get_hsv)(struct cucul_bitmap *, char *, int, int); + int red[256], green[256], blue[256], alpha[256]; + float gamma; + int gammatab[4097]; + + /* Bitmap features */ + int invert, antialias; + + /* Colour mode used for rendering */ + enum color_mode color_mode; + + /* Glyphs used for rendering */ + char const * const * glyphs; + unsigned glyph_count; + + /* Current dithering method */ + void (*init_dither) (int); + unsigned int (*get_dither) (void); + void (*increment_dither) (void); +}; + #define HSV_XRATIO 6 #define HSV_YRATIO 3 #define HSV_HRATIO 3 @@ -111,16 +166,17 @@ static void mask2shift(unsigned int, int *, int *); static float gammapow(float x, float y); static void get_rgba_default(struct cucul_bitmap const *, uint8_t *, int, int, - unsigned int *, unsigned int *, unsigned int *, unsigned int *); -static inline void rgb2hsv_default(int, int, int, int *, int *, int *); -static inline int sq(int); /* Dithering methods */ static void init_no_dither(int); static unsigned int get_no_dither(void); static void increment_no_dither(void); +static void init_fstein_dither(int); +static unsigned int get_fstein_dither(void); +static void increment_fstein_dither(void); + static void init_ordered2_dither(int); static unsigned int get_ordered2_dither(void); static void increment_ordered2_dither(void); @@ -137,107 +193,40 @@ static void init_random_dither(int); static unsigned int get_random_dither(void); static void increment_random_dither(void); -#if !defined(_DOXYGEN_SKIP_ME) -struct cucul_bitmap -{ - int bpp, has_palette, has_alpha; - int w, h, pitch; - int rmask, gmask, bmask, amask; - int rright, gright, bright, aright; - int rleft, gleft, bleft, aleft; - void (*get_hsv)(struct cucul_bitmap *, char *, int, int); - int red[256], green[256], blue[256], alpha[256]; - float gamma; - int gammatab[4097]; - unsigned char invert; -}; -#endif - -static void mask2shift(unsigned int mask, int *right, int *left) +static inline int sq(int x) { - int rshift = 0, lshift = 0; - - if(!mask) - { - *right = *left = 0; - return; - } - - while(!(mask & 1)) - { - mask >>= 1; - rshift++; - } - *right = rshift; - - while(mask & 1) - { - mask >>= 1; - lshift++; - } - *left = 12 - lshift; + return x * x; } -static float gammapow(float x, float y) +static inline void rgb2hsv_default(int r, int g, int b, + int *hue, int *sat, int *val) { -#ifdef HAVE_FLDLN2 - register double logx; - register long double v, e; -#else - register float tmp, t, t2, r; - int i; -#endif + int min, max, delta; - if(x == 0.0) - return y == 0.0 ? 1.0 : 0.0; + min = r; max = r; + if(min > g) min = g; if(max < g) max = g; + if(min > b) min = b; if(max < b) max = b; -#ifdef HAVE_FLDLN2 - /* FIXME: this can be optimised by directly calling fyl2x for x and y */ - asm volatile("fldln2; fxch; fyl2x" - : "=t" (logx) : "0" (x) : "st(1)"); + delta = max - min; /* 0 - 0xfff */ + *val = max; /* 0 - 0xfff */ - asm volatile("fldl2e\n\t" - "fmul %%st(1)\n\t" - "fst %%st(1)\n\t" - "frndint\n\t" - "fxch\n\t" - "fsub %%st(1)\n\t" - "f2xm1\n\t" - : "=t" (v), "=u" (e) : "0" (y * logx)); - v += 1.0; - asm volatile("fscale" - : "=t" (v) : "0" (v), "u" (e)); - return v; -#else - /* Compute ln(x) for x ∈ ]0,1] - * ln(x) = 2 * (t + t^3/3 + t^5/5 + ...) with t = (x-1)/(x+1) - * The convergence is a bit slow, especially when x is near 0. */ - t = (x - 1.0) / (x + 1.0); - t2 = t * t; - tmp = r = t; - for(i = 3; i < 20; i += 2) + if(delta) { - r *= t2; - tmp += r / i; - } - - /* Compute -y*ln(x) */ - tmp = - y * 2.0 * tmp; + *sat = 0xfff * delta / max; /* 0 - 0xfff */ - /* Compute x^-y as e^t where t = -y*ln(x): - * e^t = 1 + t/1! + t^2/2! + t^3/3! + t^4/4! + t^5/5! ... - * The convergence is quite faster here, thanks to the factorial. */ - r = t = tmp; - tmp = 1.0 + t; - for(i = 2; i < 16; i++) + /* Generate *hue between 0 and 0x5fff */ + if( r == max ) + *hue = 0x1000 + 0x1000 * (g - b) / delta; + else if( g == max ) + *hue = 0x3000 + 0x1000 * (b - r) / delta; + else + *hue = 0x5000 + 0x1000 * (r - g) / delta; + } + else { - r = r * t / i; - tmp += r; + *sat = 0; + *hue = 0; } - - /* Return x^y as 1/(x^-y) */ - return 1.0 / tmp; -#endif } /** @@ -310,12 +299,20 @@ struct cucul_bitmap *cucul_create_bitmap(unsigned int bpp, unsigned int w, } } + /* Default features */ + bitmap->invert = 0; + bitmap->antialias = 1; + /* Default gamma value */ for(i = 0; i < 4096; i++) bitmap->gammatab[i] = i; - /* No color inversion by default */ - bitmap->invert = 0; + /* Default colour mode */ + bitmap->color_mode = COLOR_MODE_FULL16; + + /* Default character set */ + bitmap->glyphs = ascii_glyphs; + bitmap->glyph_count = sizeof(ascii_glyphs) / sizeof(*ascii_glyphs); return bitmap; } @@ -362,6 +359,19 @@ void cucul_set_bitmap_palette(struct cucul_bitmap *bitmap, bitmap->has_alpha = has_alpha; } +/** + * \brief Set the brightness of a bitmap object. + * + * Set the brightness of bitmap. + * + * \param bitmap Bitmap object. + * \param brightness brightness value. + */ +void cucul_set_bitmap_brightness(struct cucul_bitmap *bitmap, float brightness) +{ + /* FIXME */ +} + /** * \brief Set the gamma of a bitmap object. * @@ -372,6 +382,9 @@ void cucul_set_bitmap_palette(struct cucul_bitmap *bitmap, */ void cucul_set_bitmap_gamma(struct cucul_bitmap *bitmap, float gamma) { + /* FIXME: we don't need 4096 calls to gammapow(), we can 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) @@ -383,6 +396,33 @@ void cucul_set_bitmap_gamma(struct cucul_bitmap *bitmap, float gamma) bitmap->gammatab[i] = 4096.0 * gammapow((float)i / 4096.0, 1.0 / gamma); } +/** + * \brief Set the contrast of a bitmap object. + * + * Set the contrast of bitmap. + * + * \param bitmap Bitmap object. + * \param contrast contrast value. + */ +void cucul_set_bitmap_contrast(struct cucul_bitmap *bitmap, float contrast) +{ + /* FIXME */ +} + +/** + * \brief Set bitmap antialiasing + * + * Tell the renderer whether to antialias the bitmap. Antialiasing smoothen + * the rendered image and avoids the commonly seen staircase effect. The + * method used is a simple prefilter antialiasing. + * + * \param bitmap Bitmap object. + * \param value 0 to disable antialiasing, 1 to activate it. + */ +void cucul_set_bitmap_antialias(struct cucul_bitmap *bitmap, int value) +{ + bitmap->antialias = value ? 1 : 0; +} /** * \brief Invert colors of bitmap @@ -392,118 +432,241 @@ void cucul_set_bitmap_gamma(struct cucul_bitmap *bitmap, float gamma) * \param bitmap Bitmap object. * \param value 0 for normal behaviour, 1 for invert */ -void cucul_set_bitmap_invert(struct cucul_bitmap *bitmap, unsigned char value) +void cucul_set_bitmap_invert(struct cucul_bitmap *bitmap, int value) { - bitmap->invert = (value==0)?0:1; + bitmap->invert = value ? 1 : 0; } - - /** - * \brief Free the memory associated with a bitmap. + * \brief Choose colours used for bitmap rendering * - * Free the memory allocated by cucul_create_bitmap(). + * Tell the renderer which colours should be used to render the + * bitmap. Valid values for \e str are: + * + * \li \e "mono": use light gray on a black background. + * + * \li \e "gray": use white and two shades of gray on a black background. + * + * \li \e "8": use the 8 ANSI colours on a black background. + * + * \li \e "16": use the 16 ANSI colours on a black background. + * + * \li \e "fullgray": use black, white and two shades of gray for both the + * characters and the background. + * + * \li \e "full8": use the 8 ANSI colours for both the characters and the + * background. + * + * \li \e "full16": use the 16 ANSI colours for both the characters and the + * background. This is the default value. * * \param bitmap Bitmap object. + * \param str A string describing the colour set that will be used + * for the bitmap rendering. */ -void cucul_free_bitmap(struct cucul_bitmap *bitmap) +void cucul_set_bitmap_color(struct cucul_bitmap *bitmap, char const *str) { - if(!bitmap) - return; - - free(bitmap); + if(!strcasecmp(str, "mono")) + bitmap->color_mode = COLOR_MODE_MONO; + else if(!strcasecmp(str, "gray")) + bitmap->color_mode = COLOR_MODE_GRAY; + else if(!strcasecmp(str, "8")) + bitmap->color_mode = COLOR_MODE_8; + else if(!strcasecmp(str, "16")) + bitmap->color_mode = COLOR_MODE_16; + else if(!strcasecmp(str, "fullgray")) + bitmap->color_mode = COLOR_MODE_FULLGRAY; + else if(!strcasecmp(str, "full8")) + bitmap->color_mode = COLOR_MODE_FULL8; + else /* "full16" is the default */ + bitmap->color_mode = COLOR_MODE_FULL16; } -static void get_rgba_default(struct cucul_bitmap const *bitmap, uint8_t *pixels, - int x, int y, unsigned int *r, unsigned int *g, - unsigned int *b, unsigned int *a) +/** + * \brief Get available colour modes + * + * Return a list of available colour modes for a given bitmap. The list + * is a NULL-terminated array of strings, interleaving a string containing + * the internal value for the colour mode, to be used with + * \e cucul_set_bitmap_color(), and a string containing the natural + * language description for that colour mode. + * + * \param bitmap Bitmap object. + * \return An array of strings. + */ +char const * const * + cucul_get_bitmap_color_list(struct cucul_bitmap const *bitmap) { - uint32_t bits; + static char const * const list[] = + { + "mono", "white on black", + "gray", "grayscale on black", + "8", "8 colours on black", + "16", "16 colours on black", + "fullgray", "full grayscale", + "full8", "full 8 colours", + "full16", "full 16 colours", + NULL, NULL + }; - pixels += (bitmap->bpp / 8) * x + bitmap->pitch * y; + return list; +} - switch(bitmap->bpp / 8) +/** + * \brief Choose characters used for bitmap rendering + * + * Tell the renderer which characters should be used to render the + * bitmap. Valid values for \e str are: + * + * \li \e "ascii": use only ASCII characters. This is the default value. + * + * \li \e "shades": use Unicode characters "U+2591 LIGHT SHADE", "U+2592 + * MEDIUM SHADE" and "U+2593 DARK SHADE". These characters are also + * present in the CP437 codepage available on DOS and VGA. + * + * \li \e "blocks": use Unicode quarter-cell block combinations. These + * characters are only found in the Unicode set. + * + * \param bitmap Bitmap object. + * \param str A string describing the characters that need to be used + * for the bitmap rendering. + */ +void cucul_set_bitmap_charset(struct cucul_bitmap *bitmap, char const *str) +{ + if(!strcasecmp(str, "shades")) { - case 4: - bits = *(uint32_t *)pixels; - break; - case 3: - { -#if defined(HAVE_ENDIAN_H) - if(__BYTE_ORDER == __BIG_ENDIAN) -#else - /* This is compile-time optimised with at least -O1 or -Os */ - uint32_t const rmask = 0x12345678; - if(*(uint8_t const *)&rmask == 0x12) -#endif - bits = ((uint32_t)pixels[0] << 16) | - ((uint32_t)pixels[1] << 8) | - ((uint32_t)pixels[2]); - else - bits = ((uint32_t)pixels[2] << 16) | - ((uint32_t)pixels[1] << 8) | - ((uint32_t)pixels[0]); - break; - } - case 2: - bits = *(uint16_t *)pixels; - break; - case 1: - default: - bits = pixels[0]; - break; + bitmap->glyphs = shades_glyphs; + bitmap->glyph_count = sizeof(shades_glyphs) / sizeof(*shades_glyphs); } - - if(bitmap->has_palette) + else if(!strcasecmp(str, "blocks")) { - *r += bitmap->gammatab[bitmap->red[bits]]; - *g += bitmap->gammatab[bitmap->green[bits]]; - *b += bitmap->gammatab[bitmap->blue[bits]]; - *a += bitmap->alpha[bits]; + bitmap->glyphs = blocks_glyphs; + bitmap->glyph_count = sizeof(blocks_glyphs) / sizeof(*blocks_glyphs); } - else + else /* "ascii" is the default */ { - *r += bitmap->gammatab[((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft]; - *g += bitmap->gammatab[((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft]; - *b += bitmap->gammatab[((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft]; - *a += ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft; + bitmap->glyphs = ascii_glyphs; + bitmap->glyph_count = sizeof(ascii_glyphs) / sizeof(*ascii_glyphs); } } -static inline void rgb2hsv_default(int r, int g, int b, - int *hue, int *sat, int *val) +/** + * \brief Get available bitmap character sets + * + * Return a list of available character sets for a given bitmap. The list + * is a NULL-terminated array of strings, interleaving a string containing + * the internal value for the character set, to be used with + * \e cucul_set_bitmap_charset(), and a string containing the natural + * language description for that character set. + * + * \param bitmap Bitmap object. + * \return An array of strings. + */ +char const * const * + cucul_get_bitmap_charset_list(struct cucul_bitmap const *bitmap) { - int min, max, delta; - - min = r; max = r; - if(min > g) min = g; if(max < g) max = g; - if(min > b) min = b; if(max < b) max = b; + static char const * const list[] = + { + "ascii", "plain ASCII", + "shades", "CP437 shades", + "blocks", "Unicode blocks", + NULL, NULL + }; - delta = max - min; /* 0 - 0xfff */ - *val = max; /* 0 - 0xfff */ + return list; +} - if(delta) +/** + * \brief Set bitmap dithering method + * + * Tell the renderer which dithering method should be used to render the + * bitmap. Dithering is necessary because the picture being rendered has + * usually far more colours than the available palette. Valid values for + * \e str are: + * + * \li \e "none": no dithering is used, the nearest matching colour is used. + * + * \li \e "ordered2": use a 2x2 Bayer matrix for dithering. + * + * \li \e "ordered4": use a 4x4 Bayer matrix for dithering. + * + * \li \e "ordered8": use a 8x8 Bayer matrix for dithering. + * + * \li \e "random": use random dithering. + * + * \li \e "fstein": use Floyd-Steinberg dithering. This is the default value. + * + * \param bitmap Bitmap object. + * \param str A string describing the dithering method that needs to be used + * for the bitmap rendering. + */ +void cucul_set_bitmap_dithering(struct cucul_bitmap *bitmap, char const *str) +{ + if(!strcasecmp(str, "none")) { - *sat = 0xfff * delta / max; /* 0 - 0xfff */ - - /* Generate *hue between 0 and 0x5fff */ - if( r == max ) - *hue = 0x1000 + 0x1000 * (g - b) / delta; - else if( g == max ) - *hue = 0x3000 + 0x1000 * (b - r) / delta; - else - *hue = 0x5000 + 0x1000 * (r - g) / delta; + bitmap->init_dither = init_no_dither; + bitmap->get_dither = get_no_dither; + bitmap->increment_dither = increment_no_dither; } - else + else if(!strcasecmp(str, "ordered2")) { - *sat = 0; - *hue = 0; + bitmap->init_dither = init_ordered2_dither; + bitmap->get_dither = get_ordered2_dither; + bitmap->increment_dither = increment_ordered2_dither; + } + else if(!strcasecmp(str, "ordered4")) + { + bitmap->init_dither = init_ordered4_dither; + bitmap->get_dither = get_ordered4_dither; + bitmap->increment_dither = increment_ordered4_dither; + } + else if(!strcasecmp(str, "ordered4")) + { + bitmap->init_dither = init_ordered8_dither; + bitmap->get_dither = get_ordered8_dither; + bitmap->increment_dither = increment_ordered8_dither; + } + else if(!strcasecmp(str, "random")) + { + bitmap->init_dither = init_random_dither; + bitmap->get_dither = get_random_dither; + bitmap->increment_dither = increment_random_dither; + } + else /* "fstein" is the default */ + { + bitmap->init_dither = init_fstein_dither; + bitmap->get_dither = get_fstein_dither; + bitmap->increment_dither = increment_fstein_dither; } } -static inline int sq(int x) +/** + * \brief Get bitmap dithering methods + * + * Return a list of available dithering methods for a given bitmap. The list + * is a NULL-terminated array of strings, interleaving a string containing + * the internal value for the dithering method, to be used with + * \e cucul_set_bitmap_dithering(), and a string containing the natural + * language description for that dithering method. + * + * \param bitmap Bitmap object. + * \return An array of strings. + */ +char const * const * + cucul_get_bitmap_dithering_list(struct cucul_bitmap const *bitmap) { - return x * x; + static char const * const list[] = + { + "none", "no dithering", + "ordered2", "2x2 ordered dithering", + "ordered2", "2x2 ordered dithering", + "ordered2", "2x2 ordered dithering", + "random", "random dithering", + "fstein", "Floyd-Steinberg dithering", + NULL, NULL + }; + + return list; } /** @@ -522,29 +685,10 @@ static inline int sq(int x) void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, struct cucul_bitmap const *bitmap, void *pixels) { - /* Current dithering method */ - void (*_init_dither) (int); - unsigned int (*_get_dither) (void); - void (*_increment_dither) (void); - int *floyd_steinberg, *fs_r, *fs_g, *fs_b; int fs_length; - - /* FIXME: choose better characters! */ -#if !defined(_DOXYGEN_SKIP_ME) -# define DCHMAX ((sizeof(density_chars)/sizeof(*density_chars))) -#endif - static char const * density_chars[] = - { -#if CP437 - " ", ":", "░", "▒", "?" - /* "0", "1", "2", "3", "?" */ -#else - " ", ".", ":", ";", "t", "%", "S", "X", "@", "8", "?" -#endif - }; - int x, y, w, h, pitch, deltax, deltay; + unsigned int dchmax; if(!bitmap || !pixels) return; @@ -565,49 +709,7 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, deltax = x2 - x1 + 1; deltay = y2 - y1 + 1; - - switch(qq->dithering) - { - case CUCUL_DITHERING_NONE: - _init_dither = init_no_dither; - _get_dither = get_no_dither; - _increment_dither = increment_no_dither; - break; - - case CUCUL_DITHERING_ORDERED2: - _init_dither = init_ordered2_dither; - _get_dither = get_ordered2_dither; - _increment_dither = increment_ordered2_dither; - break; - - case CUCUL_DITHERING_ORDERED4: - _init_dither = init_ordered4_dither; - _get_dither = get_ordered4_dither; - _increment_dither = increment_ordered4_dither; - break; - - case CUCUL_DITHERING_ORDERED8: - _init_dither = init_ordered8_dither; - _get_dither = get_ordered8_dither; - _increment_dither = increment_ordered8_dither; - break; - - case CUCUL_DITHERING_RANDOM: - _init_dither = init_random_dither; - _get_dither = get_random_dither; - _increment_dither = increment_random_dither; - break; - - case CUCUL_DITHERING_FSTEIN: - _init_dither = init_no_dither; - _get_dither = get_no_dither; - _increment_dither = increment_no_dither; - break; - - default: - /* Something wicked happened! */ - return; - } + dchmax = bitmap->glyph_count; fs_length = ((int)qq->width <= x2 ? (int)qq->width : x2) + 1; floyd_steinberg = malloc(3 * (fs_length + 2) * sizeof(int)); @@ -620,13 +722,13 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, { int remain_r = 0, remain_g = 0, remain_b = 0; - for(x = x1 > 0 ? x1 : 0, _init_dither(y); + for(x = x1 > 0 ? x1 : 0, bitmap->init_dither(y); x <= x2 && x <= (int)qq->width; x++) { unsigned int i; int ch = 0, distmin; - unsigned int r, g, b, a; + unsigned int rgba[4]; int fg_r = 0, fg_g = 0, fg_b = 0, bg_r, bg_g, bg_b; int fromx, fromy, tox, toy, myx, myy, dots, dist; int error[3]; @@ -634,10 +736,10 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, enum cucul_color outfg = 0, outbg = 0; char const *outch; - r = g = b = a = 0; + rgba[0] = rgba[1] = rgba[2] = rgba[3] = 0; /* First get RGB */ - if(qq->antialiasing == CUCUL_ANTIALIASING_PREFILTER) + if(bitmap->antialias) { fromx = (x - x1) * w / deltax; fromy = (y - y1) * h / deltay; @@ -654,14 +756,14 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, for(myy = fromy; myy < toy; myy++) { dots++; - get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a); + get_rgba_default(bitmap, pixels, myx, myy, rgba); } /* Normalize */ - r /= dots; - g /= dots; - b /= dots; - a /= dots; + rgba[0] /= dots; + rgba[1] /= dots; + rgba[2] /= dots; + rgba[3] /= dots; } else { @@ -676,10 +778,10 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, myx = (fromx + tox) / 2; myy = (fromy + toy) / 2; - get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a); + get_rgba_default(bitmap, pixels, myx, myy, rgba); } - if(bitmap->has_alpha && a < 0x800) + if(bitmap->has_alpha && rgba[3] < 0x800) { remain_r = remain_g = remain_b = 0; fs_r[x] = 0; @@ -688,25 +790,26 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, continue; } - if(qq->dithering == CUCUL_DITHERING_FSTEIN) + /* XXX: OMG HAX */ + if(bitmap->init_dither == init_fstein_dither) { - r += remain_r; - g += remain_g; - b += remain_b; + rgba[0] += remain_r; + rgba[1] += remain_g; + rgba[2] += remain_b; } else { - r += (_get_dither() - 0x80) * 4; - g += (_get_dither() - 0x80) * 4; - b += (_get_dither() - 0x80) * 4; + rgba[0] += (bitmap->get_dither() - 0x80) * 4; + rgba[1] += (bitmap->get_dither() - 0x80) * 4; + rgba[2] += (bitmap->get_dither() - 0x80) * 4; } distmin = INT_MAX; for(i = 0; i < 16; i++) { - dist = sq(r - rgb_palette[i * 3]) - + sq(g - rgb_palette[i * 3 + 1]) - + sq(b - rgb_palette[i * 3 + 2]); + dist = sq(rgba[0] - rgb_palette[i * 3]) + + sq(rgba[1] - rgb_palette[i * 3 + 1]) + + sq(rgba[2] - rgb_palette[i * 3 + 2]); dist *= rgb_weight[i]; if(dist < distmin) { @@ -718,16 +821,17 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, bg_g = rgb_palette[outbg * 3 + 1]; bg_b = rgb_palette[outbg * 3 + 2]; - if(qq->background == CUCUL_BACKGROUND_SOLID) + /* FIXME: we currently only honour "full16" */ + if(bitmap->color_mode == COLOR_MODE_FULL16) { distmin = INT_MAX; for(i = 0; i < 16; i++) { if(i == outbg) continue; - dist = sq(r - rgb_palette[i * 3]) - + sq(g - rgb_palette[i * 3 + 1]) - + sq(b - rgb_palette[i * 3 + 2]); + dist = sq(rgba[0] - rgb_palette[i * 3]) + + sq(rgba[1] - rgb_palette[i * 3 + 1]) + + sq(rgba[2] - rgb_palette[i * 3 + 2]); dist *= rgb_weight[i]; if(dist < distmin) { @@ -740,14 +844,14 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, fg_b = rgb_palette[outfg * 3 + 2]; distmin = INT_MAX; - for(i = 0; i < DCHMAX - 1; i++) + for(i = 0; i < dchmax - 1; i++) { - int newr = i * fg_r + ((2*DCHMAX-1) - i) * bg_r; - int newg = i * fg_g + ((2*DCHMAX-1) - i) * bg_g; - int newb = i * fg_b + ((2*DCHMAX-1) - i) * bg_b; - dist = abs(r * (2*DCHMAX-1) - newr) - + abs(g * (2*DCHMAX-1) - newg) - + abs(b * (2*DCHMAX-1) - newb); + int newr = i * fg_r + ((2*dchmax-1) - i) * bg_r; + int newg = i * fg_g + ((2*dchmax-1) - i) * bg_g; + int newb = i * fg_b + ((2*dchmax-1) - i) * bg_b; + dist = abs(rgba[0] * (2*dchmax-1) - newr) + + abs(rgba[1] * (2*dchmax-1) - newg) + + abs(rgba[2] * (2*dchmax-1) - newb); if(dist < distmin) { @@ -755,37 +859,42 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, distmin = dist; } } - outch = density_chars[ch]; + outch = bitmap->glyphs[ch]; - if(qq->dithering == CUCUL_DITHERING_FSTEIN) + /* XXX: OMG HAX */ + if(bitmap->init_dither == init_fstein_dither) { - error[0] = r - (fg_r * ch + bg_r * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); - error[1] = g - (fg_g * ch + bg_g * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); - error[2] = b - (fg_b * ch + bg_b * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); + error[0] = rgba[0] - (fg_r * ch + bg_r * ((2*dchmax-1) - ch)) / (2*dchmax-1); + error[1] = rgba[1] - (fg_g * ch + bg_g * ((2*dchmax-1) - ch)) / (2*dchmax-1); + error[2] = rgba[2] - (fg_b * ch + bg_b * ((2*dchmax-1) - ch)) / (2*dchmax-1); } } else { - unsigned int lum = r; if(g > lum) lum = g; if(b > lum) lum = b; + unsigned int lum = rgba[0]; + if(rgba[1] > lum) lum = rgba[1]; + if(rgba[2] > lum) lum = rgba[2]; outfg = outbg; outbg = CUCUL_COLOR_BLACK; - ch = lum * DCHMAX / 0x1000; + ch = lum * dchmax / 0x1000; if(ch < 0) ch = 0; - else if(ch > (int)(DCHMAX - 1)) - ch = DCHMAX - 1; - outch = density_chars[ch]; + else if(ch > (int)(dchmax - 1)) + ch = dchmax - 1; + outch = bitmap->glyphs[ch]; - if(qq->dithering == CUCUL_DITHERING_FSTEIN) + /* XXX: OMG HAX */ + if(bitmap->init_dither == init_fstein_dither) { - error[0] = r - bg_r * ch / (DCHMAX-1); - error[1] = g - bg_g * ch / (DCHMAX-1); - error[2] = b - bg_b * ch / (DCHMAX-1); + error[0] = rgba[0] - bg_r * ch / (dchmax-1); + error[1] = rgba[1] - bg_g * ch / (dchmax-1); + error[2] = rgba[2] - bg_b * ch / (dchmax-1); } } - if(qq->dithering == CUCUL_DITHERING_FSTEIN) + /* XXX: OMG HAX */ + if(bitmap->init_dither == init_fstein_dither) { remain_r = fs_r[x+1] + 7 * error[0] / 16; remain_g = fs_g[x+1] + 7 * error[1] / 16; @@ -801,16 +910,17 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, fs_b[x+1] = 1 * error[2] / 16; } - if(bitmap->invert) { - outfg = 15-outfg; - outbg = 15-outbg; + if(bitmap->invert) + { + outfg = 15 - outfg; + outbg = 15 - outbg; } /* Now output the character */ cucul_set_color(qq, outfg, outbg); cucul_putstr(qq, x, y, outch); - _increment_dither(); + bitmap->increment_dither(); } /* end loop */ } @@ -818,74 +928,168 @@ void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, free(floyd_steinberg); } -#if !defined(_DOXYGEN_SKIP_ME) -int _cucul_init_bitmap(void) +/** + * \brief Free the memory associated with a bitmap. + * + * Free the memory allocated by cucul_create_bitmap(). + * + * \param bitmap Bitmap object. + */ +void cucul_free_bitmap(struct cucul_bitmap *bitmap) { - unsigned int v, s, h; + if(!bitmap) + return; - /* These ones are constant */ - lookup_colors[0] = CUCUL_COLOR_BLACK; - lookup_colors[1] = CUCUL_COLOR_DARKGRAY; - lookup_colors[2] = CUCUL_COLOR_LIGHTGRAY; - lookup_colors[3] = CUCUL_COLOR_WHITE; + free(bitmap); +} - /* These ones will be overwritten */ - lookup_colors[4] = CUCUL_COLOR_MAGENTA; - lookup_colors[5] = CUCUL_COLOR_LIGHTMAGENTA; - lookup_colors[6] = CUCUL_COLOR_RED; - lookup_colors[7] = CUCUL_COLOR_LIGHTRED; +/* + * XXX: The following functions are local. + */ - for(v = 0; v < LOOKUP_VAL; v++) - for(s = 0; s < LOOKUP_SAT; s++) - for(h = 0; h < LOOKUP_HUE; h++) +/* Convert a mask, eg. 0x0000ff00, to shift values, eg. 8 and -4. */ +static void mask2shift(unsigned int mask, int *right, int *left) +{ + int rshift = 0, lshift = 0; + + if(!mask) { - int i, distbg, distfg, dist; - int val, sat, hue; - unsigned char outbg, outfg; + *right = *left = 0; + return; + } - val = 0xfff * v / (LOOKUP_VAL - 1); - sat = 0xfff * s / (LOOKUP_SAT - 1); - hue = 0xfff * h / (LOOKUP_HUE - 1); + while(!(mask & 1)) + { + mask >>= 1; + rshift++; + } + *right = rshift; - /* Initialise distances to the distance between pure black HSV - * coordinates and our white colour (3) */ - outbg = outfg = 3; - distbg = distfg = HSV_DISTANCE(0, 0, 0, 3); + while(mask & 1) + { + mask >>= 1; + lshift++; + } + *left = 12 - lshift; +} - /* Calculate distances to eight major colour values and store the - * two nearest points in our lookup table. */ - for(i = 0; i < 8; i++) - { - dist = HSV_DISTANCE(hue, sat, val, i); - if(dist <= distbg) - { - outfg = outbg; - distfg = distbg; - outbg = i; - distbg = dist; - } - else if(dist <= distfg) - { - outfg = i; - distfg = dist; - } - } +/* Compute x^y without relying on the math library */ +static float gammapow(float x, float y) +{ +#ifdef HAVE_FLDLN2 + register double logx; + register long double v, e; +#else + register float tmp, t, t2, r; + int i; +#endif - hsv_distances[v][s][h] = (outfg << 4) | outbg; + if(x == 0.0) + return y == 0.0 ? 1.0 : 0.0; + +#ifdef HAVE_FLDLN2 + /* FIXME: this can be optimised by directly calling fyl2x for x and y */ + asm volatile("fldln2; fxch; fyl2x" + : "=t" (logx) : "0" (x) : "st(1)"); + + asm volatile("fldl2e\n\t" + "fmul %%st(1)\n\t" + "fst %%st(1)\n\t" + "frndint\n\t" + "fxch\n\t" + "fsub %%st(1)\n\t" + "f2xm1\n\t" + : "=t" (v), "=u" (e) : "0" (y * logx)); + v += 1.0; + asm volatile("fscale" + : "=t" (v) : "0" (v), "u" (e)); + return v; +#else + /* Compute ln(x) for x ∈ ]0,1] + * ln(x) = 2 * (t + t^3/3 + t^5/5 + ...) with t = (x-1)/(x+1) + * The convergence is a bit slow, especially when x is near 0. */ + t = (x - 1.0) / (x + 1.0); + t2 = t * t; + tmp = r = t; + for(i = 3; i < 20; i += 2) + { + r *= t2; + tmp += r / i; } - return 0; + /* Compute -y*ln(x) */ + tmp = - y * 2.0 * tmp; + + /* Compute x^-y as e^t where t = -y*ln(x): + * e^t = 1 + t/1! + t^2/2! + t^3/3! + t^4/4! + t^5/5! ... + * The convergence is quite faster here, thanks to the factorial. */ + r = t = tmp; + tmp = 1.0 + t; + for(i = 2; i < 16; i++) + { + r = r * t / i; + tmp += r; + } + + /* Return x^y as 1/(x^-y) */ + return 1.0 / tmp; +#endif } -int _cucul_end_bitmap(void) +static void get_rgba_default(struct cucul_bitmap const *bitmap, uint8_t *pixels, + int x, int y, unsigned int *rgba) { - return 0; -} -#endif /* _DOXYGEN_SKIP_ME */ + uint32_t bits; -/* - * XXX: The following functions are local. - */ + pixels += (bitmap->bpp / 8) * x + bitmap->pitch * y; + + switch(bitmap->bpp / 8) + { + case 4: + bits = *(uint32_t *)pixels; + break; + case 3: + { +#if defined(HAVE_ENDIAN_H) + if(__BYTE_ORDER == __BIG_ENDIAN) +#else + /* This is compile-time optimised with at least -O1 or -Os */ + uint32_t const rmask = 0x12345678; + if(*(uint8_t const *)&rmask == 0x12) +#endif + bits = ((uint32_t)pixels[0] << 16) | + ((uint32_t)pixels[1] << 8) | + ((uint32_t)pixels[2]); + else + bits = ((uint32_t)pixels[2] << 16) | + ((uint32_t)pixels[1] << 8) | + ((uint32_t)pixels[0]); + break; + } + case 2: + bits = *(uint16_t *)pixels; + break; + case 1: + default: + bits = pixels[0]; + break; + } + + if(bitmap->has_palette) + { + rgba[0] += bitmap->gammatab[bitmap->red[bits]]; + rgba[1] += bitmap->gammatab[bitmap->green[bits]]; + rgba[2] += bitmap->gammatab[bitmap->blue[bits]]; + rgba[3] += bitmap->alpha[bits]; + } + else + { + rgba[0] += bitmap->gammatab[((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft]; + rgba[1] += bitmap->gammatab[((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft]; + rgba[2] += bitmap->gammatab[((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft]; + rgba[3] += ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft; + } +} /* * No dithering @@ -905,6 +1109,24 @@ static void increment_no_dither(void) return; } +/* + * Floyd-Steinberg dithering + */ +static void init_fstein_dither(int line) +{ + ; +} + +static unsigned int get_fstein_dither(void) +{ + return 0x80; +} + +static void increment_fstein_dither(void) +{ + return; +} + /* * Ordered 2 dithering */ @@ -1019,3 +1241,69 @@ static void increment_random_dither(void) return; } +#if !defined(_DOXYGEN_SKIP_ME) +int _cucul_init_bitmap(void) +{ + unsigned int v, s, h; + + /* These ones are constant */ + lookup_colors[0] = CUCUL_COLOR_BLACK; + lookup_colors[1] = CUCUL_COLOR_DARKGRAY; + lookup_colors[2] = CUCUL_COLOR_LIGHTGRAY; + lookup_colors[3] = CUCUL_COLOR_WHITE; + + /* These ones will be overwritten */ + lookup_colors[4] = CUCUL_COLOR_MAGENTA; + lookup_colors[5] = CUCUL_COLOR_LIGHTMAGENTA; + lookup_colors[6] = CUCUL_COLOR_RED; + lookup_colors[7] = CUCUL_COLOR_LIGHTRED; + + for(v = 0; v < LOOKUP_VAL; v++) + for(s = 0; s < LOOKUP_SAT; s++) + for(h = 0; h < LOOKUP_HUE; h++) + { + int i, distbg, distfg, dist; + int val, sat, hue; + unsigned char outbg, outfg; + + val = 0xfff * v / (LOOKUP_VAL - 1); + sat = 0xfff * s / (LOOKUP_SAT - 1); + hue = 0xfff * h / (LOOKUP_HUE - 1); + + /* Initialise distances to the distance between pure black HSV + * coordinates and our white colour (3) */ + outbg = outfg = 3; + distbg = distfg = HSV_DISTANCE(0, 0, 0, 3); + + /* Calculate distances to eight major colour values and store the + * two nearest points in our lookup table. */ + for(i = 0; i < 8; i++) + { + dist = HSV_DISTANCE(hue, sat, val, i); + if(dist <= distbg) + { + outfg = outbg; + distfg = distbg; + outbg = i; + distbg = dist; + } + else if(dist <= distfg) + { + outfg = i; + distfg = dist; + } + } + + hsv_distances[v][s][h] = (outfg << 4) | outbg; + } + + return 0; +} + +int _cucul_end_bitmap(void) +{ + return 0; +} +#endif /* _DOXYGEN_SKIP_ME */ + + diff --git a/cucul/cucul.c b/cucul/cucul.c index d6ad43c..9541688 100644 --- a/cucul/cucul.c +++ b/cucul/cucul.c @@ -28,8 +28,6 @@ #include "cucul.h" #include "cucul_internals.h" -static void cucul_read_environment(cucul_t *); - /** \brief Initialise a \e libcucul canvas. * * This function initialises internal \e libcucul structures and the backend @@ -48,8 +46,6 @@ cucul_t * cucul_create(unsigned int width, unsigned int height) { cucul_t *qq = malloc(sizeof(cucul_t)); - cucul_read_environment(qq); - qq->refcount = 0; qq->fgcolor = CUCUL_COLOR_LIGHTGRAY; @@ -201,103 +197,6 @@ char const *cucul_get_color_name(enum cucul_color color) return color_names[color]; } -/** \brief Get the current value of a feature. - * - * This function retrieves the value of an internal \e libcucul feature. A - * generic feature value is expected, such as CUCUL_ANTIALIASING. - * - * \param feature The requested feature. - * \return The current value of the feature or CUCUL_FEATURE_UNKNOWN if an - * error occurred.. - */ -enum cucul_feature cucul_get_feature(cucul_t *qq, enum cucul_feature feature) -{ - switch(feature) - { - case CUCUL_BACKGROUND: - return qq->background; - case CUCUL_ANTIALIASING: - return qq->antialiasing; - case CUCUL_DITHERING: - return qq->dithering; - - default: - return CUCUL_FEATURE_UNKNOWN; - } -} - -/** \brief Set a feature. - * - * This function sets an internal \e libcucul feature such as the antialiasing - * or dithering modes. If a specific feature such as CUCUL_DITHERING_RANDOM, - * cucul_set_feature() will set it immediately. If a generic feature is given - * instead, such as CUCUL_DITHERING, the default value will be used instead. - * - * \param feature The requested feature. - */ -void cucul_set_feature(cucul_t *qq, enum cucul_feature feature) -{ - switch(feature) - { - case CUCUL_BACKGROUND: - feature = CUCUL_BACKGROUND_SOLID; - case CUCUL_BACKGROUND_BLACK: - case CUCUL_BACKGROUND_SOLID: - qq->background = feature; - break; - - case CUCUL_ANTIALIASING: - feature = CUCUL_ANTIALIASING_PREFILTER; - case CUCUL_ANTIALIASING_NONE: - case CUCUL_ANTIALIASING_PREFILTER: - qq->antialiasing = feature; - break; - - case CUCUL_DITHERING: - feature = CUCUL_DITHERING_FSTEIN; - case CUCUL_DITHERING_NONE: - case CUCUL_DITHERING_ORDERED2: - case CUCUL_DITHERING_ORDERED4: - case CUCUL_DITHERING_ORDERED8: - case CUCUL_DITHERING_RANDOM: - case CUCUL_DITHERING_FSTEIN: - qq->dithering = feature; - break; - - case CUCUL_FEATURE_UNKNOWN: - break; - } -} - -/** \brief Translate a feature value into the feature's name. - * - * This function translates a cucul_feature enum into a human-readable - * description string of the associated feature. - * - * \param feature The feature value. - * \return A static string containing the feature's name. - */ -char const *cucul_get_feature_name(enum cucul_feature feature) -{ - switch(feature) - { - case CUCUL_BACKGROUND_BLACK: return "black background"; - case CUCUL_BACKGROUND_SOLID: return "solid background"; - - case CUCUL_ANTIALIASING_NONE: return "no antialiasing"; - case CUCUL_ANTIALIASING_PREFILTER: return "prefilter antialiasing"; - - case CUCUL_DITHERING_NONE: return "no dithering"; - case CUCUL_DITHERING_ORDERED2: return "2x2 ordered dithering"; - case CUCUL_DITHERING_ORDERED4: return "4x4 ordered dithering"; - case CUCUL_DITHERING_ORDERED8: return "8x8 ordered dithering"; - case CUCUL_DITHERING_RANDOM: return "random dithering"; - case CUCUL_DITHERING_FSTEIN: return "Floyd-Steinberg dithering"; - - default: return "unknown"; - } -} - /** \brief Uninitialise \e libcucul. * * This function frees all resources allocated by cucul_create(). After @@ -380,52 +279,6 @@ void cucul_free_export(struct cucul_export *ex) * XXX: The following functions are local. */ -static void cucul_read_environment(cucul_t * qq) -{ - /* FIXME: if strcasecmp isn't available, use strcmp */ -#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP) - char *var; -#endif - - cucul_set_feature(qq, CUCUL_BACKGROUND); - cucul_set_feature(qq, CUCUL_ANTIALIASING); - cucul_set_feature(qq, CUCUL_DITHERING); - -#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP) - if((var = getenv("CUCUL_BACKGROUND")) && *var) - { - if(!strcasecmp("black", var)) - cucul_set_feature(qq, CUCUL_BACKGROUND_BLACK); - else if(!strcasecmp("solid", var)) - cucul_set_feature(qq, CUCUL_BACKGROUND_SOLID); - } - - if((var = getenv("CUCUL_ANTIALIASING")) && *var) - { - if(!strcasecmp("none", var)) - cucul_set_feature(qq, CUCUL_ANTIALIASING_NONE); - else if(!strcasecmp("prefilter", var)) - cucul_set_feature(qq, CUCUL_ANTIALIASING_PREFILTER); - } - - if((var = getenv("CUCUL_DITHERING")) && *var) - { - if(!strcasecmp("none", var)) - cucul_set_feature(qq, CUCUL_DITHERING_NONE); - else if(!strcasecmp("ordered2", var)) - cucul_set_feature(qq, CUCUL_DITHERING_ORDERED2); - else if(!strcasecmp("ordered4", var)) - cucul_set_feature(qq, CUCUL_DITHERING_ORDERED4); - else if(!strcasecmp("ordered8", var)) - cucul_set_feature(qq, CUCUL_DITHERING_ORDERED8); - else if(!strcasecmp("random", var)) - cucul_set_feature(qq, CUCUL_DITHERING_RANDOM); - else if(!strcasecmp("fstein", var)) - cucul_set_feature(qq, CUCUL_DITHERING_FSTEIN); - } -#endif -} - void _cucul_set_size(cucul_t *qq, unsigned int width, unsigned int height) { unsigned int x, y, old_width, old_height, new_size, old_size; diff --git a/cucul/cucul.h b/cucul/cucul.h index 5703881..6019d06 100644 --- a/cucul/cucul.h +++ b/cucul/cucul.h @@ -34,68 +34,27 @@ extern "C" */ enum cucul_color { - CUCUL_COLOR_BLACK = 0, /**< The colour index for black. */ - CUCUL_COLOR_BLUE = 1, /**< The colour index for blue. */ - CUCUL_COLOR_GREEN = 2, /**< The colour index for green. */ - CUCUL_COLOR_CYAN = 3, /**< The colour index for cyan. */ - CUCUL_COLOR_RED = 4, /**< The colour index for red. */ - CUCUL_COLOR_MAGENTA = 5, /**< The colour index for magenta. */ - CUCUL_COLOR_BROWN = 6, /**< The colour index for brown. */ - CUCUL_COLOR_LIGHTGRAY = 7, /**< The colour index for light gray. */ - CUCUL_COLOR_DARKGRAY = 8, /**< The colour index for dark gray. */ - CUCUL_COLOR_LIGHTBLUE = 9, /**< The colour index for blue. */ - CUCUL_COLOR_LIGHTGREEN = 10, /**< The colour index for light green. */ - CUCUL_COLOR_LIGHTCYAN = 11, /**< The colour index for light cyan. */ - CUCUL_COLOR_LIGHTRED = 12, /**< The colour index for light red. */ - CUCUL_COLOR_LIGHTMAGENTA = 13, /**< The colour index for light magenta. */ - CUCUL_COLOR_YELLOW = 14, /**< The colour index for yellow. */ - CUCUL_COLOR_WHITE = 15 /**< The colour index for white. */ + CUCUL_COLOR_BLACK = 0x0, /**< The colour index for black. */ + CUCUL_COLOR_BLUE = 0x1, /**< The colour index for blue. */ + CUCUL_COLOR_GREEN = 0x2, /**< The colour index for green. */ + CUCUL_COLOR_CYAN = 0x3, /**< The colour index for cyan. */ + CUCUL_COLOR_RED = 0x4, /**< The colour index for red. */ + CUCUL_COLOR_MAGENTA = 0x5, /**< The colour index for magenta. */ + CUCUL_COLOR_BROWN = 0x6, /**< The colour index for brown. */ + CUCUL_COLOR_LIGHTGRAY = 0x7, /**< The colour index for light gray. */ + CUCUL_COLOR_DARKGRAY = 0x8, /**< The colour index for dark gray. */ + CUCUL_COLOR_LIGHTBLUE = 0x9, /**< The colour index for blue. */ + CUCUL_COLOR_LIGHTGREEN = 0xa, /**< The colour index for light green. */ + CUCUL_COLOR_LIGHTCYAN = 0xb, /**< The colour index for light cyan. */ + CUCUL_COLOR_LIGHTRED = 0xc, /**< The colour index for light red. */ + CUCUL_COLOR_LIGHTMAGENTA = 0xd, /**< The colour index for light magenta. */ + CUCUL_COLOR_YELLOW = 0xe, /**< The colour index for yellow. */ + CUCUL_COLOR_WHITE = 0xf, /**< The colour index for white. */ + + CUCUL_COLOR_TRANSPARENT = 0xfe, /**< The transparent colour. */ + CUCUL_COLOR_DEFAULT = 0xff, /**< The output driver's default colour. */ }; -/** \brief Internal features. - * - * Internal libcaca features such as the rendering method or the dithering - * mode. - */ -enum cucul_feature -{ - CUCUL_BACKGROUND = 0x10, /**< Properties of background characters. */ - CUCUL_BACKGROUND_BLACK = 0x11, /**< Draw only black backgrounds. */ - CUCUL_BACKGROUND_SOLID = 0x12, /**< Draw coloured solid backgorunds. */ -#define CUCUL_BACKGROUND_MIN 0x11 /**< First background property */ -#define CUCUL_BACKGROUND_MAX 0x12 /**< Last background property */ - - CUCUL_ANTIALIASING = 0x20, /**< Antialiasing features. */ - CUCUL_ANTIALIASING_NONE = 0x21, /**< No antialiasing. */ - CUCUL_ANTIALIASING_PREFILTER = 0x22, /**< Prefilter antialiasing. */ -#define CUCUL_ANTIALIASING_MIN 0x21 /**< First antialiasing feature. */ -#define CUCUL_ANTIALIASING_MAX 0x22 /**< Last antialiasing feature. */ - - CUCUL_DITHERING = 0x30, /**< Dithering methods */ - CUCUL_DITHERING_NONE = 0x31, /**< No dithering. */ - CUCUL_DITHERING_ORDERED2 = 0x32, /**< Ordered 2x2 Bayer dithering. */ - CUCUL_DITHERING_ORDERED4 = 0x33, /**< Ordered 4x4 Bayer dithering. */ - CUCUL_DITHERING_ORDERED8 = 0x34, /**< Ordered 8x8 Bayer dithering. */ - CUCUL_DITHERING_RANDOM = 0x35, /**< Random dithering. */ - CUCUL_DITHERING_FSTEIN = 0x36, /**< Floyd-Steinberg dithering. */ -#define CUCUL_DITHERING_MIN 0x31 /**< First dithering feature. */ -#define CUCUL_DITHERING_MAX 0x36 /**< Last dithering feature. */ - - CUCUL_FEATURE_UNKNOWN = 0xffff /**< Unknown feature. */ -}; - -/* - * Backwards compatibility macros - */ -#if !defined(_DOXYGEN_SKIP_ME) -#define caca_dithering cucul_feature -#define caca_set_dithering caca_set_feature -#define caca_get_dithering_name caca_get_feature_name -#define CACA_DITHER_NONE CUCUL_DITHERING_NONE -#define CACA_DITHER_ORDERED CUCUL_DITHERING_ORDERED8 -#define CACA_DITHER_RANDOM CUCUL_DITHERING_RANDOM -#endif - typedef struct cucul_context cucul_t; /** \defgroup basic Basic functions @@ -109,9 +68,6 @@ cucul_t * cucul_load(void *, unsigned int); void cucul_set_size(cucul_t *, unsigned int, unsigned int); unsigned int cucul_get_width(cucul_t *); unsigned int cucul_get_height(cucul_t *); -enum cucul_feature cucul_get_feature(cucul_t *, enum cucul_feature); -void cucul_set_feature(cucul_t *, enum cucul_feature); -char const *cucul_get_feature_name(enum cucul_feature); void cucul_free(cucul_t *); /* @} */ @@ -209,9 +165,21 @@ struct cucul_bitmap *cucul_create_bitmap(unsigned int, unsigned int, void cucul_set_bitmap_palette(struct cucul_bitmap *, unsigned int r[], unsigned int g[], unsigned int b[], unsigned int a[]); +void cucul_set_bitmap_brightness(struct cucul_bitmap *, float); void cucul_set_bitmap_gamma(struct cucul_bitmap *, float); -void cucul_draw_bitmap(cucul_t *, int, int, int, int, struct cucul_bitmap const *, void *); -void cucul_set_bitmap_invert(struct cucul_bitmap *, unsigned char); +void cucul_set_bitmap_contrast(struct cucul_bitmap *, float); +void cucul_set_bitmap_invert(struct cucul_bitmap *, int); +void cucul_set_bitmap_antialias(struct cucul_bitmap *, int); +void cucul_set_bitmap_color(struct cucul_bitmap *, char const *); +char const * const * cucul_get_bitmap_color_list(struct cucul_bitmap const *); +void cucul_set_bitmap_charset(struct cucul_bitmap *, char const *); +char const * const * cucul_get_bitmap_charset_list(struct cucul_bitmap + const *); +void cucul_set_bitmap_dithering(struct cucul_bitmap *, char const *); +char const * const * cucul_get_bitmap_dithering_list(struct cucul_bitmap + const *); +void cucul_draw_bitmap(cucul_t *, int, int, int, int, + struct cucul_bitmap const *, void *); void cucul_free_bitmap(struct cucul_bitmap *); /* @} */ diff --git a/cucul/cucul_internals.h b/cucul/cucul_internals.h index 9187c78..76beb1c 100644 --- a/cucul/cucul_internals.h +++ b/cucul/cucul_internals.h @@ -43,9 +43,6 @@ struct cucul_context enum cucul_color fgcolor; enum cucul_color bgcolor; - /* Internal libcucul features */ - enum cucul_feature background, antialiasing, dithering; - unsigned int refcount; }; diff --git a/test/demo.c b/test/demo.c index 6109691..a13f4fd 100644 --- a/test/demo.c +++ b/test/demo.c @@ -100,12 +100,14 @@ int main(int argc, char **argv) bounds = (bounds + 1) % 2; display_menu(); break; +#if 0 case 'd': case 'D': dithering = (dithering + 1) % 5; cucul_set_feature(qq, dithering); display_menu(); break; +#endif case 'c': demo = demo_color; break; @@ -217,8 +219,8 @@ static void display_menu(void) outline == 0 ? "none" : outline == 1 ? "solid" : "thin"); cucul_printf(qq, 4, 18, "'b': drawing boundaries: %s", bounds == 0 ? "screen" : "infinite"); - cucul_printf(qq, 4, 19, "'d': dithering (%s)", - cucul_get_feature_name(dithering)); + //cucul_printf(qq, 4, 19, "'d': dithering (%s)", + // cucul_get_feature_name(dithering)); cucul_putstr(qq, 4, yo - 2, "'q': quit");