View Javadoc
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 transfered 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      * Constructs a new object with keys and values initialized
959      * from the specified Map object which may be null.
960      * @param init a map of key/value pairs to initialize the hints
961      *          or null if the object should be empty
962      */
963     public RenderingHints(Map<Key,?> init) {
964         if (init != null) {
965             hintmap.putAll(init);
966         }
967     }
968 
969     /**
970      * Constructs a new object with the specified key/value pair.
971      * @param key the key of the particular hint property
972      * @param value the value of the hint property specified with
973      * <code>key</code>
974      */
975     public RenderingHints(Key key, Object value) {
976         hintmap.put(key, value);
977     }
978 
979     /**
980      * Returns the number of key-value mappings in this
981      * <code>RenderingHints</code>.
982      *
983      * @return the number of key-value mappings in this
984      * <code>RenderingHints</code>.
985      */
986     public int size() {
987         return hintmap.size();
988     }
989 
990     /**
991      * Returns <code>true</code> if this
992      * <code>RenderingHints</code> contains no key-value mappings.
993      *
994      * @return <code>true</code> if this
995      * <code>RenderingHints</code> contains no key-value mappings.
996      */
997     public boolean isEmpty() {
998         return hintmap.isEmpty();
999     }
1000 
1001     /**
1002      * Returns {@code true} if this {@code RenderingHints}
1003      *  contains a mapping for the specified key.
1004      *
1005      * @param key key whose presence in this
1006      * {@code RenderingHints} is to be tested.
1007      * @return {@code true} if this {@code RenderingHints}
1008      *          contains a mapping for the specified key.
1009      * @exception ClassCastException if the key can not
1010      *            be cast to {@code RenderingHints.Key}
1011      */
1012     public boolean containsKey(Object key) {
1013         return hintmap.containsKey((Key) key);
1014     }
1015 
1016     /**
1017      * Returns true if this RenderingHints maps one or more keys to the
1018      * specified value.
1019      * More formally, returns <code>true</code> if and only
1020      * if this <code>RenderingHints</code>
1021      * contains at least one mapping to a value <code>v</code> such that
1022      * <pre>
1023      * (value==null ? v==null : value.equals(v))
1024      * </pre>.
1025      * This operation will probably require time linear in the
1026      * <code>RenderingHints</code> size for most implementations
1027      * of <code>RenderingHints</code>.
1028      *
1029      * @param value value whose presence in this
1030      *          <code>RenderingHints</code> is to be tested.
1031      * @return <code>true</code> if this <code>RenderingHints</code>
1032      *           maps one or more keys to the specified value.
1033      */
1034     public boolean containsValue(Object value) {
1035         return hintmap.containsValue(value);
1036     }
1037 
1038     /**
1039      * Returns the value to which the specified key is mapped.
1040      * @param   key   a rendering hint key
1041      * @return  the value to which the key is mapped in this object or
1042      *          {@code null} if the key is not mapped to any value in
1043      *          this object.
1044      * @exception ClassCastException if the key can not
1045      *            be cast to {@code RenderingHints.Key}
1046      * @see     #put(Object, Object)
1047      */
1048     public Object get(Object key) {
1049         return hintmap.get((Key) key);
1050     }
1051 
1052     /**
1053      * Maps the specified {@code key} to the specified
1054      * {@code value} in this {@code RenderingHints} object.
1055      * Neither the key nor the value can be {@code null}.
1056      * The value can be retrieved by calling the {@code get} method
1057      * with a key that is equal to the original key.
1058      * @param      key     the rendering hint key.
1059      * @param      value   the rendering hint value.
1060      * @return     the previous value of the specified key in this object
1061      *             or {@code null} if it did not have one.
1062      * @exception NullPointerException if the key is
1063      *            {@code null}.
1064      * @exception ClassCastException if the key can not
1065      *            be cast to {@code RenderingHints.Key}
1066      * @exception IllegalArgumentException if the
1067      *            {@link Key#isCompatibleValue(java.lang.Object)
1068      *                   Key.isCompatibleValue()}
1069      *            method of the specified key returns false for the
1070      *            specified value
1071      * @see     #get(Object)
1072      */
1073     public Object put(Object key, Object value) {
1074         if (!((Key) key).isCompatibleValue(value)) {
1075             throw new IllegalArgumentException(value+
1076                                                " incompatible with "+
1077                                                key);
1078         }
1079         return hintmap.put((Key) key, value);
1080     }
1081 
1082     /**
1083      * Adds all of the keys and corresponding values from the specified
1084      * <code>RenderingHints</code> object to this
1085      * <code>RenderingHints</code> object. Keys that are present in
1086      * this <code>RenderingHints</code> object, but not in the specified
1087      * <code>RenderingHints</code> object are not affected.
1088      * @param hints the set of key/value pairs to be added to this
1089      * <code>RenderingHints</code> object
1090      */
1091     public void add(RenderingHints hints) {
1092         hintmap.putAll(hints.hintmap);
1093     }
1094 
1095     /**
1096      * Clears this <code>RenderingHints</code> object of all key/value
1097      * pairs.
1098      */
1099     public void clear() {
1100         hintmap.clear();
1101     }
1102 
1103     /**
1104      * Removes the key and its corresponding value from this
1105      * {@code RenderingHints} object. This method does nothing if the
1106      * key is not in this {@code RenderingHints} object.
1107      * @param   key   the rendering hints key that needs to be removed
1108      * @exception ClassCastException if the key can not
1109      *            be cast to {@code RenderingHints.Key}
1110      * @return  the value to which the key had previously been mapped in this
1111      *          {@code RenderingHints} object, or {@code null}
1112      *          if the key did not have a mapping.
1113      */
1114     public Object remove(Object key) {
1115         return hintmap.remove((Key) key);
1116     }
1117 
1118     /**
1119      * Copies all of the mappings from the specified {@code Map}
1120      * to this {@code RenderingHints}.  These mappings replace
1121      * any mappings that this {@code RenderingHints} had for any
1122      * of the keys currently in the specified {@code Map}.
1123      * @param m the specified {@code Map}
1124      * @exception ClassCastException class of a key or value
1125      *          in the specified {@code Map} prevents it from being
1126      *          stored in this {@code RenderingHints}.
1127      * @exception IllegalArgumentException some aspect
1128      *          of a key or value in the specified {@code Map}
1129      *           prevents it from being stored in
1130      *            this {@code RenderingHints}.
1131      */
1132     public void putAll(Map<?,?> m) {
1133         // ## javac bug?
1134         //if (m instanceof RenderingHints) {
1135         if (RenderingHints.class.isInstance(m)) {
1136             //hintmap.putAll(((RenderingHints) m).hintmap);
1137             for (Map.Entry<?,?> entry : m.entrySet())
1138                 hintmap.put(entry.getKey(), entry.getValue());
1139         } else {
1140             // Funnel each key/value pair through our protected put method
1141             for (Map.Entry<?,?> entry : m.entrySet())
1142                 put(entry.getKey(), entry.getValue());
1143         }
1144     }
1145 
1146     /**
1147      * Returns a <code>Set</code> view of the Keys contained in this
1148      * <code>RenderingHints</code>.  The Set is backed by the
1149      * <code>RenderingHints</code>, so changes to the
1150      * <code>RenderingHints</code> are reflected in the <code>Set</code>,
1151      * and vice-versa.  If the <code>RenderingHints</code> is modified
1152      * while an iteration over the <code>Set</code> is in progress,
1153      * the results of the iteration are undefined.  The <code>Set</code>
1154      * supports element removal, which removes the corresponding
1155      * mapping from the <code>RenderingHints</code>, via the
1156      * <code>Iterator.remove</code>, <code>Set.remove</code>,
1157      * <code>removeAll</code> <code>retainAll</code>, and
1158      * <code>clear</code> operations.  It does not support
1159      * the <code>add</code> or <code>addAll</code> operations.
1160      *
1161      * @return a <code>Set</code> view of the keys contained
1162      * in this <code>RenderingHints</code>.
1163      */
1164     public Set<Object> keySet() {
1165         return hintmap.keySet();
1166     }
1167 
1168     /**
1169      * Returns a <code>Collection</code> view of the values
1170      * contained in this <code>RenderinHints</code>.
1171      * The <code>Collection</code> is backed by the
1172      * <code>RenderingHints</code>, so changes to
1173      * the <code>RenderingHints</code> are reflected in
1174      * the <code>Collection</code>, and vice-versa.
1175      * If the <code>RenderingHints</code> is modified while
1176      * an iteration over the <code>Collection</code> is
1177      * in progress, the results of the iteration are undefined.
1178      * The <code>Collection</code> supports element removal,
1179      * which removes the corresponding mapping from the
1180      * <code>RenderingHints</code>, via the
1181      * <code>Iterator.remove</code>,
1182      * <code>Collection.remove</code>, <code>removeAll</code>,
1183      * <code>retainAll</code> and <code>clear</code> operations.
1184      * It does not support the <code>add</code> or
1185      * <code>addAll</code> operations.
1186      *
1187      * @return a <code>Collection</code> view of the values
1188      *          contained in this <code>RenderingHints</code>.
1189      */
1190     public Collection<Object> values() {
1191         return hintmap.values();
1192     }
1193 
1194     /**
1195      * Returns a <code>Set</code> view of the mappings contained
1196      * in this <code>RenderingHints</code>.  Each element in the
1197      * returned <code>Set</code> is a <code>Map.Entry</code>.
1198      * The <code>Set</code> is backed by the <code>RenderingHints</code>,
1199      * so changes to the <code>RenderingHints</code> are reflected
1200      * in the <code>Set</code>, and vice-versa.  If the
1201      * <code>RenderingHints</code> is modified while
1202      * while an iteration over the <code>Set</code> is in progress,
1203      * the results of the iteration are undefined.
1204      * <p>
1205      * The entrySet returned from a <code>RenderingHints</code> object
1206      * is not modifiable.
1207      *
1208      * @return a <code>Set</code> view of the mappings contained in
1209      * this <code>RenderingHints</code>.
1210      */
1211     public Set<Map.Entry<Object,Object>> entrySet() {
1212         return Collections.unmodifiableMap(hintmap).entrySet();
1213     }
1214 
1215     /**
1216      * Compares the specified <code>Object</code> with this
1217      * <code>RenderingHints</code> for equality.
1218      * Returns <code>true</code> if the specified object is also a
1219      * <code>Map</code> and the two <code>Map</code> objects represent
1220      * the same mappings.  More formally, two <code>Map</code> objects
1221      * <code>t1</code> and <code>t2</code> represent the same mappings
1222      * if <code>t1.keySet().equals(t2.keySet())</code> and for every
1223      * key <code>k</code> in <code>t1.keySet()</code>,
1224      * <pre>
1225      * (t1.get(k)==null ? t2.get(k)==null : t1.get(k).equals(t2.get(k)))
1226      * </pre>.
1227      * This ensures that the <code>equals</code> method works properly across
1228      * different implementations of the <code>Map</code> interface.
1229      *
1230      * @param o <code>Object</code> to be compared for equality with
1231      * this <code>RenderingHints</code>.
1232      * @return <code>true</code> if the specified <code>Object</code>
1233      * is equal to this <code>RenderingHints</code>.
1234      */
1235     public boolean equals(Object o) {
1236         if (o instanceof RenderingHints) {
1237             return hintmap.equals(((RenderingHints) o).hintmap);
1238         } else if (o instanceof Map) {
1239             return hintmap.equals(o);
1240         }
1241         return false;
1242     }
1243 
1244     /**
1245      * Returns the hash code value for this <code>RenderingHints</code>.
1246      * The hash code of a <code>RenderingHints</code> is defined to be
1247      * the sum of the hashCodes of each <code>Entry</code> in the
1248      * <code>RenderingHints</code> object's entrySet view.  This ensures that
1249      * <code>t1.equals(t2)</code> implies that
1250      * <code>t1.hashCode()==t2.hashCode()</code> for any two <code>Map</code>
1251      * objects <code>t1</code> and <code>t2</code>, as required by the general
1252      * contract of <code>Object.hashCode</code>.
1253      *
1254      * @return the hash code value for this <code>RenderingHints</code>.
1255      * @see java.util.Map.Entry#hashCode()
1256      * @see Object#hashCode()
1257      * @see Object#equals(Object)
1258      * @see #equals(Object)
1259      */
1260     public int hashCode() {
1261         return hintmap.hashCode();
1262     }
1263 
1264     /**
1265      * Creates a clone of this <code>RenderingHints</code> object
1266      * that has the same contents as this <code>RenderingHints</code>
1267      * object.
1268      * @return a clone of this instance.
1269      */
1270     @SuppressWarnings("unchecked")
1271     public Object clone() {
1272         RenderingHints rh;
1273         try {
1274             rh = (RenderingHints) super.clone();
1275             if (hintmap != null) {
1276                 rh.hintmap = (HashMap<Object,Object>) hintmap.clone();
1277             }
1278         } catch (CloneNotSupportedException e) {
1279             // this shouldn't happen, since we are Cloneable
1280             throw new InternalError(e);
1281         }
1282 
1283         return rh;
1284     }
1285 
1286     /**
1287      * Returns a rather long string representation of the hashmap
1288      * which contains the mappings of keys to values for this
1289      * <code>RenderingHints</code> object.
1290      * @return  a string representation of this object.
1291      */
1292     public String toString() {
1293         if (hintmap == null) {
1294             return getClass().getName() + "@" +
1295                 Integer.toHexString(hashCode()) +
1296                 " (0 hints)";
1297         }
1298 
1299         return hintmap.toString();
1300     }
1301 }