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