View Javadoc
1   /*
2    * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  package javax.print.attribute.standard;
26  
27  import javax.print.attribute.Attribute;
28  import javax.print.attribute.DocAttribute;
29  import javax.print.attribute.PrintJobAttribute;
30  import javax.print.attribute.PrintRequestAttribute;
31  
32  /**
33   * Class MediaPrintableArea is a printing attribute used to distinguish
34   * the printable and non-printable areas of media.
35   * <p>
36   * The printable area is specified to be a rectangle, within the overall
37   * dimensions of a media.
38   * <p>
39   * Most printers cannot print on the entire surface of the media, due
40   * to printer hardware limitations. This class can be used to query
41   * the acceptable values for a supposed print job, and to request an area
42   * within the constraints of the printable area to be used in a print job.
43   * <p>
44   * To query for the printable area, a client must supply a suitable context.
45   * Without specifying at the very least the size of the media being used
46   * no meaningful value for printable area can be obtained.
47   * <p>
48   * The attribute is not described in terms of the distance from the edge
49   * of the paper, in part to emphasise that this attribute is not independent
50   * of a particular media, but must be described within the context of a
51   * choice of other attributes. Additionally it is usually more convenient
52   * for a client to use the printable area.
53   * <p>
54   * The hardware's minimum margins is not just a property of the printer,
55   * but may be a function of the media size, orientation, media type, and
56   * any specified finishings.
57   * <code>PrintService</code> provides the method to query the supported
58   * values of an attribute in a suitable context :
59   * See  {@link javax.print.PrintService#getSupportedAttributeValues(Class,DocFlavor, AttributeSet) PrintService.getSupportedAttributeValues()}
60   * <p>
61   * The rectangular printable area is defined thus:
62   * The (x,y) origin is positioned at the top-left of the paper in portrait
63   * mode regardless of the orientation specified in the requesting context.
64   * For example a printable area for A4 paper in portrait or landscape
65   * orientation will have height {@literal >} width.
66   * <p>
67   * A printable area attribute's values are stored
68   * internally as integers in units of micrometers (&#181;m), where 1 micrometer
69   * = 10<SUP>-6</SUP> meter = 1/1000 millimeter = 1/25400 inch. This permits
70   * dimensions to be represented exactly to a precision of 1/1000 mm (= 1
71   * &#181;m) or 1/100 inch (= 254 &#181;m). If fractional inches are expressed in
72  
73   * negative powers of two, this permits dimensions to be represented exactly to
74   * a precision of 1/8 inch (= 3175 &#181;m) but not 1/16 inch (because 1/16 inch
75  
76   * does not equal an integral number of &#181;m).
77   * <p>
78   * <B>IPP Compatibility:</B> MediaPrintableArea is not an IPP attribute.
79   */
80  
81  public final class MediaPrintableArea
82        implements DocAttribute, PrintRequestAttribute, PrintJobAttribute {
83  
84      private int x, y, w, h;
85      private int units;
86  
87      private static final long serialVersionUID = -1597171464050795793L;
88  
89      /**
90       * Value to indicate units of inches (in). It is actually the conversion
91       * factor by which to multiply inches to yield &#181;m (25400).
92       */
93      public static final int INCH = 25400;
94  
95      /**
96       * Value to indicate units of millimeters (mm). It is actually the
97       * conversion factor by which to multiply mm to yield &#181;m (1000).
98       */
99      public static final int MM = 1000;
100 
101     /**
102       * Constructs a MediaPrintableArea object from floating point values.
103       * @param x      printable x
104       * @param y      printable y
105       * @param w      printable width
106       * @param h      printable height
107       * @param units  in which the values are expressed.
108       *
109       * @exception  IllegalArgumentException
110       *     Thrown if {@code x < 0} or {@code y < 0}
111       *     or {@code w <= 0} or {@code h <= 0} or
112       *     {@code units < 1}.
113       */
114     public MediaPrintableArea(float x, float y, float w, float h, int units) {
115         if ((x < 0.0) || (y < 0.0) || (w <= 0.0) || (h <= 0.0) ||
116             (units < 1)) {
117             throw new IllegalArgumentException("0 or negative value argument");
118         }
119 
120         this.x = (int) (x * units + 0.5f);
121         this.y = (int) (y * units + 0.5f);
122         this.w = (int) (w * units + 0.5f);
123         this.h = (int) (h * units + 0.5f);
124 
125     }
126 
127     /**
128       * Constructs a MediaPrintableArea object from integer values.
129       * @param x      printable x
130       * @param y      printable y
131       * @param w      printable width
132       * @param h      printable height
133       * @param units  in which the values are expressed.
134       *
135       * @exception  IllegalArgumentException
136       *     Thrown if {@code x < 0} or {@code y < 0}
137       *     or {@code w <= 0} or {@code h <= 0} or
138       *     {@code units < 1}.
139       */
140     public MediaPrintableArea(int x, int y, int w, int h, int units) {
141         if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) ||
142             (units < 1)) {
143             throw new IllegalArgumentException("0 or negative value argument");
144         }
145         this.x = x * units;
146         this.y = y * units;
147         this.w = w * units;
148         this.h = h * units;
149 
150     }
151 
152     /**
153      * Get the printable area as an array of 4 values in the order
154      * x, y, w, h. The values returned are in the given units.
155      * @param  units
156      *     Unit conversion factor, e.g. {@link #INCH INCH} or
157      *     {@link #MM MM}.
158      *
159      * @return printable area as array of x, y, w, h in the specified units.
160      *
161      * @exception  IllegalArgumentException
162      *     (unchecked exception) Thrown if {@code units < 1}.
163      */
164     public float[] getPrintableArea(int units) {
165         return new float[] { getX(units), getY(units),
166                              getWidth(units), getHeight(units) };
167     }
168 
169     /**
170      * Get the x location of the origin of the printable area in the
171      * specified units.
172      * @param  units
173      *     Unit conversion factor, e.g. {@link #INCH INCH} or
174      *     {@link #MM MM}.
175      *
176      * @return  x location of the origin of the printable area in the
177      * specified units.
178      *
179      * @exception  IllegalArgumentException
180      *     (unchecked exception) Thrown if {@code units < 1}.
181      */
182      public float getX(int units) {
183         return convertFromMicrometers(x, units);
184      }
185 
186     /**
187      * Get the y location of the origin of the printable area in the
188      * specified units.
189      * @param  units
190      *     Unit conversion factor, e.g. {@link #INCH INCH} or
191      *     {@link #MM MM}.
192      *
193      * @return  y location of the origin of the printable area in the
194      * specified units.
195      *
196      * @exception  IllegalArgumentException
197      *     (unchecked exception) Thrown if {@code units < 1}.
198      */
199      public float getY(int units) {
200         return convertFromMicrometers(y, units);
201      }
202 
203     /**
204      * Get the width of the printable area in the specified units.
205      * @param  units
206      *     Unit conversion factor, e.g. {@link #INCH INCH} or
207      *     {@link #MM MM}.
208      *
209      * @return  width of the printable area in the specified units.
210      *
211      * @exception  IllegalArgumentException
212      *     (unchecked exception) Thrown if {@code units < 1}.
213      */
214      public float getWidth(int units) {
215         return convertFromMicrometers(w, units);
216      }
217 
218     /**
219      * Get the height of the printable area in the specified units.
220      * @param  units
221      *     Unit conversion factor, e.g. {@link #INCH INCH} or
222      *     {@link #MM MM}.
223      *
224      * @return  height of the printable area in the specified units.
225      *
226      * @exception  IllegalArgumentException
227      *     (unchecked exception) Thrown if {@code units < 1}.
228      */
229      public float getHeight(int units) {
230         return convertFromMicrometers(h, units);
231      }
232 
233     /**
234      * Returns whether this media margins attribute is equivalent to the passed
235      * in object.
236      * To be equivalent, all of the following conditions must be true:
237      * <OL TYPE=1>
238      * <LI>
239      * <CODE>object</CODE> is not null.
240      * <LI>
241      * <CODE>object</CODE> is an instance of class MediaPrintableArea.
242      * <LI>
243      * The origin and dimensions are the same.
244      * </OL>
245      *
246      * @param  object  Object to compare to.
247      *
248      * @return  True if <CODE>object</CODE> is equivalent to this media margins
249      *          attribute, false otherwise.
250      */
251     public boolean equals(Object object) {
252         boolean ret = false;
253         if (object instanceof MediaPrintableArea) {
254            MediaPrintableArea mm = (MediaPrintableArea)object;
255            if (x == mm.x &&  y == mm.y && w == mm.w && h == mm.h) {
256                ret = true;
257            }
258         }
259         return ret;
260     }
261 
262     /**
263      * Get the printing attribute class which is to be used as the "category"
264      * for this printing attribute value.
265      * <P>
266      * For class MediaPrintableArea, the category is
267      * class MediaPrintableArea itself.
268      *
269      * @return  Printing attribute class (category), an instance of class
270      *          {@link java.lang.Class java.lang.Class}.
271      */
272     public final Class<? extends Attribute> getCategory() {
273         return MediaPrintableArea.class;
274     }
275 
276     /**
277      * Get the name of the category of which this attribute value is an
278      * instance.
279      * <P>
280      * For class MediaPrintableArea,
281      * the category name is <CODE>"media-printable-area"</CODE>.
282      * <p>This is not an IPP V1.1 attribute.
283      *
284      * @return  Attribute category name.
285      */
286     public final String getName() {
287         return "media-printable-area";
288     }
289 
290     /**
291      * Returns a string version of this rectangular size attribute in the
292      * given units.
293      *
294      * @param  units
295      *     Unit conversion factor, e.g. {@link #INCH INCH} or
296      *     {@link #MM MM}.
297      * @param  unitsName
298      *     Units name string, e.g. <CODE>"in"</CODE> or <CODE>"mm"</CODE>. If
299      *     null, no units name is appended to the result.
300      *
301      * @return  String version of this two-dimensional size attribute.
302      *
303      * @exception  IllegalArgumentException
304      *     (unchecked exception) Thrown if {@code units < 1}.
305      */
306     public String toString(int units, String unitsName) {
307         if (unitsName == null) {
308             unitsName = "";
309         }
310         float []vals = getPrintableArea(units);
311         String str = "("+vals[0]+","+vals[1]+")->("+vals[2]+","+vals[3]+")";
312         return str + unitsName;
313     }
314 
315     /**
316      * Returns a string version of this rectangular size attribute in mm.
317      */
318     public String toString() {
319         return(toString(MM, "mm"));
320     }
321 
322     /**
323      * Returns a hash code value for this attribute.
324      */
325     public int hashCode() {
326         return x + 37*y + 43*w + 47*h;
327     }
328 
329     private static float convertFromMicrometers(int x, int units) {
330         if (units < 1) {
331             throw new IllegalArgumentException("units is < 1");
332         }
333         return ((float)x) / ((float)units);
334     }
335 }