1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/utils/SkMultiPictureDocument.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkPicture.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPictureRecorder.h" 12cb93a386Sopenharmony_ci#include "include/core/SkSerialProcs.h" 13cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 14cb93a386Sopenharmony_ci#include "include/private/SkTArray.h" 15cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 16cb93a386Sopenharmony_ci#include "include/utils/SkNWayCanvas.h" 17cb93a386Sopenharmony_ci#include "src/utils/SkMultiPictureDocumentPriv.h" 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#include <limits.h> 20cb93a386Sopenharmony_ci#include <functional> 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci/* 23cb93a386Sopenharmony_ci File format: 24cb93a386Sopenharmony_ci BEGINNING_OF_FILE: 25cb93a386Sopenharmony_ci kMagic 26cb93a386Sopenharmony_ci uint32_t version_number (==2) 27cb93a386Sopenharmony_ci uint32_t page_count 28cb93a386Sopenharmony_ci { 29cb93a386Sopenharmony_ci float sizeX 30cb93a386Sopenharmony_ci float sizeY 31cb93a386Sopenharmony_ci } * page_count 32cb93a386Sopenharmony_ci skp file 33cb93a386Sopenharmony_ci*/ 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_cinamespace { 36cb93a386Sopenharmony_ci// The unique file signature for this file type. 37cb93a386Sopenharmony_cistatic constexpr char kMagic[] = "Skia Multi-Picture Doc\n\n"; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_cistatic constexpr char kEndPage[] = "SkMultiPictureEndPage"; 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ciconst uint32_t kVersion = 2; 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_cistatic SkSize join(const SkTArray<SkSize>& sizes) { 44cb93a386Sopenharmony_ci SkSize joined = {0, 0}; 45cb93a386Sopenharmony_ci for (SkSize s : sizes) { 46cb93a386Sopenharmony_ci joined = SkSize{std::max(joined.width(), s.width()), std::max(joined.height(), s.height())}; 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci return joined; 49cb93a386Sopenharmony_ci} 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_cistruct MultiPictureDocument final : public SkDocument { 52cb93a386Sopenharmony_ci const SkSerialProcs fProcs; 53cb93a386Sopenharmony_ci SkPictureRecorder fPictureRecorder; 54cb93a386Sopenharmony_ci SkSize fCurrentPageSize; 55cb93a386Sopenharmony_ci SkTArray<sk_sp<SkPicture>> fPages; 56cb93a386Sopenharmony_ci SkTArray<SkSize> fSizes; 57cb93a386Sopenharmony_ci std::function<void(const SkPicture*)> fOnEndPage; 58cb93a386Sopenharmony_ci MultiPictureDocument(SkWStream* s, const SkSerialProcs* procs, 59cb93a386Sopenharmony_ci std::function<void(const SkPicture*)> onEndPage) 60cb93a386Sopenharmony_ci : SkDocument(s) 61cb93a386Sopenharmony_ci , fProcs(procs ? *procs : SkSerialProcs()) 62cb93a386Sopenharmony_ci , fOnEndPage(onEndPage) 63cb93a386Sopenharmony_ci {} 64cb93a386Sopenharmony_ci ~MultiPictureDocument() override { this->close(); } 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci SkCanvas* onBeginPage(SkScalar w, SkScalar h) override { 67cb93a386Sopenharmony_ci fCurrentPageSize.set(w, h); 68cb93a386Sopenharmony_ci return fPictureRecorder.beginRecording(w, h); 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci void onEndPage() override { 71cb93a386Sopenharmony_ci fSizes.push_back(fCurrentPageSize); 72cb93a386Sopenharmony_ci sk_sp<SkPicture> lastPage = fPictureRecorder.finishRecordingAsPicture(); 73cb93a386Sopenharmony_ci fPages.push_back(lastPage); 74cb93a386Sopenharmony_ci if (fOnEndPage) { 75cb93a386Sopenharmony_ci fOnEndPage(lastPage.get()); 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci void onClose(SkWStream* wStream) override { 79cb93a386Sopenharmony_ci SkASSERT(wStream); 80cb93a386Sopenharmony_ci SkASSERT(wStream->bytesWritten() == 0); 81cb93a386Sopenharmony_ci wStream->writeText(kMagic); 82cb93a386Sopenharmony_ci wStream->write32(kVersion); 83cb93a386Sopenharmony_ci wStream->write32(SkToU32(fPages.count())); 84cb93a386Sopenharmony_ci for (SkSize s : fSizes) { 85cb93a386Sopenharmony_ci wStream->write(&s, sizeof(s)); 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci SkSize bigsize = join(fSizes); 88cb93a386Sopenharmony_ci SkCanvas* c = fPictureRecorder.beginRecording(SkRect::MakeSize(bigsize)); 89cb93a386Sopenharmony_ci for (const sk_sp<SkPicture>& page : fPages) { 90cb93a386Sopenharmony_ci c->drawPicture(page); 91cb93a386Sopenharmony_ci // Annotations must include some data. 92cb93a386Sopenharmony_ci c->drawAnnotation(SkRect::MakeEmpty(), kEndPage, SkData::MakeWithCString("X")); 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture(); 95cb93a386Sopenharmony_ci p->serialize(wStream, &fProcs); 96cb93a386Sopenharmony_ci fPages.reset(); 97cb93a386Sopenharmony_ci fSizes.reset(); 98cb93a386Sopenharmony_ci return; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci void onAbort() override { 101cb93a386Sopenharmony_ci fPages.reset(); 102cb93a386Sopenharmony_ci fSizes.reset(); 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci}; 105cb93a386Sopenharmony_ci} // namespace 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_cisk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream, const SkSerialProcs* procs, 108cb93a386Sopenharmony_ci std::function<void(const SkPicture*)> onEndPage) { 109cb93a386Sopenharmony_ci return sk_make_sp<MultiPictureDocument>(wStream, procs, onEndPage); 110cb93a386Sopenharmony_ci} 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ciint SkMultiPictureDocumentReadPageCount(SkStreamSeekable* stream) { 115cb93a386Sopenharmony_ci if (!stream) { 116cb93a386Sopenharmony_ci return 0; 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci stream->seek(0); 119cb93a386Sopenharmony_ci const size_t size = sizeof(kMagic) - 1; 120cb93a386Sopenharmony_ci char buffer[size]; 121cb93a386Sopenharmony_ci if (size != stream->read(buffer, size) || 0 != memcmp(kMagic, buffer, size)) { 122cb93a386Sopenharmony_ci stream = nullptr; 123cb93a386Sopenharmony_ci return 0; 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci uint32_t versionNumber; 126cb93a386Sopenharmony_ci if (!stream->readU32(&versionNumber) || versionNumber != kVersion) { 127cb93a386Sopenharmony_ci return 0; 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci uint32_t pageCount; 130cb93a386Sopenharmony_ci if (!stream->readU32(&pageCount) || pageCount > INT_MAX) { 131cb93a386Sopenharmony_ci return 0; 132cb93a386Sopenharmony_ci } 133cb93a386Sopenharmony_ci // leave stream position right here. 134cb93a386Sopenharmony_ci return SkTo<int>(pageCount); 135cb93a386Sopenharmony_ci} 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_cibool SkMultiPictureDocumentReadPageSizes(SkStreamSeekable* stream, 138cb93a386Sopenharmony_ci SkDocumentPage* dstArray, 139cb93a386Sopenharmony_ci int dstArrayCount) { 140cb93a386Sopenharmony_ci if (!dstArray || dstArrayCount < 1) { 141cb93a386Sopenharmony_ci return false; 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci int pageCount = SkMultiPictureDocumentReadPageCount(stream); 144cb93a386Sopenharmony_ci if (pageCount < 1 || pageCount != dstArrayCount) { 145cb93a386Sopenharmony_ci return false; 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci for (int i = 0; i < pageCount; ++i) { 148cb93a386Sopenharmony_ci SkSize& s = dstArray[i].fSize; 149cb93a386Sopenharmony_ci if (sizeof(s) != stream->read(&s, sizeof(s))) { 150cb93a386Sopenharmony_ci return false; 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci // leave stream position right here. 154cb93a386Sopenharmony_ci return true; 155cb93a386Sopenharmony_ci} 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_cinamespace { 158cb93a386Sopenharmony_cistruct PagerCanvas : public SkNWayCanvas { 159cb93a386Sopenharmony_ci SkPictureRecorder fRecorder; 160cb93a386Sopenharmony_ci SkDocumentPage* fDst; 161cb93a386Sopenharmony_ci int fCount; 162cb93a386Sopenharmony_ci int fIndex = 0; 163cb93a386Sopenharmony_ci PagerCanvas(SkISize wh, SkDocumentPage* dst, int count) 164cb93a386Sopenharmony_ci : SkNWayCanvas(wh.width(), wh.height()), fDst(dst), fCount(count) { 165cb93a386Sopenharmony_ci this->nextCanvas(); 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci void nextCanvas() { 168cb93a386Sopenharmony_ci if (fIndex < fCount) { 169cb93a386Sopenharmony_ci SkRect bounds = SkRect::MakeSize(fDst[fIndex].fSize); 170cb93a386Sopenharmony_ci this->addCanvas(fRecorder.beginRecording(bounds)); 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci void onDrawAnnotation(const SkRect& r, const char* key, SkData* d) override { 174cb93a386Sopenharmony_ci if (0 == strcmp(key, kEndPage)) { 175cb93a386Sopenharmony_ci this->removeAll(); 176cb93a386Sopenharmony_ci if (fIndex < fCount) { 177cb93a386Sopenharmony_ci fDst[fIndex].fPicture = fRecorder.finishRecordingAsPicture(); 178cb93a386Sopenharmony_ci ++fIndex; 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci this->nextCanvas(); 181cb93a386Sopenharmony_ci } else { 182cb93a386Sopenharmony_ci this->SkNWayCanvas::onDrawAnnotation(r, key, d); 183cb93a386Sopenharmony_ci } 184cb93a386Sopenharmony_ci } 185cb93a386Sopenharmony_ci}; 186cb93a386Sopenharmony_ci} // namespace 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_cibool SkMultiPictureDocumentRead(SkStreamSeekable* stream, 189cb93a386Sopenharmony_ci SkDocumentPage* dstArray, 190cb93a386Sopenharmony_ci int dstArrayCount, 191cb93a386Sopenharmony_ci const SkDeserialProcs* procs) { 192cb93a386Sopenharmony_ci if (!SkMultiPictureDocumentReadPageSizes(stream, dstArray, dstArrayCount)) { 193cb93a386Sopenharmony_ci return false; 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci SkSize joined = {0.0f, 0.0f}; 196cb93a386Sopenharmony_ci for (int i = 0; i < dstArrayCount; ++i) { 197cb93a386Sopenharmony_ci joined = SkSize{std::max(joined.width(), dstArray[i].fSize.width()), 198cb93a386Sopenharmony_ci std::max(joined.height(), dstArray[i].fSize.height())}; 199cb93a386Sopenharmony_ci } 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ci auto picture = SkPicture::MakeFromStream(stream, procs); 202cb93a386Sopenharmony_ci if (!picture) { 203cb93a386Sopenharmony_ci return false; 204cb93a386Sopenharmony_ci } 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_ci PagerCanvas canvas(joined.toCeil(), dstArray, dstArrayCount); 207cb93a386Sopenharmony_ci // Must call playback(), not drawPicture() to reach 208cb93a386Sopenharmony_ci // PagerCanvas::onDrawAnnotation(). 209cb93a386Sopenharmony_ci picture->playback(&canvas); 210cb93a386Sopenharmony_ci if (canvas.fIndex != dstArrayCount) { 211cb93a386Sopenharmony_ci SkDEBUGF("Malformed SkMultiPictureDocument: canvas.fIndex=%d dstArrayCount=%d\n", 212cb93a386Sopenharmony_ci canvas.fIndex, dstArrayCount); 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci return true; 215cb93a386Sopenharmony_ci} 216