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 kIgnore_SkAlphaType:
    186                     SkASSERT(fInfo.alphaType() == kIgnore_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                 base += x;
    520                 break;
    521             default:
    522                 SkDEBUGFAIL("Can't return addr for config");
    523                 base = NULL;
    524                 break;
    525         }
    526     }
    527     return base;
    528 }
    529 
    530 SkColor SkBitmap::getColor(int x, int y) const {
    531     SkASSERT((unsigned)x < (unsigned)this->width());
    532     SkASSERT((unsigned)y < (unsigned)this->height());
    533 
    534     switch (this->colorType()) {
    535         case kAlpha_8_SkColorType: {
    536             uint8_t* addr = this->getAddr8(x, y);
    537             return SkColorSetA(0, addr[0]);
    538         }
    539         case kIndex_8_SkColorType: {
    540             SkPMColor c = this->getIndex8Color(x, y);
    541             return SkUnPreMultiply::PMColorToColor(c);
    542         }
    543         case kRGB_565_SkColorType: {
    544             uint16_t* addr = this->getAddr16(x, y);
    545             return SkPixel16ToColor(addr[0]);
    546         }
    547         case kARGB_4444_SkColorType: {
    548             uint16_t* addr = this->getAddr16(x, y);
    549             SkPMColor c = SkPixel4444ToPixel32(addr[0]);
    550             return SkUnPreMultiply::PMColorToColor(c);
    551         }
    552         case kBGRA_8888_SkColorType:
    553         case kRGBA_8888_SkColorType: {
    554             uint32_t* addr = this->getAddr32(x, y);
    555             return SkUnPreMultiply::PMColorToColor(addr[0]);
    556         }
    557         default:
    558             SkASSERT(false);
    559             return 0;
    560     }
    561     SkASSERT(false);  // Not reached.
    562     return 0;
    563 }
    564 
    565 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
    566     SkAutoLockPixels alp(bm);
    567     if (!bm.getPixels()) {
    568         return false;
    569     }
    570 
    571     const int height = bm.height();
    572     const int width = bm.width();
    573 
    574     switch (bm.colorType()) {
    575         case kAlpha_8_SkColorType: {
    576             unsigned a = 0xFF;
    577             for (int y = 0; y < height; ++y) {
    578                 const uint8_t* row = bm.getAddr8(0, y);
    579                 for (int x = 0; x < width; ++x) {
    580                     a &= row[x];
    581                 }
    582                 if (0xFF != a) {
    583                     return false;
    584                 }
    585             }
    586             return true;
    587         } break;
    588         case kIndex_8_SkColorType: {
    589             SkAutoLockColors alc(bm);
    590             const SkPMColor* table = alc.colors();
    591             if (!table) {
    592                 return false;
    593             }
    594             SkPMColor c = (SkPMColor)~0;
    595             for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) {
    596                 c &= table[i];
    597             }
    598             return 0xFF == SkGetPackedA32(c);
    599         } break;
    600         case kRGB_565_SkColorType:
    601             return true;
    602             break;
    603         case kARGB_4444_SkColorType: {
    604             unsigned c = 0xFFFF;
    605             for (int y = 0; y < height; ++y) {
    606                 const SkPMColor16* row = bm.getAddr16(0, y);
    607                 for (int x = 0; x < width; ++x) {
    608                     c &= row[x];
    609                 }
    610                 if (0xF != SkGetPackedA4444(c)) {
    611                     return false;
    612                 }
    613             }
    614             return true;
    615         } break;
    616         case kBGRA_8888_SkColorType:
    617         case kRGBA_8888_SkColorType: {
    618             SkPMColor c = (SkPMColor)~0;
    619             for (int y = 0; y < height; ++y) {
    620                 const SkPMColor* row = bm.getAddr32(0, y);
    621                 for (int x = 0; x < width; ++x) {
    622                     c &= row[x];
    623                 }
    624                 if (0xFF != SkGetPackedA32(c)) {
    625                     return false;
    626                 }
    627             }
    628             return true;
    629         }
    630         default:
    631             break;
    632     }
    633     return false;
    634 }
    635 
    636 
    637 ///////////////////////////////////////////////////////////////////////////////
    638 ///////////////////////////////////////////////////////////////////////////////
    639 
    640 static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
    641     unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) |
    642                      (SkR32To4444(r) << SK_R4444_SHIFT) |
    643                      (SkG32To4444(g) << SK_G4444_SHIFT) |
    644                      (SkB32To4444(b) << SK_B4444_SHIFT);
    645     return SkToU16(pixel);
    646 }
    647 
    648 void SkBitmap::internalErase(const SkIRect& area,
    649                              U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
    650 #ifdef SK_DEBUG
    651     SkDEBUGCODE(this->validate();)
    652     SkASSERT(!area.isEmpty());
    653     {
    654         SkIRect total = { 0, 0, this->width(), this->height() };
    655         SkASSERT(total.contains(area));
    656     }
    657 #endif
    658 
    659     switch (fInfo.colorType()) {
    660         case kUnknown_SkColorType:
    661         case kIndex_8_SkColorType:
    662             return; // can't erase. Should we bzero so the memory is not uninitialized?
    663         default:
    664             break;
    665     }
    666 
    667     SkAutoLockPixels alp(*this);
    668     // perform this check after the lock call
    669     if (!this->readyToDraw()) {
    670         return;
    671     }
    672 
    673     int height = area.height();
    674     const int width = area.width();
    675     const int rowBytes = fRowBytes;
    676 
    677     switch (this->colorType()) {
    678         case kAlpha_8_SkColorType: {
    679             uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
    680             while (--height >= 0) {
    681                 memset(p, a, width);
    682                 p += rowBytes;
    683             }
    684             break;
    685         }
    686         case kARGB_4444_SkColorType:
    687         case kRGB_565_SkColorType: {
    688             uint16_t* p = this->getAddr16(area.fLeft, area.fTop);;
    689             uint16_t v;
    690 
    691             // make rgb premultiplied
    692             if (255 != a) {
    693                 r = SkAlphaMul(r, a);
    694                 g = SkAlphaMul(g, a);
    695                 b = SkAlphaMul(b, a);
    696             }
    697 
    698             if (kARGB_4444_SkColorType == this->colorType()) {
    699                 v = pack_8888_to_4444(a, r, g, b);
    700             } else {
    701                 v = SkPackRGB16(r >> (8 - SK_R16_BITS),
    702                                 g >> (8 - SK_G16_BITS),
    703                                 b >> (8 - SK_B16_BITS));
    704             }
    705             while (--height >= 0) {
    706                 sk_memset16(p, v, width);
    707                 p = (uint16_t*)((char*)p + rowBytes);
    708             }
    709             break;
    710         }
    711         case kBGRA_8888_SkColorType:
    712         case kRGBA_8888_SkColorType: {
    713             uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
    714 
    715             if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
    716                 r = SkAlphaMul(r, a);
    717                 g = SkAlphaMul(g, a);
    718                 b = SkAlphaMul(b, a);
    719             }
    720             uint32_t v = kRGBA_8888_SkColorType == this->colorType() ?
    721                          SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
    722 
    723             while (--height >= 0) {
    724                 sk_memset32(p, v, width);
    725                 p = (uint32_t*)((char*)p + rowBytes);
    726             }
    727             break;
    728         }
    729         default:
    730             return; // no change, so don't call notifyPixelsChanged()
    731     }
    732 
    733     this->notifyPixelsChanged();
    734 }
    735 
    736 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
    737     SkIRect area = { 0, 0, this->width(), this->height() };
    738     if (!area.isEmpty()) {
    739         this->internalErase(area, a, r, g, b);
    740     }
    741 }
    742 
    743 void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const {
    744     SkIRect area = { 0, 0, this->width(), this->height() };
    745     if (area.intersect(rect)) {
    746         this->internalErase(area, SkColorGetA(c), SkColorGetR(c),
    747                             SkColorGetG(c), SkColorGetB(c));
    748     }
    749 }
    750 
    751 //////////////////////////////////////////////////////////////////////////////////////
    752 //////////////////////////////////////////////////////////////////////////////////////
    753 
    754 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
    755     SkDEBUGCODE(this->validate();)
    756 
    757     if (NULL == result || NULL == fPixelRef) {
    758         return false;   // no src pixels
    759     }
    760 
    761     SkIRect srcRect, r;
    762     srcRect.set(0, 0, this->width(), this->height());
    763     if (!r.intersect(srcRect, subset)) {
    764         return false;   // r is empty (i.e. no intersection)
    765     }
    766 
    767     if (fPixelRef->getTexture() != NULL) {
    768         // Do a deep copy
    769         SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), &subset);
    770         if (pixelRef != NULL) {
    771             SkBitmap dst;
    772             dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(),
    773                                           this->colorType(), this->alphaType()));
    774             dst.setIsVolatile(this->isVolatile());
    775             dst.setPixelRef(pixelRef)->unref();
    776             SkDEBUGCODE(dst.validate());
    777             result->swap(dst);
    778             return true;
    779         }
    780     }
    781 
    782     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
    783     // exited above.
    784     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
    785     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
    786 
    787     SkBitmap dst;
    788     dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()),
    789                 this->rowBytes());
    790     dst.setIsVolatile(this->isVolatile());
    791 
    792     if (fPixelRef) {
    793         SkIPoint origin = fPixelRefOrigin;
    794         origin.fX += r.fLeft;
    795         origin.fY += r.fTop;
    796         // share the pixelref with a custom offset
    797         dst.setPixelRef(fPixelRef, origin);
    798     }
    799     SkDEBUGCODE(dst.validate();)
    800 
    801     // we know we're good, so commit to result
    802     result->swap(dst);
    803     return true;
    804 }
    805 
    806 ///////////////////////////////////////////////////////////////////////////////
    807 
    808 #include "SkCanvas.h"
    809 #include "SkPaint.h"
    810 
    811 bool SkBitmap::canCopyTo(SkColorType dstColorType) const {
    812     const SkColorType srcCT = this->colorType();
    813 
    814     if (srcCT == kUnknown_SkColorType) {
    815         return false;
    816     }
    817 
    818     bool sameConfigs = (srcCT == dstColorType);
    819     switch (dstColorType) {
    820         case kAlpha_8_SkColorType:
    821         case kRGB_565_SkColorType:
    822         case kRGBA_8888_SkColorType:
    823         case kBGRA_8888_SkColorType:
    824             break;
    825         case kIndex_8_SkColorType:
    826             if (!sameConfigs) {
    827                 return false;
    828             }
    829             break;
    830         case kARGB_4444_SkColorType:
    831             return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorType == srcCT;
    832         default:
    833             return false;
    834     }
    835     return true;
    836 }
    837 
    838 #include "SkConfig8888.h"
    839 
    840 bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
    841                           int x, int y) const {
    842     if (kUnknown_SkColorType == requestedDstInfo.colorType()) {
    843         return false;
    844     }
    845     if (NULL == dstPixels || dstRB < requestedDstInfo.minRowBytes()) {
    846         return false;
    847     }
    848     if (0 == requestedDstInfo.width() || 0 == requestedDstInfo.height()) {
    849         return false;
    850     }
    851 
    852     SkIRect srcR = SkIRect::MakeXYWH(x, y, requestedDstInfo.width(), requestedDstInfo.height());
    853     if (!srcR.intersect(0, 0, this->width(), this->height())) {
    854         return false;
    855     }
    856 
    857     // the intersect may have shrunk info's logical size
    858     const SkImageInfo dstInfo = requestedDstInfo.makeWH(srcR.width(), srcR.height());
    859 
    860     // if x or y are negative, then we have to adjust pixels
    861     if (x > 0) {
    862         x = 0;
    863     }
    864     if (y > 0) {
    865         y = 0;
    866     }
    867     // here x,y are either 0 or negative
    868     dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel());
    869 
    870     //////////////
    871 
    872     SkAutoLockPixels alp(*this);
    873 
    874     // since we don't stop creating un-pixeled devices yet, check for no pixels here
    875     if (NULL == this->getPixels()) {
    876         return false;
    877     }
    878 
    879     const SkImageInfo srcInfo = this->info().makeWH(dstInfo.width(), dstInfo.height());
    880 
    881     const void* srcPixels = this->getAddr(srcR.x(), srcR.y());
    882     return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, this->rowBytes(),
    883                                    this->getColorTable());
    884 }
    885 
    886 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
    887     if (!this->canCopyTo(dstColorType)) {
    888         return false;
    889     }
    890 
    891     // if we have a texture, first get those pixels
    892     SkBitmap tmpSrc;
    893     const SkBitmap* src = this;
    894 
    895     if (fPixelRef) {
    896         SkIRect subset;
    897         subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
    898                        fInfo.width(), fInfo.height());
    899         if (fPixelRef->readPixels(&tmpSrc, &subset)) {
    900             if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) {
    901                 // FIXME: The only meaningful implementation of readPixels
    902                 // (GrPixelRef) assumes premultiplied pixels.
    903                 return false;
    904             }
    905             SkASSERT(tmpSrc.width() == this->width());
    906             SkASSERT(tmpSrc.height() == this->height());
    907 
    908             // did we get lucky and we can just return tmpSrc?
    909             if (tmpSrc.colorType() == dstColorType && NULL == alloc) {
    910                 dst->swap(tmpSrc);
    911                 // If the result is an exact copy, clone the gen ID.
    912                 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
    913                     dst->pixelRef()->cloneGenID(*fPixelRef);
    914                 }
    915                 return true;
    916             }
    917 
    918             // fall through to the raster case
    919             src = &tmpSrc;
    920         }
    921     }
    922 
    923     // we lock this now, since we may need its colortable
    924     SkAutoLockPixels srclock(*src);
    925     if (!src->readyToDraw()) {
    926         return false;
    927     }
    928 
    929     // The only way to be readyToDraw is if fPixelRef is non NULL.
    930     SkASSERT(fPixelRef != NULL);
    931 
    932     const SkImageInfo dstInfo = src->info().makeColorType(dstColorType);
    933 
    934     SkBitmap tmpDst;
    935     if (!tmpDst.setInfo(dstInfo)) {
    936         return false;
    937     }
    938 
    939     // allocate colortable if srcConfig == kIndex8_Config
    940     SkAutoTUnref<SkColorTable> ctable;
    941     if (dstColorType == kIndex_8_SkColorType) {
    942         // TODO: can we just ref() the src colortable? Is it reentrant-safe?
    943         ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable())));
    944     }
    945     if (!tmpDst.tryAllocPixels(alloc, ctable)) {
    946         return false;
    947     }
    948 
    949     if (!tmpDst.readyToDraw()) {
    950         // allocator/lock failed
    951         return false;
    952     }
    953 
    954     // pixelRef must be non NULL or tmpDst.readyToDraw() would have
    955     // returned false.
    956     SkASSERT(tmpDst.pixelRef() != NULL);
    957 
    958     if (!src->readPixels(tmpDst.info(), tmpDst.getPixels(), tmpDst.rowBytes(), 0, 0)) {
    959         return false;
    960     }
    961 
    962     //  (for BitmapHeap) Clone the pixelref genID even though we have a new pixelref.
    963     //  The old copyTo impl did this, so we continue it for now.
    964     //
    965     //  TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be
    966     //      if (src_pixelref->info == dst_pixelref->info)
    967     //
    968     if (src->colorType() == dstColorType && tmpDst.getSize() == src->getSize()) {
    969         SkPixelRef* dstPixelRef = tmpDst.pixelRef();
    970         if (dstPixelRef->info() == fPixelRef->info()) {
    971             dstPixelRef->cloneGenID(*fPixelRef);
    972         }
    973     }
    974 
    975     dst->swap(tmpDst);
    976     return true;
    977 }
    978 
    979 bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
    980     const SkColorType dstCT = this->colorType();
    981 
    982     if (!this->canCopyTo(dstCT)) {
    983         return false;
    984     }
    985 
    986     // If we have a PixelRef, and it supports deep copy, use it.
    987     // Currently supported only by texture-backed bitmaps.
    988     if (fPixelRef) {
    989         SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, NULL);
    990         if (pixelRef) {
    991             uint32_t rowBytes;
    992             if (this->colorType() == dstCT) {
    993                 // Since there is no subset to pass to deepCopy, and deepCopy
    994                 // succeeded, the new pixel ref must be identical.
    995                 SkASSERT(fPixelRef->info() == pixelRef->info());
    996                 pixelRef->cloneGenID(*fPixelRef);
    997                 // Use the same rowBytes as the original.
    998                 rowBytes = fRowBytes;
    999             } else {
   1000                 // With the new config, an appropriate fRowBytes will be computed by setInfo.
   1001                 rowBytes = 0;
   1002             }
   1003 
   1004             const SkImageInfo info = fInfo.makeColorType(dstCT);
   1005             if (!dst->setInfo(info, rowBytes)) {
   1006                 return false;
   1007             }
   1008             dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
   1009             return true;
   1010         }
   1011     }
   1012 
   1013     if (this->getTexture()) {
   1014         return false;
   1015     } else {
   1016         return this->copyTo(dst, dstCT, NULL);
   1017     }
   1018 }
   1019 
   1020 ///////////////////////////////////////////////////////////////////////////////
   1021 
   1022 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
   1023                            int alphaRowBytes) {
   1024     SkASSERT(alpha != NULL);
   1025     SkASSERT(alphaRowBytes >= src.width());
   1026 
   1027     SkColorType colorType = src.colorType();
   1028     int         w = src.width();
   1029     int         h = src.height();
   1030     size_t      rb = src.rowBytes();
   1031 
   1032     SkAutoLockPixels alp(src);
   1033     if (!src.readyToDraw()) {
   1034         // zero out the alpha buffer and return
   1035         while (--h >= 0) {
   1036             memset(alpha, 0, w);
   1037             alpha += alphaRowBytes;
   1038         }
   1039         return false;
   1040     }
   1041 
   1042     if (kAlpha_8_SkColorType == colorType && !src.isOpaque()) {
   1043         const uint8_t* s = src.getAddr8(0, 0);
   1044         while (--h >= 0) {
   1045             memcpy(alpha, s, w);
   1046             s += rb;
   1047             alpha += alphaRowBytes;
   1048         }
   1049     } else if (kN32_SkColorType == colorType && !src.isOpaque()) {
   1050         const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
   1051         while (--h >= 0) {
   1052             for (int x = 0; x < w; x++) {
   1053                 alpha[x] = SkGetPackedA32(s[x]);
   1054             }
   1055             s = (const SkPMColor*)((const char*)s + rb);
   1056             alpha += alphaRowBytes;
   1057         }
   1058     } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) {
   1059         const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
   1060         while (--h >= 0) {
   1061             for (int x = 0; x < w; x++) {
   1062                 alpha[x] = SkPacked4444ToA32(s[x]);
   1063             }
   1064             s = (const SkPMColor16*)((const char*)s + rb);
   1065             alpha += alphaRowBytes;
   1066         }
   1067     } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) {
   1068         SkColorTable* ct = src.getColorTable();
   1069         if (ct) {
   1070             const SkPMColor* SK_RESTRICT table = ct->lockColors();
   1071             const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
   1072             while (--h >= 0) {
   1073                 for (int x = 0; x < w; x++) {
   1074                     alpha[x] = SkGetPackedA32(table[s[x]]);
   1075                 }
   1076                 s += rb;
   1077                 alpha += alphaRowBytes;
   1078             }
   1079             ct->unlockColors();
   1080         }
   1081     } else {    // src is opaque, so just fill alpha[] with 0xFF
   1082         memset(alpha, 0xFF, h * alphaRowBytes);
   1083     }
   1084     return true;
   1085 }
   1086 
   1087 #include "SkPaint.h"
   1088 #include "SkMaskFilter.h"
   1089 #include "SkMatrix.h"
   1090 
   1091 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
   1092                             Allocator *allocator, SkIPoint* offset) const {
   1093     SkDEBUGCODE(this->validate();)
   1094 
   1095     SkBitmap    tmpBitmap;
   1096     SkMatrix    identity;
   1097     SkMask      srcM, dstM;
   1098 
   1099     srcM.fBounds.set(0, 0, this->width(), this->height());
   1100     srcM.fRowBytes = SkAlign4(this->width());
   1101     srcM.fFormat = SkMask::kA8_Format;
   1102 
   1103     SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
   1104 
   1105     // compute our (larger?) dst bounds if we have a filter
   1106     if (filter) {
   1107         identity.reset();
   1108         srcM.fImage = NULL;
   1109         if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
   1110             goto NO_FILTER_CASE;
   1111         }
   1112         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
   1113     } else {
   1114     NO_FILTER_CASE:
   1115         tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
   1116         if (!tmpBitmap.tryAllocPixels(allocator, NULL)) {
   1117             // Allocation of pixels for alpha bitmap failed.
   1118             SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
   1119                     tmpBitmap.width(), tmpBitmap.height());
   1120             return false;
   1121         }
   1122         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
   1123         if (offset) {
   1124             offset->set(0, 0);
   1125         }
   1126         tmpBitmap.swap(*dst);
   1127         return true;
   1128     }
   1129     srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
   1130     SkAutoMaskFreeImage srcCleanup(srcM.fImage);
   1131 
   1132     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
   1133     if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
   1134         goto NO_FILTER_CASE;
   1135     }
   1136     SkAutoMaskFreeImage dstCleanup(dstM.fImage);
   1137 
   1138     tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
   1139                       dstM.fRowBytes);
   1140     if (!tmpBitmap.tryAllocPixels(allocator, NULL)) {
   1141         // Allocation of pixels for alpha bitmap failed.
   1142         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
   1143                 tmpBitmap.width(), tmpBitmap.height());
   1144         return false;
   1145     }
   1146     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
   1147     if (offset) {
   1148         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
   1149     }
   1150     SkDEBUGCODE(tmpBitmap.validate();)
   1151 
   1152     tmpBitmap.swap(*dst);
   1153     return true;
   1154 }
   1155 
   1156 ///////////////////////////////////////////////////////////////////////////////
   1157 
   1158 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
   1159     const SkImageInfo info = bitmap.info();
   1160     SkAutoLockPixels alp(bitmap);
   1161     if (0 == info.width() || 0 == info.height() || NULL == bitmap.getPixels()) {
   1162         buffer->writeUInt(0); // instead of snugRB, signaling no pixels
   1163         return;
   1164     }
   1165 
   1166     const size_t snugRB = info.width() * info.bytesPerPixel();
   1167     const char* src = (const char*)bitmap.getPixels();
   1168     const size_t ramRB = bitmap.rowBytes();
   1169 
   1170     buffer->write32(SkToU32(snugRB));
   1171     info.flatten(*buffer);
   1172 
   1173     const size_t size = snugRB * info.height();
   1174     SkAutoMalloc storage(size);
   1175     char* dst = (char*)storage.get();
   1176     for (int y = 0; y < info.height(); ++y) {
   1177         memcpy(dst, src, snugRB);
   1178         dst += snugRB;
   1179         src += ramRB;
   1180     }
   1181     buffer->writeByteArray(storage.get(), size);
   1182 
   1183     SkColorTable* ct = bitmap.getColorTable();
   1184     if (kIndex_8_SkColorType == info.colorType() && ct) {
   1185         buffer->writeBool(true);
   1186         ct->writeToBuffer(*buffer);
   1187     } else {
   1188         buffer->writeBool(false);
   1189     }
   1190 }
   1191 
   1192 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
   1193     const size_t snugRB = buffer->readUInt();
   1194     if (0 == snugRB) {  // no pixels
   1195         return false;
   1196     }
   1197 
   1198     SkImageInfo info;
   1199     info.unflatten(*buffer);
   1200 
   1201     // If there was an error reading "info", don't use it to compute minRowBytes()
   1202     if (!buffer->validate(true)) {
   1203         return false;
   1204     }
   1205 
   1206     const size_t ramRB = info.minRowBytes();
   1207     const int height = info.height();
   1208     const size_t snugSize = snugRB * height;
   1209     const size_t ramSize = ramRB * height;
   1210     if (!buffer->validate(snugSize <= ramSize)) {
   1211         return false;
   1212     }
   1213 
   1214     SkAutoDataUnref data(SkData::NewUninitialized(ramSize));
   1215     char* dst = (char*)data->writable_data();
   1216     buffer->readByteArray(dst, snugSize);
   1217 
   1218     if (snugSize != ramSize) {
   1219         const char* srcRow = dst + snugRB * (height - 1);
   1220         char* dstRow = dst + ramRB * (height - 1);
   1221         for (int y = height - 1; y >= 1; --y) {
   1222             memmove(dstRow, srcRow, snugRB);
   1223             srcRow -= snugRB;
   1224             dstRow -= ramRB;
   1225         }
   1226         SkASSERT(srcRow == dstRow); // first row does not need to be moved
   1227     }
   1228 
   1229     SkAutoTUnref<SkColorTable> ctable;
   1230     if (buffer->readBool()) {
   1231         ctable.reset(SkNEW_ARGS(SkColorTable, (*buffer)));
   1232     }
   1233 
   1234     SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(),
   1235                                                               ctable.get(), data.get()));
   1236     bitmap->setInfo(pr->info());
   1237     bitmap->setPixelRef(pr, 0, 0);
   1238     return true;
   1239 }
   1240 
   1241 enum {
   1242     SERIALIZE_PIXELTYPE_NONE,
   1243     SERIALIZE_PIXELTYPE_REF_DATA
   1244 };
   1245 
   1246 void SkBitmap::legacyUnflatten(SkReadBuffer& buffer) {
   1247 #ifdef SK_SUPPORT_LEGACY_PIXELREF_UNFLATTENABLE
   1248     this->reset();
   1249 
   1250     SkImageInfo info;
   1251     info.unflatten(buffer);
   1252     size_t rowBytes = buffer.readInt();
   1253     if (!buffer.validate((info.width() >= 0) && (info.height() >= 0) &&
   1254                          SkColorTypeIsValid(info.fColorType) &&
   1255                          SkAlphaTypeIsValid(info.fAlphaType) &&
   1256                          SkColorTypeValidateAlphaType(info.fColorType, info.fAlphaType) &&
   1257                          info.validRowBytes(rowBytes))) {
   1258         return;
   1259     }
   1260 
   1261     bool configIsValid = this->setInfo(info, rowBytes);
   1262     buffer.validate(configIsValid);
   1263 
   1264     int reftype = buffer.readInt();
   1265     if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) ||
   1266                         (SERIALIZE_PIXELTYPE_NONE == reftype))) {
   1267         switch (reftype) {
   1268             case SERIALIZE_PIXELTYPE_REF_DATA: {
   1269                 SkIPoint origin;
   1270                 origin.fX = buffer.readInt();
   1271                 origin.fY = buffer.readInt();
   1272                 size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel();
   1273                 SkPixelRef* pr = buffer.readFlattenable<SkPixelRef>();
   1274                 if (!buffer.validate((NULL == pr) ||
   1275                        (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) {
   1276                     origin.setZero();
   1277                 }
   1278                 SkSafeUnref(this->setPixelRef(pr, origin));
   1279                 break;
   1280             }
   1281             case SERIALIZE_PIXELTYPE_NONE:
   1282                 break;
   1283             default:
   1284                 SkDEBUGFAIL("unrecognized pixeltype in serialized data");
   1285                 sk_throw();
   1286         }
   1287     }
   1288 #else
   1289     sk_throw();
   1290 #endif
   1291 }
   1292 
   1293 ///////////////////////////////////////////////////////////////////////////////
   1294 
   1295 SkBitmap::RLEPixels::RLEPixels(int width, int height) {
   1296     fHeight = height;
   1297     fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
   1298 }
   1299 
   1300 SkBitmap::RLEPixels::~RLEPixels() {
   1301     sk_free(fYPtrs);
   1302 }
   1303 
   1304 ///////////////////////////////////////////////////////////////////////////////
   1305 
   1306 #ifdef SK_DEBUG
   1307 void SkBitmap::validate() const {
   1308     fInfo.validate();
   1309 
   1310     // ImageInfo may not require this, but Bitmap ensures that opaque-only
   1311     // colorTypes report opaque for their alphatype
   1312     if (kRGB_565_SkColorType == fInfo.colorType()) {
   1313         SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
   1314     }
   1315 
   1316     SkASSERT(fInfo.validRowBytes(fRowBytes));
   1317     uint8_t allFlags = kImageIsVolatile_Flag;
   1318 #ifdef SK_BUILD_FOR_ANDROID
   1319     allFlags |= kHasHardwareMipMap_Flag;
   1320 #endif
   1321     SkASSERT((~allFlags & fFlags) == 0);
   1322     SkASSERT(fPixelLockCount >= 0);
   1323 
   1324     if (fPixels) {
   1325         SkASSERT(fPixelRef);
   1326         SkASSERT(fPixelLockCount > 0);
   1327         SkASSERT(fPixelRef->isLocked());
   1328         SkASSERT(fPixelRef->rowBytes() == fRowBytes);
   1329         SkASSERT(fPixelRefOrigin.fX >= 0);
   1330         SkASSERT(fPixelRefOrigin.fY >= 0);
   1331         SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
   1332         SkASSERT(fPixelRef->info().height() >= (int)this->height() + fPixelRefOrigin.fY);
   1333         SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
   1334     } else {
   1335         SkASSERT(NULL == fColorTable);
   1336     }
   1337 }
   1338 #endif
   1339 
   1340 #ifndef SK_IGNORE_TO_STRING
   1341 void SkBitmap::toString(SkString* str) const {
   1342 
   1343     static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
   1344         "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
   1345     };
   1346 
   1347     str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
   1348                  gColorTypeNames[this->colorType()]);
   1349 
   1350     str->append(" (");
   1351     if (this->isOpaque()) {
   1352         str->append("opaque");
   1353     } else {
   1354         str->append("transparent");
   1355     }
   1356     if (this->isImmutable()) {
   1357         str->append(", immutable");
   1358     } else {
   1359         str->append(", not-immutable");
   1360     }
   1361     str->append(")");
   1362 
   1363     SkPixelRef* pr = this->pixelRef();
   1364     if (NULL == pr) {
   1365         // show null or the explicit pixel address (rare)
   1366         str->appendf(" pixels:%p", this->getPixels());
   1367     } else {
   1368         const char* uri = pr->getURI();
   1369         if (uri) {
   1370             str->appendf(" uri:\"%s\"", uri);
   1371         } else {
   1372             str->appendf(" pixelref:%p", pr);
   1373         }
   1374     }
   1375 
   1376     str->append(")");
   1377 }
   1378 #endif
   1379 
   1380 ///////////////////////////////////////////////////////////////////////////////
   1381 
   1382 #ifdef SK_DEBUG
   1383 void SkImageInfo::validate() const {
   1384     SkASSERT(fWidth >= 0);
   1385     SkASSERT(fHeight >= 0);
   1386     SkASSERT(SkColorTypeIsValid(fColorType));
   1387     SkASSERT(SkAlphaTypeIsValid(fAlphaType));
   1388 }
   1389 #endif
   1390