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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 } | 87 } |
88 | 88 |
89 void SkBitmap::reset() { | 89 void SkBitmap::reset() { |
90 this->freePixels(); | 90 this->freePixels(); |
91 sk_bzero(this, sizeof(*this)); | 91 sk_bzero(this, sizeof(*this)); |
92 } | 92 } |
93 | 93 |
94 void SkBitmap::getBounds(SkRect* bounds) const { | 94 void SkBitmap::getBounds(SkRect* bounds) const { |
95 SkASSERT(bounds); | 95 SkASSERT(bounds); |
96 bounds->set(0, 0, | 96 bounds->set(0, 0, |
97 SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight)); | 97 SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height())); |
98 } | 98 } |
99 | 99 |
100 void SkBitmap::getBounds(SkIRect* bounds) const { | 100 void SkBitmap::getBounds(SkIRect* bounds) const { |
101 SkASSERT(bounds); | 101 SkASSERT(bounds); |
102 bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight); | 102 bounds->set(0, 0, fInfo.width(), fInfo.height()); |
103 } | 103 } |
104 | 104 |
105 /////////////////////////////////////////////////////////////////////////////// | 105 /////////////////////////////////////////////////////////////////////////////// |
106 | 106 |
107 bool SkBitmap::setInfo(const SkImageInfo& origInfo, size_t rowBytes) { | 107 bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) { |
108 SkImageInfo info = origInfo; | 108 SkAlphaType newAT = info.alphaType(); |
109 | 109 if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT
)) { |
110 if (!SkColorTypeValidateAlphaType(info.fColorType, info.fAlphaType, | |
111 &info.fAlphaType)) { | |
112 return reset_return_false(this); | 110 return reset_return_false(this); |
113 } | 111 } |
| 112 // don't look at info.alphaType(), since newAT is the real value... |
114 | 113 |
115 // require that rowBytes fit in 31bits | 114 // require that rowBytes fit in 31bits |
116 int64_t mrb = info.minRowBytes64(); | 115 int64_t mrb = info.minRowBytes64(); |
117 if ((int32_t)mrb != mrb) { | 116 if ((int32_t)mrb != mrb) { |
118 return reset_return_false(this); | 117 return reset_return_false(this); |
119 } | 118 } |
120 if ((int64_t)rowBytes != (int32_t)rowBytes) { | 119 if ((int64_t)rowBytes != (int32_t)rowBytes) { |
121 return reset_return_false(this); | 120 return reset_return_false(this); |
122 } | 121 } |
123 | 122 |
124 if (info.width() < 0 || info.height() < 0) { | 123 if (info.width() < 0 || info.height() < 0) { |
125 return reset_return_false(this); | 124 return reset_return_false(this); |
126 } | 125 } |
127 | 126 |
128 if (kUnknown_SkColorType == info.colorType()) { | 127 if (kUnknown_SkColorType == info.colorType()) { |
129 rowBytes = 0; | 128 rowBytes = 0; |
130 } else if (0 == rowBytes) { | 129 } else if (0 == rowBytes) { |
131 rowBytes = (size_t)mrb; | 130 rowBytes = (size_t)mrb; |
132 } else if (!info.validRowBytes(rowBytes)) { | 131 } else if (!info.validRowBytes(rowBytes)) { |
133 return reset_return_false(this); | 132 return reset_return_false(this); |
134 } | 133 } |
135 | 134 |
136 this->freePixels(); | 135 this->freePixels(); |
137 | 136 |
138 fInfo = info; | 137 fInfo = info.makeAlphaType(newAT); |
139 fRowBytes = SkToU32(rowBytes); | 138 fRowBytes = SkToU32(rowBytes); |
140 return true; | 139 return true; |
141 } | 140 } |
142 | 141 |
143 bool SkBitmap::setAlphaType(SkAlphaType alphaType) { | 142 bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) { |
144 if (!SkColorTypeValidateAlphaType(fInfo.fColorType, alphaType, &alphaType))
{ | 143 if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlpha
Type)) { |
145 return false; | 144 return false; |
146 } | 145 } |
147 if (fInfo.fAlphaType != alphaType) { | 146 if (fInfo.alphaType() != newAlphaType) { |
148 fInfo.fAlphaType = alphaType; | 147 fInfo = fInfo.makeAlphaType(newAlphaType); |
149 if (fPixelRef) { | 148 if (fPixelRef) { |
150 fPixelRef->changeAlphaType(alphaType); | 149 fPixelRef->changeAlphaType(newAlphaType); |
151 } | 150 } |
152 } | 151 } |
153 return true; | 152 return true; |
154 } | 153 } |
155 | 154 |
156 void SkBitmap::updatePixelsFromRef() const { | 155 void SkBitmap::updatePixelsFromRef() const { |
157 if (NULL != fPixelRef) { | 156 if (NULL != fPixelRef) { |
158 if (fPixelLockCount > 0) { | 157 if (fPixelLockCount > 0) { |
159 SkASSERT(fPixelRef->isLocked()); | 158 SkASSERT(fPixelRef->isLocked()); |
160 | 159 |
(...skipping 11 matching lines...) Expand all Loading... |
172 fColorTable = NULL; | 171 fColorTable = NULL; |
173 } | 172 } |
174 } | 173 } |
175 } | 174 } |
176 | 175 |
177 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { | 176 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { |
178 #ifdef SK_DEBUG | 177 #ifdef SK_DEBUG |
179 if (pr) { | 178 if (pr) { |
180 if (kUnknown_SkColorType != fInfo.colorType()) { | 179 if (kUnknown_SkColorType != fInfo.colorType()) { |
181 const SkImageInfo& prInfo = pr->info(); | 180 const SkImageInfo& prInfo = pr->info(); |
182 SkASSERT(fInfo.fWidth <= prInfo.fWidth); | 181 SkASSERT(fInfo.width() <= prInfo.width()); |
183 SkASSERT(fInfo.fHeight <= prInfo.fHeight); | 182 SkASSERT(fInfo.height() <= prInfo.height()); |
184 SkASSERT(fInfo.fColorType == prInfo.fColorType); | 183 SkASSERT(fInfo.colorType() == prInfo.colorType()); |
185 switch (prInfo.fAlphaType) { | 184 switch (prInfo.alphaType()) { |
186 case kIgnore_SkAlphaType: | 185 case kIgnore_SkAlphaType: |
187 SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType); | 186 SkASSERT(fInfo.alphaType() == kIgnore_SkAlphaType); |
188 break; | 187 break; |
189 case kOpaque_SkAlphaType: | 188 case kOpaque_SkAlphaType: |
190 case kPremul_SkAlphaType: | 189 case kPremul_SkAlphaType: |
191 SkASSERT(fInfo.fAlphaType == kOpaque_SkAlphaType || | 190 SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType || |
192 fInfo.fAlphaType == kPremul_SkAlphaType); | 191 fInfo.alphaType() == kPremul_SkAlphaType); |
193 break; | 192 break; |
194 case kUnpremul_SkAlphaType: | 193 case kUnpremul_SkAlphaType: |
195 SkASSERT(fInfo.fAlphaType == kOpaque_SkAlphaType || | 194 SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType || |
196 fInfo.fAlphaType == kUnpremul_SkAlphaType); | 195 fInfo.alphaType() == kUnpremul_SkAlphaType); |
197 break; | 196 break; |
198 } | 197 } |
199 } | 198 } |
200 } | 199 } |
201 #endif | 200 #endif |
202 | 201 |
203 if (pr) { | 202 if (pr) { |
204 const SkImageInfo& info = pr->info(); | 203 const SkImageInfo& info = pr->info(); |
205 fPixelRefOrigin.set(SkPin32(dx, 0, info.fWidth), | 204 fPixelRefOrigin.set(SkPin32(dx, 0, info.width()), SkPin32(dy, 0, info.he
ight())); |
206 SkPin32(dy, 0, info.fHeight)); | |
207 } else { | 205 } else { |
208 // ignore dx,dy if there is no pixelref | 206 // ignore dx,dy if there is no pixelref |
209 fPixelRefOrigin.setZero(); | 207 fPixelRefOrigin.setZero(); |
210 } | 208 } |
211 | 209 |
212 if (fPixelRef != pr) { | 210 if (fPixelRef != pr) { |
213 this->freePixels(); | 211 this->freePixels(); |
214 SkASSERT(NULL == fPixelRef); | 212 SkASSERT(NULL == fPixelRef); |
215 | 213 |
216 SkSafeRef(pr); | 214 SkSafeRef(pr); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 // TODO: lockPixels could/should return bool or void*/NULL | 301 // TODO: lockPixels could/should return bool or void*/NULL |
304 this->lockPixels(); | 302 this->lockPixels(); |
305 if (NULL == this->getPixels()) { | 303 if (NULL == this->getPixels()) { |
306 return reset_return_false(this); | 304 return reset_return_false(this); |
307 } | 305 } |
308 return true; | 306 return true; |
309 } | 307 } |
310 | 308 |
311 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactor
y* factory, | 309 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactor
y* factory, |
312 SkColorTable* ctable) { | 310 SkColorTable* ctable) { |
313 if (kIndex_8_SkColorType == requestedInfo.fColorType && NULL == ctable) { | 311 if (kIndex_8_SkColorType == requestedInfo.colorType() && NULL == ctable) { |
314 return reset_return_false(this); | 312 return reset_return_false(this); |
315 } | 313 } |
316 if (!this->setInfo(requestedInfo)) { | 314 if (!this->setInfo(requestedInfo)) { |
317 return reset_return_false(this); | 315 return reset_return_false(this); |
318 } | 316 } |
319 | 317 |
320 // setInfo may have corrected info (e.g. 565 is always opaque). | 318 // setInfo may have corrected info (e.g. 565 is always opaque). |
321 const SkImageInfo& correctedInfo = this->info(); | 319 const SkImageInfo& correctedInfo = this->info(); |
322 | 320 |
323 SkMallocPixelRef::PRFactory defaultFactory; | 321 SkMallocPixelRef::PRFactory defaultFactory; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 } else { | 458 } else { |
461 // If destination has different stride than us, then copy line by line. | 459 // If destination has different stride than us, then copy line by line. |
462 if (fInfo.getSafeSize(dstRowBytes) > dstSize) { | 460 if (fInfo.getSafeSize(dstRowBytes) > dstSize) { |
463 return false; | 461 return false; |
464 } else { | 462 } else { |
465 // Just copy what we need on each line. | 463 // Just copy what we need on each line. |
466 size_t rowBytes = fInfo.minRowBytes(); | 464 size_t rowBytes = fInfo.minRowBytes(); |
467 SkAutoLockPixels lock(*this); | 465 SkAutoLockPixels lock(*this); |
468 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels()); | 466 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels()); |
469 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); | 467 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); |
470 for (int row = 0; row < fInfo.fHeight; | 468 for (int row = 0; row < fInfo.height(); row++, srcP += fRowBytes, ds
tP += dstRowBytes) { |
471 row++, srcP += fRowBytes, dstP += dstRowBytes) { | |
472 memcpy(dstP, srcP, rowBytes); | 469 memcpy(dstP, srcP, rowBytes); |
473 } | 470 } |
474 | 471 |
475 return true; | 472 return true; |
476 } | 473 } |
477 } | 474 } |
478 } | 475 } |
479 | 476 |
480 /////////////////////////////////////////////////////////////////////////////// | 477 /////////////////////////////////////////////////////////////////////////////// |
481 | 478 |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 } | 847 } |
851 if (0 == requestedDstInfo.width() || 0 == requestedDstInfo.height()) { | 848 if (0 == requestedDstInfo.width() || 0 == requestedDstInfo.height()) { |
852 return false; | 849 return false; |
853 } | 850 } |
854 | 851 |
855 SkIRect srcR = SkIRect::MakeXYWH(x, y, requestedDstInfo.width(), requestedDs
tInfo.height()); | 852 SkIRect srcR = SkIRect::MakeXYWH(x, y, requestedDstInfo.width(), requestedDs
tInfo.height()); |
856 if (!srcR.intersect(0, 0, this->width(), this->height())) { | 853 if (!srcR.intersect(0, 0, this->width(), this->height())) { |
857 return false; | 854 return false; |
858 } | 855 } |
859 | 856 |
860 SkImageInfo dstInfo = requestedDstInfo; | |
861 // the intersect may have shrunk info's logical size | 857 // the intersect may have shrunk info's logical size |
862 dstInfo.fWidth = srcR.width(); | 858 const SkImageInfo dstInfo = requestedDstInfo.makeWH(srcR.width(), srcR.heigh
t()); |
863 dstInfo.fHeight = srcR.height(); | |
864 | 859 |
865 // if x or y are negative, then we have to adjust pixels | 860 // if x or y are negative, then we have to adjust pixels |
866 if (x > 0) { | 861 if (x > 0) { |
867 x = 0; | 862 x = 0; |
868 } | 863 } |
869 if (y > 0) { | 864 if (y > 0) { |
870 y = 0; | 865 y = 0; |
871 } | 866 } |
872 // here x,y are either 0 or negative | 867 // here x,y are either 0 or negative |
873 dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel()); | 868 dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel()); |
874 | 869 |
875 ////////////// | 870 ////////////// |
876 | 871 |
877 SkAutoLockPixels alp(*this); | 872 SkAutoLockPixels alp(*this); |
878 | 873 |
879 // since we don't stop creating un-pixeled devices yet, check for no pixels
here | 874 // since we don't stop creating un-pixeled devices yet, check for no pixels
here |
880 if (NULL == this->getPixels()) { | 875 if (NULL == this->getPixels()) { |
881 return false; | 876 return false; |
882 } | 877 } |
883 | 878 |
884 SkImageInfo srcInfo = this->info(); | 879 const SkImageInfo srcInfo = this->info().makeWH(dstInfo.width(), dstInfo.hei
ght()); |
885 srcInfo.fWidth = dstInfo.width(); | |
886 srcInfo.fHeight = dstInfo.height(); | |
887 | 880 |
888 const void* srcPixels = this->getAddr(srcR.x(), srcR.y()); | 881 const void* srcPixels = this->getAddr(srcR.x(), srcR.y()); |
889 return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels
, this->rowBytes(), | 882 return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels
, this->rowBytes(), |
890 this->getColorTable()); | 883 this->getColorTable()); |
891 } | 884 } |
892 | 885 |
893 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc)
const { | 886 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc)
const { |
894 if (!this->canCopyTo(dstColorType)) { | 887 if (!this->canCopyTo(dstColorType)) { |
895 return false; | 888 return false; |
896 } | 889 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 | 922 |
930 // we lock this now, since we may need its colortable | 923 // we lock this now, since we may need its colortable |
931 SkAutoLockPixels srclock(*src); | 924 SkAutoLockPixels srclock(*src); |
932 if (!src->readyToDraw()) { | 925 if (!src->readyToDraw()) { |
933 return false; | 926 return false; |
934 } | 927 } |
935 | 928 |
936 // The only way to be readyToDraw is if fPixelRef is non NULL. | 929 // The only way to be readyToDraw is if fPixelRef is non NULL. |
937 SkASSERT(fPixelRef != NULL); | 930 SkASSERT(fPixelRef != NULL); |
938 | 931 |
939 SkImageInfo dstInfo = src->info(); | 932 const SkImageInfo dstInfo = src->info().makeColorType(dstColorType); |
940 dstInfo.fColorType = dstColorType; | |
941 | 933 |
942 SkBitmap tmpDst; | 934 SkBitmap tmpDst; |
943 if (!tmpDst.setInfo(dstInfo)) { | 935 if (!tmpDst.setInfo(dstInfo)) { |
944 return false; | 936 return false; |
945 } | 937 } |
946 | 938 |
947 // allocate colortable if srcConfig == kIndex8_Config | 939 // allocate colortable if srcConfig == kIndex8_Config |
948 SkAutoTUnref<SkColorTable> ctable; | 940 SkAutoTUnref<SkColorTable> ctable; |
949 if (dstColorType == kIndex_8_SkColorType) { | 941 if (dstColorType == kIndex_8_SkColorType) { |
950 // TODO: can we just ref() the src colortable? Is it reentrant-safe? | 942 // TODO: can we just ref() the src colortable? Is it reentrant-safe? |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 // succeeded, the new pixel ref must be identical. | 994 // succeeded, the new pixel ref must be identical. |
1003 SkASSERT(fPixelRef->info() == pixelRef->info()); | 995 SkASSERT(fPixelRef->info() == pixelRef->info()); |
1004 pixelRef->cloneGenID(*fPixelRef); | 996 pixelRef->cloneGenID(*fPixelRef); |
1005 // Use the same rowBytes as the original. | 997 // Use the same rowBytes as the original. |
1006 rowBytes = fRowBytes; | 998 rowBytes = fRowBytes; |
1007 } else { | 999 } else { |
1008 // With the new config, an appropriate fRowBytes will be compute
d by setInfo. | 1000 // With the new config, an appropriate fRowBytes will be compute
d by setInfo. |
1009 rowBytes = 0; | 1001 rowBytes = 0; |
1010 } | 1002 } |
1011 | 1003 |
1012 SkImageInfo info = fInfo; | 1004 const SkImageInfo info = fInfo.makeColorType(dstCT); |
1013 info.fColorType = dstCT; | |
1014 if (!dst->setInfo(info, rowBytes)) { | 1005 if (!dst->setInfo(info, rowBytes)) { |
1015 return false; | 1006 return false; |
1016 } | 1007 } |
1017 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); | 1008 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); |
1018 return true; | 1009 return true; |
1019 } | 1010 } |
1020 } | 1011 } |
1021 | 1012 |
1022 if (this->getTexture()) { | 1013 if (this->getTexture()) { |
1023 return false; | 1014 return false; |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 SkASSERT(fPixelLockCount >= 0); | 1322 SkASSERT(fPixelLockCount >= 0); |
1332 | 1323 |
1333 if (fPixels) { | 1324 if (fPixels) { |
1334 SkASSERT(fPixelRef); | 1325 SkASSERT(fPixelRef); |
1335 SkASSERT(fPixelLockCount > 0); | 1326 SkASSERT(fPixelLockCount > 0); |
1336 SkASSERT(fPixelRef->isLocked()); | 1327 SkASSERT(fPixelRef->isLocked()); |
1337 SkASSERT(fPixelRef->rowBytes() == fRowBytes); | 1328 SkASSERT(fPixelRef->rowBytes() == fRowBytes); |
1338 SkASSERT(fPixelRefOrigin.fX >= 0); | 1329 SkASSERT(fPixelRefOrigin.fX >= 0); |
1339 SkASSERT(fPixelRefOrigin.fY >= 0); | 1330 SkASSERT(fPixelRefOrigin.fY >= 0); |
1340 SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrig
in.fX); | 1331 SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrig
in.fX); |
1341 SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOri
gin.fY); | 1332 SkASSERT(fPixelRef->info().height() >= (int)this->height() + fPixelRefOr
igin.fY); |
1342 SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes()); | 1333 SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes()); |
1343 } else { | 1334 } else { |
1344 SkASSERT(NULL == fColorTable); | 1335 SkASSERT(NULL == fColorTable); |
1345 } | 1336 } |
1346 } | 1337 } |
1347 #endif | 1338 #endif |
1348 | 1339 |
1349 #ifndef SK_IGNORE_TO_STRING | 1340 #ifndef SK_IGNORE_TO_STRING |
1350 void SkBitmap::toString(SkString* str) const { | 1341 void SkBitmap::toString(SkString* str) const { |
1351 | 1342 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1389 /////////////////////////////////////////////////////////////////////////////// | 1380 /////////////////////////////////////////////////////////////////////////////// |
1390 | 1381 |
1391 #ifdef SK_DEBUG | 1382 #ifdef SK_DEBUG |
1392 void SkImageInfo::validate() const { | 1383 void SkImageInfo::validate() const { |
1393 SkASSERT(fWidth >= 0); | 1384 SkASSERT(fWidth >= 0); |
1394 SkASSERT(fHeight >= 0); | 1385 SkASSERT(fHeight >= 0); |
1395 SkASSERT(SkColorTypeIsValid(fColorType)); | 1386 SkASSERT(SkColorTypeIsValid(fColorType)); |
1396 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1387 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
1397 } | 1388 } |
1398 #endif | 1389 #endif |
OLD | NEW |