diff options
-rw-r--r-- | include/core/SkStream.h | 5 | ||||
-rw-r--r-- | src/core/SkStream.cpp | 24 | ||||
-rw-r--r-- | src/pdf/SkPDFBitmap.cpp | 7 | ||||
-rw-r--r-- | src/pdf/SkPDFTypes.cpp | 2 |
4 files changed, 30 insertions, 8 deletions
diff --git a/include/core/SkStream.h b/include/core/SkStream.h index b4875adda6..01fd82a530 100644 --- a/include/core/SkStream.h +++ b/include/core/SkStream.h @@ -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(); diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp index ef86bc963e..7bb2079f7f 100644 --- a/src/core/SkStream.cpp +++ b/src/core/SkStream.cpp @@ -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) { diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp index b58aaf48a5..d5eb19e552 100644 --- a/src/pdf/SkPDFBitmap.cpp +++ b/src/pdf/SkPDFBitmap.cpp @@ -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); } diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp index c66c80a6bc..2559f93106 100644 --- a/src/pdf/SkPDFTypes.cpp +++ b/src/pdf/SkPDFTypes.cpp @@ -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 |