Bug 699258 - Move skia gradient shader implementations out of the class to fix a compile error on windows. r=mattwoodrow

This commit is contained in:
Marco Castelluccio 2011-11-11 15:51:00 +13:00
Родитель d886dbad5e
Коммит 9e6c502831
3 изменённых файлов: 663 добавлений и 194 удалений

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

@ -0,0 +1,463 @@
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
@@ -1170,117 +1170,18 @@ public:
fRadius(radius)
{
// make sure our table is insync with our current #define for kSQRT_TABLE_SIZE
SkASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE);
rad_to_unit_matrix(center, radius, &fPtsToUnit);
}
- virtual void shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count);
- virtual void shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC, int count) {
- 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) << kCache16Bits;
-
- if (fDstToIndexClass != kPerspective_MatrixClass) {
- dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
- SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
- SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
-
- if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
- SkFixed storage[2];
- (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
- dx = storage[0];
- dy = storage[1];
- } else {
- SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
- dx = SkScalarToFixed(fDstToIndex.getScaleX());
- dy = SkScalarToFixed(fDstToIndex.getSkewY());
- }
-
- if (proc == clamp_tileproc) {
- const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table;
-
- /* knock these down so we can pin against +- 0x7FFF, which is an immediate load,
- rather than 0xFFFF which is slower. This is a compromise, since it reduces our
- precision, but that appears to be visually OK. If we decide this is OK for
- all of our cases, we could (it seems) put this scale-down into fDstToIndex,
- to avoid having to do these extra shifts each time.
- */
- fx >>= 1;
- dx >>= 1;
- fy >>= 1;
- dy >>= 1;
- if (dy == 0) { // might perform this check for the other modes, but the win will be a smaller % of the total
- fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
- fy *= fy;
- do {
- unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
- unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
- fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
- fx += dx;
- *dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
- toggle ^= (1 << kCache16Bits);
- } while (--count != 0);
- } else {
- do {
- unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
- unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
- fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
- fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
- fx += dx;
- fy += dy;
- *dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
- toggle ^= (1 << kCache16Bits);
- } while (--count != 0);
- }
- } else if (proc == mirror_tileproc) {
- do {
- SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
- unsigned fi = mirror_tileproc(dist);
- SkASSERT(fi <= 0xFFFF);
- fx += dx;
- fy += dy;
- *dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
- toggle ^= (1 << kCache16Bits);
- } while (--count != 0);
- } else {
- SkASSERT(proc == repeat_tileproc);
- do {
- SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
- unsigned fi = repeat_tileproc(dist);
- SkASSERT(fi <= 0xFFFF);
- fx += dx;
- fy += dy;
- *dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
- toggle ^= (1 << kCache16Bits);
- } while (--count != 0);
- }
- } else { // perspective case
- SkScalar dstX = SkIntToScalar(x);
- SkScalar dstY = SkIntToScalar(y);
- do {
- dstProc(fDstToIndex, dstX, dstY, &srcPt);
- unsigned fi = proc(SkScalarToFixed(srcPt.length()));
- SkASSERT(fi <= 0xFFFF);
-
- int index = fi >> (16 - kCache16Bits);
- *dstC++ = cache[toggle + index];
- toggle ^= (1 << kCache16Bits);
-
- dstX += SK_Scalar1;
- } while (--count != 0);
- }
- }
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
+ virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
virtual BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix* matrix,
TileMode* xy,
SkScalar* twoPointRadialParams) const {
if (bitmap) {
this->commonAsABitmap(bitmap);
}
@@ -1494,16 +1395,117 @@ void Radial_Gradient::shadeSpan(int x, i
unsigned fi = proc(SkScalarToFixed(srcPt.length()));
SkASSERT(fi <= 0xFFFF);
*dstC++ = cache[fi >> (16 - kCache32Bits)];
dstX += SK_Scalar1;
} while (--count != 0);
}
}
+void Radial_Gradient::shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC, int count) {
+ 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) << kCache16Bits;
+
+ if (fDstToIndexClass != kPerspective_MatrixClass) {
+ dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+ SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
+ SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
+
+ if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
+ SkFixed storage[2];
+ (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
+ dx = storage[0];
+ dy = storage[1];
+ } else {
+ SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
+ dx = SkScalarToFixed(fDstToIndex.getScaleX());
+ dy = SkScalarToFixed(fDstToIndex.getSkewY());
+ }
+
+ if (proc == clamp_tileproc) {
+ const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table;
+
+ /* knock these down so we can pin against +- 0x7FFF, which is an immediate load,
+ rather than 0xFFFF which is slower. This is a compromise, since it reduces our
+ precision, but that appears to be visually OK. If we decide this is OK for
+ all of our cases, we could (it seems) put this scale-down into fDstToIndex,
+ to avoid having to do these extra shifts each time.
+ */
+ fx >>= 1;
+ dx >>= 1;
+ fy >>= 1;
+ dy >>= 1;
+ if (dy == 0) { // might perform this check for the other modes, but the win will be a smaller % of the total
+ fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
+ fy *= fy;
+ do {
+ unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
+ unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
+ fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
+ fx += dx;
+ *dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
+ toggle ^= (1 << kCache16Bits);
+ } while (--count != 0);
+ } else {
+ do {
+ unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
+ unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
+ fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
+ fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
+ fx += dx;
+ fy += dy;
+ *dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
+ toggle ^= (1 << kCache16Bits);
+ } while (--count != 0);
+ }
+ } else if (proc == mirror_tileproc) {
+ do {
+ SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
+ unsigned fi = mirror_tileproc(dist);
+ SkASSERT(fi <= 0xFFFF);
+ fx += dx;
+ fy += dy;
+ *dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
+ toggle ^= (1 << kCache16Bits);
+ } while (--count != 0);
+ } else {
+ SkASSERT(proc == repeat_tileproc);
+ do {
+ SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
+ unsigned fi = repeat_tileproc(dist);
+ SkASSERT(fi <= 0xFFFF);
+ fx += dx;
+ fy += dy;
+ *dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
+ toggle ^= (1 << kCache16Bits);
+ } while (--count != 0);
+ }
+ } else { // perspective case
+ SkScalar dstX = SkIntToScalar(x);
+ SkScalar dstY = SkIntToScalar(y);
+ do {
+ dstProc(fDstToIndex, dstX, dstY, &srcPt);
+ unsigned fi = proc(SkScalarToFixed(srcPt.length()));
+ SkASSERT(fi <= 0xFFFF);
+
+ int index = fi >> (16 - kCache16Bits);
+ *dstC++ = cache[toggle + index];
+ toggle ^= (1 << kCache16Bits);
+
+ dstX += SK_Scalar1;
+ } while (--count != 0);
+ }
+}
+
/* Two-point radial gradients are specified by two circles, each with a center
point and radius. The gradient can be considered to be a series of
concentric circles, with the color interpolated from the start circle
(at t=0) to the end circle (at t=1).
For each point (x, y) in the span, we want to find the
interpolated circle that intersects that point. The center
of the desired circle (Cx, Cy) falls at some distance t
@@ -1648,109 +1650,17 @@ public:
info->fPoint[0] = fCenter1;
info->fPoint[1] = fCenter2;
info->fRadius[0] = fRadius1;
info->fRadius[1] = fRadius2;
}
return kRadial2_GradientType;
}
- virtual void shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count) {
- SkASSERT(count > 0);
-
- // Zero difference between radii: fill with transparent black.
- // TODO: Is removing this actually correct? Two circles with the
- // same radius, but different centers doesn't sound like it
- // should be cleared
- if (fDiffRadius == 0 && fCenter1 == fCenter2) {
- 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) {
- SkFixed fixedX, fixedY;
- (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
- 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;
- SkScalar db = (SkScalarMul(fDiff.fX, dx) +
- SkScalarMul(fDiff.fY, dy)) * 2;
- if (proc == clamp_tileproc) {
- for (; count > 0; --count) {
- SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, posRoot);
- if (t < 0) {
- *dstC++ = cache[-1];
- } else if (t > 0xFFFF) {
- *dstC++ = cache[kCache32Count * 2];
- } else {
- SkASSERT(t <= 0xFFFF);
- *dstC++ = cache[t >> (16 - kCache32Bits)];
- }
- fx += dx;
- fy += dy;
- b += db;
- }
- } else if (proc == mirror_tileproc) {
- 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 >> (16 - kCache32Bits)];
- fx += dx;
- fy += dy;
- b += db;
- }
- } else {
- SkASSERT(proc == repeat_tileproc);
- 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 >> (16 - kCache32Bits)];
- fx += dx;
- fy += dy;
- b += db;
- }
- }
- } 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 >> (16 - kCache32Bits)];
- dstX += SK_Scalar1;
- }
- }
- }
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
virtual bool setContext(const SkBitmap& device,
const SkPaint& paint,
const SkMatrix& matrix) {
if (!this->INHERITED::setContext(device, paint, matrix)) {
return false;
}
@@ -1804,16 +1714,110 @@ private:
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);
}
};
+void Two_Point_Radial_Gradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count) {
+ SkASSERT(count > 0);
+
+ // Zero difference between radii: fill with transparent black.
+ // TODO: Is removing this actually correct? Two circles with the
+ // same radius, but different centers doesn't sound like it
+ // should be cleared
+ if (fDiffRadius == 0 && fCenter1 == fCenter2) {
+ 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) {
+ SkFixed fixedX, fixedY;
+ (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
+ 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;
+ SkScalar db = (SkScalarMul(fDiff.fX, dx) +
+ SkScalarMul(fDiff.fY, dy)) * 2;
+ if (proc == clamp_tileproc) {
+ for (; count > 0; --count) {
+ SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, posRoot);
+ if (t < 0) {
+ *dstC++ = cache[-1];
+ } else if (t > 0xFFFF) {
+ *dstC++ = cache[kCache32Count * 2];
+ } else {
+ SkASSERT(t <= 0xFFFF);
+ *dstC++ = cache[t >> (16 - kCache32Bits)];
+ }
+ fx += dx;
+ fy += dy;
+ b += db;
+ }
+ } else if (proc == mirror_tileproc) {
+ 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 >> (16 - kCache32Bits)];
+ fx += dx;
+ fy += dy;
+ b += db;
+ }
+ } else {
+ SkASSERT(proc == repeat_tileproc);
+ 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 >> (16 - kCache32Bits)];
+ fx += dx;
+ fy += dy;
+ b += db;
+ }
+ }
+ } 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 >> (16 - kCache32Bits)];
+ dstX += SK_Scalar1;
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
class Sweep_Gradient : public Gradient_Shader {
public:
Sweep_Gradient(SkScalar cx, SkScalar cy, const SkColor colors[],
const SkScalar pos[], int count, SkUnitMapper* mapper)
: Gradient_Shader(colors, pos, count, SkShader::kClamp_TileMode, mapper),
fCenter(SkPoint::Make(cx, cy))

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

@ -1175,107 +1175,8 @@ public:
rad_to_unit_matrix(center, radius, &fPtsToUnit); rad_to_unit_matrix(center, radius, &fPtsToUnit);
} }
virtual void shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count); virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
virtual void shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC, int count) { virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
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) << kCache16Bits;
if (fDstToIndexClass != kPerspective_MatrixClass) {
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
SkFixed storage[2];
(void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
dx = storage[0];
dy = storage[1];
} else {
SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
dx = SkScalarToFixed(fDstToIndex.getScaleX());
dy = SkScalarToFixed(fDstToIndex.getSkewY());
}
if (proc == clamp_tileproc) {
const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table;
/* knock these down so we can pin against +- 0x7FFF, which is an immediate load,
rather than 0xFFFF which is slower. This is a compromise, since it reduces our
precision, but that appears to be visually OK. If we decide this is OK for
all of our cases, we could (it seems) put this scale-down into fDstToIndex,
to avoid having to do these extra shifts each time.
*/
fx >>= 1;
dx >>= 1;
fy >>= 1;
dy >>= 1;
if (dy == 0) { // might perform this check for the other modes, but the win will be a smaller % of the total
fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
fy *= fy;
do {
unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
fx += dx;
*dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
} else {
do {
unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
fx += dx;
fy += dy;
*dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
}
} else if (proc == mirror_tileproc) {
do {
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
unsigned fi = mirror_tileproc(dist);
SkASSERT(fi <= 0xFFFF);
fx += dx;
fy += dy;
*dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
} else {
SkASSERT(proc == repeat_tileproc);
do {
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
unsigned fi = repeat_tileproc(dist);
SkASSERT(fi <= 0xFFFF);
fx += dx;
fy += dy;
*dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
}
} else { // perspective case
SkScalar dstX = SkIntToScalar(x);
SkScalar dstY = SkIntToScalar(y);
do {
dstProc(fDstToIndex, dstX, dstY, &srcPt);
unsigned fi = proc(SkScalarToFixed(srcPt.length()));
SkASSERT(fi <= 0xFFFF);
int index = fi >> (16 - kCache16Bits);
*dstC++ = cache[toggle + index];
toggle ^= (1 << kCache16Bits);
dstX += SK_Scalar1;
} while (--count != 0);
}
}
virtual BitmapType asABitmap(SkBitmap* bitmap, virtual BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix* matrix, SkMatrix* matrix,
@ -1499,6 +1400,107 @@ void Radial_Gradient::shadeSpan(int x, int y,
} }
} }
void Radial_Gradient::shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC, int count) {
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) << kCache16Bits;
if (fDstToIndexClass != kPerspective_MatrixClass) {
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
SkFixed storage[2];
(void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
dx = storage[0];
dy = storage[1];
} else {
SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
dx = SkScalarToFixed(fDstToIndex.getScaleX());
dy = SkScalarToFixed(fDstToIndex.getSkewY());
}
if (proc == clamp_tileproc) {
const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table;
/* knock these down so we can pin against +- 0x7FFF, which is an immediate load,
rather than 0xFFFF which is slower. This is a compromise, since it reduces our
precision, but that appears to be visually OK. If we decide this is OK for
all of our cases, we could (it seems) put this scale-down into fDstToIndex,
to avoid having to do these extra shifts each time.
*/
fx >>= 1;
dx >>= 1;
fy >>= 1;
dy >>= 1;
if (dy == 0) { // might perform this check for the other modes, but the win will be a smaller % of the total
fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
fy *= fy;
do {
unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
fx += dx;
*dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
} else {
do {
unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
fx += dx;
fy += dy;
*dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
}
} else if (proc == mirror_tileproc) {
do {
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
unsigned fi = mirror_tileproc(dist);
SkASSERT(fi <= 0xFFFF);
fx += dx;
fy += dy;
*dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
} else {
SkASSERT(proc == repeat_tileproc);
do {
SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
unsigned fi = repeat_tileproc(dist);
SkASSERT(fi <= 0xFFFF);
fx += dx;
fy += dy;
*dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
toggle ^= (1 << kCache16Bits);
} while (--count != 0);
}
} else { // perspective case
SkScalar dstX = SkIntToScalar(x);
SkScalar dstY = SkIntToScalar(y);
do {
dstProc(fDstToIndex, dstX, dstY, &srcPt);
unsigned fi = proc(SkScalarToFixed(srcPt.length()));
SkASSERT(fi <= 0xFFFF);
int index = fi >> (16 - kCache16Bits);
*dstC++ = cache[toggle + index];
toggle ^= (1 << kCache16Bits);
dstX += SK_Scalar1;
} while (--count != 0);
}
}
/* Two-point radial gradients are specified by two circles, each with a center /* Two-point radial gradients are specified by two circles, each with a center
point and radius. The gradient can be considered to be a series of point and radius. The gradient can be considered to be a series of
concentric circles, with the color interpolated from the start circle concentric circles, with the color interpolated from the start circle
@ -1653,99 +1655,7 @@ public:
return kRadial2_GradientType; return kRadial2_GradientType;
} }
virtual void shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count) { virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
SkASSERT(count > 0);
// Zero difference between radii: fill with transparent black.
// TODO: Is removing this actually correct? Two circles with the
// same radius, but different centers doesn't sound like it
// should be cleared
if (fDiffRadius == 0 && fCenter1 == fCenter2) {
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) {
SkFixed fixedX, fixedY;
(void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
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;
SkScalar db = (SkScalarMul(fDiff.fX, dx) +
SkScalarMul(fDiff.fY, dy)) * 2;
if (proc == clamp_tileproc) {
for (; count > 0; --count) {
SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, posRoot);
if (t < 0) {
*dstC++ = cache[-1];
} else if (t > 0xFFFF) {
*dstC++ = cache[kCache32Count * 2];
} else {
SkASSERT(t <= 0xFFFF);
*dstC++ = cache[t >> (16 - kCache32Bits)];
}
fx += dx;
fy += dy;
b += db;
}
} else if (proc == mirror_tileproc) {
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 >> (16 - kCache32Bits)];
fx += dx;
fy += dy;
b += db;
}
} else {
SkASSERT(proc == repeat_tileproc);
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 >> (16 - kCache32Bits)];
fx += dx;
fy += dy;
b += db;
}
}
} 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 >> (16 - kCache32Bits)];
dstX += SK_Scalar1;
}
}
}
virtual bool setContext(const SkBitmap& device, virtual bool setContext(const SkBitmap& device,
const SkPaint& paint, const SkPaint& paint,
@ -1809,6 +1719,100 @@ private:
} }
}; };
void Two_Point_Radial_Gradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count) {
SkASSERT(count > 0);
// Zero difference between radii: fill with transparent black.
// TODO: Is removing this actually correct? Two circles with the
// same radius, but different centers doesn't sound like it
// should be cleared
if (fDiffRadius == 0 && fCenter1 == fCenter2) {
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) {
SkFixed fixedX, fixedY;
(void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
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;
SkScalar db = (SkScalarMul(fDiff.fX, dx) +
SkScalarMul(fDiff.fY, dy)) * 2;
if (proc == clamp_tileproc) {
for (; count > 0; --count) {
SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, posRoot);
if (t < 0) {
*dstC++ = cache[-1];
} else if (t > 0xFFFF) {
*dstC++ = cache[kCache32Count * 2];
} else {
SkASSERT(t <= 0xFFFF);
*dstC++ = cache[t >> (16 - kCache32Bits)];
}
fx += dx;
fy += dy;
b += db;
}
} else if (proc == mirror_tileproc) {
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 >> (16 - kCache32Bits)];
fx += dx;
fy += dy;
b += db;
}
} else {
SkASSERT(proc == repeat_tileproc);
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 >> (16 - kCache32Bits)];
fx += dx;
fy += dy;
b += db;
}
}
} 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 >> (16 - kCache32Bits)];
dstX += SK_Scalar1;
}
}
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class Sweep_Gradient : public Gradient_Shader { class Sweep_Gradient : public Gradient_Shader {

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

@ -103,3 +103,5 @@ patch -p3 < getpostextpath.patch
patch -p3 < new-aa.patch patch -p3 < new-aa.patch
# Bug 688366 - Fix Skia marking radial gradients with the same radius as invalid. # Bug 688366 - Fix Skia marking radial gradients with the same radius as invalid.
patch -p3 < radial-gradients.patch patch -p3 < radial-gradients.patch
# Fix restrict keyword problem for VS2005
patch -p3 < skia-restrict-problem.patch