/*
 * Copyright 2011 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBlurImageFilter.h"
#include "SkColorPriv.h"

SkBlurImageFilter::SkBlurImageFilter(SkFlattenableReadBuffer& buffer)
  : INHERITED(buffer) {
    fSigma.fWidth = buffer.readScalar();
    fSigma.fHeight = buffer.readScalar();
}

SkBlurImageFilter::SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY)
    : fSigma(SkSize::Make(sigmaX, sigmaY)) {
    SkASSERT(sigmaX >= 0 && sigmaY >= 0);
}

bool SkBlurImageFilter::asABlur(SkSize* sigma) const {
    *sigma = fSigma;
    return true;
}

void SkBlurImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
    this->INHERITED::flatten(buffer);
    buffer.writeScalar(fSigma.fWidth);
    buffer.writeScalar(fSigma.fHeight);
}

static void boxBlurX(const SkBitmap& src, SkBitmap* dst, int kernelSize,
                     int leftOffset, int rightOffset)
{
    int width = src.width(), height = src.height();
    int rightBorder = SkMin32(rightOffset + 1, width);
    for (int y = 0; y < height; ++y) {
        int sumA = 0, sumR = 0, sumG = 0, sumB = 0;
        SkPMColor* p = src.getAddr32(0, y);
        for (int i = 0; i < rightBorder; ++i) {
            sumA += SkGetPackedA32(*p);
            sumR += SkGetPackedR32(*p);
            sumG += SkGetPackedG32(*p);
            sumB += SkGetPackedB32(*p);
            p++;
        }

        const SkColor* sptr = src.getAddr32(0, y);
        SkColor* dptr = dst->getAddr32(0, y);
        for (int x = 0; x < width; ++x) {
            *dptr = SkPackARGB32(sumA / kernelSize,
                                 sumR / kernelSize,
                                 sumG / kernelSize,
                                 sumB / kernelSize);
            if (x >= leftOffset) {
                SkColor l = *(sptr - leftOffset);
                sumA -= SkGetPackedA32(l);
                sumR -= SkGetPackedR32(l);
                sumG -= SkGetPackedG32(l);
                sumB -= SkGetPackedB32(l);
            }
            if (x + rightOffset + 1 < width) {
                SkColor r = *(sptr + rightOffset + 1);
                sumA += SkGetPackedA32(r);
                sumR += SkGetPackedR32(r);
                sumG += SkGetPackedG32(r);
                sumB += SkGetPackedB32(r);
            }
            sptr++;
            dptr++;
        }
    }
}

static void boxBlurY(const SkBitmap& src, SkBitmap* dst, int kernelSize,
                     int topOffset, int bottomOffset)
{
    int width = src.width(), height = src.height();
    int bottomBorder = SkMin32(bottomOffset + 1, height);
    int srcStride = src.rowBytesAsPixels();
    int dstStride = dst->rowBytesAsPixels();
    for (int x = 0; x < width; ++x) {
        int sumA = 0, sumR = 0, sumG = 0, sumB = 0;
        SkColor* p = src.getAddr32(x, 0);
        for (int i = 0; i < bottomBorder; ++i) {
            sumA += SkGetPackedA32(*p);
            sumR += SkGetPackedR32(*p);
            sumG += SkGetPackedG32(*p);
            sumB += SkGetPackedB32(*p);
            p += srcStride;
        }

        const SkColor* sptr = src.getAddr32(x, 0);
        SkColor* dptr = dst->getAddr32(x, 0);
        for (int y = 0; y < height; ++y) {
            *dptr = SkPackARGB32(sumA / kernelSize,
                                 sumR / kernelSize,
                                 sumG / kernelSize,
                                 sumB / kernelSize);
            if (y >= topOffset) {
                SkColor l = *(sptr - topOffset * srcStride);
                sumA -= SkGetPackedA32(l);
                sumR -= SkGetPackedR32(l);
                sumG -= SkGetPackedG32(l);
                sumB -= SkGetPackedB32(l);
            }
            if (y + bottomOffset + 1 < height) {
                SkColor r = *(sptr + (bottomOffset + 1) * srcStride);
                sumA += SkGetPackedA32(r);
                sumR += SkGetPackedR32(r);
                sumG += SkGetPackedG32(r);
                sumB += SkGetPackedB32(r);
            }
            sptr += srcStride;
            dptr += dstStride;
        }
    }
}

static void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lowOffset, int *highOffset)
{
    float pi = SkScalarToFloat(SK_ScalarPI);
    int d = static_cast<int>(floorf(SkScalarToFloat(s) * 3.0f * sqrtf(2.0f * pi) / 4.0f + 0.5f));
    *kernelSize = d;
    if (d % 2 == 1) {
        *lowOffset = *highOffset = (d - 1) / 2;
        *kernelSize3 = d;
    } else {
        *highOffset = d / 2;
        *lowOffset = *highOffset - 1;
        *kernelSize3 = d + 1;
    }
}

bool SkBlurImageFilter::onFilterImage(Proxy*,
                                      const SkBitmap& src, const SkMatrix&,
                                      SkBitmap* dst, SkIPoint*) {
    if (src.config() != SkBitmap::kARGB_8888_Config) {
        return false;
    }

    SkAutoLockPixels alp(src);
    if (!src.getPixels()) {
        return false;
    }

    dst->setConfig(src.config(), src.width(), src.height());
    dst->allocPixels();
    int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
    int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY;
    getBox3Params(fSigma.width(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
    getBox3Params(fSigma.height(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);

    if (kernelSizeX < 0 || kernelSizeY < 0) {
        return false;
    }

    if (kernelSizeX == 0 && kernelSizeY == 0) {
        src.copyTo(dst, dst->config());
        return true;
    }

    SkBitmap temp;
    temp.setConfig(dst->config(), dst->width(), dst->height());
    if (!temp.allocPixels()) {
        return false;
    }

    if (kernelSizeX > 0 && kernelSizeY > 0) {
        boxBlurX(src,  &temp, kernelSizeX,  lowOffsetX, highOffsetX);
        boxBlurY(temp, dst,   kernelSizeY,  lowOffsetY, highOffsetY);
        boxBlurX(*dst, &temp, kernelSizeX,  highOffsetX,  lowOffsetX);
        boxBlurY(temp, dst,   kernelSizeY,  highOffsetY,  lowOffsetY);
        boxBlurX(*dst, &temp, kernelSizeX3, highOffsetX, highOffsetX);
        boxBlurY(temp, dst,   kernelSizeY3, highOffsetY, highOffsetY);
    } else if (kernelSizeX > 0) {
        boxBlurX(src,  dst,   kernelSizeX,  lowOffsetX, highOffsetX);
        boxBlurX(*dst, &temp, kernelSizeX,  highOffsetX,  lowOffsetX);
        boxBlurX(temp, dst,   kernelSizeX3, highOffsetX, highOffsetX);
    } else if (kernelSizeY > 0) {
        boxBlurY(src,  dst,   kernelSizeY,  lowOffsetY, highOffsetY);
        boxBlurY(*dst, &temp, kernelSizeY,  highOffsetY, lowOffsetY);
        boxBlurY(temp, dst,   kernelSizeY3, highOffsetY, highOffsetY);
    }
    return true;
}

SK_DEFINE_FLATTENABLE_REGISTRAR(SkBlurImageFilter)
