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