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

Side by Side Diff: src/pathops/SkOpSegment.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/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('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 "SkOpCoincidence.h" 7 #include "SkOpCoincidence.h"
8 #include "SkOpContour.h" 8 #include "SkOpContour.h"
9 #include "SkOpSegment.h" 9 #include "SkOpSegment.h"
10 #include "SkPathWriter.h" 10 #include "SkPathWriter.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 SkOpSegment* other = oPtT->segment(); 100 SkOpSegment* other = oPtT->segment();
101 SkOpSpanBase* oSpan = oPtT->span(); 101 SkOpSpanBase* oSpan = oPtT->span();
102 return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable); 102 return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable);
103 } 103 }
104 104
105 SkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) { 105 SkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) {
106 SkASSERT(!done()); 106 SkASSERT(!done());
107 SkPoint topPt = {SK_ScalarMax, SK_ScalarMax}; 107 SkPoint topPt = {SK_ScalarMax, SK_ScalarMax};
108 // see if either end is not done since we want smaller Y of the pair 108 // see if either end is not done since we want smaller Y of the pair
109 bool lastDone = true; 109 bool lastDone = true;
110 double lastT = -1;
111 SkOpSpanBase* span = &fHead; 110 SkOpSpanBase* span = &fHead;
111 SkOpSpanBase* lastSpan = NULL;
112 do { 112 do {
113 if (lastDone && (span->final() || span->upCast()->done())) { 113 if (!lastDone || (!span->final() && !span->upCast()->done())) {
114 goto next;
115 }
116 {
117 const SkPoint& xy = span->pt(); 114 const SkPoint& xy = span->pt();
118 if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { 115 if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) {
119 topPt = xy; 116 topPt = xy;
120 if (firstSpan) { 117 if (firstSpan) {
121 *firstSpan = span; 118 *firstSpan = span;
122 } 119 }
123 } 120 }
124 if (fVerb != SkPath::kLine_Verb && !lastDone) { 121 if (fVerb != SkPath::kLine_Verb && !lastDone
125 SkPoint curveTop = (*CurveTop[fVerb])(fPts, fWeight, lastT, span ->t()); 122 && fCubicType != SkDCubic::kSplitAtMaxCurvature_SkDCubicType ) {
126 if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY 123 double curveTopT;
127 && topPt.fX > curveTop.fX)) { 124 SkPoint curveTop = (*CurveTop[fVerb])(fPts, fWeight, lastSpan->t (), span->t(),
125 &curveTopT);
126 if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY && topPt. fX > curveTop.fX)) {
128 topPt = curveTop; 127 topPt = curveTop;
129 if (firstSpan) { 128 if (firstSpan) {
130 *firstSpan = span; 129 const SkPoint& lastXY = lastSpan->pt();
130 *firstSpan = lastXY.fY > xy.fY || (lastXY.fY == xy.fY && lastXY.fX > xy.fX)
131 ? span : lastSpan;
131 } 132 }
132 } 133 }
133 } 134 }
134 lastT = span->t(); 135 lastSpan = span;
135 } 136 }
136 next:
137 if (span->final()) { 137 if (span->final()) {
138 break; 138 break;
139 } 139 }
140 lastDone = span->upCast()->done(); 140 lastDone = span->upCast()->done();
141 } while ((span = span->upCast()->next())); 141 } while ((span = span->upCast()->next()));
142 return topPt; 142 return topPt;
143 } 143 }
144 144
145 bool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask , int xorSuMask, 145 bool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask , int xorSuMask,
146 SkPathOp op) { 146 SkPathOp op) {
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 angle = span->toAngle(); 483 angle = span->toAngle();
484 if (angle && angle->fCheckCoincidence) { 484 if (angle && angle->fCheckCoincidence) {
485 angle->checkNearCoincidence(); 485 angle->checkNearCoincidence();
486 } 486 }
487 } while ((base = span->next())); 487 } while ((base = span->next()));
488 } 488 }
489 489
490 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order 490 // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of -polygon-points-are-in-clockwise-order
491 bool SkOpSegment::clockwise(const SkOpSpanBase* start, const SkOpSpanBase* end, bool* swap) const { 491 bool SkOpSegment::clockwise(const SkOpSpanBase* start, const SkOpSpanBase* end, bool* swap) const {
492 SkASSERT(fVerb != SkPath::kLine_Verb); 492 SkASSERT(fVerb != SkPath::kLine_Verb);
493 SkOpCurve edge; 493 if (fVerb != SkPath::kCubic_Verb) {
494 if (fVerb == SkPath::kCubic_Verb) { 494 SkOpCurve edge;
495 double startT = start->t(); 495 this->subDivide(start, end, &edge);
496 double endT = end->t(); 496 return SkDQuad::Clockwise(edge, swap);
497 bool flip = startT > endT;
498 SkDCubic cubic;
499 cubic.set(fPts);
500 double inflectionTs[2];
501 int inflections = cubic.findInflections(inflectionTs);
502 for (int index = 0; index < inflections; ++index) {
503 double inflectionT = inflectionTs[index];
504 if (between(startT, inflectionT, endT)) {
505 if (flip) {
506 if (!roughly_equal(inflectionT, endT)) {
507 startT = inflectionT;
508 }
509 } else {
510 if (!roughly_equal(inflectionT, startT)) {
511 endT = inflectionT;
512 }
513 }
514 }
515 }
516 SkDCubic part = cubic.subDivide(startT, endT);
517 edge.set(part);
518 } else {
519 subDivide(start, end, &edge);
520 } 497 }
521 bool sumSet = false; 498 return SkDCubic::Clockwise(fPts, start->t(), end->t(), swap);
522 int points = SkPathOpsVerbToPoints(fVerb);
523 double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY) ;
524 if (!sumSet) {
525 for (int idx = 0; idx < points; ++idx){
526 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[ idx].fY);
527 }
528 }
529 if (fVerb == SkPath::kCubic_Verb) {
530 SkDCubic cubic;
531 cubic.set(edge.fPts);
532 *swap = sum > 0 && !cubic.monotonicInY();
533 } else {
534 SkDQuad quad;
535 quad.set(edge.fPts);
536 *swap = sum > 0 && !quad.monotonicInY();
537 }
538 return sum <= 0;
539 } 499 }
540 500
541 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle , 501 void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle ,
542 SkOpAngle::IncludeType includeType) { 502 SkOpAngle::IncludeType includeType) {
543 const SkOpSegment* baseSegment = baseAngle->segment(); 503 const SkOpSegment* baseSegment = baseAngle->segment();
544 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); 504 int sumMiWinding = baseSegment->updateWindingReverse(baseAngle);
545 int sumSuWinding; 505 int sumSuWinding;
546 bool binary = includeType >= SkOpAngle::kBinarySingle; 506 bool binary = includeType >= SkOpAngle::kBinarySingle;
547 if (binary) { 507 if (binary) {
548 sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle); 508 sumSuWinding = baseSegment->updateOppWindingReverse(baseAngle);
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after
1109 return NULL; 1069 return NULL;
1110 } 1070 }
1111 const SkOpAngle* baseAngle = markAngle->next() == markAngle && !isVertical() ? markAngle 1071 const SkOpAngle* baseAngle = markAngle->next() == markAngle && !isVertical() ? markAngle
1112 : markAngle->findFirst(); 1072 : markAngle->findFirst();
1113 if (!baseAngle) { 1073 if (!baseAngle) {
1114 return NULL; // nothing to do 1074 return NULL; // nothing to do
1115 } 1075 }
1116 SkScalar top = SK_ScalarMax; 1076 SkScalar top = SK_ScalarMax;
1117 const SkOpAngle* firstAngle = NULL; 1077 const SkOpAngle* firstAngle = NULL;
1118 const SkOpAngle* angle = baseAngle; 1078 const SkOpAngle* angle = baseAngle;
1079 #if DEBUG_SWAP_TOP
1080 SkDebugf("-%s- baseAngle\n", __FUNCTION__);
1081 baseAngle->debugLoop();
1082 #endif
1119 do { 1083 do {
1120 if (!angle->unorderable()) { 1084 if (!angle->unorderable()) {
1121 const SkOpSegment* next = angle->segment(); 1085 const SkOpSegment* next = angle->segment();
1122 SkPathOpsBounds bounds; 1086 SkPathOpsBounds bounds;
1123 next->subDivideBounds(angle->end(), angle->start(), &bounds); 1087 next->subDivideBounds(angle->end(), angle->start(), &bounds);
1124 bool nearSame = AlmostEqualUlps(top, bounds.top()); 1088 bool nearSame = AlmostEqualUlps(top, bounds.top());
1125 bool lowerSector = !firstAngle || angle->sectorEnd() < firstAngle->s ectorStart(); 1089 bool lowerSector = !firstAngle || angle->sectorEnd() < firstAngle->s ectorStart();
1126 bool lesserSector = top > bounds.fTop; 1090 bool lesserSector = top > bounds.fTop;
1127 if (lesserSector && (!nearSame || lowerSector)) { 1091 if (lesserSector && (!nearSame || lowerSector)) {
1128 top = bounds.fTop; 1092 top = bounds.fTop;
1129 firstAngle = angle; 1093 firstAngle = angle;
1130 } 1094 }
1131 } 1095 }
1132 angle = angle->next(); 1096 angle = angle->next();
1133 } while (angle != baseAngle); 1097 } while (angle != baseAngle);
1134 if (!firstAngle) { 1098 if (!firstAngle) {
1135 return NULL; // if all are unorderable, give up 1099 return NULL; // if all are unorderable, give up
1136 } 1100 }
1137 #if DEBUG_SORT 1101 #if DEBUG_SWAP_TOP
1138 SkDebugf("%s\n", __FUNCTION__); 1102 SkDebugf("-%s- firstAngle\n", __FUNCTION__);
1139 firstAngle->debugLoop(); 1103 firstAngle->debugLoop();
1140 #endif 1104 #endif
1141 // skip edges that have already been processed 1105 // skip edges that have already been processed
1142 angle = firstAngle; 1106 angle = firstAngle;
1143 SkOpSegment* leftSegment = NULL; 1107 SkOpSegment* leftSegment = NULL;
1144 bool looped = false; 1108 bool looped = false;
1145 do { 1109 do {
1146 *unsortable = angle->unorderable(); 1110 *unsortable = angle->unorderable();
1147 if (firstPass || !*unsortable) { 1111 if (firstPass || !*unsortable) {
1148 leftSegment = angle->segment(); 1112 leftSegment = angle->segment();
1149 *startPtr = angle->end(); 1113 *startPtr = angle->end();
1150 *endPtr = angle->start(); 1114 *endPtr = angle->start();
1151 const SkOpSpan* firstSpan = (*startPtr)->starter(*endPtr); 1115 const SkOpSpan* firstSpan = (*startPtr)->starter(*endPtr);
1152 if (!firstSpan->done()) { 1116 if (!firstSpan->done()) {
1153 break; 1117 break;
1154 } 1118 }
1155 } 1119 }
1156 angle = angle->next(); 1120 angle = angle->next();
1157 looped = true; 1121 looped = true;
1158 } while (angle != firstAngle); 1122 } while (angle != firstAngle);
1159 if (angle == firstAngle && looped) { 1123 if (angle == firstAngle && looped) {
1160 return NULL; 1124 return NULL;
1161 } 1125 }
1162 if (leftSegment->verb() >= SkPath::kQuad_Verb) { 1126 if (leftSegment->verb() >= SkPath::kQuad_Verb) {
1163 SkOpSpanBase* start = *startPtr; 1127 SkOpSpanBase* start = *startPtr;
1164 SkOpSpanBase* end = *endPtr; 1128 SkOpSpanBase* end = *endPtr;
1165 bool swap; 1129 bool swap;
1166 if (!leftSegment->clockwise(start, end, &swap)) { 1130 bool cw = leftSegment->clockwise(start, end, &swap);
1167 #if DEBUG_SWAP_TOP 1131 #if DEBUG_SWAP_TOP
1168 SkDebugf("%s swap=%d inflections=%d monotonic=%d\n", 1132 SkDebugf("%s id=%d s=%1.9g e=%1.9g (%c) cw=%d swap=%d inflections=%d mon otonic=%d\n",
1169 __FUNCTION__, 1133 __FUNCTION__, leftSegment->debugID(), start->t(), end->t(),
1170 swap, leftSegment->debugInflections(start, end), 1134 start->t() < end->t() ? '-' : '+', cw,
1171 leftSegment->monotonicInY(start, end)); 1135 swap, leftSegment->debugInflections(start, end),
1172 #endif 1136 leftSegment->monotonicInY(start, end));
1173 if (swap) { 1137 #endif
1138 if (!cw && swap) {
1174 // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not t he first 1139 // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not t he first
1175 // sorted but merely the first not already processed (i.e., not done) 1140 // sorted but merely the first not already processed (i.e., not done)
1176 SkTSwap(*startPtr, *endPtr); 1141 SkTSwap(*startPtr, *endPtr);
1177 }
1178 } 1142 }
1179 // FIXME: clockwise isn't reliable -- try computing swap from tangent ? 1143 // FIXME: clockwise isn't reliable -- try computing swap from tangent ?
1144 } else {
1145 #if DEBUG_SWAP_TOP
1146 SkDebugf("%s id=%d s=%1.9g e=%1.9g (%c) cw=%d swap=%d inflections=%d mon otonic=%d\n",
1147 __FUNCTION__, leftSegment->debugID(), (*startPtr)->t(), (*endPtr )->t(),
1148 (*startPtr)->t() < (*endPtr)->t() ? '-' : '+', -1, -1, -1, 1);
1149 #endif
1180 } 1150 }
1181 return leftSegment; 1151 return leftSegment;
1182 } 1152 }
1183 1153
1184 SkOpGlobalState* SkOpSegment::globalState() const { 1154 SkOpGlobalState* SkOpSegment::globalState() const {
1185 return contour()->globalState(); 1155 return contour()->globalState();
1186 } 1156 }
1187 1157
1188 void SkOpSegment::init(SkPoint pts[], SkScalar weight, SkOpContour* contour, SkP ath::Verb verb) { 1158 void SkOpSegment::init(SkPoint pts[], SkScalar weight, SkOpContour* contour, SkP ath::Verb verb) {
1189 fContour = contour; 1159 fContour = contour;
1190 fNext = NULL; 1160 fNext = NULL;
1191 fPts = pts; 1161 fPts = pts;
1192 fWeight = weight; 1162 fWeight = weight;
1193 fVerb = verb; 1163 fVerb = verb;
1164 fCubicType = SkDCubic::kUnsplit_SkDCubicType;
1194 fCount = 0; 1165 fCount = 0;
1195 fDoneCount = 0; 1166 fDoneCount = 0;
1196 fVisited = false; 1167 fVisited = false;
1197 SkOpSpan* zeroSpan = &fHead; 1168 SkOpSpan* zeroSpan = &fHead;
1198 zeroSpan->init(this, NULL, 0, fPts[0]); 1169 zeroSpan->init(this, NULL, 0, fPts[0]);
1199 SkOpSpanBase* oneSpan = &fTail; 1170 SkOpSpanBase* oneSpan = &fTail;
1200 zeroSpan->setNext(oneSpan); 1171 zeroSpan->setNext(oneSpan);
1201 oneSpan->initBase(this, zeroSpan, 1, fPts[SkPathOpsVerbToPoints(fVerb)]); 1172 oneSpan->initBase(this, zeroSpan, 1, fPts[SkPathOpsVerbToPoints(fVerb)]);
1202 SkDEBUGCODE(fID = globalState()->nextSegmentID()); 1173 SkDEBUGCODE(fID = globalState()->nextSegmentID());
1203 } 1174 }
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after
2057 #if DEBUG_WINDING_AT_T 2028 #if DEBUG_WINDING_AT_T
2058 SkDebugf(" dx=%c winding=%d\n", *dx > 0 ? '+' : '-', winding); 2029 SkDebugf(" dx=%c winding=%d\n", *dx > 0 ? '+' : '-', winding);
2059 #endif 2030 #endif
2060 return winding; 2031 return winding;
2061 } 2032 }
2062 2033
2063 int SkOpSegment::windSum(const SkOpAngle* angle) const { 2034 int SkOpSegment::windSum(const SkOpAngle* angle) const {
2064 const SkOpSpan* minSpan = angle->start()->starter(angle->end()); 2035 const SkOpSpan* minSpan = angle->start()->starter(angle->end());
2065 return minSpan->windSum(); 2036 return minSpan->windSum();
2066 } 2037 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698