All rSomethingTo() immediately following a close() are relative to the point we closed from, not the point we close to.  Fix that.

Seems like this has been broken since the stone ages.

BUG=skia:1474, code.google.com/p/android/issues/detail?id=41216
R=bsalomon@google.com

Author: mtklein@google.com

Review URL: https://chromiumcodereview.appspot.com/22681006

git-svn-id: http://skia.googlecode.com/svn/trunk@10666 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 97204bb..ed2f555 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -749,6 +749,7 @@
 }
 
 void SkPath::rLineTo(SkScalar x, SkScalar y) {
+    this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
     SkPoint pt;
     this->getLastPt(&pt);
     this->lineTo(pt.fX + x, pt.fY + y);
@@ -770,6 +771,7 @@
 }
 
 void SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
+    this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
     SkPoint pt;
     this->getLastPt(&pt);
     this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2);
@@ -803,6 +805,7 @@
 
 void SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
                       SkScalar w) {
+    this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
     SkPoint pt;
     this->getLastPt(&pt);
     this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w);
@@ -827,6 +830,7 @@
 
 void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                       SkScalar x3, SkScalar y3) {
+    this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
     SkPoint pt;
     this->getLastPt(&pt);
     this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2,
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index e698c7c..4637e92 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -32,6 +32,56 @@
     return SkSurface::NewRaster(info);
 }
 
+static void test_path_close_issue1474(skiatest::Reporter* reporter) {
+    // This test checks that r{Line,Quad,Conic,Cubic}To following a close()
+    // are relative to the point we close to, not relative to the point we close from.
+    SkPath path;
+    SkPoint last;
+
+    // Test rLineTo().
+    path.rLineTo(0, 100);
+    path.rLineTo(100, 0);
+    path.close();          // Returns us back to 0,0.
+    path.rLineTo(50, 50);  // This should go to 50,50.
+
+    path.getLastPt(&last);
+    REPORTER_ASSERT(reporter, 50 == last.fX);
+    REPORTER_ASSERT(reporter, 50 == last.fY);
+
+    // Test rQuadTo().
+    path.rewind();
+    path.rLineTo(0, 100);
+    path.rLineTo(100, 0);
+    path.close();
+    path.rQuadTo(50, 50, 75, 75);
+
+    path.getLastPt(&last);
+    REPORTER_ASSERT(reporter, 75 == last.fX);
+    REPORTER_ASSERT(reporter, 75 == last.fY);
+
+    // Test rConicTo().
+    path.rewind();
+    path.rLineTo(0, 100);
+    path.rLineTo(100, 0);
+    path.close();
+    path.rConicTo(50, 50, 85, 85, 2);
+
+    path.getLastPt(&last);
+    REPORTER_ASSERT(reporter, 85 == last.fX);
+    REPORTER_ASSERT(reporter, 85 == last.fY);
+
+    // Test rCubicTo().
+    path.rewind();
+    path.rLineTo(0, 100);
+    path.rLineTo(100, 0);
+    path.close();
+    path.rCubicTo(50, 50, 85, 85, 95, 95);
+
+    path.getLastPt(&last);
+    REPORTER_ASSERT(reporter, 95 == last.fX);
+    REPORTER_ASSERT(reporter, 95 == last.fY);
+}
+
 static void test_android_specific_behavior(skiatest::Reporter* reporter) {
 #ifdef SK_BUILD_FOR_ANDROID
     // Copy constructor should preserve generation ID, but assignment shouldn't.
@@ -2469,6 +2519,7 @@
     test_bad_cubic_crbug229478();
     test_bad_cubic_crbug234190();
     test_android_specific_behavior(reporter);
+    test_path_close_issue1474(reporter);
 }
 
 #include "TestClassDef.h"