aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/SkPicture.cpp17
-rw-r--r--src/core/SkPictureData.cpp101
-rw-r--r--src/core/SkPictureData.h12
3 files changed, 87 insertions, 43 deletions
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index 02d495e4c6..26ec76184e 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -139,11 +139,18 @@ SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* d
}
SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) {
+ return CreateFromStream(stream, proc, nullptr);
+}
+
+SkPicture* SkPicture::CreateFromStream(SkStream* stream,
+ InstallPixelRefProc proc,
+ SkTypefacePlayback* typefaces) {
SkPictInfo info;
if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
return nullptr;
}
- SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromStream(stream, info, proc));
+ SkAutoTDelete<SkPictureData> data(
+ SkPictureData::CreateFromStream(stream, info, proc, typefaces));
return Forwardport(info, data);
}
@@ -166,13 +173,19 @@ SkPictureData* SkPicture::backport() const {
}
void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const {
+ this->serialize(stream, pixelSerializer, nullptr);
+}
+
+void SkPicture::serialize(SkWStream* stream,
+ SkPixelSerializer* pixelSerializer,
+ SkRefCntSet* typefaceSet) const {
SkPictInfo info = this->createHeader();
SkAutoTDelete<SkPictureData> data(this->backport());
stream->write(&info, sizeof(info));
if (data) {
stream->writeBool(true);
- data->serialize(stream, pixelSerializer);
+ data->serialize(stream, pixelSerializer, typefaceSet);
} else {
stream->writeBool(false);
}
diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp
index 4f3ac37066..6ae03a3f2e 100644
--- a/src/core/SkPictureData.cpp
+++ b/src/core/SkPictureData.cpp
@@ -68,7 +68,7 @@ SkPictureData::SkPictureData(const SkPictureRecord& record,
fTextBlobRefs[i] = SkRef(blobs[i]);
}
}
-
+
const SkTDArray<const SkImage*>& imgs = record.getImageRefs();
fImageCount = imgs.count();
if (fImageCount > 0) {
@@ -102,12 +102,12 @@ SkPictureData::~SkPictureData() {
fTextBlobRefs[i]->unref();
}
SkDELETE_ARRAY(fTextBlobRefs);
-
+
for (int i = 0; i < fImageCount; i++) {
fImageRefs[i]->unref();
}
SkDELETE_ARRAY(fImageRefs);
-
+
SkDELETE(fFactoryPlayback);
}
@@ -233,7 +233,7 @@ void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
fTextBlobRefs[i]->flatten(buffer);
}
}
-
+
if (fImageCount > 0) {
write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImageCount);
for (i = 0; i < fImageCount; ++i) {
@@ -243,38 +243,54 @@ void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
}
void SkPictureData::serialize(SkWStream* stream,
- SkPixelSerializer* pixelSerializer) const {
+ SkPixelSerializer* pixelSerializer,
+ SkRefCntSet* topLevelTypeFaceSet) const {
+ // This can happen at pretty much any time, so might as well do it first.
write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
stream->write(fOpData->bytes(), fOpData->size());
- if (fPictureCount > 0) {
- write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
- for (int i = 0; i < fPictureCount; i++) {
- fPictureRefs[i]->serialize(stream, pixelSerializer);
- }
- }
-
- // Write some of our data into a writebuffer, and then serialize that
- // into our stream
- {
- SkRefCntSet typefaceSet;
- SkFactorySet factSet;
+ // We serialize all typefaces into the typeface section of the top-level picture.
+ SkRefCntSet localTypefaceSet;
+ SkRefCntSet* typefaceSet = topLevelTypeFaceSet ? topLevelTypeFaceSet : &localTypefaceSet;
+
+ // We delay serializing the bulk of our data until after we've serialized
+ // factories and typefaces by first serializing to an in-memory write buffer.
+ SkFactorySet factSet; // buffer refs factSet, so factSet must come first.
+ SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
+ buffer.setFactoryRecorder(&factSet);
+ buffer.setPixelSerializer(pixelSerializer);
+ buffer.setTypefaceRecorder(typefaceSet);
+ this->flattenToBuffer(buffer);
- SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
- buffer.setTypefaceRecorder(&typefaceSet);
- buffer.setFactoryRecorder(&factSet);
- buffer.setPixelSerializer(pixelSerializer);
+ // Dummy serialize our sub-pictures for the side effect of filling
+ // typefaceSet with typefaces from sub-pictures.
+ struct DevNull: public SkWStream {
+ DevNull() : fBytesWritten(0) {}
+ size_t fBytesWritten;
+ bool write(const void*, size_t size) override { fBytesWritten += size; return true; }
+ size_t bytesWritten() const override { return fBytesWritten; }
+ } devnull;
+ for (int i = 0; i < fPictureCount; i++) {
+ fPictureRefs[i]->serialize(&devnull, pixelSerializer, typefaceSet);
+ }
- this->flattenToBuffer(buffer);
+ // We need to write factories before we write the buffer.
+ // We need to write typefaces before we write the buffer or any sub-picture.
+ WriteFactories(stream, factSet);
+ if (typefaceSet == &localTypefaceSet) {
+ WriteTypefaces(stream, *typefaceSet);
+ }
- // We have to write these two sets into the stream *before* we write
- // the buffer, since parsing that buffer will require that we already
- // have these sets available to use.
- WriteFactories(stream, factSet);
- WriteTypefaces(stream, typefaceSet);
+ // Write the buffer.
+ write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
+ buffer.writeToStream(stream);
- write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
- buffer.writeToStream(stream);
+ // Write sub-pictures by calling serialize again.
+ if (fPictureCount > 0) {
+ write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
+ for (int i = 0; i < fPictureCount; i++) {
+ fPictureRefs[i]->serialize(stream, pixelSerializer, typefaceSet);
+ }
}
stream->write32(SK_PICT_EOF_TAG);
@@ -324,7 +340,8 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
bool SkPictureData::parseStreamTag(SkStream* stream,
uint32_t tag,
uint32_t size,
- SkPicture::InstallPixelRefProc proc) {
+ SkPicture::InstallPixelRefProc proc,
+ SkTypefacePlayback* topLevelTFPlayback) {
/*
* By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
* its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
@@ -376,7 +393,7 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
fPictureCount = 0;
fPictureRefs = SkNEW_ARRAY(const SkPicture*, size);
for (uint32_t i = 0; i < size; i++) {
- fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc);
+ fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc, topLevelTFPlayback);
if (!fPictureRefs[i]) {
return false;
}
@@ -395,9 +412,16 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
buffer.setVersion(fInfo.fVersion);
fFactoryPlayback->setupBuffer(buffer);
- fTFPlayback.setupBuffer(buffer);
buffer.setBitmapDecoder(proc);
+ if (fTFPlayback.count() > 0) {
+ // .skp files <= v43 have typefaces serialized with each sub picture.
+ fTFPlayback.setupBuffer(buffer);
+ } else {
+ // Newer .skp files serialize all typefaces with the top picture.
+ topLevelTFPlayback->setupBuffer(buffer);
+ }
+
while (!buffer.eof() && buffer.isValid()) {
tag = buffer.readUInt();
size = buffer.readUInt();
@@ -539,10 +563,14 @@ bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t
SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
const SkPictInfo& info,
- SkPicture::InstallPixelRefProc proc) {
+ SkPicture::InstallPixelRefProc proc,
+ SkTypefacePlayback* topLevelTFPlayback) {
SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
+ if (!topLevelTFPlayback) {
+ topLevelTFPlayback = &data->fTFPlayback;
+ }
- if (!data->parseStream(stream, proc)) {
+ if (!data->parseStream(stream, proc, topLevelTFPlayback)) {
return NULL;
}
return data.detach();
@@ -560,7 +588,8 @@ SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
}
bool SkPictureData::parseStream(SkStream* stream,
- SkPicture::InstallPixelRefProc proc) {
+ SkPicture::InstallPixelRefProc proc,
+ SkTypefacePlayback* topLevelTFPlayback) {
for (;;) {
uint32_t tag = stream->readU32();
if (SK_PICT_EOF_TAG == tag) {
@@ -568,7 +597,7 @@ bool SkPictureData::parseStream(SkStream* stream,
}
uint32_t size = stream->readU32();
- if (!this->parseStreamTag(stream, tag, size, proc)) {
+ if (!this->parseStreamTag(stream, tag, size, proc, topLevelTFPlayback)) {
return false; // we're invalid
}
}
diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h
index 1a490ce6e4..a68a8c8317 100644
--- a/src/core/SkPictureData.h
+++ b/src/core/SkPictureData.h
@@ -62,12 +62,13 @@ public:
// Does not affect ownership of SkStream.
static SkPictureData* CreateFromStream(SkStream*,
const SkPictInfo&,
- SkPicture::InstallPixelRefProc);
+ SkPicture::InstallPixelRefProc,
+ SkTypefacePlayback*);
static SkPictureData* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&);
virtual ~SkPictureData();
- void serialize(SkWStream*, SkPixelSerializer*) const;
+ void serialize(SkWStream*, SkPixelSerializer*, SkRefCntSet*) const;
void flatten(SkWriteBuffer&) const;
bool containsBitmaps() const;
@@ -82,7 +83,7 @@ protected:
explicit SkPictureData(const SkPictInfo& info);
// Does not affect ownership of SkStream.
- bool parseStream(SkStream*, SkPicture::InstallPixelRefProc);
+ bool parseStream(SkStream*, SkPicture::InstallPixelRefProc, SkTypefacePlayback*);
bool parseBuffer(SkReadBuffer& buffer);
public:
@@ -95,7 +96,7 @@ public:
const int index = reader->readInt();
return fImageRefs[index];
}
-
+
const SkPath& getPath(SkReader32* reader) const {
int index = reader->readInt() - 1;
return fPaths[index];
@@ -144,7 +145,8 @@ private:
// these help us with reading/writing
// Does not affect ownership of SkStream.
- bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size, SkPicture::InstallPixelRefProc);
+ bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size,
+ SkPicture::InstallPixelRefProc, SkTypefacePlayback*);
bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size);
void flattenToBuffer(SkWriteBuffer&) const;