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