[dia] Bug 710818 - Overflow safe wrappers for acos/asin
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] Bug 710818 - Overflow safe wrappers for acos/asin
- Date: Sat, 14 Dec 2013 21:32:32 +0000 (UTC)
commit 846a7ff5b5cb5d21f3c97d21f7a1890a0fcfb65b
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.)
lib/arrows.c | 4 ++--
lib/boundingbox.c | 2 +-
lib/geometry.c | 40 ++++++++++++++++++++++++++++++++++++++--
lib/geometry.h | 3 +++
lib/libdia.def | 3 +++
plug-ins/hpgl/hpgl.c | 6 +++---
6 files changed, 50 insertions(+), 8 deletions(-)
---
diff --git a/lib/arrows.c b/lib/arrows.c
index 043afee..8de39fe 100644
--- a/lib/arrows.c
+++ b/lib/arrows.c
@@ -1613,7 +1613,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);
@@ -1665,7 +1665,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 eb71f35..4c14892 100644
--- a/lib/boundingbox.c
+++ b/lib/boundingbox.c
@@ -502,7 +502,7 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
else if (co <= -1.0)
alpha = M_PI;
else
- alpha = acos(-co);
+ 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 d42b785..a67427a 100644
--- a/lib/geometry.c
+++ b/lib/geometry.c
@@ -474,7 +474,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
{
@@ -818,4 +818,40 @@ dia_matrix_is_invertible (const DiaMatrix *matrix)
det = a*d - b*c;
return finite(det) && det != 0.0;
-}
\ No newline at end of file
+}
+
+/*!
+ * \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 920f1ac..8229a08 100644
--- a/lib/geometry.h
+++ b/lib/geometry.h
@@ -381,6 +381,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 24331dd..a573ce4 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -188,6 +188,9 @@ EXPORTS
destroy_object_list
+ dia_asin
+ dia_acos
+
dia_alignment_selector_get_alignment
dia_alignment_selector_new
dia_alignment_selector_set_alignment
diff --git a/plug-ins/hpgl/hpgl.c b/plug-ins/hpgl/hpgl.c
index 43e2ccf..dbb16ad 100644
--- a/plug-ins/hpgl/hpgl.c
+++ b/plug-ins/hpgl/hpgl.c
@@ -478,7 +478,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);
@@ -488,7 +488,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;
@@ -500,7 +500,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]