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