diff options
Diffstat (limited to 'effects/gradients/SkGradientShader.cpp')
-rw-r--r-- | effects/gradients/SkGradientShader.cpp | 75 |
1 files changed, 68 insertions, 7 deletions
diff --git a/effects/gradients/SkGradientShader.cpp b/effects/gradients/SkGradientShader.cpp index f155cc5e..7f084047 100644 --- a/effects/gradients/SkGradientShader.cpp +++ b/effects/gradients/SkGradientShader.cpp @@ -118,12 +118,13 @@ 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; } } this->initCommon(); @@ -237,6 +238,30 @@ SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor return kTexture_GpuColorType; } +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; } @@ -643,11 +668,23 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { } } -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) { @@ -655,7 +692,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); } } } @@ -801,12 +838,36 @@ SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, 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, mapper, flags); + return SkNEW_ARGS(SkTwoPointConicalGradient, + (start, startRadius, end, endRadius, flipGradient, desc)); + } 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, mapper, flags); + } else { + desc_init(&desc, colorsNew.get(), NULL, colorCount, mode, mapper, flags); + } + + return SkNEW_ARGS(SkTwoPointConicalGradient, + (end, endRadius, start, startRadius, flipGradient, desc)); + } } SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy, |