--- a/gfx/skia/fix-gradient-clamp.patch
+++ b/gfx/skia/fix-gradient-clamp.patch
@@ -1,30 +1,30 @@
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
-@@ -165,16 +165,17 @@ private:
+@@ -167,16 +167,17 @@ private:
mutable uint16_t* fCache16; // working ptr. If this is NULL, we need to recompute the cache values
mutable SkPMColor* fCache32; // working ptr. If this is NULL, we need to recompute the cache values
mutable uint16_t* fCache16Storage; // storage for fCache16, allocated on demand
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);
void setCacheAlpha(U8CPU alpha) const;
+ void initCommon();
typedef SkShader INHERITED;
};
-
-@@ -505,16 +506,31 @@ static inline U8CPU dither_fixed_to_8(Sk
+@@ -512,16 +513,31 @@ static inline U8CPU dither_fixed_to_8(Sk
* For dithering with premultiply, we want to ceiling the alpha component,
* to ensure that it is always >= any color component.
*/
static inline U8CPU dither_ceil_fixed_to_8(SkFixed n) {
n >>= 8;
return ((n << 1) - (n | (n >> 8))) >> 8;
}
@@ -46,17 +46,17 @@ diff --git a/gfx/skia/src/effects/SkGrad
void Gradient_Shader::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
int count, U8CPU paintAlpha) {
SkASSERT(count > 1);
// need to apply paintAlpha to our two endpoints
SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
SkFixed da;
{
-@@ -606,24 +622,24 @@ const uint16_t* Gradient_Shader::getCach
+@@ -613,24 +629,24 @@ const uint16_t* Gradient_Shader::getCach
}
}
return fCache16;
}
const SkPMColor* Gradient_Shader::getCache32() const {
if (fCache32 == NULL) {
// double the count for dither entries
@@ -73,17 +73,17 @@ diff --git a/gfx/skia/src/effects/SkGrad
if (fColorCount == 2) {
Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
kCache32Count, fCacheAlpha);
} else {
Rec* rec = fRecs;
int prevIndex = 0;
for (int i = 1; i < fColorCount; i++) {
int nextIndex = SkFixedToFFFF(rec[i].fPos) >> (16 - kCache32Bits);
-@@ -637,28 +653,31 @@ const SkPMColor* Gradient_Shader::getCac
+@@ -644,28 +660,31 @@ const SkPMColor* Gradient_Shader::getCac
}
SkASSERT(prevIndex == kCache32Count - 1);
}
if (fMapper) {
SkMallocPixelRef* newPR = SkNEW_ARGS(SkMallocPixelRef,
(NULL, allocSize, NULL));
SkPMColor* linear = fCache32; // just computed linear data
@@ -107,85 +107,86 @@ diff --git a/gfx/skia/src/effects/SkGrad
return fCache32;
}
/*
* Because our caller might rebuild the same (logically the same) gradient
* over and over, we'd like to return exactly the same "bitmap" if possible,
* allowing the client to utilize a cache of our bitmap (e.g. with a GPU).
* To do that, we maintain a private cache of built-bitmaps, based on our
-@@ -866,29 +885,37 @@ void Linear_Gradient::shadeSpan(int x, i
+@@ -875,28 +894,38 @@ void Linear_Gradient::shadeSpan(int x, i
dx = dxStorage[0];
} else {
SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
dx = SkScalarToFixed(fDstToIndex.getScaleX());
}
if (SkFixedNearlyZero(dx)) {
// we're a vertical gradient, so no change in a span
-- unsigned fi = proc(fx);
-- SkASSERT(fi <= 0xFFFF);
-- // TODO: dither version
-- sk_memset32(dstC, cache[fi >> (16 - kCache32Bits)], count);
+- unsigned fi = proc(fx) >> (16 - kCache32Bits);
+- sk_memset32_dither(dstC, cache[toggle + fi],
+- cache[(toggle ^ TOGGLE_MASK) + fi], count);
+ if (proc == clamp_tileproc) {
+ if (fx < 0) {
+ sk_memset32(dstC, cache[-1], count);
+ } else if (fx > 0xFFFF) {
+ sk_memset32(dstC, cache[kCache32Count * 2], count);
+ } else {
-+ sk_memset32(dstC, cache[fx >> (16 - kCache32Bits)], count);
++ unsigned fi = proc(fx) >> (16 - kCache32Bits);
++ sk_memset32_dither(dstC, cache[toggle + fi],
++ cache[(toggle ^ TOGGLE_MASK) + fi], count);
+ }
+ } else {
-+ unsigned fi = proc(fx);
-+ SkASSERT(fi <= 0xFFFF);
-+ // TODO: dither version
-+ sk_memset32(dstC, cache[fi >> (16 - kCache32Bits)], count);
++ unsigned fi = proc(fx) >> (16 - kCache32Bits);
++ sk_memset32_dither(dstC, cache[toggle + fi],
++ cache[(toggle ^ TOGGLE_MASK) + fi], count);
+ }
} else if (proc == clamp_tileproc) {
SkClampRange range;
- range.init(fx, dx, count, 0, 0xFF);
+- range.init(fx, dx, count, 0, 0xFF);
++ range.init(fx, dx, count, cache[-1], cache[kCache32Count * 2]);
if ((count = range.fCount0) > 0) {
- sk_memset32_dither(dstC,
- cache[toggle + range.fV0],
- cache[(toggle ^ TOGGLE_MASK) + range.fV0],
- count);
-+ // Do we really want to dither the clamp values?
-+ sk_memset32(dstC, cache[-1], count);
++ // Do we really want to dither the clamp values?
++ sk_memset32(dstC, range.fV0, count);
dstC += count;
}
if ((count = range.fCount1) > 0) {
int unroll = count >> 3;
fx = range.fFx1;
for (int i = 0; i < unroll; i++) {
NO_CHECK_ITER; NO_CHECK_ITER;
NO_CHECK_ITER; NO_CHECK_ITER;
-@@ -897,20 +924,17 @@ void Linear_Gradient::shadeSpan(int x, i
+@@ -905,20 +934,17 @@ void Linear_Gradient::shadeSpan(int x, i
}
if ((count &= 7) > 0) {
do {
NO_CHECK_ITER;
} while (--count != 0);
}
}
if ((count = range.fCount2) > 0) {
- sk_memset32_dither(dstC,
- cache[toggle + range.fV1],
- cache[(toggle ^ TOGGLE_MASK) + range.fV1],
- count);
-+ sk_memset32(dstC, cache[kCache32Count * 2], count);
++ sk_memset32(dstC, range.fV1, count);
}
} else if (proc == mirror_tileproc) {
do {
unsigned fi = mirror_8bits(fx >> 8);
SkASSERT(fi <= 0xFF);
fx += dx;
*dstC++ = cache[toggle + fi];
toggle ^= TOGGLE_MASK;
-@@ -1662,19 +1686,24 @@ public:
+@@ -1670,19 +1699,24 @@ public:
}
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);
@@ -203,22 +204,8 @@ diff --git a/gfx/skia/src/effects/SkGrad
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);
-diff --git a/gfx/skia/update.sh b/gfx/skia/update.sh
---- a/gfx/skia/update.sh
-+++ b/gfx/skia/update.sh
-@@ -90,9 +90,10 @@ if [ -n "$rev" ]; then
- version=$rev
- sed -i "" "s/r[0-9][0-9][0-9][0-9]/r$version/" README_MOZILLA
- else
- echo "Remember to update README_MOZILLA with the version details."
- fi
-
- # Patch to get arm opts to build with frame pointers enabled. Bug 689069
- patch -p3 < arm-opts.patch
-+patch -p3
-
new file mode 100644
--- /dev/null
+++ b/gfx/skia/getpostextpath.patch
@@ -0,0 +1,70 @@
+diff --git a/gfx/skia/include/core/SkPaint.h b/gfx/skia/include/core/SkPaint.h
+--- a/gfx/skia/include/core/SkPaint.h
++++ b/gfx/skia/include/core/SkPaint.h
+@@ -836,16 +836,19 @@ public:
+
+ /** Return the path (outline) for the specified text.
+ Note: just like SkCanvas::drawText, this will respect the Align setting
+ in the paint.
+ */
+ void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
+ SkPath* path) const;
+
++ void getPosTextPath(const void* text, size_t length,
++ const SkPoint pos[], SkPath* path) const;
++
+ #ifdef SK_BUILD_FOR_ANDROID
+ const SkGlyph& getUnicharMetrics(SkUnichar);
+ const void* findImage(const SkGlyph&);
+
+ uint32_t getGenerationID() const;
+ #endif
+
+ // returns true if the paint's settings (e.g. xfermode + alpha) resolve to
+diff --git a/gfx/skia/src/core/SkPaint.cpp b/gfx/skia/src/core/SkPaint.cpp
+--- a/gfx/skia/src/core/SkPaint.cpp
++++ b/gfx/skia/src/core/SkPaint.cpp
+@@ -1242,16 +1242,43 @@ void SkPaint::getTextPath(const void* te
+ const SkPath* iterPath;
+ while ((iterPath = iter.next(&xpos)) != NULL) {
+ matrix.postTranslate(xpos - prevXPos, 0);
+ path->addPath(*iterPath, matrix);
+ prevXPos = xpos;
+ }
+ }
+
++void SkPaint::getPosTextPath(const void* textData, size_t length,
++ const SkPoint pos[], SkPath* path) const {
++ SkASSERT(length == 0 || textData != NULL);
++
++ const char* text = (const char*)textData;
++ if (text == NULL || length == 0 || path == NULL) {
++ return;
++ }
++
++ SkTextToPathIter iter(text, length, *this, false, true);
++ SkMatrix matrix;
++ SkPoint prevPos;
++ prevPos.set(0, 0);
++
++ matrix.setScale(iter.getPathScale(), iter.getPathScale());
++ path->reset();
++
++ unsigned int i = 0;
++ const SkPath* iterPath;
++ while ((iterPath = iter.next(NULL)) != NULL) {
++ matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
++ path->addPath(*iterPath, matrix);
++ prevPos = pos[i];
++ i++;
++ }
++}
++
+ static void add_flattenable(SkDescriptor* desc, uint32_t tag,
+ SkFlattenableWriteBuffer* buffer) {
+ buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
+ }
+
+ // SkFontHost can override this choice in FilterRec()
+ static SkMask::Format computeMaskFormat(const SkPaint& paint) {
+ uint32_t flags = paint.getFlags();
--- a/gfx/skia/include/core/SkPaint.h
+++ b/gfx/skia/include/core/SkPaint.h
@@ -836,16 +836,19 @@ public:
/** Return the path (outline) for the specified text.
Note: just like SkCanvas::drawText, this will respect the Align setting
in the paint.
*/
void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
SkPath* path) const;
+ void getPosTextPath(const void* text, size_t length,
+ const SkPoint pos[], SkPath* path) const;
+
#ifdef SK_BUILD_FOR_ANDROID
const SkGlyph& getUnicharMetrics(SkUnichar);
const void* findImage(const SkGlyph&);
uint32_t getGenerationID() const;
#endif
// returns true if the paint's settings (e.g. xfermode + alpha) resolve to
--- a/gfx/skia/new-aa.patch
+++ b/gfx/skia/new-aa.patch
@@ -1,22 +1,22 @@
diff --git a/gfx/skia/src/core/SkScan_AntiPath.cpp b/gfx/skia/src/core/SkScan_AntiPath.cpp
--- a/gfx/skia/src/core/SkScan_AntiPath.cpp
+++ b/gfx/skia/src/core/SkScan_AntiPath.cpp
-@@ -26,17 +26,17 @@
- this is often faster for large objects with big spans
+@@ -31,17 +31,17 @@
+ - supersampled coordinates, scale equal to the output * SCALE
NEW_AA is a set of code-changes to try to make both paths produce identical
results. Its not quite there yet, though the remaining differences may be
in the subsequent blits, and not in the different masks/runs...
*/
//#define FORCE_SUPERMASK
//#define FORCE_RLE
-//#define SK_SUPPORT_NEW_AA
+#define SK_SUPPORT_NEW_AA
///////////////////////////////////////////////////////////////////////////////
+ /// Base class for a single-pass supersampled blitter.
class BaseSuperBlitter : public SkBlitter {
public:
BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
const SkRegion& clip);
-
--- a/gfx/skia/radial-gradients.patch
+++ b/gfx/skia/radial-gradients.patch
@@ -1,17 +1,17 @@
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
-@@ -1652,17 +1652,20 @@ public:
+@@ -1665,17 +1665,20 @@ public:
}
return kRadial2_GradientType;
}
- virtual void shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count) {
+ virtual void shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count) SK_OVERRIDE {
SkASSERT(count > 0);
// Zero difference between radii: fill with transparent black.
- if (fDiffRadius == 0) {
+ // 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) {
--- a/gfx/skia/skia_restrict_problem.patch
+++ b/gfx/skia/skia_restrict_problem.patch
@@ -1,22 +1,21 @@
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)
+@@ -1184,116 +1184,17 @@ public:
{
// 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) {
+ virtual void shadeSpan(int x, int y, SkPMColor* dstC, int count) SK_OVERRIDE;
+- virtual void shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC, int count) SK_OVERRIDE {
- 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;
-
@@ -106,27 +105,26 @@ diff --git a/gfx/skia/src/effects/SkGrad
- 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 void shadeSpan16(int x, int y, uint16_t* dstC, int count) SK_OVERRIDE;
virtual BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix* matrix,
TileMode* xy,
- SkScalar* twoPointRadialParams) const {
+ SkScalar* twoPointRadialParams) const SK_OVERRIDE {
if (bitmap) {
this->commonAsABitmap(bitmap);
}
-@@ -1494,16 +1395,117 @@ void Radial_Gradient::shadeSpan(int x, i
+@@ -1507,16 +1408,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);
}
}
@@ -234,26 +232,26 @@ diff --git a/gfx/skia/src/effects/SkGrad
/* 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:
+@@ -1661,109 +1663,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) {
+- virtual void shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, int count) SK_OVERRIDE {
- 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));
@@ -336,26 +334,26 @@ diff --git a/gfx/skia/src/effects/SkGrad
- 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 void shadeSpan(int x, int y, SkPMColor* dstC, int count) SK_OVERRIDE;
virtual bool setContext(const SkBitmap& device,
const SkPaint& paint,
- const SkMatrix& matrix) {
+ const SkMatrix& matrix) SK_OVERRIDE {
if (!this->INHERITED::setContext(device, paint, matrix)) {
return false;
}
-@@ -1804,16 +1714,110 @@ private:
+@@ -1817,16 +1727,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);
}
};
@@ -374,17 +372,17 @@ diff --git a/gfx/skia/src/effects/SkGrad
+ 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);
++ 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);
--- a/gfx/skia/src/core/SkPaint.cpp
+++ b/gfx/skia/src/core/SkPaint.cpp
@@ -1242,16 +1242,43 @@ void SkPaint::getTextPath(const void* te
const SkPath* iterPath;
while ((iterPath = iter.next(&xpos)) != NULL) {
matrix.postTranslate(xpos - prevXPos, 0);
path->addPath(*iterPath, matrix);
prevXPos = xpos;
}
}
+void SkPaint::getPosTextPath(const void* textData, size_t length,
+ const SkPoint pos[], SkPath* path) const {
+ SkASSERT(length == 0 || textData != NULL);
+
+ const char* text = (const char*)textData;
+ if (text == NULL || length == 0 || path == NULL) {
+ return;
+ }
+
+ SkTextToPathIter iter(text, length, *this, false, true);
+ SkMatrix matrix;
+ SkPoint prevPos;
+ prevPos.set(0, 0);
+
+ matrix.setScale(iter.getPathScale(), iter.getPathScale());
+ path->reset();
+
+ unsigned int i = 0;
+ const SkPath* iterPath;
+ while ((iterPath = iter.next(NULL)) != NULL) {
+ matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
+ path->addPath(*iterPath, matrix);
+ prevPos = pos[i];
+ i++;
+ }
+}
+
static void add_flattenable(SkDescriptor* desc, uint32_t tag,
SkFlattenableWriteBuffer* buffer) {
buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
}
// SkFontHost can override this choice in FilterRec()
static SkMask::Format computeMaskFormat(const SkPaint& paint) {
uint32_t flags = paint.getFlags();
--- a/gfx/skia/src/core/SkScan_AntiPath.cpp
+++ b/gfx/skia/src/core/SkScan_AntiPath.cpp
@@ -31,17 +31,17 @@
- supersampled coordinates, scale equal to the output * SCALE
NEW_AA is a set of code-changes to try to make both paths produce identical
results. Its not quite there yet, though the remaining differences may be
in the subsequent blits, and not in the different masks/runs...
*/
//#define FORCE_SUPERMASK
//#define FORCE_RLE
-//#define SK_SUPPORT_NEW_AA
+#define SK_SUPPORT_NEW_AA
///////////////////////////////////////////////////////////////////////////////
/// Base class for a single-pass supersampled blitter.
class BaseSuperBlitter : public SkBlitter {
public:
BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
const SkRegion& clip);
--- a/gfx/skia/src/effects/SkGradientShader.cpp
+++ b/gfx/skia/src/effects/SkGradientShader.cpp
@@ -167,16 +167,17 @@ private:
mutable uint16_t* fCache16; // working ptr. If this is NULL, we need to recompute the cache values
mutable SkPMColor* fCache32; // working ptr. If this is NULL, we need to recompute the cache values
mutable uint16_t* fCache16Storage; // storage for fCache16, allocated on demand
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);
void setCacheAlpha(U8CPU alpha) const;
void initCommon();
typedef SkShader INHERITED;
};
@@ -512,16 +513,31 @@ static inline U8CPU dither_fixed_to_8(Sk
* For dithering with premultiply, we want to ceiling the alpha component,
* to ensure that it is always >= any color component.
*/
static inline U8CPU dither_ceil_fixed_to_8(SkFixed n) {
n >>= 8;
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);
// need to apply paintAlpha to our two endpoints
SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
SkFixed da;
{
@@ -613,24 +629,24 @@ const uint16_t* Gradient_Shader::getCach
}
}
return fCache16;
}
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],
kCache32Count, fCacheAlpha);
} else {
Rec* rec = fRecs;
int prevIndex = 0;
for (int i = 1; i < fColorCount; i++) {
int nextIndex = SkFixedToFFFF(rec[i].fPos) >> (16 - kCache32Bits);
@@ -644,28 +660,31 @@ const SkPMColor* Gradient_Shader::getCac
}
SkASSERT(prevIndex == kCache32Count - 1);
}
if (fMapper) {
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 < kCache32Count; i++) {
int index = map->mapUnit16((i << 8) | i) >> 8;
mapped[i] = linear[index];
mapped[i + kCache32Count] = linear[index + kCache32Count];
}
fCache32PixelRef->unref();
fCache32PixelRef = newPR;
- fCache32 = (SkPMColor*)newPR->getAddr();
+ fCache32 = (SkPMColor*)newPR->getAddr() + 1;
}
}
+ //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;
}
/*
* Because our caller might rebuild the same (logically the same) gradient
* over and over, we'd like to return exactly the same "bitmap" if possible,
* allowing the client to utilize a cache of our bitmap (e.g. with a GPU).
* To do that, we maintain a private cache of built-bitmaps, based on our
@@ -875,28 +894,38 @@ void Linear_Gradient::shadeSpan(int x, i
dx = dxStorage[0];
} else {
SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
dx = SkScalarToFixed(fDstToIndex.getScaleX());
}
if (SkFixedNearlyZero(dx)) {
// we're a vertical gradient, so no change in a span
- unsigned fi = proc(fx) >> (16 - kCache32Bits);
- sk_memset32_dither(dstC, cache[toggle + fi],
- cache[(toggle ^ TOGGLE_MASK) + fi], count);
+ if (proc == clamp_tileproc) {
+ if (fx < 0) {
+ sk_memset32(dstC, cache[-1], count);
+ } else if (fx > 0xFFFF) {
+ sk_memset32(dstC, cache[kCache32Count * 2], count);
+ } else {
+ unsigned fi = proc(fx) >> (16 - kCache32Bits);
+ sk_memset32_dither(dstC, cache[toggle + fi],
+ cache[(toggle ^ TOGGLE_MASK) + fi], count);
+ }
+ } else {
+ unsigned fi = proc(fx) >> (16 - kCache32Bits);
+ sk_memset32_dither(dstC, cache[toggle + fi],
+ cache[(toggle ^ TOGGLE_MASK) + fi], count);
+ }
} else if (proc == clamp_tileproc) {
SkClampRange range;
- range.init(fx, dx, count, 0, 0xFF);
+ range.init(fx, dx, count, cache[-1], cache[kCache32Count * 2]);
if ((count = range.fCount0) > 0) {
- sk_memset32_dither(dstC,
- cache[toggle + range.fV0],
- cache[(toggle ^ TOGGLE_MASK) + range.fV0],
- count);
+ // Do we really want to dither the clamp values?
+ sk_memset32(dstC, range.fV0, count);
dstC += count;
}
if ((count = range.fCount1) > 0) {
int unroll = count >> 3;
fx = range.fFx1;
for (int i = 0; i < unroll; i++) {
NO_CHECK_ITER; NO_CHECK_ITER;
NO_CHECK_ITER; NO_CHECK_ITER;
@@ -905,20 +934,17 @@ void Linear_Gradient::shadeSpan(int x, i
}
if ((count &= 7) > 0) {
do {
NO_CHECK_ITER;
} while (--count != 0);
}
}
if ((count = range.fCount2) > 0) {
- sk_memset32_dither(dstC,
- cache[toggle + range.fV1],
- cache[(toggle ^ TOGGLE_MASK) + range.fV1],
- count);
+ sk_memset32(dstC, range.fV1, count);
}
} else if (proc == mirror_tileproc) {
do {
unsigned fi = mirror_8bits(fx >> 8);
SkASSERT(fi <= 0xFF);
fx += dx;
*dstC++ = cache[toggle + fi];
toggle ^= TOGGLE_MASK;
@@ -1155,116 +1181,17 @@ public:
{
// 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* dstC, int count) SK_OVERRIDE;
- virtual void shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC, int count) SK_OVERRIDE {
- 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 shadeSpan16(int x, int y, uint16_t* dstC, int count) SK_OVERRIDE;
virtual BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix* matrix,
TileMode* xy,
SkScalar* twoPointRadialParams) const SK_OVERRIDE {
if (bitmap) {
this->commonAsABitmap(bitmap);
}
@@ -1478,16 +1405,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
@@ -1632,101 +1660,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) SK_OVERRIDE {
- SkASSERT(count > 0);
-
- // Zero difference between radii: fill with transparent black.
- if (fDiffRadius == 0) {
- 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);
- SkFixed index = SkClampMax(t, 0xFFFF);
- SkASSERT(index <= 0xFFFF);
- *dstC++ = cache[index >> (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) SK_OVERRIDE;
virtual bool setContext(const SkBitmap& device,
const SkPaint& paint,
const SkMatrix& matrix) SK_OVERRIDE {
if (!this->INHERITED::setContext(device, paint, matrix)) {
return false;
}
@@ -1780,16 +1724,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))
--- a/gfx/skia/src/opts/SkBlitRow_opts_arm.cpp
+++ b/gfx/skia/src/opts/SkBlitRow_opts_arm.cpp
@@ -545,17 +545,17 @@ static void S32A_Opaque_BlitRow32_neon(S
#define S32A_Opaque_BlitRow32_PROC S32A_Opaque_BlitRow32_neon
#else
#ifdef TEST_SRC_ALPHA
#error The ARM asm version of S32A_Opaque_BlitRow32 does not support TEST_SRC_ALPHA
#endif
-static void S32A_Opaque_BlitRow32_arm(SkPMColor* SK_RESTRICT dst,
+static void __attribute((noinline,optimize("-fomit-frame-pointer"))) S32A_Opaque_BlitRow32_arm(SkPMColor* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha) {
SkASSERT(255 == alpha);
/* Does not support the TEST_SRC_ALPHA case */
asm volatile (
"cmp %[count], #0 \n\t" /* comparing count with 0 */
@@ -642,17 +642,17 @@ static void S32A_Opaque_BlitRow32_arm(Sk
);
}
#define S32A_Opaque_BlitRow32_PROC S32A_Opaque_BlitRow32_arm
#endif
/*
* ARM asm version of S32A_Blend_BlitRow32
*/
-static void S32A_Blend_BlitRow32_arm(SkPMColor* SK_RESTRICT dst,
+static void __attribute((noinline,optimize("-fomit-frame-pointer"))) S32A_Blend_BlitRow32_arm(SkPMColor* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha) {
asm volatile (
"cmp %[count], #0 \n\t" /* comparing count with 0 */
"beq 3f \n\t" /* if zero exit */
"mov r12, #0xff \n\t" /* load the 0xff mask in r12 */
"orr r12, r12, r12, lsl #16 \n\t" /* convert it to 0xff00ff in r12 */
--- a/gfx/skia/update.sh
+++ b/gfx/skia/update.sh
@@ -99,11 +99,9 @@ patch -p3 < fix-gradient-clamp.patch
# Bug 687189 - Implement SkPaint::getPosTextPath.
patch -p3 < getpostextpath.patch
# Bug 688365 - Enable Skia 'New AA' mode.
patch -p3 < new-aa.patch
# Bug 688366 - Fix Skia marking radial gradients with the same radius as invalid.
patch -p3 < radial-gradients.patch
# Fix restrict keyword problem for VS2005
patch -p3 < skia_restrict_problem.patch
-# Bug 705656 - Broken SKIA compilation on mingw
-patch -p3 < mingw-fix.patch