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 : #include "SkBigPicture.h"
9 : #include "SkCanvasPriv.h"
10 : #include "SkImage.h"
11 : #include "SkPatchUtils.h"
12 : #include "SkPicture.h"
13 : #include "SkRecorder.h"
14 : #include "SkSurface.h"
15 :
16 0 : SkDrawableList::~SkDrawableList() {
17 0 : fArray.unrefAll();
18 0 : }
19 :
20 0 : SkBigPicture::SnapshotArray* SkDrawableList::newDrawableSnapshot() {
21 0 : const int count = fArray.count();
22 0 : if (0 == count) {
23 0 : return nullptr;
24 : }
25 0 : SkAutoTMalloc<const SkPicture*> pics(count);
26 0 : for (int i = 0; i < count; ++i) {
27 0 : pics[i] = fArray[i]->newPictureSnapshot();
28 : }
29 0 : return new SkBigPicture::SnapshotArray(pics.release(), count);
30 : }
31 :
32 0 : void SkDrawableList::append(SkDrawable* drawable) {
33 0 : *fArray.append() = SkRef(drawable);
34 0 : }
35 :
36 : ///////////////////////////////////////////////////////////////////////////////////////////////
37 :
38 0 : SkRecorder::SkRecorder(SkRecord* record, int width, int height, SkMiniRecorder* mr)
39 : : SkNoDrawCanvas(width, height)
40 : , fDrawPictureMode(Record_DrawPictureMode)
41 : , fApproxBytesUsedBySubPictures(0)
42 : , fRecord(record)
43 0 : , fMiniRecorder(mr) {}
44 :
45 0 : SkRecorder::SkRecorder(SkRecord* record, const SkRect& bounds, SkMiniRecorder* mr)
46 0 : : SkNoDrawCanvas(bounds.roundOut())
47 : , fDrawPictureMode(Record_DrawPictureMode)
48 : , fApproxBytesUsedBySubPictures(0)
49 : , fRecord(record)
50 0 : , fMiniRecorder(mr) {}
51 :
52 0 : void SkRecorder::reset(SkRecord* record, const SkRect& bounds,
53 : DrawPictureMode dpm, SkMiniRecorder* mr) {
54 0 : this->forgetRecord();
55 0 : fDrawPictureMode = dpm;
56 0 : fRecord = record;
57 0 : this->resetForNextPicture(bounds.roundOut());
58 0 : fMiniRecorder = mr;
59 0 : }
60 :
61 0 : void SkRecorder::forgetRecord() {
62 0 : fDrawableList.reset(nullptr);
63 0 : fApproxBytesUsedBySubPictures = 0;
64 0 : fRecord = nullptr;
65 0 : }
66 :
67 : // To make appending to fRecord a little less verbose.
68 : #define APPEND(T, ...) \
69 : if (fMiniRecorder) { \
70 : this->flushMiniRecorder(); \
71 : } \
72 : new (fRecord->append<SkRecords::T>()) SkRecords::T{__VA_ARGS__}
73 :
74 : #define TRY_MINIRECORDER(method, ...) \
75 : if (fMiniRecorder && fMiniRecorder->method(__VA_ARGS__)) { return; }
76 :
77 : // For methods which must call back into SkNoDrawCanvas.
78 : #define INHERITED(method, ...) this->SkNoDrawCanvas::method(__VA_ARGS__)
79 :
80 : // Use copy() only for optional arguments, to be copied if present or skipped if not.
81 : // (For most types we just pass by value and let copy constructors do their thing.)
82 : template <typename T>
83 0 : T* SkRecorder::copy(const T* src) {
84 0 : if (nullptr == src) {
85 0 : return nullptr;
86 : }
87 0 : return new (fRecord->alloc<T>()) T(*src);
88 : }
89 :
90 : // This copy() is for arrays.
91 : // It will work with POD or non-POD, though currently we only use it for POD.
92 : template <typename T>
93 0 : T* SkRecorder::copy(const T src[], size_t count) {
94 0 : if (nullptr == src) {
95 0 : return nullptr;
96 : }
97 0 : T* dst = fRecord->alloc<T>(count);
98 0 : for (size_t i = 0; i < count; i++) {
99 0 : new (dst + i) T(src[i]);
100 : }
101 0 : return dst;
102 : }
103 :
104 : // Specialization for copying strings, using memcpy.
105 : // This measured around 2x faster for copying code points,
106 : // but I found no corresponding speedup for other arrays.
107 : template <>
108 0 : char* SkRecorder::copy(const char src[], size_t count) {
109 0 : if (nullptr == src) {
110 0 : return nullptr;
111 : }
112 0 : char* dst = fRecord->alloc<char>(count);
113 0 : memcpy(dst, src, count);
114 0 : return dst;
115 : }
116 :
117 : // As above, assuming and copying a terminating \0.
118 : template <>
119 0 : char* SkRecorder::copy(const char* src) {
120 0 : return this->copy(src, strlen(src)+1);
121 : }
122 :
123 0 : void SkRecorder::flushMiniRecorder() {
124 0 : if (fMiniRecorder) {
125 0 : SkMiniRecorder* mr = fMiniRecorder;
126 0 : fMiniRecorder = nullptr; // Needs to happen before flushAndReset() or we recurse forever.
127 0 : mr->flushAndReset(this);
128 : }
129 0 : }
130 :
131 0 : void SkRecorder::onDrawPaint(const SkPaint& paint) {
132 0 : APPEND(DrawPaint, paint);
133 0 : }
134 :
135 0 : void SkRecorder::onDrawPoints(PointMode mode,
136 : size_t count,
137 : const SkPoint pts[],
138 : const SkPaint& paint) {
139 0 : APPEND(DrawPoints, paint, mode, SkToUInt(count), this->copy(pts, count));
140 0 : }
141 :
142 0 : void SkRecorder::onDrawRect(const SkRect& rect, const SkPaint& paint) {
143 0 : TRY_MINIRECORDER(drawRect, rect, paint);
144 0 : APPEND(DrawRect, paint, rect);
145 : }
146 :
147 0 : void SkRecorder::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
148 0 : APPEND(DrawRegion, paint, region);
149 0 : }
150 :
151 0 : void SkRecorder::onDrawOval(const SkRect& oval, const SkPaint& paint) {
152 0 : APPEND(DrawOval, paint, oval);
153 0 : }
154 :
155 0 : void SkRecorder::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
156 : bool useCenter, const SkPaint& paint) {
157 0 : APPEND(DrawArc, paint, oval, startAngle, sweepAngle, useCenter);
158 0 : }
159 :
160 0 : void SkRecorder::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
161 0 : APPEND(DrawRRect, paint, rrect);
162 0 : }
163 :
164 0 : void SkRecorder::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
165 0 : APPEND(DrawDRRect, paint, outer, inner);
166 0 : }
167 :
168 0 : void SkRecorder::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
169 0 : if (fDrawPictureMode == Record_DrawPictureMode) {
170 0 : if (!fDrawableList) {
171 0 : fDrawableList.reset(new SkDrawableList);
172 : }
173 0 : fDrawableList->append(drawable);
174 0 : APPEND(DrawDrawable, this->copy(matrix), drawable->getBounds(), fDrawableList->count() - 1);
175 : } else {
176 0 : SkASSERT(fDrawPictureMode == Playback_DrawPictureMode);
177 0 : drawable->draw(this, matrix);
178 : }
179 0 : }
180 :
181 0 : void SkRecorder::onDrawPath(const SkPath& path, const SkPaint& paint) {
182 0 : TRY_MINIRECORDER(drawPath, path, paint);
183 0 : APPEND(DrawPath, paint, path);
184 : }
185 :
186 0 : void SkRecorder::onDrawBitmap(const SkBitmap& bitmap,
187 : SkScalar left,
188 : SkScalar top,
189 : const SkPaint* paint) {
190 0 : sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
191 0 : if (image) {
192 0 : this->onDrawImage(image.get(), left, top, paint);
193 : }
194 0 : }
195 :
196 0 : void SkRecorder::onDrawBitmapRect(const SkBitmap& bitmap,
197 : const SkRect* src,
198 : const SkRect& dst,
199 : const SkPaint* paint,
200 : SrcRectConstraint constraint) {
201 0 : sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
202 0 : if (image) {
203 0 : this->onDrawImageRect(image.get(), src, dst, paint, constraint);
204 : }
205 0 : }
206 :
207 0 : void SkRecorder::onDrawBitmapNine(const SkBitmap& bitmap,
208 : const SkIRect& center,
209 : const SkRect& dst,
210 : const SkPaint* paint) {
211 0 : sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
212 0 : if (image) {
213 0 : this->onDrawImageNine(image.get(), center, dst, paint);
214 : }
215 0 : }
216 :
217 0 : void SkRecorder::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
218 : const SkRect& dst, const SkPaint* paint) {
219 0 : sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
220 0 : this->onDrawImageLattice(image.get(), lattice, dst, paint);
221 0 : }
222 :
223 0 : void SkRecorder::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
224 : const SkPaint* paint) {
225 0 : APPEND(DrawImage, this->copy(paint), sk_ref_sp(image), left, top);
226 0 : }
227 :
228 0 : void SkRecorder::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
229 : const SkPaint* paint, SrcRectConstraint constraint) {
230 0 : APPEND(DrawImageRect, this->copy(paint), sk_ref_sp(image), this->copy(src), dst, constraint);
231 0 : }
232 :
233 0 : void SkRecorder::onDrawImageNine(const SkImage* image, const SkIRect& center,
234 : const SkRect& dst, const SkPaint* paint) {
235 0 : APPEND(DrawImageNine, this->copy(paint), sk_ref_sp(image), center, dst);
236 0 : }
237 :
238 0 : void SkRecorder::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
239 : const SkPaint* paint) {
240 0 : int flagCount = lattice.fFlags ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0;
241 0 : SkASSERT(lattice.fBounds);
242 0 : APPEND(DrawImageLattice, this->copy(paint), sk_ref_sp(image),
243 : lattice.fXCount, this->copy(lattice.fXDivs, lattice.fXCount),
244 : lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount),
245 0 : flagCount, this->copy(lattice.fFlags, flagCount), *lattice.fBounds, dst);
246 0 : }
247 :
248 0 : void SkRecorder::onDrawText(const void* text, size_t byteLength,
249 : SkScalar x, SkScalar y, const SkPaint& paint) {
250 0 : APPEND(DrawText,
251 0 : paint, this->copy((const char*)text, byteLength), byteLength, x, y);
252 0 : }
253 :
254 0 : void SkRecorder::onDrawPosText(const void* text, size_t byteLength,
255 : const SkPoint pos[], const SkPaint& paint) {
256 0 : const int points = paint.countText(text, byteLength);
257 0 : APPEND(DrawPosText,
258 : paint,
259 : this->copy((const char*)text, byteLength),
260 : byteLength,
261 0 : this->copy(pos, points));
262 0 : }
263 :
264 0 : void SkRecorder::onDrawPosTextH(const void* text, size_t byteLength,
265 : const SkScalar xpos[], SkScalar constY, const SkPaint& paint) {
266 0 : const int points = paint.countText(text, byteLength);
267 0 : APPEND(DrawPosTextH,
268 : paint,
269 : this->copy((const char*)text, byteLength),
270 : SkToUInt(byteLength),
271 : constY,
272 0 : this->copy(xpos, points));
273 0 : }
274 :
275 0 : void SkRecorder::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
276 : const SkMatrix* matrix, const SkPaint& paint) {
277 0 : APPEND(DrawTextOnPath,
278 : paint,
279 : this->copy((const char*)text, byteLength),
280 : byteLength,
281 : path,
282 0 : matrix ? *matrix : SkMatrix::I());
283 0 : }
284 :
285 0 : void SkRecorder::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
286 : const SkRect* cull, const SkPaint& paint) {
287 0 : APPEND(DrawTextRSXform,
288 : paint,
289 : this->copy((const char*)text, byteLength),
290 : byteLength,
291 : this->copy(xform, paint.countText(text, byteLength)),
292 0 : this->copy(cull));
293 0 : }
294 :
295 0 : void SkRecorder::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
296 : const SkPaint& paint) {
297 0 : TRY_MINIRECORDER(drawTextBlob, blob, x, y, paint);
298 0 : APPEND(DrawTextBlob, paint, sk_ref_sp(blob), x, y);
299 : }
300 :
301 0 : void SkRecorder::onDrawPicture(const SkPicture* pic, const SkMatrix* matrix, const SkPaint* paint) {
302 0 : if (fDrawPictureMode == Record_DrawPictureMode) {
303 0 : fApproxBytesUsedBySubPictures += pic->approximateBytesUsed();
304 0 : APPEND(DrawPicture, this->copy(paint), sk_ref_sp(pic), matrix ? *matrix : SkMatrix::I());
305 : } else {
306 0 : SkASSERT(fDrawPictureMode == Playback_DrawPictureMode);
307 0 : SkAutoCanvasMatrixPaint acmp(this, matrix, paint, pic->cullRect());
308 0 : pic->playback(this);
309 : }
310 0 : }
311 :
312 0 : void SkRecorder::onDrawShadowedPicture(const SkPicture* pic, const SkMatrix* matrix,
313 : const SkPaint* paint, const SkShadowParams& params) {
314 0 : if (fDrawPictureMode == Record_DrawPictureMode) {
315 0 : fApproxBytesUsedBySubPictures += pic->approximateBytesUsed();
316 0 : APPEND(DrawShadowedPicture, this->copy(paint),
317 : sk_ref_sp(pic),
318 : matrix ? *matrix : SkMatrix::I(),
319 0 : params);
320 : } else {
321 : // TODO update pic->playback(this) to draw the shadowed pic
322 0 : SkASSERT(fDrawPictureMode == Playback_DrawPictureMode);
323 0 : SkAutoCanvasMatrixPaint acmp(this, matrix, paint, pic->cullRect());
324 0 : pic->playback(this);
325 : }
326 0 : }
327 :
328 :
329 0 : void SkRecorder::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
330 : const SkPaint& paint) {
331 0 : APPEND(DrawVertices, paint, sk_ref_sp(const_cast<SkVertices*>(vertices)), bmode);
332 0 : }
333 :
334 0 : void SkRecorder::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
335 : const SkPoint texCoords[4], SkBlendMode bmode,
336 : const SkPaint& paint) {
337 0 : APPEND(DrawPatch, paint,
338 : cubics ? this->copy(cubics, SkPatchUtils::kNumCtrlPts) : nullptr,
339 : colors ? this->copy(colors, SkPatchUtils::kNumCorners) : nullptr,
340 : texCoords ? this->copy(texCoords, SkPatchUtils::kNumCorners) : nullptr,
341 0 : bmode);
342 0 : }
343 :
344 0 : void SkRecorder::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
345 : const SkColor colors[], int count, SkBlendMode mode,
346 : const SkRect* cull, const SkPaint* paint) {
347 0 : APPEND(DrawAtlas, this->copy(paint),
348 : sk_ref_sp(atlas),
349 : this->copy(xform, count),
350 : this->copy(tex, count),
351 : this->copy(colors, count),
352 : count,
353 : mode,
354 0 : this->copy(cull));
355 0 : }
356 :
357 0 : void SkRecorder::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
358 0 : APPEND(DrawAnnotation, rect, SkString(key), sk_ref_sp(value));
359 0 : }
360 :
361 0 : void SkRecorder::willSave() {
362 0 : APPEND(Save);
363 0 : }
364 :
365 0 : SkCanvas::SaveLayerStrategy SkRecorder::getSaveLayerStrategy(const SaveLayerRec& rec) {
366 0 : APPEND(SaveLayer, this->copy(rec.fBounds)
367 : , this->copy(rec.fPaint)
368 : , sk_ref_sp(rec.fBackdrop)
369 0 : , rec.fSaveLayerFlags);
370 0 : return SkCanvas::kNoLayer_SaveLayerStrategy;
371 : }
372 :
373 0 : void SkRecorder::didRestore() {
374 0 : APPEND(Restore, this->getDeviceClipBounds(), this->getTotalMatrix());
375 0 : }
376 :
377 0 : void SkRecorder::didConcat(const SkMatrix& matrix) {
378 0 : APPEND(Concat, matrix);
379 0 : }
380 :
381 0 : void SkRecorder::didSetMatrix(const SkMatrix& matrix) {
382 0 : APPEND(SetMatrix, matrix);
383 0 : }
384 :
385 0 : void SkRecorder::didTranslate(SkScalar dx, SkScalar dy) {
386 0 : APPEND(Translate, dx, dy);
387 0 : }
388 :
389 0 : void SkRecorder::didTranslateZ(SkScalar z) {
390 : #ifdef SK_EXPERIMENTAL_SHADOWING
391 : APPEND(TranslateZ, z);
392 : #endif
393 0 : }
394 :
395 0 : void SkRecorder::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
396 0 : INHERITED(onClipRect, rect, op, edgeStyle);
397 0 : SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
398 0 : APPEND(ClipRect, this->getDeviceClipBounds(), rect, opAA);
399 0 : }
400 :
401 0 : void SkRecorder::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
402 0 : INHERITED(onClipRRect, rrect, op, edgeStyle);
403 0 : SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
404 0 : APPEND(ClipRRect, this->getDeviceClipBounds(), rrect, opAA);
405 0 : }
406 :
407 0 : void SkRecorder::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
408 0 : INHERITED(onClipPath, path, op, edgeStyle);
409 0 : SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
410 0 : APPEND(ClipPath, this->getDeviceClipBounds(), path, opAA);
411 0 : }
412 :
413 0 : void SkRecorder::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
414 0 : INHERITED(onClipRegion, deviceRgn, op);
415 0 : APPEND(ClipRegion, this->getDeviceClipBounds(), deviceRgn, op);
416 0 : }
417 :
418 0 : sk_sp<SkSurface> SkRecorder::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
419 0 : return nullptr;
420 : }
|