aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-12-14 15:25:36 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-12-14 15:25:36 +0000
commit512a87641fe1769fe34ceefe238e459f8d3cc0c1 (patch)
tree70739f6401e35ebaaee5a6e6787e8cbc898031f6
parent447bcfa8898ce10e7b6493ba9e3e23e08bd13f01 (diff)
make the 16bit cache larger, to handle multiple colors in the gradient w/o
obvious artifacts. We need a more comprehensive fix for all gradients (32bit and 16bit) when we have a large number of colors (or they are spaced out very non-linearly), to avoid banding. git-svn-id: http://skia.googlecode.com/svn/trunk@458 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--src/effects/SkGradientShader.cpp37
1 files changed, 21 insertions, 16 deletions
diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp
index 780ad18977..0899cfbfeb 100644
--- a/src/effects/SkGradientShader.cpp
+++ b/src/effects/SkGradientShader.cpp
@@ -107,8 +107,11 @@ protected:
Rec* fRecs;
enum {
- kCache16Bits = 6, // seems like enough for visual accuracy
+ kCache16Bits = 8, // seems like enough for visual accuracy
kCache16Count = 1 << kCache16Bits,
+ kCache16Mask = kCache16Count - 1,
+ kCache16Shift = 16 - kCache16Bits,
+
kCache32Bits = 8, // pretty much should always be 8
kCache32Count = 1 << kCache32Bits
};
@@ -135,6 +138,8 @@ private:
SkPMColor* fCache32Storage; // storage for fCache32, allocated on demand
unsigned fCacheAlpha; // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
+ static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
+
typedef SkShader INHERITED;
};
@@ -415,8 +420,8 @@ static inline uint32_t dot8_blend_packed32(uint32_t s0, uint32_t s1,
build a 16bit table as long as the original colors are opaque, even if the
paint specifies a non-opaque alpha.
*/
-static void build_16bit_cache(uint16_t cache[], SkColor c0, SkColor c1,
- int count) {
+void Gradient_Shader::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1,
+ int count) {
SkASSERT(count > 1);
SkASSERT(SkColorGetA(c0) == 0xFF);
SkASSERT(SkColorGetA(c1) == 0xFF);
@@ -438,7 +443,7 @@ static void build_16bit_cache(uint16_t cache[], SkColor c0, SkColor c1,
unsigned gg = g >> 16;
unsigned bb = b >> 16;
cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
- cache[64] = SkDitherPack888ToRGB16(rr, gg, bb);
+ cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb);
cache += 1;
r += dr;
g += dg;
@@ -496,16 +501,16 @@ const uint16_t* Gradient_Shader::getCache16() {
}
fCache16 = fCache16Storage;
if (fColorCount == 2) {
- build_16bit_cache(fCache16, fOrigColors[0], fOrigColors[1], kCache16Count);
+ 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) >> (16 - kCache16Bits);
+ int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
SkASSERT(nextIndex < kCache16Count);
if (nextIndex > prevIndex)
- build_16bit_cache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1);
+ Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1);
prevIndex = nextIndex;
}
SkASSERT(prevIndex == kCache16Count - 1);
@@ -806,21 +811,21 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
if (SkFixedNearlyZero(dx)) {
// we're a vertical gradient, so no change in a span
- unsigned fi = proc(fx) >> 10;
- SkASSERT(fi <= 63);
+ unsigned fi = proc(fx) >> kCache16Shift;
+ SkASSERT(fi <= kCache16Mask);
dither_memset16(dstC, cache[toggle + fi], cache[(toggle ^ (1 << kCache16Bits)) + fi], count);
} else if (proc == clamp_tileproc) {
do {
- unsigned fi = SkClampMax(fx >> 10, 63);
- SkASSERT(fi <= 63);
+ unsigned fi = SkClampMax(fx >> kCache16Shift, kCache16Mask);
+ SkASSERT(fi <= kCache16Mask);
fx += dx;
*dstC++ = cache[toggle + fi];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
} else if (proc == mirror_tileproc) {
do {
- unsigned fi = mirror_6bits(fx >> 10);
- SkASSERT(fi <= 0x3F);
+ unsigned fi = mirror_6bits(fx >> kCache16Shift);
+ SkASSERT(fi <= kCache16Mask);
fx += dx;
*dstC++ = cache[toggle + fi];
toggle ^= (1 << kCache16Bits);
@@ -828,8 +833,8 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
} else {
SkASSERT(proc == repeat_tileproc);
do {
- unsigned fi = repeat_6bits(fx >> 10);
- SkASSERT(fi <= 0x3F);
+ unsigned fi = repeat_6bits(fx >> kCache16Shift);
+ SkASSERT(fi <= kCache16Mask);
fx += dx;
*dstC++ = cache[toggle + fi];
toggle ^= (1 << kCache16Bits);
@@ -843,7 +848,7 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
unsigned fi = proc(SkScalarToFixed(srcPt.fX));
SkASSERT(fi <= 0xFFFF);
- int index = fi >> (16 - kCache16Bits);
+ int index = fi >> kCache16Shift;
*dstC++ = cache[toggle + index];
toggle ^= (1 << kCache16Bits);