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