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: }
|