From 6078890268c1de46cb29b0cec77a725dd2ef883b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 1 Aug 2006 22:16:22 -0400 Subject: [PATCH] Implement a better one-minus-epsilon for color computations using float.h if available. Defining a macro CAIRO_ONE_MINUS_EPSILON for internal use now. (bug 7497) --- configure.in | 14 +++++++++----- src/cairo-color.c | 18 ++++++++---------- src/cairoint.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/configure.in b/configure.in index 33fc8dc..8ba562d 100644 --- a/configure.in +++ b/configure.in @@ -446,11 +446,6 @@ fi dnl =========================================================================== -AC_CHECK_HEADERS([pthread.h], have_pthread=yes, have_pthread=no) -AM_CONDITIONAL(HAVE_PTHREAD, test "x$have_pthread" = "xyes") - -dnl =========================================================================== - CAIRO_BACKEND_ENABLE(ps, PostScript, ps, PS_SURFACE, auto, [], [ if test x"$have_ft_load_sfnt_table" != "xyes" ; then use_ps="no (requires FreeType 2.1.4 or newer)" @@ -527,10 +522,19 @@ CAIRO_BACKEND_ENABLE(atsui, ATSUI font, ]) dnl =========================================================================== + dnl Checks for precise integer types AC_CHECK_HEADERS([stdint.h inttypes.h sys/int_types.h]) AC_CHECK_TYPES([uint64_t, uint128_t]) +dnl Check for misc headers + +AC_CHECK_HEADERS([float.h]) + +AC_CHECK_HEADERS([pthread.h], have_pthread=yes, have_pthread=no) +AM_CONDITIONAL(HAVE_PTHREAD, test "x$have_pthread" = "xyes") + + dnl Use lots of warning flags with GCC WARN_CFLAGS="" diff --git a/src/cairo-color.c b/src/cairo-color.c index e202af2..9cf060a 100644 --- a/src/cairo-color.c +++ b/src/cairo-color.c @@ -89,19 +89,17 @@ _cairo_color_init_rgb (cairo_color_t *co _cairo_color_init_rgba (color, red, green, blue, 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) { - 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; + /* We multiply colors by (65536.0 * (1.0 - epsilon)), such that we get a + * uniform range even for 0xffff. In other words, (1.0 - epsilon) will + * convert to 0xffff, not 0xfffe. + */ + color->red_short = floor (color->red * color->alpha * (65536.0 * CAIRO_ONE_MINUS_EPSILON)); + color->green_short = floor (color->green * color->alpha * (65536.0 * CAIRO_ONE_MINUS_EPSILON)); + color->blue_short = floor (color->blue * color->alpha * (65536.0 * CAIRO_ONE_MINUS_EPSILON)); + color->alpha_short = floor (color->alpha * (65536.0 * CAIRO_ONE_MINUS_EPSILON)); } void diff --git a/src/cairoint.h b/src/cairoint.h index 4eb0c3c..ee008e9 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -168,6 +168,53 @@ # define CAIRO_MUTEX_LOCK(name) # define CAIRO_MUTEX_UNLOCK(name) #endif +#if HAVE_FLOAT_H +# include +#endif +#ifndef DBL_EPSILON +/* 1e-7 is a conservative value. it's less than 2^(1-24) which is + * the epsilon value for a 32-bit float. The regular value for this + * with 64-bit doubles is 2^(1-53) or approximately 1e-16. + */ +# define DBL_EPSILON 1e-7 +#endif + +/* CAIRO_ONE_MINUS_EPSILON: + * + * DBL_EPSILON is the difference between 1 and the least value greater + * than 1 that is representable in the given floating-point type. Then + * 1.0+DBL_EPSILON looks like: + * + * 1.00000000000...0000000001 * 2**0 + * + * while 1.0-DBL_EPSILON looks like: + * + * 0.11111111111...1111111111 * 2**0 + * + * and so represented as: + * + * 1.1111111111...11111111110 * 2**-1 + * + * so, in fact, 1.0-(DBL_EPSILON*.5) works too, but I don't think it + * really matters. So, I'll go with the simple 1.0-DBL_EPSILON here. + * + * The following python session shows these observations: + * + * >>> 1.0 + 2**(1-53) + * 1.0000000000000002 + * >>> 1.0 + 2**(1-54) + * 1.0 + * >>> 1.0 - 2**(1-53) + * 0.99999999999999978 + * >>> 1.0 - 2**(1-54) + * 0.99999999999999989 + * >>> 1.0 - 2**(1-53)*.5 + * 0.99999999999999989 + * >>> 1.0 - 2**(1-55) + * 1.0 + */ +#define CAIRO_ONE_MINUS_EPSILON (1.0 - DBL_EPSILON) + #undef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) -- 1.4.0