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