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