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