1 /*
   2  * Copyright (c) 1998, 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 
  26 /*
  27  * @author Charlton Innovations, Inc.
  28  */
  29 
  30 package java.awt.font;
  31 
  32 import java.awt.RenderingHints;
  33 import static java.awt.RenderingHints.*;
  34 import java.awt.geom.AffineTransform;
  35 
  36 /**
  37 *   The <code>FontRenderContext</code> class is a container for the
  38 *   information needed to correctly measure text.  The measurement of text
  39 *   can vary because of rules that map outlines to pixels, and rendering
  40 *   hints provided by an application.
  41 *   <p>
  42 *   One such piece of information is a transform that scales
  43 *   typographical points to pixels. (A point is defined to be exactly 1/72
  44 *   of an inch, which is slightly different than
  45 *   the traditional mechanical measurement of a point.)  A character that
  46 *   is rendered at 12pt on a 600dpi device might have a different size
  47 *   than the same character rendered at 12pt on a 72dpi device because of
  48 *   such factors as rounding to pixel boundaries and hints that the font
  49 *   designer may have specified.
  50 *   <p>
  51 *   Anti-aliasing and Fractional-metrics specified by an application can also
  52 *   affect the size of a character because of rounding to pixel
  53 *   boundaries.
  54 *   <p>
  55 *   Typically, instances of <code>FontRenderContext</code> are
  56 *   obtained from a {@link java.awt.Graphics2D Graphics2D} object.  A
  57 *   <code>FontRenderContext</code> which is directly constructed will
  58 *   most likely not represent any actual graphics device, and may lead
  59 *   to unexpected or incorrect results.
  60 *   @see java.awt.RenderingHints#KEY_TEXT_ANTIALIASING
  61 *   @see java.awt.RenderingHints#KEY_FRACTIONALMETRICS
  62 *   @see java.awt.Graphics2D#getFontRenderContext()
  63 *   @see java.awt.font.LineMetrics
  64 */
  65 
  66 public class FontRenderContext {
  67     private transient AffineTransform tx;
  68     private transient Object aaHintValue;
  69     private transient Object fmHintValue;
  70     private transient boolean defaulting;
  71 
  72     /**
  73      * Constructs a new <code>FontRenderContext</code>
  74      * object.
  75      *
  76      */
  77     protected FontRenderContext() {
  78         aaHintValue = VALUE_TEXT_ANTIALIAS_DEFAULT;
  79         fmHintValue = VALUE_FRACTIONALMETRICS_DEFAULT;
  80         defaulting = true;
  81     }
  82 
  83     /**
  84      * Constructs a <code>FontRenderContext</code> object from an
  85      * optional {@link AffineTransform} and two <code>boolean</code>
  86      * values that determine if the newly constructed object has
  87      * anti-aliasing or fractional metrics.
  88      * In each case the boolean values <CODE>true</CODE> and <CODE>false</CODE>
  89      * correspond to the rendering hint values <CODE>ON</CODE> and
  90      * <CODE>OFF</CODE> respectively.
  91      * <p>
  92      * To specify other hint values, use the constructor which
  93      * specifies the rendering hint values as parameters :
  94      * {@link #FontRenderContext(AffineTransform, Object, Object)}.
  95      * @param tx the transform which is used to scale typographical points
  96      * to pixels in this <code>FontRenderContext</code>.  If null, an
  97      * identity transform is used.
  98      * @param isAntiAliased determines if the newly constructed object
  99      * has anti-aliasing.
 100      * @param usesFractionalMetrics determines if the newly constructed
 101      * object has fractional metrics.
 102      */
 103     public FontRenderContext(AffineTransform tx,
 104                             boolean isAntiAliased,
 105                             boolean usesFractionalMetrics) {
 106         if (tx != null && !tx.isIdentity()) {
 107             this.tx = new AffineTransform(tx);
 108         }
 109         if (isAntiAliased) {
 110             aaHintValue = VALUE_TEXT_ANTIALIAS_ON;
 111         } else {
 112             aaHintValue = VALUE_TEXT_ANTIALIAS_OFF;
 113         }
 114         if (usesFractionalMetrics) {
 115             fmHintValue = VALUE_FRACTIONALMETRICS_ON;
 116         } else {
 117             fmHintValue = VALUE_FRACTIONALMETRICS_OFF;
 118         }
 119     }
 120 
 121     /**
 122      * Constructs a <code>FontRenderContext</code> object from an
 123      * optional {@link AffineTransform} and two <code>Object</code>
 124      * values that determine if the newly constructed object has
 125      * anti-aliasing or fractional metrics.
 126      * @param tx the transform which is used to scale typographical points
 127      * to pixels in this <code>FontRenderContext</code>.  If null, an
 128      * identity transform is used.
 129      * @param aaHint - one of the text antialiasing rendering hint values
 130      * defined in {@link java.awt.RenderingHints java.awt.RenderingHints}.
 131      * Any other value will throw <code>IllegalArgumentException</code>.
 132      * {@link java.awt.RenderingHints#VALUE_TEXT_ANTIALIAS_DEFAULT VALUE_TEXT_ANTIALIAS_DEFAULT}
 133      * may be specified, in which case the mode used is implementation
 134      * dependent.
 135      * @param fmHint - one of the text fractional rendering hint values defined
 136      * in {@link java.awt.RenderingHints java.awt.RenderingHints}.
 137      * {@link java.awt.RenderingHints#VALUE_FRACTIONALMETRICS_DEFAULT VALUE_FRACTIONALMETRICS_DEFAULT}
 138      * may be specified, in which case the mode used is implementation
 139      * dependent.
 140      * Any other value will throw <code>IllegalArgumentException</code>
 141      * @throws IllegalArgumentException if the hints are not one of the
 142      * legal values.
 143      * @since 1.6
 144      */
 145     public FontRenderContext(AffineTransform tx, Object aaHint, Object fmHint){
 146         if (tx != null && !tx.isIdentity()) {
 147             this.tx = new AffineTransform(tx);
 148         }
 149         try {
 150             if (KEY_TEXT_ANTIALIASING.isCompatibleValue(aaHint)) {
 151                 aaHintValue = aaHint;
 152             } else {
 153                 throw new IllegalArgumentException("AA hint:" + aaHint);
 154             }
 155         } catch (Exception e) {
 156             throw new IllegalArgumentException("AA hint:" +aaHint);
 157         }
 158         try {
 159             if (KEY_FRACTIONALMETRICS.isCompatibleValue(fmHint)) {
 160                 fmHintValue = fmHint;
 161             } else {
 162                 throw new IllegalArgumentException("FM hint:" + fmHint);
 163             }
 164         } catch (Exception e) {
 165             throw new IllegalArgumentException("FM hint:" +fmHint);
 166         }
 167     }
 168 
 169     /**
 170      * Indicates whether or not this <code>FontRenderContext</code> object
 171      * measures text in a transformed render context.
 172      * @return  <code>true</code> if this <code>FontRenderContext</code>
 173      *          object has a non-identity AffineTransform attribute.
 174      *          <code>false</code> otherwise.
 175      * @see     java.awt.font.FontRenderContext#getTransform
 176      * @since   1.6
 177      */
 178     public boolean isTransformed() {
 179         if (!defaulting) {
 180             return tx != null;
 181         } else {
 182             return !getTransform().isIdentity();
 183         }
 184     }
 185 
 186     /**
 187      * Returns the integer type of the affine transform for this
 188      * <code>FontRenderContext</code> as specified by
 189      * {@link java.awt.geom.AffineTransform#getType()}
 190      * @return the type of the transform.
 191      * @see AffineTransform
 192      * @since 1.6
 193      */
 194     public int getTransformType() {
 195         if (!defaulting) {
 196             if (tx == null) {
 197                 return AffineTransform.TYPE_IDENTITY;
 198             } else {
 199                 return tx.getType();
 200             }
 201         } else {
 202             return getTransform().getType();
 203         }
 204     }
 205 
 206     /**
 207     *   Gets the transform that is used to scale typographical points
 208     *   to pixels in this <code>FontRenderContext</code>.
 209     *   @return the <code>AffineTransform</code> of this
 210     *    <code>FontRenderContext</code>.
 211     *   @see AffineTransform
 212     */
 213     public AffineTransform getTransform() {
 214         return (tx == null) ? new AffineTransform() : new AffineTransform(tx);
 215     }
 216 
 217     /**
 218     * Returns a boolean which indicates whether or not some form of
 219     * antialiasing is specified by this <code>FontRenderContext</code>.
 220     * Call {@link #getAntiAliasingHint() getAntiAliasingHint()}
 221     * for the specific rendering hint value.
 222     *   @return    <code>true</code>, if text is anti-aliased in this
 223     *   <code>FontRenderContext</code>; <code>false</code> otherwise.
 224     *   @see        java.awt.RenderingHints#KEY_TEXT_ANTIALIASING
 225     *   @see #FontRenderContext(AffineTransform,boolean,boolean)
 226     *   @see #FontRenderContext(AffineTransform,Object,Object)
 227     */
 228     public boolean isAntiAliased() {
 229         return !(aaHintValue == VALUE_TEXT_ANTIALIAS_OFF ||
 230                  aaHintValue == VALUE_TEXT_ANTIALIAS_DEFAULT);
 231     }
 232 
 233     /**
 234     * Returns a boolean which whether text fractional metrics mode
 235     * is used in this <code>FontRenderContext</code>.
 236     * Call {@link #getFractionalMetricsHint() getFractionalMetricsHint()}
 237     * to obtain the corresponding rendering hint value.
 238     *   @return    <code>true</code>, if layout should be performed with
 239     *   fractional metrics; <code>false</code> otherwise.
 240     *               in this <code>FontRenderContext</code>.
 241     *   @see java.awt.RenderingHints#KEY_FRACTIONALMETRICS
 242     *   @see #FontRenderContext(AffineTransform,boolean,boolean)
 243     *   @see #FontRenderContext(AffineTransform,Object,Object)
 244     */
 245     public boolean usesFractionalMetrics() {
 246         return !(fmHintValue == VALUE_FRACTIONALMETRICS_OFF ||
 247                  fmHintValue == VALUE_FRACTIONALMETRICS_DEFAULT);
 248     }
 249 
 250     /**
 251      * Return the text anti-aliasing rendering mode hint used in this
 252      * <code>FontRenderContext</code>.
 253      * This will be one of the text antialiasing rendering hint values
 254      * defined in {@link java.awt.RenderingHints java.awt.RenderingHints}.
 255      * @return  text anti-aliasing rendering mode hint used in this
 256      * <code>FontRenderContext</code>.
 257      * @since 1.6
 258      */
 259     public Object getAntiAliasingHint() {
 260         if (defaulting) {
 261             if (isAntiAliased()) {
 262                  return VALUE_TEXT_ANTIALIAS_ON;
 263             } else {
 264                 return VALUE_TEXT_ANTIALIAS_OFF;
 265             }
 266         }
 267         return aaHintValue;
 268     }
 269 
 270     /**
 271      * Return the text fractional metrics rendering mode hint used in this
 272      * <code>FontRenderContext</code>.
 273      * This will be one of the text fractional metrics rendering hint values
 274      * defined in {@link java.awt.RenderingHints java.awt.RenderingHints}.
 275      * @return the text fractional metrics rendering mode hint used in this
 276      * <code>FontRenderContext</code>.
 277      * @since 1.6
 278      */
 279     public Object getFractionalMetricsHint() {
 280         if (defaulting) {
 281             if (usesFractionalMetrics()) {
 282                  return VALUE_FRACTIONALMETRICS_ON;
 283             } else {
 284                 return VALUE_FRACTIONALMETRICS_OFF;
 285             }
 286         }
 287         return fmHintValue;
 288     }
 289 
 290     /**
 291      * Return true if obj is an instance of FontRenderContext and has the same
 292      * transform, antialiasing, and fractional metrics values as this.
 293      * @param obj the object to test for equality
 294      * @return <code>true</code> if the specified object is equal to
 295      *         this <code>FontRenderContext</code>; <code>false</code>
 296      *         otherwise.
 297      */
 298     public boolean equals(Object obj) {
 299         try {
 300             return equals((FontRenderContext)obj);
 301         }
 302         catch (ClassCastException e) {
 303             return false;
 304         }
 305     }
 306 
 307     /**
 308      * Return true if rhs has the same transform, antialiasing,
 309      * and fractional metrics values as this.
 310      * @param rhs the <code>FontRenderContext</code> to test for equality
 311      * @return <code>true</code> if <code>rhs</code> is equal to
 312      *         this <code>FontRenderContext</code>; <code>false</code>
 313      *         otherwise.
 314      * @since 1.4
 315      */
 316     public boolean equals(FontRenderContext rhs) {
 317         if (this == rhs) {
 318             return true;
 319         }
 320         if (rhs == null) {
 321             return false;
 322         }
 323 
 324         /* if neither instance is a subclass, reference values directly. */
 325         if (!rhs.defaulting && !defaulting) {
 326             if (rhs.aaHintValue == aaHintValue &&
 327                 rhs.fmHintValue == fmHintValue) {
 328 
 329                 return tx == null ? rhs.tx == null : tx.equals(rhs.tx);
 330             }
 331             return false;
 332         } else {
 333             return
 334                 rhs.getAntiAliasingHint() == getAntiAliasingHint() &&
 335                 rhs.getFractionalMetricsHint() == getFractionalMetricsHint() &&
 336                 rhs.getTransform().equals(getTransform());
 337         }
 338     }
 339 
 340     /**
 341      * Return a hashcode for this FontRenderContext.
 342      */
 343     public int hashCode() {
 344         int hash = tx == null ? 0 : tx.hashCode();
 345         /* SunHints value objects have identity hashcode, so we can rely on
 346          * this to ensure that two equal FRC's have the same hashcode.
 347          */
 348         if (defaulting) {
 349             hash += getAntiAliasingHint().hashCode();
 350             hash += getFractionalMetricsHint().hashCode();
 351         } else {
 352             hash += aaHintValue.hashCode();
 353             hash += fmHintValue.hashCode();
 354         }
 355         return hash;
 356     }
 357 }
--- EOF ---