In the preceding sections you have seen that the rendering process is quite complex. Though the Java 2D API is surprisingly fast in most cases, there are cases when you would like to have control over trade-offs between speed and quality. You achieve this by setting rendering hints. The setRenderingHint method of the Graphics2D class lets you set a single hint. The hint keys and values are declared in the RenderingHints class. Table 7-2 summarizes the choices. Table 7-2. Rendering HintsKey | Values | Explanation |
---|
KEY_ANTIALIASING | VALUE_ANTIALIAS_ON VALUE_ANTIALIAS_OFF VALUE_ANTIALIAS_DEFAULT | Turn antialiasing for shapes on or off. | KEY_RENDERING | VALUE_RENDER_QUALITY VALUE_RENDER_SPEED VALUE_RENDER_DEFAULT | When available, select rendering algorithms for greater quality or speed. | KEY_DITHERING | VALUE_DITHER_ENABLE VALUE_DITHER_DISABLE VALUE_DITHER_DEFAULT | Turn dithering for colors on or off. Dithering approximates color values by drawing groups of pixels of similar colors. | KEY_TEXT_ANTIALIASING | VALUE_TEXT_ANTIALIAS_ON VALUE_TEXT_ANTIALIAS_OFF VALUE_TEXT_ANTIALIAS_DEFAULT | Turn antialiasing for fonts on or off. | KEY_FRACTIONALMETRICS | VALUE_FRACTIONALMETRICS_ON VALUE_FRACTIONALMETRICS_OFF VALUE_FRACTIONALMETRICS_DEFAULT | Turn the computation of fractional character dimensions on or off. Fractional character dimensions lead to better placement of characters. | KEY_ALPHA_INTERPOLATION | VALUE_ALPHA_INTERPOLATION_QUALITY VALUE_ALPHA_INTERPOLATION_SPEED VALUE_ALPHA_INTERPOLATION_DEFAULT | Turn precise computation of alpha composites on or off. | KEY_COLOR_RENDERING | VALUE_COLOR_RENDER_QUALITY VALUE_COLOR_RENDER_SPEED VALUE_COLOR_RENDER_DEFAULT | Select quality or speed for color rendering. | KEY_INTERPOLATION | VALUE_INTERPOLATION_NEAREST_NEIGHBOR VALUE_INTERPOLATION_BILINEAR VALUE_INTERPOLATION_BICUBIC | Select a rule for interpolating pixels when scaling or rotating images. | KEY_STROKE_CONTROL | VALUE_STROKE_NORMALIZE VALUE_STROKE_PURE VALUE_STROKE_DEFAULT | Select a rule for combining strokes. |
The most useful of these settings involves antialiasing. This technique removes the "jaggies" from slanted lines and curves. As you can see in Figure 7-27, a slanted line must be drawn as a "staircase" of pixels. Especially on low-resolution screens, this line can look ugly. But if, rather than drawing each pixel completely on or off, you color in the pixels that are partially covered, with the color value proportional to the area of the pixel that the line covers, then the result looks much smoother. This technique is called antialiasing. Of course, antialiasing takes a bit longer because it takes time to compute all those color values. Figure 7-27. Antialiasing 

For example, here is how you can request the use of antialiasing. g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); It also makes sense to use antialiasing for fonts. [View full width] g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints .VALUE_TEXT_ANTIALIAS_ON);
The other rendering hints are not as commonly used. You can also put a bunch of key/value hint pairs into a map and set them all at once by calling the setRenderingHints method. Any collection class implementing the map interface will do, but you may as well use the RenderingHints class itself. It implements the Map interface and supplies a default map implementation if you pass null to the constructor. For example, RenderingHints hints = new RenderingHints(null); hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); hints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2.setRenderingHints(hints); That is the technique we use in Example 7-8. The program draws an image that we thought might benefit from some of the hints. You can turn various rendering hints on or off. Not all platforms support all the hints, so you should not expect every one of the settings to have an effect. On Windows and Linux, antialiasing smooths out the ellipse, and text antialiasing improves the look of the italic font. The other hints seemed to have no effect, but they might with other platforms or with more complex images. Figure 7-28 shows a screen capture of the program. Example 7-8. RenderQualityTest.java [View full width] 1. import java.awt.*; 2. import java.awt.event.*; 3. import java.awt.geom.*; 4. import java.io.*; 5. import java.util.*; 6. import javax.imageio.*; 7. import javax.swing.*; 8. 9. /** 10. This program demonstrates the effect of the various 11. rendering hints. 12. */ 13. public class RenderQualityTest 14. { 15. public static void main(String[] args) 16. { 17. JFrame frame = new RenderQualityTestFrame(); 18. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19. frame.setVisible(true); 20. } 21. } 22. 23. /** 24. This frame contains buttons to set rendering hints 25. and an image that is drawn with the selected hints. 26. */ 27. class RenderQualityTestFrame extends JFrame 28. { 29. public RenderQualityTestFrame() 30. { 31. setTitle("RenderQualityTest"); 32. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 33. 34. buttonBox = new JPanel(); 35. buttonBox.setLayout(new GridBagLayout()); 36. hints = new RenderingHints(null); 37. 38. makeButtons("KEY_ANTIALIASING", "VALUE_ANTIALIAS_ON", "VALUE_ANTIALIAS_OFF"); 39. makeButtons("KEY_RENDERING", "VALUE_RENDER_QUALITY", "VALUE_RENDER_SPEED"); 40. makeButtons("KEY_DITHERING", "VALUE_DITHER_ENABLE", "VALUE_DITHER_DISABLE"); 41. makeButtons("KEY_TEXT_ANTIALIASING", "VALUE_TEXT_ANTIALIAS_ON", "VALUE_TEXT_ANTIALIAS_OFF"); 42. makeButtons("KEY_FRACTIONALMETRICS", 43. "VALUE_FRACTIONALMETRICS_ON", "VALUE_FRACTIONALMETRICS_OFF"); 44. makeButtons("KEY_ALPHA_INTERPOLATION", 45. "VALUE_ALPHA_INTERPOLATION_QUALITY", "VALUE_ALPHA_INTERPOLATION_SPEED"); 46. makeButtons("KEY_COLOR_RENDERING", "VALUE_COLOR_RENDER_QUALITY", "VALUE_COLOR_RENDER_SPEED"); 47. makeButtons("KEY_INTERPOLATION", 48. "VALUE_INTERPOLATION_NEAREST_NEIGHBOR", "VALUE_INTERPOLATION_BICUBIC"); 49. makeButtons("KEY_STROKE_CONTROL", "VALUE_STROKE_NORMALIZE", "VALUE_STROKE_PURE"); 50. canvas = new RenderQualityPanel(); 51. canvas.setRenderingHints(hints); 52. 53. add(canvas, BorderLayout.CENTER); 54. add(buttonBox, BorderLayout.NORTH); 55. } 56. 57. /** 58. Makes a set of buttons for a rendering hint key and values 59. @param key the key name 60. @param value1 the name of the first value for the key 61. @param value2 the name of the second value for the key 62. */ 63. void makeButtons(String key, String value1, String value2) 64. { 65. try 66. { 67. final RenderingHints.Key k 68. = (RenderingHints.Key) RenderingHints.class.getField(key).get(null); 69. final Object v1 = RenderingHints.class.getField(value1).get(null); 70. final Object v2 = RenderingHints.class.getField(value2).get(null); 71. JLabel label = new JLabel(key); 72. 73. buttonBox.add(label, new GBC(0, r).setAnchor(GBC.WEST)); 74. ButtonGroup group = new ButtonGroup(); 75. JRadioButton b1 = new JRadioButton(value1, true); 76. 77. buttonBox.add(b1, new GBC(1, r).setAnchor(GBC.WEST)); 78. group.add(b1); 79. b1.addActionListener(new 80. ActionListener() 81. { 82. public void actionPerformed(ActionEvent event) 83. { 84. hints.put(k, v1); 85. canvas.setRenderingHints(hints); 86. } 87. }); 88. JRadioButton b2 = new JRadioButton(value2, false); 89. 90. buttonBox.add(b2, new GBC(2, r).setAnchor(GBC.WEST)); 91. group.add(b2); 92. b2.addActionListener(new 93. ActionListener() 94. { 95. public void actionPerformed(ActionEvent event) 96. { 97. hints.put(k, v2); 98. canvas.setRenderingHints(hints); 99. } 100. }); 101. hints.put(k, v1); 102. r++; 103. } 104. catch (Exception e) 105. { 106. e.printStackTrace(); 107. } 108. } 109. 110. private RenderQualityPanel canvas; 111. private JPanel buttonBox; 112. private RenderingHints hints; 113. private int r; 114. private static final int DEFAULT_WIDTH = 750; 115. private static final int DEFAULT_HEIGHT = 500; 116. } 117. 118. /** 119. This panel produces a drawing that hopefully shows some 120. of the difference caused by rendering hints. 121. */ 122. class RenderQualityPanel extends JPanel 123. { 124. public RenderQualityPanel() 125. { 126. try 127. { 128. image = ImageIO.read(new File("clouds.jpg")); 129. } 130. catch (IOException e) 131. { 132. e.printStackTrace(); 133. } 134. } 135. 136. public void paintComponent(Graphics g) 137. { 138. super.paintComponent(g); 139. Graphics2D g2 = (Graphics2D) g; 140. g2.setRenderingHints(hints); 141. 142. g2.scale(1.05, 1.05); 143. g2.rotate(Math.PI / 12); 144. g2.translate(120, -30); 145. g2.drawImage(image, 0, 0, null); 146. 147. g2.draw(new Ellipse2D.Double(0, 0, image.getWidth(null), image.getHeight(null))); 148. g2.setFont(new Font("Serif", Font.ITALIC, 40)); 149. g2.drawString("Hello", 75, 75); 150. g2.setPaint(Color.YELLOW); 151. g2.translate(0,-80); 152. g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); 153. g2.fill(new Rectangle2D.Double(100, 100, 200, 100)); 154. } 155. 156. /** 157. Sets the hints and repaints. 158. @param h the rendering hints 159. */ 160. public void setRenderingHints(RenderingHints h) 161. { 162. hints = h; 163. repaint(); 164. } 165. 166. private RenderingHints hints = new RenderingHints(null); 167. private Image image; 168. } Figure 7-28. Testing the effect of rendering hints  
java.awt.Graphics2D 1.2 void setRenderingHint(RenderingHints.Key key, Object value) sets a rendering hint for this graphics context. void setRenderingHints(Map m) sets all rendering hints whose key/value pairs are stored in the map. 
java.awt.RenderingHints 1.2 RenderingHints(Map<RenderingHints.Key, ?> m) constructs a rendering hints map for storing rendering hints. If m is null, then a default map implementation is provided. |