Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2006-2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "SkBitmap.h"
     18 #include "SkColorPriv.h"
     19 #include "SkDither.h"
     20 #include "SkFlattenable.h"
     21 #include "SkMallocPixelRef.h"
     22 #include "SkMask.h"
     23 #include "SkPixelRef.h"
     24 #include "SkThread.h"
     25 #include "SkUtils.h"
     26 #include "SkPackBits.h"
     27 #include <new>
     28 
     29 static bool isPos32Bits(const Sk64& value) {
     30     return !value.isNeg() && value.is32();
     31 }
     32 
     33 struct MipLevel {
     34     void*       fPixels;
     35     uint32_t    fRowBytes;
     36     uint32_t    fWidth, fHeight;
     37 };
     38 
     39 struct SkBitmap::MipMap : SkNoncopyable {
     40     int32_t fRefCnt;
     41     int     fLevelCount;
     42 //  MipLevel    fLevel[fLevelCount];
     43 //  Pixels[]
     44 
     45     static MipMap* Alloc(int levelCount, size_t pixelSize) {
     46         if (levelCount < 0) {
     47             return NULL;
     48         }
     49         Sk64 size;
     50         size.setMul(levelCount + 1, sizeof(MipLevel));
     51         size.add(sizeof(MipMap));
     52         size.add(pixelSize);
     53         if (!isPos32Bits(size)) {
     54             return NULL;
     55         }
     56         MipMap* mm = (MipMap*)sk_malloc_throw(size.get32());
     57         mm->fRefCnt = 1;
     58         mm->fLevelCount = levelCount;
     59         return mm;
     60     }
     61 
     62     const MipLevel* levels() const { return (const MipLevel*)(this + 1); }
     63     MipLevel* levels() { return (MipLevel*)(this + 1); }
     64 
     65     const void* pixels() const { return levels() + fLevelCount; }
     66     void* pixels() { return levels() + fLevelCount; }
     67 
     68     void ref() {
     69         if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) {
     70             sk_throw();
     71         }
     72     }
     73     void unref() {
     74         SkASSERT(fRefCnt > 0);
     75         if (sk_atomic_dec(&fRefCnt) == 1) {
     76             sk_free(this);
     77         }
     78     }
     79 };
     80 
     81 ///////////////////////////////////////////////////////////////////////////////
     82 ///////////////////////////////////////////////////////////////////////////////
     83 
     84 SkBitmap::SkBitmap() {
     85     sk_bzero(this, sizeof(*this));
     86 }
     87 
     88 SkBitmap::SkBitmap(const SkBitmap& src) {
     89     SkDEBUGCODE(src.validate();)
     90     sk_bzero(this, sizeof(*this));
     91     *this = src;
     92     SkDEBUGCODE(this->validate();)
     93 }
     94 
     95 SkBitmap::~SkBitmap() {
     96     SkDEBUGCODE(this->validate();)
     97     this->freePixels();
     98 }
     99 
    100 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
    101     if (this != &src) {
    102         this->freePixels();
    103         memcpy(this, &src, sizeof(src));
    104 
    105         // inc src reference counts
    106         SkSafeRef(src.fPixelRef);
    107         SkSafeRef(src.fMipMap);
    108 
    109         // we reset our locks if we get blown away
    110         fPixelLockCount = 0;
    111 
    112         /*  The src could be in 3 states
    113             1. no pixelref, in which case we just copy/ref the pixels/ctable
    114             2. unlocked pixelref, pixels/ctable should be null
    115             3. locked pixelref, we should lock the ref again ourselves
    116         */
    117         if (NULL == fPixelRef) {
    118             // leave fPixels as it is
    119             fColorTable->safeRef(); // ref the user's ctable if present
    120         } else {    // we have a pixelref, so pixels/ctable reflect it
    121             // ignore the values from the memcpy
    122             fPixels = NULL;
    123             fColorTable = NULL;
    124         }
    125     }
    126 
    127     SkDEBUGCODE(this->validate();)
    128     return *this;
    129 }
    130 
    131 void SkBitmap::swap(SkBitmap& other) {
    132     SkTSwap<SkColorTable*>(fColorTable, other.fColorTable);
    133     SkTSwap<SkPixelRef*>(fPixelRef, other.fPixelRef);
    134     SkTSwap<size_t>(fPixelRefOffset, other.fPixelRefOffset);
    135     SkTSwap<int>(fPixelLockCount, other.fPixelLockCount);
    136     SkTSwap<MipMap*>(fMipMap, other.fMipMap);
    137     SkTSwap<void*>(fPixels, other.fPixels);
    138     SkTSwap<uint32_t>(fRowBytes, other.fRowBytes);
    139     SkTSwap<uint32_t>(fWidth, other.fWidth);
    140     SkTSwap<uint32_t>(fHeight, other.fHeight);
    141     SkTSwap<uint8_t>(fConfig, other.fConfig);
    142     SkTSwap<uint8_t>(fFlags, other.fFlags);
    143     SkTSwap<uint8_t>(fBytesPerPixel, other.fBytesPerPixel);
    144 
    145     SkDEBUGCODE(this->validate();)
    146 }
    147 
    148 void SkBitmap::reset() {
    149     this->freePixels();
    150     sk_bzero(this, sizeof(*this));
    151 }
    152 
    153 int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
    154     int bpp;
    155     switch (config) {
    156         case kNo_Config:
    157         case kA1_Config:
    158             bpp = 0;   // not applicable
    159             break;
    160         case kRLE_Index8_Config:
    161         case kA8_Config:
    162         case kIndex8_Config:
    163             bpp = 1;
    164             break;
    165         case kRGB_565_Config:
    166         case kARGB_4444_Config:
    167             bpp = 2;
    168             break;
    169         case kARGB_8888_Config:
    170             bpp = 4;
    171             break;
    172         default:
    173             SkASSERT(!"unknown config");
    174             bpp = 0;   // error
    175             break;
    176     }
    177     return bpp;
    178 }
    179 
    180 int SkBitmap::ComputeRowBytes(Config c, int width) {
    181     if (width < 0) {
    182         return 0;
    183     }
    184 
    185     Sk64 rowBytes;
    186     rowBytes.setZero();
    187 
    188     switch (c) {
    189         case kNo_Config:
    190         case kRLE_Index8_Config:
    191             break;
    192         case kA1_Config:
    193             rowBytes.set(width);
    194             rowBytes.add(7);
    195             rowBytes.shiftRight(3);
    196             break;
    197         case kA8_Config:
    198         case kIndex8_Config:
    199             rowBytes.set(width);
    200             break;
    201         case kRGB_565_Config:
    202         case kARGB_4444_Config:
    203             rowBytes.set(width);
    204             rowBytes.shiftLeft(1);
    205             break;
    206         case kARGB_8888_Config:
    207             rowBytes.set(width);
    208             rowBytes.shiftLeft(2);
    209             break;
    210         default:
    211             SkASSERT(!"unknown config");
    212             break;
    213     }
    214     return isPos32Bits(rowBytes) ? rowBytes.get32() : 0;
    215 }
    216 
    217 Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) {
    218     Sk64 size;
    219     size.setMul(SkBitmap::ComputeRowBytes(c, width), height);
    220     return size;
    221 }
    222 
    223 size_t SkBitmap::ComputeSize(Config c, int width, int height) {
    224     Sk64 size = SkBitmap::ComputeSize64(c, width, height);
    225     return isPos32Bits(size) ? size.get32() : 0;
    226 }
    227 
    228 void SkBitmap::setConfig(Config c, int width, int height, int rowBytes) {
    229     this->freePixels();
    230 
    231     if ((width | height | rowBytes) < 0) {
    232         goto err;
    233     }
    234 
    235     if (rowBytes == 0) {
    236         rowBytes = SkBitmap::ComputeRowBytes(c, width);
    237         if (0 == rowBytes && kNo_Config != c) {
    238             goto err;
    239         }
    240     }
    241 
    242     fConfig     = SkToU8(c);
    243     fWidth      = width;
    244     fHeight     = height;
    245     fRowBytes   = rowBytes;
    246 
    247     fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c);
    248 
    249     SkDEBUGCODE(this->validate();)
    250     return;
    251 
    252     // if we got here, we had an error, so we reset the bitmap to empty
    253 err:
    254     this->reset();
    255 }
    256 
    257 void SkBitmap::updatePixelsFromRef() const {
    258     if (NULL != fPixelRef) {
    259         if (fPixelLockCount > 0) {
    260             SkASSERT(fPixelRef->getLockCount() > 0);
    261 
    262             void* p = fPixelRef->pixels();
    263             if (NULL != p) {
    264                 p = (char*)p + fPixelRefOffset;
    265             }
    266             fPixels = p;
    267             SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable());
    268         } else {
    269             SkASSERT(0 == fPixelLockCount);
    270             fPixels = NULL;
    271             if (fColorTable) {
    272                 fColorTable->unref();
    273                 fColorTable = NULL;
    274             }
    275         }
    276     }
    277 }
    278 
    279 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) {
    280     // do this first, we that we never have a non-zero offset with a null ref
    281     if (NULL == pr) {
    282         offset = 0;
    283     }
    284 
    285     if (fPixelRef != pr || fPixelRefOffset != offset) {
    286         if (fPixelRef != pr) {
    287             this->freePixels();
    288             SkASSERT(NULL == fPixelRef);
    289 
    290             pr->safeRef();
    291             fPixelRef = pr;
    292         }
    293         fPixelRefOffset = offset;
    294         this->updatePixelsFromRef();
    295     }
    296 
    297     SkDEBUGCODE(this->validate();)
    298     return pr;
    299 }
    300 
    301 void SkBitmap::lockPixels() const {
    302     if (NULL != fPixelRef && 1 == ++fPixelLockCount) {
    303         fPixelRef->lockPixels();
    304         this->updatePixelsFromRef();
    305     }
    306     SkDEBUGCODE(this->validate();)
    307 }
    308 
    309 void SkBitmap::unlockPixels() const {
    310     SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
    311 
    312     if (NULL != fPixelRef && 0 == --fPixelLockCount) {
    313         fPixelRef->unlockPixels();
    314         this->updatePixelsFromRef();
    315     }
    316     SkDEBUGCODE(this->validate();)
    317 }
    318 
    319 void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
    320     this->freePixels();
    321     fPixels = p;
    322     SkRefCnt_SafeAssign(fColorTable, ctable);
    323 
    324     SkDEBUGCODE(this->validate();)
    325 }
    326 
    327 bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
    328     HeapAllocator stdalloc;
    329 
    330     if (NULL == allocator) {
    331         allocator = &stdalloc;
    332     }
    333     return allocator->allocPixelRef(this, ctable);
    334 }
    335 
    336 void SkBitmap::freePixels() {
    337     // if we're gonna free the pixels, we certainly need to free the mipmap
    338     this->freeMipMap();
    339 
    340     if (fColorTable) {
    341         fColorTable->unref();
    342         fColorTable = NULL;
    343     }
    344 
    345     if (NULL != fPixelRef) {
    346         if (fPixelLockCount > 0) {
    347             fPixelRef->unlockPixels();
    348         }
    349         fPixelRef->unref();
    350         fPixelRef = NULL;
    351         fPixelRefOffset = 0;
    352     }
    353     fPixelLockCount = 0;
    354     fPixels = NULL;
    355 }
    356 
    357 void SkBitmap::freeMipMap() {
    358     if (fMipMap) {
    359         fMipMap->unref();
    360         fMipMap = NULL;
    361     }
    362 }
    363 
    364 uint32_t SkBitmap::getGenerationID() const {
    365     return fPixelRef ? fPixelRef->getGenerationID() : 0;
    366 }
    367 
    368 void SkBitmap::notifyPixelsChanged() const {
    369     if (fPixelRef) {
    370         fPixelRef->notifyPixelsChanged();
    371     }
    372 }
    373 
    374 ///////////////////////////////////////////////////////////////////////////////
    375 
    376 SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
    377                                    SkColorTable* ctable) {
    378     SkASSERT(storage);
    379     fStorage = storage;
    380     fSize = size;
    381     fCTable = ctable;
    382     ctable->safeRef();
    383 }
    384 
    385 SkMallocPixelRef::~SkMallocPixelRef() {
    386     SkSafeUnref(fCTable);
    387     sk_free(fStorage);
    388 }
    389 
    390 void* SkMallocPixelRef::onLockPixels(SkColorTable** ct) {
    391     *ct = fCTable;
    392     return fStorage;
    393 }
    394 
    395 void SkMallocPixelRef::onUnlockPixels() {
    396     // nothing to do
    397 }
    398 
    399 void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
    400     this->INHERITED::flatten(buffer);
    401 
    402     buffer.write32(fSize);
    403     buffer.writePad(fStorage, fSize);
    404     if (fCTable) {
    405         buffer.writeBool(true);
    406         fCTable->flatten(buffer);
    407     } else {
    408         buffer.writeBool(false);
    409     }
    410 }
    411 
    412 SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer) : INHERITED(buffer, NULL) {
    413     fSize = buffer.readU32();
    414     fStorage = sk_malloc_throw(fSize);
    415     buffer.read(fStorage, fSize);
    416     if (buffer.readBool()) {
    417         fCTable = SkNEW_ARGS(SkColorTable, (buffer));
    418     } else {
    419         fCTable = NULL;
    420     }
    421 }
    422 
    423 static SkPixelRef::Registrar reg("SkMallocPixelRef",
    424                                  SkMallocPixelRef::Create);
    425 
    426 /** We explicitly use the same allocator for our pixels that SkMask does,
    427  so that we can freely assign memory allocated by one class to the other.
    428  */
    429 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
    430                                             SkColorTable* ctable) {
    431     Sk64 size = dst->getSize64();
    432     if (size.isNeg() || !size.is32()) {
    433         return false;
    434     }
    435 
    436     void* addr = sk_malloc_flags(size.get32(), 0);  // returns NULL on failure
    437     if (NULL == addr) {
    438         return false;
    439     }
    440 
    441     dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref();
    442     // since we're already allocated, we lockPixels right away
    443     dst->lockPixels();
    444     return true;
    445 }
    446 
    447 ///////////////////////////////////////////////////////////////////////////////
    448 
    449 bool SkBitmap::isOpaque() const {
    450     switch (fConfig) {
    451         case kNo_Config:
    452             return true;
    453 
    454         case kA1_Config:
    455         case kA8_Config:
    456         case kARGB_4444_Config:
    457         case kARGB_8888_Config:
    458             return (fFlags & kImageIsOpaque_Flag) != 0;
    459 
    460         case kIndex8_Config:
    461         case kRLE_Index8_Config: {
    462                 uint32_t flags = 0;
    463 
    464                 this->lockPixels();
    465                 // if lockPixels failed, we may not have a ctable ptr
    466                 if (fColorTable) {
    467                     flags = fColorTable->getFlags();
    468                 }
    469                 this->unlockPixels();
    470 
    471                 return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0;
    472             }
    473 
    474         case kRGB_565_Config:
    475             return true;
    476 
    477         default:
    478             SkASSERT(!"unknown bitmap config pased to isOpaque");
    479             return false;
    480     }
    481 }
    482 
    483 void SkBitmap::setIsOpaque(bool isOpaque) {
    484     /*  we record this regardless of fConfig, though it is ignored in
    485         isOpaque() for configs that can't support per-pixel alpha.
    486     */
    487     if (isOpaque) {
    488         fFlags |= kImageIsOpaque_Flag;
    489     } else {
    490         fFlags &= ~kImageIsOpaque_Flag;
    491     }
    492 }
    493 
    494 void* SkBitmap::getAddr(int x, int y) const {
    495     SkASSERT((unsigned)x < (unsigned)this->width());
    496     SkASSERT((unsigned)y < (unsigned)this->height());
    497 
    498     char* base = (char*)this->getPixels();
    499     if (base) {
    500         base += y * this->rowBytes();
    501         switch (this->config()) {
    502             case SkBitmap::kARGB_8888_Config:
    503                 base += x << 2;
    504                 break;
    505             case SkBitmap::kARGB_4444_Config:
    506             case SkBitmap::kRGB_565_Config:
    507                 base += x << 1;
    508                 break;
    509             case SkBitmap::kA8_Config:
    510             case SkBitmap::kIndex8_Config:
    511                 base += x;
    512                 break;
    513             case SkBitmap::kA1_Config:
    514                 base += x >> 3;
    515                 break;
    516             case kRLE_Index8_Config:
    517                 SkASSERT(!"Can't return addr for kRLE_Index8_Config");
    518                 base = NULL;
    519                 break;
    520             default:
    521                 SkASSERT(!"Can't return addr for config");
    522                 base = NULL;
    523                 break;
    524         }
    525     }
    526     return base;
    527 }
    528 
    529 ///////////////////////////////////////////////////////////////////////////////
    530 ///////////////////////////////////////////////////////////////////////////////
    531 
    532 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
    533     SkDEBUGCODE(this->validate();)
    534 
    535     if (0 == fWidth || 0 == fHeight ||
    536             kNo_Config == fConfig || kIndex8_Config == fConfig) {
    537         return;
    538     }
    539 
    540     SkAutoLockPixels alp(*this);
    541     // perform this check after the lock call
    542     if (!this->readyToDraw()) {
    543         return;
    544     }
    545 
    546     int height = fHeight;
    547     const int width = fWidth;
    548     const int rowBytes = fRowBytes;
    549 
    550     // make rgb premultiplied
    551     if (255 != a) {
    552         r = SkAlphaMul(r, a);
    553         g = SkAlphaMul(g, a);
    554         b = SkAlphaMul(b, a);
    555     }
    556 
    557     switch (fConfig) {
    558         case kA1_Config: {
    559             uint8_t* p = (uint8_t*)fPixels;
    560             const int count = (width + 7) >> 3;
    561             a = (a >> 7) ? 0xFF : 0;
    562             SkASSERT(count <= rowBytes);
    563             while (--height >= 0) {
    564                 memset(p, a, count);
    565                 p += rowBytes;
    566             }
    567             break;
    568         }
    569         case kA8_Config: {
    570             uint8_t* p = (uint8_t*)fPixels;
    571             while (--height >= 0) {
    572                 memset(p, a, width);
    573                 p += rowBytes;
    574             }
    575             break;
    576         }
    577         case kARGB_4444_Config:
    578         case kRGB_565_Config: {
    579             uint16_t* p = (uint16_t*)fPixels;
    580             uint16_t v;
    581 
    582             if (kARGB_4444_Config == fConfig) {
    583                 v = SkPackARGB4444(a >> 4, r >> 4, g >> 4, b >> 4);
    584             } else {    // kRGB_565_Config
    585                 v = SkPackRGB16(r >> (8 - SK_R16_BITS), g >> (8 - SK_G16_BITS),
    586                                 b >> (8 - SK_B16_BITS));
    587             }
    588             while (--height >= 0) {
    589                 sk_memset16(p, v, width);
    590                 p = (uint16_t*)((char*)p + rowBytes);
    591             }
    592             break;
    593         }
    594         case kARGB_8888_Config: {
    595             uint32_t* p = (uint32_t*)fPixels;
    596             uint32_t  v = SkPackARGB32(a, r, g, b);
    597 
    598             while (--height >= 0) {
    599                 sk_memset32(p, v, width);
    600                 p = (uint32_t*)((char*)p + rowBytes);
    601             }
    602             break;
    603         }
    604     }
    605 
    606     this->notifyPixelsChanged();
    607 }
    608 
    609 //////////////////////////////////////////////////////////////////////////////////////
    610 //////////////////////////////////////////////////////////////////////////////////////
    611 
    612 #define SUB_OFFSET_FAILURE  ((size_t)-1)
    613 
    614 static size_t getSubOffset(const SkBitmap& bm, int x, int y) {
    615     SkASSERT((unsigned)x < (unsigned)bm.width());
    616     SkASSERT((unsigned)y < (unsigned)bm.height());
    617 
    618     switch (bm.getConfig()) {
    619         case SkBitmap::kA8_Config:
    620         case SkBitmap:: kIndex8_Config:
    621             // x is fine as is for the calculation
    622             break;
    623 
    624         case SkBitmap::kRGB_565_Config:
    625         case SkBitmap::kARGB_4444_Config:
    626             x <<= 1;
    627             break;
    628 
    629         case SkBitmap::kARGB_8888_Config:
    630             x <<= 2;
    631             break;
    632 
    633         case SkBitmap::kNo_Config:
    634         case SkBitmap::kA1_Config:
    635         default:
    636             return SUB_OFFSET_FAILURE;
    637     }
    638     return y * bm.rowBytes() + x;
    639 }
    640 
    641 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
    642     SkDEBUGCODE(this->validate();)
    643 
    644     if (NULL == result || (NULL == fPixelRef && NULL == fPixels)) {
    645         return false;   // no src pixels
    646     }
    647 
    648     SkIRect srcRect, r;
    649     srcRect.set(0, 0, this->width(), this->height());
    650     if (!r.intersect(srcRect, subset)) {
    651         return false;   // r is empty (i.e. no intersection)
    652     }
    653 
    654     if (kRLE_Index8_Config == fConfig) {
    655         SkAutoLockPixels alp(*this);
    656         // don't call readyToDraw(), since we can operate w/o a colortable
    657         // at this stage
    658         if (this->getPixels() == NULL) {
    659             return false;
    660         }
    661         SkBitmap bm;
    662 
    663         bm.setConfig(kIndex8_Config, r.width(), r.height());
    664         bm.allocPixels(this->getColorTable());
    665         if (NULL == bm.getPixels()) {
    666             return false;
    667         }
    668 
    669         const RLEPixels* rle = (const RLEPixels*)this->getPixels();
    670         uint8_t* dst = bm.getAddr8(0, 0);
    671         const int width = bm.width();
    672         const int rowBytes = bm.rowBytes();
    673 
    674         for (int y = r.fTop; y < r.fBottom; y++) {
    675             SkPackBits::Unpack8(dst, r.fLeft, width, rle->packedAtY(y));
    676             dst += rowBytes;
    677         }
    678         result->swap(bm);
    679         return true;
    680     }
    681 
    682     size_t offset = getSubOffset(*this, r.fLeft, r.fTop);
    683     if (SUB_OFFSET_FAILURE == offset) {
    684         return false;   // config not supported
    685     }
    686 
    687     SkBitmap dst;
    688     dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes());
    689 
    690     if (fPixelRef) {
    691         // share the pixelref with a custom offset
    692         dst.setPixelRef(fPixelRef, fPixelRefOffset + offset);
    693     } else {
    694         // share the pixels (owned by the caller)
    695         dst.setPixels((char*)fPixels + offset, this->getColorTable());
    696     }
    697     SkDEBUGCODE(dst.validate();)
    698 
    699     // we know we're good, so commit to result
    700     result->swap(dst);
    701     return true;
    702 }
    703 
    704 ///////////////////////////////////////////////////////////////////////////////
    705 
    706 #include "SkCanvas.h"
    707 #include "SkPaint.h"
    708 
    709 bool SkBitmap::canCopyTo(Config dstConfig) const {
    710     if (this->getConfig() == kNo_Config) {
    711         return false;
    712     }
    713 
    714     bool sameConfigs = (this->config() == dstConfig);
    715     switch (dstConfig) {
    716         case kA8_Config:
    717         case kARGB_4444_Config:
    718         case kRGB_565_Config:
    719         case kARGB_8888_Config:
    720             break;
    721         case kA1_Config:
    722         case kIndex8_Config:
    723             if (!sameConfigs) {
    724                 return false;
    725             }
    726             break;
    727         default:
    728             return false;
    729     }
    730 
    731     // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config
    732     if (this->getConfig() == kA1_Config && !sameConfigs) {
    733         return false;
    734     }
    735 
    736     return true;
    737 }
    738 
    739 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
    740     if (!this->canCopyTo(dstConfig)) {
    741         return false;
    742     }
    743 
    744     // we lock this now, since we may need its colortable
    745     SkAutoLockPixels srclock(*this);
    746     if (!this->readyToDraw()) {
    747         return false;
    748     }
    749 
    750     SkBitmap tmp;
    751     tmp.setConfig(dstConfig, this->width(), this->height());
    752 
    753     // allocate colortable if srcConfig == kIndex8_Config
    754     SkColorTable* ctable = (dstConfig == kIndex8_Config) ?
    755         new SkColorTable(*this->getColorTable()) : NULL;
    756     SkAutoUnref au(ctable);
    757     if (!tmp.allocPixels(alloc, ctable)) {
    758         return false;
    759     }
    760 
    761     SkAutoLockPixels dstlock(tmp);
    762     if (!tmp.readyToDraw()) {
    763         // allocator/lock failed
    764         return false;
    765     }
    766 
    767     /* do memcpy for the same configs cases, else use drawing
    768     */
    769     if (this->config() == dstConfig) {
    770         if (tmp.getSize() == this->getSize()) {
    771             memcpy(tmp.getPixels(), this->getPixels(), this->getSize());
    772         } else {
    773             const char* srcP = reinterpret_cast<const char*>(this->getPixels());
    774             char* dstP = reinterpret_cast<char*>(tmp.getPixels());
    775             // to be sure we don't read too much, only copy our logical pixels
    776             size_t bytesToCopy = tmp.width() * tmp.bytesPerPixel();
    777             for (int y = 0; y < tmp.height(); y++) {
    778                 memcpy(dstP, srcP, bytesToCopy);
    779                 srcP += this->rowBytes();
    780                 dstP += tmp.rowBytes();
    781             }
    782         }
    783     } else {
    784         // if the src has alpha, we have to clear the dst first
    785         if (!this->isOpaque()) {
    786             tmp.eraseColor(0);
    787         }
    788 
    789         SkCanvas canvas(tmp);
    790         SkPaint  paint;
    791 
    792         paint.setDither(true);
    793         canvas.drawBitmap(*this, 0, 0, &paint);
    794     }
    795 
    796     tmp.setIsOpaque(this->isOpaque());
    797 
    798     dst->swap(tmp);
    799     return true;
    800 }
    801 
    802 ///////////////////////////////////////////////////////////////////////////////
    803 ///////////////////////////////////////////////////////////////////////////////
    804 
    805 static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
    806                                  const SkBitmap& src) {
    807     x <<= 1;
    808     y <<= 1;
    809     const SkPMColor* p = src.getAddr32(x, y);
    810     const SkPMColor* baseP = p;
    811     SkPMColor c, ag, rb;
    812 
    813     c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
    814     if (x < src.width() - 1) {
    815         p += 1;
    816     }
    817     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
    818 
    819     p = baseP;
    820     if (y < src.height() - 1) {
    821         p += src.rowBytes() >> 2;
    822     }
    823     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
    824     if (x < src.width() - 1) {
    825         p += 1;
    826     }
    827     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
    828 
    829     *dst->getAddr32(x >> 1, y >> 1) =
    830         ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
    831 }
    832 
    833 static inline uint32_t expand16(U16CPU c) {
    834     return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
    835 }
    836 
    837 // returns dirt in the top 16bits, but we don't care, since we only
    838 // store the low 16bits.
    839 static inline U16CPU pack16(uint32_t c) {
    840     return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
    841 }
    842 
    843 static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
    844                                  const SkBitmap& src) {
    845     x <<= 1;
    846     y <<= 1;
    847     const uint16_t* p = src.getAddr16(x, y);
    848     const uint16_t* baseP = p;
    849     SkPMColor       c;
    850 
    851     c = expand16(*p);
    852     if (x < src.width() - 1) {
    853         p += 1;
    854     }
    855     c += expand16(*p);
    856 
    857     p = baseP;
    858     if (y < src.height() - 1) {
    859         p += src.rowBytes() >> 1;
    860     }
    861     c += expand16(*p);
    862     if (x < src.width() - 1) {
    863         p += 1;
    864     }
    865     c += expand16(*p);
    866 
    867     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
    868 }
    869 
    870 static uint32_t expand4444(U16CPU c) {
    871     return (c & 0xF0F) | ((c & ~0xF0F) << 12);
    872 }
    873 
    874 static U16CPU collaps4444(uint32_t c) {
    875     return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
    876 }
    877 
    878 static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
    879                                    const SkBitmap& src) {
    880     x <<= 1;
    881     y <<= 1;
    882     const uint16_t* p = src.getAddr16(x, y);
    883     const uint16_t* baseP = p;
    884     uint32_t        c;
    885 
    886     c = expand4444(*p);
    887     if (x < src.width() - 1) {
    888         p += 1;
    889     }
    890     c += expand4444(*p);
    891 
    892     p = baseP;
    893     if (y < src.height() - 1) {
    894         p += src.rowBytes() >> 1;
    895     }
    896     c += expand4444(*p);
    897     if (x < src.width() - 1) {
    898         p += 1;
    899     }
    900     c += expand4444(*p);
    901 
    902     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
    903 }
    904 
    905 void SkBitmap::buildMipMap(bool forceRebuild) {
    906     if (forceRebuild)
    907         this->freeMipMap();
    908     else if (fMipMap)
    909         return; // we're already built
    910 
    911     SkASSERT(NULL == fMipMap);
    912 
    913     void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
    914 
    915     const SkBitmap::Config config = this->getConfig();
    916 
    917     switch (config) {
    918         case kARGB_8888_Config:
    919             proc = downsampleby2_proc32;
    920             break;
    921         case kRGB_565_Config:
    922             proc = downsampleby2_proc16;
    923             break;
    924         case kARGB_4444_Config:
    925             proc = downsampleby2_proc4444;
    926             break;
    927         case kIndex8_Config:
    928         case kA8_Config:
    929         default:
    930             return; // don't build mipmaps for these configs
    931     }
    932 
    933     SkAutoLockPixels alp(*this);
    934     if (!this->readyToDraw()) {
    935         return;
    936     }
    937 
    938     // whip through our loop to compute the exact size needed
    939     size_t  size = 0;
    940     int     maxLevels = 0;
    941     {
    942         int width = this->width();
    943         int height = this->height();
    944         for (;;) {
    945             width >>= 1;
    946             height >>= 1;
    947             if (0 == width || 0 == height) {
    948                 break;
    949             }
    950             size += ComputeRowBytes(config, width) * height;
    951             maxLevels += 1;
    952         }
    953     }
    954 
    955     // nothing to build
    956     if (0 == maxLevels) {
    957         return;
    958     }
    959 
    960     SkBitmap srcBM(*this);
    961     srcBM.lockPixels();
    962     if (!srcBM.readyToDraw()) {
    963         return;
    964     }
    965 
    966     MipMap* mm = MipMap::Alloc(maxLevels, size);
    967     if (NULL == mm) {
    968         return;
    969     }
    970 
    971     MipLevel*   level = mm->levels();
    972     uint8_t*    addr = (uint8_t*)mm->pixels();
    973     int         width = this->width();
    974     int         height = this->height();
    975     unsigned    rowBytes = this->rowBytes();
    976     SkBitmap    dstBM;
    977 
    978     for (int i = 0; i < maxLevels; i++) {
    979         width >>= 1;
    980         height >>= 1;
    981         rowBytes = ComputeRowBytes(config, width);
    982 
    983         level[i].fPixels   = addr;
    984         level[i].fWidth    = width;
    985         level[i].fHeight   = height;
    986         level[i].fRowBytes = rowBytes;
    987 
    988         dstBM.setConfig(config, width, height, rowBytes);
    989         dstBM.setPixels(addr);
    990 
    991         for (int y = 0; y < height; y++) {
    992             for (int x = 0; x < width; x++) {
    993                 proc(&dstBM, x, y, srcBM);
    994             }
    995         }
    996 
    997         srcBM = dstBM;
    998         addr += height * rowBytes;
    999     }
   1000     SkASSERT(addr == (uint8_t*)mm->pixels() + size);
   1001     fMipMap = mm;
   1002 }
   1003 
   1004 bool SkBitmap::hasMipMap() const {
   1005     return fMipMap != NULL;
   1006 }
   1007 
   1008 int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
   1009     if (NULL == fMipMap) {
   1010         return 0;
   1011     }
   1012 
   1013     int level = ComputeMipLevel(sx, sy) >> 16;
   1014     SkASSERT(level >= 0);
   1015     if (level <= 0) {
   1016         return 0;
   1017     }
   1018 
   1019     if (level >= fMipMap->fLevelCount) {
   1020         level = fMipMap->fLevelCount - 1;
   1021     }
   1022     if (dst) {
   1023         const MipLevel& mip = fMipMap->levels()[level - 1];
   1024         dst->setConfig((SkBitmap::Config)this->config(),
   1025                        mip.fWidth, mip.fHeight, mip.fRowBytes);
   1026         dst->setPixels(mip.fPixels);
   1027     }
   1028     return level;
   1029 }
   1030 
   1031 SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
   1032     sx = SkAbs32(sx);
   1033     sy = SkAbs32(sy);
   1034     if (sx < sy) {
   1035         sx = sy;
   1036     }
   1037     if (sx < SK_Fixed1) {
   1038         return 0;
   1039     }
   1040     int clz = SkCLZ(sx);
   1041     SkASSERT(clz >= 1 && clz <= 15);
   1042     return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
   1043 }
   1044 
   1045 ///////////////////////////////////////////////////////////////////////////////
   1046 
   1047 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t SK_RESTRICT alpha[],
   1048                            int alphaRowBytes) {
   1049     SkASSERT(alpha != NULL);
   1050     SkASSERT(alphaRowBytes >= src.width());
   1051 
   1052     SkBitmap::Config config = src.getConfig();
   1053     int              w = src.width();
   1054     int              h = src.height();
   1055     int              rb = src.rowBytes();
   1056 
   1057     SkAutoLockPixels alp(src);
   1058     if (!src.readyToDraw()) {
   1059         // zero out the alpha buffer and return
   1060         while (--h >= 0) {
   1061             memset(alpha, 0, w);
   1062             alpha += alphaRowBytes;
   1063         }
   1064         return false;
   1065     }
   1066 
   1067     if (SkBitmap::kA8_Config == config && !src.isOpaque()) {
   1068         const uint8_t* s = src.getAddr8(0, 0);
   1069         while (--h >= 0) {
   1070             memcpy(alpha, s, w);
   1071             s += rb;
   1072             alpha += alphaRowBytes;
   1073         }
   1074     } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) {
   1075         const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
   1076         while (--h >= 0) {
   1077             for (int x = 0; x < w; x++) {
   1078                 alpha[x] = SkGetPackedA32(s[x]);
   1079             }
   1080             s = (const SkPMColor*)((const char*)s + rb);
   1081             alpha += alphaRowBytes;
   1082         }
   1083     } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) {
   1084         const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
   1085         while (--h >= 0) {
   1086             for (int x = 0; x < w; x++) {
   1087                 alpha[x] = SkPacked4444ToA32(s[x]);
   1088             }
   1089             s = (const SkPMColor16*)((const char*)s + rb);
   1090             alpha += alphaRowBytes;
   1091         }
   1092     } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) {
   1093         SkColorTable* ct = src.getColorTable();
   1094         if (ct) {
   1095             const SkPMColor* SK_RESTRICT table = ct->lockColors();
   1096             const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
   1097             while (--h >= 0) {
   1098                 for (int x = 0; x < w; x++) {
   1099                     alpha[x] = SkGetPackedA32(table[s[x]]);
   1100                 }
   1101                 s += rb;
   1102                 alpha += alphaRowBytes;
   1103             }
   1104             ct->unlockColors(false);
   1105         }
   1106     } else {    // src is opaque, so just fill alpha[] with 0xFF
   1107         memset(alpha, 0xFF, h * alphaRowBytes);
   1108     }
   1109     return true;
   1110 }
   1111 
   1112 #include "SkPaint.h"
   1113 #include "SkMaskFilter.h"
   1114 #include "SkMatrix.h"
   1115 
   1116 void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
   1117                             SkIPoint* offset) const {
   1118     SkDEBUGCODE(this->validate();)
   1119 
   1120     SkMatrix    identity;
   1121     SkMask      srcM, dstM;
   1122 
   1123     srcM.fBounds.set(0, 0, this->width(), this->height());
   1124     srcM.fRowBytes = SkAlign4(this->width());
   1125     srcM.fFormat = SkMask::kA8_Format;
   1126 
   1127     SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
   1128 
   1129     // compute our (larger?) dst bounds if we have a filter
   1130     if (NULL != filter) {
   1131         identity.reset();
   1132         srcM.fImage = NULL;
   1133         if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
   1134             goto NO_FILTER_CASE;
   1135         }
   1136         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
   1137     } else {
   1138     NO_FILTER_CASE:
   1139         dst->setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
   1140                        srcM.fRowBytes);
   1141         dst->allocPixels();
   1142         GetBitmapAlpha(*this, dst->getAddr8(0, 0), srcM.fRowBytes);
   1143         if (offset) {
   1144             offset->set(0, 0);
   1145         }
   1146         return;
   1147     }
   1148 
   1149     SkAutoMaskImage srcCleanup(&srcM, true);
   1150 
   1151     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
   1152     if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
   1153         goto NO_FILTER_CASE;
   1154     }
   1155 
   1156     SkAutoMaskImage dstCleanup(&dstM, false);
   1157 
   1158     dst->setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
   1159                    dstM.fBounds.height(), dstM.fRowBytes);
   1160     dst->allocPixels();
   1161     memcpy(dst->getPixels(), dstM.fImage, dstM.computeImageSize());
   1162     if (offset) {
   1163         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
   1164     }
   1165     SkDEBUGCODE(dst->validate();)
   1166 }
   1167 
   1168 ///////////////////////////////////////////////////////////////////////////////
   1169 
   1170 enum {
   1171     SERIALIZE_PIXELTYPE_NONE,
   1172     SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE,
   1173     SERIALIZE_PIXELTYPE_RAW_NO_CTABLE,
   1174     SERIALIZE_PIXELTYPE_REF_DATA,
   1175     SERIALIZE_PIXELTYPE_REF_PTR,
   1176 };
   1177 
   1178 static void writeString(SkFlattenableWriteBuffer& buffer, const char str[]) {
   1179     size_t len = strlen(str);
   1180     buffer.write32(len);
   1181     buffer.writePad(str, len);
   1182 }
   1183 
   1184 static SkPixelRef::Factory deserialize_factory(SkFlattenableReadBuffer& buffer) {
   1185     size_t len = buffer.readInt();
   1186     SkAutoSMalloc<256> storage(len + 1);
   1187     char* str = (char*)storage.get();
   1188     buffer.read(str, len);
   1189     str[len] = 0;
   1190     return SkPixelRef::NameToFactory(str);
   1191 }
   1192 
   1193 /*
   1194     It is tricky to know how much to flatten. If we don't have a pixelref (i.e.
   1195     we just have pixels, then we can only flatten the pixels, or write out an
   1196     empty bitmap.
   1197 
   1198     With a pixelref, we still have the question of recognizing when two sitings
   1199     of the same pixelref are the same, and when they are different. Perhaps we
   1200     should look at the generationID and keep a record of that in some dictionary
   1201     associated with the buffer. SkGLTextureCache does this sort of thing to know
   1202     when to create a new texture.
   1203 */
   1204 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const {
   1205     buffer.write32(fWidth);
   1206     buffer.write32(fHeight);
   1207     buffer.write32(fRowBytes);
   1208     buffer.write8(fConfig);
   1209     buffer.writeBool(this->isOpaque());
   1210 
   1211     /*  If we are called in this mode, then it is up to the caller to manage
   1212         the owner-counts on the pixelref, as we just record the ptr itself.
   1213     */
   1214     if (!buffer.persistBitmapPixels()) {
   1215         if (fPixelRef) {
   1216             buffer.write8(SERIALIZE_PIXELTYPE_REF_PTR);
   1217             buffer.write32(fPixelRefOffset);
   1218             buffer.writeRefCnt(fPixelRef);
   1219             return;
   1220         } else {
   1221             // we ignore the non-persist request, since we don't have a ref
   1222             // ... or we could just write an empty bitmap...
   1223             // (true) will write an empty bitmap, (false) will flatten the pix
   1224             if (true) {
   1225                 buffer.write8(SERIALIZE_PIXELTYPE_NONE);
   1226                 return;
   1227             }
   1228         }
   1229     }
   1230 
   1231     if (fPixelRef) {
   1232         SkPixelRef::Factory fact = fPixelRef->getFactory();
   1233         if (fact) {
   1234             const char* name = SkPixelRef::FactoryToName(fact);
   1235             if (name && *name) {
   1236                 buffer.write8(SERIALIZE_PIXELTYPE_REF_DATA);
   1237                 buffer.write32(fPixelRefOffset);
   1238                 writeString(buffer, name);
   1239                 fPixelRef->flatten(buffer);
   1240                 return;
   1241             }
   1242         }
   1243         // if we get here, we can't record the pixels
   1244         buffer.write8(SERIALIZE_PIXELTYPE_NONE);
   1245     } else if (fPixels) {
   1246         if (fColorTable) {
   1247             buffer.write8(SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE);
   1248             fColorTable->flatten(buffer);
   1249         } else {
   1250             buffer.write8(SERIALIZE_PIXELTYPE_RAW_NO_CTABLE);
   1251         }
   1252         buffer.writePad(fPixels, this->getSize());
   1253     } else {
   1254         buffer.write8(SERIALIZE_PIXELTYPE_NONE);
   1255     }
   1256 }
   1257 
   1258 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) {
   1259     this->reset();
   1260 
   1261     int width = buffer.readInt();
   1262     int height = buffer.readInt();
   1263     int rowBytes = buffer.readInt();
   1264     int config = buffer.readU8();
   1265 
   1266     this->setConfig((Config)config, width, height, rowBytes);
   1267     this->setIsOpaque(buffer.readBool());
   1268 
   1269     size_t size = this->getSize();
   1270     int reftype = buffer.readU8();
   1271     switch (reftype) {
   1272         case SERIALIZE_PIXELTYPE_REF_PTR: {
   1273             size_t offset = buffer.readU32();
   1274             SkPixelRef* pr = (SkPixelRef*)buffer.readRefCnt();
   1275             this->setPixelRef(pr, offset);
   1276             break;
   1277         }
   1278         case SERIALIZE_PIXELTYPE_REF_DATA: {
   1279             size_t offset = buffer.readU32();
   1280             SkPixelRef::Factory fact = deserialize_factory(buffer);
   1281             SkPixelRef* pr = fact(buffer);
   1282             this->setPixelRef(pr, offset)->safeUnref();
   1283             break;
   1284         }
   1285         case SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE:
   1286         case SERIALIZE_PIXELTYPE_RAW_NO_CTABLE: {
   1287             SkColorTable* ctable = NULL;
   1288             if (SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE == reftype) {
   1289                 ctable = SkNEW_ARGS(SkColorTable, (buffer));
   1290             }
   1291             if (this->allocPixels(ctable)) {
   1292                 this->lockPixels();
   1293                 buffer.read(this->getPixels(), size);
   1294                 this->unlockPixels();
   1295             } else {
   1296                 buffer.skip(size);
   1297             }
   1298             SkSafeUnref(ctable);
   1299             break;
   1300         }
   1301         case SERIALIZE_PIXELTYPE_NONE:
   1302             break;
   1303         default:
   1304             SkASSERT(!"unrecognized pixeltype in serialized data");
   1305             sk_throw();
   1306     }
   1307 }
   1308 
   1309 ///////////////////////////////////////////////////////////////////////////////
   1310 
   1311 SkBitmap::RLEPixels::RLEPixels(int width, int height) {
   1312     fHeight = height;
   1313     fYPtrs = (uint8_t**)sk_malloc_throw(height * sizeof(uint8_t*));
   1314     sk_bzero(fYPtrs, height * sizeof(uint8_t*));
   1315 }
   1316 
   1317 SkBitmap::RLEPixels::~RLEPixels() {
   1318     sk_free(fYPtrs);
   1319 }
   1320 
   1321 ///////////////////////////////////////////////////////////////////////////////
   1322 
   1323 #ifdef SK_DEBUG
   1324 void SkBitmap::validate() const {
   1325     SkASSERT(fConfig < kConfigCount);
   1326     SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth));
   1327     SkASSERT(fFlags <= kImageIsOpaque_Flag);
   1328     SkASSERT(fPixelLockCount >= 0);
   1329     SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000);
   1330     SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel);
   1331 
   1332 #if 0   // these asserts are not thread-correct, so disable for now
   1333     if (fPixelRef) {
   1334         if (fPixelLockCount > 0) {
   1335             SkASSERT(fPixelRef->getLockCount() > 0);
   1336         } else {
   1337             SkASSERT(NULL == fPixels);
   1338             SkASSERT(NULL == fColorTable);
   1339         }
   1340     }
   1341 #endif
   1342 }
   1343 #endif
   1344 
   1345