1. What isclipping
Clipping is the process of confining paint operations to a limited area or shape.2. Clipping the Drawing Region
Any Shape
object can be used as a clipping path that restricts the portion of the drawing area that will be rendered. The clipping path is part of the Graphics2D
context; to set the clip attribute, you call Graphics2D.setClip
and pass in the Shape
that defines the clipping path you want to use. You can shrink the clipping path by calling the clip
method and passing in another Shape
; the clip is set to the intersection of the current clip and the specified Shape
.Example: ClipImage
This example animates a clipping path to reveal different portions of an image.ClipImage.java
contains the complete code for this applet. The applet requires the clouds.jpg
image file.The clipping path is defined by the intersection of an ellipse and a rectangle whose dimensions are set randomly. The ellipse is passed to the
setClip
method, and then clip
is called to set the clipping path to the intersection of the ellipse and the rectangle.private Ellipse2D ellipse = new Ellipse2D.Float(); private Rectangle2D rect = new Rectangle2D.Float(); ... ellipse.setFrame(x, y, ew, eh); g2.setClip(ellipse); rect.setRect(x+5, y+5, ew-10, eh-10); g2.clip(rect);
Example: Starry
A clipping area can also be created from a text string. The following example creates a TextLayout
with the string The Starry Night. Then, it gets the outline of the TextLayout
. The TextLayout.getOutline
method returns a Shape
object and a Rectangle
is created from the bounds of this Shape
object. The bounds contain all the pixels the layout can draw. The color in the graphics context is set to blue and the outline shape is drawn, as illustrated by the following image and code snippet.FontRenderContext frc = g2.getFontRenderContext();
Font f = new Font("Helvetica", 1, w/10); String s = new String("The Starry Night"); TextLayout textTl = new TextLayout(s, f, frc); AffineTransform transform = new AffineTransform(); Shape outline = textTl.getOutline(null); Rectangle r = outline.getBounds(); transform = g2.getTransform(); transform.translate(w/2-(r.width/2), h/2+(r.height/2)); g2.transform(transform); g2.setColor(Color.blue); g2.draw(outline);Next, a clipping area is set on the graphics context using the
Shape
object created from getOutline
. The starry.gif
image, which is Van Gogh's famous painting, The Starry Night, is drawn into this clipping area starting at the lower left corner of the Rectangle
object.g2.setClip(outline); g2.drawImage(img, r.x, r.y, r.width, r.height, this);
Starry.java
contains the complete code for this program. This applet requires the Starry.gif
image file.3. Clipping
By setting a clipping shape in the graphics context, you constrain all drawing operations to the interior of that clipping shape.
g2.setClip(clipShape); // but see below g2.draw(shape); // draws only the part that falls inside the clipping shapeHowever, in practice, you don't want to call the setClip operation, since it replaces any existing clipping shape that the graphics context may have. For example, as you will see later in this chapter, a graphics context for printing comes with a clip rectangle that ensures that you don't draw on the margins. Instead, call the clip method.
g2.clip(clipShape); // betterThe clip method intersects the existing clipping shape with the new one that you supply.
If you just want to apply a clipping area temporarily, then you should first get the old clip, then add your new clip, and finally restore the old clip when you are done:
Shape oldClip = g2.getClip(); // save old clip
g2.clip(clipShape); // apply temporary clip
draw on g2
g2.setClip(oldClip); // restore old clip
In Example 7-6, we show off the clipping capability with a rather dramatic drawing of a line pattern that is clipped by a complex shape, namely, the outline of a set of characters (see Figure 7-22).
Figure 7-22. The ClipTest program
To obtain character outlines, you need a font render context. Use the getFontRenderContext method of the Graphics2D class.
FontRenderContext context = g2.getFontRenderContext();
Next, using a string, a font, and the font render context, create a TextLayout object:
TextLayout layout = new TextLayout("Hello", font, context);
This text layout object describes the layout of a sequence of characters, as rendered by a particular font render context. The layout depends on the font render contextthe same characters will look different on a screen or a printer.
More important for our current application, the getOutline method returns a Shape object that describes the shape of the outline of the characters in the text layout. The outline shape starts at the origin (0, 0), which is not suitable for most drawing operations. Therefore, you need to supply an affine transform to the getOutline operation that specifies where you would like the outline to appear. We simply supply a translation that moves the base point to the point (0, 100).
AffineTransform transform = AffineTransform.getTranslateInstance(0, 100); Shape outline = layout.getOutline(transform);
Then, we append the outline to the clipping shape.
GeneralPath clipShape = new GeneralPath(); clipShape.append(outline, false);
Finally, we set the clipping shape and draw a set of lines. The lines appear only inside the character boundaries.
g2.setClip(clipShape); Point2D p = new Point2D.Double(0, 0); for (int i = 0; i < NLINES; i++) { double x = . . .; double y = . . .; Point2D q = new Point2D.Double(x, y); g2.draw(new Line2D.Double(p, q)); // lines are clipped }
Here is the complete program.
Example 7-6. ClipTest.java
1. import java.awt.*; 2. import java.awt.event.*; 3. import java.awt.font.*; 4. import java.awt.geom.*; 5. import java.util.*; 6. import javax.swing.*; 7. 8. /** 9. This program demonstrates the use of a clip shape. 10. */ 11. public class ClipTest 12. { 13. public static void main(String[] args) 14. { 15. JFrame frame = new ClipTestFrame(); 16. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 17. frame.setVisible(true); 18. } 19. } 20. 21. /** 22. This frame contains a checkbox to turn a clip off 23. and on, and a panel to draw a set of lines with or without 24. clipping. 25. */ 26. class ClipTestFrame extends JFrame 27. { 28. public ClipTestFrame() 29. { 30. setTitle("ClipTest"); 31. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 32. 33. final JCheckBox checkBox = new JCheckBox("Clip"); 34. checkBox.addActionListener(new 35. ActionListener() 36. { 37. public void actionPerformed(ActionEvent event) 38. { 39. panel.repaint(); 40. } 41. }); 42. add(checkBox, BorderLayout.NORTH); 43. 44. panel = new 45. JPanel() 46. { 47. public void paintComponent(Graphics g) 48. { 49. super.paintComponent(g); 50. Graphics2D g2 = (Graphics2D)g; 51. 52. if (clipShape == null) clipShape = makeClipShape(g2); 53. 54. g2.draw(clipShape); 55. 56. if (checkBox.isSelected()) g2.clip(clipShape); 57. 58. // draw line pattern 59. final int NLINES = 50; 60. Point2D p = new Point2D.Double(0, 0); 61. for (int i = 0; i < NLINES; i++) 62. { 63. double x = (2 * getWidth() * i) / NLINES; 64. double y = (2 * getHeight() * (NLINES - 1 - i)) / NLINES; 65. Point2D q = new Point2D.Double(x, y); 66. g2.draw(new Line2D.Double(p, q)); 67. } 68. } 69. }; 70. add(panel, BorderLayout.CENTER); 71. } 72. 73. /** 74. Makes the clip shape. 75. @param g2 the graphics context 76. @return the clip shape 77. */ 78. Shape makeClipShape(Graphics2D g2) 79. { 80. FontRenderContext context = g2.getFontRenderContext(); 81. Font f = new Font("Serif", Font.PLAIN, 100); 82. GeneralPath clipShape = new GeneralPath(); 83. 84. TextLayout layout = new TextLayout("Hello", f, context); 85. AffineTransform transform = AffineTransform.getTranslateInstance(0, 100); 86. Shape outline = layout.getOutline(transform); 87. clipShape.append(outline, false); 88. 89. layout = new TextLayout("World", f, context); 90. transform = AffineTransform.getTranslateInstance(0, 200); 91. outline = layout.getOutline(transform); 92. clipShape.append(outline, false); 93. return clipShape; 94. } 95. 96. private JPanel panel; 97. private Shape clipShape; 98. private static final int DEFAULT_WIDTH = 300; 99. private static final int DEFAULT_HEIGHT = 300; 100. }
java.awt.Graphics 1.0
- void setClip(Shape s) 1.2sets the current clipping shape to the shape s.
- Shape getClip() 1.2returns the current clipping shape.
java.awt.Graphics2D 1.2
- void clip(Shape s)intersects the current clipping shape with the shape s.
- FontRenderContext getFontRenderContext()returns a font render context that is necessary for constructing TextLayout objects.
java.awt.font.TextLayout 1.2
- TextLayout(String s, Font f, FontRenderContext context)constructs a text layout object from a given string and font, using the font render context to obtain font properties for a particular device.
- float getAdvance()returns the width of this text layout.
- float getAscent()
- float getDescent()return the height of this text layout above and below the baseline.
- float getLeading()
0 comments:
Post a Comment