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