blob: d303e9891579e109eef87ca5929d9b614502e236 [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"
reed6be2aa92014-11-18 11:08:05 -080012#include "SkCanvasDrawable.h"
reed2347b622014-08-07 12:19:50 -070013#include "SkPicture.h"
fmalita00d5c2c2014-08-21 08:53:26 -070014#include "SkTextBlob.h"
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000015
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.)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000025//
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.
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000028#define SK_RECORD_TYPES(M) \
29 M(NoOp) \
30 M(Restore) \
31 M(Save) \
32 M(SaveLayer) \
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000033 M(PushCull) \
34 M(PopCull) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000035 M(SetMatrix) \
36 M(ClipPath) \
37 M(ClipRRect) \
38 M(ClipRect) \
39 M(ClipRegion) \
40 M(Clear) \
mtklein5f0e8222014-08-22 11:44:26 -070041 M(BeginCommentGroup) \
42 M(AddComment) \
43 M(EndCommentGroup) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000044 M(DrawBitmap) \
45 M(DrawBitmapMatrix) \
46 M(DrawBitmapNine) \
47 M(DrawBitmapRectToRect) \
reed6be2aa92014-11-18 11:08:05 -080048 M(DrawDrawable) \
piotaixr65151752014-10-16 11:58:39 -070049 M(DrawImage) \
50 M(DrawImageRect) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000051 M(DrawDRRect) \
52 M(DrawOval) \
53 M(DrawPaint) \
54 M(DrawPath) \
dandov963137b2014-08-07 07:49:53 -070055 M(DrawPatch) \
reed2347b622014-08-07 12:19:50 -070056 M(DrawPicture) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000057 M(DrawPoints) \
58 M(DrawPosText) \
59 M(DrawPosTextH) \
mtkleinc551d9f2014-08-20 08:09:46 -070060 M(DrawText) \
61 M(DrawTextOnPath) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000062 M(DrawRRect) \
63 M(DrawRect) \
64 M(DrawSprite) \
mtklein29dfaa82014-09-04 14:12:44 -070065 M(DrawTextBlob) \
66 M(DrawData) \
mtkleinf4078ad2014-08-08 10:05:19 -070067 M(DrawVertices)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000068
69// Defines SkRecords::Type, an enum of all record types.
70#define ENUM(T) T##_Type,
71enum Type { SK_RECORD_TYPES(ENUM) };
72#undef ENUM
73
74// Macros to make it easier to define a record for a draw call with 0 args, 1 args, 2 args, etc.
75// These should be clearer when you look at their use below.
76#define RECORD0(T) \
77struct T { \
78 static const Type kType = T##_Type; \
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000079};
80
81// We try to be flexible about the types the constructors take. Instead of requring the exact type
82// A here, we take any type Z which implicitly casts to A. This allows the delay_copy() trick to
83// work, allowing the caller to decide whether to pass by value or by const&.
84
85#define RECORD1(T, A, a) \
86struct T { \
87 static const Type kType = T##_Type; \
88 template <typename Z> \
89 T(Z a) : a(a) {} \
90 A a; \
91};
92
93#define RECORD2(T, A, a, B, b) \
94struct T { \
95 static const Type kType = T##_Type; \
96 template <typename Z, typename Y> \
97 T(Z a, Y b) : a(a), b(b) {} \
98 A a; B b; \
99};
100
101#define RECORD3(T, A, a, B, b, C, c) \
102struct T { \
103 static const Type kType = T##_Type; \
104 template <typename Z, typename Y, typename X> \
105 T(Z a, Y b, X c) : a(a), b(b), c(c) {} \
106 A a; B b; C c; \
107};
108
109#define RECORD4(T, A, a, B, b, C, c, D, d) \
110struct T { \
111 static const Type kType = T##_Type; \
112 template <typename Z, typename Y, typename X, typename W> \
113 T(Z a, Y b, X c, W d) : a(a), b(b), c(c), d(d) {} \
114 A a; B b; C c; D d; \
115};
116
117#define RECORD5(T, A, a, B, b, C, c, D, d, E, e) \
118struct T { \
119 static const Type kType = T##_Type; \
120 template <typename Z, typename Y, typename X, typename W, typename V> \
121 T(Z a, Y b, X c, W d, V e) : a(a), b(b), c(c), d(d), e(e) {} \
122 A a; B b; C c; D d; E e; \
123};
124
mtklein9b222a52014-09-18 11:16:31 -0700125#define ACT_AS_PTR(ptr) \
126 operator T*() const { return ptr; } \
127 T* operator->() const { return ptr; }
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000128
mtklein53fecfb2014-08-21 09:11:37 -0700129template <typename T>
130class RefBox : SkNoncopyable {
131public:
mtklein9b222a52014-09-18 11:16:31 -0700132 RefBox(T* obj) : fObj(SkSafeRef(obj)) {}
133 ~RefBox() { SkSafeUnref(fObj); }
mtklein53fecfb2014-08-21 09:11:37 -0700134
135 ACT_AS_PTR(fObj);
136
137private:
138 T* fObj;
139};
140
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000141// An Optional doesn't own the pointer's memory, but may need to destroy non-POD data.
142template <typename T>
143class Optional : SkNoncopyable {
144public:
145 Optional(T* ptr) : fPtr(ptr) {}
146 ~Optional() { if (fPtr) fPtr->~T(); }
147
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000148 ACT_AS_PTR(fPtr);
149private:
150 T* fPtr;
151};
152
153// Like Optional, but ptr must not be NULL.
154template <typename T>
155class Adopted : SkNoncopyable {
156public:
157 Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); }
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000158 Adopted(Adopted* source) {
159 // Transfer ownership from source to this.
160 fPtr = source->fPtr;
161 source->fPtr = NULL;
162 }
163 ~Adopted() { if (fPtr) fPtr->~T(); }
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000164
165 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000166private:
167 T* fPtr;
168};
169
170// PODArray doesn't own the pointer's memory, and we assume the data is POD.
171template <typename T>
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000172class PODArray {
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000173public:
174 PODArray(T* ptr) : fPtr(ptr) {}
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000175 // Default copy and assign.
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000176
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000177 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000178private:
179 T* fPtr;
180};
181
commit-bot@chromium.org16307bd2014-04-22 18:32:58 +0000182#undef ACT_AS_PTR
183
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000184// Like SkBitmap, but deep copies pixels if they're not immutable.
185// Using this, we guarantee the immutability of all bitmaps we record.
mtkleinee369522014-08-27 13:02:24 -0700186class ImmutableBitmap : SkNoncopyable {
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000187public:
188 explicit ImmutableBitmap(const SkBitmap& bitmap) {
189 if (bitmap.isImmutable()) {
190 fBitmap = bitmap;
191 } else {
192 bitmap.copyTo(&fBitmap);
193 }
194 fBitmap.setImmutable();
195 }
196
197 operator const SkBitmap& () const { return fBitmap; }
198
199private:
200 SkBitmap fBitmap;
201};
202
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000203RECORD0(NoOp);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000204
mtkleina723b572014-08-15 11:49:49 -0700205RECORD2(Restore, SkIRect, devBounds, SkMatrix, matrix);
Florin Malita5f6102d2014-06-30 10:13:28 -0400206RECORD0(Save);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000207RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000208
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000209RECORD1(PushCull, SkRect, rect);
commit-bot@chromium.org03a99b82014-04-08 15:17:17 +0000210RECORD0(PopCull);
211
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000212RECORD1(SetMatrix, SkMatrix, matrix);
213
mtkleina723b572014-08-15 11:49:49 -0700214RECORD4(ClipPath, SkIRect, devBounds, SkPath, path, SkRegion::Op, op, bool, doAA);
215RECORD4(ClipRRect, SkIRect, devBounds, SkRRect, rrect, SkRegion::Op, op, bool, doAA);
216RECORD4(ClipRect, SkIRect, devBounds, SkRect, rect, SkRegion::Op, op, bool, doAA);
217RECORD3(ClipRegion, SkIRect, devBounds, SkRegion, region, SkRegion::Op, op);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000218
219RECORD1(Clear, SkColor, color);
mtklein5f0e8222014-08-22 11:44:26 -0700220
221RECORD1(BeginCommentGroup, PODArray<char>, description);
222RECORD2(AddComment, PODArray<char>, key, PODArray<char>, value);
223RECORD0(EndCommentGroup);
224
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000225// While not strictly required, if you have an SkPaint, it's fastest to put it first.
226RECORD4(DrawBitmap, Optional<SkPaint>, paint,
227 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000228 SkScalar, left,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000229 SkScalar, top);
230RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix);
231RECORD4(DrawBitmapNine, Optional<SkPaint>, paint,
232 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000233 SkIRect, center,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000234 SkRect, dst);
235RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint,
236 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000237 Optional<SkRect>, src,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000238 SkRect, dst,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000239 SkCanvas::DrawBitmapRectFlags, flags);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000240RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
reed6be2aa92014-11-18 11:08:05 -0800241RECORD2(DrawDrawable, SkRect, worstCaseBounds, int32_t, index);
piotaixr65151752014-10-16 11:58:39 -0700242RECORD4(DrawImage, Optional<SkPaint>, paint,
243 RefBox<const SkImage>, image,
244 SkScalar, left,
245 SkScalar, top);
246RECORD4(DrawImageRect, Optional<SkPaint>, paint,
247 RefBox<const SkImage>, image,
248 Optional<SkRect>, src,
249 SkRect, dst);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000250RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000251RECORD1(DrawPaint, SkPaint, paint);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000252RECORD2(DrawPath, SkPaint, paint, SkPath, path);
mtklein53fecfb2014-08-21 09:11:37 -0700253RECORD3(DrawPicture, Optional<SkPaint>, paint,
254 RefBox<const SkPicture>, picture,
255 Optional<SkMatrix>, matrix);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000256RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
257RECORD4(DrawPosText, SkPaint, paint,
258 PODArray<char>, text,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000259 size_t, byteLength,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000260 PODArray<SkPoint>, pos);
261RECORD5(DrawPosTextH, SkPaint, paint,
262 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000263 size_t, byteLength,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000264 PODArray<SkScalar>, xpos,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000265 SkScalar, y);
266RECORD2(DrawRRect, SkPaint, paint, SkRRect, rrect);
267RECORD2(DrawRect, SkPaint, paint, SkRect, rect);
268RECORD4(DrawSprite, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, int, left, int, top);
269RECORD5(DrawText, SkPaint, paint,
270 PODArray<char>, text,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000271 size_t, byteLength,
272 SkScalar, x,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000273 SkScalar, y);
fmalita00d5c2c2014-08-21 08:53:26 -0700274RECORD4(DrawTextBlob, SkPaint, paint,
mtklein53fecfb2014-08-21 09:11:37 -0700275 RefBox<const SkTextBlob>, blob,
fmalita00d5c2c2014-08-21 08:53:26 -0700276 SkScalar, x,
277 SkScalar, y);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000278RECORD5(DrawTextOnPath, SkPaint, paint,
279 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000280 size_t, byteLength,
281 SkPath, path,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000282 Optional<SkMatrix>, matrix);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000283
mtklein29dfaa82014-09-04 14:12:44 -0700284RECORD2(DrawData, PODArray<char>, data, size_t, length);
285
mtklein9b222a52014-09-18 11:16:31 -0700286RECORD5(DrawPatch, SkPaint, paint,
287 PODArray<SkPoint>, cubics,
288 PODArray<SkColor>, colors,
289 PODArray<SkPoint>, texCoords,
290 RefBox<SkXfermode>, xmode);
291
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000292// This guy is so ugly we just write it manually.
293struct DrawVertices {
294 static const Type kType = DrawVertices_Type;
295
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000296 DrawVertices(const SkPaint& paint,
297 SkCanvas::VertexMode vmode,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000298 int vertexCount,
299 SkPoint* vertices,
300 SkPoint* texs,
301 SkColor* colors,
302 SkXfermode* xmode,
303 uint16_t* indices,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000304 int indexCount)
305 : paint(paint)
306 , vmode(vmode)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000307 , vertexCount(vertexCount)
308 , vertices(vertices)
309 , texs(texs)
310 , colors(colors)
311 , xmode(SkSafeRef(xmode))
312 , indices(indices)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000313 , indexCount(indexCount) {}
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000314
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000315 SkPaint paint;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000316 SkCanvas::VertexMode vmode;
317 int vertexCount;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000318 PODArray<SkPoint> vertices;
319 PODArray<SkPoint> texs;
320 PODArray<SkColor> colors;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000321 SkAutoTUnref<SkXfermode> xmode;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000322 PODArray<uint16_t> indices;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000323 int indexCount;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000324};
mtklein6cfa73a2014-08-13 13:33:49 -0700325
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000326#undef RECORD0
327#undef RECORD1
328#undef RECORD2
329#undef RECORD3
330#undef RECORD4
331#undef RECORD5
332
333} // namespace SkRecords
334
335#endif//SkRecords_DEFINED