/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program 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. * * Copyright (c) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved. */ package org.pentaho.reporting.engine.classic.core; import org.pentaho.reporting.engine.classic.core.util.PageFormatFactory; import org.pentaho.reporting.libraries.serializer.SerializerHelper; import java.awt.geom.Rectangle2D; import java.awt.print.PageFormat; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Iterator; /** * A page definition, that consists of one or many pages. The pages are allowed to overlapp or to leave areas of the * page uncovered. * * @author Thomas Morgner * @see PageDefinition */ public class CustomPageDefinition implements PageDefinition { /** * The page bounds, the imageable area on the global virtual page. */ private transient ArrayList pageBoundsList; /** * The page format list. */ private transient ArrayList pageFormatList; /** * The total width of the page. */ private float width; /** * The total height of the page. */ private float height; /** * Creates a new (initialy empty and therefore invalid) page definition. */ public CustomPageDefinition() { pageBoundsList = new ArrayList(); pageFormatList = new ArrayList(); } /** * Adds a new page format to the page definition. * * @param format * the page format * @param x * the x-position to where the imageable-x of the pageformat is mapped. * @param y * the y-position to where the imageable-y of the pageformat is mapped. */ public void addPageFormat( final PageFormat format, final float x, final float y ) { if ( format == null ) { throw new NullPointerException( "The given pageformat must not be null." ); } width = Math.max( width, (float) ( format.getImageableWidth() + x ) ); height = Math.max( height, (float) ( format.getImageableHeight() + y ) ); final Rectangle2D bounds = new Rectangle2D.Double( x, y, format.getImageableWidth(), format.getImageableHeight() ); pageBoundsList.add( bounds ); pageFormatList.add( format.clone() ); } /** * Returns the number of physical pages in the logical page definition. * * @return the number of physical pages. */ public int getPageCount() { return pageBoundsList.size(); } /** * Returns the page format for the given page number. The page format contains local coordinates - that means that the * point (0,0) denotes the upper left corner of this returned page format and not global coordinates. * * @param pos * the position of the pageformat within the page * @return the given pageformat. */ public PageFormat getPageFormat( final int pos ) { final PageFormat fmt = (PageFormat) pageFormatList.get( pos ); return (PageFormat) fmt.clone(); } /** * Describes the internal position of the given page within the logical page. The logical page does not include any * page margins, the printable area for a page starts at (0,0). * * @param index * the index of the page. * @return the position of the page (within the global page). */ public Rectangle2D getPagePosition( final int index ) { final Rectangle2D rec = (Rectangle2D) pageBoundsList.get( index ); return rec.getBounds2D(); } /** * Returns all page positions as array. * * @return the collected page positions * @see PageDefinition#getPagePosition(int) */ public Rectangle2D[] getPagePositions() { final Rectangle2D[] rects = new Rectangle2D[pageBoundsList.size()]; for ( int i = 0; i < pageBoundsList.size(); i++ ) { final Rectangle2D rec = (Rectangle2D) pageBoundsList.get( i ); rects[i] = rec.getBounds2D(); } return rects; } /** * Returns the total width of the page definition. * * @return the total width of the page definition. */ public float getWidth() { return width; } /** * Returns the total height of the page definition. * * @return the total height of the page definition. */ public float getHeight() { return height; } /** * Clones the given page definition object. * * @return a clone of this page definition. * @throws CloneNotSupportedException * if an error occured. */ public Object clone() throws CloneNotSupportedException { final CustomPageDefinition def = (CustomPageDefinition) super.clone(); def.pageBoundsList = (ArrayList) pageBoundsList.clone(); def.pageFormatList = (ArrayList) pageFormatList.clone(); return def; } /** * Deserizalize the report and restore the pageformat. * * @param out * the objectoutput stream * @throws java.io.IOException * if errors occur */ private void writeObject( final ObjectOutputStream out ) throws IOException { out.defaultWriteObject(); final SerializerHelper instance = SerializerHelper.getInstance(); final Iterator pageBoundsIterator = pageBoundsList.iterator(); while ( pageBoundsIterator.hasNext() ) { instance.writeObject( pageBoundsIterator.next(), out ); } instance.writeObject( null, out ); final Iterator pageFormatIterator = pageFormatList.iterator(); while ( pageFormatIterator.hasNext() ) { instance.writeObject( pageFormatIterator.next(), out ); } instance.writeObject( null, out ); } /** * Resolve the pageformat, as PageFormat is not serializable. * * @param in * the input stream. * @throws java.io.IOException * if there is an IO problem. * @throws ClassNotFoundException * if there is a class problem. */ private void readObject( final ObjectInputStream in ) throws IOException, ClassNotFoundException { in.defaultReadObject(); final SerializerHelper instance = SerializerHelper.getInstance(); pageBoundsList = new ArrayList(); pageFormatList = new ArrayList(); Object o = instance.readObject( in ); while ( o != null ) { final Rectangle2D rect = (Rectangle2D) o; pageBoundsList.add( rect ); o = instance.readObject( in ); } o = instance.readObject( in ); while ( o != null ) { final PageFormat format = (PageFormat) o; pageFormatList.add( format ); o = instance.readObject( in ); } } /** * Checks whether the given object is equal to this one. * * @param obj * the other object. * @return true, if the other object is equal, false otherwise. */ public boolean equals( final Object obj ) { if ( this == obj ) { return true; } if ( !( obj instanceof CustomPageDefinition ) ) { return false; } final CustomPageDefinition customPageDefinition = (CustomPageDefinition) obj; if ( height != customPageDefinition.height ) { return false; } if ( width != customPageDefinition.width ) { return false; } if ( !pageBoundsList.equals( customPageDefinition.pageBoundsList ) ) { return false; } if ( pageFormatList.size() != customPageDefinition.pageFormatList.size() ) { return false; } for ( int i = 0; i < pageFormatList.size(); i++ ) { final PageFormat pf = (PageFormat) pageFormatList.get( i ); final PageFormat cpf = (PageFormat) customPageDefinition.pageFormatList.get( i ); if ( PageFormatFactory.isEqual( pf, cpf ) == false ) { return false; } } return true; } /** * Computes the hashcode of this page definition. * * @return the hashcode. */ public int hashCode() { int result = pageBoundsList.hashCode(); result = 29 * result + pageFormatList.hashCode(); result = 29 * result + width == 0.0f ? 0 : Float.floatToIntBits( width ); result = 29 * result + height == 0.0f ? 0 : Float.floatToIntBits( height ); return result; } }