Path: blob/master/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java
41159 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.print.attribute;2627import java.io.Serial;28import java.io.Serializable;2930/**31* Class {@code ResolutionSyntax} is an abstract base class providing the common32* implementation of all attributes denoting a printer resolution.33* <p>34* A resolution attribute's value consists of two items, the cross feed35* direction resolution and the feed direction resolution. A resolution36* attribute may be constructed by supplying the two values and indicating the37* units in which the values are measured. Methods are provided to return a38* resolution attribute's values, indicating the units in which the values are39* to be returned. The two most common resolution units are dots per inch (dpi)40* and dots per centimeter (dpcm), and exported constants {@link #DPI DPI} and41* {@link #DPCM DPCM} are provided for indicating those units.42* <p>43* Once constructed, a resolution attribute's value is immutable.44* <p>45* <b>Design</b>46* <p>47* A resolution attribute's cross feed direction resolution and feed direction48* resolution values are stored internally using units of dots per 100 inches49* (dphi). Storing the values in dphi rather than, say, metric units allows50* precise integer arithmetic conversions between dpi and dphi and between dpcm51* and dphi: 1 dpi = 100 dphi, 1 dpcm = 254 dphi. Thus, the values can be stored52* into and retrieved back from a resolution attribute in either units with no53* loss of precision. This would not be guaranteed if a floating point54* representation were used. However, roundoff error will in general occur if a55* resolution attribute's values are created in one units and retrieved in56* different units; for example, 600 dpi will be rounded to 236 dpcm, whereas57* the true value (to five figures) is 236.22 dpcm.58* <p>59* Storing the values internally in common units of dphi lets two resolution60* attributes be compared without regard to the units in which they were61* created; for example, 300 dpcm will compare equal to 762 dpi, as they both62* are stored as 76200 dphi. In particular, a lookup service can match63* resolution attributes based on equality of their serialized representations64* regardless of the units in which they were created. Again, using integers for65* internal storage allows precise equality comparisons to be done, which would66* not be guaranteed if a floating point representation were used.67* <p>68* The exported constant {@link #DPI DPI} is actually the conversion factor by69* which to multiply a value in dpi to get the value in dphi. Likewise, the70* exported constant {@link #DPCM DPCM} is the conversion factor by which to71* multiply a value in dpcm to get the value in dphi. A client can specify a72* resolution value in units other than dpi or dpcm by supplying its own73* conversion factor. However, since the internal units of dphi was chosen with74* supporting only the external units of dpi and dpcm in mind, there is no75* guarantee that the conversion factor for the client's units will be an exact76* integer. If the conversion factor isn't an exact integer, resolution values77* in the client's units won't be stored precisely.78*79* @author David Mendenhall80* @author Alan Kaminsky81*/82public abstract class ResolutionSyntax implements Serializable, Cloneable {8384/**85* Use serialVersionUID from JDK 1.4 for interoperability.86*/87@Serial88private static final long serialVersionUID = 2706743076526672017L;8990/**91* Cross feed direction resolution in units of dots per 100 inches (dphi).92*93* @serial94*/95private int crossFeedResolution;9697/**98* Feed direction resolution in units of dots per 100 inches (dphi).99*100* @serial101*/102private int feedResolution;103104/**105* Value to indicate units of dots per inch (dpi). It is actually the106* conversion factor by which to multiply dpi to yield dphi (100).107*/108public static final int DPI = 100;109110/**111* Value to indicate units of dots per centimeter (dpcm). It is actually the112* conversion factor by which to multiply dpcm to yield dphi (254).113*/114public static final int DPCM = 254;115116/**117* Construct a new resolution attribute from the given items.118*119* @param crossFeedResolution cross feed direction resolution120* @param feedResolution feed direction resolution121* @param units unit conversion factor, e.g. {@link #DPI DPI} or122* {@link #DPCM DPCM}123* @throws IllegalArgumentException if {@code crossFeedResolution < 1} or124* {@code feedResolution < 1} or {@code units < 1}125*/126public ResolutionSyntax(int crossFeedResolution, int feedResolution,127int units) {128129if (crossFeedResolution < 1) {130throw new IllegalArgumentException("crossFeedResolution is < 1");131}132if (feedResolution < 1) {133throw new IllegalArgumentException("feedResolution is < 1");134}135if (units < 1) {136throw new IllegalArgumentException("units is < 1");137}138139this.crossFeedResolution = crossFeedResolution * units;140this.feedResolution = feedResolution * units;141}142143/**144* Convert a value from dphi to some other units. The result is rounded to145* the nearest integer.146*147* @param dphi value (dphi) to convert148* @param units unit conversion factor, e.g. {@link #DPI DPI} or149* {@link #DPCM DPCM}150* @return the value of {@code dphi} converted to the desired units151* @throws IllegalArgumentException if {@code units < 1}152*/153private static int convertFromDphi(int dphi, int units) {154if (units < 1) {155throw new IllegalArgumentException(": units is < 1");156}157int round = units / 2;158return (dphi + round) / units;159}160161/**162* Get this resolution attribute's resolution values in the given units. The163* values are rounded to the nearest integer.164*165* @param units unit conversion factor, e.g. {@link #DPI DPI} or166* {@link #DPCM DPCM}167* @return a two-element array with the cross feed direction resolution at168* index 0 and the feed direction resolution at index 1169* @throws IllegalArgumentException if {@code units < 1}170*/171public int[] getResolution(int units) {172return new int[] { getCrossFeedResolution(units),173getFeedResolution(units)174};175}176177/**178* Returns this resolution attribute's cross feed direction resolution in179* the given units. The value is rounded to the nearest integer.180*181* @param units unit conversion factor, e.g. {@link #DPI DPI} or182* {@link #DPCM DPCM}183* @return cross feed direction resolution184* @throws IllegalArgumentException if {@code units < 1}185*/186public int getCrossFeedResolution(int units) {187return convertFromDphi (crossFeedResolution, units);188}189190/**191* Returns this resolution attribute's feed direction resolution in the192* given units. The value is rounded to the nearest integer.193*194* @param units unit conversion factor, e.g. {@link #DPI DPI} or195* {@link #DPCM DPCM}196* @return feed direction resolution197* @throws IllegalArgumentException if {@code units < 1}198*/199public int getFeedResolution(int units) {200return convertFromDphi (feedResolution, units);201}202203/**204* Returns a string version of this resolution attribute in the given units.205* The string takes the form <code>"<i>C</i>x<i>F</i> <i>U</i>"</code>,206* where <i>C</i> is the cross feed direction resolution, <i>F</i> is the207* feed direction resolution, and <i>U</i> is the units name. The values are208* rounded to the nearest integer.209*210* @param units unit conversion factor, e.g. {@link #DPI CODE>DPI} or211* {@link #DPCM DPCM}212* @param unitsName units name string, e.g. {@code "dpi"} or213* {@code "dpcm"}. If {@code null}, no units name is appended to the214* result.215* @return string version of this resolution attribute216* @throws IllegalArgumentException if {@code units < 1}217*/218public String toString(int units, String unitsName) {219StringBuilder result = new StringBuilder();220result.append(getCrossFeedResolution (units));221result.append('x');222result.append(getFeedResolution (units));223if (unitsName != null) {224result.append (' ');225result.append (unitsName);226}227return result.toString();228}229230/**231* Determine whether this resolution attribute's value is less than or equal232* to the given resolution attribute's value. This is true if all of the233* following conditions are true:234* <ul>235* <li>This attribute's cross feed direction resolution is less than or236* equal to the {@code other} attribute's cross feed direction resolution.237* <li>This attribute's feed direction resolution is less than or equal to238* the {@code other} attribute's feed direction resolution.239* </ul>240*241* @param other resolution attribute to compare with242* @return {@code true} if this resolution attribute is less than or equal243* to the {@code other} resolution attribute, {@code false}244* otherwise245* @throws NullPointerException if {@code other} is {@code null}246*/247public boolean lessThanOrEquals(ResolutionSyntax other) {248return (this.crossFeedResolution <= other.crossFeedResolution &&249this.feedResolution <= other.feedResolution);250}251252/**253* Returns whether this resolution attribute is equivalent to the passed in254* object. To be equivalent, all of the following conditions must be true:255* <ol type=1>256* <li>{@code object} is not {@code null}.257* <li>{@code object} is an instance of class {@code ResolutionSyntax}.258* <li>This attribute's cross feed direction resolution is equal to259* {@code object}'s cross feed direction resolution.260* <li>This attribute's feed direction resolution is equal to261* {@code object}'s feed direction resolution.262* </ol>263*264* @param object {@code Object} to compare to265* @return {@code true} if {@code object} is equivalent to this resolution266* attribute, {@code false} otherwise267*/268public boolean equals(Object object) {269270return(object != null &&271object instanceof ResolutionSyntax &&272this.crossFeedResolution ==273((ResolutionSyntax) object).crossFeedResolution &&274this.feedResolution ==275((ResolutionSyntax) object).feedResolution);276}277278/**279* Returns a hash code value for this resolution attribute.280*/281public int hashCode() {282return(((crossFeedResolution & 0x0000FFFF)) |283((feedResolution & 0x0000FFFF) << 16));284}285286/**287* Returns a string version of this resolution attribute. The string takes288* the form <code>"<i>C</i>x<i>F</i> dphi"</code>, where <i>C</i> is the289* cross feed direction resolution and <i>F</i> is the feed direction290* resolution. The values are reported in the internal units of dphi.291*/292public String toString() {293StringBuilder result = new StringBuilder();294result.append(crossFeedResolution);295result.append('x');296result.append(feedResolution);297result.append(" dphi");298return result.toString();299}300301/**302* Returns this resolution attribute's cross feed direction resolution in303* units of dphi. (For use in a subclass.)304*305* @return cross feed direction resolution306*/307protected int getCrossFeedResolutionDphi() {308return crossFeedResolution;309}310311/**312* Returns this resolution attribute's feed direction resolution in units of313* dphi. (For use in a subclass.)314*315* @return feed direction resolution316*/317protected int getFeedResolutionDphi() {318return feedResolution;319}320}321322323