SkPictureRecord.h revision d9ea09e1f29b303e6fa36079e99729d2951925b9
1/* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#ifndef SkPictureRecord_DEFINED 9#define SkPictureRecord_DEFINED 10 11#include "SkCanvas.h" 12#include "SkFlattenable.h" 13#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE 14#include "SkMatrixClipStateMgr.h" 15#endif 16#include "SkPathHeap.h" 17#include "SkPicture.h" 18#include "SkPictureFlat.h" 19#include "SkTemplates.h" 20#include "SkWriter32.h" 21 22class SkBBoxHierarchy; 23class SkOffsetTable; 24class SkPictureStateTree; 25 26// These macros help with packing and unpacking a single byte value and 27// a 3 byte value into/out of a uint32_t 28#define MASK_24 0x00FFFFFF 29#define UNPACK_8_24(combined, small, large) \ 30 small = (combined >> 24) & 0xFF; \ 31 large = combined & MASK_24; 32#define PACK_8_24(small, large) ((small << 24) | large) 33 34 35class SkPictureRecord : public SkCanvas { 36public: 37 SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags); 38 virtual ~SkPictureRecord(); 39 40 virtual void clear(SkColor) SK_OVERRIDE; 41 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE; 42 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[], 43 const SkPaint&) SK_OVERRIDE; 44 virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE; 45 virtual void drawRect(const SkRect&, const SkPaint&) SK_OVERRIDE; 46 virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE; 47 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE; 48 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, 49 const SkPaint*) SK_OVERRIDE; 50 virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, 51 const SkRect& dst, const SkPaint* paint, 52 DrawBitmapRectFlags flags) SK_OVERRIDE; 53 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, 54 const SkPaint*) SK_OVERRIDE; 55 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 56 const SkRect& dst, const SkPaint*) SK_OVERRIDE; 57 virtual void drawSprite(const SkBitmap&, int left, int top, 58 const SkPaint*) SK_OVERRIDE; 59 virtual void drawText(const void* text, size_t byteLength, SkScalar x, 60 SkScalar y, const SkPaint&) SK_OVERRIDE; 61 virtual void drawPosText(const void* text, size_t byteLength, 62 const SkPoint pos[], const SkPaint&) SK_OVERRIDE; 63 virtual void drawPosTextH(const void* text, size_t byteLength, 64 const SkScalar xpos[], SkScalar constY, const SkPaint&) SK_OVERRIDE; 65 virtual void drawTextOnPath(const void* text, size_t byteLength, 66 const SkPath& path, const SkMatrix* matrix, 67 const SkPaint&) SK_OVERRIDE; 68 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE; 69 virtual void drawVertices(VertexMode, int vertexCount, 70 const SkPoint vertices[], const SkPoint texs[], 71 const SkColor colors[], SkXfermode*, 72 const uint16_t indices[], int indexCount, 73 const SkPaint&) SK_OVERRIDE; 74 virtual void drawData(const void*, size_t) SK_OVERRIDE; 75 virtual void beginCommentGroup(const char* description) SK_OVERRIDE; 76 virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE; 77 virtual void endCommentGroup() SK_OVERRIDE; 78 virtual bool isDrawingToLayer() const SK_OVERRIDE; 79 80 void addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData&, 81 SkScalar minY, SkScalar maxY); 82 83 const SkTDArray<SkPicture* >& getPictureRefs() const { 84 return fPictureRefs; 85 } 86 87 void setFlags(uint32_t recordFlags) { 88 fRecordFlags = recordFlags; 89 } 90 91 const SkWriter32& writeStream() const { 92 return fWriter; 93 } 94 95 void beginRecording(); 96 void endRecording(); 97 98 void internalOnly_EnableOpts(bool optsEnabled) { 99 fOptsEnabled = optsEnabled; 100 } 101 102private: 103 void handleOptimization(int opt); 104 int recordRestoreOffsetPlaceholder(SkRegion::Op); 105 void fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset); 106 107#ifndef SK_COLLAPSE_MATRIX_CLIP_STATE 108 SkTDArray<int32_t> fRestoreOffsetStack; 109 int fFirstSavedLayerIndex; 110 enum { 111 kNoSavedLayerIndex = -1 112 }; 113#endif 114 115 SkTDArray<uint32_t> fCullOffsetStack; 116 117 /* 118 * Write the 'drawType' operation and chunk size to the skp. 'size' 119 * can potentially be increased if the chunk size needs its own storage 120 * location (i.e., it overflows 24 bits). 121 * Returns the start offset of the chunk. This is the location at which 122 * the opcode & size are stored. 123 * TODO: since we are handing the size into here we could call reserve 124 * and then return a pointer to the memory storage. This could decrease 125 * allocation overhead but could lead to more wasted space (the tail 126 * end of blocks could go unused). Possibly add a second addDraw that 127 * operates in this manner. 128 */ 129 size_t addDraw(DrawType drawType, uint32_t* size) { 130 size_t offset = fWriter.bytesWritten(); 131 132 this->predrawNotify(); 133 134 #ifdef SK_DEBUG_TRACE 135 SkDebugf("add %s\n", DrawTypeToString(drawType)); 136 #endif 137 138 SkASSERT(0 != *size); 139 SkASSERT(((uint8_t) drawType) == drawType); 140 141 if (0 != (*size & ~MASK_24) || *size == MASK_24) { 142 fWriter.writeInt(PACK_8_24(drawType, MASK_24)); 143 *size += 1; 144 fWriter.writeInt(*size); 145 } else { 146 fWriter.writeInt(PACK_8_24(drawType, *size)); 147 } 148 149 return offset; 150 } 151 152 void addInt(int value) { 153 fWriter.writeInt(value); 154 } 155 void addScalar(SkScalar scalar) { 156 fWriter.writeScalar(scalar); 157 } 158 159 // The command at 'offset' in the skp uses the specified bitmap 160 void trackBitmapUse(int bitmapID, size_t offset); 161 int addBitmap(const SkBitmap& bitmap); 162 void addMatrix(const SkMatrix& matrix); 163 const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); } 164 const SkFlatData* addPaintPtr(const SkPaint* paint); 165 void addFlatPaint(const SkFlatData* flatPaint); 166 void addPath(const SkPath& path); 167 void addPicture(SkPicture& picture); 168 void addPoint(const SkPoint& point); 169 void addPoints(const SkPoint pts[], int count); 170 void addRect(const SkRect& rect); 171 void addRectPtr(const SkRect* rect); 172 void addIRect(const SkIRect& rect); 173 void addIRectPtr(const SkIRect* rect); 174 void addRRect(const SkRRect&); 175 void addRegion(const SkRegion& region); 176 void addText(const void* text, size_t byteLength); 177 178 int find(const SkBitmap& bitmap); 179 180#ifdef SK_DEBUG_DUMP 181public: 182 void dumpMatrices(); 183 void dumpPaints(); 184#endif 185 186#ifdef SK_DEBUG_SIZE 187public: 188 size_t size() const; 189 int bitmaps(size_t* size) const; 190 int matrices(size_t* size) const; 191 int paints(size_t* size) const; 192 int paths(size_t* size) const; 193 int regions(size_t* size) const; 194 size_t streamlen() const; 195 196 size_t fPointBytes, fRectBytes, fTextBytes; 197 int fPointWrites, fRectWrites, fTextWrites; 198#endif 199 200#ifdef SK_DEBUG_VALIDATE 201public: 202 void validate(size_t initialOffset, uint32_t size) const; 203private: 204 void validateBitmaps() const; 205 void validateMatrices() const; 206 void validatePaints() const; 207 void validatePaths() const; 208 void validateRegions() const; 209#else 210public: 211 void validate(size_t initialOffset, uint32_t size) const { 212 SkASSERT(fWriter.bytesWritten() == initialOffset + size); 213 } 214#endif 215 216protected: 217 virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE; 218 const void* onPeekPixels(SkImageInfo*, size_t*) SK_OVERRIDE { 219 return NULL; 220 } 221 222 virtual void willSave(SaveFlags) SK_OVERRIDE; 223 virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE; 224 virtual void willRestore() SK_OVERRIDE; 225 226 virtual void didConcat(const SkMatrix&) SK_OVERRIDE; 227 virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE; 228 229 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE; 230 virtual void onPushCull(const SkRect&) SK_OVERRIDE; 231 virtual void onPopCull() SK_OVERRIDE; 232 233 virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 234 virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 235 virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 236 virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE; 237 238 // Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been 239 // tweaked by paint.computeFastBounds(). 240 static void ComputeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]); 241 242 // Make sure that flat has fTopBot written. 243 static void WriteTopBot(const SkPaint& paint, const SkFlatData& flat) { 244 if (!flat.isTopBotWritten()) { 245 ComputeFontMetricsTopBottom(paint, flat.writableTopBot()); 246 SkASSERT(flat.isTopBotWritten()); 247 } 248 } 249 // Will return a cached version when possible. 250 const SkFlatData* getFlatPaintData(const SkPaint& paint); 251 /** 252 * SkBBoxRecord::drawPosTextH gets a flat paint and uses it, 253 * then it calls this, using the extra parameter, to avoid duplication. 254 */ 255 void drawPosTextHImpl(const void* text, size_t byteLength, 256 const SkScalar xpos[], SkScalar constY, 257 const SkPaint& paint, const SkFlatData* flatPaintData); 258 259 int addPathToHeap(const SkPath& path); // does not write to ops stream 260 261 // These entry points allow the writing of matrices, clips, saves & 262 // restores to be deferred (e.g., if the MC state is being collapsed and 263 // only written out as needed). 264 void recordConcat(const SkMatrix& matrix); 265 void recordTranslate(const SkMatrix& matrix); 266 void recordScale(const SkMatrix& matrix); 267 int recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA); 268 int recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA); 269 int recordClipPath(int pathID, SkRegion::Op op, bool doAA); 270 int recordClipRegion(const SkRegion& region, SkRegion::Op op); 271 void recordSave(SaveFlags flags); 272 void recordSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags); 273 void recordRestore(bool fillInSkips = true); 274 275 // These are set to NULL in our constructor, but may be changed by 276 // subclasses, in which case they will be SkSafeUnref'd in our destructor. 277 SkBBoxHierarchy* fBoundingHierarchy; 278 SkPictureStateTree* fStateTree; 279 280 // Allocated in the constructor and managed by this class. 281 SkBitmapHeap* fBitmapHeap; 282 283private: 284 friend class MatrixClipState; // for access to *Impl methods 285 friend class SkMatrixClipStateMgr; // for access to *Impl methods 286 287 SkChunkFlatController fFlattenableHeap; 288 289 SkPaintDictionary fPaints; 290 291 SkPathHeap* fPathHeap; // reference counted 292 SkWriter32 fWriter; 293 294 // we ref each item in these arrays 295 SkTDArray<SkPicture*> fPictureRefs; 296 297 uint32_t fRecordFlags; 298 bool fOptsEnabled; 299 int fInitialSaveCount; 300 301 SkAutoTUnref<SkOffsetTable> fBitmapUseOffsets; 302 303 friend class SkPicturePlayback; 304 friend class SkPictureTester; // for unit testing 305 306#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE 307 SkMatrixClipStateMgr fMCMgr; 308#endif 309 310 typedef SkCanvas INHERITED; 311}; 312 313#endif 314