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