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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « src/core/SkPath.cpp ('k') | tests/RRectInPathTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
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 "SkBuffer.h" 8 #include "SkBuffer.h"
9 #include "SkOncePtr.h" 9 #include "SkOncePtr.h"
10 #include "SkPath.h" 10 #include "SkPath.h"
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 (*dst)->fIsFinite = false; 106 (*dst)->fIsFinite = false;
107 (*dst)->fBounds.setEmpty(); 107 (*dst)->fBounds.setEmpty();
108 } 108 }
109 } else { 109 } else {
110 (*dst)->fBoundsIsDirty = true; 110 (*dst)->fBoundsIsDirty = true;
111 } 111 }
112 112
113 (*dst)->fSegmentMask = src.fSegmentMask; 113 (*dst)->fSegmentMask = src.fSegmentMask;
114 114
115 // It's an oval only if it stays a rect. 115 // It's an oval only if it stays a rect.
116 (*dst)->fIsOval = src.fIsOval && matrix.rectStaysRect(); 116 bool rectStaysRect = matrix.rectStaysRect();
117 (*dst)->fIsOval = src.fIsOval && rectStaysRect;
118 (*dst)->fIsRRect = src.fIsRRect && rectStaysRect;
117 119
118 SkDEBUGCODE((*dst)->validate();) 120 SkDEBUGCODE((*dst)->validate();)
119 } 121 }
120 122
121 SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) { 123 SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
122 SkPathRef* ref = new SkPathRef; 124 SkPathRef* ref = new SkPathRef;
123 bool isOval;
124 uint8_t segmentMask;
125 125
126 int32_t packed; 126 int32_t packed;
127 if (!buffer->readS32(&packed)) { 127 if (!buffer->readS32(&packed)) {
128 delete ref; 128 delete ref;
129 return nullptr; 129 return nullptr;
130 } 130 }
131 131
132 ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; 132 ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
133 segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; 133 uint8_t segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
134 isOval = (packed >> kIsOval_SerializationShift) & 1; 134 bool isOval = (packed >> kIsOval_SerializationShift) & 1;
135 bool isRRect = (packed >> kIsRRect_SerializationShift) & 1;
135 136
136 int32_t verbCount, pointCount, conicCount; 137 int32_t verbCount, pointCount, conicCount;
137 if (!buffer->readU32(&(ref->fGenerationID)) || 138 if (!buffer->readU32(&(ref->fGenerationID)) ||
138 !buffer->readS32(&verbCount) || 139 !buffer->readS32(&verbCount) ||
139 !buffer->readS32(&pointCount) || 140 !buffer->readS32(&pointCount) ||
140 !buffer->readS32(&conicCount)) { 141 !buffer->readS32(&conicCount)) {
141 delete ref; 142 delete ref;
142 return nullptr; 143 return nullptr;
143 } 144 }
144 145
145 ref->resetToSize(verbCount, pointCount, conicCount); 146 ref->resetToSize(verbCount, pointCount, conicCount);
146 SkASSERT(verbCount == ref->countVerbs()); 147 SkASSERT(verbCount == ref->countVerbs());
147 SkASSERT(pointCount == ref->countPoints()); 148 SkASSERT(pointCount == ref->countPoints());
148 SkASSERT(conicCount == ref->fConicWeights.count()); 149 SkASSERT(conicCount == ref->fConicWeights.count());
149 150
150 if (!buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t)) || 151 if (!buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t)) ||
151 !buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)) || 152 !buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)) ||
152 !buffer->read(ref->fConicWeights.begin(), conicCount * sizeof(SkScalar)) || 153 !buffer->read(ref->fConicWeights.begin(), conicCount * sizeof(SkScalar)) ||
153 !buffer->read(&ref->fBounds, sizeof(SkRect))) { 154 !buffer->read(&ref->fBounds, sizeof(SkRect))) {
154 delete ref; 155 delete ref;
155 return nullptr; 156 return nullptr;
156 } 157 }
157 ref->fBoundsIsDirty = false; 158 ref->fBoundsIsDirty = false;
158 159
159 // resetToSize clears fSegmentMask and fIsOval 160 // resetToSize clears fSegmentMask and fIsOval
160 ref->fSegmentMask = segmentMask; 161 ref->fSegmentMask = segmentMask;
161 ref->fIsOval = isOval; 162 ref->fIsOval = isOval;
163 ref->fIsRRect = isRRect;
162 return ref; 164 return ref;
163 } 165 }
164 166
165 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { 167 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
166 if ((*pathRef)->unique()) { 168 if ((*pathRef)->unique()) {
167 SkDEBUGCODE((*pathRef)->validate();) 169 SkDEBUGCODE((*pathRef)->validate();)
168 (*pathRef)->callGenIDChangeListeners(); 170 (*pathRef)->callGenIDChangeListeners();
169 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite 171 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite
170 (*pathRef)->fVerbCnt = 0; 172 (*pathRef)->fVerbCnt = 0;
171 (*pathRef)->fPointCnt = 0; 173 (*pathRef)->fPointCnt = 0;
172 (*pathRef)->fFreeSpace = (*pathRef)->currSize(); 174 (*pathRef)->fFreeSpace = (*pathRef)->currSize();
173 (*pathRef)->fGenerationID = 0; 175 (*pathRef)->fGenerationID = 0;
174 (*pathRef)->fConicWeights.rewind(); 176 (*pathRef)->fConicWeights.rewind();
175 (*pathRef)->fSegmentMask = 0; 177 (*pathRef)->fSegmentMask = 0;
176 (*pathRef)->fIsOval = false; 178 (*pathRef)->fIsOval = false;
179 (*pathRef)->fIsRRect = false;
177 SkDEBUGCODE((*pathRef)->validate();) 180 SkDEBUGCODE((*pathRef)->validate();)
178 } else { 181 } else {
179 int oldVCnt = (*pathRef)->countVerbs(); 182 int oldVCnt = (*pathRef)->countVerbs();
180 int oldPCnt = (*pathRef)->countPoints(); 183 int oldPCnt = (*pathRef)->countPoints();
181 pathRef->reset(new SkPathRef); 184 pathRef->reset(new SkPathRef);
182 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt); 185 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt);
183 } 186 }
184 } 187 }
185 188
186 bool SkPathRef::operator== (const SkPathRef& ref) const { 189 bool SkPathRef::operator== (const SkPathRef& ref) const {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { 236 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const {
234 SkDEBUGCODE(this->validate();) 237 SkDEBUGCODE(this->validate();)
235 SkDEBUGCODE(size_t beforePos = buffer->pos();) 238 SkDEBUGCODE(size_t beforePos = buffer->pos();)
236 239
237 // Call getBounds() to ensure (as a side-effect) that fBounds 240 // Call getBounds() to ensure (as a side-effect) that fBounds
238 // and fIsFinite are computed. 241 // and fIsFinite are computed.
239 const SkRect& bounds = this->getBounds(); 242 const SkRect& bounds = this->getBounds();
240 243
241 int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) | 244 int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
242 ((fIsOval & 1) << kIsOval_SerializationShift) | 245 ((fIsOval & 1) << kIsOval_SerializationShift) |
246 ((fIsRRect & 1) << kIsRRect_SerializationShift) |
243 (fSegmentMask << kSegmentMask_SerializationShift); 247 (fSegmentMask << kSegmentMask_SerializationShift);
244 buffer->write32(packed); 248 buffer->write32(packed);
245 249
246 // TODO: write gen ID here. Problem: We don't know if we're cross process or not from 250 // TODO: write gen ID here. Problem: We don't know if we're cross process or not from
247 // SkWBuffer. Until this is fixed we write 0. 251 // SkWBuffer. Until this is fixed we write 0.
248 buffer->write32(0); 252 buffer->write32(0);
249 buffer->write32(fVerbCnt); 253 buffer->write32(fVerbCnt);
250 buffer->write32(fPointCnt); 254 buffer->write32(fPointCnt);
251 buffer->write32(fConicWeights.count()); 255 buffer->write32(fConicWeights.count());
252 buffer->write(verbsMemBegin(), fVerbCnt * sizeof(uint8_t)); 256 buffer->write(verbsMemBegin(), fVerbCnt * sizeof(uint8_t));
(...skipping 21 matching lines...) Expand all
274 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof( uint8_t)); 278 memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof( uint8_t));
275 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); 279 memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint));
276 fConicWeights = ref.fConicWeights; 280 fConicWeights = ref.fConicWeights;
277 fBoundsIsDirty = ref.fBoundsIsDirty; 281 fBoundsIsDirty = ref.fBoundsIsDirty;
278 if (!fBoundsIsDirty) { 282 if (!fBoundsIsDirty) {
279 fBounds = ref.fBounds; 283 fBounds = ref.fBounds;
280 fIsFinite = ref.fIsFinite; 284 fIsFinite = ref.fIsFinite;
281 } 285 }
282 fSegmentMask = ref.fSegmentMask; 286 fSegmentMask = ref.fSegmentMask;
283 fIsOval = ref.fIsOval; 287 fIsOval = ref.fIsOval;
288 fIsRRect = ref.fIsRRect;
284 SkDEBUGCODE(this->validate();) 289 SkDEBUGCODE(this->validate();)
285 } 290 }
286 291
287 SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb, 292 SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
288 int numVbs, 293 int numVbs,
289 SkScalar** weights) { 294 SkScalar** weights) {
290 // This value is just made-up for now. When count is 4, calling memset was m uch 295 // This value is just made-up for now. When count is 4, calling memset was m uch
291 // slower than just writing the loop. This seems odd, and hopefully in the 296 // slower than just writing the loop. This seems odd, and hopefully in the
292 // future this will appear to have been a fluke... 297 // future this will appear to have been a fluke...
293 static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16; 298 static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 vb[~i] = verb; 350 vb[~i] = verb;
346 } 351 }
347 } 352 }
348 353
349 fVerbCnt += numVbs; 354 fVerbCnt += numVbs;
350 fPointCnt += pCnt; 355 fPointCnt += pCnt;
351 fFreeSpace -= space; 356 fFreeSpace -= space;
352 fBoundsIsDirty = true; // this also invalidates fIsFinite 357 fBoundsIsDirty = true; // this also invalidates fIsFinite
353 if (dirtyAfterEdit) { 358 if (dirtyAfterEdit) {
354 fIsOval = false; 359 fIsOval = false;
360 fIsRRect = false;
355 } 361 }
356 362
357 if (SkPath::kConic_Verb == verb) { 363 if (SkPath::kConic_Verb == verb) {
358 SkASSERT(weights); 364 SkASSERT(weights);
359 *weights = fConicWeights.append(numVbs); 365 *weights = fConicWeights.append(numVbs);
360 } 366 }
361 367
362 SkDEBUGCODE(this->validate();) 368 SkDEBUGCODE(this->validate();)
363 return ret; 369 return ret;
364 } 370 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint); 409 size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint);
404 this->makeSpace(space); 410 this->makeSpace(space);
405 this->fVerbs[~fVerbCnt] = verb; 411 this->fVerbs[~fVerbCnt] = verb;
406 SkPoint* ret = fPoints + fPointCnt; 412 SkPoint* ret = fPoints + fPointCnt;
407 fVerbCnt += 1; 413 fVerbCnt += 1;
408 fPointCnt += pCnt; 414 fPointCnt += pCnt;
409 fFreeSpace -= space; 415 fFreeSpace -= space;
410 fBoundsIsDirty = true; // this also invalidates fIsFinite 416 fBoundsIsDirty = true; // this also invalidates fIsFinite
411 if (dirtyAfterEdit) { 417 if (dirtyAfterEdit) {
412 fIsOval = false; 418 fIsOval = false;
419 fIsRRect = false;
413 } 420 }
414 421
415 if (SkPath::kConic_Verb == verb) { 422 if (SkPath::kConic_Verb == verb) {
416 *fConicWeights.append() = weight; 423 *fConicWeights.append() = weight;
417 } 424 }
418 425
419 SkDEBUGCODE(this->validate();) 426 SkDEBUGCODE(this->validate();)
420 return ret; 427 return ret;
421 } 428 }
422 429
(...skipping 26 matching lines...) Expand all
449 // we need to be called *before* the genID gets changed or zerod 456 // we need to be called *before* the genID gets changed or zerod
450 void SkPathRef::callGenIDChangeListeners() { 457 void SkPathRef::callGenIDChangeListeners() {
451 for (int i = 0; i < fGenIDChangeListeners.count(); i++) { 458 for (int i = 0; i < fGenIDChangeListeners.count(); i++) {
452 fGenIDChangeListeners[i]->onChange(); 459 fGenIDChangeListeners[i]->onChange();
453 } 460 }
454 461
455 // Listeners get at most one shot, so whether these triggered or not, blow t hem away. 462 // Listeners get at most one shot, so whether these triggered or not, blow t hem away.
456 fGenIDChangeListeners.deleteAll(); 463 fGenIDChangeListeners.deleteAll();
457 } 464 }
458 465
466 SkRRect SkPathRef::getRRect() const {
467 const SkRect& bounds = this->getBounds();
468 SkVector radii[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
469 Iter iter(*this);
470 SkPoint pts[4];
471 uint8_t verb = iter.next(pts);
472 SkASSERT(SkPath::kMove_Verb == verb);
473 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
474 if (SkPath::kConic_Verb == verb) {
475 SkVector v1_0 = pts[1] - pts[0];
476 SkVector v2_1 = pts[2] - pts[1];
477 SkVector dxdy;
478 if (v1_0.fX) {
479 SkASSERT(!v2_1.fX && !v1_0.fY);
480 dxdy.set(SkScalarAbs(v1_0.fX), SkScalarAbs(v2_1.fY));
481 } else if (!v1_0.fY) {
482 SkASSERT(!v2_1.fX || !v2_1.fY);
483 dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v2_1.fY));
484 } else {
485 SkASSERT(!v2_1.fY);
486 dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v1_0.fY));
487 }
488 SkRRect::Corner corner =
489 pts[1].fX == bounds.fLeft ?
490 pts[1].fY == bounds.fTop ?
491 SkRRect::kUpperLeft_Corner : SkRRect::kLowerLeft_Cor ner :
492 pts[1].fY == bounds.fTop ?
493 SkRRect::kUpperRight_Corner : SkRRect::kLowerRight_C orner;
494 SkASSERT(!radii[corner].fX && !radii[corner].fY);
495 radii[corner] = dxdy;
496 } else {
497 SkASSERT((verb == SkPath::kLine_Verb
498 && (!(pts[1].fX - pts[0].fX) || !(pts[1].fY - pts[0].fY)))
499 || verb == SkPath::kClose_Verb);
500 }
501 }
502 SkRRect rrect;
503 rrect.setRectRadii(bounds, radii);
504 return rrect;
505 }
506
507 ///////////////////////////////////////////////////////////////////////////////
508
509 SkPathRef::Iter::Iter() {
510 #ifdef SK_DEBUG
511 fPts = nullptr;
512 fConicWeights = nullptr;
513 #endif
514 // need to init enough to make next() harmlessly return kDone_Verb
515 fVerbs = nullptr;
516 fVerbStop = nullptr;
517 }
518
519 SkPathRef::Iter::Iter(const SkPathRef& path) {
520 this->setPathRef(path);
521 }
522
523 void SkPathRef::Iter::setPathRef(const SkPathRef& path) {
524 fPts = path.points();
525 fVerbs = path.verbs();
526 fVerbStop = path.verbsMemBegin();
527 fConicWeights = path.conicWeights() - 1; // begin one behind
528 }
529
530 uint8_t SkPathRef::Iter::next(SkPoint pts[4]) {
531 SkASSERT(pts);
532 if (fVerbs == fVerbStop) {
533 return (uint8_t) SkPath::kDone_Verb;
534 }
535
536 // fVerbs points one beyond next verb so decrement first.
537 unsigned verb = *(--fVerbs);
538 const SkPoint* srcPts = fPts;
539
540 switch (verb) {
541 case SkPath::kMove_Verb:
542 pts[0] = srcPts[0];
543 srcPts += 1;
544 break;
545 case SkPath::kLine_Verb:
546 pts[0] = srcPts[-1];
547 pts[1] = srcPts[0];
548 srcPts += 1;
549 break;
550 case SkPath::kConic_Verb:
551 fConicWeights += 1;
552 // fall-through
553 case SkPath::kQuad_Verb:
554 pts[0] = srcPts[-1];
555 pts[1] = srcPts[0];
556 pts[2] = srcPts[1];
557 srcPts += 2;
558 break;
559 case SkPath::kCubic_Verb:
560 pts[0] = srcPts[-1];
561 pts[1] = srcPts[0];
562 pts[2] = srcPts[1];
563 pts[3] = srcPts[2];
564 srcPts += 3;
565 break;
566 case SkPath::kClose_Verb:
567 break;
568 case SkPath::kDone_Verb:
569 SkASSERT(fVerbs == fVerbStop);
570 break;
571 }
572 fPts = srcPts;
573 return (uint8_t) verb;
574 }
575
459 #ifdef SK_DEBUG 576 #ifdef SK_DEBUG
460 void SkPathRef::validate() const { 577 void SkPathRef::validate() const {
461 this->INHERITED::validate(); 578 this->INHERITED::validate();
462 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0); 579 SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0);
463 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPo ints) >= 0); 580 SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPo ints) >= 0);
464 SkASSERT((nullptr == fPoints) == (nullptr == fVerbs)); 581 SkASSERT((nullptr == fPoints) == (nullptr == fVerbs));
465 SkASSERT(!(nullptr == fPoints && 0 != fFreeSpace)); 582 SkASSERT(!(nullptr == fPoints && 0 != fFreeSpace));
466 SkASSERT(!(nullptr == fPoints && 0 != fFreeSpace)); 583 SkASSERT(!(nullptr == fPoints && 0 != fFreeSpace));
467 SkASSERT(!(nullptr == fPoints && fPointCnt)); 584 SkASSERT(!(nullptr == fPoints && fPointCnt));
468 SkASSERT(!(nullptr == fVerbs && fVerbCnt)); 585 SkASSERT(!(nullptr == fVerbs && fVerbCnt));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 break; 639 break;
523 default: 640 default:
524 SkDEBUGFAIL("Unknown Verb"); 641 SkDEBUGFAIL("Unknown Verb");
525 break; 642 break;
526 } 643 }
527 } 644 }
528 SkASSERT(mask == fSegmentMask); 645 SkASSERT(mask == fSegmentMask);
529 #endif // SK_DEBUG_PATH 646 #endif // SK_DEBUG_PATH
530 } 647 }
531 #endif 648 #endif
OLDNEW
« 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