// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/layer/policy/BufferedImageRenderPolicy.java,v $
// $RCSfile: BufferedImageRenderPolicy.java,v $
// $Revision: 1.8 $
// $Date: 2005/10/26 15:47:42 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.layer.policy;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import com.bbn.openmap.layer.OMGraphicHandlerLayer;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.proj.Proj;
import com.bbn.openmap.proj.Projection;
/**
* The PanningImageRenderPolicy renders all OMGraphics into a buffering image,
* and responds to projection changes by immediately rendering a translated
* version of the image at a new projection location before calling prepare() on
* the layer to get the OMGraphics for the new projection and untranslated
* image. When the new image is ready, it will be painted. Using this policy on
* background layers eliminates the flashing effect seen when panning or zooming
* a map when a faster-responding layer is on top.
* <P>
* NOTE: The need for this RenderPolicy is superseded by using the
* PanningMouseMode on the MapBean instead.
*
* <P>
* You can set this object on an OMGraphicHandlerLayer through the API, or set
* it in the properties:
*
* <pre>
* layer.renderPolicy=rp
* layer.rp.class=com.bbn.openmap.layer.policy.PanningImageRenderPolicy
* </pre>
*/
public class PanningImageRenderPolicy extends RenderingHintsRenderPolicy {
protected BufferedImage buffer = null;
protected Point2D offset = new Point2D.Double();
protected Point2D oldUL;
protected float oldScale;
protected Class<? extends Proj> oldProjType = null;
/**
* Set the layer at some point before use.
*/
public PanningImageRenderPolicy() {
super();
}
/**
* Don't pass in a null layer.
*/
public PanningImageRenderPolicy(OMGraphicHandlerLayer layer) {
super(layer);
}
public OMGraphicList prepare() {
if (layer != null) {
// setBuffer(null);
Projection proj = layer.getProjection();
if (layer.isProjectionOK(proj)) {
// set the offsets depending on how much the image moves
Point2D ul = proj.getUpperLeft();
if (oldUL != null && !oldUL.equals(ul) && oldScale == proj.getScale()
&& proj.getClass().equals(oldProjType)) {
Point2D currentPoint = proj.forward(ul);
Point2D oldPoint = proj.forward(oldUL);
offset.setLocation(oldPoint.getX() - currentPoint.getX(), oldPoint.getY()
- currentPoint.getY());
layer.repaint();
}
oldUL = ul;
oldProjType = ((Proj) proj).getClass();
oldScale = proj.getScale();
OMGraphicList list = layer.prepare();
setBuffer(createAndPaintImageBuffer(list));
return list;
} else {
logger.warning("NULL projection, can't do anything.");
}
} else {
logger.warning("NULL layer, can't do anything.");
}
return null;
}
public void paint(Graphics g) {
if (layer == null) {
logger.warning("NULL layer, skipping...");
return;
}
OMGraphicList list = layer.getList();
Projection proj = layer.getProjection();
Graphics2D g2 = (Graphics2D) g;
if (layer.isProjectionOK(proj)) {
if (getBuffer() == null) {
// Not sure how we get here, but it's here just in case so that
// the list might get painted if it exists and the buffered
// image wasn't created.
logger.fine("creating image buffer in paint");
if (list != null) {
setBuffer(createAndPaintImageBuffer(list));
}
}
BufferedImage bufferedImage = getBuffer();
setCompositeOnGraphics(g2);
if (bufferedImage != null) {
AffineTransform af = new AffineTransform();
af.translate(offset.getX(), offset.getY());
g2.drawRenderedImage((BufferedImage) bufferedImage, af);
if (logger.isLoggable(Level.FINE)) {
logger.fine("RenderingPolicy:" + layer.getName() + ": rendering buffer");
}
} else if (list != null) {
super.setRenderingHints(g);
list.render(g);
if (logger.isLoggable(Level.FINE)) {
logger.fine(layer.getName() + ": rendering list directly");
}
}
} else if (logger.isLoggable(Level.FINE)) {
logger.fine(layer.getName() + ".paint(): "
+ (list == null ? "NULL list, skipping..." : " skipping due to projection."));
}
}
/** Get the BufferedImage for the layer. */
protected BufferedImage getBuffer() {
return buffer;
}
/** Set the BufferedImage for the layer. */
protected void setBuffer(BufferedImage bi) {
offset.setLocation(0, 0);
buffer = bi;
}
protected BufferedImage createAndPaintImageBuffer(OMGraphicList list) {
BufferedImage bufferedImage = null;
if (list != null && layer != null) {
int w = layer.getProjection().getWidth();
int h = layer.getProjection().getHeight();
bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
super.setRenderingHints(g2d);
list.render(g2d);
if (logger.isLoggable(Level.FINE)) {
logger.fine(layer.getName() + ": rendering list into buffer");
}
}
return bufferedImage;
}
}