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 | |