/* 
 * JGimp - A Java extension for the GIMP
 * Copyright (C) 2002  Georgia Tech Research Corp.
 * Written by Michael Terry, mterry@cc.gatech.edu
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package org.gimp.jgimp.proxy;

import org.gimp.jgimp.JGimpBufferOverflowException;
import org.gimp.jgimp.JGimpDrawable;
import org.gimp.jgimp.JGimpImage;
import org.gimp.jgimp.JGimpInvalidDrawableException;
import org.gimp.jgimp.JGimpInvalidImageException;
import org.gimp.jgimp.JGimpInvalidPixelRegionException;
import org.gimp.jgimp.paint.JGimpInvalidPaintToolException;
import org.gimp.jgimp.paint.JGimpPaintTool;



/**
 * An extended proxy that provides access to internal GIMP functions.
 * An implementation requires a patched GIMP to work (will not work as
 * a mere plug-in).
 */
public class JGimpExtendedProxyImpl extends JGimpPlugInProxy implements JGimpExtendedProxy {

    private static JGimpExtendedProxyImpl s_Instance = null;

    protected JGimpExtendedProxyImpl(String jgimpJarfile, String extensionsDirectory, String pluginsDirectory) {
        super(jgimpJarfile, extensionsDirectory, pluginsDirectory);
        s_Instance = this;
    }

    private static void _startProxy(String jgimpJarfile, String extensionsDirectory, String pluginsDirectory) {
        if (s_Instance == null) {
            s_Instance = new JGimpExtendedProxyImpl(jgimpJarfile, extensionsDirectory, pluginsDirectory);
        }
    }

    private static JGimpExtendedProxyImpl _getInstance() {
        return s_Instance;
    }

    /**
     * Renders the image (layers and all) into the following buffer,
     * converting it into a Java-friendly format.
     * <br>
     * This method always returns an ARGB int representing a pixel.
     * The byte ordering is as follows
     */
    public void renderImageInJavaIntFormat(JGimpImage inImage, int x, int y, int width, int height, int[] buffer, int offset)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidImageException, JGimpBufferOverflowException {
        if (buffer == null) {
            throw new NullPointerException();
        }
        long result = _renderImageInJavaIntFormat(inImage.getID(), x, y, width, height, buffer, offset);
        if (result < 0) {
            throw new JGimpProxyException("Caught unknown exception rendering image into Java int array");
        }
    }

    /**
     * Renders the image (layers and all) into a new buffer,
     * converting it into a Java-friendly format.
     * <br>
     * This method always returns an ARGB int representing a pixel.
     * The byte ordering is as follows
     */
    public int[] renderImageInJavaIntFormat(JGimpImage inImage, int x, int y, int width, int height)
        throws JGimpProxyException, JGimpInvalidPixelRegionException, JGimpInvalidImageException, JGimpBufferOverflowException {
        int[] buffer = new int[width * height];
        renderImageInJavaIntFormat(inImage, x, y, width, height, buffer, 0);
        return buffer;
    }

    /**
     * Starts painting using the given tool.
     * The current implementation assumes only one tool is used at a time,
     * and that a full transaction is completed: start, addTo, and stop
     * must be called, in that order, with the same tool and drawable.
     * Yeah, it's not perfect, but it will do for now.
     */
    public void startPainting(
        JGimpPaintTool inTool,
        JGimpDrawable inDrawable,
        double start_x,
        double start_y,
        double pressure,
        double xtilt,
        double ytilt,
        double wheel)
        throws JGimpInvalidDrawableException, JGimpInvalidPaintToolException, JGimpProxyException {
        _startPainting(inTool.getToolID(), inDrawable.getID(), start_x, start_y, pressure, xtilt, ytilt, wheel);
    }

    /**
     * Adds a point to the current painting operation.
     * Will return a rectangle of the area affected (doesn't do so now).
     */
    public java.awt.Rectangle addToPainting(
        JGimpPaintTool inTool,
        JGimpDrawable inDrawable,
        double new_x,
        double new_y,
        double new_pressure,
        double new_xtilt,
        double new_ytilt,
        double new_wheel)
        throws JGimpInvalidDrawableException, org.gimp.jgimp.paint.JGimpInvalidPaintToolException, JGimpProxyException {
        return _addToPainting(inTool.getToolID(), inDrawable.getID(), new_x, new_y, new_pressure, new_xtilt, new_ytilt, new_wheel);
    }
    /**
     * Stops painting with the given tool.
     * Will return a rectangle of the area affected (doesn't do so now).
     */
    public java.awt.Rectangle stopPainting(JGimpPaintTool inTool, JGimpDrawable inDrawable)
        throws JGimpInvalidDrawableException, JGimpInvalidPaintToolException, JGimpProxyException {
        return _stopPainting(inTool.getToolID(), inDrawable.getID());
    }

    /**
     * Returns less than 0 on failure, otherwise, number of bytes read.
     */
    private synchronized static native long _renderImageInJavaIntFormat(int inImage, int x, int y, int width, int height, int[] buffer, int offset);
    private synchronized static native void _startPainting(
        int tool_id,
        int drawable_id,
        double start_x,
        double start_y,
        double pressure,
        double xtilt,
        double ytilt,
        double wheel);
    private synchronized static native java.awt.Rectangle _addToPainting(
        int tool_id,
        int drawable_id,
        double new_x,
        double new_y,
        double new_pressure,
        double new_xtilt,
        double new_ytilt,
        double new_wheel);
    private synchronized static native java.awt.Rectangle _stopPainting(int tool_id, int drawable_id);
}
