Chromium Code Reviews| Index: src/core/SkRecordDraw.h |
| diff --git a/src/core/SkRecordDraw.h b/src/core/SkRecordDraw.h |
| index 75921d182fd3de1e5596114b7fce2e033cba696c..9ec554252b2c66a45dfc125680e6d3543d7032aa 100644 |
| --- a/src/core/SkRecordDraw.h |
| +++ b/src/core/SkRecordDraw.h |
| @@ -71,6 +71,79 @@ private: |
| typedef Draw INHERITED; |
| }; |
| +// 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); |
|
mtklein
2014/11/03 14:55:21
Given that we do all the work in the constructor i
robertphillips
2014/11/03 15:14:17
I guess we could move CollectLayers from GrPicture
|
| + |
| + template <typename T> void operator()(const T& op) { |
| + this->updateCTM(op); |
| + this->updateClipBounds(op); |
| + this->trackBounds(op); |
| + } |
| + |
| +private: |
| + // In FillBounds, SkRect are in local coordinates, Bounds are translated back to identity space. |
| + typedef SkRect Bounds; |
| + |
| + 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); |
| + static bool PaintMayAffectTransparentBlack(const SkPaint* paint); |
| + Bounds popSaveBlock(); |
| + void pushControl(); |
| + void popControl(const Bounds& bounds); |
| + void updateSaveBounds(const Bounds& bounds); |
| + |
| + static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint); |
| + static bool AdjustForPaint(const SkPaint* paint, SkRect* rect); |
| + bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const; |
| + Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const; |
| + |
| + // 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 |