SkStream: DynamicMemoryWStream gets writeToAndReset

This is similar to copyToAndReset().

Also use this in SkPDF, for minor memory savings:
Single-threaded DM's peak RSS drops from 239MB
to 228MB.

Change-Id: I352a980e6dd54eb05d74cd057bd50e02312753b0
Reviewed-on: https://skia-review.googlesource.com/17714
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
This commit is contained in:
Hal Canary 2017-05-23 11:47:05 -04:00 committed by Skia Commit-Bot
parent 14a6430b7b
commit 6fee59b514
4 changed files with 30 additions and 8 deletions

View File

@ -384,11 +384,14 @@ public:
/** More efficient version of read(dst, 0, bytesWritten()). */
void copyTo(void* dst) const;
void writeToStream(SkWStream* dst) const;
bool writeToStream(SkWStream* dst) const;
/** Equivalent to copyTo() followed by reset(), but may save memory use. */
void copyToAndReset(void* dst);
/** Equivalent to writeToStream() followed by reset(), but may save memory use. */
bool writeToAndReset(SkWStream* dst);
/** Return the contents as SkData, and then reset the stream. */
sk_sp<SkData> detachAsData();

View File

@ -545,10 +545,13 @@ void SkDynamicMemoryWStream::copyTo(void* dst) const {
}
}
void SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const {
bool SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const {
for (Block* block = fHead; block != nullptr; block = block->fNext) {
dst->write(block->start(), block->written());
if (!dst->write(block->start(), block->written())) {
return false;
}
}
return true;
}
void SkDynamicMemoryWStream::padToAlign4() {
@ -584,6 +587,23 @@ void SkDynamicMemoryWStream::copyToAndReset(void* ptr) {
fBytesWrittenBeforeTail = 0;
}
bool SkDynamicMemoryWStream::writeToAndReset(SkWStream* dst) {
// By looping through the source and freeing as we copy, we
// can reduce real memory use with large streams.
bool dstStreamGood = true;
for (Block* block = fHead; block != nullptr; ) {
if (dstStreamGood && !dst->write(block->start(), block->written())) {
dstStreamGood = false;
}
Block* next = block->fNext;
sk_free(block);
block = next;
}
fHead = fTail = nullptr;
fBytesWrittenBeforeTail = 0;
return dstStreamGood;
}
sk_sp<SkData> SkDynamicMemoryWStream::detachAsData() {
const size_t size = this->bytesWritten();
if (0 == size) {

View File

@ -356,8 +356,7 @@ static void emit_image_xobject(SkWStream* stream,
} else {
bitmap_to_pdf_pixels(bitmap, &deflateWStream);
}
deflateWStream.finalize(); // call before detachAsStream().
std::unique_ptr<SkStreamAsset> asset(buffer.detachAsStream());
deflateWStream.finalize(); // call before buffer.bytesWritten().
SkPDFDict pdfDict("XObject");
pdfDict.insertName("Subtype", "Image");
@ -380,11 +379,11 @@ static void emit_image_xobject(SkWStream* stream,
}
pdfDict.insertInt("BitsPerComponent", 8);
pdfDict.insertName("Filter", "FlateDecode");
pdfDict.insertInt("Length", asset->getLength());
pdfDict.insertInt("Length", buffer.bytesWritten());
pdfDict.emitObject(stream, objNumMap);
pdf_stream_begin(stream);
stream->writeStream(asset.get(), asset->getLength());
buffer.writeToAndReset(stream);
pdf_stream_end(stream);
}

View File

@ -489,7 +489,7 @@ void SkPDFSharedStream::emitObject(
SkPDFUnion::Name("FlateDecode").emitObject(stream, objNumMap);
stream->writeText(">>");
stream->writeText(" stream\n");
buffer.writeToStream(stream);
buffer.writeToAndReset(stream);
stream->writeText("\nendstream");
}
#endif