Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: src/pathops/SkPathOpsCubic.cpp

Issue 1096923003: working on initial winding for cubics (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkPathOpsCubic.h ('k') | src/pathops/SkPathOpsCurve.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #include "SkGeometry.h" 7 #include "SkGeometry.h"
8 #include "SkLineParameters.h" 8 #include "SkLineParameters.h"
9 #include "SkPathOpsConic.h" 9 #include "SkPathOpsConic.h"
10 #include "SkPathOpsCubic.h" 10 #include "SkPathOpsCubic.h"
11 #include "SkPathOpsCurve.h"
11 #include "SkPathOpsLine.h" 12 #include "SkPathOpsLine.h"
12 #include "SkPathOpsQuad.h" 13 #include "SkPathOpsQuad.h"
13 #include "SkPathOpsRect.h" 14 #include "SkPathOpsRect.h"
14 #include "SkTSort.h" 15 #include "SkTSort.h"
15 16
16 const int SkDCubic::gPrecisionUnit = 256; // FIXME: test different values in te st framework 17 const int SkDCubic::gPrecisionUnit = 256; // FIXME: test different values in te st framework
17 18
18 // give up when changing t no longer moves point 19 // give up when changing t no longer moves point
19 // also, copy point rather than recompute it when it does change 20 // also, copy point rather than recompute it when it does change
20 double SkDCubic::binarySearch(double min, double max, double axisIntercept, 21 double SkDCubic::binarySearch(double min, double max, double axisIntercept,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 68
68 // FIXME: cache keep the bounds and/or precision with the caller? 69 // FIXME: cache keep the bounds and/or precision with the caller?
69 double SkDCubic::calcPrecision() const { 70 double SkDCubic::calcPrecision() const {
70 SkDRect dRect; 71 SkDRect dRect;
71 dRect.setBounds(*this); // OPTIMIZATION: just use setRawBounds ? 72 dRect.setBounds(*this); // OPTIMIZATION: just use setRawBounds ?
72 double width = dRect.fRight - dRect.fLeft; 73 double width = dRect.fRight - dRect.fLeft;
73 double height = dRect.fBottom - dRect.fTop; 74 double height = dRect.fBottom - dRect.fTop;
74 return (width > height ? width : height) / gPrecisionUnit; 75 return (width > height ? width : height) / gPrecisionUnit;
75 } 76 }
76 77
77 bool SkDCubic::clockwise() const { 78 bool SkDCubic::clockwise(bool* swap) const {
78 double sum = (fPts[0].fX - fPts[3].fX) * (fPts[0].fY + fPts[3].fY); 79 SkDPoint lastPt = fPts[kPointLast];
79 for (int idx = 0; idx < 3; ++idx) { 80 SkDPoint firstPt = fPts[0];
80 sum += (fPts[idx + 1].fX - fPts[idx].fX) * (fPts[idx + 1].fY + fPts[idx] .fY); 81 double sum = 0;
82 // pick the control point furthest from the line connecting the end points
83 SkLineParameters lineParameters;
84 lineParameters.cubicEndPoints(*this, 0, 3);
85 lineParameters.normalize();
86 double tiniest = SkTMin(SkTMin(SkTMin(SkTMin(SkTMin(SkTMin(SkTMin(fPts[0].fX , fPts[0].fY),
87 fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY), fPts[3].fX), fPt s[3].fY);
88 double largest = SkTMax(SkTMax(SkTMax(SkTMax(SkTMax(SkTMax(SkTMax(fPts[0].fX , fPts[0].fY),
89 fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY), fPts[3].fX), fPt s[3].fY);
90 largest = SkTMax(largest, -tiniest);
91 double pt1dist = lineParameters.controlPtDistance(*this, 1);
92 double pt2dist = lineParameters.controlPtDistance(*this, 2);
93 #if DEBUG_SWAP_TOP
94 SkDebugf("%s pt1dist=%1.9g pt2dist=%1.9g\n", __FUNCTION__, pt1dist, pt2dist) ;
95 #endif
96 int furthest;
97 if (!approximately_zero_when_compared_to(pt1dist, largest)
98 && !approximately_zero_when_compared_to(pt2dist, largest) && pt1dist * pt2dist < 0) {
99 furthest = 2;
100 } else {
101 furthest = fabs(pt1dist) < fabs(pt2dist) ? 2 : 1;
81 } 102 }
103 for (int idx = 1; idx <= 3; ++idx) {
104 sum += (firstPt.fX - lastPt.fX) * (firstPt.fY + lastPt.fY);
105 lastPt = firstPt;
106 firstPt = idx == 1 ? fPts[furthest] : fPts[kPointLast];
107 }
108 *swap = sum > 0 && !this->monotonicInY();
82 return sum <= 0; 109 return sum <= 0;
83 } 110 }
84 111
112 bool SkDCubic::Clockwise(const SkPoint* pts, double startT, double endT, bool* s wap) {
113 SkDCubic cubic;
114 cubic.set(pts);
115 #if 0
116 bool flip = startT > endT;
117 double inflectionTs[2];
118 int inflections = cubic.findInflections(inflectionTs);
119 for (int index = 0; index < inflections; ++index) {
120 double inflectionT = inflectionTs[index];
121 if (between(startT, inflectionT, endT)) {
122 if (flip) {
123 if (!roughly_equal(inflectionT, endT)) {
124 startT = inflectionT;
125 }
126 } else {
127 if (!roughly_equal(inflectionT, startT)) {
128 endT = inflectionT;
129 }
130 }
131 }
132 }
133 #endif
134 SkDCubic part = cubic.subDivide(startT, endT);
135 return part.clockwise(swap);
136 }
137
85 void SkDCubic::Coefficients(const double* src, double* A, double* B, double* C, double* D) { 138 void SkDCubic::Coefficients(const double* src, double* A, double* B, double* C, double* D) {
86 *A = src[6]; // d 139 *A = src[6]; // d
87 *B = src[4] * 3; // 3*c 140 *B = src[4] * 3; // 3*c
88 *C = src[2] * 3; // 3*b 141 *C = src[2] * 3; // 3*b
89 *D = src[0]; // a 142 *D = src[0]; // a
90 *A -= *D - *C + *B; // A = -a + 3*b - 3*c + d 143 *A -= *D - *C + *B; // A = -a + 3*b - 3*c + d
91 *B += 3 * *D - 2 * *C; // B = 3*a - 6*b + 3*c 144 *B += 3 * *D - 2 * *C; // B = 3*a - 6*b + 3*c
92 *C -= 3 * *D; // C = -3*a + 3*b 145 *C -= 3 * *D; // C = -3*a + 3*b
93 } 146 }
94 147
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY), fPts[3].fX), fPt s[3].fY); 232 fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY), fPts[3].fX), fPt s[3].fY);
180 largest = SkTMax(largest, -tiniest); 233 largest = SkTMax(largest, -tiniest);
181 double distance = lineParameters.controlPtDistance(*this, 1); 234 double distance = lineParameters.controlPtDistance(*this, 1);
182 if (!approximately_zero_when_compared_to(distance, largest)) { 235 if (!approximately_zero_when_compared_to(distance, largest)) {
183 return false; 236 return false;
184 } 237 }
185 distance = lineParameters.controlPtDistance(*this, 2); 238 distance = lineParameters.controlPtDistance(*this, 2);
186 return approximately_zero_when_compared_to(distance, largest); 239 return approximately_zero_when_compared_to(distance, largest);
187 } 240 }
188 241
189 bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) { 242 bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t, CubicType* resultType) {
190 SkScalar d[3]; 243 SkScalar d[3];
191 SkCubicType cubicType = SkClassifyCubic(pointsPtr, d); 244 SkCubicType cubicType = SkClassifyCubic(pointsPtr, d);
192 if (cubicType == kLoop_SkCubicType) { 245 if (cubicType == kLoop_SkCubicType) {
193 // crib code from gpu path utils that finds t values where loop self-int ersects 246 // crib code from gpu path utils that finds t values where loop self-int ersects
194 // use it to find mid of t values which should be a friendly place to ch op 247 // use it to find mid of t values which should be a friendly place to ch op
195 SkScalar tempSqrt = SkScalarSqrt(4.f * d[0] * d[2] - 3.f * d[1] * d[1]); 248 SkScalar tempSqrt = SkScalarSqrt(4.f * d[0] * d[2] - 3.f * d[1] * d[1]);
196 SkScalar ls = d[1] - tempSqrt; 249 SkScalar ls = d[1] - tempSqrt;
197 SkScalar lt = 2.f * d[0]; 250 SkScalar lt = 2.f * d[0];
198 SkScalar ms = d[1] + tempSqrt; 251 SkScalar ms = d[1] + tempSqrt;
199 SkScalar mt = 2.f * d[0]; 252 SkScalar mt = 2.f * d[0];
200 if (between(0, ls, lt) || between(0, ms, mt)) { 253 if (between(0, ls, lt) || between(0, ms, mt)) {
201 ls = ls / lt; 254 ls = ls / lt;
202 ms = ms / mt; 255 ms = ms / mt;
203 SkScalar smaller = SkTMax(0.f, SkTMin(ls, ms)); 256 SkScalar smaller = SkTMax(0.f, SkTMin(ls, ms));
204 SkScalar larger = SkTMin(1.f, SkTMax(ls, ms)); 257 SkScalar larger = SkTMin(1.f, SkTMax(ls, ms));
205 *t = (smaller + larger) / 2; 258 *t = (smaller + larger) / 2;
259 *resultType = kSplitAtLoop_SkDCubicType;
206 return *t > 0 && *t < 1; 260 return *t > 0 && *t < 1;
207 } 261 }
208 } else if (kSerpentine_SkCubicType == cubicType || kCusp_SkCubicType == cubi cType) { 262 } else if (kSerpentine_SkCubicType == cubicType || kCusp_SkCubicType == cubi cType) {
209 SkDCubic cubic; 263 SkDCubic cubic;
210 cubic.set(pointsPtr); 264 cubic.set(pointsPtr);
211 double inflectionTs[2]; 265 double inflectionTs[2];
212 int infTCount = cubic.findInflections(inflectionTs); 266 int infTCount = cubic.findInflections(inflectionTs);
213 if (infTCount == 2) { 267 if (infTCount == 2) {
214 double maxCurvature[3]; 268 double maxCurvature[3];
215 int roots = cubic.findMaxCurvature(maxCurvature); 269 int roots = cubic.findMaxCurvature(maxCurvature);
270 #if DEBUG_CUBIC_SPLIT
271 SkDebugf("%s\n", __FUNCTION__);
272 cubic.dump();
273 for (int index = 0; index < infTCount; ++index) {
274 SkDebugf("inflectionsTs[%d]=%1.9g ", index, inflectionTs[index]) ;
275 SkDPoint pt = cubic.ptAtT(inflectionTs[index]);
276 SkDVector dPt = cubic.dxdyAtT(inflectionTs[index]);
277 SkDLine perp = {{pt - dPt, pt + dPt}};
278 perp.dump();
279 }
280 for (int index = 0; index < roots; ++index) {
281 SkDebugf("maxCurvature[%d]=%1.9g ", index, maxCurvature[index]);
282 SkDPoint pt = cubic.ptAtT(maxCurvature[index]);
283 SkDVector dPt = cubic.dxdyAtT(maxCurvature[index]);
284 SkDLine perp = {{pt - dPt, pt + dPt}};
285 perp.dump();
286 }
287 #endif
216 for (int index = 0; index < roots; ++index) { 288 for (int index = 0; index < roots; ++index) {
217 if (between(inflectionTs[0], maxCurvature[index], inflectionTs[1 ])) { 289 if (between(inflectionTs[0], maxCurvature[index], inflectionTs[1 ])) {
218 *t = maxCurvature[index]; 290 *t = maxCurvature[index];
291 *resultType = kSplitAtMaxCurvature_SkDCubicType;
219 return true; 292 return true;
220 } 293 }
221 } 294 }
222 } else if (infTCount == 1) { 295 } else if (infTCount == 1) {
223 *t = inflectionTs[0]; 296 *t = inflectionTs[0];
297 *resultType = kSplitAtInflection_SkDCubicType;
224 return *t > 0 && *t < 1; 298 return *t > 0 && *t < 1;
225 } 299 }
226 return false;
227 } 300 }
228 return false; 301 return false;
229 } 302 }
230 303
231 bool SkDCubic::monotonicInY() const { 304 bool SkDCubic::monotonicInY() const {
232 return between(fPts[0].fY, fPts[1].fY, fPts[3].fY) 305 return between(fPts[0].fY, fPts[1].fY, fPts[3].fY)
233 && between(fPts[0].fY, fPts[2].fY, fPts[3].fY); 306 && between(fPts[0].fY, fPts[2].fY, fPts[3].fY);
234 } 307 }
235 308
236 void SkDCubic::otherPts(int index, const SkDPoint* o1Pts[kPointCount - 1]) const { 309 void SkDCubic::otherPts(int index, const SkDPoint* o1Pts[kPointCount - 1]) const {
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 double coeffX[4], coeffY[4]; 512 double coeffX[4], coeffY[4];
440 int i; 513 int i;
441 formulate_F1DotF2(&fPts[0].fX, coeffX); 514 formulate_F1DotF2(&fPts[0].fX, coeffX);
442 formulate_F1DotF2(&fPts[0].fY, coeffY); 515 formulate_F1DotF2(&fPts[0].fY, coeffY);
443 for (i = 0; i < 4; i++) { 516 for (i = 0; i < 4; i++) {
444 coeffX[i] = coeffX[i] + coeffY[i]; 517 coeffX[i] = coeffX[i] + coeffY[i];
445 } 518 }
446 return RootsValidT(coeffX[0], coeffX[1], coeffX[2], coeffX[3], tValues); 519 return RootsValidT(coeffX[0], coeffX[1], coeffX[2], coeffX[3], tValues);
447 } 520 }
448 521
449 SkDPoint SkDCubic::top(double startT, double endT) const { 522 SkDPoint SkDCubic::top(double startT, double endT, double* topT) const {
450 SkDCubic sub = subDivide(startT, endT); 523 SkDCubic sub = subDivide(startT, endT);
451 SkDPoint topPt = sub[0]; 524 SkDPoint topPt = sub[0];
525 *topT = startT;
452 if (topPt.fY > sub[3].fY || (topPt.fY == sub[3].fY && topPt.fX > sub[3].fX)) { 526 if (topPt.fY > sub[3].fY || (topPt.fY == sub[3].fY && topPt.fX > sub[3].fX)) {
527 *topT = endT;
453 topPt = sub[3]; 528 topPt = sub[3];
454 } 529 }
455 double extremeTs[2]; 530 double extremeTs[2];
456 if (!sub.monotonicInY()) { 531 if (!sub.monotonicInY()) {
457 int roots = FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, sub[3].fY, extr emeTs); 532 int roots = FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, sub[3].fY, extr emeTs);
458 for (int index = 0; index < roots; ++index) { 533 for (int index = 0; index < roots; ++index) {
459 double t = startT + (endT - startT) * extremeTs[index]; 534 double t = startT + (endT - startT) * extremeTs[index];
460 SkDPoint mid = ptAtT(t); 535 SkDPoint mid = ptAtT(t);
461 if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) { 536 if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) {
537 *topT = t;
462 topPt = mid; 538 topPt = mid;
463 } 539 }
464 } 540 }
465 } 541 }
466 return topPt; 542 return topPt;
467 } 543 }
468 544
469 SkDPoint SkDCubic::ptAtT(double t) const { 545 SkDPoint SkDCubic::ptAtT(double t) const {
470 if (0 == t) { 546 if (0 == t) {
471 return fPts[0]; 547 return fPts[0];
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 dst.pts[4].fY = (fPts[1].fY + 2 * fPts[2].fY + fPts[3].fY) / 4; 715 dst.pts[4].fY = (fPts[1].fY + 2 * fPts[2].fY + fPts[3].fY) / 4;
640 dst.pts[5].fX = (fPts[2].fX + fPts[3].fX) / 2; 716 dst.pts[5].fX = (fPts[2].fX + fPts[3].fX) / 2;
641 dst.pts[5].fY = (fPts[2].fY + fPts[3].fY) / 2; 717 dst.pts[5].fY = (fPts[2].fY + fPts[3].fY) / 2;
642 dst.pts[6] = fPts[3]; 718 dst.pts[6] = fPts[3];
643 return dst; 719 return dst;
644 } 720 }
645 interp_cubic_coords(&fPts[0].fX, &dst.pts[0].fX, t); 721 interp_cubic_coords(&fPts[0].fX, &dst.pts[0].fX, t);
646 interp_cubic_coords(&fPts[0].fY, &dst.pts[0].fY, t); 722 interp_cubic_coords(&fPts[0].fY, &dst.pts[0].fY, t);
647 return dst; 723 return dst;
648 } 724 }
OLDNEW
« no previous file with comments | « src/pathops/SkPathOpsCubic.h ('k') | src/pathops/SkPathOpsCurve.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698