/*
 * Copyright 2000-2004 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 javax.print.attribute.standard;

import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;

/**
 * Class MediaPrintableArea is a printing attribute used to distinguish
 * the printable and non-printable areas of media.
 * <p>
 * The printable area is specified to be a rectangle, within the overall
 * dimensions of a media.
 * <p>
 * Most printers cannot print on the entire surface of the media, due
 * to printer hardware limitations. This class can be used to query
 * the acceptable values for a supposed print job, and to request an area
 * within the constraints of the printable area to be used in a print job.
 * <p>
 * To query for the printable area, a client must supply a suitable context.
 * Without specifying at the very least the size of the media being used
 * no meaningful value for printable area can be obtained.
 * <p>
 * The attribute is not described in terms of the distance from the edge
 * of the paper, in part to emphasise that this attribute is not independent
 * of a particular media, but must be described within the context of a
 * choice of other attributes. Additionally it is usually more convenient
 * for a client to use the printable area.
 * <p>
 * The hardware's minimum margins is not just a property of the printer,
 * but may be a function of the media size, orientation, media type, and
 * any specified finishings.
 * <code>PrintService</code> provides the method to query the supported
 * values of an attribute in a suitable context :
 * See  {@link javax.print.PrintService#getSupportedAttributeValues(Class,DocFlavor, AttributeSet) <code>PrintService.getSupportedAttributeValues()</code>}
 * <p>
 * The rectangular printable area is defined thus:
 * The (x,y) origin is positioned at the top-left of the paper in portrait
 * mode regardless of the orientation specified in the requesting context.
 * For example a printable area for A4 paper in portrait or landscape
 * orientation will have height > width.
 * <p>
 * A printable area attribute's values are stored
 * internally as integers in units of micrometers (&#181;m), where 1 micrometer
 * = 10<SUP>-6</SUP> meter = 1/1000 millimeter = 1/25400 inch. This permits
 * dimensions to be represented exactly to a precision of 1/1000 mm (= 1
 * &#181;m) or 1/100 inch (= 254 &#181;m). If fractional inches are expressed in

 * negative powers of two, this permits dimensions to be represented exactly to
 * a precision of 1/8 inch (= 3175 &#181;m) but not 1/16 inch (because 1/16 inch

 * does not equal an integral number of &#181;m).
 * <p>
 * <B>IPP Compatibility:</B> MediaPrintableArea is not an IPP attribute.
 */

public final class MediaPrintableArea
      implements DocAttribute, PrintRequestAttribute, PrintJobAttribute {

    private int x, y, w, h;
    private int units;

    private static final long serialVersionUID = -1597171464050795793L;

    /**
     * Value to indicate units of inches (in). It is actually the conversion
     * factor by which to multiply inches to yield &#181;m (25400).
     */
    public static final int INCH = 25400;

    /**
     * Value to indicate units of millimeters (mm). It is actually the
     * conversion factor by which to multiply mm to yield &#181;m (1000).
     */
    public static final int MM = 1000;

    /**
      * Constructs a MediaPrintableArea object from floating point values.
      * @param x      printable x
      * @param y      printable y
      * @param w      printable width
      * @param h      printable height
      * @param units  in which the values are expressed.
      *
      * @exception  IllegalArgumentException
      *     Thrown if <CODE>x</CODE> < 0 or <CODE>y</CODE> < 0
      *     or <CODE>w</CODE> <= 0 or <CODE>h</CODE> <= 0 or
      *     <CODE>units</CODE> < 1.
      */
    public MediaPrintableArea(float x, float y, float w, float h, int units) {
        if ((x < 0.0) || (y < 0.0) || (w <= 0.0) || (h <= 0.0) ||
            (units < 1)) {
            throw new IllegalArgumentException("0 or negative value argument");
        }

        this.x = (int) (x * units + 0.5f);
        this.y = (int) (y * units + 0.5f);
        this.w = (int) (w * units + 0.5f);
        this.h = (int) (h * units + 0.5f);

    }

    /**
      * Constructs a MediaPrintableArea object from integer values.
      * @param x      printable x
      * @param y      printable y
      * @param w      printable width
      * @param h      printable height
      * @param units  in which the values are expressed.
      *
      * @exception  IllegalArgumentException
      *     Thrown if <CODE>x</CODE> < 0 or <CODE>y</CODE> < 0
      *     or <CODE>w</CODE> <= 0 or <CODE>h</CODE> <= 0 or
      *     <CODE>units</CODE> < 1.
      */
    public MediaPrintableArea(int x, int y, int w, int h, int units) {
        if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) ||
            (units < 1)) {
            throw new IllegalArgumentException("0 or negative value argument");
        }
        this.x = x * units;
        this.y = y * units;
        this.w = w * units;
        this.h = h * units;

    }

    /**
     * Get the printable area as an array of 4 values in the order
     * x, y, w, h. The values returned are in the given units.
     * @param  units
     *     Unit conversion factor, e.g. {@link #INCH <CODE>INCH</CODE>} or
     *     {@link #MM <CODE>MM</CODE>}.
     *
     * @return printable area as array of x, y, w, h in the specified units.
     *
     * @exception  IllegalArgumentException
     *     (unchecked exception) Thrown if <CODE>units</CODE> < 1.
     */
    public float[] getPrintableArea(int units) {
        return new float[] { getX(units), getY(units),
                             getWidth(units), getHeight(units) };
    }

    /**
     * Get the x location of the origin of the printable area in the
     * specified units.
     * @param  units
     *     Unit conversion factor, e.g. {@link #INCH <CODE>INCH</CODE>} or
     *     {@link #MM <CODE>MM</CODE>}.
     *
     * @return  x location of the origin of the printable area in the
     * specified units.
     *
     * @exception  IllegalArgumentException
     *     (unchecked exception) Thrown if <CODE>units</CODE> < 1.
     */
     public float getX(int units) {
        return convertFromMicrometers(x, units);
     }

    /**
     * Get the y location of the origin of the printable area in the
     * specified units.
     * @param  units
     *     Unit conversion factor, e.g. {@link #INCH <CODE>INCH</CODE>} or
     *     {@link #MM <CODE>MM</CODE>}.
     *
     * @return  y location of the origin of the printable area in the
     * specified units.
     *
     * @exception  IllegalArgumentException
     *     (unchecked exception) Thrown if <CODE>units</CODE> < 1.
     */
     public float getY(int units) {
        return convertFromMicrometers(y, units);
     }

    /**
     * Get the width of the printable area in the specified units.
     * @param  units
     *     Unit conversion factor, e.g. {@link #INCH <CODE>INCH</CODE>} or
     *     {@link #MM <CODE>MM</CODE>}.
     *
     * @return  width of the printable area in the specified units.
     *
     * @exception  IllegalArgumentException
     *     (unchecked exception) Thrown if <CODE>units</CODE> < 1.
     */
     public float getWidth(int units) {
        return convertFromMicrometers(w, units);
     }

    /**
     * Get the height of the printable area in the specified units.
     * @param  units
     *     Unit conversion factor, e.g. {@link #INCH <CODE>INCH</CODE>} or
     *     {@link #MM <CODE>MM</CODE>}.
     *
     * @return  height of the printable area in the specified units.
     *
     * @exception  IllegalArgumentException
     *     (unchecked exception) Thrown if <CODE>units</CODE> < 1.
     */
     public float getHeight(int units) {
        return convertFromMicrometers(h, units);
     }

    /**
     * Returns whether this media margins attribute is equivalent to the passed
     * in object.
     * To be equivalent, all of the following conditions must be true:
     * <OL TYPE=1>
     * <LI>
     * <CODE>object</CODE> is not null.
     * <LI>
     * <CODE>object</CODE> is an instance of class MediaPrintableArea.
     * <LI>
     * The origin and dimensions are the same.
     * </OL>
     *
     * @param  object  Object to compare to.
     *
     * @return  True if <CODE>object</CODE> is equivalent to this media margins
     *          attribute, false otherwise.
     */
    public boolean equals(Object object) {
        boolean ret = false;
        if (object instanceof MediaPrintableArea) {
           MediaPrintableArea mm = (MediaPrintableArea)object;
           if (x == mm.x &&  y == mm.y && w == mm.w && h == mm.h) {
               ret = true;
           }
        }
        return ret;
    }

    /**
     * Get the printing attribute class which is to be used as the "category"
     * for this printing attribute value.
     * <P>
     * For class MediaPrintableArea, the category is
     * class MediaPrintableArea itself.
     *
     * @return  Printing attribute class (category), an instance of class
     *          {@link java.lang.Class java.lang.Class}.
     */
    public final Class<? extends Attribute> getCategory() {
        return MediaPrintableArea.class;
    }

    /**
     * Get the name of the category of which this attribute value is an
     * instance.
     * <P>
     * For class MediaPrintableArea,
     * the category name is <CODE>"media-printable-area"</CODE>.
     * <p>This is not an IPP V1.1 attribute.
     *
     * @return  Attribute category name.
     */
    public final String getName() {
        return "media-printable-area";
    }

    /**
     * Returns a string version of this rectangular size attribute in the
     * given units.
     *
     * @param  units
     *     Unit conversion factor, e.g. {@link #INCH <CODE>INCH</CODE>} or
     *     {@link #MM <CODE>MM</CODE>}.
     * @param  unitsName
     *     Units name string, e.g. <CODE>"in"</CODE> or <CODE>"mm"</CODE>. If
     *     null, no units name is appended to the result.
     *
     * @return  String version of this two-dimensional size attribute.
     *
     * @exception  IllegalArgumentException
     *     (unchecked exception) Thrown if <CODE>units</CODE> < 1.
     */
    public String toString(int units, String unitsName) {
        if (unitsName == null) {
            unitsName = "";
        }
        float []vals = getPrintableArea(units);
        String str = "("+vals[0]+","+vals[1]+")->("+vals[2]+","+vals[3]+")";
        return str + unitsName;
    }

    /**
     * Returns a string version of this rectangular size attribute in mm.
     */
    public String toString() {
        return(toString(MM, "mm"));
    }

    /**
     * Returns a hash code value for this attribute.
     */
    public int hashCode() {
        return x + 37*y + 43*w + 47*h;
    }

    private static float convertFromMicrometers(int x, int units) {
        if (units < 1) {
            throw new IllegalArgumentException("units is < 1");
        }
        return ((float)x) / ((float)units);
    }
}
