| Index: src/effects/SkLightingImageFilter.cpp
|
| diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
|
| index 19da3ed5e8fa2389e6760ae67ba45ec9bec850d3..4be9f17db5f2be984ecc889fe81c8ff2cb6510ba 100644
|
| --- a/src/effects/SkLightingImageFilter.cpp
|
| +++ b/src/effects/SkLightingImageFilter.cpp
|
| @@ -185,35 +185,55 @@ inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
|
| surfaceScale);
|
| }
|
|
|
| -template <class LightingType, class LightType> void lightBitmap(const LightingType& lightingType,
|
| - const SkImageFilterLight* light,
|
| - const SkBitmap& src,
|
| - SkBitmap* dst,
|
| - SkScalar surfaceScale,
|
| - const SkIRect& bounds) {
|
| +
|
| +class UncheckedPixelFetcher {
|
| +public:
|
| + static inline uint32_t Fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) {
|
| + return SkGetPackedA32(*src.getAddr32(x, y));
|
| + }
|
| +};
|
| +
|
| +// The DecalPixelFetcher is used when the destination crop rect exceeds the input bitmap bounds.
|
| +class DecalPixelFetcher {
|
| +public:
|
| + static inline uint32_t Fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) {
|
| + if (x < bounds.fLeft || x >= bounds.fRight || y < bounds.fTop || y >= bounds.fBottom) {
|
| + return 0;
|
| + } else {
|
| + return SkGetPackedA32(*src.getAddr32(x, y));
|
| + }
|
| + }
|
| +};
|
| +
|
| +template <class LightingType, class LightType, class PixelFetcher>
|
| +void lightBitmap(const LightingType& lightingType,
|
| + const SkImageFilterLight* light,
|
| + const SkBitmap& src,
|
| + SkBitmap* dst,
|
| + SkScalar surfaceScale,
|
| + const SkIRect& bounds) {
|
| SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height());
|
| const LightType* l = static_cast<const LightType*>(light);
|
| int left = bounds.left(), right = bounds.right();
|
| int bottom = bounds.bottom();
|
| int y = bounds.top();
|
| + SkIRect srcBounds = src.bounds();
|
| SkPMColor* dptr = dst->getAddr32(0, 0);
|
| {
|
| int x = left;
|
| - const SkPMColor* row1 = src.getAddr32(x, y);
|
| - const SkPMColor* row2 = src.getAddr32(x, y + 1);
|
| int m[9];
|
| - m[4] = SkGetPackedA32(*row1++);
|
| - m[5] = SkGetPackedA32(*row1++);
|
| - m[7] = SkGetPackedA32(*row2++);
|
| - m[8] = SkGetPackedA32(*row2++);
|
| + m[4] = PixelFetcher::Fetch(src, x, y, srcBounds);
|
| + m[5] = PixelFetcher::Fetch(src, x + 1, y, srcBounds);
|
| + m[7] = PixelFetcher::Fetch(src, x, y + 1, srcBounds);
|
| + m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds);
|
| SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
|
| *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight,
|
| l->lightColor(surfaceToLight));
|
| for (++x; x < right - 1; ++x)
|
| {
|
| shiftMatrixLeft(m);
|
| - m[5] = SkGetPackedA32(*row1++);
|
| - m[8] = SkGetPackedA32(*row2++);
|
| + m[5] = PixelFetcher::Fetch(src, x + 1, y, srcBounds);
|
| + m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds);
|
| surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
|
| *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight,
|
| l->lightColor(surfaceToLight));
|
| @@ -226,24 +246,21 @@ template <class LightingType, class LightType> void lightBitmap(const LightingTy
|
|
|
| for (++y; y < bottom - 1; ++y) {
|
| int x = left;
|
| - const SkPMColor* row0 = src.getAddr32(x, y - 1);
|
| - const SkPMColor* row1 = src.getAddr32(x, y);
|
| - const SkPMColor* row2 = src.getAddr32(x, y + 1);
|
| int m[9];
|
| - m[1] = SkGetPackedA32(*row0++);
|
| - m[2] = SkGetPackedA32(*row0++);
|
| - m[4] = SkGetPackedA32(*row1++);
|
| - m[5] = SkGetPackedA32(*row1++);
|
| - m[7] = SkGetPackedA32(*row2++);
|
| - m[8] = SkGetPackedA32(*row2++);
|
| + m[1] = PixelFetcher::Fetch(src, x, y - 1, srcBounds);
|
| + m[2] = PixelFetcher::Fetch(src, x + 1, y - 1, srcBounds);
|
| + m[4] = PixelFetcher::Fetch(src, x, y, srcBounds);
|
| + m[5] = PixelFetcher::Fetch(src, x + 1, y, srcBounds);
|
| + m[7] = PixelFetcher::Fetch(src, x, y + 1, srcBounds);
|
| + m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds);
|
| SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
|
| *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight,
|
| l->lightColor(surfaceToLight));
|
| for (++x; x < right - 1; ++x) {
|
| shiftMatrixLeft(m);
|
| - m[2] = SkGetPackedA32(*row0++);
|
| - m[5] = SkGetPackedA32(*row1++);
|
| - m[8] = SkGetPackedA32(*row2++);
|
| + m[2] = PixelFetcher::Fetch(src, x + 1, y - 1, srcBounds);
|
| + m[5] = PixelFetcher::Fetch(src, x + 1, y, srcBounds);
|
| + m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds);
|
| surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
|
| *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight,
|
| l->lightColor(surfaceToLight));
|
| @@ -256,21 +273,19 @@ template <class LightingType, class LightType> void lightBitmap(const LightingTy
|
|
|
| {
|
| int x = left;
|
| - const SkPMColor* row0 = src.getAddr32(x, bottom - 2);
|
| - const SkPMColor* row1 = src.getAddr32(x, bottom - 1);
|
| int m[9];
|
| - m[1] = SkGetPackedA32(*row0++);
|
| - m[2] = SkGetPackedA32(*row0++);
|
| - m[4] = SkGetPackedA32(*row1++);
|
| - m[5] = SkGetPackedA32(*row1++);
|
| + m[1] = PixelFetcher::Fetch(src, x, bottom - 2, srcBounds);
|
| + m[2] = PixelFetcher::Fetch(src, x + 1, bottom - 2, srcBounds);
|
| + m[4] = PixelFetcher::Fetch(src, x, bottom - 1, srcBounds);
|
| + m[5] = PixelFetcher::Fetch(src, x + 1, bottom - 1, srcBounds);
|
| SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
|
| *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight,
|
| l->lightColor(surfaceToLight));
|
| for (++x; x < right - 1; ++x)
|
| {
|
| shiftMatrixLeft(m);
|
| - m[2] = SkGetPackedA32(*row0++);
|
| - m[5] = SkGetPackedA32(*row1++);
|
| + m[2] = PixelFetcher::Fetch(src, x + 1, bottom - 2, srcBounds);
|
| + m[5] = PixelFetcher::Fetch(src, x + 1, bottom - 1, srcBounds);
|
| surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
|
| *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight,
|
| l->lightColor(surfaceToLight));
|
| @@ -282,6 +297,22 @@ template <class LightingType, class LightType> void lightBitmap(const LightingTy
|
| }
|
| }
|
|
|
| +template <class LightingType, class LightType>
|
| +void lightBitmap(const LightingType& lightingType,
|
| + const SkImageFilterLight* light,
|
| + const SkBitmap& src,
|
| + SkBitmap* dst,
|
| + SkScalar surfaceScale,
|
| + const SkIRect& bounds) {
|
| + if (src.bounds().contains(bounds)) {
|
| + lightBitmap<LightingType, LightType, UncheckedPixelFetcher>(
|
| + lightingType, light, src, dst, surfaceScale, bounds);
|
| + } else {
|
| + lightBitmap<LightingType, LightType, DecalPixelFetcher>(
|
| + lightingType, light, src, dst, surfaceScale, bounds);
|
| + }
|
| +}
|
| +
|
| SkPoint3 readPoint3(SkReadBuffer& buffer) {
|
| SkPoint3 point;
|
| point.fX = buffer.readScalar();
|
| @@ -1187,8 +1218,10 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
|
| if (src.colorType() != kN32_SkColorType) {
|
| return false;
|
| }
|
| + SkIRect srcBounds = src.bounds();
|
| + srcBounds.offset(srcOffset);
|
| SkIRect bounds;
|
| - if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
|
| + if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
|
| return false;
|
| }
|
|
|
| @@ -1331,8 +1364,10 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
|
| return false;
|
| }
|
|
|
| + SkIRect srcBounds = src.bounds();
|
| + srcBounds.offset(srcOffset);
|
| SkIRect bounds;
|
| - if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
|
| + if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
|
| return false;
|
| }
|
|
|
|
|