| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 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 "SkRegionPriv.h" | 8 #include "SkRegionPriv.h" |
| 9 #include "SkBlitter.h" | 9 #include "SkBlitter.h" |
| 10 #include "SkScan.h" | 10 #include "SkScan.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 | 25 |
| 26 class SkRgnBuilder : public SkBlitter { | 26 class SkRgnBuilder : public SkBlitter { |
| 27 public: | 27 public: |
| 28 SkRgnBuilder(); | 28 SkRgnBuilder(); |
| 29 virtual ~SkRgnBuilder(); | 29 virtual ~SkRgnBuilder(); |
| 30 | 30 |
| 31 // returns true if it could allocate the working storage needed | 31 // returns true if it could allocate the working storage needed |
| 32 bool init(int maxHeight, int maxTransitions, bool pathIsInverse); | 32 bool init(int maxHeight, int maxTransitions, bool pathIsInverse); |
| 33 | 33 |
| 34 void done() { | 34 void done() { |
| 35 if (fCurrScanline != NULL) { | 35 if (fCurrScanline != nullptr) { |
| 36 fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurr
Scanline->firstX())); | 36 fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurr
Scanline->firstX())); |
| 37 if (!this->collapsWithPrev()) { // flush the last line | 37 if (!this->collapsWithPrev()) { // flush the last line |
| 38 fCurrScanline = fCurrScanline->nextScanline(); | 38 fCurrScanline = fCurrScanline->nextScanline(); |
| 39 } | 39 } |
| 40 } | 40 } |
| 41 } | 41 } |
| 42 | 42 |
| 43 int computeRunCount() const; | 43 int computeRunCount() const; |
| 44 void copyToRect(SkIRect*) const; | 44 void copyToRect(SkIRect*) const; |
| 45 void copyToRgn(SkRegion::RunType runs[]) const; | 45 void copyToRgn(SkRegion::RunType runs[]) const; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 SkRegion::RunType* fStorage; | 87 SkRegion::RunType* fStorage; |
| 88 Scanline* fCurrScanline; | 88 Scanline* fCurrScanline; |
| 89 Scanline* fPrevScanline; | 89 Scanline* fPrevScanline; |
| 90 // points at next avialable x[] in fCurrScanline | 90 // points at next avialable x[] in fCurrScanline |
| 91 SkRegion::RunType* fCurrXPtr; | 91 SkRegion::RunType* fCurrXPtr; |
| 92 SkRegion::RunType fTop; // first Y value | 92 SkRegion::RunType fTop; // first Y value |
| 93 | 93 |
| 94 int fStorageCount; | 94 int fStorageCount; |
| 95 | 95 |
| 96 bool collapsWithPrev() { | 96 bool collapsWithPrev() { |
| 97 if (fPrevScanline != NULL && | 97 if (fPrevScanline != nullptr && |
| 98 fPrevScanline->fLastY + 1 == fCurrScanline->fLastY && | 98 fPrevScanline->fLastY + 1 == fCurrScanline->fLastY && |
| 99 fPrevScanline->fXCount == fCurrScanline->fXCount && | 99 fPrevScanline->fXCount == fCurrScanline->fXCount && |
| 100 sk_memeq32(fPrevScanline->firstX(), fCurrScanline->firstX(), fCurrSc
anline->fXCount)) | 100 sk_memeq32(fPrevScanline->firstX(), fCurrScanline->firstX(), fCurrSc
anline->fXCount)) |
| 101 { | 101 { |
| 102 // update the height of fPrevScanline | 102 // update the height of fPrevScanline |
| 103 fPrevScanline->fLastY = fCurrScanline->fLastY; | 103 fPrevScanline->fLastY = fCurrScanline->fLastY; |
| 104 return true; | 104 return true; |
| 105 } | 105 } |
| 106 return false; | 106 return false; |
| 107 } | 107 } |
| 108 }; | 108 }; |
| 109 | 109 |
| 110 SkRgnBuilder::SkRgnBuilder() | 110 SkRgnBuilder::SkRgnBuilder() |
| 111 : fStorage(NULL) { | 111 : fStorage(nullptr) { |
| 112 } | 112 } |
| 113 | 113 |
| 114 SkRgnBuilder::~SkRgnBuilder() { | 114 SkRgnBuilder::~SkRgnBuilder() { |
| 115 sk_free(fStorage); | 115 sk_free(fStorage); |
| 116 } | 116 } |
| 117 | 117 |
| 118 bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) { | 118 bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) { |
| 119 if ((maxHeight | maxTransitions) < 0) { | 119 if ((maxHeight | maxTransitions) < 0) { |
| 120 return false; | 120 return false; |
| 121 } | 121 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 140 return false; | 140 return false; |
| 141 } | 141 } |
| 142 fStorageCount = sk_64_asS32(count); | 142 fStorageCount = sk_64_asS32(count); |
| 143 | 143 |
| 144 int64_t size = sk_64_mul(fStorageCount, sizeof(SkRegion::RunType)); | 144 int64_t size = sk_64_mul(fStorageCount, sizeof(SkRegion::RunType)); |
| 145 if (size < 0 || !sk_64_isS32(size)) { | 145 if (size < 0 || !sk_64_isS32(size)) { |
| 146 return false; | 146 return false; |
| 147 } | 147 } |
| 148 | 148 |
| 149 fStorage = (SkRegion::RunType*)sk_malloc_flags(sk_64_asS32(size), 0); | 149 fStorage = (SkRegion::RunType*)sk_malloc_flags(sk_64_asS32(size), 0); |
| 150 if (NULL == fStorage) { | 150 if (nullptr == fStorage) { |
| 151 return false; | 151 return false; |
| 152 } | 152 } |
| 153 | 153 |
| 154 fCurrScanline = NULL; // signal empty collection | 154 fCurrScanline = nullptr; // signal empty collection |
| 155 fPrevScanline = NULL; // signal first scanline | 155 fPrevScanline = nullptr; // signal first scanline |
| 156 return true; | 156 return true; |
| 157 } | 157 } |
| 158 | 158 |
| 159 void SkRgnBuilder::blitH(int x, int y, int width) { | 159 void SkRgnBuilder::blitH(int x, int y, int width) { |
| 160 if (fCurrScanline == NULL) { // first time | 160 if (fCurrScanline == nullptr) { // first time |
| 161 fTop = (SkRegion::RunType)(y); | 161 fTop = (SkRegion::RunType)(y); |
| 162 fCurrScanline = (Scanline*)fStorage; | 162 fCurrScanline = (Scanline*)fStorage; |
| 163 fCurrScanline->fLastY = (SkRegion::RunType)(y); | 163 fCurrScanline->fLastY = (SkRegion::RunType)(y); |
| 164 fCurrXPtr = fCurrScanline->firstX(); | 164 fCurrXPtr = fCurrScanline->firstX(); |
| 165 } else { | 165 } else { |
| 166 SkASSERT(y >= fCurrScanline->fLastY); | 166 SkASSERT(y >= fCurrScanline->fLastY); |
| 167 | 167 |
| 168 if (y > fCurrScanline->fLastY) { | 168 if (y > fCurrScanline->fLastY) { |
| 169 // if we get here, we're done with fCurrScanline | 169 // if we get here, we're done with fCurrScanline |
| 170 fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurr
Scanline->firstX())); | 170 fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurr
Scanline->firstX())); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 190 fCurrXPtr[-1] = (SkRegion::RunType)(x + width); | 190 fCurrXPtr[-1] = (SkRegion::RunType)(x + width); |
| 191 } else { | 191 } else { |
| 192 fCurrXPtr[0] = (SkRegion::RunType)(x); | 192 fCurrXPtr[0] = (SkRegion::RunType)(x); |
| 193 fCurrXPtr[1] = (SkRegion::RunType)(x + width); | 193 fCurrXPtr[1] = (SkRegion::RunType)(x + width); |
| 194 fCurrXPtr += 2; | 194 fCurrXPtr += 2; |
| 195 } | 195 } |
| 196 SkASSERT(fCurrXPtr - fStorage < fStorageCount); | 196 SkASSERT(fCurrXPtr - fStorage < fStorageCount); |
| 197 } | 197 } |
| 198 | 198 |
| 199 int SkRgnBuilder::computeRunCount() const { | 199 int SkRgnBuilder::computeRunCount() const { |
| 200 if (fCurrScanline == NULL) { | 200 if (fCurrScanline == nullptr) { |
| 201 return 0; | 201 return 0; |
| 202 } | 202 } |
| 203 | 203 |
| 204 const SkRegion::RunType* line = fStorage; | 204 const SkRegion::RunType* line = fStorage; |
| 205 const SkRegion::RunType* stop = (const SkRegion::RunType*)fCurrScanline; | 205 const SkRegion::RunType* stop = (const SkRegion::RunType*)fCurrScanline; |
| 206 | 206 |
| 207 return 2 + (int)(stop - line); | 207 return 2 + (int)(stop - line); |
| 208 } | 208 } |
| 209 | 209 |
| 210 void SkRgnBuilder::copyToRect(SkIRect* r) const { | 210 void SkRgnBuilder::copyToRect(SkIRect* r) const { |
| 211 SkASSERT(fCurrScanline != NULL); | 211 SkASSERT(fCurrScanline != nullptr); |
| 212 // A rect's scanline is [bottom intervals left right sentinel] == 5 | 212 // A rect's scanline is [bottom intervals left right sentinel] == 5 |
| 213 SkASSERT((const SkRegion::RunType*)fCurrScanline - fStorage == 5); | 213 SkASSERT((const SkRegion::RunType*)fCurrScanline - fStorage == 5); |
| 214 | 214 |
| 215 const Scanline* line = (const Scanline*)fStorage; | 215 const Scanline* line = (const Scanline*)fStorage; |
| 216 SkASSERT(line->fXCount == 2); | 216 SkASSERT(line->fXCount == 2); |
| 217 | 217 |
| 218 r->set(line->firstX()[0], fTop, line->firstX()[1], line->fLastY + 1); | 218 r->set(line->firstX()[0], fTop, line->firstX()[1], line->fLastY + 1); |
| 219 } | 219 } |
| 220 | 220 |
| 221 void SkRgnBuilder::copyToRgn(SkRegion::RunType runs[]) const { | 221 void SkRgnBuilder::copyToRgn(SkRegion::RunType runs[]) const { |
| 222 SkASSERT(fCurrScanline != NULL); | 222 SkASSERT(fCurrScanline != nullptr); |
| 223 SkASSERT((const SkRegion::RunType*)fCurrScanline - fStorage > 4); | 223 SkASSERT((const SkRegion::RunType*)fCurrScanline - fStorage > 4); |
| 224 | 224 |
| 225 const Scanline* line = (const Scanline*)fStorage; | 225 const Scanline* line = (const Scanline*)fStorage; |
| 226 const Scanline* stop = fCurrScanline; | 226 const Scanline* stop = fCurrScanline; |
| 227 | 227 |
| 228 *runs++ = fTop; | 228 *runs++ = fTop; |
| 229 do { | 229 do { |
| 230 *runs++ = (SkRegion::RunType)(line->fLastY + 1); | 230 *runs++ = (SkRegion::RunType)(line->fLastY + 1); |
| 231 int count = line->fXCount; | 231 int count = line->fXCount; |
| 232 *runs++ = count >> 1; // intervalCount | 232 *runs++ = count >> 1; // intervalCount |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 uint8_t fFlags; | 390 uint8_t fFlags; |
| 391 Edge* fNext; | 391 Edge* fNext; |
| 392 | 392 |
| 393 void set(int x, int y0, int y1) { | 393 void set(int x, int y0, int y1) { |
| 394 SkASSERT(y0 != y1); | 394 SkASSERT(y0 != y1); |
| 395 | 395 |
| 396 fX = (SkRegion::RunType)(x); | 396 fX = (SkRegion::RunType)(x); |
| 397 fY0 = (SkRegion::RunType)(y0); | 397 fY0 = (SkRegion::RunType)(y0); |
| 398 fY1 = (SkRegion::RunType)(y1); | 398 fY1 = (SkRegion::RunType)(y1); |
| 399 fFlags = 0; | 399 fFlags = 0; |
| 400 SkDEBUGCODE(fNext = NULL;) | 400 SkDEBUGCODE(fNext = nullptr;) |
| 401 } | 401 } |
| 402 | 402 |
| 403 int top() const { | 403 int top() const { |
| 404 return SkFastMin32(fY0, fY1); | 404 return SkFastMin32(fY0, fY1); |
| 405 } | 405 } |
| 406 }; | 406 }; |
| 407 | 407 |
| 408 static void find_link(Edge* base, Edge* stop) { | 408 static void find_link(Edge* base, Edge* stop) { |
| 409 SkASSERT(base < stop); | 409 SkASSERT(base < stop); |
| 410 | 410 |
| 411 if (base->fFlags == Edge::kCompleteLink) { | 411 if (base->fFlags == Edge::kCompleteLink) { |
| 412 SkASSERT(base->fNext); | 412 SkASSERT(base->fNext); |
| 413 return; | 413 return; |
| 414 } | 414 } |
| 415 | 415 |
| 416 SkASSERT(base + 1 < stop); | 416 SkASSERT(base + 1 < stop); |
| 417 | 417 |
| 418 int y0 = base->fY0; | 418 int y0 = base->fY0; |
| 419 int y1 = base->fY1; | 419 int y1 = base->fY1; |
| 420 | 420 |
| 421 Edge* e = base; | 421 Edge* e = base; |
| 422 if ((base->fFlags & Edge::kY0Link) == 0) { | 422 if ((base->fFlags & Edge::kY0Link) == 0) { |
| 423 for (;;) { | 423 for (;;) { |
| 424 e += 1; | 424 e += 1; |
| 425 if ((e->fFlags & Edge::kY1Link) == 0 && y0 == e->fY1) { | 425 if ((e->fFlags & Edge::kY1Link) == 0 && y0 == e->fY1) { |
| 426 SkASSERT(NULL == e->fNext); | 426 SkASSERT(nullptr == e->fNext); |
| 427 e->fNext = base; | 427 e->fNext = base; |
| 428 e->fFlags = SkToU8(e->fFlags | Edge::kY1Link); | 428 e->fFlags = SkToU8(e->fFlags | Edge::kY1Link); |
| 429 break; | 429 break; |
| 430 } | 430 } |
| 431 } | 431 } |
| 432 } | 432 } |
| 433 | 433 |
| 434 e = base; | 434 e = base; |
| 435 if ((base->fFlags & Edge::kY1Link) == 0) { | 435 if ((base->fFlags & Edge::kY1Link) == 0) { |
| 436 for (;;) { | 436 for (;;) { |
| 437 e += 1; | 437 e += 1; |
| 438 if ((e->fFlags & Edge::kY0Link) == 0 && y1 == e->fY0) { | 438 if ((e->fFlags & Edge::kY0Link) == 0 && y1 == e->fY0) { |
| 439 SkASSERT(NULL == base->fNext); | 439 SkASSERT(nullptr == base->fNext); |
| 440 base->fNext = e; | 440 base->fNext = e; |
| 441 e->fFlags = SkToU8(e->fFlags | Edge::kY0Link); | 441 e->fFlags = SkToU8(e->fFlags | Edge::kY0Link); |
| 442 break; | 442 break; |
| 443 } | 443 } |
| 444 } | 444 } |
| 445 } | 445 } |
| 446 | 446 |
| 447 base->fFlags = Edge::kCompleteLink; | 447 base->fFlags = Edge::kCompleteLink; |
| 448 } | 448 } |
| 449 | 449 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 477 return count; | 477 return count; |
| 478 } | 478 } |
| 479 | 479 |
| 480 struct EdgeLT { | 480 struct EdgeLT { |
| 481 bool operator()(const Edge& a, const Edge& b) const { | 481 bool operator()(const Edge& a, const Edge& b) const { |
| 482 return (a.fX == b.fX) ? a.top() < b.top() : a.fX < b.fX; | 482 return (a.fX == b.fX) ? a.top() < b.top() : a.fX < b.fX; |
| 483 } | 483 } |
| 484 }; | 484 }; |
| 485 | 485 |
| 486 bool SkRegion::getBoundaryPath(SkPath* path) const { | 486 bool SkRegion::getBoundaryPath(SkPath* path) const { |
| 487 // path could safely be NULL if we're empty, but the caller shouldn't | 487 // path could safely be nullptr if we're empty, but the caller shouldn't |
| 488 // *know* that | 488 // *know* that |
| 489 SkASSERT(path); | 489 SkASSERT(path); |
| 490 | 490 |
| 491 if (this->isEmpty()) { | 491 if (this->isEmpty()) { |
| 492 return false; | 492 return false; |
| 493 } | 493 } |
| 494 | 494 |
| 495 const SkIRect& bounds = this->getBounds(); | 495 const SkIRect& bounds = this->getBounds(); |
| 496 | 496 |
| 497 if (this->isRect()) { | 497 if (this->isRect()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 515 Edge* stop = start + count; | 515 Edge* stop = start + count; |
| 516 SkTQSort<Edge>(start, stop - 1, EdgeLT()); | 516 SkTQSort<Edge>(start, stop - 1, EdgeLT()); |
| 517 | 517 |
| 518 Edge* e; | 518 Edge* e; |
| 519 for (e = start; e != stop; e++) { | 519 for (e = start; e != stop; e++) { |
| 520 find_link(e, stop); | 520 find_link(e, stop); |
| 521 } | 521 } |
| 522 | 522 |
| 523 #ifdef SK_DEBUG | 523 #ifdef SK_DEBUG |
| 524 for (e = start; e != stop; e++) { | 524 for (e = start; e != stop; e++) { |
| 525 SkASSERT(e->fNext != NULL); | 525 SkASSERT(e->fNext != nullptr); |
| 526 SkASSERT(e->fFlags == Edge::kCompleteLink); | 526 SkASSERT(e->fFlags == Edge::kCompleteLink); |
| 527 } | 527 } |
| 528 #endif | 528 #endif |
| 529 | 529 |
| 530 path->incReserve(count << 1); | 530 path->incReserve(count << 1); |
| 531 do { | 531 do { |
| 532 SkASSERT(count > 1); | 532 SkASSERT(count > 1); |
| 533 count -= extract_path(start, stop, path); | 533 count -= extract_path(start, stop, path); |
| 534 } while (count > 0); | 534 } while (count > 0); |
| 535 | 535 |
| 536 return true; | 536 return true; |
| 537 } | 537 } |
| OLD | NEW |