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 #include "SkPicture.h" 13 #include "SkTextBlob.h" 14 15 namespace 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.) 24 // 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) \ 28 M(NoOp) \ 29 M(Restore) \ 30 M(Save) \ 31 M(SaveLayer) \ 32 M(PushCull) \ 33 M(PopCull) \ 34 M(SetMatrix) \ 35 M(ClipPath) \ 36 M(ClipRRect) \ 37 M(ClipRect) \ 38 M(ClipRegion) \ 39 M(Clear) \ 40 M(BeginCommentGroup) \ 41 M(AddComment) \ 42 M(EndCommentGroup) \ 43 M(DrawBitmap) \ 44 M(DrawBitmapMatrix) \ 45 M(DrawBitmapNine) \ 46 M(DrawBitmapRectToRect) \ 47 M(DrawDRRect) \ 48 M(DrawOval) \ 49 M(DrawPaint) \ 50 M(DrawPath) \ 51 M(DrawPatch) \ 52 M(DrawPicture) \ 53 M(DrawPoints) \ 54 M(DrawPosText) \ 55 M(DrawPosTextH) \ 56 M(DrawText) \ 57 M(DrawTextOnPath) \ 58 M(DrawRRect) \ 59 M(DrawRect) \ 60 M(DrawSprite) \ 61 M(DrawTextBlob) \ 62 M(DrawData) \ 63 M(DrawVertices) 64 65 // Defines SkRecords::Type, an enum of all record types. 66 #define ENUM(T) T##_Type, 67 enum 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) \ 73 struct T { \ 74 static const Type kType = T##_Type; \ 75 }; 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) \ 82 struct 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) \ 90 struct 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) \ 98 struct 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) \ 106 struct 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) \ 114 struct 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 121 #define ACT_AS_PTR(ptr) \ 122 operator T*() const { return ptr; } \ 123 T* operator->() const { return ptr; } 124 125 template <typename T> 126 class RefBox : SkNoncopyable { 127 public: 128 RefBox(T* obj) : fObj(SkSafeRef(obj)) {} 129 ~RefBox() { SkSafeUnref(fObj); } 130 131 ACT_AS_PTR(fObj); 132 133 private: 134 T* fObj; 135 }; 136 137 // An Optional doesn't own the pointer's memory, but may need to destroy non-POD data. 138 template <typename T> 139 class Optional : SkNoncopyable { 140 public: 141 Optional(T* ptr) : fPtr(ptr) {} 142 ~Optional() { if (fPtr) fPtr->~T(); } 143 144 ACT_AS_PTR(fPtr); 145 private: 146 T* fPtr; 147 }; 148 149 // Like Optional, but ptr must not be NULL. 150 template <typename T> 151 class Adopted : SkNoncopyable { 152 public: 153 Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); } 154 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(); } 160 161 ACT_AS_PTR(fPtr); 162 private: 163 T* fPtr; 164 }; 165 166 // PODArray doesn't own the pointer's memory, and we assume the data is POD. 167 template <typename T> 168 class PODArray { 169 public: 170 PODArray(T* ptr) : fPtr(ptr) {} 171 // Default copy and assign. 172 173 ACT_AS_PTR(fPtr); 174 private: 175 T* fPtr; 176 }; 177 178 #undef ACT_AS_PTR 179 180 // Like SkBitmap, but deep copies pixels if they're not immutable. 181 // Using this, we guarantee the immutability of all bitmaps we record. 182 class ImmutableBitmap : SkNoncopyable { 183 public: 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 195 private: 196 SkBitmap fBitmap; 197 }; 198 199 RECORD0(NoOp); 200 201 RECORD2(Restore, SkIRect, devBounds, SkMatrix, matrix); 202 RECORD0(Save); 203 RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags); 204 205 RECORD1(PushCull, SkRect, rect); 206 RECORD0(PopCull); 207 208 RECORD1(SetMatrix, SkMatrix, matrix); 209 210 RECORD4(ClipPath, SkIRect, devBounds, SkPath, path, SkRegion::Op, op, bool, doAA); 211 RECORD4(ClipRRect, SkIRect, devBounds, SkRRect, rrect, SkRegion::Op, op, bool, doAA); 212 RECORD4(ClipRect, SkIRect, devBounds, SkRect, rect, SkRegion::Op, op, bool, doAA); 213 RECORD3(ClipRegion, SkIRect, devBounds, SkRegion, region, SkRegion::Op, op); 214 215 RECORD1(Clear, SkColor, color); 216 217 RECORD1(BeginCommentGroup, PODArray<char>, description); 218 RECORD2(AddComment, PODArray<char>, key, PODArray<char>, value); 219 RECORD0(EndCommentGroup); 220 221 // While not strictly required, if you have an SkPaint, it's fastest to put it first. 222 RECORD4(DrawBitmap, Optional<SkPaint>, paint, 223 ImmutableBitmap, bitmap, 224 SkScalar, left, 225 SkScalar, top); 226 RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix); 227 RECORD4(DrawBitmapNine, Optional<SkPaint>, paint, 228 ImmutableBitmap, bitmap, 229 SkIRect, center, 230 SkRect, dst); 231 RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint, 232 ImmutableBitmap, bitmap, 233 Optional<SkRect>, src, 234 SkRect, dst, 235 SkCanvas::DrawBitmapRectFlags, flags); 236 RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner); 237 RECORD2(DrawOval, SkPaint, paint, SkRect, oval); 238 RECORD1(DrawPaint, SkPaint, paint); 239 RECORD2(DrawPath, SkPaint, paint, SkPath, path); 240 RECORD3(DrawPicture, Optional<SkPaint>, paint, 241 RefBox<const SkPicture>, picture, 242 Optional<SkMatrix>, matrix); 243 RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts); 244 RECORD4(DrawPosText, SkPaint, paint, 245 PODArray<char>, text, 246 size_t, byteLength, 247 PODArray<SkPoint>, pos); 248 RECORD5(DrawPosTextH, SkPaint, paint, 249 PODArray<char>, text, 250 size_t, byteLength, 251 PODArray<SkScalar>, xpos, 252 SkScalar, y); 253 RECORD2(DrawRRect, SkPaint, paint, SkRRect, rrect); 254 RECORD2(DrawRect, SkPaint, paint, SkRect, rect); 255 RECORD4(DrawSprite, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, int, left, int, top); 256 RECORD5(DrawText, SkPaint, paint, 257 PODArray<char>, text, 258 size_t, byteLength, 259 SkScalar, x, 260 SkScalar, y); 261 RECORD4(DrawTextBlob, SkPaint, paint, 262 RefBox<const SkTextBlob>, blob, 263 SkScalar, x, 264 SkScalar, y); 265 RECORD5(DrawTextOnPath, SkPaint, paint, 266 PODArray<char>, text, 267 size_t, byteLength, 268 SkPath, path, 269 Optional<SkMatrix>, matrix); 270 271 RECORD2(DrawData, PODArray<char>, data, size_t, length); 272 273 RECORD5(DrawPatch, SkPaint, paint, 274 PODArray<SkPoint>, cubics, 275 PODArray<SkColor>, colors, 276 PODArray<SkPoint>, texCoords, 277 RefBox<SkXfermode>, xmode); 278 279 // This guy is so ugly we just write it manually. 280 struct DrawVertices { 281 static const Type kType = DrawVertices_Type; 282 283 DrawVertices(const SkPaint& paint, 284 SkCanvas::VertexMode vmode, 285 int vertexCount, 286 SkPoint* vertices, 287 SkPoint* texs, 288 SkColor* colors, 289 SkXfermode* xmode, 290 uint16_t* indices, 291 int indexCount) 292 : paint(paint) 293 , vmode(vmode) 294 , vertexCount(vertexCount) 295 , vertices(vertices) 296 , texs(texs) 297 , colors(colors) 298 , xmode(SkSafeRef(xmode)) 299 , indices(indices) 300 , indexCount(indexCount) {} 301 302 SkPaint paint; 303 SkCanvas::VertexMode vmode; 304 int vertexCount; 305 PODArray<SkPoint> vertices; 306 PODArray<SkPoint> texs; 307 PODArray<SkColor> colors; 308 SkAutoTUnref<SkXfermode> xmode; 309 PODArray<uint16_t> indices; 310 int indexCount; 311 }; 312 313 #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 323