aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops/SkPathOpsCurve.cpp
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-04-29 08:28:30 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-29 08:28:30 -0700
commitaec251012542e971100e218bf463adbfb5d21d20 (patch)
tree16c2e84c2d59d94b75d7d2bc50fec53c0e38a898 /src/pathops/SkPathOpsCurve.cpp
parent97fdea6c4393cf0102d7eee5790782509fb4f57b (diff)
minor fixes to cubics code and overall alignment of how bounds and tops are computed for all curve types
All but 17 extended tests work. A helper function is privately added to SkPath.h to permit a test to modify a given point in a path. BUG=skia:3588 Review URL: https://codereview.chromium.org/1107353004
Diffstat (limited to 'src/pathops/SkPathOpsCurve.cpp')
-rw-r--r--src/pathops/SkPathOpsCurve.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/pathops/SkPathOpsCurve.cpp b/src/pathops/SkPathOpsCurve.cpp
new file mode 100644
index 0000000000..651e64a908
--- /dev/null
+++ b/src/pathops/SkPathOpsCurve.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "SkPathOpsBounds.h"
+#include "SkPathOpsRect.h"
+#include "SkPathOpsCurve.h"
+
+SkDPoint SkDCurve::conicTop(const SkPoint curve[3], SkScalar curveWeight,
+ double startT, double endT, double* topT) {
+ SkDPoint topPt = fConic[0];
+ *topT = startT;
+ if (topPt.fY > fConic[2].fY || (topPt.fY == fConic[2].fY && topPt.fX > fConic[2].fX)) {
+ *topT = endT;
+ topPt = fConic[2];
+ }
+ if (!fConic.monotonicInY()) {
+ double extremeT;
+ if (SkDConic::FindExtrema(&fConic.fPts.fPts[0].fY, fConic.fWeight, &extremeT)) {
+ SkDConic dCurve;
+ dCurve.set(curve, curveWeight);
+ extremeT = startT + (endT - startT) * extremeT;
+ SkDPoint test = dCurve.ptAtT(extremeT);
+ if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) {
+ *topT = extremeT;
+ topPt = test;
+ }
+ }
+ }
+ return topPt;
+}
+
+SkDPoint SkDCurve::cubicTop(const SkPoint curve[4], SkScalar ,
+ double startT, double endT, double* topT) {
+ SkDPoint topPt = fCubic[0];
+ *topT = startT;
+ if (topPt.fY > fCubic[3].fY || (topPt.fY == fCubic[3].fY && topPt.fX > fCubic[3].fX)) {
+ *topT = endT;
+ topPt = fCubic[3];
+ }
+ double extremeTs[2];
+ if (!fCubic.monotonicInY()) {
+ int roots = SkDCubic::FindExtrema(&fCubic.fPts[0].fY, extremeTs);
+ SkDCubic dCurve;
+ dCurve.set(curve);
+ for (int index = 0; index < roots; ++index) {
+ double t = startT + (endT - startT) * extremeTs[index];
+ SkDPoint mid = dCurve.ptAtT(t);
+ if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) {
+ *topT = t;
+ topPt = mid;
+ }
+ }
+ }
+ return topPt;
+}
+
+SkDPoint SkDCurve::lineTop(const SkPoint[2], SkScalar , double startT, double endT, double* topT) {
+ SkDPoint topPt = fLine[0];
+ *topT = startT;
+ if (topPt.fY > fLine[1].fY || (topPt.fY == fLine[1].fY && topPt.fX > fLine[1].fX)) {
+ *topT = endT;
+ topPt = fLine[1];
+ }
+ return topPt;
+}
+
+SkDPoint SkDCurve::quadTop(const SkPoint curve[3], SkScalar ,
+ double startT, double endT, double* topT) {
+ SkDPoint topPt = fQuad[0];
+ *topT = startT;
+ if (topPt.fY > fQuad[2].fY || (topPt.fY == fQuad[2].fY && topPt.fX > fQuad[2].fX)) {
+ *topT = endT;
+ topPt = fQuad[2];
+ }
+ if (!fQuad.monotonicInY()) {
+ double extremeT;
+ if (SkDQuad::FindExtrema(&fQuad.fPts[0].fY, &extremeT)) {
+ SkDQuad dCurve;
+ dCurve.set(curve);
+ extremeT = startT + (endT - startT) * extremeT;
+ SkDPoint test = dCurve.ptAtT(extremeT);
+ if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) {
+ *topT = extremeT;
+ topPt = test;
+ }
+ }
+ }
+ return topPt;
+}
+
+SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar curveWeight,
+ double tStart, double tEnd, double* topT) = {
+ NULL,
+ &SkDCurve::lineTop,
+ &SkDCurve::quadTop,
+ &SkDCurve::conicTop,
+ &SkDCurve::cubicTop
+};
+
+void SkDCurve::setConicBounds(const SkPoint curve[3], SkScalar curveWeight,
+ double tStart, double tEnd, SkPathOpsBounds* bounds) {
+ SkDConic dCurve;
+ dCurve.set(curve, curveWeight);
+ SkDRect dRect;
+ dRect.setBounds(dCurve, fConic, tStart, tEnd);
+ bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
+ SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
+}
+
+void SkDCurve::setCubicBounds(const SkPoint curve[4], SkScalar ,
+ double tStart, double tEnd, SkPathOpsBounds* bounds) {
+ SkDCubic dCurve;
+ dCurve.set(curve);
+ SkDRect dRect;
+ dRect.setBounds(dCurve, fCubic, tStart, tEnd);
+ bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
+ SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
+}
+
+void SkDCurve::setLineBounds(const SkPoint[2], SkScalar ,
+ double , double , SkPathOpsBounds* bounds) {
+ bounds->setPointBounds(fLine[0]);
+ bounds->add(fLine[1]);
+}
+
+void SkDCurve::setQuadBounds(const SkPoint curve[3], SkScalar ,
+ double tStart, double tEnd, SkPathOpsBounds* bounds) {
+ SkDQuad dCurve;
+ dCurve.set(curve);
+ SkDRect dRect;
+ dRect.setBounds(dCurve, fQuad, tStart, tEnd);
+ bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop),
+ SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom));
+}
+
+void (SkDCurve::* const SetBounds[])(const SkPoint curve[], SkScalar curveWeight,
+ double tStart, double tEnd, SkPathOpsBounds* bounds) = {
+ NULL,
+ &SkDCurve::setLineBounds,
+ &SkDCurve::setQuadBounds,
+ &SkDCurve::setConicBounds,
+ &SkDCurve::setCubicBounds
+};