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 | 7 |
8 #include "SkPictureRecord.h" | 8 #include "SkPictureRecord.h" |
9 #include "SkImage_Base.h" | 9 #include "SkImage_Base.h" |
10 #include "SkPatchUtils.h" | 10 #include "SkPatchUtils.h" |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 fContentInfo.onDrawPath(path, paint); | 461 fContentInfo.onDrawPath(path, paint); |
462 | 462 |
463 // op + paint index + path index | 463 // op + paint index + path index |
464 size_t size = 3 * kUInt32Size; | 464 size_t size = 3 * kUInt32Size; |
465 size_t initialOffset = this->addDraw(DRAW_PATH, &size); | 465 size_t initialOffset = this->addDraw(DRAW_PATH, &size); |
466 this->addPaint(paint); | 466 this->addPaint(paint); |
467 this->addPath(path); | 467 this->addPath(path); |
468 this->validate(initialOffset, size); | 468 this->validate(initialOffset, size); |
469 } | 469 } |
470 | 470 |
471 void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScal
ar top, | |
472 const SkPaint* paint) { | |
473 // op + paint index + bitmap index + left + top | |
474 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar); | |
475 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size); | |
476 this->addPaintPtr(paint); | |
477 this->addBitmap(bitmap); | |
478 this->addScalar(left); | |
479 this->addScalar(top); | |
480 this->validate(initialOffset, size); | |
481 } | |
482 | |
483 void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src
, const SkRect& dst, | |
484 const SkPaint* paint, SrcRectConstraint c
onstraint) { | |
485 // id + paint index + bitmap index + bool for 'src' + flags | |
486 size_t size = 5 * kUInt32Size; | |
487 if (src) { | |
488 size += sizeof(*src); // + rect | |
489 } | |
490 size += sizeof(dst); // + rect | |
491 | |
492 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT, &size); | |
493 this->addPaintPtr(paint); | |
494 this->addBitmap(bitmap); | |
495 this->addRectPtr(src); // may be null | |
496 this->addRect(dst); | |
497 this->addInt(constraint); | |
498 this->validate(initialOffset, size); | |
499 } | |
500 | |
501 void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, | 471 void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, |
502 const SkPaint* paint) { | 472 const SkPaint* paint) { |
503 // op + paint_index + image_index + x + y | 473 // op + paint_index + image_index + x + y |
504 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar); | 474 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar); |
505 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size); | 475 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size); |
506 this->addPaintPtr(paint); | 476 this->addPaintPtr(paint); |
507 this->addImage(image); | 477 this->addImage(image); |
508 this->addScalar(x); | 478 this->addScalar(x); |
509 this->addScalar(y); | 479 this->addScalar(y); |
510 this->validate(initialOffset, size); | 480 this->validate(initialOffset, size); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect); | 522 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect); |
553 | 523 |
554 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size); | 524 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size); |
555 this->addPaintPtr(paint); | 525 this->addPaintPtr(paint); |
556 this->addImage(img); | 526 this->addImage(img); |
557 this->addIRect(center); | 527 this->addIRect(center); |
558 this->addRect(dst); | 528 this->addRect(dst); |
559 this->validate(initialOffset, size); | 529 this->validate(initialOffset, size); |
560 } | 530 } |
561 | 531 |
562 void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& ce
nter, | |
563 const SkRect& dst, const SkPaint* paint)
{ | |
564 // op + paint index + bitmap id + center + dst rect | |
565 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst); | |
566 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size); | |
567 this->addPaintPtr(paint); | |
568 this->addBitmap(bitmap); | |
569 this->addIRect(center); | |
570 this->addRect(dst); | |
571 this->validate(initialOffset, size); | |
572 } | |
573 | |
574 void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x
, SkScalar y, | 532 void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x
, SkScalar y, |
575 const SkPaint& paint) { | 533 const SkPaint& paint) { |
576 // op + paint index + length + 'length' worth of chars + x + y | 534 // op + paint index + length + 'length' worth of chars + x + y |
577 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar); | 535 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar); |
578 | 536 |
579 DrawType op = DRAW_TEXT; | 537 DrawType op = DRAW_TEXT; |
580 size_t initialOffset = this->addDraw(op, &size); | 538 size_t initialOffset = this->addDraw(op, &size); |
581 this->addPaint(paint); | 539 this->addPaint(paint); |
582 this->addText(text, byteLength); | 540 this->addText(text, byteLength); |
583 this->addScalar(x); | 541 this->addScalar(x); |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 fWriter.writeData(value); | 838 fWriter.writeData(value); |
881 this->validate(initialOffset, size); | 839 this->validate(initialOffset, size); |
882 } | 840 } |
883 | 841 |
884 /////////////////////////////////////////////////////////////////////////////// | 842 /////////////////////////////////////////////////////////////////////////////// |
885 | 843 |
886 sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const Sk
SurfaceProps&) { | 844 sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const Sk
SurfaceProps&) { |
887 return nullptr; | 845 return nullptr; |
888 } | 846 } |
889 | 847 |
890 // If we already have a stored, can we reuse it instead of also storing b? | |
891 static bool equivalent(const SkBitmap& a, const SkBitmap& b) { | |
892 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) { | |
893 // Requiring a.info() == b.info() may be overkill in some cases (alphaty
pe mismatch), | |
894 // but it sure makes things easier to reason about below. | |
895 return false; | |
896 } | |
897 if (a.pixelRef() == b.pixelRef()) { | |
898 return true; // Same shape and same pixels -> same bitmap. | |
899 } | |
900 | |
901 // From here down we're going to have to look at the bitmap data, so we requ
ire pixelRefs(). | |
902 if (!a.pixelRef() || !b.pixelRef()) { | |
903 return false; | |
904 } | |
905 | |
906 // If the bitmaps have encoded data, check first before locking pixels so th
ey don't decode. | |
907 sk_sp<SkData> encA(a.pixelRef()->refEncodedData()), | |
908 encB(b.pixelRef()->refEncodedData()); | |
909 if (encA && encB) { | |
910 return encA->equals(encB.get()); | |
911 } else if (encA || encB) { | |
912 return false; // One has encoded data but the other does not. | |
913 } | |
914 | |
915 // As a last resort, we have to look at the pixels. This will read back tex
tures. | |
916 SkAutoLockPixels al(a), bl(b); | |
917 const char* ap = (const char*)a.getPixels(); | |
918 const char* bp = (const char*)b.getPixels(); | |
919 if (ap && bp) { | |
920 // We check row by row; row bytes might differ. | |
921 SkASSERT(a.info() == b.info()); // We checked this above. | |
922 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this b
etter be true. | |
923 const SkImageInfo info = a.info(); | |
924 const size_t bytesToCompare = info.width() * info.bytesPerPixel(); | |
925 for (int row = 0; row < info.height(); row++) { | |
926 if (0 != memcmp(ap, bp, bytesToCompare)) { | |
927 return false; | |
928 } | |
929 ap += a.rowBytes(); | |
930 bp += b.rowBytes(); | |
931 } | |
932 return true; | |
933 } | |
934 return false; // Couldn't get pixels for both bitmaps. | |
935 } | |
936 | |
937 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) { | |
938 // First see if we already have this bitmap. This deduplication should real
ly | |
939 // only be important for our tests, where bitmaps tend not to be tagged immu
table. | |
940 // In Chrome (and hopefully Android?) they're typically immutable. | |
941 for (int i = 0; i < fBitmaps.count(); i++) { | |
942 if (equivalent(fBitmaps[i], bitmap)) { | |
943 this->addInt(i); // Unlike the rest, bitmap indices are 0-based. | |
944 return; | |
945 } | |
946 } | |
947 // Don't have it. We'll add it to our list, making sure it's tagged as immu
table. | |
948 if (bitmap.isImmutable()) { | |
949 // Shallow copies of bitmaps are cheap, so immutable == fast. | |
950 fBitmaps.push_back(bitmap); | |
951 } else { | |
952 // If you see this block on a memory profile, it's a good opportunity to
reduce RAM usage. | |
953 SkBitmap copy; | |
954 bitmap.copyTo(©); | |
955 copy.setImmutable(); | |
956 fBitmaps.push_back(copy); | |
957 } | |
958 this->addInt(fBitmaps.count()-1); // Remember, 0-based. | |
959 } | |
960 | |
961 void SkPictureRecord::addImage(const SkImage* image) { | 848 void SkPictureRecord::addImage(const SkImage* image) { |
962 int index = fImageRefs.find(image); | 849 int index = fImageRefs.find(image); |
963 if (index >= 0) { | 850 if (index >= 0) { |
964 this->addInt(index); | 851 this->addInt(index); |
965 } else { | 852 } else { |
966 *fImageRefs.append() = SkRef(image); | 853 *fImageRefs.append() = SkRef(image); |
967 this->addInt(fImageRefs.count()-1); | 854 this->addInt(fImageRefs.count()-1); |
968 } | 855 } |
969 } | 856 } |
970 | 857 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 | 958 |
1072 void SkPictureRecord::addTextBlob(const SkTextBlob *blob) { | 959 void SkPictureRecord::addTextBlob(const SkTextBlob *blob) { |
1073 int index = fTextBlobRefs.count(); | 960 int index = fTextBlobRefs.count(); |
1074 *fTextBlobRefs.append() = blob; | 961 *fTextBlobRefs.append() = blob; |
1075 blob->ref(); | 962 blob->ref(); |
1076 // follow the convention of recording a 1-based index | 963 // follow the convention of recording a 1-based index |
1077 this->addInt(index + 1); | 964 this->addInt(index + 1); |
1078 } | 965 } |
1079 | 966 |
1080 /////////////////////////////////////////////////////////////////////////////// | 967 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |