diff options
author | Vladimir Vukicevic <vladimir@h-232.office.mozilla.org> | 2007-11-06 14:52:24 -0800 |
---|---|---|
committer | Vladimir Vukicevic <vladimir@h-232.office.mozilla.org> | 2007-11-09 12:50:45 -0800 |
commit | 236c52b095661be395021d511d2dca0b532f83e9 (patch) | |
tree | 1a1582c52712a877e8235b3c369c032ff861935f /src/cairo-fixed-private.h | |
parent | 5b0a0fe7a230f99a43916a16bfd2d26882bad46b (diff) | |
download | cairo-236c52b095661be395021d511d2dca0b532f83e9.tar.gz |
Handle overflow/underflow gracefully when converting to 16.16 fixed
Diffstat (limited to 'src/cairo-fixed-private.h')
-rw-r--r-- | src/cairo-fixed-private.h | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/src/cairo-fixed-private.h b/src/cairo-fixed-private.h index 35b3748d3..cb42ac13e 100644 --- a/src/cairo-fixed-private.h +++ b/src/cairo-fixed-private.h @@ -51,7 +51,7 @@ typedef cairo_int128_t cairo_fixed_96_32_t; /* Eventually, we should allow changing this, but I think * there are some assumptions in the tesselator about the - * size of a fixed type. + * size of a fixed type. For now, it must be 32. */ #define CAIRO_FIXED_BITS 32 @@ -206,10 +206,26 @@ _cairo_fixed_integer_ceil (cairo_fixed_t f) static inline cairo_fixed_16_16_t _cairo_fixed_to_16_16 (cairo_fixed_t f) { -#if CAIRO_FIXED_FRAC_BITS > 16 +#if (CAIRO_FIXED_FRAC_BITS == 16) && (CAIRO_FIXED_BITS == 32) + return f; +#elif CAIRO_FIXED_FRAC_BITS > 16 + /* We're just dropping the low bits, so we won't ever got over/underflow here */ return f >> (CAIRO_FIXED_FRAC_BITS - 16); #else - return f << (16 - CAIRO_FIXED_FRAC_BITS); + cairo_fixed_16_16_t x; + + /* Handle overflow/underflow by claping to the lowest/highest + * value representable as 16.16 + */ + if ((f >> CAIRO_FIXED_FRAC_BITS) < INT16_MIN) { + x = INT32_MIN; + } else if ((f >> CAIRO_FIXED_FRAC_BITS) > INT16_MAX) { + x = INT32_MAX; + } else { + x = f << (16 - CAIRO_FIXED_FRAC_BITS); + } + + return x; #endif } |