| 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 |