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