| 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 return true; | 114 return true; |
| 115 } | 115 } |
| 116 }; | 116 }; |
| 117 | 117 |
| 118 class SkPathStroker { | 118 class SkPathStroker { |
| 119 public: | 119 public: |
| 120 SkPathStroker(const SkPath& src, | 120 SkPathStroker(const SkPath& src, |
| 121 SkScalar radius, SkScalar miterLimit, SkPaint::Cap, | 121 SkScalar radius, SkScalar miterLimit, SkPaint::Cap, |
| 122 SkPaint::Join, SkScalar resScale); | 122 SkPaint::Join, SkScalar resScale); |
| 123 | 123 |
| 124 bool hasOnlyMoveTo() const { return 0 == fSegmentCount; } | |
| 125 SkPoint moveToPt() const { return fFirstPt; } | |
| 126 | |
| 127 void moveTo(const SkPoint&); | 124 void moveTo(const SkPoint&); |
| 128 void lineTo(const SkPoint&); | 125 void lineTo(const SkPoint&); |
| 129 void quadTo(const SkPoint&, const SkPoint&); | 126 void quadTo(const SkPoint&, const SkPoint&); |
| 130 void conicTo(const SkPoint&, const SkPoint&, SkScalar weight); | 127 void conicTo(const SkPoint&, const SkPoint&, SkScalar weight); |
| 131 void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&); | 128 void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&); |
| 132 void close(bool isLine) { this->finishContour(true, isLine); } | 129 void close(bool isLine) { this->finishContour(true, isLine); } |
| 133 | 130 |
| 134 void done(SkPath* dst, bool isLine) { | 131 void done(SkPath* dst, bool isLine) { |
| 135 this->finishContour(false, isLine); | 132 this->finishContour(false, isLine); |
| 136 fOuter.addPath(fExtra); | 133 fOuter.addPath(fExtra); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 /////////////////////////////////////////////////////////////////////////////// | 235 /////////////////////////////////////////////////////////////////////////////// |
| 239 | 236 |
| 240 bool SkPathStroker::preJoinTo(const SkPoint& currPt, SkVector* normal, | 237 bool SkPathStroker::preJoinTo(const SkPoint& currPt, SkVector* normal, |
| 241 SkVector* unitNormal, bool currIsLine) { | 238 SkVector* unitNormal, bool currIsLine) { |
| 242 SkASSERT(fSegmentCount >= 0); | 239 SkASSERT(fSegmentCount >= 0); |
| 243 | 240 |
| 244 SkScalar prevX = fPrevPt.fX; | 241 SkScalar prevX = fPrevPt.fX; |
| 245 SkScalar prevY = fPrevPt.fY; | 242 SkScalar prevY = fPrevPt.fY; |
| 246 | 243 |
| 247 if (!set_normal_unitnormal(fPrevPt, currPt, fRadius, normal, unitNormal)) { | 244 if (!set_normal_unitnormal(fPrevPt, currPt, fRadius, normal, unitNormal)) { |
| 248 if (SkStrokerPriv::CapFactory(SkPaint::kButt_Cap) == fCapper) { | 245 return false; |
| 249 return false; | |
| 250 } | |
| 251 /* Square caps and round caps draw even if the segment length is zero. | |
| 252 Since the zero length segment has no direction, set the orientation | |
| 253 to upright as the default orientation */ | |
| 254 normal->set(fRadius, 0); | |
| 255 unitNormal->set(1, 0); | |
| 256 } | 246 } |
| 257 | 247 |
| 258 if (fSegmentCount == 0) { | 248 if (fSegmentCount == 0) { |
| 259 fFirstNormal = *normal; | 249 fFirstNormal = *normal; |
| 260 fFirstUnitNormal = *unitNormal; | 250 fFirstUnitNormal = *unitNormal; |
| 261 fFirstOuterPt.set(prevX + normal->fX, prevY + normal->fY); | 251 fFirstOuterPt.set(prevX + normal->fX, prevY + normal->fY); |
| 262 | 252 |
| 263 fOuter.moveTo(fFirstOuterPt.fX, fFirstOuterPt.fY); | 253 fOuter.moveTo(fFirstOuterPt.fX, fFirstOuterPt.fY); |
| 264 fInner.moveTo(prevX - normal->fX, prevY - normal->fY); | 254 fInner.moveTo(prevX - normal->fX, prevY - normal->fY); |
| 265 } else { // we have a previous segment | 255 } else { // we have a previous segment |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 fSegmentCount = 0; | 349 fSegmentCount = 0; |
| 360 fFirstPt = fPrevPt = pt; | 350 fFirstPt = fPrevPt = pt; |
| 361 } | 351 } |
| 362 | 352 |
| 363 void SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) { | 353 void SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) { |
| 364 fOuter.lineTo(currPt.fX + normal.fX, currPt.fY + normal.fY); | 354 fOuter.lineTo(currPt.fX + normal.fX, currPt.fY + normal.fY); |
| 365 fInner.lineTo(currPt.fX - normal.fX, currPt.fY - normal.fY); | 355 fInner.lineTo(currPt.fX - normal.fX, currPt.fY - normal.fY); |
| 366 } | 356 } |
| 367 | 357 |
| 368 void SkPathStroker::lineTo(const SkPoint& currPt) { | 358 void SkPathStroker::lineTo(const SkPoint& currPt) { |
| 369 if (SkStrokerPriv::CapFactory(SkPaint::kButt_Cap) == fCapper | 359 if (SkPath::IsLineDegenerate(fPrevPt, currPt, false)) { |
| 370 && SkPath::IsLineDegenerate(fPrevPt, currPt, false)) { | |
| 371 return; | 360 return; |
| 372 } | 361 } |
| 373 SkVector normal, unitNormal; | 362 SkVector normal, unitNormal; |
| 374 | 363 |
| 375 if (!this->preJoinTo(currPt, &normal, &unitNormal, true)) { | 364 if (!this->preJoinTo(currPt, &normal, &unitNormal, true)) { |
| 376 return; | 365 return; |
| 377 } | 366 } |
| 378 this->line_to(currPt, normal); | 367 this->line_to(currPt, normal); |
| 379 this->postJoinTo(currPt, normal, unitNormal); | 368 this->postJoinTo(currPt, normal, unitNormal); |
| 380 } | 369 } |
| (...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 case SkPath::kConic_Verb: { | 1327 case SkPath::kConic_Verb: { |
| 1339 stroker.conicTo(pts[1], pts[2], iter.conicWeight()); | 1328 stroker.conicTo(pts[1], pts[2], iter.conicWeight()); |
| 1340 lastSegment = SkPath::kConic_Verb; | 1329 lastSegment = SkPath::kConic_Verb; |
| 1341 break; | 1330 break; |
| 1342 } break; | 1331 } break; |
| 1343 case SkPath::kCubic_Verb: | 1332 case SkPath::kCubic_Verb: |
| 1344 stroker.cubicTo(pts[1], pts[2], pts[3]); | 1333 stroker.cubicTo(pts[1], pts[2], pts[3]); |
| 1345 lastSegment = SkPath::kCubic_Verb; | 1334 lastSegment = SkPath::kCubic_Verb; |
| 1346 break; | 1335 break; |
| 1347 case SkPath::kClose_Verb: | 1336 case SkPath::kClose_Verb: |
| 1348 if (stroker.hasOnlyMoveTo() && SkPaint::kButt_Cap != this->getCa
p()) { | |
| 1349 /* If the stroke consists of a moveTo followed by a close, t
reat it | |
| 1350 as if it were followed by a zero-length line. Lines witho
ut length | |
| 1351 can have square and round end caps. */ | |
| 1352 stroker.lineTo(stroker.moveToPt()); | |
| 1353 lastSegment = SkPath::kLine_Verb; | |
| 1354 break; | |
| 1355 } | |
| 1356 stroker.close(lastSegment == SkPath::kLine_Verb); | 1337 stroker.close(lastSegment == SkPath::kLine_Verb); |
| 1357 break; | 1338 break; |
| 1358 case SkPath::kDone_Verb: | 1339 case SkPath::kDone_Verb: |
| 1359 goto DONE; | 1340 goto DONE; |
| 1360 } | 1341 } |
| 1361 } | 1342 } |
| 1362 DONE: | 1343 DONE: |
| 1363 stroker.done(dst, lastSegment == SkPath::kLine_Verb); | 1344 stroker.done(dst, lastSegment == SkPath::kLine_Verb); |
| 1364 | 1345 |
| 1365 if (fDoFill) { | 1346 if (fDoFill) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1469 default: | 1450 default: |
| 1470 break; | 1451 break; |
| 1471 } | 1452 } |
| 1472 | 1453 |
| 1473 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { | 1454 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { |
| 1474 r = rect; | 1455 r = rect; |
| 1475 r.inset(radius, radius); | 1456 r.inset(radius, radius); |
| 1476 dst->addRect(r, reverse_direction(dir)); | 1457 dst->addRect(r, reverse_direction(dir)); |
| 1477 } | 1458 } |
| 1478 } | 1459 } |
| OLD | NEW |