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 |