| Index: src/core/SkRecordDraw.h
|
| diff --git a/src/core/SkRecordDraw.h b/src/core/SkRecordDraw.h
|
| index 75921d182fd3de1e5596114b7fce2e033cba696c..fea3e9d55306a428683421b674b3ba1bc4049fe1 100644
|
| --- a/src/core/SkRecordDraw.h
|
| +++ b/src/core/SkRecordDraw.h
|
| @@ -71,6 +71,105 @@ private:
|
| typedef Draw INHERITED;
|
| };
|
|
|
| +template <typename VISITOR> class VisitMaster : SkNoncopyable {
|
| +public:
|
| + VisitMaster(const SkRecord& record, SkBBoxHierarchy* bbh) {
|
| + VISITOR visitor(record, bbh);
|
| +
|
| + for (unsigned curOp = 0; curOp < record.count(); curOp++) {
|
| + visitor.setCurrentOp(curOp);
|
| + record.visit<void>(curOp, visitor);
|
| + }
|
| +
|
| + visitor.cleanUp();
|
| + }
|
| +};
|
| +
|
| +// This is an SkRecord visitor that fills an SkBBoxHierarchy.
|
| +//
|
| +// The interesting part here is how to calculate bounds for ops which don't
|
| +// have intrinsic bounds. What is the bounds of a Save or a Translate?
|
| +//
|
| +// We answer this by thinking about a particular definition of bounds: if I
|
| +// don't execute this op, pixels in this rectangle might draw incorrectly. So
|
| +// the bounds of a Save, a Translate, a Restore, etc. are the union of the
|
| +// bounds of Draw* ops that they might have an effect on. For any given
|
| +// Save/Restore block, the bounds of the Save, the Restore, and any other
|
| +// non-drawing ("control") ops inside are exactly the union of the bounds of
|
| +// the drawing ops inside that block.
|
| +//
|
| +// To implement this, we keep a stack of active Save blocks. As we consume ops
|
| +// inside the Save/Restore block, drawing ops are unioned with the bounds of
|
| +// the block, and control ops are stashed away for later. When we finish the
|
| +// block with a Restore, our bounds are complete, and we go back and fill them
|
| +// in for all the control ops we stashed away.
|
| +class FillBounds : SkNoncopyable {
|
| +public:
|
| + FillBounds(const SkRecord& record, SkBBoxHierarchy* bbh);
|
| +
|
| + void setCurrentOp(unsigned currentOp) { fCurrentOp = currentOp; }
|
| + void cleanUp();
|
| +
|
| + template <typename T> void operator()(const T& op) {
|
| + this->updateCTM(op);
|
| + this->updateClipBounds(op);
|
| + this->trackBounds(op);
|
| + }
|
| +
|
| +protected:
|
| + // In FillBounds, SkRect are in local coordinates, Bounds are translated back to identity space.
|
| + typedef SkRect Bounds;
|
| +
|
| + unsigned currentOp() const { return fCurrentOp; }
|
| + const SkMatrix& ctm() const { return *fCTM; }
|
| + const Bounds& currentClipBounds() const { return fCurrentClipBounds; }
|
| +
|
| + Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const;
|
| + const Bounds& getBounds(unsigned index) const { return fBounds[index]; }
|
| +
|
| +private:
|
| + struct SaveBounds {
|
| + int controlOps; // Number of control ops in this Save block, including the Save.
|
| + Bounds bounds; // Bounds of everything in the block.
|
| + const SkPaint* paint; // Unowned. If set, adjusts the bounds of all ops in this block.
|
| + };
|
| +
|
| + template <typename T> void updateCTM(const T&);
|
| + template <typename T> void updateClipBounds(const T&);
|
| + template <typename T> void trackBounds(const T&);
|
| + template <typename T> Bounds bounds(const T&) const;
|
| +
|
| + void updateClipBoundsForClipOp(const SkIRect& devBounds);
|
| +
|
| + void pushSaveBlock(const SkPaint* paint);
|
| + Bounds popSaveBlock();
|
| + void pushControl();
|
| + void popControl(const Bounds& bounds);
|
| + void updateSaveBounds(const Bounds& bounds);
|
| +
|
| + bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const;
|
| +
|
| + const unsigned int fNumRecords;
|
| +
|
| + // The BBH being filled in
|
| + SkBBoxHierarchy* fBBH;
|
| +
|
| + // Conservative identity-space bounds for each op in the SkRecord.
|
| + SkAutoTMalloc<Bounds> fBounds;
|
| +
|
| + // We walk fCurrentOp through the SkRecord, as we go using updateCTM()
|
| + // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative
|
| + // identity-space bounds of the current clip (fCurrentClipBounds).
|
| + unsigned fCurrentOp;
|
| + const SkMatrix* fCTM;
|
| + Bounds fCurrentClipBounds;
|
| +
|
| + // Used to track the bounds of Save/Restore blocks and the control ops inside them.
|
| + SkTDArray<SaveBounds> fSaveStack;
|
| + SkTDArray<unsigned> fControlIndices;
|
| +};
|
| +
|
| +
|
| } // namespace SkRecords
|
|
|
| #endif//SkRecordDraw_DEFINED
|
|
|