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