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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 fTangentEnd = parent->fTangentEnd; | 112 fTangentEnd = parent->fTangentEnd; |
113 fEndSet = true; | 113 fEndSet = true; |
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, bool autoClose, bool reverse
Inner); |
123 | 123 |
124 bool hasOnlyMoveTo() const { return 0 == fSegmentCount; } | 124 bool hasOnlyMoveTo() const { return 0 == fSegmentCount; } |
125 SkPoint moveToPt() const { return fFirstPt; } | 125 SkPoint moveToPt() const { return fFirstPt; } |
126 | 126 |
127 void moveTo(const SkPoint&); | 127 void moveTo(const SkPoint&); |
128 void lineTo(const SkPoint&); | 128 void lineTo(const SkPoint&); |
129 void quadTo(const SkPoint&, const SkPoint&); | 129 void quadTo(const SkPoint&, const SkPoint&); |
130 void conicTo(const SkPoint&, const SkPoint&, SkScalar weight); | 130 void conicTo(const SkPoint&, const SkPoint&, SkScalar weight); |
131 void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&); | 131 void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&); |
132 void close(bool isLine) { this->finishContour(true, isLine); } | 132 void close(bool isLine) { this->finishContour(true, isLine); } |
133 | 133 |
134 void done(SkPath* dst, bool isLine) { | 134 void done(SkPath* dst, bool isLine) { |
135 this->finishContour(false, isLine); | 135 this->finishContour(fAutoClose, isLine); |
136 fOuter.addPath(fExtra); | 136 fOuter.addPath(fExtra); |
137 dst->swap(fOuter); | 137 dst->swap(fOuter); |
138 } | 138 } |
139 | 139 |
140 SkScalar getResScale() const { return fResScale; } | 140 SkScalar getResScale() const { return fResScale; } |
141 | 141 |
142 private: | 142 private: |
143 SkScalar fRadius; | 143 SkScalar fRadius; |
144 SkScalar fInvMiterLimit; | 144 SkScalar fInvMiterLimit; |
145 SkScalar fResScale; | 145 SkScalar fResScale; |
146 SkScalar fInvResScale; | 146 SkScalar fInvResScale; |
147 SkScalar fInvResScaleSquared; | 147 SkScalar fInvResScaleSquared; |
148 | 148 |
149 SkVector fFirstNormal, fPrevNormal, fFirstUnitNormal, fPrevUnitNormal; | 149 SkVector fFirstNormal, fPrevNormal, fFirstUnitNormal, fPrevUnitNormal; |
150 SkPoint fFirstPt, fPrevPt; // on original path | 150 SkPoint fFirstPt, fPrevPt; // on original path |
151 SkPoint fFirstOuterPt; | 151 SkPoint fFirstOuterPt; |
152 int fSegmentCount; | 152 int fSegmentCount; |
153 bool fPrevIsLine; | 153 bool fPrevIsLine; |
| 154 bool fAutoClose; |
| 155 bool fReverseInner; |
154 | 156 |
155 SkStrokerPriv::CapProc fCapper; | 157 SkStrokerPriv::CapProc fCapper; |
156 SkStrokerPriv::JoinProc fJoiner; | 158 SkStrokerPriv::JoinProc fJoiner; |
157 | 159 |
158 SkPath fInner, fOuter; // outer is our working answer, inner is temp | 160 SkPath fInner, fOuter; // outer is our working answer, inner is temp |
159 SkPath fExtra; // added as extra complete contours | 161 SkPath fExtra; // added as extra complete contours |
160 | 162 |
161 enum StrokeType { | 163 enum StrokeType { |
162 kOuter_StrokeType = 1, // use sign-opposite values later to flip pe
rpendicular axis | 164 kOuter_StrokeType = 1, // use sign-opposite values later to flip pe
rpendicular axis |
163 kInner_StrokeType = -1 | 165 kInner_StrokeType = -1 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 282 |
281 void SkPathStroker::finishContour(bool close, bool currIsLine) { | 283 void SkPathStroker::finishContour(bool close, bool currIsLine) { |
282 if (fSegmentCount > 0) { | 284 if (fSegmentCount > 0) { |
283 SkPoint pt; | 285 SkPoint pt; |
284 | 286 |
285 if (close) { | 287 if (close) { |
286 fJoiner(&fOuter, &fInner, fPrevUnitNormal, fPrevPt, | 288 fJoiner(&fOuter, &fInner, fPrevUnitNormal, fPrevPt, |
287 fFirstUnitNormal, fRadius, fInvMiterLimit, | 289 fFirstUnitNormal, fRadius, fInvMiterLimit, |
288 fPrevIsLine, currIsLine); | 290 fPrevIsLine, currIsLine); |
289 fOuter.close(); | 291 fOuter.close(); |
290 // now add fInner as its own contour | 292 if (fReverseInner) { |
291 fInner.getLastPt(&pt); | 293 // now add fInner as its own contour |
292 fOuter.moveTo(pt.fX, pt.fY); | 294 fInner.getLastPt(&pt); |
293 fOuter.reversePathTo(fInner); | 295 fOuter.moveTo(pt.fX, pt.fY); |
| 296 fOuter.reversePathTo(fInner); |
| 297 } else { |
| 298 fOuter.addPath(fInner); |
| 299 } |
294 fOuter.close(); | 300 fOuter.close(); |
295 } else { // add caps to start and end | 301 } else { // add caps to start and end |
296 // cap the end | 302 if (fReverseInner) { |
297 fInner.getLastPt(&pt); | 303 // cap the end |
298 fCapper(&fOuter, fPrevPt, fPrevNormal, pt, | 304 fInner.getLastPt(&pt); |
299 currIsLine ? &fInner : nullptr); | 305 fCapper(&fOuter, fPrevPt, fPrevNormal, pt, |
300 fOuter.reversePathTo(fInner); | 306 currIsLine ? &fInner : nullptr); |
301 // cap the start | 307 fOuter.reversePathTo(fInner); |
302 fCapper(&fOuter, fFirstPt, -fFirstNormal, fFirstOuterPt, | 308 // cap the start |
303 fPrevIsLine ? &fInner : nullptr); | 309 fCapper(&fOuter, fFirstPt, -fFirstNormal, fFirstOuterPt, |
304 fOuter.close(); | 310 fPrevIsLine ? &fInner : nullptr); |
| 311 fOuter.close(); |
| 312 } else { |
| 313 fOuter.addPath(fInner); |
| 314 } |
305 } | 315 } |
306 } | 316 } |
307 // since we may re-use fInner, we rewind instead of reset, to save on | 317 // since we may re-use fInner, we rewind instead of reset, to save on |
308 // reallocating its internal storage. | 318 // reallocating its internal storage. |
309 fInner.rewind(); | 319 fInner.rewind(); |
310 fSegmentCount = -1; | 320 fSegmentCount = -1; |
311 } | 321 } |
312 | 322 |
313 /////////////////////////////////////////////////////////////////////////////// | 323 /////////////////////////////////////////////////////////////////////////////// |
314 | 324 |
315 SkPathStroker::SkPathStroker(const SkPath& src, | 325 SkPathStroker::SkPathStroker(const SkPath& src, |
316 SkScalar radius, SkScalar miterLimit, | 326 SkScalar radius, SkScalar miterLimit, |
317 SkPaint::Cap cap, SkPaint::Join join, SkScalar resS
cale) | 327 SkPaint::Cap cap, SkPaint::Join join, SkScalar resS
cale, |
| 328 bool autoClose, bool reverseInner) |
318 : fRadius(radius) | 329 : fRadius(radius) |
319 , fResScale(resScale) { | 330 , fResScale(resScale) |
| 331 , fAutoClose(autoClose) |
| 332 , fReverseInner(reverseInner) { |
320 | 333 |
321 /* This is only used when join is miter_join, but we initialize it here | 334 /* This is only used when join is miter_join, but we initialize it here |
322 so that it is always defined, to fis valgrind warnings. | 335 so that it is always defined, to fis valgrind warnings. |
323 */ | 336 */ |
324 fInvMiterLimit = 0; | 337 fInvMiterLimit = 0; |
325 | 338 |
326 if (join == SkPaint::kMiter_Join) { | 339 if (join == SkPaint::kMiter_Join) { |
327 if (miterLimit <= SK_Scalar1) { | 340 if (miterLimit <= SK_Scalar1) { |
328 join = SkPaint::kBevel_Join; | 341 join = SkPaint::kBevel_Join; |
329 } else { | 342 } else { |
(...skipping 17 matching lines...) Expand all Loading... |
347 fInner.setIsVolatile(true); | 360 fInner.setIsVolatile(true); |
348 // TODO : write a common error function used by stroking and filling | 361 // TODO : write a common error function used by stroking and filling |
349 // The '4' below matches the fill scan converter's error term | 362 // The '4' below matches the fill scan converter's error term |
350 fInvResScale = SkScalarInvert(resScale * 4); | 363 fInvResScale = SkScalarInvert(resScale * 4); |
351 fInvResScaleSquared = fInvResScale * fInvResScale; | 364 fInvResScaleSquared = fInvResScale * fInvResScale; |
352 fRecursionDepth = 0; | 365 fRecursionDepth = 0; |
353 } | 366 } |
354 | 367 |
355 void SkPathStroker::moveTo(const SkPoint& pt) { | 368 void SkPathStroker::moveTo(const SkPoint& pt) { |
356 if (fSegmentCount > 0) { | 369 if (fSegmentCount > 0) { |
357 this->finishContour(false, false); | 370 this->finishContour(fAutoClose, false); |
358 } | 371 } |
359 fSegmentCount = 0; | 372 fSegmentCount = 0; |
360 fFirstPt = fPrevPt = pt; | 373 fFirstPt = fPrevPt = pt; |
361 } | 374 } |
362 | 375 |
363 void SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) { | 376 void SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) { |
364 fOuter.lineTo(currPt.fX + normal.fX, currPt.fY + normal.fY); | 377 fOuter.lineTo(currPt.fX + normal.fX, currPt.fY + normal.fY); |
365 fInner.lineTo(currPt.fX - normal.fX, currPt.fY - normal.fY); | 378 fInner.lineTo(currPt.fX - normal.fX, currPt.fY - normal.fY); |
366 } | 379 } |
367 | 380 |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 /////////////////////////////////////////////////////////////////////////////// | 1230 /////////////////////////////////////////////////////////////////////////////// |
1218 | 1231 |
1219 #include "SkPaintDefaults.h" | 1232 #include "SkPaintDefaults.h" |
1220 | 1233 |
1221 SkStroke::SkStroke() { | 1234 SkStroke::SkStroke() { |
1222 fWidth = SK_Scalar1; | 1235 fWidth = SK_Scalar1; |
1223 fMiterLimit = SkPaintDefaults_MiterLimit; | 1236 fMiterLimit = SkPaintDefaults_MiterLimit; |
1224 fCap = SkPaint::kDefault_Cap; | 1237 fCap = SkPaint::kDefault_Cap; |
1225 fJoin = SkPaint::kDefault_Join; | 1238 fJoin = SkPaint::kDefault_Join; |
1226 fDoFill = false; | 1239 fDoFill = false; |
| 1240 fAutoClose = false; |
| 1241 fReverseInner = true; |
1227 } | 1242 } |
1228 | 1243 |
1229 SkStroke::SkStroke(const SkPaint& p) { | 1244 SkStroke::SkStroke(const SkPaint& p) { |
1230 fWidth = p.getStrokeWidth(); | 1245 fWidth = p.getStrokeWidth(); |
1231 fMiterLimit = p.getStrokeMiter(); | 1246 fMiterLimit = p.getStrokeMiter(); |
1232 fCap = (uint8_t)p.getStrokeCap(); | 1247 fCap = (uint8_t)p.getStrokeCap(); |
1233 fJoin = (uint8_t)p.getStrokeJoin(); | 1248 fJoin = (uint8_t)p.getStrokeJoin(); |
1234 fDoFill = SkToU8(p.getStyle() == SkPaint::kStrokeAndFill_Style); | 1249 fDoFill = SkToU8(p.getStyle() == SkPaint::kStrokeAndFill_Style); |
| 1250 fAutoClose = false; |
| 1251 fReverseInner = true; |
1235 } | 1252 } |
1236 | 1253 |
1237 SkStroke::SkStroke(const SkPaint& p, SkScalar width) { | 1254 SkStroke::SkStroke(const SkPaint& p, SkScalar width) { |
1238 fWidth = width; | 1255 fWidth = width; |
1239 fMiterLimit = p.getStrokeMiter(); | 1256 fMiterLimit = p.getStrokeMiter(); |
1240 fCap = (uint8_t)p.getStrokeCap(); | 1257 fCap = (uint8_t)p.getStrokeCap(); |
1241 fJoin = (uint8_t)p.getStrokeJoin(); | 1258 fJoin = (uint8_t)p.getStrokeJoin(); |
1242 fDoFill = SkToU8(p.getStyle() == SkPaint::kStrokeAndFill_Style); | 1259 fDoFill = SkToU8(p.getStyle() == SkPaint::kStrokeAndFill_Style); |
| 1260 fAutoClose = false; |
| 1261 fReverseInner = true; |
1243 } | 1262 } |
1244 | 1263 |
1245 void SkStroke::setWidth(SkScalar width) { | 1264 void SkStroke::setWidth(SkScalar width) { |
1246 SkASSERT(width >= 0); | 1265 SkASSERT(width >= 0); |
1247 fWidth = width; | 1266 fWidth = width; |
1248 } | 1267 } |
1249 | 1268 |
1250 void SkStroke::setMiterLimit(SkScalar miterLimit) { | 1269 void SkStroke::setMiterLimit(SkScalar miterLimit) { |
1251 SkASSERT(miterLimit >= 0); | 1270 SkASSERT(miterLimit >= 0); |
1252 fMiterLimit = miterLimit; | 1271 fMiterLimit = miterLimit; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 this->strokeRect(rect, dst, dir); | 1329 this->strokeRect(rect, dst, dir); |
1311 // our answer should preserve the inverseness of the src | 1330 // our answer should preserve the inverseness of the src |
1312 if (src.isInverseFillType()) { | 1331 if (src.isInverseFillType()) { |
1313 SkASSERT(!dst->isInverseFillType()); | 1332 SkASSERT(!dst->isInverseFillType()); |
1314 dst->toggleInverseFillType(); | 1333 dst->toggleInverseFillType(); |
1315 } | 1334 } |
1316 return; | 1335 return; |
1317 } | 1336 } |
1318 } | 1337 } |
1319 | 1338 |
1320 SkPathStroker stroker(src, radius, fMiterLimit, this->getCap(), this->getJ
oin(), fResScale); | 1339 SkPathStroker stroker(src, radius, fMiterLimit, this->getCap(), this->getJ
oin(), fResScale, this->getAutoClose(), this->getReverseInner()); |
1321 SkPath::Iter iter(src, false); | 1340 SkPath::Iter iter(src, false); |
1322 SkPath::Verb lastSegment = SkPath::kMove_Verb; | 1341 SkPath::Verb lastSegment = SkPath::kMove_Verb; |
1323 | 1342 |
1324 for (;;) { | 1343 for (;;) { |
1325 SkPoint pts[4]; | 1344 SkPoint pts[4]; |
1326 switch (iter.next(pts, false)) { | 1345 switch (iter.next(pts, false)) { |
1327 case SkPath::kMove_Verb: | 1346 case SkPath::kMove_Verb: |
1328 stroker.moveTo(pts[0]); | 1347 stroker.moveTo(pts[0]); |
1329 break; | 1348 break; |
1330 case SkPath::kLine_Verb: | 1349 case SkPath::kLine_Verb: |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1466 case SkPaint::kRound_Join: | 1485 case SkPaint::kRound_Join: |
1467 dst->addRoundRect(r, radius, radius, dir); | 1486 dst->addRoundRect(r, radius, radius, dir); |
1468 break; | 1487 break; |
1469 default: | 1488 default: |
1470 break; | 1489 break; |
1471 } | 1490 } |
1472 | 1491 |
1473 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { | 1492 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { |
1474 r = rect; | 1493 r = rect; |
1475 r.inset(radius, radius); | 1494 r.inset(radius, radius); |
1476 dst->addRect(r, reverse_direction(dir)); | 1495 dst->addRect(r, this->getReverseInner() ? reverse_direction(dir) : dir); |
1477 } | 1496 } |
1478 } | 1497 } |
OLD | NEW |