/*
 * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

#include <math.h>
#include <float.h>
#include "jni_util.h"

#include "GraphicsPrimitiveMgr.h"
#include "LineUtils.h"
#include "ProcessPath.h"
#include "DrawPath.h"

#include "sun_java2d_loops_DrawPath.h"

static void processLine(DrawHandler* hnd,
                        jint x0, jint y0, jint x1, jint y1)
{
    LineUtils_ProcessLine(DHND(hnd)->pRasInfo,
                          DHND(hnd)->pixel,
                          DHND(hnd)->pPrim->funcs.drawline,
                          DHND(hnd)->pPrim,
                          DHND(hnd)->pCompInfo,
                          x0, y0, x1, y1, 0);
}

static void processPoint(DrawHandler* hnd, jint x0, jint y0)
{
    DHND(hnd)->pPrim->funcs.drawline(
        DHND(hnd)->pRasInfo, x0, y0, DHND(hnd)->pixel, 1, 0,
        BUMP_POS_PIXEL, 0, BUMP_NOOP, 0,
        DHND(hnd)->pPrim, DHND(hnd)->pCompInfo);
}

 /*
  * Class:     sun_java2d_loops_DrawPath
  * Method:    DrawPath
  * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;IILjava/awt/geom/Path2D.Float;)V
  */
JNIEXPORT void JNICALL Java_sun_java2d_loops_DrawPath_DrawPath
   (JNIEnv *env, jobject self,
    jobject sg2d, jobject sData,
    jint transX, jint transY, jobject p2df)
{
    jarray typesArray;
    jarray coordsArray;
    jint numTypes;
    jboolean ok = JNI_TRUE;
    jint pixel = GrPrim_Sg2dGetPixel(env, sg2d);
    jint maxCoords;
    jfloat *coords;
    SurfaceDataOps *sdOps;
    SurfaceDataRasInfo rasInfo;
    CompositeInfo compInfo;
    jint ret;
    NativePrimitive *pPrim = GetNativePrim(env, self);
    jint stroke = (*env)->GetIntField(env, sg2d, sg2dStrokeHintID);

    if (pPrim == NULL) {
        return;
    }
    if (pPrim->pCompType->getCompInfo != NULL) {
        GrPrim_Sg2dGetCompInfo(env, sg2d, pPrim, &compInfo);
    }

    sdOps = SurfaceData_GetOps(env, sData);
    if (sdOps == 0) {
        return;
    }

    typesArray = (jarray)(*env)->GetObjectField(env, p2df, path2DTypesID);
    coordsArray = (jarray)(*env)->GetObjectField(env, p2df,
                                                 path2DFloatCoordsID);
    if (coordsArray == NULL) {
        JNU_ThrowNullPointerException(env, "coordinates array");
        return;
    }
    numTypes = (*env)->GetIntField(env, p2df, path2DNumTypesID);
    if ((*env)->GetArrayLength(env, typesArray) < numTypes) {
        JNU_ThrowArrayIndexOutOfBoundsException(env, "types array");
        return;
    }

    GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);

    ret = sdOps->Lock(env, sdOps, &rasInfo, SD_LOCK_FASTEST | pPrim->dstflags);
    if (ret == SD_FAILURE) {
        return;
    }

    maxCoords = (*env)->GetArrayLength(env, coordsArray);
    coords = (jfloat*)(*env)->GetPrimitiveArrayCritical(
            env, coordsArray, NULL);

    if (ret == SD_SLOWLOCK) {
        GrPrim_RefineBounds(&rasInfo.bounds, transX, transY,
                     coords, maxCoords);
        ok = (rasInfo.bounds.x2 > rasInfo.bounds.x1 &&
              rasInfo.bounds.y2 > rasInfo.bounds.y1);
    }

    if (ok) {
        sdOps->GetRasInfo(env, sdOps, &rasInfo);
        if (rasInfo.rasBase) {
            if (rasInfo.bounds.x2 > rasInfo.bounds.x1 &&
                rasInfo.bounds.y2 > rasInfo.bounds.y1)
            {
                DrawHandlerData dHData;
                DrawHandler drawHandler =
                {
                    &processLine,
                    &processPoint,
                    NULL,
                    0, 0, 0, 0,
                    0, 0, 0, 0,
                    NULL
                };

                jbyte *types = (jbyte*)(*env)->GetPrimitiveArrayCritical(
                    env, typesArray, NULL);

                /* Initialization of the following fields in the declaration of
                 * the dHData and drawHandler above causes warnings on sun
                 * studio compiler with
                 * -xc99=%none option applied (this option means compliance
                 *  with C90 standard instead of C99)
                 */
                dHData.pRasInfo = &rasInfo;
                dHData.pixel = pixel;
                dHData.pPrim = pPrim;
                dHData.pCompInfo = &compInfo;

                drawHandler.xMin = rasInfo.bounds.x1;
                drawHandler.yMin = rasInfo.bounds.y1;
                drawHandler.xMax = rasInfo.bounds.x2;
                drawHandler.yMax = rasInfo.bounds.y2;
                drawHandler.pData = &dHData;

                if (!doDrawPath(&drawHandler, NULL, transX, transY,
                                coords, maxCoords, types, numTypes,
                                (stroke == sunHints_INTVAL_STROKE_PURE)?
                                    PH_STROKE_PURE : PH_STROKE_DEFAULT))
                {
                    JNU_ThrowArrayIndexOutOfBoundsException(env,
                                                            "coords array");
                }

                (*env)->ReleasePrimitiveArrayCritical(env, typesArray, types,
                                                      JNI_ABORT);
            }
        }
        SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
    }
    (*env)->ReleasePrimitiveArrayCritical(env, coordsArray, coords,
                                          JNI_ABORT);
    SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
}
