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