blob: c40f1c900b5fb5b5e045545d6d8a13ce5117df89 [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
8#include "SkMultiPictureDocument.h"
9#include "SkMultiPictureDocumentPriv.h"
10#include "SkPicture.h"
11#include "SkPictureRecorder.h"
12#include "SkStream.h"
halcanaryc966ef92016-08-23 09:15:04 -070013#include "SkTArray.h"
halcanary45420a92016-06-02 12:41:14 -070014
15/*
16 File format:
17 BEGINNING_OF_FILE:
18 kMagic
halcanaryc966ef92016-08-23 09:15:04 -070019 uint32_t version_number (==2)
halcanary45420a92016-06-02 12:41:14 -070020 uint32_t page_count
21 {
halcanary45420a92016-06-02 12:41:14 -070022 float sizeX
23 float sizeY
24 } * page_count
halcanary45420a92016-06-02 12:41:14 -070025 skp file
halcanary45420a92016-06-02 12:41:14 -070026*/
27
28namespace {
29static 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
halcanary45420a92016-06-02 12:41:14 -070042struct MultiPictureDocument final : public SkDocument {
43 SkPictureRecorder fPictureRecorder;
halcanary59d64022016-06-14 11:06:37 -070044 SkSize fCurrentPageSize;
halcanaryc966ef92016-08-23 09:15:04 -070045 SkTArray<sk_sp<SkPicture>> fPages;
46 SkTArray<SkSize> fSizes;
halcanary45420a92016-06-02 12:41:14 -070047 MultiPictureDocument(SkWStream* s, void (*d)(SkWStream*, bool))
48 : SkDocument(s, d) {}
49 ~MultiPictureDocument() { this->close(); }
50
51 SkCanvas* onBeginPage(SkScalar w, SkScalar h, const SkRect& c) override {
halcanary59d64022016-06-14 11:06:37 -070052 fCurrentPageSize.set(w, h);
halcanary45420a92016-06-02 12:41:14 -070053 return trim(fPictureRecorder.beginRecording(w, h), w, h, c);
54 }
55 void onEndPage() override {
halcanaryc966ef92016-08-23 09:15:04 -070056 fSizes.push_back(fCurrentPageSize);
57 fPages.push_back(fPictureRecorder.finishRecordingAsPicture());
halcanary45420a92016-06-02 12:41:14 -070058 }
59 bool onClose(SkWStream* wStream) override {
60 SkASSERT(wStream);
61 SkASSERT(wStream->bytesWritten() == 0);
62 bool good = true;
63 good &= wStream->writeText(SkMultiPictureDocumentProtocol::kMagic);
halcanaryc966ef92016-08-23 09:15:04 -070064 good &= wStream->write32(SkMultiPictureDocumentProtocol::kVersion);
65 good &= wStream->write32(SkToU32(fPages.count()));
66 for (SkSize s : fSizes) {
67 good &= wStream->write(&s, sizeof(s));
halcanary45420a92016-06-02 12:41:14 -070068 }
halcanaryc966ef92016-08-23 09:15:04 -070069 SkSize bigsize = SkMultiPictureDocumentProtocol::Join(fSizes);
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);
halcanary45420a92016-06-02 12:41:14 -070076 }
halcanaryc966ef92016-08-23 09:15:04 -070077 sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture();
78 p->serialize(wStream);
79 fPages.reset();
80 fSizes.reset();
halcanary45420a92016-06-02 12:41:14 -070081 return good;
82 }
halcanaryc966ef92016-08-23 09:15:04 -070083 void onAbort() override {
84 fPages.reset();
85 fSizes.reset();
86 }
halcanary45420a92016-06-02 12:41:14 -070087};
88}
89
90sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream) {
91 return sk_make_sp<MultiPictureDocument>(wStream, nullptr);
92}