/*
 * Copyright 1997-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.
 */

package java.awt.geom;

import java.io.Serializable;

/**
 * The <code>RoundRectangle2D</code> class defines a rectangle with
 * rounded corners defined by a location {@code (x,y)}, a
 * dimension {@code (w x h)}, and the width and height of an arc
 * with which to round the corners.
 * <p>
 * This class is the abstract superclass for all objects that
 * store a 2D rounded rectangle.
 * The actual storage representation of the coordinates is left to
 * the subclass.
 *
 * @author      Jim Graham
 * @since 1.2
 */
public abstract class RoundRectangle2D extends RectangularShape {

    /**
     * The <code>Float</code> class defines a rectangle with rounded
     * corners all specified in <code>float</code> coordinates.
     * @since 1.2
     */
    public static class Float extends RoundRectangle2D
        implements Serializable
    {
        /**
         * The X coordinate of this <code>RoundRectangle2D</code>.
         * @since 1.2
         * @serial
         */
        public float x;

        /**
         * The Y coordinate of this <code>RoundRectangle2D</code>.
         * @since 1.2
         * @serial
         */
        public float y;

        /**
         * The width of this <code>RoundRectangle2D</code>.
         * @since 1.2
         * @serial
         */
        public float width;

        /**
         * The height of this <code>RoundRectangle2D</code>.
         * @since 1.2
         * @serial
         */
        public float height;

        /**
         * The width of the arc that rounds off the corners.
         * @since 1.2
         * @serial
         */
        public float arcwidth;

        /**
         * The height of the arc that rounds off the corners.
         * @since 1.2
         * @serial
         */
        public float archeight;

        /**
         * Constructs a new <code>RoundRectangle2D</code>, initialized to
         * location (0.0,&nbsp;0.0), size (0.0,&nbsp;0.0), and corner arcs
         * of radius 0.0.
         * @since 1.2
         */
        public Float() {
        }

        /**
         * Constructs and initializes a <code>RoundRectangle2D</code>
         * from the specified <code>float</code> coordinates.
         *
         * @param x the X coordinate of the newly
         *          constructed <code>RoundRectangle2D</code>
         * @param y the Y coordinate of the newly
         *          constructed <code>RoundRectangle2D</code>
         * @param w the width to which to set the newly
         *          constructed <code>RoundRectangle2D</code>
         * @param h the height to which to set the newly
         *          constructed <code>RoundRectangle2D</code>
         * @param arcw the width of the arc to use to round off the
         *             corners of the newly constructed
         *             <code>RoundRectangle2D</code>
         * @param arch the height of the arc to use to round off the
         *             corners of the newly constructed
         *             <code>RoundRectangle2D</code>
         * @since 1.2
         */
        public Float(float x, float y, float w, float h,
                     float arcw, float arch)
        {
            setRoundRect(x, y, w, h, arcw, arch);
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getX() {
            return (double) x;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getY() {
            return (double) y;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getWidth() {
            return (double) width;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getHeight() {
            return (double) height;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getArcWidth() {
            return (double) arcwidth;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getArcHeight() {
            return (double) archeight;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public boolean isEmpty() {
            return (width <= 0.0f) || (height <= 0.0f);
        }

        /**
         * Sets the location, size, and corner radii of this
         * <code>RoundRectangle2D</code> to the specified
         * <code>float</code> values.
         *
         * @param x the X coordinate to which to set the
         *          location of this <code>RoundRectangle2D</code>
         * @param y the Y coordinate to which to set the
         *          location of this <code>RoundRectangle2D</code>
         * @param w the width to which to set this
         *          <code>RoundRectangle2D</code>
         * @param h the height to which to set this
         *          <code>RoundRectangle2D</code>
         * @param arcw the width to which to set the arc of this
         *             <code>RoundRectangle2D</code>
         * @param arch the height to which to set the arc of this
         *             <code>RoundRectangle2D</code>
         * @since 1.2
         */
        public void setRoundRect(float x, float y, float w, float h,
                                 float arcw, float arch)
        {
            this.x = x;
            this.y = y;
            this.width = w;
            this.height = h;
            this.arcwidth = arcw;
            this.archeight = arch;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public void setRoundRect(double x, double y, double w, double h,
                                 double arcw, double arch)
        {
            this.x = (float) x;
            this.y = (float) y;
            this.width = (float) w;
            this.height = (float) h;
            this.arcwidth = (float) arcw;
            this.archeight = (float) arch;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public void setRoundRect(RoundRectangle2D rr) {
            this.x = (float) rr.getX();
            this.y = (float) rr.getY();
            this.width = (float) rr.getWidth();
            this.height = (float) rr.getHeight();
            this.arcwidth = (float) rr.getArcWidth();
            this.archeight = (float) rr.getArcHeight();
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public Rectangle2D getBounds2D() {
            return new Rectangle2D.Float(x, y, width, height);
        }

        /*
         * JDK 1.6 serialVersionUID
         */
        private static final long serialVersionUID = -3423150618393866922L;
    }

    /**
     * The <code>Double</code> class defines a rectangle with rounded
     * corners all specified in <code>double</code> coordinates.
     * @since 1.2
     */
    public static class Double extends RoundRectangle2D
        implements Serializable
    {
        /**
         * The X coordinate of this <code>RoundRectangle2D</code>.
         * @since 1.2
         * @serial
         */
        public double x;

        /**
         * The Y coordinate of this <code>RoundRectangle2D</code>.
         * @since 1.2
         * @serial
         */
        public double y;

        /**
         * The width of this <code>RoundRectangle2D</code>.
         * @since 1.2
         * @serial
         */
        public double width;

        /**
         * The height of this <code>RoundRectangle2D</code>.
         * @since 1.2
         * @serial
         */
        public double height;

        /**
         * The width of the arc that rounds off the corners.
         * @since 1.2
         * @serial
         */
        public double arcwidth;

        /**
         * The height of the arc that rounds off the corners.
         * @since 1.2
         * @serial
         */
        public double archeight;

        /**
         * Constructs a new <code>RoundRectangle2D</code>, initialized to
         * location (0.0,&nbsp;0.0), size (0.0,&nbsp;0.0), and corner arcs
         * of radius 0.0.
         * @since 1.2
         */
        public Double() {
        }

        /**
         * Constructs and initializes a <code>RoundRectangle2D</code>
         * from the specified <code>double</code> coordinates.
         *
         * @param x the X coordinate of the newly
         *          constructed <code>RoundRectangle2D</code>
         * @param y the Y coordinate of the newly
         *          constructed <code>RoundRectangle2D</code>
         * @param w the width to which to set the newly
         *          constructed <code>RoundRectangle2D</code>
         * @param h the height to which to set the newly
         *          constructed <code>RoundRectangle2D</code>
         * @param arcw the width of the arc to use to round off the
         *             corners of the newly constructed
         *             <code>RoundRectangle2D</code>
         * @param arch the height of the arc to use to round off the
         *             corners of the newly constructed
         *             <code>RoundRectangle2D</code>
         * @since 1.2
         */
        public Double(double x, double y, double w, double h,
                      double arcw, double arch)
        {
            setRoundRect(x, y, w, h, arcw, arch);
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getX() {
            return x;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getY() {
            return y;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getWidth() {
            return width;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getHeight() {
            return height;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getArcWidth() {
            return arcwidth;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public double getArcHeight() {
            return archeight;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public boolean isEmpty() {
            return (width <= 0.0f) || (height <= 0.0f);
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public void setRoundRect(double x, double y, double w, double h,
                                 double arcw, double arch)
        {
            this.x = x;
            this.y = y;
            this.width = w;
            this.height = h;
            this.arcwidth = arcw;
            this.archeight = arch;
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public void setRoundRect(RoundRectangle2D rr) {
            this.x = rr.getX();
            this.y = rr.getY();
            this.width = rr.getWidth();
            this.height = rr.getHeight();
            this.arcwidth = rr.getArcWidth();
            this.archeight = rr.getArcHeight();
        }

        /**
         * {@inheritDoc}
         * @since 1.2
         */
        public Rectangle2D getBounds2D() {
            return new Rectangle2D.Double(x, y, width, height);
        }

        /*
         * JDK 1.6 serialVersionUID
         */
        private static final long serialVersionUID = 1048939333485206117L;
    }

    /**
     * This is an abstract class that cannot be instantiated directly.
     * Type-specific implementation subclasses are available for
     * instantiation and provide a number of formats for storing
     * the information necessary to satisfy the various accessor
     * methods below.
     *
     * @see java.awt.geom.RoundRectangle2D.Float
     * @see java.awt.geom.RoundRectangle2D.Double
     * @since 1.2
     */
    protected RoundRectangle2D() {
    }

    /**
     * Gets the width of the arc that rounds off the corners.
     * @return the width of the arc that rounds off the corners
     * of this <code>RoundRectangle2D</code>.
     * @since 1.2
     */
    public abstract double getArcWidth();

    /**
     * Gets the height of the arc that rounds off the corners.
     * @return the height of the arc that rounds off the corners
     * of this <code>RoundRectangle2D</code>.
     * @since 1.2
     */
    public abstract double getArcHeight();

    /**
     * Sets the location, size, and corner radii of this
     * <code>RoundRectangle2D</code> to the specified
     * <code>double</code> values.
     *
     * @param x the X coordinate to which to set the
     *          location of this <code>RoundRectangle2D</code>
     * @param y the Y coordinate to which to set the
     *          location of this <code>RoundRectangle2D</code>
     * @param w the width to which to set this
     *          <code>RoundRectangle2D</code>
     * @param h the height to which to set this
     *          <code>RoundRectangle2D</code>
     * @param arcWidth the width to which to set the arc of this
     *                 <code>RoundRectangle2D</code>
     * @param arcHeight the height to which to set the arc of this
     *                  <code>RoundRectangle2D</code>
     * @since 1.2
     */
    public abstract void setRoundRect(double x, double y, double w, double h,
                                      double arcWidth, double arcHeight);

    /**
     * Sets this <code>RoundRectangle2D</code> to be the same as the
     * specified <code>RoundRectangle2D</code>.
     * @param rr the specified <code>RoundRectangle2D</code>
     * @since 1.2
     */
    public void setRoundRect(RoundRectangle2D rr) {
        setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
                     rr.getArcWidth(), rr.getArcHeight());
    }

    /**
     * {@inheritDoc}
     * @since 1.2
     */
    public void setFrame(double x, double y, double w, double h) {
        setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
    }

    /**
     * {@inheritDoc}
     * @since 1.2
     */
    public boolean contains(double x, double y) {
        if (isEmpty()) {
            return false;
        }
        double rrx0 = getX();
        double rry0 = getY();
        double rrx1 = rrx0 + getWidth();
        double rry1 = rry0 + getHeight();
        // Check for trivial rejection - point is outside bounding rectangle
        if (x < rrx0 || y < rry0 || x >= rrx1 || y >= rry1) {
            return false;
        }
        double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
        double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
        // Check which corner point is in and do circular containment
        // test - otherwise simple acceptance
        if (x >= (rrx0 += aw) && x < (rrx0 = rrx1 - aw)) {
            return true;
        }
        if (y >= (rry0 += ah) && y < (rry0 = rry1 - ah)) {
            return true;
        }
        x = (x - rrx0) / aw;
        y = (y - rry0) / ah;
        return (x * x + y * y <= 1.0);
    }

    private int classify(double coord, double left, double right,
                         double arcsize)
    {
        if (coord < left) {
            return 0;
        } else if (coord < left + arcsize) {
            return 1;
        } else if (coord < right - arcsize) {
            return 2;
        } else if (coord < right) {
            return 3;
        } else {
            return 4;
        }
    }

    /**
     * {@inheritDoc}
     * @since 1.2
     */
    public boolean intersects(double x, double y, double w, double h) {
        if (isEmpty() || w <= 0 || h <= 0) {
            return false;
        }
        double rrx0 = getX();
        double rry0 = getY();
        double rrx1 = rrx0 + getWidth();
        double rry1 = rry0 + getHeight();
        // Check for trivial rejection - bounding rectangles do not intersect
        if (x + w <= rrx0 || x >= rrx1 || y + h <= rry0 || y >= rry1) {
            return false;
        }
        double aw = Math.min(getWidth(), Math.abs(getArcWidth())) / 2.0;
        double ah = Math.min(getHeight(), Math.abs(getArcHeight())) / 2.0;
        int x0class = classify(x, rrx0, rrx1, aw);
        int x1class = classify(x + w, rrx0, rrx1, aw);
        int y0class = classify(y, rry0, rry1, ah);
        int y1class = classify(y + h, rry0, rry1, ah);
        // Trivially accept if any point is inside inner rectangle
        if (x0class == 2 || x1class == 2 || y0class == 2 || y1class == 2) {
            return true;
        }
        // Trivially accept if either edge spans inner rectangle
        if ((x0class < 2 && x1class > 2) || (y0class < 2 && y1class > 2)) {
            return true;
        }
        // Since neither edge spans the center, then one of the corners
        // must be in one of the rounded edges.  We detect this case if
        // a [xy]0class is 3 or a [xy]1class is 1.  One of those two cases
        // must be true for each direction.
        // We now find a "nearest point" to test for being inside a rounded
        // corner.
        x = (x1class == 1) ? (x = x + w - (rrx0 + aw)) : (x = x - (rrx1 - aw));
        y = (y1class == 1) ? (y = y + h - (rry0 + ah)) : (y = y - (rry1 - ah));
        x = x / aw;
        y = y / ah;
        return (x * x + y * y <= 1.0);
    }

    /**
     * {@inheritDoc}
     * @since 1.2
     */
    public boolean contains(double x, double y, double w, double h) {
        if (isEmpty() || w <= 0 || h <= 0) {
            return false;
        }
        return (contains(x, y) &&
                contains(x + w, y) &&
                contains(x, y + h) &&
                contains(x + w, y + h));
    }

    /**
     * Returns an iteration object that defines the boundary of this
     * <code>RoundRectangle2D</code>.
     * The iterator for this class is multi-threaded safe, which means
     * that this <code>RoundRectangle2D</code> class guarantees that
     * modifications to the geometry of this <code>RoundRectangle2D</code>
     * object do not affect any iterations of that geometry that
     * are already in process.
     * @param at an optional <code>AffineTransform</code> to be applied to
     * the coordinates as they are returned in the iteration, or
     * <code>null</code> if untransformed coordinates are desired
     * @return    the <code>PathIterator</code> object that returns the
     *          geometry of the outline of this
     *          <code>RoundRectangle2D</code>, one segment at a time.
     * @since 1.2
     */
    public PathIterator getPathIterator(AffineTransform at) {
        return new RoundRectIterator(this, at);
    }

    /**
     * Returns the hashcode for this <code>RoundRectangle2D</code>.
     * @return the hashcode for this <code>RoundRectangle2D</code>.
     * @since 1.6
     */
    public int hashCode() {
        long bits = java.lang.Double.doubleToLongBits(getX());
        bits += java.lang.Double.doubleToLongBits(getY()) * 37;
        bits += java.lang.Double.doubleToLongBits(getWidth()) * 43;
        bits += java.lang.Double.doubleToLongBits(getHeight()) * 47;
        bits += java.lang.Double.doubleToLongBits(getArcWidth()) * 53;
        bits += java.lang.Double.doubleToLongBits(getArcHeight()) * 59;
        return (((int) bits) ^ ((int) (bits >> 32)));
    }

    /**
     * Determines whether or not the specified <code>Object</code> is
     * equal to this <code>RoundRectangle2D</code>.  The specified
     * <code>Object</code> is equal to this <code>RoundRectangle2D</code>
     * if it is an instance of <code>RoundRectangle2D</code> and if its
     * location, size, and corner arc dimensions are the same as this
     * <code>RoundRectangle2D</code>.
     * @param obj  an <code>Object</code> to be compared with this
     *             <code>RoundRectangle2D</code>.
     * @return  <code>true</code> if <code>obj</code> is an instance
     *          of <code>RoundRectangle2D</code> and has the same values;
     *          <code>false</code> otherwise.
     * @since 1.6
     */
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj instanceof RoundRectangle2D) {
            RoundRectangle2D rr2d = (RoundRectangle2D) obj;
            return ((getX() == rr2d.getX()) &&
                    (getY() == rr2d.getY()) &&
                    (getWidth() == rr2d.getWidth()) &&
                    (getHeight() == rr2d.getHeight()) &&
                    (getArcWidth() == rr2d.getArcWidth()) &&
                    (getArcHeight() == rr2d.getArcHeight()));
        }
        return false;
    }
}
