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