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