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 |