/*
* 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<SkImage>* images, SkRefSet<SkPicture>* pictures,
SkRefSet<SkTypeface>* typefaces, SkTDArray<SkFlattenable::Factory>* 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, 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 setDeserialProcs(const SkDeserialProcs& procs) {
fProcs = procs;
}
sk_sp<SkTypeface> makeTypeface(const void* data, size_t size);
sk_sp<SkImage> makeImage(const sk_sp<SkData>&);
private:
SkRefSet<SkImage>* fImages;
SkRefSet<SkPicture>* fPictures;
SkRefSet<SkTypeface>* fTypefaces;
SkTDArray<SkFlattenable::Factory>* 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<SkScalar>(9));
} else if (tm & SkMatrix::kAffine_Mask) {
const SkScalar* tmp = reader.skipT<SkScalar>(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<SkScalar>(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<SkScalar>(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<SkRect>() : 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();
}
sk_sp<SkImage> 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 |= (1 << 31);//SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag;
}
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<SkRect>(), 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<SkScalar>(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<SkImage> image(reader.readImage());
int count = reader.read32();
const SkRSXform* xform = reader.skipT<SkRSXform>(count);
const SkRect* rect = reader.skipT<SkRect>(count);
const SkColor* color = nullptr;
if (packedVerb & kHasColors_DrawAtlasMask) {
color = reader.skipT<SkColor>(count);
}
const SkRect* cull = nullptr;
if (packedVerb & kHasCull_DrawAtlasMask) {
cull = reader.skipT<SkRect>();
}
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<SkPoint>(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<SkScalar>(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 = reader.skipT<SkRSXform>(count);
const SkRect* cull = (packedVerb & 1) ? reader.skipT<SkRect>() : 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<SkPoint>(12);
if (packedVerb & kHasColors_DrawPatchExtraMask) {
colors = reader.skipT<SkColor>(4);
}
if (packedVerb & kHasTexture_DrawPatchExtraMask) {
tex = reader.skipT<SkPoint>(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<SkRect>();
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<char>(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<SkRect>();
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<SkPoint>(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) ?
reader.skipT<SkRect>() : nullptr;
const SkRect* dst = reader.skipT<SkRect>();
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 = reader.skipT<SkIRect>();
const SkRect* dst = reader.skipT<SkRect>();
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;
if (!SkCanvasPriv::ReadLattice(reader, &lattice)) {
return;
}
const SkRect* dst = reader.skipT<SkRect>();
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<SkData> data = reader.readByteArrayAsData();
canvas->drawVertices(SkVertices::Decode(data->data(), data->size()), 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<SkRect>();
// 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<char>(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
sk_sp<SkImage> SkPipeInflator::makeImage(const sk_sp<SkData>& 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<SkData> data = reader.readByteArrayAsData();
sk_sp<SkImage> image = inflator->makeImage(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 (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<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 = reader.skipT<SkRect>();
if (!cull) {
return;
}
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_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<SkImage> fImages;
SkRefSet<SkPicture> fPictures;
SkRefSet<SkTypeface> fTypefaces;
SkTDArray<SkFlattenable::Factory> fFactories;
SkDeserialProcs fProcs;
};
SkPipeDeserializer::SkPipeDeserializer() : fImpl(new Impl) {}
SkPipeDeserializer::~SkPipeDeserializer() {}
void SkPipeDeserializer::setDeserialProcs(const SkDeserialProcs& procs) {
fImpl->fProcs = procs;
}
sk_sp<SkImage> 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<SkPicture> 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);
}