Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 # HG changeset patch
2 # User Matt Woodrow <mwoodrow@mozilla.com>
3 # Date 1339988782 -43200
4 # Node ID 1e9dae659ee6c992f719fd4136efbcc5410ded37
5 # Parent 946750f6d95febd199fb7b748e9d2c48fd01c8a6
6 [mq]: skia-windows-gradients
8 diff --git a/gfx/skia/src/effects/SkGradientShader.cpp b/gfx/skia/src/effects/SkGradientShader.cpp
9 --- a/gfx/skia/src/effects/SkGradientShader.cpp
10 +++ b/gfx/skia/src/effects/SkGradientShader.cpp
11 @@ -847,16 +847,19 @@ bool Linear_Gradient::setContext(const S
12 fFlags |= SkShader::kConstInY32_Flag;
13 if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
14 // only claim this if we do have a 16bit mode (i.e. none of our
15 // colors have alpha), and if we are not dithering (which obviously
16 // is not const in Y).
17 fFlags |= SkShader::kConstInY16_Flag;
18 }
19 }
20 + if (fStart == fEnd) {
21 + fFlags &= ~kOpaqueAlpha_Flag;
22 + }
23 return true;
24 }
26 #define NO_CHECK_ITER \
27 do { \
28 unsigned fi = fx >> Gradient_Shader::kCache32Shift; \
29 SkASSERT(fi <= 0xFF); \
30 fx += dx; \
31 @@ -976,16 +979,21 @@ void Linear_Gradient::shadeSpan(int x, i
32 TileProc proc = fTileProc;
33 const SkPMColor* SK_RESTRICT cache = this->getCache32();
34 #ifdef USE_DITHER_32BIT_GRADIENT
35 int toggle = ((x ^ y) & 1) * kDitherStride32;
36 #else
37 int toggle = 0;
38 #endif
40 + if (fStart == fEnd) {
41 + sk_bzero(dstC, count * sizeof(*dstC));
42 + return;
43 + }
44 +
45 if (fDstToIndexClass != kPerspective_MatrixClass) {
46 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
47 SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
48 SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
50 if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
51 SkFixed dxStorage[1];
52 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
53 @@ -1169,16 +1177,21 @@ void Linear_Gradient::shadeSpan16(int x,
54 SkASSERT(count > 0);
56 SkPoint srcPt;
57 SkMatrix::MapXYProc dstProc = fDstToIndexProc;
58 TileProc proc = fTileProc;
59 const uint16_t* SK_RESTRICT cache = this->getCache16();
60 int toggle = ((x ^ y) & 1) * kDitherStride16;
62 + if (fStart == fEnd) {
63 + sk_bzero(dstC, count * sizeof(*dstC));
64 + return;
65 + }
66 +
67 if (fDstToIndexClass != kPerspective_MatrixClass) {
68 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
69 SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
70 SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
72 if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
73 SkFixed dxStorage[1];
74 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
75 @@ -1739,21 +1752,25 @@ void Radial_Gradient::shadeSpan(int x, i
76 possible circles on which the point may fall. Solving for t yields
77 the gradient value to use.
79 If a<0, the start circle is entirely contained in the
80 end circle, and one of the roots will be <0 or >1 (off the line
81 segment). If a>0, the start circle falls at least partially
82 outside the end circle (or vice versa), and the gradient
83 defines a "tube" where a point may be on one circle (on the
84 - inside of the tube) or the other (outside of the tube). We choose
85 - one arbitrarily.
86 + inside of the tube) or the other (outside of the tube). We choose
87 + the one with the highest t value, as long as the radius that it
88 + corresponds to is >=0. In the case where neither root has a positive
89 + radius, we don't draw anything.
91 + XXXmattwoodrow: I've removed this for now since it breaks
92 + down when Dr == 0. Is there something else we can do instead?
93 In order to keep the math to within the limits of fixed point,
94 - we divide the entire quadratic by Dr^2, and replace
95 + we divide the entire quadratic by Dr, and replace
96 (x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving
98 [Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2
99 + 2 * [x' * Dx / Dr + y' * Dy / Dr - Sr / Dr] * t
100 + [x'^2 + y'^2 - Sr^2/Dr^2] = 0
102 (x' and y' are computed by appending the subtract and scale to the
103 fDstToIndex matrix in the constructor).
104 @@ -1763,99 +1780,122 @@ void Radial_Gradient::shadeSpan(int x, i
105 x' and y', if x and y are linear in the span, 'B' can be computed
106 incrementally with a simple delta (db below). If it is not (e.g.,
107 a perspective projection), it must be computed in the loop.
109 */
111 namespace {
113 -inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
114 - SkScalar sr2d2, SkScalar foura,
115 - SkScalar oneOverTwoA, bool posRoot) {
116 +inline bool two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
117 + SkScalar sr2d2, SkScalar foura,
118 + SkScalar oneOverTwoA, SkScalar diffRadius,
119 + SkScalar startRadius, SkFixed& t) {
120 SkScalar c = SkScalarSquare(fx) + SkScalarSquare(fy) - sr2d2;
121 if (0 == foura) {
122 - return SkScalarToFixed(SkScalarDiv(-c, b));
123 + SkScalar result = SkScalarDiv(-c, b);
124 + if (result * diffRadius + startRadius >= 0) {
125 + t = SkScalarToFixed(result);
126 + return true;
127 + }
128 + return false;
129 }
131 SkScalar discrim = SkScalarSquare(b) - SkScalarMul(foura, c);
132 if (discrim < 0) {
133 - discrim = -discrim;
134 + return false;
135 }
136 SkScalar rootDiscrim = SkScalarSqrt(discrim);
137 - SkScalar result;
138 - if (posRoot) {
139 - result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
140 - } else {
141 - result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
142 +
143 + // Make sure the results corresponds to a positive radius.
144 + SkScalar result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
145 + if (result * diffRadius + startRadius >= 0) {
146 + t = SkScalarToFixed(result);
147 + return true;
148 }
149 - return SkScalarToFixed(result);
150 + result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
151 + if (result * diffRadius + startRadius >= 0) {
152 + t = SkScalarToFixed(result);
153 + return true;
154 + }
155 +
156 + return false;
157 }
159 typedef void (* TwoPointRadialShadeProc)(SkScalar fx, SkScalar dx,
160 SkScalar fy, SkScalar dy,
161 SkScalar b, SkScalar db,
162 - SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
163 + SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
164 + SkScalar fDiffRadius, SkScalar fRadius1,
165 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
166 int count);
168 void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
169 SkScalar fy, SkScalar dy,
170 SkScalar b, SkScalar db,
171 - SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
172 + SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
173 + SkScalar fDiffRadius, SkScalar fRadius1,
174 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
175 int count) {
176 for (; count > 0; --count) {
177 - SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
178 - fOneOverTwoA, posRoot);
179 -
180 - if (t < 0) {
181 + SkFixed t;
182 + if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
183 + *(dstC++) = 0;
184 + } else if (t < 0) {
185 *dstC++ = cache[-1];
186 } else if (t > 0xFFFF) {
187 *dstC++ = cache[Gradient_Shader::kCache32Count * 2];
188 } else {
189 SkASSERT(t <= 0xFFFF);
190 *dstC++ = cache[t >> Gradient_Shader::kCache32Shift];
191 }
193 fx += dx;
194 fy += dy;
195 b += db;
196 }
197 }
198 void shadeSpan_twopoint_mirror(SkScalar fx, SkScalar dx,
199 SkScalar fy, SkScalar dy,
200 SkScalar b, SkScalar db,
201 - SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
202 + SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
203 + SkScalar fDiffRadius, SkScalar fRadius1,
204 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
205 int count) {
206 for (; count > 0; --count) {
207 - SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
208 - fOneOverTwoA, posRoot);
209 - SkFixed index = mirror_tileproc(t);
210 - SkASSERT(index <= 0xFFFF);
211 - *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
212 + SkFixed t;
213 + if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
214 + *(dstC++) = 0;
215 + } else {
216 + SkFixed index = mirror_tileproc(t);
217 + SkASSERT(index <= 0xFFFF);
218 + *dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
219 + }
220 fx += dx;
221 fy += dy;
222 b += db;
223 }
224 }
226 void shadeSpan_twopoint_repeat(SkScalar fx, SkScalar dx,
227 SkScalar fy, SkScalar dy,
228 SkScalar b, SkScalar db,
229 - SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
230 + SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
231 + SkScalar fDiffRadius, SkScalar fRadius1,
232 SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
233 int count) {
234 for (; count > 0; --count) {
235 - SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
236 - fOneOverTwoA, posRoot);
237 - SkFixed index = repeat_tileproc(t);
238 - SkASSERT(index <= 0xFFFF);
239 - *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
240 + SkFixed t;
241 + if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
242 + *(dstC++) = 0;
243 + } else {
244 + SkFixed index = repeat_tileproc(t);
245 + SkASSERT(index <= 0xFFFF);
246 + *dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
247 + }
248 fx += dx;
249 fy += dy;
250 b += db;
251 }
252 }
256 @@ -1935,17 +1975,16 @@ public:
257 sk_bzero(dstC, count * sizeof(*dstC));
258 return;
259 }
260 SkMatrix::MapXYProc dstProc = fDstToIndexProc;
261 TileProc proc = fTileProc;
262 const SkPMColor* SK_RESTRICT cache = this->getCache32();
264 SkScalar foura = fA * 4;
265 - bool posRoot = fDiffRadius < 0;
266 if (fDstToIndexClass != kPerspective_MatrixClass) {
267 SkPoint srcPt;
268 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
269 SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
270 SkScalar dx, fx = srcPt.fX;
271 SkScalar dy, fy = srcPt.fY;
273 if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
274 @@ -1954,60 +1993,69 @@ public:
275 dx = SkFixedToScalar(fixedX);
276 dy = SkFixedToScalar(fixedY);
277 } else {
278 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
279 dx = fDstToIndex.getScaleX();
280 dy = fDstToIndex.getSkewY();
281 }
282 SkScalar b = (SkScalarMul(fDiff.fX, fx) +
283 - SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
284 + SkScalarMul(fDiff.fY, fy) - fStartRadius * fDiffRadius) * 2;
285 SkScalar db = (SkScalarMul(fDiff.fX, dx) +
286 SkScalarMul(fDiff.fY, dy)) * 2;
288 TwoPointRadialShadeProc shadeProc = shadeSpan_twopoint_repeat;
289 if (proc == clamp_tileproc) {
290 shadeProc = shadeSpan_twopoint_clamp;
291 } else if (proc == mirror_tileproc) {
292 shadeProc = shadeSpan_twopoint_mirror;
293 } else {
294 SkASSERT(proc == repeat_tileproc);
295 }
296 (*shadeProc)(fx, dx, fy, dy, b, db,
297 - fSr2D2, foura, fOneOverTwoA, posRoot,
298 + fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1,
299 dstC, cache, count);
300 } else { // perspective case
301 SkScalar dstX = SkIntToScalar(x);
302 SkScalar dstY = SkIntToScalar(y);
303 for (; count > 0; --count) {
304 SkPoint srcPt;
305 dstProc(fDstToIndex, dstX, dstY, &srcPt);
306 SkScalar fx = srcPt.fX;
307 SkScalar fy = srcPt.fY;
308 SkScalar b = (SkScalarMul(fDiff.fX, fx) +
309 SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
310 - SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
311 - fOneOverTwoA, posRoot);
312 - SkFixed index = proc(t);
313 - SkASSERT(index <= 0xFFFF);
314 - *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
315 + SkFixed t;
316 + if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
317 + *(dstC++) = 0;
318 + } else {
319 + SkFixed index = proc(t);
320 + SkASSERT(index <= 0xFFFF);
321 + *dstC++ = cache[index >> (16 - kCache32Bits)];
322 + }
323 dstX += SK_Scalar1;
324 }
325 }
326 }
328 virtual bool setContext(const SkBitmap& device,
329 const SkPaint& paint,
330 const SkMatrix& matrix) SK_OVERRIDE {
331 if (!this->INHERITED::setContext(device, paint, matrix)) {
332 return false;
333 }
335 // we don't have a span16 proc
336 fFlags &= ~kHasSpan16_Flag;
337 +
338 + // If we might end up wanting to draw nothing as part of the gradient
339 + // then we should mark ourselves as not being opaque.
340 + if (fA >= 0 || (fDiffRadius == 0 && fCenter1 == fCenter2)) {
341 + fFlags &= ~kOpaqueAlpha_Flag;
342 + }
343 return true;
344 }
346 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Two_Point_Radial_Gradient)
348 protected:
349 Two_Point_Radial_Gradient(SkFlattenableReadBuffer& buffer)
350 : INHERITED(buffer),
351 @@ -2033,26 +2081,22 @@ private:
352 const SkScalar fRadius1;
353 const SkScalar fRadius2;
354 SkPoint fDiff;
355 SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA;
357 void init() {
358 fDiff = fCenter1 - fCenter2;
359 fDiffRadius = fRadius2 - fRadius1;
360 - SkScalar inv = SkScalarInvert(fDiffRadius);
361 - fDiff.fX = SkScalarMul(fDiff.fX, inv);
362 - fDiff.fY = SkScalarMul(fDiff.fY, inv);
363 - fStartRadius = SkScalarMul(fRadius1, inv);
364 + fStartRadius = fRadius1;
365 fSr2D2 = SkScalarSquare(fStartRadius);
366 - fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
367 + fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SkScalarSquare(fDiffRadius);
368 fOneOverTwoA = fA ? SkScalarInvert(fA * 2) : 0;
370 fPtsToUnit.setTranslate(-fCenter1.fX, -fCenter1.fY);
371 - fPtsToUnit.postScale(inv, inv);
372 }
373 };
375 ///////////////////////////////////////////////////////////////////////////////
377 class Sweep_Gradient : public Gradient_Shader {
378 public:
379 Sweep_Gradient(SkScalar cx, SkScalar cy, const SkColor colors[],
380 @@ -2488,16 +2532,20 @@ SkShader* SkGradientShader::CreateTwoPoi
381 int colorCount,
382 SkShader::TileMode mode,
383 SkUnitMapper* mapper) {
384 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
385 return NULL;
386 }
387 EXPAND_1_COLOR(colorCount);
389 + if (start == end && startRadius == 0) {
390 + return CreateRadial(start, endRadius, colors, pos, colorCount, mode, mapper);
391 + }
392 +
393 return SkNEW_ARGS(Two_Point_Radial_Gradient,
394 (start, startRadius, end, endRadius, colors, pos,
395 colorCount, mode, mapper));
396 }
398 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
399 const SkColor colors[],
400 const SkScalar pos[],