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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 SkTSwap(fFlags, other.fFlags); | 135 SkTSwap(fFlags, other.fFlags); |
136 | 136 |
137 SkDEBUGCODE(this->validate();) | 137 SkDEBUGCODE(this->validate();) |
138 } | 138 } |
139 | 139 |
140 void SkBitmap::reset() { | 140 void SkBitmap::reset() { |
141 this->freePixels(); | 141 this->freePixels(); |
142 sk_bzero(this, sizeof(*this)); | 142 sk_bzero(this, sizeof(*this)); |
143 } | 143 } |
144 | 144 |
145 SkBitmap::Config SkBitmap::config() const { | |
146 return SkColorTypeToBitmapConfig(fInfo.colorType()); | |
147 } | |
148 | |
149 int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { | |
150 int bpp; | |
151 switch (config) { | |
152 case kNo_Config: | |
153 bpp = 0; // not applicable | |
154 break; | |
155 case kA8_Config: | |
156 case kIndex8_Config: | |
157 bpp = 1; | |
158 break; | |
159 case kRGB_565_Config: | |
160 case kARGB_4444_Config: | |
161 bpp = 2; | |
162 break; | |
163 case kARGB_8888_Config: | |
164 bpp = 4; | |
165 break; | |
166 default: | |
167 SkDEBUGFAIL("unknown config"); | |
168 bpp = 0; // error | |
169 break; | |
170 } | |
171 return bpp; | |
172 } | |
173 | |
174 size_t SkBitmap::ComputeRowBytes(Config c, int width) { | |
175 return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), width); | |
176 } | |
177 | |
178 int64_t SkBitmap::ComputeSize64(Config config, int width, int height) { | |
179 SkColorType ct = SkBitmapConfigToColorType(config); | |
180 int64_t rowBytes = sk_64_mul(SkColorTypeBytesPerPixel(ct), width); | |
181 return rowBytes * height; | |
182 } | |
183 | |
184 size_t SkBitmap::ComputeSize(Config c, int width, int height) { | |
185 int64_t size = SkBitmap::ComputeSize64(c, width, height); | |
186 return sk_64_isS32(size) ? sk_64_asS32(size) : 0; | |
187 } | |
188 | |
189 int64_t SkBitmap::ComputeSafeSize64(Config config, | |
190 uint32_t width, | |
191 uint32_t height, | |
192 size_t rowBytes) { | |
193 SkImageInfo info = SkImageInfo::Make(width, height, | |
194 SkBitmapConfigToColorType(config), | |
195 kPremul_SkAlphaType); | |
196 return info.getSafeSize64(rowBytes); | |
197 } | |
198 | |
199 size_t SkBitmap::ComputeSafeSize(Config config, | |
200 uint32_t width, | |
201 uint32_t height, | |
202 size_t rowBytes) { | |
203 int64_t safeSize = ComputeSafeSize64(config, width, height, rowBytes); | |
204 int32_t safeSize32 = (int32_t)safeSize; | |
205 | |
206 if (safeSize32 != safeSize) { | |
207 safeSize32 = 0; | |
208 } | |
209 return safeSize32; | |
210 } | |
211 | |
212 void SkBitmap::getBounds(SkRect* bounds) const { | 145 void SkBitmap::getBounds(SkRect* bounds) const { |
213 SkASSERT(bounds); | 146 SkASSERT(bounds); |
214 bounds->set(0, 0, | 147 bounds->set(0, 0, |
215 SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight)); | 148 SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight)); |
216 } | 149 } |
217 | 150 |
218 void SkBitmap::getBounds(SkIRect* bounds) const { | 151 void SkBitmap::getBounds(SkIRect* bounds) const { |
219 SkASSERT(bounds); | 152 SkASSERT(bounds); |
220 bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight); | 153 bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight); |
221 } | 154 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 return reset_return_false(this); | 208 return reset_return_false(this); |
276 } | 209 } |
277 | 210 |
278 this->freePixels(); | 211 this->freePixels(); |
279 | 212 |
280 fInfo = info; | 213 fInfo = info; |
281 fRowBytes = SkToU32(rowBytes); | 214 fRowBytes = SkToU32(rowBytes); |
282 return true; | 215 return true; |
283 } | 216 } |
284 | 217 |
285 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, | |
286 SkAlphaType alphaType) { | |
287 SkColorType ct = SkBitmapConfigToColorType(config); | |
288 return this->setConfig(SkImageInfo::Make(width, height, ct, alphaType), | |
289 rowBytes); | |
290 } | |
291 | |
292 bool SkBitmap::setAlphaType(SkAlphaType alphaType) { | 218 bool SkBitmap::setAlphaType(SkAlphaType alphaType) { |
293 if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) { | 219 if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) { |
294 return false; | 220 return false; |
295 } | 221 } |
296 if (fInfo.fAlphaType != alphaType) { | 222 if (fInfo.fAlphaType != alphaType) { |
297 fInfo.fAlphaType = alphaType; | 223 fInfo.fAlphaType = alphaType; |
298 if (fPixelRef) { | 224 if (fPixelRef) { |
299 fPixelRef->changeAlphaType(alphaType); | 225 fPixelRef->changeAlphaType(alphaType); |
300 } | 226 } |
301 } | 227 } |
(...skipping 14 matching lines...) Expand all Loading... |
316 fPixels = p; | 242 fPixels = p; |
317 fColorTable = fPixelRef->colorTable(); | 243 fColorTable = fPixelRef->colorTable(); |
318 } else { | 244 } else { |
319 SkASSERT(0 == fPixelLockCount); | 245 SkASSERT(0 == fPixelLockCount); |
320 fPixels = NULL; | 246 fPixels = NULL; |
321 fColorTable = NULL; | 247 fColorTable = NULL; |
322 } | 248 } |
323 } | 249 } |
324 } | 250 } |
325 | 251 |
326 static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) { | |
327 SkColorType ct; | |
328 switch (config) { | |
329 case SkBitmap::kA8_Config: | |
330 ct = kAlpha_8_SkColorType; | |
331 break; | |
332 case SkBitmap::kIndex8_Config: | |
333 ct = kIndex_8_SkColorType; | |
334 break; | |
335 case SkBitmap::kRGB_565_Config: | |
336 ct = kRGB_565_SkColorType; | |
337 break; | |
338 case SkBitmap::kARGB_4444_Config: | |
339 ct = kARGB_4444_SkColorType; | |
340 break; | |
341 case SkBitmap::kARGB_8888_Config: | |
342 ct = kPMColor_SkColorType; | |
343 break; | |
344 case SkBitmap::kNo_Config: | |
345 default: | |
346 return false; | |
347 } | |
348 if (ctOut) { | |
349 *ctOut = ct; | |
350 } | |
351 return true; | |
352 } | |
353 | |
354 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { | 252 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { |
355 #ifdef SK_DEBUG | 253 #ifdef SK_DEBUG |
356 if (pr) { | 254 if (pr) { |
357 SkImageInfo info; | 255 SkImageInfo info; |
358 if (this->asImageInfo(&info)) { | 256 if (this->asImageInfo(&info)) { |
359 const SkImageInfo& prInfo = pr->info(); | 257 const SkImageInfo& prInfo = pr->info(); |
360 SkASSERT(info.fWidth <= prInfo.fWidth); | 258 SkASSERT(info.fWidth <= prInfo.fWidth); |
361 SkASSERT(info.fHeight <= prInfo.fHeight); | 259 SkASSERT(info.fHeight <= prInfo.fHeight); |
362 SkASSERT(info.fColorType == prInfo.fColorType); | 260 SkASSERT(info.fColorType == prInfo.fColorType); |
363 switch (prInfo.fAlphaType) { | 261 switch (prInfo.fAlphaType) { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 releaseProc, context); | 398 releaseProc, context); |
501 if (!pr) { | 399 if (!pr) { |
502 this->reset(); | 400 this->reset(); |
503 return false; | 401 return false; |
504 } | 402 } |
505 | 403 |
506 this->setPixelRef(pr)->unref(); | 404 this->setPixelRef(pr)->unref(); |
507 return true; | 405 return true; |
508 } | 406 } |
509 | 407 |
510 bool SkBitmap::allocConfigPixels(Config config, int width, int height, | |
511 bool isOpaque) { | |
512 SkColorType ct; | |
513 if (!config_to_colorType(config, &ct)) { | |
514 return false; | |
515 } | |
516 | |
517 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; | |
518 return this->allocPixels(SkImageInfo::Make(width, height, ct, at)); | |
519 } | |
520 | |
521 /////////////////////////////////////////////////////////////////////////////// | 408 /////////////////////////////////////////////////////////////////////////////// |
522 | 409 |
523 void SkBitmap::freePixels() { | 410 void SkBitmap::freePixels() { |
524 // if we're gonna free the pixels, we certainly need to free the mipmap | 411 // if we're gonna free the pixels, we certainly need to free the mipmap |
525 this->freeMipMap(); | 412 this->freeMipMap(); |
526 | 413 |
527 if (NULL != fPixelRef) { | 414 if (NULL != fPixelRef) { |
528 if (fPixelLockCount > 0) { | 415 if (fPixelLockCount > 0) { |
529 fPixelRef->unlockPixels(); | 416 fPixelRef->unlockPixels(); |
530 } | 417 } |
(...skipping 28 matching lines...) Expand all Loading... |
559 return fPixelRef ? fPixelRef->getTexture() : NULL; | 446 return fPixelRef ? fPixelRef->getTexture() : NULL; |
560 } | 447 } |
561 | 448 |
562 /////////////////////////////////////////////////////////////////////////////// | 449 /////////////////////////////////////////////////////////////////////////////// |
563 | 450 |
564 /** We explicitly use the same allocator for our pixels that SkMask does, | 451 /** We explicitly use the same allocator for our pixels that SkMask does, |
565 so that we can freely assign memory allocated by one class to the other. | 452 so that we can freely assign memory allocated by one class to the other. |
566 */ | 453 */ |
567 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, | 454 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, |
568 SkColorTable* ctable) { | 455 SkColorTable* ctable) { |
569 SkImageInfo info; | 456 SkPixelRef* pr = SkMallocPixelRef::NewAllocate(dst->info(), dst->rowBytes(), |
570 if (!dst->asImageInfo(&info)) { | |
571 // SkDebugf("unsupported config for info %d\n", dst->config()); | |
572 return false; | |
573 } | |
574 | |
575 SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), | |
576 ctable); | 457 ctable); |
577 if (NULL == pr) { | 458 if (NULL == pr) { |
578 return false; | 459 return false; |
579 } | 460 } |
580 | 461 |
581 dst->setPixelRef(pr)->unref(); | 462 dst->setPixelRef(pr)->unref(); |
582 // since we're already allocated, we lockPixels right away | 463 // since we're already allocated, we lockPixels right away |
583 dst->lockPixels(); | 464 dst->lockPixels(); |
584 return true; | 465 return true; |
585 } | 466 } |
(...skipping 13 matching lines...) Expand all Loading... |
599 } | 480 } |
600 | 481 |
601 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) { | 482 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) { |
602 size_t safeSize = this->getSafeSize(); | 483 size_t safeSize = this->getSafeSize(); |
603 if (safeSize > dstSize || safeSize == 0) | 484 if (safeSize > dstSize || safeSize == 0) |
604 return false; | 485 return false; |
605 else { | 486 else { |
606 SkAutoLockPixels lock(*this); | 487 SkAutoLockPixels lock(*this); |
607 // This implementation will write bytes beyond the end of each row, | 488 // This implementation will write bytes beyond the end of each row, |
608 // excluding the last row, if the bitmap's stride is greater than | 489 // excluding the last row, if the bitmap's stride is greater than |
609 // strictly required by the current config. | 490 // strictly required by the current colorType. |
610 memcpy(dst, getPixels(), safeSize); | 491 memcpy(dst, getPixels(), safeSize); |
611 | 492 |
612 return true; | 493 return true; |
613 } | 494 } |
614 } else { | 495 } else { |
615 // If destination has different stride than us, then copy line by line. | 496 // If destination has different stride than us, then copy line by line. |
616 if (fInfo.getSafeSize(dstRowBytes) > dstSize) { | 497 if (fInfo.getSafeSize(dstRowBytes) > dstSize) { |
617 return false; | 498 return false; |
618 } else { | 499 } else { |
619 // Just copy what we need on each line. | 500 // Just copy what we need on each line. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 break; | 553 break; |
673 case kARGB_4444_SkColorType: | 554 case kARGB_4444_SkColorType: |
674 case kRGB_565_SkColorType: | 555 case kRGB_565_SkColorType: |
675 base += x << 1; | 556 base += x << 1; |
676 break; | 557 break; |
677 case kAlpha_8_SkColorType: | 558 case kAlpha_8_SkColorType: |
678 case kIndex_8_SkColorType: | 559 case kIndex_8_SkColorType: |
679 base += x; | 560 base += x; |
680 break; | 561 break; |
681 default: | 562 default: |
682 SkDEBUGFAIL("Can't return addr for config"); | 563 SkDEBUGFAIL("Can't return addr for colorType"); |
683 base = NULL; | 564 base = NULL; |
684 break; | 565 break; |
685 } | 566 } |
686 } | 567 } |
687 return base; | 568 return base; |
688 } | 569 } |
689 | 570 |
690 SkColor SkBitmap::getColor(int x, int y) const { | 571 SkColor SkBitmap::getColor(int x, int y) const { |
691 SkASSERT((unsigned)x < (unsigned)this->width()); | 572 SkASSERT((unsigned)x < (unsigned)this->width()); |
692 SkASSERT((unsigned)y < (unsigned)this->height()); | 573 SkASSERT((unsigned)y < (unsigned)this->height()); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 // share the pixelref with a custom offset | 830 // share the pixelref with a custom offset |
950 dst.setPixelRef(fPixelRef, origin); | 831 dst.setPixelRef(fPixelRef, origin); |
951 } | 832 } |
952 SkDEBUGCODE(dst.validate();) | 833 SkDEBUGCODE(dst.validate();) |
953 | 834 |
954 // we know we're good, so commit to result | 835 // we know we're good, so commit to result |
955 result->swap(dst); | 836 result->swap(dst); |
956 return true; | 837 return true; |
957 } | 838 } |
958 | 839 |
| 840 bool SkBitmap::canCopyTo(SkColorType dstColorType) const { |
| 841 if (kUnknown_SkColorType == this->colorType()) { |
| 842 return false; |
| 843 } |
| 844 |
| 845 bool sameColorTypes = (this->colorType() == dstColorType); |
| 846 switch (dstColorType) { |
| 847 case kAlpha_8_SkColorType: |
| 848 case kRGB_565_SkColorType: |
| 849 case kPMColor_SkColorType: |
| 850 break; |
| 851 case kIndex_8_SkColorType: |
| 852 if (!sameColorTypes) { |
| 853 return false; |
| 854 } |
| 855 break; |
| 856 case kARGB_4444_SkColorType: |
| 857 return sameColorTypes || kPMColor_SkColorType == this->colorType(); |
| 858 default: |
| 859 return false; |
| 860 } |
| 861 return true; |
| 862 } |
| 863 |
959 /////////////////////////////////////////////////////////////////////////////// | 864 /////////////////////////////////////////////////////////////////////////////// |
960 | 865 |
961 #include "SkCanvas.h" | 866 #include "SkCanvas.h" |
962 #include "SkPaint.h" | 867 #include "SkPaint.h" |
963 | 868 |
964 bool SkBitmap::canCopyTo(Config dstConfig) const { | |
965 if (this->config() == kNo_Config) { | |
966 return false; | |
967 } | |
968 | |
969 bool sameConfigs = (this->config() == dstConfig); | |
970 switch (dstConfig) { | |
971 case kA8_Config: | |
972 case kRGB_565_Config: | |
973 case kARGB_8888_Config: | |
974 break; | |
975 case kIndex8_Config: | |
976 if (!sameConfigs) { | |
977 return false; | |
978 } | |
979 break; | |
980 case kARGB_4444_Config: | |
981 return sameConfigs || kARGB_8888_Config == this->config(); | |
982 default: | |
983 return false; | |
984 } | |
985 return true; | |
986 } | |
987 | |
988 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { | |
989 if (!this->canCopyTo(dstConfig)) { | |
990 return false; | |
991 } | |
992 | |
993 // if we have a texture, first get those pixels | |
994 SkBitmap tmpSrc; | |
995 const SkBitmap* src = this; | |
996 | |
997 if (fPixelRef) { | |
998 SkIRect subset; | |
999 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, | |
1000 fInfo.width(), fInfo.height()); | |
1001 if (fPixelRef->readPixels(&tmpSrc, &subset)) { | |
1002 SkASSERT(tmpSrc.width() == this->width()); | |
1003 SkASSERT(tmpSrc.height() == this->height()); | |
1004 | |
1005 // did we get lucky and we can just return tmpSrc? | |
1006 if (tmpSrc.config() == dstConfig && NULL == alloc) { | |
1007 dst->swap(tmpSrc); | |
1008 // If the result is an exact copy, clone the gen ID. | |
1009 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->inf
o()) { | |
1010 dst->pixelRef()->cloneGenID(*fPixelRef); | |
1011 } | |
1012 return true; | |
1013 } | |
1014 | |
1015 // fall through to the raster case | |
1016 src = &tmpSrc; | |
1017 } | |
1018 } | |
1019 | |
1020 // we lock this now, since we may need its colortable | |
1021 SkAutoLockPixels srclock(*src); | |
1022 if (!src->readyToDraw()) { | |
1023 return false; | |
1024 } | |
1025 | |
1026 // The only way to be readyToDraw is if fPixelRef is non NULL. | |
1027 SkASSERT(fPixelRef != NULL); | |
1028 | |
1029 SkBitmap tmpDst; | |
1030 tmpDst.setConfig(dstConfig, src->width(), src->height(), 0, | |
1031 src->alphaType()); | |
1032 | |
1033 // allocate colortable if srcConfig == kIndex8_Config | |
1034 SkColorTable* ctable = (dstConfig == kIndex8_Config) ? | |
1035 new SkColorTable(*src->getColorTable()) : NULL; | |
1036 SkAutoUnref au(ctable); | |
1037 if (!tmpDst.allocPixels(alloc, ctable)) { | |
1038 return false; | |
1039 } | |
1040 | |
1041 if (!tmpDst.readyToDraw()) { | |
1042 // allocator/lock failed | |
1043 return false; | |
1044 } | |
1045 | |
1046 // pixelRef must be non NULL or tmpDst.readyToDraw() would have | |
1047 // returned false. | |
1048 SkASSERT(tmpDst.pixelRef() != NULL); | |
1049 | |
1050 /* do memcpy for the same configs cases, else use drawing | |
1051 */ | |
1052 if (src->config() == dstConfig) { | |
1053 if (tmpDst.getSize() == src->getSize()) { | |
1054 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); | |
1055 SkPixelRef* pixelRef = tmpDst.pixelRef(); | |
1056 | |
1057 // In order to reach this point, we know that the width, config and | |
1058 // rowbytes of the SkPixelRefs are the same, but it is possible for | |
1059 // the heights to differ, if this SkBitmap's height is a subset of | |
1060 // fPixelRef. Only if the SkPixelRefs' heights match are we | |
1061 // guaranteed that this is an exact copy, meaning we should clone | |
1062 // the genID. | |
1063 if (pixelRef->info().fHeight == fPixelRef->info().fHeight) { | |
1064 // TODO: what to do if the two infos match, BUT | |
1065 // fPixelRef is premul and pixelRef is opaque? | |
1066 // skipping assert for now | |
1067 // https://code.google.com/p/skia/issues/detail?id=2012 | |
1068 // SkASSERT(pixelRef->info() == fPixelRef->info()); | |
1069 SkASSERT(pixelRef->info().fWidth == fPixelRef->info().fWidth); | |
1070 SkASSERT(pixelRef->info().fColorType == fPixelRef->info().fColor
Type); | |
1071 pixelRef->cloneGenID(*fPixelRef); | |
1072 } | |
1073 } else { | |
1074 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); | |
1075 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); | |
1076 // to be sure we don't read too much, only copy our logical pixels | |
1077 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); | |
1078 for (int y = 0; y < tmpDst.height(); y++) { | |
1079 memcpy(dstP, srcP, bytesToCopy); | |
1080 srcP += src->rowBytes(); | |
1081 dstP += tmpDst.rowBytes(); | |
1082 } | |
1083 } | |
1084 } else if (SkBitmap::kARGB_4444_Config == dstConfig | |
1085 && SkBitmap::kARGB_8888_Config == src->config()) { | |
1086 SkASSERT(src->height() == tmpDst.height()); | |
1087 SkASSERT(src->width() == tmpDst.width()); | |
1088 for (int y = 0; y < src->height(); ++y) { | |
1089 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0,
y); | |
1090 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); | |
1091 DITHER_4444_SCAN(y); | |
1092 for (int x = 0; x < src->width(); ++x) { | |
1093 dstRow[x] = SkDitherARGB32To4444(srcRow[x], | |
1094 DITHER_VALUE(x)); | |
1095 } | |
1096 } | |
1097 } else { | |
1098 // Always clear the dest in case one of the blitters accesses it | |
1099 // TODO: switch the allocation of tmpDst to call sk_calloc_throw | |
1100 tmpDst.eraseColor(SK_ColorTRANSPARENT); | |
1101 | |
1102 SkCanvas canvas(tmpDst); | |
1103 SkPaint paint; | |
1104 | |
1105 paint.setDither(true); | |
1106 canvas.drawBitmap(*src, 0, 0, &paint); | |
1107 } | |
1108 | |
1109 dst->swap(tmpDst); | |
1110 return true; | |
1111 } | |
1112 | |
1113 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { | |
1114 const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig); | |
1115 | |
1116 if (!this->canCopyTo(dstConfig)) { | |
1117 return false; | |
1118 } | |
1119 | |
1120 // If we have a PixelRef, and it supports deep copy, use it. | |
1121 // Currently supported only by texture-backed bitmaps. | |
1122 if (fPixelRef) { | |
1123 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); | |
1124 if (pixelRef) { | |
1125 uint32_t rowBytes; | |
1126 if (this->colorType() == dstCT) { | |
1127 // Since there is no subset to pass to deepCopy, and deepCopy | |
1128 // succeeded, the new pixel ref must be identical. | |
1129 SkASSERT(fPixelRef->info() == pixelRef->info()); | |
1130 pixelRef->cloneGenID(*fPixelRef); | |
1131 // Use the same rowBytes as the original. | |
1132 rowBytes = fRowBytes; | |
1133 } else { | |
1134 // With the new config, an appropriate fRowBytes will be compute
d by setConfig. | |
1135 rowBytes = 0; | |
1136 } | |
1137 | |
1138 SkImageInfo info = fInfo; | |
1139 info.fColorType = dstCT; | |
1140 if (!dst->setConfig(info, rowBytes)) { | |
1141 return false; | |
1142 } | |
1143 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); | |
1144 return true; | |
1145 } | |
1146 } | |
1147 | |
1148 if (this->getTexture()) { | |
1149 return false; | |
1150 } else { | |
1151 return this->copyTo(dst, dstConfig, NULL); | |
1152 } | |
1153 } | |
1154 | |
1155 /////////////////////////////////////////////////////////////////////////////// | 869 /////////////////////////////////////////////////////////////////////////////// |
1156 /////////////////////////////////////////////////////////////////////////////// | 870 /////////////////////////////////////////////////////////////////////////////// |
1157 | 871 |
1158 static void downsampleby2_proc32(SkBitmap* dst, int x, int y, | 872 static void downsampleby2_proc32(SkBitmap* dst, int x, int y, |
1159 const SkBitmap& src) { | 873 const SkBitmap& src) { |
1160 x <<= 1; | 874 x <<= 1; |
1161 y <<= 1; | 875 y <<= 1; |
1162 const SkPMColor* p = src.getAddr32(x, y); | 876 const SkPMColor* p = src.getAddr32(x, y); |
1163 const SkPMColor* baseP = p; | 877 const SkPMColor* baseP = p; |
1164 SkPMColor c, ag, rb; | 878 SkPMColor c, ag, rb; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1258 void SkBitmap::buildMipMap(bool forceRebuild) { | 972 void SkBitmap::buildMipMap(bool forceRebuild) { |
1259 if (forceRebuild) | 973 if (forceRebuild) |
1260 this->freeMipMap(); | 974 this->freeMipMap(); |
1261 else if (fMipMap) | 975 else if (fMipMap) |
1262 return; // we're already built | 976 return; // we're already built |
1263 | 977 |
1264 SkASSERT(NULL == fMipMap); | 978 SkASSERT(NULL == fMipMap); |
1265 | 979 |
1266 void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src); | 980 void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src); |
1267 | 981 |
1268 const SkBitmap::Config config = this->config(); | 982 const SkColorType ct = this->colorType(); |
1269 | 983 |
1270 switch (config) { | 984 switch (ct) { |
1271 case kARGB_8888_Config: | 985 case kRGBA_8888_SkColorType: |
| 986 case kBGRA_8888_SkColorType: |
1272 proc = downsampleby2_proc32; | 987 proc = downsampleby2_proc32; |
1273 break; | 988 break; |
1274 case kRGB_565_Config: | 989 case kRGB_565_SkColorType: |
1275 proc = downsampleby2_proc16; | 990 proc = downsampleby2_proc16; |
1276 break; | 991 break; |
1277 case kARGB_4444_Config: | 992 case kARGB_4444_SkColorType: |
1278 proc = downsampleby2_proc4444; | 993 proc = downsampleby2_proc4444; |
1279 break; | 994 break; |
1280 case kIndex8_Config: | |
1281 case kA8_Config: | |
1282 default: | 995 default: |
1283 return; // don't build mipmaps for these configs | 996 return; // don't build mipmaps for these configs |
1284 } | 997 } |
1285 | 998 |
1286 SkAutoLockPixels alp(*this); | 999 SkAutoLockPixels alp(*this); |
1287 if (!this->readyToDraw()) { | 1000 if (!this->readyToDraw()) { |
1288 return; | 1001 return; |
1289 } | 1002 } |
1290 | 1003 |
1291 // whip through our loop to compute the exact size needed | 1004 // whip through our loop to compute the exact size needed |
1292 size_t size = 0; | 1005 size_t size = 0; |
1293 int maxLevels = 0; | 1006 int maxLevels = 0; |
1294 { | 1007 { |
1295 int width = this->width(); | 1008 int width = this->width(); |
1296 int height = this->height(); | 1009 int height = this->height(); |
1297 for (;;) { | 1010 for (;;) { |
1298 width >>= 1; | 1011 width >>= 1; |
1299 height >>= 1; | 1012 height >>= 1; |
1300 if (0 == width || 0 == height) { | 1013 if (0 == width || 0 == height) { |
1301 break; | 1014 break; |
1302 } | 1015 } |
1303 size += ComputeRowBytes(config, width) * height; | 1016 size += SkColorTypeMinRowBytes(ct, width) * height; |
1304 maxLevels += 1; | 1017 maxLevels += 1; |
1305 } | 1018 } |
1306 } | 1019 } |
1307 | 1020 |
1308 // nothing to build | 1021 // nothing to build |
1309 if (0 == maxLevels) { | 1022 if (0 == maxLevels) { |
1310 return; | 1023 return; |
1311 } | 1024 } |
1312 | 1025 |
1313 SkBitmap srcBM(*this); | 1026 SkBitmap srcBM(*this); |
(...skipping 10 matching lines...) Expand all Loading... |
1324 MipLevel* level = mm->levels(); | 1037 MipLevel* level = mm->levels(); |
1325 uint8_t* addr = (uint8_t*)mm->pixels(); | 1038 uint8_t* addr = (uint8_t*)mm->pixels(); |
1326 int width = this->width(); | 1039 int width = this->width(); |
1327 int height = this->height(); | 1040 int height = this->height(); |
1328 uint32_t rowBytes; | 1041 uint32_t rowBytes; |
1329 SkBitmap dstBM; | 1042 SkBitmap dstBM; |
1330 | 1043 |
1331 for (int i = 0; i < maxLevels; i++) { | 1044 for (int i = 0; i < maxLevels; i++) { |
1332 width >>= 1; | 1045 width >>= 1; |
1333 height >>= 1; | 1046 height >>= 1; |
1334 rowBytes = SkToU32(ComputeRowBytes(config, width)); | 1047 rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); |
1335 | 1048 |
1336 level[i].fPixels = addr; | 1049 level[i].fPixels = addr; |
1337 level[i].fWidth = width; | 1050 level[i].fWidth = width; |
1338 level[i].fHeight = height; | 1051 level[i].fHeight = height; |
1339 level[i].fRowBytes = rowBytes; | 1052 level[i].fRowBytes = rowBytes; |
1340 | 1053 |
1341 dstBM.setConfig(config, width, height, rowBytes); | 1054 SkImageInfo info = this->info(); |
1342 dstBM.setPixels(addr); | 1055 info.fWidth = width; |
| 1056 info.fHeight = height; |
| 1057 dstBM.installPixels(info, addr, rowBytes, NULL, NULL); |
1343 | 1058 |
1344 srcBM.lockPixels(); | 1059 srcBM.lockPixels(); |
1345 for (int y = 0; y < height; y++) { | 1060 for (int y = 0; y < height; y++) { |
1346 for (int x = 0; x < width; x++) { | 1061 for (int x = 0; x < width; x++) { |
1347 proc(&dstBM, x, y, srcBM); | 1062 proc(&dstBM, x, y, srcBM); |
1348 } | 1063 } |
1349 } | 1064 } |
1350 srcBM.unlockPixels(); | 1065 srcBM.unlockPixels(); |
1351 | 1066 |
1352 srcBM = dstBM; | 1067 srcBM = dstBM; |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1684 /////////////////////////////////////////////////////////////////////////////// | 1399 /////////////////////////////////////////////////////////////////////////////// |
1685 | 1400 |
1686 #ifdef SK_DEBUG | 1401 #ifdef SK_DEBUG |
1687 void SkImageInfo::validate() const { | 1402 void SkImageInfo::validate() const { |
1688 SkASSERT(fWidth >= 0); | 1403 SkASSERT(fWidth >= 0); |
1689 SkASSERT(fHeight >= 0); | 1404 SkASSERT(fHeight >= 0); |
1690 SkASSERT(SkColorTypeIsValid(fColorType)); | 1405 SkASSERT(SkColorTypeIsValid(fColorType)); |
1691 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1406 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
1692 } | 1407 } |
1693 #endif | 1408 #endif |
OLD | NEW |