blob: c06d276cfaa2e4a6a3ce4835030a41f785e9cc81 [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"
fmalita00d5c2c2014-08-21 08:53:26 -070013#include "SkTextBlob.h"
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000014
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.)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000024//
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.
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000027#define SK_RECORD_TYPES(M) \
28 M(NoOp) \
29 M(Restore) \
30 M(Save) \
31 M(SaveLayer) \
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000032 M(PushCull) \
33 M(PopCull) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000034 M(SetMatrix) \
35 M(ClipPath) \
36 M(ClipRRect) \
37 M(ClipRect) \
38 M(ClipRegion) \
39 M(Clear) \
mtklein5f0e8222014-08-22 11:44:26 -070040 M(BeginCommentGroup) \
41 M(AddComment) \
42 M(EndCommentGroup) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000043 M(DrawBitmap) \
44 M(DrawBitmapMatrix) \
45 M(DrawBitmapNine) \
46 M(DrawBitmapRectToRect) \
47 M(DrawDRRect) \
48 M(DrawOval) \
49 M(DrawPaint) \
50 M(DrawPath) \
dandov963137b2014-08-07 07:49:53 -070051 M(DrawPatch) \
reed2347b622014-08-07 12:19:50 -070052 M(DrawPicture) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000053 M(DrawPoints) \
54 M(DrawPosText) \
55 M(DrawPosTextH) \
mtkleinc551d9f2014-08-20 08:09:46 -070056 M(DrawText) \
57 M(DrawTextOnPath) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000058 M(DrawRRect) \
59 M(DrawRect) \
60 M(DrawSprite) \
mtklein29dfaa82014-09-04 14:12:44 -070061 M(DrawTextBlob) \
62 M(DrawData) \
mtkleinf4078ad2014-08-08 10:05:19 -070063 M(DrawVertices)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000064
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; \
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000075};
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
mtklein9b222a52014-09-18 11:16:31 -0700121#define ACT_AS_PTR(ptr) \
122 operator T*() const { return ptr; } \
123 T* operator->() const { return ptr; }
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000124
mtklein53fecfb2014-08-21 09:11:37 -0700125template <typename T>
126class RefBox : SkNoncopyable {
127public:
mtklein9b222a52014-09-18 11:16:31 -0700128 RefBox(T* obj) : fObj(SkSafeRef(obj)) {}
129 ~RefBox() { SkSafeUnref(fObj); }
mtklein53fecfb2014-08-21 09:11:37 -0700130
131 ACT_AS_PTR(fObj);
132
133private:
134 T* fObj;
135};
136
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000137// 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
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000144 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); }
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000154 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(); }
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000160
161 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000162private:
163 T* fPtr;
164};
165
166// PODArray doesn't own the pointer's memory, and we assume the data is POD.
167template <typename T>
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000168class PODArray {
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000169public:
170 PODArray(T* ptr) : fPtr(ptr) {}
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000171 // Default copy and assign.
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000172
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000173 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000174private:
175 T* fPtr;
176};
177
commit-bot@chromium.org16307bd2014-04-22 18:32:58 +0000178#undef ACT_AS_PTR
179
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000180// Like SkBitmap, but deep copies pixels if they're not immutable.
181// Using this, we guarantee the immutability of all bitmaps we record.
mtkleinee369522014-08-27 13:02:24 -0700182class ImmutableBitmap : SkNoncopyable {
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000183public:
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
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000199RECORD0(NoOp);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000200
mtkleina723b572014-08-15 11:49:49 -0700201RECORD2(Restore, SkIRect, devBounds, SkMatrix, matrix);
Florin Malita5f6102d2014-06-30 10:13:28 -0400202RECORD0(Save);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000203RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000204
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000205RECORD1(PushCull, SkRect, rect);
commit-bot@chromium.org03a99b82014-04-08 15:17:17 +0000206RECORD0(PopCull);
207
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000208RECORD1(SetMatrix, SkMatrix, matrix);
209
mtkleina723b572014-08-15 11:49:49 -0700210RECORD4(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);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000214
215RECORD1(Clear, SkColor, color);
mtklein5f0e8222014-08-22 11:44:26 -0700216
217RECORD1(BeginCommentGroup, PODArray<char>, description);
218RECORD2(AddComment, PODArray<char>, key, PODArray<char>, value);
219RECORD0(EndCommentGroup);
220
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000221// While not strictly required, if you have an SkPaint, it's fastest to put it first.
222RECORD4(DrawBitmap, Optional<SkPaint>, paint,
223 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000224 SkScalar, left,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000225 SkScalar, top);
226RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix);
227RECORD4(DrawBitmapNine, Optional<SkPaint>, paint,
228 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000229 SkIRect, center,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000230 SkRect, dst);
231RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint,
232 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000233 Optional<SkRect>, src,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000234 SkRect, dst,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000235 SkCanvas::DrawBitmapRectFlags, flags);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000236RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
237RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000238RECORD1(DrawPaint, SkPaint, paint);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000239RECORD2(DrawPath, SkPaint, paint, SkPath, path);
mtklein53fecfb2014-08-21 09:11:37 -0700240RECORD3(DrawPicture, Optional<SkPaint>, paint,
241 RefBox<const SkPicture>, picture,
242 Optional<SkMatrix>, matrix);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000243RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
244RECORD4(DrawPosText, SkPaint, paint,
245 PODArray<char>, text,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000246 size_t, byteLength,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000247 PODArray<SkPoint>, pos);
248RECORD5(DrawPosTextH, SkPaint, paint,
249 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000250 size_t, byteLength,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000251 PODArray<SkScalar>, xpos,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000252 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,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000258 size_t, byteLength,
259 SkScalar, x,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000260 SkScalar, y);
fmalita00d5c2c2014-08-21 08:53:26 -0700261RECORD4(DrawTextBlob, SkPaint, paint,
mtklein53fecfb2014-08-21 09:11:37 -0700262 RefBox<const SkTextBlob>, blob,
fmalita00d5c2c2014-08-21 08:53:26 -0700263 SkScalar, x,
264 SkScalar, y);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000265RECORD5(DrawTextOnPath, SkPaint, paint,
266 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000267 size_t, byteLength,
268 SkPath, path,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000269 Optional<SkMatrix>, matrix);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000270
mtklein29dfaa82014-09-04 14:12:44 -0700271RECORD2(DrawData, PODArray<char>, data, size_t, length);
272
mtklein9b222a52014-09-18 11:16:31 -0700273RECORD5(DrawPatch, SkPaint, paint,
274 PODArray<SkPoint>, cubics,
275 PODArray<SkColor>, colors,
276 PODArray<SkPoint>, texCoords,
277 RefBox<SkXfermode>, xmode);
278
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000279// This guy is so ugly we just write it manually.
280struct DrawVertices {
281 static const Type kType = DrawVertices_Type;
282
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000283 DrawVertices(const SkPaint& paint,
284 SkCanvas::VertexMode vmode,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000285 int vertexCount,
286 SkPoint* vertices,
287 SkPoint* texs,
288 SkColor* colors,
289 SkXfermode* xmode,
290 uint16_t* indices,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000291 int indexCount)
292 : paint(paint)
293 , vmode(vmode)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000294 , vertexCount(vertexCount)
295 , vertices(vertices)
296 , texs(texs)
297 , colors(colors)
298 , xmode(SkSafeRef(xmode))
299 , indices(indices)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000300 , indexCount(indexCount) {}
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000301
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000302 SkPaint paint;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000303 SkCanvas::VertexMode vmode;
304 int vertexCount;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000305 PODArray<SkPoint> vertices;
306 PODArray<SkPoint> texs;
307 PODArray<SkColor> colors;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000308 SkAutoTUnref<SkXfermode> xmode;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000309 PODArray<uint16_t> indices;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000310 int indexCount;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000311};
mtklein6cfa73a2014-08-13 13:33:49 -0700312
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