/*
 * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * This file was originally generated by JSLC
 * and then hand edited for performance.
 */

package com.sun.scenario.effect.impl.sw.java;

import com.sun.scenario.effect.FilterContext;
import com.sun.scenario.effect.impl.Renderer;

public class JSWLinearConvolveShadowPeer extends JSWLinearConvolvePeer {
    public JSWLinearConvolveShadowPeer(FilterContext fctx, Renderer r, String uniqueName) {
        super(fctx, r, uniqueName);
    }

    private float[] getShadowColor() {
        return getRenderState().getPassShadowColorComponents();
    }

    @Override
    protected void filterVector(int dstPixels[], int dstw, int dsth, int dstscan,
                                int srcPixels[], int srcw, int srch, int srcscan,
                                float weights[], int count,
                                float srcx0, float srcy0,
                                float offsetx, float offsety,
                                float deltax, float deltay,
                                float dxcol, float dycol, float dxrow, float dyrow)
    {
        float shadowColor[] = getShadowColor();

        int dstrow = 0;
        // srcxy0 point at UL corner, shift them to center of 1st dest pixel:
        srcx0 += (dxrow + dxcol) * 0.5f;
        srcy0 += (dyrow + dycol) * 0.5f;
        for (int dy = 0; dy < dsth; dy++) {
            float srcx = srcx0;
            float srcy = srcy0;
            for (int dx = 0; dx < dstw; dx++) {
                float sum = 0.0f;
                float sampx = srcx + offsetx;
                float sampy = srcy + offsety;
                for (int i = 0; i < count; ++i) {
                    if (sampx >= 0 && sampy >= 0) {
                        int ix = (int) sampx;
                        int iy = (int) sampy;
                        if (ix < srcw && iy < srch) {
                            // TODO: Usine linear interpolation here... (RT-27388)
                            int argb = srcPixels[iy * srcscan + ix];
                            sum += (argb >>> 24) * weights[i];
                        }
                    }
                    sampx += deltax;
                    sampy += deltay;
                }
                sum = (sum < 0f) ? 0f : ((sum > 255f) ? 255f : sum);
                dstPixels[dstrow + dx] = ((int) (shadowColor[0] * sum) << 16) |
                                         ((int) (shadowColor[1] * sum) <<  8) |
                                         ((int) (shadowColor[2] * sum)      ) |
                                         ((int) (shadowColor[3] * sum) << 24);
                srcx += dxcol;
                srcy += dycol;
            }
            srcx0 += dxrow;
            srcy0 += dyrow;
            dstrow += dstscan;
        }
    }

    /*
     * In the nomenclature of the argument list for this method, "row" refers
     * to the coordinate which increments once for each new stream of single
     * axis data that we are blurring in a single pass.  And "col" refers to
     * the other coordinate that increments along the row.
     * Rows are horizontal in the first pass and vertical in the second pass.
     * Cols are vice versa.
     */
    @Override
    protected void filterHV(int dstPixels[], int dstcols, int dstrows, int dcolinc, int drowinc,
                            int srcPixels[], int srccols, int srcrows, int scolinc, int srowinc,
                            float weights[])
    {
        float shadowColor[] = getShadowColor();

        // avals stores the alpha values from the surrounding K pixels
        // from x-r to x+r
        int kernelSize = weights.length / 2;
        float avals[] = new float[kernelSize];
        int dstrow = 0;
        int srcrow = 0;
        int shadowRGBs[] = new int[256];
        for (int i = 0; i < shadowRGBs.length; i++) {
            shadowRGBs[i] = ((int) (shadowColor[0] * i) << 16) |
                            ((int) (shadowColor[1] * i) <<  8) |
                            ((int) (shadowColor[2] * i)      ) |
                            ((int) (shadowColor[3] * i) << 24);
        }
        for (int r = 0; r < dstrows; r++) {
            int dstoff = dstrow;
            int srcoff = srcrow;
            // Must clear out the array at the start of every line
            // Might be able to rely on the fact that the previous line must
            // have run out of data towards the end of the scan line, though.
            for (int i = 0; i < avals.length; i++) {
                avals[i] = 0f;
            }
            int koff = kernelSize;
            for (int c = 0; c < dstcols; c++) {
                // Load the data for this x location into the array.
                avals[kernelSize - koff] =
                    ((c < srccols) ? srcPixels[srcoff] : 0) >>> 24;
                // Bump the koff to the next spot to align the coefficients.
                if (--koff <= 0) {
                    koff += kernelSize;
                }
                float sum = -0.5f;
                for (int i = 0; i < avals.length; i++) {
                    sum += avals[i] * weights[koff + i];
                }
                dstPixels[dstoff] =
                    ((sum < 0f) ? 0
                     : ((sum >= 254f) ? shadowRGBs[255]
                        : shadowRGBs[((int) sum) + 1]));
                dstoff += dcolinc;
                srcoff += scolinc;
            }
            dstrow += drowinc;
            srcrow += srowinc;
        }
    }
}
