| 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/SkM44.h" |
| 17 | #include "include/core/SkMatrix.h" |
| 18 | #include "include/core/SkPath.h" |
| 19 | #include "include/core/SkPicture.h" |
| 20 | #include "include/core/SkRRect.h" |
| 21 | #include "include/core/SkRSXform.h" |
| 22 | #include "include/core/SkRect.h" |
| 23 | #include "include/core/SkRegion.h" |
| 24 | #include "include/core/SkString.h" |
| 25 | #include "include/core/SkTextBlob.h" |
| 26 | #include "include/core/SkVertices.h" |
| 27 | #include "src/core/SkDrawShadowInfo.h" |
| 28 | |
| 29 | namespace SkRecords { |
| 30 | |
| 31 | // A list of all the types of canvas calls we can record. |
| 32 | // Each of these is reified into a struct below. |
| 33 | // |
| 34 | // (We're using the macro-of-macro trick here to do several different things with the same list.) |
| 35 | // |
| 36 | // We leave this SK_RECORD_TYPES macro defined for use by code that wants to operate on SkRecords |
| 37 | // types polymorphically. (See SkRecord::Record::{visit,mutate} for an example.) |
| 38 | // |
| 39 | // Order doesn't technically matter here, but the compiler can generally generate better code if |
| 40 | // you keep them semantically grouped, especially the Draws. It's also nice to leave NoOp at 0. |
| 41 | #define SK_RECORD_TYPES(M) \ |
| 42 | M(NoOp) \ |
| 43 | M(Flush) \ |
| 44 | M(Restore) \ |
| 45 | M(Save) \ |
| 46 | M(SaveLayer) \ |
| 47 | M(SaveBehind) \ |
| 48 | M(MarkCTM) \ |
| 49 | M(SetMatrix) \ |
| 50 | M(Translate) \ |
| 51 | M(Scale) \ |
| 52 | M(Concat) \ |
| 53 | M(Concat44) \ |
| 54 | M(ClipPath) \ |
| 55 | M(ClipRRect) \ |
| 56 | M(ClipRect) \ |
| 57 | M(ClipRegion) \ |
| 58 | M(ClipShader) \ |
| 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(DrawBehind) \ |
| 68 | M(DrawPaint) \ |
| 69 | M(DrawPath) \ |
| 70 | M(DrawPatch) \ |
| 71 | M(DrawPicture) \ |
| 72 | M(DrawPoints) \ |
| 73 | M(DrawRRect) \ |
| 74 | M(DrawRect) \ |
| 75 | M(DrawRegion) \ |
| 76 | M(DrawTextBlob) \ |
| 77 | M(DrawAtlas) \ |
| 78 | M(DrawVertices) \ |
| 79 | M(DrawShadowRec) \ |
| 80 | M(DrawAnnotation) \ |
| 81 | M(DrawEdgeAAQuad) \ |
| 82 | M(DrawEdgeAAImageSet) |
| 83 | |
| 84 | |
| 85 | // Defines SkRecords::Type, an enum of all record types. |
| 86 | #define ENUM(T) T##_Type, |
| 87 | enum Type { SK_RECORD_TYPES(ENUM) }; |
| 88 | #undef ENUM |
| 89 | |
| 90 | #define ACT_AS_PTR(ptr) \ |
| 91 | operator T*() const { return ptr; } \ |
| 92 | T* operator->() const { return ptr; } |
| 93 | |
| 94 | // An Optional doesn't own the pointer's memory, but may need to destroy non-POD data. |
| 95 | template <typename T> |
| 96 | class Optional { |
| 97 | public: |
| 98 | Optional() : fPtr(nullptr) {} |
| 99 | Optional(T* ptr) : fPtr(ptr) {} |
| 100 | Optional(Optional&& o) : fPtr(o.fPtr) { |
| 101 | o.fPtr = nullptr; |
| 102 | } |
| 103 | ~Optional() { if (fPtr) fPtr->~T(); } |
| 104 | |
| 105 | ACT_AS_PTR(fPtr) |
| 106 | private: |
| 107 | T* fPtr; |
| 108 | Optional(const Optional&) = delete; |
| 109 | Optional& operator=(const Optional&) = delete; |
| 110 | }; |
| 111 | |
| 112 | // PODArray doesn't own the pointer's memory, and we assume the data is POD. |
| 113 | template <typename T> |
| 114 | class PODArray { |
| 115 | public: |
| 116 | PODArray() {} |
| 117 | PODArray(T* ptr) : fPtr(ptr) {} |
| 118 | // Default copy and assign. |
| 119 | |
| 120 | ACT_AS_PTR(fPtr) |
| 121 | private: |
| 122 | T* fPtr; |
| 123 | }; |
| 124 | |
| 125 | #undef ACT_AS_PTR |
| 126 | |
| 127 | // SkPath::getBounds() isn't thread safe unless we precache the bounds in a singlethreaded context. |
| 128 | // SkPath::cheapComputeDirection() is similar. |
| 129 | // Recording is a convenient time to cache these, or we can delay it to between record and playback. |
| 130 | struct PreCachedPath : public SkPath { |
| 131 | PreCachedPath() {} |
| 132 | PreCachedPath(const SkPath& path); |
| 133 | }; |
| 134 | |
| 135 | // Like SkPath::getBounds(), SkMatrix::getType() isn't thread safe unless we precache it. |
| 136 | // This may not cover all SkMatrices used by the picture (e.g. some could be hiding in a shader). |
| 137 | struct TypedMatrix : public SkMatrix { |
| 138 | TypedMatrix() {} |
| 139 | TypedMatrix(const SkMatrix& matrix); |
| 140 | }; |
| 141 | |
| 142 | enum Tags { |
| 143 | kDraw_Tag = 1, // May draw something (usually named DrawFoo). |
| 144 | kHasImage_Tag = 2, // Contains an SkImage or SkBitmap. |
| 145 | kHasText_Tag = 4, // Contains text. |
| 146 | kHasPaint_Tag = 8, // May have an SkPaint field, at least optionally. |
| 147 | |
| 148 | kDrawWithPaint_Tag = kDraw_Tag | kHasPaint_Tag, |
| 149 | }; |
| 150 | |
| 151 | // A macro to make it a little easier to define a struct that can be stored in SkRecord. |
| 152 | #define RECORD(T, tags, ...) \ |
| 153 | struct T { \ |
| 154 | static const Type kType = T##_Type; \ |
| 155 | static const int kTags = tags; \ |
| 156 | __VA_ARGS__; \ |
| 157 | }; |
| 158 | |
| 159 | RECORD(NoOp, 0); |
| 160 | RECORD(Flush, 0); |
| 161 | RECORD(Restore, 0, |
| 162 | TypedMatrix matrix); |
| 163 | RECORD(Save, 0); |
| 164 | |
| 165 | RECORD(SaveLayer, kHasPaint_Tag, |
| 166 | Optional<SkRect> bounds; |
| 167 | Optional<SkPaint> paint; |
| 168 | sk_sp<const SkImageFilter> backdrop; |
| 169 | SkCanvas::SaveLayerFlags saveLayerFlags); |
| 170 | |
| 171 | RECORD(SaveBehind, 0, |
| 172 | Optional<SkRect> subset); |
| 173 | |
| 174 | RECORD(MarkCTM, 0, |
| 175 | SkString name); |
| 176 | RECORD(SetMatrix, 0, |
| 177 | TypedMatrix matrix); |
| 178 | RECORD(Concat, 0, |
| 179 | TypedMatrix matrix); |
| 180 | RECORD(Concat44, 0, |
| 181 | SkM44 matrix); |
| 182 | |
| 183 | RECORD(Translate, 0, |
| 184 | SkScalar dx; |
| 185 | SkScalar dy); |
| 186 | |
| 187 | RECORD(Scale, 0, |
| 188 | SkScalar sx; |
| 189 | SkScalar sy); |
| 190 | |
| 191 | struct ClipOpAndAA { |
| 192 | ClipOpAndAA() {} |
| 193 | ClipOpAndAA(SkClipOp op, bool aa) : fOp(static_cast<unsigned>(op)), fAA(aa) {} |
| 194 | |
| 195 | SkClipOp op() const { return static_cast<SkClipOp>(fOp); } |
| 196 | bool aa() const { return fAA != 0; } |
| 197 | |
| 198 | private: |
| 199 | unsigned fOp : 31; // This really only needs to be 3, but there's no win today to do so. |
| 200 | unsigned fAA : 1; // MSVC won't pack an enum with an bool, so we call this an unsigned. |
| 201 | }; |
| 202 | static_assert(sizeof(ClipOpAndAA) == 4, "ClipOpAndAASize" ); |
| 203 | |
| 204 | RECORD(ClipPath, 0, |
| 205 | PreCachedPath path; |
| 206 | ClipOpAndAA opAA); |
| 207 | RECORD(ClipRRect, 0, |
| 208 | SkRRect rrect; |
| 209 | ClipOpAndAA opAA); |
| 210 | RECORD(ClipRect, 0, |
| 211 | SkRect rect; |
| 212 | ClipOpAndAA opAA); |
| 213 | RECORD(ClipRegion, 0, |
| 214 | SkRegion region; |
| 215 | SkClipOp op); |
| 216 | RECORD(ClipShader, 0, |
| 217 | sk_sp<SkShader> shader; |
| 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(DrawOval, kDraw_Tag|kHasPaint_Tag, |
| 264 | SkPaint paint; |
| 265 | SkRect oval); |
| 266 | RECORD(DrawPaint, kDraw_Tag|kHasPaint_Tag, |
| 267 | SkPaint paint); |
| 268 | RECORD(DrawBehind, kDraw_Tag|kHasPaint_Tag, |
| 269 | SkPaint paint); |
| 270 | RECORD(DrawPath, kDraw_Tag|kHasPaint_Tag, |
| 271 | SkPaint paint; |
| 272 | PreCachedPath path); |
| 273 | RECORD(DrawPicture, kDraw_Tag|kHasPaint_Tag, |
| 274 | Optional<SkPaint> paint; |
| 275 | sk_sp<const SkPicture> picture; |
| 276 | TypedMatrix matrix); |
| 277 | RECORD(DrawPoints, kDraw_Tag|kHasPaint_Tag, |
| 278 | SkPaint paint; |
| 279 | SkCanvas::PointMode mode; |
| 280 | unsigned count; |
| 281 | PODArray<SkPoint> pts); |
| 282 | RECORD(DrawRRect, kDraw_Tag|kHasPaint_Tag, |
| 283 | SkPaint paint; |
| 284 | SkRRect rrect); |
| 285 | RECORD(DrawRect, kDraw_Tag|kHasPaint_Tag, |
| 286 | SkPaint paint; |
| 287 | SkRect rect); |
| 288 | RECORD(DrawRegion, kDraw_Tag|kHasPaint_Tag, |
| 289 | SkPaint paint; |
| 290 | SkRegion region); |
| 291 | RECORD(DrawTextBlob, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, |
| 292 | SkPaint paint; |
| 293 | sk_sp<const SkTextBlob> blob; |
| 294 | SkScalar x; |
| 295 | SkScalar y); |
| 296 | RECORD(DrawPatch, kDraw_Tag|kHasPaint_Tag, |
| 297 | SkPaint paint; |
| 298 | PODArray<SkPoint> cubics; |
| 299 | PODArray<SkColor> colors; |
| 300 | PODArray<SkPoint> texCoords; |
| 301 | SkBlendMode bmode); |
| 302 | RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |
| 303 | Optional<SkPaint> paint; |
| 304 | sk_sp<const SkImage> atlas; |
| 305 | PODArray<SkRSXform> xforms; |
| 306 | PODArray<SkRect> texs; |
| 307 | PODArray<SkColor> colors; |
| 308 | int count; |
| 309 | SkBlendMode mode; |
| 310 | Optional<SkRect> cull); |
| 311 | RECORD(DrawVertices, kDraw_Tag|kHasPaint_Tag, |
| 312 | SkPaint paint; |
| 313 | sk_sp<SkVertices> vertices; |
| 314 | SkBlendMode bmode); |
| 315 | RECORD(DrawShadowRec, kDraw_Tag, |
| 316 | PreCachedPath path; |
| 317 | SkDrawShadowRec rec); |
| 318 | RECORD(DrawAnnotation, 0, // TODO: kDraw_Tag, skia:5548 |
| 319 | SkRect rect; |
| 320 | SkString key; |
| 321 | sk_sp<SkData> value); |
| 322 | RECORD(DrawEdgeAAQuad, kDraw_Tag, |
| 323 | SkRect rect; |
| 324 | PODArray<SkPoint> clip; |
| 325 | SkCanvas::QuadAAFlags aa; |
| 326 | SkColor4f color; |
| 327 | SkBlendMode mode); |
| 328 | RECORD(DrawEdgeAAImageSet, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |
| 329 | Optional<SkPaint> paint; |
| 330 | SkAutoTArray<SkCanvas::ImageSetEntry> set; |
| 331 | int count; |
| 332 | PODArray<SkPoint> dstClips; |
| 333 | PODArray<SkMatrix> preViewMatrices; |
| 334 | SkCanvas::SrcRectConstraint constraint); |
| 335 | #undef RECORD |
| 336 | |
| 337 | } // namespace SkRecords |
| 338 | |
| 339 | #endif//SkRecords_DEFINED |
| 340 | |