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