//$HeadURL$
/*----------------------------------------------------------------------------
This file is part of deegree, http://deegree.org/
Copyright (C) 2001-2009 by:
- Department of Geography, University of Bonn -
and
- lat/lon GmbH -
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.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact information:
lat/lon GmbH
Aennchenstr. 19, 53177 Bonn
Germany
http://lat-lon.de/
Department of Geography, University of Bonn
Prof. Dr. Klaus Greve
Postfach 1147, 53001 Bonn
Germany
http://www.geographie.uni-bonn.de/deegree/
e-mail: info@deegree.org
----------------------------------------------------------------------------*/
package org.deegree.igeo.commands;
import static org.deegree.graphics.MapFactory.createMapView;
import java.awt.Graphics2D;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.MapUtils;
import org.deegree.graphics.MapView;
import org.deegree.graphics.Theme;
import org.deegree.igeo.ApplicationContainer;
import org.deegree.igeo.mapmodel.Layer;
import org.deegree.igeo.mapmodel.LayerGroup;
import org.deegree.igeo.mapmodel.MapModel;
import org.deegree.igeo.mapmodel.MapModelVisitor;
import org.deegree.igeo.views.LayerPane;
import org.deegree.kernel.AbstractCommand;
import org.deegree.kernel.Command;
import org.deegree.model.spatialschema.Envelope;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;
/**
* {@link Command} implementation for printing a map as a vector PDF document
*
* @author <a href="mailto:name@deegree.org">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version $Revision$, $Date$
*/
public class VectorPrintCommand extends AbstractCommand {
public static final QualifiedName commandName = new QualifiedName( "Print Map as Vector PDF" );
private static final ILogger LOG = LoggerFactory.getLogger( UnselectFeaturesCommand.class );
private PrintDescriptionBean printDefinition;
private ApplicationContainer<?> appContainer;
private Document document;
/**
*
* @param appContainer
*/
public void setApplicationContainer( ApplicationContainer<?> appContainer ) {
this.appContainer = appContainer;
}
/**
*
* @param printDefinition
*/
public void setPrintDefinition( PrintDescriptionBean printDefinition ) {
this.printDefinition = printDefinition;
}
/*
* (non-Javadoc)
*
* @see org.deegree.kernel.Command#execute()
*/
@Override
public void execute()
throws Exception {
Graphics2D g = initDocument();
java.awt.Rectangle rect = getCanvasSize();
g.setClip( rect.x, rect.y, rect.width, rect.height );
MapModel mm = appContainer.getMapModel( null );
Envelope originalExtent = mm.getEnvelope();
Envelope extent = originalExtent;
extent = MapUtils.ensureAspectRatio( extent, rect.width, rect.height );
if ( printDefinition.getScale() > 0 ) {
// use scale selected by used
double currentScale = MapUtils.calcScale( rect.width, rect.height, extent, extent.getCoordinateSystem(),
0.0254 / printDefinition.getDpi() );
extent = MapUtils.scaleEnvelope( extent, currentScale, printDefinition.getScale() );
}
double dx = printDefinition.getMapLeft() - extent.getMin().getX();
double dy = printDefinition.getMapBottom() - extent.getMin().getY();
extent.translate( dx, dy );
// change map extent for printing
mm.setEnvelope( extent );
int w = mm.getTargetDevice().getPixelWidth();
int h = mm.getTargetDevice().getPixelHeight();
mm.getTargetDevice().setPixelWidth( rect.width );
mm.getTargetDevice().setPixelHeight( rect.height );
Theme[] themes = getThemes( extent );
MapView mv = createMapView( "iGeoDesktop", extent, mm.getCoordinateSystem(), themes,
0.0254 / printDefinition.getDpi() );
for ( Theme t : mv.getAllThemes() ) {
t.setStyles( t.getStyles() );
}
mv.paint( g );
kill( g );
// reset map extent
mm.getTargetDevice().setPixelWidth( w );
mm.getTargetDevice().setPixelHeight( h );
mm.setEnvelope( originalExtent );
}
/**
*
* @param extent
* @return a {@link Theme} for each layers visible in map to be printed
* @throws Exception
*/
private Theme[] getThemes( final Envelope extent )
throws Exception {
final List<Theme> themes = new ArrayList<Theme>();
final MapModel mm = appContainer.getMapModel( null );
mm.walkLayerTree( new MapModelVisitor() {
@Override
public void visit( Layer layer )
throws Exception {
double mis = layer.getMinScaleDenominator();
double mxs = layer.getMaxScaleDenominator();
if ( layer.isVisible() && mis <= mm.getScaleDenominator() && mxs >= mm.getScaleDenominator()
&& !layer.getTitle().equals( "deegree:PrintBorder" ) ) {
List<Theme> layerThemes = LayerPane.createThemes( layer.getCurrentStyle(), layer.getDataAccess(),
extent.getCoordinateSystem() );
themes.add( 0, layerThemes.get( 0 ) );
}
}
@Override
public void visit( LayerGroup layerGroup )
throws Exception {
// not using grouping nodes
}
} );
return themes.toArray( new Theme[themes.size()] );
}
private void kill( Graphics2D g ) {
g.dispose();
document.close();
}
/**
* initializes the {@link Document} required for printing using iText
*
* @return graphic context ({@link Graphics2D}) of the initialized document
* @throws FileNotFoundException
* @throws DocumentException
*/
private Graphics2D initDocument()
throws FileNotFoundException, DocumentException {
String pageFormat = printDefinition.getPageFormat();
Rectangle pageSize;
if ( pageFormat != null )
pageSize = PageSize.getRectangle( pageFormat );
else
pageSize = new Rectangle( printDefinition.getPageWidth(), printDefinition.getPageHeight() );
LOG.logDebug( "page size", pageSize );
// create (pdf) document with selected pages size; set margin and PDF-version
document = new Document( pageSize );
document.setMargins( printDefinition.getAreaLeft(),
printDefinition.getAreaLeft() + printDefinition.getAreaWidth(),
printDefinition.getAreaTop(),
printDefinition.getAreaTop() + printDefinition.getAreaHeight() );
PdfWriter writer = PdfWriter.getInstance( document, new FileOutputStream( printDefinition.getTargetFile() ) );
writer.setPdfVersion( printDefinition.getPdfVersion() );
document.open();
PdfContentByte cb = writer.getDirectContent();
// create canvas
Graphics2D g = cb.createGraphics( convert( pageSize.getWidth() / 72 * 25.4 ),
convert( pageSize.getHeight() / 72 * 25.4 ) );
LOG.logDebug( "canvas size", convert( pageSize.getWidth() / 72 * 25.4 ) + " "
+ convert( pageSize.getHeight() / 72 * 25.4 ) );
// required for correct scaling of raster symbols
int i1 = convert( pageSize.getHeight() / 72 * 25.4 );
int i2 = convert_( pageSize.getHeight() / 72 * 25.4 );
g.translate( 0, i1 - i2 );
g.scale( 72d / printDefinition.getDpi(), 72d / printDefinition.getDpi() );
return g;
}
private int convert( double millimeter ) {
return (int) Math.round( millimeter * printDefinition.getDpi() / 25.4 );
}
private static int convert_( double millimeter ) {
return (int) Math.round( millimeter * 72 / 25.4 );
}
private java.awt.Rectangle getCanvasSize() {
int w = convert( printDefinition.getAreaWidth() );
int h = convert( printDefinition.getAreaHeight() );
int x = convert( printDefinition.getAreaLeft() );
int y = convert( printDefinition.getAreaTop() );
return new java.awt.Rectangle( x, y, w, h );
}
/*
* (non-Javadoc)
*
* @see org.deegree.kernel.Command#getName()
*/
@Override
public QualifiedName getName() {
return commandName;
}
/*
* (non-Javadoc)
*
* @see org.deegree.kernel.Command#getResult()
*/
@Override
public Object getResult() {
// TODO Auto-generated method stub
return null;
}
/**
*
* TODO add class documentation here
*
* @author <a href="mailto:name@deegree.org">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version $Revision$, $Date$
*/
public static class PrintDescriptionBean {
private int areaLeft;
private int areaTop;
private int areaWidth;
private int areaHeight;
private double mapLeft;
private double mapBottom;
private double scale;
private String pageFormat;
private float pageWidth = PageSize.A4.getWidth();
private float pageHeight = PageSize.A4.getHeight();
private char pdfVersion = PdfWriter.VERSION_1_4;
private String targetFile;
private int dpi;
/**
* @return the pdfVersion
*/
public char getPdfVersion() {
return pdfVersion;
}
/**
* @param pdfVersion
* the pdfVersion to set
*/
public void setPdfVersion( char pdfVersion ) {
this.pdfVersion = pdfVersion;
}
/**
* @return the targetFile
*/
public String getTargetFile() {
return targetFile;
}
/**
* @param targetFile
* the targetFile to set
*/
public void setTargetFile( String targetFile ) {
this.targetFile = targetFile;
}
/**
* @return the areaLeft
*/
public int getAreaLeft() {
return areaLeft;
}
/**
* @param areaLeft
* the areaLeft to set
*/
public void setAreaLeft( int areaLeft ) {
this.areaLeft = areaLeft;
}
/**
* @return the areaTop
*/
public int getAreaTop() {
return areaTop;
}
/**
* @param areaTop
* the areaTop to set
*/
public void setAreaTop( int areaTop ) {
this.areaTop = areaTop;
}
/**
* @return the areaWidth
*/
public int getAreaWidth() {
return areaWidth;
}
/**
* @param areaWidth
* the areaWidth to set
*/
public void setAreaWidth( int areaWidth ) {
this.areaWidth = areaWidth;
}
/**
* @return the areaHeight
*/
public int getAreaHeight() {
return areaHeight;
}
/**
* @param areaHeight
* the areaHeight to set
*/
public void setAreaHeight( int areaHeight ) {
this.areaHeight = areaHeight;
}
/**
* @return the mapLeft
*/
public double getMapLeft() {
return mapLeft;
}
/**
* @param mapLeft
* the mapLeft to set
*/
public void setMapLeft( double mapLeft ) {
this.mapLeft = mapLeft;
}
/**
* @return the mapBottom
*/
public double getMapBottom() {
return mapBottom;
}
/**
* @param mapBottom
* the mapBottom to set
*/
public void setMapBottom( double mapBottom ) {
this.mapBottom = mapBottom;
}
/**
* @return the scale
*/
public double getScale() {
return scale;
}
/**
* @param scale
* the scale to set
*/
public void setScale( double scale ) {
this.scale = scale;
}
/**
* @return the pageFormat
*/
public String getPageFormat() {
return pageFormat;
}
/**
* @param pageFormat
* the pageFormat to set
*/
public void setPageFormat( String pageFormat ) {
this.pageFormat = pageFormat;
}
/**
* @return the dpi
*/
public int getDpi() {
return dpi;
}
/**
* @param dpi
* the dpi to set
*/
public void setDpi( int dpi ) {
this.dpi = dpi;
}
/**
* @param pageWidth
* the individuell width of the page to print (use this and height instad of pageFormat)
*/
public void setPageWidth( float pageWidth ) {
this.pageWidth = pageWidth;
}
/**
*
* @return
*/
public float getPageWidth() {
return pageWidth;
}
/**
*
* @param pageHeight
* the individuell height of the page to print (use this and height instad of pageFormat)
*/
public void setPageHeight( float pageHeight ) {
this.pageHeight = pageHeight;
}
/**
*
* @return
*/
public float getPageHeight() {
return pageHeight;
}
}
}