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