1/*
2 * Copyright 2011 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/core/SkPictureData.h"
9
10#include "include/core/SkImageGenerator.h"
11#include "include/core/SkTypeface.h"
12#include "include/private/SkTo.h"
13#include "src/core/SkAutoMalloc.h"
14#include "src/core/SkPicturePriv.h"
15#include "src/core/SkPictureRecord.h"
16#include "src/core/SkReadBuffer.h"
17#include "src/core/SkTextBlobPriv.h"
18#include "src/core/SkVerticesPriv.h"
19#include "src/core/SkWriteBuffer.h"
20
21#include <new>
22
23template <typename T> int SafeCount(const T* obj) {
24 return obj ? obj->count() : 0;
25}
26
27SkPictureData::SkPictureData(const SkPictInfo& info)
28 : fInfo(info) {}
29
30void SkPictureData::initForPlayback() const {
31 // ensure that the paths bounds are pre-computed
32 for (int i = 0; i < fPaths.count(); i++) {
33 fPaths[i].updateBoundsCache();
34 }
35}
36
37SkPictureData::SkPictureData(const SkPictureRecord& record,
38 const SkPictInfo& info)
39 : fPictures(record.getPictures())
40 , fDrawables(record.getDrawables())
41 , fTextBlobs(record.getTextBlobs())
42 , fVertices(record.getVertices())
43 , fImages(record.getImages())
44 , fInfo(info) {
45
46 fOpData = record.opData();
47
48 fPaints = record.fPaints;
49
50 fPaths.reset(record.fPaths.count());
51 record.fPaths.foreach([this](const SkPath& path, int n) {
52 // These indices are logically 1-based, but we need to serialize them
53 // 0-based to keep the deserializing SkPictureData::getPath() working.
54 fPaths[n-1] = path;
55 });
56
57 this->initForPlayback();
58}
59
60///////////////////////////////////////////////////////////////////////////////
61///////////////////////////////////////////////////////////////////////////////
62
63#include "include/core/SkStream.h"
64
65static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
66 size_t size = 4; // for 'count'
67
68 for (int i = 0; i < count; i++) {
69 const char* name = SkFlattenable::FactoryToName(array[i]);
70 if (nullptr == name || 0 == *name) {
71 size += SkWStream::SizeOfPackedUInt(0);
72 } else {
73 size_t len = strlen(name);
74 size += SkWStream::SizeOfPackedUInt(len);
75 size += len;
76 }
77 }
78
79 return size;
80}
81
82static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
83 buffer.writeUInt(tag);
84 buffer.writeUInt(SkToU32(size));
85}
86
87static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
88 stream->write32(tag);
89 stream->write32(SkToU32(size));
90}
91
92void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
93 int count = rec.count();
94
95 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
96 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
97 rec.copyToArray(array);
98
99 size_t size = compute_chunk_size(array, count);
100
101 // TODO: write_tag_size should really take a size_t
102 write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
103 SkDEBUGCODE(size_t start = stream->bytesWritten());
104 stream->write32(count);
105
106 for (int i = 0; i < count; i++) {
107 const char* name = SkFlattenable::FactoryToName(array[i]);
108 if (nullptr == name || 0 == *name) {
109 stream->writePackedUInt(0);
110 } else {
111 size_t len = strlen(name);
112 stream->writePackedUInt(len);
113 stream->write(name, len);
114 }
115 }
116
117 SkASSERT(size == (stream->bytesWritten() - start));
118}
119
120void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec,
121 const SkSerialProcs& procs) {
122 int count = rec.count();
123
124 write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
125
126 SkAutoSTMalloc<16, SkTypeface*> storage(count);
127 SkTypeface** array = (SkTypeface**)storage.get();
128 rec.copyToArray((SkRefCnt**)array);
129
130 for (int i = 0; i < count; i++) {
131 SkTypeface* tf = array[i];
132 if (procs.fTypefaceProc) {
133 auto data = procs.fTypefaceProc(tf, procs.fTypefaceCtx);
134 if (data) {
135 stream->write(data->data(), data->size());
136 continue;
137 }
138 }
139 array[i]->serialize(stream);
140 }
141}
142
143void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer, bool textBlobsOnly) const {
144 int i, n;
145
146 if (!textBlobsOnly) {
147 if ((n = fPaints.count()) > 0) {
148 write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
149 for (i = 0; i < n; i++) {
150 buffer.writePaint(fPaints[i]);
151 }
152 }
153
154 if ((n = fPaths.count()) > 0) {
155 write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n);
156 buffer.writeInt(n);
157 for (int i = 0; i < n; i++) {
158 buffer.writePath(fPaths[i]);
159 }
160 }
161 }
162
163 if (!fTextBlobs.empty()) {
164 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobs.count());
165 for (const auto& blob : fTextBlobs) {
166 SkTextBlobPriv::Flatten(*blob, buffer);
167 }
168 }
169
170 if (!textBlobsOnly) {
171 if (!fVertices.empty()) {
172 write_tag_size(buffer, SK_PICT_VERTICES_BUFFER_TAG, fVertices.count());
173 for (const auto& vert : fVertices) {
174 vert->priv().encode(buffer);
175 }
176 }
177
178 if (!fImages.empty()) {
179 write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImages.count());
180 for (const auto& img : fImages) {
181 buffer.writeImage(img.get());
182 }
183 }
184 }
185}
186
187// SkPictureData::serialize() will write out paints, and then write out an array of typefaces
188// (unique set). However, paint's serializer will respect SerialProcs, which can cause us to
189// call that custom typefaceproc on *every* typeface, not just on the unique ones. To avoid this,
190// we ignore the custom proc (here) when we serialize the paints, and then do respect it when
191// we serialize the typefaces.
192static SkSerialProcs skip_typeface_proc(const SkSerialProcs& procs) {
193 SkSerialProcs newProcs = procs;
194 newProcs.fTypefaceProc = nullptr;
195 newProcs.fTypefaceCtx = nullptr;
196 return newProcs;
197}
198
199// topLevelTypeFaceSet is null only on the top level call.
200// This method is called recursively on every subpicture in two passes.
201// textBlobsOnly serves to indicate that we are on the first pass and skip as much work as
202// possible that is not relevant to collecting text blobs in topLevelTypeFaceSet
203// TODO(nifong): dedupe typefaces and all other shared resources in a faster and more readable way.
204void SkPictureData::serialize(SkWStream* stream, const SkSerialProcs& procs,
205 SkRefCntSet* topLevelTypeFaceSet, bool textBlobsOnly) const {
206 // This can happen at pretty much any time, so might as well do it first.
207 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
208 stream->write(fOpData->bytes(), fOpData->size());
209
210 // We serialize all typefaces into the typeface section of the top-level picture.
211 SkRefCntSet localTypefaceSet;
212 SkRefCntSet* typefaceSet = topLevelTypeFaceSet ? topLevelTypeFaceSet : &localTypefaceSet;
213
214 // We delay serializing the bulk of our data until after we've serialized
215 // factories and typefaces by first serializing to an in-memory write buffer.
216 SkFactorySet factSet; // buffer refs factSet, so factSet must come first.
217 SkBinaryWriteBuffer buffer;
218 buffer.setFactoryRecorder(sk_ref_sp(&factSet));
219 buffer.setSerialProcs(skip_typeface_proc(procs));
220 buffer.setTypefaceRecorder(sk_ref_sp(typefaceSet));
221 this->flattenToBuffer(buffer, textBlobsOnly);
222
223 // Pretend to serialize our sub-pictures for the side effect of filling typefaceSet
224 // with typefaces from sub-pictures.
225 struct DevNull: public SkWStream {
226 DevNull() : fBytesWritten(0) {}
227 size_t fBytesWritten;
228 bool write(const void*, size_t size) override { fBytesWritten += size; return true; }
229 size_t bytesWritten() const override { return fBytesWritten; }
230 } devnull;
231 for (const auto& pic : fPictures) {
232 pic->serialize(&devnull, nullptr, typefaceSet, /*textBlobsOnly=*/ true);
233 }
234 if (textBlobsOnly) { return; } // return early from fake serialize
235
236 // We need to write factories before we write the buffer.
237 // We need to write typefaces before we write the buffer or any sub-picture.
238 WriteFactories(stream, factSet);
239 // Pass the original typefaceproc (if any) now that we're ready to actually serialize the
240 // typefaces. We skipped this proc before, when we were serializing paints, so that the
241 // paints would just write indices into our typeface set.
242 WriteTypefaces(stream, *typefaceSet, procs);
243
244 // Write the buffer.
245 write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
246 buffer.writeToStream(stream);
247
248 // Write sub-pictures by calling serialize again.
249 if (!fPictures.empty()) {
250 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictures.count());
251 for (const auto& pic : fPictures) {
252 pic->serialize(stream, &procs, typefaceSet, /*textBlobsOnly=*/ false);
253 }
254 }
255
256 stream->write32(SK_PICT_EOF_TAG);
257}
258
259void SkPictureData::flatten(SkWriteBuffer& buffer) const {
260 write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
261 buffer.writeByteArray(fOpData->bytes(), fOpData->size());
262
263 if (!fPictures.empty()) {
264 write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictures.count());
265 for (const auto& pic : fPictures) {
266 SkPicturePriv::Flatten(pic, buffer);
267 }
268 }
269
270 if (!fDrawables.empty()) {
271 write_tag_size(buffer, SK_PICT_DRAWABLE_TAG, fDrawables.count());
272 for (const auto& draw : fDrawables) {
273 buffer.writeFlattenable(draw.get());
274 }
275 }
276
277 // Write this picture playback's data into a writebuffer
278 this->flattenToBuffer(buffer, false);
279 buffer.write32(SK_PICT_EOF_TAG);
280}
281
282///////////////////////////////////////////////////////////////////////////////
283
284bool SkPictureData::parseStreamTag(SkStream* stream,
285 uint32_t tag,
286 uint32_t size,
287 const SkDeserialProcs& procs,
288 SkTypefacePlayback* topLevelTFPlayback) {
289 switch (tag) {
290 case SK_PICT_READER_TAG:
291 SkASSERT(nullptr == fOpData);
292 fOpData = SkData::MakeFromStream(stream, size);
293 if (!fOpData) {
294 return false;
295 }
296 break;
297 case SK_PICT_FACTORY_TAG: {
298 if (!stream->readU32(&size)) { return false; }
299 fFactoryPlayback = std::make_unique<SkFactoryPlayback>(size);
300 for (size_t i = 0; i < size; i++) {
301 SkString str;
302 size_t len;
303 if (!stream->readPackedUInt(&len)) { return false; }
304 str.resize(len);
305 if (stream->read(str.writable_str(), len) != len) {
306 return false;
307 }
308 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
309 }
310 } break;
311 case SK_PICT_TYPEFACE_TAG: {
312 fTFPlayback.setCount(size);
313 for (uint32_t i = 0; i < size; ++i) {
314 sk_sp<SkTypeface> tf;
315 if (procs.fTypefaceProc) {
316 tf = procs.fTypefaceProc(&stream, sizeof(stream), procs.fTypefaceCtx);
317 } else {
318 tf = SkTypeface::MakeDeserialize(stream);
319 }
320 if (!tf.get()) { // failed to deserialize
321 // fTFPlayback asserts it never has a null, so we plop in
322 // the default here.
323 tf = SkTypeface::MakeDefault();
324 }
325 fTFPlayback[i] = std::move(tf);
326 }
327 } break;
328 case SK_PICT_PICTURE_TAG: {
329 SkASSERT(fPictures.empty());
330 fPictures.reserve(SkToInt(size));
331
332 for (uint32_t i = 0; i < size; i++) {
333 auto pic = SkPicture::MakeFromStream(stream, &procs, topLevelTFPlayback);
334 if (!pic) {
335 return false;
336 }
337 fPictures.push_back(std::move(pic));
338 }
339 } break;
340 case SK_PICT_BUFFER_SIZE_TAG: {
341 SkAutoMalloc storage(size);
342 if (stream->read(storage.get(), size) != size) {
343 return false;
344 }
345
346 SkReadBuffer buffer(storage.get(), size);
347 buffer.setVersion(fInfo.getVersion());
348
349 if (!fFactoryPlayback) {
350 return false;
351 }
352 fFactoryPlayback->setupBuffer(buffer);
353 buffer.setDeserialProcs(procs);
354
355 if (fTFPlayback.count() > 0) {
356 // .skp files <= v43 have typefaces serialized with each sub picture.
357 fTFPlayback.setupBuffer(buffer);
358 } else {
359 // Newer .skp files serialize all typefaces with the top picture.
360 topLevelTFPlayback->setupBuffer(buffer);
361 }
362
363 while (!buffer.eof() && buffer.isValid()) {
364 tag = buffer.readUInt();
365 size = buffer.readUInt();
366 this->parseBufferTag(buffer, tag, size);
367 }
368 if (!buffer.isValid()) {
369 return false;
370 }
371 } break;
372 }
373 return true; // success
374}
375
376static sk_sp<SkImage> create_image_from_buffer(SkReadBuffer& buffer) {
377 return buffer.readImage();
378}
379
380static sk_sp<SkDrawable> create_drawable_from_buffer(SkReadBuffer& buffer) {
381 return sk_sp<SkDrawable>((SkDrawable*)buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
382}
383
384// We need two types 'cause SkDrawable is const-variant.
385template <typename T, typename U>
386bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t inCount,
387 SkTArray<sk_sp<T>>& array, sk_sp<U> (*factory)(SkReadBuffer&)) {
388 if (!buffer.validate(array.empty() && SkTFitsIn<int>(inCount))) {
389 return false;
390 }
391 if (0 == inCount) {
392 return true;
393 }
394
395 for (uint32_t i = 0; i < inCount; ++i) {
396 auto obj = factory(buffer);
397
398 if (!buffer.validate(obj != nullptr)) {
399 array.reset();
400 return false;
401 }
402
403 array.push_back(std::move(obj));
404 }
405
406 return true;
407}
408
409void SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size) {
410 switch (tag) {
411 case SK_PICT_PAINT_BUFFER_TAG: {
412 if (!buffer.validate(SkTFitsIn<int>(size))) {
413 return;
414 }
415 const int count = SkToInt(size);
416
417 for (int i = 0; i < count; ++i) {
418 // Do we need to keep an array of fFonts for legacy draws?
419 if (!buffer.readPaint(&fPaints.push_back(), nullptr)) {
420 return;
421 }
422 }
423 } break;
424 case SK_PICT_PATH_BUFFER_TAG:
425 if (size > 0) {
426 const int count = buffer.readInt();
427 if (!buffer.validate(count >= 0)) {
428 return;
429 }
430 for (int i = 0; i < count; i++) {
431 buffer.readPath(&fPaths.push_back());
432 if (!buffer.isValid()) {
433 return;
434 }
435 }
436 } break;
437 case SK_PICT_TEXTBLOB_BUFFER_TAG:
438 new_array_from_buffer(buffer, size, fTextBlobs, SkTextBlobPriv::MakeFromBuffer);
439 break;
440 case SK_PICT_VERTICES_BUFFER_TAG:
441 new_array_from_buffer(buffer, size, fVertices, SkVerticesPriv::Decode);
442 break;
443 case SK_PICT_IMAGE_BUFFER_TAG:
444 new_array_from_buffer(buffer, size, fImages, create_image_from_buffer);
445 break;
446 case SK_PICT_READER_TAG: {
447 // Preflight check that we can initialize all data from the buffer
448 // before allocating it.
449 if (!buffer.validateCanReadN<uint8_t>(size)) {
450 return;
451 }
452 auto data(SkData::MakeUninitialized(size));
453 if (!buffer.readByteArray(data->writable_data(), size) ||
454 !buffer.validate(nullptr == fOpData)) {
455 return;
456 }
457 SkASSERT(nullptr == fOpData);
458 fOpData = std::move(data);
459 } break;
460 case SK_PICT_PICTURE_TAG:
461 new_array_from_buffer(buffer, size, fPictures, SkPicturePriv::MakeFromBuffer);
462 break;
463 case SK_PICT_DRAWABLE_TAG:
464 new_array_from_buffer(buffer, size, fDrawables, create_drawable_from_buffer);
465 break;
466 default:
467 buffer.validate(false); // The tag was invalid.
468 break;
469 }
470}
471
472SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
473 const SkPictInfo& info,
474 const SkDeserialProcs& procs,
475 SkTypefacePlayback* topLevelTFPlayback) {
476 std::unique_ptr<SkPictureData> data(new SkPictureData(info));
477 if (!topLevelTFPlayback) {
478 topLevelTFPlayback = &data->fTFPlayback;
479 }
480
481 if (!data->parseStream(stream, procs, topLevelTFPlayback)) {
482 return nullptr;
483 }
484 return data.release();
485}
486
487SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
488 const SkPictInfo& info) {
489 std::unique_ptr<SkPictureData> data(new SkPictureData(info));
490 buffer.setVersion(info.getVersion());
491
492 if (!data->parseBuffer(buffer)) {
493 return nullptr;
494 }
495 return data.release();
496}
497
498bool SkPictureData::parseStream(SkStream* stream,
499 const SkDeserialProcs& procs,
500 SkTypefacePlayback* topLevelTFPlayback) {
501 for (;;) {
502 uint32_t tag;
503 if (!stream->readU32(&tag)) { return false; }
504 if (SK_PICT_EOF_TAG == tag) {
505 break;
506 }
507
508 uint32_t size;
509 if (!stream->readU32(&size)) { return false; }
510 if (!this->parseStreamTag(stream, tag, size, procs, topLevelTFPlayback)) {
511 return false; // we're invalid
512 }
513 }
514 return true;
515}
516
517bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
518 while (buffer.isValid()) {
519 uint32_t tag = buffer.readUInt();
520 if (SK_PICT_EOF_TAG == tag) {
521 break;
522 }
523 this->parseBufferTag(buffer, tag, buffer.readUInt());
524 }
525
526 // Check that we encountered required tags
527 if (!buffer.validate(this->opData() != nullptr)) {
528 // If we didn't build any opData, we are invalid. Even an EmptyPicture allocates the
529 // SkData for the ops (though its length may be zero).
530 return false;
531 }
532 return true;
533}
534
535const SkPaint* SkPictureData::optionalPaint(SkReadBuffer* reader) const {
536 int index = reader->readInt();
537 if (index == 0) {
538 return nullptr; // recorder wrote a zero for no paint (likely drawimage)
539 }
540 return reader->validate(index > 0 && index <= fPaints.count()) ?
541 &fPaints[index - 1] : nullptr;
542}
543
544const SkPaint& SkPictureData::requiredPaint(SkReadBuffer* reader) const {
545 const SkPaint* paint = this->optionalPaint(reader);
546 if (reader->validate(paint != nullptr)) {
547 return *paint;
548 }
549 static const SkPaint& stub = *(new SkPaint);
550 return stub;
551}
552