| 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;
|
| };
|
|
|
|
|