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

org.jpedal.display.GUIDisplay 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-2015 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


 *
 * ---------------
 * GUIDisplay.java
 * ---------------
 */
package org.jpedal.display;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;

import org.jpedal.exception.PdfException;

import org.jpedal.external.Options;
import org.jpedal.external.RenderChangeListener;

import org.jpedal.objects.PdfPageData;
import org.jpedal.objects.acroforms.AcroRenderer;
import org.jpedal.parser.DecoderOptions;
import org.jpedal.render.DynamicVectorRenderer;
import org.jpedal.text.TextLines;
import org.jpedal.utils.ScalingFactory;

/**
 * hold code generic to Swing or FX
 */
public class GUIDisplay implements Display{
    
    protected int lastFormPage=-1,lastStart=-1,lastEnd=-1;

    protected int pageUsedForTransform;

    /**tracks indent so changing to continuous does not disturb display*/
    protected int lastIndent=-1;

    protected double indent;
    
    /**Normally null - user object to listen to paint events*/
    public RenderChangeListener customRenderChangeListener;

     //rectangle onscreen
    public int rx,ry,rw,rh;

    protected DisplayOffsets displayOffsets;
    
    public DecoderOptions options;
    
    /**
     * Flag if we should allow cursor to change
     */
    public static boolean allowChangeCursor = true;
    
    public final MultiDisplayOptions multiDisplayOptions=new MultiDisplayOptions(); 

    //Animation enabled (currently just turnover in facing)
    public static boolean default_turnoverOn =  true;//can be altered by user
    
    //Display the first page separately in Facing mode
    public static boolean default_separateCover =  true;//can be altered by user
    
    public DynamicVectorRenderer currentDisplay;
    
    public boolean isInitialised;
    
    /**flag to switch back to unaccelerate screen if no enough memory for scaling*/
    public boolean overRideAcceleration;

    /**render screen using hardware acceleration*/
    public boolean useAcceleration=true;
    
    public boolean ignoreScalingForAcceleration;
    
    public boolean accelerationAlwaysRedraw;
    
    public PageOffsets currentOffset;
    
    
    /** Holds the x,y,w,h of the current highlighted image, null if none */
    private int[] highlightedImage;
    
    protected GUIThumbnailPanel thumbnails;
    
    /** Keep a record of cumulative offsets for SINGLE_PAGE mode*/
    public int[] pageOffsetH, pageOffsetW;

    public boolean[] isRotated;
    
    public int topW,topH;
    public double cropX,cropY,cropW,cropH;
    
    /**used to draw demo cross*/
    public int crx,cry,crw,crh;

    /**local copies*/
    public int displayRotation,displayView=SINGLE_PAGE;
    public int lastDisplayRotation;

    public int insetW,insetH;

    public float scaling;
    public float lastScaling;

    public int pageNumber;
    
    /**any scaling factor being used to convert co-ords into correct values
     * and to alter image size
     */
    public float oldScaling=-1,oldRotation=-1;


    public PdfPageData pageData;
    
    
    @Deprecated
    /*
    * Please use PdfDecoder.setBorderPresent(boolean) instead
    * True : Show border around page.
    * Flase : Remove border around page.
    */
    public static int CURRENT_BORDER_STYLE = 1;
    
    // Affine transformation as a double array
    protected double[] displayScalingDbl;
    
//    public static void setBorderStyle(int style){
//        CURRENT_BORDER_STYLE = style;
//    }
//
//    public static int getBorderStyle(){
//        return CURRENT_BORDER_STYLE;
//    }

    /**
     * used internally by multiple pages
     * scaling -1 to ignore, -2 to force reset
     */
    @Override
    public int getYCordForPage(final int page, final float scaling) {

        if (scaling == -2 || (scaling != -1f && scaling != oldScaling)) {
            oldScaling = scaling;
            setPageOffsets(page);
        }
        return getYCordForPage(page);
    }
    
    @Override
    public boolean getBoolean(final BoolValue option) {
        switch (option) {
            case SEPARATE_COVER:
                return multiDisplayOptions.isSeparateCover();
            case TURNOVER_ON:
                return multiDisplayOptions.isTurnoverOn();
            default:
                throw new RuntimeException("GetBoolean called with unknown value "+option);
        }
    }

    @Override
    public void setBoolean(final BoolValue option, final boolean value) {
        switch (option) {
            case SEPARATE_COVER:
                multiDisplayOptions.setSeparateCover(value);
                return;
            case TURNOVER_ON:
                multiDisplayOptions.setTurnoverOn(value);
                return;
            default:
                throw new RuntimeException("setBoolean called with unkown value "+value);
        }
    }
    
     /**
     * general method to pass in Objects - only takes  RenderChangeListener at present
     * @param type
     * @param newHandler
     */
    @Override
    public void setObjectValue(final int type, final Object newHandler) {

        //set value
        switch(type){
            case Options.RenderChangeListener:
                customRenderChangeListener = (RenderChangeListener) newHandler;
                break;

            default:
                throw new RuntimeException("setObjectValue does not take value "+type);
        }
    }
    
    @Override
    public void setCursorBoxOnScreen(final Rectangle cursorBoxOnScreen, final boolean isSamePage) {
        
    }


    /**
     * 
     * @param displayView is of type int
     * @return returns an int[] with 2 values ([0]width and [1]height) 
     * which we then use to create a Dimension object in current Swing code
     */
    @Override
    public int[] getPageSize(final int displayView) {

        final int[] pageSize = new int[2];    //element 0 = width, element 1 = height
        
        //height for facing pages
        int biggestFacingHeight=0;
        int facingWidth=0;

        if((displayView==FACING)&&(multiDisplayOptions.getPageW()!=null)){
            //get 2 facing page numbers
            int p1;
            final int p2;
            if (multiDisplayOptions.isSeparateCover()) {
                p1=pageNumber;
                if((p1 & 1)==1) {
                    p1--;
                }
                p2=p1+1;
            } else {
                p1=pageNumber;
                if((p1 & 1)==0) {
                    p1--;
                }
                p2=p1+1;
            }

            if (p1 == 0) {
                biggestFacingHeight = multiDisplayOptions.getPageH(p2);
                facingWidth = multiDisplayOptions.getPageW(p2)*2;
            } else {
                biggestFacingHeight=multiDisplayOptions.getPageH(p1);
                if(p2=360) {
                displayRotation -= 360;
            }

            //swap if this page rotated and flag
            if((displayRotation==90|| displayRotation==270)){
                final int tmp=pageW[i];
                pageW[i]=pageH[i];
                pageH[i]=tmp;

                isRotated[i]=true; //flag page as rotated
            }

            if((i&1)==1){
                if(pageW[i]>RmaxWidth) {
                    RmaxWidth = pageW[i];
                }
                if(pageH[i]>RmaxHeight) {
                    RmaxHeight = pageH[i];
                }
            }else{
                if(multiDisplayOptions.getPageW(i)>LmaxWidth) {
                    LmaxWidth = multiDisplayOptions.getPageW(i);
                }
                if(pageH[i]>LmaxHeight) {
                    LmaxHeight = pageH[i];
                }
            }
        }

        int[] xReached=multiDisplayOptions.getxReached();
        int[] yReached=multiDisplayOptions.getyReached();
         
        //loop through all pages and work out positions
        for(int i=1;i=2 &&
                            (((pageData.getRotation(i) == 270 || pageData.getRotation(i) == 90) &&
                            (pageData.getRotation(i-1) != 270 || pageData.getRotation(i-1) != 90))
                            || ((pageData.getRotation(i-1) == 270 || pageData.getRotation(i-1) == 90) &&
                            (pageData.getRotation(i) != 270 || pageData.getRotation(i) != 90))))) {
                        pageOffsetW[i] = (pageW[i] - pageW[i-1]) + pageOffsetW[i-1];
                        pageOffsetH[i] = (pageH[i] - pageH[i-1]) + pageOffsetH[i-1];
                    }

                    //Left Pages
                    if((i & 1)==0){
                        //Last Page rotated so correct height
                        if(i3){
                            final int temp = (pageH[i-2]-pageH[i-1])/2;
                            if(temp>0) {
                                heightCorrection += temp;
                            }
                        }
                        yReached[i] = (yReached[i-1]+pageH[i-1] +gap)+heightCorrection;
                    }else{ //Right Pages
                        //Last Page rotated so correct height
                        heightCorrection = (pageH[i-1]-pageH[i])/2;
                        yReached[i] = (yReached[i-1])+heightCorrection;
                    }
                    
                    if((i & 1)==0){//Indent Left pages by diff between maxWidth and pageW (will only indent unrotated)
                        xReached[i] += (LmaxWidth-pageW[i]);
                    }else{//Place Right Pages with a gap (This keeps pages centered)
                        xReached[i] = xReached[i-1]+pageW[i-1] +gap;
                    }

                }else if(displayView==CONTINUOUS){
                    //Place page below last with gap
                    yReached[i] = (yReached[i-1]+pageH[i-1]+gap);

                    if(!(i>=2 &&
                            (((pageData.getRotation(i) == 270 || pageData.getRotation(i) == 90) &&
                            (pageData.getRotation(i-1) != 270 || pageData.getRotation(i-1) != 90))
                            || ((pageData.getRotation(i-1) == 270 || pageData.getRotation(i-1) == 90) &&
                            (pageData.getRotation(i) != 270 || pageData.getRotation(i) != 90))))) {
                        pageOffsetW[i] = (pageW[i] - pageW[i-1]) + pageOffsetW[i-1];
                        pageOffsetH[i] = (pageH[i] - pageH[i-1]) + pageOffsetH[i-1];
                    }

                }else if((displayView==FACING)){
                    if((i&1)==1){ //If right page, place on right with gap
                        xReached[i] = (xReached[i-1]+pageW[i-1]+gap);
                        if(pageH[i] < pageH[i-1])//Drop page down to keep pages centred
                        {
                            yReached[i] += (((pageH[i - 1] - pageH[i]) / 2));
                        }
                    }else{ //If left page, indent by diff of max and current page
                        xReached[i] = 0;
                        if(i
     */
    @Override
    public void setPageRotation(int newRotation) {


        //assume unrotated for multiple views and rotate on a page basis
        if(displayView!=Display.SINGLE_PAGE) {
            newRotation = 0;
        }

        pageUsedForTransform= pageNumber;
        if(displayView!=Display.SINGLE_PAGE && displayView!=Display.FACING){
            displayScalingDbl = ScalingFactory.getScalingForImage(1, 0, scaling,pageData);//(int)(pageData.getCropBoxWidth(pageNumber)*scaling),(int)(pageData.getCropBoxHeight(pageNumber)*scaling),
        }else{
            displayScalingDbl = ScalingFactory.getScalingForImage(pageNumber,newRotation, scaling, pageData);//(int)(pageData.getCropBoxWidth(pageNumber)*scaling),(int)(pageData.getCropBoxHeight(pageNumber)*scaling),
        }
      
        final int insetW=options.getInsetW();
        final int insetH=options.getInsetH();
        
        // Affine transformations
        if(newRotation == 90){
            
            displayScalingDbl[4] += ((insetW/scaling) * displayScalingDbl[1] );
            displayScalingDbl[5] += ((insetH/scaling) * displayScalingDbl[2] );
        }else if(newRotation == 270){
            displayScalingDbl[4] += ((-insetW/scaling) * displayScalingDbl[1] );
            displayScalingDbl[5] += ((-insetH/scaling) * displayScalingDbl[2] );
        }else if(newRotation == 180){
            displayScalingDbl[4] += ((-insetW/scaling) * displayScalingDbl[0] );
            displayScalingDbl[5] += ((insetH/scaling) * displayScalingDbl[3] );
        }else{
            displayScalingDbl[4] += ((insetW/scaling) * displayScalingDbl[0] );
            displayScalingDbl[5] += ((-insetH/scaling) * displayScalingDbl[3] );
        }
        
        //force redraw if screen being cached
        refreshDisplay();
    }

    @Override
    public void resetViewableArea() {
        throw new UnsupportedOperationException("resetViewableArea Not supported yet.");
    }

    @Override
    public void paintPage(final Graphics2D g2, final AcroRenderer formRenderer, final TextLines textLines) {
        throw new UnsupportedOperationException("paintPage not supported yet.");
    }

    /**
     * Deprecated on 04/07/2014, please use 
     * updateCursorBoxOnScreen(int[] newOutlineRectangle, int outlineColor, int pageNumber,int x_size,int y_size) instead.
     * @deprecated
     */
    @Override
    public void updateCursorBoxOnScreen(final Rectangle newOutlineRectangle, final Color outlineColor, final int pageNumber, final int x_size, final int y_size) {
        throw new UnsupportedOperationException("please use updateCursorBoxOnScreen(int[] newOutlineRectangle, int outlineColor, int pageNumber,int x_size,int y_size) instead");
    }
    
    @Override
    public void updateCursorBoxOnScreen(final int[] newOutlineRectangle, final int outlineColor, final int pageNumber, final int x_size, final int y_size){
        throw new UnsupportedOperationException("updateCursorBoxOnScreen Not supported yet."); 
    }

    @Override
    public void drawCursor(final Graphics g, final float scaling) {
        throw new UnsupportedOperationException("drawCursor Not supported yet.");
    }

    /**
     * Deprecated on 07/07/2014
     * Please use setViewableArea(int[] viewport) instead.
     * @deprecated
     */
    @Override
    public AffineTransform setViewableArea(final Rectangle viewport) throws PdfException {
        throw new UnsupportedOperationException("setViewableArea Not supported yet."); 
    }
    
    /**
     * NOT PART OF API
     *
     * allows the user to create a viewport within the displayed page, the
     * aspect ratio is keep for the PDF page 
*
* Passing in a null value is the same as calling resetViewableArea() *
*
* The viewport works from the bottom left of the PDF page
* The general formula is
* (leftMargin,
* bottomMargin,
* pdfWidth-leftMargin-rightMargin,
* pdfHeight-bottomMargin-topMargin) *
* The viewport will not be incorporated in printing
*
* Throws PdfException if the viewport is not totally enclosed within the * 100% cropped pdf */ @Override public AffineTransform setViewableArea(final int[] viewport) throws PdfException{ throw new UnsupportedOperationException("setViewableArea Not supported yet."); } @Override public void drawFacing(final Rectangle visibleRect) { throw new UnsupportedOperationException("drawFacing Not supported yet."); } @Override public void paintPage(final Object box, final AcroRenderer formRenderer, final TextLines textLines) { throw new UnsupportedOperationException("paintPage Not supported yet."); } public void setCurrentDisplay(final DynamicVectorRenderer pageView) { this.currentDisplay=pageView; } public int getDisplayRotation() { return displayRotation; } public int getRx() { return rx; } public int getRy() { return ry; } public int getRw() { return rw; } public int getRh() { return rh; } public int getInsetW() { return insetW; } public int getInsetH() { return insetH; } @Override public Rectangle getDisplayedRectangle() { throw new UnsupportedOperationException("getDisplayedRectangle Not supported yet."); } public Rectangle getDisplayedRectangle(final boolean isShowing,final Rectangle userAnnot) { //get raw rectangle rx =userAnnot.x; ry =userAnnot.y; rw =userAnnot.width; rh =userAnnot.height; //Best way I found to catch if pdf decoder is being used but never displayed if(!isShowing && (rw==0 || rh==0)){ rx = 0; ry = 0; rw = pageData.getScaledCropBoxWidth(pageNumber); rh = pageData.getScaledCropBoxHeight(pageNumber); if(pageData.getRotation(pageNumber)%180!=0){ rh = pageData.getScaledCropBoxWidth(pageNumber); rw = pageData.getScaledCropBoxHeight(pageNumber); } } return userAnnot; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy