[dia/dia-0-97] Bug 710818 - Overflow safe wrappers for acos/asin
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia/dia-0-97] Bug 710818 - Overflow safe wrappers for acos/asin
- Date: Sat, 8 Mar 2014 12:10:23 +0000 (UTC)
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]