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 "include/core/SkCanvas.h"
12#include "include/core/SkCanvasVirtualEnforcer.h"
13#include "include/core/SkFlattenable.h"
14#include "include/core/SkPicture.h"
15#include "include/core/SkVertices.h"
16#include "include/private/SkTArray.h"
17#include "include/private/SkTDArray.h"
18#include "include/private/SkTHash.h"
19#include "include/private/SkTo.h"
20#include "src/core/SkPictureData.h"
21#include "src/core/SkWriter32.h"
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
32class SkPictureRecord : public SkCanvasVirtualEnforcer<SkCanvas> {
33public:
34 SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags);
35
36 SkPictureRecord(const SkIRect& dimensions, uint32_t recordFlags);
37
38 const SkTArray<sk_sp<const SkPicture>>& getPictures() const {
39 return fPictures;
40 }
41
42 const SkTArray<sk_sp<SkDrawable>>& getDrawables() const {
43 return fDrawables;
44 }
45
46 const SkTArray<sk_sp<const SkTextBlob>>& getTextBlobs() const {
47 return fTextBlobs;
48 }
49
50 const SkTArray<sk_sp<const SkVertices>>& getVertices() const {
51 return fVertices;
52 }
53
54 const SkTArray<sk_sp<const SkImage>>& getImages() const {
55 return fImages;
56 }
57
58 sk_sp<SkData> opData() const {
59 this->validate(fWriter.bytesWritten(), 0);
60
61 if (fWriter.bytesWritten() == 0) {
62 return SkData::MakeEmpty();
63 }
64 return fWriter.snapshotAsData();
65 }
66
67 void setFlags(uint32_t recordFlags) {
68 fRecordFlags = recordFlags;
69 }
70
71 const SkWriter32& writeStream() const {
72 return fWriter;
73 }
74
75 void beginRecording();
76 void endRecording();
77
78protected:
79 void addNoOp();
80
81private:
82 void handleOptimization(int opt);
83 size_t recordRestoreOffsetPlaceholder(SkClipOp);
84 void fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset);
85
86 SkTDArray<int32_t> fRestoreOffsetStack;
87
88 SkTDArray<uint32_t> fCullOffsetStack;
89
90 /*
91 * Write the 'drawType' operation and chunk size to the skp. 'size'
92 * can potentially be increased if the chunk size needs its own storage
93 * location (i.e., it overflows 24 bits).
94 * Returns the start offset of the chunk. This is the location at which
95 * the opcode & size are stored.
96 * TODO: since we are handing the size into here we could call reserve
97 * and then return a pointer to the memory storage. This could decrease
98 * allocation overhead but could lead to more wasted space (the tail
99 * end of blocks could go unused). Possibly add a second addDraw that
100 * operates in this manner.
101 */
102 size_t addDraw(DrawType drawType, size_t* size) {
103 size_t offset = fWriter.bytesWritten();
104
105 this->predrawNotify();
106
107 SkASSERT(0 != *size);
108 SkASSERT(((uint8_t) drawType) == drawType);
109
110 if (0 != (*size & ~MASK_24) || *size == MASK_24) {
111 fWriter.writeInt(PACK_8_24(drawType, MASK_24));
112 *size += 1;
113 fWriter.writeInt(SkToU32(*size));
114 } else {
115 fWriter.writeInt(PACK_8_24(drawType, SkToU32(*size)));
116 }
117
118 return offset;
119 }
120
121 void addInt(int value) {
122 fWriter.writeInt(value);
123 }
124 void addScalar(SkScalar scalar) {
125 fWriter.writeScalar(scalar);
126 }
127
128 void addImage(const SkImage*);
129 void addMatrix(const SkMatrix& matrix);
130 void addPaint(const SkPaint& paint) { this->addPaintPtr(&paint); }
131 void addPaintPtr(const SkPaint* paint);
132 void addPatch(const SkPoint cubics[12]);
133 void addPath(const SkPath& path);
134 void addPicture(const SkPicture* picture);
135 void addDrawable(SkDrawable* picture);
136 void addPoint(const SkPoint& point);
137 void addPoints(const SkPoint pts[], int count);
138 void addRect(const SkRect& rect);
139 void addRectPtr(const SkRect* rect);
140 void addIRect(const SkIRect& rect);
141 void addIRectPtr(const SkIRect* rect);
142 void addRRect(const SkRRect&);
143 void addRegion(const SkRegion& region);
144 void addText(const void* text, size_t byteLength);
145 void addTextBlob(const SkTextBlob* blob);
146 void addVertices(const SkVertices*);
147
148 int find(const SkBitmap& bitmap);
149
150protected:
151 void validate(size_t initialOffset, size_t size) const {
152 SkASSERT(fWriter.bytesWritten() == initialOffset + size);
153 }
154
155 sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;
156 bool onPeekPixels(SkPixmap*) override { return false; }
157
158 void onFlush() override;
159
160 void willSave() override;
161 SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
162 bool onDoSaveBehind(const SkRect*) override;
163 void willRestore() override;
164
165 void onMarkCTM(MarkerID) override;
166#ifdef SK_SUPPORT_LEGACY_DIDCONCAT44
167 void didConcat44(const SkScalar[16]) override;
168#else
169 void didConcat44(const SkM44&) override;
170#endif
171 void didConcat(const SkMatrix&) override;
172 void didSetMatrix(const SkMatrix&) override;
173 void didScale(SkScalar, SkScalar) override;
174 void didTranslate(SkScalar, SkScalar) override;
175
176 void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
177
178 void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
179 const SkPaint& paint) override;
180
181 void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
182 const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint) override;
183 void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
184 SkBlendMode, const SkRect*, const SkPaint*) override;
185
186 void onDrawPaint(const SkPaint&) override;
187 void onDrawBehind(const SkPaint&) override;
188 void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
189 void onDrawRect(const SkRect&, const SkPaint&) override;
190 void onDrawRegion(const SkRegion&, const SkPaint&) override;
191 void onDrawOval(const SkRect&, const SkPaint&) override;
192 void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
193 void onDrawRRect(const SkRRect&, const SkPaint&) override;
194 void onDrawPath(const SkPath&, const SkPaint&) override;
195 void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
196 void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
197 const SkPaint*, SrcRectConstraint) override;
198 void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
199 const SkPaint*) override;
200 void onDrawImageLattice(const SkImage*, const SkCanvas::Lattice& lattice, const SkRect& dst,
201 const SkPaint*) override;
202
203 void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
204 void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
205
206 void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
207 void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
208 void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
209 void onClipShader(sk_sp<SkShader>, SkClipOp) override;
210 void onClipRegion(const SkRegion&, SkClipOp) override;
211
212 void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
213
214 void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
215 void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
216
217 void onDrawEdgeAAQuad(const SkRect&, const SkPoint[4], QuadAAFlags, const SkColor4f&,
218 SkBlendMode) override;
219 void onDrawEdgeAAImageSet(const ImageSetEntry[], int count, const SkPoint[], const SkMatrix[],
220 const SkPaint*, SrcRectConstraint) override;
221
222 int addPathToHeap(const SkPath& path); // does not write to ops stream
223
224 // These entry points allow the writing of matrices, clips, saves &
225 // restores to be deferred (e.g., if the MC state is being collapsed and
226 // only written out as needed).
227 void recordConcat(const SkMatrix& matrix);
228 void recordTranslate(const SkMatrix& matrix);
229 void recordScale(const SkMatrix& matrix);
230 size_t recordClipRect(const SkRect& rect, SkClipOp op, bool doAA);
231 size_t recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA);
232 size_t recordClipPath(int pathID, SkClipOp op, bool doAA);
233 size_t recordClipRegion(const SkRegion& region, SkClipOp op);
234 void recordSave();
235 void recordSaveLayer(const SaveLayerRec&);
236 void recordRestore(bool fillInSkips = true);
237
238private:
239 SkTArray<SkPaint> fPaints;
240
241 struct PathHash {
242 uint32_t operator()(const SkPath& p) { return p.getGenerationID(); }
243 };
244 SkTHashMap<SkPath, int, PathHash> fPaths;
245
246 SkWriter32 fWriter;
247
248 SkTArray<sk_sp<const SkImage>> fImages;
249 SkTArray<sk_sp<const SkPicture>> fPictures;
250 SkTArray<sk_sp<SkDrawable>> fDrawables;
251 SkTArray<sk_sp<const SkTextBlob>> fTextBlobs;
252 SkTArray<sk_sp<const SkVertices>> fVertices;
253
254 uint32_t fRecordFlags;
255 int fInitialSaveCount;
256
257 friend class SkPictureData; // for SkPictureData's SkPictureRecord-based constructor
258
259 typedef SkCanvasVirtualEnforcer<SkCanvas> INHERITED;
260};
261
262#endif
263