diff options
author | reed <reed@google.com> | 2016-09-13 08:09:45 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-09-13 08:09:45 -0700 |
commit | 54dc4878b02765efea39e68b218df1e4bfff4b88 (patch) | |
tree | 296347d73c08b8b1d0a0b244ca062434ac48caa1 /src/pipe/SkPipeReader.cpp | |
parent | 5f1d0f61ea182829826d9d76cb85346d3e23305d (diff) |
add pipecanvas
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2201323003
Review-Url: https://codereview.chromium.org/2201323003
Diffstat (limited to 'src/pipe/SkPipeReader.cpp')
-rw-r--r-- | src/pipe/SkPipeReader.cpp | 944 |
1 files changed, 944 insertions, 0 deletions
diff --git a/src/pipe/SkPipeReader.cpp b/src/pipe/SkPipeReader.cpp new file mode 100644 index 0000000000..d4375486d0 --- /dev/null +++ b/src/pipe/SkPipeReader.cpp @@ -0,0 +1,944 @@ +/* + * 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 "SkDeduper.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" + +class SkPipeReader; + +static bool do_playback(SkPipeReader& reader, SkCanvas* canvas, int* endPictureIndex = nullptr); + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +class SkPipeInflator : public SkInflator { +public: + SkPipeInflator(SkRefSet<SkImage>* images, SkRefSet<SkPicture>* pictures, + SkRefSet<SkTypeface>* typefaces, SkTDArray<SkFlattenable::Factory>* factories, + SkTypefaceDeserializer* tfd) + : fImages(images) + , fPictures(pictures) + , fTypefaces(typefaces) + , fFactories(factories) + , fTFDeserializer(tfd) + {} + + 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, SkImage* img) { + return fImages->set(index - 1, img); + } + bool setPicture(int index, SkPicture* pic) { + return fPictures->set(index - 1, pic); + } + bool setTypeface(int index, SkTypeface* face) { + return fTypefaces->set(index - 1, 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 setTypefaceDeserializer(SkTypefaceDeserializer* tfd) { + fTFDeserializer = tfd; + } + + sk_sp<SkTypeface> makeTypeface(const void* data, size_t size); + +private: + SkRefSet<SkImage>* fImages; + SkRefSet<SkPicture>* fPictures; + SkRefSet<SkTypeface>* fTypefaces; + SkTDArray<SkFlattenable::Factory>* fFactories; + + SkTypefaceDeserializer* fTFDeserializer; +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +template <typename T> const T* skip(SkReadBuffer& reader, int count = 1) { + return (const T*)reader.skip(count * sizeof(T)); +} + +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(skip<SkScalar>(reader, 9)); + } else if (tm & SkMatrix::kAffine_Mask) { + const SkScalar* tmp = skip<SkScalar>(reader, 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 = skip<SkScalar>(reader, 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 = skip<SkScalar>(reader, 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) { + uint32_t packedFlags = reader.read32(); + uint32_t extra = reader.read32(); + unsigned nondef = extra >> 16; + SkXfermode::Mode mode = (SkXfermode::Mode)((extra >> 8) & 0xFF); + SkASSERT((extra & 0xFF) == 0); + + SkPaint paint; + + 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(Xfermode); + CHECK_SET_FLATTENABLE(MaskFilter); + CHECK_SET_FLATTENABLE(ColorFilter); + CHECK_SET_FLATTENABLE(Rasterizer); + CHECK_SET_FLATTENABLE(ImageFilter); + CHECK_SET_FLATTENABLE(DrawLooper); + + if (!(nondef & kXfermode_NonDef)) { + paint.setXfermodeMode(mode); + } + + 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; + } + + void readPaint(SkPaint* paint) override { + *paint = read_paint(*this); + } +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +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) ? skip<SkRect>(reader) : nullptr; + SkPaint paintStorage, *paint = nullptr; + if (extra & kHasPaint_SaveLayerMask) { + paintStorage = read_paint(reader); + paint = &paintStorage; + } + sk_sp<SkImageFilter> backdrop; + if (extra & kHasBackdrop_SaveLayerMask) { + backdrop = reader.readImageFilter(); + } + SkCanvas::SaveLayerFlags flags = (SkCanvas::SaveLayerFlags)(extra & kFlags_SaveLayerMask); + + // unremap this wacky flag + if (extra & kDontClipToLayer_SaveLayerMask) { + flags |= (1 << 31);//SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag; + } + + canvas->saveLayer(SkCanvas::SaveLayerRec(bounds, paint, backdrop.get(), 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)); + SkRegion::Op op = (SkRegion::Op)(unpack_verb_extra(packedVerb) >> 1); + bool isAA = unpack_verb_extra(packedVerb) & 1; + canvas->clipRect(*skip<SkRect>(reader), op, isAA); +} + +static void clipRRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { + SkASSERT(SkPipeVerb::kClipRRect == unpack_verb(packedVerb)); + SkRegion::Op op = (SkRegion::Op)(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)); + SkRegion::Op op = (SkRegion::Op)(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)); + SkRegion::Op op = (SkRegion::Op)(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 = skip<SkScalar>(reader, 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)); + SkXfermode::Mode mode = (SkXfermode::Mode)(packedVerb & kMode_DrawAtlasMask); + sk_sp<SkImage> image(reader.readImage()); + int count = reader.read32(); + const SkRSXform* xform = skip<SkRSXform>(reader, count); + const SkRect* rect = skip<SkRect>(reader, count); + const SkColor* color = nullptr; + if (packedVerb & kHasColors_DrawAtlasMask) { + color = skip<SkColor>(reader, count); + } + const SkRect* cull = nullptr; + if (packedVerb & kHasCull_DrawAtlasMask) { + cull = skip<SkRect>(reader); + } + 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 = skip<SkPoint>(reader, 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 = skip<SkScalar>(reader, 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<SkTextBlob> 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 = skip<SkRSXform>(reader, count); + const SkRect* cull = (packedVerb & 1) ? skip<SkRect>(reader) : 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 = skip<SkPoint>(reader, 12); + if (packedVerb & kHasColors_DrawPatchExtraMask) { + colors = skip<SkColor>(reader, 4); + } + if (packedVerb & kHasTexture_DrawPatchExtraMask) { + tex = skip<SkPoint>(reader, 4); + } + sk_sp<SkXfermode> xfer; + unsigned mode = packedVerb & kModeEnum_DrawPatchExtraMask; + if (kExplicitXfer_DrawPatchExtraValue == mode) { + xfer = reader.readXfermode(); + } else { + if (mode != SkXfermode::kSrcOver_Mode) { + xfer = SkXfermode::Make((SkXfermode::Mode)mode); + } + } + canvas->drawPatch(cubics, colors, tex, xfer.get(), 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 = skip<SkRect>(reader); + 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(skip<char>(reader, SkAlign4(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 = skip<SkRect>(reader); + 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 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 = skip<SkPoint>(reader, 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<SkImage> 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<SkImage> image(reader.readImage()); + SkCanvas::SrcRectConstraint constraint = + (SkCanvas::SrcRectConstraint)(packedVerb & kConstraint_DrawImageRectMask); + const SkRect* src = (packedVerb & kHasSrcRect_DrawImageRectMask) ? + skip<SkRect>(reader) : nullptr; + const SkRect* dst = skip<SkRect>(reader); + 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<SkImage> image(reader.readImage()); + const SkIRect* center = skip<SkIRect>(reader); + const SkRect* dst = skip<SkRect>(reader); + 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<SkImage> image(reader.readImage()); + + SkCanvas::Lattice lattice; + lattice.fXCount = (packedVerb >> kXCount_DrawImageLatticeShift) & kCount_DrawImageLatticeMask; + if (lattice.fXCount == kCount_DrawImageLatticeMask) { + lattice.fXCount = reader.read32(); + } + lattice.fYCount = (packedVerb >> kXCount_DrawImageLatticeShift) & kCount_DrawImageLatticeMask; + if (lattice.fYCount == kCount_DrawImageLatticeMask) { + lattice.fYCount = reader.read32(); + } + lattice.fXDivs = skip<int32_t>(reader, lattice.fXCount); + lattice.fYDivs = skip<int32_t>(reader, lattice.fYCount); + if (packedVerb & kHasFlags_DrawImageLatticeMask) { + int32_t count = (lattice.fXCount + 1) * (lattice.fYCount + 1); + SkASSERT(count > 0); + lattice.fFlags = skip<SkCanvas::Lattice::Flags>(reader, SkAlign4(count)); + } else { + lattice.fFlags = nullptr; + } + const SkRect* dst = skip<SkRect>(reader); + + 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)); + SkCanvas::VertexMode vmode = (SkCanvas::VertexMode) + ((packedVerb & kVMode_DrawVerticesMask) >> kVMode_DrawVerticesShift); + int vertexCount = packedVerb & kVCount_DrawVerticesMask; + if (0 == vertexCount) { + vertexCount = reader.read32(); + } + sk_sp<SkXfermode> xfer; + unsigned xmode = (packedVerb & kXMode_DrawVerticesMask) >> kXMode_DrawVerticesShift; + if (0xFF == xmode) { + xfer = reader.readXfermode(); + } else { + xfer = SkXfermode::Make((SkXfermode::Mode)xmode); + } + const SkPoint* vertices = skip<SkPoint>(reader, vertexCount); + const SkPoint* texs = nullptr; + if (packedVerb & kHasTex_DrawVerticesMask) { + texs = skip<SkPoint>(reader, vertexCount); + } + const SkColor* colors = nullptr; + if (packedVerb & kHasColors_DrawVerticesMask) { + colors = skip<SkColor>(reader, vertexCount); + } + int indexCount = 0; + const uint16_t* indices = nullptr; + if (packedVerb & kHasIndices_DrawVerticesMask) { + indexCount = reader.read32(); + indices = skip<uint16_t>(reader, indexCount); + } + + canvas->drawVertices(vmode, vertexCount, vertices, texs, colors, xfer.get(), + indices, indexCount, 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 = skip<SkRect>(reader); + + // len includes the key's trailing 0 + uint32_t len = unpack_verb_extra(packedVerb) >> 1; + if (0 == len) { + len = reader.read32(); + } + const char* key = skip<char>(reader, len); + sk_sp<SkData> 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 + +static sk_sp<SkImage> make_from_skiaimageformat(const void* encoded, size_t encodedSize) { + if (encodedSize < 24) { + return nullptr; + } + + SkMemoryStream stream(encoded, encodedSize); + char signature[8]; + stream.read(signature, 8); + if (memcmp(signature, "skiaimgf", 8)) { + return nullptr; + } + + int width = stream.readU32(); + int height = stream.readU32(); + SkColorType ct = (SkColorType)stream.readU16(); + SkAlphaType at = (SkAlphaType)stream.readU16(); + SkASSERT(kAlpha_8_SkColorType == ct); + + SkDEBUGCODE(size_t colorSpaceSize =) stream.readU32(); + SkASSERT(0 == colorSpaceSize); + + SkImageInfo info = SkImageInfo::Make(width, height, ct, at); + size_t size = width * height; + sk_sp<SkData> pixels = SkData::MakeUninitialized(size); + stream.read(pixels->writable_data(), size); + SkASSERT(encodedSize == SkAlign4(stream.getPosition())); + return SkImage::MakeRasterData(info, pixels, width); +} + +static sk_sp<SkImage> make_from_encoded(const sk_sp<SkData>& data) { + sk_sp<SkImage> image = make_from_skiaimageformat(data->data(), data->size()); + if (!image) { + image = SkImage::MakeFromEncoded(data); + } + return image; +} + +static void defineImage_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { + 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<SkData> data = reader.readByteArrayAsData(); + sk_sp<SkImage> image = make_from_encoded(data); + if (!image) { + SkDebugf("-- failed to decode\n"); + } + inflator->setImage(index, image.get()); + } +} + +sk_sp<SkTypeface> SkPipeInflator::makeTypeface(const void* data, size_t size) { + if (fTFDeserializer) { + return fTFDeserializer->deserialize(data, size); + } + 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<SkData> data = reader.readByteArrayAsData(); + // TODO: seems like we could "peek" to see the array, and not need to copy it. + sk_sp<SkTypeface> tf = inflator->makeTypeface(data->data(), data->size()); + inflator->setTypeface(index, tf.get()); + } +} + +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 = skip<SkRect>(reader); + do_playback(reader, recorder.beginRecording(*cull), &pictureIndex); + SkASSERT(pictureIndex > 0); + sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); + inflator->setPicture(pictureIndex, picture.get()); + } +} + +static void endPicture_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) { + sk_throw(); // 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(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<SkImage> fImages; + SkRefSet<SkPicture> fPictures; + SkRefSet<SkTypeface> fTypefaces; + SkTDArray<SkFlattenable::Factory> fFactories; + + SkTypefaceDeserializer* fTFDeserializer = nullptr; +}; + +SkPipeDeserializer::SkPipeDeserializer() : fImpl(new Impl) {} +SkPipeDeserializer::~SkPipeDeserializer() {} + +void SkPipeDeserializer::setTypefaceDeserializer(SkTypefaceDeserializer* tfd) { + fImpl->fTFDeserializer = tfd; +} + +sk_sp<SkPicture> SkPipeDeserializer::readPicture(const void* data, size_t size) { + if (size < sizeof(uint32_t) + sizeof(SkRect)) { + return nullptr; + } + + uint32_t header; + memcpy(&header, data, 4); size -= 4; data = (const char*)data + 4; + if (kDefinePicture_ExtPipeVerb != header) { + return nullptr; + } + SkRect cull; + memcpy(&cull, data, sizeof(SkRect)); + size -= sizeof(SkRect); data = (const char*)data + sizeof(SkRect); + + SkPictureRecorder recorder; + this->playback(data, size, recorder.beginRecording(cull)); + return recorder.finishRecordingAsPicture(); +} + +sk_sp<SkImage> SkPipeDeserializer::readImage(const void* data, size_t size) { + if (size < sizeof(uint32_t)) { + return nullptr; + } + + uint32_t header; + memcpy(&header, data, 4); size -= 4; data = (const char*)data + 4; + if (kDefineImage_ExtPipeVerb != header) { + return nullptr; + } + + SkPipeInflator inflator(&fImpl->fImages, &fImpl->fPictures, + &fImpl->fTypefaces, &fImpl->fFactories, + fImpl->fTFDeserializer); + SkPipeReader reader(this, data, size); + reader.setInflator(&inflator); + return sk_sp<SkImage>(reader.readImage()); +} + +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->fTFDeserializer); + SkPipeReader reader(this, data, size); + reader.setInflator(&inflator); + return do_playback(reader, canvas); +} + |