SkBitmap.cpp revision fab349c0bf3a305b7a7388b77bab13b0f7b37393
1 2/* 3 * Copyright 2008 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkBitmap.h" 11#include "SkColorPriv.h" 12#include "SkDither.h" 13#include "SkFlattenable.h" 14#include "SkImagePriv.h" 15#include "SkMallocPixelRef.h" 16#include "SkMask.h" 17#include "SkReadBuffer.h" 18#include "SkWriteBuffer.h" 19#include "SkPixelRef.h" 20#include "SkThread.h" 21#include "SkUnPreMultiply.h" 22#include "SkUtils.h" 23#include "SkValidationUtils.h" 24#include "SkPackBits.h" 25#include <new> 26 27static bool reset_return_false(SkBitmap* bm) { 28 bm->reset(); 29 return false; 30} 31 32struct MipLevel { 33 void* fPixels; 34 uint32_t fRowBytes; 35 uint32_t fWidth, fHeight; 36}; 37 38struct SkBitmap::MipMap : SkNoncopyable { 39 int32_t fRefCnt; 40 int fLevelCount; 41// MipLevel fLevel[fLevelCount]; 42// Pixels[] 43 44 static MipMap* Alloc(int levelCount, size_t pixelSize) { 45 if (levelCount < 0) { 46 return NULL; 47 } 48 int64_t size = (levelCount + 1) * sizeof(MipLevel); 49 size += sizeof(MipMap) + pixelSize; 50 if (!sk_64_isS32(size)) { 51 return NULL; 52 } 53 MipMap* mm = (MipMap*)sk_malloc_throw(sk_64_asS32(size)); 54 mm->fRefCnt = 1; 55 mm->fLevelCount = levelCount; 56 return mm; 57 } 58 59 const MipLevel* levels() const { return (const MipLevel*)(this + 1); } 60 MipLevel* levels() { return (MipLevel*)(this + 1); } 61 62 const void* pixels() const { return levels() + fLevelCount; } 63 void* pixels() { return levels() + fLevelCount; } 64 65 void ref() { 66 if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) { 67 sk_throw(); 68 } 69 } 70 void unref() { 71 SkASSERT(fRefCnt > 0); 72 if (sk_atomic_dec(&fRefCnt) == 1) { 73 sk_free(this); 74 } 75 } 76}; 77 78/////////////////////////////////////////////////////////////////////////////// 79/////////////////////////////////////////////////////////////////////////////// 80 81SkBitmap::SkBitmap() { 82 sk_bzero(this, sizeof(*this)); 83} 84 85SkBitmap::SkBitmap(const SkBitmap& src) { 86 SkDEBUGCODE(src.validate();) 87 sk_bzero(this, sizeof(*this)); 88 *this = src; 89 SkDEBUGCODE(this->validate();) 90} 91 92SkBitmap::~SkBitmap() { 93 SkDEBUGCODE(this->validate();) 94 this->freePixels(); 95} 96 97SkBitmap& SkBitmap::operator=(const SkBitmap& src) { 98 if (this != &src) { 99 this->freePixels(); 100 memcpy(this, &src, sizeof(src)); 101 102 // inc src reference counts 103 SkSafeRef(src.fPixelRef); 104 SkSafeRef(src.fMipMap); 105 106 // we reset our locks if we get blown away 107 fPixelLockCount = 0; 108 109 if (fPixelRef) { 110 // ignore the values from the memcpy 111 fPixels = NULL; 112 fColorTable = NULL; 113 // Note that what to for genID is somewhat arbitrary. We have no 114 // way to track changes to raw pixels across multiple SkBitmaps. 115 // Would benefit from an SkRawPixelRef type created by 116 // setPixels. 117 // Just leave the memcpy'ed one but they'll get out of sync 118 // as soon either is modified. 119 } 120 } 121 122 SkDEBUGCODE(this->validate();) 123 return *this; 124} 125 126void SkBitmap::swap(SkBitmap& other) { 127 SkTSwap(fColorTable, other.fColorTable); 128 SkTSwap(fPixelRef, other.fPixelRef); 129 SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin); 130 SkTSwap(fPixelLockCount, other.fPixelLockCount); 131 SkTSwap(fMipMap, other.fMipMap); 132 SkTSwap(fPixels, other.fPixels); 133 SkTSwap(fInfo, other.fInfo); 134 SkTSwap(fRowBytes, other.fRowBytes); 135 SkTSwap(fFlags, other.fFlags); 136 137 SkDEBUGCODE(this->validate();) 138} 139 140void SkBitmap::reset() { 141 this->freePixels(); 142 sk_bzero(this, sizeof(*this)); 143} 144 145SkBitmap::Config SkBitmap::config() const { 146 return SkColorTypeToBitmapConfig(fInfo.colorType()); 147} 148 149int 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 174size_t SkBitmap::ComputeRowBytes(Config c, int width) { 175 return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), width); 176} 177 178int64_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 184size_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 189int64_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 199size_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 212void SkBitmap::getBounds(SkRect* bounds) const { 213 SkASSERT(bounds); 214 bounds->set(0, 0, 215 SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight)); 216} 217 218void SkBitmap::getBounds(SkIRect* bounds) const { 219 SkASSERT(bounds); 220 bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight); 221} 222 223/////////////////////////////////////////////////////////////////////////////// 224 225static bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType, 226 SkAlphaType* canonical = NULL) { 227 switch (colorType) { 228 case kUnknown_SkColorType: 229 alphaType = kIgnore_SkAlphaType; 230 break; 231 case kAlpha_8_SkColorType: 232 if (kUnpremul_SkAlphaType == alphaType) { 233 alphaType = kPremul_SkAlphaType; 234 } 235 // fall-through 236 case kIndex_8_SkColorType: 237 case kARGB_4444_SkColorType: 238 case kRGBA_8888_SkColorType: 239 case kBGRA_8888_SkColorType: 240 if (kIgnore_SkAlphaType == alphaType) { 241 return false; 242 } 243 break; 244 case kRGB_565_SkColorType: 245 alphaType = kOpaque_SkAlphaType; 246 break; 247 default: 248 return false; 249 } 250 if (canonical) { 251 *canonical = alphaType; 252 } 253 return true; 254} 255 256bool SkBitmap::setConfig(const SkImageInfo& origInfo, size_t rowBytes) { 257 SkImageInfo info = origInfo; 258 259 if (!validate_alphaType(info.fColorType, info.fAlphaType, 260 &info.fAlphaType)) { 261 return reset_return_false(this); 262 } 263 264 // require that rowBytes fit in 31bits 265 int64_t mrb = info.minRowBytes64(); 266 if ((int32_t)mrb != mrb) { 267 return reset_return_false(this); 268 } 269 if ((int64_t)rowBytes != (int32_t)rowBytes) { 270 return reset_return_false(this); 271 } 272 273 if (info.width() < 0 || info.height() < 0) { 274 return reset_return_false(this); 275 } 276 277 if (kUnknown_SkColorType == info.colorType()) { 278 rowBytes = 0; 279 } else if (0 == rowBytes) { 280 rowBytes = (size_t)mrb; 281 } else if (rowBytes < info.minRowBytes()) { 282 return reset_return_false(this); 283 } 284 285 this->freePixels(); 286 287 fInfo = info; 288 fRowBytes = SkToU32(rowBytes); 289 return true; 290} 291 292bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, 293 SkAlphaType alphaType) { 294 SkColorType ct = SkBitmapConfigToColorType(config); 295 return this->setConfig(SkImageInfo::Make(width, height, ct, alphaType), 296 rowBytes); 297} 298 299bool SkBitmap::setAlphaType(SkAlphaType alphaType) { 300 if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) { 301 return false; 302 } 303 if (fInfo.fAlphaType != alphaType) { 304 fInfo.fAlphaType = alphaType; 305 if (fPixelRef) { 306 fPixelRef->changeAlphaType(alphaType); 307 } 308 } 309 return true; 310} 311 312void SkBitmap::updatePixelsFromRef() const { 313 if (NULL != fPixelRef) { 314 if (fPixelLockCount > 0) { 315 SkASSERT(fPixelRef->isLocked()); 316 317 void* p = fPixelRef->pixels(); 318 if (NULL != p) { 319 p = (char*)p 320 + fPixelRefOrigin.fY * fRowBytes 321 + fPixelRefOrigin.fX * fInfo.bytesPerPixel(); 322 } 323 fPixels = p; 324 fColorTable = fPixelRef->colorTable(); 325 } else { 326 SkASSERT(0 == fPixelLockCount); 327 fPixels = NULL; 328 fColorTable = NULL; 329 } 330 } 331} 332 333static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) { 334 SkColorType ct; 335 switch (config) { 336 case SkBitmap::kA8_Config: 337 ct = kAlpha_8_SkColorType; 338 break; 339 case SkBitmap::kIndex8_Config: 340 ct = kIndex_8_SkColorType; 341 break; 342 case SkBitmap::kRGB_565_Config: 343 ct = kRGB_565_SkColorType; 344 break; 345 case SkBitmap::kARGB_4444_Config: 346 ct = kARGB_4444_SkColorType; 347 break; 348 case SkBitmap::kARGB_8888_Config: 349 ct = kPMColor_SkColorType; 350 break; 351 case SkBitmap::kNo_Config: 352 default: 353 return false; 354 } 355 if (ctOut) { 356 *ctOut = ct; 357 } 358 return true; 359} 360 361SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { 362#ifdef SK_DEBUG 363 if (pr) { 364 SkImageInfo info; 365 if (this->asImageInfo(&info)) { 366 const SkImageInfo& prInfo = pr->info(); 367 SkASSERT(info.fWidth <= prInfo.fWidth); 368 SkASSERT(info.fHeight <= prInfo.fHeight); 369 SkASSERT(info.fColorType == prInfo.fColorType); 370 switch (prInfo.fAlphaType) { 371 case kIgnore_SkAlphaType: 372 SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType); 373 break; 374 case kOpaque_SkAlphaType: 375 case kPremul_SkAlphaType: 376 SkASSERT(info.fAlphaType == kOpaque_SkAlphaType || 377 info.fAlphaType == kPremul_SkAlphaType); 378 break; 379 case kUnpremul_SkAlphaType: 380 SkASSERT(info.fAlphaType == kOpaque_SkAlphaType || 381 info.fAlphaType == kUnpremul_SkAlphaType); 382 break; 383 } 384 } 385 } 386#endif 387 388 if (pr) { 389 const SkImageInfo& info = pr->info(); 390 fPixelRefOrigin.set(SkPin32(dx, 0, info.fWidth), 391 SkPin32(dy, 0, info.fHeight)); 392 } else { 393 // ignore dx,dy if there is no pixelref 394 fPixelRefOrigin.setZero(); 395 } 396 397 if (fPixelRef != pr) { 398 if (fPixelRef != pr) { 399 this->freePixels(); 400 SkASSERT(NULL == fPixelRef); 401 402 SkSafeRef(pr); 403 fPixelRef = pr; 404 } 405 this->updatePixelsFromRef(); 406 } 407 408 SkDEBUGCODE(this->validate();) 409 return pr; 410} 411 412void SkBitmap::lockPixels() const { 413 if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) { 414 fPixelRef->lockPixels(); 415 this->updatePixelsFromRef(); 416 } 417 SkDEBUGCODE(this->validate();) 418} 419 420void SkBitmap::unlockPixels() const { 421 SkASSERT(NULL == fPixelRef || fPixelLockCount > 0); 422 423 if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) { 424 fPixelRef->unlockPixels(); 425 this->updatePixelsFromRef(); 426 } 427 SkDEBUGCODE(this->validate();) 428} 429 430bool SkBitmap::lockPixelsAreWritable() const { 431 return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false; 432} 433 434void SkBitmap::setPixels(void* p, SkColorTable* ctable) { 435 if (NULL == p) { 436 this->setPixelRef(NULL); 437 return; 438 } 439 440 SkImageInfo info; 441 if (!this->asImageInfo(&info)) { 442 this->setPixelRef(NULL); 443 return; 444 } 445 446 SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable); 447 if (NULL == pr) { 448 this->setPixelRef(NULL); 449 return; 450 } 451 452 this->setPixelRef(pr)->unref(); 453 454 // since we're already allocated, we lockPixels right away 455 this->lockPixels(); 456 SkDEBUGCODE(this->validate();) 457} 458 459bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) { 460 HeapAllocator stdalloc; 461 462 if (NULL == allocator) { 463 allocator = &stdalloc; 464 } 465 return allocator->allocPixelRef(this, ctable); 466} 467 468/////////////////////////////////////////////////////////////////////////////// 469 470bool SkBitmap::allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory, 471 SkColorTable* ctable) { 472 if (kIndex_8_SkColorType == info.fColorType && NULL == ctable) { 473 return reset_return_false(this); 474 } 475 if (!this->setConfig(info)) { 476 return reset_return_false(this); 477 } 478 479 SkMallocPixelRef::PRFactory defaultFactory; 480 if (NULL == factory) { 481 factory = &defaultFactory; 482 } 483 484 SkPixelRef* pr = factory->create(info, ctable); 485 if (NULL == pr) { 486 return reset_return_false(this); 487 } 488 this->setPixelRef(pr)->unref(); 489 490 // TODO: lockPixels could/should return bool or void*/NULL 491 this->lockPixels(); 492 if (NULL == this->getPixels()) { 493 return reset_return_false(this); 494 } 495 return true; 496} 497 498bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb, 499 void (*releaseProc)(void* addr, void* context), 500 void* context) { 501 if (!this->setConfig(info, rb)) { 502 this->reset(); 503 return false; 504 } 505 506 SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, NULL, pixels, 507 releaseProc, context); 508 if (!pr) { 509 this->reset(); 510 return false; 511 } 512 513 this->setPixelRef(pr)->unref(); 514 515 // since we're already allocated, we lockPixels right away 516 this->lockPixels(); 517 SkDEBUGCODE(this->validate();) 518 return true; 519} 520 521bool SkBitmap::installMaskPixels(const SkMask& mask) { 522 if (SkMask::kA8_Format != mask.fFormat) { 523 this->reset(); 524 return false; 525 } 526 return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), 527 mask.fBounds.height()), 528 mask.fImage, mask.fRowBytes); 529} 530 531bool SkBitmap::allocConfigPixels(Config config, int width, int height, 532 bool isOpaque) { 533 SkColorType ct; 534 if (!config_to_colorType(config, &ct)) { 535 return false; 536 } 537 538 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 539 return this->allocPixels(SkImageInfo::Make(width, height, ct, at)); 540} 541 542/////////////////////////////////////////////////////////////////////////////// 543 544void SkBitmap::freePixels() { 545 // if we're gonna free the pixels, we certainly need to free the mipmap 546 this->freeMipMap(); 547 548 if (NULL != fPixelRef) { 549 if (fPixelLockCount > 0) { 550 fPixelRef->unlockPixels(); 551 } 552 fPixelRef->unref(); 553 fPixelRef = NULL; 554 fPixelRefOrigin.setZero(); 555 } 556 fPixelLockCount = 0; 557 fPixels = NULL; 558 fColorTable = NULL; 559} 560 561void SkBitmap::freeMipMap() { 562 if (fMipMap) { 563 fMipMap->unref(); 564 fMipMap = NULL; 565 } 566} 567 568uint32_t SkBitmap::getGenerationID() const { 569 return (fPixelRef) ? fPixelRef->getGenerationID() : 0; 570} 571 572void SkBitmap::notifyPixelsChanged() const { 573 SkASSERT(!this->isImmutable()); 574 if (fPixelRef) { 575 fPixelRef->notifyPixelsChanged(); 576 } 577} 578 579GrTexture* SkBitmap::getTexture() const { 580 return fPixelRef ? fPixelRef->getTexture() : NULL; 581} 582 583/////////////////////////////////////////////////////////////////////////////// 584 585/** We explicitly use the same allocator for our pixels that SkMask does, 586 so that we can freely assign memory allocated by one class to the other. 587 */ 588bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, 589 SkColorTable* ctable) { 590 SkImageInfo info; 591 if (!dst->asImageInfo(&info)) { 592// SkDebugf("unsupported config for info %d\n", dst->config()); 593 return false; 594 } 595 596 SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), 597 ctable); 598 if (NULL == pr) { 599 return false; 600 } 601 602 dst->setPixelRef(pr)->unref(); 603 // since we're already allocated, we lockPixels right away 604 dst->lockPixels(); 605 return true; 606} 607 608/////////////////////////////////////////////////////////////////////////////// 609 610bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize, 611 size_t dstRowBytes, bool preserveDstPad) const { 612 613 if (0 == dstRowBytes) { 614 dstRowBytes = fRowBytes; 615 } 616 617 if (dstRowBytes < fInfo.minRowBytes() || 618 dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) { 619 return false; 620 } 621 622 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) { 623 size_t safeSize = this->getSafeSize(); 624 if (safeSize > dstSize || safeSize == 0) 625 return false; 626 else { 627 SkAutoLockPixels lock(*this); 628 // This implementation will write bytes beyond the end of each row, 629 // excluding the last row, if the bitmap's stride is greater than 630 // strictly required by the current config. 631 memcpy(dst, getPixels(), safeSize); 632 633 return true; 634 } 635 } else { 636 // If destination has different stride than us, then copy line by line. 637 if (fInfo.getSafeSize(dstRowBytes) > dstSize) { 638 return false; 639 } else { 640 // Just copy what we need on each line. 641 size_t rowBytes = fInfo.minRowBytes(); 642 SkAutoLockPixels lock(*this); 643 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels()); 644 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); 645 for (int row = 0; row < fInfo.fHeight; 646 row++, srcP += fRowBytes, dstP += dstRowBytes) { 647 memcpy(dstP, srcP, rowBytes); 648 } 649 650 return true; 651 } 652 } 653} 654 655/////////////////////////////////////////////////////////////////////////////// 656 657bool SkBitmap::isImmutable() const { 658 return fPixelRef ? fPixelRef->isImmutable() : 659 fFlags & kImageIsImmutable_Flag; 660} 661 662void SkBitmap::setImmutable() { 663 if (fPixelRef) { 664 fPixelRef->setImmutable(); 665 } else { 666 fFlags |= kImageIsImmutable_Flag; 667 } 668} 669 670bool SkBitmap::isVolatile() const { 671 return (fFlags & kImageIsVolatile_Flag) != 0; 672} 673 674void SkBitmap::setIsVolatile(bool isVolatile) { 675 if (isVolatile) { 676 fFlags |= kImageIsVolatile_Flag; 677 } else { 678 fFlags &= ~kImageIsVolatile_Flag; 679 } 680} 681 682void* SkBitmap::getAddr(int x, int y) const { 683 SkASSERT((unsigned)x < (unsigned)this->width()); 684 SkASSERT((unsigned)y < (unsigned)this->height()); 685 686 char* base = (char*)this->getPixels(); 687 if (base) { 688 base += y * this->rowBytes(); 689 switch (this->colorType()) { 690 case kRGBA_8888_SkColorType: 691 case kBGRA_8888_SkColorType: 692 base += x << 2; 693 break; 694 case kARGB_4444_SkColorType: 695 case kRGB_565_SkColorType: 696 base += x << 1; 697 break; 698 case kAlpha_8_SkColorType: 699 case kIndex_8_SkColorType: 700 base += x; 701 break; 702 default: 703 SkDEBUGFAIL("Can't return addr for config"); 704 base = NULL; 705 break; 706 } 707 } 708 return base; 709} 710 711SkColor SkBitmap::getColor(int x, int y) const { 712 SkASSERT((unsigned)x < (unsigned)this->width()); 713 SkASSERT((unsigned)y < (unsigned)this->height()); 714 715 switch (this->config()) { 716 case SkBitmap::kA8_Config: { 717 uint8_t* addr = this->getAddr8(x, y); 718 return SkColorSetA(0, addr[0]); 719 } 720 case SkBitmap::kIndex8_Config: { 721 SkPMColor c = this->getIndex8Color(x, y); 722 return SkUnPreMultiply::PMColorToColor(c); 723 } 724 case SkBitmap::kRGB_565_Config: { 725 uint16_t* addr = this->getAddr16(x, y); 726 return SkPixel16ToColor(addr[0]); 727 } 728 case SkBitmap::kARGB_4444_Config: { 729 uint16_t* addr = this->getAddr16(x, y); 730 SkPMColor c = SkPixel4444ToPixel32(addr[0]); 731 return SkUnPreMultiply::PMColorToColor(c); 732 } 733 case SkBitmap::kARGB_8888_Config: { 734 uint32_t* addr = this->getAddr32(x, y); 735 return SkUnPreMultiply::PMColorToColor(addr[0]); 736 } 737 case kNo_Config: 738 default: 739 SkASSERT(false); 740 return 0; 741 } 742 SkASSERT(false); // Not reached. 743 return 0; 744} 745 746bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { 747 SkAutoLockPixels alp(bm); 748 if (!bm.getPixels()) { 749 return false; 750 } 751 752 const int height = bm.height(); 753 const int width = bm.width(); 754 755 switch (bm.config()) { 756 case SkBitmap::kA8_Config: { 757 unsigned a = 0xFF; 758 for (int y = 0; y < height; ++y) { 759 const uint8_t* row = bm.getAddr8(0, y); 760 for (int x = 0; x < width; ++x) { 761 a &= row[x]; 762 } 763 if (0xFF != a) { 764 return false; 765 } 766 } 767 return true; 768 } break; 769 case SkBitmap::kIndex8_Config: { 770 SkAutoLockColors alc(bm); 771 const SkPMColor* table = alc.colors(); 772 if (!table) { 773 return false; 774 } 775 SkPMColor c = (SkPMColor)~0; 776 for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) { 777 c &= table[i]; 778 } 779 return 0xFF == SkGetPackedA32(c); 780 } break; 781 case SkBitmap::kRGB_565_Config: 782 return true; 783 break; 784 case SkBitmap::kARGB_4444_Config: { 785 unsigned c = 0xFFFF; 786 for (int y = 0; y < height; ++y) { 787 const SkPMColor16* row = bm.getAddr16(0, y); 788 for (int x = 0; x < width; ++x) { 789 c &= row[x]; 790 } 791 if (0xF != SkGetPackedA4444(c)) { 792 return false; 793 } 794 } 795 return true; 796 } break; 797 case SkBitmap::kARGB_8888_Config: { 798 SkPMColor c = (SkPMColor)~0; 799 for (int y = 0; y < height; ++y) { 800 const SkPMColor* row = bm.getAddr32(0, y); 801 for (int x = 0; x < width; ++x) { 802 c &= row[x]; 803 } 804 if (0xFF != SkGetPackedA32(c)) { 805 return false; 806 } 807 } 808 return true; 809 } 810 default: 811 break; 812 } 813 return false; 814} 815 816 817/////////////////////////////////////////////////////////////////////////////// 818/////////////////////////////////////////////////////////////////////////////// 819 820static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) { 821 unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | 822 (SkR32To4444(r) << SK_R4444_SHIFT) | 823 (SkG32To4444(g) << SK_G4444_SHIFT) | 824 (SkB32To4444(b) << SK_B4444_SHIFT); 825 return SkToU16(pixel); 826} 827 828void SkBitmap::internalErase(const SkIRect& area, 829 U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 830#ifdef SK_DEBUG 831 SkDEBUGCODE(this->validate();) 832 SkASSERT(!area.isEmpty()); 833 { 834 SkIRect total = { 0, 0, this->width(), this->height() }; 835 SkASSERT(total.contains(area)); 836 } 837#endif 838 839 switch (fInfo.colorType()) { 840 case kUnknown_SkColorType: 841 case kIndex_8_SkColorType: 842 return; // can't erase 843 default: 844 break; 845 } 846 847 SkAutoLockPixels alp(*this); 848 // perform this check after the lock call 849 if (!this->readyToDraw()) { 850 return; 851 } 852 853 int height = area.height(); 854 const int width = area.width(); 855 const int rowBytes = fRowBytes; 856 857 // make rgb premultiplied 858 if (255 != a) { 859 r = SkAlphaMul(r, a); 860 g = SkAlphaMul(g, a); 861 b = SkAlphaMul(b, a); 862 } 863 864 switch (this->colorType()) { 865 case kAlpha_8_SkColorType: { 866 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); 867 while (--height >= 0) { 868 memset(p, a, width); 869 p += rowBytes; 870 } 871 break; 872 } 873 case kARGB_4444_SkColorType: 874 case kRGB_565_SkColorType: { 875 uint16_t* p = this->getAddr16(area.fLeft, area.fTop);; 876 uint16_t v; 877 878 if (kARGB_4444_SkColorType == this->colorType()) { 879 v = pack_8888_to_4444(a, r, g, b); 880 } else { 881 v = SkPackRGB16(r >> (8 - SK_R16_BITS), 882 g >> (8 - SK_G16_BITS), 883 b >> (8 - SK_B16_BITS)); 884 } 885 while (--height >= 0) { 886 sk_memset16(p, v, width); 887 p = (uint16_t*)((char*)p + rowBytes); 888 } 889 break; 890 } 891 case kPMColor_SkColorType: { 892 // what to do about BGRA or RGBA (which ever is != PMColor ? 893 // for now we don't support them. 894 uint32_t* p = this->getAddr32(area.fLeft, area.fTop); 895 uint32_t v = SkPackARGB32(a, r, g, b); 896 897 while (--height >= 0) { 898 sk_memset32(p, v, width); 899 p = (uint32_t*)((char*)p + rowBytes); 900 } 901 break; 902 } 903 default: 904 return; // no change, so don't call notifyPixelsChanged() 905 } 906 907 this->notifyPixelsChanged(); 908} 909 910void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 911 SkIRect area = { 0, 0, this->width(), this->height() }; 912 if (!area.isEmpty()) { 913 this->internalErase(area, a, r, g, b); 914 } 915} 916 917void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { 918 SkIRect area = { 0, 0, this->width(), this->height() }; 919 if (area.intersect(rect)) { 920 this->internalErase(area, SkColorGetA(c), SkColorGetR(c), 921 SkColorGetG(c), SkColorGetB(c)); 922 } 923} 924 925////////////////////////////////////////////////////////////////////////////////////// 926////////////////////////////////////////////////////////////////////////////////////// 927 928bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { 929 SkDEBUGCODE(this->validate();) 930 931 if (NULL == result || NULL == fPixelRef) { 932 return false; // no src pixels 933 } 934 935 SkIRect srcRect, r; 936 srcRect.set(0, 0, this->width(), this->height()); 937 if (!r.intersect(srcRect, subset)) { 938 return false; // r is empty (i.e. no intersection) 939 } 940 941 if (fPixelRef->getTexture() != NULL) { 942 // Do a deep copy 943 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); 944 if (pixelRef != NULL) { 945 SkBitmap dst; 946 dst.setConfig(this->config(), subset.width(), subset.height(), 0, 947 this->alphaType()); 948 dst.setIsVolatile(this->isVolatile()); 949 dst.setPixelRef(pixelRef)->unref(); 950 SkDEBUGCODE(dst.validate()); 951 result->swap(dst); 952 return true; 953 } 954 } 955 956 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 957 // exited above. 958 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 959 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 960 961 SkBitmap dst; 962 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), 963 this->alphaType()); 964 dst.setIsVolatile(this->isVolatile()); 965 966 if (fPixelRef) { 967 SkIPoint origin = fPixelRefOrigin; 968 origin.fX += r.fLeft; 969 origin.fY += r.fTop; 970 // share the pixelref with a custom offset 971 dst.setPixelRef(fPixelRef, origin); 972 } 973 SkDEBUGCODE(dst.validate();) 974 975 // we know we're good, so commit to result 976 result->swap(dst); 977 return true; 978} 979 980/////////////////////////////////////////////////////////////////////////////// 981 982#include "SkCanvas.h" 983#include "SkPaint.h" 984 985#ifdef SK_SUPPORT_LEGACY_COPYTO_CONFIG 986bool SkBitmap::copyTo(SkBitmap* dst, Config c, Allocator* allocator) const { 987 return this->copyTo(dst, SkBitmapConfigToColorType(c), allocator); 988} 989 990bool SkBitmap::canCopyTo(Config newConfig) const { 991 return this->canCopyTo(SkBitmapConfigToColorType(newConfig)); 992} 993#endif 994 995bool SkBitmap::canCopyTo(SkColorType dstColorType) const { 996 if (this->colorType() == kUnknown_SkColorType) { 997 return false; 998 } 999 1000 bool sameConfigs = (this->colorType() == dstColorType); 1001 switch (dstColorType) { 1002 case kAlpha_8_SkColorType: 1003 case kRGB_565_SkColorType: 1004 case kPMColor_SkColorType: 1005 break; 1006 case kIndex_8_SkColorType: 1007 if (!sameConfigs) { 1008 return false; 1009 } 1010 break; 1011 case kARGB_4444_SkColorType: 1012 return sameConfigs || kPMColor_SkColorType == this->colorType(); 1013 default: 1014 return false; 1015 } 1016 return true; 1017} 1018 1019bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, 1020 Allocator* alloc) const { 1021 if (!this->canCopyTo(dstColorType)) { 1022 return false; 1023 } 1024 1025 // if we have a texture, first get those pixels 1026 SkBitmap tmpSrc; 1027 const SkBitmap* src = this; 1028 1029 if (fPixelRef) { 1030 SkIRect subset; 1031 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, 1032 fInfo.width(), fInfo.height()); 1033 if (fPixelRef->readPixels(&tmpSrc, &subset)) { 1034 SkASSERT(tmpSrc.width() == this->width()); 1035 SkASSERT(tmpSrc.height() == this->height()); 1036 1037 // did we get lucky and we can just return tmpSrc? 1038 if (tmpSrc.colorType() == dstColorType && NULL == alloc) { 1039 dst->swap(tmpSrc); 1040 // If the result is an exact copy, clone the gen ID. 1041 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) { 1042 dst->pixelRef()->cloneGenID(*fPixelRef); 1043 } 1044 return true; 1045 } 1046 1047 // fall through to the raster case 1048 src = &tmpSrc; 1049 } 1050 } 1051 1052 // we lock this now, since we may need its colortable 1053 SkAutoLockPixels srclock(*src); 1054 if (!src->readyToDraw()) { 1055 return false; 1056 } 1057 1058 // The only way to be readyToDraw is if fPixelRef is non NULL. 1059 SkASSERT(fPixelRef != NULL); 1060 1061 SkImageInfo dstInfo = src->info(); 1062 dstInfo.fColorType = dstColorType; 1063 1064 SkBitmap tmpDst; 1065 if (!tmpDst.setConfig(dstInfo)) { 1066 return false; 1067 } 1068 1069 // allocate colortable if srcConfig == kIndex8_Config 1070 SkAutoTUnref<SkColorTable> ctable; 1071 if (dstColorType == kIndex_8_SkColorType) { 1072 // TODO: can we just ref() the src colortable? Is it reentrant-safe? 1073 ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable()))); 1074 } 1075 if (!tmpDst.allocPixels(alloc, ctable)) { 1076 return false; 1077 } 1078 1079 if (!tmpDst.readyToDraw()) { 1080 // allocator/lock failed 1081 return false; 1082 } 1083 1084 // pixelRef must be non NULL or tmpDst.readyToDraw() would have 1085 // returned false. 1086 SkASSERT(tmpDst.pixelRef() != NULL); 1087 1088 /* do memcpy for the same configs cases, else use drawing 1089 */ 1090 if (src->colorType() == dstColorType) { 1091 if (tmpDst.getSize() == src->getSize()) { 1092 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); 1093 SkPixelRef* pixelRef = tmpDst.pixelRef(); 1094 1095 // In order to reach this point, we know that the width, config and 1096 // rowbytes of the SkPixelRefs are the same, but it is possible for 1097 // the heights to differ, if this SkBitmap's height is a subset of 1098 // fPixelRef. Only if the SkPixelRefs' heights match are we 1099 // guaranteed that this is an exact copy, meaning we should clone 1100 // the genID. 1101 if (pixelRef->info().fHeight == fPixelRef->info().fHeight) { 1102 // TODO: what to do if the two infos match, BUT 1103 // fPixelRef is premul and pixelRef is opaque? 1104 // skipping assert for now 1105 // https://code.google.com/p/skia/issues/detail?id=2012 1106// SkASSERT(pixelRef->info() == fPixelRef->info()); 1107 SkASSERT(pixelRef->info().fWidth == fPixelRef->info().fWidth); 1108 SkASSERT(pixelRef->info().fColorType == fPixelRef->info().fColorType); 1109 pixelRef->cloneGenID(*fPixelRef); 1110 } 1111 } else { 1112 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); 1113 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); 1114 // to be sure we don't read too much, only copy our logical pixels 1115 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); 1116 for (int y = 0; y < tmpDst.height(); y++) { 1117 memcpy(dstP, srcP, bytesToCopy); 1118 srcP += src->rowBytes(); 1119 dstP += tmpDst.rowBytes(); 1120 } 1121 } 1122 } else if (kARGB_4444_SkColorType == dstColorType 1123 && kPMColor_SkColorType == src->colorType()) { 1124 SkASSERT(src->height() == tmpDst.height()); 1125 SkASSERT(src->width() == tmpDst.width()); 1126 for (int y = 0; y < src->height(); ++y) { 1127 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); 1128 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); 1129 DITHER_4444_SCAN(y); 1130 for (int x = 0; x < src->width(); ++x) { 1131 dstRow[x] = SkDitherARGB32To4444(srcRow[x], 1132 DITHER_VALUE(x)); 1133 } 1134 } 1135 } else { 1136 // Always clear the dest in case one of the blitters accesses it 1137 // TODO: switch the allocation of tmpDst to call sk_calloc_throw 1138 tmpDst.eraseColor(SK_ColorTRANSPARENT); 1139 1140 SkCanvas canvas(tmpDst); 1141 SkPaint paint; 1142 1143 paint.setDither(true); 1144 canvas.drawBitmap(*src, 0, 0, &paint); 1145 } 1146 1147 dst->swap(tmpDst); 1148 return true; 1149} 1150 1151bool SkBitmap::deepCopyTo(SkBitmap* dst) const { 1152 const SkBitmap::Config dstConfig = this->config(); 1153 const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig); 1154 1155 if (!this->canCopyTo(dstCT)) { 1156 return false; 1157 } 1158 1159 // If we have a PixelRef, and it supports deep copy, use it. 1160 // Currently supported only by texture-backed bitmaps. 1161 if (fPixelRef) { 1162 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); 1163 if (pixelRef) { 1164 uint32_t rowBytes; 1165 if (this->colorType() == dstCT) { 1166 // Since there is no subset to pass to deepCopy, and deepCopy 1167 // succeeded, the new pixel ref must be identical. 1168 SkASSERT(fPixelRef->info() == pixelRef->info()); 1169 pixelRef->cloneGenID(*fPixelRef); 1170 // Use the same rowBytes as the original. 1171 rowBytes = fRowBytes; 1172 } else { 1173 // With the new config, an appropriate fRowBytes will be computed by setConfig. 1174 rowBytes = 0; 1175 } 1176 1177 SkImageInfo info = fInfo; 1178 info.fColorType = dstCT; 1179 if (!dst->setConfig(info, rowBytes)) { 1180 return false; 1181 } 1182 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); 1183 return true; 1184 } 1185 } 1186 1187 if (this->getTexture()) { 1188 return false; 1189 } else { 1190 return this->copyTo(dst, dstCT, NULL); 1191 } 1192} 1193 1194/////////////////////////////////////////////////////////////////////////////// 1195/////////////////////////////////////////////////////////////////////////////// 1196 1197static void downsampleby2_proc32(SkBitmap* dst, int x, int y, 1198 const SkBitmap& src) { 1199 x <<= 1; 1200 y <<= 1; 1201 const SkPMColor* p = src.getAddr32(x, y); 1202 const SkPMColor* baseP = p; 1203 SkPMColor c, ag, rb; 1204 1205 c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF; 1206 if (x < src.width() - 1) { 1207 p += 1; 1208 } 1209 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1210 1211 p = baseP; 1212 if (y < src.height() - 1) { 1213 p += src.rowBytes() >> 2; 1214 } 1215 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1216 if (x < src.width() - 1) { 1217 p += 1; 1218 } 1219 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1220 1221 *dst->getAddr32(x >> 1, y >> 1) = 1222 ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00); 1223} 1224 1225static inline uint32_t expand16(U16CPU c) { 1226 return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16); 1227} 1228 1229// returns dirt in the top 16bits, but we don't care, since we only 1230// store the low 16bits. 1231static inline U16CPU pack16(uint32_t c) { 1232 return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE); 1233} 1234 1235static void downsampleby2_proc16(SkBitmap* dst, int x, int y, 1236 const SkBitmap& src) { 1237 x <<= 1; 1238 y <<= 1; 1239 const uint16_t* p = src.getAddr16(x, y); 1240 const uint16_t* baseP = p; 1241 SkPMColor c; 1242 1243 c = expand16(*p); 1244 if (x < src.width() - 1) { 1245 p += 1; 1246 } 1247 c += expand16(*p); 1248 1249 p = baseP; 1250 if (y < src.height() - 1) { 1251 p += src.rowBytes() >> 1; 1252 } 1253 c += expand16(*p); 1254 if (x < src.width() - 1) { 1255 p += 1; 1256 } 1257 c += expand16(*p); 1258 1259 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2); 1260} 1261 1262static uint32_t expand4444(U16CPU c) { 1263 return (c & 0xF0F) | ((c & ~0xF0F) << 12); 1264} 1265 1266static U16CPU collaps4444(uint32_t c) { 1267 return (c & 0xF0F) | ((c >> 12) & ~0xF0F); 1268} 1269 1270static void downsampleby2_proc4444(SkBitmap* dst, int x, int y, 1271 const SkBitmap& src) { 1272 x <<= 1; 1273 y <<= 1; 1274 const uint16_t* p = src.getAddr16(x, y); 1275 const uint16_t* baseP = p; 1276 uint32_t c; 1277 1278 c = expand4444(*p); 1279 if (x < src.width() - 1) { 1280 p += 1; 1281 } 1282 c += expand4444(*p); 1283 1284 p = baseP; 1285 if (y < src.height() - 1) { 1286 p += src.rowBytes() >> 1; 1287 } 1288 c += expand4444(*p); 1289 if (x < src.width() - 1) { 1290 p += 1; 1291 } 1292 c += expand4444(*p); 1293 1294 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2); 1295} 1296 1297void SkBitmap::buildMipMap(bool forceRebuild) { 1298 if (forceRebuild) 1299 this->freeMipMap(); 1300 else if (fMipMap) 1301 return; // we're already built 1302 1303 SkASSERT(NULL == fMipMap); 1304 1305 void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src); 1306 1307 const SkBitmap::Config config = this->config(); 1308 1309 switch (config) { 1310 case kARGB_8888_Config: 1311 proc = downsampleby2_proc32; 1312 break; 1313 case kRGB_565_Config: 1314 proc = downsampleby2_proc16; 1315 break; 1316 case kARGB_4444_Config: 1317 proc = downsampleby2_proc4444; 1318 break; 1319 case kIndex8_Config: 1320 case kA8_Config: 1321 default: 1322 return; // don't build mipmaps for these configs 1323 } 1324 1325 SkAutoLockPixels alp(*this); 1326 if (!this->readyToDraw()) { 1327 return; 1328 } 1329 1330 // whip through our loop to compute the exact size needed 1331 size_t size = 0; 1332 int maxLevels = 0; 1333 { 1334 int width = this->width(); 1335 int height = this->height(); 1336 for (;;) { 1337 width >>= 1; 1338 height >>= 1; 1339 if (0 == width || 0 == height) { 1340 break; 1341 } 1342 size += ComputeRowBytes(config, width) * height; 1343 maxLevels += 1; 1344 } 1345 } 1346 1347 // nothing to build 1348 if (0 == maxLevels) { 1349 return; 1350 } 1351 1352 SkBitmap srcBM(*this); 1353 srcBM.lockPixels(); 1354 if (!srcBM.readyToDraw()) { 1355 return; 1356 } 1357 1358 MipMap* mm = MipMap::Alloc(maxLevels, size); 1359 if (NULL == mm) { 1360 return; 1361 } 1362 1363 MipLevel* level = mm->levels(); 1364 uint8_t* addr = (uint8_t*)mm->pixels(); 1365 int width = this->width(); 1366 int height = this->height(); 1367 uint32_t rowBytes; 1368 SkBitmap dstBM; 1369 1370 for (int i = 0; i < maxLevels; i++) { 1371 width >>= 1; 1372 height >>= 1; 1373 rowBytes = SkToU32(ComputeRowBytes(config, width)); 1374 1375 level[i].fPixels = addr; 1376 level[i].fWidth = width; 1377 level[i].fHeight = height; 1378 level[i].fRowBytes = rowBytes; 1379 1380 dstBM.setConfig(config, width, height, rowBytes); 1381 dstBM.setPixels(addr); 1382 1383 srcBM.lockPixels(); 1384 for (int y = 0; y < height; y++) { 1385 for (int x = 0; x < width; x++) { 1386 proc(&dstBM, x, y, srcBM); 1387 } 1388 } 1389 srcBM.unlockPixels(); 1390 1391 srcBM = dstBM; 1392 addr += height * rowBytes; 1393 } 1394 SkASSERT(addr == (uint8_t*)mm->pixels() + size); 1395 fMipMap = mm; 1396} 1397 1398bool SkBitmap::hasMipMap() const { 1399 return fMipMap != NULL; 1400} 1401 1402int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) { 1403 if (NULL == fMipMap) { 1404 return 0; 1405 } 1406 1407 int level = ComputeMipLevel(sx, sy) >> 16; 1408 SkASSERT(level >= 0); 1409 if (level <= 0) { 1410 return 0; 1411 } 1412 1413 if (level >= fMipMap->fLevelCount) { 1414 level = fMipMap->fLevelCount - 1; 1415 } 1416 if (dst) { 1417 const MipLevel& mip = fMipMap->levels()[level - 1]; 1418 dst->setConfig((SkBitmap::Config)this->config(), 1419 mip.fWidth, mip.fHeight, mip.fRowBytes); 1420 dst->setPixels(mip.fPixels); 1421 } 1422 return level; 1423} 1424 1425SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) { 1426 sx = SkAbs32(sx); 1427 sy = SkAbs32(sy); 1428 if (sx < sy) { 1429 sx = sy; 1430 } 1431 if (sx < SK_Fixed1) { 1432 return 0; 1433 } 1434 int clz = SkCLZ(sx); 1435 SkASSERT(clz >= 1 && clz <= 15); 1436 return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16); 1437} 1438 1439/////////////////////////////////////////////////////////////////////////////// 1440 1441static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, 1442 int alphaRowBytes) { 1443 SkASSERT(alpha != NULL); 1444 SkASSERT(alphaRowBytes >= src.width()); 1445 1446 SkBitmap::Config config = src.config(); 1447 int w = src.width(); 1448 int h = src.height(); 1449 size_t rb = src.rowBytes(); 1450 1451 SkAutoLockPixels alp(src); 1452 if (!src.readyToDraw()) { 1453 // zero out the alpha buffer and return 1454 while (--h >= 0) { 1455 memset(alpha, 0, w); 1456 alpha += alphaRowBytes; 1457 } 1458 return false; 1459 } 1460 1461 if (SkBitmap::kA8_Config == config && !src.isOpaque()) { 1462 const uint8_t* s = src.getAddr8(0, 0); 1463 while (--h >= 0) { 1464 memcpy(alpha, s, w); 1465 s += rb; 1466 alpha += alphaRowBytes; 1467 } 1468 } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) { 1469 const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0); 1470 while (--h >= 0) { 1471 for (int x = 0; x < w; x++) { 1472 alpha[x] = SkGetPackedA32(s[x]); 1473 } 1474 s = (const SkPMColor*)((const char*)s + rb); 1475 alpha += alphaRowBytes; 1476 } 1477 } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) { 1478 const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0); 1479 while (--h >= 0) { 1480 for (int x = 0; x < w; x++) { 1481 alpha[x] = SkPacked4444ToA32(s[x]); 1482 } 1483 s = (const SkPMColor16*)((const char*)s + rb); 1484 alpha += alphaRowBytes; 1485 } 1486 } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) { 1487 SkColorTable* ct = src.getColorTable(); 1488 if (ct) { 1489 const SkPMColor* SK_RESTRICT table = ct->lockColors(); 1490 const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0); 1491 while (--h >= 0) { 1492 for (int x = 0; x < w; x++) { 1493 alpha[x] = SkGetPackedA32(table[s[x]]); 1494 } 1495 s += rb; 1496 alpha += alphaRowBytes; 1497 } 1498 ct->unlockColors(); 1499 } 1500 } else { // src is opaque, so just fill alpha[] with 0xFF 1501 memset(alpha, 0xFF, h * alphaRowBytes); 1502 } 1503 return true; 1504} 1505 1506#include "SkPaint.h" 1507#include "SkMaskFilter.h" 1508#include "SkMatrix.h" 1509 1510bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, 1511 Allocator *allocator, SkIPoint* offset) const { 1512 SkDEBUGCODE(this->validate();) 1513 1514 SkBitmap tmpBitmap; 1515 SkMatrix identity; 1516 SkMask srcM, dstM; 1517 1518 srcM.fBounds.set(0, 0, this->width(), this->height()); 1519 srcM.fRowBytes = SkAlign4(this->width()); 1520 srcM.fFormat = SkMask::kA8_Format; 1521 1522 SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL; 1523 1524 // compute our (larger?) dst bounds if we have a filter 1525 if (NULL != filter) { 1526 identity.reset(); 1527 srcM.fImage = NULL; 1528 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1529 goto NO_FILTER_CASE; 1530 } 1531 dstM.fRowBytes = SkAlign4(dstM.fBounds.width()); 1532 } else { 1533 NO_FILTER_CASE: 1534 tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(), 1535 srcM.fRowBytes); 1536 if (!tmpBitmap.allocPixels(allocator, NULL)) { 1537 // Allocation of pixels for alpha bitmap failed. 1538 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1539 tmpBitmap.width(), tmpBitmap.height()); 1540 return false; 1541 } 1542 GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes); 1543 if (offset) { 1544 offset->set(0, 0); 1545 } 1546 tmpBitmap.swap(*dst); 1547 return true; 1548 } 1549 srcM.fImage = SkMask::AllocImage(srcM.computeImageSize()); 1550 SkAutoMaskFreeImage srcCleanup(srcM.fImage); 1551 1552 GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes); 1553 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1554 goto NO_FILTER_CASE; 1555 } 1556 SkAutoMaskFreeImage dstCleanup(dstM.fImage); 1557 1558 tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(), 1559 dstM.fBounds.height(), dstM.fRowBytes); 1560 if (!tmpBitmap.allocPixels(allocator, NULL)) { 1561 // Allocation of pixels for alpha bitmap failed. 1562 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1563 tmpBitmap.width(), tmpBitmap.height()); 1564 return false; 1565 } 1566 memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize()); 1567 if (offset) { 1568 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); 1569 } 1570 SkDEBUGCODE(tmpBitmap.validate();) 1571 1572 tmpBitmap.swap(*dst); 1573 return true; 1574} 1575 1576/////////////////////////////////////////////////////////////////////////////// 1577 1578enum { 1579 SERIALIZE_PIXELTYPE_NONE, 1580 SERIALIZE_PIXELTYPE_REF_DATA 1581}; 1582 1583void SkBitmap::flatten(SkWriteBuffer& buffer) const { 1584 fInfo.flatten(buffer); 1585 buffer.writeInt(fRowBytes); 1586 1587 if (fPixelRef) { 1588 if (fPixelRef->getFactory()) { 1589 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); 1590 buffer.writeInt(fPixelRefOrigin.fX); 1591 buffer.writeInt(fPixelRefOrigin.fY); 1592 buffer.writeFlattenable(fPixelRef); 1593 return; 1594 } 1595 // if we get here, we can't record the pixels 1596 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1597 } else { 1598 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1599 } 1600} 1601 1602void SkBitmap::unflatten(SkReadBuffer& buffer) { 1603 this->reset(); 1604 1605 SkImageInfo info; 1606 info.unflatten(buffer); 1607 size_t rowBytes = buffer.readInt(); 1608 if (!buffer.validate((info.width() >= 0) && (info.height() >= 0) && 1609 SkColorTypeIsValid(info.fColorType) && 1610 SkAlphaTypeIsValid(info.fAlphaType) && 1611 validate_alphaType(info.fColorType, info.fAlphaType) && 1612 info.validRowBytes(rowBytes))) { 1613 return; 1614 } 1615 1616 bool configIsValid = this->setConfig(info, rowBytes); 1617 buffer.validate(configIsValid); 1618 1619 int reftype = buffer.readInt(); 1620 if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) || 1621 (SERIALIZE_PIXELTYPE_NONE == reftype))) { 1622 switch (reftype) { 1623 case SERIALIZE_PIXELTYPE_REF_DATA: { 1624 SkIPoint origin; 1625 origin.fX = buffer.readInt(); 1626 origin.fY = buffer.readInt(); 1627 size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel(); 1628 SkPixelRef* pr = buffer.readPixelRef(); 1629 if (!buffer.validate((NULL == pr) || 1630 (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) { 1631 origin.setZero(); 1632 } 1633 SkSafeUnref(this->setPixelRef(pr, origin)); 1634 break; 1635 } 1636 case SERIALIZE_PIXELTYPE_NONE: 1637 break; 1638 default: 1639 SkDEBUGFAIL("unrecognized pixeltype in serialized data"); 1640 sk_throw(); 1641 } 1642 } 1643} 1644 1645/////////////////////////////////////////////////////////////////////////////// 1646 1647SkBitmap::RLEPixels::RLEPixels(int width, int height) { 1648 fHeight = height; 1649 fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*)); 1650} 1651 1652SkBitmap::RLEPixels::~RLEPixels() { 1653 sk_free(fYPtrs); 1654} 1655 1656/////////////////////////////////////////////////////////////////////////////// 1657 1658#ifdef SK_DEBUG 1659void SkBitmap::validate() const { 1660 fInfo.validate(); 1661 1662 // ImageInfo may not require this, but Bitmap ensures that opaque-only 1663 // colorTypes report opaque for their alphatype 1664 if (kRGB_565_SkColorType == fInfo.colorType()) { 1665 SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType()); 1666 } 1667 1668 SkASSERT(fInfo.validRowBytes(fRowBytes)); 1669 uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag; 1670#ifdef SK_BUILD_FOR_ANDROID 1671 allFlags |= kHasHardwareMipMap_Flag; 1672#endif 1673 SkASSERT(fFlags <= allFlags); 1674 SkASSERT(fPixelLockCount >= 0); 1675 1676 if (fPixels) { 1677 SkASSERT(fPixelRef); 1678 SkASSERT(fPixelLockCount > 0); 1679 SkASSERT(fPixelRef->isLocked()); 1680 SkASSERT(fPixelRef->rowBytes() == fRowBytes); 1681 SkASSERT(fPixelRefOrigin.fX >= 0); 1682 SkASSERT(fPixelRefOrigin.fY >= 0); 1683 SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX); 1684 SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOrigin.fY); 1685 SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes()); 1686 } else { 1687 SkASSERT(NULL == fColorTable); 1688 } 1689} 1690#endif 1691 1692#ifdef SK_DEVELOPER 1693void SkBitmap::toString(SkString* str) const { 1694 1695 static const char* gConfigNames[kConfigCount] = { 1696 "NONE", "A8", "INDEX8", "565", "4444", "8888" 1697 }; 1698 1699 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), 1700 gConfigNames[this->config()]); 1701 1702 str->append(" ("); 1703 if (this->isOpaque()) { 1704 str->append("opaque"); 1705 } else { 1706 str->append("transparent"); 1707 } 1708 if (this->isImmutable()) { 1709 str->append(", immutable"); 1710 } else { 1711 str->append(", not-immutable"); 1712 } 1713 str->append(")"); 1714 1715 SkPixelRef* pr = this->pixelRef(); 1716 if (NULL == pr) { 1717 // show null or the explicit pixel address (rare) 1718 str->appendf(" pixels:%p", this->getPixels()); 1719 } else { 1720 const char* uri = pr->getURI(); 1721 if (NULL != uri) { 1722 str->appendf(" uri:\"%s\"", uri); 1723 } else { 1724 str->appendf(" pixelref:%p", pr); 1725 } 1726 } 1727 1728 str->append(")"); 1729} 1730#endif 1731 1732/////////////////////////////////////////////////////////////////////////////// 1733 1734#ifdef SK_DEBUG 1735void SkImageInfo::validate() const { 1736 SkASSERT(fWidth >= 0); 1737 SkASSERT(fHeight >= 0); 1738 SkASSERT(SkColorTypeIsValid(fColorType)); 1739 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); 1740} 1741#endif 1742