diff options
author | Mike Reed <reed@google.com> | 2018-02-27 15:44:36 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-02-27 21:03:49 +0000 |
commit | bb586b2eeba59af265c9efc20d7e9795191e046d (patch) | |
tree | 2c26544bef3ae53dea67ea9f0eebe36a72f8d50b /src | |
parent | 84fdd4fcba03e656b88aa2a9586671f328b36436 (diff) |
fix crasher in path-->region
Bug: skia:7491
Change-Id: I7e8b9fbe43098094d5935331107c3f40fb6971ec
Reviewed-on: https://skia-review.googlesource.com/110721
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Cary Clark <caryclark@google.com>
Reviewed-by: Yuqian Li <liyuqian@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkBlitter.cpp | 11 | ||||
-rw-r--r-- | src/core/SkRegion.cpp | 43 | ||||
-rw-r--r-- | src/core/SkRegionPriv.h | 10 |
3 files changed, 57 insertions, 7 deletions
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 24494c1e71..ccc31d093b 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -15,6 +15,7 @@ #include "SkMask.h" #include "SkMaskFilterBase.h" #include "SkPaintPriv.h" +#include "SkRegionPriv.h" #include "SkShaderBase.h" #include "SkString.h" #include "SkTLazy.h" @@ -343,13 +344,9 @@ void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) { } void SkBlitter::blitRegion(const SkRegion& clip) { - SkRegion::Iterator iter(clip); - - while (!iter.done()) { - const SkIRect& cr = iter.rect(); - this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); - iter.next(); - } + SkRegionPriv::VisitSpans(clip, [this](const SkIRect& r) { + this->blitRect(r.left(), r.top(), r.width(), r.height()); + }); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkRegion.cpp b/src/core/SkRegion.cpp index 3a1a63e187..8ba3167297 100644 --- a/src/core/SkRegion.cpp +++ b/src/core/SkRegion.cpp @@ -1503,6 +1503,49 @@ bool SkRegion::Spanerator::next(int* left, int* right) { return true; } +/////////////////////////////////////////////////////////////////////////////////////////////////// + +static void visit_pairs(int pairCount, int y, const int32_t pairs[], + const std::function<void(const SkIRect&)>& visitor) { + for (int i = 0; i < pairCount; ++i) { + visitor({ pairs[0], y, pairs[1], y + 1 }); + pairs += 2; + } +} + +void SkRegionPriv::VisitSpans(const SkRegion& rgn, + const std::function<void(const SkIRect&)>& visitor) { + if (rgn.isEmpty()) { + return; + } + if (rgn.isRect()) { + visitor(rgn.getBounds()); + } else { + const int32_t* p = rgn.fRunHead->readonly_runs(); + int32_t top = *p++; + int32_t bot = *p++; + do { + int pairCount = *p++; + if (pairCount == 1) { + visitor({ p[0], top, p[1], bot }); + p += 2; + } else if (pairCount > 1) { + // we have to loop repeated in Y, sending each interval in Y -> X order + for (int y = top; y < bot; ++y) { + visit_pairs(pairCount, y, p, visitor); + } + p += pairCount * 2; + } + assert_sentinel(*p, true); + p += 1; // skip sentinel + + // read next bottom or sentinel + top = bot; + bot = *p++; + } while (!SkRegionValueIsSentinel(bot)); + } +} + /////////////////////////////////////////////////////////////////////////////// #ifdef SK_DEBUG diff --git a/src/core/SkRegionPriv.h b/src/core/SkRegionPriv.h index 4ccb68a392..ce21e92960 100644 --- a/src/core/SkRegionPriv.h +++ b/src/core/SkRegionPriv.h @@ -244,4 +244,14 @@ private: int32_t fIntervalCount; }; +#include <functional> + +class SkRegionPriv { +public: + // Call the function with each span, in Y -> X ascending order. + // We pass a rect, but we will still ensure the span Y->X ordering, so often the height + // of the rect may be 1. It should never be empty. + static void VisitSpans(const SkRegion& rgn, const std::function<void(const SkIRect&)>&); +}; + #endif |