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