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

Unified Diff: src/core/SkPathRef.cpp

Issue 1461763004: add SkPath::isRRect (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: incorporated Rob's comments Created 5 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkPath.cpp ('k') | tests/RRectInPathTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkPathRef.cpp
diff --git a/src/core/SkPathRef.cpp b/src/core/SkPathRef.cpp
index 119711381f6f1028ed47136138770a023ee7c6c0..12429aecfcc889b3244ab03c40dbfea423464780 100644
--- a/src/core/SkPathRef.cpp
+++ b/src/core/SkPathRef.cpp
@@ -113,15 +113,15 @@ void SkPathRef::CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst,
(*dst)->fSegmentMask = src.fSegmentMask;
// It's an oval only if it stays a rect.
- (*dst)->fIsOval = src.fIsOval && matrix.rectStaysRect();
+ bool rectStaysRect = matrix.rectStaysRect();
+ (*dst)->fIsOval = src.fIsOval && rectStaysRect;
+ (*dst)->fIsRRect = src.fIsRRect && rectStaysRect;
SkDEBUGCODE((*dst)->validate();)
}
SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
SkPathRef* ref = new SkPathRef;
- bool isOval;
- uint8_t segmentMask;
int32_t packed;
if (!buffer->readS32(&packed)) {
@@ -130,8 +130,9 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
}
ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
- segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
- isOval = (packed >> kIsOval_SerializationShift) & 1;
+ uint8_t segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
+ bool isOval = (packed >> kIsOval_SerializationShift) & 1;
+ bool isRRect = (packed >> kIsRRect_SerializationShift) & 1;
int32_t verbCount, pointCount, conicCount;
if (!buffer->readU32(&(ref->fGenerationID)) ||
@@ -159,6 +160,7 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
// resetToSize clears fSegmentMask and fIsOval
ref->fSegmentMask = segmentMask;
ref->fIsOval = isOval;
+ ref->fIsRRect = isRRect;
return ref;
}
@@ -174,6 +176,7 @@ void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
(*pathRef)->fConicWeights.rewind();
(*pathRef)->fSegmentMask = 0;
(*pathRef)->fIsOval = false;
+ (*pathRef)->fIsRRect = false;
SkDEBUGCODE((*pathRef)->validate();)
} else {
int oldVCnt = (*pathRef)->countVerbs();
@@ -240,6 +243,7 @@ void SkPathRef::writeToBuffer(SkWBuffer* buffer) const {
int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
((fIsOval & 1) << kIsOval_SerializationShift) |
+ ((fIsRRect & 1) << kIsRRect_SerializationShift) |
(fSegmentMask << kSegmentMask_SerializationShift);
buffer->write32(packed);
@@ -281,6 +285,7 @@ void SkPathRef::copy(const SkPathRef& ref,
}
fSegmentMask = ref.fSegmentMask;
fIsOval = ref.fIsOval;
+ fIsRRect = ref.fIsRRect;
SkDEBUGCODE(this->validate();)
}
@@ -352,6 +357,7 @@ SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
fBoundsIsDirty = true; // this also invalidates fIsFinite
if (dirtyAfterEdit) {
fIsOval = false;
+ fIsRRect = false;
}
if (SkPath::kConic_Verb == verb) {
@@ -410,6 +416,7 @@ SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) {
fBoundsIsDirty = true; // this also invalidates fIsFinite
if (dirtyAfterEdit) {
fIsOval = false;
+ fIsRRect = false;
}
if (SkPath::kConic_Verb == verb) {
@@ -456,6 +463,116 @@ void SkPathRef::callGenIDChangeListeners() {
fGenIDChangeListeners.deleteAll();
}
+SkRRect SkPathRef::getRRect() const {
+ const SkRect& bounds = this->getBounds();
+ SkVector radii[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
+ Iter iter(*this);
+ SkPoint pts[4];
+ uint8_t verb = iter.next(pts);
+ SkASSERT(SkPath::kMove_Verb == verb);
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ if (SkPath::kConic_Verb == verb) {
+ SkVector v1_0 = pts[1] - pts[0];
+ SkVector v2_1 = pts[2] - pts[1];
+ SkVector dxdy;
+ if (v1_0.fX) {
+ SkASSERT(!v2_1.fX && !v1_0.fY);
+ dxdy.set(SkScalarAbs(v1_0.fX), SkScalarAbs(v2_1.fY));
+ } else if (!v1_0.fY) {
+ SkASSERT(!v2_1.fX || !v2_1.fY);
+ dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v2_1.fY));
+ } else {
+ SkASSERT(!v2_1.fY);
+ dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v1_0.fY));
+ }
+ SkRRect::Corner corner =
+ pts[1].fX == bounds.fLeft ?
+ pts[1].fY == bounds.fTop ?
+ SkRRect::kUpperLeft_Corner : SkRRect::kLowerLeft_Corner :
+ pts[1].fY == bounds.fTop ?
+ SkRRect::kUpperRight_Corner : SkRRect::kLowerRight_Corner;
+ SkASSERT(!radii[corner].fX && !radii[corner].fY);
+ radii[corner] = dxdy;
+ } else {
+ SkASSERT((verb == SkPath::kLine_Verb
+ && (!(pts[1].fX - pts[0].fX) || !(pts[1].fY - pts[0].fY)))
+ || verb == SkPath::kClose_Verb);
+ }
+ }
+ SkRRect rrect;
+ rrect.setRectRadii(bounds, radii);
+ return rrect;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkPathRef::Iter::Iter() {
+#ifdef SK_DEBUG
+ fPts = nullptr;
+ fConicWeights = nullptr;
+#endif
+ // need to init enough to make next() harmlessly return kDone_Verb
+ fVerbs = nullptr;
+ fVerbStop = nullptr;
+}
+
+SkPathRef::Iter::Iter(const SkPathRef& path) {
+ this->setPathRef(path);
+}
+
+void SkPathRef::Iter::setPathRef(const SkPathRef& path) {
+ fPts = path.points();
+ fVerbs = path.verbs();
+ fVerbStop = path.verbsMemBegin();
+ fConicWeights = path.conicWeights() - 1; // begin one behind
+}
+
+uint8_t SkPathRef::Iter::next(SkPoint pts[4]) {
+ SkASSERT(pts);
+ if (fVerbs == fVerbStop) {
+ return (uint8_t) SkPath::kDone_Verb;
+ }
+
+ // fVerbs points one beyond next verb so decrement first.
+ unsigned verb = *(--fVerbs);
+ const SkPoint* srcPts = fPts;
+
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ pts[0] = srcPts[0];
+ srcPts += 1;
+ break;
+ case SkPath::kLine_Verb:
+ pts[0] = srcPts[-1];
+ pts[1] = srcPts[0];
+ srcPts += 1;
+ break;
+ case SkPath::kConic_Verb:
+ fConicWeights += 1;
+ // fall-through
+ case SkPath::kQuad_Verb:
+ pts[0] = srcPts[-1];
+ pts[1] = srcPts[0];
+ pts[2] = srcPts[1];
+ srcPts += 2;
+ break;
+ case SkPath::kCubic_Verb:
+ pts[0] = srcPts[-1];
+ pts[1] = srcPts[0];
+ pts[2] = srcPts[1];
+ pts[3] = srcPts[2];
+ srcPts += 3;
+ break;
+ case SkPath::kClose_Verb:
+ break;
+ case SkPath::kDone_Verb:
+ SkASSERT(fVerbs == fVerbStop);
+ break;
+ }
+ fPts = srcPts;
+ return (uint8_t) verb;
+}
+
#ifdef SK_DEBUG
void SkPathRef::validate() const {
this->INHERITED::validate();
« no previous file with comments | « src/core/SkPath.cpp ('k') | tests/RRectInPathTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698