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