blob: 2800a96b5615575ae048ac7a85c35f75c13dc056 [file] [log] [blame]
commit-bot@chromium.orgc4b21e62014-04-11 18:33:31 +00001/*
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
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +00008#ifndef SkRecords_DEFINED
9#define SkRecords_DEFINED
10
reedf70b5312016-03-04 16:36:20 -080011#include "SkData.h"
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000012#include "SkCanvas.h"
reed3cb38402015-02-06 08:36:15 -080013#include "SkDrawable.h"
reedbfd5f172016-01-07 11:28:08 -080014#include "SkImageFilter.h"
reeda8db7282015-07-07 10:22:31 -070015#include "SkMatrix.h"
bungemand3ebb482015-08-05 13:57:49 -070016#include "SkPath.h"
reed2347b622014-08-07 12:19:50 -070017#include "SkPicture.h"
bungemand3ebb482015-08-05 13:57:49 -070018#include "SkRect.h"
19#include "SkRRect.h"
reed71c3c762015-06-24 10:29:17 -070020#include "SkRSXform.h"
reedf70b5312016-03-04 16:36:20 -080021#include "SkString.h"
fmalita00d5c2c2014-08-21 08:53:26 -070022#include "SkTextBlob.h"
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000023
halcanary4dbbd042016-06-07 17:21:10 -070024// 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
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000032namespace 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.)
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +000041//
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.
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000044#define SK_RECORD_TYPES(M) \
45 M(NoOp) \
46 M(Restore) \
47 M(Save) \
48 M(SaveLayer) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000049 M(SetMatrix) \
mtkleincbdf0072016-08-19 09:05:27 -070050 M(Translate) \
vjiaoblacke5de1302016-07-13 14:05:28 -070051 M(TranslateZ) \
mtkleine9d20522015-11-19 12:08:24 -080052 M(Concat) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000053 M(ClipPath) \
54 M(ClipRRect) \
55 M(ClipRect) \
56 M(ClipRegion) \
bsalomonac3aa242016-08-19 11:25:19 -070057 M(DrawArc) \
reed6be2aa92014-11-18 11:08:05 -080058 M(DrawDrawable) \
piotaixr65151752014-10-16 11:58:39 -070059 M(DrawImage) \
msarettc573a402016-08-02 08:05:56 -070060 M(DrawImageLattice) \
piotaixr65151752014-10-16 11:58:39 -070061 M(DrawImageRect) \
reed4c21dc52015-06-25 12:32:03 -070062 M(DrawImageNine) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000063 M(DrawDRRect) \
64 M(DrawOval) \
65 M(DrawPaint) \
66 M(DrawPath) \
dandov963137b2014-08-07 07:49:53 -070067 M(DrawPatch) \
reed2347b622014-08-07 12:19:50 -070068 M(DrawPicture) \
vjiaoblack95302da2016-07-21 10:25:54 -070069 M(DrawShadowedPicture) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000070 M(DrawPoints) \
71 M(DrawPosText) \
72 M(DrawPosTextH) \
mtkleinc551d9f2014-08-20 08:09:46 -070073 M(DrawText) \
74 M(DrawTextOnPath) \
reed45561a02016-07-07 12:47:17 -070075 M(DrawTextRSXform) \
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000076 M(DrawRRect) \
77 M(DrawRect) \
msarett44df6512016-08-25 13:54:30 -070078 M(DrawRegion) \
mtklein29dfaa82014-09-04 14:12:44 -070079 M(DrawTextBlob) \
reed71c3c762015-06-24 10:29:17 -070080 M(DrawAtlas) \
reedf70b5312016-03-04 16:36:20 -080081 M(DrawVertices) \
82 M(DrawAnnotation)
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +000083
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
mtklein9b222a52014-09-18 11:16:31 -070089#define ACT_AS_PTR(ptr) \
90 operator T*() const { return ptr; } \
91 T* operator->() const { return ptr; }
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000092
commit-bot@chromium.org653d5182014-04-15 14:27:14 +000093// An Optional doesn't own the pointer's memory, but may need to destroy non-POD data.
94template <typename T>
95class Optional : SkNoncopyable {
96public:
mtklein9db912c2015-05-19 11:11:26 -070097 Optional() : fPtr(nullptr) {}
commit-bot@chromium.org653d5182014-04-15 14:27:14 +000098 Optional(T* ptr) : fPtr(ptr) {}
mtklein449d9b72015-09-28 10:33:02 -070099 Optional(Optional&& o) : fPtr(o.fPtr) {
100 o.fPtr = nullptr;
101 }
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000102 ~Optional() { if (fPtr) fPtr->~T(); }
103
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000104 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); }
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000114 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(); }
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000120
121 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000122private:
123 T* fPtr;
124};
125
126// PODArray doesn't own the pointer's memory, and we assume the data is POD.
127template <typename T>
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000128class PODArray {
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000129public:
mtklein9db912c2015-05-19 11:11:26 -0700130 PODArray() {}
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000131 PODArray(T* ptr) : fPtr(ptr) {}
commit-bot@chromium.orgf0ae5e42014-04-24 15:33:48 +0000132 // Default copy and assign.
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000133
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +0000134 ACT_AS_PTR(fPtr);
commit-bot@chromium.org653d5182014-04-15 14:27:14 +0000135private:
136 T* fPtr;
137};
138
commit-bot@chromium.org16307bd2014-04-22 18:32:58 +0000139#undef ACT_AS_PTR
140
mtkleinaf579032014-12-01 11:03:37 -0800141// SkPath::getBounds() isn't thread safe unless we precache the bounds in a singlethreaded context.
mtklein14ed0fd2015-01-20 13:47:19 -0800142// 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 {
mtklein9db912c2015-05-19 11:11:26 -0700145 PreCachedPath() {}
mtklein449d9b72015-09-28 10:33:02 -0700146 PreCachedPath(const SkPath& path);
mtkleinaf579032014-12-01 11:03:37 -0800147};
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000148
mtkleinaf579032014-12-01 11:03:37 -0800149// 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 {
mtklein9db912c2015-05-19 11:11:26 -0700152 TypedMatrix() {}
mtklein449d9b72015-09-28 10:33:02 -0700153 TypedMatrix(const SkMatrix& matrix);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000154};
155
mtklein449d9b72015-09-28 10:33:02 -0700156enum 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.
mtklein1bb5fec2016-08-01 13:17:47 -0700160 kHasPaint_Tag = 8, // May have an SkPaint field, at least optionally.
mtklein449d9b72015-09-28 10:33:02 -0700161};
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000162
mtklein449d9b72015-09-28 10:33:02 -0700163// 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};
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000170
mtklein449d9b72015-09-28 10:33:02 -0700171RECORD(NoOp, 0);
172RECORD(Restore, 0,
173 SkIRect devBounds;
174 TypedMatrix matrix);
175RECORD(Save, 0);
176
mtklein1bb5fec2016-08-01 13:17:47 -0700177RECORD(SaveLayer, kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700178 Optional<SkRect> bounds;
179 Optional<SkPaint> paint;
mtkleinda574d12016-08-01 11:24:03 -0700180 sk_sp<const SkImageFilter> backdrop;
reed4960eee2015-12-18 07:09:18 -0800181 SkCanvas::SaveLayerFlags saveLayerFlags);
mtklein449d9b72015-09-28 10:33:02 -0700182
183RECORD(SetMatrix, 0,
184 TypedMatrix matrix);
mtkleine9d20522015-11-19 12:08:24 -0800185RECORD(Concat, 0,
186 TypedMatrix matrix);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000187
mtkleincbdf0072016-08-19 09:05:27 -0700188RECORD(Translate, 0,
189 SkScalar dx;
190 SkScalar dy);
vjiaoblacke5de1302016-07-13 14:05:28 -0700191RECORD(TranslateZ, 0, SkScalar z);
192
mtkleincdeeb092014-11-20 09:14:28 -0800193struct RegionOpAndAA {
mtklein9db912c2015-05-19 11:11:26 -0700194 RegionOpAndAA() {}
mtkleincdeeb092014-11-20 09:14:28 -0800195 RegionOpAndAA(SkRegion::Op op, bool aa) : op(op), aa(aa) {}
196 SkRegion::Op 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};
bungeman99fe8222015-08-20 07:57:51 -0700199static_assert(sizeof(RegionOpAndAA) == 4, "RegionOpAndAASize");
mtkleincdeeb092014-11-20 09:14:28 -0800200
mtklein449d9b72015-09-28 10:33:02 -0700201RECORD(ClipPath, 0,
202 SkIRect devBounds;
203 PreCachedPath path;
204 RegionOpAndAA opAA);
205RECORD(ClipRRect, 0,
206 SkIRect devBounds;
207 SkRRect rrect;
208 RegionOpAndAA opAA);
209RECORD(ClipRect, 0,
210 SkIRect devBounds;
211 SkRect rect;
212 RegionOpAndAA opAA);
213RECORD(ClipRegion, 0,
214 SkIRect devBounds;
215 SkRegion region;
216 SkRegion::Op op);
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000217
commit-bot@chromium.org37f6e622014-05-07 22:59:38 +0000218// While not strictly required, if you have an SkPaint, it's fastest to put it first.
bsalomonac3aa242016-08-19 11:25:19 -0700219RECORD(DrawArc, kDraw_Tag|kHasPaint_Tag,
220 SkPaint paint;
221 SkRect oval;
222 SkScalar startAngle;
223 SkScalar sweepAngle;
224 unsigned useCenter);
mtklein1bb5fec2016-08-01 13:17:47 -0700225RECORD(DrawDRRect, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700226 SkPaint paint;
227 SkRRect outer;
228 SkRRect inner);
229RECORD(DrawDrawable, kDraw_Tag,
230 Optional<SkMatrix> matrix;
231 SkRect worstCaseBounds;
232 int32_t index);
mtklein1bb5fec2016-08-01 13:17:47 -0700233RECORD(DrawImage, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700234 Optional<SkPaint> paint;
mtkleinda574d12016-08-01 11:24:03 -0700235 sk_sp<const SkImage> image;
mtklein449d9b72015-09-28 10:33:02 -0700236 SkScalar left;
237 SkScalar top);
msarettc573a402016-08-02 08:05:56 -0700238RECORD(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;
msarett0764efe2016-09-02 11:24:30 -0700245 int flagCount;
246 PODArray<SkCanvas::Lattice::Flags> flags;
msarettc573a402016-08-02 08:05:56 -0700247 SkRect dst);
mtklein1bb5fec2016-08-01 13:17:47 -0700248RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700249 Optional<SkPaint> paint;
mtkleinda574d12016-08-01 11:24:03 -0700250 sk_sp<const SkImage> image;
mtklein449d9b72015-09-28 10:33:02 -0700251 Optional<SkRect> src;
252 SkRect dst;
253 SkCanvas::SrcRectConstraint constraint);
mtklein1bb5fec2016-08-01 13:17:47 -0700254RECORD(DrawImageNine, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700255 Optional<SkPaint> paint;
mtkleinda574d12016-08-01 11:24:03 -0700256 sk_sp<const SkImage> image;
mtklein449d9b72015-09-28 10:33:02 -0700257 SkIRect center;
258 SkRect dst);
mtklein1bb5fec2016-08-01 13:17:47 -0700259RECORD(DrawOval, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700260 SkPaint paint;
261 SkRect oval);
mtklein1bb5fec2016-08-01 13:17:47 -0700262RECORD(DrawPaint, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700263 SkPaint paint);
mtklein1bb5fec2016-08-01 13:17:47 -0700264RECORD(DrawPath, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700265 SkPaint paint;
266 PreCachedPath path);
mtklein1bb5fec2016-08-01 13:17:47 -0700267RECORD(DrawPicture, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700268 Optional<SkPaint> paint;
mtkleinda574d12016-08-01 11:24:03 -0700269 sk_sp<const SkPicture> picture;
mtklein449d9b72015-09-28 10:33:02 -0700270 TypedMatrix matrix);
mtklein1bb5fec2016-08-01 13:17:47 -0700271RECORD(DrawShadowedPicture, kDraw_Tag|kHasPaint_Tag,
vjiaoblack95302da2016-07-21 10:25:54 -0700272 Optional<SkPaint> paint;
mtkleinda574d12016-08-01 11:24:03 -0700273 sk_sp<const SkPicture> picture;
vjiaoblacke6f5d562016-08-25 06:30:23 -0700274 TypedMatrix matrix;
275 const SkShadowParams& params);
mtklein1bb5fec2016-08-01 13:17:47 -0700276RECORD(DrawPoints, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700277 SkPaint paint;
278 SkCanvas::PointMode mode;
279 unsigned count;
280 SkPoint* pts);
mtklein1bb5fec2016-08-01 13:17:47 -0700281RECORD(DrawPosText, kDraw_Tag|kHasText_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700282 SkPaint paint;
283 PODArray<char> text;
284 size_t byteLength;
285 PODArray<SkPoint> pos);
mtklein1bb5fec2016-08-01 13:17:47 -0700286RECORD(DrawPosTextH, kDraw_Tag|kHasText_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700287 SkPaint paint;
288 PODArray<char> text;
289 unsigned byteLength;
290 SkScalar y;
291 PODArray<SkScalar> xpos);
mtklein1bb5fec2016-08-01 13:17:47 -0700292RECORD(DrawRRect, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700293 SkPaint paint;
294 SkRRect rrect);
mtklein1bb5fec2016-08-01 13:17:47 -0700295RECORD(DrawRect, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700296 SkPaint paint;
297 SkRect rect);
msarett44df6512016-08-25 13:54:30 -0700298RECORD(DrawRegion, kDraw_Tag|kHasPaint_Tag,
299 SkPaint paint;
300 SkRegion region);
mtklein1bb5fec2016-08-01 13:17:47 -0700301RECORD(DrawText, kDraw_Tag|kHasText_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700302 SkPaint paint;
303 PODArray<char> text;
304 size_t byteLength;
305 SkScalar x;
306 SkScalar y);
mtklein1bb5fec2016-08-01 13:17:47 -0700307RECORD(DrawTextBlob, kDraw_Tag|kHasText_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700308 SkPaint paint;
mtkleinda574d12016-08-01 11:24:03 -0700309 sk_sp<const SkTextBlob> blob;
mtklein449d9b72015-09-28 10:33:02 -0700310 SkScalar x;
311 SkScalar y);
mtklein1bb5fec2016-08-01 13:17:47 -0700312RECORD(DrawTextOnPath, kDraw_Tag|kHasText_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700313 SkPaint paint;
314 PODArray<char> text;
315 size_t byteLength;
316 PreCachedPath path;
317 TypedMatrix matrix);
mtklein1bb5fec2016-08-01 13:17:47 -0700318RECORD(DrawTextRSXform, kDraw_Tag|kHasText_Tag|kHasPaint_Tag,
reed45561a02016-07-07 12:47:17 -0700319 SkPaint paint;
320 PODArray<char> text;
321 size_t byteLength;
322 PODArray<SkRSXform> xforms;
323 Optional<SkRect> cull);
mtklein1bb5fec2016-08-01 13:17:47 -0700324RECORD(DrawPatch, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700325 SkPaint paint;
326 PODArray<SkPoint> cubics;
327 PODArray<SkColor> colors;
328 PODArray<SkPoint> texCoords;
mtkleinda574d12016-08-01 11:24:03 -0700329 sk_sp<SkXfermode> xmode);
mtklein1bb5fec2016-08-01 13:17:47 -0700330RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700331 Optional<SkPaint> paint;
mtkleinda574d12016-08-01 11:24:03 -0700332 sk_sp<const SkImage> atlas;
mtklein449d9b72015-09-28 10:33:02 -0700333 PODArray<SkRSXform> xforms;
334 PODArray<SkRect> texs;
335 PODArray<SkColor> colors;
336 int count;
337 SkXfermode::Mode mode;
338 Optional<SkRect> cull);
mtklein1bb5fec2016-08-01 13:17:47 -0700339RECORD(DrawVertices, kDraw_Tag|kHasPaint_Tag,
mtklein449d9b72015-09-28 10:33:02 -0700340 SkPaint paint;
341 SkCanvas::VertexMode vmode;
342 int vertexCount;
343 PODArray<SkPoint> vertices;
344 PODArray<SkPoint> texs;
345 PODArray<SkColor> colors;
mtkleinda574d12016-08-01 11:24:03 -0700346 sk_sp<SkXfermode> xmode;
mtklein449d9b72015-09-28 10:33:02 -0700347 PODArray<uint16_t> indices;
348 int indexCount);
mtklein1bb5fec2016-08-01 13:17:47 -0700349RECORD(DrawAnnotation, 0, // TODO: kDraw_Tag, skia:5548
reedf70b5312016-03-04 16:36:20 -0800350 SkRect rect;
351 SkString key;
mtkleinda574d12016-08-01 11:24:03 -0700352 sk_sp<SkData> value);
mtklein449d9b72015-09-28 10:33:02 -0700353#undef RECORD
commit-bot@chromium.orge3ff5582014-04-01 16:24:06 +0000354
355} // namespace SkRecords
356
357#endif//SkRecords_DEFINED