blob: 217e7a3007a69d0bddb4215ad6e678dbe68c47e4 [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkMultiPictureDocument.h"
#include "SkMultiPictureDocumentPriv.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
#include "SkStream.h"
#include "SkTArray.h"
/*
File format:
BEGINNING_OF_FILE:
kMagic
uint32_t version_number (==2)
uint32_t page_count
{
float sizeX
float sizeY
} * page_count
skp file
*/
namespace {
static SkCanvas* trim(SkCanvas* canvas,
SkScalar w, SkScalar h,
const SkRect& trimBox) {
// Only trim if necessary.
if (trimBox != SkRect::MakeWH(w, h)) {
// All SkDocument implementations implement trimBox using a
// clip+translate.
canvas->clipRect(trimBox);
canvas->translate(trimBox.x(), trimBox.y());
}
return canvas;
}
struct MultiPictureDocument final : public SkDocument {
SkPictureRecorder fPictureRecorder;
SkSize fCurrentPageSize;
SkTArray<sk_sp<SkPicture>> fPages;
SkTArray<SkSize> fSizes;
MultiPictureDocument(SkWStream* s, void (*d)(SkWStream*, bool))
: SkDocument(s, d) {}
~MultiPictureDocument() { this->close(); }
SkCanvas* onBeginPage(SkScalar w, SkScalar h, const SkRect& c) override {
fCurrentPageSize.set(w, h);
return trim(fPictureRecorder.beginRecording(w, h), w, h, c);
}
void onEndPage() override {
fSizes.push_back(fCurrentPageSize);
fPages.push_back(fPictureRecorder.finishRecordingAsPicture());
}
void onClose(SkWStream* wStream) override {
SkASSERT(wStream);
SkASSERT(wStream->bytesWritten() == 0);
wStream->writeText(SkMultiPictureDocumentProtocol::kMagic);
wStream->write32(SkMultiPictureDocumentProtocol::kVersion);
wStream->write32(SkToU32(fPages.count()));
for (SkSize s : fSizes) {
wStream->write(&s, sizeof(s));
}
SkSize bigsize = SkMultiPictureDocumentProtocol::Join(fSizes);
SkCanvas* c = fPictureRecorder.beginRecording(SkRect::MakeSize(bigsize));
for (const sk_sp<SkPicture>& page : fPages) {
c->drawPicture(page);
c->drawAnnotation(SkRect::MakeEmpty(),
SkMultiPictureDocumentProtocol::kEndPage,
nullptr);
}
sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture();
p->serialize(wStream);
fPages.reset();
fSizes.reset();
return;
}
void onAbort() override {
fPages.reset();
fSizes.reset();
}
};
}
sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream) {
return sk_make_sp<MultiPictureDocument>(wStream, nullptr);
}