SkPipeCanvas.cpp revision 95e3c058ef633782f7549e9e1c2727d60dbc8ee5
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 "SkColorFilter.h"
10#include "SkDrawLooper.h"
11#include "SkImageFilter.h"
12#include "SkMaskFilter.h"
13#include "SkPathEffect.h"
14#include "SkPipeCanvas.h"
15#include "SkPipeFormat.h"
16#include "SkRSXform.h"
17#include "SkRasterizer.h"
18#include "SkShader.h"
19#include "SkStream.h"
20#include "SkTextBlob.h"
21#include "SkTypeface.h"
22
23template <typename T> void write_rrect(T* writer, const SkRRect& rrect) {
24    char tmp[SkRRect::kSizeInMemory];
25    rrect.writeToMemory(tmp);
26    writer->write(tmp, SkRRect::kSizeInMemory);
27}
28
29template <typename T> void write_pad(T* writer, const void* buffer, size_t len) {
30    writer->write(buffer, len & ~3);
31    if (len & 3) {
32        const char* src = (const char*)buffer + (len & ~3);
33        len &= 3;
34        uint32_t tmp = 0;
35        memcpy(&tmp, src, len);
36        writer->write(&tmp, 4);
37    }
38}
39
40///////////////////////////////////////////////////////////////////////////////////////////////////
41
42static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) {
43    // kRespectsStroke_PaintUsage is only valid if other bits are also set
44    SkASSERT(0 != (usage & ~kRespectsStroke_PaintUsage));
45
46    const SkScalar kTextSize_Default    = 12;
47    const SkScalar kTextScaleX_Default  = 1;
48    const SkScalar kTextSkewX_Default   = 0;
49    const SkScalar kStrokeWidth_Default = 0;
50    const SkScalar kStrokeMiter_Default = 4;
51    const SkColor  kColor_Default       = SK_ColorBLACK;
52
53    unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0;
54
55    if (usage & kText_PaintUsage) {
56        bits |= (paint.getTextSize() != kTextSize_Default       ? kTextSize_NonDef : 0);
57        bits |= (paint.getTextScaleX() != kTextScaleX_Default   ? kTextScaleX_NonDef : 0);
58        bits |= (paint.getTextSkewX() != kTextSkewX_Default     ? kTextSkewX_NonDef : 0);
59        bits |= (paint.getTypeface()                            ? kTypeface_NonDef : 0);
60    }
61
62    // TODO: kImage_PaintUsage only needs the shader/maskfilter IF its colortype is kAlpha_8
63
64    if (usage & (kVertices_PaintUsage | kDrawPaint_PaintUsage | kImage_PaintUsage |
65                 kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
66        bits |= (paint.getShader()      ? kShader_NonDef : 0);
67    }
68
69    if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
70        bits |= (paint.getPathEffect()  ? kPathEffect_NonDef : 0);
71        bits |= (paint.getRasterizer()  ? kRasterizer_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, Rasterizer);
178    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ImageFilter);
179    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, DrawLooper);
180}
181
182class SkPipeWriter : public SkBinaryWriteBuffer {
183    enum {
184        N = 1024/4,
185    };
186    uint32_t fStorage[N];
187    SkWStream* fStream;
188
189public:
190    SkPipeWriter(SkWStream* stream, SkDeduper* deduper)
191        : SkBinaryWriteBuffer(fStorage, sizeof(fStorage))
192        , fStream(stream)
193    {
194        this->setDeduper(deduper);
195    }
196
197    SkPipeWriter(SkPipeCanvas* pc) : SkPipeWriter(pc->fStream, pc->fDeduper) {}
198
199    ~SkPipeWriter() override {
200        SkASSERT(SkIsAlign4(fStream->bytesWritten()));
201        this->writeToStream(fStream);
202    }
203
204    void writePaint(const SkPaint& paint) override {
205        write_paint(*this, paint, kUnknown_PaintUsage);
206    }
207};
208
209///////////////////////////////////////////////////////////////////////////////////////////////////
210
211SkPipeCanvas::SkPipeCanvas(const SkRect& cull, SkPipeDeduper* deduper, SkWStream* stream)
212    : INHERITED(cull.roundOut())
213    , fDeduper(deduper)
214    , fStream(stream)
215{}
216
217SkPipeCanvas::~SkPipeCanvas() {}
218
219void SkPipeCanvas::willSave() {
220    fStream->write32(pack_verb(SkPipeVerb::kSave));
221    this->INHERITED::willSave();
222}
223
224SkCanvas::SaveLayerStrategy SkPipeCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
225    SkPipeWriter writer(this);
226    uint32_t extra = rec.fSaveLayerFlags;
227
228    // remap this wacky flag
229    if (extra & (1 << 31)/*SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag*/) {
230        extra &= ~(1 << 31);
231        extra |= kDontClipToLayer_SaveLayerMask;
232    }
233
234    if (rec.fBounds) {
235        extra |= kHasBounds_SaveLayerMask;
236    }
237    if (rec.fPaint) {
238        extra |= kHasPaint_SaveLayerMask;
239    }
240    if (rec.fBackdrop) {
241        extra |= kHasBackdrop_SaveLayerMask;
242    }
243
244    writer.write32(pack_verb(SkPipeVerb::kSaveLayer, extra));
245    if (rec.fBounds) {
246        writer.writeRect(*rec.fBounds);
247    }
248    if (rec.fPaint) {
249        write_paint(writer, *rec.fPaint, kSaveLayer_PaintUsage);
250    }
251    if (rec.fBackdrop) {
252        writer.writeFlattenable(rec.fBackdrop);
253    }
254    return kNoLayer_SaveLayerStrategy;
255}
256
257void SkPipeCanvas::willRestore() {
258    fStream->write32(pack_verb(SkPipeVerb::kRestore));
259    this->INHERITED::willRestore();
260}
261
262template <typename T> void write_sparse_matrix(T* writer, const SkMatrix& matrix) {
263    SkMatrix::TypeMask tm = matrix.getType();
264    SkScalar tmp[9];
265    if (tm & SkMatrix::kPerspective_Mask) {
266        matrix.get9(tmp);
267        writer->write(tmp, 9 * sizeof(SkScalar));
268    } else if (tm & SkMatrix::kAffine_Mask) {
269        tmp[0] = matrix[SkMatrix::kMScaleX];
270        tmp[1] = matrix[SkMatrix::kMSkewX];
271        tmp[2] = matrix[SkMatrix::kMTransX];
272        tmp[3] = matrix[SkMatrix::kMScaleY];
273        tmp[4] = matrix[SkMatrix::kMSkewY];
274        tmp[5] = matrix[SkMatrix::kMTransY];
275        writer->write(tmp, 6 * sizeof(SkScalar));
276    } else if (tm & SkMatrix::kScale_Mask) {
277        tmp[0] = matrix[SkMatrix::kMScaleX];
278        tmp[1] = matrix[SkMatrix::kMTransX];
279        tmp[2] = matrix[SkMatrix::kMScaleY];
280        tmp[3] = matrix[SkMatrix::kMTransY];
281        writer->write(tmp, 4 * sizeof(SkScalar));
282    } else if (tm & SkMatrix::kTranslate_Mask) {
283        tmp[0] = matrix[SkMatrix::kMTransX];
284        tmp[1] = matrix[SkMatrix::kMTransY];
285        writer->write(tmp, 2 * sizeof(SkScalar));
286    }
287    // else write nothing for Identity
288}
289
290static void do_concat(SkWStream* stream, const SkMatrix& matrix, bool isSetMatrix) {
291    unsigned mtype = matrix.getType();
292    SkASSERT(0 == (mtype & ~kTypeMask_ConcatMask));
293    unsigned extra = mtype;
294    if (isSetMatrix) {
295        extra |= kSetMatrix_ConcatMask;
296    }
297    if (mtype || isSetMatrix) {
298        stream->write32(pack_verb(SkPipeVerb::kConcat, extra));
299        write_sparse_matrix(stream, matrix);
300    }
301}
302
303void SkPipeCanvas::didConcat(const SkMatrix& matrix) {
304    do_concat(fStream, matrix, false);
305    this->INHERITED::didConcat(matrix);
306}
307
308void SkPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
309    do_concat(fStream, matrix, true);
310    this->INHERITED::didSetMatrix(matrix);
311}
312
313void SkPipeCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
314    fStream->write32(pack_verb(SkPipeVerb::kClipRect, ((unsigned)op << 1) | edgeStyle));
315    fStream->write(&rect, 4 * sizeof(SkScalar));
316
317    this->INHERITED::onClipRect(rect, op, edgeStyle);
318}
319
320void SkPipeCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
321    fStream->write32(pack_verb(SkPipeVerb::kClipRRect, ((unsigned)op << 1) | edgeStyle));
322    write_rrect(fStream, rrect);
323
324    this->INHERITED::onClipRRect(rrect, op, edgeStyle);
325}
326
327void SkPipeCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
328    SkPipeWriter writer(this);
329    writer.write32(pack_verb(SkPipeVerb::kClipPath, ((unsigned)op << 1) | edgeStyle));
330    writer.writePath(path);
331
332    this->INHERITED::onClipPath(path, op, edgeStyle);
333}
334
335void SkPipeCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
336    SkPipeWriter writer(this);
337    writer.write32(pack_verb(SkPipeVerb::kClipRegion, (unsigned)op << 1));
338    writer.writeRegion(deviceRgn);
339
340    this->INHERITED::onClipRegion(deviceRgn, op);
341}
342
343///////////////////////////////////////////////////////////////////////////////////////////////////
344
345void SkPipeCanvas::onDrawArc(const SkRect& bounds, SkScalar startAngle, SkScalar sweepAngle,
346                             bool useCenter, const SkPaint& paint) {
347    SkPipeWriter writer(this);
348    writer.write32(pack_verb(SkPipeVerb::kDrawArc, (int)useCenter));
349    writer.writeRect(bounds);
350    writer.writeScalar(startAngle);
351    writer.writeScalar(sweepAngle);
352    write_paint(writer, paint, kGeometry_PaintUsage);
353}
354
355void SkPipeCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[], const SkRect rect[],
356                               const SkColor colors[], int count, SkBlendMode mode,
357                               const SkRect* cull, const SkPaint* paint) {
358    unsigned extra = (unsigned)mode;
359    SkASSERT(0 == (extra & ~kMode_DrawAtlasMask));
360    if (colors) {
361        extra |= kHasColors_DrawAtlasMask;
362    }
363    if (cull) {
364        extra |= kHasCull_DrawAtlasMask;
365    }
366    if (paint) {
367        extra |= kHasPaint_DrawAtlasMask;
368    }
369
370    SkPipeWriter writer(this);
371    writer.write32(pack_verb(SkPipeVerb::kDrawAtlas, extra));
372    writer.writeImage(image);
373    writer.write32(count);
374    writer.write(xform, count * sizeof(SkRSXform));
375    writer.write(rect, count * sizeof(SkRect));
376    if (colors) {
377        writer.write(colors, count * sizeof(SkColor));
378    }
379    if (cull) {
380        writer.writeRect(*cull);
381    }
382    if (paint) {
383        write_paint(writer, *paint, kImage_PaintUsage);
384    }
385}
386
387void SkPipeCanvas::onDrawPaint(const SkPaint& paint) {
388    SkPipeWriter writer(this);
389    writer.write32(pack_verb(SkPipeVerb::kDrawPaint));
390    write_paint(writer, paint, kDrawPaint_PaintUsage);
391}
392
393void SkPipeCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
394                                const SkPaint& paint) {
395    SkPipeWriter writer(this);
396    writer.write32(pack_verb(SkPipeVerb::kDrawPoints, mode));
397    writer.write32(SkToU32(count));
398    writer.write(pts, count * sizeof(SkPoint));
399    write_paint(writer, paint, kGeometry_PaintUsage | kRespectsStroke_PaintUsage);
400}
401
402void SkPipeCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
403    SkPipeWriter writer(this);
404    writer.write32(pack_verb(SkPipeVerb::kDrawRect));
405    writer.write(&rect, sizeof(SkRect));
406    write_paint(writer, paint, kGeometry_PaintUsage);
407}
408
409void SkPipeCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
410    SkPipeWriter writer(this);
411    writer.write32(pack_verb(SkPipeVerb::kDrawOval));
412    writer.write(&rect, sizeof(SkRect));
413    write_paint(writer, paint, kGeometry_PaintUsage);
414}
415
416void SkPipeCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
417    SkPipeWriter writer(this);
418    writer.write32(pack_verb(SkPipeVerb::kDrawRRect));
419    write_rrect(&writer, rrect);
420    write_paint(writer, paint, kGeometry_PaintUsage);
421}
422
423void SkPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
424    SkPipeWriter writer(this);
425    writer.write32(pack_verb(SkPipeVerb::kDrawDRRect));
426    write_rrect(&writer, outer);
427    write_rrect(&writer, inner);
428    write_paint(writer, paint, kGeometry_PaintUsage);
429}
430
431void SkPipeCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
432    SkPipeWriter writer(this);
433    writer.write32(pack_verb(SkPipeVerb::kDrawPath));
434    writer.writePath(path);
435    write_paint(writer, paint, kGeometry_PaintUsage);
436}
437
438///////////////////////////////////////////////////////////////////////////////////////////////////
439
440static sk_sp<SkImage> make_from_bitmap(const SkBitmap& bitmap) {
441    // If we just "make" an image, it will force a CPU copy (if its mutable), only to have
442    // us then either find it in our cache, or compress and send it.
443    //
444    // Better could be to look it up in our cache first, and only create/compress it if we have to.
445    //
446    // But for now, just do the dumb thing...
447    return SkImage::MakeFromBitmap(bitmap);
448}
449
450void SkPipeCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
451                                const SkPaint* paint) {
452    sk_sp<SkImage> image = make_from_bitmap(bitmap);
453    if (image) {
454        this->onDrawImage(image.get(), x, y, paint);
455    }
456}
457
458void SkPipeCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
459                                    const SkPaint* paint, SrcRectConstraint constraint) {
460    sk_sp<SkImage> image = make_from_bitmap(bitmap);
461    if (image) {
462        this->onDrawImageRect(image.get(), src, dst, paint, constraint);
463    }
464}
465
466void SkPipeCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
467                                    const SkRect& dst, const SkPaint* paint) {
468    sk_sp<SkImage> image = make_from_bitmap(bitmap);
469    if (image) {
470        this->onDrawImageNine(image.get(), center, dst, paint);
471    }
472}
473
474void SkPipeCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
475                                       const SkRect& dst, const SkPaint* paint) {
476    sk_sp<SkImage> image = make_from_bitmap(bitmap);
477    if (image) {
478        this->onDrawImageLattice(image.get(), lattice, dst, paint);
479    }
480}
481
482///////////////////////////////////////////////////////////////////////////////////////////////////
483
484void SkPipeCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
485                               const SkPaint* paint) {
486    unsigned extra = 0;
487    if (paint) {
488        extra |= kHasPaint_DrawImageMask;
489    }
490    SkPipeWriter writer(this);
491    writer.write32(pack_verb(SkPipeVerb::kDrawImage, extra));
492    writer.writeImage(image);
493    writer.writeScalar(left);
494    writer.writeScalar(top);
495    if (paint) {
496        write_paint(writer, *paint, kImage_PaintUsage);
497    }
498}
499
500void SkPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
501                                   const SkPaint* paint, SrcRectConstraint constraint) {
502    SkASSERT(0 == ((unsigned)constraint & ~1));
503    unsigned extra = (unsigned)constraint;
504    if (paint) {
505        extra |= kHasPaint_DrawImageRectMask;
506    }
507    if (src) {
508        extra |= kHasSrcRect_DrawImageRectMask;
509    }
510
511    SkPipeWriter writer(this);
512    writer.write32(pack_verb(SkPipeVerb::kDrawImageRect, extra));
513    writer.writeImage(image);
514    if (src) {
515        writer.write(src, sizeof(*src));
516    }
517    writer.write(&dst, sizeof(dst));
518    if (paint) {
519        write_paint(writer, *paint, kImage_PaintUsage);
520    }
521}
522
523void SkPipeCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
524                                   const SkPaint* paint) {
525    unsigned extra = 0;
526    if (paint) {
527        extra |= kHasPaint_DrawImageNineMask;
528    }
529    SkPipeWriter writer(this);
530    writer.write32(pack_verb(SkPipeVerb::kDrawImageNine, extra));
531    writer.writeImage(image);
532    writer.write(&center, sizeof(center));
533    writer.write(&dst, sizeof(dst));
534    if (paint) {
535        write_paint(writer, *paint, kImage_PaintUsage);
536    }
537}
538
539void SkPipeCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
540                                      const SkRect& dst, const SkPaint* paint) {
541    unsigned extra = 0;
542    if (paint) {
543        extra |= kHasPaint_DrawImageLatticeMask;
544    }
545    if (lattice.fFlags) {
546        extra |= kHasFlags_DrawImageLatticeMask;
547    }
548    if (lattice.fXCount >= kCount_DrawImageLatticeMask) {
549        extra |= kCount_DrawImageLatticeMask << kXCount_DrawImageLatticeShift;
550    } else {
551        extra |= lattice.fXCount << kXCount_DrawImageLatticeShift;
552    }
553    if (lattice.fYCount >= kCount_DrawImageLatticeMask) {
554        extra |= kCount_DrawImageLatticeMask << kYCount_DrawImageLatticeShift;
555    } else {
556        extra |= lattice.fYCount << kYCount_DrawImageLatticeShift;
557    }
558
559    SkPipeWriter writer(this);
560    writer.write32(pack_verb(SkPipeVerb::kDrawImageLattice, extra));
561    writer.writeImage(image);
562    if (lattice.fXCount >= kCount_DrawImageLatticeMask) {
563        writer.write32(lattice.fXCount);
564    }
565    if (lattice.fYCount >= kCount_DrawImageLatticeMask) {
566        writer.write32(lattice.fYCount);
567    }
568    // Often these divs will be small (8 or 16 bits). Consider sniffing that and writing a flag
569    // so we can store them smaller.
570    writer.write(lattice.fXDivs, lattice.fXCount * sizeof(int32_t));
571    writer.write(lattice.fYDivs, lattice.fYCount * sizeof(int32_t));
572    if (lattice.fFlags) {
573        int32_t count = (lattice.fXCount + 1) * (lattice.fYCount + 1);
574        SkASSERT(count > 0);
575        write_pad(&writer, lattice.fFlags, count);
576    }
577    SkASSERT(lattice.fBounds);
578    writer.write(&lattice.fBounds, sizeof(*lattice.fBounds));
579    writer.write(&dst, sizeof(dst));
580    if (paint) {
581        write_paint(writer, *paint, kImage_PaintUsage);
582    }
583}
584
585///////////////////////////////////////////////////////////////////////////////////////////////////
586
587void SkPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
588                              const SkPaint& paint) {
589    SkASSERT(byteLength);
590
591    bool compact = fits_in(byteLength, 24);
592
593    SkPipeWriter writer(this);
594    writer.write32(pack_verb(SkPipeVerb::kDrawText, compact ? (unsigned)byteLength : 0));
595    if (!compact) {
596        writer.write32(SkToU32(byteLength));
597    }
598    write_pad(&writer, text, byteLength);
599    writer.writeScalar(x);
600    writer.writeScalar(y);
601    write_paint(writer, paint, kText_PaintUsage);
602}
603
604void SkPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
605                                 const SkPaint& paint) {
606    SkASSERT(byteLength);
607
608    bool compact = fits_in(byteLength, 24);
609
610    SkPipeWriter writer(this);
611    writer.write32(pack_verb(SkPipeVerb::kDrawPosText, compact ? (unsigned)byteLength : 0));
612    if (!compact) {
613        writer.write32(SkToU32(byteLength));
614    }
615    write_pad(&writer, text, byteLength);
616    writer.writePointArray(pos, paint.countText(text, byteLength));
617    write_paint(writer, paint, kText_PaintUsage);
618}
619
620void SkPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
621                                  SkScalar constY, const SkPaint& paint) {
622    SkASSERT(byteLength);
623
624    bool compact = fits_in(byteLength, 24);
625
626    SkPipeWriter writer(this);
627    writer.write32(pack_verb(SkPipeVerb::kDrawPosTextH, compact ? (unsigned)byteLength : 0));
628    if (!compact) {
629        writer.write32(SkToU32(byteLength));
630    }
631    write_pad(&writer, text, byteLength);
632    writer.writeScalarArray(xpos, paint.countText(text, byteLength));
633    writer.writeScalar(constY);
634    write_paint(writer, paint, kText_PaintUsage);
635}
636
637void SkPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
638                                    const SkMatrix* matrix, const SkPaint& paint) {
639    SkASSERT(byteLength > 0);
640
641    unsigned extra = 0;
642    if (byteLength <= kTextLength_DrawTextOnPathMask) {
643        extra |= byteLength;
644    } // else we will write the length after the packedverb
645    SkMatrix::TypeMask tm = matrix ? matrix->getType() : SkMatrix::kIdentity_Mask;
646    extra |= (unsigned)tm << kMatrixType_DrawTextOnPathShift;
647
648    SkPipeWriter writer(this);
649    writer.write32(pack_verb(SkPipeVerb::kDrawTextOnPath, extra));
650    if (byteLength > kTextLength_DrawTextOnPathMask) {
651        writer.write32(byteLength);
652    }
653    write_pad(&writer, text, byteLength);
654    writer.writePath(path);
655    if (matrix) {
656        write_sparse_matrix(&writer, *matrix);
657    }
658    write_paint(writer, paint, kText_PaintUsage);
659}
660
661void SkPipeCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
662                                     const SkRect* cull, const SkPaint& paint) {
663    SkASSERT(byteLength);
664
665    bool compact = fits_in(byteLength, 23);
666    unsigned extra = compact ? (byteLength << 1) : 0;
667    if (cull) {
668        extra |= 1;
669    }
670
671    SkPipeWriter writer(this);
672    writer.write32(pack_verb(SkPipeVerb::kDrawTextRSXform, extra));
673    if (!compact) {
674        writer.write32(SkToU32(byteLength));
675    }
676    write_pad(&writer, text, byteLength);
677
678    int count = paint.countText(text, byteLength);
679    writer.write32(count);  // maybe we can/should store this in extra as well?
680    writer.write(xform, count * sizeof(SkRSXform));
681    if (cull) {
682        writer.writeRect(*cull);
683    }
684    write_paint(writer, paint, kText_PaintUsage);
685}
686
687void SkPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
688                                  const SkPaint &paint) {
689    SkPipeWriter writer(this);
690    writer.write32(pack_verb(SkPipeVerb::kDrawTextBlob, 0));
691    blob->flatten(writer);
692    writer.writeScalar(x);
693    writer.writeScalar(y);
694    write_paint(writer, paint, kTextBlob_PaintUsage);
695}
696
697void SkPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
698                                 const SkPaint* paint) {
699    unsigned extra = fDeduper->findOrDefinePicture(const_cast<SkPicture*>(picture));
700    if (matrix) {
701        extra |= kHasMatrix_DrawPictureExtra;
702    }
703    if (paint) {
704        extra |= kHasPaint_DrawPictureExtra;
705    }
706    SkPipeWriter writer(this);
707    writer.write32(pack_verb(SkPipeVerb::kDrawPicture, extra));
708    if (matrix) {
709        writer.writeMatrix(*matrix);
710    }
711    if (paint) {
712        write_paint(writer, *paint, kSaveLayer_PaintUsage);
713    }
714}
715
716void SkPipeCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
717    size_t size = region.writeToMemory(nullptr);
718    unsigned extra = 0;
719    if (fits_in(size, 24)) {
720        extra = SkToUInt(size);
721    }
722
723    SkPipeWriter writer(this);
724    writer.write32(pack_verb(SkPipeVerb::kDrawRegion, extra));
725    if (0 == extra) {
726        writer.write32(size);
727    }
728    SkAutoSMalloc<2048> storage(size);
729    region.writeToMemory(storage.get());
730    write_pad(&writer, storage.get(), size);
731    write_paint(writer, paint, kGeometry_PaintUsage);
732}
733
734void SkPipeCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
735                                  const SkPoint vertices[], const SkPoint texs[],
736                                  const SkColor colors[], SkBlendMode bmode,
737                                  const uint16_t indices[], int indexCount,
738                                  const SkPaint& paint) {
739    SkASSERT(vertexCount > 0);
740
741    unsigned extra = 0;
742    if (vertexCount <= kVCount_DrawVerticesMask) {
743        extra |= vertexCount;
744    }
745    extra |= (unsigned)vmode << kVMode_DrawVerticesShift;
746    extra |= (unsigned)bmode << kXMode_DrawVerticesShift;
747
748    if (texs) {
749        extra |= kHasTex_DrawVerticesMask;
750    }
751    if (colors) {
752        extra |= kHasColors_DrawVerticesMask;
753    }
754    if (indexCount > 0) {
755        extra |= kHasIndices_DrawVerticesMask;
756    }
757
758    SkPipeWriter writer(this);
759    writer.write32(pack_verb(SkPipeVerb::kDrawVertices, extra));
760    if (vertexCount > kVCount_DrawVerticesMask) {
761        writer.write32(vertexCount);
762    }
763    writer.write(vertices, vertexCount * sizeof(SkPoint));
764    if (texs) {
765        writer.write(texs, vertexCount * sizeof(SkPoint));
766    }
767    if (colors) {
768        writer.write(colors, vertexCount * sizeof(SkColor));
769    }
770    if (indexCount > 0) {
771        writer.write32(indexCount);
772        SkASSERT(SkIsAlign2(indexCount));
773        writer.write(indices, indexCount * sizeof(uint16_t));
774    }
775    write_paint(writer, paint, kVertices_PaintUsage);
776}
777
778void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
779                               const SkPoint texCoords[4], SkBlendMode bmode,
780                               const SkPaint& paint) {
781    SkPipeWriter writer(this);
782    unsigned extra = 0;
783    SkASSERT(0 == ((int)bmode & ~kModeEnum_DrawPatchExtraMask));
784    extra = (unsigned)bmode;
785    if (colors) {
786        extra |= kHasColors_DrawPatchExtraMask;
787    }
788    if (texCoords) {
789        extra |= kHasTexture_DrawPatchExtraMask;
790    }
791    writer.write32(pack_verb(SkPipeVerb::kDrawPatch, extra));
792    writer.write(cubics, sizeof(SkPoint) * 12);
793    if (colors) {
794        writer.write(colors, sizeof(SkColor) * 4);
795    }
796    if (texCoords) {
797        writer.write(texCoords, sizeof(SkPoint) * 4);
798    }
799    write_paint(writer, paint, kGeometry_PaintUsage);
800}
801
802void SkPipeCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
803    const size_t len = strlen(key) + 1; // must write the trailing 0
804    bool compact = fits_in(len, 23);
805    uint32_t extra = compact ? (unsigned)len : 0;
806    extra <<= 1;   // make room for has_data_sentinel
807    if (data) {
808        extra |= 1;
809    }
810
811    fStream->write32(pack_verb(SkPipeVerb::kDrawAnnotation, extra));
812    fStream->write(&rect, sizeof(SkRect));
813    if (!compact) {
814        fStream->write32(SkToU32(len));
815    }
816    write_pad(fStream, key, len);
817    if (data) {
818        fStream->write32(SkToU32(data->size()));
819        write_pad(fStream, data->data(), data->size());
820    }
821}
822
823///////////////////////////////////////////////////////////////////////////////////////////////////
824
825class A8Serializer : public SkPixelSerializer {
826protected:
827    bool onUseEncodedData(const void* data, size_t len) {
828        return true;
829    }
830
831    SkData* onEncode(const SkPixmap& pmap) {
832        if (kAlpha_8_SkColorType == pmap.colorType()) {
833            SkDynamicMemoryWStream stream;
834            stream.write("skiaimgf", 8);
835            stream.write32(pmap.width());
836            stream.write32(pmap.height());
837            stream.write16(pmap.colorType());
838            stream.write16(pmap.alphaType());
839            stream.write32(0);  // no colorspace for now
840            for (int y = 0; y < pmap.height(); ++y) {
841                stream.write(pmap.addr8(0, y), pmap.width());
842            }
843            return stream.detachAsData().release();
844        }
845        return nullptr;
846    }
847};
848
849static sk_sp<SkData> default_image_serializer(SkImage* image) {
850    A8Serializer serial;
851    sk_sp<SkData> data(image->encode(&serial));
852    if (!data) {
853        data.reset(image->encode());
854    }
855    return data;
856}
857
858static bool show_deduper_traffic = false;
859
860int SkPipeDeduper::findOrDefineImage(SkImage* image) {
861    int index = fImages.find(image->uniqueID());
862    SkASSERT(index >= 0);
863    if (index) {
864        if (show_deduper_traffic) {
865            SkDebugf("  reuseImage(%d)\n", index - 1);
866        }
867        return index;
868    }
869
870    sk_sp<SkData> data = fIMSerializer ? fIMSerializer->serialize(image)
871                                       : default_image_serializer(image);
872    if (data) {
873        index = fImages.add(image->uniqueID());
874        SkASSERT(index > 0);
875        SkASSERT(fits_in(index, 24));
876        fStream->write32(pack_verb(SkPipeVerb::kDefineImage, index));
877
878        uint32_t len = SkToU32(data->size());
879        fStream->write32(SkAlign4(len));
880        write_pad(fStream, data->data(), len);
881
882        if (show_deduper_traffic) {
883            int size = image->width() * image->height() << 2;
884            SkDebugf("  defineImage(%d) %d -> %d\n", index - 1, size, len);
885        }
886        return index;
887    }
888    SkDebugf("+++ failed to encode image [%d %d]\n", image->width(), image->height());
889    return 0;   // failed to encode
890}
891
892int SkPipeDeduper::findOrDefinePicture(SkPicture* picture) {
893    int index = fPictures.find(picture->uniqueID());
894    SkASSERT(index >= 0);
895    if (index) {
896        if (show_deduper_traffic) {
897            SkDebugf("  reusePicture(%d)\n", index - 1);
898        }
899        return index;
900    }
901
902    size_t prevWritten = fStream->bytesWritten();
903    unsigned extra = 0; // 0 means we're defining a new picture, non-zero means undef_index + 1
904    fStream->write32(pack_verb(SkPipeVerb::kDefinePicture, extra));
905    const SkRect cull = picture->cullRect();
906    fStream->write(&cull, sizeof(cull));
907    picture->playback(fPipeCanvas);
908    // call fPictures.add *after* we're written the picture, so that any nested pictures will have
909    // already been defined, and we get the "last" index value.
910    index = fPictures.add(picture->uniqueID());
911    ASSERT_FITS_IN(index, kObjectDefinitionBits);
912    fStream->write32(pack_verb(SkPipeVerb::kEndPicture, index));
913
914    SkDebugf("  definePicture(%d) %d\n",
915             index - 1, SkToU32(fStream->bytesWritten() - prevWritten));
916    return index;
917}
918
919static sk_sp<SkData> encode(SkTypeface* tf) {
920    SkDynamicMemoryWStream stream;
921    tf->serialize(&stream);
922    return sk_sp<SkData>(stream.detachAsData());
923}
924
925int SkPipeDeduper::findOrDefineTypeface(SkTypeface* typeface) {
926    if (!typeface) {
927        return 0;   // default
928    }
929
930    int index = fTypefaces.find(typeface->uniqueID());
931    SkASSERT(index >= 0);
932    if (index) {
933        if (show_deduper_traffic) {
934            SkDebugf("  reuseTypeface(%d)\n", index - 1);
935        }
936        return index;
937    }
938
939    sk_sp<SkData> data = fTFSerializer ? fTFSerializer->serialize(typeface) : encode(typeface);
940    if (data) {
941        index = fTypefaces.add(typeface->uniqueID());
942        SkASSERT(index > 0);
943        SkASSERT(fits_in(index, 24));
944        fStream->write32(pack_verb(SkPipeVerb::kDefineTypeface, index));
945
946        uint32_t len = SkToU32(data->size());
947        fStream->write32(SkAlign4(len));
948        write_pad(fStream, data->data(), len);
949
950        if (show_deduper_traffic) {
951            SkDebugf("  defineTypeface(%d) %d\n", index - 1, len);
952        }
953        return index;
954    }
955    SkDebugf("+++ failed to encode typeface %d\n", typeface->uniqueID());
956    return 0;   // failed to encode
957}
958
959int SkPipeDeduper::findOrDefineFactory(SkFlattenable* flattenable) {
960    if (!flattenable) {
961        return 0;
962    }
963
964    int index = fFactories.find(flattenable->getFactory());
965    SkASSERT(index >= 0);
966    if (index) {
967        if (show_deduper_traffic) {
968            SkDebugf("  reuseFactory(%d)\n", index - 1);
969        }
970        return index;
971    }
972
973    index = fFactories.add(flattenable->getFactory());
974    ASSERT_FITS_IN(index, kIndex_DefineFactoryExtraBits);
975    const char* name = flattenable->getTypeName();
976    size_t len = strlen(name);
977    ASSERT_FITS_IN(len, kNameLength_DefineFactoryExtraBits);
978    unsigned extra = (index << kNameLength_DefineFactoryExtraBits) | len;
979    size_t prevWritten = fStream->bytesWritten();
980    fStream->write32(pack_verb(SkPipeVerb::kDefineFactory, extra));
981    write_pad(fStream, name, len + 1);
982    if (false) {
983        SkDebugf("  defineFactory(%d) %d %s\n",
984             index - 1, SkToU32(fStream->bytesWritten() - prevWritten), name);
985    }
986    return index;
987}
988
989///////////////////////////////////////////////////////////////////////////////////////////////////
990#include "SkPipe.h"
991
992class SkPipeSerializer::Impl {
993public:
994    SkPipeDeduper   fDeduper;
995    std::unique_ptr<SkPipeCanvas> fCanvas;
996};
997
998SkPipeSerializer::SkPipeSerializer() : fImpl(new Impl) {}
999
1000SkPipeSerializer::~SkPipeSerializer() {
1001    if (fImpl->fCanvas) {
1002        this->endWrite();
1003    }
1004}
1005
1006void SkPipeSerializer::setTypefaceSerializer(SkTypefaceSerializer* tfs) {
1007    fImpl->fDeduper.setTypefaceSerializer(tfs);
1008}
1009
1010void SkPipeSerializer::setImageSerializer(SkImageSerializer* ims) {
1011    fImpl->fDeduper.setImageSerializer(ims);
1012}
1013
1014void SkPipeSerializer::resetCache() {
1015    fImpl->fDeduper.resetCaches();
1016}
1017
1018sk_sp<SkData> SkPipeSerializer::writeImage(SkImage* image) {
1019    SkDynamicMemoryWStream stream;
1020    this->writeImage(image, &stream);
1021    return stream.detachAsData();
1022}
1023
1024sk_sp<SkData> SkPipeSerializer::writePicture(SkPicture* picture) {
1025    SkDynamicMemoryWStream stream;
1026    this->writePicture(picture, &stream);
1027    return stream.detachAsData();
1028}
1029
1030void SkPipeSerializer::writePicture(SkPicture* picture, SkWStream* stream) {
1031    int index = fImpl->fDeduper.findPicture(picture);
1032    if (0 == index) {
1033        // Try to define the picture
1034        this->beginWrite(picture->cullRect(), stream);
1035        index = fImpl->fDeduper.findOrDefinePicture(picture);
1036        this->endWrite();
1037    }
1038    stream->write32(pack_verb(SkPipeVerb::kWritePicture, index));
1039}
1040
1041void SkPipeSerializer::writeImage(SkImage* image, SkWStream* stream) {
1042    int index = fImpl->fDeduper.findImage(image);
1043    if (0 == index) {
1044        // Try to define the image
1045        fImpl->fDeduper.setStream(stream);
1046        index = fImpl->fDeduper.findOrDefineImage(image);
1047    }
1048    stream->write32(pack_verb(SkPipeVerb::kWriteImage, index));
1049}
1050
1051SkCanvas* SkPipeSerializer::beginWrite(const SkRect& cull, SkWStream* stream) {
1052    SkASSERT(nullptr == fImpl->fCanvas);
1053    fImpl->fCanvas.reset(new SkPipeCanvas(cull, &fImpl->fDeduper, stream));
1054    fImpl->fDeduper.setStream(stream);
1055    fImpl->fDeduper.setCanvas(fImpl->fCanvas.get());
1056    return fImpl->fCanvas.get();
1057}
1058
1059void SkPipeSerializer::endWrite() {
1060    fImpl->fCanvas->restoreToCount(1);
1061    fImpl->fCanvas.reset(nullptr);
1062    fImpl->fDeduper.setCanvas(nullptr);
1063}
1064