75 * The keys used to control the hints are all special values that
76 * subclass the associated {@link RenderingHints.Key} class.
77 * Many common hints are expressed below as static constants in this
78 * class, but the list is not meant to be exhaustive.
79 * Other hints may be created by other packages by defining new objects
80 * which subclass the {@code Key} class and defining the associated values.
81 */
82 public class RenderingHints
83 implements Map<Object,Object>, Cloneable
84 {
85 /**
86 * Defines the base type of all keys used along with the
87 * {@link RenderingHints} class to control various
88 * algorithm choices in the rendering and imaging pipelines.
89 * Instances of this class are immutable and unique which
90 * means that tests for matches can be made using the
91 * {@code ==} operator instead of the more expensive
92 * {@code equals()} method.
93 */
94 public abstract static class Key {
95 private static HashMap identitymap = new HashMap(17);
96
97 private String getIdentity() {
98 // Note that the identity string is dependent on 3 variables:
99 // - the name of the subclass of Key
100 // - the identityHashCode of the subclass of Key
101 // - the integer key of the Key
102 // It is theoretically possible for 2 distinct keys to collide
103 // along all 3 of those attributes in the context of multiple
104 // class loaders, but that occurence will be extremely rare and
105 // we account for that possibility below in the recordIdentity
106 // method by slightly relaxing our uniqueness guarantees if we
107 // end up in that situation.
108 return getClass().getName()+"@"+
109 Integer.toHexString(System.identityHashCode(getClass()))+":"+
110 Integer.toHexString(privatekey);
111 }
112
113 private synchronized static void recordIdentity(Key k) {
114 Object identity = k.getIdentity();
115 Object otherref = identitymap.get(identity);
121 }
122 // Note that this system can fail in a mostly harmless
123 // way. If we end up generating the same identity
124 // String for 2 different classes (a very rare case)
125 // then we correctly avoid throwing the exception above,
126 // but we are about to drop through to a statement that
127 // will replace the entry for the old Key subclass with
128 // an entry for the new Key subclass. At that time the
129 // old subclass will be vulnerable to someone generating
130 // a duplicate Key instance for it. We could bail out
131 // of the method here and let the old identity keep its
132 // record in the map, but we are more likely to see a
133 // duplicate key go by for the new class than the old
134 // one since the new one is probably still in the
135 // initialization stage. In either case, the probability
136 // of loading 2 classes in the same VM with the same name
137 // and identityHashCode should be nearly impossible.
138 }
139 // Note: Use a weak reference to avoid holding on to extra
140 // objects and classes after they should be unloaded.
141 identitymap.put(identity, new WeakReference(k));
142 }
143
144 private int privatekey;
145
146 /**
147 * Construct a key using the indicated private key. Each
148 * subclass of Key maintains its own unique domain of integer
149 * keys. No two objects with the same integer key and of the
150 * same specific subclass can be constructed. An exception
151 * will be thrown if an attempt is made to construct another
152 * object of a given class with the same integer key as a
153 * pre-existing instance of that subclass of Key.
154 * @param privatekey the specified key
155 */
156 protected Key(int privatekey) {
157 this.privatekey = privatekey;
158 recordIdentity(this);
159 }
160
161 /**
178 }
179
180 /**
181 * The hash code for all Key objects will be the same as the
182 * system identity code of the object as defined by the
183 * System.identityHashCode() method.
184 */
185 public final int hashCode() {
186 return super.hashCode();
187 }
188
189 /**
190 * The equals method for all Key objects will return the same
191 * result as the equality operator '=='.
192 */
193 public final boolean equals(Object o) {
194 return this == o;
195 }
196 }
197
198 HashMap hintmap = new HashMap(7);
199
200 /**
201 * Antialiasing hint key.
202 * The {@code ANTIALIASING} hint controls whether or not the
203 * geometry rendering methods of a {@link Graphics2D} object
204 * will attempt to reduce aliasing artifacts along the edges
205 * of shapes.
206 * <p>
207 * A typical antialiasing algorithm works by blending the existing
208 * colors of the pixels along the boundary of a shape with the
209 * requested fill paint according to the estimated partial pixel
210 * coverage of the shape.
211 * <p>
212 * The allowable values for this hint are
213 * <ul>
214 * <li>{@link #VALUE_ANTIALIAS_ON}
215 * <li>{@link #VALUE_ANTIALIAS_OFF}
216 * <li>{@link #VALUE_ANTIALIAS_DEFAULT}
217 * </ul>
218 */
1250 * <code>t1.hashCode()==t2.hashCode()</code> for any two <code>Map</code>
1251 * objects <code>t1</code> and <code>t2</code>, as required by the general
1252 * contract of <code>Object.hashCode</code>.
1253 *
1254 * @return the hash code value for this <code>RenderingHints</code>.
1255 * @see java.util.Map.Entry#hashCode()
1256 * @see Object#hashCode()
1257 * @see Object#equals(Object)
1258 * @see #equals(Object)
1259 */
1260 public int hashCode() {
1261 return hintmap.hashCode();
1262 }
1263
1264 /**
1265 * Creates a clone of this <code>RenderingHints</code> object
1266 * that has the same contents as this <code>RenderingHints</code>
1267 * object.
1268 * @return a clone of this instance.
1269 */
1270 public Object clone() {
1271 RenderingHints rh;
1272 try {
1273 rh = (RenderingHints) super.clone();
1274 if (hintmap != null) {
1275 rh.hintmap = (HashMap) hintmap.clone();
1276 }
1277 } catch (CloneNotSupportedException e) {
1278 // this shouldn't happen, since we are Cloneable
1279 throw new InternalError(e);
1280 }
1281
1282 return rh;
1283 }
1284
1285 /**
1286 * Returns a rather long string representation of the hashmap
1287 * which contains the mappings of keys to values for this
1288 * <code>RenderingHints</code> object.
1289 * @return a string representation of this object.
1290 */
1291 public String toString() {
1292 if (hintmap == null) {
1293 return getClass().getName() + "@" +
1294 Integer.toHexString(hashCode()) +
1295 " (0 hints)";
|
75 * The keys used to control the hints are all special values that
76 * subclass the associated {@link RenderingHints.Key} class.
77 * Many common hints are expressed below as static constants in this
78 * class, but the list is not meant to be exhaustive.
79 * Other hints may be created by other packages by defining new objects
80 * which subclass the {@code Key} class and defining the associated values.
81 */
82 public class RenderingHints
83 implements Map<Object,Object>, Cloneable
84 {
85 /**
86 * Defines the base type of all keys used along with the
87 * {@link RenderingHints} class to control various
88 * algorithm choices in the rendering and imaging pipelines.
89 * Instances of this class are immutable and unique which
90 * means that tests for matches can be made using the
91 * {@code ==} operator instead of the more expensive
92 * {@code equals()} method.
93 */
94 public abstract static class Key {
95 private static HashMap<Object,Object> identitymap = new HashMap<>(17);
96
97 private String getIdentity() {
98 // Note that the identity string is dependent on 3 variables:
99 // - the name of the subclass of Key
100 // - the identityHashCode of the subclass of Key
101 // - the integer key of the Key
102 // It is theoretically possible for 2 distinct keys to collide
103 // along all 3 of those attributes in the context of multiple
104 // class loaders, but that occurence will be extremely rare and
105 // we account for that possibility below in the recordIdentity
106 // method by slightly relaxing our uniqueness guarantees if we
107 // end up in that situation.
108 return getClass().getName()+"@"+
109 Integer.toHexString(System.identityHashCode(getClass()))+":"+
110 Integer.toHexString(privatekey);
111 }
112
113 private synchronized static void recordIdentity(Key k) {
114 Object identity = k.getIdentity();
115 Object otherref = identitymap.get(identity);
121 }
122 // Note that this system can fail in a mostly harmless
123 // way. If we end up generating the same identity
124 // String for 2 different classes (a very rare case)
125 // then we correctly avoid throwing the exception above,
126 // but we are about to drop through to a statement that
127 // will replace the entry for the old Key subclass with
128 // an entry for the new Key subclass. At that time the
129 // old subclass will be vulnerable to someone generating
130 // a duplicate Key instance for it. We could bail out
131 // of the method here and let the old identity keep its
132 // record in the map, but we are more likely to see a
133 // duplicate key go by for the new class than the old
134 // one since the new one is probably still in the
135 // initialization stage. In either case, the probability
136 // of loading 2 classes in the same VM with the same name
137 // and identityHashCode should be nearly impossible.
138 }
139 // Note: Use a weak reference to avoid holding on to extra
140 // objects and classes after they should be unloaded.
141 identitymap.put(identity, new WeakReference<Key>(k));
142 }
143
144 private int privatekey;
145
146 /**
147 * Construct a key using the indicated private key. Each
148 * subclass of Key maintains its own unique domain of integer
149 * keys. No two objects with the same integer key and of the
150 * same specific subclass can be constructed. An exception
151 * will be thrown if an attempt is made to construct another
152 * object of a given class with the same integer key as a
153 * pre-existing instance of that subclass of Key.
154 * @param privatekey the specified key
155 */
156 protected Key(int privatekey) {
157 this.privatekey = privatekey;
158 recordIdentity(this);
159 }
160
161 /**
178 }
179
180 /**
181 * The hash code for all Key objects will be the same as the
182 * system identity code of the object as defined by the
183 * System.identityHashCode() method.
184 */
185 public final int hashCode() {
186 return super.hashCode();
187 }
188
189 /**
190 * The equals method for all Key objects will return the same
191 * result as the equality operator '=='.
192 */
193 public final boolean equals(Object o) {
194 return this == o;
195 }
196 }
197
198 HashMap<Object,Object> hintmap = new HashMap<>(7);
199
200 /**
201 * Antialiasing hint key.
202 * The {@code ANTIALIASING} hint controls whether or not the
203 * geometry rendering methods of a {@link Graphics2D} object
204 * will attempt to reduce aliasing artifacts along the edges
205 * of shapes.
206 * <p>
207 * A typical antialiasing algorithm works by blending the existing
208 * colors of the pixels along the boundary of a shape with the
209 * requested fill paint according to the estimated partial pixel
210 * coverage of the shape.
211 * <p>
212 * The allowable values for this hint are
213 * <ul>
214 * <li>{@link #VALUE_ANTIALIAS_ON}
215 * <li>{@link #VALUE_ANTIALIAS_OFF}
216 * <li>{@link #VALUE_ANTIALIAS_DEFAULT}
217 * </ul>
218 */
1250 * <code>t1.hashCode()==t2.hashCode()</code> for any two <code>Map</code>
1251 * objects <code>t1</code> and <code>t2</code>, as required by the general
1252 * contract of <code>Object.hashCode</code>.
1253 *
1254 * @return the hash code value for this <code>RenderingHints</code>.
1255 * @see java.util.Map.Entry#hashCode()
1256 * @see Object#hashCode()
1257 * @see Object#equals(Object)
1258 * @see #equals(Object)
1259 */
1260 public int hashCode() {
1261 return hintmap.hashCode();
1262 }
1263
1264 /**
1265 * Creates a clone of this <code>RenderingHints</code> object
1266 * that has the same contents as this <code>RenderingHints</code>
1267 * object.
1268 * @return a clone of this instance.
1269 */
1270 @SuppressWarnings("unchecked")
1271 public Object clone() {
1272 RenderingHints rh;
1273 try {
1274 rh = (RenderingHints) super.clone();
1275 if (hintmap != null) {
1276 rh.hintmap = (HashMap<Object,Object>) hintmap.clone();
1277 }
1278 } catch (CloneNotSupportedException e) {
1279 // this shouldn't happen, since we are Cloneable
1280 throw new InternalError(e);
1281 }
1282
1283 return rh;
1284 }
1285
1286 /**
1287 * Returns a rather long string representation of the hashmap
1288 * which contains the mappings of keys to values for this
1289 * <code>RenderingHints</code> object.
1290 * @return a string representation of this object.
1291 */
1292 public String toString() {
1293 if (hintmap == null) {
1294 return getClass().getName() + "@" +
1295 Integer.toHexString(hashCode()) +
1296 " (0 hints)";
|