//$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; } } }