OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include <new> | 7 #include <new> |
8 #include "SkPictureData.h" | 8 #include "SkPictureData.h" |
9 #include "SkPictureRecord.h" | 9 #include "SkPictureRecord.h" |
10 #include "SkReadBuffer.h" | 10 #include "SkReadBuffer.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
61 | 61 |
62 // templatize to consolidate with similar picture logic? | 62 // templatize to consolidate with similar picture logic? |
63 const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs(); | 63 const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs(); |
64 fTextBlobCount = blobs.count(); | 64 fTextBlobCount = blobs.count(); |
65 if (fTextBlobCount > 0) { | 65 if (fTextBlobCount > 0) { |
66 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount); | 66 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount); |
67 for (int i = 0; i < fTextBlobCount; ++i) { | 67 for (int i = 0; i < fTextBlobCount; ++i) { |
68 fTextBlobRefs[i] = SkRef(blobs[i]); | 68 fTextBlobRefs[i] = SkRef(blobs[i]); |
69 } | 69 } |
70 } | 70 } |
71 | |
72 const SkTDArray<const SkImage*>& imgs = record.getImageRefs(); | |
73 fImageCount = imgs.count(); | |
74 if (fImageCount > 0) { | |
75 fImageRefs = SkNEW_ARRAY(const SkImage*, fImageCount); | |
76 for (int i = 0; i < fImageCount; ++i) { | |
77 fImageRefs[i] = SkRef(imgs[i]); | |
78 } | |
79 } | |
71 } | 80 } |
72 | 81 |
73 void SkPictureData::init() { | 82 void SkPictureData::init() { |
74 fPictureRefs = NULL; | 83 fPictureRefs = NULL; |
75 fPictureCount = 0; | 84 fPictureCount = 0; |
76 fTextBlobRefs = NULL; | 85 fTextBlobRefs = NULL; |
77 fTextBlobCount = 0; | 86 fTextBlobCount = 0; |
87 fImageRefs = NULL; | |
88 fImageCount = 0; | |
78 fOpData = NULL; | 89 fOpData = NULL; |
79 fFactoryPlayback = NULL; | 90 fFactoryPlayback = NULL; |
80 } | 91 } |
81 | 92 |
82 SkPictureData::~SkPictureData() { | 93 SkPictureData::~SkPictureData() { |
83 SkSafeUnref(fOpData); | 94 SkSafeUnref(fOpData); |
84 | 95 |
85 for (int i = 0; i < fPictureCount; i++) { | 96 for (int i = 0; i < fPictureCount; i++) { |
86 fPictureRefs[i]->unref(); | 97 fPictureRefs[i]->unref(); |
87 } | 98 } |
88 SkDELETE_ARRAY(fPictureRefs); | 99 SkDELETE_ARRAY(fPictureRefs); |
89 | 100 |
90 for (int i = 0; i < fTextBlobCount; i++) { | 101 for (int i = 0; i < fTextBlobCount; i++) { |
91 fTextBlobRefs[i]->unref(); | 102 fTextBlobRefs[i]->unref(); |
92 } | 103 } |
93 SkDELETE_ARRAY(fTextBlobRefs); | 104 SkDELETE_ARRAY(fTextBlobRefs); |
94 | 105 |
106 for (int i = 0; i < fImageCount; i++) { | |
107 fImageRefs[i]->unref(); | |
108 } | |
109 SkDELETE_ARRAY(fImageRefs); | |
110 | |
95 SkDELETE(fFactoryPlayback); | 111 SkDELETE(fFactoryPlayback); |
96 } | 112 } |
97 | 113 |
98 bool SkPictureData::containsBitmaps() const { | 114 bool SkPictureData::containsBitmaps() const { |
99 if (fBitmaps.count() > 0) { | 115 if (fBitmaps.count() > 0 || fImageCount > 0) { |
100 return true; | 116 return true; |
101 } | 117 } |
102 for (int i = 0; i < fPictureCount; ++i) { | 118 for (int i = 0; i < fPictureCount; ++i) { |
103 if (fPictureRefs[i]->willPlayBackBitmaps()) { | 119 if (fPictureRefs[i]->willPlayBackBitmaps()) { |
104 return true; | 120 return true; |
105 } | 121 } |
106 } | 122 } |
107 return false; | 123 return false; |
108 } | 124 } |
109 | 125 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 buffer.writePath(fPaths[i]); | 226 buffer.writePath(fPaths[i]); |
211 } | 227 } |
212 } | 228 } |
213 | 229 |
214 if (fTextBlobCount > 0) { | 230 if (fTextBlobCount > 0) { |
215 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount); | 231 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount); |
216 for (i = 0; i < fTextBlobCount; ++i) { | 232 for (i = 0; i < fTextBlobCount; ++i) { |
217 fTextBlobRefs[i]->flatten(buffer); | 233 fTextBlobRefs[i]->flatten(buffer); |
218 } | 234 } |
219 } | 235 } |
236 | |
237 if (fImageCount > 0) { | |
238 write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImageCount); | |
239 for (i = 0; i < fImageCount; ++i) { | |
240 buffer.writeImage(fImageRefs[i]); | |
241 } | |
242 } | |
220 } | 243 } |
221 | 244 |
222 void SkPictureData::serialize(SkWStream* stream, | 245 void SkPictureData::serialize(SkWStream* stream, |
223 SkPixelSerializer* pixelSerializer) const { | 246 SkPixelSerializer* pixelSerializer) const { |
224 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size()); | 247 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size()); |
225 stream->write(fOpData->bytes(), fOpData->size()); | 248 stream->write(fOpData->bytes(), fOpData->size()); |
226 | 249 |
227 if (fPictureCount > 0) { | 250 if (fPictureCount > 0) { |
228 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount); | 251 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount); |
229 for (int i = 0; i < fPictureCount; i++) { | 252 for (int i = 0; i < fPictureCount; i++) { |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
396 } | 419 } |
397 if (!buffer.isValid()) { | 420 if (!buffer.isValid()) { |
398 return false; | 421 return false; |
399 } | 422 } |
400 SkDEBUGCODE(haveBuffer = true;) | 423 SkDEBUGCODE(haveBuffer = true;) |
401 } break; | 424 } break; |
402 } | 425 } |
403 return true; // success | 426 return true; // success |
404 } | 427 } |
405 | 428 |
406 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, | 429 static const SkImage* create_image_from_buffer(SkReadBuffer& buffer) { |
407 uint32_t tag, uint32_t size) { | 430 int width = buffer.read32(); |
431 int height = buffer.read32(); | |
432 if (width < 0 || height < 0) { | |
scroggo
2015/06/22 17:40:01
I thought images had to have non-zero dimensions?
reed1
2015/06/22 18:41:50
Done.
| |
433 buffer.validate(false); | |
434 return NULL; | |
435 } | |
436 | |
437 SkAutoTUnref<SkData> encoded(buffer.readByteArrayAsData()); | |
438 int originX = buffer.read32(); | |
439 int originY = buffer.read32(); | |
440 if (!encoded || originX < 0 || originY < 0) { | |
scroggo
2015/06/22 17:40:01
It looks like readByteArrayAsData() always returns
reed1
2015/06/22 18:41:51
Done.
| |
441 buffer.validate(false); | |
442 return NULL; | |
443 } | |
444 | |
445 const SkIRect subset = SkIRect::MakeXYWH(originX, originY, width, height); | |
446 return SkImage::NewFromEncoded(encoded, &subset); | |
447 } | |
448 | |
449 static const SkPicture* create_picture_from_buffer(SkReadBuffer& buffer) { | |
scroggo
2015/06/22 17:40:01
Can we not just use SkPicture::CreateFromBuffer di
reed1
2015/06/22 18:41:51
That is defined to return SkPicture*, but the othe
| |
450 return SkPicture::CreateFromBuffer(buffer); | |
451 } | |
452 | |
453 template <typename T> | |
454 bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t size, | |
scroggo
2015/06/22 17:40:01
I found this signature confusing until I found the
reed1
2015/06/22 18:41:50
Done.
| |
455 const T**& array, int& count, const T* (*factory)(SkR eadBuffer&)) { | |
scroggo
2015/06/22 17:40:01
nit: Don't we typically use pointers for variables
reed1
2015/06/22 18:41:51
Done.
| |
456 if (!buffer.validate((0 == count) && (NULL == array))) { | |
457 return false; | |
458 } | |
459 count = size; | |
460 array = SkNEW_ARRAY(const T*, count); | |
scroggo
2015/06/22 17:40:01
If size is 0, we dutifully create a 0 size array.
reed1
2015/06/22 18:41:50
Done.
| |
461 bool success = true; | |
462 int i = 0; | |
463 for (; i < count; i++) { | |
464 array[i] = factory(buffer); | |
465 if (NULL == array[i]) { | |
466 success = false; | |
467 break; | |
468 } | |
469 } | |
470 if (!success) { | |
471 // Delete all of the blobs that were already created (up to but excludin g i): | |
472 for (int j = 0; j < i; j++) { | |
473 array[j]->unref(); | |
474 } | |
475 // Delete the array | |
476 SkDELETE_ARRAY(array); | |
477 array = NULL; | |
478 count = 0; | |
479 return false; | |
scroggo
2015/06/22 17:40:01
Should we validate(false) the buffer? Or do we ass
reed1
2015/06/22 18:41:51
I think we assume the factories did it, if somethi
| |
480 } | |
481 return true; | |
482 } | |
483 | |
484 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size) { | |
408 switch (tag) { | 485 switch (tag) { |
409 case SK_PICT_BITMAP_BUFFER_TAG: { | 486 case SK_PICT_BITMAP_BUFFER_TAG: { |
410 const int count = SkToInt(size); | 487 const int count = SkToInt(size); |
411 fBitmaps.reset(count); | 488 fBitmaps.reset(count); |
412 for (int i = 0; i < count; ++i) { | 489 for (int i = 0; i < count; ++i) { |
413 SkBitmap* bm = &fBitmaps[i]; | 490 SkBitmap* bm = &fBitmaps[i]; |
414 if (buffer.readBitmap(bm)) { | 491 if (buffer.readBitmap(bm)) { |
415 bm->setImmutable(); | 492 bm->setImmutable(); |
416 } else { | 493 } else { |
417 return false; | 494 return false; |
418 } | 495 } |
419 } | 496 } |
420 } break; | 497 } break; |
421 case SK_PICT_PAINT_BUFFER_TAG: { | 498 case SK_PICT_PAINT_BUFFER_TAG: { |
422 const int count = SkToInt(size); | 499 const int count = SkToInt(size); |
423 fPaints.reset(count); | 500 fPaints.reset(count); |
424 for (int i = 0; i < count; ++i) { | 501 for (int i = 0; i < count; ++i) { |
425 buffer.readPaint(&fPaints[i]); | 502 buffer.readPaint(&fPaints[i]); |
426 } | 503 } |
427 } break; | 504 } break; |
428 case SK_PICT_PATH_BUFFER_TAG: | 505 case SK_PICT_PATH_BUFFER_TAG: |
429 if (size > 0) { | 506 if (size > 0) { |
430 const int count = buffer.readInt(); | 507 const int count = buffer.readInt(); |
431 fPaths.reset(count); | 508 fPaths.reset(count); |
432 for (int i = 0; i < count; i++) { | 509 for (int i = 0; i < count; i++) { |
433 buffer.readPath(&fPaths[i]); | 510 buffer.readPath(&fPaths[i]); |
434 } | 511 } |
435 } break; | 512 } break; |
436 case SK_PICT_TEXTBLOB_BUFFER_TAG: { | 513 case SK_PICT_TEXTBLOB_BUFFER_TAG: |
437 if (!buffer.validate((0 == fTextBlobCount) && (NULL == fTextBlobRefs ))) { | 514 if (!new_array_from_buffer(buffer, size, fTextBlobRefs, fTextBlobCou nt, |
515 SkTextBlob::CreateFromBuffer)) { | |
438 return false; | 516 return false; |
439 } | 517 } |
440 fTextBlobCount = size; | 518 break; |
441 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount); | 519 case SK_PICT_IMAGE_BUFFER_TAG: |
442 bool success = true; | 520 if (!new_array_from_buffer(buffer, size, fImageRefs, fImageCount, |
443 int i = 0; | 521 create_image_from_buffer)) { |
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; | 522 return false; |
461 } | 523 } |
462 } break; | 524 break; |
463 case SK_PICT_READER_TAG: { | 525 case SK_PICT_READER_TAG: { |
464 SkAutoDataUnref data(SkData::NewUninitialized(size)); | 526 SkAutoDataUnref data(SkData::NewUninitialized(size)); |
465 if (!buffer.readByteArray(data->writable_data(), size) || | 527 if (!buffer.readByteArray(data->writable_data(), size) || |
466 !buffer.validate(NULL == fOpData)) { | 528 !buffer.validate(NULL == fOpData)) { |
467 return false; | 529 return false; |
468 } | 530 } |
469 SkASSERT(NULL == fOpData); | 531 SkASSERT(NULL == fOpData); |
470 fOpData = data.detach(); | 532 fOpData = data.detach(); |
471 } break; | 533 } break; |
472 case SK_PICT_PICTURE_TAG: { | 534 case SK_PICT_PICTURE_TAG: |
473 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs)) ) { | 535 if (!new_array_from_buffer(buffer, size, fPictureRefs, fPictureCount , |
536 create_picture_from_buffer)) { | |
474 return false; | 537 return false; |
475 } | 538 } |
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 b ut 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: | 539 default: |
499 // The tag was invalid. | 540 // The tag was invalid. |
500 return false; | 541 return false; |
501 } | 542 } |
502 return true; // success | 543 return true; // success |
503 } | 544 } |
504 | 545 |
505 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream, | 546 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream, |
506 const SkPictInfo& info, | 547 const SkPictInfo& info, |
507 SkPicture::InstallPixelRefProc pr oc) { | 548 SkPicture::InstallPixelRefProc pr oc) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 } | 616 } |
576 } | 617 } |
577 | 618 |
578 bool SkPictureData::suitableForLayerOptimization() const { | 619 bool SkPictureData::suitableForLayerOptimization() const { |
579 return fContentInfo.numLayers() > 0; | 620 return fContentInfo.numLayers() > 0; |
580 } | 621 } |
581 #endif | 622 #endif |
582 /////////////////////////////////////////////////////////////////////////////// | 623 /////////////////////////////////////////////////////////////////////////////// |
583 | 624 |
584 | 625 |
OLD | NEW |