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/SkMiniRecorder.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 SkCanvas;
23 class SkDrawable;
24 class SkPictureRecord;
25 class SkRecord;
26 class SkRecorder;
27 
28 class SK_API SkPictureRecorder : SkNoncopyable {
29 public:
30     SkPictureRecorder();
31     ~SkPictureRecorder();
32 
33     enum RecordFlags {
34         // This flag indicates that, if some BHH is being computed, saveLayer
35         // information should also be extracted at the same time.
36         kComputeSaveLayerInfo_RecordFlag = 0x01,
37 
38         // If you call drawPicture() or drawDrawable() on the recording canvas, this flag forces
39         // that object to playback its contents immediately rather than reffing the object.
40         kPlaybackDrawPicture_RecordFlag  = 0x02,
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 = NULL,
52                              uint32_t recordFlags = 0);
53 
54     SkCanvas* beginRecording(SkScalar width, SkScalar height,
55                              SkBBHFactory* bbhFactory = NULL,
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     SkPicture* SK_WARN_UNUSED_RESULT endRecordingAsPicture();
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      *  endRecordingAsPicture(), 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     SkPicture* SK_WARN_UNUSED_RESULT endRecordingAsPicture(const SkRect& cullRect);
87 
88     /**
89      *  Signal that the caller is done recording. This invalidates the canvas returned by
90      *  beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
91      *  must call unref() when they are done using it.
92      *
93      *  Unlike endRecordingAsPicture(), which returns an immutable picture, the returned drawable
94      *  may contain live references to other drawables (if they were added to the recording canvas)
95      *  and therefore this drawable will reflect the current state of those nested drawables anytime
96      *  it is drawn or a new picture is snapped from it (by calling drawable->newPictureSnapshot()).
97      */
98     SkDrawable* SK_WARN_UNUSED_RESULT endRecordingAsDrawable();
99 
100     // Legacy API -- use endRecordingAsPicture instead.
endRecording()101     SkPicture* SK_WARN_UNUSED_RESULT endRecording() { return this->endRecordingAsPicture(); }
102 
103 private:
104     void reset();
105 
106     /** Replay the current (partially recorded) operation stream into
107         canvas. This call doesn't close the current recording.
108     */
109 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
110     friend class android::Picture;
111 #endif
112     friend class SkPictureRecorderReplayTester; // for unit testing
113     void partialReplay(SkCanvas* canvas) const;
114 
115     bool                          fActivelyRecording;
116     uint32_t                      fFlags;
117     SkRect                        fCullRect;
118     SkAutoTUnref<SkBBoxHierarchy> fBBH;
119     SkAutoTUnref<SkRecorder>      fRecorder;
120     SkAutoTUnref<SkRecord>        fRecord;
121     SkMiniRecorder                fMiniRecorder;
122 
123     typedef SkNoncopyable INHERITED;
124 };
125 
126 #endif
127