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