/* * 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.util; import java.awt.Insets; import java.awt.print.PageFormat; import java.awt.print.Paper; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * The PageFormatFactory is used to create PageFormats on a higher level. The Factory contains templates for all * PageSizes defined by Adobe: * <p/> * <a href="http://partners.adobe.com/asn/developer/pdfs/tn/5003.PPD_Spec_v4.3.pdf" >Postscript Specifications</a> * <p/> * Usage for creating an printjob on A4 paper with 2.5 cm border: * * <pre> * Paper paper = PageFormatFactory.createPaper (PageSize.A4); * PageFormatFactory.setBordersMm (paper, 25, 25, 25, 25); * PageFormat format = PageFormatFactory.createPageFormat (paper, PageFormat.PORTRAIT); * </code> * * Defining a pageformat can be an ugly task and full of dependencies. The call to * PageFormatFactory.setBorders(...) will setup the paper's border and always assumes * that the paper is laid out in Portrait. * * Changing the PageFormat's orientation does not change the PageFormat's paper object, * but it changes the way, how the paper object is interpreted. * * @author Thomas Morgner */ public final class PageFormatFactory { private static final Log logger = LogFactory.getLog( PageFormatFactory.class ); /** * A single instance of the factory. */ private static PageFormatFactory singleton; private static final String[] EMPTY_PAGEFORMATS = new String[0]; /** * Default constructor. */ private PageFormatFactory() { } /** * Returns a single instance of the factory. * * @return an instance of a PageFormatFactory. */ public static synchronized PageFormatFactory getInstance() { if ( singleton == null ) { singleton = new PageFormatFactory(); } return singleton; } /** * Creates a paper by using the paper size in points found in the int-array. The array must have a length of 2 and the * first value of this array has to contain the width and the second the height parameter. The created Paper has no * ImagableArea defined. * * @param papersize * the definition of the papersize in a 2-element int-array * @return the created paper */ public Paper createPaper( final int[] papersize ) { if ( papersize.length != 2 ) { throw new IllegalArgumentException( "Paper must have a width and a height" ); } return createPaper( (double) papersize[0], (double) papersize[1] ); } /** * Creates a paper by using the paper size in points found in the int-array. The array must have a length of 2 and the * first value of this array has to contain the width and the second the height parameter. The created Paper has no * ImagableArea defined. * * @param papersize * the definition of the papersize in a 2-element int-array * @return the created paper */ public Paper createPaper( final PageSize papersize ) { return createPaper( papersize.getWidth(), papersize.getHeight() ); } /** * Creates a paper by using the paper size in points. The created Paper has no ImagableArea defined. * * @param width * the width of the paper in points * @param height * the height of the paper in points * @return the created paper */ public Paper createPaper( final double width, final double height ) { final Paper p = new Paper(); p.setSize( width, height ); setBorders( p, 0, 0, 0, 0 ); return p; } /** * Defines the imageable area of the given paper by adjusting the border around the imagable area. The bordersizes are * given in points. * * @param paper * the paper that should be modified * @param top * the bordersize of the top-border * @param left * the border in points in the left * @param bottom * the border in points in the bottom * @param right * the border in points in the right */ public void setBorders( final Paper paper, final double top, final double left, final double bottom, final double right ) { final double w = paper.getWidth() - ( right + left ); final double h = paper.getHeight() - ( bottom + top ); paper.setImageableArea( left, top, w, h ); } /** * Defines the imageable area of the given paper by adjusting the border around the imagable area. The bordersizes are * given in inches. * * @param paper * the paper that should be modified * @param top * the bordersize of the top-border * @param left * the border in points in the left * @param bottom * the border in points in the bottom * @param right * the border in points in the right */ public void setBordersInch( final Paper paper, final double top, final double left, final double bottom, final double right ) { setBorders( paper, convertInchToPoints( top ), convertInchToPoints( left ), convertInchToPoints( bottom ), convertInchToPoints( right ) ); } /** * Defines the imageable area of the given paper by adjusting the border around the imagable area. The bordersizes are * given in millimeters. * * @param paper * the paper that should be modified * @param top * the bordersize of the top-border * @param left * the border in points in the left * @param bottom * the border in points in the bottom * @param right * the border in points in the right */ public void setBordersMm( final Paper paper, final double top, final double left, final double bottom, final double right ) { setBorders( paper, convertMmToPoints( top ), convertMmToPoints( left ), convertMmToPoints( bottom ), convertMmToPoints( right ) ); } /** * Converts the given inch value to a valid point-value. * * @param inches * the size in inch * @return the size in points */ public double convertInchToPoints( final double inches ) { return inches * 72.0f; } /** * Converts the given millimeter value to a valid point-value. * * @param mm * the size in inch * @return the size in points */ public double convertMmToPoints( final double mm ) { return mm * ( 72.0d / 254.0d ) * 10; } /** * Creates a new pageformat using the given paper and the given orientation. * * @param paper * the paper to use in the new pageformat * @param orientation * one of PageFormat.PORTRAIT, PageFormat.LANDSCAPE or PageFormat.REVERSE_LANDSCAPE * @return the created Pageformat * @throws NullPointerException * if the paper given was null */ public PageFormat createPageFormat( final Paper paper, final int orientation ) { if ( paper == null ) { throw new NullPointerException( "Paper given must not be null" ); } final PageFormat pf = new PageFormat(); pf.setPaper( paper ); pf.setOrientation( orientation ); return pf; } /** * Creates a paper by looking up the given Uppercase name in this classes defined constants. The value if looked up by * introspection, if the value is not defined in this class, null is returned. * * @param name * the name of the constant defining the papersize * @return the defined paper or null, if the name was invalid. */ public Paper createPaper( final String name ) { try { final Field f = PageSize.class.getDeclaredField( name ); final Object o = f.get( null ); if ( o instanceof PageSize == false ) { // Log.debug ("Is no valid pageformat definition"); return null; } final PageSize pageformat = (PageSize) o; return createPaper( pageformat ); } catch ( NoSuchFieldException nfe ) { // Log.debug ("There is no pageformat " + name + " defined."); return null; } catch ( IllegalAccessException aie ) { // Log.debug ("There is no pageformat " + name + " accessible."); return null; } } public static PageFormat create( final PageSize papersize, final int orientation, final Insets margins ) { final PageFormatFactory instance = PageFormatFactory.getInstance(); final PageFormat pageFormat = instance.createPageFormat( instance.createPaper( papersize ), orientation ); instance.setPageMargins( pageFormat, margins ); return pageFormat; } /** * Logs the page format. * * @param pf * the page format. */ public static void logPageFormat( final PageFormat pf ) { logger.debug( printPageFormat( pf ) ); } public static String printPageFormat( final PageFormat pf ) { StringBuffer b = new StringBuffer(); b.append( "PageFormat={width=" ); b.append( pf.getWidth() ); b.append( ", height=" ); b.append( pf.getHeight() ); b.append( ", imageableX=" ); b.append( pf.getImageableX() ); b.append( ", imageableY=" ); b.append( pf.getImageableY() ); b.append( ", imageableWidth=" ); b.append( pf.getImageableWidth() ); b.append( ", imageableHeight=" ); b.append( pf.getImageableHeight() ); b.append( ", orientation=" ).append( pf.getOrientation() ); b.append( ", paper=" ); b.append( printPaper( pf.getPaper() ) ); b.append( "}" ); return b.toString(); } private static String printPaper( final Paper paper ) { StringBuffer b = new StringBuffer(); b.append( "Paper={width=" ); b.append( paper.getWidth() ); b.append( ", height=" ); b.append( paper.getHeight() ); b.append( ", imageableX=" ); b.append( paper.getImageableX() ); b.append( ", imageableY=" ); b.append( paper.getImageableY() ); b.append( ", imageableWidth=" ); b.append( paper.getImageableWidth() ); b.append( ", imageableHeight=" ); b.append( paper.getImageableHeight() ); b.append( "}" ); return b.toString(); } /** * Logs the paper size. * * @param pf * the paper size. */ public static void logPaper( final Paper pf ) { logger.debug( printPaper( pf ) ); } /** * Tests, whether the given two page format objects are equal. * * @param pf1 * the first page format that should be compared. * @param pf2 * the second page format that should be compared. * @return true, if both page formats are equal, false otherwise. */ public static boolean isEqual( final PageFormat pf1, final PageFormat pf2 ) { if ( pf1 == pf2 ) { return true; } if ( pf1 == null || pf2 == null ) { return false; } if ( pf1.getOrientation() != pf2.getOrientation() ) { return false; } final Paper p1 = pf1.getPaper(); final Paper p2 = pf2.getPaper(); if ( p1.getWidth() != p2.getWidth() ) { return false; } if ( p1.getHeight() != p2.getHeight() ) { return false; } if ( p1.getImageableX() != p2.getImageableX() ) { return false; } if ( p1.getImageableY() != p2.getImageableY() ) { return false; } if ( p1.getImageableWidth() != p2.getImageableWidth() ) { return false; } if ( p1.getImageableHeight() != p2.getImageableHeight() ) { return false; } return true; } /** * Returns the left border of the given paper. * * @param p * the paper that defines the borders. * @return the left border. */ public double getLeftBorder( final Paper p ) { return p.getImageableX(); } /** * Returns the right border of the given paper. * * @param p * the paper that defines the borders. * @return the right border. */ public double getRightBorder( final Paper p ) { return p.getWidth() - ( p.getImageableX() + p.getImageableWidth() ); } /** * Returns the top border of the given paper. * * @param p * the paper that defines the borders. * @return the top border. */ public double getTopBorder( final Paper p ) { return p.getImageableY(); } /** * Returns the bottom border of the given paper. * * @param p * the paper that defines the borders. * @return the bottom border. */ public double getBottomBorder( final Paper p ) { return p.getHeight() - ( p.getImageableY() + p.getImageableHeight() ); } public Insets getPageMargins( final PageFormat format ) { final int marginLeft = (int) format.getImageableX(); final int marginRight = (int) ( format.getWidth() - format.getImageableWidth() - format.getImageableX() ); final int marginTop = (int) ( format.getImageableY() ); final int marginBottom = (int) ( format.getHeight() - format.getImageableHeight() - format.getImageableY() ); return new Insets( marginTop, marginLeft, marginBottom, marginRight ); } public String getPageFormatName( final double width, final double height ) { try { final Field[] fields = PageSize.class.getFields(); for ( int i = 0; i < fields.length; i++ ) { final Field f = fields[i]; if ( Modifier.isPublic( f.getModifiers() ) && Modifier.isStatic( f.getModifiers() ) ) { final Object o = f.get( PageFormatFactory.getInstance() ); if ( o instanceof PageSize ) { final PageSize pageDef = (PageSize) o; if ( pageDef.getWidth() == width && pageDef.getHeight() == height ) { return f.getName(); } } } } } catch ( Exception e ) { PageFormatFactory.logger.warn( "Unable to lookup the page name", e ); } return null; } public String[] getPageFormats() { try { final ArrayList a = new ArrayList(); final Field[] fields = PageSize.class.getFields(); for ( int i = 0; i < fields.length; i++ ) { final Field f = fields[i]; if ( Modifier.isPublic( f.getModifiers() ) && Modifier.isStatic( f.getModifiers() ) ) { final Object o = f.get( PageFormatFactory.getInstance() ); if ( o instanceof PageSize ) { a.add( f.getName() ); } } } return (String[]) a.toArray( new String[a.size()] ); } catch ( Exception e ) { PageFormatFactory.logger.warn( "Unable to lookup the page name", e ); } return PageFormatFactory.EMPTY_PAGEFORMATS; } public void setPageMargins( final PageFormat pageFormat, final Insets pageMargins ) { final Paper paper = pageFormat.getPaper(); setBorders( paper, pageMargins.top, pageMargins.left, pageMargins.bottom, pageMargins.right ); pageFormat.setPaper( paper ); } }