|
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.
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. AntialiasingFor 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.
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
java.awt.RenderingHints 1.2
|
|