aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/PathBench.cpp107
-rw-r--r--include/core/SkGeometry.h9
-rw-r--r--src/core/SkGeometry.cpp53
3 files changed, 127 insertions, 42 deletions
diff --git a/bench/PathBench.cpp b/bench/PathBench.cpp
index dc95ea669b..6ef78ccdd7 100644
--- a/bench/PathBench.cpp
+++ b/bench/PathBench.cpp
@@ -15,7 +15,6 @@
#include "SkString.h"
#include "SkTArray.h"
-
enum Flags {
kStroke_Flag = 1 << 0,
kBig_Flag = 1 << 1
@@ -908,22 +907,120 @@ public:
fRQ.fPts[2].set(100, 100);
fRQ.fW = SkScalarCos(SK_ScalarPI/4);
}
-
+
private:
virtual const char* onGetName() SK_OVERRIDE {
return "ratquad-chop-half";
}
-
+
virtual void onDraw(SkCanvas*) SK_OVERRIDE {
SkConic dst[2];
for (int i = 0; i < N; ++i) {
fRQ.chop(dst);
}
}
+
+ typedef SkBenchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+static void rand_conic(SkConic* conic, SkRandom& rand) {
+ for (int i = 0; i < 3; ++i) {
+ conic->fPts[i].set(rand.nextUScalar1() * 100, rand.nextUScalar1() * 100);
+ }
+ if (rand.nextUScalar1() > 0.5f) {
+ conic->fW = rand.nextUScalar1();
+ } else {
+ conic->fW = 1 + rand.nextUScalar1() * 4;
+ }
+}
+
+class ConicBench : public SkBenchmark {
+public:
+ ConicBench(void* param) : INHERITED(param) {
+ SkRandom rand;
+ for (int i = 0; i < CONICS; ++i) {
+ rand_conic(&fConics[i], rand);
+ }
+ fIsRendering = false;
+ }
+
+protected:
+ enum {
+ N = 20000,
+ CONICS = 100
+ };
+ SkConic fConics[CONICS];
+
+private:
typedef SkBenchmark INHERITED;
};
+class ConicBench_ComputeError : public ConicBench {
+public:
+ ConicBench_ComputeError(void* param) : INHERITED(param) {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "conic-compute-error";
+ }
+
+ virtual void onDraw(SkCanvas*) SK_OVERRIDE {
+ SkVector err;
+ for (int i = 0; i < N; ++i) {
+ for (int j = 0; j < CONICS; ++j) {
+ fConics[j].computeAsQuadError(&err);
+ }
+ }
+ }
+
+private:
+ typedef ConicBench INHERITED;
+};
+
+class ConicBench_asQuadTol : public ConicBench {
+public:
+ ConicBench_asQuadTol(void* param) : INHERITED(param) {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "conic-asQuadTol";
+ }
+
+ virtual void onDraw(SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < N; ++i) {
+ for (int j = 0; j < CONICS; ++j) {
+ fConics[j].asQuadTol(SK_ScalarHalf);
+ }
+ }
+ }
+
+private:
+ typedef ConicBench INHERITED;
+};
+
+class ConicBench_quadPow2 : public ConicBench {
+public:
+ ConicBench_quadPow2(void* param) : INHERITED(param) {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "conic-quadPow2";
+ }
+
+ virtual void onDraw(SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < N; ++i) {
+ for (int j = 0; j < CONICS; ++j) {
+ fConics[j].computeQuadPOW2(SK_ScalarHalf);
+ }
+ }
+ }
+
+private:
+ typedef ConicBench INHERITED;
+};
+
///////////////////////////////////////////////////////////////////////////////
const SkRect ConservativelyContainsBench::kBounds = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
@@ -983,3 +1080,7 @@ DEF_BENCH( return new ConservativelyContainsBench(p, ConservativelyContainsBench
DEF_BENCH( return new ConicBench_Chop5(p) )
DEF_BENCH( return new ConicBench_ChopHalf(p) )
+DEF_BENCH( return new ConicBench_ComputeError(p) )
+DEF_BENCH( return new ConicBench_asQuadTol(p) )
+DEF_BENCH( return new ConicBench_quadPow2(p) )
+
diff --git a/include/core/SkGeometry.h b/include/core/SkGeometry.h
index 97997c410a..1251fcf98d 100644
--- a/include/core/SkGeometry.h
+++ b/include/core/SkGeometry.h
@@ -220,13 +220,8 @@ struct SkConic {
void chopAt(SkScalar t, SkConic dst[2]) const;
void chop(SkConic dst[2]) const;
- /**
- * Return the max difference between the conic and its framing quadratic
- * in err and return true. If the conic is degenerate (a line between
- * pts[0] and pts[2]) or has a negative weight, return false and ignore
- * the diff parameter.
- */
- bool computeErrorAsQuad(SkVector* err) const;
+ void computeAsQuadError(SkVector* err) const;
+ bool asQuadTol(SkScalar tol) const;
int computeQuadPOW2(SkScalar tol) const;
int chopIntoQuadsPOW2(SkPoint pts[], int pow2) const;
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index dcdbf9c2a4..b6b23bcfd0 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -1547,32 +1547,36 @@ void SkConic::chop(SkConic dst[2]) const {
* "High order approximation of conic sections by quadratic splines"
* by Michael Floater, 1993
*/
-bool SkConic::computeErrorAsQuad(SkVector* err) const {
- if (fW <= 0) {
- return false;
- }
- SkScalar a = fW - 1;
- SkScalar k = a / (4 * (2 + a));
- err->set(k * (fPts[0].fX - 2 * fPts[1].fX + fPts[2].fX),
- k * (fPts[0].fY - 2 * fPts[1].fY + fPts[2].fY));
- return true;
+#define AS_QUAD_ERROR_SETUP \
+ SkScalar a = fW - 1; \
+ SkScalar k = a / (4 * (2 + a)); \
+ SkScalar x = k * (fPts[0].fX - 2 * fPts[1].fX + fPts[2].fX); \
+ SkScalar y = k * (fPts[0].fY - 2 * fPts[1].fY + fPts[2].fY);
+
+void SkConic::computeAsQuadError(SkVector* err) const {
+ AS_QUAD_ERROR_SETUP
+ err->set(x, y);
+}
+
+bool SkConic::asQuadTol(SkScalar tol) const {
+ AS_QUAD_ERROR_SETUP
+ return (x * x + y * y) <= tol * tol;
}
int SkConic::computeQuadPOW2(SkScalar tol) const {
- SkVector diff;
- if (!this->computeErrorAsQuad(&diff)) {
+ AS_QUAD_ERROR_SETUP
+ SkScalar error = SkScalarSqrt(x * x + y * y) - tol;
+
+ if (error <= 0) {
return 0;
}
-
- // the error reduces by 4 with each subdivision, so return the subdivision
- // count needed.
- SkScalar error = diff.length() - SkScalarAbs(tol);
uint32_t ierr = (uint32_t)error;
- return (33 - SkCLZ(ierr)) >> 1;
+ return (34 - SkCLZ(ierr)) >> 1;
}
static SkPoint* subdivide(const SkConic& src, SkPoint pts[], int level) {
SkASSERT(level >= 0);
+
if (0 == level) {
memcpy(pts, &src.fPts[1], 2 * sizeof(SkPoint));
return pts + 2;
@@ -1586,22 +1590,7 @@ static SkPoint* subdivide(const SkConic& src, SkPoint pts[], int level) {
}
int SkConic::chopIntoQuadsPOW2(SkPoint pts[], int pow2) const {
- if (pow2 < 0) {
- return 0;
- }
- if (0 == pow2) {
- memcpy(pts, fPts, 3 * sizeof(SkPoint));
- return 1;
- }
- if (1 == pow2) {
- SkConic dst[2];
- this->chop(dst);
- memcpy(pts, dst[0].fPts, 3 * sizeof(SkPoint));
- pts += 3;
- memcpy(pts, dst[1].fPts + 1, 2 * sizeof(SkPoint));
- return 2;
- }
-
+ SkASSERT(pow2 >= 0);
*pts = fPts[0];
SkDEBUGCODE(SkPoint* endPts =) subdivide(*this, pts + 1, pow2);
SkASSERT(endPts - pts == (2 * (1 << pow2) + 1));