blob: 3d5b1908934f4c7fc0d401980a94d9996bc73490 [file] [log] [blame]
commit-bot@chromium.orgc4b21e62014-04-11 18:33:31 +00001/*
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
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +00008#ifndef SkRecords_DEFINED
9#define SkRecords_DEFINED
10
11#include "SkCanvas.h"
reed2347b622014-08-07 12:19:50 -070012#include "SkPicture.h"
13
14class SkPictureBox {
15public:
16 SkPictureBox(const SkPicture* obj) : fObj(SkRef(obj)) {}
reed2347b622014-08-07 12:19:50 -070017 ~SkPictureBox() { fObj->unref(); }
18
reed2347b622014-08-07 12:19:50 -070019 operator const SkPicture*() const { return fObj; }
20
21private:
reedd5fa1a42014-08-09 11:08:05 -070022 SkPictureBox(const SkPictureBox&);
23 SkPictureBox& operator=(const SkPictureBox&);
24
reed2347b622014-08-07 12:19:50 -070025 const SkPicture* fObj;
26};
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000027
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.)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000037//
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.
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000040#define SK_RECORD_TYPES(M) \
41 M(NoOp) \
42 M(Restore) \
43 M(Save) \
44 M(SaveLayer) \
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000045 M(PushCull) \
46 M(PopCull) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000047 M(Concat) \
48 M(SetMatrix) \
49 M(ClipPath) \
50 M(ClipRRect) \
51 M(ClipRect) \
52 M(ClipRegion) \
53 M(Clear) \
54 M(DrawBitmap) \
55 M(DrawBitmapMatrix) \
56 M(DrawBitmapNine) \
57 M(DrawBitmapRectToRect) \
58 M(DrawDRRect) \
59 M(DrawOval) \
60 M(DrawPaint) \
61 M(DrawPath) \
dandov963137b2014-08-07 07:49:53 -070062 M(DrawPatch) \
reed2347b622014-08-07 12:19:50 -070063 M(DrawPicture) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000064 M(DrawPoints) \
65 M(DrawPosText) \
66 M(DrawPosTextH) \
67 M(DrawRRect) \
68 M(DrawRect) \
69 M(DrawSprite) \
70 M(DrawText) \
71 M(DrawTextOnPath) \
mtkleinf4078ad2014-08-08 10:05:19 -070072 M(DrawVertices)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000073
74// Defines SkRecords::Type, an enum of all record types.
75#define ENUM(T) T##_Type,
76enum Type { SK_RECORD_TYPES(ENUM) };
77#undef ENUM
78
79// Macros to make it easier to define a record for a draw call with 0 args, 1 args, 2 args, etc.
80// These should be clearer when you look at their use below.
81#define RECORD0(T) \
82struct T { \
83 static const Type kType = T##_Type; \
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000084};
85
86// We try to be flexible about the types the constructors take. Instead of requring the exact type
87// A here, we take any type Z which implicitly casts to A. This allows the delay_copy() trick to
88// work, allowing the caller to decide whether to pass by value or by const&.
89
90#define RECORD1(T, A, a) \
91struct T { \
92 static const Type kType = T##_Type; \
93 template <typename Z> \
94 T(Z a) : a(a) {} \
95 A a; \
96};
97
98#define RECORD2(T, A, a, B, b) \
99struct T { \
100 static const Type kType = T##_Type; \
101 template <typename Z, typename Y> \
102 T(Z a, Y b) : a(a), b(b) {} \
103 A a; B b; \
104};
105
106#define RECORD3(T, A, a, B, b, C, c) \
107struct T { \
108 static const Type kType = T##_Type; \
109 template <typename Z, typename Y, typename X> \
110 T(Z a, Y b, X c) : a(a), b(b), c(c) {} \
111 A a; B b; C c; \
112};
113
114#define RECORD4(T, A, a, B, b, C, c, D, d) \
115struct T { \
116 static const Type kType = T##_Type; \
117 template <typename Z, typename Y, typename X, typename W> \
118 T(Z a, Y b, X c, W d) : a(a), b(b), c(c), d(d) {} \
119 A a; B b; C c; D d; \
120};
121
122#define RECORD5(T, A, a, B, b, C, c, D, d, E, e) \
123struct T { \
124 static const Type kType = T##_Type; \
125 template <typename Z, typename Y, typename X, typename W, typename V> \
126 T(Z a, Y b, X c, W d, V e) : a(a), b(b), c(c), d(d), e(e) {} \
127 A a; B b; C c; D d; E e; \
128};
129
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000130#define ACT_AS_PTR(ptr) \
131 operator T*() { return ptr; } \
132 operator const T*() const { return ptr; } \
133 T* operator->() { return ptr; } \
134 const T* operator->() const { return ptr; }
135
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000136// An Optional doesn't own the pointer's memory, but may need to destroy non-POD data.
137template <typename T>
138class Optional : SkNoncopyable {
139public:
140 Optional(T* ptr) : fPtr(ptr) {}
141 ~Optional() { if (fPtr) fPtr->~T(); }
142
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000143 ACT_AS_PTR(fPtr);
144private:
145 T* fPtr;
146};
147
148// Like Optional, but ptr must not be NULL.
149template <typename T>
150class Adopted : SkNoncopyable {
151public:
152 Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); }
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000153 Adopted(Adopted* source) {
154 // Transfer ownership from source to this.
155 fPtr = source->fPtr;
156 source->fPtr = NULL;
157 }
158 ~Adopted() { if (fPtr) fPtr->~T(); }
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000159
160 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000161private:
162 T* fPtr;
163};
164
165// PODArray doesn't own the pointer's memory, and we assume the data is POD.
166template <typename T>
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000167class PODArray {
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000168public:
169 PODArray(T* ptr) : fPtr(ptr) {}
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000170 // Default copy and assign.
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000171
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000172 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000173private:
174 T* fPtr;
175};
176
commit-bot@chromium.org16307bd2014-04-22 18:32:58 +0000177#undef ACT_AS_PTR
178
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000179// Like SkBitmap, but deep copies pixels if they're not immutable.
180// Using this, we guarantee the immutability of all bitmaps we record.
181class ImmutableBitmap {
182public:
183 explicit ImmutableBitmap(const SkBitmap& bitmap) {
184 if (bitmap.isImmutable()) {
185 fBitmap = bitmap;
186 } else {
187 bitmap.copyTo(&fBitmap);
188 }
189 fBitmap.setImmutable();
190 }
191
192 operator const SkBitmap& () const { return fBitmap; }
193
194private:
195 SkBitmap fBitmap;
196};
197
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000198RECORD0(NoOp);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000199
mtklein6cfa73a2014-08-13 13:33:49 -0700200RECORD1(Restore, SkMatrix, matrix);
Florin Malita5f6102d2014-06-30 10:13:28 -0400201RECORD0(Save);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000202RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000203
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000204RECORD1(PushCull, SkRect, rect);
commit-bot@chromium.org03a99b82014-04-08 15:17:17 +0000205RECORD0(PopCull);
206
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000207RECORD1(Concat, SkMatrix, matrix);
208RECORD1(SetMatrix, SkMatrix, matrix);
209
210RECORD3(ClipPath, SkPath, path, SkRegion::Op, op, bool, doAA);
211RECORD3(ClipRRect, SkRRect, rrect, SkRegion::Op, op, bool, doAA);
212RECORD3(ClipRect, SkRect, rect, SkRegion::Op, op, bool, doAA);
213RECORD2(ClipRegion, SkRegion, region, SkRegion::Op, op);
214
215RECORD1(Clear, SkColor, color);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000216// While not strictly required, if you have an SkPaint, it's fastest to put it first.
217RECORD4(DrawBitmap, Optional<SkPaint>, paint,
218 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000219 SkScalar, left,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000220 SkScalar, top);
221RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix);
222RECORD4(DrawBitmapNine, Optional<SkPaint>, paint,
223 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000224 SkIRect, center,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000225 SkRect, dst);
226RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint,
227 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000228 Optional<SkRect>, src,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000229 SkRect, dst,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000230 SkCanvas::DrawBitmapRectFlags, flags);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000231RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
232RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000233RECORD1(DrawPaint, SkPaint, paint);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000234RECORD2(DrawPath, SkPaint, paint, SkPath, path);
dandovb3c9d1c2014-08-12 08:34:29 -0700235//RECORD2(DrawPatch, SkPaint, paint, SkPatch, patch);
reedd5fa1a42014-08-09 11:08:05 -0700236RECORD3(DrawPicture, Optional<SkPaint>, paint, SkPictureBox, picture, Optional<SkMatrix>, matrix);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000237RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
238RECORD4(DrawPosText, SkPaint, paint,
239 PODArray<char>, text,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000240 size_t, byteLength,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000241 PODArray<SkPoint>, pos);
242RECORD5(DrawPosTextH, SkPaint, paint,
243 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000244 size_t, byteLength,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000245 PODArray<SkScalar>, xpos,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000246 SkScalar, y);
247RECORD2(DrawRRect, SkPaint, paint, SkRRect, rrect);
248RECORD2(DrawRect, SkPaint, paint, SkRect, rect);
249RECORD4(DrawSprite, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, int, left, int, top);
250RECORD5(DrawText, SkPaint, paint,
251 PODArray<char>, text,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000252 size_t, byteLength,
253 SkScalar, x,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000254 SkScalar, y);
255RECORD5(DrawTextOnPath, SkPaint, paint,
256 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000257 size_t, byteLength,
258 SkPath, path,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000259 Optional<SkMatrix>, matrix);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000260
261// This guy is so ugly we just write it manually.
262struct DrawVertices {
263 static const Type kType = DrawVertices_Type;
264
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000265 DrawVertices(const SkPaint& paint,
266 SkCanvas::VertexMode vmode,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000267 int vertexCount,
268 SkPoint* vertices,
269 SkPoint* texs,
270 SkColor* colors,
271 SkXfermode* xmode,
272 uint16_t* indices,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000273 int indexCount)
274 : paint(paint)
275 , vmode(vmode)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000276 , vertexCount(vertexCount)
277 , vertices(vertices)
278 , texs(texs)
279 , colors(colors)
280 , xmode(SkSafeRef(xmode))
281 , indices(indices)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000282 , indexCount(indexCount) {}
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000283
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000284 SkPaint paint;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000285 SkCanvas::VertexMode vmode;
286 int vertexCount;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000287 PODArray<SkPoint> vertices;
288 PODArray<SkPoint> texs;
289 PODArray<SkColor> colors;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000290 SkAutoTUnref<SkXfermode> xmode;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000291 PODArray<uint16_t> indices;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000292 int indexCount;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000293};
mtklein6cfa73a2014-08-13 13:33:49 -0700294
dandovb3c9d1c2014-08-12 08:34:29 -0700295struct DrawPatch {
296 static const Type kType = DrawPatch_Type;
mtklein6cfa73a2014-08-13 13:33:49 -0700297
dandovb3c9d1c2014-08-12 08:34:29 -0700298 DrawPatch(const SkPaint& paint, SkPoint cubics[12], SkColor colors[4],
299 SkPoint texCoords[4], SkXfermode* xmode)
300 : paint(paint)
301 , cubics(cubics)
302 , colors(colors)
303 , texCoords(texCoords)
304 , xmode(SkSafeRef(xmode)) { }
mtklein6cfa73a2014-08-13 13:33:49 -0700305
dandovb3c9d1c2014-08-12 08:34:29 -0700306 SkPaint paint;
307 PODArray<SkPoint> cubics;
308 PODArray<SkColor> colors;
309 PODArray<SkPoint> texCoords;
310 SkAutoTUnref<SkXfermode> xmode;
311};
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000312
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000313#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