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