summaryrefslogtreecommitdiff
path: root/src/cairo-fixed-private.h
diff options
context:
space:
mode:
authorVladimir Vukicevic <vladimir@h-232.office.mozilla.org>2007-11-06 14:52:24 -0800
committerVladimir Vukicevic <vladimir@h-232.office.mozilla.org>2007-11-09 12:50:45 -0800
commit236c52b095661be395021d511d2dca0b532f83e9 (patch)
tree1a1582c52712a877e8235b3c369c032ff861935f /src/cairo-fixed-private.h
parent5b0a0fe7a230f99a43916a16bfd2d26882bad46b (diff)
downloadcairo-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.h22
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
}