blob: e4105fa31dbdea8ab509f6b93a68c187facad332 [file] [log] [blame]
halcanary45420a92016-06-02 12:41:14 -07001/*
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
halcanary59d64022016-06-14 11:06:37 -07008#include <vector>
9
halcanary45420a92016-06-02 12:41:14 -070010#include "SkMultiPictureDocument.h"
11#include "SkMultiPictureDocumentPriv.h"
12#include "SkPicture.h"
13#include "SkPictureRecorder.h"
14#include "SkStream.h"
15
16/*
17 File format:
18 BEGINNING_OF_FILE:
19 kMagic
20 uint32_t version_number
21 uint32_t page_count
22 {
23 uint64_t offset
24 float sizeX
25 float sizeY
26 } * page_count
27 FIRST_OFFSET:
28 skp file
29 SECOND_OFFSET:
30 skp file
31 ...
32 LAST_OFFSET:
33 skp file
34 "\nEndOfMultiPicture\n"
35*/
36
37namespace {
38static SkCanvas* trim(SkCanvas* canvas,
39 SkScalar w, SkScalar h,
40 const SkRect& trimBox) {
41 // Only trim if necessary.
42 if (trimBox != SkRect::MakeWH(w, h)) {
43 // All SkDocument implementations implement trimBox using a
44 // clip+translate.
45 canvas->clipRect(trimBox);
46 canvas->translate(trimBox.x(), trimBox.y());
47 }
48 return canvas;
49}
50
51struct 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
halcanary59d64022016-06-14 11:06:37 -070061struct Page {
62 Page(SkSize s, sk_sp<SkPicture> c) : fSize(s), fContent(std::move(c)) {}
63 Page(Page&& that) : fSize(that.fSize), fContent(std::move(that.fContent)) {}
64 Page(const Page&) = default;
65 Page& operator=(const Page&) = default;
66 Page& operator=(Page&& that) {
67 fSize = that.fSize;
68 fContent = std::move(that.fContent);
69 return *this;
70 }
71 SkSize fSize;
72 sk_sp<SkPicture> fContent;
73};
74
halcanary45420a92016-06-02 12:41:14 -070075struct MultiPictureDocument final : public SkDocument {
76 SkPictureRecorder fPictureRecorder;
halcanary59d64022016-06-14 11:06:37 -070077 SkSize fCurrentPageSize;
78 std::vector<Page> fPages;
halcanary45420a92016-06-02 12:41:14 -070079 MultiPictureDocument(SkWStream* s, void (*d)(SkWStream*, bool))
80 : SkDocument(s, d) {}
81 ~MultiPictureDocument() { this->close(); }
82
83 SkCanvas* onBeginPage(SkScalar w, SkScalar h, const SkRect& c) override {
halcanary59d64022016-06-14 11:06:37 -070084 fCurrentPageSize.set(w, h);
halcanary45420a92016-06-02 12:41:14 -070085 return trim(fPictureRecorder.beginRecording(w, h), w, h, c);
86 }
87 void onEndPage() override {
halcanary59d64022016-06-14 11:06:37 -070088 fPages.emplace_back(fCurrentPageSize,
89 fPictureRecorder.finishRecordingAsPicture());
halcanary45420a92016-06-02 12:41:14 -070090 }
91 bool onClose(SkWStream* wStream) override {
92 SkASSERT(wStream);
93 SkASSERT(wStream->bytesWritten() == 0);
94 bool good = true;
95 good &= wStream->writeText(SkMultiPictureDocumentProtocol::kMagic);
96 good &= wStream->write32(SkToU32(1)); // version
halcanary59d64022016-06-14 11:06:37 -070097 good &= wStream->write32(SkToU32(fPages.size()));
halcanary45420a92016-06-02 12:41:14 -070098 uint64_t offset = wStream->bytesWritten();
halcanary59d64022016-06-14 11:06:37 -070099 offset += fPages.size() * sizeof(SkMultiPictureDocumentProtocol::Entry);
halcanary45420a92016-06-02 12:41:14 -0700100 for (const auto& page : fPages) {
halcanary45420a92016-06-02 12:41:14 -0700101 SkMultiPictureDocumentProtocol::Entry entry{
halcanary59d64022016-06-14 11:06:37 -0700102 offset, page.fSize.width(), page.fSize.height()};
halcanary45420a92016-06-02 12:41:14 -0700103 good &= wStream->write(&entry, sizeof(entry));
104 NullWStream buffer;
halcanary59d64022016-06-14 11:06:37 -0700105 page.fContent->serialize(&buffer);
halcanary45420a92016-06-02 12:41:14 -0700106 offset += buffer.bytesWritten();
107 }
108 for (const auto& page : fPages) {
halcanary59d64022016-06-14 11:06:37 -0700109 page.fContent->serialize(wStream);
halcanary45420a92016-06-02 12:41:14 -0700110 }
111 SkASSERT(wStream->bytesWritten() == offset);
112 good &= wStream->writeText("\nEndOfMultiPicture\n");
halcanary59d64022016-06-14 11:06:37 -0700113 fPages.clear();
halcanary45420a92016-06-02 12:41:14 -0700114 return good;
115 }
halcanary59d64022016-06-14 11:06:37 -0700116 void onAbort() override { fPages.clear(); }
halcanary45420a92016-06-02 12:41:14 -0700117};
118}
119
120sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream) {
121 return sk_make_sp<MultiPictureDocument>(wStream, nullptr);
122}