• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkMultiPictureDocumentPriv.h"
9 #include "SkMultiPictureDocumentReader.h"
10 #include "SkPicture.h"
11 #include "SkStream.h"
12 #include "SkPictureRecorder.h"
13 #include "SkNWayCanvas.h"
14 
init(SkStreamSeekable * stream)15 bool SkMultiPictureDocumentReader::init(SkStreamSeekable* stream) {
16     if (!stream) {
17         return false;
18     }
19     stream->seek(0);
20     const size_t size = sizeof(SkMultiPictureDocumentProtocol::kMagic) - 1;
21     char buffer[size];
22     if (size != stream->read(buffer, size) ||
23         0 != memcmp(SkMultiPictureDocumentProtocol::kMagic, buffer, size)) {
24         stream = nullptr;
25         return false;
26     }
27     bool good = true;
28     uint32_t versionNumber = stream->readU32();
29     if (versionNumber != SkMultiPictureDocumentProtocol::kVersion) {
30         return false;
31     }
32     uint32_t pageCount = stream->readU32();
33     fSizes.reset(pageCount);
34     for (uint32_t i = 0; i < pageCount; ++i) {
35         SkSize size;
36         good &= sizeof(size) == stream->read(&size, sizeof(size));
37         fSizes[i] = size;
38     }
39     fOffset = stream->getPosition();
40     return good;
41 }
42 
43 namespace {
44 struct PagerCanvas : public SkNWayCanvas {
45     SkPictureRecorder fRecorder;
46     const SkTArray<SkSize>* fSizes;
47     SkTArray<sk_sp<SkPicture>>* fDest;
PagerCanvas__anon4313dda60111::PagerCanvas48     PagerCanvas(SkISize  wh,
49                 const SkTArray<SkSize>* s,
50                 SkTArray<sk_sp<SkPicture>>* d)
51         : SkNWayCanvas(wh.width(), wh.height()), fSizes(s), fDest(d) {
52         this->nextCanvas();
53     }
nextCanvas__anon4313dda60111::PagerCanvas54     void nextCanvas() {
55         int i = fDest->count();
56         if (i < fSizes->count()) {
57             SkRect bounds = SkRect::MakeSize((*fSizes)[i]);
58             this->addCanvas(fRecorder.beginRecording(bounds));
59         }
60     }
onDrawAnnotation__anon4313dda60111::PagerCanvas61     void onDrawAnnotation(const SkRect& r, const char* key, SkData* d) override {
62         if (0 == strcmp(key, SkMultiPictureDocumentProtocol::kEndPage)) {
63             this->removeAll();
64             if (fRecorder.getRecordingCanvas()) {
65                 fDest->emplace_back(fRecorder.finishRecordingAsPicture());
66             }
67             this->nextCanvas();
68         } else {
69             this->SkNWayCanvas::onDrawAnnotation(r, key, d);
70         }
71     }
72 };
73 }  // namespace
74 
readPage(SkStreamSeekable * stream,int pageNumber) const75 sk_sp<SkPicture> SkMultiPictureDocumentReader::readPage(SkStreamSeekable* stream,
76                                                         int pageNumber) const {
77     SkASSERT(pageNumber >= 0);
78     SkASSERT(pageNumber < fSizes.count());
79     if (0 == fPages.count()) {
80         stream->seek(fOffset); // jump to beginning of skp
81         auto picture = SkPicture::MakeFromStream(stream);
82         SkISize size = SkMultiPictureDocumentProtocol::Join(fSizes).toCeil();
83         PagerCanvas canvas(size, &fSizes, &this->fPages);
84         // Must call playback(), not drawPicture() to reach
85         // PagerCanvas::onDrawAnnotation().
86         picture->playback(&canvas);
87         if (fPages.count() != fSizes.count()) {
88             SkDEBUGF(("Malformed SkMultiPictureDocument\n"));
89         }
90     }
91     // Allow for malformed document.
92     return pageNumber < fPages.count() ? fPages[pageNumber] : nullptr;
93 }
94