blob: 217e7a3007a69d0bddb4215ad6e678dbe68c47e4 [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 }
reedd14df7c2016-09-22 14:12:46 -070059 void onClose(SkWStream* wStream) override {
halcanary45420a92016-06-02 12:41:14 -070060 SkASSERT(wStream);
61 SkASSERT(wStream->bytesWritten() == 0);
reedd14df7c2016-09-22 14:12:46 -070062 wStream->writeText(SkMultiPictureDocumentProtocol::kMagic);
63 wStream->write32(SkMultiPictureDocumentProtocol::kVersion);
64 wStream->write32(SkToU32(fPages.count()));
halcanaryc966ef92016-08-23 09:15:04 -070065 for (SkSize s : fSizes) {
reedd14df7c2016-09-22 14:12:46 -070066 wStream->write(&s, sizeof(s));
halcanary45420a92016-06-02 12:41:14 -070067 }
halcanaryc966ef92016-08-23 09:15:04 -070068 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);
halcanary45420a92016-06-02 12:41:14 -070075 }
halcanaryc966ef92016-08-23 09:15:04 -070076 sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture();
77 p->serialize(wStream);
78 fPages.reset();
79 fSizes.reset();
reedd14df7c2016-09-22 14:12:46 -070080 return;
halcanary45420a92016-06-02 12:41:14 -070081 }
halcanaryc966ef92016-08-23 09:15:04 -070082 void onAbort() override {
83 fPages.reset();
84 fSizes.reset();
85 }
halcanary45420a92016-06-02 12:41:14 -070086};
87}
88
89sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream) {
90 return sk_make_sp<MultiPictureDocument>(wStream, nullptr);
91}