• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 SkRecords_DEFINED
9 #define SkRecords_DEFINED
10 
11 #include "SkCanvas.h"
12 #include "SkDrawable.h"
13 #include "SkImageFilter.h"
14 #include "SkMatrix.h"
15 #include "SkPath.h"
16 #include "SkPicture.h"
17 #include "SkRect.h"
18 #include "SkRRect.h"
19 #include "SkRSXform.h"
20 #include "SkTextBlob.h"
21 
22 namespace SkRecords {
23 
24 // A list of all the types of canvas calls we can record.
25 // Each of these is reified into a struct below.
26 //
27 // (We're using the macro-of-macro trick here to do several different things with the same list.)
28 //
29 // We leave this SK_RECORD_TYPES macro defined for use by code that wants to operate on SkRecords
30 // types polymorphically.  (See SkRecord::Record::{visit,mutate} for an example.)
31 //
32 // Order doesn't technically matter here, but the compiler can generally generate better code if
33 // you keep them semantically grouped, especially the Draws.  It's also nice to leave NoOp at 0.
34 #define SK_RECORD_TYPES(M)                                          \
35     M(NoOp)                                                         \
36     M(Restore)                                                      \
37     M(Save)                                                         \
38     M(SaveLayer)                                                    \
39     M(SetMatrix)                                                    \
40     M(Concat)                                                       \
41     M(ClipPath)                                                     \
42     M(ClipRRect)                                                    \
43     M(ClipRect)                                                     \
44     M(ClipRegion)                                                   \
45     M(DrawBitmap)                                                   \
46     M(DrawBitmapNine)                                               \
47     M(DrawBitmapRect)                                               \
48     M(DrawBitmapRectFast)                                           \
49     M(DrawBitmapRectFixedSize)                                      \
50     M(DrawDrawable)                                                 \
51     M(DrawImage)                                                    \
52     M(DrawImageRect)                                                \
53     M(DrawImageNine)                                                \
54     M(DrawDRRect)                                                   \
55     M(DrawOval)                                                     \
56     M(DrawPaint)                                                    \
57     M(DrawPath)                                                     \
58     M(DrawPatch)                                                    \
59     M(DrawPicture)                                                  \
60     M(DrawPoints)                                                   \
61     M(DrawPosText)                                                  \
62     M(DrawPosTextH)                                                 \
63     M(DrawText)                                                     \
64     M(DrawTextOnPath)                                               \
65     M(DrawRRect)                                                    \
66     M(DrawRect)                                                     \
67     M(DrawTextBlob)                                                 \
68     M(DrawAtlas)                                                    \
69     M(DrawVertices)
70 
71 // Defines SkRecords::Type, an enum of all record types.
72 #define ENUM(T) T##_Type,
73 enum Type { SK_RECORD_TYPES(ENUM) };
74 #undef ENUM
75 
76 #define ACT_AS_PTR(ptr)                 \
77     operator T*() const { return ptr; } \
78     T* operator->() const { return ptr; }
79 
80 template <typename T>
81 class RefBox : SkNoncopyable {
82 public:
RefBox()83     RefBox() {}
RefBox(T * obj)84     RefBox(T* obj) : fObj(SkSafeRef(obj)) {}
RefBox(RefBox && o)85     RefBox(RefBox&& o) : fObj(o.fObj) {
86         o.fObj = nullptr;
87     }
~RefBox()88     ~RefBox() { SkSafeUnref(fObj); }
89 
90     ACT_AS_PTR(fObj);
91 
92 private:
93     T* fObj;
94 };
95 
96 // An Optional doesn't own the pointer's memory, but may need to destroy non-POD data.
97 template <typename T>
98 class Optional : SkNoncopyable {
99 public:
Optional()100     Optional() : fPtr(nullptr) {}
Optional(T * ptr)101     Optional(T* ptr) : fPtr(ptr) {}
Optional(Optional && o)102     Optional(Optional&& o) : fPtr(o.fPtr) {
103         o.fPtr = nullptr;
104     }
~Optional()105     ~Optional() { if (fPtr) fPtr->~T(); }
106 
107     ACT_AS_PTR(fPtr);
108 private:
109     T* fPtr;
110 };
111 
112 // Like Optional, but ptr must not be NULL.
113 template <typename T>
114 class Adopted : SkNoncopyable {
115 public:
Adopted(T * ptr)116     Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); }
Adopted(Adopted * source)117     Adopted(Adopted* source) {
118         // Transfer ownership from source to this.
119         fPtr = source->fPtr;
120         source->fPtr = NULL;
121     }
~Adopted()122     ~Adopted() { if (fPtr) fPtr->~T(); }
123 
124     ACT_AS_PTR(fPtr);
125 private:
126     T* fPtr;
127 };
128 
129 // PODArray doesn't own the pointer's memory, and we assume the data is POD.
130 template <typename T>
131 class PODArray {
132 public:
PODArray()133     PODArray() {}
PODArray(T * ptr)134     PODArray(T* ptr) : fPtr(ptr) {}
135     // Default copy and assign.
136 
137     ACT_AS_PTR(fPtr);
138 private:
139     T* fPtr;
140 };
141 
142 #undef ACT_AS_PTR
143 
144 // Like SkBitmap, but deep copies pixels if they're not immutable.
145 // Using this, we guarantee the immutability of all bitmaps we record.
146 class ImmutableBitmap : SkNoncopyable {
147 public:
ImmutableBitmap()148     ImmutableBitmap() {}
149     ImmutableBitmap(const SkBitmap& bitmap);
ImmutableBitmap(ImmutableBitmap && o)150     ImmutableBitmap(ImmutableBitmap&& o) {
151         fBitmap.swap(o.fBitmap);
152     }
153 
width()154     int width()  const { return fBitmap.width();  }
height()155     int height() const { return fBitmap.height(); }
156 
157     // While the pixels are immutable, SkBitmap itself is not thread-safe, so return a copy.
shallowCopy()158     SkBitmap shallowCopy() const { return fBitmap; }
159 private:
160     SkBitmap fBitmap;
161 };
162 
163 // SkPath::getBounds() isn't thread safe unless we precache the bounds in a singlethreaded context.
164 // SkPath::cheapComputeDirection() is similar.
165 // Recording is a convenient time to cache these, or we can delay it to between record and playback.
166 struct PreCachedPath : public SkPath {
PreCachedPathPreCachedPath167     PreCachedPath() {}
168     PreCachedPath(const SkPath& path);
169 };
170 
171 // Like SkPath::getBounds(), SkMatrix::getType() isn't thread safe unless we precache it.
172 // This may not cover all SkMatrices used by the picture (e.g. some could be hiding in a shader).
173 struct TypedMatrix : public SkMatrix {
TypedMatrixTypedMatrix174     TypedMatrix() {}
175     TypedMatrix(const SkMatrix& matrix);
176 };
177 
178 enum Tags {
179     kDraw_Tag      = 1,   // May draw something (usually named DrawFoo).
180     kHasImage_Tag  = 2,   // Contains an SkImage or SkBitmap.
181     kHasText_Tag   = 4,   // Contains text.
182 };
183 
184 // A macro to make it a little easier to define a struct that can be stored in SkRecord.
185 #define RECORD(T, tags, ...)            \
186 struct T {                              \
187     static const Type kType = T##_Type; \
188     static const int kTags = tags;      \
189     __VA_ARGS__;                        \
190 };
191 
192 RECORD(NoOp, 0);
193 RECORD(Restore, 0,
194         SkIRect devBounds;
195         TypedMatrix matrix);
196 RECORD(Save, 0);
197 
198 RECORD(SaveLayer, 0,
199        Optional<SkRect> bounds;
200        Optional<SkPaint> paint;
201        RefBox<const SkImageFilter> backdrop;
202        SkCanvas::SaveLayerFlags saveLayerFlags);
203 
204 RECORD(SetMatrix, 0,
205         TypedMatrix matrix);
206 RECORD(Concat, 0,
207         TypedMatrix matrix);
208 
209 struct RegionOpAndAA {
RegionOpAndAARegionOpAndAA210     RegionOpAndAA() {}
RegionOpAndAARegionOpAndAA211     RegionOpAndAA(SkRegion::Op op, bool aa) : op(op), aa(aa) {}
212     SkRegion::Op op : 31;  // This really only needs to be 3, but there's no win today to do so.
213     unsigned     aa :  1;  // MSVC won't pack an enum with an bool, so we call this an unsigned.
214 };
215 static_assert(sizeof(RegionOpAndAA) == 4, "RegionOpAndAASize");
216 
217 RECORD(ClipPath, 0,
218         SkIRect devBounds;
219         PreCachedPath path;
220         RegionOpAndAA opAA);
221 RECORD(ClipRRect, 0,
222         SkIRect devBounds;
223         SkRRect rrect;
224         RegionOpAndAA opAA);
225 RECORD(ClipRect, 0,
226         SkIRect devBounds;
227         SkRect rect;
228         RegionOpAndAA opAA);
229 RECORD(ClipRegion, 0,
230         SkIRect devBounds;
231         SkRegion region;
232         SkRegion::Op op);
233 
234 // While not strictly required, if you have an SkPaint, it's fastest to put it first.
235 RECORD(DrawBitmap, kDraw_Tag|kHasImage_Tag,
236         Optional<SkPaint> paint;
237         ImmutableBitmap bitmap;
238         SkScalar left;
239         SkScalar top);
240 RECORD(DrawBitmapNine, kDraw_Tag|kHasImage_Tag,
241         Optional<SkPaint> paint;
242         ImmutableBitmap bitmap;
243         SkIRect center;
244         SkRect dst);
245 RECORD(DrawBitmapRect, kDraw_Tag|kHasImage_Tag,
246         Optional<SkPaint> paint;
247         ImmutableBitmap bitmap;
248         Optional<SkRect> src;
249         SkRect dst);
250 RECORD(DrawBitmapRectFast, kDraw_Tag|kHasImage_Tag,
251         Optional<SkPaint> paint;
252         ImmutableBitmap bitmap;
253         Optional<SkRect> src;
254         SkRect dst);
255 RECORD(DrawBitmapRectFixedSize, kDraw_Tag|kHasImage_Tag,
256         SkPaint paint;
257         ImmutableBitmap bitmap;
258         SkRect src;
259         SkRect dst;
260         SkCanvas::SrcRectConstraint constraint);
261 RECORD(DrawDRRect, kDraw_Tag,
262         SkPaint paint;
263         SkRRect outer;
264         SkRRect inner);
265 RECORD(DrawDrawable, kDraw_Tag,
266         Optional<SkMatrix> matrix;
267         SkRect worstCaseBounds;
268         int32_t index);
269 RECORD(DrawImage, kDraw_Tag|kHasImage_Tag,
270         Optional<SkPaint> paint;
271         RefBox<const SkImage> image;
272         SkScalar left;
273         SkScalar top);
274 RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag,
275         Optional<SkPaint> paint;
276         RefBox<const SkImage> image;
277         Optional<SkRect> src;
278         SkRect dst;
279         SkCanvas::SrcRectConstraint constraint);
280 RECORD(DrawImageNine, kDraw_Tag|kHasImage_Tag,
281         Optional<SkPaint> paint;
282         RefBox<const SkImage> image;
283         SkIRect center;
284         SkRect dst);
285 RECORD(DrawOval, kDraw_Tag,
286         SkPaint paint;
287         SkRect oval);
288 RECORD(DrawPaint, kDraw_Tag,
289         SkPaint paint);
290 RECORD(DrawPath, kDraw_Tag,
291         SkPaint paint;
292         PreCachedPath path);
293 RECORD(DrawPicture, kDraw_Tag,
294         Optional<SkPaint> paint;
295         RefBox<const SkPicture> picture;
296         TypedMatrix matrix);
297 RECORD(DrawPoints, kDraw_Tag,
298         SkPaint paint;
299         SkCanvas::PointMode mode;
300         unsigned count;
301         SkPoint* pts);
302 RECORD(DrawPosText, kDraw_Tag|kHasText_Tag,
303         SkPaint paint;
304         PODArray<char> text;
305         size_t byteLength;
306         PODArray<SkPoint> pos);
307 RECORD(DrawPosTextH, kDraw_Tag|kHasText_Tag,
308         SkPaint paint;
309         PODArray<char> text;
310         unsigned byteLength;
311         SkScalar y;
312         PODArray<SkScalar> xpos);
313 RECORD(DrawRRect, kDraw_Tag,
314         SkPaint paint;
315         SkRRect rrect);
316 RECORD(DrawRect, kDraw_Tag,
317         SkPaint paint;
318         SkRect rect);
319 RECORD(DrawText, kDraw_Tag|kHasText_Tag,
320         SkPaint paint;
321         PODArray<char> text;
322         size_t byteLength;
323         SkScalar x;
324         SkScalar y);
325 RECORD(DrawTextBlob, kDraw_Tag|kHasText_Tag,
326         SkPaint paint;
327         RefBox<const SkTextBlob> blob;
328         SkScalar x;
329         SkScalar y);
330 RECORD(DrawTextOnPath, kDraw_Tag|kHasText_Tag,
331         SkPaint paint;
332         PODArray<char> text;
333         size_t byteLength;
334         PreCachedPath path;
335         TypedMatrix matrix);
336 RECORD(DrawPatch, kDraw_Tag,
337         SkPaint paint;
338         PODArray<SkPoint> cubics;
339         PODArray<SkColor> colors;
340         PODArray<SkPoint> texCoords;
341         RefBox<SkXfermode> xmode);
342 RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag,
343         Optional<SkPaint> paint;
344         RefBox<const SkImage> atlas;
345         PODArray<SkRSXform> xforms;
346         PODArray<SkRect> texs;
347         PODArray<SkColor> colors;
348         int count;
349         SkXfermode::Mode mode;
350         Optional<SkRect> cull);
351 RECORD(DrawVertices, kDraw_Tag,
352         SkPaint paint;
353         SkCanvas::VertexMode vmode;
354         int vertexCount;
355         PODArray<SkPoint> vertices;
356         PODArray<SkPoint> texs;
357         PODArray<SkColor> colors;
358         RefBox<SkXfermode> xmode;
359         PODArray<uint16_t> indices;
360         int indexCount);
361 
362 #undef RECORD
363 
364 }  // namespace SkRecords
365 
366 #endif//SkRecords_DEFINED
367