SkPicture.h revision fbb0ed959de64f16d236d2f0d81ddf5cb318e1fe
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 static const int PICTURE_VERSION = 9; 162 163 // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to 164 // install their own SkPicturePlayback-derived players,SkPictureRecord-derived 165 // recorders and set the picture size 166 SkPicturePlayback* fPlayback; 167 SkPictureRecord* fRecord; 168 int fWidth, fHeight; 169 170 // For testing. Derived classes may instantiate an alternate 171 // SkBBoxHierarchy implementation 172 virtual SkBBoxHierarchy* createBBoxHierarchy() const; 173 174private: 175 176 friend class SkFlatPicture; 177 friend class SkPicturePlayback; 178 179 typedef SkRefCnt INHERITED; 180}; 181 182class SkAutoPictureRecord : SkNoncopyable { 183public: 184 SkAutoPictureRecord(SkPicture* pict, int width, int height, 185 uint32_t recordingFlags = 0) { 186 fPicture = pict; 187 fCanvas = pict->beginRecording(width, height, recordingFlags); 188 } 189 ~SkAutoPictureRecord() { 190 fPicture->endRecording(); 191 } 192 193 /** Return the canvas to draw into for recording into the picture. 194 */ 195 SkCanvas* getRecordingCanvas() const { return fCanvas; } 196 197private: 198 SkPicture* fPicture; 199 SkCanvas* fCanvas; 200}; 201 202 203#endif 204