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
This commit is contained in:
reed@android.com 2009-12-14 15:25:36 +00:00
Родитель 447bcfa889
Коммит 512a87641f
1 изменённых файлов: 21 добавлений и 16 удалений

Просмотреть файл

@ -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);