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 ctable.reset(new SkColorTable(*src->getColorTable())); |
scroggo
2014/02/20 22:14:43
nit: SkNEW_ARGS.
I know the old code did the same
reed1
2014/02/21 19:17:53
Are we convinced ctables are thread-safe-immutable
reed1
2014/02/21 19:17:53
Done.
| |
1073 } | |
1058 if (!tmpDst.allocPixels(alloc, ctable)) { | 1074 if (!tmpDst.allocPixels(alloc, ctable)) { |
1059 return false; | 1075 return false; |
1060 } | 1076 } |
1061 | 1077 |
1062 if (!tmpDst.readyToDraw()) { | 1078 if (!tmpDst.readyToDraw()) { |
1063 // allocator/lock failed | 1079 // allocator/lock failed |
1064 return false; | 1080 return false; |
1065 } | 1081 } |
1066 | 1082 |
1067 // pixelRef must be non NULL or tmpDst.readyToDraw() would have | 1083 // pixelRef must be non NULL or tmpDst.readyToDraw() would have |
1068 // returned false. | 1084 // returned false. |
1069 SkASSERT(tmpDst.pixelRef() != NULL); | 1085 SkASSERT(tmpDst.pixelRef() != NULL); |
1070 | 1086 |
1071 /* do memcpy for the same configs cases, else use drawing | 1087 /* do memcpy for the same configs cases, else use drawing |
1072 */ | 1088 */ |
1073 if (src->config() == dstConfig) { | 1089 if (src->colorType() == dstColorType) { |
1074 if (tmpDst.getSize() == src->getSize()) { | 1090 if (tmpDst.getSize() == src->getSize()) { |
1075 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); | 1091 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); |
1076 SkPixelRef* pixelRef = tmpDst.pixelRef(); | 1092 SkPixelRef* pixelRef = tmpDst.pixelRef(); |
1077 | 1093 |
1078 // In order to reach this point, we know that the width, config and | 1094 // 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 | 1095 // 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 | 1096 // the heights to differ, if this SkBitmap's height is a subset of |
1081 // fPixelRef. Only if the SkPixelRefs' heights match are we | 1097 // fPixelRef. Only if the SkPixelRefs' heights match are we |
1082 // guaranteed that this is an exact copy, meaning we should clone | 1098 // guaranteed that this is an exact copy, meaning we should clone |
1083 // the genID. | 1099 // the genID. |
(...skipping 11 matching lines...) Expand all Loading... | |
1095 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); | 1111 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); |
1096 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); | 1112 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); |
1097 // to be sure we don't read too much, only copy our logical pixels | 1113 // to be sure we don't read too much, only copy our logical pixels |
1098 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); | 1114 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); |
1099 for (int y = 0; y < tmpDst.height(); y++) { | 1115 for (int y = 0; y < tmpDst.height(); y++) { |
1100 memcpy(dstP, srcP, bytesToCopy); | 1116 memcpy(dstP, srcP, bytesToCopy); |
1101 srcP += src->rowBytes(); | 1117 srcP += src->rowBytes(); |
1102 dstP += tmpDst.rowBytes(); | 1118 dstP += tmpDst.rowBytes(); |
1103 } | 1119 } |
1104 } | 1120 } |
1105 } else if (SkBitmap::kARGB_4444_Config == dstConfig | 1121 } else if (kARGB_4444_SkColorType == dstColorType |
1106 && SkBitmap::kARGB_8888_Config == src->config()) { | 1122 && kPMColor_SkColorType == src->colorType()) { |
1107 SkASSERT(src->height() == tmpDst.height()); | 1123 SkASSERT(src->height() == tmpDst.height()); |
1108 SkASSERT(src->width() == tmpDst.width()); | 1124 SkASSERT(src->width() == tmpDst.width()); |
1109 for (int y = 0; y < src->height(); ++y) { | 1125 for (int y = 0; y < src->height(); ++y) { |
1110 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); | 1126 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); |
1111 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); | 1127 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); |
1112 DITHER_4444_SCAN(y); | 1128 DITHER_4444_SCAN(y); |
1113 for (int x = 0; x < src->width(); ++x) { | 1129 for (int x = 0; x < src->width(); ++x) { |
1114 dstRow[x] = SkDitherARGB32To4444(srcRow[x], | 1130 dstRow[x] = SkDitherARGB32To4444(srcRow[x], |
1115 DITHER_VALUE(x)); | 1131 DITHER_VALUE(x)); |
1116 } | 1132 } |
(...skipping 10 matching lines...) Expand all Loading... | |
1127 canvas.drawBitmap(*src, 0, 0, &paint); | 1143 canvas.drawBitmap(*src, 0, 0, &paint); |
1128 } | 1144 } |
1129 | 1145 |
1130 dst->swap(tmpDst); | 1146 dst->swap(tmpDst); |
1131 return true; | 1147 return true; |
1132 } | 1148 } |
1133 | 1149 |
1134 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { | 1150 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { |
1135 const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig); | 1151 const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig); |
1136 | 1152 |
1137 if (!this->canCopyTo(dstConfig)) { | 1153 if (!this->canCopyTo(dstCT)) { |
1138 return false; | 1154 return false; |
1139 } | 1155 } |
1140 | 1156 |
1141 // If we have a PixelRef, and it supports deep copy, use it. | 1157 // If we have a PixelRef, and it supports deep copy, use it. |
1142 // Currently supported only by texture-backed bitmaps. | 1158 // Currently supported only by texture-backed bitmaps. |
1143 if (fPixelRef) { | 1159 if (fPixelRef) { |
1144 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); | 1160 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); |
1145 if (pixelRef) { | 1161 if (pixelRef) { |
1146 uint32_t rowBytes; | 1162 uint32_t rowBytes; |
1147 if (this->colorType() == dstCT) { | 1163 if (this->colorType() == dstCT) { |
(...skipping 14 matching lines...) Expand all Loading... | |
1162 return false; | 1178 return false; |
1163 } | 1179 } |
1164 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); | 1180 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); |
1165 return true; | 1181 return true; |
1166 } | 1182 } |
1167 } | 1183 } |
1168 | 1184 |
1169 if (this->getTexture()) { | 1185 if (this->getTexture()) { |
1170 return false; | 1186 return false; |
1171 } else { | 1187 } else { |
1172 return this->copyTo(dst, dstConfig, NULL); | 1188 return this->copyTo(dst, dstCT, NULL); |
1173 } | 1189 } |
1174 } | 1190 } |
1175 | 1191 |
1176 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { | 1192 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { |
1177 return this->deepCopyTo(dst, this->config()); | 1193 return this->deepCopyTo(dst, this->config()); |
1178 } | 1194 } |
1179 | 1195 |
1180 /////////////////////////////////////////////////////////////////////////////// | 1196 /////////////////////////////////////////////////////////////////////////////// |
1181 /////////////////////////////////////////////////////////////////////////////// | 1197 /////////////////////////////////////////////////////////////////////////////// |
1182 | 1198 |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1718 /////////////////////////////////////////////////////////////////////////////// | 1734 /////////////////////////////////////////////////////////////////////////////// |
1719 | 1735 |
1720 #ifdef SK_DEBUG | 1736 #ifdef SK_DEBUG |
1721 void SkImageInfo::validate() const { | 1737 void SkImageInfo::validate() const { |
1722 SkASSERT(fWidth >= 0); | 1738 SkASSERT(fWidth >= 0); |
1723 SkASSERT(fHeight >= 0); | 1739 SkASSERT(fHeight >= 0); |
1724 SkASSERT(SkColorTypeIsValid(fColorType)); | 1740 SkASSERT(SkColorTypeIsValid(fColorType)); |
1725 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1741 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
1726 } | 1742 } |
1727 #endif | 1743 #endif |
OLD | NEW |