Staging
v0.5.0
v0.5.0
https://repo1.maven.org/maven2/org/prefuse/prefuse
BackgroundPainter.java
/**
* Copyright (c) 2004-2006 Regents of the University of California.
* See "license-prefuse.txt" for licensing terms.
*/
package prefuse.util.display;
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.net.URL;
import prefuse.Display;
import prefuse.util.io.IOLib;
/**
* Paints a background image in a display. The image can either pan and zoom
* along with the display or stay stationary. Additionally, the image can
* be optionally tiled across the Display space. This class is used by
* the {@link prefuse.Display} class in response to the
* {@link prefuse.Display#setBackgroundImage(Image, boolean, boolean)} and
* {@link prefuse.Display#setBackgroundImage(String, boolean, boolean)}
* methods.
*
* @author <a href="http://jheer.org">jeffrey heer</a>
*/
public class BackgroundPainter implements PaintListener {
private static final double THRESH = 0.01;
private Image m_img;
private boolean m_fixed;
private boolean m_tiled;
private AffineTransform m_identity;
private Clip m_clip;
/**
* Create a new BackgroundPainter.
* @param imageLocation a location String of where to retrieve the
* image file from. Uses
* {@link prefuse.util.io.IOLib#urlFromString(String)} to resolve
* the String.
* @param fixed true if the background image should stay in a fixed
* position, invariant to panning, zooming, or rotation; false if
* the image should be subject to view transforms
* @param tile true to tile the image across the visible background,
* false to only include the image once
*/
public BackgroundPainter(String imageLocation, boolean fixed, boolean tile)
{
URL url = IOLib.urlFromString(imageLocation);
m_img = Toolkit.getDefaultToolkit().getImage(url);
MediaTracker mt = new MediaTracker(new Container());
mt.addImage(m_img, 0);
try {
mt.waitForID(0);
} catch ( Exception e ) { e.printStackTrace(); }
mt.removeImage(m_img, 0);
m_fixed = fixed;
m_tiled = tile;
}
/**
* Create a new BackgroundPainter.
* @param image the background Image
* @param fixed true if the background image should stay in a fixed
* position, invariant to panning, zooming, or rotation; false if
* the image should be subject to view transforms
* @param tile true to tile the image across the visible background,
* false to only include the image once
*/
public BackgroundPainter(Image image, boolean fixed, boolean tile) {
m_img = image;
m_fixed = fixed;
m_tiled = tile;
}
/**
* Paint the background.
* @see prefuse.util.display.PaintListener#prePaint(prefuse.Display, java.awt.Graphics2D)
*/
public void prePaint(Display d, Graphics2D g) {
AffineTransform at = g.getTransform();
boolean translate = isTranslation(at);
if ( m_fixed || translate )
{
// if the background is fixed, we can unset the transform.
// if we have no scaling component, we draw the image directly
// rather than run it through the transform.
// this avoids rendering artifacts on Java 1.5 on Win32.
int tx = m_fixed ? 0 : (int)at.getTranslateX();
int ty = m_fixed ? 0 : (int)at.getTranslateY();
g.setTransform(getIdentity());
if ( m_tiled ) {
// if tiled, compute visible background region and draw tiles
int w = d.getWidth(), iw = m_img.getWidth(null);
int h = d.getHeight(), ih = m_img.getHeight(null);
int sx = m_fixed ? 0 : tx%iw;
int sy = m_fixed ? 0 : ty%ih;
if ( sx > 0 ) sx -= iw;
if ( sy > 0 ) sy -= ih;
for ( int x=sx; x<w-sx; x+=iw ) {
for ( int y=sy; y<h-sy; y+=ih )
g.drawImage(m_img, x, y, null);
}
} else {
// if not tiled, simply draw the image at the translated origin
g.drawImage(m_img, tx, ty, null);
}
g.setTransform(at);
}
else
{
// run the image through the display transform
if ( m_tiled ) {
int iw = m_img.getWidth(null);
int ih = m_img.getHeight(null);
// get the screen region and map it into item-space
Clip c = getClip();
c.setClip(0, 0, d.getWidth(), d.getHeight());
c.transform(d.getInverseTransform());
// get the bounding region for image tiles
int w = (int)Math.ceil(c.getWidth());
int h = (int)Math.ceil(c.getHeight());
int tx = (int)c.getMinX();
int ty = (int)c.getMinY();
int dw = tx%iw + iw;
int dh = ty%ih + ih;
tx -= dw; w += dw;
ty -= dh; h += dh;
// draw the image tiles
for ( int x=tx; x<tx+w; x+=iw ) {
for ( int y=ty; y<ty+h; y+=ih )
g.drawImage(m_img, x, y, null);
}
} else {
// if not tiled, simply draw the image
g.drawImage(m_img, 0, 0, null);
}
}
}
/**
* Check if the given AffineTransform is a translation
* (within thresholds -- see {@link #THRESH}.
*/
private static boolean isTranslation(AffineTransform at) {
return ( Math.abs(at.getScaleX()-1.0) < THRESH &&
Math.abs(at.getScaleY()-1.0) < THRESH &&
Math.abs(at.getShearX()) < THRESH &&
Math.abs(at.getShearY()) < THRESH );
}
/**
* Get an identity transform (creating it if necessary)
*/
private AffineTransform getIdentity() {
if ( m_identity == null )
m_identity = new AffineTransform();
return m_identity;
}
/**
* Get a clip instance (creating it if necessary)
*/
private Clip getClip() {
if ( m_clip == null )
m_clip = new Clip();
return m_clip;
}
/**
* Does nothing.
* @see prefuse.util.display.PaintListener#postPaint(prefuse.Display, java.awt.Graphics2D)
*/
public void postPaint(Display d, Graphics2D g) {
// do nothing
}
} // end of class BackgroundPainter