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