blob: 6baabe6b7655de5a8199ae5b32aa5906efc9feef [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
fmalita00d5c2c2014-08-21 08:53:26 -070017template <typename T>
18class RefBox : SkNoncopyable {
19public:
20 RefBox(const T* obj) : fObj(SkRef(obj)) {}
21 ~RefBox() { fObj->unref(); }
22
23 operator const T*() const { return fObj; }
24
25private:
26 const T* fObj;
27};
28
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000029// A list of all the types of canvas calls we can record.
30// Each of these is reified into a struct below.
31//
32// (We're using the macro-of-macro trick here to do several different things with the same list.)
33//
34// We leave this SK_RECORD_TYPES macro defined for use by code that wants to operate on SkRecords
35// types polymorphically. (See SkRecord::Record::{visit,mutate} for an example.)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000036//
37// Order doesn't technically matter here, but the compiler can generally generate better code if
38// 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 +000039#define SK_RECORD_TYPES(M) \
40 M(NoOp) \
41 M(Restore) \
42 M(Save) \
43 M(SaveLayer) \
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000044 M(PushCull) \
45 M(PopCull) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000046 M(SetMatrix) \
47 M(ClipPath) \
48 M(ClipRRect) \
49 M(ClipRect) \
50 M(ClipRegion) \
51 M(Clear) \
52 M(DrawBitmap) \
53 M(DrawBitmapMatrix) \
54 M(DrawBitmapNine) \
55 M(DrawBitmapRectToRect) \
56 M(DrawDRRect) \
57 M(DrawOval) \
58 M(DrawPaint) \
59 M(DrawPath) \
dandov963137b2014-08-07 07:49:53 -070060 M(DrawPatch) \
reed2347b622014-08-07 12:19:50 -070061 M(DrawPicture) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000062 M(DrawPoints) \
63 M(DrawPosText) \
64 M(DrawPosTextH) \
mtkleinc551d9f2014-08-20 08:09:46 -070065 M(DrawText) \
66 M(DrawTextOnPath) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000067 M(DrawRRect) \
68 M(DrawRect) \
69 M(DrawSprite) \
fmalita00d5c2c2014-08-21 08:53:26 -070070 M(DrawTextBlob) \
mtkleinf4078ad2014-08-08 10:05:19 -070071 M(DrawVertices)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000072
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; \
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000083};
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
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000129#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
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000135// 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
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000142 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); }
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000152 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(); }
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000158
159 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000160private:
161 T* fPtr;
162};
163
164// PODArray doesn't own the pointer's memory, and we assume the data is POD.
165template <typename T>
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000166class PODArray {
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000167public:
168 PODArray(T* ptr) : fPtr(ptr) {}
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000169 // Default copy and assign.
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000170
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000171 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000172private:
173 T* fPtr;
174};
175
commit-bot@chromium.org16307bd2014-04-22 18:32:58 +0000176#undef ACT_AS_PTR
177
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000178// 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
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000197RECORD0(NoOp);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000198
mtkleina723b572014-08-15 11:49:49 -0700199RECORD2(Restore, SkIRect, devBounds, SkMatrix, matrix);
Florin Malita5f6102d2014-06-30 10:13:28 -0400200RECORD0(Save);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000201RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000202
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000203RECORD1(PushCull, SkRect, rect);
commit-bot@chromium.org03a99b82014-04-08 15:17:17 +0000204RECORD0(PopCull);
205
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000206RECORD1(SetMatrix, SkMatrix, matrix);
207
mtkleina723b572014-08-15 11:49:49 -0700208RECORD4(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);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000212
213RECORD1(Clear, SkColor, color);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000214// While not strictly required, if you have an SkPaint, it's fastest to put it first.
215RECORD4(DrawBitmap, Optional<SkPaint>, paint,
216 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000217 SkScalar, left,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000218 SkScalar, top);
219RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix);
220RECORD4(DrawBitmapNine, Optional<SkPaint>, paint,
221 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000222 SkIRect, center,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000223 SkRect, dst);
224RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint,
225 ImmutableBitmap, bitmap,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000226 Optional<SkRect>, src,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000227 SkRect, dst,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000228 SkCanvas::DrawBitmapRectFlags, flags);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000229RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
230RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000231RECORD1(DrawPaint, SkPaint, paint);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000232RECORD2(DrawPath, SkPaint, paint, SkPath, path);
dandovb3c9d1c2014-08-12 08:34:29 -0700233//RECORD2(DrawPatch, SkPaint, paint, SkPatch, patch);
fmalita00d5c2c2014-08-21 08:53:26 -0700234RECORD3(DrawPicture, Optional<SkPaint>, paint, RefBox<SkPicture>, picture, Optional<SkMatrix>, matrix);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000235RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
236RECORD4(DrawPosText, SkPaint, paint,
237 PODArray<char>, text,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000238 size_t, byteLength,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000239 PODArray<SkPoint>, pos);
240RECORD5(DrawPosTextH, SkPaint, paint,
241 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000242 size_t, byteLength,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000243 PODArray<SkScalar>, xpos,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000244 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,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000250 size_t, byteLength,
251 SkScalar, x,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000252 SkScalar, y);
fmalita00d5c2c2014-08-21 08:53:26 -0700253RECORD4(DrawTextBlob, SkPaint, paint,
254 RefBox<SkTextBlob>, blob,
255 SkScalar, x,
256 SkScalar, y);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000257RECORD5(DrawTextOnPath, SkPaint, paint,
258 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000259 size_t, byteLength,
260 SkPath, path,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000261 Optional<SkMatrix>, matrix);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000262
263// This guy is so ugly we just write it manually.
264struct DrawVertices {
265 static const Type kType = DrawVertices_Type;
266
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000267 DrawVertices(const SkPaint& paint,
268 SkCanvas::VertexMode vmode,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000269 int vertexCount,
270 SkPoint* vertices,
271 SkPoint* texs,
272 SkColor* colors,
273 SkXfermode* xmode,
274 uint16_t* indices,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000275 int indexCount)
276 : paint(paint)
277 , vmode(vmode)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000278 , vertexCount(vertexCount)
279 , vertices(vertices)
280 , texs(texs)
281 , colors(colors)
282 , xmode(SkSafeRef(xmode))
283 , indices(indices)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000284 , indexCount(indexCount) {}
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000285
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000286 SkPaint paint;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000287 SkCanvas::VertexMode vmode;
288 int vertexCount;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000289 PODArray<SkPoint> vertices;
290 PODArray<SkPoint> texs;
291 PODArray<SkColor> colors;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000292 SkAutoTUnref<SkXfermode> xmode;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000293 PODArray<uint16_t> indices;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000294 int indexCount;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000295};
mtklein6cfa73a2014-08-13 13:33:49 -0700296
dandovb3c9d1c2014-08-12 08:34:29 -0700297struct DrawPatch {
298 static const Type kType = DrawPatch_Type;
mtklein6cfa73a2014-08-13 13:33:49 -0700299
dandovb3c9d1c2014-08-12 08:34:29 -0700300 DrawPatch(const SkPaint& paint, SkPoint cubics[12], SkColor colors[4],
301 SkPoint texCoords[4], SkXfermode* xmode)
302 : paint(paint)
303 , cubics(cubics)
304 , colors(colors)
305 , texCoords(texCoords)
306 , xmode(SkSafeRef(xmode)) { }
mtklein6cfa73a2014-08-13 13:33:49 -0700307
dandovb3c9d1c2014-08-12 08:34:29 -0700308 SkPaint paint;
309 PODArray<SkPoint> cubics;
310 PODArray<SkColor> colors;
311 PODArray<SkPoint> texCoords;
312 SkAutoTUnref<SkXfermode> xmode;
313};
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000314
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000315#undef RECORD0
316#undef RECORD1
317#undef RECORD2
318#undef RECORD3
319#undef RECORD4
320#undef RECORD5
321
322} // namespace SkRecords
323
324#endif//SkRecords_DEFINED