diff options
author | 2014-07-11 09:56:03 -0700 | |
---|---|---|
committer | 2014-07-11 09:56:03 -0700 | |
commit | 6ca0b6a46cbe9bef3e2b9b9db813ec864efd62de (patch) | |
tree | 777045a1ad412b4a0e6856b152a499f7782bc3ae /src/core/SkBBoxRecord.cpp | |
parent | c855ca0c9408d2a218655a138fab9cc18a2b3940 (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/core/SkBBoxRecord.cpp')
-rw-r--r-- | src/core/SkBBoxRecord.cpp | 35 |
1 files changed, 35 insertions, 0 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); |