OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2008 The Android Open Source Project | 3 * Copyright 2008 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 result->swap(dst); | 814 result->swap(dst); |
815 return true; | 815 return true; |
816 } | 816 } |
817 | 817 |
818 /////////////////////////////////////////////////////////////////////////////// | 818 /////////////////////////////////////////////////////////////////////////////// |
819 | 819 |
820 #include "SkCanvas.h" | 820 #include "SkCanvas.h" |
821 #include "SkPaint.h" | 821 #include "SkPaint.h" |
822 | 822 |
823 bool SkBitmap::canCopyTo(SkColorType dstColorType) const { | 823 bool SkBitmap::canCopyTo(SkColorType dstColorType) const { |
824 const SkColorType srcCT = this->colorType(); | 824 if (this->colorType() == kUnknown_SkColorType) { |
825 | |
826 if (srcCT == kUnknown_SkColorType) { | |
827 return false; | 825 return false; |
828 } | 826 } |
829 | 827 |
830 bool sameConfigs = (srcCT == dstColorType); | 828 bool sameConfigs = (this->colorType() == dstColorType); |
831 switch (dstColorType) { | 829 switch (dstColorType) { |
832 case kAlpha_8_SkColorType: | 830 case kAlpha_8_SkColorType: |
833 case kRGB_565_SkColorType: | 831 case kRGB_565_SkColorType: |
834 case kRGBA_8888_SkColorType: | 832 case kRGBA_8888_SkColorType: |
835 case kBGRA_8888_SkColorType: | 833 case kBGRA_8888_SkColorType: |
836 break; | 834 break; |
837 case kIndex_8_SkColorType: | 835 case kIndex_8_SkColorType: |
838 if (!sameConfigs) { | 836 if (!sameConfigs) { |
839 return false; | 837 return false; |
840 } | 838 } |
841 break; | 839 break; |
842 case kARGB_4444_SkColorType: | 840 case kARGB_4444_SkColorType: |
843 return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorT
ype == srcCT; | 841 return sameConfigs || kN32_SkColorType == this->colorType(); |
844 default: | 842 default: |
845 return false; | 843 return false; |
846 } | 844 } |
847 return true; | 845 return true; |
848 } | 846 } |
849 | 847 |
850 #include "SkConfig8888.h" | 848 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, |
851 | 849 Allocator* alloc) const { |
852 bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels,
size_t dstRB, | |
853 int x, int y) const { | |
854 if (kUnknown_SkColorType == requestedDstInfo.colorType()) { | |
855 return false; | |
856 } | |
857 if (NULL == dstPixels || dstRB < requestedDstInfo.minRowBytes()) { | |
858 return false; | |
859 } | |
860 if (0 == requestedDstInfo.width() || 0 == requestedDstInfo.height()) { | |
861 return false; | |
862 } | |
863 | |
864 SkIRect srcR = SkIRect::MakeXYWH(x, y, requestedDstInfo.width(), requestedDs
tInfo.height()); | |
865 if (!srcR.intersect(0, 0, this->width(), this->height())) { | |
866 return false; | |
867 } | |
868 | |
869 SkImageInfo dstInfo = requestedDstInfo; | |
870 // the intersect may have shrunk info's logical size | |
871 dstInfo.fWidth = srcR.width(); | |
872 dstInfo.fHeight = srcR.height(); | |
873 | |
874 // if x or y are negative, then we have to adjust pixels | |
875 if (x > 0) { | |
876 x = 0; | |
877 } | |
878 if (y > 0) { | |
879 y = 0; | |
880 } | |
881 // here x,y are either 0 or negative | |
882 dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel()); | |
883 | |
884 ////////////// | |
885 | |
886 SkAutoLockPixels alp(*this); | |
887 | |
888 // since we don't stop creating un-pixeled devices yet, check for no pixels
here | |
889 if (NULL == this->getPixels()) { | |
890 return false; | |
891 } | |
892 | |
893 SkImageInfo srcInfo = this->info(); | |
894 srcInfo.fWidth = dstInfo.width(); | |
895 srcInfo.fHeight = dstInfo.height(); | |
896 | |
897 const void* srcPixels = this->getAddr(srcR.x(), srcR.y()); | |
898 return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels
, this->rowBytes(), | |
899 this->getColorTable()); | |
900 } | |
901 | |
902 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc)
const { | |
903 if (!this->canCopyTo(dstColorType)) { | 850 if (!this->canCopyTo(dstColorType)) { |
904 return false; | 851 return false; |
905 } | 852 } |
906 | 853 |
907 // if we have a texture, first get those pixels | 854 // if we have a texture, first get those pixels |
908 SkBitmap tmpSrc; | 855 SkBitmap tmpSrc; |
909 const SkBitmap* src = this; | 856 const SkBitmap* src = this; |
910 | 857 |
911 if (fPixelRef) { | 858 if (fPixelRef) { |
912 SkIRect subset; | 859 SkIRect subset; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
965 | 912 |
966 if (!tmpDst.readyToDraw()) { | 913 if (!tmpDst.readyToDraw()) { |
967 // allocator/lock failed | 914 // allocator/lock failed |
968 return false; | 915 return false; |
969 } | 916 } |
970 | 917 |
971 // pixelRef must be non NULL or tmpDst.readyToDraw() would have | 918 // pixelRef must be non NULL or tmpDst.readyToDraw() would have |
972 // returned false. | 919 // returned false. |
973 SkASSERT(tmpDst.pixelRef() != NULL); | 920 SkASSERT(tmpDst.pixelRef() != NULL); |
974 | 921 |
975 if (!src->readPixels(tmpDst.info(), tmpDst.getPixels(), tmpDst.rowBytes(), 0
, 0)) { | 922 /* do memcpy for the same configs cases, else use drawing |
976 return false; | 923 */ |
977 } | 924 if (src->colorType() == dstColorType) { |
| 925 if (tmpDst.getSize() == src->getSize()) { |
| 926 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); |
978 | 927 |
979 // (for BitmapHeap) Clone the pixelref genID even though we have a new pixe
lref. | 928 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); |
980 // The old copyTo impl did this, so we continue it for now. | 929 if (dstPixelRef->info() == fPixelRef->info()) { |
981 // | 930 dstPixelRef->cloneGenID(*fPixelRef); |
982 // TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be | 931 } |
983 // if (src_pixelref->info == dst_pixelref->info) | 932 } else { |
984 // | 933 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); |
985 if (src->colorType() == dstColorType && tmpDst.getSize() == src->getSize())
{ | 934 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); |
986 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); | 935 // to be sure we don't read too much, only copy our logical pixels |
987 if (dstPixelRef->info() == fPixelRef->info()) { | 936 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); |
988 dstPixelRef->cloneGenID(*fPixelRef); | 937 for (int y = 0; y < tmpDst.height(); y++) { |
| 938 memcpy(dstP, srcP, bytesToCopy); |
| 939 srcP += src->rowBytes(); |
| 940 dstP += tmpDst.rowBytes(); |
| 941 } |
989 } | 942 } |
| 943 } else if (kARGB_4444_SkColorType == dstColorType |
| 944 && kN32_SkColorType == src->colorType()) { |
| 945 if (src->alphaType() == kUnpremul_SkAlphaType) { |
| 946 // Our method for converting to 4444 assumes premultiplied. |
| 947 return false; |
| 948 } |
| 949 SkASSERT(src->height() == tmpDst.height()); |
| 950 SkASSERT(src->width() == tmpDst.width()); |
| 951 for (int y = 0; y < src->height(); ++y) { |
| 952 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0,
y); |
| 953 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); |
| 954 DITHER_4444_SCAN(y); |
| 955 for (int x = 0; x < src->width(); ++x) { |
| 956 dstRow[x] = SkDitherARGB32To4444(srcRow[x], |
| 957 DITHER_VALUE(x)); |
| 958 } |
| 959 } |
| 960 } else { |
| 961 if (tmpDst.alphaType() == kUnpremul_SkAlphaType) { |
| 962 // We do not support drawing to unpremultiplied bitmaps. |
| 963 return false; |
| 964 } |
| 965 |
| 966 // Always clear the dest in case one of the blitters accesses it |
| 967 // TODO: switch the allocation of tmpDst to call sk_calloc_throw |
| 968 tmpDst.eraseColor(SK_ColorTRANSPARENT); |
| 969 |
| 970 SkCanvas canvas(tmpDst); |
| 971 SkPaint paint; |
| 972 |
| 973 paint.setDither(true); |
| 974 canvas.drawBitmap(*src, 0, 0, &paint); |
990 } | 975 } |
991 | 976 |
992 dst->swap(tmpDst); | 977 dst->swap(tmpDst); |
993 return true; | 978 return true; |
994 } | 979 } |
995 | 980 |
996 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { | 981 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { |
997 const SkColorType dstCT = this->colorType(); | 982 const SkColorType dstCT = this->colorType(); |
998 | 983 |
999 if (!this->canCopyTo(dstCT)) { | 984 if (!this->canCopyTo(dstCT)) { |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1398 /////////////////////////////////////////////////////////////////////////////// | 1383 /////////////////////////////////////////////////////////////////////////////// |
1399 | 1384 |
1400 #ifdef SK_DEBUG | 1385 #ifdef SK_DEBUG |
1401 void SkImageInfo::validate() const { | 1386 void SkImageInfo::validate() const { |
1402 SkASSERT(fWidth >= 0); | 1387 SkASSERT(fWidth >= 0); |
1403 SkASSERT(fHeight >= 0); | 1388 SkASSERT(fHeight >= 0); |
1404 SkASSERT(SkColorTypeIsValid(fColorType)); | 1389 SkASSERT(SkColorTypeIsValid(fColorType)); |
1405 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1390 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
1406 } | 1391 } |
1407 #endif | 1392 #endif |
OLD | NEW |