/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkCanvas.h" #include "SkCanvasPriv.h" #include "SkDeduper.h" #include "SkDrawShadowInfo.h" #include "SkPicture.h" #include "SkPictureRecorder.h" #include "SkPipe.h" #include "SkPipeFormat.h" #include "SkReadBuffer.h" #include "SkRefSet.h" #include "SkRSXform.h" #include "SkTextBlob.h" #include "SkTypeface.h" #include "SkVertices.h" class SkPipeReader; static bool do_playback(SkPipeReader& reader, SkCanvas* canvas, int* endPictureIndex = nullptr); /////////////////////////////////////////////////////////////////////////////////////////////////// class SkPipeInflator : public SkInflator { public: SkPipeInflator(SkRefSet* images, SkRefSet* pictures, SkRefSet* typefaces, SkTDArray* factories, const SkDeserialProcs& procs) : fImages(images) , fPictures(pictures) , fTypefaces(typefaces) , fFactories(factories) , fProcs(procs) {} SkImage* getImage(int index) override { return index ? fImages->get(index - 1) : nullptr; } SkPicture* getPicture(int index) override { return index ? fPictures->get(index - 1) : nullptr; } SkTypeface* getTypeface(int index) override { return fTypefaces->get(index - 1); } SkFlattenable::Factory getFactory(int index) override { return index ? fFactories->getAt(index - 1) : nullptr; } bool setImage(int index, sk_sp img) { return fImages->set(index - 1, std::move(img)); } bool setPicture(int index, sk_sp pic) { return fPictures->set(index - 1, std::move(pic)); } bool setTypeface(int index, sk_sp face) { return fTypefaces->set(index - 1, std::move(face)); } bool setFactory(int index, SkFlattenable::Factory factory) { SkASSERT(index > 0); SkASSERT(factory); index -= 1; if ((unsigned)index < (unsigned)fFactories->count()) { (*fFactories)[index] = factory; return true; } if (fFactories->count() == index) { *fFactories->append() = factory; return true; } SkDebugf("setFactory: index [%d] out of range %d\n", index, fFactories->count()); return false; } void setDeserialProcs(const SkDeserialProcs& procs) { fProcs = procs; } sk_sp makeTypeface(const void* data, size_t size); sk_sp makeImage(const sk_sp&); private: SkRefSet* fImages; SkRefSet* fPictures; SkRefSet* fTypefaces; SkTDArray* fFactories; SkDeserialProcs fProcs; }; /////////////////////////////////////////////////////////////////////////////////////////////////// static SkRRect read_rrect(SkReadBuffer& reader) { SkRRect rrect; rrect.readFromMemory(reader.skip(SkRRect::kSizeInMemory), SkRRect::kSizeInMemory); return rrect; } static SkMatrix read_sparse_matrix(SkReadBuffer& reader, SkMatrix::TypeMask tm) { SkMatrix matrix; matrix.reset(); if (tm & SkMatrix::kPerspective_Mask) { matrix.set9(reader.skipT(9)); } else if (tm & SkMatrix::kAffine_Mask) { const SkScalar* tmp = reader.skipT(6); matrix[SkMatrix::kMScaleX] = tmp[0]; matrix[SkMatrix::kMSkewX] = tmp[1]; matrix[SkMatrix::kMTransX] = tmp[2]; matrix[SkMatrix::kMScaleY] = tmp[3]; matrix[SkMatrix::kMSkewY] = tmp[4]; matrix[SkMatrix::kMTransY] = tmp[5]; } else if (tm & SkMatrix::kScale_Mask) { const SkScalar* tmp = reader.skipT(4); matrix[SkMatrix::kMScaleX] = tmp[0]; matrix[SkMatrix::kMTransX] = tmp[1]; matrix[SkMatrix::kMScaleY] = tmp[2]; matrix[SkMatrix::kMTransY] = tmp[3]; } else if (tm & SkMatrix::kTranslate_Mask) { const SkScalar* tmp = reader.skipT(2); matrix[SkMatrix::kMTransX] = tmp[0]; matrix[SkMatrix::kMTransY] = tmp[1]; } // else read nothing for Identity return matrix; } /////////////////////////////////////////////////////////////////////////////////////////////////// #define CHECK_SET_SCALAR(Field) \ do { if (nondef & k##Field##_NonDef) { \ paint.set##Field(reader.readScalar()); \ }} while (0) #define CHECK_SET_FLATTENABLE(Field) \ do { if (nondef & k##Field##_NonDef) { \ paint.set##Field(reader.read##Field()); \ }} while (0) /* * Header: * paint flags : 32 * non_def bits : 16 * xfermode enum : 8 * pad zeros : 8 */ static SkPaint read_paint(SkReadBuffer& reader) { SkPaint paint; uint32_t packedFlags = reader.read32(); uint32_t extra = reader.read32(); unsigned nondef = extra >> 16; paint.setBlendMode(SkBlendMode((extra >> 8) & 0xFF)); SkASSERT((extra & 0xFF) == 0); // zero pad byte packedFlags >>= 2; // currently unused paint.setTextEncoding((SkPaint::TextEncoding)(packedFlags & 3)); packedFlags >>= 2; paint.setTextAlign((SkPaint::Align)(packedFlags & 3)); packedFlags >>= 2; paint.setHinting((SkPaint::Hinting)(packedFlags & 3)); packedFlags >>= 2; paint.setStrokeJoin((SkPaint::Join)(packedFlags & 3)); packedFlags >>= 2; paint.setStrokeCap((SkPaint::Cap)(packedFlags & 3)); packedFlags >>= 2; paint.setStyle((SkPaint::Style)(packedFlags & 3)); packedFlags >>= 2; paint.setFilterQuality((SkFilterQuality)(packedFlags & 3)); packedFlags >>= 2; paint.setFlags(packedFlags); CHECK_SET_SCALAR(TextSize); CHECK_SET_SCALAR(TextScaleX); CHECK_SET_SCALAR(TextSkewX); CHECK_SET_SCALAR(StrokeWidth); CHECK_SET_SCALAR(StrokeMiter); if (nondef & kColor_NonDef) { paint.setColor(reader.read32()); } CHECK_SET_FLATTENABLE(Typeface); CHECK_SET_FLATTENABLE(PathEffect); CHECK_SET_FLATTENABLE(Shader); CHECK_SET_FLATTENABLE(MaskFilter); CHECK_SET_FLATTENABLE(ColorFilter); CHECK_SET_FLATTENABLE(ImageFilter); CHECK_SET_FLATTENABLE(DrawLooper); return paint; } class SkPipeReader : public SkReadBuffer { public: SkPipeReader(SkPipeDeserializer* sink, const void* data, size_t size) : SkReadBuffer(data, size) , fSink(sink) {} SkPipeDeserializer* fSink; SkFlattenable::Factory findFactory(const char name[]) { SkFlattenable::Factory factory; // Check if a custom Factory has been specified for this flattenable. if (!(factory = this->getCustomFactory(SkString(name)))) { // If there is no custom Factory, check for a default. factory = SkFlattenable::NameToFactory(name); } return factory; } bool readPaint(SkPaint* paint) override { *paint = read_paint(*this); return this->isValid(); } }; /////////////////////////////////////////////////////////////////////////////////////////////////// typedef void (*SkPipeHandler)(SkPipeReader&, uint32_t packedVerb, SkCanvas*); static void save_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kSave == unpack_verb(packedVerb)); canvas->save(); } static void saveLayer_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kSaveLayer == unpack_verb(packedVerb)); unsigned extra = unpack_verb_extra(packedVerb); const SkRect* bounds = (extra & kHasBounds_SaveLayerMask) ? reader.skipT() : nullptr; SkPaint paintStorage, *paint = nullptr; if (extra & kHasPaint_SaveLayerMask) { paintStorage = read_paint(reader); paint = &paintStorage; } sk_sp backdrop; if (extra & kHasBackdrop_SaveLayerMask) { backdrop = reader.readImageFilter(); } sk_sp clipMask; if (extra & kHasClipMask_SaveLayerMask) { clipMask = reader.readImage(); } SkMatrix clipMatrix; if (extra & kHasClipMatrix_SaveLayerMask) { reader.readMatrix(&clipMatrix); } SkCanvas::SaveLayerFlags flags = (SkCanvas::SaveLayerFlags)(extra & kFlags_SaveLayerMask); // unremap this wacky flag if (extra & kDontClipToLayer_SaveLayerMask) { flags |= SkCanvasPriv::kDontClipToLayer_SaveLayerFlag; } canvas->saveLayer(SkCanvas::SaveLayerRec(bounds, paint, backdrop.get(), clipMask.get(), (extra & kHasClipMatrix_SaveLayerMask) ? &clipMatrix : nullptr, flags)); } static void restore_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kRestore == unpack_verb(packedVerb)); canvas->restore(); } static void concat_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kConcat == unpack_verb(packedVerb)); SkMatrix::TypeMask tm = (SkMatrix::TypeMask)(packedVerb & kTypeMask_ConcatMask); const SkMatrix matrix = read_sparse_matrix(reader, tm); if (packedVerb & kSetMatrix_ConcatMask) { canvas->setMatrix(matrix); } else { canvas->concat(matrix); } } static void clipRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kClipRect == unpack_verb(packedVerb)); SkClipOp op = (SkClipOp)(unpack_verb_extra(packedVerb) >> 1); bool isAA = unpack_verb_extra(packedVerb) & 1; canvas->clipRect(*reader.skipT(), op, isAA); } static void clipRRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kClipRRect == unpack_verb(packedVerb)); SkClipOp op = (SkClipOp)(unpack_verb_extra(packedVerb) >> 1); bool isAA = unpack_verb_extra(packedVerb) & 1; canvas->clipRRect(read_rrect(reader), op, isAA); } static void clipPath_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kClipPath == unpack_verb(packedVerb)); SkClipOp op = (SkClipOp)(unpack_verb_extra(packedVerb) >> 1); bool isAA = unpack_verb_extra(packedVerb) & 1; SkPath path; reader.readPath(&path); canvas->clipPath(path, op, isAA); } static void clipRegion_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kClipRegion == unpack_verb(packedVerb)); SkClipOp op = (SkClipOp)(unpack_verb_extra(packedVerb) >> 1); SkRegion region; reader.readRegion(®ion); canvas->clipRegion(region, op); } static void drawArc_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawArc == unpack_verb(packedVerb)); const bool useCenter = (bool)(unpack_verb_extra(packedVerb) & 1); const SkScalar* scalars = reader.skipT(6); // bounds[0..3], start[4], sweep[5] const SkRect* bounds = (const SkRect*)scalars; canvas->drawArc(*bounds, scalars[4], scalars[5], useCenter, read_paint(reader)); } static void drawAtlas_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawAtlas == unpack_verb(packedVerb)); SkBlendMode mode = (SkBlendMode)(packedVerb & kMode_DrawAtlasMask); sk_sp image(reader.readImage()); int count = reader.read32(); const SkRSXform* xform = reader.skipT(count); const SkRect* rect = reader.skipT(count); const SkColor* color = nullptr; if (packedVerb & kHasColors_DrawAtlasMask) { color = reader.skipT(count); } const SkRect* cull = nullptr; if (packedVerb & kHasCull_DrawAtlasMask) { cull = reader.skipT(); } SkPaint paintStorage, *paint = nullptr; if (packedVerb & kHasPaint_DrawAtlasMask) { paintStorage = read_paint(reader); paint = &paintStorage; } canvas->drawAtlas(image, xform, rect, color, count, mode, cull, paint); } static void drawDRRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawDRRect == unpack_verb(packedVerb)); const SkRRect outer = read_rrect(reader); const SkRRect inner = read_rrect(reader); canvas->drawDRRect(outer, inner, read_paint(reader)); } static void drawText_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawText == unpack_verb(packedVerb)); uint32_t len = unpack_verb_extra(packedVerb); if (0 == len) { len = reader.read32(); } const void* text = reader.skip(SkAlign4(len)); SkScalar x = reader.readScalar(); SkScalar y = reader.readScalar(); canvas->drawText(text, len, x, y, read_paint(reader)); } static void drawPosText_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawPosText == unpack_verb(packedVerb)); uint32_t len = unpack_verb_extra(packedVerb); if (0 == len) { len = reader.read32(); } const void* text = reader.skip(SkAlign4(len)); int count = reader.read32(); const SkPoint* pos = reader.skipT(count); SkPaint paint = read_paint(reader); SkASSERT(paint.countText(text, len) == count); canvas->drawPosText(text, len, pos, paint); } static void drawPosTextH_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawPosTextH == unpack_verb(packedVerb)); uint32_t len = unpack_verb_extra(packedVerb); if (0 == len) { len = reader.read32(); } const void* text = reader.skip(SkAlign4(len)); int count = reader.read32(); const SkScalar* xpos = reader.skipT(count); SkScalar constY = reader.readScalar(); SkPaint paint = read_paint(reader); SkASSERT(paint.countText(text, len) == count); canvas->drawPosTextH(text, len, xpos, constY, paint); } static void drawTextOnPath_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawTextOnPath == unpack_verb(packedVerb)); uint32_t byteLength = packedVerb & kTextLength_DrawTextOnPathMask; SkMatrix::TypeMask tm = (SkMatrix::TypeMask) ((packedVerb & kMatrixType_DrawTextOnPathMask) >> kMatrixType_DrawTextOnPathShift); if (0 == byteLength) { byteLength = reader.read32(); } const void* text = reader.skip(SkAlign4(byteLength)); SkPath path; reader.readPath(&path); const SkMatrix* matrix = nullptr; SkMatrix matrixStorage; if (tm != SkMatrix::kIdentity_Mask) { matrixStorage = read_sparse_matrix(reader, tm); matrix = &matrixStorage; } canvas->drawTextOnPath(text, byteLength, path, matrix, read_paint(reader)); } static void drawTextBlob_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { sk_sp tb = SkTextBlob::MakeFromBuffer(reader); SkScalar x = reader.readScalar(); SkScalar y = reader.readScalar(); canvas->drawTextBlob(tb, x, y, read_paint(reader)); } static void drawTextRSXform_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawTextRSXform == unpack_verb(packedVerb)); uint32_t len = unpack_verb_extra(packedVerb) >> 1; if (0 == len) { len = reader.read32(); } const void* text = reader.skip(SkAlign4(len)); int count = reader.read32(); const SkRSXform* xform = reader.skipT(count); const SkRect* cull = (packedVerb & 1) ? reader.skipT() : nullptr; SkPaint paint = read_paint(reader); SkASSERT(paint.countText(text, len) == count); canvas->drawTextRSXform(text, len, xform, cull, paint); } static void drawPatch_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawPatch == unpack_verb(packedVerb)); const SkColor* colors = nullptr; const SkPoint* tex = nullptr; const SkPoint* cubics = reader.skipT(12); if (packedVerb & kHasColors_DrawPatchExtraMask) { colors = reader.skipT(4); } if (packedVerb & kHasTexture_DrawPatchExtraMask) { tex = reader.skipT(4); } SkBlendMode mode = (SkBlendMode)(packedVerb & kModeEnum_DrawPatchExtraMask); canvas->drawPatch(cubics, colors, tex, mode, read_paint(reader)); } static void drawPaint_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawPaint == unpack_verb(packedVerb)); canvas->drawPaint(read_paint(reader)); } static void drawRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawRect == unpack_verb(packedVerb)); const SkRect* rect = reader.skipT(); canvas->drawRect(*rect, read_paint(reader)); } static void drawRegion_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawRegion == unpack_verb(packedVerb)); size_t size = unpack_verb_extra(packedVerb); if (0 == size) { size = reader.read32(); } SkRegion region; region.readFromMemory(reader.skipT(size), size); canvas->drawRegion(region, read_paint(reader)); } static void drawOval_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawOval == unpack_verb(packedVerb)); const SkRect* rect = reader.skipT(); canvas->drawOval(*rect, read_paint(reader)); } static void drawRRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawRRect == unpack_verb(packedVerb)); SkRRect rrect = read_rrect(reader); canvas->drawRRect(rrect, read_paint(reader)); } static void drawPath_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawPath == unpack_verb(packedVerb)); SkPath path; reader.readPath(&path); canvas->drawPath(path, read_paint(reader)); } static void drawShadowRec_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawShadowRec == unpack_verb(packedVerb)); SkPath path; reader.readPath(&path); SkDrawShadowRec rec; reader.readPad32(&rec, sizeof(rec)); canvas->private_draw_shadow_rec(path, rec); } static void drawPoints_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawPoints == unpack_verb(packedVerb)); SkCanvas::PointMode mode = (SkCanvas::PointMode)unpack_verb_extra(packedVerb); int count = reader.read32(); const SkPoint* points = reader.skipT(count); canvas->drawPoints(mode, count, points, read_paint(reader)); } static void drawImage_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawImage == unpack_verb(packedVerb)); sk_sp image(reader.readImage()); SkScalar x = reader.readScalar(); SkScalar y = reader.readScalar(); SkPaint paintStorage, *paint = nullptr; if (packedVerb & kHasPaint_DrawImageMask) { paintStorage = read_paint(reader); paint = &paintStorage; } canvas->drawImage(image, x, y, paint); } static void drawImageRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawImageRect == unpack_verb(packedVerb)); sk_sp image(reader.readImage()); SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)(packedVerb & kConstraint_DrawImageRectMask); const SkRect* src = (packedVerb & kHasSrcRect_DrawImageRectMask) ? reader.skipT() : nullptr; const SkRect* dst = reader.skipT(); SkPaint paintStorage, *paint = nullptr; if (packedVerb & kHasPaint_DrawImageRectMask) { paintStorage = read_paint(reader); paint = &paintStorage; } if (src) { canvas->drawImageRect(image, *src, *dst, paint, constraint); } else { canvas->drawImageRect(image, *dst, paint); } } static void drawImageNine_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawImageNine == unpack_verb(packedVerb)); sk_sp image(reader.readImage()); const SkIRect* center = reader.skipT(); const SkRect* dst = reader.skipT(); SkPaint paintStorage, *paint = nullptr; if (packedVerb & kHasPaint_DrawImageNineMask) { paintStorage = read_paint(reader); paint = &paintStorage; } canvas->drawImageNine(image, *center, *dst, paint); } static void drawImageLattice_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawImageLattice == unpack_verb(packedVerb)); sk_sp image(reader.readImage()); SkCanvas::Lattice lattice; if (!SkCanvasPriv::ReadLattice(reader, &lattice)) { return; } const SkRect* dst = reader.skipT(); SkPaint paintStorage, *paint = nullptr; if (packedVerb & kHasPaint_DrawImageLatticeMask) { paintStorage = read_paint(reader); paint = &paintStorage; } canvas->drawImageLattice(image.get(), lattice, *dst, paint); } static void drawVertices_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawVertices == unpack_verb(packedVerb)); SkBlendMode bmode = (SkBlendMode)unpack_verb_extra(packedVerb); sk_sp vertices = nullptr; if (sk_sp data = reader.readByteArrayAsData()) { vertices = SkVertices::Decode(data->data(), data->size()); } int boneCount = reader.read32(); const SkMatrix* bones = boneCount ? reader.skipT(boneCount) : nullptr; if (vertices) { canvas->drawVertices(vertices, bones, boneCount, bmode, read_paint(reader)); } } static void drawPicture_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawPicture == unpack_verb(packedVerb)); unsigned extra = unpack_verb_extra(packedVerb); int index = extra & kIndex_ObjectDefinitionMask; SkPicture* pic = reader.getInflator()->getPicture(index); SkMatrix matrixStorage, *matrix = nullptr; SkPaint paintStorage, *paint = nullptr; if (extra & kHasMatrix_DrawPictureExtra) { reader.readMatrix(&matrixStorage); matrix = &matrixStorage; } if (extra & kHasPaint_DrawPictureExtra) { paintStorage = read_paint(reader); paint = &paintStorage; } canvas->drawPicture(pic, matrix, paint); } static void drawAnnotation_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDrawAnnotation == unpack_verb(packedVerb)); const SkRect* rect = reader.skipT(); // len includes the key's trailing 0 uint32_t len = unpack_verb_extra(packedVerb) >> 1; if (0 == len) { len = reader.read32(); } const char* key = reader.skipT(len); sk_sp data; if (packedVerb & 1) { uint32_t size = reader.read32(); data = SkData::MakeWithCopy(reader.skip(SkAlign4(size)), size); } canvas->drawAnnotation(*rect, key, data); } #if 0 stream.write("skiacodc", 8); stream.write32(pmap.width()); stream.write32(pmap.height()); stream.write16(pmap.colorType()); stream.write16(pmap.alphaType()); stream.write32(0); // no colorspace for now for (int y = 0; y < pmap.height(); ++y) { stream.write(pmap.addr8(0, y), pmap.width()); } #endif sk_sp SkPipeInflator::makeImage(const sk_sp& data) { if (fProcs.fImageProc) { return fProcs.fImageProc(data->data(), data->size(), fProcs.fImageCtx); } return SkImage::MakeFromEncoded(data); } static void defineImage_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas*) { SkASSERT(SkPipeVerb::kDefineImage == unpack_verb(packedVerb)); SkPipeInflator* inflator = (SkPipeInflator*)reader.getInflator(); uint32_t extra = unpack_verb_extra(packedVerb); int index = extra & kIndex_ObjectDefinitionMask; if (extra & kUndef_ObjectDefinitionMask) { // zero-index means we are "forgetting" that cache entry inflator->setImage(index, nullptr); } else { // we are defining a new image sk_sp data = reader.readByteArrayAsData(); sk_sp image = data ? inflator->makeImage(data) : nullptr; if (!image) { SkDebugf("-- failed to decode\n"); } inflator->setImage(index, std::move(image)); } } sk_sp SkPipeInflator::makeTypeface(const void* data, size_t size) { if (fProcs.fTypefaceProc) { return fProcs.fTypefaceProc(data, size, fProcs.fTypefaceCtx); } SkMemoryStream stream(data, size, false); return SkTypeface::MakeDeserialize(&stream); } static void defineTypeface_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDefineTypeface == unpack_verb(packedVerb)); SkPipeInflator* inflator = (SkPipeInflator*)reader.getInflator(); uint32_t extra = unpack_verb_extra(packedVerb); int index = extra & kIndex_ObjectDefinitionMask; if (extra & kUndef_ObjectDefinitionMask) { // zero-index means we are "forgetting" that cache entry inflator->setTypeface(index, nullptr); } else { // we are defining a new image sk_sp data = reader.readByteArrayAsData(); // TODO: seems like we could "peek" to see the array, and not need to copy it. sk_sp tf = data ? inflator->makeTypeface(data->data(), data->size()) : nullptr; inflator->setTypeface(index, std::move(tf)); } } static void defineFactory_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDefineFactory == unpack_verb(packedVerb)); SkPipeInflator* inflator = (SkPipeInflator*)reader.getInflator(); uint32_t extra = unpack_verb_extra(packedVerb); int index = extra >> kNameLength_DefineFactoryExtraBits; size_t len = extra & kNameLength_DefineFactoryExtraMask; // +1 for the trailing null char const char* name = (const char*)reader.skip(SkAlign4(len + 1)); SkFlattenable::Factory factory = reader.findFactory(name); if (factory) { inflator->setFactory(index, factory); } } static void definePicture_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SkASSERT(SkPipeVerb::kDefinePicture == unpack_verb(packedVerb)); int deleteIndex = unpack_verb_extra(packedVerb); SkPipeInflator* inflator = (SkPipeInflator*)reader.getInflator(); if (deleteIndex) { inflator->setPicture(deleteIndex - 1, nullptr); } else { SkPictureRecorder recorder; int pictureIndex = -1; // invalid const SkRect* cull = reader.skipT(); if (!cull) { return; } do_playback(reader, recorder.beginRecording(*cull), &pictureIndex); SkASSERT(pictureIndex > 0); sk_sp picture = recorder.finishRecordingAsPicture(); inflator->setPicture(pictureIndex, std::move(picture)); } } static void endPicture_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { SK_ABORT("not reached"); // never call me } /////////////////////////////////////////////////////////////////////////////////////////////////// struct HandlerRec { SkPipeHandler fProc; const char* fName; }; #define HANDLER(name) { name##_handler, #name } const HandlerRec gPipeHandlers[] = { HANDLER(save), HANDLER(saveLayer), HANDLER(restore), HANDLER(concat), HANDLER(clipRect), HANDLER(clipRRect), HANDLER(clipPath), HANDLER(clipRegion), HANDLER(drawArc), HANDLER(drawAtlas), HANDLER(drawDRRect), HANDLER(drawText), HANDLER(drawPosText), HANDLER(drawPosTextH), HANDLER(drawRegion), HANDLER(drawTextOnPath), HANDLER(drawTextBlob), HANDLER(drawTextRSXform), HANDLER(drawPatch), HANDLER(drawPaint), HANDLER(drawPoints), HANDLER(drawRect), HANDLER(drawPath), HANDLER(drawShadowRec), HANDLER(drawOval), HANDLER(drawRRect), HANDLER(drawImage), HANDLER(drawImageRect), HANDLER(drawImageNine), HANDLER(drawImageLattice), HANDLER(drawVertices), HANDLER(drawPicture), HANDLER(drawAnnotation), HANDLER(defineImage), HANDLER(defineTypeface), HANDLER(defineFactory), HANDLER(definePicture), HANDLER(endPicture), // handled special -- should never be called }; #undef HANDLER /////////////////////////////////////////////////////////////////////////////////////////////////// class SkPipeDeserializer::Impl { public: SkRefSet fImages; SkRefSet fPictures; SkRefSet fTypefaces; SkTDArray fFactories; SkDeserialProcs fProcs; }; SkPipeDeserializer::SkPipeDeserializer() : fImpl(new Impl) {} SkPipeDeserializer::~SkPipeDeserializer() {} void SkPipeDeserializer::setDeserialProcs(const SkDeserialProcs& procs) { fImpl->fProcs = procs; } sk_sp SkPipeDeserializer::readImage(const void* data, size_t size) { if (size < sizeof(uint32_t)) { SkDebugf("-------- data length too short for readImage %d\n", size); return nullptr; } const uint32_t* ptr = (const uint32_t*)data; uint32_t packedVerb = *ptr++; size -= 4; if (SkPipeVerb::kDefineImage == unpack_verb(packedVerb)) { SkPipeInflator inflator(&fImpl->fImages, &fImpl->fPictures, &fImpl->fTypefaces, &fImpl->fFactories, fImpl->fProcs); SkPipeReader reader(this, ptr, size); reader.setInflator(&inflator); defineImage_handler(reader, packedVerb, nullptr); packedVerb = reader.read32(); // read the next verb } if (SkPipeVerb::kWriteImage != unpack_verb(packedVerb)) { SkDebugf("-------- unexpected verb for readImage %d\n", unpack_verb(packedVerb)); return nullptr; } int index = unpack_verb_extra(packedVerb); if (0 == index) { return nullptr; // writer failed } return sk_ref_sp(fImpl->fImages.get(index - 1)); } sk_sp SkPipeDeserializer::readPicture(const void* data, size_t size) { if (size < sizeof(uint32_t)) { SkDebugf("-------- data length too short for readPicture %d\n", size); return nullptr; } const uint32_t* ptr = (const uint32_t*)data; uint32_t packedVerb = *ptr++; size -= 4; if (SkPipeVerb::kDefinePicture == unpack_verb(packedVerb)) { SkPipeInflator inflator(&fImpl->fImages, &fImpl->fPictures, &fImpl->fTypefaces, &fImpl->fFactories, fImpl->fProcs); SkPipeReader reader(this, ptr, size); reader.setInflator(&inflator); definePicture_handler(reader, packedVerb, nullptr); packedVerb = reader.read32(); // read the next verb } if (SkPipeVerb::kWritePicture != unpack_verb(packedVerb)) { SkDebugf("-------- unexpected verb for readPicture %d\n", unpack_verb(packedVerb)); return nullptr; } int index = unpack_verb_extra(packedVerb); if (0 == index) { return nullptr; // writer failed } return sk_ref_sp(fImpl->fPictures.get(index - 1)); } static bool do_playback(SkPipeReader& reader, SkCanvas* canvas, int* endPictureIndex) { int indent = 0; const bool showEachVerb = false; int counter = 0; while (!reader.eof()) { uint32_t prevOffset = reader.offset(); uint32_t packedVerb = reader.read32(); SkPipeVerb verb = unpack_verb(packedVerb); if ((unsigned)verb >= SK_ARRAY_COUNT(gPipeHandlers)) { SkDebugf("------- bad verb %d\n", verb); return false; } if (SkPipeVerb::kRestore == verb) { indent -= 1; SkASSERT(indent >= 0); } if (SkPipeVerb::kEndPicture == verb) { if (endPictureIndex) { *endPictureIndex = unpack_verb_extra(packedVerb); } return true; } HandlerRec rec = gPipeHandlers[(unsigned)verb]; rec.fProc(reader, packedVerb, canvas); if (showEachVerb) { for (int i = 0; i < indent; ++i) { SkDebugf(" "); } SkDebugf("%d [%d] %s %d\n", prevOffset, counter++, rec.fName, reader.offset() - prevOffset); } if (!reader.isValid()) { SkDebugf("-------- bad reader\n"); return false; } switch (verb) { case SkPipeVerb::kSave: case SkPipeVerb::kSaveLayer: indent += 1; break; default: break; } } return true; } bool SkPipeDeserializer::playback(const void* data, size_t size, SkCanvas* canvas) { SkPipeInflator inflator(&fImpl->fImages, &fImpl->fPictures, &fImpl->fTypefaces, &fImpl->fFactories, fImpl->fProcs); SkPipeReader reader(this, data, size); reader.setInflator(&inflator); return do_playback(reader, canvas); }