Package org.jpedal.utils

Source Code of org.jpedal.utils.PdfPageFormat

/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info:  http://www.jpedal.org
* (C) Copyright 2011, IDRsolutions.
*
*   This file is part of JPedal
*
     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


  *
  * ---------------
  * PdfPageFormat.java
  * ---------------
*/

package org.jpedal.utils;

/**
* Factory methods for PdfPageFormats. 
*
* <p>Encapsulates all PageFormat creation for Acrobat-like results.  Queries the printer
* in order to find the most suitable PageFormat.</p>
*/

import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.Size2DSyntax;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;

import org.jpedal.PdfDecoder;
import org.jpedal.objects.PdfPageData;

public class PdfPageFormat
{
    private static Set<PageFormat>  availablePaper;
 
    public PdfPageFormat()
    {
        throw new AssertionError("PdfPageFormat cannot be instanced.  Use factory methods.");
    }
   
    /**
     * The purpose of this method is to create a <tt>PageFormat</tt> object that covers the correct printable area
     * of the given device.  Use this method to create paper in order to get Acrobat like results.
     *
     * The size of the <tt>PageFormat</tt> is based on the given <tt>MediaSize</tt>
     * See http://download.oracle.com/javase/1.4.2/docs/api/javax/print/attribute/standard/MediaSize.html
     *
     * @param mediaSize       The desired paper size (ie <tt>MediaSize.ISO.A4</tt>)
     * @param printingService The device to be printed to
     * @return A formatted <tt>PageFormat</tt> for use with printing PDFs.  May return null if there is no available size information.
     */
    public static final PageFormat createPdfPageFormat(MediaSizeName mediaSizeName, PrintService printingDevice)
    {
      boolean testFlag = false;
      if(printingDevice == null) {
        printingDevice = PrintServiceLookup.lookupDefaultPrintService();
      }
     
      if(testFlag && printingDevice==null)
        System.out.println("Print Device is null");
     
        PageFormat pdfPageFormat = new PageFormat();
       
        MediaSize mediaSize = MediaSize.getMediaSizeForName(mediaSizeName);
       
        if(mediaSize == null) {
          mediaSize = MediaSize.getMediaSizeForName(PdfPageFormat.getDefaultMediaSizeName(printingDevice));
        }
       
        if(testFlag && mediaSize==null)
        System.out.println("Media Size is null");
       
        float xSize = mediaSize.getX(Size2DSyntax.INCH) * 72;
        float ySize = mediaSize.getY(Size2DSyntax.INCH) * 72;
       
        Paper pdfPaper = new Paper();
        pdfPaper.setSize(xSize, ySize);
               
        MediaPrintableArea area = (MediaPrintableArea) printingDevice.getDefaultAttributeValue(MediaPrintableArea.class);
       
        if(testFlag && area==null)
        System.out.println("Area is null");
       
        float[] imagable;
       
        //On my cheap tesco printer this return null, so accounted for that case.
//        if(area != null) {
//            imagable = area.getPrintableArea(Size2DSyntax.INCH);
//        }
//        else {
          PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
          attributes.add(mediaSizeName);
          MediaPrintableArea areas[] = (MediaPrintableArea[]) printingDevice.getSupportedAttributeValues(MediaPrintableArea.class, null, attributes);
         
          if(testFlag && areas==null)
          System.out.println("Printable Area array is null");
         
          imagable = areas[0].getPrintableArea(Size2DSyntax.INCH);
//        }
       
        for(int i = 0; i < 4; i++) {
          imagable[i] *= 72;
        }

        if(imagable[2] + imagable[0] > xSize) {
          imagable[2] = xSize - imagable[0];
        }
       
        if(imagable[3] + imagable[1] > ySize) {
          imagable[3] = ySize - imagable[1];
        }
       
        pdfPaper.setImageableArea(imagable[0], imagable[1], imagable[2], imagable[3]);
       
        pdfPageFormat.setPaper(pdfPaper);
       
        return pdfPageFormat;
    }

    /**
     * Find the default size for the given printer.  If the printer hasnt got a default it will figure
     * it out based on the locale.
     *
     * @param printingDevice The <tt>PrintService</tt> to inspect
     * @return The default page size suitable for printing PDF files too.
     */
    public static PageFormat getDefaultPage(PrintService printingDevice)
    {
      if(printingDevice == null) {
        printingDevice = PrintServiceLookup.lookupDefaultPrintService();
      }
     
      return createPdfPageFormat(getDefaultMediaSizeName(printingDevice), printingDevice);
    }
   
    /**
     * Find an the default MediaSizeName from the <tt>PrintService</tt>.  If there isnt a decent default one
     * available get one based on locale.
     *
     * @param printingDevice
     * @return A valid, default <tt>MediaSizeName</tt>
     */
    public static MediaSizeName getDefaultMediaSizeName(PrintService printingDevice)
    {
      MediaSizeName size = (MediaSizeName) printingDevice.getDefaultAttributeValue(MediaSizeName.class);
     
      if(size == null || MediaSize.getMediaSizeForName(size) == null) {
        Locale locale = Locale.getDefault();
       
        if(locale.equals(Locale.UK)) {
            size = MediaSizeName.ISO_A4;
        }
        else if(locale.equals(Locale.US)) {
          size = MediaSizeName.NA_LETTER;
        }
        else {
            size = MediaSizeName.ISO_A4;
        }
      }
     
      return size;
    }
   
    /**
     * Used to create a set of available <tt>PageFormat</tt> based on what is available
     * on the given device.
     *
     * @param printingDevice The <tt>PrintService</tt> to examine
     */
    public static void findPrinterPapers(PrintService printingDevice)
    {
        availablePaper = new HashSet<PageFormat>();
     
      if(printingDevice == null) {
        printingDevice = PrintServiceLookup.lookupDefaultPrintService();
      }

      Media[] res = (Media[]) printingDevice.getSupportedAttributeValues(javax.print.attribute.standard.Media.class, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
      for(Media m : res) {
        if(m instanceof javax.print.attribute.standard.MediaSizeName ) {
            MediaSize size = MediaSize.getMediaSizeForName((MediaSizeName) m);
            if(size != null) { //The sun.print.CustomMediaSizeName returns null for some reason?
                availablePaper.add(createPdfPageFormat((MediaSizeName) m, printingDevice));
            }
        }
      }
    }
   
    /**
     * Find the best fitting <tt>PageFormat</tt< for a given page.
     *
     * @param p        The page to examine by PDF page number.
     * @param pdfDecoder    The <tt>PdfDecoder</tt> encapsulating the PdfPage
     * @return  The nearest available <tt>PageFormat</tt> for this <tt>PrintService</tt>
     */
    public static PageFormat getPageFormat(int p, PdfDecoder pdfDecoder)
    {
        PdfPageData pageData = pdfDecoder.getPdfPageData();
      
        float cropW = pageData.getCropBoxWidth(p);
        float cropH = pageData.getCropBoxHeight(p);
              
        PageFormat result = PdfPageFormat.getAppropriatePageFormat(cropW, cropH);
       
        return result;
    }

    /**
     * Examine the Set of <tt>PageFormat</tt>s to find the best fit.
     *
     * @param cropW The desired paper width
     * @param cropH The desired paper height
     * @return
     */
    private static PageFormat getAppropriatePageFormat(float cropW, float cropH)
    {
      if(availablePaper == null) {
        findPrinterPapers(null);
      }
     
      //Start off with null
        PageFormat result = null;
       
        for(PageFormat pf : availablePaper) {
          result = getClosestPageFormat(result, pf, cropW, cropH);
        }
       
        if(result == null) { //return the default PageFormat if null.  Shouldnt really occur.
          result = PdfPageFormat.getDefaultPage(null);
        }
       
        return result;
    }
   
    /**
     * Compare two <tt>PageFormat</tt> objects to find which is a better fit.
     *
     * @param original    The current best fit <tt>PageFormat</tt> may be null.
     * @param newFormat     The <tt>PageFormat</tt> to compare against
     * @param cropW         The width of the PDF page
     * @param cropH         The height of the PDF page
     * @return The best fitting <tt>PageFormat</tt> either the original or a clone of the new best fitting one.
     */
    private static PageFormat getClosestPageFormat(PageFormat original, PageFormat newFormat, float cropW, float cropH)
    {
      double newLongSide = newFormat.getHeight() > newFormat.getWidth() ? newFormat.getHeight() : newFormat.getWidth();
      double newShortSide = newFormat.getHeight() < newFormat.getWidth() ? newFormat.getHeight() : newFormat.getWidth();
          
      double cropLongSide = cropH > cropW ? cropH : cropW;
      double cropShortSide = cropH < cropW ? cropH : cropW;
        
      if(newShortSide >= cropShortSide && newLongSide >= cropLongSide) {

          if(original == null) { //No others so far so just have this one to start off with
              PageFormat result = (PageFormat) newFormat.clone();
              return result;
          }

          double origLongSide = original.getHeight() > original.getWidth() ? original.getHeight() : original.getWidth();
          double origShortSide = original.getHeight() < original.getWidth() ? original.getHeight() : original.getWidth();

          if((origLongSide + origShortSide) > (newShortSide + newLongSide)) {
            PageFormat result = (PageFormat) newFormat.clone();
            return result;
          }
      }
     
      return original;
    }
   
}
TOP

Related Classes of org.jpedal.utils.PdfPageFormat

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.