Index: src/utils/SkMultiPictureDocumentReader.cpp |
diff --git a/src/utils/SkMultiPictureDocumentReader.cpp b/src/utils/SkMultiPictureDocumentReader.cpp |
index 6bc77bfc7624ea66be86c2b56b9998cf27f8dd5d..3924f3eb42cf9c930777eeab84ae39b88b7000de 100644 |
--- a/src/utils/SkMultiPictureDocumentReader.cpp |
+++ b/src/utils/SkMultiPictureDocumentReader.cpp |
@@ -9,6 +9,8 @@ |
#include "SkMultiPictureDocumentReader.h" |
#include "SkPicture.h" |
#include "SkStream.h" |
+#include "SkPictureRecorder.h" |
+#include "SkNWayCanvas.h" |
bool SkMultiPictureDocumentReader::init(SkStreamSeekable* stream) { |
if (!stream) { |
@@ -24,26 +26,68 @@ bool SkMultiPictureDocumentReader::init(SkStreamSeekable* stream) { |
} |
bool good = true; |
uint32_t versionNumber = stream->readU32(); |
- if (versionNumber != 1) { |
+ if (versionNumber != SkMultiPictureDocumentProtocol::kVersion) { |
return false; |
} |
uint32_t pageCount = stream->readU32(); |
fSizes.reset(pageCount); |
- fOffsets.reset(pageCount); |
for (uint32_t i = 0; i < pageCount; ++i) { |
- SkMultiPictureDocumentProtocol::Entry entry; |
- good &= sizeof(entry) == stream->read(&entry, sizeof(entry)); |
- fSizes[i] = SkSize::Make(entry.sizeX, entry.sizeY); |
- good &= SkTFitsIn<size_t>(entry.offset); |
- fOffsets[i] = static_cast<size_t>(entry.offset); |
+ SkSize size; |
+ good &= sizeof(size) == stream->read(&size, sizeof(size)); |
+ fSizes[i] = size; |
} |
+ fOffset = stream->getPosition(); |
return good; |
} |
+namespace { |
+struct PagerCanvas : public SkNWayCanvas { |
+ SkPictureRecorder fRecorder; |
+ const SkTArray<SkSize>* fSizes; |
+ SkTArray<sk_sp<SkPicture>>* fDest; |
+ PagerCanvas(SkISize wh, |
+ const SkTArray<SkSize>* s, |
+ SkTArray<sk_sp<SkPicture>>* d) |
+ : SkNWayCanvas(wh.width(), wh.height()), fSizes(s), fDest(d) { |
+ this->nextCanvas(); |
+ } |
+ void nextCanvas() { |
+ int i = fDest->count(); |
+ if (i < fSizes->count()) { |
+ SkRect bounds = SkRect::MakeSize((*fSizes)[i]); |
+ this->addCanvas(fRecorder.beginRecording(bounds)); |
+ } |
+ } |
+ void onDrawAnnotation(const SkRect& r, const char* key, SkData* d) override { |
+ if (0 == strcmp(key, SkMultiPictureDocumentProtocol::kEndPage)) { |
+ this->removeAll(); |
+ if (fRecorder.getRecordingCanvas()) { |
+ fDest->emplace_back(fRecorder.finishRecordingAsPicture()); |
+ } |
+ this->nextCanvas(); |
+ } else { |
+ this->SkNWayCanvas::onDrawAnnotation(r, key, d); |
+ } |
+ } |
+}; |
+} // namespace |
+ |
sk_sp<SkPicture> SkMultiPictureDocumentReader::readPage(SkStreamSeekable* stream, |
int pageNumber) const { |
SkASSERT(pageNumber >= 0); |
- SkASSERT(pageNumber < fOffsets.count()); |
- SkAssertResult(stream->seek(fOffsets[pageNumber])); |
- return SkPicture::MakeFromStream(stream); |
+ SkASSERT(pageNumber < fSizes.count()); |
+ if (0 == fPages.count()) { |
+ stream->seek(fOffset); // jump to beginning of skp |
+ auto picture = SkPicture::MakeFromStream(stream); |
+ SkISize size = SkMultiPictureDocumentProtocol::Join(fSizes).toCeil(); |
+ PagerCanvas canvas(size, &fSizes, &this->fPages); |
+ // Must call playback(), not drawPicture() to reach |
+ // PagerCanvas::onDrawAnnotation(). |
+ picture->playback(&canvas); |
+ if (fPages.count() != fSizes.count()) { |
+ SkDEBUGF(("Malformed SkMultiPictureDocument\n")); |
+ } |
+ } |
+ // Allow for malformed document. |
+ return pageNumber < fPages.count() ? fPages[pageNumber] : nullptr; |
} |