[cairo] Use 8-bit colour values internally
Jason Dorje Short
jdorje at users.sf.net
Mon Aug 22 20:37:04 PDT 2005
Billy Biggs wrote:
> The 16-bit representation of colours (cairo_color_t's shorts) is only
> used by the fill_rectangles implementation for the image and Xlib
> backends. However, neither really needs this much precision: pixman and
> X both convert back to 8 bit internally by shifting.
In the pixman code in the patch it looks like pixman is using 16-bit
values...
> I would rather see cairo internally just store the values as 8-bit.
> I'd also rather cairo round rather than truncate and push towards 1. I
> admit that this is a matter of taste and not correctness. Some test
> output would change, for example the 0.3 used in the linear-gradient
> test will map to 77/255 rather than 76/255.
With some good preprocessor macros this could be made a lot more
transparent and less error-prone.
> ------------------------------------------------------------------------
>
> Index: cairo-color.c
> ===================================================================
> RCS file: /cvs/cairo/cairo/src/cairo-color.c,v
> retrieving revision 1.15
> diff -p -u -r1.15 cairo-color.c
> --- cairo-color.c 13 Aug 2005 08:04:55 -0000 1.15
> +++ cairo-color.c 23 Aug 2005 00:46:26 -0000
> @@ -38,13 +38,13 @@
> #include "cairoint.h"
>
> static cairo_color_t const cairo_color_white = {
> - 1.0, 1.0, 1.0, 1.0,
> - 0xffff, 0xffff, 0xffff, 0xffff
> + 1.0, 1.0, 1.0, 1.0,
> + 0xff, 0xff, 0xff, 0xff
> };
#define COLOR_MAX 255
#define COLOR_TO_INT(c) ((int)(c) * (double)COLOR_MAX + 0.5))
#define COLOR(r, g, b, a) \
{ \
(r), (g), (b), (a), \
COLOR_TO_INT(r), COLOR_TO_INT(g), COLOR_TO_INT(b), COLOR_TO_INT(a) \
}
static cairo_color_t const cairo_color_white
= COLOR(1.0, 1.0, 1.0, 1.0);
> -/* We multiply colors by (0x10000 - epsilon), such that we get a uniform
> - * range even for 0xffff. In other words, (1.0 - epsilon) would convert
> - * to 0xffff, not 0xfffe.
> - */
> -#define CAIRO_COLOR_ONE_MINUS_EPSILON (65536.0 - 1e-5)
> -
> static void
> -_cairo_color_compute_shorts (cairo_color_t *color)
> +_cairo_color_compute_chars (cairo_color_t *color)
> {
> - color->red_short = color->red * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
> - color->green_short = color->green * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
> - color->blue_short = color->blue * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
> - color->alpha_short = color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
> + color->red_char = floor (color->red * color->alpha * 255.0 + 0.5);
> + color->green_char = floor (color->green * color->alpha * 255.0 + 0.5);
> + color->blue_char = floor (color->blue * color->alpha * 255.0 + 0.5);
> + color->alpha_char = floor (color->alpha * 255.0 + 0.5);
> }
color->red_char = COLOR_TO_INT(color->red * color->alpha);
Looks like the uniform-distribution hack here is trying to do the same
thing you're doing with rounding (otherwise 0.{9} would never give
COLOR_MAX, always COLOR_MAX-1). Clearly rounding is more accurate
though (if I understand rightly what this code does).
> - pixman_color.red = color->red_short;
> - pixman_color.green = color->green_short;
> - pixman_color.blue = color->blue_short;
> - pixman_color.alpha = color->alpha_short;
> + pixman_color.red = color->red_char << 8;
> + pixman_color.green = color->green_char << 8;
> + pixman_color.blue = color->blue_char << 8;
> + pixman_color.alpha = color->alpha_char << 8;
#define COLOR_INT_TO_SHORT(c) ((c) << 8)
> - unsigned short red_short;
> - unsigned short green_short;
> - unsigned short blue_short;
> - unsigned short alpha_short;
> + unsigned char red_char;
> + unsigned char green_char;
> + unsigned char blue_char;
> + unsigned char alpha_char;
typedef color_int_t char;
(Naming could use some improvement.)
-jason
More information about the cairo
mailing list