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 package java.awt;
  27 
  28 import java.util.Map;
  29 import java.util.Set;
  30 import java.util.Collection;
  31 import java.util.Collections;
  32 import java.util.HashMap;
  33 import java.util.Iterator;
  34 import sun.awt.SunHints;
  35 import java.lang.ref.WeakReference;
  36 
  37 /**
  38  * The {@code RenderingHints} class defines and manages collections of
  39  * keys and associated values which allow an application to provide input
  40  * into the choice of algorithms used by other classes which perform
  41  * rendering and image manipulation services.
  42  * The {@link java.awt.Graphics2D} class, and classes that implement
  43  * {@link java.awt.image.BufferedImageOp} and
  44  * {@link java.awt.image.RasterOp} all provide methods to get and
  45  * possibly to set individual or groups of {@code RenderingHints}
  46  * keys and their associated values.
  47  * When those implementations perform any rendering or image manipulation
  48  * operations they should examine the values of any {@code RenderingHints}
  49  * that were requested by the caller and tailor the algorithms used
  50  * accordingly and to the best of their ability.
  51  * <p>
  52  * Note that since these keys and values are <i>hints</i>, there is
  53  * no requirement that a given implementation supports all possible
  54  * choices indicated below or that it can respond to requests to
  55  * modify its choice of algorithm.
  56  * The values of the various hint keys may also interact such that
  57  * while all variants of a given key are supported in one situation,
  58  * the implementation may be more restricted when the values associated
  59  * with other keys are modified.
  60  * For example, some implementations may be able to provide several
  61  * types of dithering when the antialiasing hint is turned off, but
  62  * have little control over dithering when antialiasing is on.
  63  * The full set of supported keys and hints may also vary by destination
  64  * since runtimes may use different underlying modules to render to
  65  * the screen, or to {@link java.awt.image.BufferedImage} objects,
  66  * or while printing.
  67  * <p>
  68  * Implementations are free to ignore the hints completely, but should
  69  * try to use an implementation algorithm that is as close as possible
  70  * to the request.
  71  * If an implementation supports a given algorithm when any value is used
  72  * for an associated hint key, then minimally it must do so when the
  73  * value for that key is the exact value that specifies the algorithm.
  74  * <p>
  75  * The keys used to control the hints are all special values that
  76  * subclass the associated {@link RenderingHints.Key} class.
  77  * Many common hints are expressed below as static constants in this
  78  * class, but the list is not meant to be exhaustive.
  79  * Other hints may be created by other packages by defining new objects
  80  * which subclass the {@code Key} class and defining the associated values.
  81  */
  82 public class RenderingHints
  83     implements Map<Object,Object>, Cloneable
  84 {
  85     /**
  86      * Defines the base type of all keys used along with the
  87      * {@link RenderingHints} class to control various
  88      * algorithm choices in the rendering and imaging pipelines.
  89      * Instances of this class are immutable and unique which
  90      * means that tests for matches can be made using the
  91      * {@code ==} operator instead of the more expensive
  92      * {@code equals()} method.
  93      */
  94     public abstract static class Key {
  95         private static HashMap<Object,Object> identitymap = new HashMap<>(17);
  96 
  97         private String getIdentity() {
  98             // Note that the identity string is dependent on 3 variables:
  99             //     - the name of the subclass of Key
 100             //     - the identityHashCode of the subclass of Key
 101             //     - the integer key of the Key
 102             // It is theoretically possible for 2 distinct keys to collide
 103             // along all 3 of those attributes in the context of multiple
 104             // class loaders, but that occurrence will be extremely rare and
 105             // we account for that possibility below in the recordIdentity
 106             // method by slightly relaxing our uniqueness guarantees if we
 107             // end up in that situation.
 108             return getClass().getName()+"@"+
 109                 Integer.toHexString(System.identityHashCode(getClass()))+":"+
 110                 Integer.toHexString(privatekey);
 111         }
 112 
 113         private synchronized static void recordIdentity(Key k) {
 114             Object identity = k.getIdentity();
 115             Object otherref = identitymap.get(identity);
 116             if (otherref != null) {
 117                 Key otherkey = (Key) ((WeakReference) otherref).get();
 118                 if (otherkey != null && otherkey.getClass() == k.getClass()) {
 119                     throw new IllegalArgumentException(identity+
 120                                                        " already registered");
 121                 }
 122                 // Note that this system can fail in a mostly harmless
 123                 // way.  If we end up generating the same identity
 124                 // String for 2 different classes (a very rare case)
 125                 // then we correctly avoid throwing the exception above,
 126                 // but we are about to drop through to a statement that
 127                 // will replace the entry for the old Key subclass with
 128                 // an entry for the new Key subclass.  At that time the
 129                 // old subclass will be vulnerable to someone generating
 130                 // a duplicate Key instance for it.  We could bail out
 131                 // of the method here and let the old identity keep its
 132                 // record in the map, but we are more likely to see a
 133                 // duplicate key go by for the new class than the old
 134                 // one since the new one is probably still in the
 135                 // initialization stage.  In either case, the probability
 136                 // of loading 2 classes in the same VM with the same name
 137                 // and identityHashCode should be nearly impossible.
 138             }
 139             // Note: Use a weak reference to avoid holding on to extra
 140             // objects and classes after they should be unloaded.
 141             identitymap.put(identity, new WeakReference<Key>(k));
 142         }
 143 
 144         private int privatekey;
 145 
 146         /**
 147          * Construct a key using the indicated private key.  Each
 148          * subclass of Key maintains its own unique domain of integer
 149          * keys.  No two objects with the same integer key and of the
 150          * same specific subclass can be constructed.  An exception
 151          * will be thrown if an attempt is made to construct another
 152          * object of a given class with the same integer key as a
 153          * pre-existing instance of that subclass of Key.
 154          * @param privatekey the specified key
 155          */
 156         protected Key(int privatekey) {
 157             this.privatekey = privatekey;
 158             recordIdentity(this);
 159         }
 160 
 161         /**
 162          * Returns true if the specified object is a valid value
 163          * for this Key.
 164          * @param val the <code>Object</code> to test for validity
 165          * @return <code>true</code> if <code>val</code> is valid;
 166          *         <code>false</code> otherwise.
 167          */
 168         public abstract boolean isCompatibleValue(Object val);
 169 
 170         /**
 171          * Returns the private integer key that the subclass
 172          * instantiated this Key with.
 173          * @return the private integer key that the subclass
 174          * instantiated this Key with.
 175          */
 176         protected final int intKey() {
 177             return privatekey;
 178         }
 179 
 180         /**
 181          * The hash code for all Key objects will be the same as the
 182          * system identity code of the object as defined by the
 183          * System.identityHashCode() method.
 184          */
 185         public final int hashCode() {
 186             return super.hashCode();
 187         }
 188 
 189         /**
 190          * The equals method for all Key objects will return the same
 191          * result as the equality operator '=='.
 192          */
 193         public final boolean equals(Object o) {
 194             return this == o;
 195         }
 196     }
 197 
 198     HashMap<Object,Object> hintmap = new HashMap<>(7);
 199 
 200     /**
 201      * Antialiasing hint key.
 202      * The {@code ANTIALIASING} hint controls whether or not the
 203      * geometry rendering methods of a {@link Graphics2D} object
 204      * will attempt to reduce aliasing artifacts along the edges
 205      * of shapes.
 206      * <p>
 207      * A typical antialiasing algorithm works by blending the existing
 208      * colors of the pixels along the boundary of a shape with the
 209      * requested fill paint according to the estimated partial pixel
 210      * coverage of the shape.
 211      * <p>
 212      * The allowable values for this hint are
 213      * <ul>
 214      * <li>{@link #VALUE_ANTIALIAS_ON}
 215      * <li>{@link #VALUE_ANTIALIAS_OFF}
 216      * <li>{@link #VALUE_ANTIALIAS_DEFAULT}
 217      * </ul>
 218      */
 219     public static final Key KEY_ANTIALIASING =
 220         SunHints.KEY_ANTIALIASING;
 221 
 222     /**
 223      * Antialiasing hint value -- rendering is done with antialiasing.
 224      * @see #KEY_ANTIALIASING
 225      */
 226     public static final Object VALUE_ANTIALIAS_ON =
 227         SunHints.VALUE_ANTIALIAS_ON;
 228 
 229     /**
 230      * Antialiasing hint value -- rendering is done without antialiasing.
 231      * @see #KEY_ANTIALIASING
 232      */
 233     public static final Object VALUE_ANTIALIAS_OFF =
 234         SunHints.VALUE_ANTIALIAS_OFF;
 235 
 236     /**
 237      * Antialiasing hint value -- rendering is done with a default
 238      * antialiasing mode chosen by the implementation.
 239      * @see #KEY_ANTIALIASING
 240      */
 241     public static final Object VALUE_ANTIALIAS_DEFAULT =
 242          SunHints.VALUE_ANTIALIAS_DEFAULT;
 243 
 244     /**
 245      * Rendering hint key.
 246      * The {@code RENDERING} hint is a general hint that provides
 247      * a high level recommendation as to whether to bias algorithm
 248      * choices more for speed or quality when evaluating tradeoffs.
 249      * This hint could be consulted for any rendering or image
 250      * manipulation operation, but decisions will usually honor
 251      * other, more specific hints in preference to this hint.
 252      * <p>
 253      * The allowable values for this hint are
 254      * <ul>
 255      * <li>{@link #VALUE_RENDER_SPEED}
 256      * <li>{@link #VALUE_RENDER_QUALITY}
 257      * <li>{@link #VALUE_RENDER_DEFAULT}
 258      * </ul>
 259      */
 260     public static final Key KEY_RENDERING =
 261          SunHints.KEY_RENDERING;
 262 
 263     /**
 264      * Rendering hint value -- rendering algorithms are chosen
 265      * with a preference for output speed.
 266      * @see #KEY_RENDERING
 267      */
 268     public static final Object VALUE_RENDER_SPEED =
 269          SunHints.VALUE_RENDER_SPEED;
 270 
 271     /**
 272      * Rendering hint value -- rendering algorithms are chosen
 273      * with a preference for output quality.
 274      * @see #KEY_RENDERING
 275      */
 276     public static final Object VALUE_RENDER_QUALITY =
 277          SunHints.VALUE_RENDER_QUALITY;
 278 
 279     /**
 280      * Rendering hint value -- rendering algorithms are chosen
 281      * by the implementation for a good tradeoff of performance
 282      * vs. quality.
 283      * @see #KEY_RENDERING
 284      */
 285     public static final Object VALUE_RENDER_DEFAULT =
 286          SunHints.VALUE_RENDER_DEFAULT;
 287 
 288     /**
 289      * Dithering hint key.
 290      * The {@code DITHERING} hint controls how closely to approximate
 291      * a color when storing into a destination with limited color
 292      * resolution.
 293      * <p>
 294      * Some rendering destinations may support a limited number of
 295      * color choices which may not be able to accurately represent
 296      * the full spectrum of colors that can result during rendering
 297      * operations.
 298      * For such a destination the {@code DITHERING} hint controls
 299      * whether rendering is done with a flat solid fill of a single
 300      * pixel value which is the closest supported color to what was
 301      * requested, or whether shapes will be filled with a pattern of
 302      * colors which combine to better approximate that color.
 303      * <p>
 304      * The allowable values for this hint are
 305      * <ul>
 306      * <li>{@link #VALUE_DITHER_DISABLE}
 307      * <li>{@link #VALUE_DITHER_ENABLE}
 308      * <li>{@link #VALUE_DITHER_DEFAULT}
 309      * </ul>
 310      */
 311     public static final Key KEY_DITHERING =
 312          SunHints.KEY_DITHERING;
 313 
 314     /**
 315      * Dithering hint value -- do not dither when rendering geometry.
 316      * @see #KEY_DITHERING
 317      */
 318     public static final Object VALUE_DITHER_DISABLE =
 319          SunHints.VALUE_DITHER_DISABLE;
 320 
 321     /**
 322      * Dithering hint value -- dither when rendering geometry, if needed.
 323      * @see #KEY_DITHERING
 324      */
 325     public static final Object VALUE_DITHER_ENABLE =
 326          SunHints.VALUE_DITHER_ENABLE;
 327 
 328     /**
 329      * Dithering hint value -- use a default for dithering chosen by
 330      * the implementation.
 331      * @see #KEY_DITHERING
 332      */
 333     public static final Object VALUE_DITHER_DEFAULT =
 334          SunHints.VALUE_DITHER_DEFAULT;
 335 
 336     /**
 337      * Text antialiasing hint key.
 338      * The {@code TEXT_ANTIALIASING} hint can control the use of
 339      * antialiasing algorithms for text independently of the
 340      * choice used for shape rendering.
 341      * Often an application may want to use antialiasing for text
 342      * only and not for other shapes.
 343      * Additionally, the algorithms for reducing the aliasing
 344      * artifacts for text are often more sophisticated than those
 345      * that have been developed for general rendering so this
 346      * hint key provides additional values which can control
 347      * the choices of some of those text-specific algorithms.
 348      * If left in the {@code DEFAULT} state, this hint will
 349      * generally defer to the value of the regular
 350      * {@link #KEY_ANTIALIASING} hint key.
 351      * <p>
 352      * The allowable values for this hint are
 353      * <ul>
 354      * <li>{@link #VALUE_TEXT_ANTIALIAS_ON}
 355      * <li>{@link #VALUE_TEXT_ANTIALIAS_OFF}
 356      * <li>{@link #VALUE_TEXT_ANTIALIAS_DEFAULT}
 357      * <li>{@link #VALUE_TEXT_ANTIALIAS_GASP}
 358      * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}
 359      * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_HBGR}
 360      * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_VRGB}
 361      * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_VBGR}
 362      * </ul>
 363      */
 364     public static final Key KEY_TEXT_ANTIALIASING =
 365          SunHints.KEY_TEXT_ANTIALIASING;
 366 
 367     /**
 368      * Text antialiasing hint value -- text rendering is done with
 369      * some form of antialiasing.
 370      * @see #KEY_TEXT_ANTIALIASING
 371      */
 372     public static final Object VALUE_TEXT_ANTIALIAS_ON =
 373          SunHints.VALUE_TEXT_ANTIALIAS_ON;
 374 
 375     /**
 376      * Text antialiasing hint value -- text rendering is done without
 377      * any form of antialiasing.
 378      * @see #KEY_TEXT_ANTIALIASING
 379      */
 380     public static final Object VALUE_TEXT_ANTIALIAS_OFF =
 381          SunHints.VALUE_TEXT_ANTIALIAS_OFF;
 382 
 383     /**
 384      * Text antialiasing hint value -- text rendering is done according
 385      * to the {@link #KEY_ANTIALIASING} hint or a default chosen by the
 386      * implementation.
 387      * @see #KEY_TEXT_ANTIALIASING
 388      */
 389     public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT =
 390          SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
 391 
 392     /**
 393      * Text antialiasing hint value -- text rendering is requested to
 394      * use information in the font resource which specifies for each point
 395      * size whether to apply {@link #VALUE_TEXT_ANTIALIAS_ON} or
 396      * {@link #VALUE_TEXT_ANTIALIAS_OFF}.
 397      * <p>
 398      * TrueType fonts typically provide this information in the 'gasp' table.
 399      * In the absence of this information, the behaviour for a particular
 400      * font and size is determined by implementation defaults.
 401      * <p>
 402      * <i>Note:</i>A font designer will typically carefully hint a font for
 403      * the most common user interface point sizes. Consequently the 'gasp'
 404      * table will likely specify to use only hinting at those sizes and not
 405      * "smoothing". So in many cases the resulting text display is
 406      * equivalent to {@code VALUE_TEXT_ANTIALIAS_OFF}.
 407      * This may be unexpected but is correct.
 408      * <p>
 409      * Logical fonts which are composed of multiple physical fonts will for
 410      * consistency will use the setting most appropriate for the overall
 411      * composite font.
 412      *
 413      * @see #KEY_TEXT_ANTIALIASING
 414      * @since 1.6
 415      */
 416     public static final Object VALUE_TEXT_ANTIALIAS_GASP =
 417          SunHints.VALUE_TEXT_ANTIALIAS_GASP;
 418 
 419     /**
 420      * Text antialiasing hint value -- request that text be displayed
 421      * optimised for an LCD display with subpixels in order from display
 422      * left to right of R,G,B such that the horizontal subpixel resolution
 423      * is three times that of the full pixel horizontal resolution (HRGB).
 424      * This is the most common configuration.
 425      * Selecting this hint for displays with one of the other LCD subpixel
 426      * configurations will likely result in unfocused text.
 427      * <p>
 428      * <i>Notes:</i><br>
 429      * An implementation when choosing whether to apply any of the
 430      * LCD text hint values may take into account factors including requiring
 431      * color depth of the destination to be at least 15 bits per pixel
 432      * (ie 5 bits per color component),
 433      * characteristics of a font such as whether embedded bitmaps may
 434      * produce better results, or when displaying to a non-local networked
 435      * display device enabling it only if suitable protocols are available,
 436      * or ignoring the hint if performing very high resolution rendering
 437      * or the target device is not appropriate: eg when printing.
 438      * <p>
 439      * These hints can equally be applied when rendering to software images,
 440      * but these images may not then be suitable for general export, as the
 441      * text will have been rendered appropriately for a specific subpixel
 442      * organisation. Also lossy images are not a good choice, nor image
 443      * formats such as GIF which have limited colors.
 444      * So unless the image is destined solely for rendering on a
 445      * display device with the same configuration, some other text
 446      * anti-aliasing hint such as
 447      * {@link #VALUE_TEXT_ANTIALIAS_ON}
 448      * may be a better choice.
 449      * <p>Selecting a value which does not match the LCD display in use
 450      * will likely lead to a degradation in text quality.
 451      * On display devices (ie CRTs) which do not have the same characteristics
 452      * as LCD displays, the overall effect may appear similar to standard text
 453      * anti-aliasing, but the quality may be degraded by color distortion.
 454      * Analog connected LCD displays may also show little advantage over
 455      * standard text-antialiasing and be similar to CRTs.
 456      * <p>
 457      * In other words for the best results use an LCD display with a digital
 458      * display connector and specify the appropriate sub-pixel configuration.
 459      *
 460      * @see #KEY_TEXT_ANTIALIASING
 461      * @since 1.6
 462      */
 463     public static final Object VALUE_TEXT_ANTIALIAS_LCD_HRGB =
 464          SunHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB;
 465 
 466     /**
 467      * Text antialiasing hint value -- request that text be displayed
 468      * optimised for an LCD display with subpixels in order from display
 469      * left to right of B,G,R such that the horizontal subpixel resolution
 470      * is three times that of the full pixel horizontal resolution (HBGR).
 471      * This is a much less common configuration than HRGB.
 472      * Selecting this hint for displays with one of the other LCD subpixel
 473      * configurations will likely result in unfocused text.
 474      * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB},
 475      * for more information on when this hint is applied.
 476      *
 477      * @see #KEY_TEXT_ANTIALIASING
 478      * @since 1.6
 479      */
 480     public static final Object VALUE_TEXT_ANTIALIAS_LCD_HBGR =
 481          SunHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR;
 482 
 483     /**
 484      * Text antialiasing hint value -- request that text be displayed
 485      * optimised for an LCD display with subpixel organisation from display
 486      * top to bottom of R,G,B such that the vertical subpixel resolution is
 487      * three times that of the full pixel vertical resolution (VRGB).
 488      * Vertical orientation is very uncommon and probably mainly useful
 489      * for a physically rotated display.
 490      * Selecting this hint for displays with one of the other LCD subpixel
 491      * configurations will likely result in unfocused text.
 492      * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB},
 493      * for more information on when this hint is applied.
 494      *
 495      * @see #KEY_TEXT_ANTIALIASING
 496      * @since 1.6
 497      */
 498     public static final Object VALUE_TEXT_ANTIALIAS_LCD_VRGB =
 499          SunHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB;
 500 
 501     /**
 502      * Text antialiasing hint value -- request that text be displayed
 503      * optimised for an LCD display with subpixel organisation from display
 504      * top to bottom of B,G,R such that the vertical subpixel resolution is
 505      * three times that of the full pixel vertical resolution (VBGR).
 506      * Vertical orientation is very uncommon and probably mainly useful
 507      * for a physically rotated display.
 508      * Selecting this hint for displays with one of the other LCD subpixel
 509      * configurations will likely result in unfocused text.
 510      * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB},
 511      * for more information on when this hint is applied.
 512      *
 513      * @see #KEY_TEXT_ANTIALIASING
 514      * @since 1.6
 515      */
 516     public static final Object VALUE_TEXT_ANTIALIAS_LCD_VBGR =
 517          SunHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR;
 518 
 519 
 520     /**
 521      * LCD text contrast rendering hint key.
 522      * The value is an <code>Integer</code> object which is used as a text
 523      * contrast adjustment when used in conjunction with an LCD text
 524      * anti-aliasing hint such as
 525      * {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}.
 526      * <ul>
 527      * <li>Values should be a positive integer in the range 100 to 250.
 528      * <li>A lower value (eg 100) corresponds to higher contrast text when
 529      * displaying dark text on a light background.
 530      * <li>A higher value (eg 200) corresponds to lower contrast text when
 531      * displaying dark text on a light background.
 532      * <li>A typical useful value is in the narrow range 140-180.
 533      * <li>If no value is specified, a system or implementation default value
 534      * will be applied.
 535      * </ul>
 536      * The default value can be expected to be adequate for most purposes,
 537      * so clients should rarely need to specify a value for this hint unless
 538      * they have concrete information as to an appropriate value.
 539      * A higher value does not mean a higher contrast, in fact the opposite
 540      * is true.
 541      * The correction is applied in a similar manner to a gamma adjustment
 542      * for non-linear perceptual luminance response of display systems, but
 543      * does not indicate a full correction for this.
 544      *
 545      * @see #KEY_TEXT_ANTIALIASING
 546      * @since 1.6
 547      */
 548     public static final Key KEY_TEXT_LCD_CONTRAST =
 549         SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST;
 550 
 551     /**
 552      * Font fractional metrics hint key.
 553      * The {@code FRACTIONALMETRICS} hint controls whether the positioning
 554      * of individual character glyphs takes into account the sub-pixel
 555      * accuracy of the scaled character advances of the font or whether
 556      * such advance vectors are rounded to an integer number of whole
 557      * device pixels.
 558      * This hint only recommends how much accuracy should be used to
 559      * position the glyphs and does not specify or recommend whether or
 560      * not the actual rasterization or pixel bounds of the glyph should
 561      * be modified to match.
 562      * <p>
 563      * Rendering text to a low resolution device like a screen will
 564      * necessarily involve a number of rounding operations as the
 565      * high quality and very precise definition of the shape and
 566      * metrics of the character glyphs must be matched to discrete
 567      * device pixels.
 568      * Ideally the positioning of glyphs during text layout would be
 569      * calculated by scaling the design metrics in the font according
 570      * to the point size, but then the scaled advance width will not
 571      * necessarily be an integer number of pixels.
 572      * If the glyphs are positioned with sub-pixel accuracy according
 573      * to these scaled design metrics then the rasterization would
 574      * ideally need to be adjusted for each possible sub-pixel origin.
 575      * <p>
 576      * Unfortunately, scaling each glyph customized to its exact
 577      * subpixel origin during text layout would be prohibitively
 578      * expensive so a simplified system based on integer device
 579      * positions is typically used to lay out the text.
 580      * The rasterization of the glyph and the scaled advance width
 581      * are both adjusted together to yield text that looks good at
 582      * device resolution and has consistent integer pixel distances
 583      * between glyphs that help the glyphs look uniformly and
 584      * consistently spaced and readable.
 585      * <p>
 586      * This process of rounding advance widths for rasterized glyphs
 587      * to integer distances means that the character density and the
 588      * overall length of a string of text will be different from the
 589      * theoretical design measurements due to the accumulation of
 590      * a series of small differences in the adjusted widths of
 591      * each glyph.
 592      * The specific differences will be different for each glyph,
 593      * some being wider and some being narrower than their theoretical
 594      * design measurements.
 595      * Thus the overall difference in character density and length
 596      * will vary by a number of factors including the font, the
 597      * specific device resolution being targeted, and the glyphs
 598      * chosen to represent the string being rendered.
 599      * As a result, rendering the same string at multiple device
 600      * resolutions can yield widely varying metrics for whole strings.
 601      * <p>
 602      * When {@code FRACTIONALMETRICS} are enabled, the true font design
 603      * metrics are scaled by the point size and used for layout with
 604      * sub-pixel accuracy.
 605      * The average density of glyphs and total length of a long
 606      * string of characters will therefore more closely match the
 607      * theoretical design of the font, but readability may be affected
 608      * since individual pairs of characters may not always appear to
 609      * be consistent distances apart depending on how the sub-pixel
 610      * accumulation of the glyph origins meshes with the device pixel
 611      * grid.
 612      * Enabling this hint may be desirable when text layout is being
 613      * performed that must be consistent across a wide variety of
 614      * output resolutions.
 615      * Specifically, this hint may be desirable in situations where
 616      * the layout of text is being previewed on a low resolution
 617      * device like a screen for output that will eventually be
 618      * rendered on a high resolution printer or typesetting device.
 619      * <p>
 620      * When disabled, the scaled design metrics are rounded or adjusted
 621      * to integer distances for layout.
 622      * The distances between any specific pair of glyphs will be more
 623      * uniform on the device, but the density and total length of long
 624      * strings may no longer match the theoretical intentions of the
 625      * font designer.
 626      * Disabling this hint will typically produce more readable results
 627      * on low resolution devices like computer monitors.
 628      * <p>
 629      * The allowable values for this key are
 630      * <ul>
 631      * <li>{@link #VALUE_FRACTIONALMETRICS_OFF}
 632      * <li>{@link #VALUE_FRACTIONALMETRICS_ON}
 633      * <li>{@link #VALUE_FRACTIONALMETRICS_DEFAULT}
 634      * </ul>
 635      */
 636     public static final Key KEY_FRACTIONALMETRICS =
 637          SunHints.KEY_FRACTIONALMETRICS;
 638 
 639     /**
 640      * Font fractional metrics hint value -- character glyphs are
 641      * positioned with advance widths rounded to pixel boundaries.
 642      * @see #KEY_FRACTIONALMETRICS
 643      */
 644     public static final Object VALUE_FRACTIONALMETRICS_OFF =
 645          SunHints.VALUE_FRACTIONALMETRICS_OFF;
 646 
 647     /**
 648      * Font fractional metrics hint value -- character glyphs are
 649      * positioned with sub-pixel accuracy.
 650      * @see #KEY_FRACTIONALMETRICS
 651      */
 652     public static final Object VALUE_FRACTIONALMETRICS_ON =
 653          SunHints.VALUE_FRACTIONALMETRICS_ON;
 654 
 655     /**
 656      * Font fractional metrics hint value -- character glyphs are
 657      * positioned with accuracy chosen by the implementation.
 658      * @see #KEY_FRACTIONALMETRICS
 659      */
 660     public static final Object VALUE_FRACTIONALMETRICS_DEFAULT =
 661          SunHints.VALUE_FRACTIONALMETRICS_DEFAULT;
 662 
 663     /**
 664      * Interpolation hint key.
 665      * The {@code INTERPOLATION} hint controls how image pixels are
 666      * filtered or resampled during an image rendering operation.
 667      * <p>
 668      * Implicitly images are defined to provide color samples at
 669      * integer coordinate locations.
 670      * When images are rendered upright with no scaling onto a
 671      * destination, the choice of which image pixels map to which
 672      * device pixels is obvious and the samples at the integer
 673      * coordinate locations in the image are transferred to the
 674      * pixels at the corresponding integer locations on the device
 675      * pixel grid one for one.
 676      * When images are rendered in a scaled, rotated, or otherwise
 677      * transformed coordinate system, then the mapping of device
 678      * pixel coordinates back to the image can raise the question
 679      * of what color sample to use for the continuous coordinates
 680      * that lie between the integer locations of the provided image
 681      * samples.
 682      * Interpolation algorithms define functions which provide a
 683      * color sample for any continuous coordinate in an image based
 684      * on the color samples at the surrounding integer coordinates.
 685      * <p>
 686      * The allowable values for this hint are
 687      * <ul>
 688      * <li>{@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR}
 689      * <li>{@link #VALUE_INTERPOLATION_BILINEAR}
 690      * <li>{@link #VALUE_INTERPOLATION_BICUBIC}
 691      * </ul>
 692      */
 693     public static final Key KEY_INTERPOLATION =
 694          SunHints.KEY_INTERPOLATION;
 695 
 696     /**
 697      * Interpolation hint value -- the color sample of the nearest
 698      * neighboring integer coordinate sample in the image is used.
 699      * Conceptually the image is viewed as a grid of unit-sized
 700      * square regions of color centered around the center of each
 701      * image pixel.
 702      * <p>
 703      * As the image is scaled up, it will look correspondingly blocky.
 704      * As the image is scaled down, the colors for source pixels will
 705      * be either used unmodified, or skipped entirely in the output
 706      * representation.
 707      *
 708      * @see #KEY_INTERPOLATION
 709      */
 710     public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR =
 711          SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
 712 
 713     /**
 714      * Interpolation hint value -- the color samples of the 4 nearest
 715      * neighboring integer coordinate samples in the image are
 716      * interpolated linearly to produce a color sample.
 717      * Conceptually the image is viewed as a set of infinitely small
 718      * point color samples which have value only at the centers of
 719      * integer coordinate pixels and the space between those pixel
 720      * centers is filled with linear ramps of colors that connect
 721      * adjacent discrete samples in a straight line.
 722      * <p>
 723      * As the image is scaled up, there are no blocky edges between
 724      * the colors in the image as there are with
 725      * {@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR NEAREST_NEIGHBOR},
 726      * but the blending may show some subtle discontinuities along the
 727      * horizontal and vertical edges that line up with the samples
 728      * caused by a sudden change in the slope of the interpolation
 729      * from one side of a sample to the other.
 730      * As the image is scaled down, more image pixels have their
 731      * color samples represented in the resulting output since each
 732      * output pixel receives color information from up to 4 image
 733      * pixels.
 734      *
 735      * @see #KEY_INTERPOLATION
 736      */
 737     public static final Object VALUE_INTERPOLATION_BILINEAR =
 738          SunHints.VALUE_INTERPOLATION_BILINEAR;
 739 
 740     /**
 741      * Interpolation hint value -- the color samples of 9 nearby
 742      * integer coordinate samples in the image are interpolated using
 743      * a cubic function in both {@code X} and {@code Y} to produce
 744      * a color sample.
 745      * Conceptually the view of the image is very similar to the view
 746      * used in the {@link #VALUE_INTERPOLATION_BILINEAR BILINEAR}
 747      * algorithm except that the ramps of colors that connect between
 748      * the samples are curved and have better continuity of slope
 749      * as they cross over between sample boundaries.
 750      * <p>
 751      * As the image is scaled up, there are no blocky edges and the
 752      * interpolation should appear smoother and with better depictions
 753      * of any edges in the original image than with {@code BILINEAR}.
 754      * As the image is scaled down, even more of the original color
 755      * samples from the original image will have their color information
 756      * carried through and represented.
 757      *
 758      * @see #KEY_INTERPOLATION
 759      */
 760     public static final Object VALUE_INTERPOLATION_BICUBIC =
 761          SunHints.VALUE_INTERPOLATION_BICUBIC;
 762 
 763     /**
 764      * Alpha interpolation hint key.
 765      * The {@code ALPHA_INTERPOLATION} hint is a general hint that
 766      * provides a high level recommendation as to whether to bias
 767      * alpha blending algorithm choices more for speed or quality
 768      * when evaluating tradeoffs.
 769      * <p>
 770      * This hint could control the choice of alpha blending
 771      * calculations that sacrifice some precision to use fast
 772      * lookup tables or lower precision SIMD instructions.
 773      * This hint could also control whether or not the color
 774      * and alpha values are converted into a linear color space
 775      * during the calculations for a more linear visual effect
 776      * at the expense of additional per-pixel calculations.
 777      * <p>
 778      * The allowable values for this hint are
 779      * <ul>
 780      * <li>{@link #VALUE_ALPHA_INTERPOLATION_SPEED}
 781      * <li>{@link #VALUE_ALPHA_INTERPOLATION_QUALITY}
 782      * <li>{@link #VALUE_ALPHA_INTERPOLATION_DEFAULT}
 783      * </ul>
 784      */
 785     public static final Key KEY_ALPHA_INTERPOLATION =
 786          SunHints.KEY_ALPHA_INTERPOLATION;
 787 
 788     /**
 789      * Alpha interpolation hint value -- alpha blending algorithms
 790      * are chosen with a preference for calculation speed.
 791      * @see #KEY_ALPHA_INTERPOLATION
 792      */
 793     public static final Object VALUE_ALPHA_INTERPOLATION_SPEED =
 794          SunHints.VALUE_ALPHA_INTERPOLATION_SPEED;
 795 
 796     /**
 797      * Alpha interpolation hint value -- alpha blending algorithms
 798      * are chosen with a preference for precision and visual quality.
 799      * @see #KEY_ALPHA_INTERPOLATION
 800      */
 801     public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY =
 802          SunHints.VALUE_ALPHA_INTERPOLATION_QUALITY;
 803 
 804     /**
 805      * Alpha interpolation hint value -- alpha blending algorithms
 806      * are chosen by the implementation for a good tradeoff of
 807      * performance vs. quality.
 808      * @see #KEY_ALPHA_INTERPOLATION
 809      */
 810     public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT =
 811          SunHints.VALUE_ALPHA_INTERPOLATION_DEFAULT;
 812 
 813     /**
 814      * Color rendering hint key.
 815      * The {@code COLOR_RENDERING} hint controls the accuracy of
 816      * approximation and conversion when storing colors into a
 817      * destination image or surface.
 818      * <p>
 819      * When a rendering or image manipulation operation produces
 820      * a color value that must be stored into a destination, it
 821      * must first convert that color into a form suitable for
 822      * storing into the destination image or surface.
 823      * Minimally, the color components must be converted to bit
 824      * representations and ordered in the correct order or an
 825      * index into a color lookup table must be chosen before
 826      * the data can be stored into the destination memory.
 827      * Without this minimal conversion, the data in the destination
 828      * would likely represent random, incorrect or possibly even
 829      * unsupported values.
 830      * Algorithms to quickly convert the results of rendering
 831      * operations into the color format of most common destinations
 832      * are well known and fairly optimal to execute.
 833      * <p>
 834      * Simply performing the most basic color format conversion to
 835      * store colors into a destination can potentially ignore a
 836      * difference in the calibration of the
 837      * {@link java.awt.color.ColorSpace}
 838      * of the source and destination or other factors such as the
 839      * linearity of the gamma correction.
 840      * Unless the source and destination {@code ColorSpace} are
 841      * identical, to correctly perform a rendering operation with
 842      * the most care taken for the accuracy of the colors being
 843      * represented, the source colors should be converted to a
 844      * device independent {@code ColorSpace} and the results then
 845      * converted back to the destination {@code ColorSpace}.
 846      * Furthermore, if calculations such as the blending of multiple
 847      * source colors are to be performed during the rendering
 848      * operation, greater visual clarity can be achieved if the
 849      * intermediate device independent {@code ColorSpace} is
 850      * chosen to have a linear relationship between the values
 851      * being calculated and the perception of the human eye to
 852      * the response curves of the output device.
 853      * <p>
 854      * The allowable values for this hint are
 855      * <ul>
 856      * <li>{@link #VALUE_COLOR_RENDER_SPEED}
 857      * <li>{@link #VALUE_COLOR_RENDER_QUALITY}
 858      * <li>{@link #VALUE_COLOR_RENDER_DEFAULT}
 859      * </ul>
 860      */
 861     public static final Key KEY_COLOR_RENDERING =
 862          SunHints.KEY_COLOR_RENDERING;
 863 
 864     /**
 865      * Color rendering hint value -- perform the fastest color
 866      * conversion to the format of the output device.
 867      * @see #KEY_COLOR_RENDERING
 868      */
 869     public static final Object VALUE_COLOR_RENDER_SPEED =
 870          SunHints.VALUE_COLOR_RENDER_SPEED;
 871 
 872     /**
 873      * Color rendering hint value -- perform the color conversion
 874      * calculations with the highest accuracy and visual quality.
 875      * @see #KEY_COLOR_RENDERING
 876      */
 877     public static final Object VALUE_COLOR_RENDER_QUALITY =
 878          SunHints.VALUE_COLOR_RENDER_QUALITY;
 879 
 880     /**
 881      * Color rendering hint value -- perform color conversion
 882      * calculations as chosen by the implementation to represent
 883      * the best available tradeoff between performance and
 884      * accuracy.
 885      * @see #KEY_COLOR_RENDERING
 886      */
 887     public static final Object VALUE_COLOR_RENDER_DEFAULT =
 888          SunHints.VALUE_COLOR_RENDER_DEFAULT;
 889 
 890     /**
 891      * Stroke normalization control hint key.
 892      * The {@code STROKE_CONTROL} hint controls whether a rendering
 893      * implementation should or is allowed to modify the geometry
 894      * of rendered shapes for various purposes.
 895      * <p>
 896      * Some implementations may be able to use an optimized platform
 897      * rendering library which may be faster than traditional software
 898      * rendering algorithms on a given platform, but which may also
 899      * not support floating point coordinates.
 900      * Some implementations may also have sophisticated algorithms
 901      * which perturb the coordinates of a path so that wide lines
 902      * appear more uniform in width and spacing.
 903      * <p>
 904      * If an implementation performs any type of modification or
 905      * "normalization" of a path, it should never move the coordinates
 906      * by more than half a pixel in any direction.
 907      * <p>
 908      * The allowable values for this hint are
 909      * <ul>
 910      * <li>{@link #VALUE_STROKE_NORMALIZE}
 911      * <li>{@link #VALUE_STROKE_PURE}
 912      * <li>{@link #VALUE_STROKE_DEFAULT}
 913      * </ul>
 914      * @since 1.3
 915      */
 916     public static final Key KEY_STROKE_CONTROL =
 917         SunHints.KEY_STROKE_CONTROL;
 918 
 919     /**
 920      * Stroke normalization control hint value -- geometry may be
 921      * modified or left pure depending on the tradeoffs in a given
 922      * implementation.
 923      * Typically this setting allows an implementation to use a fast
 924      * integer coordinate based platform rendering library, but does
 925      * not specifically request normalization for uniformity or
 926      * aesthetics.
 927      *
 928      * @see #KEY_STROKE_CONTROL
 929      * @since 1.3
 930      */
 931     public static final Object VALUE_STROKE_DEFAULT =
 932         SunHints.VALUE_STROKE_DEFAULT;
 933 
 934     /**
 935      * Stroke normalization control hint value -- geometry should
 936      * be normalized to improve uniformity or spacing of lines and
 937      * overall aesthetics.
 938      * Note that different normalization algorithms may be more
 939      * successful than others for given input paths.
 940      *
 941      * @see #KEY_STROKE_CONTROL
 942      * @since 1.3
 943      */
 944     public static final Object VALUE_STROKE_NORMALIZE =
 945         SunHints.VALUE_STROKE_NORMALIZE;
 946 
 947     /**
 948      * Stroke normalization control hint value -- geometry should
 949      * be left unmodified and rendered with sub-pixel accuracy.
 950      *
 951      * @see #KEY_STROKE_CONTROL
 952      * @since 1.3
 953      */
 954     public static final Object VALUE_STROKE_PURE =
 955         SunHints.VALUE_STROKE_PURE;
 956 
 957     /**
 958      * Image resolution variant hint key.
 959      * The {@code RESOLUTION_VARIANT} hint controls which image resolution
 960      * variant should be chosen for image drawing.
 961      *
 962      * <ul>
 963      * <li>{@link #VALUE_RESOLUTION_VARIANT_DEFAULT}
 964      * <li>{@link #VALUE_RESOLUTION_VARIANT_BASE}
 965      * <li>{@link #VALUE_RESOLUTION_VARIANT_SIZE_FIT}
 966      * <li>{@link #VALUE_RESOLUTION_VARIANT_DPI_FIT}
 967      * </ul>
 968      * @since 1.9
 969      */
 970     public static final Key KEY_RESOLUTION_VARIANT =
 971         SunHints.KEY_RESOLUTION_VARIANT;
 972 
 973     /**
 974      * Image resolution variant hint value -- an image resolution variant is
 975      * chosen based on a default heuristic which may depend on the policies
 976      * of the platform
 977      *
 978      * @see #KEY_RESOLUTION_VARIANT
 979      * @since 1.9
 980      */
 981     public static final Object VALUE_RESOLUTION_VARIANT_DEFAULT =
 982         SunHints.VALUE_RESOLUTION_VARIANT_DEFAULT;
 983 
 984     /**
 985      * Image resolution variant hint value -- the standard resolution of an image
 986      * is always used.
 987      *
 988      * @see #KEY_RESOLUTION_VARIANT
 989      * @since 1.9
 990      */
 991     public static final Object VALUE_RESOLUTION_VARIANT_BASE =
 992         SunHints.VALUE_RESOLUTION_VARIANT_BASE;
 993 
 994     /**
 995      * Image resolution variant hint value -- an image resolution variant is
 996      * chosen based on the DPI of the screen and the transform in the Graphics2D
 997      * context.
 998      *
 999      * @see #KEY_RESOLUTION_VARIANT
1000      * @since 1.9
1001      */
1002     public static final Object VALUE_RESOLUTION_VARIANT_SIZE_FIT =
1003         SunHints.VALUE_RESOLUTION_VARIANT_SIZE_FIT;
1004 
1005     /**
1006      * Image resolution variant hint value -- an image resolution variant is
1007      * chosen based only on the DPI of the screen.
1008      *
1009      * @see #KEY_RESOLUTION_VARIANT
1010      * @since 1.9
1011      */
1012     public static final Object VALUE_RESOLUTION_VARIANT_DPI_FIT =
1013         SunHints.VALUE_RESOLUTION_VARIANT_DPI_FIT;
1014 
1015     /**
1016      * Constructs a new object with keys and values initialized
1017      * from the specified Map object which may be null.
1018      * @param init a map of key/value pairs to initialize the hints
1019      *          or null if the object should be empty
1020      */
1021     public RenderingHints(Map<Key,?> init) {
1022         if (init != null) {
1023             hintmap.putAll(init);
1024         }
1025     }
1026 
1027     /**
1028      * Constructs a new object with the specified key/value pair.
1029      * @param key the key of the particular hint property
1030      * @param value the value of the hint property specified with
1031      * <code>key</code>
1032      */
1033     public RenderingHints(Key key, Object value) {
1034         hintmap.put(key, value);
1035     }
1036 
1037     /**
1038      * Returns the number of key-value mappings in this
1039      * <code>RenderingHints</code>.
1040      *
1041      * @return the number of key-value mappings in this
1042      * <code>RenderingHints</code>.
1043      */
1044     public int size() {
1045         return hintmap.size();
1046     }
1047 
1048     /**
1049      * Returns <code>true</code> if this
1050      * <code>RenderingHints</code> contains no key-value mappings.
1051      *
1052      * @return <code>true</code> if this
1053      * <code>RenderingHints</code> contains no key-value mappings.
1054      */
1055     public boolean isEmpty() {
1056         return hintmap.isEmpty();
1057     }
1058 
1059     /**
1060      * Returns {@code true} if this {@code RenderingHints}
1061      *  contains a mapping for the specified key.
1062      *
1063      * @param key key whose presence in this
1064      * {@code RenderingHints} is to be tested.
1065      * @return {@code true} if this {@code RenderingHints}
1066      *          contains a mapping for the specified key.
1067      * @exception ClassCastException if the key can not
1068      *            be cast to {@code RenderingHints.Key}
1069      */
1070     public boolean containsKey(Object key) {
1071         return hintmap.containsKey((Key) key);
1072     }
1073 
1074     /**
1075      * Returns true if this RenderingHints maps one or more keys to the
1076      * specified value.
1077      * More formally, returns <code>true</code> if and only
1078      * if this <code>RenderingHints</code>
1079      * contains at least one mapping to a value <code>v</code> such that
1080      * <pre>
1081      * (value==null ? v==null : value.equals(v))
1082      * </pre>.
1083      * This operation will probably require time linear in the
1084      * <code>RenderingHints</code> size for most implementations
1085      * of <code>RenderingHints</code>.
1086      *
1087      * @param value value whose presence in this
1088      *          <code>RenderingHints</code> is to be tested.
1089      * @return <code>true</code> if this <code>RenderingHints</code>
1090      *           maps one or more keys to the specified value.
1091      */
1092     public boolean containsValue(Object value) {
1093         return hintmap.containsValue(value);
1094     }
1095 
1096     /**
1097      * Returns the value to which the specified key is mapped.
1098      * @param   key   a rendering hint key
1099      * @return  the value to which the key is mapped in this object or
1100      *          {@code null} if the key is not mapped to any value in
1101      *          this object.
1102      * @exception ClassCastException if the key can not
1103      *            be cast to {@code RenderingHints.Key}
1104      * @see     #put(Object, Object)
1105      */
1106     public Object get(Object key) {
1107         return hintmap.get((Key) key);
1108     }
1109 
1110     /**
1111      * Maps the specified {@code key} to the specified
1112      * {@code value} in this {@code RenderingHints} object.
1113      * Neither the key nor the value can be {@code null}.
1114      * The value can be retrieved by calling the {@code get} method
1115      * with a key that is equal to the original key.
1116      * @param      key     the rendering hint key.
1117      * @param      value   the rendering hint value.
1118      * @return     the previous value of the specified key in this object
1119      *             or {@code null} if it did not have one.
1120      * @exception NullPointerException if the key is
1121      *            {@code null}.
1122      * @exception ClassCastException if the key can not
1123      *            be cast to {@code RenderingHints.Key}
1124      * @exception IllegalArgumentException if the
1125      *            {@link Key#isCompatibleValue(java.lang.Object)
1126      *                   Key.isCompatibleValue()}
1127      *            method of the specified key returns false for the
1128      *            specified value
1129      * @see     #get(Object)
1130      */
1131     public Object put(Object key, Object value) {
1132         if (!((Key) key).isCompatibleValue(value)) {
1133             throw new IllegalArgumentException(value+
1134                                                " incompatible with "+
1135                                                key);
1136         }
1137         return hintmap.put((Key) key, value);
1138     }
1139 
1140     /**
1141      * Adds all of the keys and corresponding values from the specified
1142      * <code>RenderingHints</code> object to this
1143      * <code>RenderingHints</code> object. Keys that are present in
1144      * this <code>RenderingHints</code> object, but not in the specified
1145      * <code>RenderingHints</code> object are not affected.
1146      * @param hints the set of key/value pairs to be added to this
1147      * <code>RenderingHints</code> object
1148      */
1149     public void add(RenderingHints hints) {
1150         hintmap.putAll(hints.hintmap);
1151     }
1152 
1153     /**
1154      * Clears this <code>RenderingHints</code> object of all key/value
1155      * pairs.
1156      */
1157     public void clear() {
1158         hintmap.clear();
1159     }
1160 
1161     /**
1162      * Removes the key and its corresponding value from this
1163      * {@code RenderingHints} object. This method does nothing if the
1164      * key is not in this {@code RenderingHints} object.
1165      * @param   key   the rendering hints key that needs to be removed
1166      * @exception ClassCastException if the key can not
1167      *            be cast to {@code RenderingHints.Key}
1168      * @return  the value to which the key had previously been mapped in this
1169      *          {@code RenderingHints} object, or {@code null}
1170      *          if the key did not have a mapping.
1171      */
1172     public Object remove(Object key) {
1173         return hintmap.remove((Key) key);
1174     }
1175 
1176     /**
1177      * Copies all of the mappings from the specified {@code Map}
1178      * to this {@code RenderingHints}.  These mappings replace
1179      * any mappings that this {@code RenderingHints} had for any
1180      * of the keys currently in the specified {@code Map}.
1181      * @param m the specified {@code Map}
1182      * @exception ClassCastException class of a key or value
1183      *          in the specified {@code Map} prevents it from being
1184      *          stored in this {@code RenderingHints}.
1185      * @exception IllegalArgumentException some aspect
1186      *          of a key or value in the specified {@code Map}
1187      *           prevents it from being stored in
1188      *            this {@code RenderingHints}.
1189      */
1190     public void putAll(Map<?,?> m) {
1191         // ## javac bug?
1192         //if (m instanceof RenderingHints) {
1193         if (RenderingHints.class.isInstance(m)) {
1194             //hintmap.putAll(((RenderingHints) m).hintmap);
1195             for (Map.Entry<?,?> entry : m.entrySet())
1196                 hintmap.put(entry.getKey(), entry.getValue());
1197         } else {
1198             // Funnel each key/value pair through our protected put method
1199             for (Map.Entry<?,?> entry : m.entrySet())
1200                 put(entry.getKey(), entry.getValue());
1201         }
1202     }
1203 
1204     /**
1205      * Returns a <code>Set</code> view of the Keys contained in this
1206      * <code>RenderingHints</code>.  The Set is backed by the
1207      * <code>RenderingHints</code>, so changes to the
1208      * <code>RenderingHints</code> are reflected in the <code>Set</code>,
1209      * and vice-versa.  If the <code>RenderingHints</code> is modified
1210      * while an iteration over the <code>Set</code> is in progress,
1211      * the results of the iteration are undefined.  The <code>Set</code>
1212      * supports element removal, which removes the corresponding
1213      * mapping from the <code>RenderingHints</code>, via the
1214      * <code>Iterator.remove</code>, <code>Set.remove</code>,
1215      * <code>removeAll</code> <code>retainAll</code>, and
1216      * <code>clear</code> operations.  It does not support
1217      * the <code>add</code> or <code>addAll</code> operations.
1218      *
1219      * @return a <code>Set</code> view of the keys contained
1220      * in this <code>RenderingHints</code>.
1221      */
1222     public Set<Object> keySet() {
1223         return hintmap.keySet();
1224     }
1225 
1226     /**
1227      * Returns a <code>Collection</code> view of the values
1228      * contained in this <code>RenderingHints</code>.
1229      * The <code>Collection</code> is backed by the
1230      * <code>RenderingHints</code>, so changes to
1231      * the <code>RenderingHints</code> are reflected in
1232      * the <code>Collection</code>, and vice-versa.
1233      * If the <code>RenderingHints</code> is modified while
1234      * an iteration over the <code>Collection</code> is
1235      * in progress, the results of the iteration are undefined.
1236      * The <code>Collection</code> supports element removal,
1237      * which removes the corresponding mapping from the
1238      * <code>RenderingHints</code>, via the
1239      * <code>Iterator.remove</code>,
1240      * <code>Collection.remove</code>, <code>removeAll</code>,
1241      * <code>retainAll</code> and <code>clear</code> operations.
1242      * It does not support the <code>add</code> or
1243      * <code>addAll</code> operations.
1244      *
1245      * @return a <code>Collection</code> view of the values
1246      *          contained in this <code>RenderingHints</code>.
1247      */
1248     public Collection<Object> values() {
1249         return hintmap.values();
1250     }
1251 
1252     /**
1253      * Returns a <code>Set</code> view of the mappings contained
1254      * in this <code>RenderingHints</code>.  Each element in the
1255      * returned <code>Set</code> is a <code>Map.Entry</code>.
1256      * The <code>Set</code> is backed by the <code>RenderingHints</code>,
1257      * so changes to the <code>RenderingHints</code> are reflected
1258      * in the <code>Set</code>, and vice-versa.  If the
1259      * <code>RenderingHints</code> is modified while
1260      * while an iteration over the <code>Set</code> is in progress,
1261      * the results of the iteration are undefined.
1262      * <p>
1263      * The entrySet returned from a <code>RenderingHints</code> object
1264      * is not modifiable.
1265      *
1266      * @return a <code>Set</code> view of the mappings contained in
1267      * this <code>RenderingHints</code>.
1268      */
1269     public Set<Map.Entry<Object,Object>> entrySet() {
1270         return Collections.unmodifiableMap(hintmap).entrySet();
1271     }
1272 
1273     /**
1274      * Compares the specified <code>Object</code> with this
1275      * <code>RenderingHints</code> for equality.
1276      * Returns <code>true</code> if the specified object is also a
1277      * <code>Map</code> and the two <code>Map</code> objects represent
1278      * the same mappings.  More formally, two <code>Map</code> objects
1279      * <code>t1</code> and <code>t2</code> represent the same mappings
1280      * if <code>t1.keySet().equals(t2.keySet())</code> and for every
1281      * key <code>k</code> in <code>t1.keySet()</code>,
1282      * <pre>
1283      * (t1.get(k)==null ? t2.get(k)==null : t1.get(k).equals(t2.get(k)))
1284      * </pre>.
1285      * This ensures that the <code>equals</code> method works properly across
1286      * different implementations of the <code>Map</code> interface.
1287      *
1288      * @param o <code>Object</code> to be compared for equality with
1289      * this <code>RenderingHints</code>.
1290      * @return <code>true</code> if the specified <code>Object</code>
1291      * is equal to this <code>RenderingHints</code>.
1292      */
1293     public boolean equals(Object o) {
1294         if (o instanceof RenderingHints) {
1295             return hintmap.equals(((RenderingHints) o).hintmap);
1296         } else if (o instanceof Map) {
1297             return hintmap.equals(o);
1298         }
1299         return false;
1300     }
1301 
1302     /**
1303      * Returns the hash code value for this <code>RenderingHints</code>.
1304      * The hash code of a <code>RenderingHints</code> is defined to be
1305      * the sum of the hashCodes of each <code>Entry</code> in the
1306      * <code>RenderingHints</code> object's entrySet view.  This ensures that
1307      * <code>t1.equals(t2)</code> implies that
1308      * <code>t1.hashCode()==t2.hashCode()</code> for any two <code>Map</code>
1309      * objects <code>t1</code> and <code>t2</code>, as required by the general
1310      * contract of <code>Object.hashCode</code>.
1311      *
1312      * @return the hash code value for this <code>RenderingHints</code>.
1313      * @see java.util.Map.Entry#hashCode()
1314      * @see Object#hashCode()
1315      * @see Object#equals(Object)
1316      * @see #equals(Object)
1317      */
1318     public int hashCode() {
1319         return hintmap.hashCode();
1320     }
1321 
1322     /**
1323      * Creates a clone of this <code>RenderingHints</code> object
1324      * that has the same contents as this <code>RenderingHints</code>
1325      * object.
1326      * @return a clone of this instance.
1327      */
1328     @SuppressWarnings("unchecked")
1329     public Object clone() {
1330         RenderingHints rh;
1331         try {
1332             rh = (RenderingHints) super.clone();
1333             if (hintmap != null) {
1334                 rh.hintmap = (HashMap<Object,Object>) hintmap.clone();
1335             }
1336         } catch (CloneNotSupportedException e) {
1337             // this shouldn't happen, since we are Cloneable
1338             throw new InternalError(e);
1339         }
1340 
1341         return rh;
1342     }
1343 
1344     /**
1345      * Returns a rather long string representation of the hashmap
1346      * which contains the mappings of keys to values for this
1347      * <code>RenderingHints</code> object.
1348      * @return  a string representation of this object.
1349      */
1350     public String toString() {
1351         if (hintmap == null) {
1352             return getClass().getName() + "@" +
1353                 Integer.toHexString(hashCode()) +
1354                 " (0 hints)";
1355         }
1356 
1357         return hintmap.toString();
1358     }
1359 }