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