aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar senorblanco <senorblanco@chromium.org>2014-07-11 09:56:03 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-07-11 09:56:03 -0700
commit6ca0b6a46cbe9bef3e2b9b9db813ec864efd62de (patch)
tree777045a1ad412b4a0e6856b152a499f7782bc3ae /src
parentc855ca0c9408d2a218655a138fab9cc18a2b3940 (diff)
Fix for saveLayer() with filters vs. the BBox Hierarchy.
When building acceleration structures for SkPicture, we must transform the primitive's bounds not only by its own SkPaint, but by the paints of any saveLayer()s currently active above it. We do this by pushing the SkPaint onto a stack on saveLayer(), and popping them on restore(). We also push a NULL paint in save(), so that the pushes and pops are balanced. BUG=skia:2734 R=mtklein@google.com, reed@google.com Author: senorblanco@chromium.org Review URL: https://codereview.chromium.org/380373003
Diffstat (limited to 'src')
-rw-r--r--src/core/SkBBoxRecord.cpp35
-rw-r--r--src/core/SkBBoxRecord.h12
2 files changed, 46 insertions, 1 deletions
diff --git a/src/core/SkBBoxRecord.cpp b/src/core/SkBBoxRecord.cpp
index a40ea8ba0d..3670f9145e 100644
--- a/src/core/SkBBoxRecord.cpp
+++ b/src/core/SkBBoxRecord.cpp
@@ -8,6 +8,13 @@
#include "SkBBoxRecord.h"
+SkBBoxRecord::~SkBBoxRecord() {
+ while (!fSaveStack.empty()) {
+ delete fSaveStack.top();
+ fSaveStack.pop();
+ }
+}
+
void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
if (this->transformBounds(rect, &paint)) {
INHERITED::drawOval(rect, paint);
@@ -287,6 +294,26 @@ void SkBBoxRecord::onDrawPicture(const SkPicture* picture) {
}
}
+void SkBBoxRecord::willSave() {
+ fSaveStack.push(NULL);
+ this->INHERITED::willSave();
+}
+
+SkCanvas::SaveLayerStrategy SkBBoxRecord::willSaveLayer(const SkRect* bounds,
+ const SkPaint* paint,
+ SaveFlags flags) {
+ // Image filters can affect the effective bounds of primitives drawn inside saveLayer().
+ // Copy the paint so we can compute the modified bounds in transformBounds().
+ fSaveStack.push(paint && paint->getImageFilter() ? new SkPaint(*paint) : NULL);
+ return this->INHERITED::willSaveLayer(bounds, paint, flags);
+}
+
+void SkBBoxRecord::willRestore() {
+ delete fSaveStack.top();
+ fSaveStack.pop();
+ this->INHERITED::willRestore();
+}
+
bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
SkRect outBounds = bounds;
outBounds.sort();
@@ -305,6 +332,14 @@ bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
}
}
+ for (int i = fSaveStack.count() - 1; i >= 0; --i) {
+ const SkPaint* paint = fSaveStack.index(i);
+ if (paint && paint->canComputeFastBounds()) {
+ SkRect temp;
+ outBounds = paint->computeFastBounds(outBounds, &temp);
+ }
+ }
+
if (!outBounds.isEmpty() && !this->quickReject(outBounds)) {
this->getTotalMatrix().mapRect(&outBounds);
this->handleBBox(outBounds);
diff --git a/src/core/SkBBoxRecord.h b/src/core/SkBBoxRecord.h
index f3d72b0448..f3f8eb8f49 100644
--- a/src/core/SkBBoxRecord.h
+++ b/src/core/SkBBoxRecord.h
@@ -10,6 +10,7 @@
#define SkBBoxRecord_DEFINED
#include "SkPictureRecord.h"
+#include "SkTDStack.h"
/**
* This is an abstract SkPictureRecord subclass that intercepts draw calls and computes an
@@ -22,7 +23,7 @@ public:
SkBBoxRecord(const SkISize& size, uint32_t recordFlags)
: INHERITED(size, recordFlags) {
}
- virtual ~SkBBoxRecord() { }
+ virtual ~SkBBoxRecord();
/**
* This is called each time we get a bounding box, it will be axis-aligned,
@@ -66,6 +67,9 @@ protected:
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE;
+ virtual void willSave() SK_OVERRIDE;
+ virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
+ virtual void willRestore() SK_OVERRIDE;
private:
/**
@@ -75,6 +79,12 @@ private:
**/
bool transformBounds(const SkRect& bounds, const SkPaint* paint);
+ /**
+ * Paints from currently-active saveLayers that need to be applied to bounding boxes of all
+ * primitives drawn inside them. We own these pointers.
+ **/
+ SkTDStack<const SkPaint*> fSaveStack;
+
typedef SkPictureRecord INHERITED;
};