diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2013-10-09 15:53:16 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2013-10-22 14:27:43 -0400 |
commit | 98fef3cef2d0f7f463a2e4f9f1b35b09f7b6ea77 (patch) | |
tree | dadc80d6826ef32fb9a8ad281e813444f69404fd | |
parent | 6f05ecf488314e4b0c6c6b0110963c449bebe7d7 (diff) |
_cairo_color_double_to_short(): Use standard rounding algorithm
The _cairo_color_double_to_short() function converts a double
precision floating point value in the range of [0.0, 1.0] to a
uint16_t integer by dividing the [0.0, 1.0] range into 65536
equal-sized intervals and then associating each interval with an
integer.
Under the assumption that an integer i corresponds to the real value i
/ 65535.0 this algorithm introduces more error than necessary as can
be seen from the following picture showing the analogous
transformation for two-bit integers:
+-----------+-----------+-----------+-----------+
0b00 | 0b01 | 0b10 | 0b11
+-----------+-----------+-----------+-----------+
which shows that some floating point values are not converted to the
integer that would minimize the error in value that that integer
corresponds to.
Instead, this patch uses standard rounding, which makes the diagram
look like this:
+-------+---------------+---------------+-------+
0b00 | 0b01 | 0b10 | 0b11
+-------+---------------+---------------+-------+
It's clear that if the values corresponding to the given integers are
fixed, then it's not possible to decrease the resulting error by
moving any of the interval boundaries.
See this thread for more information:
http://lists.freedesktop.org/archives/cairo/2013-October/024691.html
Reference images updated:
pthread-similar.ref.png
record-paint-alpha.ref.png
record90-paint-alpha.argb32.ref
record90-paint-alpha.rgb24.ref.png
xcb-huge-image-shm.ref.png
xcb-huge-subimage.ref.png
All of these have only one-step differences to the old images.
-rw-r--r-- | src/cairo-color.c | 193 | ||||
-rw-r--r-- | test/reference/pthread-similar.ref.png | bin | 140728321541552 -> 176 bytes | |||
-rw-r--r-- | test/reference/record-paint-alpha.ref.png | bin | 140728321541552 -> 245 bytes | |||
-rw-r--r-- | test/reference/record90-paint-alpha.argb32.ref.png | bin | 105 -> 105 bytes | |||
-rw-r--r-- | test/reference/record90-paint-alpha.rgb24.ref.png | bin | 105 -> 105 bytes | |||
-rw-r--r-- | test/reference/xcb-huge-image-shm.ref.png | bin | 105 -> 97 bytes | |||
-rw-r--r-- | test/reference/xcb-huge-subimage.ref.png | bin | 105 -> 97 bytes |
7 files changed, 193 insertions, 0 deletions
diff --git a/src/cairo-color.c b/src/cairo-color.c index 9c85255..c2a11a1 100644 --- a/src/cairo-color.c +++ b/src/cairo-color.c @@ -0,0 +1,193 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2002 University of Southern California + * Copyright © 2005 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Carl D. Worth <cworth@cworth.org> + */ + +#include "cairoint.h" + +static cairo_color_t const cairo_color_white = { + 1.0, 1.0, 1.0, 1.0, + 0xffff, 0xffff, 0xffff, 0xffff +}; + +static cairo_color_t const cairo_color_black = { + 0.0, 0.0, 0.0, 1.0, + 0x0, 0x0, 0x0, 0xffff +}; + +static cairo_color_t const cairo_color_transparent = { + 0.0, 0.0, 0.0, 0.0, + 0x0, 0x0, 0x0, 0x0 +}; + +static cairo_color_t const cairo_color_magenta = { + 1.0, 0.0, 1.0, 1.0, + 0xffff, 0x0, 0xffff, 0xffff +}; + +const cairo_color_t * +_cairo_stock_color (cairo_stock_t stock) +{ + switch (stock) { + case CAIRO_STOCK_WHITE: + return &cairo_color_white; + case CAIRO_STOCK_BLACK: + return &cairo_color_black; + case CAIRO_STOCK_TRANSPARENT: + return &cairo_color_transparent; + + case CAIRO_STOCK_NUM_COLORS: + default: + ASSERT_NOT_REACHED; + /* If the user can get here somehow, give a color that indicates a + * problem. */ + return &cairo_color_magenta; + } +} + +/* Convert a double in [0.0, 1.0] to an integer in [0, 65535] + * The conversion is designed to choose the integer i such that + * i / 65535.0 is as close as possible to the input value. + */ +uint16_t +_cairo_color_double_to_short (double d) +{ + return d * 65535.0 + 0.5; +} + +static void +_cairo_color_compute_shorts (cairo_color_t *color) +{ + color->red_short = _cairo_color_double_to_short (color->red * color->alpha); + color->green_short = _cairo_color_double_to_short (color->green * color->alpha); + color->blue_short = _cairo_color_double_to_short (color->blue * color->alpha); + color->alpha_short = _cairo_color_double_to_short (color->alpha); +} + +void +_cairo_color_init_rgba (cairo_color_t *color, + double red, double green, double blue, + double alpha) +{ + color->red = red; + color->green = green; + color->blue = blue; + color->alpha = alpha; + + _cairo_color_compute_shorts (color); +} + +void +_cairo_color_multiply_alpha (cairo_color_t *color, + double alpha) +{ + color->alpha *= alpha; + + _cairo_color_compute_shorts (color); +} + +void +_cairo_color_get_rgba (cairo_color_t *color, + double *red, + double *green, + double *blue, + double *alpha) +{ + *red = color->red; + *green = color->green; + *blue = color->blue; + *alpha = color->alpha; +} + +void +_cairo_color_get_rgba_premultiplied (cairo_color_t *color, + double *red, + double *green, + double *blue, + double *alpha) +{ + *red = color->red * color->alpha; + *green = color->green * color->alpha; + *blue = color->blue * color->alpha; + *alpha = color->alpha; +} + +/* NB: This function works both for unmultiplied and premultiplied colors */ +cairo_bool_t +_cairo_color_equal (const cairo_color_t *color_a, + const cairo_color_t *color_b) +{ + if (color_a == color_b) + return TRUE; + + if (color_a->alpha_short != color_b->alpha_short) + return FALSE; + + if (color_a->alpha_short == 0) + return TRUE; + + return color_a->red_short == color_b->red_short && + color_a->green_short == color_b->green_short && + color_a->blue_short == color_b->blue_short; +} + +cairo_bool_t +_cairo_color_stop_equal (const cairo_color_stop_t *color_a, + const cairo_color_stop_t *color_b) +{ + if (color_a == color_b) + return TRUE; + + return color_a->alpha_short == color_b->alpha_short && + color_a->red_short == color_b->red_short && + color_a->green_short == color_b->green_short && + color_a->blue_short == color_b->blue_short; +} + +cairo_content_t +_cairo_color_get_content (const cairo_color_t *color) +{ + if (CAIRO_COLOR_IS_OPAQUE (color)) + return CAIRO_CONTENT_COLOR; + + if (color->red_short == 0 && + color->green_short == 0 && + color->blue_short == 0) + { + return CAIRO_CONTENT_ALPHA; + } + + return CAIRO_CONTENT_COLOR_ALPHA; +} diff --git a/test/reference/pthread-similar.ref.png b/test/reference/pthread-similar.ref.png Binary files differindex a22210d..c8763ba 100644 --- a/test/reference/pthread-similar.ref.png +++ b/test/reference/pthread-similar.ref.png diff --git a/test/reference/record-paint-alpha.ref.png b/test/reference/record-paint-alpha.ref.png Binary files differindex ab7ce3e..487b8b6 100644 --- a/test/reference/record-paint-alpha.ref.png +++ b/test/reference/record-paint-alpha.ref.png diff --git a/test/reference/record90-paint-alpha.argb32.ref.png b/test/reference/record90-paint-alpha.argb32.ref.png Binary files differindex 57aa95d..5e9cb58 100644 --- a/test/reference/record90-paint-alpha.argb32.ref.png +++ b/test/reference/record90-paint-alpha.argb32.ref.png diff --git a/test/reference/record90-paint-alpha.rgb24.ref.png b/test/reference/record90-paint-alpha.rgb24.ref.png Binary files differindex 57aa95d..5e9cb58 100644 --- a/test/reference/record90-paint-alpha.rgb24.ref.png +++ b/test/reference/record90-paint-alpha.rgb24.ref.png diff --git a/test/reference/xcb-huge-image-shm.ref.png b/test/reference/xcb-huge-image-shm.ref.png Binary files differindex a0b24c8..5c274f8 100644 --- a/test/reference/xcb-huge-image-shm.ref.png +++ b/test/reference/xcb-huge-image-shm.ref.png diff --git a/test/reference/xcb-huge-subimage.ref.png b/test/reference/xcb-huge-subimage.ref.png Binary files differindex a0b24c8..5c274f8 100644 --- a/test/reference/xcb-huge-subimage.ref.png +++ b/test/reference/xcb-huge-subimage.ref.png |