Index: src/core/SkPictureRecord.h |
=================================================================== |
--- src/core/SkPictureRecord.h (revision 13263) |
+++ src/core/SkPictureRecord.h (working copy) |
@@ -16,6 +16,291 @@ |
#include "SkTemplates.h" |
#include "SkWriter32.h" |
+#define COLLAPSE_MATRIX_CLIP_STATE 1 |
+ |
+#ifdef COLLAPSE_MATRIX_CLIP_STATE |
+#include "SkTypes.h" |
+ |
+class MatrixClipState { |
+public: |
+ class MatrixInfo { |
+ public: |
+ SkMatrix fMatrix; |
+ // TODO: add an internal dictionary and an ID here |
+ }; |
+ |
+ class ClipInfo : public SkNoncopyable { |
+ public: |
+ ClipInfo() {} |
+ |
+ bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAA, const SkMatrix& matrix) { |
+ ClipOp* newClip = fClips.append(); |
+ newClip->fClipType = kRect_ClipType; |
+ newClip->fGeom.fRRect.setRect(rect); // store the clipRect in the RRect |
+ newClip->fOp = op; |
+ newClip->fDoAA = doAA; |
+ newClip->fMatrix = matrix; |
+ newClip->fOffset = kInvalidJumpOffset; |
+ return false; |
+ } |
+ |
+ bool clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA, const SkMatrix& matrix) { |
+ ClipOp* newClip = fClips.append(); |
+ newClip->fClipType = kRRect_ClipType; |
+ newClip->fGeom.fRRect = rrect; |
+ newClip->fOp = op; |
+ newClip->fDoAA = doAA; |
+ newClip->fMatrix = matrix; |
+ newClip->fOffset = kInvalidJumpOffset; |
+ return false; |
+ } |
+ |
+ bool clipPath(SkPictureRecord* picRecord, |
+ const SkPath& path, |
+ SkRegion::Op op, |
+ bool doAA, |
+ const SkMatrix& matrix); |
+ bool clipRegion(SkPictureRecord* picRecord, |
+ const SkRegion& region, |
+ SkRegion::Op op, |
+ const SkMatrix& matrix); |
+ void writeClip(SkMatrix* curMat, SkPictureRecord* picRecord, |
+ bool* overrideFirstOp); |
+ void fillInSkips(SkWriter32* writer, int32_t restoreOffset); |
+ |
+ private: |
+ enum ClipType { |
+ kRect_ClipType, |
+ kRRect_ClipType, |
+ kPath_ClipType, |
+ kRegion_ClipType |
+ }; |
+ |
+ static const int kInvalidJumpOffset = -1; |
+ |
+ struct ClipOp { |
+ ClipType fClipType; |
+ |
+ union { |
+ SkRRect fRRect; // also stores clipRect |
+ int fPathID; |
+ // TODO: add internal dictionary of regions |
+ // Arrg - need to free this in dtor!!! |
+ const SkRegion* fRegion; |
+ } fGeom; |
+ |
+ bool fDoAA; |
+ SkRegion::Op fOp; |
+ |
+ // This used to be and int (when matrices were in a dictionary) |
+ // now it is a full matrix. |
+ // The CTM in effect when this clip call was issued |
+ SkMatrix fMatrix; |
+ |
+ // The offset of this clipOp's "jump-to-offset" variable in the skp. |
+ // -1 means the offset hasn't been written. |
+ int32_t fOffset; |
+ }; |
+ |
+ SkTDArray<ClipOp> fClips; |
+ |
+ typedef SkNoncopyable INHERITED; |
+ }; |
+ |
+ MatrixClipState(MatrixClipState *prev, int flags) { |
+ if (NULL == prev) { |
+ fLayerID = 0; |
+ |
+ fMatrixInfoStorage.fMatrix.reset(); |
+ fMatrixInfo = &fMatrixInfoStorage; |
+ fClipInfo = &fClipInfoStorage; |
+ |
+ fIsCurrent = true; |
+ } |
+ else { |
+ fLayerID = prev->fLayerID; |
+ |
+ if (flags & SkCanvas::kMatrix_SaveFlag) { |
+ fMatrixInfoStorage = *prev->fMatrixInfo; |
+ fMatrixInfo = &fMatrixInfoStorage; |
+ } else { |
+ fMatrixInfo = prev->fMatrixInfo; |
+ } |
+ |
+ if (flags & SkCanvas::kClip_SaveFlag) { |
+ // We don't copy the ClipOps of the previous clip states |
+ fClipInfo = &fClipInfoStorage; |
+ } else { |
+ fClipInfo = prev->fClipInfo; |
+ } |
+ |
+ fIsCurrent = prev->fIsCurrent; |
+ } |
+ |
+ fWroteSave = false; |
+ fIsSaveLayer = false; |
+ } |
+ |
+ MatrixInfo* fMatrixInfo; |
+ MatrixInfo fMatrixInfoStorage; |
+ |
+ ClipInfo* fClipInfo; |
+ ClipInfo fClipInfoStorage; |
+ |
+ int fLayerID; |
+ // Does this MC state represent a saveLayer call? |
+ bool fIsSaveLayer; |
+ // Is this the current MC state in the picture command stream? |
+ bool fIsCurrent; |
+ // Is there an unbalanced 'save' for this MC state already in the command stream? |
+ bool fWroteSave; |
+}; |
+ |
+ |
+class MatrixClipStateMgr { |
+public: |
+ enum CallType { |
+ kMatrix_CallType, |
+ kClip_CallType, |
+ kOther_CallType |
+ }; |
+ |
+ MatrixClipStateMgr(); |
+ |
+ void init(SkPictureRecord* picRecord) { |
+ fPicRecord = picRecord; |
+ } |
+ |
+ // TODO: need to override canvas' getSaveCount |
+ int getSaveCount() const { return fMatrixClipStack.count(); } |
+ |
+ int save(SkCanvas::SaveFlags flags) { |
+ MatrixClipState* newTop = (MatrixClipState*)fMatrixClipStack.push_back(); |
+ new (newTop) MatrixClipState(fCurMCState, flags); // balanced in restore() |
+ fCurMCState = newTop; |
+ return fMatrixClipStack.count(); |
+ } |
+ |
+ int saveLayer(const SkRect* bounds, const SkPaint* paint, |
+ SkCanvas::SaveFlags flags) { |
+ int result = this->save(flags); |
+ ++fCurMCState->fLayerID; |
+ fCurMCState->fIsSaveLayer = true; |
+ return result; |
+ } |
+ |
+ bool isDrawingToLayer() const { |
+ return fCurMCState->fLayerID > 0; |
+ } |
+ |
+ void restore(); |
+ |
+ bool translate(SkScalar dx, SkScalar dy) { |
+ this->call(kMatrix_CallType); |
+ bool result = fCurMCState->fMatrixInfo->fMatrix.preTranslate(dx, dy); |
+// fCurMCState->fMatrixInfo->fID = -1; |
+ fCurMCState->fIsCurrent = false; |
+ return result; |
+ } |
+ |
+ bool scale(SkScalar sx, SkScalar sy) { |
+ this->call(kMatrix_CallType); |
+ bool result = fCurMCState->fMatrixInfo->fMatrix.preScale(sx, sy); |
+// fCurMCState->fMatrixInfo->fID = -1; |
+ fCurMCState->fIsCurrent = false; |
+ return result; |
+ } |
+ |
+ bool rotate(SkScalar degrees) { |
+ this->call(kMatrix_CallType); |
+ bool result = fCurMCState->fMatrixInfo->fMatrix.preRotate(degrees); |
+// fCurMCState->fMatrixInfo->fID = -1; |
+ fCurMCState->fIsCurrent = false; |
+ return result; |
+ } |
+ |
+ bool skew(SkScalar sx, SkScalar sy) { |
+ this->call(kMatrix_CallType); |
+ bool result = fCurMCState->fMatrixInfo->fMatrix.preSkew(sx, sy); |
+// fCurMCState->fMatrixInfo->fID = -1; |
+ fCurMCState->fIsCurrent = false; |
+ return result; |
+ } |
+ |
+ bool concat(const SkMatrix& matrix) { |
+ this->call(kMatrix_CallType); |
+ bool result = fCurMCState->fMatrixInfo->fMatrix.preConcat(matrix); |
+// fCurMCState->fMatrixInfo->fID = -1; |
+ fCurMCState->fIsCurrent = false; |
+ return result; |
+ } |
+ |
+ void setMatrix(const SkMatrix& matrix) { |
+ this->call(kMatrix_CallType); |
+ fCurMCState->fMatrixInfo->fMatrix = matrix; |
+// fCurMCState->fMatrixInfo->fID = -1; |
+ fCurMCState->fIsCurrent = false; |
+ } |
+ |
+ bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { |
+ this->call(MatrixClipStateMgr::kClip_CallType); |
+ |
+ fCurMCState->fIsCurrent = false; |
+ return fCurMCState->fClipInfo->clipRect(rect, op, doAA, |
+ fCurMCState->fMatrixInfo->fMatrix); |
+ } |
+ |
+ bool clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { |
+ this->call(MatrixClipStateMgr::kClip_CallType); |
+ |
+ fCurMCState->fIsCurrent = false; |
+ return fCurMCState->fClipInfo->clipRRect(rrect, op, doAA, |
+ fCurMCState->fMatrixInfo->fMatrix); |
+ } |
+ |
+ bool clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
+ this->call(MatrixClipStateMgr::kClip_CallType); |
+ |
+ fCurMCState->fIsCurrent = false; |
+ bool result = fCurMCState->fClipInfo->clipPath(fPicRecord, path, op, doAA, |
+ fCurMCState->fMatrixInfo->fMatrix); |
+ return result; |
+ } |
+ |
+ bool clipRegion(const SkRegion& region, SkRegion::Op op) { |
+ this->call(MatrixClipStateMgr::kClip_CallType); |
+ |
+ fCurMCState->fIsCurrent = false; |
+ bool result = fCurMCState->fClipInfo->clipRegion(fPicRecord, region, op, |
+ fCurMCState->fMatrixInfo->fMatrix); |
+ return result; |
+ } |
+ |
+ void call(CallType callType); |
+ |
+ void fillInSkips(SkWriter32* writer, int32_t restoreOffset) { |
+ fCurMCState->fClipInfo->fillInSkips(writer, restoreOffset); |
+ } |
+ |
+ void finish1() { |
+#if 0 |
+ if (fCurMCState->fWroteSave) { |
+ fCurMCState->fWroteSave = false; |
+ fPicRecord->restoreImpl(); |
+ } |
+#endif |
+ } |
+ |
+protected: |
+ SkPictureRecord* fPicRecord; |
+ |
+ uint32_t fMatrixClipStackStorage[43]; // sized to fit 2 clip states |
+ SkDeque fMatrixClipStack; |
+ MatrixClipState* fCurMCState; |
+}; |
+#endif |
+ |
+ |
class SkPictureStateTree; |
class SkBBoxHierarchy; |
@@ -108,15 +393,16 @@ |
private: |
void handleOptimization(int opt); |
- void recordRestoreOffsetPlaceholder(SkRegion::Op); |
- void fillRestoreOffsetPlaceholdersForCurrentStackLevel( |
- uint32_t restoreOffset); |
+ int recordRestoreOffsetPlaceholder(SkRegion::Op); |
+ void fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset); |
+#ifndef COLLAPSE_MATRIX_CLIP_STATE |
SkTDArray<int32_t> fRestoreOffsetStack; |
int fFirstSavedLayerIndex; |
enum { |
kNoSavedLayerIndex = -1 |
}; |
+#endif |
/* |
* Write the 'drawType' operation and chunk size to the skp. 'size' |
@@ -161,10 +447,12 @@ |
} |
void addBitmap(const SkBitmap& bitmap); |
+ int addMatrixToHeap(const SkMatrix& matrix); |
void addMatrix(const SkMatrix& matrix); |
const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); } |
const SkFlatData* addPaintPtr(const SkPaint* paint); |
void addFlatPaint(const SkFlatData* flatPaint); |
+ int addPathToHeap(const SkPath& path); |
void addPath(const SkPath& path); |
void addPicture(SkPicture& picture); |
void addPoint(const SkPoint& point); |
@@ -174,6 +462,7 @@ |
void addIRect(const SkIRect& rect); |
void addIRectPtr(const SkIRect* rect); |
void addRRect(const SkRRect&); |
+ int addRegionToHeap(const SkRegion& region); |
void addRegion(const SkRegion& region); |
void addText(const void* text, size_t byteLength); |
@@ -237,6 +526,15 @@ |
const SkScalar xpos[], SkScalar constY, |
const SkPaint& paint, const SkFlatData* flatPaintData); |
+ void concatImpl(const SkMatrix& matrix); |
+ void setMatrixImpl(const SkMatrix& matrix); |
+ int clipRectImpl(const SkRect& rect, SkRegion::Op op, bool doAA); |
+ int clipRRectImpl(const SkRRect& rrect, SkRegion::Op op, bool doAA); |
+ int clipPathImpl(int pathID, SkRegion::Op op, bool doAA); |
+ int clipRegionImpl(const SkRegion& region, SkRegion::Op op); |
+ void saveImpl(SaveFlags flags); |
+ void restoreImpl(); |
+ |
// These are set to NULL in our constructor, but may be changed by |
// subclasses, in which case they will be SkSafeUnref'd in our destructor. |
SkBBoxHierarchy* fBoundingHierarchy; |
@@ -246,6 +544,11 @@ |
SkBitmapHeap* fBitmapHeap; |
private: |
+#ifdef COLLAPSE_MATRIX_CLIP_STATE |
+ friend class MatrixClipState; // for access to *Impl methods |
+ friend class MatrixClipStateMgr; // for access to *Impl methods |
+#endif |
+ |
SkChunkFlatController fFlattenableHeap; |
SkPaintDictionary fPaints; |
@@ -262,6 +565,10 @@ |
friend class SkPicturePlayback; |
friend class SkPictureTester; // for unit testing |
+#ifdef COLLAPSE_MATRIX_CLIP_STATE |
+ MatrixClipStateMgr fMCMgr; |
+#endif |
+ |
typedef SkCanvas INHERITED; |
}; |