
org.jpedal.objects.GraphicsState Maven / Gradle / Ivy
/*
* ===========================================
* 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
*
* ---------------
* GraphicsState.java
* ---------------
*/
package org.jpedal.objects;
import java.awt.BasicStroke;
import java.awt.Stroke;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import javafx.scene.shape.Shape;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
import org.jpedal.color.DeviceGrayColorSpace;
import org.jpedal.color.GenericColorSpace;
import org.jpedal.color.PdfColor;
import org.jpedal.color.PdfPaint;
import org.jpedal.external.ExternalHandlers;
import org.jpedal.fonts.glyph.JavaFXSupport;
import org.jpedal.objects.raw.PdfArrayIterator;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.utils.LogWriter;
/**
* holds the graphics state as stream decoded
*/
@SuppressWarnings("MagicConstant")
public class GraphicsState implements Cloneable
{
//hold image co-ords
public float x,y;
TextState currentTextState=new TextState();
//transparency
private float strokeAlpha=1.0f;
private float nonstrokeAlpha=1.0f;
private float maxStrokeAlpha=1.0f;
private float maxNonstrokeAlpha=1.0f;
/** copy used for images*/
public final float[][] lastCTM = new float[3][3];
//TR value
private PdfObject TR;
public PdfObject SMask;
/**stroke colorspace*/
public GenericColorSpace strokeColorSpace=new DeviceGrayColorSpace();
/**nonstroke colorspace*/
public GenericColorSpace nonstrokeColorSpace=new DeviceGrayColorSpace();
private boolean hasClipChanged;
//overprinting
private boolean op;
private boolean OP;
private float OPM;
private PdfPaint nonstrokeColor=new PdfColor(0,0,0);
private PdfPaint strokeColor=new PdfColor(0,0,0);
/**holds current clipping shape*/
private Area current_clipping_shape;
private PdfClip current_clip;
private static final boolean debugClip=false;
/** CTM which is used for plotting (see pdf
* spec for explanation*/
public float[][] CTM = new float[3][3];
public float[][] scaleFactor;
/**dash of lines (phase) for drawing*/
private int current_line_dash_phase;
/**used for TR effect*/
private GeneralPath TRmask;
/**fill type for drawing*/
private int fill_type;
/**mitre limit for drawing - Set default limit to 10 as per the PDF spec */
private int mitre_limit = 10;
/**dash of lines (array) for drawing*/
private float[] current_line_dash_array=new float[0];
/**join style of lines for drawing*/
private int current_line_cap_style;
/**width of lines for drawing*/
private float current_line_width = 1;
/**width of lines to use when outputting to HTML/SVG etc**/
private int output_line_width = -1;
/**join of lines for drawing*/
private int current_line_join_style;
/**Type of draw to use*/
private int text_render_type = GraphicsState.FILL;
/**displacement to allow for negative page displacement*/
private int minX;//%%
/**displacement to allow for negative page displacement*/
private int minY;//%%
public static final int STROKE = 1;
public static final int FILL = 2;
public static final int FILLSTROKE = 3;
public static final int INVISIBLE = 4;
public static final int CLIPTEXT=7;
private int BMvalue=PdfDictionary.Normal;
public GraphicsState(final GraphicsState gs){
resetCTM();
BMvalue= gs.BMvalue;
}
public GraphicsState(){
resetCTM();
}
/**
* initialise the GraphicsState
* @param minX
* @param minY
*/
public GraphicsState(final int minX, final int minY)
{
this.minX=-minX;/*keep%%*/
this.minY=-minY;/*keep%%*/
resetCTM();
}
public void setMaxAlpha(final int type, final float value){
switch(type){
case STROKE:
this.maxStrokeAlpha=value;
break;
case FILL :
this.maxNonstrokeAlpha=value;
break;
}
}
public void setAlpha(final int type, float value){
switch(type){
case STROKE:
if(value>maxStrokeAlpha) {
value = maxStrokeAlpha;
}
this.strokeAlpha=value;
break;
case FILL :
if(value>maxNonstrokeAlpha) {
value = maxNonstrokeAlpha;
}
this.nonstrokeAlpha=value;
break;
}
}
/**use STROKE or FILL
* @param type
* @return*/
public float getAlpha(final int type){
float value=1f;
switch(type){
case STROKE:
if(strokeAlpha>maxStrokeAlpha){
value=maxStrokeAlpha;
}else{
value=this.strokeAlpha;
}
break;
case FILL :
if(nonstrokeAlpha>maxNonstrokeAlpha){
value=maxNonstrokeAlpha;
}else{
value=this.nonstrokeAlpha;
}
break;
}
return value;
}
/**use STROKE or FILL
* @param type
* @return*/
public float getAlphaMax(final int type){
float value=1f;
switch(type){
case STROKE:
value=this.maxStrokeAlpha ;
break;
case FILL :
value=this.maxNonstrokeAlpha;
break;
}
return value;
}
/**get stroke op*
public boolean getStrokeOP(){
return this.OP;
} /**/
/**get stroke op
* @return*/
public boolean getNonStrokeOP(){
return this.op;
}
/**get stroke op
* @return*/
public float getOPM(){
return this.OPM;
}
public PdfObject getTR() {
return TR;
}
//////////////////////////////////////////////////////////////////////////
/**
* set text render type
* @param text_render_type
*/
public final void setTextRenderType( final int text_render_type )
{
this.text_render_type = text_render_type;
TRmask=null;
}
//////////////////////////////////////////////////////////////////////////
/**
* set text render type
* @return
*/
public final int getTextRenderType()
{
return text_render_type;
}
///////////////////////////////////////////////////////////////////////////
/**
* set mitre limit
* @param mitre_limit
*/
public final void setMitreLimit( final int mitre_limit )
{
this.mitre_limit = mitre_limit;
}
/**
* get line width
* @return
*/
public final float getLineWidth()
{
return current_line_width;
}
/**
* get line width for HTML/SVG etc. value is -1 if not set.
* @return
*/
public final int getOutputLineWidth() {
return output_line_width;
}
//////////////////////////////////////////////////////////////////////////
/**
* set fill type
* @param fill_type
*/
public final void setFillType( final int fill_type )
{
this.fill_type = fill_type;
}
//////////////////////////////////////////////////////////////////////////
/**
* update clip
* @param current_area
*/
public final void updateClip( final Area current_area )
{
// System.out.println("Update clip "+current_area.getBounds());
if( current_clipping_shape == null || current_area==null){
current_clipping_shape = current_area;
hasClipChanged=true;
}else{// if(current_clipping_shape.intersects(current_area.getBounds2D().getX(),current_area.getBounds2D().getY(),
//current_area.getBounds2D().getWidth(),current_area.getBounds2D().getHeight())){
current_clipping_shape.intersect( current_area );
/**if( current_clipping_shape.getBounds().getHeight() == 0 ){
current_clipping_shape = current_area;
System.out.println("Reset to area");
}*/
hasClipChanged=true;
}
if(debugClip){
System.out.println("[updateClip]");
if(current_clipping_shape==null){
System.out.println("Null shape");
}else{
System.out.println("Shape bounds= "+current_clipping_shape.getBounds());
}
}
}
/**
* add to clip (used for TR 7)
* @param current_area
*/
public final void addClip( final Area current_area )
{
if(TRmask==null) {
TRmask = new GeneralPath();
}
TRmask.append(current_area,false);
}
//////////////////////////////////////////////////////////////////////////
/**
* get the current stroke to be used - basic solid line or pattern
* @return
*/
public final Stroke getStroke()
{
//hold the stroke for the path
final Stroke current_stroke;
//factor in scaling to line width
float w=current_line_width;
if(CTM[0][0]!=0) {
w *= CTM[0][0];
} else if( CTM[0][1]!=0) {
w *= CTM[0][1];
}
if(w<0) {
w = -w;
}
//check values all in legal boundaries
if( mitre_limit < 1 ) {
mitre_limit = 1;
}
final int dashCount=current_line_dash_array.length;
if( dashCount > 0 ){
//factor in scaling
final float[] dash=new float[dashCount];
for(int aa=0;aa 0 ){
//factor in scaling
final float[] dash=new float[dashCount];
for(int aa=0;aa max_y+2) && //2 is margin for error needed on some files
(current_clipping_shape.getBounds().y>=0)){
current_clipping_shape = null;
hasClipChanged=true;
if(debugClip){
System.out.println("[checkWholePageClip] current_clipping_shape="+current_clipping_shape);
if(current_clipping_shape==null){
System.out.println("Null shape");
}else{
System.out.println("Shape bounds= "+current_clipping_shape.getBounds());
}
}
}
}
/**
* set dash array
* @param current_line_dash_array
*/
public final void setDashArray( final float[] current_line_dash_array ){
this.current_line_dash_array = current_line_dash_array;
}
/**
* custom clone method
*/
@Override
public final Object clone(){
try {
super.clone();
} catch (CloneNotSupportedException ex) {
LogWriter.writeLog("Unable to clone "+ex);
}
final GraphicsState newGS=new GraphicsState();
newGS.x=x;
newGS.y=y;
if(TR!=null) {
newGS.TR = (PdfObject) TR.clone();
}
newGS.maxNonstrokeAlpha=maxNonstrokeAlpha;
newGS.maxStrokeAlpha=maxStrokeAlpha;
newGS.strokeAlpha = strokeAlpha;
newGS.nonstrokeAlpha = nonstrokeAlpha;
newGS.op = op;
newGS.OP = OP;
newGS.OPM = OPM;
newGS.nonstrokeColor = nonstrokeColor;
newGS.strokeColor = strokeColor;
if(current_clipping_shape != null) {
newGS.current_clipping_shape = (Area) current_clipping_shape.clone();
}
if(CTM != null){
for(int i=0;i<3;i++){
System.arraycopy(CTM[i], 0, newGS.CTM[i], 0, 3);
}
}
newGS.hasClipChanged=hasClipChanged;
newGS.current_line_dash_phase = current_line_dash_phase;
if(TRmask != null) {
newGS.TRmask = (GeneralPath) TRmask.clone();
}
newGS.fill_type = fill_type;
newGS.mitre_limit = mitre_limit;
if(current_line_dash_array!=null){
final int size=current_line_dash_array.length;
newGS.current_line_dash_array=new float[size];
System.arraycopy(current_line_dash_array, 0, newGS.current_line_dash_array, 0, size);
}
newGS.current_line_cap_style = current_line_cap_style;
newGS.current_line_width = current_line_width;
newGS.current_line_join_style = current_line_join_style;
newGS.text_render_type = text_render_type;
newGS.minX = minX;
newGS.minY = minY;
return newGS;
}
/**
* reset CTM
*/
private void resetCTM()
{
//init CTM
CTM[0][0] = (float)1.0;
CTM[1][0] = (float)0.0;
CTM[2][0] = minX;
CTM[0][1] = (float)0.0;
CTM[1][1] = (float)1.0;
CTM[2][1] = minY;
CTM[0][2] = (float)0.0;
CTM[1][2] = (float)0.0;
CTM[2][2] = (float)1.0;
}
/**
* set dash phase
* @param current_line_dash_phase
*/
public final void setDashPhase( final int current_line_dash_phase )
{
this.current_line_dash_phase = current_line_dash_phase;
}
/**
* get fill type
* @return
*/
public final int getFillType()
{
return fill_type;
}
/**
* set clipping shape
* @param new_clip
*/
public final void setClippingShape( final Area new_clip )
{
this.current_clipping_shape = new_clip;
hasClipChanged=true;
if(debugClip){
System.out.println("[setClippingShape]");
if(current_clipping_shape==null){
System.out.println("Null shape");
}else{
System.out.println("Shape bounds= "+current_clipping_shape.getBounds());
}
}
}
/**
* @return Returns the currentNonstrokeColor.
*/
public PdfPaint getNonstrokeColor() {
return nonstrokeColor;
}
/**
* @param currentNonstrokeColor The currentNonstrokeColor to set.
*/
public void setNonstrokeColor(final PdfPaint currentNonstrokeColor) {
this.nonstrokeColor = currentNonstrokeColor;
}
/**
* @return Returns the strokeColor.
*/
public PdfPaint getStrokeColor() {
return strokeColor;
}
/**
* @param strokeColor The strokeColor to set.
*/
public void setStrokeColor(final PdfPaint strokeColor) {
this.strokeColor = strokeColor;
}
/**
* tell software if clip has changed and
* return
* @return
*/
public boolean hasClipChanged() {
final boolean flag=hasClipChanged;
hasClipChanged=false;
return flag;
}
public void setTextState(final TextState currentTextState) {
this.currentTextState=currentTextState;
}
public TextState getTextState() {
return currentTextState;
}
public void updateClip(final Object fxPath) {
// Initialise when needed
if(current_clip == null){
JavaFXSupport fxSupport = ExternalHandlers.getFXHandler();
if(fxSupport!=null){
current_clip = fxSupport.getFXClip();
}
}
hasClipChanged = current_clip.updateClip(fxPath);
}
public Shape getFXClippingShape(){
if (current_clip == null) {
return null;
}
return (Shape)current_clip.getClippingShape();
}
public int getBMValue() {
return BMvalue;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy