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