Backout bug 718849

This commit is contained in:
Nicholas Cameron 2012-07-30 11:40:42 +12:00
parent ece476b5d1
commit f0af80156d
3 changed files with 46 additions and 495 deletions

View File

@ -1,400 +0,0 @@
# HG changeset patch
# User Matt Woodrow <mwoodrow@mozilla.com>
# Date 1339988782 -43200
# Node ID 1e9dae659ee6c992f719fd4136efbcc5410ded37
# Parent 946750f6d95febd199fb7b748e9d2c48fd01c8a6
[mq]: skia-windows-gradients
diff --git a/gfx/skia/src/effects/SkGradientShader.cpp b/gfx/skia/src/effects/SkGradientShader.cpp
--- a/gfx/skia/src/effects/SkGradientShader.cpp
+++ b/gfx/skia/src/effects/SkGradientShader.cpp
@@ -847,16 +847,19 @@ bool Linear_Gradient::setContext(const S
fFlags |= SkShader::kConstInY32_Flag;
if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
// only claim this if we do have a 16bit mode (i.e. none of our
// colors have alpha), and if we are not dithering (which obviously
// is not const in Y).
fFlags |= SkShader::kConstInY16_Flag;
}
}
+ if (fStart == fEnd) {
+ fFlags &= ~kOpaqueAlpha_Flag;
+ }
return true;
}
#define NO_CHECK_ITER \
do { \
unsigned fi = fx >> Gradient_Shader::kCache32Shift; \
SkASSERT(fi <= 0xFF); \
fx += dx; \
@@ -976,16 +979,21 @@ void Linear_Gradient::shadeSpan(int x, i
TileProc proc = fTileProc;
const SkPMColor* SK_RESTRICT cache = this->getCache32();
#ifdef USE_DITHER_32BIT_GRADIENT
int toggle = ((x ^ y) & 1) * kDitherStride32;
#else
int toggle = 0;
#endif
+ if (fStart == fEnd) {
+ sk_bzero(dstC, count * sizeof(*dstC));
+ return;
+ }
+
if (fDstToIndexClass != kPerspective_MatrixClass) {
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
SkFixed dxStorage[1];
(void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
@@ -1169,16 +1177,21 @@ void Linear_Gradient::shadeSpan16(int x,
SkASSERT(count > 0);
SkPoint srcPt;
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
TileProc proc = fTileProc;
const uint16_t* SK_RESTRICT cache = this->getCache16();
int toggle = ((x ^ y) & 1) * kDitherStride16;
+ if (fStart == fEnd) {
+ sk_bzero(dstC, count * sizeof(*dstC));
+ return;
+ }
+
if (fDstToIndexClass != kPerspective_MatrixClass) {
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
SkFixed dxStorage[1];
(void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
@@ -1739,21 +1752,25 @@ void Radial_Gradient::shadeSpan(int x, i
possible circles on which the point may fall. Solving for t yields
the gradient value to use.
If a<0, the start circle is entirely contained in the
end circle, and one of the roots will be <0 or >1 (off the line
segment). If a>0, the start circle falls at least partially
outside the end circle (or vice versa), and the gradient
defines a "tube" where a point may be on one circle (on the
- inside of the tube) or the other (outside of the tube). We choose
- one arbitrarily.
+ inside of the tube) or the other (outside of the tube). We choose
+ the one with the highest t value, as long as the radius that it
+ corresponds to is >=0. In the case where neither root has a positive
+ radius, we don't draw anything.
+ XXXmattwoodrow: I've removed this for now since it breaks
+ down when Dr == 0. Is there something else we can do instead?
In order to keep the math to within the limits of fixed point,
- we divide the entire quadratic by Dr^2, and replace
+ we divide the entire quadratic by Dr, and replace
(x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving
[Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2
+ 2 * [x' * Dx / Dr + y' * Dy / Dr - Sr / Dr] * t
+ [x'^2 + y'^2 - Sr^2/Dr^2] = 0
(x' and y' are computed by appending the subtract and scale to the
fDstToIndex matrix in the constructor).
@@ -1763,99 +1780,122 @@ void Radial_Gradient::shadeSpan(int x, i
x' and y', if x and y are linear in the span, 'B' can be computed
incrementally with a simple delta (db below). If it is not (e.g.,
a perspective projection), it must be computed in the loop.
*/
namespace {
-inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
- SkScalar sr2d2, SkScalar foura,
- SkScalar oneOverTwoA, bool posRoot) {
+inline bool two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
+ SkScalar sr2d2, SkScalar foura,
+ SkScalar oneOverTwoA, SkScalar diffRadius,
+ SkScalar startRadius, SkFixed& t) {
SkScalar c = SkScalarSquare(fx) + SkScalarSquare(fy) - sr2d2;
if (0 == foura) {
- return SkScalarToFixed(SkScalarDiv(-c, b));
+ SkScalar result = SkScalarDiv(-c, b);
+ if (result * diffRadius + startRadius >= 0) {
+ t = SkScalarToFixed(result);
+ return true;
+ }
+ return false;
}
SkScalar discrim = SkScalarSquare(b) - SkScalarMul(foura, c);
if (discrim < 0) {
- discrim = -discrim;
+ return false;
}
SkScalar rootDiscrim = SkScalarSqrt(discrim);
- SkScalar result;
- if (posRoot) {
- result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
- } else {
- result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
+
+ // Make sure the results corresponds to a positive radius.
+ SkScalar result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
+ if (result * diffRadius + startRadius >= 0) {
+ t = SkScalarToFixed(result);
+ return true;
}
- return SkScalarToFixed(result);
+ result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
+ if (result * diffRadius + startRadius >= 0) {
+ t = SkScalarToFixed(result);
+ return true;
+ }
+
+ return false;
}
typedef void (* TwoPointRadialShadeProc)(SkScalar fx, SkScalar dx,
SkScalar fy, SkScalar dy,
SkScalar b, SkScalar db,
- SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
+ SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
+ SkScalar fDiffRadius, SkScalar fRadius1,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count);
void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
SkScalar fy, SkScalar dy,
SkScalar b, SkScalar db,
- SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
+ SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
+ SkScalar fDiffRadius, SkScalar fRadius1,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) {
for (; count > 0; --count) {
- SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
- fOneOverTwoA, posRoot);
-
- if (t < 0) {
+ SkFixed t;
+ if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
+ *(dstC++) = 0;
+ } else 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;
}
}
void shadeSpan_twopoint_mirror(SkScalar fx, SkScalar dx,
SkScalar fy, SkScalar dy,
SkScalar b, SkScalar db,
- SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
+ SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
+ SkScalar fDiffRadius, SkScalar fRadius1,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) {
for (; count > 0; --count) {
- SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
- fOneOverTwoA, posRoot);
- SkFixed index = mirror_tileproc(t);
- SkASSERT(index <= 0xFFFF);
- *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
+ SkFixed t;
+ if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
+ *(dstC++) = 0;
+ } else {
+ SkFixed index = mirror_tileproc(t);
+ SkASSERT(index <= 0xFFFF);
+ *dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
+ }
fx += dx;
fy += dy;
b += db;
}
}
void shadeSpan_twopoint_repeat(SkScalar fx, SkScalar dx,
SkScalar fy, SkScalar dy,
SkScalar b, SkScalar db,
- SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
+ SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
+ SkScalar fDiffRadius, SkScalar fRadius1,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) {
for (; count > 0; --count) {
- SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
- fOneOverTwoA, posRoot);
- SkFixed index = repeat_tileproc(t);
- SkASSERT(index <= 0xFFFF);
- *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
+ SkFixed t;
+ if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
+ *(dstC++) = 0;
+ } else {
+ SkFixed index = repeat_tileproc(t);
+ SkASSERT(index <= 0xFFFF);
+ *dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
+ }
fx += dx;
fy += dy;
b += db;
}
}
@@ -1935,17 +1975,16 @@ public:
sk_bzero(dstC, count * sizeof(*dstC));
return;
}
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
TileProc proc = fTileProc;
const SkPMColor* SK_RESTRICT cache = this->getCache32();
SkScalar foura = fA * 4;
- bool posRoot = fDiffRadius < 0;
if (fDstToIndexClass != kPerspective_MatrixClass) {
SkPoint srcPt;
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
SkScalar dx, fx = srcPt.fX;
SkScalar dy, fy = srcPt.fY;
if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
@@ -1954,60 +1993,69 @@ public:
dx = SkFixedToScalar(fixedX);
dy = SkFixedToScalar(fixedY);
} else {
SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
dx = fDstToIndex.getScaleX();
dy = fDstToIndex.getSkewY();
}
SkScalar b = (SkScalarMul(fDiff.fX, fx) +
- SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
+ SkScalarMul(fDiff.fY, fy) - fStartRadius * fDiffRadius) * 2;
SkScalar db = (SkScalarMul(fDiff.fX, dx) +
SkScalarMul(fDiff.fY, dy)) * 2;
TwoPointRadialShadeProc shadeProc = shadeSpan_twopoint_repeat;
if (proc == clamp_tileproc) {
shadeProc = shadeSpan_twopoint_clamp;
} else if (proc == mirror_tileproc) {
shadeProc = shadeSpan_twopoint_mirror;
} else {
SkASSERT(proc == repeat_tileproc);
}
(*shadeProc)(fx, dx, fy, dy, b, db,
- fSr2D2, foura, fOneOverTwoA, posRoot,
+ fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1,
dstC, cache, count);
} else { // perspective case
SkScalar dstX = SkIntToScalar(x);
SkScalar dstY = SkIntToScalar(y);
for (; count > 0; --count) {
SkPoint srcPt;
dstProc(fDstToIndex, dstX, dstY, &srcPt);
SkScalar fx = srcPt.fX;
SkScalar fy = srcPt.fY;
SkScalar b = (SkScalarMul(fDiff.fX, fx) +
SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
- SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
- fOneOverTwoA, posRoot);
- SkFixed index = proc(t);
- SkASSERT(index <= 0xFFFF);
- *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
+ SkFixed t;
+ if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
+ *(dstC++) = 0;
+ } else {
+ SkFixed index = proc(t);
+ SkASSERT(index <= 0xFFFF);
+ *dstC++ = cache[index >> (16 - kCache32Bits)];
+ }
dstX += SK_Scalar1;
}
}
}
virtual bool setContext(const SkBitmap& device,
const SkPaint& paint,
const SkMatrix& matrix) SK_OVERRIDE {
if (!this->INHERITED::setContext(device, paint, matrix)) {
return false;
}
// we don't have a span16 proc
fFlags &= ~kHasSpan16_Flag;
+
+ // If we might end up wanting to draw nothing as part of the gradient
+ // then we should mark ourselves as not being opaque.
+ if (fA >= 0 || (fDiffRadius == 0 && fCenter1 == fCenter2)) {
+ fFlags &= ~kOpaqueAlpha_Flag;
+ }
return true;
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Two_Point_Radial_Gradient)
protected:
Two_Point_Radial_Gradient(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer),
@@ -2033,26 +2081,22 @@ private:
const SkScalar fRadius1;
const SkScalar fRadius2;
SkPoint fDiff;
SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA;
void init() {
fDiff = fCenter1 - fCenter2;
fDiffRadius = fRadius2 - fRadius1;
- SkScalar inv = SkScalarInvert(fDiffRadius);
- fDiff.fX = SkScalarMul(fDiff.fX, inv);
- fDiff.fY = SkScalarMul(fDiff.fY, inv);
- fStartRadius = SkScalarMul(fRadius1, inv);
+ fStartRadius = fRadius1;
fSr2D2 = SkScalarSquare(fStartRadius);
- fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
+ fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SkScalarSquare(fDiffRadius);
fOneOverTwoA = fA ? SkScalarInvert(fA * 2) : 0;
fPtsToUnit.setTranslate(-fCenter1.fX, -fCenter1.fY);
- fPtsToUnit.postScale(inv, inv);
}
};
///////////////////////////////////////////////////////////////////////////////
class Sweep_Gradient : public Gradient_Shader {
public:
Sweep_Gradient(SkScalar cx, SkScalar cy, const SkColor colors[],
@@ -2488,16 +2532,20 @@ SkShader* SkGradientShader::CreateTwoPoi
int colorCount,
SkShader::TileMode mode,
SkUnitMapper* mapper) {
if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
+ if (start == end && startRadius == 0) {
+ return CreateRadial(start, endRadius, colors, pos, colorCount, mode, mapper);
+ }
+
return SkNEW_ARGS(Two_Point_Radial_Gradient,
(start, startRadius, end, endRadius, colors, pos,
colorCount, mode, mapper));
}
SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
const SkColor colors[],
const SkScalar pos[],

View File

@ -18,4 +18,3 @@ See the relevant bugs in bugzilla for information on these patches:
0013-Bug-761890-fonts.patch
0014-Bug-765038-Fix-clang-build.patch
0015-Bug-766017-warnings.patch
0016-Bug-718849-Radial-Gradients.patch

View File

@ -852,9 +852,6 @@ bool Linear_Gradient::setContext(const SkBitmap& device, const SkPaint& paint,
fFlags |= SkShader::kConstInY16_Flag;
}
}
if (fStart == fEnd) {
fFlags &= ~kOpaqueAlpha_Flag;
}
return true;
}
@ -984,11 +981,6 @@ void Linear_Gradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
int toggle = 0;
#endif
if (fStart == fEnd) {
sk_bzero(dstC, count * sizeof(*dstC));
return;
}
if (fDstToIndexClass != kPerspective_MatrixClass) {
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -1182,11 +1174,6 @@ void Linear_Gradient::shadeSpan16(int x, int y,
const uint16_t* SK_RESTRICT cache = this->getCache16();
int toggle = ((x ^ y) & 1) * kDitherStride16;
if (fStart == fEnd) {
sk_bzero(dstC, count * sizeof(*dstC));
return;
}
if (fDstToIndexClass != kPerspective_MatrixClass) {
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
@ -1757,15 +1744,11 @@ void Radial_Gradient::shadeSpan(int x, int y,
segment). If a>0, the start circle falls at least partially
outside the end circle (or vice versa), and the gradient
defines a "tube" where a point may be on one circle (on the
inside of the tube) or the other (outside of the tube). We choose
the one with the highest t value, as long as the radius that it
corresponds to is >=0. In the case where neither root has a positive
radius, we don't draw anything.
inside of the tube) or the other (outside of the tube). We choose
one arbitrarily.
XXXmattwoodrow: I've removed this for now since it breaks
down when Dr == 0. Is there something else we can do instead?
In order to keep the math to within the limits of fixed point,
we divide the entire quadratic by Dr, and replace
we divide the entire quadratic by Dr^2, and replace
(x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving
[Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2
@ -1785,61 +1768,46 @@ void Radial_Gradient::shadeSpan(int x, int y,
namespace {
inline bool two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
SkScalar sr2d2, SkScalar foura,
SkScalar oneOverTwoA, SkScalar diffRadius,
SkScalar startRadius, SkFixed& t) {
inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
SkScalar sr2d2, SkScalar foura,
SkScalar oneOverTwoA, bool posRoot) {
SkScalar c = SkScalarSquare(fx) + SkScalarSquare(fy) - sr2d2;
if (0 == foura) {
SkScalar result = SkScalarDiv(-c, b);
if (result * diffRadius + startRadius >= 0) {
t = SkScalarToFixed(result);
return true;
}
return false;
return SkScalarToFixed(SkScalarDiv(-c, b));
}
SkScalar discrim = SkScalarSquare(b) - SkScalarMul(foura, c);
if (discrim < 0) {
return false;
discrim = -discrim;
}
SkScalar rootDiscrim = SkScalarSqrt(discrim);
// Make sure the results corresponds to a positive radius.
SkScalar result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
if (result * diffRadius + startRadius >= 0) {
t = SkScalarToFixed(result);
return true;
SkScalar result;
if (posRoot) {
result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
} else {
result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
}
result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
if (result * diffRadius + startRadius >= 0) {
t = SkScalarToFixed(result);
return true;
}
return false;
return SkScalarToFixed(result);
}
typedef void (* TwoPointRadialShadeProc)(SkScalar fx, SkScalar dx,
SkScalar fy, SkScalar dy,
SkScalar b, SkScalar db,
SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
SkScalar fDiffRadius, SkScalar fRadius1,
SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count);
void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
SkScalar fy, SkScalar dy,
SkScalar b, SkScalar db,
SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
SkScalar fDiffRadius, SkScalar fRadius1,
SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) {
for (; count > 0; --count) {
SkFixed t;
if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
*(dstC++) = 0;
} else if (t < 0) {
SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
fOneOverTwoA, posRoot);
if (t < 0) {
*dstC++ = cache[-1];
} else if (t > 0xFFFF) {
*dstC++ = cache[Gradient_Shader::kCache32Count * 2];
@ -1856,19 +1824,15 @@ void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
void shadeSpan_twopoint_mirror(SkScalar fx, SkScalar dx,
SkScalar fy, SkScalar dy,
SkScalar b, SkScalar db,
SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
SkScalar fDiffRadius, SkScalar fRadius1,
SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) {
for (; count > 0; --count) {
SkFixed t;
if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
*(dstC++) = 0;
} else {
SkFixed index = mirror_tileproc(t);
SkASSERT(index <= 0xFFFF);
*dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
}
SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
fOneOverTwoA, posRoot);
SkFixed index = mirror_tileproc(t);
SkASSERT(index <= 0xFFFF);
*dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
fx += dx;
fy += dy;
b += db;
@ -1878,19 +1842,15 @@ void shadeSpan_twopoint_mirror(SkScalar fx, SkScalar dx,
void shadeSpan_twopoint_repeat(SkScalar fx, SkScalar dx,
SkScalar fy, SkScalar dy,
SkScalar b, SkScalar db,
SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
SkScalar fDiffRadius, SkScalar fRadius1,
SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
int count) {
for (; count > 0; --count) {
SkFixed t;
if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
*(dstC++) = 0;
} else {
SkFixed index = repeat_tileproc(t);
SkASSERT(index <= 0xFFFF);
*dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
}
SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
fOneOverTwoA, posRoot);
SkFixed index = repeat_tileproc(t);
SkASSERT(index <= 0xFFFF);
*dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
fx += dx;
fy += dy;
b += db;
@ -1980,6 +1940,7 @@ public:
const SkPMColor* SK_RESTRICT cache = this->getCache32();
SkScalar foura = fA * 4;
bool posRoot = fDiffRadius < 0;
if (fDstToIndexClass != kPerspective_MatrixClass) {
SkPoint srcPt;
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
@ -1998,7 +1959,7 @@ public:
dy = fDstToIndex.getSkewY();
}
SkScalar b = (SkScalarMul(fDiff.fX, fx) +
SkScalarMul(fDiff.fY, fy) - fStartRadius * fDiffRadius) * 2;
SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
SkScalar db = (SkScalarMul(fDiff.fX, dx) +
SkScalarMul(fDiff.fY, dy)) * 2;
@ -2011,7 +1972,7 @@ public:
SkASSERT(proc == repeat_tileproc);
}
(*shadeProc)(fx, dx, fy, dy, b, db,
fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1,
fSr2D2, foura, fOneOverTwoA, posRoot,
dstC, cache, count);
} else { // perspective case
SkScalar dstX = SkIntToScalar(x);
@ -2023,14 +1984,11 @@ public:
SkScalar fy = srcPt.fY;
SkScalar b = (SkScalarMul(fDiff.fX, fx) +
SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
SkFixed t;
if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
*(dstC++) = 0;
} else {
SkFixed index = proc(t);
SkASSERT(index <= 0xFFFF);
*dstC++ = cache[index >> (16 - kCache32Bits)];
}
SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
fOneOverTwoA, posRoot);
SkFixed index = proc(t);
SkASSERT(index <= 0xFFFF);
*dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
dstX += SK_Scalar1;
}
}
@ -2045,12 +2003,6 @@ public:
// we don't have a span16 proc
fFlags &= ~kHasSpan16_Flag;
// If we might end up wanting to draw nothing as part of the gradient
// then we should mark ourselves as not being opaque.
if (fA >= 0 || (fDiffRadius == 0 && fCenter1 == fCenter2)) {
fFlags &= ~kOpaqueAlpha_Flag;
}
return true;
}
@ -2086,12 +2038,16 @@ private:
void init() {
fDiff = fCenter1 - fCenter2;
fDiffRadius = fRadius2 - fRadius1;
fStartRadius = fRadius1;
SkScalar inv = SkScalarInvert(fDiffRadius);
fDiff.fX = SkScalarMul(fDiff.fX, inv);
fDiff.fY = SkScalarMul(fDiff.fY, inv);
fStartRadius = SkScalarMul(fRadius1, inv);
fSr2D2 = SkScalarSquare(fStartRadius);
fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SkScalarSquare(fDiffRadius);
fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
fOneOverTwoA = fA ? SkScalarInvert(fA * 2) : 0;
fPtsToUnit.setTranslate(-fCenter1.fX, -fCenter1.fY);
fPtsToUnit.postScale(inv, inv);
}
};
@ -2537,10 +2493,6 @@ SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start,
}
EXPAND_1_COLOR(colorCount);
if (start == end && startRadius == 0) {
return CreateRadial(start, endRadius, colors, pos, colorCount, mode, mapper);
}
return SkNEW_ARGS(Two_Point_Radial_Gradient,
(start, startRadius, end, endRadius, colors, pos,
colorCount, mode, mapper));