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