Java tutorial
/* * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.awt; import java.util.Map; import java.util.Set; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import sun.awt.SunHints; import java.lang.ref.WeakReference; /** * The {@code RenderingHints} class defines and manages collections of * keys and associated values which allow an application to provide input * into the choice of algorithms used by other classes which perform * rendering and image manipulation services. * The {@link java.awt.Graphics2D} class, and classes that implement * {@link java.awt.image.BufferedImageOp} and * {@link java.awt.image.RasterOp} all provide methods to get and * possibly to set individual or groups of {@code RenderingHints} * keys and their associated values. * When those implementations perform any rendering or image manipulation * operations they should examine the values of any {@code RenderingHints} * that were requested by the caller and tailor the algorithms used * accordingly and to the best of their ability. * <p> * Note that since these keys and values are <i>hints</i>, there is * no requirement that a given implementation supports all possible * choices indicated below or that it can respond to requests to * modify its choice of algorithm. * The values of the various hint keys may also interact such that * while all variants of a given key are supported in one situation, * the implementation may be more restricted when the values associated * with other keys are modified. * For example, some implementations may be able to provide several * types of dithering when the antialiasing hint is turned off, but * have little control over dithering when antialiasing is on. * The full set of supported keys and hints may also vary by destination * since runtimes may use different underlying modules to render to * the screen, or to {@link java.awt.image.BufferedImage} objects, * or while printing. * <p> * Implementations are free to ignore the hints completely, but should * try to use an implementation algorithm that is as close as possible * to the request. * If an implementation supports a given algorithm when any value is used * for an associated hint key, then minimally it must do so when the * value for that key is the exact value that specifies the algorithm. * <p> * The keys used to control the hints are all special values that * subclass the associated {@link RenderingHints.Key} class. * Many common hints are expressed below as static constants in this * class, but the list is not meant to be exhaustive. * Other hints may be created by other packages by defining new objects * which subclass the {@code Key} class and defining the associated values. */ public class RenderingHints implements Map<Object, Object>, Cloneable { /** * Defines the base type of all keys used along with the * {@link RenderingHints} class to control various * algorithm choices in the rendering and imaging pipelines. * Instances of this class are immutable and unique which * means that tests for matches can be made using the * {@code ==} operator instead of the more expensive * {@code equals()} method. */ public abstract static class Key { private static HashMap<Object, Object> identitymap = new HashMap<>(17); private String getIdentity() { // Note that the identity string is dependent on 3 variables: // - the name of the subclass of Key // - the identityHashCode of the subclass of Key // - the integer key of the Key // It is theoretically possible for 2 distinct keys to collide // along all 3 of those attributes in the context of multiple // class loaders, but that occurrence will be extremely rare and // we account for that possibility below in the recordIdentity // method by slightly relaxing our uniqueness guarantees if we // end up in that situation. return getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(getClass())) + ":" + Integer.toHexString(privatekey); } private static synchronized void recordIdentity(Key k) { Object identity = k.getIdentity(); Object otherref = identitymap.get(identity); if (otherref != null) { Key otherkey = (Key) ((WeakReference) otherref).get(); if (otherkey != null && otherkey.getClass() == k.getClass()) { throw new IllegalArgumentException(identity + " already registered"); } // Note that this system can fail in a mostly harmless // way. If we end up generating the same identity // String for 2 different classes (a very rare case) // then we correctly avoid throwing the exception above, // but we are about to drop through to a statement that // will replace the entry for the old Key subclass with // an entry for the new Key subclass. At that time the // old subclass will be vulnerable to someone generating // a duplicate Key instance for it. We could bail out // of the method here and let the old identity keep its // record in the map, but we are more likely to see a // duplicate key go by for the new class than the old // one since the new one is probably still in the // initialization stage. In either case, the probability // of loading 2 classes in the same VM with the same name // and identityHashCode should be nearly impossible. } // Note: Use a weak reference to avoid holding on to extra // objects and classes after they should be unloaded. identitymap.put(identity, new WeakReference<Key>(k)); } private int privatekey; /** * Construct a key using the indicated private key. Each * subclass of Key maintains its own unique domain of integer * keys. No two objects with the same integer key and of the * same specific subclass can be constructed. An exception * will be thrown if an attempt is made to construct another * object of a given class with the same integer key as a * pre-existing instance of that subclass of Key. * @param privatekey the specified key */ protected Key(int privatekey) { this.privatekey = privatekey; recordIdentity(this); } /** * Returns true if the specified object is a valid value * for this Key. * @param val the {@code Object} to test for validity * @return {@code true} if {@code val} is valid; * {@code false} otherwise. */ public abstract boolean isCompatibleValue(Object val); /** * Returns the private integer key that the subclass * instantiated this Key with. * @return the private integer key that the subclass * instantiated this Key with. */ protected final int intKey() { return privatekey; } /** * The hash code for all Key objects will be the same as the * system identity code of the object as defined by the * System.identityHashCode() method. */ public final int hashCode() { return super.hashCode(); } /** * The equals method for all Key objects will return the same * result as the equality operator '=='. */ public final boolean equals(Object o) { return this == o; } } HashMap<Object, Object> hintmap = new HashMap<>(7); /** * Antialiasing hint key. * The {@code ANTIALIASING} hint controls whether or not the * geometry rendering methods of a {@link Graphics2D} object * will attempt to reduce aliasing artifacts along the edges * of shapes. * <p> * A typical antialiasing algorithm works by blending the existing * colors of the pixels along the boundary of a shape with the * requested fill paint according to the estimated partial pixel * coverage of the shape. * <p> * The allowable values for this hint are * <ul> * <li>{@link #VALUE_ANTIALIAS_ON} * <li>{@link #VALUE_ANTIALIAS_OFF} * <li>{@link #VALUE_ANTIALIAS_DEFAULT} * </ul> */ public static final Key KEY_ANTIALIASING = SunHints.KEY_ANTIALIASING; /** * Antialiasing hint value -- rendering is done with antialiasing. * @see #KEY_ANTIALIASING */ public static final Object VALUE_ANTIALIAS_ON = SunHints.VALUE_ANTIALIAS_ON; /** * Antialiasing hint value -- rendering is done without antialiasing. * @see #KEY_ANTIALIASING */ public static final Object VALUE_ANTIALIAS_OFF = SunHints.VALUE_ANTIALIAS_OFF; /** * Antialiasing hint value -- rendering is done with a default * antialiasing mode chosen by the implementation. * @see #KEY_ANTIALIASING */ public static final Object VALUE_ANTIALIAS_DEFAULT = SunHints.VALUE_ANTIALIAS_DEFAULT; /** * Rendering hint key. * The {@code RENDERING} hint is a general hint that provides * a high level recommendation as to whether to bias algorithm * choices more for speed or quality when evaluating tradeoffs. * This hint could be consulted for any rendering or image * manipulation operation, but decisions will usually honor * other, more specific hints in preference to this hint. * <p> * The allowable values for this hint are * <ul> * <li>{@link #VALUE_RENDER_SPEED} * <li>{@link #VALUE_RENDER_QUALITY} * <li>{@link #VALUE_RENDER_DEFAULT} * </ul> */ public static final Key KEY_RENDERING = SunHints.KEY_RENDERING; /** * Rendering hint value -- rendering algorithms are chosen * with a preference for output speed. * @see #KEY_RENDERING */ public static final Object VALUE_RENDER_SPEED = SunHints.VALUE_RENDER_SPEED; /** * Rendering hint value -- rendering algorithms are chosen * with a preference for output quality. * @see #KEY_RENDERING */ public static final Object VALUE_RENDER_QUALITY = SunHints.VALUE_RENDER_QUALITY; /** * Rendering hint value -- rendering algorithms are chosen * by the implementation for a good tradeoff of performance * vs. quality. * @see #KEY_RENDERING */ public static final Object VALUE_RENDER_DEFAULT = SunHints.VALUE_RENDER_DEFAULT; /** * Dithering hint key. * The {@code DITHERING} hint controls how closely to approximate * a color when storing into a destination with limited color * resolution. * <p> * Some rendering destinations may support a limited number of * color choices which may not be able to accurately represent * the full spectrum of colors that can result during rendering * operations. * For such a destination the {@code DITHERING} hint controls * whether rendering is done with a flat solid fill of a single * pixel value which is the closest supported color to what was * requested, or whether shapes will be filled with a pattern of * colors which combine to better approximate that color. * <p> * The allowable values for this hint are * <ul> * <li>{@link #VALUE_DITHER_DISABLE} * <li>{@link #VALUE_DITHER_ENABLE} * <li>{@link #VALUE_DITHER_DEFAULT} * </ul> */ public static final Key KEY_DITHERING = SunHints.KEY_DITHERING; /** * Dithering hint value -- do not dither when rendering geometry. * @see #KEY_DITHERING */ public static final Object VALUE_DITHER_DISABLE = SunHints.VALUE_DITHER_DISABLE; /** * Dithering hint value -- dither when rendering geometry, if needed. * @see #KEY_DITHERING */ public static final Object VALUE_DITHER_ENABLE = SunHints.VALUE_DITHER_ENABLE; /** * Dithering hint value -- use a default for dithering chosen by * the implementation. * @see #KEY_DITHERING */ public static final Object VALUE_DITHER_DEFAULT = SunHints.VALUE_DITHER_DEFAULT; /** * Text antialiasing hint key. * The {@code TEXT_ANTIALIASING} hint can control the use of * antialiasing algorithms for text independently of the * choice used for shape rendering. * Often an application may want to use antialiasing for text * only and not for other shapes. * Additionally, the algorithms for reducing the aliasing * artifacts for text are often more sophisticated than those * that have been developed for general rendering so this * hint key provides additional values which can control * the choices of some of those text-specific algorithms. * If left in the {@code DEFAULT} state, this hint will * generally defer to the value of the regular * {@link #KEY_ANTIALIASING} hint key. * <p> * The allowable values for this hint are * <ul> * <li>{@link #VALUE_TEXT_ANTIALIAS_ON} * <li>{@link #VALUE_TEXT_ANTIALIAS_OFF} * <li>{@link #VALUE_TEXT_ANTIALIAS_DEFAULT} * <li>{@link #VALUE_TEXT_ANTIALIAS_GASP} * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB} * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_HBGR} * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_VRGB} * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_VBGR} * </ul> */ public static final Key KEY_TEXT_ANTIALIASING = SunHints.KEY_TEXT_ANTIALIASING; /** * Text antialiasing hint value -- text rendering is done with * some form of antialiasing. * @see #KEY_TEXT_ANTIALIASING */ public static final Object VALUE_TEXT_ANTIALIAS_ON = SunHints.VALUE_TEXT_ANTIALIAS_ON; /** * Text antialiasing hint value -- text rendering is done without * any form of antialiasing. * @see #KEY_TEXT_ANTIALIASING */ public static final Object VALUE_TEXT_ANTIALIAS_OFF = SunHints.VALUE_TEXT_ANTIALIAS_OFF; /** * Text antialiasing hint value -- text rendering is done according * to the {@link #KEY_ANTIALIASING} hint or a default chosen by the * implementation. * @see #KEY_TEXT_ANTIALIASING */ public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT = SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT; /** * Text antialiasing hint value -- text rendering is requested to * use information in the font resource which specifies for each point * size whether to apply {@link #VALUE_TEXT_ANTIALIAS_ON} or * {@link #VALUE_TEXT_ANTIALIAS_OFF}. * <p> * TrueType fonts typically provide this information in the 'gasp' table. * In the absence of this information, the behaviour for a particular * font and size is determined by implementation defaults. * <p> * <i>Note:</i>A font designer will typically carefully hint a font for * the most common user interface point sizes. Consequently the 'gasp' * table will likely specify to use only hinting at those sizes and not * "smoothing". So in many cases the resulting text display is * equivalent to {@code VALUE_TEXT_ANTIALIAS_OFF}. * This may be unexpected but is correct. * <p> * Logical fonts which are composed of multiple physical fonts will for * consistency will use the setting most appropriate for the overall * composite font. * * @see #KEY_TEXT_ANTIALIASING * @since 1.6 */ public static final Object VALUE_TEXT_ANTIALIAS_GASP = SunHints.VALUE_TEXT_ANTIALIAS_GASP; /** * Text antialiasing hint value -- request that text be displayed * optimised for an LCD display with subpixels in order from display * left to right of R,G,B such that the horizontal subpixel resolution * is three times that of the full pixel horizontal resolution (HRGB). * This is the most common configuration. * Selecting this hint for displays with one of the other LCD subpixel * configurations will likely result in unfocused text. * <p> * <i>Notes:</i><br> * An implementation when choosing whether to apply any of the * LCD text hint values may take into account factors including requiring * color depth of the destination to be at least 15 bits per pixel * (ie 5 bits per color component), * characteristics of a font such as whether embedded bitmaps may * produce better results, or when displaying to a non-local networked * display device enabling it only if suitable protocols are available, * or ignoring the hint if performing very high resolution rendering * or the target device is not appropriate: eg when printing. * <p> * These hints can equally be applied when rendering to software images, * but these images may not then be suitable for general export, as the * text will have been rendered appropriately for a specific subpixel * organisation. Also lossy images are not a good choice, nor image * formats such as GIF which have limited colors. * So unless the image is destined solely for rendering on a * display device with the same configuration, some other text * anti-aliasing hint such as * {@link #VALUE_TEXT_ANTIALIAS_ON} * may be a better choice. * <p>Selecting a value which does not match the LCD display in use * will likely lead to a degradation in text quality. * On display devices (ie CRTs) which do not have the same characteristics * as LCD displays, the overall effect may appear similar to standard text * anti-aliasing, but the quality may be degraded by color distortion. * Analog connected LCD displays may also show little advantage over * standard text-antialiasing and be similar to CRTs. * <p> * In other words for the best results use an LCD display with a digital * display connector and specify the appropriate sub-pixel configuration. * * @see #KEY_TEXT_ANTIALIASING * @since 1.6 */ public static final Object VALUE_TEXT_ANTIALIAS_LCD_HRGB = SunHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB; /** * Text antialiasing hint value -- request that text be displayed * optimised for an LCD display with subpixels in order from display * left to right of B,G,R such that the horizontal subpixel resolution * is three times that of the full pixel horizontal resolution (HBGR). * This is a much less common configuration than HRGB. * Selecting this hint for displays with one of the other LCD subpixel * configurations will likely result in unfocused text. * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}, * for more information on when this hint is applied. * * @see #KEY_TEXT_ANTIALIASING * @since 1.6 */ public static final Object VALUE_TEXT_ANTIALIAS_LCD_HBGR = SunHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR; /** * Text antialiasing hint value -- request that text be displayed * optimised for an LCD display with subpixel organisation from display * top to bottom of R,G,B such that the vertical subpixel resolution is * three times that of the full pixel vertical resolution (VRGB). * Vertical orientation is very uncommon and probably mainly useful * for a physically rotated display. * Selecting this hint for displays with one of the other LCD subpixel * configurations will likely result in unfocused text. * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}, * for more information on when this hint is applied. * * @see #KEY_TEXT_ANTIALIASING * @since 1.6 */ public static final Object VALUE_TEXT_ANTIALIAS_LCD_VRGB = SunHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB; /** * Text antialiasing hint value -- request that text be displayed * optimised for an LCD display with subpixel organisation from display * top to bottom of B,G,R such that the vertical subpixel resolution is * three times that of the full pixel vertical resolution (VBGR). * Vertical orientation is very uncommon and probably mainly useful * for a physically rotated display. * Selecting this hint for displays with one of the other LCD subpixel * configurations will likely result in unfocused text. * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}, * for more information on when this hint is applied. * * @see #KEY_TEXT_ANTIALIASING * @since 1.6 */ public static final Object VALUE_TEXT_ANTIALIAS_LCD_VBGR = SunHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR; /** * LCD text contrast rendering hint key. * The value is an {@code Integer} object which is used as a text * contrast adjustment when used in conjunction with an LCD text * anti-aliasing hint such as * {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}. * <ul> * <li>Values should be a positive integer in the range 100 to 250. * <li>A lower value (eg 100) corresponds to higher contrast text when * displaying dark text on a light background. * <li>A higher value (eg 200) corresponds to lower contrast text when * displaying dark text on a light background. * <li>A typical useful value is in the narrow range 140-180. * <li>If no value is specified, a system or implementation default value * will be applied. * </ul> * The default value can be expected to be adequate for most purposes, * so clients should rarely need to specify a value for this hint unless * they have concrete information as to an appropriate value. * A higher value does not mean a higher contrast, in fact the opposite * is true. * The correction is applied in a similar manner to a gamma adjustment * for non-linear perceptual luminance response of display systems, but * does not indicate a full correction for this. * * @see #KEY_TEXT_ANTIALIASING * @since 1.6 */ public static final Key KEY_TEXT_LCD_CONTRAST = SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST; /** * Font fractional metrics hint key. * The {@code FRACTIONALMETRICS} hint controls whether the positioning * of individual character glyphs takes into account the sub-pixel * accuracy of the scaled character advances of the font or whether * such advance vectors are rounded to an integer number of whole * device pixels. * This hint only recommends how much accuracy should be used to * position the glyphs and does not specify or recommend whether or * not the actual rasterization or pixel bounds of the glyph should * be modified to match. * <p> * Rendering text to a low resolution device like a screen will * necessarily involve a number of rounding operations as the * high quality and very precise definition of the shape and * metrics of the character glyphs must be matched to discrete * device pixels. * Ideally the positioning of glyphs during text layout would be * calculated by scaling the design metrics in the font according * to the point size, but then the scaled advance width will not * necessarily be an integer number of pixels. * If the glyphs are positioned with sub-pixel accuracy according * to these scaled design metrics then the rasterization would * ideally need to be adjusted for each possible sub-pixel origin. * <p> * Unfortunately, scaling each glyph customized to its exact * subpixel origin during text layout would be prohibitively * expensive so a simplified system based on integer device * positions is typically used to lay out the text. * The rasterization of the glyph and the scaled advance width * are both adjusted together to yield text that looks good at * device resolution and has consistent integer pixel distances * between glyphs that help the glyphs look uniformly and * consistently spaced and readable. * <p> * This process of rounding advance widths for rasterized glyphs * to integer distances means that the character density and the * overall length of a string of text will be different from the * theoretical design measurements due to the accumulation of * a series of small differences in the adjusted widths of * each glyph. * The specific differences will be different for each glyph, * some being wider and some being narrower than their theoretical * design measurements. * Thus the overall difference in character density and length * will vary by a number of factors including the font, the * specific device resolution being targeted, and the glyphs * chosen to represent the string being rendered. * As a result, rendering the same string at multiple device * resolutions can yield widely varying metrics for whole strings. * <p> * When {@code FRACTIONALMETRICS} are enabled, the true font design * metrics are scaled by the point size and used for layout with * sub-pixel accuracy. * The average density of glyphs and total length of a long * string of characters will therefore more closely match the * theoretical design of the font, but readability may be affected * since individual pairs of characters may not always appear to * be consistent distances apart depending on how the sub-pixel * accumulation of the glyph origins meshes with the device pixel * grid. * Enabling this hint may be desirable when text layout is being * performed that must be consistent across a wide variety of * output resolutions. * Specifically, this hint may be desirable in situations where * the layout of text is being previewed on a low resolution * device like a screen for output that will eventually be * rendered on a high resolution printer or typesetting device. * <p> * When disabled, the scaled design metrics are rounded or adjusted * to integer distances for layout. * The distances between any specific pair of glyphs will be more * uniform on the device, but the density and total length of long * strings may no longer match the theoretical intentions of the * font designer. * Disabling this hint will typically produce more readable results * on low resolution devices like computer monitors. * <p> * The allowable values for this key are * <ul> * <li>{@link #VALUE_FRACTIONALMETRICS_OFF} * <li>{@link #VALUE_FRACTIONALMETRICS_ON} * <li>{@link #VALUE_FRACTIONALMETRICS_DEFAULT} * </ul> */ public static final Key KEY_FRACTIONALMETRICS = SunHints.KEY_FRACTIONALMETRICS; /** * Font fractional metrics hint value -- character glyphs are * positioned with advance widths rounded to pixel boundaries. * @see #KEY_FRACTIONALMETRICS */ public static final Object VALUE_FRACTIONALMETRICS_OFF = SunHints.VALUE_FRACTIONALMETRICS_OFF; /** * Font fractional metrics hint value -- character glyphs are * positioned with sub-pixel accuracy. * @see #KEY_FRACTIONALMETRICS */ public static final Object VALUE_FRACTIONALMETRICS_ON = SunHints.VALUE_FRACTIONALMETRICS_ON; /** * Font fractional metrics hint value -- character glyphs are * positioned with accuracy chosen by the implementation. * @see #KEY_FRACTIONALMETRICS */ public static final Object VALUE_FRACTIONALMETRICS_DEFAULT = SunHints.VALUE_FRACTIONALMETRICS_DEFAULT; /** * Interpolation hint key. * The {@code INTERPOLATION} hint controls how image pixels are * filtered or resampled during an image rendering operation. * <p> * Implicitly images are defined to provide color samples at * integer coordinate locations. * When images are rendered upright with no scaling onto a * destination, the choice of which image pixels map to which * device pixels is obvious and the samples at the integer * coordinate locations in the image are transferred to the * pixels at the corresponding integer locations on the device * pixel grid one for one. * When images are rendered in a scaled, rotated, or otherwise * transformed coordinate system, then the mapping of device * pixel coordinates back to the image can raise the question * of what color sample to use for the continuous coordinates * that lie between the integer locations of the provided image * samples. * Interpolation algorithms define functions which provide a * color sample for any continuous coordinate in an image based * on the color samples at the surrounding integer coordinates. * <p> * The allowable values for this hint are * <ul> * <li>{@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR} * <li>{@link #VALUE_INTERPOLATION_BILINEAR} * <li>{@link #VALUE_INTERPOLATION_BICUBIC} * </ul> */ public static final Key KEY_INTERPOLATION = SunHints.KEY_INTERPOLATION; /** * Interpolation hint value -- the color sample of the nearest * neighboring integer coordinate sample in the image is used. * Conceptually the image is viewed as a grid of unit-sized * square regions of color centered around the center of each * image pixel. * <p> * As the image is scaled up, it will look correspondingly blocky. * As the image is scaled down, the colors for source pixels will * be either used unmodified, or skipped entirely in the output * representation. * * @see #KEY_INTERPOLATION */ public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR = SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; /** * Interpolation hint value -- the color samples of the 4 nearest * neighboring integer coordinate samples in the image are * interpolated linearly to produce a color sample. * Conceptually the image is viewed as a set of infinitely small * point color samples which have value only at the centers of * integer coordinate pixels and the space between those pixel * centers is filled with linear ramps of colors that connect * adjacent discrete samples in a straight line. * <p> * As the image is scaled up, there are no blocky edges between * the colors in the image as there are with * {@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR NEAREST_NEIGHBOR}, * but the blending may show some subtle discontinuities along the * horizontal and vertical edges that line up with the samples * caused by a sudden change in the slope of the interpolation * from one side of a sample to the other. * As the image is scaled down, more image pixels have their * color samples represented in the resulting output since each * output pixel receives color information from up to 4 image * pixels. * * @see #KEY_INTERPOLATION */ public static final Object VALUE_INTERPOLATION_BILINEAR = SunHints.VALUE_INTERPOLATION_BILINEAR; /** * Interpolation hint value -- the color samples of 9 nearby * integer coordinate samples in the image are interpolated using * a cubic function in both {@code X} and {@code Y} to produce * a color sample. * Conceptually the view of the image is very similar to the view * used in the {@link #VALUE_INTERPOLATION_BILINEAR BILINEAR} * algorithm except that the ramps of colors that connect between * the samples are curved and have better continuity of slope * as they cross over between sample boundaries. * <p> * As the image is scaled up, there are no blocky edges and the * interpolation should appear smoother and with better depictions * of any edges in the original image than with {@code BILINEAR}. * As the image is scaled down, even more of the original color * samples from the original image will have their color information * carried through and represented. * * @see #KEY_INTERPOLATION */ public static final Object VALUE_INTERPOLATION_BICUBIC = SunHints.VALUE_INTERPOLATION_BICUBIC; /** * Alpha interpolation hint key. * The {@code ALPHA_INTERPOLATION} hint is a general hint that * provides a high level recommendation as to whether to bias * alpha blending algorithm choices more for speed or quality * when evaluating tradeoffs. * <p> * This hint could control the choice of alpha blending * calculations that sacrifice some precision to use fast * lookup tables or lower precision SIMD instructions. * This hint could also control whether or not the color * and alpha values are converted into a linear color space * during the calculations for a more linear visual effect * at the expense of additional per-pixel calculations. * <p> * The allowable values for this hint are * <ul> * <li>{@link #VALUE_ALPHA_INTERPOLATION_SPEED} * <li>{@link #VALUE_ALPHA_INTERPOLATION_QUALITY} * <li>{@link #VALUE_ALPHA_INTERPOLATION_DEFAULT} * </ul> */ public static final Key KEY_ALPHA_INTERPOLATION = SunHints.KEY_ALPHA_INTERPOLATION; /** * Alpha interpolation hint value -- alpha blending algorithms * are chosen with a preference for calculation speed. * @see #KEY_ALPHA_INTERPOLATION */ public static final Object VALUE_ALPHA_INTERPOLATION_SPEED = SunHints.VALUE_ALPHA_INTERPOLATION_SPEED; /** * Alpha interpolation hint value -- alpha blending algorithms * are chosen with a preference for precision and visual quality. * @see #KEY_ALPHA_INTERPOLATION */ public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY = SunHints.VALUE_ALPHA_INTERPOLATION_QUALITY; /** * Alpha interpolation hint value -- alpha blending algorithms * are chosen by the implementation for a good tradeoff of * performance vs. quality. * @see #KEY_ALPHA_INTERPOLATION */ public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT = SunHints.VALUE_ALPHA_INTERPOLATION_DEFAULT; /** * Color rendering hint key. * The {@code COLOR_RENDERING} hint controls the accuracy of * approximation and conversion when storing colors into a * destination image or surface. * <p> * When a rendering or image manipulation operation produces * a color value that must be stored into a destination, it * must first convert that color into a form suitable for * storing into the destination image or surface. * Minimally, the color components must be converted to bit * representations and ordered in the correct order or an * index into a color lookup table must be chosen before * the data can be stored into the destination memory. * Without this minimal conversion, the data in the destination * would likely represent random, incorrect or possibly even * unsupported values. * Algorithms to quickly convert the results of rendering * operations into the color format of most common destinations * are well known and fairly optimal to execute. * <p> * Simply performing the most basic color format conversion to * store colors into a destination can potentially ignore a * difference in the calibration of the * {@link java.awt.color.ColorSpace} * of the source and destination or other factors such as the * linearity of the gamma correction. * Unless the source and destination {@code ColorSpace} are * identical, to correctly perform a rendering operation with * the most care taken for the accuracy of the colors being * represented, the source colors should be converted to a * device independent {@code ColorSpace} and the results then * converted back to the destination {@code ColorSpace}. * Furthermore, if calculations such as the blending of multiple * source colors are to be performed during the rendering * operation, greater visual clarity can be achieved if the * intermediate device independent {@code ColorSpace} is * chosen to have a linear relationship between the values * being calculated and the perception of the human eye to * the response curves of the output device. * <p> * The allowable values for this hint are * <ul> * <li>{@link #VALUE_COLOR_RENDER_SPEED} * <li>{@link #VALUE_COLOR_RENDER_QUALITY} * <li>{@link #VALUE_COLOR_RENDER_DEFAULT} * </ul> */ public static final Key KEY_COLOR_RENDERING = SunHints.KEY_COLOR_RENDERING; /** * Color rendering hint value -- perform the fastest color * conversion to the format of the output device. * @see #KEY_COLOR_RENDERING */ public static final Object VALUE_COLOR_RENDER_SPEED = SunHints.VALUE_COLOR_RENDER_SPEED; /** * Color rendering hint value -- perform the color conversion * calculations with the highest accuracy and visual quality. * @see #KEY_COLOR_RENDERING */ public static final Object VALUE_COLOR_RENDER_QUALITY = SunHints.VALUE_COLOR_RENDER_QUALITY; /** * Color rendering hint value -- perform color conversion * calculations as chosen by the implementation to represent * the best available tradeoff between performance and * accuracy. * @see #KEY_COLOR_RENDERING */ public static final Object VALUE_COLOR_RENDER_DEFAULT = SunHints.VALUE_COLOR_RENDER_DEFAULT; /** * Stroke normalization control hint key. * The {@code STROKE_CONTROL} hint controls whether a rendering * implementation should or is allowed to modify the geometry * of rendered shapes for various purposes. * <p> * Some implementations may be able to use an optimized platform * rendering library which may be faster than traditional software * rendering algorithms on a given platform, but which may also * not support floating point coordinates. * Some implementations may also have sophisticated algorithms * which perturb the coordinates of a path so that wide lines * appear more uniform in width and spacing. * <p> * If an implementation performs any type of modification or * "normalization" of a path, it should never move the coordinates * by more than half a pixel in any direction. * <p> * The allowable values for this hint are * <ul> * <li>{@link #VALUE_STROKE_NORMALIZE} * <li>{@link #VALUE_STROKE_PURE} * <li>{@link #VALUE_STROKE_DEFAULT} * </ul> * @since 1.3 */ public static final Key KEY_STROKE_CONTROL = SunHints.KEY_STROKE_CONTROL; /** * Stroke normalization control hint value -- geometry may be * modified or left pure depending on the tradeoffs in a given * implementation. * Typically this setting allows an implementation to use a fast * integer coordinate based platform rendering library, but does * not specifically request normalization for uniformity or * aesthetics. * * @see #KEY_STROKE_CONTROL * @since 1.3 */ public static final Object VALUE_STROKE_DEFAULT = SunHints.VALUE_STROKE_DEFAULT; /** * Stroke normalization control hint value -- geometry should * be normalized to improve uniformity or spacing of lines and * overall aesthetics. * Note that different normalization algorithms may be more * successful than others for given input paths. * * @see #KEY_STROKE_CONTROL * @since 1.3 */ public static final Object VALUE_STROKE_NORMALIZE = SunHints.VALUE_STROKE_NORMALIZE; /** * Stroke normalization control hint value -- geometry should * be left unmodified and rendered with sub-pixel accuracy. * * @see #KEY_STROKE_CONTROL * @since 1.3 */ public static final Object VALUE_STROKE_PURE = SunHints.VALUE_STROKE_PURE; /** * Image resolution variant hint key. * The {@code RESOLUTION_VARIANT} hint controls which image resolution * variant should be chosen for image drawing. * * <ul> * <li>{@link #VALUE_RESOLUTION_VARIANT_DEFAULT} * <li>{@link #VALUE_RESOLUTION_VARIANT_BASE} * <li>{@link #VALUE_RESOLUTION_VARIANT_SIZE_FIT} * <li>{@link #VALUE_RESOLUTION_VARIANT_DPI_FIT} * </ul> * @since 9 */ public static final Key KEY_RESOLUTION_VARIANT = SunHints.KEY_RESOLUTION_VARIANT; /** * Image resolution variant hint value -- an image resolution variant is * chosen based on a default heuristic which may depend on the policies * of the platform * * @see #KEY_RESOLUTION_VARIANT * @since 9 */ public static final Object VALUE_RESOLUTION_VARIANT_DEFAULT = SunHints.VALUE_RESOLUTION_VARIANT_DEFAULT; /** * Image resolution variant hint value -- the standard resolution of an image * is always used. * * @see #KEY_RESOLUTION_VARIANT * @since 9 */ public static final Object VALUE_RESOLUTION_VARIANT_BASE = SunHints.VALUE_RESOLUTION_VARIANT_BASE; /** * Image resolution variant hint value -- an image resolution variant is * chosen based on the DPI of the screen and the transform in the Graphics2D * context. * * @see #KEY_RESOLUTION_VARIANT * @since 9 */ public static final Object VALUE_RESOLUTION_VARIANT_SIZE_FIT = SunHints.VALUE_RESOLUTION_VARIANT_SIZE_FIT; /** * Image resolution variant hint value -- an image resolution variant is * chosen based only on the DPI of the screen. * * @see #KEY_RESOLUTION_VARIANT * @since 9 */ public static final Object VALUE_RESOLUTION_VARIANT_DPI_FIT = SunHints.VALUE_RESOLUTION_VARIANT_DPI_FIT; /** * Constructs a new object with keys and values initialized * from the specified Map object which may be null. * @param init a map of key/value pairs to initialize the hints * or null if the object should be empty */ public RenderingHints(Map<Key, ?> init) { if (init != null) { hintmap.putAll(init); } } /** * Constructs a new object with the specified key/value pair. * @param key the key of the particular hint property * @param value the value of the hint property specified with * {@code key} */ public RenderingHints(Key key, Object value) { hintmap.put(key, value); } /** * Returns the number of key-value mappings in this * {@code RenderingHints}. * * @return the number of key-value mappings in this * {@code RenderingHints}. */ public int size() { return hintmap.size(); } /** * Returns {@code true} if this * {@code RenderingHints} contains no key-value mappings. * * @return {@code true} if this * {@code RenderingHints} contains no key-value mappings. */ public boolean isEmpty() { return hintmap.isEmpty(); } /** * Returns {@code true} if this {@code RenderingHints} * contains a mapping for the specified key. * * @param key key whose presence in this * {@code RenderingHints} is to be tested. * @return {@code true} if this {@code RenderingHints} * contains a mapping for the specified key. * @exception ClassCastException if the key can not * be cast to {@code RenderingHints.Key} */ public boolean containsKey(Object key) { return hintmap.containsKey((Key) key); } /** * Returns true if this RenderingHints maps one or more keys to the * specified value. * More formally, returns {@code true} if and only * if this {@code RenderingHints} * contains at least one mapping to a value {@code v} such that * <pre> * (value==null ? v==null : value.equals(v)) * </pre>. * This operation will probably require time linear in the * {@code RenderingHints} size for most implementations * of {@code RenderingHints}. * * @param value value whose presence in this * {@code RenderingHints} is to be tested. * @return {@code true} if this {@code RenderingHints} * maps one or more keys to the specified value. */ public boolean containsValue(Object value) { return hintmap.containsValue(value); } /** * Returns the value to which the specified key is mapped. * @param key a rendering hint key * @return the value to which the key is mapped in this object or * {@code null} if the key is not mapped to any value in * this object. * @exception ClassCastException if the key can not * be cast to {@code RenderingHints.Key} * @see #put(Object, Object) */ public Object get(Object key) { return hintmap.get((Key) key); } /** * Maps the specified {@code key} to the specified * {@code value} in this {@code RenderingHints} object. * Neither the key nor the value can be {@code null}. * The value can be retrieved by calling the {@code get} method * with a key that is equal to the original key. * @param key the rendering hint key. * @param value the rendering hint value. * @return the previous value of the specified key in this object * or {@code null} if it did not have one. * @exception NullPointerException if the key is * {@code null}. * @exception ClassCastException if the key can not * be cast to {@code RenderingHints.Key} * @exception IllegalArgumentException if the * {@link Key#isCompatibleValue(java.lang.Object) * Key.isCompatibleValue()} * method of the specified key returns false for the * specified value * @see #get(Object) */ public Object put(Object key, Object value) { if (!((Key) key).isCompatibleValue(value)) { throw new IllegalArgumentException(value + " incompatible with " + key); } return hintmap.put((Key) key, value); } /** * Adds all of the keys and corresponding values from the specified * {@code RenderingHints} object to this * {@code RenderingHints} object. Keys that are present in * this {@code RenderingHints} object, but not in the specified * {@code RenderingHints} object are not affected. * @param hints the set of key/value pairs to be added to this * {@code RenderingHints} object */ public void add(RenderingHints hints) { hintmap.putAll(hints.hintmap); } /** * Clears this {@code RenderingHints} object of all key/value * pairs. */ public void clear() { hintmap.clear(); } /** * Removes the key and its corresponding value from this * {@code RenderingHints} object. This method does nothing if the * key is not in this {@code RenderingHints} object. * @param key the rendering hints key that needs to be removed * @exception ClassCastException if the key can not * be cast to {@code RenderingHints.Key} * @return the value to which the key had previously been mapped in this * {@code RenderingHints} object, or {@code null} * if the key did not have a mapping. */ public Object remove(Object key) { return hintmap.remove((Key) key); } /** * Copies all of the mappings from the specified {@code Map} * to this {@code RenderingHints}. These mappings replace * any mappings that this {@code RenderingHints} had for any * of the keys currently in the specified {@code Map}. * @param m the specified {@code Map} * @exception ClassCastException class of a key or value * in the specified {@code Map} prevents it from being * stored in this {@code RenderingHints}. * @exception IllegalArgumentException some aspect * of a key or value in the specified {@code Map} * prevents it from being stored in * this {@code RenderingHints}. */ public void putAll(Map<?, ?> m) { // ## javac bug? //if (m instanceof RenderingHints) { if (RenderingHints.class.isInstance(m)) { //hintmap.putAll(((RenderingHints) m).hintmap); for (Map.Entry<?, ?> entry : m.entrySet()) hintmap.put(entry.getKey(), entry.getValue()); } else { // Funnel each key/value pair through our protected put method for (Map.Entry<?, ?> entry : m.entrySet()) put(entry.getKey(), entry.getValue()); } } /** * Returns a {@code Set} view of the Keys contained in this * {@code RenderingHints}. The Set is backed by the * {@code RenderingHints}, so changes to the * {@code RenderingHints} are reflected in the {@code Set}, * and vice-versa. If the {@code RenderingHints} is modified * while an iteration over the {@code Set} is in progress, * the results of the iteration are undefined. The {@code Set} * supports element removal, which removes the corresponding * mapping from the {@code RenderingHints}, via the * {@code Iterator.remove}, {@code Set.remove}, * {@code removeAll retainAll}, and * {@code clear} operations. It does not support * the {@code add} or {@code addAll} operations. * * @return a {@code Set} view of the keys contained * in this {@code RenderingHints}. */ public Set<Object> keySet() { return hintmap.keySet(); } /** * Returns a {@code Collection} view of the values * contained in this {@code RenderingHints}. * The {@code Collection} is backed by the * {@code RenderingHints}, so changes to * the {@code RenderingHints} are reflected in * the {@code Collection}, and vice-versa. * If the {@code RenderingHints} is modified while * an iteration over the {@code Collection} is * in progress, the results of the iteration are undefined. * The {@code Collection} supports element removal, * which removes the corresponding mapping from the * {@code RenderingHints}, via the * {@code Iterator.remove}, * {@code Collection.remove}, {@code removeAll}, * {@code retainAll} and {@code clear} operations. * It does not support the {@code add} or * {@code addAll} operations. * * @return a {@code Collection} view of the values * contained in this {@code RenderingHints}. */ public Collection<Object> values() { return hintmap.values(); } /** * Returns a {@code Set} view of the mappings contained * in this {@code RenderingHints}. Each element in the * returned {@code Set} is a {@code Map.Entry}. * The {@code Set} is backed by the {@code RenderingHints}, * so changes to the {@code RenderingHints} are reflected * in the {@code Set}, and vice-versa. If the * {@code RenderingHints} is modified while * while an iteration over the {@code Set} is in progress, * the results of the iteration are undefined. * <p> * The entrySet returned from a {@code RenderingHints} object * is not modifiable. * * @return a {@code Set} view of the mappings contained in * this {@code RenderingHints}. */ public Set<Map.Entry<Object, Object>> entrySet() { return Collections.unmodifiableMap(hintmap).entrySet(); } /** * Compares the specified {@code Object} with this * {@code RenderingHints} for equality. * Returns {@code true} if the specified object is also a * {@code Map} and the two {@code Map} objects represent * the same mappings. More formally, two {@code Map} objects * {@code t1} and {@code t2} represent the same mappings * if {@code t1.keySet().equals(t2.keySet())} and for every * key {@code k} in {@code t1.keySet()}, * <pre> * (t1.get(k)==null ? t2.get(k)==null : t1.get(k).equals(t2.get(k))) * </pre>. * This ensures that the {@code equals} method works properly across * different implementations of the {@code Map} interface. * * @param o {@code Object} to be compared for equality with * this {@code RenderingHints}. * @return {@code true} if the specified {@code Object} * is equal to this {@code RenderingHints}. */ public boolean equals(Object o) { if (o instanceof RenderingHints) { return hintmap.equals(((RenderingHints) o).hintmap); } else if (o instanceof Map) { return hintmap.equals(o); } return false; } /** * Returns the hash code value for this {@code RenderingHints}. * The hash code of a {@code RenderingHints} is defined to be * the sum of the hashCodes of each {@code Entry} in the * {@code RenderingHints} object's entrySet view. This ensures that * {@code t1.equals(t2)} implies that * {@code t1.hashCode()==t2.hashCode()} for any two {@code Map} * objects {@code t1} and {@code t2}, as required by the general * contract of {@code Object.hashCode}. * * @return the hash code value for this {@code RenderingHints}. * @see java.util.Map.Entry#hashCode() * @see Object#hashCode() * @see Object#equals(Object) * @see #equals(Object) */ public int hashCode() { return hintmap.hashCode(); } /** * Creates a clone of this {@code RenderingHints} object * that has the same contents as this {@code RenderingHints} * object. * @return a clone of this instance. */ @SuppressWarnings("unchecked") public Object clone() { RenderingHints rh; try { rh = (RenderingHints) super.clone(); if (hintmap != null) { rh.hintmap = (HashMap<Object, Object>) hintmap.clone(); } } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } return rh; } /** * Returns a rather long string representation of the hashmap * which contains the mappings of keys to values for this * {@code RenderingHints} object. * @return a string representation of this object. */ public String toString() { if (hintmap == null) { return getClass().getName() + "@" + Integer.toHexString(hashCode()) + " (0 hints)"; } return hintmap.toString(); } }