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