Java/2D Graphics GUI/Clip
Содержание
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). * * @returntrue
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>