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:
parent
14a6430b7b
commit
6fee59b514
@ -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();
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user