Home | History | Annotate | Download | only in pipe
      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 
     23 template <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 
     29 template <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 
     42 static 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 
     92 static 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  */
    145 static 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 
    182 class SkPipeWriter : public SkBinaryWriteBuffer {
    183     enum {
    184         N = 1024/4,
    185     };
    186     uint32_t fStorage[N];
    187     SkWStream* fStream;
    188 
    189 public:
    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 
    211 SkPipeCanvas::SkPipeCanvas(const SkRect& cull, SkPipeDeduper* deduper, SkWStream* stream)
    212     : INHERITED(cull.roundOut())
    213     , fDeduper(deduper)
    214     , fStream(stream)
    215 {}
    216 
    217 SkPipeCanvas::~SkPipeCanvas() {}
    218 
    219 void SkPipeCanvas::willSave() {
    220     fStream->write32(pack_verb(SkPipeVerb::kSave));
    221     this->INHERITED::willSave();
    222 }
    223 
    224 SkCanvas::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 
    257 void SkPipeCanvas::willRestore() {
    258     fStream->write32(pack_verb(SkPipeVerb::kRestore));
    259     this->INHERITED::willRestore();
    260 }
    261 
    262 template <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 
    290 static 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 
    303 void SkPipeCanvas::didConcat(const SkMatrix& matrix) {
    304     do_concat(fStream, matrix, false);
    305     this->INHERITED::didConcat(matrix);
    306 }
    307 
    308 void SkPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
    309     do_concat(fStream, matrix, true);
    310     this->INHERITED::didSetMatrix(matrix);
    311 }
    312 
    313 void 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 
    320 void 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 
    327 void 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 
    335 void 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 
    345 void 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 
    355 void 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 
    387 void 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 
    393 void 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 
    402 void 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 
    409 void 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 
    416 void 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 
    423 void 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 
    431 void 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 
    440 static 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 
    450 void 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 
    458 void 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 
    466 void 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 
    474 void 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 
    484 void 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 
    500 void 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 
    523 void 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 
    539 void 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 
    587 void 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 
    604 void 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 
    620 void 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 
    637 void 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 
    661 void 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 
    687 void 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 
    697 void 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 
    716 void 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 
    734 void SkPipeCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
    735                                         const SkPaint& paint) {
    736     unsigned extra = static_cast<unsigned>(bmode);
    737 
    738     SkPipeWriter writer(this);
    739     writer.write32(pack_verb(SkPipeVerb::kDrawVertices, extra));
    740     // TODO: dedup vertices?
    741     writer.writeDataAsByteArray(vertices->encode().get());
    742     write_paint(writer, paint, kVertices_PaintUsage);
    743 }
    744 
    745 void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
    746                                const SkPoint texCoords[4], SkBlendMode bmode,
    747                                const SkPaint& paint) {
    748     SkPipeWriter writer(this);
    749     unsigned extra = 0;
    750     SkASSERT(0 == ((int)bmode & ~kModeEnum_DrawPatchExtraMask));
    751     extra = (unsigned)bmode;
    752     if (colors) {
    753         extra |= kHasColors_DrawPatchExtraMask;
    754     }
    755     if (texCoords) {
    756         extra |= kHasTexture_DrawPatchExtraMask;
    757     }
    758     writer.write32(pack_verb(SkPipeVerb::kDrawPatch, extra));
    759     writer.write(cubics, sizeof(SkPoint) * 12);
    760     if (colors) {
    761         writer.write(colors, sizeof(SkColor) * 4);
    762     }
    763     if (texCoords) {
    764         writer.write(texCoords, sizeof(SkPoint) * 4);
    765     }
    766     write_paint(writer, paint, kGeometry_PaintUsage);
    767 }
    768 
    769 void SkPipeCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
    770     const size_t len = strlen(key) + 1; // must write the trailing 0
    771     bool compact = fits_in(len, 23);
    772     uint32_t extra = compact ? (unsigned)len : 0;
    773     extra <<= 1;   // make room for has_data_sentinel
    774     if (data) {
    775         extra |= 1;
    776     }
    777 
    778     fStream->write32(pack_verb(SkPipeVerb::kDrawAnnotation, extra));
    779     fStream->write(&rect, sizeof(SkRect));
    780     if (!compact) {
    781         fStream->write32(SkToU32(len));
    782     }
    783     write_pad(fStream, key, len);
    784     if (data) {
    785         fStream->write32(SkToU32(data->size()));
    786         write_pad(fStream, data->data(), data->size());
    787     }
    788 }
    789 
    790 ///////////////////////////////////////////////////////////////////////////////////////////////////
    791 
    792 class A8Serializer : public SkPixelSerializer {
    793 protected:
    794     bool onUseEncodedData(const void* data, size_t len) {
    795         return true;
    796     }
    797 
    798     SkData* onEncode(const SkPixmap& pmap) {
    799         if (kAlpha_8_SkColorType == pmap.colorType()) {
    800             SkDynamicMemoryWStream stream;
    801             stream.write("skiaimgf", 8);
    802             stream.write32(pmap.width());
    803             stream.write32(pmap.height());
    804             stream.write16(pmap.colorType());
    805             stream.write16(pmap.alphaType());
    806             stream.write32(0);  // no colorspace for now
    807             for (int y = 0; y < pmap.height(); ++y) {
    808                 stream.write(pmap.addr8(0, y), pmap.width());
    809             }
    810             return stream.detachAsData().release();
    811         }
    812         return nullptr;
    813     }
    814 };
    815 
    816 static sk_sp<SkData> default_image_serializer(SkImage* image) {
    817     A8Serializer serial;
    818     sk_sp<SkData> data(image->encode(&serial));
    819     if (!data) {
    820         data.reset(image->encode());
    821     }
    822     return data;
    823 }
    824 
    825 static bool show_deduper_traffic = false;
    826 
    827 int SkPipeDeduper::findOrDefineImage(SkImage* image) {
    828     int index = fImages.find(image->uniqueID());
    829     SkASSERT(index >= 0);
    830     if (index) {
    831         if (show_deduper_traffic) {
    832             SkDebugf("  reuseImage(%d)\n", index - 1);
    833         }
    834         return index;
    835     }
    836 
    837     sk_sp<SkData> data = fIMSerializer ? fIMSerializer->serialize(image)
    838                                        : default_image_serializer(image);
    839     if (data) {
    840         index = fImages.add(image->uniqueID());
    841         SkASSERT(index > 0);
    842         SkASSERT(fits_in(index, 24));
    843         fStream->write32(pack_verb(SkPipeVerb::kDefineImage, index));
    844 
    845         uint32_t len = SkToU32(data->size());
    846         fStream->write32(SkAlign4(len));
    847         write_pad(fStream, data->data(), len);
    848 
    849         if (show_deduper_traffic) {
    850             int size = image->width() * image->height() << 2;
    851             SkDebugf("  defineImage(%d) %d -> %d\n", index - 1, size, len);
    852         }
    853         return index;
    854     }
    855     SkDebugf("+++ failed to encode image [%d %d]\n", image->width(), image->height());
    856     return 0;   // failed to encode
    857 }
    858 
    859 int SkPipeDeduper::findOrDefinePicture(SkPicture* picture) {
    860     int index = fPictures.find(picture->uniqueID());
    861     SkASSERT(index >= 0);
    862     if (index) {
    863         if (show_deduper_traffic) {
    864             SkDebugf("  reusePicture(%d)\n", index - 1);
    865         }
    866         return index;
    867     }
    868 
    869     size_t prevWritten = fStream->bytesWritten();
    870     unsigned extra = 0; // 0 means we're defining a new picture, non-zero means undef_index + 1
    871     fStream->write32(pack_verb(SkPipeVerb::kDefinePicture, extra));
    872     const SkRect cull = picture->cullRect();
    873     fStream->write(&cull, sizeof(cull));
    874     picture->playback(fPipeCanvas);
    875     // call fPictures.add *after* we're written the picture, so that any nested pictures will have
    876     // already been defined, and we get the "last" index value.
    877     index = fPictures.add(picture->uniqueID());
    878     ASSERT_FITS_IN(index, kObjectDefinitionBits);
    879     fStream->write32(pack_verb(SkPipeVerb::kEndPicture, index));
    880 
    881     if (show_deduper_traffic) {
    882         SkDebugf("  definePicture(%d) %d\n",
    883                  index - 1, SkToU32(fStream->bytesWritten() - prevWritten));
    884     }
    885     return index;
    886 }
    887 
    888 static sk_sp<SkData> encode(SkTypeface* tf) {
    889     SkDynamicMemoryWStream stream;
    890     tf->serialize(&stream);
    891     return sk_sp<SkData>(stream.detachAsData());
    892 }
    893 
    894 int SkPipeDeduper::findOrDefineTypeface(SkTypeface* typeface) {
    895     if (!typeface) {
    896         return 0;   // default
    897     }
    898 
    899     int index = fTypefaces.find(typeface->uniqueID());
    900     SkASSERT(index >= 0);
    901     if (index) {
    902         if (show_deduper_traffic) {
    903             SkDebugf("  reuseTypeface(%d)\n", index - 1);
    904         }
    905         return index;
    906     }
    907 
    908     sk_sp<SkData> data = fTFSerializer ? fTFSerializer->serialize(typeface) : encode(typeface);
    909     if (data) {
    910         index = fTypefaces.add(typeface->uniqueID());
    911         SkASSERT(index > 0);
    912         SkASSERT(fits_in(index, 24));
    913         fStream->write32(pack_verb(SkPipeVerb::kDefineTypeface, index));
    914 
    915         uint32_t len = SkToU32(data->size());
    916         fStream->write32(SkAlign4(len));
    917         write_pad(fStream, data->data(), len);
    918 
    919         if (show_deduper_traffic) {
    920             SkDebugf("  defineTypeface(%d) %d\n", index - 1, len);
    921         }
    922         return index;
    923     }
    924     SkDebugf("+++ failed to encode typeface %d\n", typeface->uniqueID());
    925     return 0;   // failed to encode
    926 }
    927 
    928 int SkPipeDeduper::findOrDefineFactory(SkFlattenable* flattenable) {
    929     if (!flattenable) {
    930         return 0;
    931     }
    932 
    933     int index = fFactories.find(flattenable->getFactory());
    934     SkASSERT(index >= 0);
    935     if (index) {
    936         if (show_deduper_traffic) {
    937             SkDebugf("  reuseFactory(%d)\n", index - 1);
    938         }
    939         return index;
    940     }
    941 
    942     index = fFactories.add(flattenable->getFactory());
    943     ASSERT_FITS_IN(index, kIndex_DefineFactoryExtraBits);
    944     const char* name = flattenable->getTypeName();
    945     size_t len = strlen(name);
    946     ASSERT_FITS_IN(len, kNameLength_DefineFactoryExtraBits);
    947     unsigned extra = (index << kNameLength_DefineFactoryExtraBits) | len;
    948     size_t prevWritten = fStream->bytesWritten();
    949     fStream->write32(pack_verb(SkPipeVerb::kDefineFactory, extra));
    950     write_pad(fStream, name, len + 1);
    951     if (false) {
    952         SkDebugf("  defineFactory(%d) %d %s\n",
    953              index - 1, SkToU32(fStream->bytesWritten() - prevWritten), name);
    954     }
    955     return index;
    956 }
    957 
    958 ///////////////////////////////////////////////////////////////////////////////////////////////////
    959 #include "SkPipe.h"
    960 
    961 class SkPipeSerializer::Impl {
    962 public:
    963     SkPipeDeduper   fDeduper;
    964     std::unique_ptr<SkPipeCanvas> fCanvas;
    965 };
    966 
    967 SkPipeSerializer::SkPipeSerializer() : fImpl(new Impl) {}
    968 
    969 SkPipeSerializer::~SkPipeSerializer() {
    970     if (fImpl->fCanvas) {
    971         this->endWrite();
    972     }
    973 }
    974 
    975 void SkPipeSerializer::setTypefaceSerializer(SkTypefaceSerializer* tfs) {
    976     fImpl->fDeduper.setTypefaceSerializer(tfs);
    977 }
    978 
    979 void SkPipeSerializer::setImageSerializer(SkImageSerializer* ims) {
    980     fImpl->fDeduper.setImageSerializer(ims);
    981 }
    982 
    983 void SkPipeSerializer::resetCache() {
    984     fImpl->fDeduper.resetCaches();
    985 }
    986 
    987 sk_sp<SkData> SkPipeSerializer::writeImage(SkImage* image) {
    988     SkDynamicMemoryWStream stream;
    989     this->writeImage(image, &stream);
    990     return stream.detachAsData();
    991 }
    992 
    993 sk_sp<SkData> SkPipeSerializer::writePicture(SkPicture* picture) {
    994     SkDynamicMemoryWStream stream;
    995     this->writePicture(picture, &stream);
    996     return stream.detachAsData();
    997 }
    998 
    999 void SkPipeSerializer::writePicture(SkPicture* picture, SkWStream* stream) {
   1000     int index = fImpl->fDeduper.findPicture(picture);
   1001     if (0 == index) {
   1002         // Try to define the picture
   1003         this->beginWrite(picture->cullRect(), stream);
   1004         index = fImpl->fDeduper.findOrDefinePicture(picture);
   1005         this->endWrite();
   1006     }
   1007     stream->write32(pack_verb(SkPipeVerb::kWritePicture, index));
   1008 }
   1009 
   1010 void SkPipeSerializer::writeImage(SkImage* image, SkWStream* stream) {
   1011     int index = fImpl->fDeduper.findImage(image);
   1012     if (0 == index) {
   1013         // Try to define the image
   1014         fImpl->fDeduper.setStream(stream);
   1015         index = fImpl->fDeduper.findOrDefineImage(image);
   1016     }
   1017     stream->write32(pack_verb(SkPipeVerb::kWriteImage, index));
   1018 }
   1019 
   1020 SkCanvas* SkPipeSerializer::beginWrite(const SkRect& cull, SkWStream* stream) {
   1021     SkASSERT(nullptr == fImpl->fCanvas);
   1022     fImpl->fCanvas.reset(new SkPipeCanvas(cull, &fImpl->fDeduper, stream));
   1023     fImpl->fDeduper.setStream(stream);
   1024     fImpl->fDeduper.setCanvas(fImpl->fCanvas.get());
   1025     return fImpl->fCanvas.get();
   1026 }
   1027 
   1028 void SkPipeSerializer::endWrite() {
   1029     fImpl->fCanvas->restoreToCount(1);
   1030     fImpl->fCanvas.reset(nullptr);
   1031     fImpl->fDeduper.setCanvas(nullptr);
   1032 }
   1033