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 "SkColorTable.h"
     12 #include "SkConvertPixels.h"
     13 #include "SkData.h"
     14 #include "SkFilterQuality.h"
     15 #include "SkHalf.h"
     16 #include "SkImageInfoPriv.h"
     17 #include "SkMallocPixelRef.h"
     18 #include "SkMask.h"
     19 #include "SkMath.h"
     20 #include "SkPixelRef.h"
     21 #include "SkReadBuffer.h"
     22 #include "SkRect.h"
     23 #include "SkScalar.h"
     24 #include "SkTemplates.h"
     25 #include "SkUnPreMultiply.h"
     26 #include "SkWriteBuffer.h"
     27 #include "SkWritePixelsRec.h"
     28 
     29 #include <string.h>
     30 
     31 static bool reset_return_false(SkBitmap* bm) {
     32     bm->reset();
     33     return false;
     34 }
     35 
     36 SkBitmap::SkBitmap()
     37     : fPixels        (nullptr)
     38     , fPixelRefOrigin{0, 0}
     39     , fRowBytes      (0)
     40     , fFlags         (0) {}
     41 
     42 SkBitmap::SkBitmap(const SkBitmap& src)
     43     : fPixelRef      (src.fPixelRef)
     44     , fPixels        (src.fPixels)
     45     , fPixelRefOrigin(src.fPixelRefOrigin)
     46     , fInfo          (src.fInfo)
     47     , fRowBytes      (src.fRowBytes)
     48     , fFlags         (src.fFlags)
     49 {
     50     SkDEBUGCODE(src.validate();)
     51     SkDEBUGCODE(this->validate();)
     52 }
     53 
     54 SkBitmap::SkBitmap(SkBitmap&& other)
     55     : fPixelRef      (std::move(other.fPixelRef))
     56     , fPixels                  (other.fPixels)
     57     , fPixelRefOrigin          (other.fPixelRefOrigin)
     58     , fInfo          (std::move(other.fInfo))
     59     , fRowBytes                (other.fRowBytes)
     60     , fFlags                   (other.fFlags)
     61 {
     62     SkASSERT(!other.fPixelRef);
     63     other.fInfo.reset();
     64     other.fPixels         = nullptr;
     65     other.fPixelRefOrigin = SkIPoint{0, 0};
     66     other.fRowBytes       = 0;
     67     other.fFlags          = 0;
     68 }
     69 
     70 SkBitmap::~SkBitmap() {}
     71 
     72 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
     73     if (this != &src) {
     74         fPixelRef       = src.fPixelRef;
     75         fPixels         = src.fPixels;
     76         fPixelRefOrigin = src.fPixelRefOrigin;
     77         fInfo           = src.fInfo;
     78         fRowBytes       = src.fRowBytes;
     79         fFlags          = src.fFlags;
     80     }
     81     SkDEBUGCODE(this->validate();)
     82     return *this;
     83 }
     84 
     85 SkBitmap& SkBitmap::operator=(SkBitmap&& other) {
     86     if (this != &other) {
     87         fPixelRef       = std::move(other.fPixelRef);
     88         fInfo           = std::move(other.fInfo);
     89         fPixels         = other.fPixels;
     90         fPixelRefOrigin = other.fPixelRefOrigin;
     91         fRowBytes       = other.fRowBytes;
     92         fFlags          = other.fFlags;
     93         SkASSERT(!other.fPixelRef);
     94         other.fInfo.reset();
     95         other.fPixels         = nullptr;
     96         other.fPixelRefOrigin = SkIPoint{0, 0};
     97         other.fRowBytes       = 0;
     98         other.fFlags          = 0;
     99     }
    100     return *this;
    101 }
    102 
    103 void SkBitmap::swap(SkBitmap& other) {
    104     SkTSwap(*this, other);
    105     SkDEBUGCODE(this->validate();)
    106 }
    107 
    108 void SkBitmap::reset() {
    109     this->freePixels();
    110     this->fInfo.reset();
    111     sk_bzero(this, sizeof(*this));
    112 }
    113 
    114 void SkBitmap::getBounds(SkRect* bounds) const {
    115     SkASSERT(bounds);
    116     bounds->set(0, 0,
    117                 SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height()));
    118 }
    119 
    120 void SkBitmap::getBounds(SkIRect* bounds) const {
    121     SkASSERT(bounds);
    122     bounds->set(0, 0, fInfo.width(), fInfo.height());
    123 }
    124 
    125 ///////////////////////////////////////////////////////////////////////////////
    126 
    127 bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
    128     SkAlphaType newAT = info.alphaType();
    129     if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
    130         return reset_return_false(this);
    131     }
    132     // don't look at info.alphaType(), since newAT is the real value...
    133 
    134     // require that rowBytes fit in 31bits
    135     int64_t mrb = info.minRowBytes64();
    136     if ((int32_t)mrb != mrb) {
    137         return reset_return_false(this);
    138     }
    139     if ((int64_t)rowBytes != (int32_t)rowBytes) {
    140         return reset_return_false(this);
    141     }
    142 
    143     if (info.width() < 0 || info.height() < 0) {
    144         return reset_return_false(this);
    145     }
    146 
    147     if (kUnknown_SkColorType == info.colorType()) {
    148         rowBytes = 0;
    149     } else if (0 == rowBytes) {
    150         rowBytes = (size_t)mrb;
    151     } else if (!info.validRowBytes(rowBytes)) {
    152         return reset_return_false(this);
    153     }
    154 
    155     this->freePixels();
    156 
    157     fInfo = info.makeAlphaType(newAT);
    158     fRowBytes = SkToU32(rowBytes);
    159     SkDEBUGCODE(this->validate();)
    160     return true;
    161 }
    162 
    163 bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
    164     if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) {
    165         return false;
    166     }
    167     if (fInfo.alphaType() != newAlphaType) {
    168         fInfo = fInfo.makeAlphaType(newAlphaType);
    169     }
    170     SkDEBUGCODE(this->validate();)
    171     return true;
    172 }
    173 
    174 void SkBitmap::updatePixelsFromRef() {
    175     void* p = nullptr;
    176     if (fPixelRef) {
    177         // wish we could assert that a pixelref *always* has pixels
    178         p = fPixelRef->pixels();
    179         if (p) {
    180             SkASSERT(fRowBytes == fPixelRef->rowBytes());
    181             p = (char*)p
    182                 + fPixelRefOrigin.fY * fRowBytes
    183                 + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
    184         }
    185     }
    186     fPixels = p;
    187 }
    188 
    189 void SkBitmap::setPixelRef(sk_sp<SkPixelRef> pr, int dx, int dy) {
    190 #ifdef SK_DEBUG
    191     if (pr) {
    192         if (kUnknown_SkColorType != fInfo.colorType()) {
    193             SkASSERT(fInfo.width() + dx <= pr->width());
    194             SkASSERT(fInfo.height() + dy <= pr->height());
    195         }
    196     }
    197 #endif
    198 
    199     fPixelRef = std::move(pr);
    200     if (fPixelRef) {
    201         fPixelRefOrigin.set(SkTPin(dx, 0, fPixelRef->width()), SkTPin(dy, 0, fPixelRef->height()));
    202         this->updatePixelsFromRef();
    203     } else {
    204         // ignore dx,dy if there is no pixelref
    205         fPixelRefOrigin.setZero();
    206         fPixels = nullptr;
    207     }
    208 
    209     SkDEBUGCODE(this->validate();)
    210 }
    211 
    212 void SkBitmap::setPixels(void* p) {
    213     if (nullptr == p) {
    214         this->setPixelRef(nullptr, 0, 0);
    215         return;
    216     }
    217 
    218     if (kUnknown_SkColorType == fInfo.colorType()) {
    219         this->setPixelRef(nullptr, 0, 0);
    220         return;
    221     }
    222 
    223     this->setPixelRef(SkMallocPixelRef::MakeDirect(fInfo, p, fRowBytes), 0, 0);
    224     if (!fPixelRef) {
    225         return;
    226     }
    227     SkDEBUGCODE(this->validate();)
    228 }
    229 
    230 bool SkBitmap::tryAllocPixels(Allocator* allocator) {
    231     HeapAllocator stdalloc;
    232 
    233     if (nullptr == allocator) {
    234         allocator = &stdalloc;
    235     }
    236 #ifdef SK_SUPPORT_LEGACY_COLORTABLE
    237     return allocator->allocPixelRef(this, nullptr);
    238 #else
    239     return allocator->allocPixelRef(this);
    240 #endif
    241 }
    242 
    243 ///////////////////////////////////////////////////////////////////////////////
    244 
    245 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
    246     if (!this->setInfo(requestedInfo, rowBytes)) {
    247         return reset_return_false(this);
    248     }
    249 
    250     // setInfo may have corrected info (e.g. 565 is always opaque).
    251     const SkImageInfo& correctedInfo = this->info();
    252     // setInfo may have computed a valid rowbytes if 0 were passed in
    253     rowBytes = this->rowBytes();
    254 
    255     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(correctedInfo, rowBytes);
    256     if (!pr) {
    257         return reset_return_false(this);
    258     }
    259     this->setPixelRef(std::move(pr), 0, 0);
    260     if (nullptr == this->getPixels()) {
    261         return reset_return_false(this);
    262     }
    263     SkDEBUGCODE(this->validate();)
    264     return true;
    265 }
    266 
    267 bool SkBitmap::tryAllocPixelsFlags(const SkImageInfo& requestedInfo, uint32_t allocFlags) {
    268     if (!this->setInfo(requestedInfo)) {
    269         return reset_return_false(this);
    270     }
    271 
    272     // setInfo may have corrected info (e.g. 565 is always opaque).
    273     const SkImageInfo& correctedInfo = this->info();
    274 
    275     sk_sp<SkPixelRef> pr = (allocFlags & kZeroPixels_AllocFlag) ?
    276         SkMallocPixelRef::MakeZeroed(correctedInfo, correctedInfo.minRowBytes()) :
    277         SkMallocPixelRef::MakeAllocate(correctedInfo, correctedInfo.minRowBytes());
    278     if (!pr) {
    279         return reset_return_false(this);
    280     }
    281     this->setPixelRef(std::move(pr), 0, 0);
    282     if (nullptr == this->getPixels()) {
    283         return reset_return_false(this);
    284     }
    285     SkDEBUGCODE(this->validate();)
    286     return true;
    287 }
    288 
    289 static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) {
    290     if (proc) {
    291         proc(pixels, ctx);
    292     }
    293 }
    294 
    295 bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
    296                              void (*releaseProc)(void* addr, void* context), void* context) {
    297     if (!this->setInfo(requestedInfo, rb)) {
    298         invoke_release_proc(releaseProc, pixels, context);
    299         this->reset();
    300         return false;
    301     }
    302     if (nullptr == pixels) {
    303         invoke_release_proc(releaseProc, pixels, context);
    304         return true;    // we behaved as if they called setInfo()
    305     }
    306 
    307     // setInfo may have corrected info (e.g. 565 is always opaque).
    308     const SkImageInfo& correctedInfo = this->info();
    309 
    310     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeWithProc(correctedInfo, rb, pixels,
    311                                                           releaseProc, context);
    312     if (!pr) {
    313         this->reset();
    314         return false;
    315     }
    316 
    317     this->setPixelRef(std::move(pr), 0, 0);
    318     SkDEBUGCODE(this->validate();)
    319     return true;
    320 }
    321 
    322 bool SkBitmap::installPixels(const SkPixmap& pixmap) {
    323     return this->installPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(),
    324                                nullptr, nullptr);
    325 }
    326 
    327 bool SkBitmap::installMaskPixels(const SkMask& mask) {
    328     if (SkMask::kA8_Format != mask.fFormat) {
    329         this->reset();
    330         return false;
    331     }
    332     return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
    333                                                    mask.fBounds.height()),
    334                                mask.fImage, mask.fRowBytes);
    335 }
    336 
    337 ///////////////////////////////////////////////////////////////////////////////
    338 
    339 void SkBitmap::freePixels() {
    340     fPixelRef = nullptr;
    341     fPixelRefOrigin.setZero();
    342     fPixels = nullptr;
    343 }
    344 
    345 uint32_t SkBitmap::getGenerationID() const {
    346     return fPixelRef ? fPixelRef->getGenerationID() : 0;
    347 }
    348 
    349 void SkBitmap::notifyPixelsChanged() const {
    350     SkASSERT(!this->isImmutable());
    351     if (fPixelRef) {
    352         fPixelRef->notifyPixelsChanged();
    353     }
    354 }
    355 
    356 ///////////////////////////////////////////////////////////////////////////////
    357 
    358 /** We explicitly use the same allocator for our pixels that SkMask does,
    359  so that we can freely assign memory allocated by one class to the other.
    360  */
    361 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst
    362 #ifdef SK_SUPPORT_LEGACY_COLORTABLE
    363                                             , SkColorTable*
    364 #endif
    365                                             ) {
    366     const SkImageInfo info = dst->info();
    367     if (kUnknown_SkColorType == info.colorType()) {
    368 //        SkDebugf("unsupported config for info %d\n", dst->config());
    369         return false;
    370     }
    371 
    372     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, dst->rowBytes());
    373     if (!pr) {
    374         return false;
    375     }
    376 
    377     dst->setPixelRef(std::move(pr), 0, 0);
    378     SkDEBUGCODE(dst->validate();)
    379     return true;
    380 }
    381 
    382 ///////////////////////////////////////////////////////////////////////////////
    383 
    384 bool SkBitmap::isImmutable() const {
    385     return fPixelRef ? fPixelRef->isImmutable() : false;
    386 }
    387 
    388 void SkBitmap::setImmutable() {
    389     if (fPixelRef) {
    390         fPixelRef->setImmutable();
    391     }
    392 }
    393 
    394 bool SkBitmap::isVolatile() const {
    395     return (fFlags & kImageIsVolatile_Flag) != 0;
    396 }
    397 
    398 void SkBitmap::setIsVolatile(bool isVolatile) {
    399     if (isVolatile) {
    400         fFlags |= kImageIsVolatile_Flag;
    401     } else {
    402         fFlags &= ~kImageIsVolatile_Flag;
    403     }
    404 }
    405 
    406 void* SkBitmap::getAddr(int x, int y) const {
    407     SkASSERT((unsigned)x < (unsigned)this->width());
    408     SkASSERT((unsigned)y < (unsigned)this->height());
    409 
    410     char* base = (char*)this->getPixels();
    411     if (base) {
    412         base += y * this->rowBytes();
    413         switch (this->colorType()) {
    414             case kRGBA_F16_SkColorType:
    415                 base += x << 3;
    416                 break;
    417             case kRGBA_8888_SkColorType:
    418             case kBGRA_8888_SkColorType:
    419                 base += x << 2;
    420                 break;
    421             case kARGB_4444_SkColorType:
    422             case kRGB_565_SkColorType:
    423                 base += x << 1;
    424                 break;
    425             case kAlpha_8_SkColorType:
    426             case kGray_8_SkColorType:
    427                 base += x;
    428                 break;
    429             default:
    430                 SkDEBUGFAIL("Can't return addr for config");
    431                 base = nullptr;
    432                 break;
    433         }
    434     }
    435     return base;
    436 }
    437 
    438 ///////////////////////////////////////////////////////////////////////////////
    439 ///////////////////////////////////////////////////////////////////////////////
    440 
    441 void SkBitmap::erase(SkColor c, const SkIRect& area) const {
    442     SkDEBUGCODE(this->validate();)
    443 
    444     switch (fInfo.colorType()) {
    445         case kUnknown_SkColorType:
    446             // TODO: can we ASSERT that we never get here?
    447             return; // can't erase. Should we bzero so the memory is not uninitialized?
    448         default:
    449             break;
    450     }
    451 
    452     SkPixmap result;
    453     if (!this->peekPixels(&result)) {
    454         return;
    455     }
    456 
    457     if (result.erase(c, area)) {
    458         this->notifyPixelsChanged();
    459     }
    460 }
    461 
    462 void SkBitmap::eraseColor(SkColor c) const {
    463     this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
    464 }
    465 
    466 //////////////////////////////////////////////////////////////////////////////////////
    467 //////////////////////////////////////////////////////////////////////////////////////
    468 
    469 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
    470     SkDEBUGCODE(this->validate();)
    471 
    472     if (nullptr == result || !fPixelRef) {
    473         return false;   // no src pixels
    474     }
    475 
    476     SkIRect srcRect, r;
    477     srcRect.set(0, 0, this->width(), this->height());
    478     if (!r.intersect(srcRect, subset)) {
    479         return false;   // r is empty (i.e. no intersection)
    480     }
    481 
    482     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
    483     // exited above.
    484     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
    485     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
    486 
    487     SkBitmap dst;
    488     dst.setInfo(this->info().makeWH(r.width(), r.height()), this->rowBytes());
    489     dst.setIsVolatile(this->isVolatile());
    490 
    491     if (fPixelRef) {
    492         SkIPoint origin = fPixelRefOrigin;
    493         origin.fX += r.fLeft;
    494         origin.fY += r.fTop;
    495         // share the pixelref with a custom offset
    496         dst.setPixelRef(fPixelRef, origin.x(), origin.y());
    497     }
    498     SkDEBUGCODE(dst.validate();)
    499 
    500     // we know we're good, so commit to result
    501     result->swap(dst);
    502     return true;
    503 }
    504 
    505 ///////////////////////////////////////////////////////////////////////////////
    506 
    507 bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
    508                           int x, int y, SkTransferFunctionBehavior behavior) const {
    509     SkPixmap src;
    510     if (!this->peekPixels(&src)) {
    511         return false;
    512     }
    513     return src.readPixels(requestedDstInfo, dstPixels, dstRB, x, y, behavior);
    514 }
    515 
    516 bool SkBitmap::readPixels(const SkPixmap& dst, int srcX, int srcY) const {
    517     return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
    518 }
    519 
    520 bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY,
    521                            SkTransferFunctionBehavior behavior) {
    522     if (!SkImageInfoValidConversion(fInfo, src.info())) {
    523         return false;
    524     }
    525 
    526     SkWritePixelsRec rec(src.info(), src.addr(), src.rowBytes(), dstX, dstY);
    527     if (!rec.trim(fInfo.width(), fInfo.height())) {
    528         return false;
    529     }
    530 
    531     void* dstPixels = this->getAddr(rec.fX, rec.fY);
    532     const SkImageInfo dstInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height());
    533     SkConvertPixels(dstInfo, dstPixels, this->rowBytes(), rec.fInfo, rec.fPixels, rec.fRowBytes,
    534                     nullptr, behavior);
    535     return true;
    536 }
    537 
    538 ///////////////////////////////////////////////////////////////////////////////
    539 
    540 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
    541     SkASSERT(alpha != nullptr);
    542     SkASSERT(alphaRowBytes >= src.width());
    543 
    544     SkPixmap pmap;
    545     if (!src.peekPixels(&pmap)) {
    546         for (int y = 0; y < src.height(); ++y) {
    547             memset(alpha, 0, src.width());
    548             alpha += alphaRowBytes;
    549         }
    550         return false;
    551     }
    552     SkConvertPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
    553                     pmap.info(), pmap.addr(), pmap.rowBytes(), nullptr,
    554                     SkTransferFunctionBehavior::kRespect);
    555     return true;
    556 }
    557 
    558 #include "SkPaint.h"
    559 #include "SkMaskFilter.h"
    560 #include "SkMatrix.h"
    561 
    562 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
    563                             Allocator *allocator, SkIPoint* offset) const {
    564     SkDEBUGCODE(this->validate();)
    565 
    566     SkBitmap    tmpBitmap;
    567     SkMatrix    identity;
    568     SkMask      srcM, dstM;
    569 
    570     srcM.fBounds.set(0, 0, this->width(), this->height());
    571     srcM.fRowBytes = SkAlign4(this->width());
    572     srcM.fFormat = SkMask::kA8_Format;
    573 
    574     SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr;
    575 
    576     // compute our (larger?) dst bounds if we have a filter
    577     if (filter) {
    578         identity.reset();
    579         if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
    580             goto NO_FILTER_CASE;
    581         }
    582         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
    583     } else {
    584     NO_FILTER_CASE:
    585         tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
    586         if (!tmpBitmap.tryAllocPixels(allocator)) {
    587             // Allocation of pixels for alpha bitmap failed.
    588             SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
    589                     tmpBitmap.width(), tmpBitmap.height());
    590             return false;
    591         }
    592         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
    593         if (offset) {
    594             offset->set(0, 0);
    595         }
    596         tmpBitmap.swap(*dst);
    597         return true;
    598     }
    599     srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
    600     SkAutoMaskFreeImage srcCleanup(srcM.fImage);
    601 
    602     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
    603     if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
    604         goto NO_FILTER_CASE;
    605     }
    606     SkAutoMaskFreeImage dstCleanup(dstM.fImage);
    607 
    608     tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
    609                       dstM.fRowBytes);
    610     if (!tmpBitmap.tryAllocPixels(allocator)) {
    611         // Allocation of pixels for alpha bitmap failed.
    612         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
    613                 tmpBitmap.width(), tmpBitmap.height());
    614         return false;
    615     }
    616     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
    617     if (offset) {
    618         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
    619     }
    620     SkDEBUGCODE(tmpBitmap.validate();)
    621 
    622     tmpBitmap.swap(*dst);
    623     return true;
    624 }
    625 
    626 ///////////////////////////////////////////////////////////////////////////////
    627 
    628 static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) {
    629     const SkImageInfo& info = pmap.info();
    630     const size_t snugRB = info.width() * info.bytesPerPixel();
    631     const char* src = (const char*)pmap.addr();
    632     const size_t ramRB = pmap.rowBytes();
    633 
    634     buffer->write32(SkToU32(snugRB));
    635     info.flatten(*buffer);
    636 
    637     const size_t size = snugRB * info.height();
    638     SkAutoTMalloc<char> storage(size);
    639     char* dst = storage.get();
    640     for (int y = 0; y < info.height(); ++y) {
    641         memcpy(dst, src, snugRB);
    642         dst += snugRB;
    643         src += ramRB;
    644     }
    645     buffer->writeByteArray(storage.get(), size);
    646     // no colortable
    647     buffer->writeBool(false);
    648 }
    649 
    650 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
    651     const SkImageInfo info = bitmap.info();
    652     if (0 == info.width() || 0 == info.height() || bitmap.isNull()) {
    653         buffer->writeUInt(0); // instead of snugRB, signaling no pixels
    654         return;
    655     }
    656 
    657     SkPixmap result;
    658     if (!bitmap.peekPixels(&result)) {
    659         buffer->writeUInt(0); // instead of snugRB, signaling no pixels
    660         return;
    661     }
    662 
    663     write_raw_pixels(buffer, result);
    664 }
    665 
    666 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
    667     const size_t snugRB = buffer->readUInt();
    668     if (0 == snugRB) {  // no pixels
    669         return false;
    670     }
    671 
    672     SkImageInfo info;
    673     info.unflatten(*buffer);
    674 
    675     if (info.width() < 0 || info.height() < 0) {
    676         return false;
    677     }
    678 
    679     // If there was an error reading "info" or if it is bogus,
    680     // don't use it to compute minRowBytes()
    681     if (!buffer->validate(SkColorTypeValidateAlphaType(info.colorType(),
    682                                                        info.alphaType()))) {
    683         return false;
    684     }
    685 
    686     const size_t ramRB = info.minRowBytes();
    687     const int height = SkMax32(info.height(), 0);
    688     const uint64_t snugSize = sk_64_mul(snugRB, height);
    689     const uint64_t ramSize = sk_64_mul(ramRB, height);
    690     static const uint64_t max_size_t = (size_t)(-1);
    691     if (!buffer->validate((snugSize <= ramSize) && (ramSize <= max_size_t))) {
    692         return false;
    693     }
    694 
    695     sk_sp<SkData> data(SkData::MakeUninitialized(SkToSizeT(ramSize)));
    696     unsigned char* dst = (unsigned char*)data->writable_data();
    697     buffer->readByteArray(dst, SkToSizeT(snugSize));
    698 
    699     if (snugSize != ramSize) {
    700         const unsigned char* srcRow = dst + snugRB * (height - 1);
    701         unsigned char* dstRow = dst + ramRB * (height - 1);
    702         for (int y = height - 1; y >= 1; --y) {
    703             memmove(dstRow, srcRow, snugRB);
    704             srcRow -= snugRB;
    705             dstRow -= ramRB;
    706         }
    707         SkASSERT(srcRow == dstRow); // first row does not need to be moved
    708     }
    709 
    710     if (buffer->readBool()) {
    711         sk_sp<SkColorTable> ctable = SkColorTable::Create(*buffer);
    712         if (!ctable) {
    713             return false;
    714         }
    715 
    716         if (info.isEmpty()) {
    717             // require an empty ctable
    718             if (ctable->count() != 0) {
    719                 buffer->validate(false);
    720                 return false;
    721             }
    722         } else {
    723             // require a non-empty ctable
    724             if (ctable->count() == 0) {
    725                 buffer->validate(false);
    726                 return false;
    727             }
    728             unsigned char maxIndex = ctable->count() - 1;
    729             for (uint64_t i = 0; i < ramSize; ++i) {
    730                 dst[i] = SkTMin(dst[i], maxIndex);
    731             }
    732         }
    733     }
    734 
    735     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeWithData(info, info.minRowBytes(),
    736                                                           std::move(data));
    737     if (!pr) {
    738         return false;
    739     }
    740     bitmap->setInfo(info);
    741     bitmap->setPixelRef(std::move(pr), 0, 0);
    742     return true;
    743 }
    744 
    745 enum {
    746     SERIALIZE_PIXELTYPE_NONE,
    747     SERIALIZE_PIXELTYPE_REF_DATA
    748 };
    749 
    750 ///////////////////////////////////////////////////////////////////////////////
    751 
    752 #ifdef SK_DEBUG
    753 void SkBitmap::validate() const {
    754     fInfo.validate();
    755 
    756     // ImageInfo may not require this, but Bitmap ensures that opaque-only
    757     // colorTypes report opaque for their alphatype
    758     if (kRGB_565_SkColorType == fInfo.colorType()) {
    759         SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
    760     }
    761 
    762     SkASSERT(fInfo.validRowBytes(fRowBytes));
    763     uint8_t allFlags = kImageIsVolatile_Flag;
    764 #ifdef SK_BUILD_FOR_ANDROID
    765     allFlags |= kHasHardwareMipMap_Flag;
    766 #endif
    767     SkASSERT((~allFlags & fFlags) == 0);
    768 
    769     if (fPixelRef && fPixelRef->pixels()) {
    770         SkASSERT(fPixels);
    771     } else {
    772         SkASSERT(!fPixels);
    773     }
    774 
    775     if (fPixels) {
    776         SkASSERT(fPixelRef);
    777         SkASSERT(fPixelRef->rowBytes() == fRowBytes);
    778         SkASSERT(fPixelRefOrigin.fX >= 0);
    779         SkASSERT(fPixelRefOrigin.fY >= 0);
    780         SkASSERT(fPixelRef->width() >= (int)this->width() + fPixelRefOrigin.fX);
    781         SkASSERT(fPixelRef->height() >= (int)this->height() + fPixelRefOrigin.fY);
    782         SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
    783     }
    784 }
    785 #endif
    786 
    787 #ifndef SK_IGNORE_TO_STRING
    788 #include "SkString.h"
    789 void SkBitmap::toString(SkString* str) const {
    790 
    791     static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
    792         "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
    793     };
    794 
    795     str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
    796                  gColorTypeNames[this->colorType()]);
    797 
    798     str->append(" (");
    799     if (this->isOpaque()) {
    800         str->append("opaque");
    801     } else {
    802         str->append("transparent");
    803     }
    804     if (this->isImmutable()) {
    805         str->append(", immutable");
    806     } else {
    807         str->append(", not-immutable");
    808     }
    809     str->append(")");
    810 
    811     str->appendf(" pixelref:%p", this->pixelRef());
    812     str->append(")");
    813 }
    814 #endif
    815 
    816 ///////////////////////////////////////////////////////////////////////////////
    817 
    818 bool SkBitmap::peekPixels(SkPixmap* pmap) const {
    819     if (fPixels) {
    820         if (pmap) {
    821             pmap->reset(fInfo, fPixels, fRowBytes);
    822         }
    823         return true;
    824     }
    825     return false;
    826 }
    827 
    828 ///////////////////////////////////////////////////////////////////////////////
    829 
    830 #ifdef SK_DEBUG
    831 void SkImageInfo::validate() const {
    832     SkASSERT(fWidth >= 0);
    833     SkASSERT(fHeight >= 0);
    834     SkASSERT(SkColorTypeIsValid(fColorType));
    835     SkASSERT(SkAlphaTypeIsValid(fAlphaType));
    836 }
    837 #endif
    838