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