| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2008 The Android Open Source Project | 2 * Copyright 2008 The Android Open Source Project |
| 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 | 7 |
| 8 #include "SkStrokerPriv.h" | 8 #include "SkStrokerPriv.h" |
| 9 #include "SkGeometry.h" | 9 #include "SkGeometry.h" |
| 10 #include "SkPathPriv.h" | 10 #include "SkPathPriv.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 class SkPathStroker { | 119 class SkPathStroker { |
| 120 public: | 120 public: |
| 121 SkPathStroker(const SkPath& src, | 121 SkPathStroker(const SkPath& src, |
| 122 SkScalar radius, SkScalar miterLimit, SkPaint::Cap, | 122 SkScalar radius, SkScalar miterLimit, SkPaint::Cap, |
| 123 SkPaint::Join, SkScalar resScale); | 123 SkPaint::Join, SkScalar resScale); |
| 124 | 124 |
| 125 bool hasOnlyMoveTo() const { return 0 == fSegmentCount; } | 125 bool hasOnlyMoveTo() const { return 0 == fSegmentCount; } |
| 126 SkPoint moveToPt() const { return fFirstPt; } | 126 SkPoint moveToPt() const { return fFirstPt; } |
| 127 | 127 |
| 128 void moveTo(const SkPoint&); | 128 void moveTo(const SkPoint&); |
| 129 void lineTo(const SkPoint&); | 129 void lineTo(const SkPoint&, const SkPath::Iter* iter = nullptr); |
| 130 void quadTo(const SkPoint&, const SkPoint&); | 130 void quadTo(const SkPoint&, const SkPoint&); |
| 131 void conicTo(const SkPoint&, const SkPoint&, SkScalar weight); | 131 void conicTo(const SkPoint&, const SkPoint&, SkScalar weight); |
| 132 void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&); | 132 void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&); |
| 133 void close(bool isLine) { this->finishContour(true, isLine); } | 133 void close(bool isLine) { this->finishContour(true, isLine); } |
| 134 | 134 |
| 135 void done(SkPath* dst, bool isLine) { | 135 void done(SkPath* dst, bool isLine) { |
| 136 this->finishContour(false, isLine); | 136 this->finishContour(false, isLine); |
| 137 fOuter.addPath(fExtra); | 137 fOuter.addPath(fExtra); |
| 138 dst->swap(fOuter); | 138 dst->swap(fOuter); |
| 139 } | 139 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 kDegenerate3_ReductionType, // three areas of max curvature found (for c
ubic) | 180 kDegenerate3_ReductionType, // three areas of max curvature found (for c
ubic) |
| 181 }; | 181 }; |
| 182 | 182 |
| 183 enum IntersectRayType { | 183 enum IntersectRayType { |
| 184 kCtrlPt_RayType, | 184 kCtrlPt_RayType, |
| 185 kResultType_RayType, | 185 kResultType_RayType, |
| 186 }; | 186 }; |
| 187 | 187 |
| 188 int fRecursionDepth; // track stack depth to abort if numerics ru
n amok | 188 int fRecursionDepth; // track stack depth to abort if numerics ru
n amok |
| 189 bool fFoundTangents; // do less work until tangents meet (cubic) | 189 bool fFoundTangents; // do less work until tangents meet (cubic) |
| 190 bool fJoinCompleted; // previous join was not degenerate |
| 190 | 191 |
| 191 void addDegenerateLine(const SkQuadConstruct* ); | 192 void addDegenerateLine(const SkQuadConstruct* ); |
| 192 static ReductionType CheckConicLinear(const SkConic& , SkPoint* reduction); | 193 static ReductionType CheckConicLinear(const SkConic& , SkPoint* reduction); |
| 193 static ReductionType CheckCubicLinear(const SkPoint cubic[4], SkPoint reduct
ion[3], | 194 static ReductionType CheckCubicLinear(const SkPoint cubic[4], SkPoint reduct
ion[3], |
| 194 const SkPoint** tanPtPtr); | 195 const SkPoint** tanPtPtr); |
| 195 static ReductionType CheckQuadLinear(const SkPoint quad[3], SkPoint* reducti
on); | 196 static ReductionType CheckQuadLinear(const SkPoint quad[3], SkPoint* reducti
on); |
| 196 ResultType compareQuadConic(const SkConic& , SkQuadConstruct* ) const; | 197 ResultType compareQuadConic(const SkConic& , SkQuadConstruct* ) const; |
| 197 ResultType compareQuadCubic(const SkPoint cubic[4], SkQuadConstruct* ); | 198 ResultType compareQuadCubic(const SkPoint cubic[4], SkQuadConstruct* ); |
| 198 ResultType compareQuadQuad(const SkPoint quad[3], SkQuadConstruct* ); | 199 ResultType compareQuadQuad(const SkPoint quad[3], SkQuadConstruct* ); |
| 199 void conicPerpRay(const SkConic& , SkScalar t, SkPoint* tPt, SkPoint* onPt, | 200 void conicPerpRay(const SkConic& , SkScalar t, SkPoint* tPt, SkPoint* onPt, |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 } else { // we have a previous segment | 267 } else { // we have a previous segment |
| 267 fJoiner(&fOuter, &fInner, fPrevUnitNormal, fPrevPt, *unitNormal, | 268 fJoiner(&fOuter, &fInner, fPrevUnitNormal, fPrevPt, *unitNormal, |
| 268 fRadius, fInvMiterLimit, fPrevIsLine, currIsLine); | 269 fRadius, fInvMiterLimit, fPrevIsLine, currIsLine); |
| 269 } | 270 } |
| 270 fPrevIsLine = currIsLine; | 271 fPrevIsLine = currIsLine; |
| 271 return true; | 272 return true; |
| 272 } | 273 } |
| 273 | 274 |
| 274 void SkPathStroker::postJoinTo(const SkPoint& currPt, const SkVector& normal, | 275 void SkPathStroker::postJoinTo(const SkPoint& currPt, const SkVector& normal, |
| 275 const SkVector& unitNormal) { | 276 const SkVector& unitNormal) { |
| 277 fJoinCompleted = true; |
| 276 fPrevPt = currPt; | 278 fPrevPt = currPt; |
| 277 fPrevUnitNormal = unitNormal; | 279 fPrevUnitNormal = unitNormal; |
| 278 fPrevNormal = normal; | 280 fPrevNormal = normal; |
| 279 fSegmentCount += 1; | 281 fSegmentCount += 1; |
| 280 } | 282 } |
| 281 | 283 |
| 282 void SkPathStroker::finishContour(bool close, bool currIsLine) { | 284 void SkPathStroker::finishContour(bool close, bool currIsLine) { |
| 283 if (fSegmentCount > 0) { | 285 if (fSegmentCount > 0) { |
| 284 SkPoint pt; | 286 SkPoint pt; |
| 285 | 287 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 fInvResScaleSquared = fInvResScale * fInvResScale; | 354 fInvResScaleSquared = fInvResScale * fInvResScale; |
| 353 fRecursionDepth = 0; | 355 fRecursionDepth = 0; |
| 354 } | 356 } |
| 355 | 357 |
| 356 void SkPathStroker::moveTo(const SkPoint& pt) { | 358 void SkPathStroker::moveTo(const SkPoint& pt) { |
| 357 if (fSegmentCount > 0) { | 359 if (fSegmentCount > 0) { |
| 358 this->finishContour(false, false); | 360 this->finishContour(false, false); |
| 359 } | 361 } |
| 360 fSegmentCount = 0; | 362 fSegmentCount = 0; |
| 361 fFirstPt = fPrevPt = pt; | 363 fFirstPt = fPrevPt = pt; |
| 364 fJoinCompleted = false; |
| 362 } | 365 } |
| 363 | 366 |
| 364 void SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) { | 367 void SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) { |
| 365 fOuter.lineTo(currPt.fX + normal.fX, currPt.fY + normal.fY); | 368 fOuter.lineTo(currPt.fX + normal.fX, currPt.fY + normal.fY); |
| 366 fInner.lineTo(currPt.fX - normal.fX, currPt.fY - normal.fY); | 369 fInner.lineTo(currPt.fX - normal.fX, currPt.fY - normal.fY); |
| 367 } | 370 } |
| 368 | 371 |
| 369 void SkPathStroker::lineTo(const SkPoint& currPt) { | 372 static bool has_valid_tangent(const SkPath::Iter* iter) { |
| 373 SkPath::Iter copy = *iter; |
| 374 SkPath::Verb verb; |
| 375 SkPoint pts[4]; |
| 376 while ((verb = copy.next(pts))) { |
| 377 switch (verb) { |
| 378 case SkPath::kMove_Verb: |
| 379 return false; |
| 380 case SkPath::kLine_Verb: |
| 381 if (pts[0] == pts[1]) { |
| 382 continue; |
| 383 } |
| 384 return true; |
| 385 case SkPath::kQuad_Verb: |
| 386 case SkPath::kConic_Verb: |
| 387 if (pts[0] == pts[1] && pts[0] == pts[2]) { |
| 388 continue; |
| 389 } |
| 390 return true; |
| 391 case SkPath::kCubic_Verb: |
| 392 if (pts[0] == pts[1] && pts[0] == pts[2] && pts[0] == pts[3]) { |
| 393 continue; |
| 394 } |
| 395 return true; |
| 396 case SkPath::kClose_Verb: |
| 397 case SkPath::kDone_Verb: |
| 398 return false; |
| 399 } |
| 400 } |
| 401 return false; |
| 402 } |
| 403 |
| 404 void SkPathStroker::lineTo(const SkPoint& currPt, const SkPath::Iter* iter) { |
| 370 if (SkStrokerPriv::CapFactory(SkPaint::kButt_Cap) == fCapper | 405 if (SkStrokerPriv::CapFactory(SkPaint::kButt_Cap) == fCapper |
| 371 && fPrevPt.equalsWithinTolerance(currPt, SK_ScalarNearlyZero * fInvR
esScale)) { | 406 && fPrevPt.equalsWithinTolerance(currPt, SK_ScalarNearlyZero * fInvR
esScale)) { |
| 372 return; | 407 return; |
| 373 } | 408 } |
| 409 if (fPrevPt == currPt && (fJoinCompleted || (iter && has_valid_tangent(iter)
))) { |
| 410 return; |
| 411 } |
| 374 SkVector normal, unitNormal; | 412 SkVector normal, unitNormal; |
| 375 | 413 |
| 376 if (!this->preJoinTo(currPt, &normal, &unitNormal, true)) { | 414 if (!this->preJoinTo(currPt, &normal, &unitNormal, true)) { |
| 377 return; | 415 return; |
| 378 } | 416 } |
| 379 this->line_to(currPt, normal); | 417 this->line_to(currPt, normal); |
| 380 this->postJoinTo(currPt, normal, unitNormal); | 418 this->postJoinTo(currPt, normal, unitNormal); |
| 381 } | 419 } |
| 382 | 420 |
| 383 void SkPathStroker::setQuadEndNormal(const SkPoint quad[3], const SkVector& norm
alAB, | 421 void SkPathStroker::setQuadEndNormal(const SkPoint quad[3], const SkVector& norm
alAB, |
| (...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1332 SkPath::Iter iter(src, false); | 1370 SkPath::Iter iter(src, false); |
| 1333 SkPath::Verb lastSegment = SkPath::kMove_Verb; | 1371 SkPath::Verb lastSegment = SkPath::kMove_Verb; |
| 1334 | 1372 |
| 1335 for (;;) { | 1373 for (;;) { |
| 1336 SkPoint pts[4]; | 1374 SkPoint pts[4]; |
| 1337 switch (iter.next(pts, false)) { | 1375 switch (iter.next(pts, false)) { |
| 1338 case SkPath::kMove_Verb: | 1376 case SkPath::kMove_Verb: |
| 1339 stroker.moveTo(pts[0]); | 1377 stroker.moveTo(pts[0]); |
| 1340 break; | 1378 break; |
| 1341 case SkPath::kLine_Verb: | 1379 case SkPath::kLine_Verb: |
| 1342 stroker.lineTo(pts[1]); | 1380 stroker.lineTo(pts[1], &iter); |
| 1343 lastSegment = SkPath::kLine_Verb; | 1381 lastSegment = SkPath::kLine_Verb; |
| 1344 break; | 1382 break; |
| 1345 case SkPath::kQuad_Verb: | 1383 case SkPath::kQuad_Verb: |
| 1346 stroker.quadTo(pts[1], pts[2]); | 1384 stroker.quadTo(pts[1], pts[2]); |
| 1347 lastSegment = SkPath::kQuad_Verb; | 1385 lastSegment = SkPath::kQuad_Verb; |
| 1348 break; | 1386 break; |
| 1349 case SkPath::kConic_Verb: { | 1387 case SkPath::kConic_Verb: { |
| 1350 stroker.conicTo(pts[1], pts[2], iter.conicWeight()); | 1388 stroker.conicTo(pts[1], pts[2], iter.conicWeight()); |
| 1351 lastSegment = SkPath::kConic_Verb; | 1389 lastSegment = SkPath::kConic_Verb; |
| 1352 break; | 1390 break; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1480 default: | 1518 default: |
| 1481 break; | 1519 break; |
| 1482 } | 1520 } |
| 1483 | 1521 |
| 1484 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { | 1522 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { |
| 1485 r = rect; | 1523 r = rect; |
| 1486 r.inset(radius, radius); | 1524 r.inset(radius, radius); |
| 1487 dst->addRect(r, reverse_direction(dir)); | 1525 dst->addRect(r, reverse_direction(dir)); |
| 1488 } | 1526 } |
| 1489 } | 1527 } |
| OLD | NEW |