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