blob: 1de16754528c408ec195657ff5fd8c60240a19f3 [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)) {}
17 SkPictureBox(const SkPictureBox& src) : fObj(SkRef(src.fObj)) {}
18 ~SkPictureBox() { fObj->unref(); }
19
20 SkPictureBox& operator=(const SkPictureBox& src) {
21 SkRefCnt_SafeAssign(fObj, src.fObj);
22 return *this;
23 }
24
25 operator const SkPicture*() const { return fObj; }
26
27private:
28 const SkPicture* fObj;
29};
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000030
31namespace SkRecords {
32
33// A list of all the types of canvas calls we can record.
34// Each of these is reified into a struct below.
35//
36// (We're using the macro-of-macro trick here to do several different things with the same list.)
37//
38// We leave this SK_RECORD_TYPES macro defined for use by code that wants to operate on SkRecords
39// types polymorphically. (See SkRecord::Record::{visit,mutate} for an example.)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000040//
41// Order doesn't technically matter here, but the compiler can generally generate better code if
42// 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 +000043#define SK_RECORD_TYPES(M) \
44 M(NoOp) \
45 M(Restore) \
46 M(Save) \
47 M(SaveLayer) \
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000048 M(PushCull) \
49 M(PopCull) \
50 M(PairedPushCull) /*From SkRecordAnnotateCullingPairs*/ \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000051 M(Concat) \
52 M(SetMatrix) \
53 M(ClipPath) \
54 M(ClipRRect) \
55 M(ClipRect) \
56 M(ClipRegion) \
57 M(Clear) \
58 M(DrawBitmap) \
59 M(DrawBitmapMatrix) \
60 M(DrawBitmapNine) \
61 M(DrawBitmapRectToRect) \
62 M(DrawDRRect) \
63 M(DrawOval) \
64 M(DrawPaint) \
65 M(DrawPath) \
dandov963137b2014-08-07 07:49:53 -070066 M(DrawPatch) \
reed2347b622014-08-07 12:19:50 -070067 M(DrawPicture) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000068 M(DrawPoints) \
69 M(DrawPosText) \
70 M(DrawPosTextH) \
71 M(DrawRRect) \
72 M(DrawRect) \
73 M(DrawSprite) \
74 M(DrawText) \
75 M(DrawTextOnPath) \
76 M(DrawVertices) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000077 M(BoundedDrawPosTextH) /*From SkRecordBoundDrawPosTextH*/
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000078
79// Defines SkRecords::Type, an enum of all record types.
80#define ENUM(T) T##_Type,
81enum Type { SK_RECORD_TYPES(ENUM) };
82#undef ENUM
83
84// Macros to make it easier to define a record for a draw call with 0 args, 1 args, 2 args, etc.
85// These should be clearer when you look at their use below.
86#define RECORD0(T) \
87struct T { \
88 static const Type kType = T##_Type; \
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000089};
90
91// We try to be flexible about the types the constructors take. Instead of requring the exact type
92// A here, we take any type Z which implicitly casts to A. This allows the delay_copy() trick to
93// work, allowing the caller to decide whether to pass by value or by const&.
94
95#define RECORD1(T, A, a) \
96struct T { \
97 static const Type kType = T##_Type; \
98 template <typename Z> \
99 T(Z a) : a(a) {} \
100 A a; \
101};
102
103#define RECORD2(T, A, a, B, b) \
104struct T { \
105 static const Type kType = T##_Type; \
106 template <typename Z, typename Y> \
107 T(Z a, Y b) : a(a), b(b) {} \
108 A a; B b; \
109};
110
111#define RECORD3(T, A, a, B, b, C, c) \
112struct T { \
113 static const Type kType = T##_Type; \
114 template <typename Z, typename Y, typename X> \
115 T(Z a, Y b, X c) : a(a), b(b), c(c) {} \
116 A a; B b; C c; \
117};
118
119#define RECORD4(T, A, a, B, b, C, c, D, d) \
120struct T { \
121 static const Type kType = T##_Type; \
122 template <typename Z, typename Y, typename X, typename W> \
123 T(Z a, Y b, X c, W d) : a(a), b(b), c(c), d(d) {} \
124 A a; B b; C c; D d; \
125};
126
127#define RECORD5(T, A, a, B, b, C, c, D, d, E, e) \
128struct T { \
129 static const Type kType = T##_Type; \
130 template <typename Z, typename Y, typename X, typename W, typename V> \
131 T(Z a, Y b, X c, W d, V e) : a(a), b(b), c(c), d(d), e(e) {} \
132 A a; B b; C c; D d; E e; \
133};
134
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000135#define ACT_AS_PTR(ptr) \
136 operator T*() { return ptr; } \
137 operator const T*() const { return ptr; } \
138 T* operator->() { return ptr; } \
139 const T* operator->() const { return ptr; }
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.
186class ImmutableBitmap {
187public:
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
205RECORD0(Restore);
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(Concat, SkMatrix, matrix);
213RECORD1(SetMatrix, SkMatrix, matrix);
214
215RECORD3(ClipPath, SkPath, path, SkRegion::Op, op, bool, doAA);
216RECORD3(ClipRRect, SkRRect, rrect, SkRegion::Op, op, bool, doAA);
217RECORD3(ClipRect, SkRect, rect, SkRegion::Op, op, bool, doAA);
218RECORD2(ClipRegion, SkRegion, region, SkRegion::Op, op);
219
220RECORD1(Clear, SkColor, color);
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);
dandov963137b2014-08-07 07:49:53 -0700240RECORD2(DrawPatch, SkPaint, paint, SkPatch, patch);
reed2347b622014-08-07 12:19:50 -0700241RECORD1(DrawPicture, SkPictureBox, picture);
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000242RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
243RECORD4(DrawPosText, SkPaint, paint,
244 PODArray<char>, text,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000245 size_t, byteLength,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000246 PODArray<SkPoint>, pos);
247RECORD5(DrawPosTextH, SkPaint, paint,
248 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000249 size_t, byteLength,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000250 PODArray<SkScalar>, xpos,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000251 SkScalar, y);
252RECORD2(DrawRRect, SkPaint, paint, SkRRect, rrect);
253RECORD2(DrawRect, SkPaint, paint, SkRect, rect);
254RECORD4(DrawSprite, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, int, left, int, top);
255RECORD5(DrawText, SkPaint, paint,
256 PODArray<char>, text,
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000257 size_t, byteLength,
258 SkScalar, x,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000259 SkScalar, y);
260RECORD5(DrawTextOnPath, SkPaint, paint,
261 PODArray<char>, text,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000262 size_t, byteLength,
263 SkPath, path,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000264 Optional<SkMatrix>, matrix);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000265
266// This guy is so ugly we just write it manually.
267struct DrawVertices {
268 static const Type kType = DrawVertices_Type;
269
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000270 DrawVertices(const SkPaint& paint,
271 SkCanvas::VertexMode vmode,
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000272 int vertexCount,
273 SkPoint* vertices,
274 SkPoint* texs,
275 SkColor* colors,
276 SkXfermode* xmode,
277 uint16_t* indices,
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000278 int indexCount)
279 : paint(paint)
280 , vmode(vmode)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000281 , vertexCount(vertexCount)
282 , vertices(vertices)
283 , texs(texs)
284 , colors(colors)
285 , xmode(SkSafeRef(xmode))
286 , indices(indices)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000287 , indexCount(indexCount) {}
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000288
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000289 SkPaint paint;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000290 SkCanvas::VertexMode vmode;
291 int vertexCount;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000292 PODArray<SkPoint> vertices;
293 PODArray<SkPoint> texs;
294 PODArray<SkColor> colors;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000295 SkAutoTUnref<SkXfermode> xmode;
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000296 PODArray<uint16_t> indices;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000297 int indexCount;
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000298};
299
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000300// Records added by optimizations.
301RECORD2(PairedPushCull, Adopted<PushCull>, base, unsigned, skip);
302RECORD3(BoundedDrawPosTextH, Adopted<DrawPosTextH>, base, SkScalar, minY, SkScalar, maxY);
303
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000304#undef RECORD0
305#undef RECORD1
306#undef RECORD2
307#undef RECORD3
308#undef RECORD4
309#undef RECORD5
310
311} // namespace SkRecords
312
313#endif//SkRecords_DEFINED