| 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 |