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