1 /*
2  * Copyright 2014 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 SkPictureRecorder_DEFINED
9 #define SkPictureRecorder_DEFINED
10 
11 #include "include/core/SkBBHFactory.h"
12 #include "include/core/SkPicture.h"
13 #include "include/core/SkRefCnt.h"
14 
15 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
16 namespace android {
17     class Picture;
18 };
19 #endif
20 
21 class GrContext;
22 class SkCanvas;
23 class SkDrawable;
24 class SkMiniRecorder;
25 class SkPictureRecord;
26 class SkRecord;
27 class SkRecorder;
28 
29 class SK_API SkPictureRecorder {
30 public:
31     SkPictureRecorder();
32     ~SkPictureRecorder();
33 
34     enum RecordFlags {
35         // If you call drawPicture() or drawDrawable() on the recording canvas, this flag forces
36         // that object to playback its contents immediately rather than reffing the object.
37         kPlaybackDrawPicture_RecordFlag     = 1 << 0,
38     };
39 
40     enum FinishFlags {
41     };
42 
43     /** Returns the canvas that records the drawing commands.
44         @param bounds the cull rect used when recording this picture. Any drawing the falls outside
45                       of this rect is undefined, and may be drawn or it may not.
46         @param bbhFactory factory to create desired acceleration structure
47         @param recordFlags optional flags that control recording.
48         @return the canvas.
49     */
50     SkCanvas* beginRecording(const SkRect& bounds,
51                              SkBBHFactory* bbhFactory = nullptr,
52                              uint32_t recordFlags = 0);
53 
54     SkCanvas* beginRecording(SkScalar width, SkScalar height,
55                              SkBBHFactory* bbhFactory = nullptr,
56                              uint32_t recordFlags = 0) {
57         return this->beginRecording(SkRect::MakeWH(width, height), bbhFactory, recordFlags);
58     }
59 
60     /** Returns the recording canvas if one is active, or NULL if recording is
61         not active. This does not alter the refcnt on the canvas (if present).
62     */
63     SkCanvas* getRecordingCanvas();
64 
65     /**
66      *  Signal that the caller is done recording. This invalidates the canvas returned by
67      *  beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
68      *  must call unref() when they are done using it.
69      *
70      *  The returned picture is immutable. If during recording drawables were added to the canvas,
71      *  these will have been "drawn" into a recording canvas, so that this resulting picture will
72      *  reflect their current state, but will not contain a live reference to the drawables
73      *  themselves.
74      */
75     sk_sp<SkPicture> finishRecordingAsPicture(uint32_t endFlags = 0);
76 
77     /**
78      *  Signal that the caller is done recording, and update the cull rect to use for bounding
79      *  box hierarchy (BBH) generation. The behavior is the same as calling
80      *  finishRecordingAsPicture(), except that this method updates the cull rect initially passed
81      *  into beginRecording.
82      *  @param cullRect the new culling rectangle to use as the overall bound for BBH generation
83      *                  and subsequent culling operations.
84      *  @return the picture containing the recorded content.
85      */
86     sk_sp<SkPicture> finishRecordingAsPictureWithCull(const SkRect& cullRect,
87                                                       uint32_t endFlags = 0);
88 
89     /**
90      *  Signal that the caller is done recording. This invalidates the canvas returned by
91      *  beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
92      *  must call unref() when they are done using it.
93      *
94      *  Unlike finishRecordingAsPicture(), which returns an immutable picture, the returned drawable
95      *  may contain live references to other drawables (if they were added to the recording canvas)
96      *  and therefore this drawable will reflect the current state of those nested drawables anytime
97      *  it is drawn or a new picture is snapped from it (by calling drawable->newPictureSnapshot()).
98      */
99     sk_sp<SkDrawable> finishRecordingAsDrawable(uint32_t endFlags = 0);
100 
101 private:
102     void reset();
103 
104     /** Replay the current (partially recorded) operation stream into
105         canvas. This call doesn't close the current recording.
106     */
107 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
108     friend class android::Picture;
109 #endif
110     friend class SkPictureRecorderReplayTester; // for unit testing
111     void partialReplay(SkCanvas* canvas) const;
112 
113     bool                        fActivelyRecording;
114     uint32_t                    fFlags;
115     SkRect                      fCullRect;
116     sk_sp<SkBBoxHierarchy>      fBBH;
117     std::unique_ptr<SkRecorder> fRecorder;
118     sk_sp<SkRecord>             fRecord;
119     std::unique_ptr<SkMiniRecorder> fMiniRecorder;
120 
121     SkPictureRecorder(SkPictureRecorder&&) = delete;
122     SkPictureRecorder& operator=(SkPictureRecorder&&) = delete;
123 };
124 
125 #endif
126