aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2018-02-27 15:44:36 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-27 21:03:49 +0000
commitbb586b2eeba59af265c9efc20d7e9795191e046d (patch)
tree2c26544bef3ae53dea67ea9f0eebe36a72f8d50b /src
parent84fdd4fcba03e656b88aa2a9586671f328b36436 (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.cpp11
-rw-r--r--src/core/SkRegion.cpp43
-rw-r--r--src/core/SkRegionPriv.h10
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