Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkMultiPictureDocument.cpp
Go to the documentation of this file.
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
9
11#include "include/core/SkData.h"
15#include "include/core/SkRect.h"
24
25#include <algorithm>
26#include <climits>
27#include <cstdint>
28#include <cstring>
29#include <functional>
30#include <utility>
31
32using namespace skia_private;
33
34/*
35 File format:
36 BEGINNING_OF_FILE:
37 kMagic
38 uint32_t version_number (==2)
39 uint32_t page_count
40 {
41 float sizeX
42 float sizeY
43 } * page_count
44 skp file
45*/
46
47namespace {
48// The unique file signature for this file type.
49static constexpr char kMagic[] = "Skia Multi-Picture Doc\n\n";
50
51static constexpr char kEndPage[] = "SkMultiPictureEndPage";
52
53const uint32_t kVersion = 2;
54
55static SkSize join(const TArray<SkSize>& sizes) {
56 SkSize joined = {0, 0};
57 for (SkSize s : sizes) {
58 joined = SkSize{std::max(joined.width(), s.width()), std::max(joined.height(), s.height())};
59 }
60 return joined;
61}
62
63struct MultiPictureDocument final : public SkDocument {
64 const SkSerialProcs fProcs;
65 SkPictureRecorder fPictureRecorder;
66 SkSize fCurrentPageSize;
68 TArray<SkSize> fSizes;
69 std::function<void(const SkPicture*)> fOnEndPage;
70 MultiPictureDocument(SkWStream* s,
71 const SkSerialProcs* procs,
72 std::function<void(const SkPicture*)> onEndPage)
73 : SkDocument(s)
74 , fProcs(procs ? *procs : SkSerialProcs())
75 , fOnEndPage(std::move(onEndPage)) {}
76
77 ~MultiPictureDocument() override { this->close(); }
78
80 fCurrentPageSize.set(w, h);
81 return fPictureRecorder.beginRecording(w, h);
82 }
83 void onEndPage() override {
84 fSizes.push_back(fCurrentPageSize);
85 sk_sp<SkPicture> lastPage = fPictureRecorder.finishRecordingAsPicture();
86 fPages.push_back(lastPage);
87 if (fOnEndPage) {
88 fOnEndPage(lastPage.get());
89 }
90 }
91 void onClose(SkWStream* wStream) override {
92 SkASSERT(wStream);
93 SkASSERT(wStream->bytesWritten() == 0);
94 wStream->writeText(kMagic);
95 wStream->write32(kVersion);
96 wStream->write32(SkToU32(fPages.size()));
97 for (SkSize s : fSizes) {
98 wStream->write(&s, sizeof(s));
99 }
100 SkSize bigsize = join(fSizes);
101 SkCanvas* c = fPictureRecorder.beginRecording(SkRect::MakeSize(bigsize));
102 for (const sk_sp<SkPicture>& page : fPages) {
103 c->drawPicture(page);
104 // Annotations must include some data.
106 }
107 sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture();
108 p->serialize(wStream, &fProcs);
109 fPages.clear();
110 fSizes.clear();
111 }
112 void onAbort() override {
113 fPages.clear();
114 fSizes.clear();
115 }
116};
117
118struct PagerCanvas : public SkNWayCanvas {
119 SkPictureRecorder fRecorder;
120 SkDocumentPage* fDst;
121 int fCount;
122 int fIndex = 0;
123 PagerCanvas(SkISize wh, SkDocumentPage* dst, int count)
124 : SkNWayCanvas(wh.width(), wh.height()), fDst(dst), fCount(count) {
125 this->nextCanvas();
126 }
127 void nextCanvas() {
128 if (fIndex < fCount) {
129 SkRect bounds = SkRect::MakeSize(fDst[fIndex].fSize);
130 this->addCanvas(fRecorder.beginRecording(bounds));
131 }
132 }
133 void onDrawAnnotation(const SkRect& r, const char* key, SkData* d) override {
134 if (0 == strcmp(key, kEndPage)) {
135 this->removeAll();
136 if (fIndex < fCount) {
137 fDst[fIndex].fPicture = fRecorder.finishRecordingAsPicture();
138 ++fIndex;
139 }
140 this->nextCanvas();
141 } else {
143 }
144 }
145};
146
147} // namespace
148
149namespace SkMultiPictureDocument {
151 const SkSerialProcs* procs,
152 std::function<void(const SkPicture*)> onEndPage) {
153 return sk_make_sp<MultiPictureDocument>(dst, procs, std::move(onEndPage));
154}
155
157 if (!src) {
158 return 0;
159 }
160 src->seek(0);
161 const size_t size = sizeof(kMagic) - 1;
162 char buffer[size];
163 if (size != src->read(buffer, size) || 0 != memcmp(kMagic, buffer, size)) {
164 src = nullptr;
165 return 0;
166 }
167 uint32_t versionNumber;
168 if (!src->readU32(&versionNumber) || versionNumber != kVersion) {
169 return 0;
170 }
171 uint32_t pageCount;
172 if (!src->readU32(&pageCount) || pageCount > INT_MAX) {
173 return 0;
174 }
175 // leave stream position right here.
176 return SkTo<int>(pageCount);
177}
178
180 SkDocumentPage* dstArray,
181 int dstArrayCount) {
182 if (!dstArray || dstArrayCount < 1) {
183 return false;
184 }
185 int pageCount = ReadPageCount(stream);
186 if (pageCount < 1 || pageCount != dstArrayCount) {
187 return false;
188 }
189 for (int i = 0; i < pageCount; ++i) {
190 SkSize& s = dstArray[i].fSize;
191 if (sizeof(s) != stream->read(&s, sizeof(s))) {
192 return false;
193 }
194 }
195 // leave stream position right here.
196 return true;
197}
198
200 SkDocumentPage* dstArray,
201 int dstArrayCount,
202 const SkDeserialProcs* procs) {
203 if (!ReadPageSizes(src, dstArray, dstArrayCount)) {
204 return false;
205 }
206 SkSize joined = {0.0f, 0.0f};
207 for (int i = 0; i < dstArrayCount; ++i) {
208 joined = SkSize{std::max(joined.width(), dstArray[i].fSize.width()),
209 std::max(joined.height(), dstArray[i].fSize.height())};
210 }
211
212 auto picture = SkPicture::MakeFromStream(src, procs);
213 if (!picture) {
214 return false;
215 }
216
217 PagerCanvas canvas(joined.toCeil(), dstArray, dstArrayCount);
218 // Must call playback(), not drawPicture() to reach
219 // PagerCanvas::onDrawAnnotation().
220 picture->playback(&canvas);
221 if (canvas.fIndex != dstArrayCount) {
222 SkDEBUGF("Malformed SkMultiPictureDocument: canvas.fIndex=%d dstArrayCount=%d\n",
223 canvas.fIndex, dstArrayCount);
224 }
225 return true;
226}
227} // namespace SkMultiPictureDocument
int count
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGF(...)
Definition SkDebug.h:24
static const char kMagic[]
Definition SkPicture.cpp:58
constexpr uint32_t SkToU32(S x)
Definition SkTo.h:26
void drawAnnotation(const SkRect &rect, const char key[], SkData *value)
void drawPicture(const SkPicture *picture)
Definition SkCanvas.h:1961
static sk_sp< SkData > MakeWithCString(const char cstr[])
Definition SkData.cpp:195
virtual void onClose(SkWStream *)=0
virtual void onAbort()=0
void close()
virtual SkCanvas * onBeginPage(SkScalar width, SkScalar height)=0
virtual void onEndPage()=0
virtual void addCanvas(SkCanvas *)
void onDrawAnnotation(const SkRect &, const char[], SkData *) override
virtual void removeAll()
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
virtual void playback(SkCanvas *canvas, AbortCallback *callback=nullptr) const =0
static sk_sp< SkPicture > MakeFromStream(SkStream *stream, const SkDeserialProcs *procs=nullptr)
virtual bool write(const void *buffer, size_t size)=0
bool write32(uint32_t v)
Definition SkStream.h:243
virtual size_t bytesWritten() const =0
bool writeText(const char text[])
Definition SkStream.h:247
T * get() const
Definition SkRefCnt.h:303
int size() const
Definition SkTArray.h:416
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
float SkScalar
Definition extension.cpp:12
struct MyStruct s
static const uint8_t buffer[]
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
SK_API bool Read(SkStreamSeekable *src, SkDocumentPage *dstArray, int dstArrayCount, const SkDeserialProcs *=nullptr)
SK_API int ReadPageCount(SkStreamSeekable *src)
bool ReadPageSizes(SkStreamSeekable *stream, SkDocumentPage *dstArray, int dstArrayCount)
Optional< SkRect > bounds
Definition SkRecords.h:189
dst
Definition cp.py:12
SINT Vec< 2 *N, T > join(const Vec< N, T > &lo, const Vec< N, T > &hi)
Definition SkVx.h:242
Definition ref_ptr.h:256
SkScalar w
SkScalar h
int32_t height
int32_t width
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595
static constexpr SkRect MakeSize(const SkSize &size)
Definition SkRect.h:633
void set(SkScalar w, SkScalar h)
Definition SkSize.h:64
SkISize toCeil() const
Definition SkSize.h:83
SkScalar width() const
Definition SkSize.h:76
SkScalar height() const
Definition SkSize.h:77