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 "SkReadBuffer.h" 18 #include "SkWriteBuffer.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 27 static bool reset_return_false(SkBitmap* bm) { 28 bm->reset(); 29 return false; 30 } 31 32 SkBitmap::SkBitmap() { 33 sk_bzero(this, sizeof(*this)); 34 } 35 36 SkBitmap::SkBitmap(const SkBitmap& src) { 37 SkDEBUGCODE(src.validate();) 38 sk_bzero(this, sizeof(*this)); 39 *this = src; 40 SkDEBUGCODE(this->validate();) 41 } 42 43 SkBitmap::~SkBitmap() { 44 SkDEBUGCODE(this->validate();) 45 this->freePixels(); 46 } 47 48 SkBitmap& SkBitmap::operator=(const SkBitmap& src) { 49 if (this != &src) { 50 this->freePixels(); 51 memcpy(this, &src, sizeof(src)); 52 53 // inc src reference counts 54 SkSafeRef(src.fPixelRef); 55 56 // we reset our locks if we get blown away 57 fPixelLockCount = 0; 58 59 if (fPixelRef) { 60 // ignore the values from the memcpy 61 fPixels = NULL; 62 fColorTable = NULL; 63 // Note that what to for genID is somewhat arbitrary. We have no 64 // way to track changes to raw pixels across multiple SkBitmaps. 65 // Would benefit from an SkRawPixelRef type created by 66 // setPixels. 67 // Just leave the memcpy'ed one but they'll get out of sync 68 // as soon either is modified. 69 } 70 } 71 72 SkDEBUGCODE(this->validate();) 73 return *this; 74 } 75 76 void SkBitmap::swap(SkBitmap& other) { 77 SkTSwap(fColorTable, other.fColorTable); 78 SkTSwap(fPixelRef, other.fPixelRef); 79 SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin); 80 SkTSwap(fPixelLockCount, other.fPixelLockCount); 81 SkTSwap(fPixels, other.fPixels); 82 SkTSwap(fInfo, other.fInfo); 83 SkTSwap(fRowBytes, other.fRowBytes); 84 SkTSwap(fFlags, other.fFlags); 85 86 SkDEBUGCODE(this->validate();) 87 } 88 89 void SkBitmap::reset() { 90 this->freePixels(); 91 sk_bzero(this, sizeof(*this)); 92 } 93 94 #ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 95 SkBitmap::Config SkBitmap::config() const { 96 return SkColorTypeToBitmapConfig(fInfo.colorType()); 97 } 98 #endif 99 100 #ifdef SK_SUPPORT_LEGACY_COMPUTE_CONFIG_SIZE 101 int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { 102 int bpp; 103 switch (config) { 104 case kNo_Config: 105 bpp = 0; // not applicable 106 break; 107 case kA8_Config: 108 case kIndex8_Config: 109 bpp = 1; 110 break; 111 case kRGB_565_Config: 112 case kARGB_4444_Config: 113 bpp = 2; 114 break; 115 case kARGB_8888_Config: 116 bpp = 4; 117 break; 118 default: 119 SkDEBUGFAIL("unknown config"); 120 bpp = 0; // error 121 break; 122 } 123 return bpp; 124 } 125 126 size_t SkBitmap::ComputeRowBytes(Config c, int width) { 127 return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), width); 128 } 129 130 int64_t SkBitmap::ComputeSize64(Config config, int width, int height) { 131 SkColorType ct = SkBitmapConfigToColorType(config); 132 int64_t rowBytes = sk_64_mul(SkColorTypeBytesPerPixel(ct), width); 133 return rowBytes * height; 134 } 135 136 size_t SkBitmap::ComputeSize(Config c, int width, int height) { 137 int64_t size = SkBitmap::ComputeSize64(c, width, height); 138 return sk_64_isS32(size) ? sk_64_asS32(size) : 0; 139 } 140 #endif 141 142 void SkBitmap::getBounds(SkRect* bounds) const { 143 SkASSERT(bounds); 144 bounds->set(0, 0, 145 SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight)); 146 } 147 148 void SkBitmap::getBounds(SkIRect* bounds) const { 149 SkASSERT(bounds); 150 bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight); 151 } 152 153 /////////////////////////////////////////////////////////////////////////////// 154 155 static bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType, 156 SkAlphaType* canonical = NULL) { 157 switch (colorType) { 158 case kUnknown_SkColorType: 159 alphaType = kIgnore_SkAlphaType; 160 break; 161 case kAlpha_8_SkColorType: 162 if (kUnpremul_SkAlphaType == alphaType) { 163 alphaType = kPremul_SkAlphaType; 164 } 165 // fall-through 166 case kIndex_8_SkColorType: 167 case kARGB_4444_SkColorType: 168 case kRGBA_8888_SkColorType: 169 case kBGRA_8888_SkColorType: 170 if (kIgnore_SkAlphaType == alphaType) { 171 return false; 172 } 173 break; 174 case kRGB_565_SkColorType: 175 alphaType = kOpaque_SkAlphaType; 176 break; 177 default: 178 return false; 179 } 180 if (canonical) { 181 *canonical = alphaType; 182 } 183 return true; 184 } 185 186 bool SkBitmap::setInfo(const SkImageInfo& origInfo, size_t rowBytes) { 187 SkImageInfo info = origInfo; 188 189 if (!validate_alphaType(info.fColorType, info.fAlphaType, 190 &info.fAlphaType)) { 191 return reset_return_false(this); 192 } 193 194 // require that rowBytes fit in 31bits 195 int64_t mrb = info.minRowBytes64(); 196 if ((int32_t)mrb != mrb) { 197 return reset_return_false(this); 198 } 199 if ((int64_t)rowBytes != (int32_t)rowBytes) { 200 return reset_return_false(this); 201 } 202 203 if (info.width() < 0 || info.height() < 0) { 204 return reset_return_false(this); 205 } 206 207 if (kUnknown_SkColorType == info.colorType()) { 208 rowBytes = 0; 209 } else if (0 == rowBytes) { 210 rowBytes = (size_t)mrb; 211 } else if (rowBytes < info.minRowBytes()) { 212 return reset_return_false(this); 213 } 214 215 this->freePixels(); 216 217 fInfo = info; 218 fRowBytes = SkToU32(rowBytes); 219 return true; 220 } 221 222 #ifdef SK_SUPPORT_LEGACY_SETCONFIG 223 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, 224 SkAlphaType alphaType) { 225 SkColorType ct = SkBitmapConfigToColorType(config); 226 return this->setInfo(SkImageInfo::Make(width, height, ct, alphaType), rowBytes); 227 } 228 #endif 229 230 bool SkBitmap::setAlphaType(SkAlphaType alphaType) { 231 if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) { 232 return false; 233 } 234 if (fInfo.fAlphaType != alphaType) { 235 fInfo.fAlphaType = alphaType; 236 if (fPixelRef) { 237 fPixelRef->changeAlphaType(alphaType); 238 } 239 } 240 return true; 241 } 242 243 void SkBitmap::updatePixelsFromRef() const { 244 if (NULL != fPixelRef) { 245 if (fPixelLockCount > 0) { 246 SkASSERT(fPixelRef->isLocked()); 247 248 void* p = fPixelRef->pixels(); 249 if (NULL != p) { 250 p = (char*)p 251 + fPixelRefOrigin.fY * fRowBytes 252 + fPixelRefOrigin.fX * fInfo.bytesPerPixel(); 253 } 254 fPixels = p; 255 fColorTable = fPixelRef->colorTable(); 256 } else { 257 SkASSERT(0 == fPixelLockCount); 258 fPixels = NULL; 259 fColorTable = NULL; 260 } 261 } 262 } 263 264 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { 265 #ifdef SK_DEBUG 266 if (pr) { 267 if (kUnknown_SkColorType != fInfo.colorType()) { 268 const SkImageInfo& prInfo = pr->info(); 269 SkASSERT(fInfo.fWidth <= prInfo.fWidth); 270 SkASSERT(fInfo.fHeight <= prInfo.fHeight); 271 SkASSERT(fInfo.fColorType == prInfo.fColorType); 272 switch (prInfo.fAlphaType) { 273 case kIgnore_SkAlphaType: 274 SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType); 275 break; 276 case kOpaque_SkAlphaType: 277 case kPremul_SkAlphaType: 278 SkASSERT(fInfo.fAlphaType == kOpaque_SkAlphaType || 279 fInfo.fAlphaType == kPremul_SkAlphaType); 280 break; 281 case kUnpremul_SkAlphaType: 282 SkASSERT(fInfo.fAlphaType == kOpaque_SkAlphaType || 283 fInfo.fAlphaType == kUnpremul_SkAlphaType); 284 break; 285 } 286 } 287 } 288 #endif 289 290 if (pr) { 291 const SkImageInfo& info = pr->info(); 292 fPixelRefOrigin.set(SkPin32(dx, 0, info.fWidth), 293 SkPin32(dy, 0, info.fHeight)); 294 } else { 295 // ignore dx,dy if there is no pixelref 296 fPixelRefOrigin.setZero(); 297 } 298 299 if (fPixelRef != pr) { 300 this->freePixels(); 301 SkASSERT(NULL == fPixelRef); 302 303 SkSafeRef(pr); 304 fPixelRef = pr; 305 this->updatePixelsFromRef(); 306 } 307 308 SkDEBUGCODE(this->validate();) 309 return pr; 310 } 311 312 void SkBitmap::lockPixels() const { 313 if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) { 314 fPixelRef->lockPixels(); 315 this->updatePixelsFromRef(); 316 } 317 SkDEBUGCODE(this->validate();) 318 } 319 320 void SkBitmap::unlockPixels() const { 321 SkASSERT(NULL == fPixelRef || fPixelLockCount > 0); 322 323 if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) { 324 fPixelRef->unlockPixels(); 325 this->updatePixelsFromRef(); 326 } 327 SkDEBUGCODE(this->validate();) 328 } 329 330 bool SkBitmap::lockPixelsAreWritable() const { 331 return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false; 332 } 333 334 void SkBitmap::setPixels(void* p, SkColorTable* ctable) { 335 if (NULL == p) { 336 this->setPixelRef(NULL); 337 return; 338 } 339 340 if (kUnknown_SkColorType == fInfo.colorType()) { 341 this->setPixelRef(NULL); 342 return; 343 } 344 345 SkPixelRef* pr = SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable); 346 if (NULL == pr) { 347 this->setPixelRef(NULL); 348 return; 349 } 350 351 this->setPixelRef(pr)->unref(); 352 353 // since we're already allocated, we lockPixels right away 354 this->lockPixels(); 355 SkDEBUGCODE(this->validate();) 356 } 357 358 bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) { 359 HeapAllocator stdalloc; 360 361 if (NULL == allocator) { 362 allocator = &stdalloc; 363 } 364 return allocator->allocPixelRef(this, ctable); 365 } 366 367 /////////////////////////////////////////////////////////////////////////////// 368 369 bool SkBitmap::allocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory, 370 SkColorTable* ctable) { 371 if (kIndex_8_SkColorType == requestedInfo.fColorType && NULL == ctable) { 372 return reset_return_false(this); 373 } 374 if (!this->setInfo(requestedInfo)) { 375 return reset_return_false(this); 376 } 377 378 // setInfo may have corrected info (e.g. 565 is always opaque). 379 const SkImageInfo& correctedInfo = this->info(); 380 381 SkMallocPixelRef::PRFactory defaultFactory; 382 if (NULL == factory) { 383 factory = &defaultFactory; 384 } 385 386 SkPixelRef* pr = factory->create(correctedInfo, ctable); 387 if (NULL == pr) { 388 return reset_return_false(this); 389 } 390 this->setPixelRef(pr)->unref(); 391 392 // TODO: lockPixels could/should return bool or void*/NULL 393 this->lockPixels(); 394 if (NULL == this->getPixels()) { 395 return reset_return_false(this); 396 } 397 return true; 398 } 399 400 bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb, 401 SkColorTable* ct, void (*releaseProc)(void* addr, void* context), 402 void* context) { 403 if (!this->setInfo(requestedInfo, rb)) { 404 this->reset(); 405 return false; 406 } 407 408 // setInfo may have corrected info (e.g. 565 is always opaque). 409 const SkImageInfo& correctedInfo = this->info(); 410 411 SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc, 412 context); 413 if (!pr) { 414 this->reset(); 415 return false; 416 } 417 418 this->setPixelRef(pr)->unref(); 419 420 // since we're already allocated, we lockPixels right away 421 this->lockPixels(); 422 SkDEBUGCODE(this->validate();) 423 return true; 424 } 425 426 bool SkBitmap::installMaskPixels(const SkMask& mask) { 427 if (SkMask::kA8_Format != mask.fFormat) { 428 this->reset(); 429 return false; 430 } 431 return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), 432 mask.fBounds.height()), 433 mask.fImage, mask.fRowBytes); 434 } 435 436 /////////////////////////////////////////////////////////////////////////////// 437 438 void SkBitmap::freePixels() { 439 if (NULL != fPixelRef) { 440 if (fPixelLockCount > 0) { 441 fPixelRef->unlockPixels(); 442 } 443 fPixelRef->unref(); 444 fPixelRef = NULL; 445 fPixelRefOrigin.setZero(); 446 } 447 fPixelLockCount = 0; 448 fPixels = NULL; 449 fColorTable = NULL; 450 } 451 452 uint32_t SkBitmap::getGenerationID() const { 453 return (fPixelRef) ? fPixelRef->getGenerationID() : 0; 454 } 455 456 void SkBitmap::notifyPixelsChanged() const { 457 SkASSERT(!this->isImmutable()); 458 if (fPixelRef) { 459 fPixelRef->notifyPixelsChanged(); 460 } 461 } 462 463 GrTexture* SkBitmap::getTexture() const { 464 return fPixelRef ? fPixelRef->getTexture() : NULL; 465 } 466 467 /////////////////////////////////////////////////////////////////////////////// 468 469 /** We explicitly use the same allocator for our pixels that SkMask does, 470 so that we can freely assign memory allocated by one class to the other. 471 */ 472 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, 473 SkColorTable* ctable) { 474 const SkImageInfo info = dst->info(); 475 if (kUnknown_SkColorType == info.colorType()) { 476 // SkDebugf("unsupported config for info %d\n", dst->config()); 477 return false; 478 } 479 480 SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable); 481 if (NULL == pr) { 482 return false; 483 } 484 485 dst->setPixelRef(pr)->unref(); 486 // since we're already allocated, we lockPixels right away 487 dst->lockPixels(); 488 return true; 489 } 490 491 /////////////////////////////////////////////////////////////////////////////// 492 493 bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize, 494 size_t dstRowBytes, bool preserveDstPad) const { 495 496 if (0 == dstRowBytes) { 497 dstRowBytes = fRowBytes; 498 } 499 500 if (dstRowBytes < fInfo.minRowBytes() || 501 dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) { 502 return false; 503 } 504 505 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) { 506 size_t safeSize = this->getSafeSize(); 507 if (safeSize > dstSize || safeSize == 0) 508 return false; 509 else { 510 SkAutoLockPixels lock(*this); 511 // This implementation will write bytes beyond the end of each row, 512 // excluding the last row, if the bitmap's stride is greater than 513 // strictly required by the current config. 514 memcpy(dst, getPixels(), safeSize); 515 516 return true; 517 } 518 } else { 519 // If destination has different stride than us, then copy line by line. 520 if (fInfo.getSafeSize(dstRowBytes) > dstSize) { 521 return false; 522 } else { 523 // Just copy what we need on each line. 524 size_t rowBytes = fInfo.minRowBytes(); 525 SkAutoLockPixels lock(*this); 526 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels()); 527 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); 528 for (int row = 0; row < fInfo.fHeight; 529 row++, srcP += fRowBytes, dstP += dstRowBytes) { 530 memcpy(dstP, srcP, rowBytes); 531 } 532 533 return true; 534 } 535 } 536 } 537 538 /////////////////////////////////////////////////////////////////////////////// 539 540 bool SkBitmap::isImmutable() const { 541 return fPixelRef ? fPixelRef->isImmutable() : 542 fFlags & kImageIsImmutable_Flag; 543 } 544 545 void SkBitmap::setImmutable() { 546 if (fPixelRef) { 547 fPixelRef->setImmutable(); 548 } else { 549 fFlags |= kImageIsImmutable_Flag; 550 } 551 } 552 553 bool SkBitmap::isVolatile() const { 554 return (fFlags & kImageIsVolatile_Flag) != 0; 555 } 556 557 void SkBitmap::setIsVolatile(bool isVolatile) { 558 if (isVolatile) { 559 fFlags |= kImageIsVolatile_Flag; 560 } else { 561 fFlags &= ~kImageIsVolatile_Flag; 562 } 563 } 564 565 void* SkBitmap::getAddr(int x, int y) const { 566 SkASSERT((unsigned)x < (unsigned)this->width()); 567 SkASSERT((unsigned)y < (unsigned)this->height()); 568 569 char* base = (char*)this->getPixels(); 570 if (base) { 571 base += y * this->rowBytes(); 572 switch (this->colorType()) { 573 case kRGBA_8888_SkColorType: 574 case kBGRA_8888_SkColorType: 575 base += x << 2; 576 break; 577 case kARGB_4444_SkColorType: 578 case kRGB_565_SkColorType: 579 base += x << 1; 580 break; 581 case kAlpha_8_SkColorType: 582 case kIndex_8_SkColorType: 583 base += x; 584 break; 585 default: 586 SkDEBUGFAIL("Can't return addr for config"); 587 base = NULL; 588 break; 589 } 590 } 591 return base; 592 } 593 594 SkColor SkBitmap::getColor(int x, int y) const { 595 SkASSERT((unsigned)x < (unsigned)this->width()); 596 SkASSERT((unsigned)y < (unsigned)this->height()); 597 598 switch (this->colorType()) { 599 case kAlpha_8_SkColorType: { 600 uint8_t* addr = this->getAddr8(x, y); 601 return SkColorSetA(0, addr[0]); 602 } 603 case kIndex_8_SkColorType: { 604 SkPMColor c = this->getIndex8Color(x, y); 605 return SkUnPreMultiply::PMColorToColor(c); 606 } 607 case kRGB_565_SkColorType: { 608 uint16_t* addr = this->getAddr16(x, y); 609 return SkPixel16ToColor(addr[0]); 610 } 611 case kARGB_4444_SkColorType: { 612 uint16_t* addr = this->getAddr16(x, y); 613 SkPMColor c = SkPixel4444ToPixel32(addr[0]); 614 return SkUnPreMultiply::PMColorToColor(c); 615 } 616 case kBGRA_8888_SkColorType: 617 case kRGBA_8888_SkColorType: { 618 uint32_t* addr = this->getAddr32(x, y); 619 return SkUnPreMultiply::PMColorToColor(addr[0]); 620 } 621 default: 622 SkASSERT(false); 623 return 0; 624 } 625 SkASSERT(false); // Not reached. 626 return 0; 627 } 628 629 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { 630 SkAutoLockPixels alp(bm); 631 if (!bm.getPixels()) { 632 return false; 633 } 634 635 const int height = bm.height(); 636 const int width = bm.width(); 637 638 switch (bm.colorType()) { 639 case kAlpha_8_SkColorType: { 640 unsigned a = 0xFF; 641 for (int y = 0; y < height; ++y) { 642 const uint8_t* row = bm.getAddr8(0, y); 643 for (int x = 0; x < width; ++x) { 644 a &= row[x]; 645 } 646 if (0xFF != a) { 647 return false; 648 } 649 } 650 return true; 651 } break; 652 case kIndex_8_SkColorType: { 653 SkAutoLockColors alc(bm); 654 const SkPMColor* table = alc.colors(); 655 if (!table) { 656 return false; 657 } 658 SkPMColor c = (SkPMColor)~0; 659 for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) { 660 c &= table[i]; 661 } 662 return 0xFF == SkGetPackedA32(c); 663 } break; 664 case kRGB_565_SkColorType: 665 return true; 666 break; 667 case kARGB_4444_SkColorType: { 668 unsigned c = 0xFFFF; 669 for (int y = 0; y < height; ++y) { 670 const SkPMColor16* row = bm.getAddr16(0, y); 671 for (int x = 0; x < width; ++x) { 672 c &= row[x]; 673 } 674 if (0xF != SkGetPackedA4444(c)) { 675 return false; 676 } 677 } 678 return true; 679 } break; 680 case kBGRA_8888_SkColorType: 681 case kRGBA_8888_SkColorType: { 682 SkPMColor c = (SkPMColor)~0; 683 for (int y = 0; y < height; ++y) { 684 const SkPMColor* row = bm.getAddr32(0, y); 685 for (int x = 0; x < width; ++x) { 686 c &= row[x]; 687 } 688 if (0xFF != SkGetPackedA32(c)) { 689 return false; 690 } 691 } 692 return true; 693 } 694 default: 695 break; 696 } 697 return false; 698 } 699 700 701 /////////////////////////////////////////////////////////////////////////////// 702 /////////////////////////////////////////////////////////////////////////////// 703 704 static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) { 705 unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | 706 (SkR32To4444(r) << SK_R4444_SHIFT) | 707 (SkG32To4444(g) << SK_G4444_SHIFT) | 708 (SkB32To4444(b) << SK_B4444_SHIFT); 709 return SkToU16(pixel); 710 } 711 712 void SkBitmap::internalErase(const SkIRect& area, 713 U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 714 #ifdef SK_DEBUG 715 SkDEBUGCODE(this->validate();) 716 SkASSERT(!area.isEmpty()); 717 { 718 SkIRect total = { 0, 0, this->width(), this->height() }; 719 SkASSERT(total.contains(area)); 720 } 721 #endif 722 723 switch (fInfo.colorType()) { 724 case kUnknown_SkColorType: 725 case kIndex_8_SkColorType: 726 return; // can't erase. Should we bzero so the memory is not uninitialized? 727 default: 728 break; 729 } 730 731 SkAutoLockPixels alp(*this); 732 // perform this check after the lock call 733 if (!this->readyToDraw()) { 734 return; 735 } 736 737 int height = area.height(); 738 const int width = area.width(); 739 const int rowBytes = fRowBytes; 740 741 switch (this->colorType()) { 742 case kAlpha_8_SkColorType: { 743 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); 744 while (--height >= 0) { 745 memset(p, a, width); 746 p += rowBytes; 747 } 748 break; 749 } 750 case kARGB_4444_SkColorType: 751 case kRGB_565_SkColorType: { 752 uint16_t* p = this->getAddr16(area.fLeft, area.fTop);; 753 uint16_t v; 754 755 // make rgb premultiplied 756 if (255 != a) { 757 r = SkAlphaMul(r, a); 758 g = SkAlphaMul(g, a); 759 b = SkAlphaMul(b, a); 760 } 761 762 if (kARGB_4444_SkColorType == this->colorType()) { 763 v = pack_8888_to_4444(a, r, g, b); 764 } else { 765 v = SkPackRGB16(r >> (8 - SK_R16_BITS), 766 g >> (8 - SK_G16_BITS), 767 b >> (8 - SK_B16_BITS)); 768 } 769 while (--height >= 0) { 770 sk_memset16(p, v, width); 771 p = (uint16_t*)((char*)p + rowBytes); 772 } 773 break; 774 } 775 case kBGRA_8888_SkColorType: 776 case kRGBA_8888_SkColorType: { 777 uint32_t* p = this->getAddr32(area.fLeft, area.fTop); 778 779 if (255 != a && kPremul_SkAlphaType == this->alphaType()) { 780 r = SkAlphaMul(r, a); 781 g = SkAlphaMul(g, a); 782 b = SkAlphaMul(b, a); 783 } 784 uint32_t v = kRGBA_8888_SkColorType == this->colorType() ? 785 SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b); 786 787 while (--height >= 0) { 788 sk_memset32(p, v, width); 789 p = (uint32_t*)((char*)p + rowBytes); 790 } 791 break; 792 } 793 default: 794 return; // no change, so don't call notifyPixelsChanged() 795 } 796 797 this->notifyPixelsChanged(); 798 } 799 800 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 801 SkIRect area = { 0, 0, this->width(), this->height() }; 802 if (!area.isEmpty()) { 803 this->internalErase(area, a, r, g, b); 804 } 805 } 806 807 void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { 808 SkIRect area = { 0, 0, this->width(), this->height() }; 809 if (area.intersect(rect)) { 810 this->internalErase(area, SkColorGetA(c), SkColorGetR(c), 811 SkColorGetG(c), SkColorGetB(c)); 812 } 813 } 814 815 ////////////////////////////////////////////////////////////////////////////////////// 816 ////////////////////////////////////////////////////////////////////////////////////// 817 818 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { 819 SkDEBUGCODE(this->validate();) 820 821 if (NULL == result || NULL == fPixelRef) { 822 return false; // no src pixels 823 } 824 825 SkIRect srcRect, r; 826 srcRect.set(0, 0, this->width(), this->height()); 827 if (!r.intersect(srcRect, subset)) { 828 return false; // r is empty (i.e. no intersection) 829 } 830 831 if (fPixelRef->getTexture() != NULL) { 832 // Do a deep copy 833 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), &subset); 834 if (pixelRef != NULL) { 835 SkBitmap dst; 836 dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(), 837 this->colorType(), this->alphaType())); 838 dst.setIsVolatile(this->isVolatile()); 839 dst.setPixelRef(pixelRef)->unref(); 840 SkDEBUGCODE(dst.validate()); 841 result->swap(dst); 842 return true; 843 } 844 } 845 846 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 847 // exited above. 848 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 849 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 850 851 SkBitmap dst; 852 dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()), 853 this->rowBytes()); 854 dst.setIsVolatile(this->isVolatile()); 855 856 if (fPixelRef) { 857 SkIPoint origin = fPixelRefOrigin; 858 origin.fX += r.fLeft; 859 origin.fY += r.fTop; 860 // share the pixelref with a custom offset 861 dst.setPixelRef(fPixelRef, origin); 862 } 863 SkDEBUGCODE(dst.validate();) 864 865 // we know we're good, so commit to result 866 result->swap(dst); 867 return true; 868 } 869 870 /////////////////////////////////////////////////////////////////////////////// 871 872 #include "SkCanvas.h" 873 #include "SkPaint.h" 874 875 bool SkBitmap::canCopyTo(SkColorType dstColorType) const { 876 if (this->colorType() == kUnknown_SkColorType) { 877 return false; 878 } 879 880 bool sameConfigs = (this->colorType() == dstColorType); 881 switch (dstColorType) { 882 case kAlpha_8_SkColorType: 883 case kRGB_565_SkColorType: 884 case kRGBA_8888_SkColorType: 885 case kBGRA_8888_SkColorType: 886 break; 887 case kIndex_8_SkColorType: 888 if (!sameConfigs) { 889 return false; 890 } 891 break; 892 case kARGB_4444_SkColorType: 893 return sameConfigs || kN32_SkColorType == this->colorType(); 894 default: 895 return false; 896 } 897 return true; 898 } 899 900 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, 901 Allocator* alloc) const { 902 if (!this->canCopyTo(dstColorType)) { 903 return false; 904 } 905 906 // if we have a texture, first get those pixels 907 SkBitmap tmpSrc; 908 const SkBitmap* src = this; 909 910 if (fPixelRef) { 911 SkIRect subset; 912 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, 913 fInfo.width(), fInfo.height()); 914 if (fPixelRef->readPixels(&tmpSrc, &subset)) { 915 if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) { 916 // FIXME: The only meaningful implementation of readPixels 917 // (GrPixelRef) assumes premultiplied pixels. 918 return false; 919 } 920 SkASSERT(tmpSrc.width() == this->width()); 921 SkASSERT(tmpSrc.height() == this->height()); 922 923 // did we get lucky and we can just return tmpSrc? 924 if (tmpSrc.colorType() == dstColorType && NULL == alloc) { 925 dst->swap(tmpSrc); 926 // If the result is an exact copy, clone the gen ID. 927 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) { 928 dst->pixelRef()->cloneGenID(*fPixelRef); 929 } 930 return true; 931 } 932 933 // fall through to the raster case 934 src = &tmpSrc; 935 } 936 } 937 938 // we lock this now, since we may need its colortable 939 SkAutoLockPixels srclock(*src); 940 if (!src->readyToDraw()) { 941 return false; 942 } 943 944 // The only way to be readyToDraw is if fPixelRef is non NULL. 945 SkASSERT(fPixelRef != NULL); 946 947 SkImageInfo dstInfo = src->info(); 948 dstInfo.fColorType = dstColorType; 949 950 SkBitmap tmpDst; 951 if (!tmpDst.setInfo(dstInfo)) { 952 return false; 953 } 954 955 // allocate colortable if srcConfig == kIndex8_Config 956 SkAutoTUnref<SkColorTable> ctable; 957 if (dstColorType == kIndex_8_SkColorType) { 958 // TODO: can we just ref() the src colortable? Is it reentrant-safe? 959 ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable()))); 960 } 961 if (!tmpDst.allocPixels(alloc, ctable)) { 962 return false; 963 } 964 965 if (!tmpDst.readyToDraw()) { 966 // allocator/lock failed 967 return false; 968 } 969 970 // pixelRef must be non NULL or tmpDst.readyToDraw() would have 971 // returned false. 972 SkASSERT(tmpDst.pixelRef() != NULL); 973 974 /* do memcpy for the same configs cases, else use drawing 975 */ 976 if (src->colorType() == dstColorType) { 977 if (tmpDst.getSize() == src->getSize()) { 978 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); 979 980 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); 981 if (dstPixelRef->info() == fPixelRef->info()) { 982 dstPixelRef->cloneGenID(*fPixelRef); 983 } 984 } else { 985 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); 986 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); 987 // to be sure we don't read too much, only copy our logical pixels 988 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); 989 for (int y = 0; y < tmpDst.height(); y++) { 990 memcpy(dstP, srcP, bytesToCopy); 991 srcP += src->rowBytes(); 992 dstP += tmpDst.rowBytes(); 993 } 994 } 995 } else if (kARGB_4444_SkColorType == dstColorType 996 && kN32_SkColorType == src->colorType()) { 997 if (src->alphaType() == kUnpremul_SkAlphaType) { 998 // Our method for converting to 4444 assumes premultiplied. 999 return false; 1000 } 1001 SkASSERT(src->height() == tmpDst.height()); 1002 SkASSERT(src->width() == tmpDst.width()); 1003 for (int y = 0; y < src->height(); ++y) { 1004 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); 1005 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); 1006 DITHER_4444_SCAN(y); 1007 for (int x = 0; x < src->width(); ++x) { 1008 dstRow[x] = SkDitherARGB32To4444(srcRow[x], 1009 DITHER_VALUE(x)); 1010 } 1011 } 1012 } else { 1013 if (tmpDst.alphaType() == kUnpremul_SkAlphaType) { 1014 // We do not support drawing to unpremultiplied bitmaps. 1015 return false; 1016 } 1017 1018 // Always clear the dest in case one of the blitters accesses it 1019 // TODO: switch the allocation of tmpDst to call sk_calloc_throw 1020 tmpDst.eraseColor(SK_ColorTRANSPARENT); 1021 1022 SkCanvas canvas(tmpDst); 1023 SkPaint paint; 1024 1025 paint.setDither(true); 1026 canvas.drawBitmap(*src, 0, 0, &paint); 1027 } 1028 1029 dst->swap(tmpDst); 1030 return true; 1031 } 1032 1033 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { 1034 const SkColorType dstCT = this->colorType(); 1035 1036 if (!this->canCopyTo(dstCT)) { 1037 return false; 1038 } 1039 1040 // If we have a PixelRef, and it supports deep copy, use it. 1041 // Currently supported only by texture-backed bitmaps. 1042 if (fPixelRef) { 1043 SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, NULL); 1044 if (pixelRef) { 1045 uint32_t rowBytes; 1046 if (this->colorType() == dstCT) { 1047 // Since there is no subset to pass to deepCopy, and deepCopy 1048 // succeeded, the new pixel ref must be identical. 1049 SkASSERT(fPixelRef->info() == pixelRef->info()); 1050 pixelRef->cloneGenID(*fPixelRef); 1051 // Use the same rowBytes as the original. 1052 rowBytes = fRowBytes; 1053 } else { 1054 // With the new config, an appropriate fRowBytes will be computed by setInfo. 1055 rowBytes = 0; 1056 } 1057 1058 SkImageInfo info = fInfo; 1059 info.fColorType = dstCT; 1060 if (!dst->setInfo(info, rowBytes)) { 1061 return false; 1062 } 1063 dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); 1064 return true; 1065 } 1066 } 1067 1068 if (this->getTexture()) { 1069 return false; 1070 } else { 1071 return this->copyTo(dst, dstCT, NULL); 1072 } 1073 } 1074 1075 /////////////////////////////////////////////////////////////////////////////// 1076 1077 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, 1078 int alphaRowBytes) { 1079 SkASSERT(alpha != NULL); 1080 SkASSERT(alphaRowBytes >= src.width()); 1081 1082 SkColorType colorType = src.colorType(); 1083 int w = src.width(); 1084 int h = src.height(); 1085 size_t rb = src.rowBytes(); 1086 1087 SkAutoLockPixels alp(src); 1088 if (!src.readyToDraw()) { 1089 // zero out the alpha buffer and return 1090 while (--h >= 0) { 1091 memset(alpha, 0, w); 1092 alpha += alphaRowBytes; 1093 } 1094 return false; 1095 } 1096 1097 if (kAlpha_8_SkColorType == colorType && !src.isOpaque()) { 1098 const uint8_t* s = src.getAddr8(0, 0); 1099 while (--h >= 0) { 1100 memcpy(alpha, s, w); 1101 s += rb; 1102 alpha += alphaRowBytes; 1103 } 1104 } else if (kN32_SkColorType == colorType && !src.isOpaque()) { 1105 const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0); 1106 while (--h >= 0) { 1107 for (int x = 0; x < w; x++) { 1108 alpha[x] = SkGetPackedA32(s[x]); 1109 } 1110 s = (const SkPMColor*)((const char*)s + rb); 1111 alpha += alphaRowBytes; 1112 } 1113 } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) { 1114 const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0); 1115 while (--h >= 0) { 1116 for (int x = 0; x < w; x++) { 1117 alpha[x] = SkPacked4444ToA32(s[x]); 1118 } 1119 s = (const SkPMColor16*)((const char*)s + rb); 1120 alpha += alphaRowBytes; 1121 } 1122 } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) { 1123 SkColorTable* ct = src.getColorTable(); 1124 if (ct) { 1125 const SkPMColor* SK_RESTRICT table = ct->lockColors(); 1126 const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0); 1127 while (--h >= 0) { 1128 for (int x = 0; x < w; x++) { 1129 alpha[x] = SkGetPackedA32(table[s[x]]); 1130 } 1131 s += rb; 1132 alpha += alphaRowBytes; 1133 } 1134 ct->unlockColors(); 1135 } 1136 } else { // src is opaque, so just fill alpha[] with 0xFF 1137 memset(alpha, 0xFF, h * alphaRowBytes); 1138 } 1139 return true; 1140 } 1141 1142 #include "SkPaint.h" 1143 #include "SkMaskFilter.h" 1144 #include "SkMatrix.h" 1145 1146 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, 1147 Allocator *allocator, SkIPoint* offset) const { 1148 SkDEBUGCODE(this->validate();) 1149 1150 SkBitmap tmpBitmap; 1151 SkMatrix identity; 1152 SkMask srcM, dstM; 1153 1154 srcM.fBounds.set(0, 0, this->width(), this->height()); 1155 srcM.fRowBytes = SkAlign4(this->width()); 1156 srcM.fFormat = SkMask::kA8_Format; 1157 1158 SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL; 1159 1160 // compute our (larger?) dst bounds if we have a filter 1161 if (NULL != filter) { 1162 identity.reset(); 1163 srcM.fImage = NULL; 1164 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1165 goto NO_FILTER_CASE; 1166 } 1167 dstM.fRowBytes = SkAlign4(dstM.fBounds.width()); 1168 } else { 1169 NO_FILTER_CASE: 1170 tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes); 1171 if (!tmpBitmap.allocPixels(allocator, NULL)) { 1172 // Allocation of pixels for alpha bitmap failed. 1173 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1174 tmpBitmap.width(), tmpBitmap.height()); 1175 return false; 1176 } 1177 GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes); 1178 if (offset) { 1179 offset->set(0, 0); 1180 } 1181 tmpBitmap.swap(*dst); 1182 return true; 1183 } 1184 srcM.fImage = SkMask::AllocImage(srcM.computeImageSize()); 1185 SkAutoMaskFreeImage srcCleanup(srcM.fImage); 1186 1187 GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes); 1188 if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1189 goto NO_FILTER_CASE; 1190 } 1191 SkAutoMaskFreeImage dstCleanup(dstM.fImage); 1192 1193 tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()), 1194 dstM.fRowBytes); 1195 if (!tmpBitmap.allocPixels(allocator, NULL)) { 1196 // Allocation of pixels for alpha bitmap failed. 1197 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1198 tmpBitmap.width(), tmpBitmap.height()); 1199 return false; 1200 } 1201 memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize()); 1202 if (offset) { 1203 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); 1204 } 1205 SkDEBUGCODE(tmpBitmap.validate();) 1206 1207 tmpBitmap.swap(*dst); 1208 return true; 1209 } 1210 1211 /////////////////////////////////////////////////////////////////////////////// 1212 1213 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) { 1214 const SkImageInfo info = bitmap.info(); 1215 SkAutoLockPixels alp(bitmap); 1216 if (0 == info.width() || 0 == info.height() || NULL == bitmap.getPixels()) { 1217 buffer->writeUInt(0); // instead of snugRB, signaling no pixels 1218 return; 1219 } 1220 1221 const size_t snugRB = info.width() * info.bytesPerPixel(); 1222 const char* src = (const char*)bitmap.getPixels(); 1223 const size_t ramRB = bitmap.rowBytes(); 1224 1225 buffer->write32(SkToU32(snugRB)); 1226 info.flatten(*buffer); 1227 1228 const size_t size = snugRB * info.height(); 1229 SkAutoMalloc storage(size); 1230 char* dst = (char*)storage.get(); 1231 for (int y = 0; y < info.height(); ++y) { 1232 memcpy(dst, src, snugRB); 1233 dst += snugRB; 1234 src += ramRB; 1235 } 1236 buffer->writeByteArray(storage.get(), size); 1237 1238 SkColorTable* ct = bitmap.getColorTable(); 1239 if (kIndex_8_SkColorType == info.colorType() && ct) { 1240 buffer->writeBool(true); 1241 ct->writeToBuffer(*buffer); 1242 } else { 1243 buffer->writeBool(false); 1244 } 1245 } 1246 1247 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) { 1248 const size_t snugRB = buffer->readUInt(); 1249 if (0 == snugRB) { // no pixels 1250 return false; 1251 } 1252 1253 SkImageInfo info; 1254 info.unflatten(*buffer); 1255 1256 const size_t ramRB = info.minRowBytes(); 1257 const int height = info.height(); 1258 const size_t snugSize = snugRB * height; 1259 const size_t ramSize = ramRB * height; 1260 if (!buffer->validate(snugSize <= ramSize)) { 1261 return false; 1262 } 1263 1264 char* dst = (char*)sk_malloc_throw(ramSize); 1265 buffer->readByteArray(dst, snugSize); 1266 SkAutoDataUnref data(SkData::NewFromMalloc(dst, ramSize)); 1267 1268 if (snugSize != ramSize) { 1269 const char* srcRow = dst + snugRB * (height - 1); 1270 char* dstRow = dst + ramRB * (height - 1); 1271 for (int y = height - 1; y >= 1; --y) { 1272 memmove(dstRow, srcRow, snugRB); 1273 srcRow -= snugRB; 1274 dstRow -= ramRB; 1275 } 1276 SkASSERT(srcRow == dstRow); // first row does not need to be moved 1277 } 1278 1279 SkAutoTUnref<SkColorTable> ctable; 1280 if (buffer->readBool()) { 1281 ctable.reset(SkNEW_ARGS(SkColorTable, (*buffer))); 1282 } 1283 1284 SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(), 1285 ctable.get(), data.get())); 1286 bitmap->setInfo(pr->info()); 1287 bitmap->setPixelRef(pr, 0, 0); 1288 return true; 1289 } 1290 1291 enum { 1292 SERIALIZE_PIXELTYPE_NONE, 1293 SERIALIZE_PIXELTYPE_REF_DATA 1294 }; 1295 1296 void SkBitmap::legacyUnflatten(SkReadBuffer& buffer) { 1297 this->reset(); 1298 1299 SkImageInfo info; 1300 info.unflatten(buffer); 1301 size_t rowBytes = buffer.readInt(); 1302 if (!buffer.validate((info.width() >= 0) && (info.height() >= 0) && 1303 SkColorTypeIsValid(info.fColorType) && 1304 SkAlphaTypeIsValid(info.fAlphaType) && 1305 validate_alphaType(info.fColorType, info.fAlphaType) && 1306 info.validRowBytes(rowBytes))) { 1307 return; 1308 } 1309 1310 bool configIsValid = this->setInfo(info, rowBytes); 1311 buffer.validate(configIsValid); 1312 1313 int reftype = buffer.readInt(); 1314 if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) || 1315 (SERIALIZE_PIXELTYPE_NONE == reftype))) { 1316 switch (reftype) { 1317 case SERIALIZE_PIXELTYPE_REF_DATA: { 1318 SkIPoint origin; 1319 origin.fX = buffer.readInt(); 1320 origin.fY = buffer.readInt(); 1321 size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel(); 1322 SkPixelRef* pr = buffer.readPixelRef(); 1323 if (!buffer.validate((NULL == pr) || 1324 (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) { 1325 origin.setZero(); 1326 } 1327 SkSafeUnref(this->setPixelRef(pr, origin)); 1328 break; 1329 } 1330 case SERIALIZE_PIXELTYPE_NONE: 1331 break; 1332 default: 1333 SkDEBUGFAIL("unrecognized pixeltype in serialized data"); 1334 sk_throw(); 1335 } 1336 } 1337 } 1338 1339 /////////////////////////////////////////////////////////////////////////////// 1340 1341 SkBitmap::RLEPixels::RLEPixels(int width, int height) { 1342 fHeight = height; 1343 fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*)); 1344 } 1345 1346 SkBitmap::RLEPixels::~RLEPixels() { 1347 sk_free(fYPtrs); 1348 } 1349 1350 /////////////////////////////////////////////////////////////////////////////// 1351 1352 #ifdef SK_DEBUG 1353 void SkBitmap::validate() const { 1354 fInfo.validate(); 1355 1356 // ImageInfo may not require this, but Bitmap ensures that opaque-only 1357 // colorTypes report opaque for their alphatype 1358 if (kRGB_565_SkColorType == fInfo.colorType()) { 1359 SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType()); 1360 } 1361 1362 SkASSERT(fInfo.validRowBytes(fRowBytes)); 1363 uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag; 1364 #ifdef SK_BUILD_FOR_ANDROID 1365 allFlags |= kHasHardwareMipMap_Flag; 1366 #endif 1367 SkASSERT(fFlags <= allFlags); 1368 SkASSERT(fPixelLockCount >= 0); 1369 1370 if (fPixels) { 1371 SkASSERT(fPixelRef); 1372 SkASSERT(fPixelLockCount > 0); 1373 SkASSERT(fPixelRef->isLocked()); 1374 SkASSERT(fPixelRef->rowBytes() == fRowBytes); 1375 SkASSERT(fPixelRefOrigin.fX >= 0); 1376 SkASSERT(fPixelRefOrigin.fY >= 0); 1377 SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX); 1378 SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOrigin.fY); 1379 SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes()); 1380 } else { 1381 SkASSERT(NULL == fColorTable); 1382 } 1383 } 1384 #endif 1385 1386 #ifndef SK_IGNORE_TO_STRING 1387 void SkBitmap::toString(SkString* str) const { 1388 1389 static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = { 1390 "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8", 1391 }; 1392 1393 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), 1394 gColorTypeNames[this->colorType()]); 1395 1396 str->append(" ("); 1397 if (this->isOpaque()) { 1398 str->append("opaque"); 1399 } else { 1400 str->append("transparent"); 1401 } 1402 if (this->isImmutable()) { 1403 str->append(", immutable"); 1404 } else { 1405 str->append(", not-immutable"); 1406 } 1407 str->append(")"); 1408 1409 SkPixelRef* pr = this->pixelRef(); 1410 if (NULL == pr) { 1411 // show null or the explicit pixel address (rare) 1412 str->appendf(" pixels:%p", this->getPixels()); 1413 } else { 1414 const char* uri = pr->getURI(); 1415 if (NULL != uri) { 1416 str->appendf(" uri:\"%s\"", uri); 1417 } else { 1418 str->appendf(" pixelref:%p", pr); 1419 } 1420 } 1421 1422 str->append(")"); 1423 } 1424 #endif 1425 1426 /////////////////////////////////////////////////////////////////////////////// 1427 1428 #ifdef SK_DEBUG 1429 void SkImageInfo::validate() const { 1430 SkASSERT(fWidth >= 0); 1431 SkASSERT(fHeight >= 0); 1432 SkASSERT(SkColorTypeIsValid(fColorType)); 1433 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); 1434 } 1435 #endif 1436