2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
7 #include "PathOpsTestCommon.h"
8 #include "SkPathOpsBounds.h"
9 #include "SkPathOpsCubic.h"
10 #include "SkPathOpsLine.h"
11 #include "SkPathOpsQuad.h"
12 #include "SkPathOpsTriangle.h"
14 void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, true>& quads) {
15 SkTArray<double, true> ts;
16 cubic.toQuadraticTs(precision, &ts);
17 if (ts.count() <= 0) {
18 SkDQuad quad = cubic.toQuad();
19 quads.push_back(quad);
23 for (int i1 = 0; i1 <= ts.count(); ++i1) {
24 const double tEnd = i1 < ts.count() ? ts[i1] : 1;
25 SkDCubic part = cubic.subDivide(tStart, tEnd);
26 SkDQuad quad = part.toQuad();
27 quads.push_back(quad);
32 void CubicPathToQuads(const SkPath& cubicPath, SkPath* quadPath) {
35 SkTArray<SkDQuad, true> quads;
36 SkPath::RawIter iter(cubicPath);
39 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
41 case SkPath::kMove_Verb:
42 quadPath->moveTo(pts[0].fX, pts[0].fY);
44 case SkPath::kLine_Verb:
45 quadPath->lineTo(pts[1].fX, pts[1].fY);
47 case SkPath::kQuad_Verb:
48 quadPath->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
50 case SkPath::kCubic_Verb:
53 CubicToQuads(cubic, cubic.calcPrecision(), quads);
54 for (int index = 0; index < quads.count(); ++index) {
56 quads[index][1].asSkPoint(),
57 quads[index][2].asSkPoint()
59 quadPath->quadTo(qPts[0].fX, qPts[0].fY, qPts[1].fX, qPts[1].fY);
62 case SkPath::kClose_Verb:
66 SkDEBUGFAIL("bad verb");
72 void CubicPathToSimple(const SkPath& cubicPath, SkPath* simplePath) {
75 SkPath::RawIter iter(cubicPath);
78 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
80 case SkPath::kMove_Verb:
81 simplePath->moveTo(pts[0].fX, pts[0].fY);
83 case SkPath::kLine_Verb:
84 simplePath->lineTo(pts[1].fX, pts[1].fY);
86 case SkPath::kQuad_Verb:
87 simplePath->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
89 case SkPath::kCubic_Verb: {
92 int inflections = cubic.findInflections(tInflects);
93 if (inflections > 1 && tInflects[0] > tInflects[1]) {
94 SkTSwap(tInflects[0], tInflects[1]);
97 for (int index = 0; index <= inflections; ++index) {
98 double hi = index < inflections ? tInflects[index] : 1;
99 SkDCubic part = cubic.subDivide(lo, hi);
101 cPts[0] = part[1].asSkPoint();
102 cPts[1] = part[2].asSkPoint();
103 cPts[2] = part[3].asSkPoint();
104 simplePath->cubicTo(cPts[0].fX, cPts[0].fY, cPts[1].fX, cPts[1].fY,
105 cPts[2].fX, cPts[2].fY);
110 case SkPath::kClose_Verb:
114 SkDEBUGFAIL("bad verb");
120 static bool SkDoubleIsNaN(double x) {
124 bool ValidBounds(const SkPathOpsBounds& bounds) {
125 if (SkScalarIsNaN(bounds.fLeft)) {
128 if (SkScalarIsNaN(bounds.fTop)) {
131 if (SkScalarIsNaN(bounds.fRight)) {
134 return !SkScalarIsNaN(bounds.fBottom);
137 bool ValidCubic(const SkDCubic& cubic) {
138 for (int index = 0; index < 4; ++index) {
139 if (!ValidPoint(cubic[index])) {
146 bool ValidLine(const SkDLine& line) {
147 for (int index = 0; index < 2; ++index) {
148 if (!ValidPoint(line[index])) {
155 bool ValidPoint(const SkDPoint& pt) {
156 if (SkDoubleIsNaN(pt.fX)) {
159 return !SkDoubleIsNaN(pt.fY);
162 bool ValidPoints(const SkPoint* pts, int count) {
163 for (int index = 0; index < count; ++index) {
164 if (SkScalarIsNaN(pts[index].fX)) {
167 if (SkScalarIsNaN(pts[index].fY)) {
174 bool ValidQuad(const SkDQuad& quad) {
175 for (int index = 0; index < 3; ++index) {
176 if (!ValidPoint(quad[index])) {
183 bool ValidTriangle(const SkDTriangle& triangle) {
184 for (int index = 0; index < 3; ++index) {
185 if (!ValidPoint(triangle.fPts[index])) {
192 bool ValidVector(const SkDVector& v) {
193 if (SkDoubleIsNaN(v.fX)) {
196 return !SkDoubleIsNaN(v.fY);