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 if (this->colorType() == kUnknown_SkColorType) { | 824 const SkColorType srcCT = this->colorType(); |
| 825 |
| 826 if (srcCT == kUnknown_SkColorType) { |
825 return false; | 827 return false; |
826 } | 828 } |
827 | 829 |
828 bool sameConfigs = (this->colorType() == dstColorType); | 830 bool sameConfigs = (srcCT == dstColorType); |
829 switch (dstColorType) { | 831 switch (dstColorType) { |
830 case kAlpha_8_SkColorType: | 832 case kAlpha_8_SkColorType: |
831 case kRGB_565_SkColorType: | 833 case kRGB_565_SkColorType: |
832 case kRGBA_8888_SkColorType: | 834 case kRGBA_8888_SkColorType: |
833 case kBGRA_8888_SkColorType: | 835 case kBGRA_8888_SkColorType: |
834 break; | 836 break; |
835 case kIndex_8_SkColorType: | 837 case kIndex_8_SkColorType: |
836 if (!sameConfigs) { | 838 if (!sameConfigs) { |
837 return false; | 839 return false; |
838 } | 840 } |
839 break; | 841 break; |
840 case kARGB_4444_SkColorType: | 842 case kARGB_4444_SkColorType: |
841 return sameConfigs || kN32_SkColorType == this->colorType(); | 843 return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorT
ype == srcCT; |
842 default: | 844 default: |
843 return false; | 845 return false; |
844 } | 846 } |
845 return true; | 847 return true; |
846 } | 848 } |
847 | 849 |
848 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, | 850 #include "SkConfig8888.h" |
849 Allocator* alloc) const { | 851 |
| 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 { |
850 if (!this->canCopyTo(dstColorType)) { | 903 if (!this->canCopyTo(dstColorType)) { |
851 return false; | 904 return false; |
852 } | 905 } |
853 | 906 |
854 // if we have a texture, first get those pixels | 907 // if we have a texture, first get those pixels |
855 SkBitmap tmpSrc; | 908 SkBitmap tmpSrc; |
856 const SkBitmap* src = this; | 909 const SkBitmap* src = this; |
857 | 910 |
858 if (fPixelRef) { | 911 if (fPixelRef) { |
859 SkIRect subset; | 912 SkIRect subset; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 | 965 |
913 if (!tmpDst.readyToDraw()) { | 966 if (!tmpDst.readyToDraw()) { |
914 // allocator/lock failed | 967 // allocator/lock failed |
915 return false; | 968 return false; |
916 } | 969 } |
917 | 970 |
918 // pixelRef must be non NULL or tmpDst.readyToDraw() would have | 971 // pixelRef must be non NULL or tmpDst.readyToDraw() would have |
919 // returned false. | 972 // returned false. |
920 SkASSERT(tmpDst.pixelRef() != NULL); | 973 SkASSERT(tmpDst.pixelRef() != NULL); |
921 | 974 |
922 /* do memcpy for the same configs cases, else use drawing | 975 if (!src->readPixels(tmpDst.info(), tmpDst.getPixels(), tmpDst.rowBytes(), 0
, 0)) { |
923 */ | 976 return false; |
924 if (src->colorType() == dstColorType) { | 977 } |
925 if (tmpDst.getSize() == src->getSize()) { | |
926 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); | |
927 | 978 |
928 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); | 979 // (for BitmapHeap) Clone the pixelref genID even though we have a new pixe
lref. |
929 if (dstPixelRef->info() == fPixelRef->info()) { | 980 // The old copyTo impl did this, so we continue it for now. |
930 dstPixelRef->cloneGenID(*fPixelRef); | 981 // |
931 } | 982 // TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be |
932 } else { | 983 // if (src_pixelref->info == dst_pixelref->info) |
933 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); | 984 // |
934 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); | 985 if (src->colorType() == dstColorType && tmpDst.getSize() == src->getSize())
{ |
935 // to be sure we don't read too much, only copy our logical pixels | 986 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); |
936 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); | 987 if (dstPixelRef->info() == fPixelRef->info()) { |
937 for (int y = 0; y < tmpDst.height(); y++) { | 988 dstPixelRef->cloneGenID(*fPixelRef); |
938 memcpy(dstP, srcP, bytesToCopy); | |
939 srcP += src->rowBytes(); | |
940 dstP += tmpDst.rowBytes(); | |
941 } | |
942 } | 989 } |
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); | |
975 } | 990 } |
976 | 991 |
977 dst->swap(tmpDst); | 992 dst->swap(tmpDst); |
978 return true; | 993 return true; |
979 } | 994 } |
980 | 995 |
981 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { | 996 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { |
982 const SkColorType dstCT = this->colorType(); | 997 const SkColorType dstCT = this->colorType(); |
983 | 998 |
984 if (!this->canCopyTo(dstCT)) { | 999 if (!this->canCopyTo(dstCT)) { |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 /////////////////////////////////////////////////////////////////////////////// | 1398 /////////////////////////////////////////////////////////////////////////////// |
1384 | 1399 |
1385 #ifdef SK_DEBUG | 1400 #ifdef SK_DEBUG |
1386 void SkImageInfo::validate() const { | 1401 void SkImageInfo::validate() const { |
1387 SkASSERT(fWidth >= 0); | 1402 SkASSERT(fWidth >= 0); |
1388 SkASSERT(fHeight >= 0); | 1403 SkASSERT(fHeight >= 0); |
1389 SkASSERT(SkColorTypeIsValid(fColorType)); | 1404 SkASSERT(SkColorTypeIsValid(fColorType)); |
1390 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1405 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
1391 } | 1406 } |
1392 #endif | 1407 #endif |
OLD | NEW |