Index: src/effects/gradients/SkGradientShader.cpp |
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp |
index 5b0b9c763da184ec9b732112cbb2d76ed02ece26..ae70ddd878ea9a7f162cd3c7b5746ff9410b47c0 100644 |
--- a/src/effects/gradients/SkGradientShader.cpp |
+++ b/src/effects/gradients/SkGradientShader.cpp |
@@ -15,8 +15,6 @@ |
SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { |
SkASSERT(desc.fCount > 1); |
- fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return |
- |
fMapper = desc.fMapper; |
SkSafeRef(fMapper); |
fGradFlags = SkToU8(desc.fFlags); |
@@ -26,10 +24,6 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { |
fTileMode = desc.fTileMode; |
fTileProc = gTileProcs[desc.fTileMode]; |
- fCache16 = fCache16Storage = NULL; |
- fCache32 = NULL; |
- fCache32PixelRef = NULL; |
- |
/* Note: we let the caller skip the first and/or last position. |
i.e. pos[0] = 0.3, pos[1] = 0.7 |
In these cases, we insert dummy entries to ensure that the final data |
@@ -144,14 +138,8 @@ static uint32_t unpack_flags(uint32_t packed) { |
} |
SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buffer) { |
- fCacheAlpha = 256; |
- |
fMapper = buffer.readUnitMapper(); |
- fCache16 = fCache16Storage = NULL; |
- fCache32 = NULL; |
- fCache32PixelRef = NULL; |
- |
int colorCount = fColorCount = buffer.getArrayCount(); |
if (colorCount > kColorStorageCount) { |
size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) * colorCount; |
@@ -186,10 +174,6 @@ SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf |
} |
SkGradientShaderBase::~SkGradientShaderBase() { |
- if (fCache16Storage) { |
- sk_free(fCache16Storage); |
- } |
- SkSafeUnref(fCache32PixelRef); |
if (fOrigColors != fStorage) { |
sk_free(fOrigColors); |
} |
@@ -197,7 +181,6 @@ SkGradientShaderBase::~SkGradientShaderBase() { |
} |
void SkGradientShaderBase::initCommon() { |
- fFlags = 0; |
unsigned colorAlpha = 0xFF; |
for (int i = 0; i < fColorCount; i++) { |
colorAlpha &= SkColorGetA(fOrigColors[i]); |
@@ -224,6 +207,53 @@ bool SkGradientShaderBase::isOpaque() const { |
return fColorsAreOpaque; |
} |
+bool SkGradientShaderBase::validContext(const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix, SkMatrix* totalInverse) const { |
+ // Make sure we can use totalInverse as a cache. |
+ SkMatrix totalInverseLocal; |
+ if (NULL == totalInverse) { |
+ totalInverse = &totalInverseLocal; |
+ } |
+ |
+ if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { |
+ return false; |
+ } |
+ |
+ SkMatrix dstToIndex; |
+ return dstToIndex.setConcat(fPtsToUnit, *totalInverse); |
+} |
+ |
+size_t SkGradientShaderBase::contextSize() const { |
scroggo
2014/04/02 20:16:53
Is it possible to create an SkGradientShaderBase?
Dominik Grewe
2014/04/03 12:12:59
No. Removed.
|
+ return sizeof(GradientShaderBaseContext); |
+} |
+ |
+SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext( |
+ const SkGradientShaderBase& shader, const SkBitmap& device, |
+ const SkPaint& paint, const SkMatrix& matrix) |
+ : INHERITED(shader, device, paint, matrix), fCache(this->getPaintAlpha()) |
scroggo
2014/04/02 20:16:53
nit: fCache should go on its own line.
Dominik Grewe
2014/04/03 12:12:59
Done.
|
+{ |
+ const SkMatrix& inverse = this->getTotalInverse(); |
+ |
+ SkAssertResult(fDstToIndex.setConcat(shader.fPtsToUnit, inverse)); |
scroggo
2014/04/02 20:16:53
I don't think you can assert this result unless yo
Dominik Grewe
2014/04/03 12:12:59
The constructor of SkShader::Context asserts that
|
+ |
+ fDstToIndexProc = fDstToIndex.getMapXYProc(); |
+ fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToIndex); |
+ |
+ // now convert our colors in to PMColors |
+ unsigned paintAlpha = this->getPaintAlpha(); |
+ |
+ fFlags = this->INHERITED::getFlags(); |
+ if (shader.fColorsAreOpaque && paintAlpha == 0xFF) { |
+ fFlags |= kOpaqueAlpha_Flag; |
+ } |
+ // we can do span16 as long as our individual colors are opaque, |
+ // regardless of the paint's alpha |
+ if (shader.fColorsAreOpaque) { |
+ fFlags |= kHasSpan16_Flag; |
+ } |
+} |
+ |
+#if 0 |
bool SkGradientShaderBase::setContext(const SkBitmap& device, |
const SkPaint& paint, |
const SkMatrix& matrix) { |
@@ -258,20 +288,21 @@ bool SkGradientShaderBase::setContext(const SkBitmap& device, |
this->setCacheAlpha(paintAlpha); |
return true; |
} |
+#endif |
-void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const { |
- // if the new alpha differs from the previous time we were called, inval our cache |
- // this will trigger the cache to be rebuilt. |
- // we don't care about the first time, since the cache ptrs will already be NULL |
- if (fCacheAlpha != alpha) { |
- fCache16 = NULL; // inval the cache |
- fCache32 = NULL; // inval the cache |
- fCacheAlpha = alpha; // record the new alpha |
- // inform our subclasses |
- if (fCache32PixelRef) { |
- fCache32PixelRef->notifyPixelsChanged(); |
- } |
- } |
+ |
+SkGradientShaderBase::GradientShaderCache::GradientShaderCache(U8CPU alpha) { |
+ // Invalidate the cache. |
scroggo
2014/04/02 20:16:53
I don't think this comment is appropriate, given t
Dominik Grewe
2014/04/03 12:12:59
Maybe "invalidate" is the wrong term, but I wanted
|
+ fCache16 = NULL; |
+ fCache32 = NULL; |
+ fCache16Storage = NULL; |
+ fCache32PixelRef = NULL; |
+ fCacheAlpha = alpha; |
+} |
+ |
+SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { |
+ sk_free(fCache16Storage); |
+ SkSafeUnref(fCache32PixelRef); |
} |
#define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) |
@@ -280,8 +311,8 @@ void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const { |
build a 16bit table as long as the original colors are opaque, even if the |
paint specifies a non-opaque alpha. |
*/ |
-void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1, |
- int count) { |
+void SkGradientShaderBase::GradientShaderCache::Build16bitCache( |
+ uint16_t cache[], SkColor c0, SkColor c1, int count) { |
SkASSERT(count > 1); |
SkASSERT(SkColorGetA(c0) == 0xFF); |
SkASSERT(SkColorGetA(c1) == 0xFF); |
@@ -329,8 +360,9 @@ void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor |
*/ |
typedef uint32_t SkUFixed; |
-void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1, |
- int count, U8CPU paintAlpha, uint32_t gradFlags) { |
+void SkGradientShaderBase::GradientShaderCache::Build32bitCache( |
+ SkPMColor cache[], SkColor c0, SkColor c1, |
+ int count, U8CPU paintAlpha, uint32_t gradFlags) { |
SkASSERT(count > 1); |
// need to apply paintAlpha to our two endpoints |
@@ -473,7 +505,8 @@ static inline U16CPU bitsTo16(unsigned x, const unsigned bits) { |
return 0; |
} |
-const uint16_t* SkGradientShaderBase::getCache16() const { |
+const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16( |
+ const SkGradientShaderBase& shader) { |
if (fCache16 == NULL) { |
// double the count for dither entries |
const int entryCount = kCache16Count * 2; |
@@ -483,27 +516,28 @@ const uint16_t* SkGradientShaderBase::getCache16() const { |
fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
} |
fCache16 = fCache16Storage; |
- if (fColorCount == 2) { |
- Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], |
+ if (shader.fColorCount == 2) { |
+ Build16bitCache(fCache16, shader.fOrigColors[0], shader.fOrigColors[1], |
kCache16Count); |
} else { |
- Rec* rec = fRecs; |
+ Rec* rec = shader.fRecs; |
int prevIndex = 0; |
- for (int i = 1; i < fColorCount; i++) { |
+ for (int i = 1; i < shader.fColorCount; i++) { |
int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; |
SkASSERT(nextIndex < kCache16Count); |
if (nextIndex > prevIndex) |
- Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1); |
+ Build16bitCache(fCache16 + prevIndex, shader.fOrigColors[i-1], |
+ shader.fOrigColors[i], nextIndex - prevIndex + 1); |
prevIndex = nextIndex; |
} |
} |
- if (fMapper) { |
+ if (shader.fMapper) { |
fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
uint16_t* linear = fCache16; // just computed linear data |
uint16_t* mapped = fCache16Storage; // storage for mapped data |
- SkUnitMapper* map = fMapper; |
+ SkUnitMapper* map = shader.fMapper; |
for (int i = 0; i < kCache16Count; i++) { |
int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift; |
mapped[i] = linear[index]; |
@@ -516,7 +550,8 @@ const uint16_t* SkGradientShaderBase::getCache16() const { |
return fCache16; |
} |
-const SkPMColor* SkGradientShaderBase::getCache32() const { |
+const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32( |
+ const SkGradientShaderBase& shader) { |
if (fCache32 == NULL) { |
SkImageInfo info; |
info.fWidth = kCache32Count; |
@@ -528,29 +563,29 @@ const SkPMColor* SkGradientShaderBase::getCache32() const { |
fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); |
} |
fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); |
- if (fColorCount == 2) { |
- Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], |
- kCache32Count, fCacheAlpha, fGradFlags); |
+ if (shader.fColorCount == 2) { |
+ Build32bitCache(fCache32, shader.fOrigColors[0], shader.fOrigColors[1], |
+ kCache32Count, fCacheAlpha, shader.fGradFlags); |
} else { |
- Rec* rec = fRecs; |
+ Rec* rec = shader.fRecs; |
int prevIndex = 0; |
- for (int i = 1; i < fColorCount; i++) { |
+ for (int i = 1; i < shader.fColorCount; i++) { |
int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; |
SkASSERT(nextIndex < kCache32Count); |
if (nextIndex > prevIndex) |
- Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1], |
- fOrigColors[i], nextIndex - prevIndex + 1, |
- fCacheAlpha, fGradFlags); |
+ Build32bitCache(fCache32 + prevIndex, shader.fOrigColors[i-1], |
+ shader.fOrigColors[i], nextIndex - prevIndex + 1, |
+ fCacheAlpha, shader.fGradFlags); |
prevIndex = nextIndex; |
} |
} |
- if (fMapper) { |
+ if (shader.fMapper) { |
SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL); |
SkPMColor* linear = fCache32; // just computed linear data |
SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data |
- SkUnitMapper* map = fMapper; |
+ SkUnitMapper* map = shader.fMapper; |
for (int i = 0; i < kCache32Count; i++) { |
int index = map->mapUnit16((i << 8) | i) >> 8; |
mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; |
@@ -577,14 +612,14 @@ const SkPMColor* SkGradientShaderBase::getCache32() const { |
void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { |
// our caller assumes no external alpha, so we ensure that our cache is |
// built with 0xFF |
- this->setCacheAlpha(0xFF); |
+ GradientShaderCache cache(0xFF); |
// don't have a way to put the mapper into our cache-key yet |
if (fMapper) { |
// force our cahce32pixelref to be built |
- (void)this->getCache32(); |
+ (void)cache.getCache32(*this); |
bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
- bitmap->setPixelRef(fCache32PixelRef); |
+ bitmap->setPixelRef(cache.getCache32PixelRef()); |
return; |
} |
@@ -623,9 +658,9 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { |
if (!gCache->find(storage.get(), size, bitmap)) { |
// force our cahce32pixelref to be built |
- (void)this->getCache32(); |
+ (void)cache.getCache32(*this); |
bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
- bitmap->setPixelRef(fCache32PixelRef); |
+ bitmap->setPixelRef(cache.getCache32PixelRef()); |
gCache->add(storage.get(), size, *bitmap); |
} |