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 "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 
     24 template <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 
     30 template <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 
     43 static 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 
     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, ImageFilter);
    178     CHECK_WRITE_FLATTENABLE(writer, nondef, paint, DrawLooper);
    179 }
    180 
    181 class SkPipeWriter : public SkBinaryWriteBuffer {
    182     enum {
    183         N = 1024/4,
    184     };
    185     uint32_t fStorage[N];
    186     SkWStream* fStream;
    187 
    188 public:
    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 
    210 SkPipeCanvas::SkPipeCanvas(const SkRect& cull, SkPipeDeduper* deduper, SkWStream* stream)
    211     : INHERITED(cull.roundOut())
    212     , fDeduper(deduper)
    213     , fStream(stream)
    214 {}
    215 
    216 SkPipeCanvas::~SkPipeCanvas() {}
    217 
    218 void SkPipeCanvas::willSave() {
    219     fStream->write32(pack_verb(SkPipeVerb::kSave));
    220     this->INHERITED::willSave();
    221 }
    222 
    223 SkCanvas::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 
    269 void SkPipeCanvas::willRestore() {
    270     fStream->write32(pack_verb(SkPipeVerb::kRestore));
    271     this->INHERITED::willRestore();
    272 }
    273 
    274 template <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 
    302 static 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 
    315 void SkPipeCanvas::didConcat(const SkMatrix& matrix) {
    316     do_concat(fStream, matrix, false);
    317     this->INHERITED::didConcat(matrix);
    318 }
    319 
    320 void SkPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
    321     do_concat(fStream, matrix, true);
    322     this->INHERITED::didSetMatrix(matrix);
    323 }
    324 
    325 void 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 
    332 void 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 
    339 void 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 
    347 void 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 
    357 void 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 
    367 void 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 
    399 void 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 
    405 void 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 
    414 void 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 
    421 void 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 
    428 void 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 
    435 void 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 
    443 void 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 
    450 void 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 
    459 static 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 
    469 void 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 
    477 void 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 
    485 void 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 
    493 void 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 
    503 void 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 
    519 void 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 
    542 void 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 
    558 void 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 
    576 void 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 
    593 void 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 
    609 void 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 
    626 void 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 
    650 void 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 
    676 void 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 
    686 void 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 
    705 void 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 
    723 void 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 
    734 void 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 
    758 void 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 
    781 static 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 
    790 static bool show_deduper_traffic = false;
    791 
    792 int 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 
    823 int 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 
    852 static 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 
    864 int 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 
    898 int 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 
    931 class SkPipeSerializer::Impl {
    932 public:
    933     SkPipeDeduper   fDeduper;
    934     std::unique_ptr<SkPipeCanvas> fCanvas;
    935 };
    936 
    937 SkPipeSerializer::SkPipeSerializer() : fImpl(new Impl) {}
    938 
    939 SkPipeSerializer::~SkPipeSerializer() {
    940     if (fImpl->fCanvas) {
    941         this->endWrite();
    942     }
    943 }
    944 
    945 void SkPipeSerializer::resetCache() {
    946     fImpl->fDeduper.resetCaches();
    947 }
    948 
    949 sk_sp<SkData> SkPipeSerializer::writeImage(SkImage* image) {
    950     SkDynamicMemoryWStream stream;
    951     this->writeImage(image, &stream);
    952     return stream.detachAsData();
    953 }
    954 
    955 sk_sp<SkData> SkPipeSerializer::writePicture(SkPicture* picture) {
    956     SkDynamicMemoryWStream stream;
    957     this->writePicture(picture, &stream);
    958     return stream.detachAsData();
    959 }
    960 
    961 void 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 
    972 void 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 
    982 SkCanvas* 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 
    990 void SkPipeSerializer::endWrite() {
    991     fImpl->fCanvas->restoreToCount(1);
    992     fImpl->fCanvas.reset(nullptr);
    993     fImpl->fDeduper.setCanvas(nullptr);
    994 }
    995