All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jpedal.utils.PrintUtils Maven / Gradle / Ivy

There is a newer version: 20151002
Show newest version
/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/support/
 *
 * (C) Copyright 1997-2017 IDRsolutions and Contributors.
 *
 * This file is part of JPedal/JPDF2HTML5
 *
     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


 *
 * ---------------
 * PrintUtils.java
 * ---------------
 */

package org.jpedal.utils;

/*
 * Encapsulates the creation of a AffineTransform that mimics the effects
 * of the printing options available in Adobe Acrobat.
 *
 * 

The available options additional are auto rotate and centre, fit to page and shrink to page. * If page is larger than the page when asked to fit or smaller than the page when asked to shrink * it is unaffected apart from being centred. This is same effect found in Acrobat printing.

*

Currently implements Printable for testing purposes

* */ import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.awt.print.PageFormat; import javax.print.PrintServiceLookup; import org.jpedal.objects.PrinterOptions; public final class PrintUtils { /** * Create a AffineTransform to effect page according to scaling and * centring options. * * @param cropBoxX The crop box x position * @param cropBoxY The crop box y position * @param width The crop box width position * @param height The crop box height position * @param pageRotation The pages rotation * @param format The print page format * @param autoRotate The print auto rotate option * @param centerOnScaling The print centre on scaling option * @param chooseSourceByPDFSize Use PDF page size for print page format * @param scalingMode The print scaling option * @return Page transform for the given options */ public static AffineTransform getPageTransform(final int cropBoxX, final int cropBoxY, final int width, final int height, final int pageRotation, final PageFormat format, final boolean autoRotate, final boolean centerOnScaling, final boolean chooseSourceByPDFSize, final int scalingMode){ return getPageTransform(new Rectangle(cropBoxX, cropBoxY, width, height), pageRotation, format, autoRotate, centerOnScaling, chooseSourceByPDFSize, scalingMode); } /** * Create a AffineTransform to effect page according to scaling and * centring options. * * @param crop The pages crop box * @param pageRotation The pages rotation * @param format The print page format * @param autoRotate The print auto rotate option * @param centerOnScaling The print centre on scaling option * @param chooseSourceByPDFSize Use PDF page size for print page format * @param scalingMode The print scaling option * @return Page transform for the given options */ public static AffineTransform getPageTransform(final Rectangle crop, int pageRotation, final PageFormat format, final boolean autoRotate, final boolean centerOnScaling, final boolean chooseSourceByPDFSize, final int scalingMode){ final AffineTransform result = new AffineTransform(); double scalingFactor = 1; //Reset scaling factor boolean shouldRotate = false; //Find whether the page needs to be rotated for best fit if(autoRotate || chooseSourceByPDFSize) { final boolean isPageWidthLong = format.getImageableWidth() > format.getImageableHeight(); boolean isImageWidthLong = crop.width > crop.height; //As adobe does we print page based on the rotation the page is displayed at //so take this into account when determining if the width is longer than height if(pageRotation==90 || pageRotation==270){ //Use height as width isImageWidthLong = crop.width < crop.height; } shouldRotate = isPageWidthLong != isImageWidthLong; } //Printed page will output all upside down to factor this out we add 180 on to all page rotations if(!shouldRotate){ pageRotation += 180; if(pageRotation>360) { pageRotation-=360; } }else{ //To rotate to match adobe requires a 270 degree turn on top of the 180 to turn page upright. //Instead of adding 270 we ignore the 180 rotation and instead only rotate by 90 (as total is 90 over a full 360 spin). pageRotation += 90; if(pageRotation>360) { pageRotation-=360; } } //Calculate scaling factor final double w = pageRotation%180==0 ? crop.width : crop.height; final double h = pageRotation%180==0 ? crop.height : crop.width; final double widthRatio = (format.getImageableWidth() - 1) / w; final double heightRatio = (format.getImageableHeight() - 1) / h; if(((widthRatio < 1 || heightRatio < 1) && scalingMode == PrinterOptions.PAGE_SCALING_REDUCE_TO_PRINTER_MARGINS) || (scalingMode == PrinterOptions.PAGE_SCALING_FIT_TO_PRINTER_MARGINS)) { scalingFactor = widthRatio < heightRatio ? widthRatio : heightRatio; } //If page is had rotation, rotate content for printing. if(pageRotation!=0 || shouldRotate){ //Apply rotation to transform PrintUtils.applyRotation(result, pageRotation, crop, scalingFactor); } //Factor out crop box if(crop.x!=0 || crop.y!=0){ PrintUtils.applyCrop(result, pageRotation, crop, scalingFactor); } //Offset based on imagable area PrintUtils.applyOffset(result, pageRotation, format); //if we center the page, center it here if(centerOnScaling){ PrintUtils.applyCentering(result, pageRotation, format, crop, scalingFactor); } //Scale page if(scalingMode != PrinterOptions.PAGE_SCALING_NONE) { result.scale(scalingFactor, scalingFactor); } //Flip page result.scale(-1, 1); result.translate(-crop.width, 0); //Return transform for the page. return result; } //Add the rotation of the page to the transform so page can appear in the imageable area private static void applyRotation(final AffineTransform result, final int rotation, final Rectangle crop, final double scalingFactor){ final int factor = rotation / 90; //Perform rotation result.rotate(factor * Math.PI / 2.0); //Move page back into display, this varies based on rotation switch(factor){ case 1 : // 90 degree rotation result.translate(0, -(crop.height*scalingFactor)); break; case 2 : //180 degree rotation result.translate(-(crop.width*scalingFactor), -(crop.height*scalingFactor)); break; case 3 : //270 degree rotation result.translate(-(crop.width*scalingFactor), 0); break; } } //Add the crop of the page to the transform so page can appear in the imageable area private static void applyCrop(final AffineTransform result, final int rotation, final Rectangle crop, final double scalingFactor){ /* * Annoyingly I do not understand why the code below works. * By my reckoning the crop x / y values should change from positive to negative based on rotation. * How ever when I tried this the crop values were broke in all cases except 90 degrees. * When I tested this combination in other broken cases, they worked correctly.. * * I have kept the switch in here in case I am proved wrong at any point so we can quickly tweak * the values for different rotations. */ switch(rotation){ case 0 : result.translate(crop.x*scalingFactor, -crop.y*scalingFactor); break; case 90 : result.translate(crop.x*scalingFactor, -crop.y*scalingFactor); break; case 180 : result.translate(crop.x*scalingFactor, -crop.y*scalingFactor); break; case 270 : result.translate(crop.x*scalingFactor, -crop.y*scalingFactor); break; } } //Add the offset of the imageable area private static void applyOffset(final AffineTransform result, final int rotation, final PageFormat format){ switch(rotation){ case 0 : result.translate(format.getImageableX(), format.getImageableY()); break; case 90 : result.translate(format.getImageableX(), -format.getImageableY()); break; case 180 : result.translate(-format.getImageableX(), -format.getImageableY()); break; case 270 : result.translate(-format.getImageableX(), format.getImageableY()); break; } } //Add an offset so page will be centered in the iamgeable area private static void applyCentering(final AffineTransform result, final int rotation, final PageFormat format, final Rectangle crop, final double scalingFactor){ double centerOnX = 0; double centerOnY = 0; switch (rotation) { case 0: centerOnX = (format.getImageableWidth()-(crop.width*scalingFactor))/2; centerOnY = (format.getImageableHeight()-(crop.height*scalingFactor))/2; break; case 90: centerOnX = (format.getImageableHeight()-(crop.width*scalingFactor))/2; centerOnY = -((format.getImageableWidth()-(crop.height*scalingFactor))/2); break; case 180: centerOnX = -(format.getImageableWidth()-(crop.width*scalingFactor))/2; centerOnY = -(format.getImageableHeight()-(crop.height*scalingFactor))/2; break; case 270: centerOnX = -(format.getImageableHeight()-(crop.width*scalingFactor))/2; centerOnY = (format.getImageableWidth()-(crop.height*scalingFactor))/2; break; } result.translate(centerOnX, centerOnY); } public static void refreshPrinterList() { final Class[] classes = PrintServiceLookup.class.getDeclaredClasses(); for (final Class classe : classes) { if (classe.getName().equals("javax.print.PrintServiceLookup$Services")) { sun.awt.AppContext.getAppContext().remove(classe); break; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy