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 "SkImagePriv.h"
     15 #include "SkMallocPixelRef.h"
     16 #include "SkMask.h"
     17 #include "SkReadBuffer.h"
     18 #include "SkWriteBuffer.h"
     19 #include "SkPixelRef.h"
     20 #include "SkThread.h"
     21 #include "SkUnPreMultiply.h"
     22 #include "SkUtils.h"
     23 #include "SkValidationUtils.h"
     24 #include "SkPackBits.h"
     25 #include <new>
     26 
     27 static bool reset_return_false(SkBitmap* bm) {
     28     bm->reset();
     29     return false;
     30 }
     31 
     32 SkBitmap::SkBitmap() {
     33     sk_bzero(this, sizeof(*this));
     34 }
     35 
     36 SkBitmap::SkBitmap(const SkBitmap& src) {
     37     SkDEBUGCODE(src.validate();)
     38     sk_bzero(this, sizeof(*this));
     39     *this = src;
     40     SkDEBUGCODE(this->validate();)
     41 }
     42 
     43 SkBitmap::~SkBitmap() {
     44     SkDEBUGCODE(this->validate();)
     45     this->freePixels();
     46 }
     47 
     48 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
     49     if (this != &src) {
     50         this->freePixels();
     51         memcpy(this, &src, sizeof(src));
     52 
     53         // inc src reference counts
     54         SkSafeRef(src.fPixelRef);
     55 
     56         // we reset our locks if we get blown away
     57         fPixelLockCount = 0;
     58 
     59         if (fPixelRef) {
     60             // ignore the values from the memcpy
     61             fPixels = NULL;
     62             fColorTable = NULL;
     63             // Note that what to for genID is somewhat arbitrary. We have no
     64             // way to track changes to raw pixels across multiple SkBitmaps.
     65             // Would benefit from an SkRawPixelRef type created by
     66             // setPixels.
     67             // Just leave the memcpy'ed one but they'll get out of sync
     68             // as soon either is modified.
     69         }
     70     }
     71 
     72     SkDEBUGCODE(this->validate();)
     73     return *this;
     74 }
     75 
     76 void SkBitmap::swap(SkBitmap& other) {
     77     SkTSwap(fColorTable, other.fColorTable);
     78     SkTSwap(fPixelRef, other.fPixelRef);
     79     SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin);
     80     SkTSwap(fPixelLockCount, other.fPixelLockCount);
     81     SkTSwap(fPixels, other.fPixels);
     82     SkTSwap(fInfo, other.fInfo);
     83     SkTSwap(fRowBytes, other.fRowBytes);
     84     SkTSwap(fFlags, other.fFlags);
     85 
     86     SkDEBUGCODE(this->validate();)
     87 }
     88 
     89 void SkBitmap::reset() {
     90     this->freePixels();
     91     sk_bzero(this, sizeof(*this));
     92 }
     93 
     94 void SkBitmap::getBounds(SkRect* bounds) const {
     95     SkASSERT(bounds);
     96     bounds->set(0, 0,
     97                 SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height()));
     98 }
     99 
    100 void SkBitmap::getBounds(SkIRect* bounds) const {
    101     SkASSERT(bounds);
    102     bounds->set(0, 0, fInfo.width(), fInfo.height());
    103 }
    104 
    105 ///////////////////////////////////////////////////////////////////////////////
    106 
    107 bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
    108     SkAlphaType newAT = info.alphaType();
    109     if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
    110         return reset_return_false(this);
    111     }
    112     // don't look at info.alphaType(), since newAT is the real value...
    113 
    114     // require that rowBytes fit in 31bits
    115     int64_t mrb = info.minRowBytes64();
    116     if ((int32_t)mrb != mrb) {
    117         return reset_return_false(this);
    118     }
    119     if ((int64_t)rowBytes != (int32_t)rowBytes) {
    120         return reset_return_false(this);
    121     }
    122 
    123     if (info.width() < 0 || info.height() < 0) {
    124         return reset_return_false(this);
    125     }
    126 
    127     if (kUnknown_SkColorType == info.colorType()) {
    128         rowBytes = 0;
    129     } else if (0 == rowBytes) {
    130         rowBytes = (size_t)mrb;
    131     } else if (!info.validRowBytes(rowBytes)) {
    132         return reset_return_false(this);
    133     }
    134 
    135     this->freePixels();
    136 
    137     fInfo = info.makeAlphaType(newAT);
    138     fRowBytes = SkToU32(rowBytes);
    139     return true;
    140 }
    141 
    142 bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
    143     if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) {
    144         return false;
    145     }
    146     if (fInfo.alphaType() != newAlphaType) {
    147         fInfo = fInfo.makeAlphaType(newAlphaType);
    148         if (fPixelRef) {
    149             fPixelRef->changeAlphaType(newAlphaType);
    150         }
    151     }
    152     return true;
    153 }
    154 
    155 void SkBitmap::updatePixelsFromRef() const {
    156     if (fPixelRef) {
    157         if (fPixelLockCount > 0) {
    158             SkASSERT(fPixelRef->isLocked());
    159 
    160             void* p = fPixelRef->pixels();
    161             if (p) {
    162                 p = (char*)p
    163                     + fPixelRefOrigin.fY * fRowBytes
    164                     + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
    165             }
    166             fPixels = p;
    167             fColorTable = fPixelRef->colorTable();
    168         } else {
    169             SkASSERT(0 == fPixelLockCount);
    170             fPixels = NULL;
    171             fColorTable = NULL;
    172         }
    173     }
    174 }
    175 
    176 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
    177 #ifdef SK_DEBUG
    178     if (pr) {
    179         if (kUnknown_SkColorType != fInfo.colorType()) {
    180             const SkImageInfo& prInfo = pr->info();
    181             SkASSERT(fInfo.width() <= prInfo.width());
    182             SkASSERT(fInfo.height() <= prInfo.height());
    183             SkASSERT(fInfo.colorType() == prInfo.colorType());
    184             switch (prInfo.alphaType()) {
    185                 case kUnknown_SkAlphaType:
    186                     SkASSERT(fInfo.alphaType() == kUnknown_SkAlphaType);
    187                     break;
    188                 case kOpaque_SkAlphaType:
    189                 case kPremul_SkAlphaType:
    190                     SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
    191                              fInfo.alphaType() == kPremul_SkAlphaType);
    192                     break;
    193                 case kUnpremul_SkAlphaType:
    194                     SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
    195                              fInfo.alphaType() == kUnpremul_SkAlphaType);
    196                     break;
    197             }
    198         }
    199     }
    200 #endif
    201 
    202     if (pr) {
    203         const SkImageInfo& info = pr->info();
    204         fPixelRefOrigin.set(SkPin32(dx, 0, info.width()), SkPin32(dy, 0, info.height()));
    205     } else {
    206         // ignore dx,dy if there is no pixelref
    207         fPixelRefOrigin.setZero();
    208     }
    209 
    210     if (fPixelRef != pr) {
    211         this->freePixels();
    212         SkASSERT(NULL == fPixelRef);
    213 
    214         SkSafeRef(pr);
    215         fPixelRef = pr;
    216         this->updatePixelsFromRef();
    217     }
    218 
    219     SkDEBUGCODE(this->validate();)
    220     return pr;
    221 }
    222 
    223 void SkBitmap::lockPixels() const {
    224     if (fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) {
    225         fPixelRef->lockPixels();
    226         this->updatePixelsFromRef();
    227     }
    228     SkDEBUGCODE(this->validate();)
    229 }
    230 
    231 void SkBitmap::unlockPixels() const {
    232     SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
    233 
    234     if (fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) {
    235         fPixelRef->unlockPixels();
    236         this->updatePixelsFromRef();
    237     }
    238     SkDEBUGCODE(this->validate();)
    239 }
    240 
    241 bool SkBitmap::lockPixelsAreWritable() const {
    242     return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false;
    243 }
    244 
    245 void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
    246     if (NULL == p) {
    247         this->setPixelRef(NULL);
    248         return;
    249     }
    250 
    251     if (kUnknown_SkColorType == fInfo.colorType()) {
    252         this->setPixelRef(NULL);
    253         return;
    254     }
    255 
    256     SkPixelRef* pr = SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable);
    257     if (NULL == pr) {
    258         this->setPixelRef(NULL);
    259         return;
    260     }
    261 
    262     this->setPixelRef(pr)->unref();
    263 
    264     // since we're already allocated, we lockPixels right away
    265     this->lockPixels();
    266     SkDEBUGCODE(this->validate();)
    267 }
    268 
    269 bool SkBitmap::tryAllocPixels(Allocator* allocator, SkColorTable* ctable) {
    270     HeapAllocator stdalloc;
    271 
    272     if (NULL == allocator) {
    273         allocator = &stdalloc;
    274     }
    275     return allocator->allocPixelRef(this, ctable);
    276 }
    277 
    278 ///////////////////////////////////////////////////////////////////////////////
    279 
    280 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
    281     if (kIndex_8_SkColorType == requestedInfo.colorType()) {
    282         return reset_return_false(this);
    283     }
    284     if (!this->setInfo(requestedInfo, rowBytes)) {
    285         return reset_return_false(this);
    286     }
    287 
    288     // setInfo may have corrected info (e.g. 565 is always opaque).
    289     const SkImageInfo& correctedInfo = this->info();
    290     // setInfo may have computed a valid rowbytes if 0 were passed in
    291     rowBytes = this->rowBytes();
    292 
    293     SkMallocPixelRef::PRFactory defaultFactory;
    294 
    295     SkPixelRef* pr = defaultFactory.create(correctedInfo, rowBytes, NULL);
    296     if (NULL == pr) {
    297         return reset_return_false(this);
    298     }
    299     this->setPixelRef(pr)->unref();
    300 
    301     // TODO: lockPixels could/should return bool or void*/NULL
    302     this->lockPixels();
    303     if (NULL == this->getPixels()) {
    304         return reset_return_false(this);
    305     }
    306     return true;
    307 }
    308 
    309 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory,
    310                                 SkColorTable* ctable) {
    311     if (kIndex_8_SkColorType == requestedInfo.colorType() && NULL == ctable) {
    312         return reset_return_false(this);
    313     }
    314     if (!this->setInfo(requestedInfo)) {
    315         return reset_return_false(this);
    316     }
    317 
    318     // setInfo may have corrected info (e.g. 565 is always opaque).
    319     const SkImageInfo& correctedInfo = this->info();
    320 
    321     SkMallocPixelRef::PRFactory defaultFactory;
    322     if (NULL == factory) {
    323         factory = &defaultFactory;
    324     }
    325 
    326     SkPixelRef* pr = factory->create(correctedInfo, correctedInfo.minRowBytes(), ctable);
    327     if (NULL == pr) {
    328         return reset_return_false(this);
    329     }
    330     this->setPixelRef(pr)->unref();
    331 
    332     // TODO: lockPixels could/should return bool or void*/NULL
    333     this->lockPixels();
    334     if (NULL == this->getPixels()) {
    335         return reset_return_false(this);
    336     }
    337     return true;
    338 }
    339 
    340 bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
    341                              SkColorTable* ct, void (*releaseProc)(void* addr, void* context),
    342                              void* context) {
    343     if (!this->setInfo(requestedInfo, rb)) {
    344         this->reset();
    345         return false;
    346     }
    347 
    348     // setInfo may have corrected info (e.g. 565 is always opaque).
    349     const SkImageInfo& correctedInfo = this->info();
    350 
    351     SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc,
    352                                                    context);
    353     if (!pr) {
    354         this->reset();
    355         return false;
    356     }
    357 
    358     this->setPixelRef(pr)->unref();
    359 
    360     // since we're already allocated, we lockPixels right away
    361     this->lockPixels();
    362     SkDEBUGCODE(this->validate();)
    363     return true;
    364 }
    365 
    366 bool SkBitmap::installMaskPixels(const SkMask& mask) {
    367     if (SkMask::kA8_Format != mask.fFormat) {
    368         this->reset();
    369         return false;
    370     }
    371     return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
    372                                                    mask.fBounds.height()),
    373                                mask.fImage, mask.fRowBytes);
    374 }
    375 
    376 ///////////////////////////////////////////////////////////////////////////////
    377 
    378 void SkBitmap::freePixels() {
    379     if (fPixelRef) {
    380         if (fPixelLockCount > 0) {
    381             fPixelRef->unlockPixels();
    382         }
    383         fPixelRef->unref();
    384         fPixelRef = NULL;
    385         fPixelRefOrigin.setZero();
    386     }
    387     fPixelLockCount = 0;
    388     fPixels = NULL;
    389     fColorTable = NULL;
    390 }
    391 
    392 uint32_t SkBitmap::getGenerationID() const {
    393     return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
    394 }
    395 
    396 void SkBitmap::notifyPixelsChanged() const {
    397     SkASSERT(!this->isImmutable());
    398     if (fPixelRef) {
    399         fPixelRef->notifyPixelsChanged();
    400     }
    401 }
    402 
    403 GrTexture* SkBitmap::getTexture() const {
    404     return fPixelRef ? fPixelRef->getTexture() : NULL;
    405 }
    406 
    407 ///////////////////////////////////////////////////////////////////////////////
    408 
    409 /** We explicitly use the same allocator for our pixels that SkMask does,
    410  so that we can freely assign memory allocated by one class to the other.
    411  */
    412 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
    413                                             SkColorTable* ctable) {
    414     const SkImageInfo info = dst->info();
    415     if (kUnknown_SkColorType == info.colorType()) {
    416 //        SkDebugf("unsupported config for info %d\n", dst->config());
    417         return false;
    418     }
    419 
    420     SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable);
    421     if (NULL == pr) {
    422         return false;
    423     }
    424 
    425     dst->setPixelRef(pr)->unref();
    426     // since we're already allocated, we lockPixels right away
    427     dst->lockPixels();
    428     return true;
    429 }
    430 
    431 ///////////////////////////////////////////////////////////////////////////////
    432 
    433 bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
    434                             size_t dstRowBytes, bool preserveDstPad) const {
    435 
    436     if (0 == dstRowBytes) {
    437         dstRowBytes = fRowBytes;
    438     }
    439 
    440     if (dstRowBytes < fInfo.minRowBytes() ||
    441         dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) {
    442         return false;
    443     }
    444 
    445     if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
    446         size_t safeSize = this->getSafeSize();
    447         if (safeSize > dstSize || safeSize == 0)
    448             return false;
    449         else {
    450             SkAutoLockPixels lock(*this);
    451             // This implementation will write bytes beyond the end of each row,
    452             // excluding the last row, if the bitmap's stride is greater than
    453             // strictly required by the current config.
    454             memcpy(dst, getPixels(), safeSize);
    455 
    456             return true;
    457         }
    458     } else {
    459         // If destination has different stride than us, then copy line by line.
    460         if (fInfo.getSafeSize(dstRowBytes) > dstSize) {
    461             return false;
    462         } else {
    463             // Just copy what we need on each line.
    464             size_t rowBytes = fInfo.minRowBytes();
    465             SkAutoLockPixels lock(*this);
    466             const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
    467             uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
    468             for (int row = 0; row < fInfo.height(); row++, srcP += fRowBytes, dstP += dstRowBytes) {
    469                 memcpy(dstP, srcP, rowBytes);
    470             }
    471 
    472             return true;
    473         }
    474     }
    475 }
    476 
    477 ///////////////////////////////////////////////////////////////////////////////
    478 
    479 bool SkBitmap::isImmutable() const {
    480     return fPixelRef ? fPixelRef->isImmutable() : false;
    481 }
    482 
    483 void SkBitmap::setImmutable() {
    484     if (fPixelRef) {
    485         fPixelRef->setImmutable();
    486     }
    487 }
    488 
    489 bool SkBitmap::isVolatile() const {
    490     return (fFlags & kImageIsVolatile_Flag) != 0;
    491 }
    492 
    493 void SkBitmap::setIsVolatile(bool isVolatile) {
    494     if (isVolatile) {
    495         fFlags |= kImageIsVolatile_Flag;
    496     } else {
    497         fFlags &= ~kImageIsVolatile_Flag;
    498     }
    499 }
    500 
    501 void* SkBitmap::getAddr(int x, int y) const {
    502     SkASSERT((unsigned)x < (unsigned)this->width());
    503     SkASSERT((unsigned)y < (unsigned)this->height());
    504 
    505     char* base = (char*)this->getPixels();
    506     if (base) {
    507         base += y * this->rowBytes();
    508         switch (this->colorType()) {
    509             case kRGBA_8888_SkColorType:
    510             case kBGRA_8888_SkColorType:
    511                 base += x << 2;
    512                 break;
    513             case kARGB_4444_SkColorType:
    514             case kRGB_565_SkColorType:
    515                 base += x << 1;
    516                 break;
    517             case kAlpha_8_SkColorType:
    518             case kIndex_8_SkColorType:
    519             case kGray_8_SkColorType:
    520                 base += x;
    521                 break;
    522             default:
    523                 SkDEBUGFAIL("Can't return addr for config");
    524                 base = NULL;
    525                 break;
    526         }
    527     }
    528     return base;
    529 }
    530 
    531 SkColor SkBitmap::getColor(int x, int y) const {
    532     SkASSERT((unsigned)x < (unsigned)this->width());
    533     SkASSERT((unsigned)y < (unsigned)this->height());
    534 
    535     switch (this->colorType()) {
    536         case kGray_8_SkColorType: {
    537             uint8_t* addr = this->getAddr8(x, y);
    538             return SkColorSetRGB(*addr, *addr, *addr);
    539         }
    540         case kAlpha_8_SkColorType: {
    541             uint8_t* addr = this->getAddr8(x, y);
    542             return SkColorSetA(0, addr[0]);
    543         }
    544         case kIndex_8_SkColorType: {
    545             SkPMColor c = this->getIndex8Color(x, y);
    546             return SkUnPreMultiply::PMColorToColor(c);
    547         }
    548         case kRGB_565_SkColorType: {
    549             uint16_t* addr = this->getAddr16(x, y);
    550             return SkPixel16ToColor(addr[0]);
    551         }
    552         case kARGB_4444_SkColorType: {
    553             uint16_t* addr = this->getAddr16(x, y);
    554             SkPMColor c = SkPixel4444ToPixel32(addr[0]);
    555             return SkUnPreMultiply::PMColorToColor(c);
    556         }
    557         case kBGRA_8888_SkColorType:
    558         case kRGBA_8888_SkColorType: {
    559             uint32_t* addr = this->getAddr32(x, y);
    560             return SkUnPreMultiply::PMColorToColor(addr[0]);
    561         }
    562         default:
    563             SkASSERT(false);
    564             return 0;
    565     }
    566     SkASSERT(false);  // Not reached.
    567     return 0;
    568 }
    569 
    570 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
    571     SkAutoLockPixels alp(bm);
    572     if (!bm.getPixels()) {
    573         return false;
    574     }
    575 
    576     const int height = bm.height();
    577     const int width = bm.width();
    578 
    579     switch (bm.colorType()) {
    580         case kAlpha_8_SkColorType: {
    581             unsigned a = 0xFF;
    582             for (int y = 0; y < height; ++y) {
    583                 const uint8_t* row = bm.getAddr8(0, y);
    584                 for (int x = 0; x < width; ++x) {
    585                     a &= row[x];
    586                 }
    587                 if (0xFF != a) {
    588                     return false;
    589                 }
    590             }
    591             return true;
    592         } break;
    593         case kIndex_8_SkColorType: {
    594             if (!bm.getColorTable()) {
    595                 return false;
    596             }
    597             const SkPMColor* table = bm.getColorTable()->readColors();
    598             SkPMColor c = (SkPMColor)~0;
    599             for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) {
    600                 c &= table[i];
    601             }
    602             return 0xFF == SkGetPackedA32(c);
    603         } break;
    604         case kRGB_565_SkColorType:
    605         case kGray_8_SkColorType:
    606             return true;
    607             break;
    608         case kARGB_4444_SkColorType: {
    609             unsigned c = 0xFFFF;
    610             for (int y = 0; y < height; ++y) {
    611                 const SkPMColor16* row = bm.getAddr16(0, y);
    612                 for (int x = 0; x < width; ++x) {
    613                     c &= row[x];
    614                 }
    615                 if (0xF != SkGetPackedA4444(c)) {
    616                     return false;
    617                 }
    618             }
    619             return true;
    620         } break;
    621         case kBGRA_8888_SkColorType:
    622         case kRGBA_8888_SkColorType: {
    623             SkPMColor c = (SkPMColor)~0;
    624             for (int y = 0; y < height; ++y) {
    625                 const SkPMColor* row = bm.getAddr32(0, y);
    626                 for (int x = 0; x < width; ++x) {
    627                     c &= row[x];
    628                 }
    629                 if (0xFF != SkGetPackedA32(c)) {
    630                     return false;
    631                 }
    632             }
    633             return true;
    634         }
    635         default:
    636             break;
    637     }
    638     return false;
    639 }
    640 
    641 
    642 ///////////////////////////////////////////////////////////////////////////////
    643 ///////////////////////////////////////////////////////////////////////////////
    644 
    645 static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
    646     unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) |
    647                      (SkR32To4444(r) << SK_R4444_SHIFT) |
    648                      (SkG32To4444(g) << SK_G4444_SHIFT) |
    649                      (SkB32To4444(b) << SK_B4444_SHIFT);
    650     return SkToU16(pixel);
    651 }
    652 
    653 void SkBitmap::internalErase(const SkIRect& area,
    654                              U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
    655 #ifdef SK_DEBUG
    656     SkDEBUGCODE(this->validate();)
    657     SkASSERT(!area.isEmpty());
    658     {
    659         SkIRect total = { 0, 0, this->width(), this->height() };
    660         SkASSERT(total.contains(area));
    661     }
    662 #endif
    663 
    664     switch (fInfo.colorType()) {
    665         case kUnknown_SkColorType:
    666         case kIndex_8_SkColorType:
    667             return; // can't erase. Should we bzero so the memory is not uninitialized?
    668         default:
    669             break;
    670     }
    671 
    672     SkAutoLockPixels alp(*this);
    673     // perform this check after the lock call
    674     if (!this->readyToDraw()) {
    675         return;
    676     }
    677 
    678     int height = area.height();
    679     const int width = area.width();
    680     const int rowBytes = fRowBytes;
    681 
    682     switch (this->colorType()) {
    683         case kGray_8_SkColorType: {
    684             if (255 != a) {
    685                 r = SkMulDiv255Round(r, a);
    686                 g = SkMulDiv255Round(g, a);
    687                 b = SkMulDiv255Round(b, a);
    688             }
    689             int gray = SkComputeLuminance(r, g, b);
    690             uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
    691             while (--height >= 0) {
    692                 memset(p, gray, width);
    693                 p += rowBytes;
    694             }
    695             break;
    696         }
    697         case kAlpha_8_SkColorType: {
    698             uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
    699             while (--height >= 0) {
    700                 memset(p, a, width);
    701                 p += rowBytes;
    702             }
    703             break;
    704         }
    705         case kARGB_4444_SkColorType:
    706         case kRGB_565_SkColorType: {
    707             uint16_t* p = this->getAddr16(area.fLeft, area.fTop);
    708             uint16_t v;
    709 
    710             // make rgb premultiplied
    711             if (255 != a) {
    712                 r = SkAlphaMul(r, a);
    713                 g = SkAlphaMul(g, a);
    714                 b = SkAlphaMul(b, a);
    715             }
    716 
    717             if (kARGB_4444_SkColorType == this->colorType()) {
    718                 v = pack_8888_to_4444(a, r, g, b);
    719             } else {
    720                 v = SkPackRGB16(r >> (8 - SK_R16_BITS),
    721                                 g >> (8 - SK_G16_BITS),
    722                                 b >> (8 - SK_B16_BITS));
    723             }
    724             while (--height >= 0) {
    725                 sk_memset16(p, v, width);
    726                 p = (uint16_t*)((char*)p + rowBytes);
    727             }
    728             break;
    729         }
    730         case kBGRA_8888_SkColorType:
    731         case kRGBA_8888_SkColorType: {
    732             uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
    733 
    734             if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
    735                 r = SkAlphaMul(r, a);
    736                 g = SkAlphaMul(g, a);
    737                 b = SkAlphaMul(b, a);
    738             }
    739             uint32_t v = kRGBA_8888_SkColorType == this->colorType() ?
    740                          SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
    741 
    742             while (--height >= 0) {
    743                 sk_memset32(p, v, width);
    744                 p = (uint32_t*)((char*)p + rowBytes);
    745             }
    746             break;
    747         }
    748         default:
    749             return; // no change, so don't call notifyPixelsChanged()
    750     }
    751 
    752     this->notifyPixelsChanged();
    753 }
    754 
    755 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
    756     SkIRect area = { 0, 0, this->width(), this->height() };
    757     if (!area.isEmpty()) {
    758         this->internalErase(area, a, r, g, b);
    759     }
    760 }
    761 
    762 void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const {
    763     SkIRect area = { 0, 0, this->width(), this->height() };
    764     if (area.intersect(rect)) {
    765         this->internalErase(area, SkColorGetA(c), SkColorGetR(c),
    766                             SkColorGetG(c), SkColorGetB(c));
    767     }
    768 }
    769 
    770 //////////////////////////////////////////////////////////////////////////////////////
    771 //////////////////////////////////////////////////////////////////////////////////////
    772 
    773 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
    774     SkDEBUGCODE(this->validate();)
    775 
    776     if (NULL == result || NULL == fPixelRef) {
    777         return false;   // no src pixels
    778     }
    779 
    780     SkIRect srcRect, r;
    781     srcRect.set(0, 0, this->width(), this->height());
    782     if (!r.intersect(srcRect, subset)) {
    783         return false;   // r is empty (i.e. no intersection)
    784     }
    785 
    786     if (fPixelRef->getTexture() != NULL) {
    787         // Do a deep copy
    788         SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), this->profileType(), &subset);
    789         if (pixelRef != NULL) {
    790             SkBitmap dst;
    791             dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(),
    792                                           this->colorType(), this->alphaType()));
    793             dst.setIsVolatile(this->isVolatile());
    794             dst.setPixelRef(pixelRef)->unref();
    795             SkDEBUGCODE(dst.validate());
    796             result->swap(dst);
    797             return true;
    798         }
    799     }
    800 
    801     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
    802     // exited above.
    803     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
    804     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
    805 
    806     SkBitmap dst;
    807     dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()),
    808                 this->rowBytes());
    809     dst.setIsVolatile(this->isVolatile());
    810 
    811     if (fPixelRef) {
    812         SkIPoint origin = fPixelRefOrigin;
    813         origin.fX += r.fLeft;
    814         origin.fY += r.fTop;
    815         // share the pixelref with a custom offset
    816         dst.setPixelRef(fPixelRef, origin);
    817     }
    818     SkDEBUGCODE(dst.validate();)
    819 
    820     // we know we're good, so commit to result
    821     result->swap(dst);
    822     return true;
    823 }
    824 
    825 ///////////////////////////////////////////////////////////////////////////////
    826 
    827 #include "SkCanvas.h"
    828 #include "SkPaint.h"
    829 
    830 bool SkBitmap::canCopyTo(SkColorType dstColorType) const {
    831     const SkColorType srcCT = this->colorType();
    832 
    833     if (srcCT == kUnknown_SkColorType) {
    834         return false;
    835     }
    836 
    837     bool sameConfigs = (srcCT == dstColorType);
    838     switch (dstColorType) {
    839         case kAlpha_8_SkColorType:
    840         case kRGB_565_SkColorType:
    841         case kRGBA_8888_SkColorType:
    842         case kBGRA_8888_SkColorType:
    843             break;
    844         case kIndex_8_SkColorType:
    845             if (!sameConfigs) {
    846                 return false;
    847             }
    848             break;
    849         case kARGB_4444_SkColorType:
    850             return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorType == srcCT;
    851         case kGray_8_SkColorType:
    852             switch (srcCT) {
    853                 case kGray_8_SkColorType:
    854                 case kRGBA_8888_SkColorType:
    855                 case kBGRA_8888_SkColorType:
    856                     return true;
    857                 default:
    858                     break;
    859             }
    860             return false;
    861         default:
    862             return false;
    863     }
    864     return true;
    865 }
    866 
    867 #include "SkConfig8888.h"
    868 
    869 bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
    870                           int x, int y) const {
    871     if (kUnknown_SkColorType == requestedDstInfo.colorType()) {
    872         return false;
    873     }
    874     if (NULL == dstPixels || dstRB < requestedDstInfo.minRowBytes()) {
    875         return false;
    876     }
    877     if (0 == requestedDstInfo.width() || 0 == requestedDstInfo.height()) {
    878         return false;
    879     }
    880 
    881     SkIRect srcR = SkIRect::MakeXYWH(x, y, requestedDstInfo.width(), requestedDstInfo.height());
    882     if (!srcR.intersect(0, 0, this->width(), this->height())) {
    883         return false;
    884     }
    885 
    886     // the intersect may have shrunk info's logical size
    887     const SkImageInfo dstInfo = requestedDstInfo.makeWH(srcR.width(), srcR.height());
    888 
    889     // if x or y are negative, then we have to adjust pixels
    890     if (x > 0) {
    891         x = 0;
    892     }
    893     if (y > 0) {
    894         y = 0;
    895     }
    896     // here x,y are either 0 or negative
    897     dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel());
    898 
    899     //////////////
    900 
    901     SkAutoLockPixels alp(*this);
    902 
    903     // since we don't stop creating un-pixeled devices yet, check for no pixels here
    904     if (NULL == this->getPixels()) {
    905         return false;
    906     }
    907 
    908     const SkImageInfo srcInfo = this->info().makeWH(dstInfo.width(), dstInfo.height());
    909 
    910     const void* srcPixels = this->getAddr(srcR.x(), srcR.y());
    911     return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, this->rowBytes(),
    912                                    this->getColorTable());
    913 }
    914 
    915 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
    916     if (!this->canCopyTo(dstColorType)) {
    917         return false;
    918     }
    919 
    920     // if we have a texture, first get those pixels
    921     SkBitmap tmpSrc;
    922     const SkBitmap* src = this;
    923 
    924     if (fPixelRef) {
    925         SkIRect subset;
    926         subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
    927                        fInfo.width(), fInfo.height());
    928         if (fPixelRef->readPixels(&tmpSrc, &subset)) {
    929             if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) {
    930                 // FIXME: The only meaningful implementation of readPixels
    931                 // (GrPixelRef) assumes premultiplied pixels.
    932                 return false;
    933             }
    934             SkASSERT(tmpSrc.width() == this->width());
    935             SkASSERT(tmpSrc.height() == this->height());
    936 
    937             // did we get lucky and we can just return tmpSrc?
    938             if (tmpSrc.colorType() == dstColorType && NULL == alloc) {
    939                 dst->swap(tmpSrc);
    940                 // If the result is an exact copy, clone the gen ID.
    941                 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
    942                     dst->pixelRef()->cloneGenID(*fPixelRef);
    943                 }
    944                 return true;
    945             }
    946 
    947             // fall through to the raster case
    948             src = &tmpSrc;
    949         }
    950     }
    951 
    952     // we lock this now, since we may need its colortable
    953     SkAutoLockPixels srclock(*src);
    954     if (!src->readyToDraw()) {
    955         return false;
    956     }
    957 
    958     // The only way to be readyToDraw is if fPixelRef is non NULL.
    959     SkASSERT(fPixelRef != NULL);
    960 
    961     const SkImageInfo dstInfo = src->info().makeColorType(dstColorType);
    962 
    963     SkBitmap tmpDst;
    964     if (!tmpDst.setInfo(dstInfo)) {
    965         return false;
    966     }
    967 
    968     // allocate colortable if srcConfig == kIndex8_Config
    969     SkAutoTUnref<SkColorTable> ctable;
    970     if (dstColorType == kIndex_8_SkColorType) {
    971         ctable.reset(SkRef(src->getColorTable()));
    972     }
    973     if (!tmpDst.tryAllocPixels(alloc, ctable)) {
    974         return false;
    975     }
    976 
    977     if (!tmpDst.readyToDraw()) {
    978         // allocator/lock failed
    979         return false;
    980     }
    981 
    982     // pixelRef must be non NULL or tmpDst.readyToDraw() would have
    983     // returned false.
    984     SkASSERT(tmpDst.pixelRef() != NULL);
    985 
    986     if (!src->readPixels(tmpDst.info(), tmpDst.getPixels(), tmpDst.rowBytes(), 0, 0)) {
    987         return false;
    988     }
    989 
    990     //  (for BitmapHeap) Clone the pixelref genID even though we have a new pixelref.
    991     //  The old copyTo impl did this, so we continue it for now.
    992     //
    993     //  TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be
    994     //      if (src_pixelref->info == dst_pixelref->info)
    995     //
    996     if (src->colorType() == dstColorType && tmpDst.getSize() == src->getSize()) {
    997         SkPixelRef* dstPixelRef = tmpDst.pixelRef();
    998         if (dstPixelRef->info() == fPixelRef->info()) {
    999             dstPixelRef->cloneGenID(*fPixelRef);
   1000         }
   1001     }
   1002 
   1003     dst->swap(tmpDst);
   1004     return true;
   1005 }
   1006 
   1007 bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
   1008     const SkColorType dstCT = this->colorType();
   1009     const SkColorProfileType dstPT = this->profileType();
   1010 
   1011     if (!this->canCopyTo(dstCT)) {
   1012         return false;
   1013     }
   1014 
   1015     // If we have a PixelRef, and it supports deep copy, use it.
   1016     // Currently supported only by texture-backed bitmaps.
   1017     if (fPixelRef) {
   1018         SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, dstPT, NULL);
   1019         if (pixelRef) {
   1020             uint32_t rowBytes;
   1021             if (this->colorType() == dstCT && this->profileType() == dstPT) {
   1022                 // Since there is no subset to pass to deepCopy, and deepCopy
   1023                 // succeeded, the new pixel ref must be identical.
   1024                 SkASSERT(fPixelRef->info() == pixelRef->info());
   1025                 pixelRef->cloneGenID(*fPixelRef);
   1026                 // Use the same rowBytes as the original.
   1027                 rowBytes = fRowBytes;
   1028             } else {
   1029                 // With the new config, an appropriate fRowBytes will be computed by setInfo.
   1030                 rowBytes = 0;
   1031             }
   1032 
   1033             const SkImageInfo info = fInfo.makeColorType(dstCT);
   1034             if (!dst->setInfo(info, rowBytes)) {
   1035                 return false;
   1036             }
   1037             dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
   1038             return true;
   1039         }
   1040     }
   1041 
   1042     if (this->getTexture()) {
   1043         return false;
   1044     } else {
   1045         return this->copyTo(dst, dstCT, NULL);
   1046     }
   1047 }
   1048 
   1049 ///////////////////////////////////////////////////////////////////////////////
   1050 
   1051 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
   1052                            int alphaRowBytes) {
   1053     SkASSERT(alpha != NULL);
   1054     SkASSERT(alphaRowBytes >= src.width());
   1055 
   1056     SkColorType colorType = src.colorType();
   1057     int         w = src.width();
   1058     int         h = src.height();
   1059     size_t      rb = src.rowBytes();
   1060 
   1061     SkAutoLockPixels alp(src);
   1062     if (!src.readyToDraw()) {
   1063         // zero out the alpha buffer and return
   1064         while (--h >= 0) {
   1065             memset(alpha, 0, w);
   1066             alpha += alphaRowBytes;
   1067         }
   1068         return false;
   1069     }
   1070 
   1071     if (kAlpha_8_SkColorType == colorType && !src.isOpaque()) {
   1072         const uint8_t* s = src.getAddr8(0, 0);
   1073         while (--h >= 0) {
   1074             memcpy(alpha, s, w);
   1075             s += rb;
   1076             alpha += alphaRowBytes;
   1077         }
   1078     } else if (kN32_SkColorType == colorType && !src.isOpaque()) {
   1079         const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
   1080         while (--h >= 0) {
   1081             for (int x = 0; x < w; x++) {
   1082                 alpha[x] = SkGetPackedA32(s[x]);
   1083             }
   1084             s = (const SkPMColor*)((const char*)s + rb);
   1085             alpha += alphaRowBytes;
   1086         }
   1087     } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) {
   1088         const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
   1089         while (--h >= 0) {
   1090             for (int x = 0; x < w; x++) {
   1091                 alpha[x] = SkPacked4444ToA32(s[x]);
   1092             }
   1093             s = (const SkPMColor16*)((const char*)s + rb);
   1094             alpha += alphaRowBytes;
   1095         }
   1096     } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) {
   1097         SkColorTable* ct = src.getColorTable();
   1098         if (ct) {
   1099             const SkPMColor* SK_RESTRICT table = ct->readColors();
   1100             const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
   1101             while (--h >= 0) {
   1102                 for (int x = 0; x < w; x++) {
   1103                     alpha[x] = SkGetPackedA32(table[s[x]]);
   1104                 }
   1105                 s += rb;
   1106                 alpha += alphaRowBytes;
   1107             }
   1108         }
   1109     } else {    // src is opaque, so just fill alpha[] with 0xFF
   1110         memset(alpha, 0xFF, h * alphaRowBytes);
   1111     }
   1112     return true;
   1113 }
   1114 
   1115 #include "SkPaint.h"
   1116 #include "SkMaskFilter.h"
   1117 #include "SkMatrix.h"
   1118 
   1119 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
   1120                             Allocator *allocator, SkIPoint* offset) const {
   1121     SkDEBUGCODE(this->validate();)
   1122 
   1123     SkBitmap    tmpBitmap;
   1124     SkMatrix    identity;
   1125     SkMask      srcM, dstM;
   1126 
   1127     srcM.fBounds.set(0, 0, this->width(), this->height());
   1128     srcM.fRowBytes = SkAlign4(this->width());
   1129     srcM.fFormat = SkMask::kA8_Format;
   1130 
   1131     SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
   1132 
   1133     // compute our (larger?) dst bounds if we have a filter
   1134     if (filter) {
   1135         identity.reset();
   1136         srcM.fImage = NULL;
   1137         if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
   1138             goto NO_FILTER_CASE;
   1139         }
   1140         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
   1141     } else {
   1142     NO_FILTER_CASE:
   1143         tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
   1144         if (!tmpBitmap.tryAllocPixels(allocator, NULL)) {
   1145             // Allocation of pixels for alpha bitmap failed.
   1146             SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
   1147                     tmpBitmap.width(), tmpBitmap.height());
   1148             return false;
   1149         }
   1150         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
   1151         if (offset) {
   1152             offset->set(0, 0);
   1153         }
   1154         tmpBitmap.swap(*dst);
   1155         return true;
   1156     }
   1157     srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
   1158     SkAutoMaskFreeImage srcCleanup(srcM.fImage);
   1159 
   1160     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
   1161     if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
   1162         goto NO_FILTER_CASE;
   1163     }
   1164     SkAutoMaskFreeImage dstCleanup(dstM.fImage);
   1165 
   1166     tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
   1167                       dstM.fRowBytes);
   1168     if (!tmpBitmap.tryAllocPixels(allocator, NULL)) {
   1169         // Allocation of pixels for alpha bitmap failed.
   1170         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
   1171                 tmpBitmap.width(), tmpBitmap.height());
   1172         return false;
   1173     }
   1174     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
   1175     if (offset) {
   1176         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
   1177     }
   1178     SkDEBUGCODE(tmpBitmap.validate();)
   1179 
   1180     tmpBitmap.swap(*dst);
   1181     return true;
   1182 }
   1183 
   1184 ///////////////////////////////////////////////////////////////////////////////
   1185 
   1186 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
   1187     const SkImageInfo info = bitmap.info();
   1188     SkAutoLockPixels alp(bitmap);
   1189     if (0 == info.width() || 0 == info.height() || NULL == bitmap.getPixels()) {
   1190         buffer->writeUInt(0); // instead of snugRB, signaling no pixels
   1191         return;
   1192     }
   1193 
   1194     const size_t snugRB = info.width() * info.bytesPerPixel();
   1195     const char* src = (const char*)bitmap.getPixels();
   1196     const size_t ramRB = bitmap.rowBytes();
   1197 
   1198     buffer->write32(SkToU32(snugRB));
   1199     info.flatten(*buffer);
   1200 
   1201     const size_t size = snugRB * info.height();
   1202     SkAutoMalloc storage(size);
   1203     char* dst = (char*)storage.get();
   1204     for (int y = 0; y < info.height(); ++y) {
   1205         memcpy(dst, src, snugRB);
   1206         dst += snugRB;
   1207         src += ramRB;
   1208     }
   1209     buffer->writeByteArray(storage.get(), size);
   1210 
   1211     SkColorTable* ct = bitmap.getColorTable();
   1212     if (kIndex_8_SkColorType == info.colorType() && ct) {
   1213         buffer->writeBool(true);
   1214         ct->writeToBuffer(*buffer);
   1215     } else {
   1216         buffer->writeBool(false);
   1217     }
   1218 }
   1219 
   1220 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
   1221     const size_t snugRB = buffer->readUInt();
   1222     if (0 == snugRB) {  // no pixels
   1223         return false;
   1224     }
   1225 
   1226     SkImageInfo info;
   1227     info.unflatten(*buffer);
   1228 
   1229     // If there was an error reading "info", don't use it to compute minRowBytes()
   1230     if (!buffer->validate(true)) {
   1231         return false;
   1232     }
   1233 
   1234     const size_t ramRB = info.minRowBytes();
   1235     const int height = SkMax32(info.height(), 0);
   1236     const uint64_t snugSize = sk_64_mul(snugRB, height);
   1237     const uint64_t ramSize = sk_64_mul(ramRB, height);
   1238     static const uint64_t max_size_t = (size_t)(-1);
   1239     if (!buffer->validate((snugSize <= ramSize) && (ramSize <= max_size_t))) {
   1240         return false;
   1241     }
   1242 
   1243     SkAutoDataUnref data(SkData::NewUninitialized(SkToSizeT(ramSize)));
   1244     char* dst = (char*)data->writable_data();
   1245     buffer->readByteArray(dst, SkToSizeT(snugSize));
   1246 
   1247     if (snugSize != ramSize) {
   1248         const char* srcRow = dst + snugRB * (height - 1);
   1249         char* dstRow = dst + ramRB * (height - 1);
   1250         for (int y = height - 1; y >= 1; --y) {
   1251             memmove(dstRow, srcRow, snugRB);
   1252             srcRow -= snugRB;
   1253             dstRow -= ramRB;
   1254         }
   1255         SkASSERT(srcRow == dstRow); // first row does not need to be moved
   1256     }
   1257 
   1258     SkAutoTUnref<SkColorTable> ctable;
   1259     if (buffer->readBool()) {
   1260         ctable.reset(SkNEW_ARGS(SkColorTable, (*buffer)));
   1261     }
   1262 
   1263     SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(),
   1264                                                               ctable.get(), data.get()));
   1265     if (!pr.get()) {
   1266         return false;
   1267     }
   1268     bitmap->setInfo(pr->info());
   1269     bitmap->setPixelRef(pr, 0, 0);
   1270     return true;
   1271 }
   1272 
   1273 enum {
   1274     SERIALIZE_PIXELTYPE_NONE,
   1275     SERIALIZE_PIXELTYPE_REF_DATA
   1276 };
   1277 
   1278 ///////////////////////////////////////////////////////////////////////////////
   1279 
   1280 SkBitmap::RLEPixels::RLEPixels(int width, int height) {
   1281     fHeight = height;
   1282     fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
   1283 }
   1284 
   1285 SkBitmap::RLEPixels::~RLEPixels() {
   1286     sk_free(fYPtrs);
   1287 }
   1288 
   1289 ///////////////////////////////////////////////////////////////////////////////
   1290 
   1291 #ifdef SK_DEBUG
   1292 void SkBitmap::validate() const {
   1293     fInfo.validate();
   1294 
   1295     // ImageInfo may not require this, but Bitmap ensures that opaque-only
   1296     // colorTypes report opaque for their alphatype
   1297     if (kRGB_565_SkColorType == fInfo.colorType()) {
   1298         SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
   1299     }
   1300 
   1301     SkASSERT(fInfo.validRowBytes(fRowBytes));
   1302     uint8_t allFlags = kImageIsVolatile_Flag;
   1303 #ifdef SK_BUILD_FOR_ANDROID
   1304     allFlags |= kHasHardwareMipMap_Flag;
   1305 #endif
   1306     SkASSERT((~allFlags & fFlags) == 0);
   1307     SkASSERT(fPixelLockCount >= 0);
   1308 
   1309     if (fPixels) {
   1310         SkASSERT(fPixelRef);
   1311         SkASSERT(fPixelLockCount > 0);
   1312         SkASSERT(fPixelRef->isLocked());
   1313         SkASSERT(fPixelRef->rowBytes() == fRowBytes);
   1314         SkASSERT(fPixelRefOrigin.fX >= 0);
   1315         SkASSERT(fPixelRefOrigin.fY >= 0);
   1316         SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
   1317         SkASSERT(fPixelRef->info().height() >= (int)this->height() + fPixelRefOrigin.fY);
   1318         SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
   1319     } else {
   1320         SkASSERT(NULL == fColorTable);
   1321     }
   1322 }
   1323 #endif
   1324 
   1325 #ifndef SK_IGNORE_TO_STRING
   1326 void SkBitmap::toString(SkString* str) const {
   1327 
   1328     static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
   1329         "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
   1330     };
   1331 
   1332     str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
   1333                  gColorTypeNames[this->colorType()]);
   1334 
   1335     str->append(" (");
   1336     if (this->isOpaque()) {
   1337         str->append("opaque");
   1338     } else {
   1339         str->append("transparent");
   1340     }
   1341     if (this->isImmutable()) {
   1342         str->append(", immutable");
   1343     } else {
   1344         str->append(", not-immutable");
   1345     }
   1346     str->append(")");
   1347 
   1348     SkPixelRef* pr = this->pixelRef();
   1349     if (NULL == pr) {
   1350         // show null or the explicit pixel address (rare)
   1351         str->appendf(" pixels:%p", this->getPixels());
   1352     } else {
   1353         const char* uri = pr->getURI();
   1354         if (uri) {
   1355             str->appendf(" uri:\"%s\"", uri);
   1356         } else {
   1357             str->appendf(" pixelref:%p", pr);
   1358         }
   1359     }
   1360 
   1361     str->append(")");
   1362 }
   1363 #endif
   1364 
   1365 ///////////////////////////////////////////////////////////////////////////////
   1366 
   1367 #ifdef SK_DEBUG
   1368 void SkImageInfo::validate() const {
   1369     SkASSERT(fWidth >= 0);
   1370     SkASSERT(fHeight >= 0);
   1371     SkASSERT(SkColorTypeIsValid(fColorType));
   1372     SkASSERT(SkAlphaTypeIsValid(fAlphaType));
   1373 }
   1374 #endif
   1375