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