| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include <vector> | |
| 9 | |
| 10 #include "SkMultiPictureDocument.h" | 8 #include "SkMultiPictureDocument.h" |
| 11 #include "SkMultiPictureDocumentPriv.h" | 9 #include "SkMultiPictureDocumentPriv.h" |
| 12 #include "SkPicture.h" | 10 #include "SkPicture.h" |
| 13 #include "SkPictureRecorder.h" | 11 #include "SkPictureRecorder.h" |
| 14 #include "SkStream.h" | 12 #include "SkStream.h" |
| 13 #include "SkTArray.h" |
| 15 | 14 |
| 16 /* | 15 /* |
| 17 File format: | 16 File format: |
| 18 BEGINNING_OF_FILE: | 17 BEGINNING_OF_FILE: |
| 19 kMagic | 18 kMagic |
| 20 uint32_t version_number | 19 uint32_t version_number (==2) |
| 21 uint32_t page_count | 20 uint32_t page_count |
| 22 { | 21 { |
| 23 uint64_t offset | |
| 24 float sizeX | 22 float sizeX |
| 25 float sizeY | 23 float sizeY |
| 26 } * page_count | 24 } * page_count |
| 27 FIRST_OFFSET: | |
| 28 skp file | 25 skp file |
| 29 SECOND_OFFSET: | |
| 30 skp file | |
| 31 ... | |
| 32 LAST_OFFSET: | |
| 33 skp file | |
| 34 "\nEndOfMultiPicture\n" | |
| 35 */ | 26 */ |
| 36 | 27 |
| 37 namespace { | 28 namespace { |
| 38 static SkCanvas* trim(SkCanvas* canvas, | 29 static SkCanvas* trim(SkCanvas* canvas, |
| 39 SkScalar w, SkScalar h, | 30 SkScalar w, SkScalar h, |
| 40 const SkRect& trimBox) { | 31 const SkRect& trimBox) { |
| 41 // Only trim if necessary. | 32 // Only trim if necessary. |
| 42 if (trimBox != SkRect::MakeWH(w, h)) { | 33 if (trimBox != SkRect::MakeWH(w, h)) { |
| 43 // All SkDocument implementations implement trimBox using a | 34 // All SkDocument implementations implement trimBox using a |
| 44 // clip+translate. | 35 // clip+translate. |
| 45 canvas->clipRect(trimBox); | 36 canvas->clipRect(trimBox); |
| 46 canvas->translate(trimBox.x(), trimBox.y()); | 37 canvas->translate(trimBox.x(), trimBox.y()); |
| 47 } | 38 } |
| 48 return canvas; | 39 return canvas; |
| 49 } | 40 } |
| 50 | 41 |
| 51 struct NullWStream : public SkWStream { | |
| 52 NullWStream() : fN(0) {} | |
| 53 bool write(const void*, size_t n) override { | |
| 54 fN += n; | |
| 55 return true; | |
| 56 } | |
| 57 size_t bytesWritten() const override { return fN; } | |
| 58 size_t fN; | |
| 59 }; | |
| 60 | |
| 61 struct Page { | |
| 62 Page(SkSize s, sk_sp<SkPicture> c) : fSize(s), fContent(std::move(c)) {} | |
| 63 Page(Page&&) = default; | |
| 64 Page(const Page&) = default; | |
| 65 Page& operator=(const Page&) = default; | |
| 66 Page& operator=(Page&&) = default; | |
| 67 SkSize fSize; | |
| 68 sk_sp<SkPicture> fContent; | |
| 69 }; | |
| 70 | |
| 71 struct MultiPictureDocument final : public SkDocument { | 42 struct MultiPictureDocument final : public SkDocument { |
| 72 SkPictureRecorder fPictureRecorder; | 43 SkPictureRecorder fPictureRecorder; |
| 73 SkSize fCurrentPageSize; | 44 SkSize fCurrentPageSize; |
| 74 std::vector<Page> fPages; | 45 SkTArray<sk_sp<SkPicture>> fPages; |
| 46 SkTArray<SkSize> fSizes; |
| 75 MultiPictureDocument(SkWStream* s, void (*d)(SkWStream*, bool)) | 47 MultiPictureDocument(SkWStream* s, void (*d)(SkWStream*, bool)) |
| 76 : SkDocument(s, d) {} | 48 : SkDocument(s, d) {} |
| 77 ~MultiPictureDocument() { this->close(); } | 49 ~MultiPictureDocument() { this->close(); } |
| 78 | 50 |
| 79 SkCanvas* onBeginPage(SkScalar w, SkScalar h, const SkRect& c) override { | 51 SkCanvas* onBeginPage(SkScalar w, SkScalar h, const SkRect& c) override { |
| 80 fCurrentPageSize.set(w, h); | 52 fCurrentPageSize.set(w, h); |
| 81 return trim(fPictureRecorder.beginRecording(w, h), w, h, c); | 53 return trim(fPictureRecorder.beginRecording(w, h), w, h, c); |
| 82 } | 54 } |
| 83 void onEndPage() override { | 55 void onEndPage() override { |
| 84 fPages.emplace_back(fCurrentPageSize, | 56 fSizes.push_back(fCurrentPageSize); |
| 85 fPictureRecorder.finishRecordingAsPicture()); | 57 fPages.push_back(fPictureRecorder.finishRecordingAsPicture()); |
| 86 } | 58 } |
| 87 bool onClose(SkWStream* wStream) override { | 59 bool onClose(SkWStream* wStream) override { |
| 88 SkASSERT(wStream); | 60 SkASSERT(wStream); |
| 89 SkASSERT(wStream->bytesWritten() == 0); | 61 SkASSERT(wStream->bytesWritten() == 0); |
| 90 bool good = true; | 62 bool good = true; |
| 91 good &= wStream->writeText(SkMultiPictureDocumentProtocol::kMagic); | 63 good &= wStream->writeText(SkMultiPictureDocumentProtocol::kMagic); |
| 92 good &= wStream->write32(SkToU32(1)); // version | 64 good &= wStream->write32(SkMultiPictureDocumentProtocol::kVersion); |
| 93 good &= wStream->write32(SkToU32(fPages.size())); | 65 good &= wStream->write32(SkToU32(fPages.count())); |
| 94 uint64_t offset = wStream->bytesWritten(); | 66 for (SkSize s : fSizes) { |
| 95 offset += fPages.size() * sizeof(SkMultiPictureDocumentProtocol::Entry); | 67 good &= wStream->write(&s, sizeof(s)); |
| 96 for (const auto& page : fPages) { | |
| 97 SkMultiPictureDocumentProtocol::Entry entry{ | |
| 98 offset, page.fSize.width(), page.fSize.height()}; | |
| 99 good &= wStream->write(&entry, sizeof(entry)); | |
| 100 NullWStream buffer; | |
| 101 page.fContent->serialize(&buffer); | |
| 102 offset += buffer.bytesWritten(); | |
| 103 } | 68 } |
| 104 for (const auto& page : fPages) { | 69 SkSize bigsize = SkMultiPictureDocumentProtocol::Join(fSizes); |
| 105 page.fContent->serialize(wStream); | 70 SkCanvas* c = fPictureRecorder.beginRecording(SkRect::MakeSize(bigsize))
; |
| 71 for (const sk_sp<SkPicture>& page : fPages) { |
| 72 c->drawPicture(page); |
| 73 c->drawAnnotation(SkRect::MakeEmpty(), |
| 74 SkMultiPictureDocumentProtocol::kEndPage, |
| 75 nullptr); |
| 106 } | 76 } |
| 107 SkASSERT(wStream->bytesWritten() == offset); | 77 sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture(); |
| 108 good &= wStream->writeText("\nEndOfMultiPicture\n"); | 78 p->serialize(wStream); |
| 109 fPages.clear(); | 79 fPages.reset(); |
| 80 fSizes.reset(); |
| 110 return good; | 81 return good; |
| 111 } | 82 } |
| 112 void onAbort() override { fPages.clear(); } | 83 void onAbort() override { |
| 84 fPages.reset(); |
| 85 fSizes.reset(); |
| 86 } |
| 113 }; | 87 }; |
| 114 } | 88 } |
| 115 | 89 |
| 116 sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream) { | 90 sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream) { |
| 117 return sk_make_sp<MultiPictureDocument>(wStream, nullptr); | 91 return sk_make_sp<MultiPictureDocument>(wStream, nullptr); |
| 118 } | 92 } |
| OLD | NEW |