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 #include "SkTArray.h"
14
15 /*
16 File format:
17 BEGINNING_OF_FILE:
18 kMagic
19 uint32_t version_number (==2)
20 uint32_t page_count
21 {
22 float sizeX
23 float sizeY
24 } * page_count
25 skp file
26 */
27
28 namespace {
trim(SkCanvas * canvas,SkScalar w,SkScalar h,const SkRect & trimBox)29 static SkCanvas* trim(SkCanvas* canvas,
30 SkScalar w, SkScalar h,
31 const SkRect& trimBox) {
32 // Only trim if necessary.
33 if (trimBox != SkRect::MakeWH(w, h)) {
34 // All SkDocument implementations implement trimBox using a
35 // clip+translate.
36 canvas->clipRect(trimBox);
37 canvas->translate(trimBox.x(), trimBox.y());
38 }
39 return canvas;
40 }
41
42 struct MultiPictureDocument final : public SkDocument {
43 SkPictureRecorder fPictureRecorder;
44 SkSize fCurrentPageSize;
45 SkTArray<sk_sp<SkPicture>> fPages;
46 SkTArray<SkSize> fSizes;
MultiPictureDocument__anon73b624930111::MultiPictureDocument47 MultiPictureDocument(SkWStream* s, void (*d)(SkWStream*, bool))
48 : SkDocument(s, d) {}
~MultiPictureDocument__anon73b624930111::MultiPictureDocument49 ~MultiPictureDocument() override { this->close(); }
50
onBeginPage__anon73b624930111::MultiPictureDocument51 SkCanvas* onBeginPage(SkScalar w, SkScalar h, const SkRect& c) override {
52 fCurrentPageSize.set(w, h);
53 return trim(fPictureRecorder.beginRecording(w, h), w, h, c);
54 }
onEndPage__anon73b624930111::MultiPictureDocument55 void onEndPage() override {
56 fSizes.push_back(fCurrentPageSize);
57 fPages.push_back(fPictureRecorder.finishRecordingAsPicture());
58 }
onClose__anon73b624930111::MultiPictureDocument59 void onClose(SkWStream* wStream) override {
60 SkASSERT(wStream);
61 SkASSERT(wStream->bytesWritten() == 0);
62 wStream->writeText(SkMultiPictureDocumentProtocol::kMagic);
63 wStream->write32(SkMultiPictureDocumentProtocol::kVersion);
64 wStream->write32(SkToU32(fPages.count()));
65 for (SkSize s : fSizes) {
66 wStream->write(&s, sizeof(s));
67 }
68 SkSize bigsize = SkMultiPictureDocumentProtocol::Join(fSizes);
69 SkCanvas* c = fPictureRecorder.beginRecording(SkRect::MakeSize(bigsize));
70 for (const sk_sp<SkPicture>& page : fPages) {
71 c->drawPicture(page);
72 c->drawAnnotation(SkRect::MakeEmpty(),
73 SkMultiPictureDocumentProtocol::kEndPage,
74 nullptr);
75 }
76 sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture();
77 p->serialize(wStream);
78 fPages.reset();
79 fSizes.reset();
80 return;
81 }
onAbort__anon73b624930111::MultiPictureDocument82 void onAbort() override {
83 fPages.reset();
84 fSizes.reset();
85 }
86 };
87 }
88
SkMakeMultiPictureDocument(SkWStream * wStream)89 sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream) {
90 return sk_make_sp<MultiPictureDocument>(wStream, nullptr);
91 }
92