LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkBitmap.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 831 0 0.0 %
Date: 2012-06-02 Functions: 70 0 0.0 %

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

Generated by: LCOV version 1.7