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