org.jpedal.display.GUIDisplay Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of OpenViewerFX Show documentation
Show all versions of OpenViewerFX Show documentation
An Open Source JavaFX PDF Viewer
/*
* ===========================================
* 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-2016 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.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
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;
// Affine transformation as a double array
protected double[] displayScalingDbl;
/**
* 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);
}
}
/**
*
* @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
switch (newRotation) {
case 90:
displayScalingDbl[4] += ((insetW/scaling) * displayScalingDbl[1] );
displayScalingDbl[5] += ((insetH/scaling) * displayScalingDbl[2] );
break;
case 270:
displayScalingDbl[4] += ((-insetW/scaling) * displayScalingDbl[1] );
displayScalingDbl[5] += ((-insetH/scaling) * displayScalingDbl[2] );
break;
case 180:
displayScalingDbl[4] += ((-insetW/scaling) * displayScalingDbl[0] );
displayScalingDbl[5] += ((insetH/scaling) * displayScalingDbl[3] );
break;
default:
displayScalingDbl[4] += ((insetW/scaling) * displayScalingDbl[0] );
displayScalingDbl[5] += ((-insetH/scaling) * displayScalingDbl[3] );
break;
}
//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.");
}
@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.");
}
@Override
public void drawFacing(final Rectangle visibleRect) {
throw new UnsupportedOperationException("drawFacing 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;
}
}