blob: 258160c4fe9a6930cb514cc5eef4bdfc0e7c3663 [file] [log] [blame]
reed54dc4872016-09-13 08:09:45 -07001/*
2 * Copyright 2016 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
Hal Canaryc640d0d2018-06-13 09:59:02 -04008#include "SkPipeCanvas.h"
9
Hal Canary95e3c052017-01-11 12:44:43 -050010#include "SkAutoMalloc.h"
Mike Reed7c9c9e42018-01-03 09:23:34 -050011#include "SkCanvasPriv.h"
reed54dc4872016-09-13 08:09:45 -070012#include "SkColorFilter.h"
13#include "SkDrawLooper.h"
Mike Reed7c9c9e42018-01-03 09:23:34 -050014#include "SkDrawShadowInfo.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040015#include "SkDrawable.h"
reed54dc4872016-09-13 08:09:45 -070016#include "SkImageFilter.h"
17#include "SkMaskFilter.h"
Hal Canary95e3c052017-01-11 12:44:43 -050018#include "SkPathEffect.h"
reed54dc4872016-09-13 08:09:45 -070019#include "SkPipeFormat.h"
Kevin Lubickc456b732017-01-11 17:21:57 +000020#include "SkRSXform.h"
reed54dc4872016-09-13 08:09:45 -070021#include "SkShader.h"
22#include "SkStream.h"
Cary Clark53c87692018-07-17 08:59:34 -040023#include "SkTextBlobPriv.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040024#include "SkTo.h"
reed54dc4872016-09-13 08:09:45 -070025#include "SkTypeface.h"
26
27template <typename T> void write_rrect(T* writer, const SkRRect& rrect) {
28 char tmp[SkRRect::kSizeInMemory];
29 rrect.writeToMemory(tmp);
30 writer->write(tmp, SkRRect::kSizeInMemory);
31}
32
33template <typename T> void write_pad(T* writer, const void* buffer, size_t len) {
34 writer->write(buffer, len & ~3);
35 if (len & 3) {
36 const char* src = (const char*)buffer + (len & ~3);
37 len &= 3;
38 uint32_t tmp = 0;
39 memcpy(&tmp, src, len);
40 writer->write(&tmp, 4);
41 }
42}
43
44///////////////////////////////////////////////////////////////////////////////////////////////////
45
46static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) {
47 // kRespectsStroke_PaintUsage is only valid if other bits are also set
48 SkASSERT(0 != (usage & ~kRespectsStroke_PaintUsage));
49
50 const SkScalar kTextSize_Default = 12;
51 const SkScalar kTextScaleX_Default = 1;
52 const SkScalar kTextSkewX_Default = 0;
53 const SkScalar kStrokeWidth_Default = 0;
54 const SkScalar kStrokeMiter_Default = 4;
55 const SkColor kColor_Default = SK_ColorBLACK;
56
57 unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0;
58
59 if (usage & kText_PaintUsage) {
60 bits |= (paint.getTextSize() != kTextSize_Default ? kTextSize_NonDef : 0);
61 bits |= (paint.getTextScaleX() != kTextScaleX_Default ? kTextScaleX_NonDef : 0);
62 bits |= (paint.getTextSkewX() != kTextSkewX_Default ? kTextSkewX_NonDef : 0);
63 bits |= (paint.getTypeface() ? kTypeface_NonDef : 0);
64 }
65
66 // TODO: kImage_PaintUsage only needs the shader/maskfilter IF its colortype is kAlpha_8
67
68 if (usage & (kVertices_PaintUsage | kDrawPaint_PaintUsage | kImage_PaintUsage |
69 kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
70 bits |= (paint.getShader() ? kShader_NonDef : 0);
71 }
72
73 if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
74 bits |= (paint.getPathEffect() ? kPathEffect_NonDef : 0);
reed54dc4872016-09-13 08:09:45 -070075
76 if (paint.getStyle() != SkPaint::kFill_Style || (usage & kRespectsStroke_PaintUsage)) {
77 bits |= (paint.getStrokeWidth() != kStrokeWidth_Default ? kStrokeWidth_NonDef : 0);
78 bits |= (paint.getStrokeMiter() != kStrokeMiter_Default ? kStrokeMiter_NonDef : 0);
79 }
80 }
81
82 if (usage &
83 (kText_PaintUsage | kGeometry_PaintUsage | kImage_PaintUsage | kTextBlob_PaintUsage))
84 {
85 bits |= (paint.getMaskFilter() ? kMaskFilter_NonDef : 0);
86 }
87
reed54dc4872016-09-13 08:09:45 -070088 bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0);
89 bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0);
90 bits |= (paint.getDrawLooper() ? kDrawLooper_NonDef : 0);
91
92 return SkToU16(bits);
93}
94
95static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
96 unsigned filter, unsigned style, unsigned caps, unsigned joins,
97 unsigned encoding) {
98 SkASSERT(kFlags_BPF + kHint_BPF + kAlign_BPF + kFilter_BPF <= 32);
99
100 ASSERT_FITS_IN(flags, kFlags_BPF);
101 ASSERT_FITS_IN(filter, kFilter_BPF);
102 ASSERT_FITS_IN(style, kStyle_BPF);
103 ASSERT_FITS_IN(caps, kCaps_BPF);
104 ASSERT_FITS_IN(joins, kJoins_BPF);
105 ASSERT_FITS_IN(hint, kHint_BPF);
106 ASSERT_FITS_IN(align, kAlign_BPF);
107 ASSERT_FITS_IN(encoding, kEncoding_BPF);
108
109 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
110 // add more bits in the future.
111
112 uint32_t packed = 0;
113 int shift = 32;
114
115 shift -= kFlags_BPF; packed |= (flags << shift);
116 shift -= kFilter_BPF; packed |= (filter << shift);
117 shift -= kStyle_BPF; packed |= (style << shift);
118 // these are only needed for stroking (geometry or text)
119 shift -= kCaps_BPF; packed |= (caps << shift);
120 shift -= kJoins_BPF; packed |= (joins << shift);
121 // these are only needed for text
122 shift -= kHint_BPF; packed |= (hint << shift);
123 shift -= kAlign_BPF; packed |= (align << shift);
124 shift -= kEncoding_BPF; packed |= (encoding << shift);
125
126 return packed;
127}
128
129#define CHECK_WRITE_SCALAR(writer, nondef, paint, Field) \
130 do { if (nondef & (k##Field##_NonDef)) { \
131 writer.writeScalar(paint.get##Field()); \
132 }} while (0)
133
134#define CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Field) \
135 do { if (nondef & (k##Field##_NonDef)) { \
136 SkFlattenable* f = paint.get##Field(); \
137 SkASSERT(f != nullptr); \
138 writer.writeFlattenable(f); \
139 } } while (0)
140
141/*
142 * Header:
143 * paint flags : 32
144 * non_def bits : 16
145 * xfermode enum : 8
146 * pad zeros : 8
147 */
148static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, unsigned usage) {
149 uint32_t packedFlags = pack_paint_flags(paint.getFlags(), paint.getHinting(),
150 paint.getTextAlign(), paint.getFilterQuality(),
151 paint.getStyle(), paint.getStrokeCap(),
152 paint.getStrokeJoin(), paint.getTextEncoding());
153 writer.write32(packedFlags);
154
155 unsigned nondef = compute_nondef(paint, (PaintUsage)usage);
reed54dc4872016-09-13 08:09:45 -0700156 const uint8_t pad = 0;
reed374772b2016-10-05 17:33:02 -0700157 writer.write32((nondef << 16) | ((unsigned)paint.getBlendMode() << 8) | pad);
reed54dc4872016-09-13 08:09:45 -0700158
159 CHECK_WRITE_SCALAR(writer, nondef, paint, TextSize);
160 CHECK_WRITE_SCALAR(writer, nondef, paint, TextScaleX);
161 CHECK_WRITE_SCALAR(writer, nondef, paint, TextSkewX);
162 CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeWidth);
163 CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeMiter);
164
165 if (nondef & kColor_NonDef) {
166 writer.write32(paint.getColor());
167 }
168 if (nondef & kTypeface_NonDef) {
169 // TODO: explore idea of writing bits indicating "use the prev (or prev N) face"
170 // e.g. 1-N bits is an index into a ring buffer of typefaces
171 SkTypeface* tf = paint.getTypeface();
172 SkASSERT(tf);
173 writer.writeTypeface(tf);
174 }
175
176 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, PathEffect);
177 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Shader);
reed54dc4872016-09-13 08:09:45 -0700178 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, MaskFilter);
179 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ColorFilter);
reed54dc4872016-09-13 08:09:45 -0700180 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ImageFilter);
181 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, DrawLooper);
182}
183
184class SkPipeWriter : public SkBinaryWriteBuffer {
185 enum {
186 N = 1024/4,
187 };
188 uint32_t fStorage[N];
189 SkWStream* fStream;
190
191public:
192 SkPipeWriter(SkWStream* stream, SkDeduper* deduper)
193 : SkBinaryWriteBuffer(fStorage, sizeof(fStorage))
194 , fStream(stream)
195 {
196 this->setDeduper(deduper);
197 }
198
199 SkPipeWriter(SkPipeCanvas* pc) : SkPipeWriter(pc->fStream, pc->fDeduper) {}
200
201 ~SkPipeWriter() override {
202 SkASSERT(SkIsAlign4(fStream->bytesWritten()));
203 this->writeToStream(fStream);
204 }
205
206 void writePaint(const SkPaint& paint) override {
207 write_paint(*this, paint, kUnknown_PaintUsage);
208 }
209};
210
211///////////////////////////////////////////////////////////////////////////////////////////////////
212
213SkPipeCanvas::SkPipeCanvas(const SkRect& cull, SkPipeDeduper* deduper, SkWStream* stream)
Florin Malita439ace92016-12-02 12:05:41 -0500214 : INHERITED(cull.roundOut())
reed54dc4872016-09-13 08:09:45 -0700215 , fDeduper(deduper)
216 , fStream(stream)
217{}
218
219SkPipeCanvas::~SkPipeCanvas() {}
220
221void SkPipeCanvas::willSave() {
222 fStream->write32(pack_verb(SkPipeVerb::kSave));
223 this->INHERITED::willSave();
224}
225
226SkCanvas::SaveLayerStrategy SkPipeCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
227 SkPipeWriter writer(this);
228 uint32_t extra = rec.fSaveLayerFlags;
229
230 // remap this wacky flag
Cary Clark7eddfb82018-03-13 14:41:10 -0400231 if (extra & SkCanvasPriv::kDontClipToLayer_SaveLayerFlag) {
232 extra &= ~SkCanvasPriv::kDontClipToLayer_SaveLayerFlag;
reed54dc4872016-09-13 08:09:45 -0700233 extra |= kDontClipToLayer_SaveLayerMask;
234 }
235
236 if (rec.fBounds) {
237 extra |= kHasBounds_SaveLayerMask;
238 }
239 if (rec.fPaint) {
240 extra |= kHasPaint_SaveLayerMask;
241 }
242 if (rec.fBackdrop) {
243 extra |= kHasBackdrop_SaveLayerMask;
244 }
Florin Malita53f77bd2017-04-28 13:48:37 -0400245 if (rec.fClipMask) {
246 extra |= kHasClipMask_SaveLayerMask;
247 }
248 if (rec.fClipMatrix) {
249 extra |= kHasClipMatrix_SaveLayerMask;
250 }
Mike Kleinb3384842017-03-27 14:28:07 -0400251
reed54dc4872016-09-13 08:09:45 -0700252 writer.write32(pack_verb(SkPipeVerb::kSaveLayer, extra));
253 if (rec.fBounds) {
254 writer.writeRect(*rec.fBounds);
255 }
256 if (rec.fPaint) {
257 write_paint(writer, *rec.fPaint, kSaveLayer_PaintUsage);
258 }
259 if (rec.fBackdrop) {
260 writer.writeFlattenable(rec.fBackdrop);
261 }
Florin Malita53f77bd2017-04-28 13:48:37 -0400262 if (rec.fClipMask) {
Mike Kleinb34ab042017-05-01 21:34:14 +0000263 writer.writeImage(rec.fClipMask);
Florin Malita53f77bd2017-04-28 13:48:37 -0400264 }
265 if (rec.fClipMatrix) {
266 writer.writeMatrix(*rec.fClipMatrix);
267 }
268
reed54dc4872016-09-13 08:09:45 -0700269 return kNoLayer_SaveLayerStrategy;
270}
271
272void SkPipeCanvas::willRestore() {
273 fStream->write32(pack_verb(SkPipeVerb::kRestore));
274 this->INHERITED::willRestore();
275}
276
277template <typename T> void write_sparse_matrix(T* writer, const SkMatrix& matrix) {
278 SkMatrix::TypeMask tm = matrix.getType();
279 SkScalar tmp[9];
280 if (tm & SkMatrix::kPerspective_Mask) {
281 matrix.get9(tmp);
282 writer->write(tmp, 9 * sizeof(SkScalar));
283 } else if (tm & SkMatrix::kAffine_Mask) {
284 tmp[0] = matrix[SkMatrix::kMScaleX];
285 tmp[1] = matrix[SkMatrix::kMSkewX];
286 tmp[2] = matrix[SkMatrix::kMTransX];
287 tmp[3] = matrix[SkMatrix::kMScaleY];
288 tmp[4] = matrix[SkMatrix::kMSkewY];
289 tmp[5] = matrix[SkMatrix::kMTransY];
290 writer->write(tmp, 6 * sizeof(SkScalar));
291 } else if (tm & SkMatrix::kScale_Mask) {
292 tmp[0] = matrix[SkMatrix::kMScaleX];
293 tmp[1] = matrix[SkMatrix::kMTransX];
294 tmp[2] = matrix[SkMatrix::kMScaleY];
295 tmp[3] = matrix[SkMatrix::kMTransY];
296 writer->write(tmp, 4 * sizeof(SkScalar));
297 } else if (tm & SkMatrix::kTranslate_Mask) {
298 tmp[0] = matrix[SkMatrix::kMTransX];
299 tmp[1] = matrix[SkMatrix::kMTransY];
300 writer->write(tmp, 2 * sizeof(SkScalar));
301 }
302 // else write nothing for Identity
303}
304
305static void do_concat(SkWStream* stream, const SkMatrix& matrix, bool isSetMatrix) {
306 unsigned mtype = matrix.getType();
307 SkASSERT(0 == (mtype & ~kTypeMask_ConcatMask));
308 unsigned extra = mtype;
309 if (isSetMatrix) {
310 extra |= kSetMatrix_ConcatMask;
311 }
312 if (mtype || isSetMatrix) {
313 stream->write32(pack_verb(SkPipeVerb::kConcat, extra));
314 write_sparse_matrix(stream, matrix);
315 }
316}
317
318void SkPipeCanvas::didConcat(const SkMatrix& matrix) {
319 do_concat(fStream, matrix, false);
320 this->INHERITED::didConcat(matrix);
321}
322
323void SkPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
324 do_concat(fStream, matrix, true);
325 this->INHERITED::didSetMatrix(matrix);
326}
327
Mike Reedc1f77742016-12-09 09:00:50 -0500328void SkPipeCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
reed54dc4872016-09-13 08:09:45 -0700329 fStream->write32(pack_verb(SkPipeVerb::kClipRect, ((unsigned)op << 1) | edgeStyle));
330 fStream->write(&rect, 4 * sizeof(SkScalar));
331
332 this->INHERITED::onClipRect(rect, op, edgeStyle);
333}
334
Mike Reedc1f77742016-12-09 09:00:50 -0500335void SkPipeCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
reed54dc4872016-09-13 08:09:45 -0700336 fStream->write32(pack_verb(SkPipeVerb::kClipRRect, ((unsigned)op << 1) | edgeStyle));
337 write_rrect(fStream, rrect);
338
339 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
340}
341
Mike Reedc1f77742016-12-09 09:00:50 -0500342void SkPipeCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
reed54dc4872016-09-13 08:09:45 -0700343 SkPipeWriter writer(this);
344 writer.write32(pack_verb(SkPipeVerb::kClipPath, ((unsigned)op << 1) | edgeStyle));
345 writer.writePath(path);
346
347 this->INHERITED::onClipPath(path, op, edgeStyle);
348}
349
Mike Reedc1f77742016-12-09 09:00:50 -0500350void SkPipeCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
reed54dc4872016-09-13 08:09:45 -0700351 SkPipeWriter writer(this);
352 writer.write32(pack_verb(SkPipeVerb::kClipRegion, (unsigned)op << 1));
353 writer.writeRegion(deviceRgn);
354
355 this->INHERITED::onClipRegion(deviceRgn, op);
356}
357
358///////////////////////////////////////////////////////////////////////////////////////////////////
359
360void SkPipeCanvas::onDrawArc(const SkRect& bounds, SkScalar startAngle, SkScalar sweepAngle,
361 bool useCenter, const SkPaint& paint) {
362 SkPipeWriter writer(this);
363 writer.write32(pack_verb(SkPipeVerb::kDrawArc, (int)useCenter));
364 writer.writeRect(bounds);
365 writer.writeScalar(startAngle);
366 writer.writeScalar(sweepAngle);
367 write_paint(writer, paint, kGeometry_PaintUsage);
368}
369
370void SkPipeCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[], const SkRect rect[],
Mike Reedfaba3712016-11-03 14:45:31 -0400371 const SkColor colors[], int count, SkBlendMode mode,
reed54dc4872016-09-13 08:09:45 -0700372 const SkRect* cull, const SkPaint* paint) {
373 unsigned extra = (unsigned)mode;
374 SkASSERT(0 == (extra & ~kMode_DrawAtlasMask));
375 if (colors) {
376 extra |= kHasColors_DrawAtlasMask;
377 }
378 if (cull) {
379 extra |= kHasCull_DrawAtlasMask;
380 }
381 if (paint) {
382 extra |= kHasPaint_DrawAtlasMask;
383 }
384
385 SkPipeWriter writer(this);
386 writer.write32(pack_verb(SkPipeVerb::kDrawAtlas, extra));
387 writer.writeImage(image);
388 writer.write32(count);
389 writer.write(xform, count * sizeof(SkRSXform));
390 writer.write(rect, count * sizeof(SkRect));
391 if (colors) {
392 writer.write(colors, count * sizeof(SkColor));
393 }
394 if (cull) {
395 writer.writeRect(*cull);
396 }
397 if (paint) {
398 write_paint(writer, *paint, kImage_PaintUsage);
399 }
400}
401
402void SkPipeCanvas::onDrawPaint(const SkPaint& paint) {
403 SkPipeWriter writer(this);
404 writer.write32(pack_verb(SkPipeVerb::kDrawPaint));
405 write_paint(writer, paint, kDrawPaint_PaintUsage);
406}
407
408void SkPipeCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
409 const SkPaint& paint) {
410 SkPipeWriter writer(this);
411 writer.write32(pack_verb(SkPipeVerb::kDrawPoints, mode));
412 writer.write32(SkToU32(count));
413 writer.write(pts, count * sizeof(SkPoint));
414 write_paint(writer, paint, kGeometry_PaintUsage | kRespectsStroke_PaintUsage);
415}
416
417void SkPipeCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
418 SkPipeWriter writer(this);
419 writer.write32(pack_verb(SkPipeVerb::kDrawRect));
420 writer.write(&rect, sizeof(SkRect));
421 write_paint(writer, paint, kGeometry_PaintUsage);
422}
423
424void SkPipeCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
425 SkPipeWriter writer(this);
426 writer.write32(pack_verb(SkPipeVerb::kDrawOval));
427 writer.write(&rect, sizeof(SkRect));
428 write_paint(writer, paint, kGeometry_PaintUsage);
429}
430
431void SkPipeCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
432 SkPipeWriter writer(this);
433 writer.write32(pack_verb(SkPipeVerb::kDrawRRect));
434 write_rrect(&writer, rrect);
435 write_paint(writer, paint, kGeometry_PaintUsage);
436}
437
438void SkPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
439 SkPipeWriter writer(this);
440 writer.write32(pack_verb(SkPipeVerb::kDrawDRRect));
441 write_rrect(&writer, outer);
442 write_rrect(&writer, inner);
443 write_paint(writer, paint, kGeometry_PaintUsage);
444}
445
446void SkPipeCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
447 SkPipeWriter writer(this);
448 writer.write32(pack_verb(SkPipeVerb::kDrawPath));
449 writer.writePath(path);
450 write_paint(writer, paint, kGeometry_PaintUsage);
451}
452
Mike Reed7c9c9e42018-01-03 09:23:34 -0500453void SkPipeCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
454 SkPipeWriter writer(this);
455 writer.write32(pack_verb(SkPipeVerb::kDrawShadowRec));
456 writer.writePath(path);
457 writer.write(&rec, sizeof(rec));
458}
459
reed54dc4872016-09-13 08:09:45 -0700460///////////////////////////////////////////////////////////////////////////////////////////////////
461
462static sk_sp<SkImage> make_from_bitmap(const SkBitmap& bitmap) {
463 // If we just "make" an image, it will force a CPU copy (if its mutable), only to have
464 // us then either find it in our cache, or compress and send it.
465 //
466 // Better could be to look it up in our cache first, and only create/compress it if we have to.
467 //
468 // But for now, just do the dumb thing...
469 return SkImage::MakeFromBitmap(bitmap);
470}
471
472void SkPipeCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
473 const SkPaint* paint) {
474 sk_sp<SkImage> image = make_from_bitmap(bitmap);
475 if (image) {
476 this->onDrawImage(image.get(), x, y, paint);
477 }
478}
479
480void SkPipeCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
481 const SkPaint* paint, SrcRectConstraint constraint) {
482 sk_sp<SkImage> image = make_from_bitmap(bitmap);
483 if (image) {
484 this->onDrawImageRect(image.get(), src, dst, paint, constraint);
485 }
486}
487
488void SkPipeCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
489 const SkRect& dst, const SkPaint* paint) {
490 sk_sp<SkImage> image = make_from_bitmap(bitmap);
491 if (image) {
492 this->onDrawImageNine(image.get(), center, dst, paint);
493 }
494}
495
496void SkPipeCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
497 const SkRect& dst, const SkPaint* paint) {
498 sk_sp<SkImage> image = make_from_bitmap(bitmap);
499 if (image) {
500 this->onDrawImageLattice(image.get(), lattice, dst, paint);
501 }
502}
503
504///////////////////////////////////////////////////////////////////////////////////////////////////
Mike Kleinb3384842017-03-27 14:28:07 -0400505
reed54dc4872016-09-13 08:09:45 -0700506void SkPipeCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
507 const SkPaint* paint) {
508 unsigned extra = 0;
509 if (paint) {
510 extra |= kHasPaint_DrawImageMask;
511 }
512 SkPipeWriter writer(this);
513 writer.write32(pack_verb(SkPipeVerb::kDrawImage, extra));
514 writer.writeImage(image);
515 writer.writeScalar(left);
516 writer.writeScalar(top);
517 if (paint) {
518 write_paint(writer, *paint, kImage_PaintUsage);
519 }
520}
521
522void SkPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
523 const SkPaint* paint, SrcRectConstraint constraint) {
524 SkASSERT(0 == ((unsigned)constraint & ~1));
525 unsigned extra = (unsigned)constraint;
526 if (paint) {
527 extra |= kHasPaint_DrawImageRectMask;
528 }
529 if (src) {
530 extra |= kHasSrcRect_DrawImageRectMask;
531 }
532
533 SkPipeWriter writer(this);
534 writer.write32(pack_verb(SkPipeVerb::kDrawImageRect, extra));
535 writer.writeImage(image);
536 if (src) {
537 writer.write(src, sizeof(*src));
538 }
539 writer.write(&dst, sizeof(dst));
540 if (paint) {
541 write_paint(writer, *paint, kImage_PaintUsage);
542 }
543}
544
545void SkPipeCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
546 const SkPaint* paint) {
547 unsigned extra = 0;
548 if (paint) {
549 extra |= kHasPaint_DrawImageNineMask;
550 }
551 SkPipeWriter writer(this);
552 writer.write32(pack_verb(SkPipeVerb::kDrawImageNine, extra));
553 writer.writeImage(image);
554 writer.write(&center, sizeof(center));
555 writer.write(&dst, sizeof(dst));
556 if (paint) {
557 write_paint(writer, *paint, kImage_PaintUsage);
558 }
559}
560
561void SkPipeCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
562 const SkRect& dst, const SkPaint* paint) {
563 unsigned extra = 0;
564 if (paint) {
565 extra |= kHasPaint_DrawImageLatticeMask;
566 }
reed54dc4872016-09-13 08:09:45 -0700567 SkPipeWriter writer(this);
568 writer.write32(pack_verb(SkPipeVerb::kDrawImageLattice, extra));
569 writer.writeImage(image);
Mike Reed7c9c9e42018-01-03 09:23:34 -0500570 SkCanvasPriv::WriteLattice(writer, lattice);
reed54dc4872016-09-13 08:09:45 -0700571 writer.write(&dst, sizeof(dst));
572 if (paint) {
573 write_paint(writer, *paint, kImage_PaintUsage);
574 }
575}
576
577///////////////////////////////////////////////////////////////////////////////////////////////////
578
579void SkPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
580 const SkPaint& paint) {
581 SkASSERT(byteLength);
582
583 bool compact = fits_in(byteLength, 24);
584
585 SkPipeWriter writer(this);
586 writer.write32(pack_verb(SkPipeVerb::kDrawText, compact ? (unsigned)byteLength : 0));
587 if (!compact) {
588 writer.write32(SkToU32(byteLength));
589 }
590 write_pad(&writer, text, byteLength);
591 writer.writeScalar(x);
592 writer.writeScalar(y);
593 write_paint(writer, paint, kText_PaintUsage);
594}
595
596void SkPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
597 const SkPaint& paint) {
598 SkASSERT(byteLength);
Mike Kleinb3384842017-03-27 14:28:07 -0400599
reed54dc4872016-09-13 08:09:45 -0700600 bool compact = fits_in(byteLength, 24);
Mike Kleinb3384842017-03-27 14:28:07 -0400601
reed54dc4872016-09-13 08:09:45 -0700602 SkPipeWriter writer(this);
603 writer.write32(pack_verb(SkPipeVerb::kDrawPosText, compact ? (unsigned)byteLength : 0));
604 if (!compact) {
605 writer.write32(SkToU32(byteLength));
606 }
607 write_pad(&writer, text, byteLength);
608 writer.writePointArray(pos, paint.countText(text, byteLength));
609 write_paint(writer, paint, kText_PaintUsage);
610}
611
612void SkPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
613 SkScalar constY, const SkPaint& paint) {
614 SkASSERT(byteLength);
Mike Kleinb3384842017-03-27 14:28:07 -0400615
reed54dc4872016-09-13 08:09:45 -0700616 bool compact = fits_in(byteLength, 24);
Mike Kleinb3384842017-03-27 14:28:07 -0400617
reed54dc4872016-09-13 08:09:45 -0700618 SkPipeWriter writer(this);
619 writer.write32(pack_verb(SkPipeVerb::kDrawPosTextH, compact ? (unsigned)byteLength : 0));
620 if (!compact) {
621 writer.write32(SkToU32(byteLength));
622 }
623 write_pad(&writer, text, byteLength);
624 writer.writeScalarArray(xpos, paint.countText(text, byteLength));
625 writer.writeScalar(constY);
626 write_paint(writer, paint, kText_PaintUsage);
627}
628
629void SkPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
630 const SkMatrix* matrix, const SkPaint& paint) {
631 SkASSERT(byteLength > 0);
632
633 unsigned extra = 0;
634 if (byteLength <= kTextLength_DrawTextOnPathMask) {
635 extra |= byteLength;
636 } // else we will write the length after the packedverb
637 SkMatrix::TypeMask tm = matrix ? matrix->getType() : SkMatrix::kIdentity_Mask;
638 extra |= (unsigned)tm << kMatrixType_DrawTextOnPathShift;
639
640 SkPipeWriter writer(this);
641 writer.write32(pack_verb(SkPipeVerb::kDrawTextOnPath, extra));
642 if (byteLength > kTextLength_DrawTextOnPathMask) {
643 writer.write32(byteLength);
644 }
645 write_pad(&writer, text, byteLength);
646 writer.writePath(path);
647 if (matrix) {
648 write_sparse_matrix(&writer, *matrix);
649 }
650 write_paint(writer, paint, kText_PaintUsage);
651}
652
653void SkPipeCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
654 const SkRect* cull, const SkPaint& paint) {
655 SkASSERT(byteLength);
Mike Kleinb3384842017-03-27 14:28:07 -0400656
reed54dc4872016-09-13 08:09:45 -0700657 bool compact = fits_in(byteLength, 23);
658 unsigned extra = compact ? (byteLength << 1) : 0;
659 if (cull) {
660 extra |= 1;
661 }
Mike Kleinb3384842017-03-27 14:28:07 -0400662
reed54dc4872016-09-13 08:09:45 -0700663 SkPipeWriter writer(this);
664 writer.write32(pack_verb(SkPipeVerb::kDrawTextRSXform, extra));
665 if (!compact) {
666 writer.write32(SkToU32(byteLength));
667 }
668 write_pad(&writer, text, byteLength);
669
670 int count = paint.countText(text, byteLength);
671 writer.write32(count); // maybe we can/should store this in extra as well?
672 writer.write(xform, count * sizeof(SkRSXform));
673 if (cull) {
674 writer.writeRect(*cull);
675 }
676 write_paint(writer, paint, kText_PaintUsage);
677}
678
679void SkPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
680 const SkPaint &paint) {
681 SkPipeWriter writer(this);
682 writer.write32(pack_verb(SkPipeVerb::kDrawTextBlob, 0));
Cary Clark53c87692018-07-17 08:59:34 -0400683 SkTextBlobPriv::Flatten(*blob, writer);
reed54dc4872016-09-13 08:09:45 -0700684 writer.writeScalar(x);
685 writer.writeScalar(y);
686 write_paint(writer, paint, kTextBlob_PaintUsage);
687}
688
689void SkPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
690 const SkPaint* paint) {
691 unsigned extra = fDeduper->findOrDefinePicture(const_cast<SkPicture*>(picture));
692 if (matrix) {
693 extra |= kHasMatrix_DrawPictureExtra;
694 }
695 if (paint) {
696 extra |= kHasPaint_DrawPictureExtra;
697 }
698 SkPipeWriter writer(this);
699 writer.write32(pack_verb(SkPipeVerb::kDrawPicture, extra));
700 if (matrix) {
701 writer.writeMatrix(*matrix);
702 }
703 if (paint) {
704 write_paint(writer, *paint, kSaveLayer_PaintUsage);
705 }
706}
707
Brian Osman37886ce2018-03-09 13:40:31 -0500708void SkPipeCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
709 // TODO: Is there a better solution than just exploding the drawable?
710 drawable->draw(this, matrix);
711}
712
reed54dc4872016-09-13 08:09:45 -0700713void SkPipeCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
714 size_t size = region.writeToMemory(nullptr);
715 unsigned extra = 0;
716 if (fits_in(size, 24)) {
717 extra = SkToUInt(size);
718 }
719
720 SkPipeWriter writer(this);
721 writer.write32(pack_verb(SkPipeVerb::kDrawRegion, extra));
722 if (0 == extra) {
723 writer.write32(size);
724 }
725 SkAutoSMalloc<2048> storage(size);
726 region.writeToMemory(storage.get());
727 write_pad(&writer, storage.get(), size);
728 write_paint(writer, paint, kGeometry_PaintUsage);
729}
730
Ruiqi Maof5101492018-06-29 14:32:21 -0400731void SkPipeCanvas::onDrawVerticesObject(const SkVertices* vertices, const SkMatrix* bones,
732 int boneCount, SkBlendMode bmode, const SkPaint& paint) {
Mike Reedfed9cfd2017-03-17 12:09:04 -0400733 unsigned extra = static_cast<unsigned>(bmode);
reed54dc4872016-09-13 08:09:45 -0700734
735 SkPipeWriter writer(this);
736 writer.write32(pack_verb(SkPipeVerb::kDrawVertices, extra));
Mike Reedfed9cfd2017-03-17 12:09:04 -0400737 // TODO: dedup vertices?
738 writer.writeDataAsByteArray(vertices->encode().get());
Ruiqi Maof5101492018-06-29 14:32:21 -0400739 writer.write32(boneCount);
740 writer.write(bones, sizeof(SkMatrix) * boneCount);
reed54dc4872016-09-13 08:09:45 -0700741 write_paint(writer, paint, kVertices_PaintUsage);
742}
743
744void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
Mike Reedfaba3712016-11-03 14:45:31 -0400745 const SkPoint texCoords[4], SkBlendMode bmode,
reed54dc4872016-09-13 08:09:45 -0700746 const SkPaint& paint) {
747 SkPipeWriter writer(this);
748 unsigned extra = 0;
Mike Reed7d954ad2016-10-28 15:42:34 -0400749 SkASSERT(0 == ((int)bmode & ~kModeEnum_DrawPatchExtraMask));
750 extra = (unsigned)bmode;
reed54dc4872016-09-13 08:09:45 -0700751 if (colors) {
752 extra |= kHasColors_DrawPatchExtraMask;
753 }
754 if (texCoords) {
755 extra |= kHasTexture_DrawPatchExtraMask;
756 }
757 writer.write32(pack_verb(SkPipeVerb::kDrawPatch, extra));
758 writer.write(cubics, sizeof(SkPoint) * 12);
759 if (colors) {
760 writer.write(colors, sizeof(SkColor) * 4);
761 }
762 if (texCoords) {
763 writer.write(texCoords, sizeof(SkPoint) * 4);
764 }
reed54dc4872016-09-13 08:09:45 -0700765 write_paint(writer, paint, kGeometry_PaintUsage);
766}
767
768void SkPipeCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
769 const size_t len = strlen(key) + 1; // must write the trailing 0
770 bool compact = fits_in(len, 23);
771 uint32_t extra = compact ? (unsigned)len : 0;
772 extra <<= 1; // make room for has_data_sentinel
773 if (data) {
774 extra |= 1;
775 }
776
777 fStream->write32(pack_verb(SkPipeVerb::kDrawAnnotation, extra));
778 fStream->write(&rect, sizeof(SkRect));
779 if (!compact) {
780 fStream->write32(SkToU32(len));
781 }
782 write_pad(fStream, key, len);
783 if (data) {
784 fStream->write32(SkToU32(data->size()));
785 write_pad(fStream, data->data(), data->size());
786 }
787}
788
789///////////////////////////////////////////////////////////////////////////////////////////////////
790
Mike Reedc0cec872017-12-14 10:45:27 -0500791static sk_sp<SkData> encode(SkImage* img, SkSerialImageProc proc, void* ctx) {
792 if (proc) {
793 if (auto data = proc(img, ctx)) {
794 return data;
reed54dc4872016-09-13 08:09:45 -0700795 }
reed54dc4872016-09-13 08:09:45 -0700796 }
Mike Reedc0cec872017-12-14 10:45:27 -0500797 return img->encodeToData();
Mike Reed3ac64b42016-10-18 19:34:08 -0400798}
799
reed54dc4872016-09-13 08:09:45 -0700800static bool show_deduper_traffic = false;
801
802int SkPipeDeduper::findOrDefineImage(SkImage* image) {
803 int index = fImages.find(image->uniqueID());
804 SkASSERT(index >= 0);
805 if (index) {
806 if (show_deduper_traffic) {
807 SkDebugf(" reuseImage(%d)\n", index - 1);
808 }
809 return index;
810 }
811
Mike Reedc0cec872017-12-14 10:45:27 -0500812 sk_sp<SkData> data = encode(image, fProcs.fImageProc, fProcs.fImageCtx);
reed54dc4872016-09-13 08:09:45 -0700813 if (data) {
814 index = fImages.add(image->uniqueID());
815 SkASSERT(index > 0);
816 SkASSERT(fits_in(index, 24));
817 fStream->write32(pack_verb(SkPipeVerb::kDefineImage, index));
818
819 uint32_t len = SkToU32(data->size());
820 fStream->write32(SkAlign4(len));
821 write_pad(fStream, data->data(), len);
822
823 if (show_deduper_traffic) {
824 int size = image->width() * image->height() << 2;
825 SkDebugf(" defineImage(%d) %d -> %d\n", index - 1, size, len);
826 }
827 return index;
828 }
829 SkDebugf("+++ failed to encode image [%d %d]\n", image->width(), image->height());
830 return 0; // failed to encode
831}
832
833int SkPipeDeduper::findOrDefinePicture(SkPicture* picture) {
834 int index = fPictures.find(picture->uniqueID());
835 SkASSERT(index >= 0);
836 if (index) {
837 if (show_deduper_traffic) {
838 SkDebugf(" reusePicture(%d)\n", index - 1);
839 }
840 return index;
841 }
842
843 size_t prevWritten = fStream->bytesWritten();
844 unsigned extra = 0; // 0 means we're defining a new picture, non-zero means undef_index + 1
845 fStream->write32(pack_verb(SkPipeVerb::kDefinePicture, extra));
846 const SkRect cull = picture->cullRect();
847 fStream->write(&cull, sizeof(cull));
848 picture->playback(fPipeCanvas);
849 // call fPictures.add *after* we're written the picture, so that any nested pictures will have
850 // already been defined, and we get the "last" index value.
851 index = fPictures.add(picture->uniqueID());
852 ASSERT_FITS_IN(index, kObjectDefinitionBits);
853 fStream->write32(pack_verb(SkPipeVerb::kEndPicture, index));
854
Mike Kleinb3384842017-03-27 14:28:07 -0400855 if (show_deduper_traffic) {
856 SkDebugf(" definePicture(%d) %d\n",
857 index - 1, SkToU32(fStream->bytesWritten() - prevWritten));
858 }
reed54dc4872016-09-13 08:09:45 -0700859 return index;
860}
861
Mike Reedc0cec872017-12-14 10:45:27 -0500862static sk_sp<SkData> encode(const SkSerialProcs& procs, SkTypeface* tf) {
863 if (procs.fTypefaceProc) {
864 auto data = procs.fTypefaceProc(tf, procs.fTypefaceCtx);
865 if (data) {
866 return data;
867 }
868 }
reed54dc4872016-09-13 08:09:45 -0700869 SkDynamicMemoryWStream stream;
870 tf->serialize(&stream);
871 return sk_sp<SkData>(stream.detachAsData());
872}
873
874int SkPipeDeduper::findOrDefineTypeface(SkTypeface* typeface) {
875 if (!typeface) {
876 return 0; // default
877 }
878
879 int index = fTypefaces.find(typeface->uniqueID());
880 SkASSERT(index >= 0);
881 if (index) {
882 if (show_deduper_traffic) {
883 SkDebugf(" reuseTypeface(%d)\n", index - 1);
884 }
885 return index;
886 }
887
Mike Reedc0cec872017-12-14 10:45:27 -0500888 sk_sp<SkData> data = encode(fProcs, typeface);
reed54dc4872016-09-13 08:09:45 -0700889 if (data) {
890 index = fTypefaces.add(typeface->uniqueID());
891 SkASSERT(index > 0);
892 SkASSERT(fits_in(index, 24));
893 fStream->write32(pack_verb(SkPipeVerb::kDefineTypeface, index));
894
895 uint32_t len = SkToU32(data->size());
896 fStream->write32(SkAlign4(len));
897 write_pad(fStream, data->data(), len);
898
899 if (show_deduper_traffic) {
900 SkDebugf(" defineTypeface(%d) %d\n", index - 1, len);
901 }
902 return index;
903 }
904 SkDebugf("+++ failed to encode typeface %d\n", typeface->uniqueID());
905 return 0; // failed to encode
906}
907
908int SkPipeDeduper::findOrDefineFactory(SkFlattenable* flattenable) {
909 if (!flattenable) {
910 return 0;
911 }
912
913 int index = fFactories.find(flattenable->getFactory());
914 SkASSERT(index >= 0);
915 if (index) {
916 if (show_deduper_traffic) {
917 SkDebugf(" reuseFactory(%d)\n", index - 1);
918 }
919 return index;
920 }
921
922 index = fFactories.add(flattenable->getFactory());
923 ASSERT_FITS_IN(index, kIndex_DefineFactoryExtraBits);
924 const char* name = flattenable->getTypeName();
925 size_t len = strlen(name);
926 ASSERT_FITS_IN(len, kNameLength_DefineFactoryExtraBits);
927 unsigned extra = (index << kNameLength_DefineFactoryExtraBits) | len;
928 size_t prevWritten = fStream->bytesWritten();
929 fStream->write32(pack_verb(SkPipeVerb::kDefineFactory, extra));
930 write_pad(fStream, name, len + 1);
931 if (false) {
932 SkDebugf(" defineFactory(%d) %d %s\n",
933 index - 1, SkToU32(fStream->bytesWritten() - prevWritten), name);
934 }
935 return index;
936}
937
938///////////////////////////////////////////////////////////////////////////////////////////////////
939#include "SkPipe.h"
940
941class SkPipeSerializer::Impl {
942public:
943 SkPipeDeduper fDeduper;
944 std::unique_ptr<SkPipeCanvas> fCanvas;
945};
946
947SkPipeSerializer::SkPipeSerializer() : fImpl(new Impl) {}
948
949SkPipeSerializer::~SkPipeSerializer() {
950 if (fImpl->fCanvas) {
951 this->endWrite();
952 }
953}
954
reed54dc4872016-09-13 08:09:45 -0700955void SkPipeSerializer::resetCache() {
956 fImpl->fDeduper.resetCaches();
957}
958
reed262052c2016-09-15 14:24:53 -0700959sk_sp<SkData> SkPipeSerializer::writeImage(SkImage* image) {
960 SkDynamicMemoryWStream stream;
961 this->writeImage(image, &stream);
962 return stream.detachAsData();
reed54dc4872016-09-13 08:09:45 -0700963}
964
reed262052c2016-09-15 14:24:53 -0700965sk_sp<SkData> SkPipeSerializer::writePicture(SkPicture* picture) {
966 SkDynamicMemoryWStream stream;
967 this->writePicture(picture, &stream);
968 return stream.detachAsData();
969}
970
971void SkPipeSerializer::writePicture(SkPicture* picture, SkWStream* stream) {
972 int index = fImpl->fDeduper.findPicture(picture);
973 if (0 == index) {
974 // Try to define the picture
975 this->beginWrite(picture->cullRect(), stream);
976 index = fImpl->fDeduper.findOrDefinePicture(picture);
977 this->endWrite();
978 }
979 stream->write32(pack_verb(SkPipeVerb::kWritePicture, index));
980}
981
982void SkPipeSerializer::writeImage(SkImage* image, SkWStream* stream) {
reed7e3ba9f2016-09-13 17:25:19 -0700983 int index = fImpl->fDeduper.findImage(image);
984 if (0 == index) {
985 // Try to define the image
986 fImpl->fDeduper.setStream(stream);
987 index = fImpl->fDeduper.findOrDefineImage(image);
988 }
989 stream->write32(pack_verb(SkPipeVerb::kWriteImage, index));
reed54dc4872016-09-13 08:09:45 -0700990}
991
992SkCanvas* SkPipeSerializer::beginWrite(const SkRect& cull, SkWStream* stream) {
993 SkASSERT(nullptr == fImpl->fCanvas);
994 fImpl->fCanvas.reset(new SkPipeCanvas(cull, &fImpl->fDeduper, stream));
995 fImpl->fDeduper.setStream(stream);
996 fImpl->fDeduper.setCanvas(fImpl->fCanvas.get());
997 return fImpl->fCanvas.get();
998}
999
1000void SkPipeSerializer::endWrite() {
1001 fImpl->fCanvas->restoreToCount(1);
1002 fImpl->fCanvas.reset(nullptr);
reed7e3ba9f2016-09-13 17:25:19 -07001003 fImpl->fDeduper.setCanvas(nullptr);
reed54dc4872016-09-13 08:09:45 -07001004}