blob: 7d33dbe3f5a8d3e54993979addf36ce587e1f0e6 [file] [log] [blame]
/*
* Copyright (c) 1998, 2006, 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 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 occurence 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 synchronized static 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(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</code> to test for validity
* @return <code>true</code> if <code>val</code> is valid;
* <code>false</code> 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 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</code> 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 transfered 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 recieves 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;
/**
* 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</code>
*/
public RenderingHints(Key key, Object value) {
hintmap.put(key, value);
}
/**
* Returns the number of key-value mappings in this
* <code>RenderingHints</code>.
*
* @return the number of key-value mappings in this
* <code>RenderingHints</code>.
*/
public int size() {
return hintmap.size();
}
/**
* Returns <code>true</code> if this
* <code>RenderingHints</code> contains no key-value mappings.
*
* @return <code>true</code> if this
* <code>RenderingHints</code> contains no key-value mappings.
*/
public boolean isEmpty() {
return hintmap.isEmpty();
}
/**
* Returns <code>true</code> if this <code>RenderingHints</code>
* contains a mapping for the specified key.
*
* @param key key whose presence in this
* <code>RenderingHints</code> is to be tested.
* @return <code>true</code> if this <code>RenderingHints</code>
* contains a mapping for the specified key.
* @exception <code>ClassCastException</code> if the key can not
* be cast to <code>RenderingHints.Key</code>
*/
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</code> if and only
* if this <code>RenderingHints</code>
* contains at least one mapping to a value <code>v</code> such that
* <pre>
* (value==null ? v==null : value.equals(v))
* </pre>.
* This operation will probably require time linear in the
* <code>RenderingHints</code> size for most implementations
* of <code>RenderingHints</code>.
*
* @param value value whose presence in this
* <code>RenderingHints</code> is to be tested.
* @return <code>true</code> if this <code>RenderingHints</code>
* 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</code> if the key is not mapped to any value in
* this object.
* @exception <code>ClassCastException</code> if the key can not
* be cast to <code>RenderingHints.Key</code>
* @see #put(Object, Object)
*/
public Object get(Object key) {
return hintmap.get((Key) key);
}
/**
* Maps the specified <code>key</code> to the specified
* <code>value</code> in this <code>RenderingHints</code> object.
* Neither the key nor the value can be <code>null</code>.
* The value can be retrieved by calling the <code>get</code> 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</code> if it did not have one.
* @exception <code>NullPointerException</code> if the key is
* <code>null</code>.
* @exception <code>ClassCastException</code> if the key can not
* be cast to <code>RenderingHints.Key</code>
* @exception <code>IllegalArgumentException</code> 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</code> object to this
* <code>RenderingHints</code> object. Keys that are present in
* this <code>RenderingHints</code> object, but not in the specified
* <code>RenderingHints</code> object are not affected.
* @param hints the set of key/value pairs to be added to this
* <code>RenderingHints</code> object
*/
public void add(RenderingHints hints) {
hintmap.putAll(hints.hintmap);
}
/**
* Clears this <code>RenderingHints</code> object of all key/value
* pairs.
*/
public void clear() {
hintmap.clear();
}
/**
* Removes the key and its corresponding value from this
* <code>RenderingHints</code> object. This method does nothing if the
* key is not in this <code>RenderingHints</code> object.
* @param key the rendering hints key that needs to be removed
* @exception <code>ClassCastException</code> if the key can not
* be cast to <code>RenderingHints.Key</code>
* @return the value to which the key had previously been mapped in this
* <code>RenderingHints</code> object, or <code>null</code>
* 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</code>
* to this <code>RenderingHints</code>. These mappings replace
* any mappings that this <code>RenderingHints</code> had for any
* of the keys currently in the specified <code>Map</code>.
* @param m the specified <code>Map</code>
* @exception <code>ClassCastException</code> class of a key or value
* in the specified <code>Map</code> prevents it from being
* stored in this <code>RenderingHints</code>.
* @exception <code>IllegalArgumentException</code> some aspect
* of a key or value in the specified <code>Map</code>
* prevents it from being stored in
* this <code>RenderingHints</code>.
*/
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</code> view of the Keys contained in this
* <code>RenderingHints</code>. The Set is backed by the
* <code>RenderingHints</code>, so changes to the
* <code>RenderingHints</code> are reflected in the <code>Set</code>,
* and vice-versa. If the <code>RenderingHints</code> is modified
* while an iteration over the <code>Set</code> is in progress,
* the results of the iteration are undefined. The <code>Set</code>
* supports element removal, which removes the corresponding
* mapping from the <code>RenderingHints</code>, via the
* <code>Iterator.remove</code>, <code>Set.remove</code>,
* <code>removeAll</code> <code>retainAll</code>, and
* <code>clear</code> operations. It does not support
* the <code>add</code> or <code>addAll</code> operations.
*
* @return a <code>Set</code> view of the keys contained
* in this <code>RenderingHints</code>.
*/
public Set<Object> keySet() {
return hintmap.keySet();
}
/**
* Returns a <code>Collection</code> view of the values
* contained in this <code>RenderinHints</code>.
* The <code>Collection</code> is backed by the
* <code>RenderingHints</code>, so changes to
* the <code>RenderingHints</code> are reflected in
* the <code>Collection</code>, and vice-versa.
* If the <code>RenderingHints</code> is modified while
* an iteration over the <code>Collection</code> is
* in progress, the results of the iteration are undefined.
* The <code>Collection</code> supports element removal,
* which removes the corresponding mapping from the
* <code>RenderingHints</code>, via the
* <code>Iterator.remove</code>,
* <code>Collection.remove</code>, <code>removeAll</code>,
* <code>retainAll</code> and <code>clear</code> operations.
* It does not support the <code>add</code> or
* <code>addAll</code> operations.
*
* @return a <code>Collection</code> view of the values
* contained in this <code>RenderingHints</code>.
*/
public Collection<Object> values() {
return hintmap.values();
}
/**
* Returns a <code>Set</code> view of the mappings contained
* in this <code>RenderingHints</code>. Each element in the
* returned <code>Set</code> is a <code>Map.Entry</code>.
* The <code>Set</code> is backed by the <code>RenderingHints</code>,
* so changes to the <code>RenderingHints</code> are reflected
* in the <code>Set</code>, and vice-versa. If the
* <code>RenderingHints</code> is modified while
* while an iteration over the <code>Set</code> is in progress,
* the results of the iteration are undefined.
* <p>
* The entrySet returned from a <code>RenderingHints</code> object
* is not modifiable.
*
* @return a <code>Set</code> view of the mappings contained in
* this <code>RenderingHints</code>.
*/
public Set<Map.Entry<Object,Object>> entrySet() {
return Collections.unmodifiableMap(hintmap).entrySet();
}
/**
* Compares the specified <code>Object</code> with this
* <code>RenderingHints</code> for equality.
* Returns <code>true</code> if the specified object is also a
* <code>Map</code> and the two <code>Map</code> objects represent
* the same mappings. More formally, two <code>Map</code> objects
* <code>t1</code> and <code>t2</code> represent the same mappings
* if <code>t1.keySet().equals(t2.keySet())</code> and for every
* key <code>k</code> in <code>t1.keySet()</code>,
* <pre>
* (t1.get(k)==null ? t2.get(k)==null : t1.get(k).equals(t2.get(k)))
* </pre>.
* This ensures that the <code>equals</code> method works properly across
* different implementations of the <code>Map</code> interface.
*
* @param o <code>Object</code> to be compared for equality with
* this <code>RenderingHints</code>.
* @return <code>true</code> if the specified <code>Object</code>
* is equal to this <code>RenderingHints</code>.
*/
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</code>.
* The hash code of a <code>RenderingHints</code> is defined to be
* the sum of the hashCodes of each <code>Entry</code> in the
* <code>RenderingHints</code> object's entrySet view. This ensures that
* <code>t1.equals(t2)</code> implies that
* <code>t1.hashCode()==t2.hashCode()</code> for any two <code>Map</code>
* objects <code>t1</code> and <code>t2</code>, as required by the general
* contract of <code>Object.hashCode</code>.
*
* @return the hash code value for this <code>RenderingHints</code>.
* @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</code> object
* that has the same contents as this <code>RenderingHints</code>
* object.
* @return a clone of this instance.
*/
public Object clone() {
RenderingHints rh;
try {
rh = (RenderingHints) super.clone();
if (hintmap != null) {
rh.hintmap = (HashMap) hintmap.clone();
}
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
return rh;
}
/**
* Returns a rather long string representation of the hashmap
* which contains the mappings of keys to values for this
* <code>RenderingHints</code> 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();
}
}