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