1. /*
  2. * @(#)RenderingHints.java 1.21 04/05/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.util.Map;
  9. import java.util.Set;
  10. import java.util.Collection;
  11. import java.util.Collections;
  12. import java.util.HashMap;
  13. import java.util.Iterator;
  14. import sun.awt.SunHints;
  15. import java.lang.ref.WeakReference;
  16. /**
  17. * The <code>RenderingHints</code> class contains rendering hints that can
  18. * be used by the {@link java.awt.Graphics2D} class, and classes that
  19. * implement {@link java.awt.image.BufferedImageOp} and
  20. * {@link java.awt.image.Raster}.
  21. */
  22. public class RenderingHints
  23. implements Map<Object,Object>, Cloneable
  24. {
  25. /**
  26. * Defines the base type of all keys used to control various
  27. * aspects of the rendering and imaging pipelines. Instances
  28. * of this class are immutable and unique which means that
  29. * tests for matches can be made using the == operator instead
  30. * of the more expensive equals() method.
  31. */
  32. public abstract static class Key {
  33. private static HashMap identitymap = new HashMap(17);
  34. private String getIdentity() {
  35. // Note that the identity string is dependent on 3 variables:
  36. // - the name of the subclass of Key
  37. // - the identityHashCode of the subclass of Key
  38. // - the integer key of the Key
  39. // It is theoretically possible for 2 distinct keys to collide
  40. // along all 3 of those attributes in the context of multiple
  41. // class loaders, but that occurence will be extremely rare and
  42. // we account for that possibility below in the recordIdentity
  43. // method by slightly relaxing our uniqueness guarantees if we
  44. // end up in that situation.
  45. return getClass().getName()+"@"+
  46. Integer.toHexString(System.identityHashCode(getClass()))+":"+
  47. Integer.toHexString(privatekey);
  48. }
  49. private synchronized static void recordIdentity(Key k) {
  50. Object identity = k.getIdentity();
  51. Object otherref = identitymap.get(identity);
  52. if (otherref != null) {
  53. Key otherkey = (Key) ((WeakReference) otherref).get();
  54. if (otherkey != null && otherkey.getClass() == k.getClass()) {
  55. throw new IllegalArgumentException(identity+
  56. " already registered");
  57. }
  58. // Note that this system can fail in a mostly harmless
  59. // way. If we end up generating the same identity
  60. // String for 2 different classes (a very rare case)
  61. // then we correctly avoid throwing the exception above,
  62. // but we are about to drop through to a statement that
  63. // will replace the entry for the old Key subclass with
  64. // an entry for the new Key subclass. At that time the
  65. // old subclass will be vulnerable to someone generating
  66. // a duplicate Key instance for it. We could bail out
  67. // of the method here and let the old identity keep its
  68. // record in the map, but we are more likely to see a
  69. // duplicate key go by for the new class than the old
  70. // one since the new one is probably still in the
  71. // initialization stage. In either case, the probability
  72. // of loading 2 classes in the same VM with the same name
  73. // and identityHashCode should be nearly impossible.
  74. }
  75. // Note: Use a weak reference to avoid holding on to extra
  76. // objects and classes after they should be unloaded.
  77. identitymap.put(identity, new WeakReference(k));
  78. }
  79. private int privatekey;
  80. /**
  81. * Construct a key using the indicated private key. Each
  82. * subclass of Key maintains its own unique domain of integer
  83. * keys. No two objects with the same integer key and of the
  84. * same specific subclass can be constructed. An exception
  85. * will be thrown if an attempt is made to construct another
  86. * object of a given class with the same integer key as a
  87. * pre-existing instance of that subclass of Key.
  88. * @param privatekey the specified key
  89. */
  90. protected Key(int privatekey) {
  91. this.privatekey = privatekey;
  92. recordIdentity(this);
  93. }
  94. /**
  95. * Returns true if the specified object is a valid value
  96. * for this Key.
  97. * @param val the <code>Object</code> to test for validity
  98. * @return <code>true</code> if <code>val</code> is valid;
  99. * <code>false</code> otherwise.
  100. */
  101. public abstract boolean isCompatibleValue(Object val);
  102. /**
  103. * Returns the private integer key that the subclass
  104. * instantiated this Key with.
  105. * @return the private integer key that the subclass
  106. * instantiated this Key with.
  107. */
  108. protected final int intKey() {
  109. return privatekey;
  110. }
  111. /**
  112. * The hash code for all Key objects will be the same as the
  113. * system identity code of the object as defined by the
  114. * System.identityHashCode() method.
  115. */
  116. public final int hashCode() {
  117. return System.identityHashCode(this);
  118. }
  119. /**
  120. * The equals method for all Key objects will return the same
  121. * result as the equality operator '=='.
  122. */
  123. public final boolean equals(Object o) {
  124. return this == o;
  125. }
  126. }
  127. HashMap hintmap = new HashMap(7);
  128. /**
  129. * Antialiasing hint key.
  130. */
  131. public static final Key KEY_ANTIALIASING =
  132. SunHints.KEY_ANTIALIASING;
  133. /**
  134. * Antialiasing hint values -- rendering is done with antialiasing.
  135. */
  136. public static final Object VALUE_ANTIALIAS_ON =
  137. SunHints.VALUE_ANTIALIAS_ON;
  138. /**
  139. * Antialiasing hint values -- rendering is done without antialiasing.
  140. */
  141. public static final Object VALUE_ANTIALIAS_OFF =
  142. SunHints.VALUE_ANTIALIAS_OFF;
  143. /**
  144. * Antialiasing hint values -- rendering is done with the platform
  145. * default antialiasing mode.
  146. */
  147. public static final Object VALUE_ANTIALIAS_DEFAULT =
  148. SunHints.VALUE_ANTIALIAS_DEFAULT;
  149. /**
  150. * Rendering hint key.
  151. */
  152. public static final Key KEY_RENDERING =
  153. SunHints.KEY_RENDERING;
  154. /**
  155. * Rendering hint values -- Appropriate rendering algorithms are chosen
  156. * with a preference for output speed.
  157. */
  158. public static final Object VALUE_RENDER_SPEED =
  159. SunHints.VALUE_RENDER_SPEED;
  160. /**
  161. * Rendering hint values -- Appropriate rendering algorithms are chosen
  162. * with a preference for output quality.
  163. */
  164. public static final Object VALUE_RENDER_QUALITY =
  165. SunHints.VALUE_RENDER_QUALITY;
  166. /**
  167. * Rendering hint values -- The platform default rendering algorithms
  168. * are chosen.
  169. */
  170. public static final Object VALUE_RENDER_DEFAULT =
  171. SunHints.VALUE_RENDER_DEFAULT;
  172. /**
  173. * Dithering hint key.
  174. */
  175. public static final Key KEY_DITHERING =
  176. SunHints.KEY_DITHERING;
  177. /**
  178. * Dithering hint values -- do not dither when rendering.
  179. */
  180. public static final Object VALUE_DITHER_DISABLE =
  181. SunHints.VALUE_DITHER_DISABLE;
  182. /**
  183. * Dithering hint values -- dither when rendering, if needed.
  184. */
  185. public static final Object VALUE_DITHER_ENABLE =
  186. SunHints.VALUE_DITHER_ENABLE;
  187. /**
  188. * Dithering hint values -- use the platform default for dithering.
  189. */
  190. public static final Object VALUE_DITHER_DEFAULT =
  191. SunHints.VALUE_DITHER_DEFAULT;
  192. /**
  193. * Text antialiasing hint key.
  194. */
  195. public static final Key KEY_TEXT_ANTIALIASING =
  196. SunHints.KEY_TEXT_ANTIALIASING;
  197. /**
  198. * Text antialiasing hint value -- text rendering is done with
  199. * antialiasing.
  200. */
  201. public static final Object VALUE_TEXT_ANTIALIAS_ON =
  202. SunHints.VALUE_TEXT_ANTIALIAS_ON;
  203. /**
  204. * Text antialiasing hint value -- text rendering is done without
  205. * antialiasing.
  206. */
  207. public static final Object VALUE_TEXT_ANTIALIAS_OFF =
  208. SunHints.VALUE_TEXT_ANTIALIAS_OFF;
  209. /**
  210. * Text antialiasing hint value -- text rendering is done using the
  211. * platform default text antialiasing mode.
  212. */
  213. public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT =
  214. SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
  215. /**
  216. * Font fractional metrics hint key.
  217. */
  218. public static final Key KEY_FRACTIONALMETRICS =
  219. SunHints.KEY_FRACTIONALMETRICS;
  220. /**
  221. * Font fractional metrics hint values -- fractional metrics disabled.
  222. */
  223. public static final Object VALUE_FRACTIONALMETRICS_OFF =
  224. SunHints.VALUE_FRACTIONALMETRICS_OFF;
  225. /**
  226. * Font fractional metrics hint values -- fractional metrics enabled.
  227. */
  228. public static final Object VALUE_FRACTIONALMETRICS_ON =
  229. SunHints.VALUE_FRACTIONALMETRICS_ON;
  230. /**
  231. * Font fractional metrics hint values -- use the platform default for
  232. * fractional metrics.
  233. */
  234. public static final Object VALUE_FRACTIONALMETRICS_DEFAULT =
  235. SunHints.VALUE_FRACTIONALMETRICS_DEFAULT;
  236. /**
  237. * Interpolation hint key.
  238. */
  239. public static final Key KEY_INTERPOLATION =
  240. SunHints.KEY_INTERPOLATION;
  241. /**
  242. * Interpolation hint value -- INTERPOLATION_NEAREST_NEIGHBOR.
  243. */
  244. public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR =
  245. SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
  246. /**
  247. * Interpolation hint value -- INTERPOLATION_BILINEAR.
  248. */
  249. public static final Object VALUE_INTERPOLATION_BILINEAR =
  250. SunHints.VALUE_INTERPOLATION_BILINEAR;
  251. /**
  252. * Interpolation hint value -- INTERPOLATION_BICUBIC.
  253. */
  254. public static final Object VALUE_INTERPOLATION_BICUBIC =
  255. SunHints.VALUE_INTERPOLATION_BICUBIC;
  256. /**
  257. * Alpha interpolation hint key.
  258. */
  259. public static final Key KEY_ALPHA_INTERPOLATION =
  260. SunHints.KEY_ALPHA_INTERPOLATION;
  261. /**
  262. * Alpha interpolation hint value -- ALPHA_INTERPOLATION_SPEED.
  263. */
  264. public static final Object VALUE_ALPHA_INTERPOLATION_SPEED =
  265. SunHints.VALUE_ALPHA_INTERPOLATION_SPEED;
  266. /**
  267. * Alpha interpolation hint value -- ALPHA_INTERPOLATION_QUALITY.
  268. */
  269. public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY =
  270. SunHints.VALUE_ALPHA_INTERPOLATION_QUALITY;
  271. /**
  272. * Alpha interpolation hint value -- ALPHA_INTERPOLATION_DEFAULT.
  273. */
  274. public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT =
  275. SunHints.VALUE_ALPHA_INTERPOLATION_DEFAULT;
  276. /**
  277. * Color rendering hint key.
  278. */
  279. public static final Key KEY_COLOR_RENDERING =
  280. SunHints.KEY_COLOR_RENDERING;
  281. /**
  282. * Color rendering hint value -- COLOR_RENDER_SPEED.
  283. */
  284. public static final Object VALUE_COLOR_RENDER_SPEED =
  285. SunHints.VALUE_COLOR_RENDER_SPEED;
  286. /**
  287. * Color rendering hint value -- COLOR_RENDER_QUALITY.
  288. */
  289. public static final Object VALUE_COLOR_RENDER_QUALITY =
  290. SunHints.VALUE_COLOR_RENDER_QUALITY;
  291. /**
  292. * Color rendering hint value -- COLOR_RENDER_DEFAULT.
  293. */
  294. public static final Object VALUE_COLOR_RENDER_DEFAULT =
  295. SunHints.VALUE_COLOR_RENDER_DEFAULT;
  296. /**
  297. * Stroke normalization control hint key.
  298. */
  299. public static final Key KEY_STROKE_CONTROL =
  300. SunHints.KEY_STROKE_CONTROL;
  301. /**
  302. * Stroke normalization control hint value -- STROKE_DEFAULT.
  303. */
  304. public static final Object VALUE_STROKE_DEFAULT =
  305. SunHints.VALUE_STROKE_DEFAULT;
  306. /**
  307. * Stroke normalization control hint value -- STROKE_NORMALIZE.
  308. */
  309. public static final Object VALUE_STROKE_NORMALIZE =
  310. SunHints.VALUE_STROKE_NORMALIZE;
  311. /**
  312. * Stroke normalization control hint value -- STROKE_PURE.
  313. */
  314. public static final Object VALUE_STROKE_PURE =
  315. SunHints.VALUE_STROKE_PURE;
  316. /**
  317. * Constructs a new object with keys and values initialized
  318. * from the specified Map object (which may be null).
  319. * @param init a map of key/value pairs to initialize the hints
  320. * or null if the object should be empty
  321. */
  322. public RenderingHints(Map<Key,?> init) {
  323. if (init != null) {
  324. hintmap.putAll(init);
  325. }
  326. }
  327. /**
  328. * Constructs a new object with the specified key/value pair.
  329. * @param key the key of the particular hint property
  330. * @param value the value of the hint property specified with
  331. * <code>key</code>
  332. */
  333. public RenderingHints(Key key, Object value) {
  334. hintmap.put(key, value);
  335. }
  336. /**
  337. * Returns the number of key-value mappings in this
  338. * <code>RenderingHints</code>.
  339. *
  340. * @return the number of key-value mappings in this
  341. * <code>RenderingHints</code>.
  342. */
  343. public int size() {
  344. return hintmap.size();
  345. }
  346. /**
  347. * Returns <code>true</code> if this
  348. * <code>RenderingHints</code> contains no key-value mappings.
  349. *
  350. * @return <code>true</code> if this
  351. * <code>RenderingHints</code> contains no key-value mappings.
  352. */
  353. public boolean isEmpty() {
  354. return hintmap.isEmpty();
  355. }
  356. /**
  357. * Returns <code>true</code> if this <code>RenderingHints</code>
  358. * contains a mapping for the specified key.
  359. *
  360. * @param key key whose presence in this
  361. * <code>RenderingHints</code> is to be tested.
  362. * @return <code>true</code> if this <code>RenderingHints</code>
  363. * contains a mapping for the specified key.
  364. * @exception <code>ClassCastException</code> key is not
  365. * of type <code>RenderingHints.Key</code>
  366. * @exception <code>NullPointerException</code>
  367. * key is <code>null</code>
  368. */
  369. public boolean containsKey(Object key) {
  370. return hintmap.containsKey((Key) key);
  371. }
  372. /**
  373. * Returns true if this RenderingHints maps one or more keys to the
  374. * specified value.
  375. * More formally, returns <code>true</code> if and only
  376. * if this <code>RenderingHints</code>
  377. * contains at least one mapping to a value <code>v</code> such that
  378. * <pre>
  379. * (value==null ? v==null : value.equals(v))
  380. * </pre>.
  381. * This operation will probably require time linear in the
  382. * <code>RenderingHints</code> size for most implementations
  383. * of <code>RenderingHints</code>.
  384. *
  385. * @param value value whose presence in this
  386. * <code>RenderingHints</code> is to be tested.
  387. * @return <code>true</code> if this <code>RenderingHints</code>
  388. * maps one or more keys to the specified value.
  389. */
  390. public boolean containsValue(Object value) {
  391. return hintmap.containsValue(value);
  392. }
  393. /**
  394. * Returns the value to which the specified key is mapped.
  395. * @param key a rendering hint key
  396. * @return the value to which the key is mapped in this object or
  397. * <code>null</code> if the key is not mapped to any value in
  398. * this object.
  399. * @exception <code>ClassCastException</code> key is not of
  400. * type <code>RenderingHints.Key</code>.
  401. * @see #put(Object, Object)
  402. */
  403. public Object get(Object key) {
  404. return hintmap.get((Key) key);
  405. }
  406. /**
  407. * Maps the specified <code>key</code> to the specified
  408. * <code>value</code> in this <code>RenderingHints</code> object.
  409. * Neither the key nor the value can be <code>null</code>.
  410. * The value can be retrieved by calling the <code>get</code> method
  411. * with a key that is equal to the original key.
  412. * @param key the rendering hint key.
  413. * @param value the rendering hint value.
  414. * @return the previous value of the specified key in this object
  415. * or <code>null</code> if it did not have one.
  416. * @exception <code>NullPointerException</code> if the key or value is
  417. * <code>null</code>.
  418. * @exception <code>ClassCastException</code> key is not of
  419. * type <code>RenderingHints.Key</code>.
  420. * @exception <code>IllegalArgumentException</code> value is not
  421. * appropriate for the specified key.
  422. * @see #get(Object)
  423. */
  424. public Object put(Object key, Object value) {
  425. if (!((Key) key).isCompatibleValue(value)) {
  426. throw new IllegalArgumentException(value+
  427. " incompatible with "+
  428. key);
  429. }
  430. return hintmap.put((Key) key, value);
  431. }
  432. /**
  433. * Adds all of the keys and corresponding values from the specified
  434. * <code>RenderingHints</code> object to this
  435. * <code>RenderingHints</code> object. Keys that are present in
  436. * this <code>RenderingHints</code> object, but not in the specified
  437. * <code>RenderingHints</code> object are not affected.
  438. * @param hints the set of key/value pairs to be added to this
  439. * <code>RenderingHints</code> object
  440. */
  441. public void add(RenderingHints hints) {
  442. hintmap.putAll(hints.hintmap);
  443. }
  444. /**
  445. * Clears this <code>RenderingHints</code> object of all key/value
  446. * pairs.
  447. */
  448. public void clear() {
  449. hintmap.clear();
  450. }
  451. /**
  452. * Removes the key and its corresponding value from this
  453. * <code>RenderingHints</code> object. This method does nothing if the
  454. * key is not in this <code>RenderingHints</code> object.
  455. * @param key the rendering hints key that needs to be removed
  456. * @exception <code>ClassCastException</code> key is not of
  457. * type <code>RenderingHints.Key</code>.
  458. * @return the value to which the key had previously been mapped in this
  459. * <code>RenderingHints</code> object, or <code>null</code>
  460. * if the key did not have a mapping.
  461. */
  462. public Object remove(Object key) {
  463. return hintmap.remove((Key) key);
  464. }
  465. /**
  466. * Copies all of the mappings from the specified <code>Map</code>
  467. * to this <code>RenderingHints</code>. These mappings replace
  468. * any mappings that this <code>RenderingHints</code> had for any
  469. * of the keys currently in the specified <code>Map</code>.
  470. * @param m the specified <code>Map</code>
  471. * @exception <code>ClassCastException</code> class of a key or value
  472. * in the specified <code>Map</code> prevents it from being
  473. * stored in this <code>RenderingHints</code>.
  474. * @exception <code>IllegalArgumentException</code> some aspect
  475. * of a key or value in the specified <code>Map</code>
  476. * prevents it from being stored in
  477. * this <code>RenderingHints</code>.
  478. */
  479. public void putAll(Map<?,?> m) {
  480. // ## javac bug?
  481. //if (m instanceof RenderingHints) {
  482. if (RenderingHints.class.isInstance(m)) {
  483. //hintmap.putAll(((RenderingHints) m).hintmap);
  484. for (Map.Entry<?,?> entry : m.entrySet())
  485. hintmap.put(entry.getKey(), entry.getValue());
  486. } else {
  487. // Funnel each key/value pair through our protected put method
  488. for (Map.Entry<?,?> entry : m.entrySet())
  489. put(entry.getKey(), entry.getValue());
  490. }
  491. }
  492. /**
  493. * Returns a <code>Set</code> view of the Keys contained in this
  494. * <code>RenderingHints</code>. The Set is backed by the
  495. * <code>RenderingHints</code>, so changes to the
  496. * <code>RenderingHints</code> are reflected in the <code>Set</code>,
  497. * and vice-versa. If the <code>RenderingHints</code> is modified
  498. * while an iteration over the <code>Set</code> is in progress,
  499. * the results of the iteration are undefined. The <code>Set</code>
  500. * supports element removal, which removes the corresponding
  501. * mapping from the <code>RenderingHints</code>, via the
  502. * <code>Iterator.remove</code>, <code>Set.remove</code>,
  503. * <code>removeAll</code> <code>retainAll</code>, and
  504. * <code>clear</code> operations. It does not support
  505. * the <code>add</code> or <code>addAll</code> operations.
  506. *
  507. * @return a <code>Set</code> view of the keys contained
  508. * in this <code>RenderingHints</code>.
  509. */
  510. public Set<Object> keySet() {
  511. return hintmap.keySet();
  512. }
  513. /**
  514. * Returns a <code>Collection</code> view of the values
  515. * contained in this <code>RenderinHints</code>.
  516. * The <code>Collection</code> is backed by the
  517. * <code>RenderingHints</code>, so changes to
  518. * the <code>RenderingHints</code> are reflected in
  519. * the <code>Collection</code>, and vice-versa.
  520. * If the <code>RenderingHints</code> is modified while
  521. * an iteration over the <code>Collection</code> is
  522. * in progress, the results of the iteration are undefined.
  523. * The <code>Collection</code> supports element removal,
  524. * which removes the corresponding mapping from the
  525. * <code>RenderingHints</code>, via the
  526. * <code>Iterator.remove</code>,
  527. * <code>Collection.remove</code>, <code>removeAll</code>,
  528. * <code>retainAll</code> and <code>clear</code> operations.
  529. * It does not support the <code>add</code> or
  530. * <code>addAll</code> operations.
  531. *
  532. * @return a <code>Collection</code> view of the values
  533. * contained in this <code>RenderingHints</code>.
  534. */
  535. public Collection<Object> values() {
  536. return hintmap.values();
  537. }
  538. /**
  539. * Returns a <code>Set</code> view of the mappings contained
  540. * in this <code>RenderingHints</code>. Each element in the
  541. * returned <code>Set</code> is a <code>Map.Entry</code>.
  542. * The <code>Set</code> is backed by the <code>RenderingHints</code>,
  543. * so changes to the <code>RenderingHints</code> are reflected
  544. * in the <code>Set</code>, and vice-versa. If the
  545. * <code>RenderingHints</code> is modified while
  546. * while an iteration over the <code>Set</code> is in progress,
  547. * the results of the iteration are undefined.
  548. * <p>
  549. * The entrySet returned from a <code>RenderingHints</code> object
  550. * is not modifiable.
  551. *
  552. * @return a <code>Set</code> view of the mappings contained in
  553. * this <code>RenderingHints</code>.
  554. */
  555. public Set<Map.Entry<Object,Object>> entrySet() {
  556. return Collections.unmodifiableMap(hintmap).entrySet();
  557. }
  558. /**
  559. * Compares the specified <code>Object</code> with this
  560. * <code>RenderingHints</code> for equality.
  561. * Returns <code>true</code> if the specified object is also a
  562. * <code>Map</code> and the two <code>Map</code> objects represent
  563. * the same mappings. More formally, two <code>Map</code> objects
  564. * <code>t1</code> and <code>t2</code> represent the same mappings
  565. * if <code>t1.keySet().equals(t2.keySet())</code> and for every
  566. * key <code>k</code> in <code>t1.keySet()</code>,
  567. * <pre>
  568. * (t1.get(k)==null ? t2.get(k)==null : t1.get(k).equals(t2.get(k)))
  569. * </pre>.
  570. * This ensures that the <code>equals</code> method works properly across
  571. * different implementations of the <code>Map</code> interface.
  572. *
  573. * @param o <code>Object</code> to be compared for equality with
  574. * this <code>RenderingHints</code>.
  575. * @return <code>true</code> if the specified <code>Object</code>
  576. * is equal to this <code>RenderingHints</code>.
  577. */
  578. public boolean equals(Object o) {
  579. if (o instanceof RenderingHints) {
  580. return hintmap.equals(((RenderingHints) o).hintmap);
  581. } else if (o instanceof Map) {
  582. return hintmap.equals(o);
  583. }
  584. return false;
  585. }
  586. /**
  587. * Returns the hash code value for this <code>RenderingHints</code>.
  588. * The hash code of a <code>RenderingHints</code> is defined to be
  589. * the sum of the hashCodes of each <code>Entry</code> in the
  590. * <code>RenderingHints</code> object's entrySet view. This ensures that
  591. * <code>t1.equals(t2)</code> implies that
  592. * <code>t1.hashCode()==t2.hashCode()</code> for any two <code>Map</code>
  593. * objects <code>t1</code> and <code>t2</code>, as required by the general
  594. * contract of <code>Object.hashCode</code>.
  595. *
  596. * @return the hash code value for this <code>RenderingHints</code>.
  597. * @see java.util.Map.Entry#hashCode()
  598. * @see Object#hashCode()
  599. * @see Object#equals(Object)
  600. * @see #equals(Object)
  601. */
  602. public int hashCode() {
  603. return hintmap.hashCode();
  604. }
  605. /**
  606. * Creates a clone of this <code>RenderingHints</code> object
  607. * that has the same contents as this <code>RenderingHints</code>
  608. * object.
  609. * @return a clone of this instance.
  610. */
  611. public Object clone() {
  612. RenderingHints rh;
  613. try {
  614. rh = (RenderingHints) super.clone();
  615. if (hintmap != null) {
  616. rh.hintmap = (HashMap) hintmap.clone();
  617. }
  618. } catch (CloneNotSupportedException e) {
  619. // this shouldn't happen, since we are Cloneable
  620. throw new InternalError();
  621. }
  622. return rh;
  623. }
  624. /**
  625. * Returns a rather long string representation of the hashmap
  626. * which contains the mappings of keys to values for this
  627. * <code>RenderingHints</code> object.
  628. * @return a string representation of this object.
  629. */
  630. public String toString() {
  631. if (hintmap == null) {
  632. return getClass().getName() + "@" +
  633. Integer.toHexString(hashCode()) +
  634. " (0 hints)";
  635. }
  636. return hintmap.toString();
  637. }
  638. }