SkRecords.h revision 42ddcd49060f64be57f00e651650154f9b4f3a08
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 "SkCanvasDrawable.h"
13#include "SkPicture.h"
14#include "SkTextBlob.h"
15
16namespace SkRecords {
17
18// A list of all the types of canvas calls we can record.
19// Each of these is reified into a struct below.
20//
21// (We're using the macro-of-macro trick here to do several different things with the same list.)
22//
23// We leave this SK_RECORD_TYPES macro defined for use by code that wants to operate on SkRecords
24// types polymorphically.  (See SkRecord::Record::{visit,mutate} for an example.)
25//
26// Order doesn't technically matter here, but the compiler can generally generate better code if
27// you keep them semantically grouped, especially the Draws.  It's also nice to leave NoOp at 0.
28#define SK_RECORD_TYPES(M)                                          \
29    M(NoOp)                                                         \
30    M(Restore)                                                      \
31    M(Save)                                                         \
32    M(SaveLayer)                                                    \
33    M(PushCull)                                                     \
34    M(PopCull)                                                      \
35    M(SetMatrix)                                                    \
36    M(ClipPath)                                                     \
37    M(ClipRRect)                                                    \
38    M(ClipRect)                                                     \
39    M(ClipRegion)                                                   \
40    M(Clear)                                                        \
41    M(BeginCommentGroup)                                            \
42    M(AddComment)                                                   \
43    M(EndCommentGroup)                                              \
44    M(DrawBitmap)                                                   \
45    M(DrawBitmapMatrix)                                             \
46    M(DrawBitmapNine)                                               \
47    M(DrawBitmapRectToRect)                                         \
48    M(DrawBitmapRectToRectBleed)                                    \
49    M(DrawDrawable)                                                 \
50    M(DrawImage)                                                    \
51    M(DrawImageRect)                                                \
52    M(DrawDRRect)                                                   \
53    M(DrawOval)                                                     \
54    M(DrawPaint)                                                    \
55    M(DrawPath)                                                     \
56    M(DrawPatch)                                                    \
57    M(DrawPicture)                                                  \
58    M(DrawPoints)                                                   \
59    M(DrawPosText)                                                  \
60    M(DrawPosTextH)                                                 \
61    M(DrawText)                                                     \
62    M(DrawTextOnPath)                                               \
63    M(DrawRRect)                                                    \
64    M(DrawRect)                                                     \
65    M(DrawSprite)                                                   \
66    M(DrawTextBlob)                                                 \
67    M(DrawData)                                                     \
68    M(DrawVertices)
69
70// Defines SkRecords::Type, an enum of all record types.
71#define ENUM(T) T##_Type,
72enum Type { SK_RECORD_TYPES(ENUM) };
73#undef ENUM
74
75// Macros to make it easier to define a record for a draw call with 0 args, 1 args, 2 args, etc.
76// These should be clearer when you look at their use below.
77#define RECORD0(T)                      \
78struct T {                              \
79    static const Type kType = T##_Type; \
80};
81
82// We try to be flexible about the types the constructors take.  Instead of requring the exact type
83// A here, we take any type Z which implicitly casts to A.  This allows the delay_copy() trick to
84// work, allowing the caller to decide whether to pass by value or by const&.
85
86#define RECORD1(T, A, a)                \
87struct T {                              \
88    static const Type kType = T##_Type; \
89    template <typename Z>               \
90    T(Z a) : a(a) {}                    \
91    A a;                                \
92};
93
94#define RECORD2(T, A, a, B, b)          \
95struct T {                              \
96    static const Type kType = T##_Type; \
97    template <typename Z, typename Y>   \
98    T(Z a, Y b) : a(a), b(b) {}         \
99    A a; B b;                           \
100};
101
102#define RECORD3(T, A, a, B, b, C, c)              \
103struct T {                                        \
104    static const Type kType = T##_Type;           \
105    template <typename Z, typename Y, typename X> \
106    T(Z a, Y b, X c) : a(a), b(b), c(c) {}        \
107    A a; B b; C c;                                \
108};
109
110#define RECORD4(T, A, a, B, b, C, c, D, d)                    \
111struct T {                                                    \
112    static const Type kType = T##_Type;                       \
113    template <typename Z, typename Y, typename X, typename W> \
114    T(Z a, Y b, X c, W d) : a(a), b(b), c(c), d(d) {}         \
115    A a; B b; C c; D d;                                       \
116};
117
118#define RECORD5(T, A, a, B, b, C, c, D, d, E, e)                          \
119struct T {                                                                \
120    static const Type kType = T##_Type;                                   \
121    template <typename Z, typename Y, typename X, typename W, typename V> \
122    T(Z a, Y b, X c, W d, V e) : a(a), b(b), c(c), d(d), e(e) {}          \
123    A a; B b; C c; D d; E e;                                              \
124};
125
126#define ACT_AS_PTR(ptr)                 \
127    operator T*() const { return ptr; } \
128    T* operator->() const { return ptr; }
129
130template <typename T>
131class RefBox : SkNoncopyable {
132public:
133    RefBox(T* obj) : fObj(SkSafeRef(obj)) {}
134    ~RefBox() { SkSafeUnref(fObj); }
135
136    ACT_AS_PTR(fObj);
137
138private:
139    T* fObj;
140};
141
142// An Optional doesn't own the pointer's memory, but may need to destroy non-POD data.
143template <typename T>
144class Optional : SkNoncopyable {
145public:
146    Optional(T* ptr) : fPtr(ptr) {}
147    ~Optional() { if (fPtr) fPtr->~T(); }
148
149    ACT_AS_PTR(fPtr);
150private:
151    T* fPtr;
152};
153
154// Like Optional, but ptr must not be NULL.
155template <typename T>
156class Adopted : SkNoncopyable {
157public:
158    Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); }
159    Adopted(Adopted* source) {
160        // Transfer ownership from source to this.
161        fPtr = source->fPtr;
162        source->fPtr = NULL;
163    }
164    ~Adopted() { if (fPtr) fPtr->~T(); }
165
166    ACT_AS_PTR(fPtr);
167private:
168    T* fPtr;
169};
170
171// PODArray doesn't own the pointer's memory, and we assume the data is POD.
172template <typename T>
173class PODArray {
174public:
175    PODArray(T* ptr) : fPtr(ptr) {}
176    // Default copy and assign.
177
178    ACT_AS_PTR(fPtr);
179private:
180    T* fPtr;
181};
182
183#undef ACT_AS_PTR
184
185// Like SkBitmap, but deep copies pixels if they're not immutable.
186// Using this, we guarantee the immutability of all bitmaps we record.
187class ImmutableBitmap : SkNoncopyable {
188public:
189    explicit ImmutableBitmap(const SkBitmap& bitmap) {
190        if (bitmap.isImmutable()) {
191            fBitmap = bitmap;
192        } else {
193            bitmap.copyTo(&fBitmap);
194        }
195        fBitmap.setImmutable();
196    }
197
198    operator const SkBitmap& () const { return fBitmap; }
199
200private:
201    SkBitmap fBitmap;
202};
203
204RECORD0(NoOp);
205
206RECORD2(Restore, SkIRect, devBounds, SkMatrix, matrix);
207RECORD0(Save);
208RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags);
209
210RECORD1(PushCull, SkRect, rect);
211RECORD0(PopCull);
212
213RECORD1(SetMatrix, SkMatrix, matrix);
214
215struct RegionOpAndAA {
216    RegionOpAndAA(SkRegion::Op op, bool aa) : op(op), aa(aa) {}
217    SkRegion::Op op : 31;  // This really only needs to be 3, but there's no win today to do so.
218    unsigned     aa :  1;  // MSVC won't pack an enum with an bool, so we call this an unsigned.
219};
220SK_COMPILE_ASSERT(sizeof(RegionOpAndAA) == 4, RegionOpAndAASize);
221
222RECORD3(ClipPath,   SkIRect, devBounds, SkPath,   path,   RegionOpAndAA, opAA);
223RECORD3(ClipRRect,  SkIRect, devBounds, SkRRect,  rrect,  RegionOpAndAA, opAA);
224RECORD3(ClipRect,   SkIRect, devBounds, SkRect,   rect,   RegionOpAndAA, opAA);
225RECORD3(ClipRegion, SkIRect, devBounds, SkRegion, region, SkRegion::Op,    op);
226
227RECORD1(Clear, SkColor, color);
228
229RECORD1(BeginCommentGroup, PODArray<char>, description);
230RECORD2(AddComment, PODArray<char>, key, PODArray<char>, value);
231RECORD0(EndCommentGroup);
232
233// While not strictly required, if you have an SkPaint, it's fastest to put it first.
234RECORD4(DrawBitmap, Optional<SkPaint>, paint,
235                    ImmutableBitmap, bitmap,
236                    SkScalar, left,
237                    SkScalar, top);
238RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix);
239RECORD4(DrawBitmapNine, Optional<SkPaint>, paint,
240                        ImmutableBitmap, bitmap,
241                        SkIRect, center,
242                        SkRect, dst);
243RECORD4(DrawBitmapRectToRect, Optional<SkPaint>, paint,
244                              ImmutableBitmap, bitmap,
245                              Optional<SkRect>, src,
246                              SkRect, dst);
247RECORD4(DrawBitmapRectToRectBleed, Optional<SkPaint>, paint,
248                                   ImmutableBitmap, bitmap,
249                                   Optional<SkRect>, src,
250                                   SkRect, dst);
251RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
252RECORD2(DrawDrawable, SkRect, worstCaseBounds, int32_t, index);
253RECORD4(DrawImage, Optional<SkPaint>, paint,
254                   RefBox<const SkImage>, image,
255                   SkScalar, left,
256                   SkScalar, top);
257RECORD4(DrawImageRect, Optional<SkPaint>, paint,
258                       RefBox<const SkImage>, image,
259                       Optional<SkRect>, src,
260                       SkRect, dst);
261RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
262RECORD1(DrawPaint, SkPaint, paint);
263RECORD2(DrawPath, SkPaint, paint, SkPath, path);
264RECORD3(DrawPicture, Optional<SkPaint>, paint,
265                     RefBox<const SkPicture>, picture,
266                     Optional<SkMatrix>, matrix);
267RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, unsigned, count, SkPoint*, pts);
268RECORD4(DrawPosText, SkPaint, paint,
269                     PODArray<char>, text,
270                     size_t, byteLength,
271                     PODArray<SkPoint>, pos);
272RECORD5(DrawPosTextH, SkPaint, paint,
273                      PODArray<char>, text,
274                      unsigned, byteLength,
275                      SkScalar, y,
276                      PODArray<SkScalar>, xpos);
277RECORD2(DrawRRect, SkPaint, paint, SkRRect, rrect);
278RECORD2(DrawRect, SkPaint, paint, SkRect, rect);
279RECORD4(DrawSprite, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, int, left, int, top);
280RECORD5(DrawText, SkPaint, paint,
281                  PODArray<char>, text,
282                  size_t, byteLength,
283                  SkScalar, x,
284                  SkScalar, y);
285RECORD4(DrawTextBlob, SkPaint, paint,
286                      RefBox<const SkTextBlob>, blob,
287                      SkScalar, x,
288                      SkScalar, y);
289RECORD5(DrawTextOnPath, SkPaint, paint,
290                        PODArray<char>, text,
291                        size_t, byteLength,
292                        SkPath, path,
293                        Optional<SkMatrix>, matrix);
294
295RECORD2(DrawData, PODArray<char>, data, size_t, length);
296
297RECORD5(DrawPatch, SkPaint, paint,
298                   PODArray<SkPoint>, cubics,
299                   PODArray<SkColor>, colors,
300                   PODArray<SkPoint>, texCoords,
301                   RefBox<SkXfermode>, xmode);
302
303// This guy is so ugly we just write it manually.
304struct DrawVertices {
305    static const Type kType = DrawVertices_Type;
306
307    DrawVertices(const SkPaint& paint,
308                 SkCanvas::VertexMode vmode,
309                 int vertexCount,
310                 SkPoint* vertices,
311                 SkPoint* texs,
312                 SkColor* colors,
313                 SkXfermode* xmode,
314                 uint16_t* indices,
315                 int indexCount)
316        : paint(paint)
317        , vmode(vmode)
318        , vertexCount(vertexCount)
319        , vertices(vertices)
320        , texs(texs)
321        , colors(colors)
322        , xmode(SkSafeRef(xmode))
323        , indices(indices)
324        , indexCount(indexCount) {}
325
326    SkPaint paint;
327    SkCanvas::VertexMode vmode;
328    int vertexCount;
329    PODArray<SkPoint> vertices;
330    PODArray<SkPoint> texs;
331    PODArray<SkColor> colors;
332    SkAutoTUnref<SkXfermode> xmode;
333    PODArray<uint16_t> indices;
334    int indexCount;
335};
336
337#undef RECORD0
338#undef RECORD1
339#undef RECORD2
340#undef RECORD3
341#undef RECORD4
342#undef RECORD5
343
344}  // namespace SkRecords
345
346#endif//SkRecords_DEFINED
347