SkPicture.h revision 4ed0fb768409bf97b79899c3990d8c15f5e9d784
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 "SkRefCnt.h"
14#include "SkSerializationHelpers.h"
15
16class SkBBoxHierarchy;
17class SkBitmap;
18class SkCanvas;
19class SkPicturePlayback;
20class SkPictureRecord;
21class SkStream;
22class SkWStream;
23
24/** \class SkPicture
25
26    The SkPicture class records the drawing commands made to a canvas, to
27    be played back at a later time.
28*/
29class SK_API SkPicture : public SkRefCnt {
30public:
31    SK_DECLARE_INST_COUNT(SkPicture)
32
33    /** The constructor prepares the picture to record.
34        @param width the width of the virtual device the picture records.
35        @param height the height of the virtual device the picture records.
36    */
37    SkPicture();
38    /** Make a copy of the contents of src. If src records more drawing after
39        this call, those elements will not appear in this picture.
40    */
41    SkPicture(const SkPicture& src);
42    /**
43     *  Recreate a picture that was serialized into a stream. *success is set to
44     *  true if the picture was deserialized successfully and false otherwise.
45     *  decoder is used to decode any SkBitmaps that were encoded into the stream.
46     */
47    explicit SkPicture(SkStream*, bool* success = NULL,
48                       SkSerializationHelpers::DecodeBitmap decoder = NULL);
49    virtual ~SkPicture();
50
51    /**
52     *  Swap the contents of the two pictures. Guaranteed to succeed.
53     */
54    void swap(SkPicture& other);
55
56    /**
57     *  Creates a thread-safe clone of the picture that is ready for playback.
58     */
59    SkPicture* clone() const;
60
61    /**
62     * Creates multiple thread-safe clones of this picture that are ready for
63     * playback. The resulting clones are stored in the provided array of
64     * SkPictures.
65     */
66    void clone(SkPicture* pictures, int count) const;
67
68    enum RecordingFlags {
69        /*  This flag specifies that when clipPath() is called, the path will
70            be faithfully recorded, but the recording canvas' current clip will
71            only see the path's bounds. This speeds up the recording process
72            without compromising the fidelity of the playback. The only side-
73            effect for recording is that calling getTotalClip() or related
74            clip-query calls will reflect the path's bounds, not the actual
75            path.
76         */
77        kUsePathBoundsForClip_RecordingFlag = 0x01,
78        /*  This flag causes the picture to compute bounding boxes and build
79            up a spatial hierarchy (currently an R-Tree), plus a tree of Canvas'
80            usually stack-based clip/etc state. This requires an increase in
81            recording time (often ~2x; likely more for very complex pictures),
82            but allows us to perform much faster culling at playback time, and
83            completely avoid some unnecessary clips and other operations. This
84            is ideal for tiled rendering, or any other situation where you're
85            drawing a fraction of a large scene into a smaller viewport.
86
87            In most cases the record cost is offset by the playback improvement
88            after a frame or two of tiled rendering (and complex pictures that
89            induce the worst record times will generally get the largest
90            speedups at playback time).
91
92            Note: Currently this is not serializable, the bounding data will be
93            discarded if you serialize into a stream and then deserialize.
94        */
95        kOptimizeForClippedPlayback_RecordingFlag = 0x02
96    };
97
98    /** Returns the canvas that records the drawing commands.
99        @param width the base width for the picture, as if the recording
100                     canvas' bitmap had this width.
101        @param height the base width for the picture, as if the recording
102                     canvas' bitmap had this height.
103        @param recordFlags optional flags that control recording.
104        @return the picture canvas.
105    */
106    SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0);
107
108    /** Returns the recording canvas if one is active, or NULL if recording is
109        not active. This does not alter the refcnt on the canvas (if present).
110    */
111    SkCanvas* getRecordingCanvas() const;
112    /** Signal that the caller is done recording. This invalidates the canvas
113        returned by beginRecording/getRecordingCanvas, and prepares the picture
114        for drawing. Note: this happens implicitly the first time the picture
115        is drawn.
116    */
117    void endRecording();
118
119    /** Replays the drawing commands on the specified canvas. This internally
120        calls endRecording() if that has not already been called.
121        @param surface the canvas receiving the drawing commands.
122    */
123    void draw(SkCanvas* surface);
124
125    /** Return the width of the picture's recording canvas. This
126        value reflects what was passed to setSize(), and does not necessarily
127        reflect the bounds of what has been recorded into the picture.
128        @return the width of the picture's recording canvas
129    */
130    int width() const { return fWidth; }
131
132    /** Return the height of the picture's recording canvas. This
133        value reflects what was passed to setSize(), and does not necessarily
134        reflect the bounds of what has been recorded into the picture.
135        @return the height of the picture's recording canvas
136    */
137    int height() const { return fHeight; }
138
139    /**
140     *  Serialize to a stream. If non NULL, encoder will be used to encode
141     *  any bitmaps in the picture.
142     */
143    void serialize(SkWStream*, SkSerializationHelpers::EncodeBitmap encoder = NULL) const;
144
145    /** Signals that the caller is prematurely done replaying the drawing
146        commands. This can be called from a canvas virtual while the picture
147        is drawing. Has no effect if the picture is not drawing.
148    */
149    void abortPlayback();
150
151protected:
152    // V2 : adds SkPixelRef's generation ID.
153    // V3 : PictInfo tag at beginning, and EOF tag at the end
154    // V4 : move SkPictInfo to be the header
155    // V5 : don't read/write FunctionPtr on cross-process (we can detect that)
156    // V6 : added serialization of SkPath's bounds (and packed its flags tighter)
157    // V7 : changed drawBitmapRect(IRect) to drawBitmapRectToRect(Rect)
158    // V8 : Add an option for encoding bitmaps
159    // V9 : Allow the reader and writer of an SKP disagree on whether to support
160    //      SK_SUPPORT_HINTING_SCALE_FACTOR
161    // V10: add drawRRect, drawOval, clipRRect
162    static const uint32_t PICTURE_VERSION = 10;
163
164    // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
165    // install their own SkPicturePlayback-derived players,SkPictureRecord-derived
166    // recorders and set the picture size
167    SkPicturePlayback* fPlayback;
168    SkPictureRecord* fRecord;
169    int fWidth, fHeight;
170
171    // For testing. Derived classes may instantiate an alternate
172    // SkBBoxHierarchy implementation
173    virtual SkBBoxHierarchy* createBBoxHierarchy() const;
174
175private:
176
177    friend class SkFlatPicture;
178    friend class SkPicturePlayback;
179
180    typedef SkRefCnt INHERITED;
181};
182
183class SkAutoPictureRecord : SkNoncopyable {
184public:
185    SkAutoPictureRecord(SkPicture* pict, int width, int height,
186                        uint32_t recordingFlags = 0) {
187        fPicture = pict;
188        fCanvas = pict->beginRecording(width, height, recordingFlags);
189    }
190    ~SkAutoPictureRecord() {
191        fPicture->endRecording();
192    }
193
194    /** Return the canvas to draw into for recording into the picture.
195    */
196    SkCanvas* getRecordingCanvas() const { return fCanvas; }
197
198private:
199    SkPicture*  fPicture;
200    SkCanvas*   fCanvas;
201};
202
203
204#endif
205