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