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 "SkData.h" 12 #include "SkCanvas.h" 13 #include "SkDrawable.h" 14 #include "SkDrawShadowInfo.h" 15 #include "SkImage.h" 16 #include "SkImageFilter.h" 17 #include "SkMatrix.h" 18 #include "SkPath.h" 19 #include "SkPicture.h" 20 #include "SkRect.h" 21 #include "SkRegion.h" 22 #include "SkRRect.h" 23 #include "SkRSXform.h" 24 #include "SkString.h" 25 #include "SkTextBlob.h" 26 #include "SkVertices.h" 27 28 namespace 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(Flush) \ 43 M(Restore) \ 44 M(Save) \ 45 M(SaveLayer) \ 46 M(SaveBehind) \ 47 M(SetMatrix) \ 48 M(Translate) \ 49 M(Concat) \ 50 M(ClipPath) \ 51 M(ClipRRect) \ 52 M(ClipRect) \ 53 M(ClipRegion) \ 54 M(DrawArc) \ 55 M(DrawDrawable) \ 56 M(DrawImage) \ 57 M(DrawImageLattice) \ 58 M(DrawImageRect) \ 59 M(DrawImageNine) \ 60 M(DrawImageSet) \ 61 M(DrawDRRect) \ 62 M(DrawOval) \ 63 M(DrawPaint) \ 64 M(DrawPath) \ 65 M(DrawPatch) \ 66 M(DrawPicture) \ 67 M(DrawPoints) \ 68 M(DrawRRect) \ 69 M(DrawRect) \ 70 M(DrawEdgeAARect) \ 71 M(DrawRegion) \ 72 M(DrawTextBlob) \ 73 M(DrawAtlas) \ 74 M(DrawVertices) \ 75 M(DrawShadowRec) \ 76 M(DrawAnnotation) 77 78 // Defines SkRecords::Type, an enum of all record types. 79 #define ENUM(T) T##_Type, 80 enum Type { SK_RECORD_TYPES(ENUM) }; 81 #undef ENUM 82 83 #define ACT_AS_PTR(ptr) \ 84 operator T*() const { return ptr; } \ 85 T* operator->() const { return ptr; } 86 87 // An Optional doesn't own the pointer's memory, but may need to destroy non-POD data. 88 template <typename T> 89 class Optional : SkNoncopyable { 90 public: Optional()91 Optional() : fPtr(nullptr) {} Optional(T * ptr)92 Optional(T* ptr) : fPtr(ptr) {} Optional(Optional && o)93 Optional(Optional&& o) : fPtr(o.fPtr) { 94 o.fPtr = nullptr; 95 } ~Optional()96 ~Optional() { if (fPtr) fPtr->~T(); } 97 98 ACT_AS_PTR(fPtr) 99 private: 100 T* fPtr; 101 }; 102 103 // Like Optional, but ptr must not be NULL. 104 template <typename T> 105 class Adopted : SkNoncopyable { 106 public: 107 Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); } 108 Adopted(Adopted* source) { 109 // Transfer ownership from source to this. 110 fPtr = source->fPtr; 111 source->fPtr = NULL; 112 } 113 ~Adopted() { if (fPtr) fPtr->~T(); } 114 115 ACT_AS_PTR(fPtr) 116 private: 117 T* fPtr; 118 }; 119 120 // PODArray doesn't own the pointer's memory, and we assume the data is POD. 121 template <typename T> 122 class PODArray { 123 public: 124 PODArray() {} 125 PODArray(T* ptr) : fPtr(ptr) {} 126 // Default copy and assign. 127 128 ACT_AS_PTR(fPtr) 129 private: 130 T* fPtr; 131 }; 132 133 #undef ACT_AS_PTR 134 135 // SkPath::getBounds() isn't thread safe unless we precache the bounds in a singlethreaded context. 136 // SkPath::cheapComputeDirection() is similar. 137 // Recording is a convenient time to cache these, or we can delay it to between record and playback. 138 struct PreCachedPath : public SkPath { 139 PreCachedPath() {} 140 PreCachedPath(const SkPath& path); 141 }; 142 143 // Like SkPath::getBounds(), SkMatrix::getType() isn't thread safe unless we precache it. 144 // This may not cover all SkMatrices used by the picture (e.g. some could be hiding in a shader). 145 struct TypedMatrix : public SkMatrix { 146 TypedMatrix() {} 147 TypedMatrix(const SkMatrix& matrix); 148 }; 149 150 enum Tags { 151 kDraw_Tag = 1, // May draw something (usually named DrawFoo). 152 kHasImage_Tag = 2, // Contains an SkImage or SkBitmap. 153 kHasText_Tag = 4, // Contains text. 154 kHasPaint_Tag = 8, // May have an SkPaint field, at least optionally. 155 156 kDrawWithPaint_Tag = kDraw_Tag | kHasPaint_Tag, 157 }; 158 159 // A macro to make it a little easier to define a struct that can be stored in SkRecord. 160 #define RECORD(T, tags, ...) \ 161 struct T { \ 162 static const Type kType = T##_Type; \ 163 static const int kTags = tags; \ 164 __VA_ARGS__; \ 165 }; 166 167 RECORD(NoOp, 0); 168 RECORD(Flush, 0); 169 RECORD(Restore, 0, 170 TypedMatrix matrix); 171 RECORD(Save, 0); 172 173 RECORD(SaveLayer, kHasPaint_Tag, 174 Optional<SkRect> bounds; 175 Optional<SkPaint> paint; 176 sk_sp<const SkImageFilter> backdrop; 177 sk_sp<const SkImage> clipMask; 178 Optional<SkMatrix> clipMatrix; 179 SkCanvas::SaveLayerFlags saveLayerFlags); 180 181 RECORD(SaveBehind, 0, 182 Optional<SkRect> subset); 183 184 RECORD(SetMatrix, 0, 185 TypedMatrix matrix); 186 RECORD(Concat, 0, 187 TypedMatrix matrix); 188 189 RECORD(Translate, 0, 190 SkScalar dx; 191 SkScalar dy); 192 193 struct ClipOpAndAA { 194 ClipOpAndAA() {} 195 ClipOpAndAA(SkClipOp op, bool aa) : fOp(static_cast<unsigned>(op)), fAA(aa) {} 196 197 SkClipOp op() const { return static_cast<SkClipOp>(fOp); } 198 bool aa() const { return fAA != 0; } 199 200 private: 201 unsigned fOp : 31; // This really only needs to be 3, but there's no win today to do so. 202 unsigned fAA : 1; // MSVC won't pack an enum with an bool, so we call this an unsigned. 203 }; 204 static_assert(sizeof(ClipOpAndAA) == 4, "ClipOpAndAASize"); 205 206 RECORD(ClipPath, 0, 207 PreCachedPath path; 208 ClipOpAndAA opAA); 209 RECORD(ClipRRect, 0, 210 SkRRect rrect; 211 ClipOpAndAA opAA); 212 RECORD(ClipRect, 0, 213 SkRect rect; 214 ClipOpAndAA opAA); 215 RECORD(ClipRegion, 0, 216 SkRegion region; 217 SkClipOp op); 218 219 // While not strictly required, if you have an SkPaint, it's fastest to put it first. 220 RECORD(DrawArc, kDraw_Tag|kHasPaint_Tag, 221 SkPaint paint; 222 SkRect oval; 223 SkScalar startAngle; 224 SkScalar sweepAngle; 225 unsigned useCenter); 226 RECORD(DrawDRRect, kDraw_Tag|kHasPaint_Tag, 227 SkPaint paint; 228 SkRRect outer; 229 SkRRect inner); 230 RECORD(DrawDrawable, kDraw_Tag, 231 Optional<SkMatrix> matrix; 232 SkRect worstCaseBounds; 233 int32_t index); 234 RECORD(DrawImage, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, 235 Optional<SkPaint> paint; 236 sk_sp<const SkImage> image; 237 SkScalar left; 238 SkScalar top); 239 RECORD(DrawImageLattice, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, 240 Optional<SkPaint> paint; 241 sk_sp<const SkImage> image; 242 int xCount; 243 PODArray<int> xDivs; 244 int yCount; 245 PODArray<int> yDivs; 246 int flagCount; 247 PODArray<SkCanvas::Lattice::RectType> flags; 248 PODArray<SkColor> colors; 249 SkIRect src; 250 SkRect dst); 251 RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, 252 Optional<SkPaint> paint; 253 sk_sp<const SkImage> image; 254 Optional<SkRect> src; 255 SkRect dst; 256 SkCanvas::SrcRectConstraint constraint); 257 RECORD(DrawImageNine, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, 258 Optional<SkPaint> paint; 259 sk_sp<const SkImage> image; 260 SkIRect center; 261 SkRect dst); 262 RECORD(DrawImageSet, kDraw_Tag|kHasImage_Tag, 263 SkAutoTArray<SkCanvas::ImageSetEntry> set; 264 int count; 265 SkFilterQuality quality; 266 SkBlendMode mode); 267 RECORD(DrawOval, kDraw_Tag|kHasPaint_Tag, 268 SkPaint paint; 269 SkRect oval); 270 RECORD(DrawPaint, kDraw_Tag|kHasPaint_Tag, 271 SkPaint paint); 272 RECORD(DrawPath, kDraw_Tag|kHasPaint_Tag, 273 SkPaint paint; 274 PreCachedPath path); 275 RECORD(DrawPicture, kDraw_Tag|kHasPaint_Tag, 276 Optional<SkPaint> paint; 277 sk_sp<const SkPicture> picture; 278 TypedMatrix matrix); 279 RECORD(DrawPoints, kDraw_Tag|kHasPaint_Tag, 280 SkPaint paint; 281 SkCanvas::PointMode mode; 282 unsigned count; 283 SkPoint* pts); 284 RECORD(DrawRRect, kDraw_Tag|kHasPaint_Tag, 285 SkPaint paint; 286 SkRRect rrect); 287 RECORD(DrawRect, kDraw_Tag|kHasPaint_Tag, 288 SkPaint paint; 289 SkRect rect); 290 RECORD(DrawEdgeAARect, kDraw_Tag, 291 SkRect rect; 292 SkCanvas::QuadAAFlags aa; 293 SkColor color; 294 SkBlendMode mode); 295 RECORD(DrawRegion, kDraw_Tag|kHasPaint_Tag, 296 SkPaint paint; 297 SkRegion region); 298 RECORD(DrawTextBlob, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, 299 SkPaint paint; 300 sk_sp<const SkTextBlob> blob; 301 SkScalar x; 302 SkScalar y); 303 RECORD(DrawPatch, kDraw_Tag|kHasPaint_Tag, 304 SkPaint paint; 305 PODArray<SkPoint> cubics; 306 PODArray<SkColor> colors; 307 PODArray<SkPoint> texCoords; 308 SkBlendMode bmode); 309 RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, 310 Optional<SkPaint> paint; 311 sk_sp<const SkImage> atlas; 312 PODArray<SkRSXform> xforms; 313 PODArray<SkRect> texs; 314 PODArray<SkColor> colors; 315 int count; 316 SkBlendMode mode; 317 Optional<SkRect> cull); 318 RECORD(DrawVertices, kDraw_Tag|kHasPaint_Tag, 319 SkPaint paint; 320 sk_sp<SkVertices> vertices; 321 PODArray<SkVertices::Bone> bones; 322 int boneCount; 323 SkBlendMode bmode); 324 RECORD(DrawShadowRec, kDraw_Tag, 325 PreCachedPath path; 326 SkDrawShadowRec rec); 327 RECORD(DrawAnnotation, 0, // TODO: kDraw_Tag, skia:5548 328 SkRect rect; 329 SkString key; 330 sk_sp<SkData> value); 331 #undef RECORD 332 333 } // namespace SkRecords 334 335 #endif//SkRecords_DEFINED 336