diff options
Diffstat (limited to 'fitz/base_geometry.c')
-rw-r--r-- | fitz/base_geometry.c | 110 |
1 files changed, 89 insertions, 21 deletions
diff --git a/fitz/base_geometry.c b/fitz/base_geometry.c index 1486279f..317c8df1 100644 --- a/fitz/base_geometry.c +++ b/fitz/base_geometry.c @@ -3,6 +3,24 @@ #define MAX4(a,b,c,d) fz_max(fz_max(a,b), fz_max(c,d)) #define MIN4(a,b,c,d) fz_min(fz_min(a,b), fz_min(c,d)) +/* A useful macro to add with overflow detection and clamping. + + We want to do "b = a + x", but to allow for overflow. Consider the + top bits, and the cases in which overflow occurs: + + overflow a x b ~a^x a^b (~a^x)&(a^b) + no 0 0 0 1 0 0 + yes 0 0 1 1 1 1 + no 0 1 0 0 0 0 + no 0 1 1 0 1 0 + no 1 0 0 0 1 0 + no 1 0 1 0 0 0 + yes 1 1 0 1 1 1 + no 1 1 1 1 0 0 +*/ +#define ADD_WITH_SAT(b,a,x) \ + ((b) = (a) + (x), (b) = (((~(a)^(x))&((a)^(b))) < 0 ? ((x) < 0 ? INT_MIN : INT_MAX) : (b))) + /* Matrices, points and affine transformations */ const fz_matrix fz_identity = { 1, 0, 0, 1, 0, 0 }; @@ -170,36 +188,57 @@ const fz_rect fz_infinite_rect = { 1, 1, -1, -1 }; const fz_rect fz_empty_rect = { 0, 0, 0, 0 }; const fz_rect fz_unit_rect = { 0, 0, 1, 1 }; -fz_rect -fz_rect_covering_rect(fz_rect f) +const fz_irect fz_infinite_irect = { 1, 1, -1, -1 }; +const fz_irect fz_empty_irect = { 0, 0, 0, 0 }; +const fz_irect fz_unit_irect = { 0, 0, 1, 1 }; + +fz_irect +fz_rect_covering_rect(fz_rect a) { - f.x0 = floorf(f.x0); - f.y0 = floorf(f.y0); - f.x1 = ceilf(f.x1); - f.y1 = ceilf(f.y1); + fz_irect b; + + a.x0 = floorf(a.x0); + a.y0 = floorf(a.y0); + a.x1 = ceilf(a.x1); + a.y1 = ceilf(a.y1); /* check for integer overflow */ - f.x0 = fz_clamp(f.x0, MIN_SAFE_INT, MAX_SAFE_INT); - f.y0 = fz_clamp(f.y0, MIN_SAFE_INT, MAX_SAFE_INT); - f.x1 = fz_clamp(f.x1, MIN_SAFE_INT, MAX_SAFE_INT); - f.y1 = fz_clamp(f.y1, MIN_SAFE_INT, MAX_SAFE_INT); - return f; + b.x0 = fz_clamp(a.x0, MIN_SAFE_INT, MAX_SAFE_INT); + b.y0 = fz_clamp(a.y0, MIN_SAFE_INT, MAX_SAFE_INT); + b.x1 = fz_clamp(a.x1, MIN_SAFE_INT, MAX_SAFE_INT); + b.y1 = fz_clamp(a.y1, MIN_SAFE_INT, MAX_SAFE_INT); + + return b; } fz_rect -fz_round_rect(fz_rect f) +fz_rect_from_irect(fz_irect a) { - f.x0 = floorf(f.x0 + 0.001); - f.y0 = floorf(f.y0 + 0.001); - f.x1 = ceilf(f.x1 - 0.001); - f.y1 = ceilf(f.y1 - 0.001); + fz_rect b; + b.x0 = a.x0; + b.y0 = a.y0; + b.x1 = a.x1; + b.y1 = a.y1; + return b; +} + +fz_irect +fz_round_rect(fz_rect a) +{ + fz_irect b; + + a.x0 = floorf(a.x0 + 0.001); + a.y0 = floorf(a.y0 + 0.001); + a.x1 = ceilf(a.x1 - 0.001); + a.y1 = ceilf(a.y1 - 0.001); /* check for integer overflow */ - f.x0 = fz_clamp(f.x0, MIN_SAFE_INT, MAX_SAFE_INT); - f.y0 = fz_clamp(f.y0, MIN_SAFE_INT, MAX_SAFE_INT); - f.x1 = fz_clamp(f.x1, MIN_SAFE_INT, MAX_SAFE_INT); - f.y1 = fz_clamp(f.y1, MIN_SAFE_INT, MAX_SAFE_INT); - return f; + b.x0 = fz_clamp(a.x0, MIN_SAFE_INT, MAX_SAFE_INT); + b.y0 = fz_clamp(a.y0, MIN_SAFE_INT, MAX_SAFE_INT); + b.x1 = fz_clamp(a.x1, MIN_SAFE_INT, MAX_SAFE_INT); + b.y1 = fz_clamp(a.y1, MIN_SAFE_INT, MAX_SAFE_INT); + + return b; } fz_rect @@ -218,6 +257,22 @@ fz_intersect_rect(fz_rect a, fz_rect b) return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_rect : r; } +fz_irect +fz_intersect_irect(fz_irect a, fz_irect b) +{ + fz_irect r; + /* Check for empty box before infinite box */ + if (fz_is_empty_rect(a)) return fz_empty_irect; + if (fz_is_empty_rect(b)) return fz_empty_irect; + if (fz_is_infinite_rect(a)) return b; + if (fz_is_infinite_rect(b)) return a; + r.x0 = fz_maxi(a.x0, b.x0); + r.y0 = fz_maxi(a.y0, b.y0); + r.x1 = fz_mini(a.x1, b.x1); + r.y1 = fz_mini(a.y1, b.y1); + return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_irect : r; +} + fz_rect fz_union_rect(fz_rect a, fz_rect b) { @@ -270,6 +325,19 @@ fz_translate_rect(fz_rect a, float xoff, float yoff) return b; } +fz_irect +fz_translate_irect(fz_irect a, int xoff, int yoff) +{ + fz_irect b; + if (fz_is_empty_rect(a)) return a; + if (fz_is_infinite_rect(a)) return a; + ADD_WITH_SAT(b.x0, a.x0, xoff); + ADD_WITH_SAT(b.y0, a.y0, yoff); + ADD_WITH_SAT(b.x1, a.x1, xoff); + ADD_WITH_SAT(b.y1, a.y1, yoff); + return b; +} + fz_rect fz_expand_rect(fz_rect a, float expand) { |