0001 /*
0002 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt;
0027
0028 import java.util.Map;
0029 import java.util.Set;
0030 import java.util.Collection;
0031 import java.util.Collections;
0032 import java.util.HashMap;
0033 import java.util.Iterator;
0034 import sun.awt.SunHints;
0035 import java.lang.ref.WeakReference;
0036
0037 /**
0038 * The {@code RenderingHints} class defines and manages collections of
0039 * keys and associated values which allow an application to provide input
0040 * into the choice of algorithms used by other classes which perform
0041 * rendering and image manipulation services.
0042 * The {@link java.awt.Graphics2D} class, and classes that implement
0043 * {@link java.awt.image.BufferedImageOp} and
0044 * {@link java.awt.image.RasterOp} all provide methods to get and
0045 * possibly to set individual or groups of {@code RenderingHints}
0046 * keys and their associated values.
0047 * When those implementations perform any rendering or image manipulation
0048 * operations they should examine the values of any {@code RenderingHints}
0049 * that were requested by the caller and tailor the algorithms used
0050 * accordingly and to the best of their ability.
0051 * <p>
0052 * Note that since these keys and values are <i>hints</i>, there is
0053 * no requirement that a given implementation supports all possible
0054 * choices indicated below or that it can respond to requests to
0055 * modify its choice of algorithm.
0056 * The values of the various hint keys may also interact such that
0057 * while all variants of a given key are supported in one situation,
0058 * the implementation may be more restricted when the values associated
0059 * with other keys are modified.
0060 * For example, some implementations may be able to provide several
0061 * types of dithering when the antialiasing hint is turned off, but
0062 * have little control over dithering when antialiasing is on.
0063 * The full set of supported keys and hints may also vary by destination
0064 * since runtimes may use different underlying modules to render to
0065 * the screen, or to {@link java.awt.image.BufferedImage} objects,
0066 * or while printing.
0067 * <p>
0068 * Implementations are free to ignore the hints completely, but should
0069 * try to use an implementation algorithm that is as close as possible
0070 * to the request.
0071 * If an implementation supports a given algorithm when any value is used
0072 * for an associated hint key, then minimally it must do so when the
0073 * value for that key is the exact value that specifies the algorithm.
0074 * <p>
0075 * The keys used to control the hints are all special values that
0076 * subclass the associated {@link RenderingHints.Key} class.
0077 * Many common hints are expressed below as static constants in this
0078 * class, but the list is not meant to be exhaustive.
0079 * Other hints may be created by other packages by defining new objects
0080 * which subclass the {@code Key} class and defining the associated values.
0081 */
0082 public class RenderingHints implements Map<Object, Object>, Cloneable {
0083 /**
0084 * Defines the base type of all keys used along with the
0085 * {@link RenderingHints} class to control various
0086 * algorithm choices in the rendering and imaging pipelines.
0087 * Instances of this class are immutable and unique which
0088 * means that tests for matches can be made using the
0089 * {@code ==} operator instead of the more expensive
0090 * {@code equals()} method.
0091 */
0092 public abstract static class Key {
0093 private static HashMap identitymap = new HashMap(17);
0094
0095 private String getIdentity() {
0096 // Note that the identity string is dependent on 3 variables:
0097 // - the name of the subclass of Key
0098 // - the identityHashCode of the subclass of Key
0099 // - the integer key of the Key
0100 // It is theoretically possible for 2 distinct keys to collide
0101 // along all 3 of those attributes in the context of multiple
0102 // class loaders, but that occurence will be extremely rare and
0103 // we account for that possibility below in the recordIdentity
0104 // method by slightly relaxing our uniqueness guarantees if we
0105 // end up in that situation.
0106 return getClass().getName()
0107 + "@"
0108 + Integer.toHexString(System
0109 .identityHashCode(getClass())) + ":"
0110 + Integer.toHexString(privatekey);
0111 }
0112
0113 private synchronized static void recordIdentity(Key k) {
0114 Object identity = k.getIdentity();
0115 Object otherref = identitymap.get(identity);
0116 if (otherref != null) {
0117 Key otherkey = (Key) ((WeakReference) otherref).get();
0118 if (otherkey != null
0119 && otherkey.getClass() == k.getClass()) {
0120 throw new IllegalArgumentException(identity
0121 + " already registered");
0122 }
0123 // Note that this system can fail in a mostly harmless
0124 // way. If we end up generating the same identity
0125 // String for 2 different classes (a very rare case)
0126 // then we correctly avoid throwing the exception above,
0127 // but we are about to drop through to a statement that
0128 // will replace the entry for the old Key subclass with
0129 // an entry for the new Key subclass. At that time the
0130 // old subclass will be vulnerable to someone generating
0131 // a duplicate Key instance for it. We could bail out
0132 // of the method here and let the old identity keep its
0133 // record in the map, but we are more likely to see a
0134 // duplicate key go by for the new class than the old
0135 // one since the new one is probably still in the
0136 // initialization stage. In either case, the probability
0137 // of loading 2 classes in the same VM with the same name
0138 // and identityHashCode should be nearly impossible.
0139 }
0140 // Note: Use a weak reference to avoid holding on to extra
0141 // objects and classes after they should be unloaded.
0142 identitymap.put(identity, new WeakReference(k));
0143 }
0144
0145 private int privatekey;
0146
0147 /**
0148 * Construct a key using the indicated private key. Each
0149 * subclass of Key maintains its own unique domain of integer
0150 * keys. No two objects with the same integer key and of the
0151 * same specific subclass can be constructed. An exception
0152 * will be thrown if an attempt is made to construct another
0153 * object of a given class with the same integer key as a
0154 * pre-existing instance of that subclass of Key.
0155 * @param privatekey the specified key
0156 */
0157 protected Key(int privatekey) {
0158 this .privatekey = privatekey;
0159 recordIdentity(this );
0160 }
0161
0162 /**
0163 * Returns true if the specified object is a valid value
0164 * for this Key.
0165 * @param val the <code>Object</code> to test for validity
0166 * @return <code>true</code> if <code>val</code> is valid;
0167 * <code>false</code> otherwise.
0168 */
0169 public abstract boolean isCompatibleValue(Object val);
0170
0171 /**
0172 * Returns the private integer key that the subclass
0173 * instantiated this Key with.
0174 * @return the private integer key that the subclass
0175 * instantiated this Key with.
0176 */
0177 protected final int intKey() {
0178 return privatekey;
0179 }
0180
0181 /**
0182 * The hash code for all Key objects will be the same as the
0183 * system identity code of the object as defined by the
0184 * System.identityHashCode() method.
0185 */
0186 public final int hashCode() {
0187 return super .hashCode();
0188 }
0189
0190 /**
0191 * The equals method for all Key objects will return the same
0192 * result as the equality operator '=='.
0193 */
0194 public final boolean equals(Object o) {
0195 return this == o;
0196 }
0197 }
0198
0199 HashMap hintmap = new HashMap(7);
0200
0201 /**
0202 * Antialiasing hint key.
0203 * The {@code ANTIALIASING} hint controls whether or not the
0204 * geometry rendering methods of a {@link Graphics2D} object
0205 * will attempt to reduce aliasing artifacts along the edges
0206 * of shapes.
0207 * <p>
0208 * A typical antialiasing algorithm works by blending the existing
0209 * colors of the pixels along the boundary of a shape with the
0210 * requested fill paint according to the estimated partial pixel
0211 * coverage of the shape.
0212 * <p>
0213 * The allowable values for this hint are
0214 * <ul>
0215 * <li>{@link #VALUE_ANTIALIAS_ON}
0216 * <li>{@link #VALUE_ANTIALIAS_OFF}
0217 * <li>{@link #VALUE_ANTIALIAS_DEFAULT}
0218 * </ul>
0219 */
0220 public static final Key KEY_ANTIALIASING = SunHints.KEY_ANTIALIASING;
0221
0222 /**
0223 * Antialiasing hint value -- rendering is done with antialiasing.
0224 * @see #KEY_ANTIALIASING
0225 */
0226 public static final Object VALUE_ANTIALIAS_ON = SunHints.VALUE_ANTIALIAS_ON;
0227
0228 /**
0229 * Antialiasing hint value -- rendering is done without antialiasing.
0230 * @see #KEY_ANTIALIASING
0231 */
0232 public static final Object VALUE_ANTIALIAS_OFF = SunHints.VALUE_ANTIALIAS_OFF;
0233
0234 /**
0235 * Antialiasing hint value -- rendering is done with a default
0236 * antialiasing mode chosen by the implementation.
0237 * @see #KEY_ANTIALIASING
0238 */
0239 public static final Object VALUE_ANTIALIAS_DEFAULT = SunHints.VALUE_ANTIALIAS_DEFAULT;
0240
0241 /**
0242 * Rendering hint key.
0243 * The {@code RENDERING} hint is a general hint that provides
0244 * a high level recommendation as to whether to bias algorithm
0245 * choices more for speed or quality when evaluating tradeoffs.
0246 * This hint could be consulted for any rendering or image
0247 * manipulation operation, but decisions will usually honor
0248 * other, more specific hints in preference to this hint.
0249 * <p>
0250 * The allowable values for this hint are
0251 * <ul>
0252 * <li>{@link #VALUE_RENDER_SPEED}
0253 * <li>{@link #VALUE_RENDER_QUALITY}
0254 * <li>{@link #VALUE_RENDER_DEFAULT}
0255 * </ul>
0256 */
0257 public static final Key KEY_RENDERING = SunHints.KEY_RENDERING;
0258
0259 /**
0260 * Rendering hint value -- rendering algorithms are chosen
0261 * with a preference for output speed.
0262 * @see #KEY_RENDERING
0263 */
0264 public static final Object VALUE_RENDER_SPEED = SunHints.VALUE_RENDER_SPEED;
0265
0266 /**
0267 * Rendering hint value -- rendering algorithms are chosen
0268 * with a preference for output quality.
0269 * @see #KEY_RENDERING
0270 */
0271 public static final Object VALUE_RENDER_QUALITY = SunHints.VALUE_RENDER_QUALITY;
0272
0273 /**
0274 * Rendering hint value -- rendering algorithms are chosen
0275 * by the implementation for a good tradeoff of performance
0276 * vs. quality.
0277 * @see #KEY_RENDERING
0278 */
0279 public static final Object VALUE_RENDER_DEFAULT = SunHints.VALUE_RENDER_DEFAULT;
0280
0281 /**
0282 * Dithering hint key.
0283 * The {@code DITHERING} hint controls how closely to approximate
0284 * a color when storing into a destination with limited color
0285 * resolution.
0286 * <p>
0287 * Some rendering destinations may support a limited number of
0288 * color choices which may not be able to accurately represent
0289 * the full spectrum of colors that can result during rendering
0290 * operations.
0291 * For such a destination the {@code DITHERING} hint controls
0292 * whether rendering is done with a flat solid fill of a single
0293 * pixel value which is the closest supported color to what was
0294 * requested, or whether shapes will be filled with a pattern of
0295 * colors which combine to better approximate that color.
0296 * <p>
0297 * The allowable values for this hint are
0298 * <ul>
0299 * <li>{@link #VALUE_DITHER_DISABLE}
0300 * <li>{@link #VALUE_DITHER_ENABLE}
0301 * <li>{@link #VALUE_DITHER_DEFAULT}
0302 * </ul>
0303 */
0304 public static final Key KEY_DITHERING = SunHints.KEY_DITHERING;
0305
0306 /**
0307 * Dithering hint value -- do not dither when rendering geometry.
0308 * @see #KEY_DITHERING
0309 */
0310 public static final Object VALUE_DITHER_DISABLE = SunHints.VALUE_DITHER_DISABLE;
0311
0312 /**
0313 * Dithering hint value -- dither when rendering geometry, if needed.
0314 * @see #KEY_DITHERING
0315 */
0316 public static final Object VALUE_DITHER_ENABLE = SunHints.VALUE_DITHER_ENABLE;
0317
0318 /**
0319 * Dithering hint value -- use a default for dithering chosen by
0320 * the implementation.
0321 * @see #KEY_DITHERING
0322 */
0323 public static final Object VALUE_DITHER_DEFAULT = SunHints.VALUE_DITHER_DEFAULT;
0324
0325 /**
0326 * Text antialiasing hint key.
0327 * The {@code TEXT_ANTIALIASING} hint can control the use of
0328 * antialiasing algorithms for text independently of the
0329 * choice used for shape rendering.
0330 * Often an application may want to use antialiasing for text
0331 * only and not for other shapes.
0332 * Additionally, the algorithms for reducing the aliasing
0333 * artifacts for text are often more sophisticated than those
0334 * that have been developed for general rendering so this
0335 * hint key provides additional values which can control
0336 * the choices of some of those text-specific algorithms.
0337 * If left in the {@code DEFAULT} state, this hint will
0338 * generally defer to the value of the regular
0339 * {@link #KEY_ANTIALIASING} hint key.
0340 * <p>
0341 * The allowable values for this hint are
0342 * <ul>
0343 * <li>{@link #VALUE_TEXT_ANTIALIAS_ON}
0344 * <li>{@link #VALUE_TEXT_ANTIALIAS_OFF}
0345 * <li>{@link #VALUE_TEXT_ANTIALIAS_DEFAULT}
0346 * <li>{@link #VALUE_TEXT_ANTIALIAS_GASP}
0347 * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}
0348 * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_HBGR}
0349 * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_VRGB}
0350 * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_VBGR}
0351 * </ul>
0352 */
0353 public static final Key KEY_TEXT_ANTIALIASING = SunHints.KEY_TEXT_ANTIALIASING;
0354
0355 /**
0356 * Text antialiasing hint value -- text rendering is done with
0357 * some form of antialiasing.
0358 * @see #KEY_TEXT_ANTIALIASING
0359 */
0360 public static final Object VALUE_TEXT_ANTIALIAS_ON = SunHints.VALUE_TEXT_ANTIALIAS_ON;
0361
0362 /**
0363 * Text antialiasing hint value -- text rendering is done without
0364 * any form of antialiasing.
0365 * @see #KEY_TEXT_ANTIALIASING
0366 */
0367 public static final Object VALUE_TEXT_ANTIALIAS_OFF = SunHints.VALUE_TEXT_ANTIALIAS_OFF;
0368
0369 /**
0370 * Text antialiasing hint value -- text rendering is done according
0371 * to the {@link #KEY_ANTIALIASING} hint or a default chosen by the
0372 * implementation.
0373 * @see #KEY_TEXT_ANTIALIASING
0374 */
0375 public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT = SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
0376
0377 /**
0378 * Text antialiasing hint value -- text rendering is requested to
0379 * use information in the font resource which specifies for each point
0380 * size whether to apply {@link #VALUE_TEXT_ANTIALIAS_ON} or
0381 * {@link #VALUE_TEXT_ANTIALIAS_OFF}.
0382 * <p>
0383 * TrueType fonts typically provide this information in the 'gasp' table.
0384 * In the absence of this information, the behaviour for a particular
0385 * font and size is determined by implementation defaults.
0386 * <p>
0387 * <i>Note:</i>A font designer will typically carefully hint a font for
0388 * the most common user interface point sizes. Consequently the 'gasp'
0389 * table will likely specify to use only hinting at those sizes and not
0390 * "smoothing". So in many cases the resulting text display is
0391 * equivalent to {@code VALUE_TEXT_ANTIALIAS_OFF}.
0392 * This may be unexpected but is correct.
0393 * <p>
0394 * Logical fonts which are composed of multiple physical fonts will for
0395 * consistency will use the setting most appropriate for the overall
0396 * composite font.
0397 *
0398 * @see #KEY_TEXT_ANTIALIASING
0399 * @since 1.6
0400 */
0401 public static final Object VALUE_TEXT_ANTIALIAS_GASP = SunHints.VALUE_TEXT_ANTIALIAS_GASP;
0402
0403 /**
0404 * Text antialiasing hint value -- request that text be displayed
0405 * optimised for an LCD display with subpixels in order from display
0406 * left to right of R,G,B such that the horizontal subpixel resolution
0407 * is three times that of the full pixel horizontal resolution (HRGB).
0408 * This is the most common configuration.
0409 * Selecting this hint for displays with one of the other LCD subpixel
0410 * configurations will likely result in unfocused text.
0411 * <p>
0412 * <i>Notes:</i><br>
0413 * An implementation when choosing whether to apply any of the
0414 * LCD text hint values may take into account factors including requiring
0415 * color depth of the destination to be at least 15 bits per pixel
0416 * (ie 5 bits per color component),
0417 * characteristics of a font such as whether embedded bitmaps may
0418 * produce better results, or when displaying to a non-local networked
0419 * display device enabling it only if suitable protocols are available,
0420 * or ignoring the hint if performing very high resolution rendering
0421 * or the target device is not appropriate: eg when printing.
0422 * <p>
0423 * These hints can equally be applied when rendering to software images,
0424 * but these images may not then be suitable for general export, as the
0425 * text will have been rendered appropriately for a specific subpixel
0426 * organisation. Also lossy images are not a good choice, nor image
0427 * formats such as GIF which have limited colors.
0428 * So unless the image is destined solely for rendering on a
0429 * display device with the same configuration, some other text
0430 * anti-aliasing hint such as
0431 * {@link #VALUE_TEXT_ANTIALIAS_ON}
0432 * may be a better choice.
0433 * <p>Selecting a value which does not match the LCD display in use
0434 * will likely lead to a degradation in text quality.
0435 * On display devices (ie CRTs) which do not have the same characteristics
0436 * as LCD displays, the overall effect may appear similar to standard text
0437 * anti-aliasing, but the quality may be degraded by color distortion.
0438 * Analog connected LCD displays may also show little advantage over
0439 * standard text-antialiasing and be similar to CRTs.
0440 * <p>
0441 * In other words for the best results use an LCD display with a digital
0442 * display connector and specify the appropriate sub-pixel configuration.
0443 *
0444 * @see #KEY_TEXT_ANTIALIASING
0445 * @since 1.6
0446 */
0447 public static final Object VALUE_TEXT_ANTIALIAS_LCD_HRGB = SunHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB;
0448
0449 /**
0450 * Text antialiasing hint value -- request that text be displayed
0451 * optimised for an LCD display with subpixels in order from display
0452 * left to right of B,G,R such that the horizontal subpixel resolution
0453 * is three times that of the full pixel horizontal resolution (HBGR).
0454 * This is a much less common configuration than HRGB.
0455 * Selecting this hint for displays with one of the other LCD subpixel
0456 * configurations will likely result in unfocused text.
0457 * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB},
0458 * for more information on when this hint is applied.
0459 *
0460 * @see #KEY_TEXT_ANTIALIASING
0461 * @since 1.6
0462 */
0463 public static final Object VALUE_TEXT_ANTIALIAS_LCD_HBGR = SunHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR;
0464
0465 /**
0466 * Text antialiasing hint value -- request that text be displayed
0467 * optimised for an LCD display with subpixel organisation from display
0468 * top to bottom of R,G,B such that the vertical subpixel resolution is
0469 * three times that of the full pixel vertical resolution (VRGB).
0470 * Vertical orientation is very uncommon and probably mainly useful
0471 * for a physically rotated display.
0472 * Selecting this hint for displays with one of the other LCD subpixel
0473 * configurations will likely result in unfocused text.
0474 * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB},
0475 * for more information on when this hint is applied.
0476 *
0477 * @see #KEY_TEXT_ANTIALIASING
0478 * @since 1.6
0479 */
0480 public static final Object VALUE_TEXT_ANTIALIAS_LCD_VRGB = SunHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB;
0481
0482 /**
0483 * Text antialiasing hint value -- request that text be displayed
0484 * optimised for an LCD display with subpixel organisation from display
0485 * top to bottom of B,G,R such that the vertical subpixel resolution is
0486 * three times that of the full pixel vertical resolution (VBGR).
0487 * Vertical orientation is very uncommon and probably mainly useful
0488 * for a physically rotated display.
0489 * Selecting this hint for displays with one of the other LCD subpixel
0490 * configurations will likely result in unfocused text.
0491 * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB},
0492 * for more information on when this hint is applied.
0493 *
0494 * @see #KEY_TEXT_ANTIALIASING
0495 * @since 1.6
0496 */
0497 public static final Object VALUE_TEXT_ANTIALIAS_LCD_VBGR = SunHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR;
0498
0499 /**
0500 * LCD text contrast rendering hint key.
0501 * The value is an <code>Integer</code> object which is used as a text
0502 * contrast adjustment when used in conjunction with an LCD text
0503 * anti-aliasing hint such as
0504 * {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}.
0505 * <ul>
0506 * <li>Values should be a positive integer in the range 100 to 250.
0507 * <li>A lower value (eg 100) corresponds to higher contrast text when
0508 * displaying dark text on a light background.
0509 * <li>A higher value (eg 200) corresponds to lower contrast text when
0510 * displaying dark text on a light background.
0511 * <li>A typical useful value is in the narrow range 140-180.
0512 * <li>If no value is specified, a system or implementation default value
0513 * will be applied.
0514 * </ul>
0515 * The default value can be expected to be adequate for most purposes,
0516 * so clients should rarely need to specify a value for this hint unless
0517 * they have concrete information as to an appropriate value.
0518 * A higher value does not mean a higher contrast, in fact the opposite
0519 * is true.
0520 * The correction is applied in a similar manner to a gamma adjustment
0521 * for non-linear perceptual luminance response of display systems, but
0522 * does not indicate a full correction for this.
0523 *
0524 * @see #KEY_TEXT_ANTIALIASING
0525 * @since 1.6
0526 */
0527 public static final Key KEY_TEXT_LCD_CONTRAST = SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST;
0528
0529 /**
0530 * Font fractional metrics hint key.
0531 * The {@code FRACTIONALMETRICS} hint controls whether the positioning
0532 * of individual character glyphs takes into account the sub-pixel
0533 * accuracy of the scaled character advances of the font or whether
0534 * such advance vectors are rounded to an integer number of whole
0535 * device pixels.
0536 * This hint only recommends how much accuracy should be used to
0537 * position the glyphs and does not specify or recommend whether or
0538 * not the actual rasterization or pixel bounds of the glyph should
0539 * be modified to match.
0540 * <p>
0541 * Rendering text to a low resolution device like a screen will
0542 * necessarily involve a number of rounding operations as the
0543 * high quality and very precise definition of the shape and
0544 * metrics of the character glyphs must be matched to discrete
0545 * device pixels.
0546 * Ideally the positioning of glyphs during text layout would be
0547 * calculated by scaling the design metrics in the font according
0548 * to the point size, but then the scaled advance width will not
0549 * necessarily be an integer number of pixels.
0550 * If the glyphs are positioned with sub-pixel accuracy according
0551 * to these scaled design metrics then the rasterization would
0552 * ideally need to be adjusted for each possible sub-pixel origin.
0553 * <p>
0554 * Unfortunately, scaling each glyph customized to its exact
0555 * subpixel origin during text layout would be prohibitively
0556 * expensive so a simplified system based on integer device
0557 * positions is typically used to lay out the text.
0558 * The rasterization of the glyph and the scaled advance width
0559 * are both adjusted together to yield text that looks good at
0560 * device resolution and has consistent integer pixel distances
0561 * between glyphs that help the glyphs look uniformly and
0562 * consistently spaced and readable.
0563 * <p>
0564 * This process of rounding advance widths for rasterized glyphs
0565 * to integer distances means that the character density and the
0566 * overall length of a string of text will be different from the
0567 * theoretical design measurements due to the accumulation of
0568 * a series of small differences in the adjusted widths of
0569 * each glyph.
0570 * The specific differences will be different for each glyph,
0571 * some being wider and some being narrower than their theoretical
0572 * design measurements.
0573 * Thus the overall difference in character density and length
0574 * will vary by a number of factors including the font, the
0575 * specific device resolution being targeted, and the glyphs
0576 * chosen to represent the string being rendered.
0577 * As a result, rendering the same string at multiple device
0578 * resolutions can yield widely varying metrics for whole strings.
0579 * <p>
0580 * When {@code FRACTIONALMETRICS} are enabled, the true font design
0581 * metrics are scaled by the point size and used for layout with
0582 * sub-pixel accuracy.
0583 * The average density of glyphs and total length of a long
0584 * string of characters will therefore more closely match the
0585 * theoretical design of the font, but readability may be affected
0586 * since individual pairs of characters may not always appear to
0587 * be consistent distances apart depending on how the sub-pixel
0588 * accumulation of the glyph origins meshes with the device pixel
0589 * grid.
0590 * Enabling this hint may be desirable when text layout is being
0591 * performed that must be consistent across a wide variety of
0592 * output resolutions.
0593 * Specifically, this hint may be desirable in situations where
0594 * the layout of text is being previewed on a low resolution
0595 * device like a screen for output that will eventually be
0596 * rendered on a high resolution printer or typesetting device.
0597 * <p>
0598 * When disabled, the scaled design metrics are rounded or adjusted
0599 * to integer distances for layout.
0600 * The distances between any specific pair of glyphs will be more
0601 * uniform on the device, but the density and total length of long
0602 * strings may no longer match the theoretical intentions of the
0603 * font designer.
0604 * Disabling this hint will typically produce more readable results
0605 * on low resolution devices like computer monitors.
0606 * <p>
0607 * The allowable values for this key are
0608 * <ul>
0609 * <li>{@link #VALUE_FRACTIONALMETRICS_OFF}
0610 * <li>{@link #VALUE_FRACTIONALMETRICS_ON}
0611 * <li>{@link #VALUE_FRACTIONALMETRICS_DEFAULT}
0612 * </ul>
0613 */
0614 public static final Key KEY_FRACTIONALMETRICS = SunHints.KEY_FRACTIONALMETRICS;
0615
0616 /**
0617 * Font fractional metrics hint value -- character glyphs are
0618 * positioned with advance widths rounded to pixel boundaries.
0619 * @see #KEY_FRACTIONALMETRICS
0620 */
0621 public static final Object VALUE_FRACTIONALMETRICS_OFF = SunHints.VALUE_FRACTIONALMETRICS_OFF;
0622
0623 /**
0624 * Font fractional metrics hint value -- character glyphs are
0625 * positioned with sub-pixel accuracy.
0626 * @see #KEY_FRACTIONALMETRICS
0627 */
0628 public static final Object VALUE_FRACTIONALMETRICS_ON = SunHints.VALUE_FRACTIONALMETRICS_ON;
0629
0630 /**
0631 * Font fractional metrics hint value -- character glyphs are
0632 * positioned with accuracy chosen by the implementation.
0633 * @see #KEY_FRACTIONALMETRICS
0634 */
0635 public static final Object VALUE_FRACTIONALMETRICS_DEFAULT = SunHints.VALUE_FRACTIONALMETRICS_DEFAULT;
0636
0637 /**
0638 * Interpolation hint key.
0639 * The {@code INTERPOLATION} hint controls how image pixels are
0640 * filtered or resampled during an image rendering operation.
0641 * <p>
0642 * Implicitly images are defined to provide color samples at
0643 * integer coordinate locations.
0644 * When images are rendered upright with no scaling onto a
0645 * destination, the choice of which image pixels map to which
0646 * device pixels is obvious and the samples at the integer
0647 * coordinate locations in the image are transfered to the
0648 * pixels at the corresponding integer locations on the device
0649 * pixel grid one for one.
0650 * When images are rendered in a scaled, rotated, or otherwise
0651 * transformed coordinate system, then the mapping of device
0652 * pixel coordinates back to the image can raise the question
0653 * of what color sample to use for the continuous coordinates
0654 * that lie between the integer locations of the provided image
0655 * samples.
0656 * Interpolation algorithms define functions which provide a
0657 * color sample for any continuous coordinate in an image based
0658 * on the color samples at the surrounding integer coordinates.
0659 * <p>
0660 * The allowable values for this hint are
0661 * <ul>
0662 * <li>{@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR}
0663 * <li>{@link #VALUE_INTERPOLATION_BILINEAR}
0664 * <li>{@link #VALUE_INTERPOLATION_BICUBIC}
0665 * </ul>
0666 */
0667 public static final Key KEY_INTERPOLATION = SunHints.KEY_INTERPOLATION;
0668
0669 /**
0670 * Interpolation hint value -- the color sample of the nearest
0671 * neighboring integer coordinate sample in the image is used.
0672 * Conceptually the image is viewed as a grid of unit-sized
0673 * square regions of color centered around the center of each
0674 * image pixel.
0675 * <p>
0676 * As the image is scaled up, it will look correspondingly blocky.
0677 * As the image is scaled down, the colors for source pixels will
0678 * be either used unmodified, or skipped entirely in the output
0679 * representation.
0680 *
0681 * @see #KEY_INTERPOLATION
0682 */
0683 public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR = SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
0684
0685 /**
0686 * Interpolation hint value -- the color samples of the 4 nearest
0687 * neighboring integer coordinate samples in the image are
0688 * interpolated linearly to produce a color sample.
0689 * Conceptually the image is viewed as a set of infinitely small
0690 * point color samples which have value only at the centers of
0691 * integer coordinate pixels and the space between those pixel
0692 * centers is filled with linear ramps of colors that connect
0693 * adjacent discrete samples in a straight line.
0694 * <p>
0695 * As the image is scaled up, there are no blocky edges between
0696 * the colors in the image as there are with
0697 * {@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR NEAREST_NEIGHBOR},
0698 * but the blending may show some subtle discontinuities along the
0699 * horizontal and vertical edges that line up with the samples
0700 * caused by a sudden change in the slope of the interpolation
0701 * from one side of a sample to the other.
0702 * As the image is scaled down, more image pixels have their
0703 * color samples represented in the resulting output since each
0704 * output pixel recieves color information from up to 4 image
0705 * pixels.
0706 *
0707 * @see #KEY_INTERPOLATION
0708 */
0709 public static final Object VALUE_INTERPOLATION_BILINEAR = SunHints.VALUE_INTERPOLATION_BILINEAR;
0710
0711 /**
0712 * Interpolation hint value -- the color samples of 9 nearby
0713 * integer coordinate samples in the image are interpolated using
0714 * a cubic function in both {@code X} and {@code Y} to produce
0715 * a color sample.
0716 * Conceptually the view of the image is very similar to the view
0717 * used in the {@link #VALUE_INTERPOLATION_BILINEAR BILINEAR}
0718 * algorithm except that the ramps of colors that connect between
0719 * the samples are curved and have better continuity of slope
0720 * as they cross over between sample boundaries.
0721 * <p>
0722 * As the image is scaled up, there are no blocky edges and the
0723 * interpolation should appear smoother and with better depictions
0724 * of any edges in the original image than with {@code BILINEAR}.
0725 * As the image is scaled down, even more of the original color
0726 * samples from the original image will have their color information
0727 * carried through and represented.
0728 *
0729 * @see #KEY_INTERPOLATION
0730 */
0731 public static final Object VALUE_INTERPOLATION_BICUBIC = SunHints.VALUE_INTERPOLATION_BICUBIC;
0732
0733 /**
0734 * Alpha interpolation hint key.
0735 * The {@code ALPHA_INTERPOLATION} hint is a general hint that
0736 * provides a high level recommendation as to whether to bias
0737 * alpha blending algorithm choices more for speed or quality
0738 * when evaluating tradeoffs.
0739 * <p>
0740 * This hint could control the choice of alpha blending
0741 * calculations that sacrifice some precision to use fast
0742 * lookup tables or lower precision SIMD instructions.
0743 * This hint could also control whether or not the color
0744 * and alpha values are converted into a linear color space
0745 * during the calculations for a more linear visual effect
0746 * at the expense of additional per-pixel calculations.
0747 * <p>
0748 * The allowable values for this hint are
0749 * <ul>
0750 * <li>{@link #VALUE_ALPHA_INTERPOLATION_SPEED}
0751 * <li>{@link #VALUE_ALPHA_INTERPOLATION_QUALITY}
0752 * <li>{@link #VALUE_ALPHA_INTERPOLATION_DEFAULT}
0753 * </ul>
0754 */
0755 public static final Key KEY_ALPHA_INTERPOLATION = SunHints.KEY_ALPHA_INTERPOLATION;
0756
0757 /**
0758 * Alpha interpolation hint value -- alpha blending algorithms
0759 * are chosen with a preference for calculation speed.
0760 * @see #KEY_ALPHA_INTERPOLATION
0761 */
0762 public static final Object VALUE_ALPHA_INTERPOLATION_SPEED = SunHints.VALUE_ALPHA_INTERPOLATION_SPEED;
0763
0764 /**
0765 * Alpha interpolation hint value -- alpha blending algorithms
0766 * are chosen with a preference for precision and visual quality.
0767 * @see #KEY_ALPHA_INTERPOLATION
0768 */
0769 public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY = SunHints.VALUE_ALPHA_INTERPOLATION_QUALITY;
0770
0771 /**
0772 * Alpha interpolation hint value -- alpha blending algorithms
0773 * are chosen by the implementation for a good tradeoff of
0774 * performance vs. quality.
0775 * @see #KEY_ALPHA_INTERPOLATION
0776 */
0777 public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT = SunHints.VALUE_ALPHA_INTERPOLATION_DEFAULT;
0778
0779 /**
0780 * Color rendering hint key.
0781 * The {@code COLOR_RENDERING} hint controls the accuracy of
0782 * approximation and conversion when storing colors into a
0783 * destination image or surface.
0784 * <p>
0785 * When a rendering or image manipulation operation produces
0786 * a color value that must be stored into a destination, it
0787 * must first convert that color into a form suitable for
0788 * storing into the destination image or surface.
0789 * Minimally, the color components must be converted to bit
0790 * representations and ordered in the correct order or an
0791 * index into a color lookup table must be chosen before
0792 * the data can be stored into the destination memory.
0793 * Without this minimal conversion, the data in the destination
0794 * would likely represent random, incorrect or possibly even
0795 * unsupported values.
0796 * Algorithms to quickly convert the results of rendering
0797 * operations into the color format of most common destinations
0798 * are well known and fairly optimal to execute.
0799 * <p>
0800 * Simply performing the most basic color format conversion to
0801 * store colors into a destination can potentially ignore a
0802 * difference in the calibration of the
0803 * {@link java.awt.color.ColorSpace}
0804 * of the source and destination or other factors such as the
0805 * linearity of the gamma correction.
0806 * Unless the source and destination {@code ColorSpace} are
0807 * identical, to correctly perform a rendering operation with
0808 * the most care taken for the accuracy of the colors being
0809 * represented, the source colors should be converted to a
0810 * device independent {@code ColorSpace} and the results then
0811 * converted back to the destination {@code ColorSpace}.
0812 * Furthermore, if calculations such as the blending of multiple
0813 * source colors are to be performed during the rendering
0814 * operation, greater visual clarity can be achieved if the
0815 * intermediate device independent {@code ColorSpace} is
0816 * chosen to have a linear relationship between the values
0817 * being calculated and the perception of the human eye to
0818 * the response curves of the output device.
0819 * <p>
0820 * The allowable values for this hint are
0821 * <ul>
0822 * <li>{@link #VALUE_COLOR_RENDER_SPEED}
0823 * <li>{@link #VALUE_COLOR_RENDER_QUALITY}
0824 * <li>{@link #VALUE_COLOR_RENDER_DEFAULT}
0825 * </ul>
0826 */
0827 public static final Key KEY_COLOR_RENDERING = SunHints.KEY_COLOR_RENDERING;
0828
0829 /**
0830 * Color rendering hint value -- perform the fastest color
0831 * conversion to the format of the output device.
0832 * @see #KEY_COLOR_RENDERING
0833 */
0834 public static final Object VALUE_COLOR_RENDER_SPEED = SunHints.VALUE_COLOR_RENDER_SPEED;
0835
0836 /**
0837 * Color rendering hint value -- perform the color conversion
0838 * calculations with the highest accuracy and visual quality.
0839 * @see #KEY_COLOR_RENDERING
0840 */
0841 public static final Object VALUE_COLOR_RENDER_QUALITY = SunHints.VALUE_COLOR_RENDER_QUALITY;
0842
0843 /**
0844 * Color rendering hint value -- perform color conversion
0845 * calculations as chosen by the implementation to represent
0846 * the best available tradeoff between performance and
0847 * accuracy.
0848 * @see #KEY_COLOR_RENDERING
0849 */
0850 public static final Object VALUE_COLOR_RENDER_DEFAULT = SunHints.VALUE_COLOR_RENDER_DEFAULT;
0851
0852 /**
0853 * Stroke normalization control hint key.
0854 * The {@code STROKE_CONTROL} hint controls whether a rendering
0855 * implementation should or is allowed to modify the geometry
0856 * of rendered shapes for various purposes.
0857 * <p>
0858 * Some implementations may be able to use an optimized platform
0859 * rendering library which may be faster than traditional software
0860 * rendering algorithms on a given platform, but which may also
0861 * not support floating point coordinates.
0862 * Some implementations may also have sophisticated algorithms
0863 * which perturb the coordinates of a path so that wide lines
0864 * appear more uniform in width and spacing.
0865 * <p>
0866 * If an implementation performs any type of modification or
0867 * "normalization" of a path, it should never move the coordinates
0868 * by more than half a pixel in any direction.
0869 * <p>
0870 * The allowable values for this hint are
0871 * <ul>
0872 * <li>{@link #VALUE_STROKE_NORMALIZE}
0873 * <li>{@link #VALUE_STROKE_PURE}
0874 * <li>{@link #VALUE_STROKE_DEFAULT}
0875 * </ul>
0876 * @since 1.3
0877 */
0878 public static final Key KEY_STROKE_CONTROL = SunHints.KEY_STROKE_CONTROL;
0879
0880 /**
0881 * Stroke normalization control hint value -- geometry may be
0882 * modified or left pure depending on the tradeoffs in a given
0883 * implementation.
0884 * Typically this setting allows an implementation to use a fast
0885 * integer coordinate based platform rendering library, but does
0886 * not specifically request normalization for uniformity or
0887 * aesthetics.
0888 *
0889 * @see #KEY_STROKE_CONTROL
0890 * @since 1.3
0891 */
0892 public static final Object VALUE_STROKE_DEFAULT = SunHints.VALUE_STROKE_DEFAULT;
0893
0894 /**
0895 * Stroke normalization control hint value -- geometry should
0896 * be normalized to improve uniformity or spacing of lines and
0897 * overall aesthetics.
0898 * Note that different normalization algorithms may be more
0899 * successful than others for given input paths.
0900 *
0901 * @see #KEY_STROKE_CONTROL
0902 * @since 1.3
0903 */
0904 public static final Object VALUE_STROKE_NORMALIZE = SunHints.VALUE_STROKE_NORMALIZE;
0905
0906 /**
0907 * Stroke normalization control hint value -- geometry should
0908 * be left unmodified and rendered with sub-pixel accuracy.
0909 *
0910 * @see #KEY_STROKE_CONTROL
0911 * @since 1.3
0912 */
0913 public static final Object VALUE_STROKE_PURE = SunHints.VALUE_STROKE_PURE;
0914
0915 /**
0916 * Constructs a new object with keys and values initialized
0917 * from the specified Map object which may be null.
0918 * @param init a map of key/value pairs to initialize the hints
0919 * or null if the object should be empty
0920 */
0921 public RenderingHints(Map<Key, ?> init) {
0922 if (init != null) {
0923 hintmap.putAll(init);
0924 }
0925 }
0926
0927 /**
0928 * Constructs a new object with the specified key/value pair.
0929 * @param key the key of the particular hint property
0930 * @param value the value of the hint property specified with
0931 * <code>key</code>
0932 */
0933 public RenderingHints(Key key, Object value) {
0934 hintmap.put(key, value);
0935 }
0936
0937 /**
0938 * Returns the number of key-value mappings in this
0939 * <code>RenderingHints</code>.
0940 *
0941 * @return the number of key-value mappings in this
0942 * <code>RenderingHints</code>.
0943 */
0944 public int size() {
0945 return hintmap.size();
0946 }
0947
0948 /**
0949 * Returns <code>true</code> if this
0950 * <code>RenderingHints</code> contains no key-value mappings.
0951 *
0952 * @return <code>true</code> if this
0953 * <code>RenderingHints</code> contains no key-value mappings.
0954 */
0955 public boolean isEmpty() {
0956 return hintmap.isEmpty();
0957 }
0958
0959 /**
0960 * Returns <code>true</code> if this <code>RenderingHints</code>
0961 * contains a mapping for the specified key.
0962 *
0963 * @param key key whose presence in this
0964 * <code>RenderingHints</code> is to be tested.
0965 * @return <code>true</code> if this <code>RenderingHints</code>
0966 * contains a mapping for the specified key.
0967 * @exception <code>ClassCastException</code> if the key can not
0968 * be cast to <code>RenderingHints.Key</code>
0969 */
0970 public boolean containsKey(Object key) {
0971 return hintmap.containsKey((Key) key);
0972 }
0973
0974 /**
0975 * Returns true if this RenderingHints maps one or more keys to the
0976 * specified value.
0977 * More formally, returns <code>true</code> if and only
0978 * if this <code>RenderingHints</code>
0979 * contains at least one mapping to a value <code>v</code> such that
0980 * <pre>
0981 * (value==null ? v==null : value.equals(v))
0982 * </pre>.
0983 * This operation will probably require time linear in the
0984 * <code>RenderingHints</code> size for most implementations
0985 * of <code>RenderingHints</code>.
0986 *
0987 * @param value value whose presence in this
0988 * <code>RenderingHints</code> is to be tested.
0989 * @return <code>true</code> if this <code>RenderingHints</code>
0990 * maps one or more keys to the specified value.
0991 */
0992 public boolean containsValue(Object value) {
0993 return hintmap.containsValue(value);
0994 }
0995
0996 /**
0997 * Returns the value to which the specified key is mapped.
0998 * @param key a rendering hint key
0999 * @return the value to which the key is mapped in this object or
1000 * <code>null</code> if the key is not mapped to any value in
1001 * this object.
1002 * @exception <code>ClassCastException</code> if the key can not
1003 * be cast to <code>RenderingHints.Key</code>
1004 * @see #put(Object, Object)
1005 */
1006 public Object get(Object key) {
1007 return hintmap.get((Key) key);
1008 }
1009
1010 /**
1011 * Maps the specified <code>key</code> to the specified
1012 * <code>value</code> in this <code>RenderingHints</code> object.
1013 * Neither the key nor the value can be <code>null</code>.
1014 * The value can be retrieved by calling the <code>get</code> method
1015 * with a key that is equal to the original key.
1016 * @param key the rendering hint key.
1017 * @param value the rendering hint value.
1018 * @return the previous value of the specified key in this object
1019 * or <code>null</code> if it did not have one.
1020 * @exception <code>NullPointerException</code> if the key is
1021 * <code>null</code>.
1022 * @exception <code>ClassCastException</code> if the key can not
1023 * be cast to <code>RenderingHints.Key</code>
1024 * @exception <code>IllegalArgumentException</code> if the
1025 * {@link Key#isCompatibleValue(java.lang.Object)
1026 * Key.isCompatibleValue()}
1027 * method of the specified key returns false for the
1028 * specified value
1029 * @see #get(Object)
1030 */
1031 public Object put(Object key, Object value) {
1032 if (!((Key) key).isCompatibleValue(value)) {
1033 throw new IllegalArgumentException(value
1034 + " incompatible with " + key);
1035 }
1036 return hintmap.put((Key) key, value);
1037 }
1038
1039 /**
1040 * Adds all of the keys and corresponding values from the specified
1041 * <code>RenderingHints</code> object to this
1042 * <code>RenderingHints</code> object. Keys that are present in
1043 * this <code>RenderingHints</code> object, but not in the specified
1044 * <code>RenderingHints</code> object are not affected.
1045 * @param hints the set of key/value pairs to be added to this
1046 * <code>RenderingHints</code> object
1047 */
1048 public void add(RenderingHints hints) {
1049 hintmap.putAll(hints.hintmap);
1050 }
1051
1052 /**
1053 * Clears this <code>RenderingHints</code> object of all key/value
1054 * pairs.
1055 */
1056 public void clear() {
1057 hintmap.clear();
1058 }
1059
1060 /**
1061 * Removes the key and its corresponding value from this
1062 * <code>RenderingHints</code> object. This method does nothing if the
1063 * key is not in this <code>RenderingHints</code> object.
1064 * @param key the rendering hints key that needs to be removed
1065 * @exception <code>ClassCastException</code> if the key can not
1066 * be cast to <code>RenderingHints.Key</code>
1067 * @return the value to which the key had previously been mapped in this
1068 * <code>RenderingHints</code> object, or <code>null</code>
1069 * if the key did not have a mapping.
1070 */
1071 public Object remove(Object key) {
1072 return hintmap.remove((Key) key);
1073 }
1074
1075 /**
1076 * Copies all of the mappings from the specified <code>Map</code>
1077 * to this <code>RenderingHints</code>. These mappings replace
1078 * any mappings that this <code>RenderingHints</code> had for any
1079 * of the keys currently in the specified <code>Map</code>.
1080 * @param m the specified <code>Map</code>
1081 * @exception <code>ClassCastException</code> class of a key or value
1082 * in the specified <code>Map</code> prevents it from being
1083 * stored in this <code>RenderingHints</code>.
1084 * @exception <code>IllegalArgumentException</code> some aspect
1085 * of a key or value in the specified <code>Map</code>
1086 * prevents it from being stored in
1087 * this <code>RenderingHints</code>.
1088 */
1089 public void putAll(Map<?, ?> m) {
1090 // ## javac bug?
1091 //if (m instanceof RenderingHints) {
1092 if (RenderingHints.class.isInstance(m)) {
1093 //hintmap.putAll(((RenderingHints) m).hintmap);
1094 for (Map.Entry<?, ?> entry : m.entrySet())
1095 hintmap.put(entry.getKey(), entry.getValue());
1096 } else {
1097 // Funnel each key/value pair through our protected put method
1098 for (Map.Entry<?, ?> entry : m.entrySet())
1099 put(entry.getKey(), entry.getValue());
1100 }
1101 }
1102
1103 /**
1104 * Returns a <code>Set</code> view of the Keys contained in this
1105 * <code>RenderingHints</code>. The Set is backed by the
1106 * <code>RenderingHints</code>, so changes to the
1107 * <code>RenderingHints</code> are reflected in the <code>Set</code>,
1108 * and vice-versa. If the <code>RenderingHints</code> is modified
1109 * while an iteration over the <code>Set</code> is in progress,
1110 * the results of the iteration are undefined. The <code>Set</code>
1111 * supports element removal, which removes the corresponding
1112 * mapping from the <code>RenderingHints</code>, via the
1113 * <code>Iterator.remove</code>, <code>Set.remove</code>,
1114 * <code>removeAll</code> <code>retainAll</code>, and
1115 * <code>clear</code> operations. It does not support
1116 * the <code>add</code> or <code>addAll</code> operations.
1117 *
1118 * @return a <code>Set</code> view of the keys contained
1119 * in this <code>RenderingHints</code>.
1120 */
1121 public Set<Object> keySet() {
1122 return hintmap.keySet();
1123 }
1124
1125 /**
1126 * Returns a <code>Collection</code> view of the values
1127 * contained in this <code>RenderinHints</code>.
1128 * The <code>Collection</code> is backed by the
1129 * <code>RenderingHints</code>, so changes to
1130 * the <code>RenderingHints</code> are reflected in
1131 * the <code>Collection</code>, and vice-versa.
1132 * If the <code>RenderingHints</code> is modified while
1133 * an iteration over the <code>Collection</code> is
1134 * in progress, the results of the iteration are undefined.
1135 * The <code>Collection</code> supports element removal,
1136 * which removes the corresponding mapping from the
1137 * <code>RenderingHints</code>, via the
1138 * <code>Iterator.remove</code>,
1139 * <code>Collection.remove</code>, <code>removeAll</code>,
1140 * <code>retainAll</code> and <code>clear</code> operations.
1141 * It does not support the <code>add</code> or
1142 * <code>addAll</code> operations.
1143 *
1144 * @return a <code>Collection</code> view of the values
1145 * contained in this <code>RenderingHints</code>.
1146 */
1147 public Collection<Object> values() {
1148 return hintmap.values();
1149 }
1150
1151 /**
1152 * Returns a <code>Set</code> view of the mappings contained
1153 * in this <code>RenderingHints</code>. Each element in the
1154 * returned <code>Set</code> is a <code>Map.Entry</code>.
1155 * The <code>Set</code> is backed by the <code>RenderingHints</code>,
1156 * so changes to the <code>RenderingHints</code> are reflected
1157 * in the <code>Set</code>, and vice-versa. If the
1158 * <code>RenderingHints</code> is modified while
1159 * while an iteration over the <code>Set</code> is in progress,
1160 * the results of the iteration are undefined.
1161 * <p>
1162 * The entrySet returned from a <code>RenderingHints</code> object
1163 * is not modifiable.
1164 *
1165 * @return a <code>Set</code> view of the mappings contained in
1166 * this <code>RenderingHints</code>.
1167 */
1168 public Set<Map.Entry<Object, Object>> entrySet() {
1169 return Collections.unmodifiableMap(hintmap).entrySet();
1170 }
1171
1172 /**
1173 * Compares the specified <code>Object</code> with this
1174 * <code>RenderingHints</code> for equality.
1175 * Returns <code>true</code> if the specified object is also a
1176 * <code>Map</code> and the two <code>Map</code> objects represent
1177 * the same mappings. More formally, two <code>Map</code> objects
1178 * <code>t1</code> and <code>t2</code> represent the same mappings
1179 * if <code>t1.keySet().equals(t2.keySet())</code> and for every
1180 * key <code>k</code> in <code>t1.keySet()</code>,
1181 * <pre>
1182 * (t1.get(k)==null ? t2.get(k)==null : t1.get(k).equals(t2.get(k)))
1183 * </pre>.
1184 * This ensures that the <code>equals</code> method works properly across
1185 * different implementations of the <code>Map</code> interface.
1186 *
1187 * @param o <code>Object</code> to be compared for equality with
1188 * this <code>RenderingHints</code>.
1189 * @return <code>true</code> if the specified <code>Object</code>
1190 * is equal to this <code>RenderingHints</code>.
1191 */
1192 public boolean equals(Object o) {
1193 if (o instanceof RenderingHints) {
1194 return hintmap.equals(((RenderingHints) o).hintmap);
1195 } else if (o instanceof Map) {
1196 return hintmap.equals(o);
1197 }
1198 return false;
1199 }
1200
1201 /**
1202 * Returns the hash code value for this <code>RenderingHints</code>.
1203 * The hash code of a <code>RenderingHints</code> is defined to be
1204 * the sum of the hashCodes of each <code>Entry</code> in the
1205 * <code>RenderingHints</code> object's entrySet view. This ensures that
1206 * <code>t1.equals(t2)</code> implies that
1207 * <code>t1.hashCode()==t2.hashCode()</code> for any two <code>Map</code>
1208 * objects <code>t1</code> and <code>t2</code>, as required by the general
1209 * contract of <code>Object.hashCode</code>.
1210 *
1211 * @return the hash code value for this <code>RenderingHints</code>.
1212 * @see java.util.Map.Entry#hashCode()
1213 * @see Object#hashCode()
1214 * @see Object#equals(Object)
1215 * @see #equals(Object)
1216 */
1217 public int hashCode() {
1218 return hintmap.hashCode();
1219 }
1220
1221 /**
1222 * Creates a clone of this <code>RenderingHints</code> object
1223 * that has the same contents as this <code>RenderingHints</code>
1224 * object.
1225 * @return a clone of this instance.
1226 */
1227 public Object clone() {
1228 RenderingHints rh;
1229 try {
1230 rh = (RenderingHints) super .clone();
1231 if (hintmap != null) {
1232 rh.hintmap = (HashMap) hintmap.clone();
1233 }
1234 } catch (CloneNotSupportedException e) {
1235 // this shouldn't happen, since we are Cloneable
1236 throw new InternalError();
1237 }
1238
1239 return rh;
1240 }
1241
1242 /**
1243 * Returns a rather long string representation of the hashmap
1244 * which contains the mappings of keys to values for this
1245 * <code>RenderingHints</code> object.
1246 * @return a string representation of this object.
1247 */
1248 public String toString() {
1249 if (hintmap == null) {
1250 return getClass().getName() + "@"
1251 + Integer.toHexString(hashCode()) + " (0 hints)";
1252 }
1253
1254 return hintmap.toString();
1255 }
1256 }
|