summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/android/PathAndroid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/android/PathAndroid.cpp')
-rw-r--r--WebCore/platform/graphics/android/PathAndroid.cpp61
1 files changed, 45 insertions, 16 deletions
diff --git a/WebCore/platform/graphics/android/PathAndroid.cpp b/WebCore/platform/graphics/android/PathAndroid.cpp
index 68f4c0d..f6d3d43 100644
--- a/WebCore/platform/graphics/android/PathAndroid.cpp
+++ b/WebCore/platform/graphics/android/PathAndroid.cpp
@@ -122,7 +122,16 @@ void Path::closeSubpath()
m_path->close();
}
-static const float gPI = 3.1415926f;
+static const float gPI = 3.14159265f;
+static const float g2PI = 6.28318531f;
+static const float g180OverPI = 57.29577951308f;
+
+static float fast_mod(float angle, float max) {
+ if (angle >= max || angle <= -max) {
+ angle = fmodf(angle, max);
+ }
+ return angle;
+}
void Path::addArc(const FloatPoint& p, float r, float sa, float ea,
bool clockwise) {
@@ -134,23 +143,43 @@ void Path::addArc(const FloatPoint& p, float r, float sa, float ea,
oval.set(cx - radius, cy - radius, cx + radius, cy + radius);
float sweep = ea - sa;
- // check for a circle
- if (sweep >= 2*gPI || sweep <= -2*gPI) {
- m_path->addOval(oval);
- } else {
- SkScalar startDegrees = SkFloatToScalar(sa * 180 / gPI);
- SkScalar sweepDegrees = SkFloatToScalar(sweep * 180 / gPI);
-
- if (clockwise && sweepDegrees > 0) {
- sweepDegrees -= SkIntToScalar(360);
- } else if (!clockwise && sweepDegrees < 0) {
- sweepDegrees = SkIntToScalar(360) - sweepDegrees;
- }
+ bool prependOval = false;
+
+ /* Note if clockwise and the sign of the sweep disagree. This particular
+ logic was deduced from http://canvex.lazyilluminati.com/misc/arc.html
+ */
+ if (clockwise && (sweep > 0 || sweep < -g2PI)) {
+ sweep = fmodf(sweep, g2PI) - g2PI;
+ } else if (!clockwise && (sweep < 0 || sweep > g2PI)) {
+ sweep = fmodf(sweep, g2PI) + g2PI;
+ }
+
+ // If the abs(sweep) >= 2PI, then we need to add a circle before we call
+ // arcTo, since it treats the sweep mod 2PI. We don't have a prepend call,
+ // so we just remember this, and at the end create a new path with an oval
+ // and our current path, and then swap then.
+ //
+ if (sweep >= g2PI || sweep <= -g2PI) {
+ prependOval = true;
+// SkDebugf("addArc sa=%g ea=%g cw=%d sweep %g treat as circle\n", sa, ea, clockwise, sweep);
+
+ // now reduce sweep to just the amount we need, so that the current
+ // point is left where the caller expects it.
+ sweep = fmodf(sweep, g2PI);
+ }
-// SkDebugf("addArc sa=%g ea=%g cw=%d start=%g sweep=%g\n", sa, ea, clockwise,
-// SkScalarToFloat(startDegrees), SkScalarToFloat(sweepDegrees));
+ sa = fast_mod(sa, g2PI);
+ SkScalar startDegrees = SkFloatToScalar(sa * g180OverPI);
+ SkScalar sweepDegrees = SkFloatToScalar(sweep * g180OverPI);
- m_path->arcTo(oval, startDegrees, sweepDegrees, false);
+// SkDebugf("addArc sa=%g ea=%g cw=%d sweep=%g ssweep=%g\n", sa, ea, clockwise, sweep, SkScalarToFloat(sweepDegrees));
+ m_path->arcTo(oval, startDegrees, sweepDegrees, false);
+
+ if (prependOval) {
+ SkPath tmp;
+ tmp.addOval(oval);
+ tmp.addPath(*m_path);
+ m_path->swap(tmp);
}
}