blob: 3d0e69569ccc680219bae610c519de553ce17bf6 [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 Canary95e3c052017-01-11 12:44:43 -05008#include "SkAutoMalloc.h"
Mike Reed7c9c9e42018-01-03 09:23:34 -05009#include "SkCanvasPriv.h"
reed54dc4872016-09-13 08:09:45 -070010#include "SkColorFilter.h"
11#include "SkDrawLooper.h"
Mike Reed7c9c9e42018-01-03 09:23:34 -050012#include "SkDrawShadowInfo.h"
reed54dc4872016-09-13 08:09:45 -070013#include "SkImageFilter.h"
14#include "SkMaskFilter.h"
Hal Canary95e3c052017-01-11 12:44:43 -050015#include "SkPathEffect.h"
reed54dc4872016-09-13 08:09:45 -070016#include "SkPipeCanvas.h"
17#include "SkPipeFormat.h"
Kevin Lubickc456b732017-01-11 17:21:57 +000018#include "SkRSXform.h"
Hal Canary95e3c052017-01-11 12:44:43 -050019#include "SkRasterizer.h"
reed54dc4872016-09-13 08:09:45 -070020#include "SkShader.h"
21#include "SkStream.h"
22#include "SkTextBlob.h"
23#include "SkTypeface.h"
24
25template <typename T> void write_rrect(T* writer, const SkRRect& rrect) {
26 char tmp[SkRRect::kSizeInMemory];
27 rrect.writeToMemory(tmp);
28 writer->write(tmp, SkRRect::kSizeInMemory);
29}
30
31template <typename T> void write_pad(T* writer, const void* buffer, size_t len) {
32 writer->write(buffer, len & ~3);
33 if (len & 3) {
34 const char* src = (const char*)buffer + (len & ~3);
35 len &= 3;
36 uint32_t tmp = 0;
37 memcpy(&tmp, src, len);
38 writer->write(&tmp, 4);
39 }
40}
41
42///////////////////////////////////////////////////////////////////////////////////////////////////
43
44static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) {
45 // kRespectsStroke_PaintUsage is only valid if other bits are also set
46 SkASSERT(0 != (usage & ~kRespectsStroke_PaintUsage));
47
48 const SkScalar kTextSize_Default = 12;
49 const SkScalar kTextScaleX_Default = 1;
50 const SkScalar kTextSkewX_Default = 0;
51 const SkScalar kStrokeWidth_Default = 0;
52 const SkScalar kStrokeMiter_Default = 4;
53 const SkColor kColor_Default = SK_ColorBLACK;
54
55 unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0;
56
57 if (usage & kText_PaintUsage) {
58 bits |= (paint.getTextSize() != kTextSize_Default ? kTextSize_NonDef : 0);
59 bits |= (paint.getTextScaleX() != kTextScaleX_Default ? kTextScaleX_NonDef : 0);
60 bits |= (paint.getTextSkewX() != kTextSkewX_Default ? kTextSkewX_NonDef : 0);
61 bits |= (paint.getTypeface() ? kTypeface_NonDef : 0);
62 }
63
64 // TODO: kImage_PaintUsage only needs the shader/maskfilter IF its colortype is kAlpha_8
65
66 if (usage & (kVertices_PaintUsage | kDrawPaint_PaintUsage | kImage_PaintUsage |
67 kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
68 bits |= (paint.getShader() ? kShader_NonDef : 0);
69 }
70
71 if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
72 bits |= (paint.getPathEffect() ? kPathEffect_NonDef : 0);
73 bits |= (paint.getRasterizer() ? kRasterizer_NonDef : 0);
74
75 if (paint.getStyle() != SkPaint::kFill_Style || (usage & kRespectsStroke_PaintUsage)) {
76 bits |= (paint.getStrokeWidth() != kStrokeWidth_Default ? kStrokeWidth_NonDef : 0);
77 bits |= (paint.getStrokeMiter() != kStrokeMiter_Default ? kStrokeMiter_NonDef : 0);
78 }
79 }
80
81 if (usage &
82 (kText_PaintUsage | kGeometry_PaintUsage | kImage_PaintUsage | kTextBlob_PaintUsage))
83 {
84 bits |= (paint.getMaskFilter() ? kMaskFilter_NonDef : 0);
85 }
86
reed54dc4872016-09-13 08:09:45 -070087 bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0);
88 bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0);
89 bits |= (paint.getDrawLooper() ? kDrawLooper_NonDef : 0);
90
91 return SkToU16(bits);
92}
93
94static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
95 unsigned filter, unsigned style, unsigned caps, unsigned joins,
96 unsigned encoding) {
97 SkASSERT(kFlags_BPF + kHint_BPF + kAlign_BPF + kFilter_BPF <= 32);
98
99 ASSERT_FITS_IN(flags, kFlags_BPF);
100 ASSERT_FITS_IN(filter, kFilter_BPF);
101 ASSERT_FITS_IN(style, kStyle_BPF);
102 ASSERT_FITS_IN(caps, kCaps_BPF);
103 ASSERT_FITS_IN(joins, kJoins_BPF);
104 ASSERT_FITS_IN(hint, kHint_BPF);
105 ASSERT_FITS_IN(align, kAlign_BPF);
106 ASSERT_FITS_IN(encoding, kEncoding_BPF);
107
108 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
109 // add more bits in the future.
110
111 uint32_t packed = 0;
112 int shift = 32;
113
114 shift -= kFlags_BPF; packed |= (flags << shift);
115 shift -= kFilter_BPF; packed |= (filter << shift);
116 shift -= kStyle_BPF; packed |= (style << shift);
117 // these are only needed for stroking (geometry or text)
118 shift -= kCaps_BPF; packed |= (caps << shift);
119 shift -= kJoins_BPF; packed |= (joins << shift);
120 // these are only needed for text
121 shift -= kHint_BPF; packed |= (hint << shift);
122 shift -= kAlign_BPF; packed |= (align << shift);
123 shift -= kEncoding_BPF; packed |= (encoding << shift);
124
125 return packed;
126}
127
128#define CHECK_WRITE_SCALAR(writer, nondef, paint, Field) \
129 do { if (nondef & (k##Field##_NonDef)) { \
130 writer.writeScalar(paint.get##Field()); \
131 }} while (0)
132
133#define CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Field) \
134 do { if (nondef & (k##Field##_NonDef)) { \
135 SkFlattenable* f = paint.get##Field(); \
136 SkASSERT(f != nullptr); \
137 writer.writeFlattenable(f); \
138 } } while (0)
139
140/*
141 * Header:
142 * paint flags : 32
143 * non_def bits : 16
144 * xfermode enum : 8
145 * pad zeros : 8
146 */
147static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, unsigned usage) {
148 uint32_t packedFlags = pack_paint_flags(paint.getFlags(), paint.getHinting(),
149 paint.getTextAlign(), paint.getFilterQuality(),
150 paint.getStyle(), paint.getStrokeCap(),
151 paint.getStrokeJoin(), paint.getTextEncoding());
152 writer.write32(packedFlags);
153
154 unsigned nondef = compute_nondef(paint, (PaintUsage)usage);
reed54dc4872016-09-13 08:09:45 -0700155 const uint8_t pad = 0;
reed374772b2016-10-05 17:33:02 -0700156 writer.write32((nondef << 16) | ((unsigned)paint.getBlendMode() << 8) | pad);
reed54dc4872016-09-13 08:09:45 -0700157
158 CHECK_WRITE_SCALAR(writer, nondef, paint, TextSize);
159 CHECK_WRITE_SCALAR(writer, nondef, paint, TextScaleX);
160 CHECK_WRITE_SCALAR(writer, nondef, paint, TextSkewX);
161 CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeWidth);
162 CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeMiter);
163
164 if (nondef & kColor_NonDef) {
165 writer.write32(paint.getColor());
166 }
167 if (nondef & kTypeface_NonDef) {
168 // TODO: explore idea of writing bits indicating "use the prev (or prev N) face"
169 // e.g. 1-N bits is an index into a ring buffer of typefaces
170 SkTypeface* tf = paint.getTypeface();
171 SkASSERT(tf);
172 writer.writeTypeface(tf);
173 }
174
175 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, PathEffect);
176 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Shader);
reed54dc4872016-09-13 08:09:45 -0700177 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, MaskFilter);
178 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ColorFilter);
179 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Rasterizer);
180 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
231 if (extra & (1 << 31)/*SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag*/) {
232 extra &= ~(1 << 31);
233 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));
683 blob->flatten(writer);
684 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
708void SkPipeCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
709 size_t size = region.writeToMemory(nullptr);
710 unsigned extra = 0;
711 if (fits_in(size, 24)) {
712 extra = SkToUInt(size);
713 }
714
715 SkPipeWriter writer(this);
716 writer.write32(pack_verb(SkPipeVerb::kDrawRegion, extra));
717 if (0 == extra) {
718 writer.write32(size);
719 }
720 SkAutoSMalloc<2048> storage(size);
721 region.writeToMemory(storage.get());
722 write_pad(&writer, storage.get(), size);
723 write_paint(writer, paint, kGeometry_PaintUsage);
724}
725
Mike Reedfed9cfd2017-03-17 12:09:04 -0400726void SkPipeCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
727 const SkPaint& paint) {
728 unsigned extra = static_cast<unsigned>(bmode);
reed54dc4872016-09-13 08:09:45 -0700729
730 SkPipeWriter writer(this);
731 writer.write32(pack_verb(SkPipeVerb::kDrawVertices, extra));
Mike Reedfed9cfd2017-03-17 12:09:04 -0400732 // TODO: dedup vertices?
733 writer.writeDataAsByteArray(vertices->encode().get());
reed54dc4872016-09-13 08:09:45 -0700734 write_paint(writer, paint, kVertices_PaintUsage);
735}
736
737void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
Mike Reedfaba3712016-11-03 14:45:31 -0400738 const SkPoint texCoords[4], SkBlendMode bmode,
reed54dc4872016-09-13 08:09:45 -0700739 const SkPaint& paint) {
740 SkPipeWriter writer(this);
741 unsigned extra = 0;
Mike Reed7d954ad2016-10-28 15:42:34 -0400742 SkASSERT(0 == ((int)bmode & ~kModeEnum_DrawPatchExtraMask));
743 extra = (unsigned)bmode;
reed54dc4872016-09-13 08:09:45 -0700744 if (colors) {
745 extra |= kHasColors_DrawPatchExtraMask;
746 }
747 if (texCoords) {
748 extra |= kHasTexture_DrawPatchExtraMask;
749 }
750 writer.write32(pack_verb(SkPipeVerb::kDrawPatch, extra));
751 writer.write(cubics, sizeof(SkPoint) * 12);
752 if (colors) {
753 writer.write(colors, sizeof(SkColor) * 4);
754 }
755 if (texCoords) {
756 writer.write(texCoords, sizeof(SkPoint) * 4);
757 }
reed54dc4872016-09-13 08:09:45 -0700758 write_paint(writer, paint, kGeometry_PaintUsage);
759}
760
761void SkPipeCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
762 const size_t len = strlen(key) + 1; // must write the trailing 0
763 bool compact = fits_in(len, 23);
764 uint32_t extra = compact ? (unsigned)len : 0;
765 extra <<= 1; // make room for has_data_sentinel
766 if (data) {
767 extra |= 1;
768 }
769
770 fStream->write32(pack_verb(SkPipeVerb::kDrawAnnotation, extra));
771 fStream->write(&rect, sizeof(SkRect));
772 if (!compact) {
773 fStream->write32(SkToU32(len));
774 }
775 write_pad(fStream, key, len);
776 if (data) {
777 fStream->write32(SkToU32(data->size()));
778 write_pad(fStream, data->data(), data->size());
779 }
780}
781
782///////////////////////////////////////////////////////////////////////////////////////////////////
783
Mike Reedc0cec872017-12-14 10:45:27 -0500784static sk_sp<SkData> encode(SkImage* img, SkSerialImageProc proc, void* ctx) {
785 if (proc) {
786 if (auto data = proc(img, ctx)) {
787 return data;
reed54dc4872016-09-13 08:09:45 -0700788 }
reed54dc4872016-09-13 08:09:45 -0700789 }
Mike Reedc0cec872017-12-14 10:45:27 -0500790 return img->encodeToData();
Mike Reed3ac64b42016-10-18 19:34:08 -0400791}
792
reed54dc4872016-09-13 08:09:45 -0700793static bool show_deduper_traffic = false;
794
795int SkPipeDeduper::findOrDefineImage(SkImage* image) {
796 int index = fImages.find(image->uniqueID());
797 SkASSERT(index >= 0);
798 if (index) {
799 if (show_deduper_traffic) {
800 SkDebugf(" reuseImage(%d)\n", index - 1);
801 }
802 return index;
803 }
804
Mike Reedc0cec872017-12-14 10:45:27 -0500805 sk_sp<SkData> data = encode(image, fProcs.fImageProc, fProcs.fImageCtx);
reed54dc4872016-09-13 08:09:45 -0700806 if (data) {
807 index = fImages.add(image->uniqueID());
808 SkASSERT(index > 0);
809 SkASSERT(fits_in(index, 24));
810 fStream->write32(pack_verb(SkPipeVerb::kDefineImage, index));
811
812 uint32_t len = SkToU32(data->size());
813 fStream->write32(SkAlign4(len));
814 write_pad(fStream, data->data(), len);
815
816 if (show_deduper_traffic) {
817 int size = image->width() * image->height() << 2;
818 SkDebugf(" defineImage(%d) %d -> %d\n", index - 1, size, len);
819 }
820 return index;
821 }
822 SkDebugf("+++ failed to encode image [%d %d]\n", image->width(), image->height());
823 return 0; // failed to encode
824}
825
826int SkPipeDeduper::findOrDefinePicture(SkPicture* picture) {
827 int index = fPictures.find(picture->uniqueID());
828 SkASSERT(index >= 0);
829 if (index) {
830 if (show_deduper_traffic) {
831 SkDebugf(" reusePicture(%d)\n", index - 1);
832 }
833 return index;
834 }
835
836 size_t prevWritten = fStream->bytesWritten();
837 unsigned extra = 0; // 0 means we're defining a new picture, non-zero means undef_index + 1
838 fStream->write32(pack_verb(SkPipeVerb::kDefinePicture, extra));
839 const SkRect cull = picture->cullRect();
840 fStream->write(&cull, sizeof(cull));
841 picture->playback(fPipeCanvas);
842 // call fPictures.add *after* we're written the picture, so that any nested pictures will have
843 // already been defined, and we get the "last" index value.
844 index = fPictures.add(picture->uniqueID());
845 ASSERT_FITS_IN(index, kObjectDefinitionBits);
846 fStream->write32(pack_verb(SkPipeVerb::kEndPicture, index));
847
Mike Kleinb3384842017-03-27 14:28:07 -0400848 if (show_deduper_traffic) {
849 SkDebugf(" definePicture(%d) %d\n",
850 index - 1, SkToU32(fStream->bytesWritten() - prevWritten));
851 }
reed54dc4872016-09-13 08:09:45 -0700852 return index;
853}
854
Mike Reedc0cec872017-12-14 10:45:27 -0500855static sk_sp<SkData> encode(const SkSerialProcs& procs, SkTypeface* tf) {
856 if (procs.fTypefaceProc) {
857 auto data = procs.fTypefaceProc(tf, procs.fTypefaceCtx);
858 if (data) {
859 return data;
860 }
861 }
reed54dc4872016-09-13 08:09:45 -0700862 SkDynamicMemoryWStream stream;
863 tf->serialize(&stream);
864 return sk_sp<SkData>(stream.detachAsData());
865}
866
867int SkPipeDeduper::findOrDefineTypeface(SkTypeface* typeface) {
868 if (!typeface) {
869 return 0; // default
870 }
871
872 int index = fTypefaces.find(typeface->uniqueID());
873 SkASSERT(index >= 0);
874 if (index) {
875 if (show_deduper_traffic) {
876 SkDebugf(" reuseTypeface(%d)\n", index - 1);
877 }
878 return index;
879 }
880
Mike Reedc0cec872017-12-14 10:45:27 -0500881 sk_sp<SkData> data = encode(fProcs, typeface);
reed54dc4872016-09-13 08:09:45 -0700882 if (data) {
883 index = fTypefaces.add(typeface->uniqueID());
884 SkASSERT(index > 0);
885 SkASSERT(fits_in(index, 24));
886 fStream->write32(pack_verb(SkPipeVerb::kDefineTypeface, index));
887
888 uint32_t len = SkToU32(data->size());
889 fStream->write32(SkAlign4(len));
890 write_pad(fStream, data->data(), len);
891
892 if (show_deduper_traffic) {
893 SkDebugf(" defineTypeface(%d) %d\n", index - 1, len);
894 }
895 return index;
896 }
897 SkDebugf("+++ failed to encode typeface %d\n", typeface->uniqueID());
898 return 0; // failed to encode
899}
900
901int SkPipeDeduper::findOrDefineFactory(SkFlattenable* flattenable) {
902 if (!flattenable) {
903 return 0;
904 }
905
906 int index = fFactories.find(flattenable->getFactory());
907 SkASSERT(index >= 0);
908 if (index) {
909 if (show_deduper_traffic) {
910 SkDebugf(" reuseFactory(%d)\n", index - 1);
911 }
912 return index;
913 }
914
915 index = fFactories.add(flattenable->getFactory());
916 ASSERT_FITS_IN(index, kIndex_DefineFactoryExtraBits);
917 const char* name = flattenable->getTypeName();
918 size_t len = strlen(name);
919 ASSERT_FITS_IN(len, kNameLength_DefineFactoryExtraBits);
920 unsigned extra = (index << kNameLength_DefineFactoryExtraBits) | len;
921 size_t prevWritten = fStream->bytesWritten();
922 fStream->write32(pack_verb(SkPipeVerb::kDefineFactory, extra));
923 write_pad(fStream, name, len + 1);
924 if (false) {
925 SkDebugf(" defineFactory(%d) %d %s\n",
926 index - 1, SkToU32(fStream->bytesWritten() - prevWritten), name);
927 }
928 return index;
929}
930
931///////////////////////////////////////////////////////////////////////////////////////////////////
932#include "SkPipe.h"
933
934class SkPipeSerializer::Impl {
935public:
936 SkPipeDeduper fDeduper;
937 std::unique_ptr<SkPipeCanvas> fCanvas;
938};
939
940SkPipeSerializer::SkPipeSerializer() : fImpl(new Impl) {}
941
942SkPipeSerializer::~SkPipeSerializer() {
943 if (fImpl->fCanvas) {
944 this->endWrite();
945 }
946}
947
reed54dc4872016-09-13 08:09:45 -0700948void SkPipeSerializer::resetCache() {
949 fImpl->fDeduper.resetCaches();
950}
951
reed262052c2016-09-15 14:24:53 -0700952sk_sp<SkData> SkPipeSerializer::writeImage(SkImage* image) {
953 SkDynamicMemoryWStream stream;
954 this->writeImage(image, &stream);
955 return stream.detachAsData();
reed54dc4872016-09-13 08:09:45 -0700956}
957
reed262052c2016-09-15 14:24:53 -0700958sk_sp<SkData> SkPipeSerializer::writePicture(SkPicture* picture) {
959 SkDynamicMemoryWStream stream;
960 this->writePicture(picture, &stream);
961 return stream.detachAsData();
962}
963
964void SkPipeSerializer::writePicture(SkPicture* picture, SkWStream* stream) {
965 int index = fImpl->fDeduper.findPicture(picture);
966 if (0 == index) {
967 // Try to define the picture
968 this->beginWrite(picture->cullRect(), stream);
969 index = fImpl->fDeduper.findOrDefinePicture(picture);
970 this->endWrite();
971 }
972 stream->write32(pack_verb(SkPipeVerb::kWritePicture, index));
973}
974
975void SkPipeSerializer::writeImage(SkImage* image, SkWStream* stream) {
reed7e3ba9f2016-09-13 17:25:19 -0700976 int index = fImpl->fDeduper.findImage(image);
977 if (0 == index) {
978 // Try to define the image
979 fImpl->fDeduper.setStream(stream);
980 index = fImpl->fDeduper.findOrDefineImage(image);
981 }
982 stream->write32(pack_verb(SkPipeVerb::kWriteImage, index));
reed54dc4872016-09-13 08:09:45 -0700983}
984
985SkCanvas* SkPipeSerializer::beginWrite(const SkRect& cull, SkWStream* stream) {
986 SkASSERT(nullptr == fImpl->fCanvas);
987 fImpl->fCanvas.reset(new SkPipeCanvas(cull, &fImpl->fDeduper, stream));
988 fImpl->fDeduper.setStream(stream);
989 fImpl->fDeduper.setCanvas(fImpl->fCanvas.get());
990 return fImpl->fCanvas.get();
991}
992
993void SkPipeSerializer::endWrite() {
994 fImpl->fCanvas->restoreToCount(1);
995 fImpl->fCanvas.reset(nullptr);
reed7e3ba9f2016-09-13 17:25:19 -0700996 fImpl->fDeduper.setCanvas(nullptr);
reed54dc4872016-09-13 08:09:45 -0700997}