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