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