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