diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h index f53a0a7e45..af0c8b87e7 100644 --- a/include/core/SkBitmap.h +++ b/include/core/SkBitmap.h @@ -18,6 +18,7 @@ struct SkIRect; struct SkRect; class SkPaint; class SkPixelRef; +class SkPixelRefFactory; class SkRegion; class SkString; @@ -249,6 +250,35 @@ public: bool setConfig(const SkImageInfo& info, size_t rowBytes = 0); + /** + * Allocate a pixelref to match the specified image info. If the Factory + * is non-null, call it to allcoate the pixelref. If the ImageInfo requires + * a colortable, then ColorTable must be non-null, and will be ref'd. + * On failure, the bitmap will be set to empty and return false. + */ + bool allocPixels(const SkImageInfo&, SkPixelRefFactory*, SkColorTable*); + + /** + * Allocate a pixelref to match the specified image info, using the default + * allocator. + * On success, the bitmap's pixels will be "locked", and return true. + * On failure, the bitmap will be set to empty and return false. + */ + bool allocPixels(const SkImageInfo& info) { + return this->allocPixels(info, NULL, NULL); + } + + /** + * Install a pixelref that wraps the specified pixels and rowBytes, and + * optional ReleaseProc and context. When the pixels are no longer + * referenced, if ReleaseProc is not null, it will be called with the + * pixels and context as parameters. + * On failure, the bitmap will be set to empty and return false. + */ + bool installPixels(const SkImageInfo&, void* pixels, size_t rowBytes, + void (*ReleaseProc)(void* addr, void* context), + void* context); + /** * If the bitmap's config can be represented as SkImageInfo, return true, * and if info is not-null, set it to the bitmap's info. If it cannot be @@ -637,7 +667,7 @@ public: */ class HeapAllocator : public Allocator { public: - virtual bool allocPixelRef(SkBitmap*, SkColorTable*); + virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE; }; class RLEPixels { diff --git a/include/core/SkMallocPixelRef.h b/include/core/SkMallocPixelRef.h index 6642af57bb..4607fa2843 100644 --- a/include/core/SkMallocPixelRef.h +++ b/include/core/SkMallocPixelRef.h @@ -79,6 +79,12 @@ public: void* getAddr() const { return fStorage; } + class PRFactory : public SkPixelRefFactory { + public: + virtual SkPixelRef* create(const SkImageInfo&, + SkColorTable*) SK_OVERRIDE; + }; + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef) protected: diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h index fc0feb042a..e65f4a04c5 100644 --- a/include/core/SkPixelRef.h +++ b/include/core/SkPixelRef.h @@ -364,4 +364,15 @@ private: typedef SkFlattenable INHERITED; }; +class SkPixelRefFactory : public SkRefCnt { +public: + /** + * Allocate a new pixelref matching the specified ImageInfo, allocating + * the memory for the pixels. If the ImageInfo requires a ColorTable, + * the pixelref will ref() the colortable. + * On failure return NULL. + */ + virtual SkPixelRef* create(const SkImageInfo&, SkColorTable*) = 0; +}; + #endif diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 2464d5d596..9227906eab 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -488,13 +488,67 @@ void SkBitmap::setPixels(void* p, SkColorTable* ctable) { bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) { HeapAllocator stdalloc; - + if (NULL == allocator) { allocator = &stdalloc; } return allocator->allocPixelRef(this, ctable); } +/////////////////////////////////////////////////////////////////////////////// + +static bool reset_return_false(SkBitmap* bm) { + bm->reset(); + return false; +} + +bool SkBitmap::allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory, + SkColorTable* ctable) { + if (kIndex_8_SkColorType == info.fColorType && NULL == ctable) { + return reset_return_false(this); + } + if (!this->setConfig(info)) { + return reset_return_false(this); + } + + SkMallocPixelRef::PRFactory defaultFactory; + if (NULL == factory) { + factory = &defaultFactory; + } + + SkPixelRef* pr = factory->create(info, ctable); + if (NULL == pr) { + return reset_return_false(this); + } + this->setPixelRef(pr)->unref(); + + // TODO: lockPixels could/should return bool or void*/NULL + this->lockPixels(); + if (NULL == this->getPixels()) { + return reset_return_false(this); + } + return true; +} + +bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb, + void (*releaseProc)(void* addr, void* context), + void* context) { + if (!this->setConfig(info)) { + this->reset(); + return false; + } + + SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, NULL, pixels, + releaseProc, context); + if (!pr) { + this->reset(); + return false; + } + + this->setPixelRef(pr)->unref(); + return true; +} + void SkBitmap::freePixels() { // if we're gonna free the pixels, we certainly need to free the mipmap this->freeMipMap(); diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 0570fd9afd..4b4f45317f 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -164,10 +164,8 @@ void SkBitmapDevice::writePixels(const SkBitmap& bitmap, drawSprite = false; } else { // we convert to a temporary bitmap and draw that as a sprite - dstBmp.setConfig(SkBitmap::kARGB_8888_Config, - spriteRect.width(), - spriteRect.height()); - if (!dstBmp.allocPixels()) { + if (!dstBmp.allocPixels(SkImageInfo::MakeN32Premul(spriteRect.width(), + spriteRect.height()))) { return; } drawSprite = true; diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 0c9e9d66b6..c08ae26159 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -92,9 +92,8 @@ bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y, SkBitmap tmp; SkBitmap* bmp; if (bitmap->isNull()) { - tmp.setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(), - bitmap->height()); - if (!tmp.allocPixels()) { + if (!tmp.allocPixels(SkImageInfo::MakeN32Premul(bitmap->width(), + bitmap->height()))) { return false; } bmp = &tmp; diff --git a/src/core/SkMallocPixelRef.cpp b/src/core/SkMallocPixelRef.cpp index 50357e469b..c591ffb37d 100644 --- a/src/core/SkMallocPixelRef.cpp +++ b/src/core/SkMallocPixelRef.cpp @@ -238,3 +238,11 @@ SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer) this->setPreLocked(fStorage, fRB, fCTable); } + +/////////////////////////////////////////////////////////////////////////////// + +SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, + SkColorTable* ctable) { + return SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), ctable); +} + diff --git a/src/core/SkOrderedReadBuffer.cpp b/src/core/SkOrderedReadBuffer.cpp index 69c60cbe09..1ebaac4da8 100644 --- a/src/core/SkOrderedReadBuffer.cpp +++ b/src/core/SkOrderedReadBuffer.cpp @@ -252,8 +252,7 @@ void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) { } } // Could not read the SkBitmap. Use a placeholder bitmap. - bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height); - bitmap->allocPixels(); + bitmap->allocPixels(SkImageInfo::MakeN32Premul(width, height)); bitmap->eraseColor(SK_ColorRED); } diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp index f15a13dd8b..4bcb32031b 100644 --- a/src/effects/SkAlphaThresholdFilter.cpp +++ b/src/effects/SkAlphaThresholdFilter.cpp @@ -323,8 +323,7 @@ bool SkAlphaThresholdFilterImpl::onFilterImage(Proxy*, const SkBitmap& src, } dst->setConfig(src.config(), src.width(), src.height()); - dst->allocPixels(); - if (!dst->getPixels()) { + if (!dst->allocPixels()) { return false; } diff --git a/src/effects/SkBicubicImageFilter.cpp b/src/effects/SkBicubicImageFilter.cpp index 96d46aa7ce..8b89a343d0 100644 --- a/src/effects/SkBicubicImageFilter.cpp +++ b/src/effects/SkBicubicImageFilter.cpp @@ -108,8 +108,7 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy, return false; } result->setConfig(src.config(), dstIRect.width(), dstIRect.height()); - result->allocPixels(); - if (!result->getPixels()) { + if (!result->allocPixels()) { return false; } diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp index 7f3f532079..3e60c9bb87 100644 --- a/src/effects/SkBlurImageFilter.cpp +++ b/src/effects/SkBlurImageFilter.cpp @@ -160,8 +160,7 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy, dst->setConfig(src.config(), srcBounds.width(), srcBounds.height()); dst->getBounds(&dstBounds); - dst->allocPixels(); - if (!dst->getPixels()) { + if (!dst->allocPixels()) { return false; } diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index 8264ec8e06..6ad46badb9 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -229,8 +229,7 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy, } dst->setConfig(color.config(), bounds.width(), bounds.height()); - dst->allocPixels(); - if (!dst->getPixels()) { + if (!dst->allocPixels()) { return false; } diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index b24a91eb44..81c62fe6dc 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -952,8 +952,7 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy, } dst->setConfig(src.config(), bounds.width(), bounds.height()); - dst->allocPixels(); - if (!dst->getPixels()) { + if (!dst->allocPixels()) { return false; } diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp index 77ce9cb348..cdf8baf682 100644 --- a/src/effects/SkPerlinNoiseShader.cpp +++ b/src/effects/SkPerlinNoiseShader.cpp @@ -241,8 +241,7 @@ public: { if (!fPermutationsBitmap) { fPermutationsBitmap = SkNEW(SkBitmap); - fPermutationsBitmap->setConfig(SkBitmap::kA8_Config, kBlockSize, 1); - fPermutationsBitmap->allocPixels(); + fPermutationsBitmap->allocPixels(SkImageInfo::MakeA8(kBlockSize, 1)); uint8_t* bitmapPixels = fPermutationsBitmap->getAddr8(0, 0); memcpy(bitmapPixels, fLatticeSelector, sizeof(uint8_t) * kBlockSize); } @@ -253,8 +252,7 @@ public: { if (!fNoiseBitmap) { fNoiseBitmap = SkNEW(SkBitmap); - fNoiseBitmap->setConfig(SkBitmap::kARGB_8888_Config, kBlockSize, 4); - fNoiseBitmap->allocPixels(); + fNoiseBitmap->allocPixels(SkImageInfo::MakeN32Premul(kBlockSize, 4)); uint32_t* bitmapPixels = fNoiseBitmap->getAddr32(0, 0); memcpy(bitmapPixels, fNoise[0][0], sizeof(uint16_t) * kBlockSize * 4 * 2); } diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp index 203f058364..2872ed14b0 100644 --- a/src/effects/SkTableColorFilter.cpp +++ b/src/effects/SkTableColorFilter.cpp @@ -203,8 +203,7 @@ bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const { if (table) { if (NULL == fBitmap) { SkBitmap* bmp = SkNEW(SkBitmap); - bmp->setConfig(SkBitmap::kA8_Config, 256, 4, 256); - bmp->allocPixels(); + bmp->allocPixels(SkImageInfo::MakeA8(256, 4)); uint8_t* bitmapPixels = bmp->getAddr8(0, 0); int offset = 0; static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag }; diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp index eefc951e7e..504f5a0a35 100644 --- a/src/gpu/GrSWMaskHelper.cpp +++ b/src/gpu/GrSWMaskHelper.cpp @@ -99,8 +99,7 @@ bool GrSWMaskHelper::init(const SkIRect& resultBounds, SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height()); - fBM.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom); - if (!fBM.allocPixels()) { + if (!fBM.allocPixels(SkImageInfo::MakeA8(bounds.fRight, bounds.fBottom))) { return false; } sk_bzero(fBM.getPixels(), fBM.getSafeSize()); diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp index 1fcc4ff18b..66ebe3b1e1 100644 --- a/src/gpu/GrSurface.cpp +++ b/src/gpu/GrSurface.cpp @@ -23,8 +23,10 @@ void GrSurface::asImageInfo(SkImageInfo* info) const { bool GrSurface::savePixels(const char* filename) { SkBitmap bm; - bm.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height()); - bm.allocPixels(); + if (!bm.allocPixels(SkImageInfo::MakeN32Premul(this->width(), + this->height()))) { + return false; + } bool result = readPixels(0, 0, this->width(), this->height(), kSkia8888_GrPixelConfig, bm.getPixels()); diff --git a/src/gpu/SkGrPixelRef.cpp b/src/gpu/SkGrPixelRef.cpp index 8a16437780..fdf94870cc 100644 --- a/src/gpu/SkGrPixelRef.cpp +++ b/src/gpu/SkGrPixelRef.cpp @@ -178,8 +178,7 @@ bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { top = 0; height = fSurface->height(); } - dst->setConfig(SkBitmap::kARGB_8888_Config, width, height); - if (!dst->allocPixels()) { + if (!dst->allocPixels(SkImageInfo::MakeN32Premul(width, height))) { SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n"); return false; } diff --git a/src/images/SkMovie_gif.cpp b/src/images/SkMovie_gif.cpp index b6d068a391..decefd5acc 100644 --- a/src/images/SkMovie_gif.cpp +++ b/src/images/SkMovie_gif.cpp @@ -364,13 +364,11 @@ bool SkGIFMovie::onGetBitmap(SkBitmap* bm) startIndex = 0; // create bitmap - bm->setConfig(SkBitmap::kARGB_8888_Config, width, height, 0); - if (!bm->allocPixels(NULL)) { + if (!bm->allocPixels(SkImageInfo::MakeN32Premul(width, height))) { return false; } // create bitmap for backup - fBackup.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0); - if (!fBackup.allocPixels(NULL)) { + if (!fBackup.allocPixels(SkImageInfo::MakeN32Premul(width, height))) { return false; } } else if (startIndex > fCurrIndex) { diff --git a/src/lazy/SkDiscardablePixelRef.cpp b/src/lazy/SkDiscardablePixelRef.cpp index abd80f2e0a..0878d00335 100644 --- a/src/lazy/SkDiscardablePixelRef.cpp +++ b/src/lazy/SkDiscardablePixelRef.cpp @@ -89,7 +89,7 @@ bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, } SkASSERT(dst->config() != SkBitmap::kNo_Config); if (dst->empty()) { // Use a normal pixelref. - return dst->allocPixels(NULL, NULL); + return dst->allocPixels(); } SkAutoTUnref ref( SkNEW_ARGS(SkDiscardablePixelRef, diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index a9ad49e9ee..ff83aadeee 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -2250,13 +2250,11 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, // the image. Avoiding alpha will reduce the pdf size and generation // CPU time some. - perspectiveBitmap.setConfig( - SkBitmap::kARGB_8888_Config, - SkScalarCeilToInt( - physicalPerspectiveOutline.getBounds().width()), - SkScalarCeilToInt( - physicalPerspectiveOutline.getBounds().height())); - perspectiveBitmap.allocPixels(); + const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().width()); + const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().height()); + if (!perspectiveBitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) { + return; + } perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); SkBitmapDevice device(perspectiveBitmap); diff --git a/src/utils/SkPDFRasterizer.cpp b/src/utils/SkPDFRasterizer.cpp index 68a31196ec..66634804bc 100644 --- a/src/utils/SkPDFRasterizer.cpp +++ b/src/utils/SkPDFRasterizer.cpp @@ -50,8 +50,7 @@ bool SkPopplerRasterizePDF(SkStream* pdf, SkBitmap* output) { char *imgData = image.data(); SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); - if (!bitmap.allocPixels()) { + if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height))) { return false; } bitmap.eraseColor(SK_ColorWHITE); diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp index e491f3b8a7..1c3e26e643 100644 --- a/src/utils/debugger/SkDebugCanvas.cpp +++ b/src/utils/debugger/SkDebugCanvas.cpp @@ -74,8 +74,7 @@ void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) { int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) { SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); - bitmap.allocPixels(); + bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1)); SkCanvas canvas(bitmap); canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y)); diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp index 0677b7bc30..1b52ba31a6 100644 --- a/src/utils/mac/SkCreateCGImageRef.cpp +++ b/src/utils/mac/SkCreateCGImageRef.cpp @@ -209,8 +209,9 @@ bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) { int h = (int)CGRectGetHeight(bounds); SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h); - bitmap.allocPixels(); + if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) { + return false; + } bitmap.eraseColor(SK_ColorWHITE); size_t bitsPerComponent;