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