LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/pipe - SkPipeCanvas.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 670 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 80 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13