| Index: src/core/SkRecordDraw.cpp
|
| diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
|
| index a94312225a034808f86ba379d83d720f7ee23aef..bdebcb7c1560fce0ef6fe0f91306e528f7aadaf9 100644
|
| --- a/src/core/SkRecordDraw.cpp
|
| +++ b/src/core/SkRecordDraw.cpp
|
| @@ -7,6 +7,7 @@
|
|
|
| #include "SkRecordDraw.h"
|
| #include "SkPatchUtils.h"
|
| +#include "SkTLogic.h"
|
|
|
| void SkRecordDraw(const SkRecord& record,
|
| SkCanvas* canvas,
|
| @@ -184,17 +185,27 @@ private:
|
| void updateCTM(const Restore& op) { fCTM = &op.matrix; }
|
| void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; }
|
|
|
| - template <typename T> void updateClipBounds(const T&) { /* most ops don't change the clip */ }
|
| - // Each of these devBounds fields is the state of the device bounds after the op.
|
| - // So Restore's devBounds are those bounds saved by its paired Save or SaveLayer.
|
| - void updateClipBounds(const Restore& op) { fCurrentClipBounds = Bounds::Make(op.devBounds); }
|
| - void updateClipBounds(const ClipPath& op) { fCurrentClipBounds = Bounds::Make(op.devBounds); }
|
| - void updateClipBounds(const ClipRRect& op) { fCurrentClipBounds = Bounds::Make(op.devBounds); }
|
| - void updateClipBounds(const ClipRect& op) { fCurrentClipBounds = Bounds::Make(op.devBounds); }
|
| - void updateClipBounds(const ClipRegion& op) { fCurrentClipBounds = Bounds::Make(op.devBounds); }
|
| + // Most ops don't change the clip. Those that do generally have a field named devBounds.
|
| + SK_CREATE_MEMBER_DETECTOR(devBounds);
|
| +
|
| + template <typename T>
|
| + SK_WHEN(!HasMember_devBounds<T>, void) updateClipBounds(const T& op) {}
|
| +
|
| + // Each of the devBounds fields holds the state of the device bounds after the op.
|
| + // (So Restore's devBounds are those bounds saved by its paired Save or SaveLayer.)
|
| + template <typename T>
|
| + SK_WHEN(HasMember_devBounds<T>, void) updateClipBounds(const T& op) {
|
| + Bounds clip = SkRect::Make(op.devBounds);
|
| + // We don't call adjustAndMap() because as its last step it would intersect the adjusted
|
| + // clip bounds with the previous clip, exactly what we can't do when the clip grows.
|
| + fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip) ? clip : Bounds::MakeLargest();
|
| + }
|
| +
|
| + // We also take advantage of SaveLayer bounds when present to further cut the clip down.
|
| void updateClipBounds(const SaveLayer& op) {
|
| if (op.bounds) {
|
| - fCurrentClipBounds.intersect(this->adjustAndMap(*op.bounds, op.paint));
|
| + // adjustAndMap() intersects these layer bounds with the previous clip for us.
|
| + fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint);
|
| }
|
| }
|
|
|
| @@ -467,6 +478,15 @@ private:
|
| return true;
|
| }
|
|
|
| + bool adjustForSaveLayerPaints(SkRect* rect) const {
|
| + for (int i = fSaveStack.count() - 1; i >= 0; i--) {
|
| + if (!AdjustForPaint(fSaveStack[i].paint, rect)) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| +
|
| // Adjust rect for all paints that may affect its geometry, then map it to identity space.
|
| Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const {
|
| // Inverted rectangles really confuse our BBHs.
|
| @@ -479,11 +499,9 @@ private:
|
| }
|
|
|
| // Adjust rect for all the paints from the SaveLayers we're inside.
|
| - for (int i = fSaveStack.count() - 1; i >= 0; i--) {
|
| - if (!AdjustForPaint(fSaveStack[i].paint, &rect)) {
|
| - // Same deal as above.
|
| - return fCurrentClipBounds;
|
| - }
|
| + if (!this->adjustForSaveLayerPaints(&rect)) {
|
| + // Same deal as above.
|
| + return fCurrentClipBounds;
|
| }
|
|
|
| // Map the rect back to identity space.
|
|
|