OLD | NEW |
(Empty) | |
| 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 "SkMultiPictureDocument.h" |
| 9 #include "SkMultiPictureDocumentPriv.h" |
| 10 #include "SkPicture.h" |
| 11 #include "SkPictureRecorder.h" |
| 12 #include "SkStream.h" |
| 13 |
| 14 /* |
| 15 File format: |
| 16 BEGINNING_OF_FILE: |
| 17 kMagic |
| 18 uint32_t version_number |
| 19 uint32_t page_count |
| 20 { |
| 21 uint64_t offset |
| 22 float sizeX |
| 23 float sizeY |
| 24 } * page_count |
| 25 FIRST_OFFSET: |
| 26 skp file |
| 27 SECOND_OFFSET: |
| 28 skp file |
| 29 ... |
| 30 LAST_OFFSET: |
| 31 skp file |
| 32 "\nEndOfMultiPicture\n" |
| 33 */ |
| 34 |
| 35 namespace { |
| 36 static SkCanvas* trim(SkCanvas* canvas, |
| 37 SkScalar w, SkScalar h, |
| 38 const SkRect& trimBox) { |
| 39 // Only trim if necessary. |
| 40 if (trimBox != SkRect::MakeWH(w, h)) { |
| 41 // All SkDocument implementations implement trimBox using a |
| 42 // clip+translate. |
| 43 canvas->clipRect(trimBox); |
| 44 canvas->translate(trimBox.x(), trimBox.y()); |
| 45 } |
| 46 return canvas; |
| 47 } |
| 48 |
| 49 struct NullWStream : public SkWStream { |
| 50 NullWStream() : fN(0) {} |
| 51 bool write(const void*, size_t n) override { |
| 52 fN += n; |
| 53 return true; |
| 54 } |
| 55 size_t bytesWritten() const override { return fN; } |
| 56 size_t fN; |
| 57 }; |
| 58 |
| 59 struct MultiPictureDocument final : public SkDocument { |
| 60 SkPictureRecorder fPictureRecorder; |
| 61 SkTArray<sk_sp<SkPicture>> fPages; |
| 62 MultiPictureDocument(SkWStream* s, void (*d)(SkWStream*, bool)) |
| 63 : SkDocument(s, d) {} |
| 64 ~MultiPictureDocument() { this->close(); } |
| 65 |
| 66 SkCanvas* onBeginPage(SkScalar w, SkScalar h, const SkRect& c) override { |
| 67 return trim(fPictureRecorder.beginRecording(w, h), w, h, c); |
| 68 } |
| 69 void onEndPage() override { |
| 70 fPages.emplace_back(fPictureRecorder.finishRecordingAsPicture()); |
| 71 } |
| 72 bool onClose(SkWStream* wStream) override { |
| 73 SkASSERT(wStream); |
| 74 SkASSERT(wStream->bytesWritten() == 0); |
| 75 bool good = true; |
| 76 good &= wStream->writeText(SkMultiPictureDocumentProtocol::kMagic); |
| 77 good &= wStream->write32(SkToU32(1)); // version |
| 78 good &= wStream->write32(SkToU32(fPages.count())); |
| 79 uint64_t offset = wStream->bytesWritten(); |
| 80 offset += fPages.count() * sizeof(SkMultiPictureDocumentProtocol::Entry)
; |
| 81 for (const auto& page : fPages) { |
| 82 SkRect cullRect = page->cullRect(); |
| 83 // We recorded a picture at the origin. |
| 84 SkASSERT(cullRect.x() == 0 && cullRect.y() == 0); |
| 85 SkMultiPictureDocumentProtocol::Entry entry{ |
| 86 offset, (float)cullRect.right(), (float)cullRect.bottom()}; |
| 87 good &= wStream->write(&entry, sizeof(entry)); |
| 88 NullWStream buffer; |
| 89 page->serialize(&buffer); |
| 90 offset += buffer.bytesWritten(); |
| 91 } |
| 92 for (const auto& page : fPages) { |
| 93 page->serialize(wStream); |
| 94 } |
| 95 SkASSERT(wStream->bytesWritten() == offset); |
| 96 good &= wStream->writeText("\nEndOfMultiPicture\n"); |
| 97 fPages.reset(); |
| 98 return good; |
| 99 } |
| 100 void onAbort() override { fPages.reset(); } |
| 101 }; |
| 102 } |
| 103 |
| 104 sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream) { |
| 105 return sk_make_sp<MultiPictureDocument>(wStream, nullptr); |
| 106 } |
OLD | NEW |