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 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 // we know we're good, so commit to result | 975 // we know we're good, so commit to result |
976 result->swap(dst); | 976 result->swap(dst); |
977 return true; | 977 return true; |
978 } | 978 } |
979 | 979 |
980 /////////////////////////////////////////////////////////////////////////////// | 980 /////////////////////////////////////////////////////////////////////////////// |
981 | 981 |
982 #include "SkCanvas.h" | 982 #include "SkCanvas.h" |
983 #include "SkPaint.h" | 983 #include "SkPaint.h" |
984 | 984 |
985 bool SkBitmap::canCopyTo(Config dstConfig) const { | 985 #ifdef SK_SUPPORT_LEGACY_COPYTO_CONFIG |
986 if (this->config() == kNo_Config) { | 986 bool SkBitmap::copyTo(SkBitmap* dst, Config c, Allocator* allocator) const { |
| 987 return this->copyTo(dst, SkBitmapConfigToSkColorType(c), allocator); |
| 988 } |
| 989 |
| 990 bool SkBitmap::canCopyTo(Config newConfig) const { |
| 991 return this->canCopyTo(SkBitmapConfigToSkColorType(c)); |
| 992 } |
| 993 #endif |
| 994 |
| 995 bool SkBitmap::canCopyTo(SkColorType dstColorType) const { |
| 996 if (this->colorType() == kUnknown_SkColorType) { |
987 return false; | 997 return false; |
988 } | 998 } |
989 | 999 |
990 bool sameConfigs = (this->config() == dstConfig); | 1000 bool sameConfigs = (this->colorType() == dstColorType); |
991 switch (dstConfig) { | 1001 switch (dstColorType) { |
992 case kA8_Config: | 1002 case kAlpha_8_SkColorType: |
993 case kRGB_565_Config: | 1003 case kRGB_565_SkColorType: |
994 case kARGB_8888_Config: | 1004 case kPMColor_SkColorType: |
995 break; | 1005 break; |
996 case kIndex8_Config: | 1006 case kIndex_8_SkColorType: |
997 if (!sameConfigs) { | 1007 if (!sameConfigs) { |
998 return false; | 1008 return false; |
999 } | 1009 } |
1000 break; | 1010 break; |
1001 case kARGB_4444_Config: | 1011 case kARGB_4444_SkColorType: |
1002 return sameConfigs || kARGB_8888_Config == this->config(); | 1012 return sameConfigs || kPMColor_SkColorType == this->colorType(); |
1003 default: | 1013 default: |
1004 return false; | 1014 return false; |
1005 } | 1015 } |
1006 return true; | 1016 return true; |
1007 } | 1017 } |
1008 | 1018 |
1009 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { | 1019 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, |
1010 if (!this->canCopyTo(dstConfig)) { | 1020 Allocator* alloc) const { |
| 1021 if (!this->canCopyTo(dstColorType)) { |
1011 return false; | 1022 return false; |
1012 } | 1023 } |
1013 | 1024 |
1014 // if we have a texture, first get those pixels | 1025 // if we have a texture, first get those pixels |
1015 SkBitmap tmpSrc; | 1026 SkBitmap tmpSrc; |
1016 const SkBitmap* src = this; | 1027 const SkBitmap* src = this; |
1017 | 1028 |
1018 if (fPixelRef) { | 1029 if (fPixelRef) { |
1019 SkIRect subset; | 1030 SkIRect subset; |
1020 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, | 1031 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, |
1021 fInfo.width(), fInfo.height()); | 1032 fInfo.width(), fInfo.height()); |
1022 if (fPixelRef->readPixels(&tmpSrc, &subset)) { | 1033 if (fPixelRef->readPixels(&tmpSrc, &subset)) { |
1023 SkASSERT(tmpSrc.width() == this->width()); | 1034 SkASSERT(tmpSrc.width() == this->width()); |
1024 SkASSERT(tmpSrc.height() == this->height()); | 1035 SkASSERT(tmpSrc.height() == this->height()); |
1025 | 1036 |
1026 // did we get lucky and we can just return tmpSrc? | 1037 // did we get lucky and we can just return tmpSrc? |
1027 if (tmpSrc.config() == dstConfig && NULL == alloc) { | 1038 if (tmpSrc.colorType() == dstColorType && NULL == alloc) { |
1028 dst->swap(tmpSrc); | 1039 dst->swap(tmpSrc); |
1029 // If the result is an exact copy, clone the gen ID. | 1040 // If the result is an exact copy, clone the gen ID. |
1030 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->inf
o()) { | 1041 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->inf
o()) { |
1031 dst->pixelRef()->cloneGenID(*fPixelRef); | 1042 dst->pixelRef()->cloneGenID(*fPixelRef); |
1032 } | 1043 } |
1033 return true; | 1044 return true; |
1034 } | 1045 } |
1035 | 1046 |
1036 // fall through to the raster case | 1047 // fall through to the raster case |
1037 src = &tmpSrc; | 1048 src = &tmpSrc; |
1038 } | 1049 } |
1039 } | 1050 } |
1040 | 1051 |
1041 // we lock this now, since we may need its colortable | 1052 // we lock this now, since we may need its colortable |
1042 SkAutoLockPixels srclock(*src); | 1053 SkAutoLockPixels srclock(*src); |
1043 if (!src->readyToDraw()) { | 1054 if (!src->readyToDraw()) { |
1044 return false; | 1055 return false; |
1045 } | 1056 } |
1046 | 1057 |
1047 // The only way to be readyToDraw is if fPixelRef is non NULL. | 1058 // The only way to be readyToDraw is if fPixelRef is non NULL. |
1048 SkASSERT(fPixelRef != NULL); | 1059 SkASSERT(fPixelRef != NULL); |
1049 | 1060 |
| 1061 SkImageInfo dstInfo = src->info(); |
| 1062 dstInfo.fColorType = dstColorType; |
| 1063 |
1050 SkBitmap tmpDst; | 1064 SkBitmap tmpDst; |
1051 tmpDst.setConfig(dstConfig, src->width(), src->height(), 0, | 1065 if (!tmpDst.setConfig(dstInfo)) { |
1052 src->alphaType()); | 1066 return false; |
| 1067 } |
1053 | 1068 |
1054 // allocate colortable if srcConfig == kIndex8_Config | 1069 // allocate colortable if srcConfig == kIndex8_Config |
1055 SkColorTable* ctable = (dstConfig == kIndex8_Config) ? | 1070 SkAutoTUnref<SkColorTable> ctable; |
1056 new SkColorTable(*src->getColorTable()) : NULL; | 1071 if (dstColorType == kIndex_8_SkColorType) { |
1057 SkAutoUnref au(ctable); | 1072 // TODO: can we just ref() the src colortable? Is it reentrant-safe? |
| 1073 ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable()))); |
| 1074 } |
1058 if (!tmpDst.allocPixels(alloc, ctable)) { | 1075 if (!tmpDst.allocPixels(alloc, ctable)) { |
1059 return false; | 1076 return false; |
1060 } | 1077 } |
1061 | 1078 |
1062 if (!tmpDst.readyToDraw()) { | 1079 if (!tmpDst.readyToDraw()) { |
1063 // allocator/lock failed | 1080 // allocator/lock failed |
1064 return false; | 1081 return false; |
1065 } | 1082 } |
1066 | 1083 |
1067 // pixelRef must be non NULL or tmpDst.readyToDraw() would have | 1084 // pixelRef must be non NULL or tmpDst.readyToDraw() would have |
1068 // returned false. | 1085 // returned false. |
1069 SkASSERT(tmpDst.pixelRef() != NULL); | 1086 SkASSERT(tmpDst.pixelRef() != NULL); |
1070 | 1087 |
1071 /* do memcpy for the same configs cases, else use drawing | 1088 /* do memcpy for the same configs cases, else use drawing |
1072 */ | 1089 */ |
1073 if (src->config() == dstConfig) { | 1090 if (src->colorType() == dstColorType) { |
1074 if (tmpDst.getSize() == src->getSize()) { | 1091 if (tmpDst.getSize() == src->getSize()) { |
1075 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); | 1092 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); |
1076 SkPixelRef* pixelRef = tmpDst.pixelRef(); | 1093 SkPixelRef* pixelRef = tmpDst.pixelRef(); |
1077 | 1094 |
1078 // In order to reach this point, we know that the width, config and | 1095 // In order to reach this point, we know that the width, config and |
1079 // rowbytes of the SkPixelRefs are the same, but it is possible for | 1096 // rowbytes of the SkPixelRefs are the same, but it is possible for |
1080 // the heights to differ, if this SkBitmap's height is a subset of | 1097 // the heights to differ, if this SkBitmap's height is a subset of |
1081 // fPixelRef. Only if the SkPixelRefs' heights match are we | 1098 // fPixelRef. Only if the SkPixelRefs' heights match are we |
1082 // guaranteed that this is an exact copy, meaning we should clone | 1099 // guaranteed that this is an exact copy, meaning we should clone |
1083 // the genID. | 1100 // the genID. |
(...skipping 11 matching lines...) Expand all Loading... |
1095 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); | 1112 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); |
1096 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); | 1113 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); |
1097 // to be sure we don't read too much, only copy our logical pixels | 1114 // to be sure we don't read too much, only copy our logical pixels |
1098 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); | 1115 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); |
1099 for (int y = 0; y < tmpDst.height(); y++) { | 1116 for (int y = 0; y < tmpDst.height(); y++) { |
1100 memcpy(dstP, srcP, bytesToCopy); | 1117 memcpy(dstP, srcP, bytesToCopy); |
1101 srcP += src->rowBytes(); | 1118 srcP += src->rowBytes(); |
1102 dstP += tmpDst.rowBytes(); | 1119 dstP += tmpDst.rowBytes(); |
1103 } | 1120 } |
1104 } | 1121 } |
1105 } else if (SkBitmap::kARGB_4444_Config == dstConfig | 1122 } else if (kARGB_4444_SkColorType == dstColorType |
1106 && SkBitmap::kARGB_8888_Config == src->config()) { | 1123 && kPMColor_SkColorType == src->colorType()) { |
1107 SkASSERT(src->height() == tmpDst.height()); | 1124 SkASSERT(src->height() == tmpDst.height()); |
1108 SkASSERT(src->width() == tmpDst.width()); | 1125 SkASSERT(src->width() == tmpDst.width()); |
1109 for (int y = 0; y < src->height(); ++y) { | 1126 for (int y = 0; y < src->height(); ++y) { |
1110 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0,
y); | 1127 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0,
y); |
1111 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); | 1128 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); |
1112 DITHER_4444_SCAN(y); | 1129 DITHER_4444_SCAN(y); |
1113 for (int x = 0; x < src->width(); ++x) { | 1130 for (int x = 0; x < src->width(); ++x) { |
1114 dstRow[x] = SkDitherARGB32To4444(srcRow[x], | 1131 dstRow[x] = SkDitherARGB32To4444(srcRow[x], |
1115 DITHER_VALUE(x)); | 1132 DITHER_VALUE(x)); |
1116 } | 1133 } |
(...skipping 10 matching lines...) Expand all Loading... |
1127 canvas.drawBitmap(*src, 0, 0, &paint); | 1144 canvas.drawBitmap(*src, 0, 0, &paint); |
1128 } | 1145 } |
1129 | 1146 |
1130 dst->swap(tmpDst); | 1147 dst->swap(tmpDst); |
1131 return true; | 1148 return true; |
1132 } | 1149 } |
1133 | 1150 |
1134 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { | 1151 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { |
1135 const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig); | 1152 const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig); |
1136 | 1153 |
1137 if (!this->canCopyTo(dstConfig)) { | 1154 if (!this->canCopyTo(dstCT)) { |
1138 return false; | 1155 return false; |
1139 } | 1156 } |
1140 | 1157 |
1141 // If we have a PixelRef, and it supports deep copy, use it. | 1158 // If we have a PixelRef, and it supports deep copy, use it. |
1142 // Currently supported only by texture-backed bitmaps. | 1159 // Currently supported only by texture-backed bitmaps. |
1143 if (fPixelRef) { | 1160 if (fPixelRef) { |
1144 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); | 1161 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); |
1145 if (pixelRef) { | 1162 if (pixelRef) { |
1146 uint32_t rowBytes; | 1163 uint32_t rowBytes; |
1147 if (this->colorType() == dstCT) { | 1164 if (this->colorType() == dstCT) { |
(...skipping 14 matching lines...) Expand all Loading... |
1162 return false; | 1179 return false; |
1163 } | 1180 } |
1164 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); | 1181 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); |
1165 return true; | 1182 return true; |
1166 } | 1183 } |
1167 } | 1184 } |
1168 | 1185 |
1169 if (this->getTexture()) { | 1186 if (this->getTexture()) { |
1170 return false; | 1187 return false; |
1171 } else { | 1188 } else { |
1172 return this->copyTo(dst, dstConfig, NULL); | 1189 return this->copyTo(dst, dstCT, NULL); |
1173 } | 1190 } |
1174 } | 1191 } |
1175 | 1192 |
1176 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { | 1193 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { |
1177 return this->deepCopyTo(dst, this->config()); | 1194 return this->deepCopyTo(dst, this->config()); |
1178 } | 1195 } |
1179 | 1196 |
1180 /////////////////////////////////////////////////////////////////////////////// | 1197 /////////////////////////////////////////////////////////////////////////////// |
1181 /////////////////////////////////////////////////////////////////////////////// | 1198 /////////////////////////////////////////////////////////////////////////////// |
1182 | 1199 |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1718 /////////////////////////////////////////////////////////////////////////////// | 1735 /////////////////////////////////////////////////////////////////////////////// |
1719 | 1736 |
1720 #ifdef SK_DEBUG | 1737 #ifdef SK_DEBUG |
1721 void SkImageInfo::validate() const { | 1738 void SkImageInfo::validate() const { |
1722 SkASSERT(fWidth >= 0); | 1739 SkASSERT(fWidth >= 0); |
1723 SkASSERT(fHeight >= 0); | 1740 SkASSERT(fHeight >= 0); |
1724 SkASSERT(SkColorTypeIsValid(fColorType)); | 1741 SkASSERT(SkColorTypeIsValid(fColorType)); |
1725 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1742 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
1726 } | 1743 } |
1727 #endif | 1744 #endif |
OLD | NEW |