1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
From f941ea32e44a2436d235e83ef1a434289a9d9c1e Mon Sep 17 00:00:00 2001
From: George Wright <gwright@mozilla.com>
Date: Wed, 23 May 2012 11:40:25 -0400
Subject: [PATCH 08/10] Bug 755869 - [11] Re-apply bug 687188 - Skia
radial gradients should use the 0/1 color stop values
for clamping. r=mattwoodrow
---
gfx/skia/src/effects/SkGradientShader.cpp | 76 +++++++++++++++++++++++------
1 files changed, 61 insertions(+), 15 deletions(-)
diff --git a/gfx/skia/src/effects/SkGradientShader.cpp b/gfx/skia/src/effects/SkGradientShader.cpp
index 59ba48c..ea05a39 100644
--- a/gfx/skia/src/effects/SkGradientShader.cpp
+++ b/gfx/skia/src/effects/SkGradientShader.cpp
@@ -204,6 +204,7 @@ private:
mutable SkMallocPixelRef* fCache32PixelRef;
mutable unsigned fCacheAlpha; // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
+ static SkPMColor PremultiplyColor(SkColor c0, U8CPU alpha);
static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
U8CPU alpha);
@@ -507,6 +508,21 @@ static inline U8CPU dither_ceil_fixed_to_8(SkFixed n) {
return ((n << 1) - (n | (n >> 8))) >> 8;
}
+SkPMColor Gradient_Shader::PremultiplyColor(SkColor c0, U8CPU paintAlpha)
+{
+ SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
+ SkFixed r = SkColorGetR(c0);
+ SkFixed g = SkColorGetG(c0);
+ SkFixed b = SkColorGetB(c0);
+
+ a = SkIntToFixed(a) + 0x8000;
+ r = SkIntToFixed(r) + 0x8000;
+ g = SkIntToFixed(g) + 0x8000;
+ b = SkIntToFixed(b) + 0x8000;
+
+ return SkPremultiplyARGBInline(a >> 16, r >> 16, g >> 16, b >> 16);
+}
+
void Gradient_Shader::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
int count, U8CPU paintAlpha) {
SkASSERT(count > 1);
@@ -628,14 +644,14 @@ static void complete_32bit_cache(SkPMColor* cache, int stride) {
const SkPMColor* Gradient_Shader::getCache32() const {
if (fCache32 == NULL) {
// double the count for dither entries
- const int entryCount = kCache32Count * 2;
+ const int entryCount = kCache32Count * 2 + 2;
const size_t allocSize = sizeof(SkPMColor) * entryCount;
if (NULL == fCache32PixelRef) {
fCache32PixelRef = SkNEW_ARGS(SkMallocPixelRef,
(NULL, allocSize, NULL));
}
- fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
+ fCache32 = (SkPMColor*)fCache32PixelRef->getAddr() + 1;
if (fColorCount == 2) {
Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
kGradient32Length, fCacheAlpha);
@@ -659,7 +675,7 @@ const SkPMColor* Gradient_Shader::getCache32() const {
SkMallocPixelRef* newPR = SkNEW_ARGS(SkMallocPixelRef,
(NULL, allocSize, NULL));
SkPMColor* linear = fCache32; // just computed linear data
- SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data
+ SkPMColor* mapped = (SkPMColor*)newPR->getAddr() + 1; // storage for mapped data
SkUnitMapper* map = fMapper;
for (int i = 0; i < kGradient32Length; i++) {
int index = map->mapUnit16((i << 8) | i) >> 8;
@@ -668,10 +684,13 @@ const SkPMColor* Gradient_Shader::getCache32() const {
}
fCache32PixelRef->unref();
fCache32PixelRef = newPR;
- fCache32 = (SkPMColor*)newPR->getAddr();
+ fCache32 = (SkPMColor*)newPR->getAddr() + 1;
}
complete_32bit_cache(fCache32, kCache32Count);
}
+ //Write the clamp colours into the first and last entries of fCache32
+ fCache32[-1] = PremultiplyColor(fOrigColors[0], fCacheAlpha);
+ fCache32[kCache32Count * 2] = PremultiplyColor(fOrigColors[fColorCount - 1], fCacheAlpha);
return fCache32;
}
@@ -857,6 +876,18 @@ void shadeSpan_linear_vertical(TileProc proc, SkFixed dx, SkFixed fx,
SkPMColor* SK_RESTRICT dstC,
const SkPMColor* SK_RESTRICT cache,
int toggle, int count) {
+ if (proc == clamp_tileproc) {
+ // Read out clamp values from beginning/end of the cache. No need to lerp
+ // or dither
+ if (fx < 0) {
+ sk_memset32(dstC, cache[-1], count);
+ return;
+ } else if (fx > 0xFFFF) {
+ sk_memset32(dstC, cache[Gradient_Shader::kCache32Count * 2], count);
+ return;
+ }
+ }
+
// We're a vertical gradient, so no change in a span.
// If colors change sharply across the gradient, dithering is
// insufficient (it subsamples the color space) and we need to lerp.
@@ -875,6 +906,18 @@ void shadeSpan_linear_vertical_lerp(TileProc proc, SkFixed dx, SkFixed fx,
SkPMColor* SK_RESTRICT dstC,
const SkPMColor* SK_RESTRICT cache,
int toggle, int count) {
+ if (proc == clamp_tileproc) {
+ // Read out clamp values from beginning/end of the cache. No need to lerp
+ // or dither
+ if (fx < 0) {
+ sk_memset32(dstC, cache[-1], count);
+ return;
+ } else if (fx > 0xFFFF) {
+ sk_memset32(dstC, cache[Gradient_Shader::kCache32Count * 2], count);
+ return;
+ }
+ }
+
// We're a vertical gradient, so no change in a span.
// If colors change sharply across the gradient, dithering is
// insufficient (it subsamples the color space) and we need to lerp.
@@ -900,10 +943,8 @@ void shadeSpan_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx,
range.init(fx, dx, count, 0, Gradient_Shader::kGradient32Length);
if ((count = range.fCount0) > 0) {
- sk_memset32_dither(dstC,
- cache[toggle + range.fV0],
- cache[(toggle ^ Gradient_Shader::kDitherStride32) + range.fV0],
- count);
+ // Shouldn't be any need to dither for clamping?
+ sk_memset32(dstC, cache[-1], count);
dstC += count;
}
if ((count = range.fCount1) > 0) {
@@ -922,10 +963,8 @@ void shadeSpan_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx,
}
}
if ((count = range.fCount2) > 0) {
- sk_memset32_dither(dstC,
- cache[toggle + range.fV1],
- cache[(toggle ^ Gradient_Shader::kDitherStride32) + range.fV1],
- count);
+ // Shouldn't be any need to dither for clamping?
+ sk_memset32(dstC, cache[Gradient_Shader::kCache32Count * 2], count);
}
}
@@ -1796,9 +1835,16 @@ void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
for (; count > 0; --count) {
SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
fOneOverTwoA, posRoot);
- SkFixed index = SkClampMax(t, 0xFFFF);
- SkASSERT(index <= 0xFFFF);
- *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
+
+ if (t < 0) {
+ *dstC++ = cache[-1];
+ } else if (t > 0xFFFF) {
+ *dstC++ = cache[Gradient_Shader::kCache32Count * 2];
+ } else {
+ SkASSERT(t <= 0xFFFF);
+ *dstC++ = cache[t >> Gradient_Shader::kCache32Shift];
+ }
+
fx += dx;
fy += dy;
b += db;
--
1.7.5.4
|