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