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 "SkMallocPixelRef.h" 15#include "SkMask.h" 16#include "SkOrderedReadBuffer.h" 17#include "SkOrderedWriteBuffer.h" 18#include "SkPixelRef.h" 19#include "SkThread.h" 20#include "SkUnPreMultiply.h" 21#include "SkUtils.h" 22#include "SkPackBits.h" 23#include <new> 24 25SK_DEFINE_INST_COUNT(SkBitmap::Allocator) 26 27static bool isPos32Bits(const Sk64& value) { 28 return !value.isNeg() && value.is32(); 29} 30 31struct MipLevel { 32 void* fPixels; 33 uint32_t fRowBytes; 34 uint32_t fWidth, fHeight; 35}; 36 37struct SkBitmap::MipMap : SkNoncopyable { 38 int32_t fRefCnt; 39 int fLevelCount; 40// MipLevel fLevel[fLevelCount]; 41// Pixels[] 42 43 static MipMap* Alloc(int levelCount, size_t pixelSize) { 44 if (levelCount < 0) { 45 return NULL; 46 } 47 Sk64 size; 48 size.setMul(levelCount + 1, sizeof(MipLevel)); 49 size.add(sizeof(MipMap)); 50 size.add(SkToS32(pixelSize)); 51 if (!isPos32Bits(size)) { 52 return NULL; 53 } 54 MipMap* mm = (MipMap*)sk_malloc_throw(size.get32()); 55 mm->fRefCnt = 1; 56 mm->fLevelCount = levelCount; 57 return mm; 58 } 59 60 const MipLevel* levels() const { return (const MipLevel*)(this + 1); } 61 MipLevel* levels() { return (MipLevel*)(this + 1); } 62 63 const void* pixels() const { return levels() + fLevelCount; } 64 void* pixels() { return levels() + fLevelCount; } 65 66 void ref() { 67 if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) { 68 sk_throw(); 69 } 70 } 71 void unref() { 72 SkASSERT(fRefCnt > 0); 73 if (sk_atomic_dec(&fRefCnt) == 1) { 74 sk_free(this); 75 } 76 } 77}; 78 79/////////////////////////////////////////////////////////////////////////////// 80/////////////////////////////////////////////////////////////////////////////// 81 82SkBitmap::SkBitmap() { 83 sk_bzero(this, sizeof(*this)); 84} 85 86SkBitmap::SkBitmap(const SkBitmap& src) { 87 SkDEBUGCODE(src.validate();) 88 sk_bzero(this, sizeof(*this)); 89 *this = src; 90 SkDEBUGCODE(this->validate();) 91} 92 93SkBitmap::~SkBitmap() { 94 SkDEBUGCODE(this->validate();) 95 this->freePixels(); 96} 97 98SkBitmap& SkBitmap::operator=(const SkBitmap& src) { 99 if (this != &src) { 100 this->freePixels(); 101 memcpy(this, &src, sizeof(src)); 102 103 // inc src reference counts 104 SkSafeRef(src.fPixelRef); 105 SkSafeRef(src.fMipMap); 106 107 // we reset our locks if we get blown away 108 fPixelLockCount = 0; 109 110 /* The src could be in 3 states 111 1. no pixelref, in which case we just copy/ref the pixels/ctable 112 2. unlocked pixelref, pixels/ctable should be null 113 3. locked pixelref, we should lock the ref again ourselves 114 */ 115 if (NULL == fPixelRef) { 116 // leave fPixels as it is 117 SkSafeRef(fColorTable); // ref the user's ctable if present 118 } else { // we have a pixelref, so pixels/ctable reflect it 119 // ignore the values from the memcpy 120 fPixels = NULL; 121 fColorTable = NULL; 122 // Note that what to for genID is somewhat arbitrary. We have no 123 // way to track changes to raw pixels across multiple SkBitmaps. 124 // Would benefit from an SkRawPixelRef type created by 125 // setPixels. 126 // Just leave the memcpy'ed one but they'll get out of sync 127 // as soon either is modified. 128 } 129 } 130 131 SkDEBUGCODE(this->validate();) 132 return *this; 133} 134 135void SkBitmap::swap(SkBitmap& other) { 136 SkTSwap(fColorTable, other.fColorTable); 137 SkTSwap(fPixelRef, other.fPixelRef); 138 SkTSwap(fPixelRefOffset, other.fPixelRefOffset); 139 SkTSwap(fPixelLockCount, other.fPixelLockCount); 140 SkTSwap(fMipMap, other.fMipMap); 141 SkTSwap(fPixels, other.fPixels); 142 SkTSwap(fRowBytes, other.fRowBytes); 143 SkTSwap(fWidth, other.fWidth); 144 SkTSwap(fHeight, other.fHeight); 145 SkTSwap(fConfig, other.fConfig); 146 SkTSwap(fFlags, other.fFlags); 147 SkTSwap(fBytesPerPixel, other.fBytesPerPixel); 148 149 SkDEBUGCODE(this->validate();) 150} 151 152void SkBitmap::reset() { 153 this->freePixels(); 154 sk_bzero(this, sizeof(*this)); 155} 156 157int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { 158 int bpp; 159 switch (config) { 160 case kNo_Config: 161 case kA1_Config: 162 bpp = 0; // not applicable 163 break; 164 case kA8_Config: 165 case kIndex8_Config: 166 bpp = 1; 167 break; 168 case kRGB_565_Config: 169 case kARGB_4444_Config: 170 bpp = 2; 171 break; 172 case kARGB_8888_Config: 173 bpp = 4; 174 break; 175 default: 176 SkDEBUGFAIL("unknown config"); 177 bpp = 0; // error 178 break; 179 } 180 return bpp; 181} 182 183size_t SkBitmap::ComputeRowBytes(Config c, int width) { 184 if (width < 0) { 185 return 0; 186 } 187 188 Sk64 rowBytes; 189 rowBytes.setZero(); 190 191 switch (c) { 192 case kNo_Config: 193 break; 194 case kA1_Config: 195 rowBytes.set(width); 196 rowBytes.add(7); 197 rowBytes.shiftRight(3); 198 break; 199 case kA8_Config: 200 case kIndex8_Config: 201 rowBytes.set(width); 202 break; 203 case kRGB_565_Config: 204 case kARGB_4444_Config: 205 rowBytes.set(width); 206 rowBytes.shiftLeft(1); 207 break; 208 case kARGB_8888_Config: 209 rowBytes.set(width); 210 rowBytes.shiftLeft(2); 211 break; 212 default: 213 SkDEBUGFAIL("unknown config"); 214 break; 215 } 216 return isPos32Bits(rowBytes) ? rowBytes.get32() : 0; 217} 218 219Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) { 220 Sk64 size; 221 size.setMul(SkToS32(SkBitmap::ComputeRowBytes(c, width)), height); 222 return size; 223} 224 225size_t SkBitmap::ComputeSize(Config c, int width, int height) { 226 Sk64 size = SkBitmap::ComputeSize64(c, width, height); 227 return isPos32Bits(size) ? size.get32() : 0; 228} 229 230Sk64 SkBitmap::ComputeSafeSize64(Config config, 231 uint32_t width, 232 uint32_t height, 233 size_t rowBytes) { 234 Sk64 safeSize; 235 safeSize.setZero(); 236 if (height > 0) { 237 // TODO: Handle the case where the return value from 238 // ComputeRowBytes is more than 31 bits. 239 safeSize.set(SkToS32(ComputeRowBytes(config, width))); 240 Sk64 sizeAllButLastRow; 241 sizeAllButLastRow.setMul(height - 1, SkToS32(rowBytes)); 242 safeSize.add(sizeAllButLastRow); 243 } 244 SkASSERT(!safeSize.isNeg()); 245 return safeSize; 246} 247 248size_t SkBitmap::ComputeSafeSize(Config config, 249 uint32_t width, 250 uint32_t height, 251 size_t rowBytes) { 252 Sk64 safeSize = ComputeSafeSize64(config, width, height, rowBytes); 253 return (safeSize.is32() ? safeSize.get32() : 0); 254} 255 256void SkBitmap::getBounds(SkRect* bounds) const { 257 SkASSERT(bounds); 258 bounds->set(0, 0, 259 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); 260} 261 262void SkBitmap::getBounds(SkIRect* bounds) const { 263 SkASSERT(bounds); 264 bounds->set(0, 0, fWidth, fHeight); 265} 266 267/////////////////////////////////////////////////////////////////////////////// 268 269void SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes) { 270 this->freePixels(); 271 272 if ((width | height) < 0) { 273 goto err; 274 } 275 276 if (rowBytes == 0) { 277 rowBytes = SkBitmap::ComputeRowBytes(c, width); 278 if (0 == rowBytes && kNo_Config != c) { 279 goto err; 280 } 281 } 282 283 fConfig = SkToU8(c); 284 fWidth = width; 285 fHeight = height; 286 fRowBytes = SkToU32(rowBytes); 287 288 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); 289 290 SkDEBUGCODE(this->validate();) 291 return; 292 293 // if we got here, we had an error, so we reset the bitmap to empty 294err: 295 this->reset(); 296} 297 298void SkBitmap::updatePixelsFromRef() const { 299 if (NULL != fPixelRef) { 300 if (fPixelLockCount > 0) { 301 SkASSERT(fPixelRef->isLocked()); 302 303 void* p = fPixelRef->pixels(); 304 if (NULL != p) { 305 p = (char*)p + fPixelRefOffset; 306 } 307 fPixels = p; 308 SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable()); 309 } else { 310 SkASSERT(0 == fPixelLockCount); 311 fPixels = NULL; 312 if (fColorTable) { 313 fColorTable->unref(); 314 fColorTable = NULL; 315 } 316 } 317 } 318} 319 320SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) { 321 // do this first, we that we never have a non-zero offset with a null ref 322 if (NULL == pr) { 323 offset = 0; 324 } 325 326 if (fPixelRef != pr || fPixelRefOffset != offset) { 327 if (fPixelRef != pr) { 328 this->freePixels(); 329 SkASSERT(NULL == fPixelRef); 330 331 SkSafeRef(pr); 332 fPixelRef = pr; 333 } 334 fPixelRefOffset = offset; 335 this->updatePixelsFromRef(); 336 } 337 338 SkDEBUGCODE(this->validate();) 339 return pr; 340} 341 342void SkBitmap::lockPixels() const { 343 if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) { 344 fPixelRef->lockPixels(); 345 this->updatePixelsFromRef(); 346 } 347 SkDEBUGCODE(this->validate();) 348} 349 350void SkBitmap::unlockPixels() const { 351 SkASSERT(NULL == fPixelRef || fPixelLockCount > 0); 352 353 if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) { 354 fPixelRef->unlockPixels(); 355 this->updatePixelsFromRef(); 356 } 357 SkDEBUGCODE(this->validate();) 358} 359 360bool SkBitmap::lockPixelsAreWritable() const { 361 return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false; 362} 363 364void SkBitmap::setPixels(void* p, SkColorTable* ctable) { 365 if (NULL == p) { 366 this->setPixelRef(NULL, 0); 367 return; 368 } 369 370 Sk64 size = this->getSize64(); 371 SkASSERT(!size.isNeg() && size.is32()); 372 373 this->setPixelRef(new SkMallocPixelRef(p, size.get32(), ctable, false))->unref(); 374 // since we're already allocated, we lockPixels right away 375 this->lockPixels(); 376 SkDEBUGCODE(this->validate();) 377} 378 379bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) { 380 HeapAllocator stdalloc; 381 382 if (NULL == allocator) { 383 allocator = &stdalloc; 384 } 385 return allocator->allocPixelRef(this, ctable); 386} 387 388void SkBitmap::freePixels() { 389 // if we're gonna free the pixels, we certainly need to free the mipmap 390 this->freeMipMap(); 391 392 if (fColorTable) { 393 fColorTable->unref(); 394 fColorTable = NULL; 395 } 396 397 if (NULL != fPixelRef) { 398 if (fPixelLockCount > 0) { 399 fPixelRef->unlockPixels(); 400 } 401 fPixelRef->unref(); 402 fPixelRef = NULL; 403 fPixelRefOffset = 0; 404 } 405 fPixelLockCount = 0; 406 fPixels = NULL; 407} 408 409void SkBitmap::freeMipMap() { 410 if (fMipMap) { 411 fMipMap->unref(); 412 fMipMap = NULL; 413 } 414} 415 416uint32_t SkBitmap::getGenerationID() const { 417 return (fPixelRef) ? fPixelRef->getGenerationID() : 0; 418} 419 420void SkBitmap::notifyPixelsChanged() const { 421 SkASSERT(!this->isImmutable()); 422 if (fPixelRef) { 423 fPixelRef->notifyPixelsChanged(); 424 } 425} 426 427GrTexture* SkBitmap::getTexture() const { 428 return fPixelRef ? fPixelRef->getTexture() : NULL; 429} 430 431/////////////////////////////////////////////////////////////////////////////// 432 433/** We explicitly use the same allocator for our pixels that SkMask does, 434 so that we can freely assign memory allocated by one class to the other. 435 */ 436bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, 437 SkColorTable* ctable) { 438 Sk64 size = dst->getSize64(); 439 if (size.isNeg() || !size.is32()) { 440 return false; 441 } 442 443 void* addr = sk_malloc_flags(size.get32(), 0); // returns NULL on failure 444 if (NULL == addr) { 445 return false; 446 } 447 448 dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref(); 449 // since we're already allocated, we lockPixels right away 450 dst->lockPixels(); 451 return true; 452} 453 454/////////////////////////////////////////////////////////////////////////////// 455 456size_t SkBitmap::getSafeSize() const { 457 // This is intended to be a size_t version of ComputeSafeSize64(), just 458 // faster. The computation is meant to be identical. 459 return (fHeight ? ((fHeight - 1) * fRowBytes) + 460 ComputeRowBytes(getConfig(), fWidth): 0); 461} 462 463Sk64 SkBitmap::getSafeSize64() const { 464 return ComputeSafeSize64(getConfig(), fWidth, fHeight, fRowBytes); 465} 466 467bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize, 468 size_t dstRowBytes, bool preserveDstPad) const { 469 470 if (0 == dstRowBytes) { 471 dstRowBytes = fRowBytes; 472 } 473 474 if (dstRowBytes < ComputeRowBytes(getConfig(), fWidth) || 475 dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) 476 return false; 477 478 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) { 479 size_t safeSize = getSafeSize(); 480 if (safeSize > dstSize || safeSize == 0) 481 return false; 482 else { 483 SkAutoLockPixels lock(*this); 484 // This implementation will write bytes beyond the end of each row, 485 // excluding the last row, if the bitmap's stride is greater than 486 // strictly required by the current config. 487 memcpy(dst, getPixels(), safeSize); 488 489 return true; 490 } 491 } else { 492 // If destination has different stride than us, then copy line by line. 493 if (ComputeSafeSize(getConfig(), fWidth, fHeight, dstRowBytes) > 494 dstSize) 495 return false; 496 else { 497 // Just copy what we need on each line. 498 size_t rowBytes = ComputeRowBytes(getConfig(), fWidth); 499 SkAutoLockPixels lock(*this); 500 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels()); 501 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); 502 for (uint32_t row = 0; row < fHeight; 503 row++, srcP += fRowBytes, dstP += dstRowBytes) { 504 memcpy(dstP, srcP, rowBytes); 505 } 506 507 return true; 508 } 509 } 510} 511 512/////////////////////////////////////////////////////////////////////////////// 513 514bool SkBitmap::isImmutable() const { 515 return fPixelRef ? fPixelRef->isImmutable() : 516 fFlags & kImageIsImmutable_Flag; 517} 518 519void SkBitmap::setImmutable() { 520 if (fPixelRef) { 521 fPixelRef->setImmutable(); 522 } else { 523 fFlags |= kImageIsImmutable_Flag; 524 } 525} 526 527bool SkBitmap::isOpaque() const { 528 switch (fConfig) { 529 case kNo_Config: 530 return true; 531 532 case kA1_Config: 533 case kA8_Config: 534 case kARGB_4444_Config: 535 case kARGB_8888_Config: 536 return (fFlags & kImageIsOpaque_Flag) != 0; 537 538 case kIndex8_Config: { 539 uint32_t flags = 0; 540 541 this->lockPixels(); 542 // if lockPixels failed, we may not have a ctable ptr 543 if (fColorTable) { 544 flags = fColorTable->getFlags(); 545 } 546 this->unlockPixels(); 547 548 return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0; 549 } 550 551 case kRGB_565_Config: 552 return true; 553 554 default: 555 SkDEBUGFAIL("unknown bitmap config pased to isOpaque"); 556 return false; 557 } 558} 559 560void SkBitmap::setIsOpaque(bool isOpaque) { 561 /* we record this regardless of fConfig, though it is ignored in 562 isOpaque() for configs that can't support per-pixel alpha. 563 */ 564 if (isOpaque) { 565 fFlags |= kImageIsOpaque_Flag; 566 } else { 567 fFlags &= ~kImageIsOpaque_Flag; 568 } 569} 570 571bool SkBitmap::isVolatile() const { 572 return (fFlags & kImageIsVolatile_Flag) != 0; 573} 574 575void SkBitmap::setIsVolatile(bool isVolatile) { 576 if (isVolatile) { 577 fFlags |= kImageIsVolatile_Flag; 578 } else { 579 fFlags &= ~kImageIsVolatile_Flag; 580 } 581} 582 583void* SkBitmap::getAddr(int x, int y) const { 584 SkASSERT((unsigned)x < (unsigned)this->width()); 585 SkASSERT((unsigned)y < (unsigned)this->height()); 586 587 char* base = (char*)this->getPixels(); 588 if (base) { 589 base += y * this->rowBytes(); 590 switch (this->config()) { 591 case SkBitmap::kARGB_8888_Config: 592 base += x << 2; 593 break; 594 case SkBitmap::kARGB_4444_Config: 595 case SkBitmap::kRGB_565_Config: 596 base += x << 1; 597 break; 598 case SkBitmap::kA8_Config: 599 case SkBitmap::kIndex8_Config: 600 base += x; 601 break; 602 case SkBitmap::kA1_Config: 603 base += x >> 3; 604 break; 605 default: 606 SkDEBUGFAIL("Can't return addr for config"); 607 base = NULL; 608 break; 609 } 610 } 611 return base; 612} 613 614SkColor SkBitmap::getColor(int x, int y) const { 615 SkASSERT((unsigned)x < (unsigned)this->width()); 616 SkASSERT((unsigned)y < (unsigned)this->height()); 617 618 switch (this->config()) { 619 case SkBitmap::kA1_Config: { 620 uint8_t* addr = this->getAddr1(x, y); 621 uint8_t mask = 1 << (7 - (x % 8)); 622 if (addr[0] & mask) { 623 return SK_ColorBLACK; 624 } else { 625 return 0; 626 } 627 } 628 case SkBitmap::kA8_Config: { 629 uint8_t* addr = this->getAddr8(x, y); 630 return SkColorSetA(0, addr[0]); 631 } 632 case SkBitmap::kIndex8_Config: { 633 SkPMColor c = this->getIndex8Color(x, y); 634 return SkUnPreMultiply::PMColorToColor(c); 635 } 636 case SkBitmap::kRGB_565_Config: { 637 uint16_t* addr = this->getAddr16(x, y); 638 return SkPixel16ToColor(addr[0]); 639 } 640 case SkBitmap::kARGB_4444_Config: { 641 uint16_t* addr = this->getAddr16(x, y); 642 SkPMColor c = SkPixel4444ToPixel32(addr[0]); 643 return SkUnPreMultiply::PMColorToColor(c); 644 } 645 case SkBitmap::kARGB_8888_Config: { 646 uint32_t* addr = this->getAddr32(x, y); 647 return SkUnPreMultiply::PMColorToColor(addr[0]); 648 } 649 case kNo_Config: 650 SkASSERT(false); 651 return 0; 652 } 653 SkASSERT(false); // Not reached. 654 return 0; 655} 656 657bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { 658 SkAutoLockPixels alp(bm); 659 if (!bm.getPixels()) { 660 return false; 661 } 662 663 const int height = bm.height(); 664 const int width = bm.width(); 665 666 switch (bm.config()) { 667 case SkBitmap::kA1_Config: { 668 // TODO 669 } break; 670 case SkBitmap::kA8_Config: { 671 unsigned a = 0xFF; 672 for (int y = 0; y < height; ++y) { 673 const uint8_t* row = bm.getAddr8(0, y); 674 for (int x = 0; x < width; ++x) { 675 a &= row[x]; 676 } 677 if (0xFF != a) { 678 return false; 679 } 680 } 681 return true; 682 } break; 683 case SkBitmap::kIndex8_Config: { 684 SkAutoLockColors alc(bm); 685 const SkPMColor* table = alc.colors(); 686 if (!table) { 687 return false; 688 } 689 SkPMColor c = (SkPMColor)~0; 690 for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) { 691 c &= table[i]; 692 } 693 return 0xFF == SkGetPackedA32(c); 694 } break; 695 case SkBitmap::kRGB_565_Config: 696 return true; 697 break; 698 case SkBitmap::kARGB_4444_Config: { 699 unsigned c = 0xFFFF; 700 for (int y = 0; y < height; ++y) { 701 const SkPMColor16* row = bm.getAddr16(0, y); 702 for (int x = 0; x < width; ++x) { 703 c &= row[x]; 704 } 705 if (0xF != SkGetPackedA4444(c)) { 706 return false; 707 } 708 } 709 return true; 710 } break; 711 case SkBitmap::kARGB_8888_Config: { 712 SkPMColor c = (SkPMColor)~0; 713 for (int y = 0; y < height; ++y) { 714 const SkPMColor* row = bm.getAddr32(0, y); 715 for (int x = 0; x < width; ++x) { 716 c &= row[x]; 717 } 718 if (0xFF != SkGetPackedA32(c)) { 719 return false; 720 } 721 } 722 return true; 723 } 724 default: 725 break; 726 } 727 return false; 728} 729 730 731/////////////////////////////////////////////////////////////////////////////// 732/////////////////////////////////////////////////////////////////////////////// 733 734static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) { 735 unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | 736 (SkR32To4444(r) << SK_R4444_SHIFT) | 737 (SkG32To4444(g) << SK_G4444_SHIFT) | 738 (SkB32To4444(b) << SK_B4444_SHIFT); 739 return SkToU16(pixel); 740} 741 742void SkBitmap::internalErase(const SkIRect& area, 743 U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 744#ifdef SK_DEBUG 745 SkDEBUGCODE(this->validate();) 746 SkASSERT(!area.isEmpty()); 747 { 748 SkIRect total = { 0, 0, this->width(), this->height() }; 749 SkASSERT(total.contains(area)); 750 } 751#endif 752 753 if (kNo_Config == fConfig || kIndex8_Config == fConfig) { 754 return; 755 } 756 757 SkAutoLockPixels alp(*this); 758 // perform this check after the lock call 759 if (!this->readyToDraw()) { 760 return; 761 } 762 763 int height = area.height(); 764 const int width = area.width(); 765 const int rowBytes = fRowBytes; 766 767 // make rgb premultiplied 768 if (255 != a) { 769 r = SkAlphaMul(r, a); 770 g = SkAlphaMul(g, a); 771 b = SkAlphaMul(b, a); 772 } 773 774 switch (fConfig) { 775 case kA1_Config: { 776 uint8_t* p = this->getAddr1(area.fLeft, area.fTop); 777 const int left = area.fLeft >> 3; 778 const int right = area.fRight >> 3; 779 780 int middle = right - left - 1; 781 782 uint8_t leftMask = 0xFF >> (area.fLeft & 7); 783 uint8_t rightMask = ~(0xFF >> (area.fRight & 7)); 784 if (left == right) { 785 leftMask &= rightMask; 786 rightMask = 0; 787 } 788 789 a = (a >> 7) ? 0xFF : 0; 790 while (--height >= 0) { 791 uint8_t* startP = p; 792 793 *p = (*p & ~leftMask) | (a & leftMask); 794 p++; 795 if (middle > 0) { 796 memset(p, a, middle); 797 p += middle; 798 } 799 if (rightMask) { 800 *p = (*p & ~rightMask) | (a & rightMask); 801 } 802 803 p = startP + rowBytes; 804 } 805 break; 806 } 807 case kA8_Config: { 808 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); 809 while (--height >= 0) { 810 memset(p, a, width); 811 p += rowBytes; 812 } 813 break; 814 } 815 case kARGB_4444_Config: 816 case kRGB_565_Config: { 817 uint16_t* p = this->getAddr16(area.fLeft, area.fTop);; 818 uint16_t v; 819 820 if (kARGB_4444_Config == fConfig) { 821 v = pack_8888_to_4444(a, r, g, b); 822 } else { 823 v = SkPackRGB16(r >> (8 - SK_R16_BITS), 824 g >> (8 - SK_G16_BITS), 825 b >> (8 - SK_B16_BITS)); 826 } 827 while (--height >= 0) { 828 sk_memset16(p, v, width); 829 p = (uint16_t*)((char*)p + rowBytes); 830 } 831 break; 832 } 833 case kARGB_8888_Config: { 834 uint32_t* p = this->getAddr32(area.fLeft, area.fTop); 835 uint32_t v = SkPackARGB32(a, r, g, b); 836 837 while (--height >= 0) { 838 sk_memset32(p, v, width); 839 p = (uint32_t*)((char*)p + rowBytes); 840 } 841 break; 842 } 843 } 844 845 this->notifyPixelsChanged(); 846} 847 848void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 849 SkIRect area = { 0, 0, this->width(), this->height() }; 850 if (!area.isEmpty()) { 851 this->internalErase(area, a, r, g, b); 852 } 853} 854 855void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { 856 SkIRect area = { 0, 0, this->width(), this->height() }; 857 if (area.intersect(rect)) { 858 this->internalErase(area, SkColorGetA(c), SkColorGetR(c), 859 SkColorGetG(c), SkColorGetB(c)); 860 } 861} 862 863////////////////////////////////////////////////////////////////////////////////////// 864////////////////////////////////////////////////////////////////////////////////////// 865 866#define SUB_OFFSET_FAILURE ((size_t)-1) 867 868/** 869 * Based on the Config and rowBytes() of bm, return the offset into an SkPixelRef of the pixel at 870 * (x, y). 871 * Note that the SkPixelRef does not need to be set yet. deepCopyTo takes advantage of this fact. 872 * Also note that (x, y) may be outside the range of (0 - width(), 0 - height()), so long as it is 873 * within the bounds of the SkPixelRef being used. 874 */ 875static size_t get_sub_offset(const SkBitmap& bm, int x, int y) { 876 switch (bm.getConfig()) { 877 case SkBitmap::kA8_Config: 878 case SkBitmap:: kIndex8_Config: 879 // x is fine as is for the calculation 880 break; 881 882 case SkBitmap::kRGB_565_Config: 883 case SkBitmap::kARGB_4444_Config: 884 x <<= 1; 885 break; 886 887 case SkBitmap::kARGB_8888_Config: 888 x <<= 2; 889 break; 890 891 case SkBitmap::kNo_Config: 892 case SkBitmap::kA1_Config: 893 default: 894 return SUB_OFFSET_FAILURE; 895 } 896 return y * bm.rowBytes() + x; 897} 898 899/** 900 * Using the pixelRefOffset(), rowBytes(), and Config of bm, determine the (x, y) coordinate of the 901 * upper left corner of bm relative to its SkPixelRef. 902 * x and y must be non-NULL. 903 */ 904bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes, 905 int32_t* x, int32_t* y); 906bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes, 907 int32_t* x, int32_t* y) { 908 SkASSERT(x != NULL && y != NULL); 909 if (0 == offset) { 910 *x = *y = 0; 911 return true; 912 } 913 // Use integer division to find the correct y position. 914 *y = SkToS32(offset / rowBytes); 915 // The remainder will be the x position, after we reverse get_sub_offset. 916 *x = SkToS32(offset % rowBytes); 917 switch (config) { 918 case SkBitmap::kA8_Config: 919 // Fall through. 920 case SkBitmap::kIndex8_Config: 921 // x is unmodified 922 break; 923 924 case SkBitmap::kRGB_565_Config: 925 // Fall through. 926 case SkBitmap::kARGB_4444_Config: 927 *x >>= 1; 928 break; 929 930 case SkBitmap::kARGB_8888_Config: 931 *x >>= 2; 932 break; 933 934 case SkBitmap::kNo_Config: 935 // Fall through. 936 case SkBitmap::kA1_Config: 937 // Fall through. 938 default: 939 return false; 940 } 941 return true; 942} 943 944static bool get_upper_left_from_offset(const SkBitmap& bm, int32_t* x, int32_t* y) { 945 return get_upper_left_from_offset(bm.config(), bm.pixelRefOffset(), bm.rowBytes(), x, y); 946} 947 948bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { 949 SkDEBUGCODE(this->validate();) 950 951 if (NULL == result || NULL == fPixelRef) { 952 return false; // no src pixels 953 } 954 955 SkIRect srcRect, r; 956 srcRect.set(0, 0, this->width(), this->height()); 957 if (!r.intersect(srcRect, subset)) { 958 return false; // r is empty (i.e. no intersection) 959 } 960 961 if (fPixelRef->getTexture() != NULL) { 962 // Do a deep copy 963 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); 964 if (pixelRef != NULL) { 965 SkBitmap dst; 966 dst.setConfig(this->config(), subset.width(), subset.height()); 967 dst.setIsVolatile(this->isVolatile()); 968 dst.setIsOpaque(this->isOpaque()); 969 dst.setPixelRef(pixelRef)->unref(); 970 SkDEBUGCODE(dst.validate()); 971 result->swap(dst); 972 return true; 973 } 974 } 975 976 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 977 // exited above. 978 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 979 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 980 981 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); 982 if (SUB_OFFSET_FAILURE == offset) { 983 return false; // config not supported 984 } 985 986 SkBitmap dst; 987 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes()); 988 dst.setIsVolatile(this->isVolatile()); 989 dst.setIsOpaque(this->isOpaque()); 990 991 if (fPixelRef) { 992 // share the pixelref with a custom offset 993 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); 994 } 995 SkDEBUGCODE(dst.validate();) 996 997 // we know we're good, so commit to result 998 result->swap(dst); 999 return true; 1000} 1001 1002/////////////////////////////////////////////////////////////////////////////// 1003 1004#include "SkCanvas.h" 1005#include "SkPaint.h" 1006 1007bool SkBitmap::canCopyTo(Config dstConfig) const { 1008 if (this->getConfig() == kNo_Config) { 1009 return false; 1010 } 1011 1012 bool sameConfigs = (this->config() == dstConfig); 1013 switch (dstConfig) { 1014 case kA8_Config: 1015 case kRGB_565_Config: 1016 case kARGB_8888_Config: 1017 break; 1018 case kA1_Config: 1019 case kIndex8_Config: 1020 if (!sameConfigs) { 1021 return false; 1022 } 1023 break; 1024 case kARGB_4444_Config: 1025 return sameConfigs || kARGB_8888_Config == this->config(); 1026 default: 1027 return false; 1028 } 1029 1030 // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config 1031 if (this->getConfig() == kA1_Config && !sameConfigs) { 1032 return false; 1033 } 1034 1035 return true; 1036} 1037 1038bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { 1039 if (!this->canCopyTo(dstConfig)) { 1040 return false; 1041 } 1042 1043 // if we have a texture, first get those pixels 1044 SkBitmap tmpSrc; 1045 const SkBitmap* src = this; 1046 1047 if (fPixelRef) { 1048 SkIRect subset; 1049 if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) { 1050 subset.fRight = subset.fLeft + fWidth; 1051 subset.fBottom = subset.fTop + fHeight; 1052 if (fPixelRef->readPixels(&tmpSrc, &subset)) { 1053 SkASSERT(tmpSrc.width() == this->width()); 1054 SkASSERT(tmpSrc.height() == this->height()); 1055 1056 // did we get lucky and we can just return tmpSrc? 1057 if (tmpSrc.config() == dstConfig && NULL == alloc) { 1058 dst->swap(tmpSrc); 1059 if (dst->pixelRef() && this->config() == dstConfig) { 1060 dst->pixelRef()->fGenerationID = fPixelRef->getGenerationID(); 1061 } 1062 return true; 1063 } 1064 1065 // fall through to the raster case 1066 src = &tmpSrc; 1067 } 1068 } 1069 } 1070 1071 // we lock this now, since we may need its colortable 1072 SkAutoLockPixels srclock(*src); 1073 if (!src->readyToDraw()) { 1074 return false; 1075 } 1076 1077 SkBitmap tmpDst; 1078 tmpDst.setConfig(dstConfig, src->width(), src->height()); 1079 1080 // allocate colortable if srcConfig == kIndex8_Config 1081 SkColorTable* ctable = (dstConfig == kIndex8_Config) ? 1082 new SkColorTable(*src->getColorTable()) : NULL; 1083 SkAutoUnref au(ctable); 1084 if (!tmpDst.allocPixels(alloc, ctable)) { 1085 return false; 1086 } 1087 1088 if (!tmpDst.readyToDraw()) { 1089 // allocator/lock failed 1090 return false; 1091 } 1092 1093 /* do memcpy for the same configs cases, else use drawing 1094 */ 1095 if (src->config() == dstConfig) { 1096 if (tmpDst.getSize() == src->getSize()) { 1097 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); 1098 SkPixelRef* pixelRef = tmpDst.pixelRef(); 1099 if (pixelRef != NULL) { 1100 pixelRef->fGenerationID = this->getGenerationID(); 1101 } 1102 } else { 1103 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); 1104 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); 1105 // to be sure we don't read too much, only copy our logical pixels 1106 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); 1107 for (int y = 0; y < tmpDst.height(); y++) { 1108 memcpy(dstP, srcP, bytesToCopy); 1109 srcP += src->rowBytes(); 1110 dstP += tmpDst.rowBytes(); 1111 } 1112 } 1113 } else if (SkBitmap::kARGB_4444_Config == dstConfig 1114 && SkBitmap::kARGB_8888_Config == src->config()) { 1115 SkASSERT(src->height() == tmpDst.height()); 1116 SkASSERT(src->width() == tmpDst.width()); 1117 for (int y = 0; y < src->height(); ++y) { 1118 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); 1119 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); 1120 DITHER_4444_SCAN(y); 1121 for (int x = 0; x < src->width(); ++x) { 1122 dstRow[x] = SkDitherARGB32To4444(srcRow[x], 1123 DITHER_VALUE(x)); 1124 } 1125 } 1126 } else { 1127 // if the src has alpha, we have to clear the dst first 1128 if (!src->isOpaque()) { 1129 tmpDst.eraseColor(SK_ColorTRANSPARENT); 1130 } 1131 1132 SkCanvas canvas(tmpDst); 1133 SkPaint paint; 1134 1135 paint.setDither(true); 1136 canvas.drawBitmap(*src, 0, 0, &paint); 1137 } 1138 1139 tmpDst.setIsOpaque(src->isOpaque()); 1140 1141 dst->swap(tmpDst); 1142 return true; 1143} 1144 1145bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { 1146 if (!this->canCopyTo(dstConfig)) { 1147 return false; 1148 } 1149 1150 // If we have a PixelRef, and it supports deep copy, use it. 1151 // Currently supported only by texture-backed bitmaps. 1152 if (fPixelRef) { 1153 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); 1154 if (pixelRef) { 1155 uint32_t rowBytes; 1156 if (dstConfig == fConfig) { 1157 pixelRef->fGenerationID = fPixelRef->getGenerationID(); 1158 // Use the same rowBytes as the original. 1159 rowBytes = fRowBytes; 1160 } else { 1161 // With the new config, an appropriate fRowBytes will be computed by setConfig. 1162 rowBytes = 0; 1163 } 1164 dst->setConfig(dstConfig, fWidth, fHeight, rowBytes); 1165 1166 size_t pixelRefOffset; 1167 if (0 == fPixelRefOffset || dstConfig == fConfig) { 1168 // Use the same offset as the original. 1169 pixelRefOffset = fPixelRefOffset; 1170 } else { 1171 // Find the correct offset in the new config. This needs to be done after calling 1172 // setConfig so dst's fConfig and fRowBytes have been set properly. 1173 int32_t x, y; 1174 if (!get_upper_left_from_offset(*this, &x, &y)) { 1175 return false; 1176 } 1177 pixelRefOffset = get_sub_offset(*dst, x, y); 1178 if (SUB_OFFSET_FAILURE == pixelRefOffset) { 1179 return false; 1180 } 1181 } 1182 dst->setPixelRef(pixelRef, pixelRefOffset)->unref(); 1183 return true; 1184 } 1185 } 1186 1187 if (this->getTexture()) { 1188 return false; 1189 } else { 1190 return this->copyTo(dst, dstConfig, 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->getConfig(); 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.getConfig(); 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(false); 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(SkFlattenableWriteBuffer& buffer) const { 1584 buffer.writeInt(fWidth); 1585 buffer.writeInt(fHeight); 1586 buffer.writeInt(fRowBytes); 1587 buffer.writeInt(fConfig); 1588 buffer.writeBool(this->isOpaque()); 1589 1590 if (fPixelRef) { 1591 if (fPixelRef->getFactory()) { 1592 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); 1593 buffer.writeUInt(SkToU32(fPixelRefOffset)); 1594 buffer.writeFlattenable(fPixelRef); 1595 return; 1596 } 1597 // if we get here, we can't record the pixels 1598 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1599 } else { 1600 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1601 } 1602} 1603 1604void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { 1605 this->reset(); 1606 1607 int width = buffer.readInt(); 1608 int height = buffer.readInt(); 1609 int rowBytes = buffer.readInt(); 1610 int config = buffer.readInt(); 1611 1612 this->setConfig((Config)config, width, height, rowBytes); 1613 this->setIsOpaque(buffer.readBool()); 1614 1615 int reftype = buffer.readInt(); 1616 switch (reftype) { 1617 case SERIALIZE_PIXELTYPE_REF_DATA: { 1618 size_t offset = buffer.readUInt(); 1619 SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>(); 1620 SkSafeUnref(this->setPixelRef(pr, offset)); 1621 break; 1622 } 1623 case SERIALIZE_PIXELTYPE_NONE: 1624 break; 1625 default: 1626 SkDEBUGFAIL("unrecognized pixeltype in serialized data"); 1627 sk_throw(); 1628 } 1629} 1630 1631/////////////////////////////////////////////////////////////////////////////// 1632 1633SkBitmap::RLEPixels::RLEPixels(int width, int height) { 1634 fHeight = height; 1635 fYPtrs = (uint8_t**)sk_malloc_throw(height * sizeof(uint8_t*)); 1636 sk_bzero(fYPtrs, height * sizeof(uint8_t*)); 1637} 1638 1639SkBitmap::RLEPixels::~RLEPixels() { 1640 sk_free(fYPtrs); 1641} 1642 1643/////////////////////////////////////////////////////////////////////////////// 1644 1645#ifdef SK_DEBUG 1646void SkBitmap::validate() const { 1647 SkASSERT(fConfig < kConfigCount); 1648 SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth)); 1649 uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag; 1650#ifdef SK_BUILD_FOR_ANDROID 1651 allFlags |= kHasHardwareMipMap_Flag; 1652#endif 1653 SkASSERT(fFlags <= allFlags); 1654 SkASSERT(fPixelLockCount >= 0); 1655 SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000); 1656 SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel); 1657 1658#if 0 // these asserts are not thread-correct, so disable for now 1659 if (fPixelRef) { 1660 if (fPixelLockCount > 0) { 1661 SkASSERT(fPixelRef->isLocked()); 1662 } else { 1663 SkASSERT(NULL == fPixels); 1664 SkASSERT(NULL == fColorTable); 1665 } 1666 } 1667#endif 1668} 1669#endif 1670 1671#ifdef SK_DEVELOPER 1672void SkBitmap::toString(SkString* str) const { 1673 1674 static const char* gConfigNames[kConfigCount] = { 1675 "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888" 1676 }; 1677 1678 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), 1679 gConfigNames[this->config()]); 1680 1681 str->append(" ("); 1682 if (this->isOpaque()) { 1683 str->append("opaque"); 1684 } else { 1685 str->append("transparent"); 1686 } 1687 if (this->isImmutable()) { 1688 str->append(", immutable"); 1689 } else { 1690 str->append(", not-immutable"); 1691 } 1692 str->append(")"); 1693 1694 SkPixelRef* pr = this->pixelRef(); 1695 if (NULL == pr) { 1696 // show null or the explicit pixel address (rare) 1697 str->appendf(" pixels:%p", this->getPixels()); 1698 } else { 1699 const char* uri = pr->getURI(); 1700 if (NULL != uri) { 1701 str->appendf(" uri:\"%s\"", uri); 1702 } else { 1703 str->appendf(" pixelref:%p", pr); 1704 } 1705 } 1706 1707 str->append(")"); 1708} 1709#endif 1710