- /*
- * @(#)RenderingHints.java 1.21 04/05/05
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- 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</code> class contains rendering hints that can
- * be used by the {@link java.awt.Graphics2D} class, and classes that
- * implement {@link java.awt.image.BufferedImageOp} and
- * {@link java.awt.image.Raster}.
- */
- public class RenderingHints
- implements Map<Object,Object>, Cloneable
- {
- /**
- * Defines the base type of all keys used to control various
- * aspects of the rendering and imaging pipelines. Instances
- * of this class are immutable and unique which means that
- * tests for matches can be made using the == operator instead
- * of the more expensive 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 System.identityHashCode(this);
- }
-
- /**
- * 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.
- */
- public static final Key KEY_ANTIALIASING =
- SunHints.KEY_ANTIALIASING;
-
- /**
- * Antialiasing hint values -- rendering is done with antialiasing.
- */
- public static final Object VALUE_ANTIALIAS_ON =
- SunHints.VALUE_ANTIALIAS_ON;
-
- /**
- * Antialiasing hint values -- rendering is done without antialiasing.
- */
- public static final Object VALUE_ANTIALIAS_OFF =
- SunHints.VALUE_ANTIALIAS_OFF;
-
- /**
- * Antialiasing hint values -- rendering is done with the platform
- * default antialiasing mode.
- */
- public static final Object VALUE_ANTIALIAS_DEFAULT =
- SunHints.VALUE_ANTIALIAS_DEFAULT;
-
- /**
- * Rendering hint key.
- */
- public static final Key KEY_RENDERING =
- SunHints.KEY_RENDERING;
-
- /**
- * Rendering hint values -- Appropriate rendering algorithms are chosen
- * with a preference for output speed.
- */
- public static final Object VALUE_RENDER_SPEED =
- SunHints.VALUE_RENDER_SPEED;
-
- /**
- * Rendering hint values -- Appropriate rendering algorithms are chosen
- * with a preference for output quality.
- */
- public static final Object VALUE_RENDER_QUALITY =
- SunHints.VALUE_RENDER_QUALITY;
-
- /**
- * Rendering hint values -- The platform default rendering algorithms
- * are chosen.
- */
- public static final Object VALUE_RENDER_DEFAULT =
- SunHints.VALUE_RENDER_DEFAULT;
-
-
- /**
- * Dithering hint key.
- */
- public static final Key KEY_DITHERING =
- SunHints.KEY_DITHERING;
-
- /**
- * Dithering hint values -- do not dither when rendering.
- */
- public static final Object VALUE_DITHER_DISABLE =
- SunHints.VALUE_DITHER_DISABLE;
-
- /**
- * Dithering hint values -- dither when rendering, if needed.
- */
- public static final Object VALUE_DITHER_ENABLE =
- SunHints.VALUE_DITHER_ENABLE;
-
- /**
- * Dithering hint values -- use the platform default for dithering.
- */
- public static final Object VALUE_DITHER_DEFAULT =
- SunHints.VALUE_DITHER_DEFAULT;
-
- /**
- * Text antialiasing hint key.
- */
- public static final Key KEY_TEXT_ANTIALIASING =
- SunHints.KEY_TEXT_ANTIALIASING;
-
- /**
- * Text antialiasing hint value -- text rendering is done with
- * antialiasing.
- */
- public static final Object VALUE_TEXT_ANTIALIAS_ON =
- SunHints.VALUE_TEXT_ANTIALIAS_ON;
-
- /**
- * Text antialiasing hint value -- text rendering is done without
- * antialiasing.
- */
- public static final Object VALUE_TEXT_ANTIALIAS_OFF =
- SunHints.VALUE_TEXT_ANTIALIAS_OFF;
-
- /**
- * Text antialiasing hint value -- text rendering is done using the
- * platform default text antialiasing mode.
- */
- public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT =
- SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
-
- /**
- * Font fractional metrics hint key.
- */
- public static final Key KEY_FRACTIONALMETRICS =
- SunHints.KEY_FRACTIONALMETRICS;
-
- /**
- * Font fractional metrics hint values -- fractional metrics disabled.
- */
- public static final Object VALUE_FRACTIONALMETRICS_OFF =
- SunHints.VALUE_FRACTIONALMETRICS_OFF;
-
- /**
- * Font fractional metrics hint values -- fractional metrics enabled.
- */
- public static final Object VALUE_FRACTIONALMETRICS_ON =
- SunHints.VALUE_FRACTIONALMETRICS_ON;
-
- /**
- * Font fractional metrics hint values -- use the platform default for
- * fractional metrics.
- */
- public static final Object VALUE_FRACTIONALMETRICS_DEFAULT =
- SunHints.VALUE_FRACTIONALMETRICS_DEFAULT;
-
-
- /**
- * Interpolation hint key.
- */
- public static final Key KEY_INTERPOLATION =
- SunHints.KEY_INTERPOLATION;
-
- /**
- * Interpolation hint value -- INTERPOLATION_NEAREST_NEIGHBOR.
- */
- public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR =
- SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
-
- /**
- * Interpolation hint value -- INTERPOLATION_BILINEAR.
- */
- public static final Object VALUE_INTERPOLATION_BILINEAR =
- SunHints.VALUE_INTERPOLATION_BILINEAR;
-
- /**
- * Interpolation hint value -- INTERPOLATION_BICUBIC.
- */
- public static final Object VALUE_INTERPOLATION_BICUBIC =
- SunHints.VALUE_INTERPOLATION_BICUBIC;
-
- /**
- * Alpha interpolation hint key.
- */
- public static final Key KEY_ALPHA_INTERPOLATION =
- SunHints.KEY_ALPHA_INTERPOLATION;
-
- /**
- * Alpha interpolation hint value -- ALPHA_INTERPOLATION_SPEED.
- */
- public static final Object VALUE_ALPHA_INTERPOLATION_SPEED =
- SunHints.VALUE_ALPHA_INTERPOLATION_SPEED;
-
- /**
- * Alpha interpolation hint value -- ALPHA_INTERPOLATION_QUALITY.
- */
- public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY =
- SunHints.VALUE_ALPHA_INTERPOLATION_QUALITY;
-
- /**
- * Alpha interpolation hint value -- ALPHA_INTERPOLATION_DEFAULT.
- */
- public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT =
- SunHints.VALUE_ALPHA_INTERPOLATION_DEFAULT;
-
- /**
- * Color rendering hint key.
- */
- public static final Key KEY_COLOR_RENDERING =
- SunHints.KEY_COLOR_RENDERING;
-
- /**
- * Color rendering hint value -- COLOR_RENDER_SPEED.
- */
- public static final Object VALUE_COLOR_RENDER_SPEED =
- SunHints.VALUE_COLOR_RENDER_SPEED;
-
- /**
- * Color rendering hint value -- COLOR_RENDER_QUALITY.
- */
- public static final Object VALUE_COLOR_RENDER_QUALITY =
- SunHints.VALUE_COLOR_RENDER_QUALITY;
-
- /**
- * Color rendering hint value -- COLOR_RENDER_DEFAULT.
- */
- public static final Object VALUE_COLOR_RENDER_DEFAULT =
- SunHints.VALUE_COLOR_RENDER_DEFAULT;
-
- /**
- * Stroke normalization control hint key.
- */
- public static final Key KEY_STROKE_CONTROL =
- SunHints.KEY_STROKE_CONTROL;
-
- /**
- * Stroke normalization control hint value -- STROKE_DEFAULT.
- */
- public static final Object VALUE_STROKE_DEFAULT =
- SunHints.VALUE_STROKE_DEFAULT;
-
- /**
- * Stroke normalization control hint value -- STROKE_NORMALIZE.
- */
- public static final Object VALUE_STROKE_NORMALIZE =
- SunHints.VALUE_STROKE_NORMALIZE;
-
- /**
- * Stroke normalization control hint value -- STROKE_PURE.
- */
- 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> key is not
- * of type <code>RenderingHints.Key</code>
- * @exception <code>NullPointerException</code>
- * key is <code>null</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> key is not of
- * type <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 or value is
- * <code>null</code>.
- * @exception <code>ClassCastException</code> key is not of
- * type <code>RenderingHints.Key</code>.
- * @exception <code>IllegalArgumentException</code> value is not
- * appropriate for the specified key.
- * @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> key is not of
- * type <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();
- }
- }