aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-20 17:24:16 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-20 17:24:16 +0000
commit17bb458fe897411218d8c9781770948d4398b723 (patch)
treed2396f5677b678aaac5d344d68bd4916677f3e05
parentb00a85b7f30c9c3dc549524205631b9f2f429cf8 (diff)
Add fast path in arcTo and addArc for 0==sweep && 0|360==sweepAngle
-rw-r--r--bench/PathBench.cpp55
-rw-r--r--src/core/SkPath.cpp10
2 files changed, 65 insertions, 0 deletions
diff --git a/bench/PathBench.cpp b/bench/PathBench.cpp
index a8b31e2777..61014e832e 100644
--- a/bench/PathBench.cpp
+++ b/bench/PathBench.cpp
@@ -617,6 +617,57 @@ private:
typedef RandomPathBench INHERITED;
};
+
+class CirclesBench : public SkBenchmark {
+protected:
+ SkString fName;
+
+ enum {
+ N = SkBENCHLOOP(100)
+ };
+public:
+ CirclesBench(void* param) : INHERITED(param) {
+ fName.printf("circles");
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+
+ paint.setColor(SK_ColorBLACK);
+ paint.setAntiAlias(true);
+
+ SkRandom rand;
+
+ SkRect r;
+
+ for (int i = 0; i < 5000; ++i) {
+ SkScalar radius = rand.nextUScalar1() * 3;
+ r.fLeft = rand.nextUScalar1() * 300;
+ r.fTop = rand.nextUScalar1() * 300;
+ r.fRight = r.fLeft + 2 * radius;
+ r.fBottom = r.fTop + 2 * radius;
+
+ SkPath temp;
+
+ // mimic how Chrome does circles
+ temp.arcTo(r, 0, 0, false);
+ temp.addOval(r, SkPath::kCCW_Direction);
+ temp.arcTo(r, 360, 0, true);
+ temp.close();
+
+ canvas->drawPath(temp, paint);
+ }
+ }
+
+private:
+ typedef SkBenchmark INHERITED;
+};
+
static SkBenchmark* FactT00(void* p) { return new TrianglePathBench(p, FLAGS00); }
static SkBenchmark* FactT01(void* p) { return new TrianglePathBench(p, FLAGS01); }
static SkBenchmark* FactT10(void* p) { return new TrianglePathBench(p, FLAGS10); }
@@ -712,3 +763,7 @@ static BenchRegistry gRegAddMatrix(FactAddMatrix);
static BenchRegistry gRegPathTo(FactPathTo);
static BenchRegistry gRegReverseAdd(FactReverseAdd);
static BenchRegistry gRegReverseTo(FactReverseTo);
+
+static SkBenchmark* CirclesTest(void* p) { return new CirclesBench(p); }
+static BenchRegistry gRegCirclesTest(CirclesTest);
+
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 674ba980f6..8184345a5b 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -933,6 +933,16 @@ void SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) {
static int build_arc_points(const SkRect& oval, SkScalar startAngle,
SkScalar sweepAngle,
SkPoint pts[kSkBuildQuadArcStorage]) {
+
+ if (0 == sweepAngle &&
+ (0 == startAngle || SkIntToScalar(360) == startAngle)) {
+ // Chrome uses this path to move into and out of ovals. If not
+ // treated as a special case the moves can distort the oval's
+ // bounding box (and break the circle special case).
+ pts[0].set(oval.fRight, oval.centerY());
+ return 1;
+ }
+
SkVector start, stop;
start.fY = SkScalarSinCos(SkDegreesToRadians(startAngle), &start.fX);