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