|
1 |
|
2 /* |
|
3 * Copyright 2007 The Android Open Source Project |
|
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 |
|
9 |
|
10 #ifndef SkPicture_DEFINED |
|
11 #define SkPicture_DEFINED |
|
12 |
|
13 #include "SkBitmap.h" |
|
14 #include "SkImageDecoder.h" |
|
15 #include "SkRefCnt.h" |
|
16 |
|
17 class SkBBoxHierarchy; |
|
18 class SkCanvas; |
|
19 class SkDrawPictureCallback; |
|
20 class SkData; |
|
21 class SkPicturePlayback; |
|
22 class SkPictureRecord; |
|
23 class SkStream; |
|
24 class SkWStream; |
|
25 |
|
26 struct SkPictInfo; |
|
27 |
|
28 /** \class SkPicture |
|
29 |
|
30 The SkPicture class records the drawing commands made to a canvas, to |
|
31 be played back at a later time. |
|
32 */ |
|
33 class SK_API SkPicture : public SkRefCnt { |
|
34 public: |
|
35 SK_DECLARE_INST_COUNT(SkPicture) |
|
36 |
|
37 // AccelData provides a base class for device-specific acceleration |
|
38 // data. It is added to the picture via a call to a device's optimize |
|
39 // method. |
|
40 class AccelData : public SkRefCnt { |
|
41 public: |
|
42 typedef uint8_t Domain; |
|
43 typedef uint32_t Key; |
|
44 |
|
45 AccelData(Key key) : fKey(key) { } |
|
46 |
|
47 const Key& getKey() const { return fKey; } |
|
48 |
|
49 // This entry point allows user's to get a unique domain prefix |
|
50 // for their keys |
|
51 static Domain GenerateDomain(); |
|
52 private: |
|
53 Key fKey; |
|
54 |
|
55 typedef SkRefCnt INHERITED; |
|
56 }; |
|
57 |
|
58 /** The constructor prepares the picture to record. |
|
59 @param width the width of the virtual device the picture records. |
|
60 @param height the height of the virtual device the picture records. |
|
61 */ |
|
62 SkPicture(); |
|
63 /** Make a copy of the contents of src. If src records more drawing after |
|
64 this call, those elements will not appear in this picture. |
|
65 */ |
|
66 SkPicture(const SkPicture& src); |
|
67 |
|
68 /** PRIVATE / EXPERIMENTAL -- do not call */ |
|
69 void EXPERIMENTAL_addAccelData(const AccelData* data) { |
|
70 SkRefCnt_SafeAssign(fAccelData, data); |
|
71 } |
|
72 /** PRIVATE / EXPERIMENTAL -- do not call */ |
|
73 const AccelData* EXPERIMENTAL_getAccelData(AccelData::Key key) const { |
|
74 if (NULL != fAccelData && fAccelData->getKey() == key) { |
|
75 return fAccelData; |
|
76 } |
|
77 return NULL; |
|
78 } |
|
79 |
|
80 /** |
|
81 * Function signature defining a function that sets up an SkBitmap from encoded data. On |
|
82 * success, the SkBitmap should have its Config, width, height, rowBytes and pixelref set. |
|
83 * If the installed pixelref has decoded the data into pixels, then the src buffer need not be |
|
84 * copied. If the pixelref defers the actual decode until its lockPixels() is called, then it |
|
85 * must make a copy of the src buffer. |
|
86 * @param src Encoded data. |
|
87 * @param length Size of the encoded data, in bytes. |
|
88 * @param dst SkBitmap to install the pixel ref on. |
|
89 * @param bool Whether or not a pixel ref was successfully installed. |
|
90 */ |
|
91 typedef bool (*InstallPixelRefProc)(const void* src, size_t length, SkBitmap* dst); |
|
92 |
|
93 /** |
|
94 * Recreate a picture that was serialized into a stream. |
|
95 * @param SkStream Serialized picture data. |
|
96 * @param proc Function pointer for installing pixelrefs on SkBitmaps representing the |
|
97 * encoded bitmap data from the stream. |
|
98 * @return A new SkPicture representing the serialized data, or NULL if the stream is |
|
99 * invalid. |
|
100 */ |
|
101 static SkPicture* CreateFromStream(SkStream*, |
|
102 InstallPixelRefProc proc = &SkImageDecoder::DecodeMemory); |
|
103 |
|
104 /** |
|
105 * Recreate a picture that was serialized into a buffer. If the creation requires bitmap |
|
106 * decoding, the decoder must be set on the SkReadBuffer parameter by calling |
|
107 * SkReadBuffer::setBitmapDecoder() before calling SkPicture::CreateFromBuffer(). |
|
108 * @param SkReadBuffer Serialized picture data. |
|
109 * @return A new SkPicture representing the serialized data, or NULL if the buffer is |
|
110 * invalid. |
|
111 */ |
|
112 static SkPicture* CreateFromBuffer(SkReadBuffer&); |
|
113 |
|
114 virtual ~SkPicture(); |
|
115 |
|
116 /** |
|
117 * Swap the contents of the two pictures. Guaranteed to succeed. |
|
118 */ |
|
119 void swap(SkPicture& other); |
|
120 |
|
121 /** |
|
122 * Creates a thread-safe clone of the picture that is ready for playback. |
|
123 */ |
|
124 SkPicture* clone() const; |
|
125 |
|
126 /** |
|
127 * Creates multiple thread-safe clones of this picture that are ready for |
|
128 * playback. The resulting clones are stored in the provided array of |
|
129 * SkPictures. |
|
130 */ |
|
131 void clone(SkPicture* pictures, int count) const; |
|
132 |
|
133 enum RecordingFlags { |
|
134 /* This flag specifies that when clipPath() is called, the path will |
|
135 be faithfully recorded, but the recording canvas' current clip will |
|
136 only see the path's bounds. This speeds up the recording process |
|
137 without compromising the fidelity of the playback. The only side- |
|
138 effect for recording is that calling getTotalClip() or related |
|
139 clip-query calls will reflect the path's bounds, not the actual |
|
140 path. |
|
141 */ |
|
142 kUsePathBoundsForClip_RecordingFlag = 0x01, |
|
143 /* This flag causes the picture to compute bounding boxes and build |
|
144 up a spatial hierarchy (currently an R-Tree), plus a tree of Canvas' |
|
145 usually stack-based clip/etc state. This requires an increase in |
|
146 recording time (often ~2x; likely more for very complex pictures), |
|
147 but allows us to perform much faster culling at playback time, and |
|
148 completely avoid some unnecessary clips and other operations. This |
|
149 is ideal for tiled rendering, or any other situation where you're |
|
150 drawing a fraction of a large scene into a smaller viewport. |
|
151 |
|
152 In most cases the record cost is offset by the playback improvement |
|
153 after a frame or two of tiled rendering (and complex pictures that |
|
154 induce the worst record times will generally get the largest |
|
155 speedups at playback time). |
|
156 |
|
157 Note: Currently this is not serializable, the bounding data will be |
|
158 discarded if you serialize into a stream and then deserialize. |
|
159 */ |
|
160 kOptimizeForClippedPlayback_RecordingFlag = 0x02, |
|
161 }; |
|
162 |
|
163 /** Returns the canvas that records the drawing commands. |
|
164 @param width the base width for the picture, as if the recording |
|
165 canvas' bitmap had this width. |
|
166 @param height the base width for the picture, as if the recording |
|
167 canvas' bitmap had this height. |
|
168 @param recordFlags optional flags that control recording. |
|
169 @return the picture canvas. |
|
170 */ |
|
171 SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0); |
|
172 |
|
173 /** Returns the recording canvas if one is active, or NULL if recording is |
|
174 not active. This does not alter the refcnt on the canvas (if present). |
|
175 */ |
|
176 SkCanvas* getRecordingCanvas() const; |
|
177 /** Signal that the caller is done recording. This invalidates the canvas |
|
178 returned by beginRecording/getRecordingCanvas, and prepares the picture |
|
179 for drawing. Note: this happens implicitly the first time the picture |
|
180 is drawn. |
|
181 */ |
|
182 void endRecording(); |
|
183 |
|
184 /** Replays the drawing commands on the specified canvas. This internally |
|
185 calls endRecording() if that has not already been called. |
|
186 @param canvas the canvas receiving the drawing commands. |
|
187 */ |
|
188 void draw(SkCanvas* canvas, SkDrawPictureCallback* = NULL); |
|
189 |
|
190 /** Return the width of the picture's recording canvas. This |
|
191 value reflects what was passed to setSize(), and does not necessarily |
|
192 reflect the bounds of what has been recorded into the picture. |
|
193 @return the width of the picture's recording canvas |
|
194 */ |
|
195 int width() const { return fWidth; } |
|
196 |
|
197 /** Return the height of the picture's recording canvas. This |
|
198 value reflects what was passed to setSize(), and does not necessarily |
|
199 reflect the bounds of what has been recorded into the picture. |
|
200 @return the height of the picture's recording canvas |
|
201 */ |
|
202 int height() const { return fHeight; } |
|
203 |
|
204 /** |
|
205 * Function to encode an SkBitmap to an SkData. A function with this |
|
206 * signature can be passed to serialize() and SkWriteBuffer. |
|
207 * Returning NULL will tell the SkWriteBuffer to use |
|
208 * SkBitmap::flatten() to store the bitmap. |
|
209 * |
|
210 * @param pixelRefOffset DEPRECATED -- caller assumes it will return 0. |
|
211 * @return SkData If non-NULL, holds encoded data representing the passed |
|
212 * in bitmap. The caller is responsible for calling unref(). |
|
213 */ |
|
214 typedef SkData* (*EncodeBitmap)(size_t* pixelRefOffset, const SkBitmap& bm); |
|
215 |
|
216 /** |
|
217 * Serialize to a stream. If non NULL, encoder will be used to encode |
|
218 * any bitmaps in the picture. |
|
219 * encoder will never be called with a NULL pixelRefOffset. |
|
220 */ |
|
221 void serialize(SkWStream*, EncodeBitmap encoder = NULL) const; |
|
222 |
|
223 /** |
|
224 * Serialize to a buffer. |
|
225 */ |
|
226 void flatten(SkWriteBuffer&) const; |
|
227 |
|
228 /** |
|
229 * Returns true if any bitmaps may be produced when this SkPicture |
|
230 * is replayed. |
|
231 * Returns false if called while still recording. |
|
232 */ |
|
233 bool willPlayBackBitmaps() const; |
|
234 |
|
235 #ifdef SK_BUILD_FOR_ANDROID |
|
236 /** Signals that the caller is prematurely done replaying the drawing |
|
237 commands. This can be called from a canvas virtual while the picture |
|
238 is drawing. Has no effect if the picture is not drawing. |
|
239 @deprecated preserving for legacy purposes |
|
240 */ |
|
241 void abortPlayback(); |
|
242 #endif |
|
243 |
|
244 /** Return true if the SkStream/Buffer represents a serialized picture, and |
|
245 fills out SkPictInfo. After this function returns, the data source is not |
|
246 rewound so it will have to be manually reset before passing to |
|
247 CreateFromStream or CreateFromBuffer. Note, CreateFromStream and |
|
248 CreateFromBuffer perform this check internally so these entry points are |
|
249 intended for stand alone tools. |
|
250 If false is returned, SkPictInfo is unmodified. |
|
251 */ |
|
252 static bool InternalOnly_StreamIsSKP(SkStream*, SkPictInfo*); |
|
253 static bool InternalOnly_BufferIsSKP(SkReadBuffer&, SkPictInfo*); |
|
254 |
|
255 /** Enable/disable all the picture recording optimizations (i.e., |
|
256 those in SkPictureRecord). It is mainly intended for testing the |
|
257 existing optimizations (i.e., to actually have the pattern |
|
258 appear in an .skp we have to disable the optimization). Call right |
|
259 after 'beginRecording'. |
|
260 */ |
|
261 void internalOnly_EnableOpts(bool enableOpts); |
|
262 |
|
263 protected: |
|
264 // V2 : adds SkPixelRef's generation ID. |
|
265 // V3 : PictInfo tag at beginning, and EOF tag at the end |
|
266 // V4 : move SkPictInfo to be the header |
|
267 // V5 : don't read/write FunctionPtr on cross-process (we can detect that) |
|
268 // V6 : added serialization of SkPath's bounds (and packed its flags tighter) |
|
269 // V7 : changed drawBitmapRect(IRect) to drawBitmapRectToRect(Rect) |
|
270 // V8 : Add an option for encoding bitmaps |
|
271 // V9 : Allow the reader and writer of an SKP disagree on whether to support |
|
272 // SK_SUPPORT_HINTING_SCALE_FACTOR |
|
273 // V10: add drawRRect, drawOval, clipRRect |
|
274 // V11: modify how readBitmap and writeBitmap store their info. |
|
275 // V12: add conics to SkPath, use new SkPathRef flattening |
|
276 // V13: add flag to drawBitmapRectToRect |
|
277 // parameterize blurs by sigma rather than radius |
|
278 // V14: Add flags word to PathRef serialization |
|
279 // V15: Remove A1 bitmpa config (and renumber remaining configs) |
|
280 // V16: Move SkPath's isOval flag to SkPathRef |
|
281 // V17: SkPixelRef now writes SkImageInfo |
|
282 // V18: SkBitmap now records x,y for its pixelref origin, instead of offset. |
|
283 // V19: encode matrices and regions into the ops stream |
|
284 // V20: added bool to SkPictureImageFilter's serialization (to allow SkPicture serialization) |
|
285 // V21: add pushCull, popCull |
|
286 // V22: SK_PICT_FACTORY_TAG's size is now the chunk size in bytes |
|
287 |
|
288 // Note: If the picture version needs to be increased then please follow the |
|
289 // steps to generate new SKPs in (only accessible to Googlers): http://goo.gl/qATVcw |
|
290 |
|
291 // Only SKPs within the min/current picture version range (inclusive) can be read. |
|
292 static const uint32_t MIN_PICTURE_VERSION = 19; |
|
293 static const uint32_t CURRENT_PICTURE_VERSION = 22; |
|
294 |
|
295 // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to |
|
296 // install their own SkPicturePlayback-derived players,SkPictureRecord-derived |
|
297 // recorders and set the picture size |
|
298 SkPicturePlayback* fPlayback; |
|
299 SkPictureRecord* fRecord; |
|
300 int fWidth, fHeight; |
|
301 const AccelData* fAccelData; |
|
302 |
|
303 // Create a new SkPicture from an existing SkPicturePlayback. Ref count of |
|
304 // playback is unchanged. |
|
305 SkPicture(SkPicturePlayback*, int width, int height); |
|
306 |
|
307 // For testing. Derived classes may instantiate an alternate |
|
308 // SkBBoxHierarchy implementation |
|
309 virtual SkBBoxHierarchy* createBBoxHierarchy() const; |
|
310 private: |
|
311 void createHeader(SkPictInfo* info) const; |
|
312 static bool IsValidPictInfo(const SkPictInfo& info); |
|
313 |
|
314 friend class SkFlatPicture; |
|
315 friend class SkPicturePlayback; |
|
316 |
|
317 typedef SkRefCnt INHERITED; |
|
318 }; |
|
319 |
|
320 /** |
|
321 * Subclasses of this can be passed to canvas.drawPicture. During the drawing |
|
322 * of the picture, this callback will periodically be invoked. If its |
|
323 * abortDrawing() returns true, then picture playback will be interrupted. |
|
324 * |
|
325 * The resulting drawing is undefined, as there is no guarantee how often the |
|
326 * callback will be invoked. If the abort happens inside some level of nested |
|
327 * calls to save(), restore will automatically be called to return the state |
|
328 * to the same level it was before the drawPicture call was made. |
|
329 */ |
|
330 class SK_API SkDrawPictureCallback { |
|
331 public: |
|
332 SkDrawPictureCallback() {} |
|
333 virtual ~SkDrawPictureCallback() {} |
|
334 |
|
335 virtual bool abortDrawing() = 0; |
|
336 }; |
|
337 |
|
338 #endif |