2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkRecords_DEFINED
9 #define SkRecords_DEFINED
12 #include "SkPicture.h"
13 #include "SkTextBlob.h"
17 // A list of all the types of canvas calls we can record.
18 // Each of these is reified into a struct below.
20 // (We're using the macro-of-macro trick here to do several different things with the same list.)
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.)
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.
27 #define SK_RECORD_TYPES(M) \
40 M(BeginCommentGroup) \
46 M(DrawBitmapRectToRect) \
67 // Defines SkRecords::Type, an enum of all record types.
68 #define ENUM(T) T##_Type,
69 enum Type { SK_RECORD_TYPES(ENUM) };
72 // Macros to make it easier to define a record for a draw call with 0 args, 1 args, 2 args, etc.
73 // These should be clearer when you look at their use below.
76 static const Type kType = T##_Type; \
79 // We try to be flexible about the types the constructors take. Instead of requring the exact type
80 // A here, we take any type Z which implicitly casts to A. This allows the delay_copy() trick to
81 // work, allowing the caller to decide whether to pass by value or by const&.
83 #define RECORD1(T, A, a) \
85 static const Type kType = T##_Type; \
86 template <typename Z> \
91 #define RECORD2(T, A, a, B, b) \
93 static const Type kType = T##_Type; \
94 template <typename Z, typename Y> \
95 T(Z a, Y b) : a(a), b(b) {} \
99 #define RECORD3(T, A, a, B, b, C, c) \
101 static const Type kType = T##_Type; \
102 template <typename Z, typename Y, typename X> \
103 T(Z a, Y b, X c) : a(a), b(b), c(c) {} \
107 #define RECORD4(T, A, a, B, b, C, c, D, d) \
109 static const Type kType = T##_Type; \
110 template <typename Z, typename Y, typename X, typename W> \
111 T(Z a, Y b, X c, W d) : a(a), b(b), c(c), d(d) {} \
112 A a; B b; C c; D d; \
115 #define RECORD5(T, A, a, B, b, C, c, D, d, E, e) \
117 static const Type kType = T##_Type; \
118 template <typename Z, typename Y, typename X, typename W, typename V> \
119 T(Z a, Y b, X c, W d, V e) : a(a), b(b), c(c), d(d), e(e) {} \
120 A a; B b; C c; D d; E e; \
123 #define ACT_AS_PTR(ptr) \
124 operator T*() const { return ptr; } \
125 T* operator->() const { return ptr; }
127 template <typename T>
128 class RefBox : SkNoncopyable {
130 RefBox(T* obj) : fObj(SkSafeRef(obj)) {}
131 ~RefBox() { SkSafeUnref(fObj); }
139 // An Optional doesn't own the pointer's memory, but may need to destroy non-POD data.
140 template <typename T>
141 class Optional : SkNoncopyable {
143 Optional(T* ptr) : fPtr(ptr) {}
144 ~Optional() { if (fPtr) fPtr->~T(); }
151 // Like Optional, but ptr must not be NULL.
152 template <typename T>
153 class Adopted : SkNoncopyable {
155 Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); }
156 Adopted(Adopted* source) {
157 // Transfer ownership from source to this.
161 ~Adopted() { if (fPtr) fPtr->~T(); }
168 // PODArray doesn't own the pointer's memory, and we assume the data is POD.
169 template <typename T>
172 PODArray(T* ptr) : fPtr(ptr) {}
173 // Default copy and assign.
182 // Like SkBitmap, but deep copies pixels if they're not immutable.
183 // Using this, we guarantee the immutability of all bitmaps we record.
184 class ImmutableBitmap : SkNoncopyable {
186 explicit ImmutableBitmap(const SkBitmap& bitmap) {
187 if (bitmap.isImmutable()) {
190 bitmap.copyTo(&fBitmap);
192 fBitmap.setImmutable();
195 operator const SkBitmap& () const { return fBitmap; }
203 RECORD2(Restore, SkIRect, devBounds, SkMatrix, matrix);
205 RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags);
207 RECORD1(PushCull, SkRect, rect);
210 RECORD1(SetMatrix, SkMatrix, matrix);
212 RECORD4(ClipPath, SkIRect, devBounds, SkPath, path, SkRegion::Op, op, bool, doAA);
213 RECORD4(ClipRRect, SkIRect, devBounds, SkRRect, rrect, SkRegion::Op, op, bool, doAA);
214 RECORD4(ClipRect, SkIRect, devBounds, SkRect, rect, SkRegion::Op, op, bool, doAA);
215 RECORD3(ClipRegion, SkIRect, devBounds, SkRegion, region, SkRegion::Op, op);
217 RECORD1(Clear, SkColor, color);
219 RECORD1(BeginCommentGroup, PODArray<char>, description);
220 RECORD2(AddComment, PODArray<char>, key, PODArray<char>, value);
221 RECORD0(EndCommentGroup);
223 // While not strictly required, if you have an SkPaint, it's fastest to put it first.
224 RECORD4(DrawBitmap, Optional<SkPaint>, paint,
225 ImmutableBitmap, bitmap,
228 RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix);
229 RECORD4(DrawBitmapNine, Optional<SkPaint>, paint,
230 ImmutableBitmap, bitmap,
233 RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint,
234 ImmutableBitmap, bitmap,
235 Optional<SkRect>, src,
237 SkCanvas::DrawBitmapRectFlags, flags);
238 RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
239 RECORD4(DrawImage, Optional<SkPaint>, paint,
240 RefBox<const SkImage>, image,
243 RECORD4(DrawImageRect, Optional<SkPaint>, paint,
244 RefBox<const SkImage>, image,
245 Optional<SkRect>, src,
247 RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
248 RECORD1(DrawPaint, SkPaint, paint);
249 RECORD2(DrawPath, SkPaint, paint, SkPath, path);
250 RECORD3(DrawPicture, Optional<SkPaint>, paint,
251 RefBox<const SkPicture>, picture,
252 Optional<SkMatrix>, matrix);
253 RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
254 RECORD4(DrawPosText, SkPaint, paint,
255 PODArray<char>, text,
257 PODArray<SkPoint>, pos);
258 RECORD5(DrawPosTextH, SkPaint, paint,
259 PODArray<char>, text,
261 PODArray<SkScalar>, xpos,
263 RECORD2(DrawRRect, SkPaint, paint, SkRRect, rrect);
264 RECORD2(DrawRect, SkPaint, paint, SkRect, rect);
265 RECORD4(DrawSprite, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, int, left, int, top);
266 RECORD5(DrawText, SkPaint, paint,
267 PODArray<char>, text,
271 RECORD4(DrawTextBlob, SkPaint, paint,
272 RefBox<const SkTextBlob>, blob,
275 RECORD5(DrawTextOnPath, SkPaint, paint,
276 PODArray<char>, text,
279 Optional<SkMatrix>, matrix);
281 RECORD2(DrawData, PODArray<char>, data, size_t, length);
283 RECORD5(DrawPatch, SkPaint, paint,
284 PODArray<SkPoint>, cubics,
285 PODArray<SkColor>, colors,
286 PODArray<SkPoint>, texCoords,
287 RefBox<SkXfermode>, xmode);
289 // This guy is so ugly we just write it manually.
290 struct DrawVertices {
291 static const Type kType = DrawVertices_Type;
293 DrawVertices(const SkPaint& paint,
294 SkCanvas::VertexMode vmode,
304 , vertexCount(vertexCount)
308 , xmode(SkSafeRef(xmode))
310 , indexCount(indexCount) {}
313 SkCanvas::VertexMode vmode;
315 PODArray<SkPoint> vertices;
316 PODArray<SkPoint> texs;
317 PODArray<SkColor> colors;
318 SkAutoTUnref<SkXfermode> xmode;
319 PODArray<uint16_t> indices;
330 } // namespace SkRecords
332 #endif//SkRecords_DEFINED