gfx/skia/trunk/src/core/SkBitmap.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
    10 #include "SkBitmap.h"
    11 #include "SkColorPriv.h"
    12 #include "SkDither.h"
    13 #include "SkFlattenable.h"
    14 #include "SkImagePriv.h"
    15 #include "SkMallocPixelRef.h"
    16 #include "SkMask.h"
    17 #include "SkReadBuffer.h"
    18 #include "SkWriteBuffer.h"
    19 #include "SkPixelRef.h"
    20 #include "SkThread.h"
    21 #include "SkUnPreMultiply.h"
    22 #include "SkUtils.h"
    23 #include "SkValidationUtils.h"
    24 #include "SkPackBits.h"
    25 #include <new>
    27 static bool reset_return_false(SkBitmap* bm) {
    28     bm->reset();
    29     return false;
    30 }
    32 struct MipLevel {
    33     void*       fPixels;
    34     uint32_t    fRowBytes;
    35     uint32_t    fWidth, fHeight;
    36 };
    38 struct SkBitmap::MipMap : SkNoncopyable {
    39     int32_t fRefCnt;
    40     int     fLevelCount;
    41 //  MipLevel    fLevel[fLevelCount];
    42 //  Pixels[]
    44     static MipMap* Alloc(int levelCount, size_t pixelSize) {
    45         if (levelCount < 0) {
    46             return NULL;
    47         }
    48         int64_t size = (levelCount + 1) * sizeof(MipLevel);
    49         size += sizeof(MipMap) + pixelSize;
    50         if (!sk_64_isS32(size)) {
    51             return NULL;
    52         }
    53         MipMap* mm = (MipMap*)sk_malloc_throw(sk_64_asS32(size));
    54         mm->fRefCnt = 1;
    55         mm->fLevelCount = levelCount;
    56         return mm;
    57     }
    59     const MipLevel* levels() const { return (const MipLevel*)(this + 1); }
    60     MipLevel* levels() { return (MipLevel*)(this + 1); }
    62     const void* pixels() const { return levels() + fLevelCount; }
    63     void* pixels() { return levels() + fLevelCount; }
    65     void ref() {
    66         if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) {
    67             sk_throw();
    68         }
    69     }
    70     void unref() {
    71         SkASSERT(fRefCnt > 0);
    72         if (sk_atomic_dec(&fRefCnt) == 1) {
    73             sk_free(this);
    74         }
    75     }
    76 };
    78 ///////////////////////////////////////////////////////////////////////////////
    79 ///////////////////////////////////////////////////////////////////////////////
    81 SkBitmap::SkBitmap() {
    82     sk_bzero(this, sizeof(*this));
    83 }
    85 SkBitmap::SkBitmap(const SkBitmap& src) {
    86     SkDEBUGCODE(src.validate();)
    87     sk_bzero(this, sizeof(*this));
    88     *this = src;
    89     SkDEBUGCODE(this->validate();)
    90 }
    92 SkBitmap::~SkBitmap() {
    93     SkDEBUGCODE(this->validate();)
    94     this->freePixels();
    95 }
    97 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
    98     if (this != &src) {
    99         this->freePixels();
   100         memcpy(this, &src, sizeof(src));
   102         // inc src reference counts
   103         SkSafeRef(src.fPixelRef);
   104         SkSafeRef(src.fMipMap);
   106         // we reset our locks if we get blown away
   107         fPixelLockCount = 0;
   109         if (fPixelRef) {
   110             // ignore the values from the memcpy
   111             fPixels = NULL;
   112             fColorTable = NULL;
   113             // Note that what to for genID is somewhat arbitrary. We have no
   114             // way to track changes to raw pixels across multiple SkBitmaps.
   115             // Would benefit from an SkRawPixelRef type created by
   116             // setPixels.
   117             // Just leave the memcpy'ed one but they'll get out of sync
   118             // as soon either is modified.
   119         }
   120     }
   122     SkDEBUGCODE(this->validate();)
   123     return *this;
   124 }
   126 void SkBitmap::swap(SkBitmap& other) {
   127     SkTSwap(fColorTable, other.fColorTable);
   128     SkTSwap(fPixelRef, other.fPixelRef);
   129     SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin);
   130     SkTSwap(fPixelLockCount, other.fPixelLockCount);
   131     SkTSwap(fMipMap, other.fMipMap);
   132     SkTSwap(fPixels, other.fPixels);
   133     SkTSwap(fInfo, other.fInfo);
   134     SkTSwap(fRowBytes, other.fRowBytes);
   135     SkTSwap(fFlags, other.fFlags);
   137     SkDEBUGCODE(this->validate();)
   138 }
   140 void SkBitmap::reset() {
   141     this->freePixels();
   142     sk_bzero(this, sizeof(*this));
   143 }
   145 SkBitmap::Config SkBitmap::config() const {
   146     return SkColorTypeToBitmapConfig(fInfo.colorType());
   147 }
   149 int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
   150     int bpp;
   151     switch (config) {
   152         case kNo_Config:
   153             bpp = 0;   // not applicable
   154             break;
   155         case kA8_Config:
   156         case kIndex8_Config:
   157             bpp = 1;
   158             break;
   159         case kRGB_565_Config:
   160         case kARGB_4444_Config:
   161             bpp = 2;
   162             break;
   163         case kARGB_8888_Config:
   164             bpp = 4;
   165             break;
   166         default:
   167             SkDEBUGFAIL("unknown config");
   168             bpp = 0;   // error
   169             break;
   170     }
   171     return bpp;
   172 }
   174 size_t SkBitmap::ComputeRowBytes(Config c, int width) {
   175     return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), width);
   176 }
   178 int64_t SkBitmap::ComputeSize64(Config config, int width, int height) {
   179     SkColorType ct = SkBitmapConfigToColorType(config);
   180     int64_t rowBytes = sk_64_mul(SkColorTypeBytesPerPixel(ct), width);
   181     return rowBytes * height;
   182 }
   184 size_t SkBitmap::ComputeSize(Config c, int width, int height) {
   185     int64_t size = SkBitmap::ComputeSize64(c, width, height);
   186     return sk_64_isS32(size) ? sk_64_asS32(size) : 0;
   187 }
   189 int64_t SkBitmap::ComputeSafeSize64(Config config,
   190                                     uint32_t width,
   191                                     uint32_t height,
   192                                     size_t rowBytes) {
   193     SkImageInfo info = SkImageInfo::Make(width, height,
   194                                          SkBitmapConfigToColorType(config),
   195                                          kPremul_SkAlphaType);
   196     return info.getSafeSize64(rowBytes);
   197 }
   199 size_t SkBitmap::ComputeSafeSize(Config config,
   200                                  uint32_t width,
   201                                  uint32_t height,
   202                                  size_t rowBytes) {
   203     int64_t safeSize = ComputeSafeSize64(config, width, height, rowBytes);
   204     int32_t safeSize32 = (int32_t)safeSize;
   206     if (safeSize32 != safeSize) {
   207         safeSize32 = 0;
   208     }
   209     return safeSize32;
   210 }
   212 void SkBitmap::getBounds(SkRect* bounds) const {
   213     SkASSERT(bounds);
   214     bounds->set(0, 0,
   215                 SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight));
   216 }
   218 void SkBitmap::getBounds(SkIRect* bounds) const {
   219     SkASSERT(bounds);
   220     bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight);
   221 }
   223 ///////////////////////////////////////////////////////////////////////////////
   225 static bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType,
   226                                SkAlphaType* canonical = NULL) {
   227     switch (colorType) {
   228         case kUnknown_SkColorType:
   229             alphaType = kIgnore_SkAlphaType;
   230             break;
   231         case kAlpha_8_SkColorType:
   232             if (kUnpremul_SkAlphaType == alphaType) {
   233                 alphaType = kPremul_SkAlphaType;
   234             }
   235             // fall-through
   236         case kIndex_8_SkColorType:
   237         case kARGB_4444_SkColorType:
   238         case kRGBA_8888_SkColorType:
   239         case kBGRA_8888_SkColorType:
   240             if (kIgnore_SkAlphaType == alphaType) {
   241                 return false;
   242             }
   243             break;
   244         case kRGB_565_SkColorType:
   245             alphaType = kOpaque_SkAlphaType;
   246             break;
   247         default:
   248             return false;
   249     }
   250     if (canonical) {
   251         *canonical = alphaType;
   252     }
   253     return true;
   254 }
   256 bool SkBitmap::setConfig(const SkImageInfo& origInfo, size_t rowBytes) {
   257     SkImageInfo info = origInfo;
   259     if (!validate_alphaType(info.fColorType, info.fAlphaType,
   260                             &info.fAlphaType)) {
   261         return reset_return_false(this);
   262     }
   264     // require that rowBytes fit in 31bits
   265     int64_t mrb = info.minRowBytes64();
   266     if ((int32_t)mrb != mrb) {
   267         return reset_return_false(this);
   268     }
   269     if ((int64_t)rowBytes != (int32_t)rowBytes) {
   270         return reset_return_false(this);
   271     }
   273     if (info.width() < 0 || info.height() < 0) {
   274         return reset_return_false(this);
   275     }
   277     if (kUnknown_SkColorType == info.colorType()) {
   278         rowBytes = 0;
   279     } else if (0 == rowBytes) {
   280         rowBytes = (size_t)mrb;
   281     } else if (rowBytes < info.minRowBytes()) {
   282         return reset_return_false(this);
   283     }
   285     this->freePixels();
   287     fInfo = info;
   288     fRowBytes = SkToU32(rowBytes);
   289     return true;
   290 }
   292 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
   293                          SkAlphaType alphaType) {
   294     SkColorType ct = SkBitmapConfigToColorType(config);
   295     return this->setConfig(SkImageInfo::Make(width, height, ct, alphaType),
   296                            rowBytes);
   297 }
   299 bool SkBitmap::setAlphaType(SkAlphaType alphaType) {
   300     if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) {
   301         return false;
   302     }
   303     if (fInfo.fAlphaType != alphaType) {
   304         fInfo.fAlphaType = alphaType;
   305         if (fPixelRef) {
   306             fPixelRef->changeAlphaType(alphaType);
   307         }
   308     }
   309     return true;
   310 }
   312 void SkBitmap::updatePixelsFromRef() const {
   313     if (NULL != fPixelRef) {
   314         if (fPixelLockCount > 0) {
   315             SkASSERT(fPixelRef->isLocked());
   317             void* p = fPixelRef->pixels();
   318             if (NULL != p) {
   319                 p = (char*)p
   320                     + fPixelRefOrigin.fY * fRowBytes
   321                     + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
   322             }
   323             fPixels = p;
   324             fColorTable = fPixelRef->colorTable();
   325         } else {
   326             SkASSERT(0 == fPixelLockCount);
   327             fPixels = NULL;
   328             fColorTable = NULL;
   329         }
   330     }
   331 }
   333 static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) {
   334     SkColorType ct;
   335     switch (config) {
   336         case SkBitmap::kA8_Config:
   337             ct = kAlpha_8_SkColorType;
   338             break;
   339         case SkBitmap::kIndex8_Config:
   340             ct = kIndex_8_SkColorType;
   341             break;
   342         case SkBitmap::kRGB_565_Config:
   343             ct = kRGB_565_SkColorType;
   344             break;
   345         case SkBitmap::kARGB_4444_Config:
   346             ct = kARGB_4444_SkColorType;
   347             break;
   348         case SkBitmap::kARGB_8888_Config:
   349             ct = kPMColor_SkColorType;
   350             break;
   351         case SkBitmap::kNo_Config:
   352         default:
   353             return false;
   354     }
   355     if (ctOut) {
   356         *ctOut = ct;
   357     }
   358     return true;
   359 }
   361 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
   362 #ifdef SK_DEBUG
   363     if (pr) {
   364         SkImageInfo info;
   365         if (this->asImageInfo(&info)) {
   366             const SkImageInfo& prInfo = pr->info();
   367             SkASSERT(info.fWidth <= prInfo.fWidth);
   368             SkASSERT(info.fHeight <= prInfo.fHeight);
   369             SkASSERT(info.fColorType == prInfo.fColorType);
   370             switch (prInfo.fAlphaType) {
   371                 case kIgnore_SkAlphaType:
   372                     SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType);
   373                     break;
   374                 case kOpaque_SkAlphaType:
   375                 case kPremul_SkAlphaType:
   376                     SkASSERT(info.fAlphaType == kOpaque_SkAlphaType ||
   377                              info.fAlphaType == kPremul_SkAlphaType);
   378                     break;
   379                 case kUnpremul_SkAlphaType:
   380                     SkASSERT(info.fAlphaType == kOpaque_SkAlphaType ||
   381                              info.fAlphaType == kUnpremul_SkAlphaType);
   382                     break;
   383             }
   384         }
   385     }
   386 #endif
   388     if (pr) {
   389         const SkImageInfo& info = pr->info();
   390         fPixelRefOrigin.set(SkPin32(dx, 0, info.fWidth),
   391                             SkPin32(dy, 0, info.fHeight));
   392     } else {
   393         // ignore dx,dy if there is no pixelref
   394         fPixelRefOrigin.setZero();
   395     }
   397     if (fPixelRef != pr) {
   398         if (fPixelRef != pr) {
   399             this->freePixels();
   400             SkASSERT(NULL == fPixelRef);
   402             SkSafeRef(pr);
   403             fPixelRef = pr;
   404         }
   405         this->updatePixelsFromRef();
   406     }
   408     SkDEBUGCODE(this->validate();)
   409     return pr;
   410 }
   412 void SkBitmap::lockPixels() const {
   413     if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) {
   414         fPixelRef->lockPixels();
   415         this->updatePixelsFromRef();
   416     }
   417     SkDEBUGCODE(this->validate();)
   418 }
   420 void SkBitmap::unlockPixels() const {
   421     SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
   423     if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) {
   424         fPixelRef->unlockPixels();
   425         this->updatePixelsFromRef();
   426     }
   427     SkDEBUGCODE(this->validate();)
   428 }
   430 bool SkBitmap::lockPixelsAreWritable() const {
   431     return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false;
   432 }
   434 void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
   435     if (NULL == p) {
   436         this->setPixelRef(NULL);
   437         return;
   438     }
   440     SkImageInfo info;
   441     if (!this->asImageInfo(&info)) {
   442         this->setPixelRef(NULL);
   443         return;
   444     }
   446     SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable);
   447     if (NULL == pr) {
   448         this->setPixelRef(NULL);
   449         return;
   450     }
   452     this->setPixelRef(pr)->unref();
   454     // since we're already allocated, we lockPixels right away
   455     this->lockPixels();
   456     SkDEBUGCODE(this->validate();)
   457 }
   459 bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
   460     HeapAllocator stdalloc;
   462     if (NULL == allocator) {
   463         allocator = &stdalloc;
   464     }
   465     return allocator->allocPixelRef(this, ctable);
   466 }
   468 ///////////////////////////////////////////////////////////////////////////////
   470 bool SkBitmap::allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory,
   471                            SkColorTable* ctable) {
   472     if (kIndex_8_SkColorType == info.fColorType && NULL == ctable) {
   473         return reset_return_false(this);
   474     }
   475     if (!this->setConfig(info)) {
   476         return reset_return_false(this);
   477     }
   479     SkMallocPixelRef::PRFactory defaultFactory;
   480     if (NULL == factory) {
   481         factory = &defaultFactory;
   482     }
   484     SkPixelRef* pr = factory->create(info, ctable);
   485     if (NULL == pr) {
   486         return reset_return_false(this);
   487     }
   488     this->setPixelRef(pr)->unref();
   490     // TODO: lockPixels could/should return bool or void*/NULL
   491     this->lockPixels();
   492     if (NULL == this->getPixels()) {
   493         return reset_return_false(this);
   494     }
   495     return true;
   496 }
   498 bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb,
   499                              void (*releaseProc)(void* addr, void* context),
   500                              void* context) {
   501     if (!this->setConfig(info, rb)) {
   502         this->reset();
   503         return false;
   504     }
   506     SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, NULL, pixels,
   507                                                    releaseProc, context);
   508     if (!pr) {
   509         this->reset();
   510         return false;
   511     }
   513     this->setPixelRef(pr)->unref();
   515     // since we're already allocated, we lockPixels right away
   516     this->lockPixels();
   517     SkDEBUGCODE(this->validate();)
   518     return true;
   519 }
   521 bool SkBitmap::installMaskPixels(const SkMask& mask) {
   522     if (SkMask::kA8_Format != mask.fFormat) {
   523         this->reset();
   524         return false;
   525     }
   526     return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
   527                                                    mask.fBounds.height()),
   528                                mask.fImage, mask.fRowBytes);
   529 }
   531 bool SkBitmap::allocConfigPixels(Config config, int width, int height,
   532                                  bool isOpaque) {
   533     SkColorType ct;
   534     if (!config_to_colorType(config, &ct)) {
   535         return false;
   536     }
   538     SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
   539     return this->allocPixels(SkImageInfo::Make(width, height, ct, at));
   540 }
   542 ///////////////////////////////////////////////////////////////////////////////
   544 void SkBitmap::freePixels() {
   545     // if we're gonna free the pixels, we certainly need to free the mipmap
   546     this->freeMipMap();
   548     if (NULL != fPixelRef) {
   549         if (fPixelLockCount > 0) {
   550             fPixelRef->unlockPixels();
   551         }
   552         fPixelRef->unref();
   553         fPixelRef = NULL;
   554         fPixelRefOrigin.setZero();
   555     }
   556     fPixelLockCount = 0;
   557     fPixels = NULL;
   558     fColorTable = NULL;
   559 }
   561 void SkBitmap::freeMipMap() {
   562     if (fMipMap) {
   563         fMipMap->unref();
   564         fMipMap = NULL;
   565     }
   566 }
   568 uint32_t SkBitmap::getGenerationID() const {
   569     return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
   570 }
   572 void SkBitmap::notifyPixelsChanged() const {
   573     SkASSERT(!this->isImmutable());
   574     if (fPixelRef) {
   575         fPixelRef->notifyPixelsChanged();
   576     }
   577 }
   579 GrTexture* SkBitmap::getTexture() const {
   580     return fPixelRef ? fPixelRef->getTexture() : NULL;
   581 }
   583 ///////////////////////////////////////////////////////////////////////////////
   585 /** We explicitly use the same allocator for our pixels that SkMask does,
   586  so that we can freely assign memory allocated by one class to the other.
   587  */
   588 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
   589                                             SkColorTable* ctable) {
   590     SkImageInfo info;
   591     if (!dst->asImageInfo(&info)) {
   592 //        SkDebugf("unsupported config for info %d\n", dst->config());
   593         return false;
   594     }
   596     SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(),
   597                                                    ctable);
   598     if (NULL == pr) {
   599         return false;
   600     }
   602     dst->setPixelRef(pr)->unref();
   603     // since we're already allocated, we lockPixels right away
   604     dst->lockPixels();
   605     return true;
   606 }
   608 ///////////////////////////////////////////////////////////////////////////////
   610 bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
   611                             size_t dstRowBytes, bool preserveDstPad) const {
   613     if (0 == dstRowBytes) {
   614         dstRowBytes = fRowBytes;
   615     }
   617     if (dstRowBytes < fInfo.minRowBytes() ||
   618         dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) {
   619         return false;
   620     }
   622     if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
   623         size_t safeSize = this->getSafeSize();
   624         if (safeSize > dstSize || safeSize == 0)
   625             return false;
   626         else {
   627             SkAutoLockPixels lock(*this);
   628             // This implementation will write bytes beyond the end of each row,
   629             // excluding the last row, if the bitmap's stride is greater than
   630             // strictly required by the current config.
   631             memcpy(dst, getPixels(), safeSize);
   633             return true;
   634         }
   635     } else {
   636         // If destination has different stride than us, then copy line by line.
   637         if (fInfo.getSafeSize(dstRowBytes) > dstSize) {
   638             return false;
   639         } else {
   640             // Just copy what we need on each line.
   641             size_t rowBytes = fInfo.minRowBytes();
   642             SkAutoLockPixels lock(*this);
   643             const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
   644             uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
   645             for (int row = 0; row < fInfo.fHeight;
   646                  row++, srcP += fRowBytes, dstP += dstRowBytes) {
   647                 memcpy(dstP, srcP, rowBytes);
   648             }
   650             return true;
   651         }
   652     }
   653 }
   655 ///////////////////////////////////////////////////////////////////////////////
   657 bool SkBitmap::isImmutable() const {
   658     return fPixelRef ? fPixelRef->isImmutable() :
   659         fFlags & kImageIsImmutable_Flag;
   660 }
   662 void SkBitmap::setImmutable() {
   663     if (fPixelRef) {
   664         fPixelRef->setImmutable();
   665     } else {
   666         fFlags |= kImageIsImmutable_Flag;
   667     }
   668 }
   670 bool SkBitmap::isVolatile() const {
   671     return (fFlags & kImageIsVolatile_Flag) != 0;
   672 }
   674 void SkBitmap::setIsVolatile(bool isVolatile) {
   675     if (isVolatile) {
   676         fFlags |= kImageIsVolatile_Flag;
   677     } else {
   678         fFlags &= ~kImageIsVolatile_Flag;
   679     }
   680 }
   682 void* SkBitmap::getAddr(int x, int y) const {
   683     SkASSERT((unsigned)x < (unsigned)this->width());
   684     SkASSERT((unsigned)y < (unsigned)this->height());
   686     char* base = (char*)this->getPixels();
   687     if (base) {
   688         base += y * this->rowBytes();
   689         switch (this->colorType()) {
   690             case kRGBA_8888_SkColorType:
   691             case kBGRA_8888_SkColorType:
   692                 base += x << 2;
   693                 break;
   694             case kARGB_4444_SkColorType:
   695             case kRGB_565_SkColorType:
   696                 base += x << 1;
   697                 break;
   698             case kAlpha_8_SkColorType:
   699             case kIndex_8_SkColorType:
   700                 base += x;
   701                 break;
   702             default:
   703                 SkDEBUGFAIL("Can't return addr for config");
   704                 base = NULL;
   705                 break;
   706         }
   707     }
   708     return base;
   709 }
   711 SkColor SkBitmap::getColor(int x, int y) const {
   712     SkASSERT((unsigned)x < (unsigned)this->width());
   713     SkASSERT((unsigned)y < (unsigned)this->height());
   715     switch (this->config()) {
   716         case SkBitmap::kA8_Config: {
   717             uint8_t* addr = this->getAddr8(x, y);
   718             return SkColorSetA(0, addr[0]);
   719         }
   720         case SkBitmap::kIndex8_Config: {
   721             SkPMColor c = this->getIndex8Color(x, y);
   722             return SkUnPreMultiply::PMColorToColor(c);
   723         }
   724         case SkBitmap::kRGB_565_Config: {
   725             uint16_t* addr = this->getAddr16(x, y);
   726             return SkPixel16ToColor(addr[0]);
   727         }
   728         case SkBitmap::kARGB_4444_Config: {
   729             uint16_t* addr = this->getAddr16(x, y);
   730             SkPMColor c = SkPixel4444ToPixel32(addr[0]);
   731             return SkUnPreMultiply::PMColorToColor(c);
   732         }
   733         case SkBitmap::kARGB_8888_Config: {
   734             uint32_t* addr = this->getAddr32(x, y);
   735             return SkUnPreMultiply::PMColorToColor(addr[0]);
   736         }
   737         case kNo_Config:
   738         default:
   739             SkASSERT(false);
   740             return 0;
   741     }
   742     SkASSERT(false);  // Not reached.
   743     return 0;
   744 }
   746 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
   747     SkAutoLockPixels alp(bm);
   748     if (!bm.getPixels()) {
   749         return false;
   750     }
   752     const int height = bm.height();
   753     const int width = bm.width();
   755     switch (bm.config()) {
   756         case SkBitmap::kA8_Config: {
   757             unsigned a = 0xFF;
   758             for (int y = 0; y < height; ++y) {
   759                 const uint8_t* row = bm.getAddr8(0, y);
   760                 for (int x = 0; x < width; ++x) {
   761                     a &= row[x];
   762                 }
   763                 if (0xFF != a) {
   764                     return false;
   765                 }
   766             }
   767             return true;
   768         } break;
   769         case SkBitmap::kIndex8_Config: {
   770             SkAutoLockColors alc(bm);
   771             const SkPMColor* table = alc.colors();
   772             if (!table) {
   773                 return false;
   774             }
   775             SkPMColor c = (SkPMColor)~0;
   776             for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) {
   777                 c &= table[i];
   778             }
   779             return 0xFF == SkGetPackedA32(c);
   780         } break;
   781         case SkBitmap::kRGB_565_Config:
   782             return true;
   783             break;
   784         case SkBitmap::kARGB_4444_Config: {
   785             unsigned c = 0xFFFF;
   786             for (int y = 0; y < height; ++y) {
   787                 const SkPMColor16* row = bm.getAddr16(0, y);
   788                 for (int x = 0; x < width; ++x) {
   789                     c &= row[x];
   790                 }
   791                 if (0xF != SkGetPackedA4444(c)) {
   792                     return false;
   793                 }
   794             }
   795             return true;
   796         } break;
   797         case SkBitmap::kARGB_8888_Config: {
   798             SkPMColor c = (SkPMColor)~0;
   799             for (int y = 0; y < height; ++y) {
   800                 const SkPMColor* row = bm.getAddr32(0, y);
   801                 for (int x = 0; x < width; ++x) {
   802                     c &= row[x];
   803                 }
   804                 if (0xFF != SkGetPackedA32(c)) {
   805                     return false;
   806                 }
   807             }
   808             return true;
   809         }
   810         default:
   811             break;
   812     }
   813     return false;
   814 }
   817 ///////////////////////////////////////////////////////////////////////////////
   818 ///////////////////////////////////////////////////////////////////////////////
   820 static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
   821     unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) |
   822                      (SkR32To4444(r) << SK_R4444_SHIFT) |
   823                      (SkG32To4444(g) << SK_G4444_SHIFT) |
   824                      (SkB32To4444(b) << SK_B4444_SHIFT);
   825     return SkToU16(pixel);
   826 }
   828 void SkBitmap::internalErase(const SkIRect& area,
   829                              U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
   830 #ifdef SK_DEBUG
   831     SkDEBUGCODE(this->validate();)
   832     SkASSERT(!area.isEmpty());
   833     {
   834         SkIRect total = { 0, 0, this->width(), this->height() };
   835         SkASSERT(total.contains(area));
   836     }
   837 #endif
   839     switch (fInfo.colorType()) {
   840         case kUnknown_SkColorType:
   841         case kIndex_8_SkColorType:
   842             return; // can't erase
   843         default:
   844             break;
   845     }
   847     SkAutoLockPixels alp(*this);
   848     // perform this check after the lock call
   849     if (!this->readyToDraw()) {
   850         return;
   851     }
   853     int height = area.height();
   854     const int width = area.width();
   855     const int rowBytes = fRowBytes;
   857     // make rgb premultiplied
   858     if (255 != a) {
   859         r = SkAlphaMul(r, a);
   860         g = SkAlphaMul(g, a);
   861         b = SkAlphaMul(b, a);
   862     }
   864     switch (this->colorType()) {
   865         case kAlpha_8_SkColorType: {
   866             uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
   867             while (--height >= 0) {
   868                 memset(p, a, width);
   869                 p += rowBytes;
   870             }
   871             break;
   872         }
   873         case kARGB_4444_SkColorType:
   874         case kRGB_565_SkColorType: {
   875             uint16_t* p = this->getAddr16(area.fLeft, area.fTop);;
   876             uint16_t v;
   878             if (kARGB_4444_SkColorType == this->colorType()) {
   879                 v = pack_8888_to_4444(a, r, g, b);
   880             } else {
   881                 v = SkPackRGB16(r >> (8 - SK_R16_BITS),
   882                                 g >> (8 - SK_G16_BITS),
   883                                 b >> (8 - SK_B16_BITS));
   884             }
   885             while (--height >= 0) {
   886                 sk_memset16(p, v, width);
   887                 p = (uint16_t*)((char*)p + rowBytes);
   888             }
   889             break;
   890         }
   891         case kPMColor_SkColorType: {
   892             // what to do about BGRA or RGBA (which ever is != PMColor ?
   893             // for now we don't support them.
   894             uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
   895             uint32_t  v = SkPackARGB32(a, r, g, b);
   897             while (--height >= 0) {
   898                 sk_memset32(p, v, width);
   899                 p = (uint32_t*)((char*)p + rowBytes);
   900             }
   901             break;
   902         }
   903         default:
   904             return; // no change, so don't call notifyPixelsChanged()
   905     }
   907     this->notifyPixelsChanged();
   908 }
   910 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
   911     SkIRect area = { 0, 0, this->width(), this->height() };
   912     if (!area.isEmpty()) {
   913         this->internalErase(area, a, r, g, b);
   914     }
   915 }
   917 void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const {
   918     SkIRect area = { 0, 0, this->width(), this->height() };
   919     if (area.intersect(rect)) {
   920         this->internalErase(area, SkColorGetA(c), SkColorGetR(c),
   921                             SkColorGetG(c), SkColorGetB(c));
   922     }
   923 }
   925 //////////////////////////////////////////////////////////////////////////////////////
   926 //////////////////////////////////////////////////////////////////////////////////////
   928 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
   929     SkDEBUGCODE(this->validate();)
   931     if (NULL == result || NULL == fPixelRef) {
   932         return false;   // no src pixels
   933     }
   935     SkIRect srcRect, r;
   936     srcRect.set(0, 0, this->width(), this->height());
   937     if (!r.intersect(srcRect, subset)) {
   938         return false;   // r is empty (i.e. no intersection)
   939     }
   941     if (fPixelRef->getTexture() != NULL) {
   942         // Do a deep copy
   943         SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset);
   944         if (pixelRef != NULL) {
   945             SkBitmap dst;
   946             dst.setConfig(this->config(), subset.width(), subset.height(), 0,
   947                           this->alphaType());
   948             dst.setIsVolatile(this->isVolatile());
   949             dst.setPixelRef(pixelRef)->unref();
   950             SkDEBUGCODE(dst.validate());
   951             result->swap(dst);
   952             return true;
   953         }
   954     }
   956     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
   957     // exited above.
   958     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
   959     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
   961     SkBitmap dst;
   962     dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(),
   963                   this->alphaType());
   964     dst.setIsVolatile(this->isVolatile());
   966     if (fPixelRef) {
   967         SkIPoint origin = fPixelRefOrigin;
   968         origin.fX += r.fLeft;
   969         origin.fY += r.fTop;
   970         // share the pixelref with a custom offset
   971         dst.setPixelRef(fPixelRef, origin);
   972     }
   973     SkDEBUGCODE(dst.validate();)
   975     // we know we're good, so commit to result
   976     result->swap(dst);
   977     return true;
   978 }
   980 ///////////////////////////////////////////////////////////////////////////////
   982 #include "SkCanvas.h"
   983 #include "SkPaint.h"
   985 bool SkBitmap::canCopyTo(SkColorType dstColorType) const {
   986     if (this->colorType() == kUnknown_SkColorType) {
   987         return false;
   988     }
   990     bool sameConfigs = (this->colorType() == dstColorType);
   991     switch (dstColorType) {
   992         case kAlpha_8_SkColorType:
   993         case kRGB_565_SkColorType:
   994         case kPMColor_SkColorType:
   995             break;
   996         case kIndex_8_SkColorType:
   997             if (!sameConfigs) {
   998                 return false;
   999             }
  1000             break;
  1001         case kARGB_4444_SkColorType:
  1002             return sameConfigs || kPMColor_SkColorType == this->colorType();
  1003         default:
  1004             return false;
  1006     return true;
  1009 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType,
  1010                       Allocator* alloc) const {
  1011     if (!this->canCopyTo(dstColorType)) {
  1012         return false;
  1015     // if we have a texture, first get those pixels
  1016     SkBitmap tmpSrc;
  1017     const SkBitmap* src = this;
  1019     if (fPixelRef) {
  1020         SkIRect subset;
  1021         subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
  1022                        fInfo.width(), fInfo.height());
  1023         if (fPixelRef->readPixels(&tmpSrc, &subset)) {
  1024             SkASSERT(tmpSrc.width() == this->width());
  1025             SkASSERT(tmpSrc.height() == this->height());
  1027             // did we get lucky and we can just return tmpSrc?
  1028             if (tmpSrc.colorType() == dstColorType && NULL == alloc) {
  1029                 dst->swap(tmpSrc);
  1030                 // If the result is an exact copy, clone the gen ID.
  1031                 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
  1032                     dst->pixelRef()->cloneGenID(*fPixelRef);
  1034                 return true;
  1037             // fall through to the raster case
  1038             src = &tmpSrc;
  1042     // we lock this now, since we may need its colortable
  1043     SkAutoLockPixels srclock(*src);
  1044     if (!src->readyToDraw()) {
  1045         return false;
  1048     // The only way to be readyToDraw is if fPixelRef is non NULL.
  1049     SkASSERT(fPixelRef != NULL);
  1051     SkImageInfo dstInfo = src->info();
  1052     dstInfo.fColorType = dstColorType;
  1054     SkBitmap tmpDst;
  1055     if (!tmpDst.setConfig(dstInfo)) {
  1056         return false;
  1059     // allocate colortable if srcConfig == kIndex8_Config
  1060     SkAutoTUnref<SkColorTable> ctable;
  1061     if (dstColorType == kIndex_8_SkColorType) {
  1062         // TODO: can we just ref() the src colortable? Is it reentrant-safe?
  1063         ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable())));
  1065     if (!tmpDst.allocPixels(alloc, ctable)) {
  1066         return false;
  1069     if (!tmpDst.readyToDraw()) {
  1070         // allocator/lock failed
  1071         return false;
  1074     // pixelRef must be non NULL or tmpDst.readyToDraw() would have
  1075     // returned false.
  1076     SkASSERT(tmpDst.pixelRef() != NULL);
  1078     /* do memcpy for the same configs cases, else use drawing
  1079     */
  1080     if (src->colorType() == dstColorType) {
  1081         if (tmpDst.getSize() == src->getSize()) {
  1082             memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize());
  1083             SkPixelRef* pixelRef = tmpDst.pixelRef();
  1085             // In order to reach this point, we know that the width, config and
  1086             // rowbytes of the SkPixelRefs are the same, but it is possible for
  1087             // the heights to differ, if this SkBitmap's height is a subset of
  1088             // fPixelRef. Only if the SkPixelRefs' heights match are we
  1089             // guaranteed that this is an exact copy, meaning we should clone
  1090             // the genID.
  1091             if (pixelRef->info().fHeight == fPixelRef->info().fHeight) {
  1092                 // TODO: what to do if the two infos match, BUT
  1093                 // fPixelRef is premul and pixelRef is opaque?
  1094                 // skipping assert for now
  1095                 // https://code.google.com/p/skia/issues/detail?id=2012
  1096 //                SkASSERT(pixelRef->info() == fPixelRef->info());
  1097                 SkASSERT(pixelRef->info().fWidth == fPixelRef->info().fWidth);
  1098                 SkASSERT(pixelRef->info().fColorType == fPixelRef->info().fColorType);
  1099                 pixelRef->cloneGenID(*fPixelRef);
  1101         } else {
  1102             const char* srcP = reinterpret_cast<const char*>(src->getPixels());
  1103             char* dstP = reinterpret_cast<char*>(tmpDst.getPixels());
  1104             // to be sure we don't read too much, only copy our logical pixels
  1105             size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel();
  1106             for (int y = 0; y < tmpDst.height(); y++) {
  1107                 memcpy(dstP, srcP, bytesToCopy);
  1108                 srcP += src->rowBytes();
  1109                 dstP += tmpDst.rowBytes();
  1112     } else if (kARGB_4444_SkColorType == dstColorType
  1113                && kPMColor_SkColorType == src->colorType()) {
  1114         SkASSERT(src->height() == tmpDst.height());
  1115         SkASSERT(src->width() == tmpDst.width());
  1116         for (int y = 0; y < src->height(); ++y) {
  1117             SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y);
  1118             SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y);
  1119             DITHER_4444_SCAN(y);
  1120             for (int x = 0; x < src->width(); ++x) {
  1121                 dstRow[x] = SkDitherARGB32To4444(srcRow[x],
  1122                                                  DITHER_VALUE(x));
  1125     } else {
  1126         // Always clear the dest in case one of the blitters accesses it
  1127         // TODO: switch the allocation of tmpDst to call sk_calloc_throw
  1128         tmpDst.eraseColor(SK_ColorTRANSPARENT);
  1130         SkCanvas canvas(tmpDst);
  1131         SkPaint  paint;
  1133         paint.setDither(true);
  1134         canvas.drawBitmap(*src, 0, 0, &paint);
  1137     dst->swap(tmpDst);
  1138     return true;
  1141 bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
  1142     const SkBitmap::Config dstConfig = this->config();
  1143     const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig);
  1145     if (!this->canCopyTo(dstCT)) {
  1146         return false;
  1149     // If we have a PixelRef, and it supports deep copy, use it.
  1150     // Currently supported only by texture-backed bitmaps.
  1151     if (fPixelRef) {
  1152         SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig);
  1153         if (pixelRef) {
  1154             uint32_t rowBytes;
  1155             if (this->colorType() == dstCT) {
  1156                 // Since there is no subset to pass to deepCopy, and deepCopy
  1157                 // succeeded, the new pixel ref must be identical.
  1158                 SkASSERT(fPixelRef->info() == pixelRef->info());
  1159                 pixelRef->cloneGenID(*fPixelRef);
  1160                 // Use the same rowBytes as the original.
  1161                 rowBytes = fRowBytes;
  1162             } else {
  1163                 // With the new config, an appropriate fRowBytes will be computed by setConfig.
  1164                 rowBytes = 0;
  1167             SkImageInfo info = fInfo;
  1168             info.fColorType = dstCT;
  1169             if (!dst->setConfig(info, rowBytes)) {
  1170                 return false;
  1172             dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
  1173             return true;
  1177     if (this->getTexture()) {
  1178         return false;
  1179     } else {
  1180         return this->copyTo(dst, dstCT, NULL);
  1184 ///////////////////////////////////////////////////////////////////////////////
  1185 ///////////////////////////////////////////////////////////////////////////////
  1187 static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
  1188                                  const SkBitmap& src) {
  1189     x <<= 1;
  1190     y <<= 1;
  1191     const SkPMColor* p = src.getAddr32(x, y);
  1192     const SkPMColor* baseP = p;
  1193     SkPMColor c, ag, rb;
  1195     c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
  1196     if (x < src.width() - 1) {
  1197         p += 1;
  1199     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
  1201     p = baseP;
  1202     if (y < src.height() - 1) {
  1203         p += src.rowBytes() >> 2;
  1205     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
  1206     if (x < src.width() - 1) {
  1207         p += 1;
  1209     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
  1211     *dst->getAddr32(x >> 1, y >> 1) =
  1212         ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
  1215 static inline uint32_t expand16(U16CPU c) {
  1216     return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
  1219 // returns dirt in the top 16bits, but we don't care, since we only
  1220 // store the low 16bits.
  1221 static inline U16CPU pack16(uint32_t c) {
  1222     return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
  1225 static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
  1226                                  const SkBitmap& src) {
  1227     x <<= 1;
  1228     y <<= 1;
  1229     const uint16_t* p = src.getAddr16(x, y);
  1230     const uint16_t* baseP = p;
  1231     SkPMColor       c;
  1233     c = expand16(*p);
  1234     if (x < src.width() - 1) {
  1235         p += 1;
  1237     c += expand16(*p);
  1239     p = baseP;
  1240     if (y < src.height() - 1) {
  1241         p += src.rowBytes() >> 1;
  1243     c += expand16(*p);
  1244     if (x < src.width() - 1) {
  1245         p += 1;
  1247     c += expand16(*p);
  1249     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
  1252 static uint32_t expand4444(U16CPU c) {
  1253     return (c & 0xF0F) | ((c & ~0xF0F) << 12);
  1256 static U16CPU collaps4444(uint32_t c) {
  1257     return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
  1260 static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
  1261                                    const SkBitmap& src) {
  1262     x <<= 1;
  1263     y <<= 1;
  1264     const uint16_t* p = src.getAddr16(x, y);
  1265     const uint16_t* baseP = p;
  1266     uint32_t        c;
  1268     c = expand4444(*p);
  1269     if (x < src.width() - 1) {
  1270         p += 1;
  1272     c += expand4444(*p);
  1274     p = baseP;
  1275     if (y < src.height() - 1) {
  1276         p += src.rowBytes() >> 1;
  1278     c += expand4444(*p);
  1279     if (x < src.width() - 1) {
  1280         p += 1;
  1282     c += expand4444(*p);
  1284     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
  1287 void SkBitmap::buildMipMap(bool forceRebuild) {
  1288     if (forceRebuild)
  1289         this->freeMipMap();
  1290     else if (fMipMap)
  1291         return; // we're already built
  1293     SkASSERT(NULL == fMipMap);
  1295     void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
  1297     const SkBitmap::Config config = this->config();
  1299     switch (config) {
  1300         case kARGB_8888_Config:
  1301             proc = downsampleby2_proc32;
  1302             break;
  1303         case kRGB_565_Config:
  1304             proc = downsampleby2_proc16;
  1305             break;
  1306         case kARGB_4444_Config:
  1307             proc = downsampleby2_proc4444;
  1308             break;
  1309         case kIndex8_Config:
  1310         case kA8_Config:
  1311         default:
  1312             return; // don't build mipmaps for these configs
  1315     SkAutoLockPixels alp(*this);
  1316     if (!this->readyToDraw()) {
  1317         return;
  1320     // whip through our loop to compute the exact size needed
  1321     size_t  size = 0;
  1322     int     maxLevels = 0;
  1324         int width = this->width();
  1325         int height = this->height();
  1326         for (;;) {
  1327             width >>= 1;
  1328             height >>= 1;
  1329             if (0 == width || 0 == height) {
  1330                 break;
  1332             size += ComputeRowBytes(config, width) * height;
  1333             maxLevels += 1;
  1337     // nothing to build
  1338     if (0 == maxLevels) {
  1339         return;
  1342     SkBitmap srcBM(*this);
  1343     srcBM.lockPixels();
  1344     if (!srcBM.readyToDraw()) {
  1345         return;
  1348     MipMap* mm = MipMap::Alloc(maxLevels, size);
  1349     if (NULL == mm) {
  1350         return;
  1353     MipLevel*   level = mm->levels();
  1354     uint8_t*    addr = (uint8_t*)mm->pixels();
  1355     int         width = this->width();
  1356     int         height = this->height();
  1357     uint32_t    rowBytes;
  1358     SkBitmap    dstBM;
  1360     for (int i = 0; i < maxLevels; i++) {
  1361         width >>= 1;
  1362         height >>= 1;
  1363         rowBytes = SkToU32(ComputeRowBytes(config, width));
  1365         level[i].fPixels   = addr;
  1366         level[i].fWidth    = width;
  1367         level[i].fHeight   = height;
  1368         level[i].fRowBytes = rowBytes;
  1370         dstBM.setConfig(config, width, height, rowBytes);
  1371         dstBM.setPixels(addr);
  1373         srcBM.lockPixels();
  1374         for (int y = 0; y < height; y++) {
  1375             for (int x = 0; x < width; x++) {
  1376                 proc(&dstBM, x, y, srcBM);
  1379         srcBM.unlockPixels();
  1381         srcBM = dstBM;
  1382         addr += height * rowBytes;
  1384     SkASSERT(addr == (uint8_t*)mm->pixels() + size);
  1385     fMipMap = mm;
  1388 bool SkBitmap::hasMipMap() const {
  1389     return fMipMap != NULL;
  1392 int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
  1393     if (NULL == fMipMap) {
  1394         return 0;
  1397     int level = ComputeMipLevel(sx, sy) >> 16;
  1398     SkASSERT(level >= 0);
  1399     if (level <= 0) {
  1400         return 0;
  1403     if (level >= fMipMap->fLevelCount) {
  1404         level = fMipMap->fLevelCount - 1;
  1406     if (dst) {
  1407         const MipLevel& mip = fMipMap->levels()[level - 1];
  1408         dst->setConfig((SkBitmap::Config)this->config(),
  1409                        mip.fWidth, mip.fHeight, mip.fRowBytes);
  1410         dst->setPixels(mip.fPixels);
  1412     return level;
  1415 SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
  1416     sx = SkAbs32(sx);
  1417     sy = SkAbs32(sy);
  1418     if (sx < sy) {
  1419         sx = sy;
  1421     if (sx < SK_Fixed1) {
  1422         return 0;
  1424     int clz = SkCLZ(sx);
  1425     SkASSERT(clz >= 1 && clz <= 15);
  1426     return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
  1429 ///////////////////////////////////////////////////////////////////////////////
  1431 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
  1432                            int alphaRowBytes) {
  1433     SkASSERT(alpha != NULL);
  1434     SkASSERT(alphaRowBytes >= src.width());
  1436     SkBitmap::Config config = src.config();
  1437     int              w = src.width();
  1438     int              h = src.height();
  1439     size_t           rb = src.rowBytes();
  1441     SkAutoLockPixels alp(src);
  1442     if (!src.readyToDraw()) {
  1443         // zero out the alpha buffer and return
  1444         while (--h >= 0) {
  1445             memset(alpha, 0, w);
  1446             alpha += alphaRowBytes;
  1448         return false;
  1451     if (SkBitmap::kA8_Config == config && !src.isOpaque()) {
  1452         const uint8_t* s = src.getAddr8(0, 0);
  1453         while (--h >= 0) {
  1454             memcpy(alpha, s, w);
  1455             s += rb;
  1456             alpha += alphaRowBytes;
  1458     } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) {
  1459         const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
  1460         while (--h >= 0) {
  1461             for (int x = 0; x < w; x++) {
  1462                 alpha[x] = SkGetPackedA32(s[x]);
  1464             s = (const SkPMColor*)((const char*)s + rb);
  1465             alpha += alphaRowBytes;
  1467     } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) {
  1468         const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
  1469         while (--h >= 0) {
  1470             for (int x = 0; x < w; x++) {
  1471                 alpha[x] = SkPacked4444ToA32(s[x]);
  1473             s = (const SkPMColor16*)((const char*)s + rb);
  1474             alpha += alphaRowBytes;
  1476     } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) {
  1477         SkColorTable* ct = src.getColorTable();
  1478         if (ct) {
  1479             const SkPMColor* SK_RESTRICT table = ct->lockColors();
  1480             const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
  1481             while (--h >= 0) {
  1482                 for (int x = 0; x < w; x++) {
  1483                     alpha[x] = SkGetPackedA32(table[s[x]]);
  1485                 s += rb;
  1486                 alpha += alphaRowBytes;
  1488             ct->unlockColors();
  1490     } else {    // src is opaque, so just fill alpha[] with 0xFF
  1491         memset(alpha, 0xFF, h * alphaRowBytes);
  1493     return true;
  1496 #include "SkPaint.h"
  1497 #include "SkMaskFilter.h"
  1498 #include "SkMatrix.h"
  1500 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
  1501                             Allocator *allocator, SkIPoint* offset) const {
  1502     SkDEBUGCODE(this->validate();)
  1504     SkBitmap    tmpBitmap;
  1505     SkMatrix    identity;
  1506     SkMask      srcM, dstM;
  1508     srcM.fBounds.set(0, 0, this->width(), this->height());
  1509     srcM.fRowBytes = SkAlign4(this->width());
  1510     srcM.fFormat = SkMask::kA8_Format;
  1512     SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
  1514     // compute our (larger?) dst bounds if we have a filter
  1515     if (NULL != filter) {
  1516         identity.reset();
  1517         srcM.fImage = NULL;
  1518         if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
  1519             goto NO_FILTER_CASE;
  1521         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
  1522     } else {
  1523     NO_FILTER_CASE:
  1524         tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
  1525                        srcM.fRowBytes);
  1526         if (!tmpBitmap.allocPixels(allocator, NULL)) {
  1527             // Allocation of pixels for alpha bitmap failed.
  1528             SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
  1529                     tmpBitmap.width(), tmpBitmap.height());
  1530             return false;
  1532         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
  1533         if (offset) {
  1534             offset->set(0, 0);
  1536         tmpBitmap.swap(*dst);
  1537         return true;
  1539     srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
  1540     SkAutoMaskFreeImage srcCleanup(srcM.fImage);
  1542     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
  1543     if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
  1544         goto NO_FILTER_CASE;
  1546     SkAutoMaskFreeImage dstCleanup(dstM.fImage);
  1548     tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
  1549                    dstM.fBounds.height(), dstM.fRowBytes);
  1550     if (!tmpBitmap.allocPixels(allocator, NULL)) {
  1551         // Allocation of pixels for alpha bitmap failed.
  1552         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
  1553                 tmpBitmap.width(), tmpBitmap.height());
  1554         return false;
  1556     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
  1557     if (offset) {
  1558         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
  1560     SkDEBUGCODE(tmpBitmap.validate();)
  1562     tmpBitmap.swap(*dst);
  1563     return true;
  1566 ///////////////////////////////////////////////////////////////////////////////
  1568 enum {
  1569     SERIALIZE_PIXELTYPE_NONE,
  1570     SERIALIZE_PIXELTYPE_REF_DATA
  1571 };
  1573 void SkBitmap::flatten(SkWriteBuffer& buffer) const {
  1574     fInfo.flatten(buffer);
  1575     buffer.writeInt(fRowBytes);
  1577     if (fPixelRef) {
  1578         if (fPixelRef->getFactory()) {
  1579             buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA);
  1580             buffer.writeInt(fPixelRefOrigin.fX);
  1581             buffer.writeInt(fPixelRefOrigin.fY);
  1582             buffer.writeFlattenable(fPixelRef);
  1583             return;
  1585         // if we get here, we can't record the pixels
  1586         buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
  1587     } else {
  1588         buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
  1592 void SkBitmap::unflatten(SkReadBuffer& buffer) {
  1593     this->reset();
  1595     SkImageInfo info;
  1596     info.unflatten(buffer);
  1597     size_t rowBytes = buffer.readInt();
  1598     if (!buffer.validate((info.width() >= 0) && (info.height() >= 0) &&
  1599                          SkColorTypeIsValid(info.fColorType) &&
  1600                          SkAlphaTypeIsValid(info.fAlphaType) &&
  1601                          validate_alphaType(info.fColorType, info.fAlphaType) &&
  1602                          info.validRowBytes(rowBytes))) {
  1603         return;
  1606     bool configIsValid = this->setConfig(info, rowBytes);
  1607     buffer.validate(configIsValid);
  1609     int reftype = buffer.readInt();
  1610     if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) ||
  1611                         (SERIALIZE_PIXELTYPE_NONE == reftype))) {
  1612         switch (reftype) {
  1613             case SERIALIZE_PIXELTYPE_REF_DATA: {
  1614                 SkIPoint origin;
  1615                 origin.fX = buffer.readInt();
  1616                 origin.fY = buffer.readInt();
  1617                 size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel();
  1618                 SkPixelRef* pr = buffer.readPixelRef();
  1619                 if (!buffer.validate((NULL == pr) ||
  1620                        (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) {
  1621                     origin.setZero();
  1623                 SkSafeUnref(this->setPixelRef(pr, origin));
  1624                 break;
  1626             case SERIALIZE_PIXELTYPE_NONE:
  1627                 break;
  1628             default:
  1629                 SkDEBUGFAIL("unrecognized pixeltype in serialized data");
  1630                 sk_throw();
  1635 ///////////////////////////////////////////////////////////////////////////////
  1637 SkBitmap::RLEPixels::RLEPixels(int width, int height) {
  1638     fHeight = height;
  1639     fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
  1642 SkBitmap::RLEPixels::~RLEPixels() {
  1643     sk_free(fYPtrs);
  1646 ///////////////////////////////////////////////////////////////////////////////
  1648 #ifdef SK_DEBUG
  1649 void SkBitmap::validate() const {
  1650     fInfo.validate();
  1652     // ImageInfo may not require this, but Bitmap ensures that opaque-only
  1653     // colorTypes report opaque for their alphatype
  1654     if (kRGB_565_SkColorType == fInfo.colorType()) {
  1655         SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
  1658     SkASSERT(fInfo.validRowBytes(fRowBytes));
  1659     uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag;
  1660 #ifdef SK_BUILD_FOR_ANDROID
  1661     allFlags |= kHasHardwareMipMap_Flag;
  1662 #endif
  1663     SkASSERT(fFlags <= allFlags);
  1664     SkASSERT(fPixelLockCount >= 0);
  1666     if (fPixels) {
  1667         SkASSERT(fPixelRef);
  1668         SkASSERT(fPixelLockCount > 0);
  1669         SkASSERT(fPixelRef->isLocked());
  1670         SkASSERT(fPixelRef->rowBytes() == fRowBytes);
  1671         SkASSERT(fPixelRefOrigin.fX >= 0);
  1672         SkASSERT(fPixelRefOrigin.fY >= 0);
  1673         SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
  1674         SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOrigin.fY);
  1675         SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
  1676     } else {
  1677         SkASSERT(NULL == fColorTable);
  1680 #endif
  1682 #ifndef SK_IGNORE_TO_STRING
  1683 void SkBitmap::toString(SkString* str) const {
  1685     static const char* gConfigNames[kConfigCount] = {
  1686         "NONE", "A8", "INDEX8", "565", "4444", "8888"
  1687     };
  1689     str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
  1690                  gConfigNames[this->config()]);
  1692     str->append(" (");
  1693     if (this->isOpaque()) {
  1694         str->append("opaque");
  1695     } else {
  1696         str->append("transparent");
  1698     if (this->isImmutable()) {
  1699         str->append(", immutable");
  1700     } else {
  1701         str->append(", not-immutable");
  1703     str->append(")");
  1705     SkPixelRef* pr = this->pixelRef();
  1706     if (NULL == pr) {
  1707         // show null or the explicit pixel address (rare)
  1708         str->appendf(" pixels:%p", this->getPixels());
  1709     } else {
  1710         const char* uri = pr->getURI();
  1711         if (NULL != uri) {
  1712             str->appendf(" uri:\"%s\"", uri);
  1713         } else {
  1714             str->appendf(" pixelref:%p", pr);
  1718     str->append(")");
  1720 #endif
  1722 ///////////////////////////////////////////////////////////////////////////////
  1724 #ifdef SK_DEBUG
  1725 void SkImageInfo::validate() const {
  1726     SkASSERT(fWidth >= 0);
  1727     SkASSERT(fHeight >= 0);
  1728     SkASSERT(SkColorTypeIsValid(fColorType));
  1729     SkASSERT(SkAlphaTypeIsValid(fAlphaType));
  1731 #endif

mercurial