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 #include <new>
8 #include "SkPictureData.h"
9 #include "SkPictureRecord.h"
10 #include "SkReadBuffer.h"
11 #include "SkTextBlob.h"
12 #include "SkTypeface.h"
13 #include "SkWriteBuffer.h"
14
15 #if SK_SUPPORT_GPU
16 #include "GrContext.h"
17 #endif
18
SafeCount(const T * obj)19 template <typename T> int SafeCount(const T* obj) {
20 return obj ? obj->count() : 0;
21 }
22
SkPictureData(const SkPictInfo & info)23 SkPictureData::SkPictureData(const SkPictInfo& info)
24 : fInfo(info) {
25 this->init();
26 }
27
initForPlayback() const28 void SkPictureData::initForPlayback() const {
29 // ensure that the paths bounds are pre-computed
30 for (int i = 0; i < fPaths.count(); i++) {
31 fPaths[i].updateBoundsCache();
32 }
33 }
34
SkPictureData(const SkPictureRecord & record,const SkPictInfo & info,bool deepCopyOps)35 SkPictureData::SkPictureData(const SkPictureRecord& record,
36 const SkPictInfo& info,
37 bool deepCopyOps)
38 : fInfo(info) {
39
40 this->init();
41
42 fOpData = record.opData(deepCopyOps);
43
44 fContentInfo.set(record.fContentInfo);
45
46 fBitmaps = record.fBitmaps;
47 fPaints = record.fPaints;
48 fPaths = record.fPaths;
49
50 this->initForPlayback();
51
52 const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs();
53 fPictureCount = pictures.count();
54 if (fPictureCount > 0) {
55 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
56 for (int i = 0; i < fPictureCount; i++) {
57 fPictureRefs[i] = pictures[i];
58 fPictureRefs[i]->ref();
59 }
60 }
61
62 // templatize to consolidate with similar picture logic?
63 const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs();
64 fTextBlobCount = blobs.count();
65 if (fTextBlobCount > 0) {
66 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount);
67 for (int i = 0; i < fTextBlobCount; ++i) {
68 fTextBlobRefs[i] = SkRef(blobs[i]);
69 }
70 }
71 }
72
init()73 void SkPictureData::init() {
74 fPictureRefs = NULL;
75 fPictureCount = 0;
76 fTextBlobRefs = NULL;
77 fTextBlobCount = 0;
78 fOpData = NULL;
79 fFactoryPlayback = NULL;
80 }
81
~SkPictureData()82 SkPictureData::~SkPictureData() {
83 SkSafeUnref(fOpData);
84
85 for (int i = 0; i < fPictureCount; i++) {
86 fPictureRefs[i]->unref();
87 }
88 SkDELETE_ARRAY(fPictureRefs);
89
90 for (int i = 0; i < fTextBlobCount; i++) {
91 fTextBlobRefs[i]->unref();
92 }
93 SkDELETE_ARRAY(fTextBlobRefs);
94
95 SkDELETE(fFactoryPlayback);
96 }
97
containsBitmaps() const98 bool SkPictureData::containsBitmaps() const {
99 if (fBitmaps.count() > 0) {
100 return true;
101 }
102 for (int i = 0; i < fPictureCount; ++i) {
103 if (fPictureRefs[i]->willPlayBackBitmaps()) {
104 return true;
105 }
106 }
107 return false;
108 }
109
110 ///////////////////////////////////////////////////////////////////////////////
111 ///////////////////////////////////////////////////////////////////////////////
112
113 #include "SkStream.h"
114
compute_chunk_size(SkFlattenable::Factory * array,int count)115 static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
116 size_t size = 4; // for 'count'
117
118 for (int i = 0; i < count; i++) {
119 const char* name = SkFlattenable::FactoryToName(array[i]);
120 if (NULL == name || 0 == *name) {
121 size += SkWStream::SizeOfPackedUInt(0);
122 } else {
123 size_t len = strlen(name);
124 size += SkWStream::SizeOfPackedUInt(len);
125 size += len;
126 }
127 }
128
129 return size;
130 }
131
write_tag_size(SkWriteBuffer & buffer,uint32_t tag,size_t size)132 static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
133 buffer.writeUInt(tag);
134 buffer.writeUInt(SkToU32(size));
135 }
136
write_tag_size(SkWStream * stream,uint32_t tag,size_t size)137 static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
138 stream->write32(tag);
139 stream->write32(SkToU32(size));
140 }
141
WriteFactories(SkWStream * stream,const SkFactorySet & rec)142 void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
143 int count = rec.count();
144
145 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
146 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
147 rec.copyToArray(array);
148
149 size_t size = compute_chunk_size(array, count);
150
151 // TODO: write_tag_size should really take a size_t
152 write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
153 SkDEBUGCODE(size_t start = stream->bytesWritten());
154 stream->write32(count);
155
156 for (int i = 0; i < count; i++) {
157 const char* name = SkFlattenable::FactoryToName(array[i]);
158 if (NULL == name || 0 == *name) {
159 stream->writePackedUInt(0);
160 } else {
161 size_t len = strlen(name);
162 stream->writePackedUInt(len);
163 stream->write(name, len);
164 }
165 }
166
167 SkASSERT(size == (stream->bytesWritten() - start));
168 }
169
WriteTypefaces(SkWStream * stream,const SkRefCntSet & rec)170 void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
171 int count = rec.count();
172
173 write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
174
175 SkAutoSTMalloc<16, SkTypeface*> storage(count);
176 SkTypeface** array = (SkTypeface**)storage.get();
177 rec.copyToArray((SkRefCnt**)array);
178
179 for (int i = 0; i < count; i++) {
180 #ifdef SK_PICTURE_FORCE_FONT_EMBEDDING
181 array[i]->serializeForcingEmbedding(stream);
182 #else
183 // TODO: if (embedFonts) { array[i]->serializeForcingEmbedding(stream) } else
184 array[i]->serialize(stream);
185 #endif
186 }
187 }
188
flattenToBuffer(SkWriteBuffer & buffer) const189 void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
190 int i, n;
191
192 if ((n = fBitmaps.count()) > 0) {
193 write_tag_size(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
194 for (i = 0; i < n; i++) {
195 buffer.writeBitmap(fBitmaps[i]);
196 }
197 }
198
199 if ((n = fPaints.count()) > 0) {
200 write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
201 for (i = 0; i < n; i++) {
202 buffer.writePaint(fPaints[i]);
203 }
204 }
205
206 if ((n = fPaths.count()) > 0) {
207 write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n);
208 buffer.writeInt(n);
209 for (int i = 0; i < n; i++) {
210 buffer.writePath(fPaths[i]);
211 }
212 }
213
214 if (fTextBlobCount > 0) {
215 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount);
216 for (i = 0; i < fTextBlobCount; ++i) {
217 fTextBlobRefs[i]->flatten(buffer);
218 }
219 }
220 }
221
serialize(SkWStream * stream,SkPixelSerializer * pixelSerializer) const222 void SkPictureData::serialize(SkWStream* stream,
223 SkPixelSerializer* pixelSerializer) const {
224 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
225 stream->write(fOpData->bytes(), fOpData->size());
226
227 if (fPictureCount > 0) {
228 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
229 for (int i = 0; i < fPictureCount; i++) {
230 fPictureRefs[i]->serialize(stream, pixelSerializer);
231 }
232 }
233
234 // Write some of our data into a writebuffer, and then serialize that
235 // into our stream
236 {
237 SkRefCntSet typefaceSet;
238 SkFactorySet factSet;
239
240 SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
241 buffer.setTypefaceRecorder(&typefaceSet);
242 buffer.setFactoryRecorder(&factSet);
243 buffer.setPixelSerializer(pixelSerializer);
244
245 this->flattenToBuffer(buffer);
246
247 // We have to write these two sets into the stream *before* we write
248 // the buffer, since parsing that buffer will require that we already
249 // have these sets available to use.
250 WriteFactories(stream, factSet);
251 WriteTypefaces(stream, typefaceSet);
252
253 write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
254 buffer.writeToStream(stream);
255 }
256
257 stream->write32(SK_PICT_EOF_TAG);
258 }
259
flatten(SkWriteBuffer & buffer) const260 void SkPictureData::flatten(SkWriteBuffer& buffer) const {
261 write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
262 buffer.writeByteArray(fOpData->bytes(), fOpData->size());
263
264 if (fPictureCount > 0) {
265 write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
266 for (int i = 0; i < fPictureCount; i++) {
267 fPictureRefs[i]->flatten(buffer);
268 }
269 }
270
271 // Write this picture playback's data into a writebuffer
272 this->flattenToBuffer(buffer);
273 buffer.write32(SK_PICT_EOF_TAG);
274 }
275
276 ///////////////////////////////////////////////////////////////////////////////
277
278 /**
279 * Return the corresponding SkReadBuffer flags, given a set of
280 * SkPictInfo flags.
281 */
pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags)282 static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
283 static const struct {
284 uint32_t fSrc;
285 uint32_t fDst;
286 } gSD[] = {
287 { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag },
288 { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag },
289 { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag },
290 };
291
292 uint32_t rbMask = 0;
293 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
294 if (pictInfoFlags & gSD[i].fSrc) {
295 rbMask |= gSD[i].fDst;
296 }
297 }
298 return rbMask;
299 }
300
parseStreamTag(SkStream * stream,uint32_t tag,uint32_t size,SkPicture::InstallPixelRefProc proc)301 bool SkPictureData::parseStreamTag(SkStream* stream,
302 uint32_t tag,
303 uint32_t size,
304 SkPicture::InstallPixelRefProc proc) {
305 /*
306 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
307 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
308 * but if they are present, they need to have been seen before the buffer.
309 *
310 * We assert that if/when we see either of these, that we have not yet seen
311 * the buffer tag, because if we have, then its too-late to deal with the
312 * factories or typefaces.
313 */
314 SkDEBUGCODE(bool haveBuffer = false;)
315
316 switch (tag) {
317 case SK_PICT_READER_TAG:
318 SkASSERT(NULL == fOpData);
319 fOpData = SkData::NewFromStream(stream, size);
320 if (!fOpData) {
321 return false;
322 }
323 break;
324 case SK_PICT_FACTORY_TAG: {
325 SkASSERT(!haveBuffer);
326 size = stream->readU32();
327 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
328 for (size_t i = 0; i < size; i++) {
329 SkString str;
330 const size_t len = stream->readPackedUInt();
331 str.resize(len);
332 if (stream->read(str.writable_str(), len) != len) {
333 return false;
334 }
335 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
336 }
337 } break;
338 case SK_PICT_TYPEFACE_TAG: {
339 SkASSERT(!haveBuffer);
340 const int count = SkToInt(size);
341 fTFPlayback.setCount(count);
342 for (int i = 0; i < count; i++) {
343 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream));
344 if (!tf.get()) { // failed to deserialize
345 // fTFPlayback asserts it never has a null, so we plop in
346 // the default here.
347 tf.reset(SkTypeface::RefDefault());
348 }
349 fTFPlayback.set(i, tf);
350 }
351 } break;
352 case SK_PICT_PICTURE_TAG: {
353 fPictureCount = size;
354 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
355 bool success = true;
356 int i = 0;
357 for ( ; i < fPictureCount; i++) {
358 fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc);
359 if (NULL == fPictureRefs[i]) {
360 success = false;
361 break;
362 }
363 }
364 if (!success) {
365 // Delete all of the pictures that were already created (up to but excluding i):
366 for (int j = 0; j < i; j++) {
367 fPictureRefs[j]->unref();
368 }
369 // Delete the array
370 SkDELETE_ARRAY(fPictureRefs);
371 fPictureCount = 0;
372 return false;
373 }
374 } break;
375 case SK_PICT_BUFFER_SIZE_TAG: {
376 SkAutoMalloc storage(size);
377 if (stream->read(storage.get(), size) != size) {
378 return false;
379 }
380
381 /* Should we use SkValidatingReadBuffer instead? */
382 SkReadBuffer buffer(storage.get(), size);
383 buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
384 buffer.setVersion(fInfo.fVersion);
385
386 fFactoryPlayback->setupBuffer(buffer);
387 fTFPlayback.setupBuffer(buffer);
388 buffer.setBitmapDecoder(proc);
389
390 while (!buffer.eof() && buffer.isValid()) {
391 tag = buffer.readUInt();
392 size = buffer.readUInt();
393 if (!this->parseBufferTag(buffer, tag, size)) {
394 return false;
395 }
396 }
397 if (!buffer.isValid()) {
398 return false;
399 }
400 SkDEBUGCODE(haveBuffer = true;)
401 } break;
402 }
403 return true; // success
404 }
405
parseBufferTag(SkReadBuffer & buffer,uint32_t tag,uint32_t size)406 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer,
407 uint32_t tag, uint32_t size) {
408 switch (tag) {
409 case SK_PICT_BITMAP_BUFFER_TAG: {
410 const int count = SkToInt(size);
411 fBitmaps.reset(count);
412 for (int i = 0; i < count; ++i) {
413 SkBitmap* bm = &fBitmaps[i];
414 if (buffer.readBitmap(bm)) {
415 bm->setImmutable();
416 } else {
417 return false;
418 }
419 }
420 } break;
421 case SK_PICT_PAINT_BUFFER_TAG: {
422 const int count = SkToInt(size);
423 fPaints.reset(count);
424 for (int i = 0; i < count; ++i) {
425 buffer.readPaint(&fPaints[i]);
426 }
427 } break;
428 case SK_PICT_PATH_BUFFER_TAG:
429 if (size > 0) {
430 const int count = buffer.readInt();
431 fPaths.reset(count);
432 for (int i = 0; i < count; i++) {
433 buffer.readPath(&fPaths[i]);
434 }
435 } break;
436 case SK_PICT_TEXTBLOB_BUFFER_TAG: {
437 if (!buffer.validate((0 == fTextBlobCount) && (NULL == fTextBlobRefs))) {
438 return false;
439 }
440 fTextBlobCount = size;
441 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount);
442 bool success = true;
443 int i = 0;
444 for ( ; i < fTextBlobCount; i++) {
445 fTextBlobRefs[i] = SkTextBlob::CreateFromBuffer(buffer);
446 if (NULL == fTextBlobRefs[i]) {
447 success = false;
448 break;
449 }
450 }
451 if (!success) {
452 // Delete all of the blobs that were already created (up to but excluding i):
453 for (int j = 0; j < i; j++) {
454 fTextBlobRefs[j]->unref();
455 }
456 // Delete the array
457 SkDELETE_ARRAY(fTextBlobRefs);
458 fTextBlobRefs = NULL;
459 fTextBlobCount = 0;
460 return false;
461 }
462 } break;
463 case SK_PICT_READER_TAG: {
464 SkAutoDataUnref data(SkData::NewUninitialized(size));
465 if (!buffer.readByteArray(data->writable_data(), size) ||
466 !buffer.validate(NULL == fOpData)) {
467 return false;
468 }
469 SkASSERT(NULL == fOpData);
470 fOpData = data.detach();
471 } break;
472 case SK_PICT_PICTURE_TAG: {
473 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) {
474 return false;
475 }
476 fPictureCount = size;
477 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
478 bool success = true;
479 int i = 0;
480 for ( ; i < fPictureCount; i++) {
481 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer);
482 if (NULL == fPictureRefs[i]) {
483 success = false;
484 break;
485 }
486 }
487 if (!success) {
488 // Delete all of the pictures that were already created (up to but excluding i):
489 for (int j = 0; j < i; j++) {
490 fPictureRefs[j]->unref();
491 }
492 // Delete the array
493 SkDELETE_ARRAY(fPictureRefs);
494 fPictureCount = 0;
495 return false;
496 }
497 } break;
498 default:
499 // The tag was invalid.
500 return false;
501 }
502 return true; // success
503 }
504
CreateFromStream(SkStream * stream,const SkPictInfo & info,SkPicture::InstallPixelRefProc proc)505 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
506 const SkPictInfo& info,
507 SkPicture::InstallPixelRefProc proc) {
508 SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
509
510 if (!data->parseStream(stream, proc)) {
511 return NULL;
512 }
513 return data.detach();
514 }
515
CreateFromBuffer(SkReadBuffer & buffer,const SkPictInfo & info)516 SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
517 const SkPictInfo& info) {
518 SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
519 buffer.setVersion(info.fVersion);
520
521 if (!data->parseBuffer(buffer)) {
522 return NULL;
523 }
524 return data.detach();
525 }
526
parseStream(SkStream * stream,SkPicture::InstallPixelRefProc proc)527 bool SkPictureData::parseStream(SkStream* stream,
528 SkPicture::InstallPixelRefProc proc) {
529 for (;;) {
530 uint32_t tag = stream->readU32();
531 if (SK_PICT_EOF_TAG == tag) {
532 break;
533 }
534
535 uint32_t size = stream->readU32();
536 if (!this->parseStreamTag(stream, tag, size, proc)) {
537 return false; // we're invalid
538 }
539 }
540 return true;
541 }
542
parseBuffer(SkReadBuffer & buffer)543 bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
544 for (;;) {
545 uint32_t tag = buffer.readUInt();
546 if (SK_PICT_EOF_TAG == tag) {
547 break;
548 }
549
550 uint32_t size = buffer.readUInt();
551 if (!this->parseBufferTag(buffer, tag, size)) {
552 return false; // we're invalid
553 }
554 }
555 return true;
556 }
557
558 ///////////////////////////////////////////////////////////////////////////////
559 ///////////////////////////////////////////////////////////////////////////////
560
561 #if SK_SUPPORT_GPU
suitableForGpuRasterization(GrContext * context,const char ** reason,int sampleCount) const562 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
563 int sampleCount) const {
564 return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
565 }
566
suitableForGpuRasterization(GrContext * context,const char ** reason,GrPixelConfig config,SkScalar dpi) const567 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
568 GrPixelConfig config, SkScalar dpi) const {
569
570 if (context != NULL) {
571 return this->suitableForGpuRasterization(context, reason,
572 context->getRecommendedSampleCount(config, dpi));
573 } else {
574 return this->suitableForGpuRasterization(NULL, reason);
575 }
576 }
577
suitableForLayerOptimization() const578 bool SkPictureData::suitableForLayerOptimization() const {
579 return fContentInfo.numLayers() > 0;
580 }
581 #endif
582 ///////////////////////////////////////////////////////////////////////////////
583
584
585