Java/2D Graphics GUI/Clip

Материал из Java эксперт
Перейти к: навигация, поиск

Clip another area

<source lang="java"> import java.awt.BorderLayout; import java.awt.Canvas; import java.awt.Color; import java.awt.Container; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.geom.Ellipse2D; import javax.swing.ButtonGroup; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.border.TitledBorder; public class ClipArea extends JFrame {

 MyCanvas canvas;
 JRadioButton clipButton, clipFurButton;
 public ClipArea() {
   super();
   Container contentPane = getContentPane();
   canvas = new MyCanvas();
   contentPane.add(canvas);
   JPanel panel = new JPanel();
   panel.setLayout(new GridLayout(1, 2));
   clipButton = new JRadioButton("Clip", true);
   clipButton.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       canvas.clip = true;
       canvas.clipFurther = false;
       canvas.repaint();
     }
   });
   clipFurButton = new JRadioButton("Clip Further");
   clipFurButton.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       canvas.clipFurther = true;
       canvas.repaint();
     }
   });
   ButtonGroup group = new ButtonGroup();
   group.add(clipButton);
   group.add(clipFurButton);
   panel.add(clipButton);
   panel.add(clipFurButton);
   contentPane.add(BorderLayout.SOUTH, panel);
   // 4. Add a window listener to close the frame properly.
   addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   });
   pack(); 
   setVisible(true); 
 }
 public static void main(String arg[]) {
   new ClipArea();
 }

} class MyCanvas extends JPanel{

 boolean clip = true;
 boolean clipFurther = false;
 MyCanvas() {
   setSize(300, 300);
   setBackground(Color.white);
 }
 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   int w = getSize().width;
   int h = getSize().height;
   if (clip) {
     Ellipse2D e = new Ellipse2D.Float(w / 4.0f, h / 4.0f, w / 2.0f,
         h / 2.0f);
     g2.setClip(e);
     g2.setColor(Color.yellow);
     g2.fillRect(0, 0, w, h);
   }
   if (clipFurther) {
     Rectangle r = new Rectangle(w / 2, h / 2, w / 2, h / 2);
     g2.clip(r);
     g2.setColor(Color.green);
     g2.fillRect(0, 0, w, h);
   }
 }

}



 </source>   



Clip Image

<source lang="java"> import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.MediaTracker; import java.awt.RenderingHints; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.net.URL; import javax.swing.JApplet; import javax.swing.JFrame; public class ClipImage extends JApplet implements Runnable {

 private Image img;
 private final double OINC[] = { 5.0, 3.0 };
 private final double SINC[] = { 5.0, 5.0 };
 private double x, y;
 private double ix = OINC[0];
 private double iy = OINC[1];
 private double iw = SINC[0];
 private double ih = SINC[1];
 private double ew, eh; // ellipse width & height
 private GeneralPath p = new GeneralPath();
 private AffineTransform at = new AffineTransform();
 private BasicStroke bs = new BasicStroke(20.0f);
 private Arc2D arc = new Arc2D.Float();
 private Ellipse2D ellipse = new Ellipse2D.Float();
 private RoundRectangle2D roundRect = new RoundRectangle2D.Float();
 private Rectangle2D rect = new Rectangle2D.Float();
 private Color redBlend = new Color(255, 0, 0, 120);
 private Color greenBlend = new Color(0, 255, 0, 120);
 private Thread thread;
 private BufferedImage offImg;
 private int w, h;
 private boolean newBufferedImage;
 public void init() {
   img = getImage(getURL("largejexpLogo.GIF"));
   try {
     MediaTracker tracker = new MediaTracker(this);
     tracker.addImage(img, 0);
     tracker.waitForID(0);
   } catch (Exception e) {
   }
 }
 public void drawDemo(Graphics2D g2) {
   if (newBufferedImage) {
     x = Math.random() * w;
     y = Math.random() * h;
     ew = (Math.random() * w) / 2;
     eh = (Math.random() * h) / 2;
   }
   x += ix;
   y += iy;
   ew += iw;
   eh += ih;
   if (ew > w / 2) {
     ew = w / 2;
     iw = Math.random() * -w / 16 - 1;
   }
   if (ew < w / 8) {
     ew = w / 8;
     iw = Math.random() * w / 16 + 1;
   }
   if (eh > h / 2) {
     eh = h / 2;
     ih = Math.random() * -h / 16 - 1;
   }
   if (eh < h / 8) {
     eh = h / 8;
     ih = Math.random() * h / 16 + 1;
   }
   if ((x + ew) > w) {
     x = (w - ew) - 1;
     ix = Math.random() * -w / 32 - 1;
   }
   if (x < 0) {
     x = 2;
     ix = Math.random() * w / 32 + 1;
   }
   if ((y + eh) > h) {
     y = (h - eh) - 2;
     iy = Math.random() * -h / 32 - 1;
   }
   if (y < 0) {
     y = 2;
     iy = Math.random() * h / 32 + 1;
   }
   ellipse.setFrame(x, y, ew, eh);
   g2.setClip(ellipse);
   rect.setRect(x + 5, y + 5, ew - 10, eh - 10);
   g2.clip(rect);
   g2.drawImage(img, 0, 0, w, h, this);
   p.reset();
   p.moveTo(-w / 2.0f, -h / 8.0f);
   p.lineTo(+w / 2.0f, -h / 8.0f);
   p.lineTo(-w / 4.0f, +h / 2.0f);
   p.lineTo(+0.0f, -h / 2.0f);
   p.lineTo(+w / 4.0f, +h / 2.0f);
   p.closePath();
   at.setToIdentity();
   at.translate(w * .5f, h * .5f);
   g2.transform(at);
   g2.setStroke(bs);
   g2.setPaint(redBlend);
   g2.draw(p);
   at.setToIdentity();
   g2.setTransform(at);
   g2.setPaint(greenBlend);
   for (int yy = 0; yy < h; yy += 50) {
     for (int xx = 0, i = 0; xx < w; i++, xx += 50) {
       switch (i) {
       case 0:
         arc.setArc(xx, yy, 25, 25, 45, 270, Arc2D.PIE);
         g2.fill(arc);
         break;
       case 1:
         ellipse.setFrame(xx, yy, 25, 25);
         g2.fill(ellipse);
         break;
       case 2:
         roundRect.setRoundRect(xx, yy, 25, 25, 4, 4);
         g2.fill(roundRect);
         break;
       case 3:
         rect.setRect(xx, yy, 25, 25);
         g2.fill(rect);
         i = -1;
       }
     }
   }
 }
 public Graphics2D createDemoGraphics2D(Graphics g) {
   Graphics2D g2 = null;
   if (offImg == null || offImg.getWidth() != w || offImg.getHeight() != h) {
     offImg = (BufferedImage) createImage(w, h);
     newBufferedImage = true;
   }
   if (offImg != null) {
     g2 = offImg.createGraphics();
     g2.setBackground(getBackground());
   }
   // .. set attributes ..
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   g2.setRenderingHint(RenderingHints.KEY_RENDERING,
       RenderingHints.VALUE_RENDER_QUALITY);
   // .. clear canvas ..
   g2.clearRect(0, 0, w, h);
   return g2;
 }
 public void paint(Graphics g) {
   w = getWidth();
   h = getHeight();
   if (w <= 0 || h <= 0)
     return;
   Graphics2D g2 = createDemoGraphics2D(g);
   drawDemo(g2);
   g2.dispose();
   if (offImg != null && isShowing()) {
     g.drawImage(offImg, 0, 0, this);
   }
   newBufferedImage = false;
 }
 public void start() {
   thread = new Thread(this);
   thread.start();
 }
 public synchronized void stop() {
   thread = null;
 }
 public void run() {
   Thread me = Thread.currentThread();
   while (thread == me && isShowing()) {
     Graphics g = getGraphics();
     paint(g);
     g.dispose();
     thread.yield();
   }
   thread = null;
 }
 protected URL getURL(String filename) {
   URL codeBase = this.getCodeBase();
   URL url = null;
   try {
     url = new URL(codeBase, filename);
   } catch (java.net.MalformedURLException e) {
     System.out.println("Couldn"t create image: "
         + "badly specified URL");
     return null;
   }
   return url;
 }
 public static void main(String s[]) {
   final ClipImage demo = new ClipImage();
   WindowListener l = new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
     public void windowDeiconified(WindowEvent e) {
       demo.start();
     }
     public void windowIconified(WindowEvent e) {
       demo.stop();
     }
   };
   JFrame f = new JFrame("Java 2D Demo - ClipImage");
   f.addWindowListener(l);
   f.getContentPane().add("Center", demo);
   f.setSize(new Dimension(400, 300));
   f.show();
   demo.start();
 }

}



 </source>   



Clipping is restricting of drawing to a certain area.

<source lang="java"> import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Ellipse2D; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; public class Clipping extends JPanel implements ActionListener {

 int x = 8, y = 8, radius = 90;
 Timer timer;
 Image image = new ImageIcon("yourImage.png").getImage();
 double delta[] = { 3, 3 };
 public Clipping() {
   timer = new Timer(15, this);
   timer.start();
 }
 public void paint(Graphics g) {
   Graphics2D g2d = (Graphics2D) g;
   g2d.setClip(new Ellipse2D.Double(x, y, radius, radius));
   g2d.drawImage(image, 5, 5, null);
 }
 public static void main(String[] args) {
   JFrame frame = new JFrame();
   frame.add(new Clipping());
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setSize(400, 400);
   frame.setVisible(true);
 }
 public void actionPerformed(ActionEvent e) {
   int w = 400;
   int h = 400;
   if (x < 0) {
     delta[0] = Math.random() % 4 + 5;
   } else if (x > w - radius) {
     delta[0] = -(Math.random() % 4 + 5);
   }
   if (y < 0) {
     delta[1] = Math.random() % 4 + 5;
   } else if (y > h - radius) {
     delta[1] = -(Math.random() % 4 + 5);
   }
   x += delta[0];
   y += delta[1];
   repaint();
 }

}



 </source>   



Clips the specified line to the given rectangle.

<source lang="java"> /*

* JFreeChart : a free chart library for the Java(tm) platform
* 
*
* (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
*
* Project Info:  http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------------
* LineUtilities.java
* ------------------
* (C) Copyright 2008, by Object Refinery Limited and Contributors.
*
* Original Author:  David Gilbert (for Object Refinery Limited);
* Contributor(s):   -;
*
* Changes
* -------
* 05-Nov-2008 : Version 1 (DG);
*
*/

import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; /**

* Some utility methods for {@link Line2D} objects.
*
* @since 1.0.12
*/

public class LineUtilities {

   /**
    * Clips the specified line to the given rectangle.
    *
    * @param line  the line (null not permitted).
    * @param rect  the clipping rectangle (null not permitted).
    *
    * @return true if the clipped line is visible, and
    *     false otherwise.
    */
   public static boolean clipLine(Line2D line, Rectangle2D rect) {
       double x1 = line.getX1();
       double y1 = line.getY1();
       double x2 = line.getX2();
       double y2 = line.getY2();
       double minX = rect.getMinX();
       double maxX = rect.getMaxX();
       double minY = rect.getMinY();
       double maxY = rect.getMaxY();
       int f1 = rect.outcode(x1, y1);
       int f2 = rect.outcode(x2, y2);
       while ((f1 | f2) != 0) {
           if ((f1 & f2) != 0) {
               return false;
           }
           double dx = (x2 - x1);
           double dy = (y2 - y1);
           // update (x1, y1), (x2, y2) and f1 and f2 using intersections
           // then recheck
           if (f1 != 0) {
               // first point is outside, so we update it against one of the
               // four sides then continue
               if ((f1 & Rectangle2D.OUT_LEFT) == Rectangle2D.OUT_LEFT
                       && dx != 0.0) {
                   y1 = y1 + (minX - x1) * dy / dx;
                   x1 = minX;
               }
               else if ((f1 & Rectangle2D.OUT_RIGHT) == Rectangle2D.OUT_RIGHT
                       && dx != 0.0) {
                   y1 = y1 + (maxX - x1) * dy / dx;
                   x1 = maxX;
               }
               else if ((f1 & Rectangle2D.OUT_BOTTOM) == Rectangle2D.OUT_BOTTOM
                       && dy != 0.0) {
                   x1 = x1 + (maxY - y1) * dx / dy;
                   y1 = maxY;
               }
               else if ((f1 & Rectangle2D.OUT_TOP) == Rectangle2D.OUT_TOP
                       && dy != 0.0) {
                   x1 = x1 + (minY - y1) * dx / dy;
                   y1 = minY;
               }
               f1 = rect.outcode(x1, y1);
           }
           else if (f2 != 0) {
               // second point is outside, so we update it against one of the
               // four sides then continue
               if ((f2 & Rectangle2D.OUT_LEFT) == Rectangle2D.OUT_LEFT
                       && dx != 0.0) {
                   y2 = y2 + (minX - x2) * dy / dx;
                   x2 = minX;
               }
               else if ((f2 & Rectangle2D.OUT_RIGHT) == Rectangle2D.OUT_RIGHT
                       && dx != 0.0) {
                   y2 = y2 + (maxX - x2) * dy / dx;
                   x2 = maxX;
               }
               else if ((f2 & Rectangle2D.OUT_BOTTOM) == Rectangle2D.OUT_BOTTOM
                       && dy != 0.0) {
                   x2 = x2 + (maxY - y2) * dx / dy;
                   y2 = maxY;
               }
               else if ((f2 & Rectangle2D.OUT_TOP) == Rectangle2D.OUT_TOP
                       && dy != 0.0) {
                   x2 = x2 + (minY - y2) * dx / dy;
                   y2 = minY;
               }
               f2 = rect.outcode(x2, y2);
           }
       }
       line.setLine(x1, y1, x2, y2);
       return true;  // the line is visible - if it wasn"t, we"d have
                     // returned false from within the while loop above
   }

}


 </source>   



Clip the area

<source lang="java"> import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Rectangle; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; public class ClipDemo extends JComponent {

 private static Color red = new Color(255, 0, 0, 150);
 private static Color green = new Color(0, 255, 0, 150);
 private static Color blue = new Color(0, 0, 255, 150);
 private static Font monoFont = new Font("Monospaced", Font.BOLD
     | Font.ITALIC, 36);
 private static Font sanFont = new Font("SanSerif", Font.PLAIN, 12);
 private static Font serifFont = new Font("Serif", Font.BOLD, 24);
 private static ImageIcon jexpLogo = new ImageIcon("jexpLogo.gif");
 public void paintComponent(Graphics g) {
   super.paintComponent(g);
   // get damaged region
   Rectangle clipRect = g.getClipBounds();
   int clipx = clipRect.x;
   int clipy = clipRect.y;
   int clipw = clipRect.width;
   int cliph = clipRect.height;
   // fill damaged region only
   g.setColor(Color.white);
   g.fillRect(clipx, clipy, clipw, cliph);
   if (clipx <= 240 && clipy <= 240) {
     g.setColor(Color.yellow);
     g.fillOval(0, 0, 240, 240);
     System.out.println(" yellow Oval repainted.");
   }
   if (clipx + clipw >= 160 && clipx <= 400 && clipy + cliph >= 160
       && clipy <= 400) {
     g.setColor(Color.magenta);
     g.fillOval(160, 160, 240, 240);
     System.out.println(" magenta Oval repainted.");
   }
   int iconWidth = jexpLogo.getIconWidth();
   int iconHeight = jexpLogo.getIconHeight();
   if (clipx + clipw >= 280 - (iconWidth / 2) && clipx <= (280 + (iconWidth / 2))
       && clipy + cliph >= 120 - (iconHeight / 2) && clipy <= (120 + (iconHeight / 2))) {
     jexpLogo.paintIcon(this, g, 280 - (iconWidth / 2), 120 - (iconHeight / 2));
     System.out.println(" logo below blue Rect repainted.");
   }
   if (clipx + clipw >= 120 - (iconWidth / 2) && clipx <= (120 + (iconWidth / 2))
       && clipy + cliph >= 280 - (iconHeight / 2) && clipy <= (280 + (iconHeight / 2))) {
     jexpLogo.paintIcon(this, g, 120 - (iconWidth / 2), 280 - (iconHeight / 2));
     System.out.println(" logo below red Rect repainted.");
   }
   if (clipx + clipw >= 60 && clipx <= 180 && clipy + cliph >= 220
       && clipy <= 340) {
     g.setColor(red);
     g.fillRect(60, 220, 120, 120);
     System.out.println(" red Rect repainted.");
   }
   if (clipx + clipw > 140 && clipx < 260 && clipy + cliph > 140
       && clipy < 260) {
     g.setColor(green);
     g.fillOval(140, 140, 120, 120);
     System.out.println(" green Oval repainted.");
   }
   if (clipx + clipw > 220 && clipx < 380 && clipy + cliph > 60
       && clipy < 180) {
     g.setColor(blue);
     g.fillRect(220, 60, 120, 120);
     System.out.println(" blue Rect repainted.");
   }
   g.setColor(Color.black);
   g.setFont(monoFont);
   FontMetrics fm = g.getFontMetrics();
   iconWidth = fm.stringWidth("Java Source");
   iconHeight = fm.getAscent();
   int d = fm.getDescent();
   if (clipx + clipw > 120 - (iconWidth / 2) && clipx < (120 + (iconWidth / 2))
       && clipy + cliph > (120 + (iconHeight / 4)) - iconHeight
       && clipy < (120 + (iconHeight / 4)) + d) {
     g.drawString("Java Source", 120 - (iconWidth / 2), 120 + (iconHeight / 4));
     System.out.println(" Java Source repainted.");
   }
   g.setFont(sanFont);
   fm = g.getFontMetrics();
   iconWidth = fm.stringWidth("and");
   iconHeight = fm.getAscent();
   d = fm.getDescent();
   if (clipx + clipw > 200 - (iconWidth / 2) && clipx < (200 + (iconWidth / 2))
       && clipy + cliph > (200 + (iconHeight / 4)) - iconHeight
       && clipy < (200 + (iconHeight / 4)) + d) {
     g.drawString("and", 200 - (iconWidth / 2), 200 + (iconHeight / 4));
     System.out.println(" and repainted.");
   }
   g.setFont(serifFont);
   fm = g.getFontMetrics();
   iconWidth = fm.stringWidth("Support.");
   iconHeight = fm.getAscent();
   d = fm.getDescent();
   if (clipx + clipw > 280 - (iconWidth / 2) && clipx < (280 + (iconWidth / 2))
       && clipy + cliph > (280 + (iconHeight / 4)) - iconHeight
       && clipy < (280 + (iconHeight / 4)) + d) {
     g.drawString("Support.", 280 - (iconWidth / 2), 280 + (iconHeight / 4));
     System.out.println(" Support. repainted.");
   }
 }
 public Dimension getPreferredSize() {
   return new Dimension(400, 400);
 }
 public Dimension getMinimumSize() {
   return getPreferredSize();
 }
 public static void main(String args[]) {
   JFrame mainFrame = new JFrame();
   mainFrame.getContentPane().add(new ClipDemo());
   mainFrame.pack();
   mainFrame.setVisible(true);
 }

}



 </source>   



Copy Area Performance

<source lang="java">


import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.SwingUtilities; /*

* CopyAreaPerformance.java
*
* Created on May 1, 2007, 4:24 PM
*
* Copyright (c) 2007, Sun Microsystems, Inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the TimingFramework project nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

* 
* @author Chet
*/

public class CopyAreaPerformance extends JComponent implements KeyListener {

 private static final int SMILEY_SIZE = 10;
 private static final int PADDING = 2;
 private static final int MIN_COLOR = 0;
 private static final int CANVAS_W = SMILEY_SIZE * (256 - MIN_COLOR);
 private static final int CANVAS_H = SMILEY_SIZE * (256 - MIN_COLOR);
 private static final int SCROLL_SIZE = 100;
 private int viewX = CANVAS_W / 2;
 private int viewY = CANVAS_H / 2;
 private boolean useCopyArea = false;
 private boolean useClip = false;
 int prevVX;
 int prevVY;
 /** Creates a new instance of CopyAreaPerformance */
 public CopyAreaPerformance() {
   setOpaque(true);
 }
 private void drawSmiley(Graphics g, Color faceColor, int x, int y) {
   // fill face color
   g.setColor(faceColor);
   g.fillOval(x, y, SMILEY_SIZE, SMILEY_SIZE);
   g.setColor(Color.BLACK);
   // draw head
   g.drawOval(x, y, SMILEY_SIZE, SMILEY_SIZE);
   // draw smile
   g.drawArc(x + (int) ((SMILEY_SIZE * .2)), (int) (y + (SMILEY_SIZE * .2)),
       (int) (SMILEY_SIZE * .6), (int) (SMILEY_SIZE * .6), 200, 140);
   // draw eyes
   int eyeSize = Math.max(2, (int) (SMILEY_SIZE * .1));
   g.fillOval(x + (int) ((SMILEY_SIZE * .5) - (SMILEY_SIZE * .1) - eyeSize), y
       + (int) (SMILEY_SIZE * .3), eyeSize, eyeSize);
   g.fillOval(x + (int) ((SMILEY_SIZE * .5) + (SMILEY_SIZE * .1)), y + (int) (SMILEY_SIZE * .3),
       eyeSize, eyeSize);
 }
 protected void paintComponent(Graphics g) {
   long startTime = System.nanoTime();
   // prevVX is set to -10000 when first enabled
   if (useCopyArea && prevVX > -9999) {
     // Most of this code determines the proper areas to copy and clip
     int scrollX = viewX - prevVX;
     int scrollY = viewY - prevVY;
     int copyFromY, copyFromX;
     int clipFromY, clipFromX;
     if (scrollX == 0) {
       // vertical scroll
       if (scrollY < 0) {
         copyFromY = 0;
         clipFromY = 0;
       } else {
         copyFromY = scrollY;
         clipFromY = getHeight() - scrollY;
       }
       // copy the old content, set the clip to the new area
       g.copyArea(0, copyFromY, getWidth(), getHeight() - Math.abs(scrollY), 0, -scrollY);
       g.setClip(0, clipFromY, getWidth(), Math.abs(scrollY));
     } else {
       // horizontal scroll
       if (scrollX < 0) {
         copyFromX = 0;
         clipFromX = 0;
       } else {
         copyFromX = scrollX;
         clipFromX = getWidth() - scrollX;
       }
       // copy the old content, set the clip to the new area
       g.copyArea(copyFromX, 0, getWidth() - Math.abs(scrollX), getHeight(), -scrollX, 0);
       g.setClip(clipFromX, 0, Math.abs(scrollX), getHeight());
     }
   }
   // Track previous view position for next scrolling operation
   prevVX = viewX;
   prevVY = viewY;
   // Get the clip in case we need it later
   Rectangle clipRect = g.getClip().getBounds();
   int clipL = (int) (clipRect.getX());
   int clipT = (int) (clipRect.getY());
   int clipR = (int) (clipRect.getMaxX());
   int clipB = (int) (clipRect.getMaxY());
   g.setColor(Color.WHITE);
   g.fillRect(clipL, clipT, (int) clipRect.getWidth(), (int) clipRect.getHeight());
   for (int column = 0; column < 256; ++column) {
     int x = column * (SMILEY_SIZE + PADDING) - viewX;
     if (useClip) {
       if (x > clipR || (x + (SMILEY_SIZE + PADDING)) < clipL) {
         // trivial reject; outside to the left or right
         continue;
       }
     }
     for (int row = 0; row < 256; ++row) {
       int y = row * (SMILEY_SIZE + PADDING) - viewY;
       if (useClip) {
         if (y > clipB || (y + (SMILEY_SIZE + PADDING)) < clipT) {
           // trivial reject; outside to the top or bottom
           continue;
         }
       }
       Color faceColor = new Color(column, row, 0);
       drawSmiley(g, faceColor, x, y);
     }
   }
   long stopTime = System.nanoTime();
   System.out.println("Painted in " + ((stopTime - startTime) / 1000000) + " ms");
 }
 private void scroll(int scrollX, int scrollY) {
   viewX += scrollX;
   viewY += scrollY;
   viewX = Math.max(viewX, 0);
   viewX = Math.min(viewX, CANVAS_W - viewX);
   viewY = Math.max(viewY, 0);
   viewY = Math.min(viewY, CANVAS_H - viewY);
   repaint();
 }
 // KeyListener methods
 /**
  * Arrow keys scroll the view around. The "c" key toggles clip area
  * optimization. The "a" key toggles copyArea optimization.
  */
 public void keyPressed(KeyEvent e) {
   if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
     scroll(SCROLL_SIZE, 0);
   } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
     scroll(-SCROLL_SIZE, 0);
   } else if (e.getKeyCode() == KeyEvent.VK_UP) {
     scroll(0, -SCROLL_SIZE);
   } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
     scroll(0, SCROLL_SIZE);
   } else if (e.getKeyCode() == KeyEvent.VK_C) {
     useClip = !useClip;
     System.out.println("useClip = " + useClip);
   } else if (e.getKeyCode() == KeyEvent.VK_A) {
     useCopyArea = !useCopyArea;
     prevVX = -10000;
     System.out.println("useCopyArea = " + useCopyArea);
   }
 }
 public void keyReleased(KeyEvent e) {
 }
 public void keyTyped(KeyEvent e) {
 }
 private static void createAndShowGUI() {
   JFrame f = new JFrame("CopyAreaPerformance");
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   f.setSize(600, 600);
   CopyAreaPerformance component = new CopyAreaPerformance();
   f.add(component);
   f.addKeyListener(component);
   f.setVisible(true);
 }
 public static void main(String args[]) {
   Runnable doCreateAndShowGUI = new Runnable() {
     public void run() {
       createAndShowGUI();
     }
   };
   SwingUtilities.invokeLater(doCreateAndShowGUI);
 }

}



 </source>   



Represents a clipping rectangle in a prefuse Display

<source lang="java"> //revised from prefuse display; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.util.logging.Logger; /**

* Represents a clipping rectangle in a prefuse Display.
*
* @author 
*/

public class Clip {

   private static final byte EMPTY   = 0;
   private static final byte INUSE   = 1;
   private static final byte INVALID = 2;
   
   private double[] clip = new double[8];
   private byte status = INVALID;
   
   /**
    * Reset the clip to an empty status.
    */
   public void reset() {
       status = EMPTY;
   }
   
   /**
    * Invalidate the clip. In this state, the clip contents have no meaning.
    */
   public void invalidate() {
       status = INVALID;
   }
      
   /**
    * Set the clip contents, and set the status to valid and in use.
    * @param c the clip whose contents should be copied
    */
   public void setClip(Clip c) {
       status = INUSE;
       System.arraycopy(c.clip, 0, clip, 0, clip.length);
   }
   
   /**
    * Set the clip contents, and set the status to valid and in use.
    * @param r the clip contents to copy
    */
   public void setClip(Rectangle2D r) {
       setClip(r.getX(),r.getY(),r.getWidth(),r.getHeight());
   }
   
   /**
    * Set the clip contents, and set the status to valid and in use.
    * @param x the minimum x-coordinate
    * @param y the minimum y-coorindate
    * @param w the clip width
    * @param h the clip height
    */
   public void setClip(double x, double y, double w, double h) {
       status = INUSE;
       clip[0] = x;
       clip[1] = y;
       clip[6] = x+w;
       clip[7] = y+h;
   }
   
   /**
    * Transform the clip contents. A new clip region will be created
    * which is the bounding box of the transformed region.
    * @param at the affine transform
    */
   public void transform(AffineTransform at) {
       // make the extra corner points valid
       clip[2] = clip[0]; clip[3] = clip[7];
       clip[4] = clip[6]; clip[5] = clip[1];
       
       // transform the points
       at.transform(clip,0,clip,0,4);
       
       // make safe against rotation
       double xmin = clip[0], ymin = clip[1];
       double xmax = clip[6], ymax = clip[7];
       for ( int i=0; i<7; i+=2 ) {
           if ( clip[i] < xmin )
               xmin = clip[i];
           if ( clip[i] > xmax )
               xmax = clip[i];
           if ( clip[i+1] < ymin )
               ymin = clip[i+1];
           if ( clip[i+1] > ymax )
               ymax = clip[i+1];
       }
       clip[0] = xmin; clip[1] = ymin;
       clip[6] = xmax; clip[7] = ymax;
   }
   
   /**
    * Limit the clip such that it fits within the specified region.
    * @param x1 the minimum x-coordinate
    * @param y1 the minimum y-coorindate
    * @param x2 the maximum x-coordinate
    * @param y2 the maximum y-coorindate
    */
   public void limit(double x1, double y1, double x2, double y2) {
       clip[0] = Math.max(clip[0],x1);
       clip[1] = Math.max(clip[1],y1);
       clip[6] = Math.min(clip[6],x2);
       clip[7] = Math.min(clip[7],y2);
   }
   
   /**
    * Indicates if this Clip intersects the given rectangle expanded
    * by the additional margin pace.
    * @param r the rectangle to test for intersect
    * @param margin additional margin "bleed" to include in the intersection
    * @return true if the clip intersects the expanded region, false otherwise
    */
   public boolean intersects(Rectangle2D r, double margin) {
       double tw = clip[6]-clip[0];
       double th = clip[7]-clip[1];
       double rw = r.getWidth();
       double rh = r.getHeight();
       if (rw < 0 || rh < 0 || tw < 0 || th < 0) {
           return false;
       }
       double tx = clip[0];
       double ty = clip[1];
       double rx = r.getX()-margin;
       double ry = r.getY()-margin;
       rw += rx+2*margin;
       rh += ry+2*margin;
       tw += tx;
       th += ty;
       //      overflow || intersect
       return ((rw < rx || rw > tx) &&
               (rh < ry || rh > ty) &&
               (tw < tx || tw > rx) &&
               (th < ty || th > ry));
   }
     
   /**
    * Union this clip with another clip. As a result, this clip
    * will become a bounding box around the two original clips.
    * @param c the clip to union with
    */
   public void union(Clip c) {
       if ( status == INVALID )
           return;
       if ( status == EMPTY ) {
           setClip(c);
           status = INUSE;
           return;
       }
       clip[0] = Math.min(clip[0], c.clip[0]);
       clip[1] = Math.min(clip[1], c.clip[1]);
       clip[6] = Math.max(clip[6], c.clip[6]);
       clip[7] = Math.max(clip[7], c.clip[7]);
   }
   
   /**
    * Union this clip with another region. As a result, this clip
    * will become a bounding box around the two original regions.
    * @param r the rectangle to union with
    */
   public void union(Rectangle2D r) {
       if ( status == INVALID )
           return;
       
       double minx = r.getMinX();
       double miny = r.getMinY();
       double maxx = r.getMaxX();
       double maxy = r.getMaxY();
       
       if ( Double.isNaN(minx) || Double.isNaN(miny) ||
            Double.isNaN(maxx) || Double.isNaN(maxy) ) {
           Logger.getLogger(getClass().getName()).warning(
               "Union with invalid clip region: "+r);
           return;
       }
       
       if ( status == EMPTY ) {
           setClip(r);
           status = INUSE;
           return;
       }
       clip[0] = Math.min(clip[0], minx);
       clip[1] = Math.min(clip[1], miny);
       clip[6] = Math.max(clip[6], maxx);
       clip[7] = Math.max(clip[7], maxy);
   }
   
   /**
    * Union this clip with another region. As a result, this clip
    * will become a bounding box around the two original regions.
    * @param x the x-coordinate of the region to union with
    * @param y the y-coordinate of the region to union with
    * @param w the width of the region to union with
    * @param h the height of the region to union with
    */
   public void union(double x, double y, double w, double h) {
       if ( status == INVALID )
           return;
       if ( status == EMPTY ) {
           setClip(x,y,w,h);
           status = INUSE;
           return;
       }
       clip[0] = Math.min(clip[0], x);
       clip[1] = Math.min(clip[1], y);
       clip[6] = Math.max(clip[6], x+w);
       clip[7] = Math.max(clip[7], y+h);
   }
   
   /**
    * Intersect this clip with another region. As a result, this
    * clip will become the intersecting area of the two regions.
    * @param c the clip to intersect with
    */
   public void intersection(Clip c) {
       if ( status == INVALID )
           return;
       if ( status == EMPTY ) {
           setClip(c);
           status = INUSE;
           return;
       }
       clip[0] = Math.max(clip[0], c.clip[0]);
       clip[1] = Math.max(clip[1], c.clip[1]);
       clip[6] = Math.min(clip[6], c.clip[6]);
       clip[7] = Math.min(clip[7], c.clip[7]);
   }
   
   /**
    * Intersect this clip with another region. As a result, this
    * clip will become the intersecting area of the two regions.
    * @param r the rectangle to intersect with
    */
   public void intersection(Rectangle2D r) {
       if ( status == INVALID )
           return;
       if ( status == EMPTY ) {
           setClip(r);
           status = INUSE;
           return;
       }
       clip[0] = Math.max(clip[0], r.getMinX());
       clip[1] = Math.max(clip[1], r.getMinY());
       clip[6] = Math.min(clip[6], r.getMaxX());
       clip[7] = Math.min(clip[7], r.getMaxY());
   }
   
   /**
    * Intersect this clip with another region. As a result, this
    * clip will become the intersecting area of the two regions.
    * @param x the x-coordinate of the region to intersect with
    * @param y the y-coordinate of the region to intersect with
    * @param w the width of the region to intersect with
    * @param h the height of the region to intersect with
    */
   public void intersection(double x, double y, double w, double h) {
       if ( status == INVALID )
           return;
       if ( status == EMPTY ) {
           setClip(x,y,w,h);
           status = INUSE;
           return;
       }
       clip[0] = Math.max(clip[0], x);
       clip[1] = Math.max(clip[1], y);
       clip[6] = Math.min(clip[6], x+w);
       clip[7] = Math.min(clip[7], y+h);
   }
   
   /**
    * Minimally expand the clip such that each coordinate is an integer.
    */
   public void expandToIntegerLimits() {
       clip[0] = Math.floor(clip[0]);
       clip[1] = Math.floor(clip[1]);
       clip[6] = Math.ceil(clip[6]);
       clip[7] = Math.ceil(clip[7]);
   }
   
   /**
    * Expand the clip in all directions by the given value.
    * @param b the value to expand by
    */
   public void expand(double b) {
       clip[0] -= b; clip[1] -= b;
       clip[6] += b; clip[7] += b;
   }
   /**
    * Grow the clip width and height by the given value. The minimum
    * coordinates will be unchanged.
    * @param b the value to grow the width and height by
    */
   public void grow(double b) {
       clip[6] += b; clip[7] += b;
   }
   
   /**
    * Get the minimum x-coordinate.
    * @return the minimum x-coordinate
    */
   public double getMinX() {
       return clip[0];
   }
   
   /**
    * Get the minimum y-coordinate.
    * @return the minimum y-coordinate
    */
   public double getMinY() {
       return clip[1];
   }
   
   /**
    * Get the maximum x-coordinate.
    * @return the maximum x-coordinate
    */
   public double getMaxX() {
       return clip[6];
   }
   
   /**
    * Get the maximum y-coordinate.
    * @return the maximum y-coordinate
    */
   public double getMaxY() {
       return clip[7];
   }
   
   /**
    * Get the clip"s width
    * @return the clip width
    */
   public double getWidth() {
       return clip[6]-clip[0];
   }
   /**
    * Get the clip"s height
    * @return the clip height
    */
   public double getHeight() {
       return clip[7]-clip[1];
   }
   
   /**
    * Indicates if the clip is set to an empty status.
    * @return true if the clip is set to empty, false otherwise
    */
   public boolean isEmpty() {
       return status==EMPTY;
   }
   
   /**
    * Indicates if the clip is set to an invalid status.
    * @return true if the clip is set to invalid, false otherwise
    */
   public boolean isInvalid() {
       return status==INVALID;
   }
   
   // ------------------------------------------------------------------------
   
   /**
    * @see java.lang.Object#equals(java.lang.Object)
    */
   public boolean equals(Object o) {
       if ( o instanceof Rectangle2D ) {
           Rectangle2D r = (Rectangle2D)o;
           return ( r.getMinX()==clip[0] && r.getMinY()==clip[1] &&
                    r.getMaxX()==clip[6] && r.getMaxY()==clip[7] );
       } else if ( o instanceof Clip ) {
           Clip r = (Clip)o;
           if ( r.status == status ) {
               if ( status == Clip.INUSE )
                   return ( r.clip[0]==clip[0] && r.clip[1]==clip[1] &&
                           r.clip[6]==clip[6] && r.clip[7]==clip[7] );
               else
                   return true;
           } else {
               return false;
           }
       } else {
           return false;
       }
   }
   
   /**
    * @see java.lang.Object#toString()
    */
   public String toString() {
       StringBuffer sb = new StringBuffer(20);
       sb.append("Clip[");
       switch (status) {
       case INVALID:
           sb.append("invalid");
           break;
       case EMPTY:
           sb.append("empty");
           break;
       default:
           sb.append(clip[0]).append(",");
           sb.append(clip[1]).append(",");
           sb.append(clip[6]).append(",");
           sb.append(clip[7]);
       }
       sb.append("]");
       return sb.toString();
   }
   

} // end of class Clip


 </source>   



set Clip and get Clip

<source lang="java"> /*

* Java2DUtils.java
* 
* Created on Aug 30, 2007, 11:40:18 AM
* 
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

//Revised from jaspersoft ireport designer import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.util.Stack; /**

*
* @author gtoffoli
*/

public class Java2DUtils {

 private static Stack clipBoundsStack = new Stack();
 private static Stack transforms = new Stack();
 public static void setClip(Graphics g, int x, int y, int width, int height)
 {
   setClip(g, new Rectangle(x, y, width, height));
 }
   @SuppressWarnings("unchecked")
 public static void setClip(Graphics g, Rectangle clipBounds)
 {
   Rectangle currentClipBounds;
   clipBounds = new Rectangle(clipBounds);
   clipBounds.width += 1;
   clipBounds.height += 1;
   currentClipBounds = g.getClipBounds();
   if(currentClipBounds != null)
   {
     clipBounds = clipBounds.intersection(g.getClipBounds());
   }
   clipBoundsStack.push(currentClipBounds);
   g.setClip(clipBounds);
 }
 public static void resetClip(Graphics g)
 {
   g.setClip((Shape) clipBoundsStack.pop());
 }
 
   @SuppressWarnings("unchecked")
   public static void setTransform(Graphics2D g2, AffineTransform transform)
 {
   AffineTransform current;
   current = g2.getTransform();
   transforms.push(current);
   g2.setTransform(transform);
 }
 public static void resetTransform(Graphics2D g2)
 {
   if(transforms.empty())
   {
     return;
   }
   g2.setTransform((AffineTransform) transforms.pop());
 }
 

}


 </source>   



Setting the Clipping Area with a Shape

<source lang="java"> import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; public class BasicDraw {

 public static void main(String[] args) {
   JFrame frame = new JFrame();
   frame.add(new MyComponent());
   frame.setSize(300, 300);
   frame.setVisible(true);
 }

} class MyComponent extends JComponent {

 public void paint(Graphics g) {
   Graphics2D g2d = (Graphics2D) g;
   Shape shape = new java.awt.geom.Ellipse2D.Float(20, 20, 200,200);
   g2d.setClip(shape);
   int x = 0;
   int y = 0;
   g2d.drawImage(new ImageIcon("a.png").getImage(), x, y, this);
 }

}



 </source>