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