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

org.jpedal.objects.PdfPageData Maven / Gradle / Ivy

The newest version!
/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/java-pdf-library-support/
 *
 * (C) Copyright 1997-2013, IDRsolutions and Contributors.
 *
 * 	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


 *
 * ---------------
 * PdfPageData.java
 * ---------------
 */
package org.jpedal.objects;

import java.io.Serializable;

import org.jpedal.utils.repositories.Vector_Int;
import org.jpedal.utils.repositories.Vector_Object;

/**
 * store data relating to page sizes set in PDF (MediaBox, CropBox, rotation)
 */
public class PdfPageData implements Serializable {

	private static final long serialVersionUID = -8258244553460848813L;

	private boolean valuesSet = false;

	private int lastPage = -1;

	private int pagesRead = -1;

	private int pageCount = 1; // number of pages

	private float[] defaultMediaBox = null;

	/** any rotation on page (defined in degress) */
	private int rotation = 0;

	/** max media string for page */
	private Vector_Object mediaBoxes = new Vector_Object(500);
	private Vector_Object cropBoxes = new Vector_Object(500);

	private Vector_Int rotations = null;

	/** current x and y read from page info */
	private float cropBoxX = -99999, cropBoxY = -1, cropBoxW = -1, cropBoxH = -1;

	/** current x and y read from page info */
	private float mediaBoxX = -1, mediaBoxY, mediaBoxW, mediaBoxH;

	/** whether the document has varying page sizes and rotation */
	private boolean hasMultipleSizes = false, hasMultipleSizesSet = false;

	/** string representation of crop box */
	private float scalingValue = 1f;

	private float[] mediaBox, cropBox;

	/** string representation of media box */
	private int defaultrotation;
	private float defaultcropBoxX, defaultcropBoxY, defaultcropBoxW, defaultcropBoxH;
	private float defaultmediaBoxX, defaultmediaBoxY, defaultmediaBoxW, defaultmediaBoxH;

	public PdfPageData() {}

	/**
	 * make sure a value set for crop and media box (used internally to trap 'odd' settings and insure setup correctly)
	 */
	public void checkSizeSet(int pageNumber) {

		// use default
		if (this.mediaBox == null) this.mediaBox = this.defaultMediaBox;

		// value we keep
		if (this.cropBox != null
				&& (this.cropBox[0] != this.mediaBox[0] || this.cropBox[1] != this.mediaBox[1] || this.cropBox[2] != this.mediaBox[2] || this.cropBox[3] != this.mediaBox[3])) {

			this.mediaBoxes.setElementAt(this.mediaBox, pageNumber);

			if (this.cropBox[0] >= this.mediaBox[0] && this.cropBox[1] >= this.mediaBox[1]
					&& (this.cropBox[2] - this.cropBox[0]) <= (this.mediaBox[2] - this.mediaBox[0])
					&& (this.cropBox[3] - this.cropBox[1]) <= (this.mediaBox[3] - this.mediaBox[1])) this.cropBoxes.setElementAt(this.cropBox,
					pageNumber);

		}
		else
			if (this.mediaBox != null
					&& (this.defaultMediaBox[0] != this.mediaBox[0] || this.defaultMediaBox[1] != this.mediaBox[1]
							|| this.defaultMediaBox[2] != this.mediaBox[2] || this.defaultMediaBox[3] != this.mediaBox[3])) // if matches default
																															// don't save
			this.mediaBoxes.setElementAt(this.mediaBox, pageNumber);

		// track which pages actually read
		if (this.pagesRead < pageNumber) this.pagesRead = pageNumber;

		this.lastPage = -1;
		this.mediaBox = null;
		this.cropBox = null;
	}

	/**
	 * return height of mediaBox
	 */
	final public int getMediaBoxHeight(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return (int) this.mediaBoxH;
	}

	/**
	 * return mediaBox y value
	 */
	final public int getMediaBoxY(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return (int) this.mediaBoxY;
	}

	/**
	 * return mediaBox x value
	 */
	final public int getMediaBoxX(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return (int) this.mediaBoxX;
	}

	/**
	 * set string with raw values and assign values to crop and media size
	 */
	public void setMediaBox(float[] mediaBox) {

		this.mediaBox = mediaBox;
		this.cropBox = null;

		if (this.defaultMediaBox == null) this.defaultMediaBox = mediaBox;
	}

	/**
	 * set crop with values and align with media box
	 */
	public void setCropBox(float[] cropBox) {

		this.cropBox = cropBox;

		// If mediaBox is set and crop box leaves this area
		// we should limit the cropBox by the mediaBox
		boolean testAlteredCrop = true;
		if (testAlteredCrop && (this.mediaBox != null && !(this.mediaBox.length < 4))) {
			if (cropBox[0] < this.mediaBox[0]) cropBox[0] = this.mediaBox[0];

			if (cropBox[1] < this.mediaBox[1]) cropBox[1] = this.mediaBox[1];

			if (cropBox[2] > this.mediaBox[2]) cropBox[2] = this.mediaBox[2];

			if (cropBox[3] > this.mediaBox[3]) cropBox[3] = this.mediaBox[3];
		}
	}

	public int setPageRotation(int value, int pageNumber) {

		int raw_rotation = value;

		// convert negative
		if (raw_rotation < 0) raw_rotation = 360 + raw_rotation;

		// only create if we need and set value
		if (raw_rotation != 0 || this.rotations != null) {
			if (this.rotations == null) {
				if (pageNumber < 2000) this.rotations = new Vector_Int(2000);
				else this.rotations = new Vector_Int(pageNumber * 2);
			}

			this.rotations.setElementAt(raw_rotation, pageNumber);

		}
		return raw_rotation;
	}

	/**
	 * return width of media box
	 */
	final public int getMediaBoxWidth(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return (int) this.mediaBoxW;
	}

	/**
	 * return mediaBox string found in PDF file
	 */
	public String getMediaValue(int currentPage) {

		StringBuilder returnValue = new StringBuilder();

		float[] mediaBox = this.defaultMediaBox;

		if (this.mediaBoxes != null) mediaBox = (float[]) this.mediaBoxes.elementAt(currentPage);

		if (mediaBox != null) {

			for (int j = 0; j < 4; j++) {
				returnValue.append(mediaBox[j]);
				returnValue.append(' ');
			}
		}

		return returnValue.toString();
	}

	/**
	 * return cropBox string found in PDF file
	 */
	public String getCropValue(int currentPage) {

		float[] cropBox = null;

		// use default
		if (this.cropBoxes != null) cropBox = (float[]) this.cropBoxes.elementAt(currentPage);
		else
			if (cropBox != null) cropBox = (float[]) this.mediaBoxes.elementAt(currentPage);

		if (cropBox == null) cropBox = this.defaultMediaBox;

		StringBuilder returnValue = new StringBuilder();

		for (int j = 0; j < 4; j++) {
			returnValue.append(cropBox[j]);
			returnValue.append(' ');
		}

		return returnValue.toString();
	}

	/**
	 * return Scaled x value for cropBox
	 */
	public int getScaledCropBoxX(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return roundFloat(this.cropBoxX * this.scalingValue);
	}

	/**
	 * return Scaled cropBox width
	 */
	public int getScaledCropBoxWidth(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return roundFloat(this.cropBoxW * this.scalingValue);
	}

	/**
	 * return Scaled y value for cropox
	 */
	public int getScaledCropBoxY(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return roundFloat(this.cropBoxY * this.scalingValue);
	}

	/**
	 * return Scaled cropBox height
	 */
	public int getScaledCropBoxHeight(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return roundFloat(this.cropBoxH * this.scalingValue);
	}

	/**
	 * return x value for cropBox
	 */
	public int getCropBoxX(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return (int) this.cropBoxX;
	}

	/**
	 * return x value for cropBox
	 */
	public float getCropBoxX2D(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return this.cropBoxX;
	}

	/**
	 * return cropBox width
	 */
	public int getCropBoxWidth(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return (int) this.cropBoxW;
	}

	/**
	 * return cropBox width
	 */
	public float getCropBoxWidth2D(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return this.cropBoxW;
	}

	/**
	 * return y value for cropox
	 */
	public int getCropBoxY(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return (int) this.cropBoxY;
	}

	/**
	 * return y value for cropox
	 */
	public float getCropBoxY2D(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return this.cropBoxY;
	}

	/**
	 * return cropBox height
	 */
	public int getCropBoxHeight(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return (int) this.cropBoxH;
	}

	/**
	 * return cropBox height
	 */
	public float getCropBoxHeight2D(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return this.cropBoxH;
	}

	/** see if current figures generated for this page and setup if not */
	private synchronized void setSizeForPage(int pageNumber) {

		if (pageNumber == this.lastPage) return;

		if (pageNumber > this.pageCount) this.pageCount = pageNumber;

		/** calculate values if first call for this page */
		if (pageNumber > this.pagesRead) {

			// set values if no value
			this.mediaBoxX = 0;
			this.mediaBoxY = 0;
			this.mediaBoxW = 0;
			this.mediaBoxH = 0;

			// set values if no value
			this.cropBoxX = 0;
			this.cropBoxY = 0;
			this.cropBoxW = 0;
			this.cropBoxH = 0;

			this.lastPage = pageNumber;

		}
		else
			if (pageNumber > 0 && this.lastPage != pageNumber) {

				this.lastPage = pageNumber;

				boolean usingDefault = false;

				float[] cropBox = (float[]) this.cropBoxes.elementAt(pageNumber);
				float[] mediaBox = (float[]) this.mediaBoxes.elementAt(pageNumber);
				if (mediaBox == null && this.defaultMediaBox != null) {
					mediaBox = this.defaultMediaBox;
					usingDefault = true;
				}

				// set rotation
				if (this.rotations != null) this.rotation = this.rotations.elementAt(pageNumber);
				else this.rotation = this.defaultrotation;

				while (this.rotation >= 360)
					this.rotation = this.rotation - 360;

				if (this.valuesSet && usingDefault) {

					this.cropBoxX = this.defaultcropBoxX;
					this.mediaBoxX = this.defaultmediaBoxX;
					this.cropBoxY = this.defaultcropBoxY;
					this.mediaBoxY = this.defaultmediaBoxY;
					this.cropBoxW = this.defaultcropBoxW;
					this.mediaBoxW = this.defaultmediaBoxW;
					this.cropBoxH = this.defaultcropBoxH;
					this.mediaBoxH = this.defaultmediaBoxH;

				}
				else {

					/**
					 * set mediaBox, cropBox and default if none
					 */

					// set values if no value
					this.mediaBoxX = 0;
					this.mediaBoxY = 0;
					this.mediaBoxW = 800;
					this.mediaBoxH = 800;

					if (mediaBox != null) {
						this.mediaBoxX = mediaBox[0];
						this.mediaBoxY = mediaBox[1];
						this.mediaBoxW = mediaBox[2] - this.mediaBoxX;
						this.mediaBoxH = mediaBox[3] - this.mediaBoxY;

						if (this.mediaBoxY > 0 && this.mediaBoxH == -this.mediaBoxY) {
							this.mediaBoxH = -this.mediaBoxH;
							this.mediaBoxY = 0;
						}
					}

					/**
					 * set crop
					 */
					if (cropBox != null) {

						this.cropBoxX = cropBox[0];
						this.cropBoxY = cropBox[1];
						this.cropBoxW = cropBox[2];
						this.cropBoxH = cropBox[3];

						if (this.cropBoxX > this.cropBoxW) {
							float temp = this.cropBoxX;
							this.cropBoxX = this.cropBoxW;
							this.cropBoxW = temp;
						}
						if (this.cropBoxY > this.cropBoxH) {
							float temp = this.cropBoxY;
							this.cropBoxY = this.cropBoxH;
							this.cropBoxH = temp;
						}

						this.cropBoxW = this.cropBoxW - this.cropBoxX;
						this.cropBoxH = this.cropBoxH - this.cropBoxY;

						if (this.cropBoxY > 0 && this.cropBoxH == -this.cropBoxY) {
							this.cropBoxH = -this.cropBoxH;
							this.cropBoxY = 0;
						}

					}
					else {
						this.cropBoxX = this.mediaBoxX;
						this.cropBoxY = this.mediaBoxY;
						this.cropBoxW = this.mediaBoxW;
						this.cropBoxH = this.mediaBoxH;
					}
				}

				// fix for odd file with negative height
				if (this.cropBoxH < 0) {
					this.cropBoxY = this.cropBoxY + this.cropBoxH;
					this.cropBoxH = -this.cropBoxH;
				}
				if (this.cropBoxW < 0) {
					this.cropBoxX = this.cropBoxX + this.cropBoxW;
					this.cropBoxW = -this.cropBoxW;
				}

				if (usingDefault && !this.valuesSet) {

					this.defaultrotation = this.rotation;
					this.defaultcropBoxX = this.cropBoxX;
					this.defaultmediaBoxX = this.mediaBoxX;
					this.defaultcropBoxY = this.cropBoxY;
					this.defaultmediaBoxY = this.mediaBoxY;
					this.defaultcropBoxW = this.cropBoxW;
					this.defaultmediaBoxW = this.mediaBoxW;
					this.defaultcropBoxH = this.cropBoxH;
					this.defaultmediaBoxH = this.mediaBoxH;

					this.valuesSet = true;
				}
			}
	}

	/**
	 * Get the scaling value currently being used
	 */
	public float getScalingValue() {
		return this.scalingValue;
	}

	/**
	 * Scaling value to apply to all values
	 */
	public void setScalingValue(float scalingValue) {
		this.scalingValue = scalingValue;
	}

	private static int roundFloat(float origValue) {
		int roundedValue = (int) origValue;

		boolean useCustomRounding = true;
		if (useCustomRounding) {
			float frac = origValue - roundedValue;
			if (frac > 0.3) roundedValue = roundedValue + 1;
		}
		return roundedValue;
	}

	/**
	 * get page count
	 */
	final public int getPageCount() {
		return this.pageCount;
	}

	/** return rotation value (for outside class) */
	final public int getRotation(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return this.rotation;
	}

	/**
	 * return Scaled height of mediaBox
	 */
	final public int getScaledMediaBoxHeight(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return roundFloat(this.mediaBoxH * this.scalingValue);
	}

	/**
	 * return Scaled width of media box
	 */
	final public int getScaledMediaBoxWidth(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return roundFloat(this.mediaBoxW * this.scalingValue);
	}

	/**
	 * return Scaled mediaBox x value
	 */
	final public int getScaledMediaBoxX(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return roundFloat(this.mediaBoxX * this.scalingValue);
	}

	/**
	 * return Scaled mediaBox y value
	 */
	final public int getScaledMediaBoxY(int pageNumber) {

		// check values correctly set
		setSizeForPage(pageNumber);

		return roundFloat(this.mediaBoxY * this.scalingValue);
	}

	public boolean hasMultipleSizes() {
		// return if already calculated
		if (this.hasMultipleSizesSet) {
			return this.hasMultipleSizes;
		}

		// scan all pages and if we find one different, disable page turn
		int pageCount = this.pageCount;
		int pageW = getCropBoxWidth(1);
		int pageH = getCropBoxHeight(1);
		int pageR = getRotation(1);

		if (pageCount > 1) {
			for (int jj = 2; jj < pageCount + 1; jj++) {

				if (pageW != getCropBoxWidth(jj) || pageH != getCropBoxHeight(jj) || pageR != getRotation(jj)) {
					jj = pageCount;
					this.hasMultipleSizes = true;
				}
			}
		}
		this.hasMultipleSizesSet = true;
		return this.hasMultipleSizes;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy