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 | // Like Optional, but ptr must not be NULL. |
113 | template <typename T> |
114 | class Adopted { |
115 | public: |
116 | Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); } |
117 | Adopted(Adopted* source) { |
118 | // Transfer ownership from source to this. |
119 | fPtr = source->fPtr; |
120 | source->fPtr = NULL; |
121 | } |
122 | ~Adopted() { if (fPtr) fPtr->~T(); } |
123 | |
124 | ACT_AS_PTR(fPtr) |
125 | private: |
126 | T* fPtr; |
127 | Adopted(const Adopted&) = delete; |
128 | Adopted& operator=(const Adopted&) = delete; |
129 | }; |
130 | |
131 | // PODArray doesn't own the pointer's memory, and we assume the data is POD. |
132 | template <typename T> |
133 | class PODArray { |
134 | public: |
135 | PODArray() {} |
136 | PODArray(T* ptr) : fPtr(ptr) {} |
137 | // Default copy and assign. |
138 | |
139 | ACT_AS_PTR(fPtr) |
140 | private: |
141 | T* fPtr; |
142 | }; |
143 | |
144 | #undef ACT_AS_PTR |
145 | |
146 | // SkPath::getBounds() isn't thread safe unless we precache the bounds in a singlethreaded context. |
147 | // SkPath::cheapComputeDirection() is similar. |
148 | // Recording is a convenient time to cache these, or we can delay it to between record and playback. |
149 | struct PreCachedPath : public SkPath { |
150 | PreCachedPath() {} |
151 | PreCachedPath(const SkPath& path); |
152 | }; |
153 | |
154 | // Like SkPath::getBounds(), SkMatrix::getType() isn't thread safe unless we precache it. |
155 | // This may not cover all SkMatrices used by the picture (e.g. some could be hiding in a shader). |
156 | struct TypedMatrix : public SkMatrix { |
157 | TypedMatrix() {} |
158 | TypedMatrix(const SkMatrix& matrix); |
159 | }; |
160 | |
161 | enum Tags { |
162 | kDraw_Tag = 1, // May draw something (usually named DrawFoo). |
163 | kHasImage_Tag = 2, // Contains an SkImage or SkBitmap. |
164 | kHasText_Tag = 4, // Contains text. |
165 | kHasPaint_Tag = 8, // May have an SkPaint field, at least optionally. |
166 | |
167 | kDrawWithPaint_Tag = kDraw_Tag | kHasPaint_Tag, |
168 | }; |
169 | |
170 | // A macro to make it a little easier to define a struct that can be stored in SkRecord. |
171 | #define RECORD(T, tags, ...) \ |
172 | struct T { \ |
173 | static const Type kType = T##_Type; \ |
174 | static const int kTags = tags; \ |
175 | __VA_ARGS__; \ |
176 | }; |
177 | |
178 | RECORD(NoOp, 0); |
179 | RECORD(Flush, 0); |
180 | RECORD(Restore, 0, |
181 | TypedMatrix matrix); |
182 | RECORD(Save, 0); |
183 | |
184 | RECORD(SaveLayer, kHasPaint_Tag, |
185 | Optional<SkRect> bounds; |
186 | Optional<SkPaint> paint; |
187 | sk_sp<const SkImageFilter> backdrop; |
188 | sk_sp<const SkImage> clipMask; |
189 | Optional<SkMatrix> clipMatrix; |
190 | SkCanvas::SaveLayerFlags saveLayerFlags); |
191 | |
192 | RECORD(SaveBehind, 0, |
193 | Optional<SkRect> subset); |
194 | |
195 | RECORD(MarkCTM, 0, |
196 | uint32_t id); |
197 | RECORD(SetMatrix, 0, |
198 | TypedMatrix matrix); |
199 | RECORD(Concat, 0, |
200 | TypedMatrix matrix); |
201 | RECORD(Concat44, 0, |
202 | SkM44 matrix); |
203 | |
204 | RECORD(Translate, 0, |
205 | SkScalar dx; |
206 | SkScalar dy); |
207 | |
208 | RECORD(Scale, 0, |
209 | SkScalar sx; |
210 | SkScalar sy); |
211 | |
212 | struct ClipOpAndAA { |
213 | ClipOpAndAA() {} |
214 | ClipOpAndAA(SkClipOp op, bool aa) : fOp(static_cast<unsigned>(op)), fAA(aa) {} |
215 | |
216 | SkClipOp op() const { return static_cast<SkClipOp>(fOp); } |
217 | bool aa() const { return fAA != 0; } |
218 | |
219 | private: |
220 | unsigned fOp : 31; // This really only needs to be 3, but there's no win today to do so. |
221 | unsigned fAA : 1; // MSVC won't pack an enum with an bool, so we call this an unsigned. |
222 | }; |
223 | static_assert(sizeof(ClipOpAndAA) == 4, "ClipOpAndAASize" ); |
224 | |
225 | RECORD(ClipPath, 0, |
226 | PreCachedPath path; |
227 | ClipOpAndAA opAA); |
228 | RECORD(ClipRRect, 0, |
229 | SkRRect rrect; |
230 | ClipOpAndAA opAA); |
231 | RECORD(ClipRect, 0, |
232 | SkRect rect; |
233 | ClipOpAndAA opAA); |
234 | RECORD(ClipRegion, 0, |
235 | SkRegion region; |
236 | SkClipOp op); |
237 | RECORD(ClipShader, 0, |
238 | sk_sp<SkShader> shader; |
239 | SkClipOp op); |
240 | |
241 | // While not strictly required, if you have an SkPaint, it's fastest to put it first. |
242 | RECORD(DrawArc, kDraw_Tag|kHasPaint_Tag, |
243 | SkPaint paint; |
244 | SkRect oval; |
245 | SkScalar startAngle; |
246 | SkScalar sweepAngle; |
247 | unsigned useCenter); |
248 | RECORD(DrawDRRect, kDraw_Tag|kHasPaint_Tag, |
249 | SkPaint paint; |
250 | SkRRect outer; |
251 | SkRRect inner); |
252 | RECORD(DrawDrawable, kDraw_Tag, |
253 | Optional<SkMatrix> matrix; |
254 | SkRect worstCaseBounds; |
255 | int32_t index); |
256 | RECORD(DrawImage, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |
257 | Optional<SkPaint> paint; |
258 | sk_sp<const SkImage> image; |
259 | SkScalar left; |
260 | SkScalar top); |
261 | RECORD(DrawImageLattice, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |
262 | Optional<SkPaint> paint; |
263 | sk_sp<const SkImage> image; |
264 | int xCount; |
265 | PODArray<int> xDivs; |
266 | int yCount; |
267 | PODArray<int> yDivs; |
268 | int flagCount; |
269 | PODArray<SkCanvas::Lattice::RectType> flags; |
270 | PODArray<SkColor> colors; |
271 | SkIRect src; |
272 | SkRect dst); |
273 | RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |
274 | Optional<SkPaint> paint; |
275 | sk_sp<const SkImage> image; |
276 | Optional<SkRect> src; |
277 | SkRect dst; |
278 | SkCanvas::SrcRectConstraint constraint); |
279 | RECORD(DrawImageNine, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |
280 | Optional<SkPaint> paint; |
281 | sk_sp<const SkImage> image; |
282 | SkIRect center; |
283 | SkRect dst); |
284 | RECORD(DrawOval, kDraw_Tag|kHasPaint_Tag, |
285 | SkPaint paint; |
286 | SkRect oval); |
287 | RECORD(DrawPaint, kDraw_Tag|kHasPaint_Tag, |
288 | SkPaint paint); |
289 | RECORD(DrawBehind, kDraw_Tag|kHasPaint_Tag, |
290 | SkPaint paint); |
291 | RECORD(DrawPath, kDraw_Tag|kHasPaint_Tag, |
292 | SkPaint paint; |
293 | PreCachedPath path); |
294 | RECORD(DrawPicture, kDraw_Tag|kHasPaint_Tag, |
295 | Optional<SkPaint> paint; |
296 | sk_sp<const SkPicture> picture; |
297 | TypedMatrix matrix); |
298 | RECORD(DrawPoints, kDraw_Tag|kHasPaint_Tag, |
299 | SkPaint paint; |
300 | SkCanvas::PointMode mode; |
301 | unsigned count; |
302 | SkPoint* pts); |
303 | RECORD(DrawRRect, kDraw_Tag|kHasPaint_Tag, |
304 | SkPaint paint; |
305 | SkRRect rrect); |
306 | RECORD(DrawRect, kDraw_Tag|kHasPaint_Tag, |
307 | SkPaint paint; |
308 | SkRect rect); |
309 | RECORD(DrawRegion, kDraw_Tag|kHasPaint_Tag, |
310 | SkPaint paint; |
311 | SkRegion region); |
312 | RECORD(DrawTextBlob, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, |
313 | SkPaint paint; |
314 | sk_sp<const SkTextBlob> blob; |
315 | SkScalar x; |
316 | SkScalar y); |
317 | RECORD(DrawPatch, kDraw_Tag|kHasPaint_Tag, |
318 | SkPaint paint; |
319 | PODArray<SkPoint> cubics; |
320 | PODArray<SkColor> colors; |
321 | PODArray<SkPoint> texCoords; |
322 | SkBlendMode bmode); |
323 | RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |
324 | Optional<SkPaint> paint; |
325 | sk_sp<const SkImage> atlas; |
326 | PODArray<SkRSXform> xforms; |
327 | PODArray<SkRect> texs; |
328 | PODArray<SkColor> colors; |
329 | int count; |
330 | SkBlendMode mode; |
331 | Optional<SkRect> cull); |
332 | RECORD(DrawVertices, kDraw_Tag|kHasPaint_Tag, |
333 | SkPaint paint; |
334 | sk_sp<SkVertices> vertices; |
335 | SkBlendMode bmode); |
336 | RECORD(DrawShadowRec, kDraw_Tag, |
337 | PreCachedPath path; |
338 | SkDrawShadowRec rec); |
339 | RECORD(DrawAnnotation, 0, // TODO: kDraw_Tag, skia:5548 |
340 | SkRect rect; |
341 | SkString key; |
342 | sk_sp<SkData> value); |
343 | RECORD(DrawEdgeAAQuad, kDraw_Tag, |
344 | SkRect rect; |
345 | PODArray<SkPoint> clip; |
346 | SkCanvas::QuadAAFlags aa; |
347 | SkColor4f color; |
348 | SkBlendMode mode); |
349 | RECORD(DrawEdgeAAImageSet, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |
350 | Optional<SkPaint> paint; |
351 | SkAutoTArray<SkCanvas::ImageSetEntry> set; |
352 | int count; |
353 | PODArray<SkPoint> dstClips; |
354 | PODArray<SkMatrix> preViewMatrices; |
355 | SkCanvas::SrcRectConstraint constraint); |
356 | #undef RECORD |
357 | |
358 | } // namespace SkRecords |
359 | |
360 | #endif//SkRecords_DEFINED |
361 | |