diff options
Diffstat (limited to 'chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp')
-rw-r--r-- | chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp | 492 |
1 files changed, 254 insertions, 238 deletions
diff --git a/chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp b/chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp index 5d200d18d35..038044d5618 100644 --- a/chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp +++ b/chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp @@ -12,24 +12,18 @@ #include "SkTwoPointConicalGradient.h" #include "SkSweepGradient.h" -SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { +SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatrix* localMatrix) + : INHERITED(localMatrix) +{ 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); + fGradFlags = SkToU8(desc.fGradFlags); SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); 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 @@ -118,12 +112,14 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { SkFixed dp = SK_Fixed1 / (desc.fCount - 1); SkFixed p = dp; SkFixed scale = (desc.fCount - 1) << 8; // (1 << 24) / dp - for (int i = 1; i < desc.fCount; i++) { + for (int i = 1; i < desc.fCount - 1; i++) { recs->fPos = p; recs->fScale = scale; recs += 1; p += dp; } + recs->fPos = SK_Fixed1; + recs->fScale = scale; } } this->initCommon(); @@ -143,19 +139,21 @@ static uint32_t unpack_flags(uint32_t packed) { return packed >> 4; } -SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { - fCacheAlpha = 256; - - fMapper = buffer.readUnitMapper(); - - fCache16 = fCache16Storage = NULL; - fCache32 = NULL; - fCache32PixelRef = NULL; +SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buffer) { + if (buffer.isVersionLT(SkReadBuffer::kNoUnitMappers_Version)) { + // skip the old SkUnitMapper slot + buffer.skipFlattenable(); + } int colorCount = fColorCount = buffer.getArrayCount(); if (colorCount > kColorStorageCount) { - size_t size = sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec); - fOrigColors = (SkColor*)sk_malloc_throw(size * colorCount); + size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) * colorCount; + if (buffer.validateAvailable(allocSize)) { + fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize)); + } else { + fOrigColors = NULL; + colorCount = fColorCount = 0; + } } else { fOrigColors = fStorage; } @@ -181,18 +179,12 @@ SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) : IN } SkGradientShaderBase::~SkGradientShaderBase() { - if (fCache16Storage) { - sk_free(fCache16Storage); - } - SkSafeUnref(fCache32PixelRef); if (fOrigColors != fStorage) { sk_free(fOrigColors); } - SkSafeUnref(fMapper); } void SkGradientShaderBase::initCommon() { - fFlags = 0; unsigned colorAlpha = 0xFF; for (int i = 0; i < fColorCount; i++) { colorAlpha &= SkColorGetA(fOrigColors[i]); @@ -200,9 +192,8 @@ void SkGradientShaderBase::initCommon() { fColorsAreOpaque = colorAlpha == 0xFF; } -void SkGradientShaderBase::flatten(SkFlattenableWriteBuffer& buffer) const { +void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); - buffer.writeFlattenable(fMapper); buffer.writeColorArray(fOrigColors, fColorCount); buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags)); if (fColorCount > 2) { @@ -215,58 +206,94 @@ void SkGradientShaderBase::flatten(SkFlattenableWriteBuffer& buffer) const { buffer.writeMatrix(fPtsToUnit); } -bool SkGradientShaderBase::isOpaque() const { - return fColorsAreOpaque; +SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor colors[3]) const { + if (fColorCount <= 3) { + memcpy(colors, fOrigColors, fColorCount * sizeof(SkColor)); + } + + if (SkShader::kClamp_TileMode == fTileMode) { + if (2 == fColorCount) { + return kTwo_GpuColorType; + } else if (3 == fColorCount && + (SkScalarAbs( + SkFixedToScalar(fRecs[1].fPos) - SK_ScalarHalf) < SK_Scalar1 / 1000)) { + return kThree_GpuColorType; + } + } + return kTexture_GpuColorType; } -bool SkGradientShaderBase::setContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix) { - if (!this->INHERITED::setContext(device, paint, matrix)) { - return false; +void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst, + SkColor* colorSrc, Rec* recSrc, + int count) { + SkAutoSTArray<8, SkColor> colorsTemp(count); + for (int i = 0; i < count; ++i) { + int offset = count - i - 1; + colorsTemp[i] = colorSrc[offset]; + } + if (count > 2) { + SkAutoSTArray<8, Rec> recsTemp(count); + for (int i = 0; i < count; ++i) { + int offset = count - i - 1; + recsTemp[i].fPos = SK_Fixed1 - recSrc[offset].fPos; + recsTemp[i].fScale = recSrc[offset].fScale; + } + memcpy(recDst, recsTemp.get(), count * sizeof(Rec)); } + memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor)); +} + +void SkGradientShaderBase::flipGradientColors() { + FlipGradientColors(fOrigColors, fRecs, fOrigColors, fRecs, fColorCount); +} + +bool SkGradientShaderBase::isOpaque() const { + return fColorsAreOpaque; +} +SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext( + const SkGradientShaderBase& shader, const ContextRec& rec) + : INHERITED(shader, rec) + , fCache(shader.refCache(getPaintAlpha())) +{ const SkMatrix& inverse = this->getTotalInverse(); - if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) { - // need to keep our set/end context calls balanced. - this->INHERITED::endContext(); - return false; - } + fDstToIndex.setConcat(shader.fPtsToUnit, inverse); fDstToIndexProc = fDstToIndex.getMapXYProc(); - fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex); + fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToIndex); // now convert our colors in to PMColors unsigned paintAlpha = this->getPaintAlpha(); fFlags = this->INHERITED::getFlags(); - if (fColorsAreOpaque && paintAlpha == 0xFF) { + 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 (fColorsAreOpaque) { + if (shader.fColorsAreOpaque) { fFlags |= kHasSpan16_Flag; } +} - this->setCacheAlpha(paintAlpha); - return true; +SkGradientShaderBase::GradientShaderCache::GradientShaderCache( + U8CPU alpha, const SkGradientShaderBase& shader) + : fCacheAlpha(alpha) + , fShader(shader) + , fCache16Inited(false) + , fCache32Inited(false) +{ + // Only initialize the cache in getCache16/32. + fCache16 = NULL; + fCache32 = NULL; + fCache16Storage = NULL; + fCache32PixelRef = NULL; } -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() { + sk_free(fCache16Storage); + SkSafeUnref(fCache32PixelRef); } #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) @@ -275,8 +302,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); @@ -324,8 +351,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 @@ -456,109 +484,90 @@ static inline int SkFixedToFFFF(SkFixed x) { return x - (x >> 16); } -static inline U16CPU bitsTo16(unsigned x, const unsigned bits) { - SkASSERT(x < (1U << bits)); - if (6 == bits) { - return (x << 10) | (x << 4) | (x >> 2); - } - if (8 == bits) { - return (x << 8) | x; - } - sk_throw(); - return 0; +const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16() { + SkOnce(&fCache16Inited, &fCache16Mutex, SkGradientShaderBase::GradientShaderCache::initCache16, + this); + SkASSERT(fCache16); + return fCache16; } -const uint16_t* SkGradientShaderBase::getCache16() const { - if (fCache16 == NULL) { - // double the count for dither entries - const int entryCount = kCache16Count * 2; - const size_t allocSize = sizeof(uint16_t) * entryCount; - - if (fCache16Storage == NULL) { // set the storage and our working ptr - fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); - } - fCache16 = fCache16Storage; - if (fColorCount == 2) { - Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], - kCache16Count); - } else { - Rec* rec = fRecs; - int prevIndex = 0; - for (int i = 1; i < 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); - prevIndex = nextIndex; - } - } - - if (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; - for (int i = 0; i < kCache16Count; i++) { - int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift; - mapped[i] = linear[index]; - mapped[i + kCache16Count] = linear[index + kCache16Count]; - } - sk_free(fCache16); - fCache16 = fCache16Storage; +void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache* cache) { + // double the count for dither entries + const int entryCount = kCache16Count * 2; + const size_t allocSize = sizeof(uint16_t) * entryCount; + + SkASSERT(NULL == cache->fCache16Storage); + cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); + cache->fCache16 = cache->fCache16Storage; + if (cache->fShader.fColorCount == 2) { + Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0], + cache->fShader.fOrigColors[1], kCache16Count); + } else { + Rec* rec = cache->fShader.fRecs; + int prevIndex = 0; + for (int i = 1; i < cache->fShader.fColorCount; i++) { + int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; + SkASSERT(nextIndex < kCache16Count); + + if (nextIndex > prevIndex) + Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOrigColors[i-1], + cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1); + prevIndex = nextIndex; } } - return fCache16; } -const SkPMColor* SkGradientShaderBase::getCache32() const { - if (fCache32 == NULL) { - SkImageInfo info; - info.fWidth = kCache32Count; - info.fHeight = 4; // for our 4 dither rows - info.fAlphaType = kPremul_SkAlphaType; - info.fColorType = kPMColor_SkColorType; +const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() { + SkOnce(&fCache32Inited, &fCache32Mutex, SkGradientShaderBase::GradientShaderCache::initCache32, + this); + SkASSERT(fCache32); + return fCache32; +} - if (NULL == fCache32PixelRef) { - fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); - } - fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); - if (fColorCount == 2) { - Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], - kCache32Count, fCacheAlpha, fGradFlags); - } else { - Rec* rec = fRecs; - int prevIndex = 0; - for (int i = 1; i < 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); - prevIndex = nextIndex; - } +void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache* cache) { + SkImageInfo info; + info.fWidth = kCache32Count; + info.fHeight = 4; // for our 4 dither rows + info.fAlphaType = kPremul_SkAlphaType; + info.fColorType = kN32_SkColorType; + + SkASSERT(NULL == cache->fCache32PixelRef); + cache->fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); + cache->fCache32 = (SkPMColor*)cache->fCache32PixelRef->getAddr(); + if (cache->fShader.fColorCount == 2) { + Build32bitCache(cache->fCache32, cache->fShader.fOrigColors[0], + cache->fShader.fOrigColors[1], kCache32Count, cache->fCacheAlpha, + cache->fShader.fGradFlags); + } else { + Rec* rec = cache->fShader.fRecs; + int prevIndex = 0; + for (int i = 1; i < cache->fShader.fColorCount; i++) { + int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; + SkASSERT(nextIndex < kCache32Count); + + if (nextIndex > prevIndex) + Build32bitCache(cache->fCache32 + prevIndex, cache->fShader.fOrigColors[i-1], + cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1, + cache->fCacheAlpha, cache->fShader.fGradFlags); + prevIndex = nextIndex; } + } +} - if (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; - for (int i = 0; i < kCache32Count; i++) { - int index = map->mapUnit16((i << 8) | i) >> 8; - mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; - mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; - mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; - mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; - } - fCache32PixelRef->unref(); - fCache32PixelRef = newPR; - fCache32 = (SkPMColor*)newPR->getAddr(); - } +/* + * The gradient holds a cache for the most recent value of alpha. Successive + * callers with the same alpha value will share the same cache. + */ +SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::refCache(U8CPU alpha) const { + SkAutoMutexAcquire ama(fCacheMutex); + if (!fCache || fCache->getAlpha() != alpha) { + fCache.reset(SkNEW_ARGS(GradientShaderCache, (alpha, *this))); } - return fCache32; + // Increment the ref counter inside the mutex to ensure the returned pointer is still valid. + // Otherwise, the pointer may have been overwritten on a different thread before the object's + // ref count was incremented. + fCache.get()->ref(); + return fCache; } /* @@ -572,16 +581,7 @@ 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); - - // 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(); - bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1); - bitmap->setPixelRef(fCache32PixelRef); - return; - } + SkAutoTUnref<GradientShaderCache> cache(this->refCache(0xFF)); // build our key: [numColors + colors[] + {positions[]} + flags ] int count = 1 + fColorCount + 1; @@ -618,19 +618,31 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { if (!gCache->find(storage.get(), size, bitmap)) { // force our cahce32pixelref to be built - (void)this->getCache32(); - bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1); - bitmap->setPixelRef(fCache32PixelRef); + (void)cache->getCache32(); + bitmap->setInfo(SkImageInfo::MakeN32Premul(kCache32Count, 1)); + bitmap->setPixelRef(cache->getCache32PixelRef()); gCache->add(storage.get(), size, *bitmap); } } -void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { +void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad) const { if (info) { if (info->fColorCount >= fColorCount) { + SkColor* colorLoc; + Rec* recLoc; + if (flipGrad && (info->fColors || info->fColorOffsets)) { + SkAutoSTArray<8, SkColor> colorStorage(fColorCount); + SkAutoSTArray<8, Rec> recStorage(fColorCount); + colorLoc = colorStorage.get(); + recLoc = recStorage.get(); + FlipGradientColors(colorLoc, recLoc, fOrigColors, fRecs, fColorCount); + } else { + colorLoc = fOrigColors; + recLoc = fRecs; + } if (info->fColors) { - memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor)); + memcpy(info->fColors, colorLoc, fColorCount * sizeof(SkColor)); } if (info->fColorOffsets) { if (fColorCount == 2) { @@ -638,7 +650,7 @@ void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { info->fColorOffsets[1] = SK_Scalar1; } else if (fColorCount > 2) { for (int i = 0; i < fColorCount; ++i) { - info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos); + info->fColorOffsets[i] = SkFixedToScalar(recLoc[i].fPos); } } } @@ -649,7 +661,7 @@ void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { } } -#ifdef SK_DEVELOPER +#ifndef SK_IGNORE_TO_STRING void SkGradientShaderBase::toString(SkString* str) const { str->appendf("%d colors: ", fColorCount); @@ -679,8 +691,6 @@ void SkGradientShaderBase::toString(SkString* str) const { str->append(" "); str->append(gTileModeName[fTileMode]); - // TODO: add "fMapper->toString(str);" when SkUnitMapper::toString is added - this->INHERITED::toString(str); } #endif @@ -705,46 +715,44 @@ void SkGradientShaderBase::toString(SkString* str) const { static void desc_init(SkGradientShaderBase::Descriptor* desc, const SkColor colors[], const SkScalar pos[], int colorCount, - SkShader::TileMode mode, - SkUnitMapper* mapper, uint32_t flags) { - desc->fColors = colors; - desc->fPos = pos; - desc->fCount = colorCount; - desc->fTileMode = mode; - desc->fMapper = mapper; - desc->fFlags = flags; + SkShader::TileMode mode, uint32_t flags) { + desc->fColors = colors; + desc->fPos = pos; + desc->fCount = colorCount; + desc->fTileMode = mode; + desc->fGradFlags = flags; } SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int colorCount, SkShader::TileMode mode, - SkUnitMapper* mapper, - uint32_t flags) { + uint32_t flags, + const SkMatrix* localMatrix) { if (NULL == pts || NULL == colors || colorCount < 1) { return NULL; } EXPAND_1_COLOR(colorCount); SkGradientShaderBase::Descriptor desc; - desc_init(&desc, colors, pos, colorCount, mode, mapper, flags); - return SkNEW_ARGS(SkLinearGradient, (pts, desc)); + desc_init(&desc, colors, pos, colorCount, mode, flags); + return SkNEW_ARGS(SkLinearGradient, (pts, desc, localMatrix)); } SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius, const SkColor colors[], const SkScalar pos[], int colorCount, SkShader::TileMode mode, - SkUnitMapper* mapper, - uint32_t flags) { + uint32_t flags, + const SkMatrix* localMatrix) { if (radius <= 0 || NULL == colors || colorCount < 1) { return NULL; } EXPAND_1_COLOR(colorCount); SkGradientShaderBase::Descriptor desc; - desc_init(&desc, colors, pos, colorCount, mode, mapper, flags); - return SkNEW_ARGS(SkRadialGradient, (center, radius, desc)); + desc_init(&desc, colors, pos, colorCount, mode, flags); + return SkNEW_ARGS(SkRadialGradient, (center, radius, desc, localMatrix)); } SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start, @@ -755,17 +763,17 @@ SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start, const SkScalar pos[], int colorCount, SkShader::TileMode mode, - SkUnitMapper* mapper, - uint32_t flags) { + uint32_t flags, + const SkMatrix* localMatrix) { if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { return NULL; } EXPAND_1_COLOR(colorCount); SkGradientShaderBase::Descriptor desc; - desc_init(&desc, colors, pos, colorCount, mode, mapper, flags); + desc_init(&desc, colors, pos, colorCount, mode, flags); return SkNEW_ARGS(SkTwoPointRadialGradient, - (start, startRadius, end, endRadius, desc)); + (start, startRadius, end, endRadius, desc, localMatrix)); } SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, @@ -776,35 +784,60 @@ SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, const SkScalar pos[], int colorCount, SkShader::TileMode mode, - SkUnitMapper* mapper, - uint32_t flags) { + uint32_t flags, + const SkMatrix* localMatrix) { if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { return NULL; } if (start == end && startRadius == endRadius) { return SkNEW(SkEmptyShader); } + EXPAND_1_COLOR(colorCount); + bool flipGradient = startRadius > endRadius; + SkGradientShaderBase::Descriptor desc; - desc_init(&desc, colors, pos, colorCount, mode, mapper, flags); - return SkNEW_ARGS(SkTwoPointConicalGradient, - (start, startRadius, end, endRadius, desc)); + + if (!flipGradient) { + desc_init(&desc, colors, pos, colorCount, mode, flags); + return SkNEW_ARGS(SkTwoPointConicalGradient, + (start, startRadius, end, endRadius, flipGradient, desc, localMatrix)); + } else { + SkAutoSTArray<8, SkColor> colorsNew(colorCount); + SkAutoSTArray<8, SkScalar> posNew(colorCount); + for (int i = 0; i < colorCount; ++i) { + colorsNew[i] = colors[colorCount - i - 1]; + } + + if (pos) { + for (int i = 0; i < colorCount; ++i) { + posNew[i] = 1 - pos[colorCount - i - 1]; + } + desc_init(&desc, colorsNew.get(), posNew.get(), colorCount, mode, flags); + } else { + desc_init(&desc, colorsNew.get(), NULL, colorCount, mode, flags); + } + + return SkNEW_ARGS(SkTwoPointConicalGradient, + (end, endRadius, start, startRadius, flipGradient, desc, localMatrix)); + } } SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy, const SkColor colors[], const SkScalar pos[], - int colorCount, SkUnitMapper* mapper, - uint32_t flags) { + int colorCount, + uint32_t flags, + const SkMatrix* localMatrix) { if (NULL == colors || colorCount < 1) { return NULL; } EXPAND_1_COLOR(colorCount); SkGradientShaderBase::Descriptor desc; - desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper, flags); - return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc)); + desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, flags); + return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc, localMatrix)); } SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) @@ -832,13 +865,13 @@ GrGLGradientEffect::~GrGLGradientEffect() { } void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) { - if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)) { // 2 Color case + if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(key)) { // 2 Color case fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientStartColor"); fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientEndColor"); - } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){ // 3 Color Case + } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(key)){ // 3 Color Case fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "GradientStartColor"); fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, @@ -880,7 +913,7 @@ void GrGLGradientEffect::setData(const GrGLUniformManager& uman, const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>(); - if (GrGradientEffect::kTwo_ColorType == e.getColorType()){ + if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){ if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { set_mul_color_uni(uman, fColorStartUni, e.getColors(0)); @@ -890,7 +923,7 @@ void GrGLGradientEffect::setData(const GrGLUniformManager& uman, set_color_uni(uman, fColorEndUni, e.getColors(1)); } - } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){ + } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){ if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { set_mul_color_uni(uman, fColorStartUni, e.getColors(0)); @@ -917,9 +950,9 @@ GrGLEffect::EffectKey GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect& EffectKey key = 0; - if (GrGradientEffect::kTwo_ColorType == e.getColorType()) { + if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) { key |= kTwoColorKey; - } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){ + } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){ key |= kThreeColorKey; } @@ -936,7 +969,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder, const char* outputColor, const char* inputColor, const TextureSamplerArray& samplers) { - if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)){ + if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(key)){ builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n", builder->getUniformVariable(fColorStartUni).c_str(), builder->getUniformVariable(fColorEndUni).c_str(), @@ -952,7 +985,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder, builder->fsCodeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str()); - } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){ + } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(key)){ builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n", gradientTValue); builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n", @@ -997,30 +1030,14 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, fIsOpaque = shader.isOpaque(); - SkShader::GradientInfo info; - SkScalar pos[3] = {0}; - - info.fColorCount = 3; - info.fColors = &fColors[0]; - info.fColorOffsets = &pos[0]; - shader.asAGradient(&info); + fColorType = shader.getGpuColorType(&fColors[0]); // The two and three color specializations do not currently support tiling. - bool foundSpecialCase = false; - if (SkShader::kClamp_TileMode == info.fTileMode) { - if (2 == info.fColorCount) { - fRow = -1; // flag for no atlas - fColorType = kTwo_ColorType; - foundSpecialCase = true; - } else if (3 == info.fColorCount && - (SkScalarAbs(pos[1] - SK_ScalarHalf) < SK_Scalar1 / 1000)) { // 3 color symmetric - fRow = -1; // flag for no atlas - fColorType = kThree_ColorType; - foundSpecialCase = true; - } - } - if (foundSpecialCase) { - if (SkGradientShader::kInterpolateColorsInPremul_Flag & info.fGradientFlags) { + if (SkGradientShaderBase::kTwo_GpuColorType == fColorType || + SkGradientShaderBase::kThree_GpuColorType == fColorType) { + fRow = -1; + + if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) { fPremulType = kBeforeInterp_PremulType; } else { fPremulType = kAfterInterp_PremulType; @@ -1031,14 +1048,13 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx, fPremulType = kBeforeInterp_PremulType; SkBitmap bitmap; shader.getGradientTableBitmap(&bitmap); - fColorType = kTexture_ColorType; GrTextureStripAtlas::Desc desc; desc.fWidth = bitmap.width(); desc.fHeight = 32; desc.fRowHeight = bitmap.height(); desc.fContext = ctx; - desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); + desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info()); fAtlas = GrTextureStripAtlas::GetAtlas(desc); SkASSERT(NULL != fAtlas); @@ -1080,12 +1096,12 @@ bool GrGradientEffect::onIsEqual(const GrEffect& effect) const { if (this->fColorType == s.getColorType()){ - if (kTwo_ColorType == fColorType) { + if (SkGradientShaderBase::kTwo_GpuColorType == fColorType) { if (*this->getColors(0) != *s.getColors(0) || *this->getColors(1) != *s.getColors(1)) { return false; } - } else if (kThree_ColorType == fColorType) { + } else if (SkGradientShaderBase::kThree_GpuColorType == fColorType) { if (*this->getColors(0) != *s.getColors(0) || *this->getColors(1) != *s.getColors(1) || *this->getColors(2) != *s.getColors(2)) { |