aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-23 19:18:37 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-23 19:18:37 +0000
commit5b56d9e43fee4393f25f41d400981ce3960cd1aa (patch)
treecdbed69db73ae382a4fd748141041c7abb5880a4
parent8796ee60b79307629c56bf9f3e146833b312b957 (diff)
In convex path renderer, translate polygon to origin for fanPt computation
Review URL: http://codereview.appspot.com/5698051/ git-svn-id: http://skia.googlecode.com/svn/trunk@3241 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--gm/convexpaths.cpp4
-rw-r--r--src/gpu/GrAAConvexPathRenderer.cpp35
2 files changed, 29 insertions, 10 deletions
diff --git a/gm/convexpaths.cpp b/gm/convexpaths.cpp
index 9aedcbc4fc..2c719e826d 100644
--- a/gm/convexpaths.cpp
+++ b/gm/convexpaths.cpp
@@ -162,6 +162,10 @@ protected:
fPaths.push_back().cubicTo(0, 0,
0, 0,
100 * SK_Scalar1, 100 * SK_Scalar1);
+
+ // small circle. This is listed last so that it has device coords far
+ // from the origin (small area relative to x,y values).
+ fPaths.push_back().addCircle(0, 0, SkFloatToScalar(0.8f));
}
virtual void onDraw(SkCanvas* canvas) {
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index 1a8a38904c..d5962849f0 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -60,18 +60,32 @@ void center_of_mass(const SegmentArray& segments, SkPoint* c) {
SkPoint center;
center.set(0, 0);
int count = segments.count();
- for (int i = 0; i < count; ++i) {
- const SkPoint& pi = segments[i].endPt();
- int j = (i + 1) % count;
- const SkPoint& pj = segments[j].endPt();
- GrScalar t = GrMul(pi.fX, pj.fY) - GrMul(pj.fX, pi.fY);
- area += t;
- center.fX += (pi.fX + pj.fX) * t;
- center.fY += (pi.fY + pj.fY) * t;
+ SkPoint p0;
+ if (count > 2) {
+ // We translate the polygon so that the first point is at the origin.
+ // This avoids some precision issues with small area polygons far away
+ // from the origin.
+ p0 = segments[0].endPt();
+ SkPoint pi;
+ SkPoint pj;
+ // the first and last interation of the below loop would compute
+ // zeros since the starting / ending point is (0,0). So instead we start
+ // at i=1 and make the last iteration i=count-2.
+ pj = segments[1].endPt() - p0;
+ for (int i = 1; i < count - 1; ++i) {
+ pi = pj;
+ const SkPoint pj = segments[i + 1].endPt() - p0;
+
+ GrScalar t = GrMul(pi.fX, pj.fY) - GrMul(pj.fX, pi.fY);
+ area += t;
+ center.fX += (pi.fX + pj.fX) * t;
+ center.fY += (pi.fY + pj.fY) * t;
+
+ }
}
// If the poly has no area then we instead return the average of
// its points.
- if (SkScalarAbs(area) < SK_ScalarNearlyZero) {
+ if (SkScalarNearlyZero(area)) {
SkPoint avg;
avg.set(0, 0);
for (int i = 0; i < count; ++i) {
@@ -87,7 +101,8 @@ void center_of_mass(const SegmentArray& segments, SkPoint* c) {
area = GrScalarDiv(GR_Scalar1, area);
center.fX = GrScalarMul(center.fX, area);
center.fY = GrScalarMul(center.fY, area);
- *c = center;
+ // undo the translate of p0 to the origin.
+ *c = center + p0;
}
GrAssert(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY));
}