summaryrefslogtreecommitdiff
path: root/effects/gradients/SkGradientShader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'effects/gradients/SkGradientShader.cpp')
-rw-r--r--effects/gradients/SkGradientShader.cpp75
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,