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