1 /* 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 8 #ifndef SkRecords_DEFINED 9 #define SkRecords_DEFINED 10 11 #include "SkCanvas.h" 12 13 namespace SkRecords { 14 15 // A list of all the types of canvas calls we can record. 16 // Each of these is reified into a struct below. 17 // 18 // (We're using the macro-of-macro trick here to do several different things with the same list.) 19 // 20 // We leave this SK_RECORD_TYPES macro defined for use by code that wants to operate on SkRecords 21 // types polymorphically. (See SkRecord::Record::{visit,mutate} for an example.) 22 // 23 // Order doesn't technically matter here, but the compiler can generally generate better code if 24 // you keep them semantically grouped, especially the Draws. It's also nice to leave NoOp at 0. 25 #define SK_RECORD_TYPES(M) \ 26 M(NoOp) \ 27 M(Restore) \ 28 M(Save) \ 29 M(SaveLayer) \ 30 M(PushCull) \ 31 M(PopCull) \ 32 M(PairedPushCull) /*From SkRecordAnnotateCullingPairs*/ \ 33 M(Concat) \ 34 M(SetMatrix) \ 35 M(ClipPath) \ 36 M(ClipRRect) \ 37 M(ClipRect) \ 38 M(ClipRegion) \ 39 M(Clear) \ 40 M(DrawBitmap) \ 41 M(DrawBitmapMatrix) \ 42 M(DrawBitmapNine) \ 43 M(DrawBitmapRectToRect) \ 44 M(DrawDRRect) \ 45 M(DrawOval) \ 46 M(DrawPaint) \ 47 M(DrawPath) \ 48 M(DrawPoints) \ 49 M(DrawPosText) \ 50 M(DrawPosTextH) \ 51 M(DrawRRect) \ 52 M(DrawRect) \ 53 M(DrawSprite) \ 54 M(DrawText) \ 55 M(DrawTextOnPath) \ 56 M(DrawVertices) \ 57 M(BoundedDrawPosTextH) /*From SkRecordBoundDrawPosTextH*/ 58 59 // Defines SkRecords::Type, an enum of all record types. 60 #define ENUM(T) T##_Type, 61 enum Type { SK_RECORD_TYPES(ENUM) }; 62 #undef ENUM 63 64 // Macros to make it easier to define a record for a draw call with 0 args, 1 args, 2 args, etc. 65 // These should be clearer when you look at their use below. 66 #define RECORD0(T) \ 67 struct T { \ 68 static const Type kType = T##_Type; \ 69 }; 70 71 // We try to be flexible about the types the constructors take. Instead of requring the exact type 72 // A here, we take any type Z which implicitly casts to A. This allows the delay_copy() trick to 73 // work, allowing the caller to decide whether to pass by value or by const&. 74 75 #define RECORD1(T, A, a) \ 76 struct T { \ 77 static const Type kType = T##_Type; \ 78 template <typename Z> \ 79 T(Z a) : a(a) {} \ 80 A a; \ 81 }; 82 83 #define RECORD2(T, A, a, B, b) \ 84 struct T { \ 85 static const Type kType = T##_Type; \ 86 template <typename Z, typename Y> \ 87 T(Z a, Y b) : a(a), b(b) {} \ 88 A a; B b; \ 89 }; 90 91 #define RECORD3(T, A, a, B, b, C, c) \ 92 struct T { \ 93 static const Type kType = T##_Type; \ 94 template <typename Z, typename Y, typename X> \ 95 T(Z a, Y b, X c) : a(a), b(b), c(c) {} \ 96 A a; B b; C c; \ 97 }; 98 99 #define RECORD4(T, A, a, B, b, C, c, D, d) \ 100 struct T { \ 101 static const Type kType = T##_Type; \ 102 template <typename Z, typename Y, typename X, typename W> \ 103 T(Z a, Y b, X c, W d) : a(a), b(b), c(c), d(d) {} \ 104 A a; B b; C c; D d; \ 105 }; 106 107 #define RECORD5(T, A, a, B, b, C, c, D, d, E, e) \ 108 struct T { \ 109 static const Type kType = T##_Type; \ 110 template <typename Z, typename Y, typename X, typename W, typename V> \ 111 T(Z a, Y b, X c, W d, V e) : a(a), b(b), c(c), d(d), e(e) {} \ 112 A a; B b; C c; D d; E e; \ 113 }; 114 115 #define ACT_AS_PTR(ptr) \ 116 operator T*() { return ptr; } \ 117 operator const T*() const { return ptr; } \ 118 T* operator->() { return ptr; } \ 119 const T* operator->() const { return ptr; } 120 121 // An Optional doesn't own the pointer's memory, but may need to destroy non-POD data. 122 template <typename T> 123 class Optional : SkNoncopyable { 124 public: 125 Optional(T* ptr) : fPtr(ptr) {} 126 ~Optional() { if (fPtr) fPtr->~T(); } 127 128 ACT_AS_PTR(fPtr); 129 private: 130 T* fPtr; 131 }; 132 133 // Like Optional, but ptr must not be NULL. 134 template <typename T> 135 class Adopted : SkNoncopyable { 136 public: 137 Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); } 138 Adopted(Adopted* source) { 139 // Transfer ownership from source to this. 140 fPtr = source->fPtr; 141 source->fPtr = NULL; 142 } 143 ~Adopted() { if (fPtr) fPtr->~T(); } 144 145 ACT_AS_PTR(fPtr); 146 private: 147 T* fPtr; 148 }; 149 150 // PODArray doesn't own the pointer's memory, and we assume the data is POD. 151 template <typename T> 152 class PODArray { 153 public: 154 PODArray(T* ptr) : fPtr(ptr) {} 155 // Default copy and assign. 156 157 ACT_AS_PTR(fPtr); 158 private: 159 T* fPtr; 160 }; 161 162 #undef ACT_AS_PTR 163 164 // Like SkBitmap, but deep copies pixels if they're not immutable. 165 // Using this, we guarantee the immutability of all bitmaps we record. 166 class ImmutableBitmap { 167 public: 168 explicit ImmutableBitmap(const SkBitmap& bitmap) { 169 if (bitmap.isImmutable()) { 170 fBitmap = bitmap; 171 } else { 172 bitmap.copyTo(&fBitmap); 173 } 174 fBitmap.setImmutable(); 175 } 176 177 operator const SkBitmap& () const { return fBitmap; } 178 179 private: 180 SkBitmap fBitmap; 181 }; 182 183 RECORD0(NoOp); 184 185 RECORD0(Restore); 186 RECORD1(Save, SkCanvas::SaveFlags, flags); 187 RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags); 188 189 RECORD1(PushCull, SkRect, rect); 190 RECORD0(PopCull); 191 192 RECORD1(Concat, SkMatrix, matrix); 193 RECORD1(SetMatrix, SkMatrix, matrix); 194 195 RECORD3(ClipPath, SkPath, path, SkRegion::Op, op, bool, doAA); 196 RECORD3(ClipRRect, SkRRect, rrect, SkRegion::Op, op, bool, doAA); 197 RECORD3(ClipRect, SkRect, rect, SkRegion::Op, op, bool, doAA); 198 RECORD2(ClipRegion, SkRegion, region, SkRegion::Op, op); 199 200 RECORD1(Clear, SkColor, color); 201 // While not strictly required, if you have an SkPaint, it's fastest to put it first. 202 RECORD4(DrawBitmap, Optional<SkPaint>, paint, 203 ImmutableBitmap, bitmap, 204 SkScalar, left, 205 SkScalar, top); 206 RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix); 207 RECORD4(DrawBitmapNine, Optional<SkPaint>, paint, 208 ImmutableBitmap, bitmap, 209 SkIRect, center, 210 SkRect, dst); 211 RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint, 212 ImmutableBitmap, bitmap, 213 Optional<SkRect>, src, 214 SkRect, dst, 215 SkCanvas::DrawBitmapRectFlags, flags); 216 RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner); 217 RECORD2(DrawOval, SkPaint, paint, SkRect, oval); 218 RECORD1(DrawPaint, SkPaint, paint); 219 RECORD2(DrawPath, SkPaint, paint, SkPath, path); 220 RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts); 221 RECORD4(DrawPosText, SkPaint, paint, 222 PODArray<char>, text, 223 size_t, byteLength, 224 PODArray<SkPoint>, pos); 225 RECORD5(DrawPosTextH, SkPaint, paint, 226 PODArray<char>, text, 227 size_t, byteLength, 228 PODArray<SkScalar>, xpos, 229 SkScalar, y); 230 RECORD2(DrawRRect, SkPaint, paint, SkRRect, rrect); 231 RECORD2(DrawRect, SkPaint, paint, SkRect, rect); 232 RECORD4(DrawSprite, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, int, left, int, top); 233 RECORD5(DrawText, SkPaint, paint, 234 PODArray<char>, text, 235 size_t, byteLength, 236 SkScalar, x, 237 SkScalar, y); 238 RECORD5(DrawTextOnPath, SkPaint, paint, 239 PODArray<char>, text, 240 size_t, byteLength, 241 SkPath, path, 242 Optional<SkMatrix>, matrix); 243 244 // This guy is so ugly we just write it manually. 245 struct DrawVertices { 246 static const Type kType = DrawVertices_Type; 247 248 DrawVertices(const SkPaint& paint, 249 SkCanvas::VertexMode vmode, 250 int vertexCount, 251 SkPoint* vertices, 252 SkPoint* texs, 253 SkColor* colors, 254 SkXfermode* xmode, 255 uint16_t* indices, 256 int indexCount) 257 : paint(paint) 258 , vmode(vmode) 259 , vertexCount(vertexCount) 260 , vertices(vertices) 261 , texs(texs) 262 , colors(colors) 263 , xmode(SkSafeRef(xmode)) 264 , indices(indices) 265 , indexCount(indexCount) {} 266 267 SkPaint paint; 268 SkCanvas::VertexMode vmode; 269 int vertexCount; 270 PODArray<SkPoint> vertices; 271 PODArray<SkPoint> texs; 272 PODArray<SkColor> colors; 273 SkAutoTUnref<SkXfermode> xmode; 274 PODArray<uint16_t> indices; 275 int indexCount; 276 }; 277 278 // Records added by optimizations. 279 RECORD2(PairedPushCull, Adopted<PushCull>, base, unsigned, skip); 280 RECORD3(BoundedDrawPosTextH, Adopted<DrawPosTextH>, base, SkScalar, minY, SkScalar, maxY); 281 282 #undef RECORD0 283 #undef RECORD1 284 #undef RECORD2 285 #undef RECORD3 286 #undef RECORD4 287 #undef RECORD5 288 289 } // namespace SkRecords 290 291 #endif//SkRecords_DEFINED 292