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