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