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 "SkDrawable.h" 13 #include "SkImageFilter.h" 14 #include "SkMatrix.h" 15 #include "SkPath.h" 16 #include "SkPicture.h" 17 #include "SkRect.h" 18 #include "SkRRect.h" 19 #include "SkRSXform.h" 20 #include "SkTextBlob.h" 21 22 namespace SkRecords { 23 24 // A list of all the types of canvas calls we can record. 25 // Each of these is reified into a struct below. 26 // 27 // (We're using the macro-of-macro trick here to do several different things with the same list.) 28 // 29 // We leave this SK_RECORD_TYPES macro defined for use by code that wants to operate on SkRecords 30 // types polymorphically. (See SkRecord::Record::{visit,mutate} for an example.) 31 // 32 // Order doesn't technically matter here, but the compiler can generally generate better code if 33 // you keep them semantically grouped, especially the Draws. It's also nice to leave NoOp at 0. 34 #define SK_RECORD_TYPES(M) \ 35 M(NoOp) \ 36 M(Restore) \ 37 M(Save) \ 38 M(SaveLayer) \ 39 M(SetMatrix) \ 40 M(Concat) \ 41 M(ClipPath) \ 42 M(ClipRRect) \ 43 M(ClipRect) \ 44 M(ClipRegion) \ 45 M(DrawBitmap) \ 46 M(DrawBitmapNine) \ 47 M(DrawBitmapRect) \ 48 M(DrawBitmapRectFast) \ 49 M(DrawBitmapRectFixedSize) \ 50 M(DrawDrawable) \ 51 M(DrawImage) \ 52 M(DrawImageRect) \ 53 M(DrawImageNine) \ 54 M(DrawDRRect) \ 55 M(DrawOval) \ 56 M(DrawPaint) \ 57 M(DrawPath) \ 58 M(DrawPatch) \ 59 M(DrawPicture) \ 60 M(DrawPoints) \ 61 M(DrawPosText) \ 62 M(DrawPosTextH) \ 63 M(DrawText) \ 64 M(DrawTextOnPath) \ 65 M(DrawRRect) \ 66 M(DrawRect) \ 67 M(DrawTextBlob) \ 68 M(DrawAtlas) \ 69 M(DrawVertices) 70 71 // Defines SkRecords::Type, an enum of all record types. 72 #define ENUM(T) T##_Type, 73 enum Type { SK_RECORD_TYPES(ENUM) }; 74 #undef ENUM 75 76 #define ACT_AS_PTR(ptr) \ 77 operator T*() const { return ptr; } \ 78 T* operator->() const { return ptr; } 79 80 template <typename T> 81 class RefBox : SkNoncopyable { 82 public: RefBox()83 RefBox() {} RefBox(T * obj)84 RefBox(T* obj) : fObj(SkSafeRef(obj)) {} RefBox(RefBox && o)85 RefBox(RefBox&& o) : fObj(o.fObj) { 86 o.fObj = nullptr; 87 } ~RefBox()88 ~RefBox() { SkSafeUnref(fObj); } 89 90 ACT_AS_PTR(fObj); 91 92 private: 93 T* fObj; 94 }; 95 96 // An Optional doesn't own the pointer's memory, but may need to destroy non-POD data. 97 template <typename T> 98 class Optional : SkNoncopyable { 99 public: Optional()100 Optional() : fPtr(nullptr) {} Optional(T * ptr)101 Optional(T* ptr) : fPtr(ptr) {} Optional(Optional && o)102 Optional(Optional&& o) : fPtr(o.fPtr) { 103 o.fPtr = nullptr; 104 } ~Optional()105 ~Optional() { if (fPtr) fPtr->~T(); } 106 107 ACT_AS_PTR(fPtr); 108 private: 109 T* fPtr; 110 }; 111 112 // Like Optional, but ptr must not be NULL. 113 template <typename T> 114 class Adopted : SkNoncopyable { 115 public: Adopted(T * ptr)116 Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); } Adopted(Adopted * source)117 Adopted(Adopted* source) { 118 // Transfer ownership from source to this. 119 fPtr = source->fPtr; 120 source->fPtr = NULL; 121 } ~Adopted()122 ~Adopted() { if (fPtr) fPtr->~T(); } 123 124 ACT_AS_PTR(fPtr); 125 private: 126 T* fPtr; 127 }; 128 129 // PODArray doesn't own the pointer's memory, and we assume the data is POD. 130 template <typename T> 131 class PODArray { 132 public: PODArray()133 PODArray() {} PODArray(T * ptr)134 PODArray(T* ptr) : fPtr(ptr) {} 135 // Default copy and assign. 136 137 ACT_AS_PTR(fPtr); 138 private: 139 T* fPtr; 140 }; 141 142 #undef ACT_AS_PTR 143 144 // Like SkBitmap, but deep copies pixels if they're not immutable. 145 // Using this, we guarantee the immutability of all bitmaps we record. 146 class ImmutableBitmap : SkNoncopyable { 147 public: ImmutableBitmap()148 ImmutableBitmap() {} 149 ImmutableBitmap(const SkBitmap& bitmap); ImmutableBitmap(ImmutableBitmap && o)150 ImmutableBitmap(ImmutableBitmap&& o) { 151 fBitmap.swap(o.fBitmap); 152 } 153 width()154 int width() const { return fBitmap.width(); } height()155 int height() const { return fBitmap.height(); } 156 157 // While the pixels are immutable, SkBitmap itself is not thread-safe, so return a copy. shallowCopy()158 SkBitmap shallowCopy() const { return fBitmap; } 159 private: 160 SkBitmap fBitmap; 161 }; 162 163 // SkPath::getBounds() isn't thread safe unless we precache the bounds in a singlethreaded context. 164 // SkPath::cheapComputeDirection() is similar. 165 // Recording is a convenient time to cache these, or we can delay it to between record and playback. 166 struct PreCachedPath : public SkPath { PreCachedPathPreCachedPath167 PreCachedPath() {} 168 PreCachedPath(const SkPath& path); 169 }; 170 171 // Like SkPath::getBounds(), SkMatrix::getType() isn't thread safe unless we precache it. 172 // This may not cover all SkMatrices used by the picture (e.g. some could be hiding in a shader). 173 struct TypedMatrix : public SkMatrix { TypedMatrixTypedMatrix174 TypedMatrix() {} 175 TypedMatrix(const SkMatrix& matrix); 176 }; 177 178 enum Tags { 179 kDraw_Tag = 1, // May draw something (usually named DrawFoo). 180 kHasImage_Tag = 2, // Contains an SkImage or SkBitmap. 181 kHasText_Tag = 4, // Contains text. 182 }; 183 184 // A macro to make it a little easier to define a struct that can be stored in SkRecord. 185 #define RECORD(T, tags, ...) \ 186 struct T { \ 187 static const Type kType = T##_Type; \ 188 static const int kTags = tags; \ 189 __VA_ARGS__; \ 190 }; 191 192 RECORD(NoOp, 0); 193 RECORD(Restore, 0, 194 SkIRect devBounds; 195 TypedMatrix matrix); 196 RECORD(Save, 0); 197 198 RECORD(SaveLayer, 0, 199 Optional<SkRect> bounds; 200 Optional<SkPaint> paint; 201 RefBox<const SkImageFilter> backdrop; 202 SkCanvas::SaveLayerFlags saveLayerFlags); 203 204 RECORD(SetMatrix, 0, 205 TypedMatrix matrix); 206 RECORD(Concat, 0, 207 TypedMatrix matrix); 208 209 struct RegionOpAndAA { RegionOpAndAARegionOpAndAA210 RegionOpAndAA() {} RegionOpAndAARegionOpAndAA211 RegionOpAndAA(SkRegion::Op op, bool aa) : op(op), aa(aa) {} 212 SkRegion::Op op : 31; // This really only needs to be 3, but there's no win today to do so. 213 unsigned aa : 1; // MSVC won't pack an enum with an bool, so we call this an unsigned. 214 }; 215 static_assert(sizeof(RegionOpAndAA) == 4, "RegionOpAndAASize"); 216 217 RECORD(ClipPath, 0, 218 SkIRect devBounds; 219 PreCachedPath path; 220 RegionOpAndAA opAA); 221 RECORD(ClipRRect, 0, 222 SkIRect devBounds; 223 SkRRect rrect; 224 RegionOpAndAA opAA); 225 RECORD(ClipRect, 0, 226 SkIRect devBounds; 227 SkRect rect; 228 RegionOpAndAA opAA); 229 RECORD(ClipRegion, 0, 230 SkIRect devBounds; 231 SkRegion region; 232 SkRegion::Op op); 233 234 // While not strictly required, if you have an SkPaint, it's fastest to put it first. 235 RECORD(DrawBitmap, kDraw_Tag|kHasImage_Tag, 236 Optional<SkPaint> paint; 237 ImmutableBitmap bitmap; 238 SkScalar left; 239 SkScalar top); 240 RECORD(DrawBitmapNine, kDraw_Tag|kHasImage_Tag, 241 Optional<SkPaint> paint; 242 ImmutableBitmap bitmap; 243 SkIRect center; 244 SkRect dst); 245 RECORD(DrawBitmapRect, kDraw_Tag|kHasImage_Tag, 246 Optional<SkPaint> paint; 247 ImmutableBitmap bitmap; 248 Optional<SkRect> src; 249 SkRect dst); 250 RECORD(DrawBitmapRectFast, kDraw_Tag|kHasImage_Tag, 251 Optional<SkPaint> paint; 252 ImmutableBitmap bitmap; 253 Optional<SkRect> src; 254 SkRect dst); 255 RECORD(DrawBitmapRectFixedSize, kDraw_Tag|kHasImage_Tag, 256 SkPaint paint; 257 ImmutableBitmap bitmap; 258 SkRect src; 259 SkRect dst; 260 SkCanvas::SrcRectConstraint constraint); 261 RECORD(DrawDRRect, kDraw_Tag, 262 SkPaint paint; 263 SkRRect outer; 264 SkRRect inner); 265 RECORD(DrawDrawable, kDraw_Tag, 266 Optional<SkMatrix> matrix; 267 SkRect worstCaseBounds; 268 int32_t index); 269 RECORD(DrawImage, kDraw_Tag|kHasImage_Tag, 270 Optional<SkPaint> paint; 271 RefBox<const SkImage> image; 272 SkScalar left; 273 SkScalar top); 274 RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag, 275 Optional<SkPaint> paint; 276 RefBox<const SkImage> image; 277 Optional<SkRect> src; 278 SkRect dst; 279 SkCanvas::SrcRectConstraint constraint); 280 RECORD(DrawImageNine, kDraw_Tag|kHasImage_Tag, 281 Optional<SkPaint> paint; 282 RefBox<const SkImage> image; 283 SkIRect center; 284 SkRect dst); 285 RECORD(DrawOval, kDraw_Tag, 286 SkPaint paint; 287 SkRect oval); 288 RECORD(DrawPaint, kDraw_Tag, 289 SkPaint paint); 290 RECORD(DrawPath, kDraw_Tag, 291 SkPaint paint; 292 PreCachedPath path); 293 RECORD(DrawPicture, kDraw_Tag, 294 Optional<SkPaint> paint; 295 RefBox<const SkPicture> picture; 296 TypedMatrix matrix); 297 RECORD(DrawPoints, kDraw_Tag, 298 SkPaint paint; 299 SkCanvas::PointMode mode; 300 unsigned count; 301 SkPoint* pts); 302 RECORD(DrawPosText, kDraw_Tag|kHasText_Tag, 303 SkPaint paint; 304 PODArray<char> text; 305 size_t byteLength; 306 PODArray<SkPoint> pos); 307 RECORD(DrawPosTextH, kDraw_Tag|kHasText_Tag, 308 SkPaint paint; 309 PODArray<char> text; 310 unsigned byteLength; 311 SkScalar y; 312 PODArray<SkScalar> xpos); 313 RECORD(DrawRRect, kDraw_Tag, 314 SkPaint paint; 315 SkRRect rrect); 316 RECORD(DrawRect, kDraw_Tag, 317 SkPaint paint; 318 SkRect rect); 319 RECORD(DrawText, kDraw_Tag|kHasText_Tag, 320 SkPaint paint; 321 PODArray<char> text; 322 size_t byteLength; 323 SkScalar x; 324 SkScalar y); 325 RECORD(DrawTextBlob, kDraw_Tag|kHasText_Tag, 326 SkPaint paint; 327 RefBox<const SkTextBlob> blob; 328 SkScalar x; 329 SkScalar y); 330 RECORD(DrawTextOnPath, kDraw_Tag|kHasText_Tag, 331 SkPaint paint; 332 PODArray<char> text; 333 size_t byteLength; 334 PreCachedPath path; 335 TypedMatrix matrix); 336 RECORD(DrawPatch, kDraw_Tag, 337 SkPaint paint; 338 PODArray<SkPoint> cubics; 339 PODArray<SkColor> colors; 340 PODArray<SkPoint> texCoords; 341 RefBox<SkXfermode> xmode); 342 RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag, 343 Optional<SkPaint> paint; 344 RefBox<const SkImage> atlas; 345 PODArray<SkRSXform> xforms; 346 PODArray<SkRect> texs; 347 PODArray<SkColor> colors; 348 int count; 349 SkXfermode::Mode mode; 350 Optional<SkRect> cull); 351 RECORD(DrawVertices, kDraw_Tag, 352 SkPaint paint; 353 SkCanvas::VertexMode vmode; 354 int vertexCount; 355 PODArray<SkPoint> vertices; 356 PODArray<SkPoint> texs; 357 PODArray<SkColor> colors; 358 RefBox<SkXfermode> xmode; 359 PODArray<uint16_t> indices; 360 int indexCount); 361 362 #undef RECORD 363 364 } // namespace SkRecords 365 366 #endif//SkRecords_DEFINED 367