[dia/dia-0-97] Bug 710818 - Overflow safe wrappers for acos/asin



commit 335ced1909180f0bc4fb064aaa676a86c740dce0
Author: Hans Breuer <hans breuer org>
Date:   Sun Nov 17 11:29:42 2013 +0100

    Bug 710818 - Overflow safe wrappers for acos/asin
    
    acos() and asin() are only defined in a certain range. Implement some
    range/overflow safe wrappers rather than potentially passing infinite
    to other modules (e.g. cairo did assert() on it.)
    
    (cherry picked from commit 846a7ff5b5cb5d21f3c97d21f7a1890a0fcfb65b)
    
    Conflicts:
        lib/boundingbox.c
        lib/geometry.c

 lib/arrows.c         |    4 ++--
 lib/boundingbox.c    |    9 +++++++--
 lib/geometry.c       |   37 ++++++++++++++++++++++++++++++++++++-
 lib/geometry.h       |    3 +++
 lib/libdia.def       |    3 +++
 plug-ins/hpgl/hpgl.c |    6 +++---
 6 files changed, 54 insertions(+), 8 deletions(-)
---
diff --git a/lib/arrows.c b/lib/arrows.c
index 4371946..b546709 100644
--- a/lib/arrows.c
+++ b/lib/arrows.c
@@ -1621,7 +1621,7 @@ draw_rounded(DiaRenderer *renderer, Point *to, Point *from,
     p.x += delta.x * rapport;
     p.y += delta.y * rapport;
   }  
-  angle_start = 90.0 - asin((p.y - to->y) / rayon) * (180.0 / 3.14);
+  angle_start = 90.0 - dia_asin((p.y - to->y) / rayon) * (180.0 / 3.14);
   if (p.x - to->x < 0) { angle_start = 360.0 - angle_start;  }
   
   DIA_RENDERER_GET_CLASS(renderer)->draw_arc(renderer, &p, width, length, angle_start, angle_start - 180.0, 
fg_color);
@@ -1673,7 +1673,7 @@ draw_open_rounded(DiaRenderer *renderer, Point *to, Point *from,
     p.x += delta.x * rapport;
     p.y += delta.y * rapport;
   }  
-  angle_start = 90.0 - asin((p.y - to->y) / rayon) * (180.0 / 3.14);
+  angle_start = 90.0 - dia_asin((p.y - to->y) / rayon) * (180.0 / 3.14);
   if (p.x - to->x < 0) { angle_start = 360.0 - angle_start;  }
 
   p_line = p;
diff --git a/lib/boundingbox.c b/lib/boundingbox.c
index 6d2749f..fd50da7 100644
--- a/lib/boundingbox.c
+++ b/lib/boundingbox.c
@@ -503,8 +503,13 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
       point_copy_add_scaled(&vxn,&vn,&vx,-1);
       point_normalize(&vxn);
 
-      co = point_dot(&vpx,&vxn);      
-      alpha = acos(-co); 
+      co = point_dot(&vpx,&vxn);
+      if (co >= 1.0)
+        alpha = 0.0;
+      else if (co <= -1.0)
+        alpha = M_PI;
+      else
+        alpha = dia_acos(-co);
       if (co > -0.9816) { /* 0.9816 = cos(11deg) */
         /* we have a pointy join. */
         real overshoot;
diff --git a/lib/geometry.c b/lib/geometry.c
index c6f649a..598e86b 100644
--- a/lib/geometry.c
+++ b/lib/geometry.c
@@ -565,7 +565,7 @@ real dot2(Point *p1, Point *p2)
   if ( d != 0.0 )
   {
     t = (p1->x*p2->x+p1->y*p2->y)/d;
-    return (acos(t));
+    return (dia_acos(t));
   }
   else
   {
@@ -781,3 +781,38 @@ calculate_object_edge(Point *objmid, Point *end, DiaObject *obj)
   return mid2;
 }
 
+/*!
+ * \brief asin wrapped to limit to valid result range
+ *
+ * Although clipping the value might hide some miscalculation
+ * elsewhere this should still be used in all of Dia. Continuing
+ * calculation with bogus values might final fall on our foots
+ * because rendering libraries might not be graceful.
+ * See https://bugzilla.gnome.org/show_bug.cgi?id=710818
+ */
+real
+dia_asin (real x)
+{
+  real r = asin (x);
+  /* clamp to valid range */
+  if (r < -M_PI/2)
+    return -M_PI/2;
+  else if (r > M_PI/2)
+    return M_PI/2;
+  return r;
+}
+
+/*!
+ * \brief acos wrapped to limit to valid result range
+ */
+real
+dia_acos (real x)
+{
+  real r = acos (x);
+  /* clamp to valid range */
+  if (r < 0)
+    return 0;
+  else if (r > M_PI)
+    return M_PI;
+  return r;
+}
diff --git a/lib/geometry.h b/lib/geometry.h
index 9ca1631..d2f9a37 100644
--- a/lib/geometry.h
+++ b/lib/geometry.h
@@ -367,6 +367,9 @@ int  three_point_circle(const Point *p1, const Point *p2, const Point *p3,
 real point_cross(Point *p1, Point *p2);
 Point calculate_object_edge(Point *objmid, Point *end, DiaObject *obj);
 
+real dia_asin (real x);
+real dia_acos (real x);
+
 G_END_DECLS
 
 #endif /* GEOMETRY_H */
diff --git a/lib/libdia.def b/lib/libdia.def
index 977bf7f..d50d6db 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -169,6 +169,9 @@ EXPORTS
 
  destroy_object_list
 
+ dia_asin
+ dia_acos
+
  dia_alignment_selector_get_alignment
  dia_alignment_selector_get_type
  dia_alignment_selector_new
diff --git a/plug-ins/hpgl/hpgl.c b/plug-ins/hpgl/hpgl.c
index e205070..eff37ea 100644
--- a/plug-ins/hpgl/hpgl.c
+++ b/plug-ins/hpgl/hpgl.c
@@ -479,7 +479,7 @@ draw_ellipse_by_arc (DiaRenderer *renderer,
   b = height / 2;
   e = sqrt(a*a - b*b);
 
-  alpha = 0.25*M_PI - asin((e/a) * sin(0.75*M_PI));
+  alpha = 0.25*M_PI - dia_asin((e/a) * sin(0.75*M_PI));
   d = 2*a*sin(alpha);
 
   c = (sin(0.25*M_PI) * (2*e + d)) / sin(0.75*M_PI - alpha);
@@ -489,7 +489,7 @@ draw_ellipse_by_arc (DiaRenderer *renderer,
 
   /* draw arcs */
   g = sqrt((a-x)*(a-x) + y*y);
-  gamma = acos((a-x)/g);
+  gamma = dia_acos((a-x)/g);
   r = (sin(gamma) * g) / sin(M_PI-2*gamma);
 
   pt.y = center->y;
@@ -501,7 +501,7 @@ draw_ellipse_by_arc (DiaRenderer *renderer,
 
 
   g = sqrt((b-y)*(b-y) + x*x);
-  gamma = acos((b-y)/g);
+  gamma = dia_acos((b-y)/g);
   r = (sin(gamma) * g) / sin(M_PI-2*gamma);
 
   pt.x = center->x;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]