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

org.jpedal.objects.raw.FormObject 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


 *
 * ---------------
 * FormObject.java
 * ---------------
 */
package org.jpedal.objects.raw;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.swing.*;
import javax.swing.text.JTextComponent;
import org.jpedal.color.DeviceCMYKColorSpace;
import org.jpedal.external.ExternalHandlers;
import org.jpedal.fonts.glyph.JavaFXSupport;
import org.jpedal.objects.acroforms.creation.FormFactory;
import org.jpedal.objects.acroforms.creation.GenericFormFactory;
import org.jpedal.objects.javascript.defaultactions.DisplayJavascriptActions;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.ObjectCloneFactory;
import org.jpedal.utils.StringUtils;

public class FormObject extends PdfObject{

    private static final JavaFXSupport fxSupport = ExternalHandlers.getFXHandler();
                 
    private int formType = -1;

    private String fontName="Arial";
    
    Object guiComp;
    private int guiType;

    //rotation on page
    private int rawRotation;
    
    Point currentLocation;
    
	float currentScaling = -1.0f;
	
	//unknown CMAP as String
	private String EOPROPtype, Filter, Location, M, Reason, SubFilter;
	private byte[] rawEOPROPtype, rawFilter, rawLocation, rawM,rawReason, rawSubFilter;

    /**
     * the C color for annotations
     */
    private Color cColor;
    /**
     * the contents for any text display on the annotation
     */
    private String contents;
    /**
     * whether the annotation is being displayed or not by default
     */
    private boolean show;

    private Map OptValues; // values from Opt

    private String validValue;
    
    private int[] matteDetails = {0,0,0,0};
    

    /** 1 form flag indexes for the field flags */
    public static final int READONLY_ID = 1;
    /** 2 form flag indexes for the field flags */
    public static final int REQUIRED_ID = 2;
    /** 3 form flag indexes for the field flags */
    public static final int NOEXPORT_ID = 3;
    /** 13 form flag indexes for the field flags */
    public static final int MULTILINE_ID = 13;
    /** 14 form flag indexes for the field flags */
    public static final int PASSWORD_ID = 14;
    /** 15 form flag indexes for the field flags */
    public static final int NOTOGGLETOOFF_ID = 15;
    /** 16 form flag indexes for the field flags */
    public static final int RADIO_ID = 16;
    /** 17 form flag indexes for the field flags */
    public static final int PUSHBUTTON_ID = 17;
    /** 18 form flag indexes for the field flags */
    public static final int COMBO_ID = 18;
    /** 19 form flag indexes for the field flags */
    public static final int EDIT_ID = 19;
    /** 20 form flag indexes for the field flags */
    public static final int SORT_ID = 20;
    /** 21 form flag indexes for the field flags */
    public static final int FILESELECT_ID = 21;
    /** 22 form flag indexes for the field flags */
    public static final int MULTISELECT_ID = 22;
    /** 23 form flag indexes for the field flags */
    public static final int DONOTSPELLCHECK_ID = 23;
    /** 24 form flag indexes for the field flags */
    public static final int DONOTSCROLL_ID = 24;
    /** 25 form flag indexes for the field flags */
    public static final int COMB_ID = 25;
    /** 26 form flag indexes for the field flags */
    public static final int RICHTEXT_ID = 26;//same as RADIOINUNISON_ID (radio buttons)
    /** 26 form flag indexes for the field flags */
    public static final int RADIOINUNISON_ID = 26;//same as RICHTEXT_ID (text fields)
    /** 27 form flag indexes for the field flags */
    public static final int COMMITONSELCHANGE_ID = 27;

    /* variables for forms to check with the (Ff)  flags field
     * (1<
     * appearance characteristics dictionary  (all optional)
     * R rotation on wiget relative to page
     * BC array of numbers, range between 0-1 specifiying the border color
     * number of array elements defines type of colorspace
     * 0=transparant
     * 1=gray
     * 3=rgb
     * 4=cmyk
     * BG same as BC but specifies wigets background color
     * 

* buttons only - * CA its normal caption text *

* pushbuttons only - * RC rollover caption text * AC down caption text * I formXObject defining its normal icon * RI formXObject defining its rollover icon * IX formXObject defining its down icon * IF icon fit dictionary, how to fit its icon into its rectangle * (if specified must contain all following) * SW when it should be scaled to fit ( default A) * A always * B when icon is bigger * S when icon is smaller * N never * S type of scaling - (default P) * P keep aspect ratio * A ignore aspect ratio (fit exactly to width and hight) * A array of 2 numbers specifying its location when scaled keeping the aspect ratio * range between 0.0-1.0, [x y] would be positioned x acress, y up * TP positioning of text relative to icon - (integer) * 0=caption only * 1=icon only * 2=caption below icon * 3=caption above icon * 4=caption on right of icon * 5=caption on left of icon * 6=caption overlaid ontop of icon */ private PdfObject MK; private PdfObject DC, DP, DR, DS, E, Fdict, Fo, FS, JS, K, Nobj, Next, O, PC, PI, PO, Popup, PV, R, Sig, Sound, U, V, Win, WP, WS, X; protected int[] ByteRange, selectionIndices; protected byte[] rawAS, rawCert, rawContactInfo, rawContents, rawDstring, rawDA, rawDV, rawFstring, rawJS, rawH, rawN, rawNM, rawPstring, rawRC, rawRT, rawS, rawSubj, rawT, rawTM, rawTU, rawURI, rawV,rawX; protected int FT=-1; protected String AS, Cert, ContactInfo, Contents, Dstring, DA, DV, Fstring, JSString, H, N, NM, Pstring, RC, S, Subj, T, TM, TU, URI, Vstring; private byte[][] Border, DmixedArray, Fields, State, rawXFAasArray; protected PdfObject Bl, OC, Off, On, P; private PdfObject XFAasStream; protected Object[] CO, InkList, Opt,Reference; protected byte[][] Kids; private String htmlName; public void setHTMLName(final String name) { htmlName = name; } public String getHTMLName(){ return htmlName; } public FormObject(final String ref) { super(ref); objType=PdfDictionary.Form; } public FormObject(final String ref, final boolean flag) { super(ref); objType=PdfDictionary.Form; this.includeParent=flag; } public FormObject(final int ref, final int gen) { super(ref,gen); objType=PdfDictionary.Form; } public FormObject(final int type) { super(type); objType=PdfDictionary.Form; } public FormObject() { objType=PdfDictionary.Form; } public FormObject(final String ref, final int parentType) { super(ref); objType=PdfDictionary.Form; this.parentType=parentType; } @Override public boolean getBoolean(final int id){ switch(id){ case PdfDictionary.H: return H_Boolean; case PdfDictionary.NeedAppearances: return NeedAppearances; case PdfDictionary.Open: return Open; default: return super.getBoolean(id); } } @Override public void setBoolean(final int id, final boolean value){ switch(id){ case PdfDictionary.H: H_Boolean=value; break; case PdfDictionary.NeedAppearances: NeedAppearances=value; break; case PdfDictionary.Open: Open=value; break; default: super.setBoolean(id, value); } } /** * used internally to set status while parsing - should not be called * @param popup */ public void setActionFlag(final int popup) { popupFlag=popup; } /** * get status found during decode */ public int getActionFlag() { return popupFlag; } @Override public PdfObject getDictionary(final int id){ switch(id){ case PdfDictionary.A: return A; case PdfDictionary.AA: return AA; case PdfDictionary.AP: if(AP==null) { AP = new FormObject(); } return AP; case PdfDictionary.BI: return BI; case PdfDictionary.Bl: return Bl; case PdfDictionary.BS: if(BS==null){ if(parentPdfObj!=null){ final PdfObject BSdic = parentPdfObj.getDictionary(PdfDictionary.BS); if(BSdic!=null){ return (PdfObject)BSdic.clone(); } } BS = new FormObject(); } return BS; case PdfDictionary.C: return Cdict; //case PdfDictionary.C2: //return C2; case PdfDictionary.D: return D; case PdfDictionary.DC: return DC; case PdfDictionary.DP: return DP; case PdfDictionary.DR: return DR; case PdfDictionary.DS: return DS; case PdfDictionary.E: return E; case PdfDictionary.F: return Fdict; case PdfDictionary.Fo: return Fo; case PdfDictionary.FS: return FS; case PdfDictionary.JS: return JS; //case PdfDictionary.I: //return I; case PdfDictionary.IF: return IF; case PdfDictionary.IRT: return IRT; case PdfDictionary.K: return K; case PdfDictionary.MK: //can't return null if(MK==null){ if(parentPdfObj!=null){ final PdfObject MKdic = parentPdfObj.getDictionary(PdfDictionary.MK); if(MKdic!=null){ return (PdfObject)MKdic.clone(); } } MK=new MKObject(); } return MK; case PdfDictionary.N: return Nobj; case PdfDictionary.Next: return Next; case PdfDictionary.O: return O; case PdfDictionary.OC: return OC; case PdfDictionary.Off: //System.out.println("Off "+this.getObjectRefAsString()+" "+Off); // if(Off==null){ // System.out.println(otherValues); // return (PdfObject) otherValues.get("Off"); // }else return Off; case PdfDictionary.On: // System.out.println("On "+this.getObjectRefAsString()+" "+On); // if(On==null){ // System.out.println(otherValues); // return (PdfObject) otherValues.get("On"); // }else return On; case PdfDictionary.P: return P; case PdfDictionary.PC: return PC; case PdfDictionary.PI: return PI; case PdfDictionary.PO: return PO; case PdfDictionary.Popup: return Popup; case PdfDictionary.PV: return PV; case PdfDictionary.R: return R; case PdfDictionary.RichMediaContent: return RichMediaContent; case PdfDictionary.Sig: return Sig; case PdfDictionary.Sound: return Sound; case PdfDictionary.U: return U; case PdfDictionary.V: return V; case PdfDictionary.Win: return Win; case PdfDictionary.WP: return WP; case PdfDictionary.WS: return WS; case PdfDictionary.X: return X; case PdfDictionary.XFA: return XFAasStream; default: return super.getDictionary(id); } } @Override public void setIntNumber(final int id, final int value){ switch(id){ case PdfDictionary.F: F=value; break; case PdfDictionary.Ff: Ff=value; commandFf(Ff); break; case PdfDictionary.Q: //correct alignment converted to Java value switch(value){ case 0: Q = JTextField.LEFT; break; case 1: Q = JTextField.CENTER; break; case 2: Q = JTextField.RIGHT; break; default: Q = JTextField.LEFT; break; } break; case PdfDictionary.MaxLen: MaxLen=value; break; case PdfDictionary.Rotate://store in MK so works for Annot if(MK==null) { MK = new MKObject(); } //factor in page rotation if(rawRotation==0){ MK.setIntNumber(PdfDictionary.R,value); } else{ int diff=rawRotation-value; if(diff<0) { diff = 360 + diff; } //if(diff!=0) MK.setIntNumber(PdfDictionary.R,diff); } break; case PdfDictionary.SigFlags: SigFlags=value; break; case PdfDictionary.StructParent: StructParent=value; break; case PdfDictionary.TI: TI=value; break; case PdfDictionary.W: W=value; break; case PdfDictionary.Flags: Flags=value; break; default: super.setIntNumber(id, value); } } @Override public int getInt(final int id){ switch(id){ case PdfDictionary.F: return F; case PdfDictionary.Ff: return Ff; case PdfDictionary.MaxLen: return MaxLen; case PdfDictionary.Q: return Q; case PdfDictionary.SigFlags: return SigFlags; case PdfDictionary.StructParent: return StructParent; case PdfDictionary.TI: return TI; case PdfDictionary.W: return W; case PdfDictionary.Flags: return Flags; default: return super.getInt(id); } } @Override public void setDictionary(final int id, final PdfObject value){ value.setID(id); //if in AP array as other value store here if(currentKey!=null){ //System.out.println("Other values---- "+id+" "+value+" "+objType); setOtherValues(value); return; } switch(id){ case PdfDictionary.A: A=value; break; case PdfDictionary.AA: AA=value; break; case PdfDictionary.AP: AP=value; //copy across if(MK==null && AP!=null && AP.getDictionary(PdfDictionary.N)!=null) { MK = AP.getDictionary(PdfDictionary.N).getDictionary(PdfDictionary.MK); } break; case PdfDictionary.BI: BI=value; break; case PdfDictionary.Bl: Bl=value; break; case PdfDictionary.BS: BS=value; break; case PdfDictionary.C: Cdict=value; break; //case PdfDictionary.C2: //C2=value; //break; case PdfDictionary.D: D=value; break; case PdfDictionary.DC: DC=value; break; case PdfDictionary.DP: DP=value; break; case PdfDictionary.DR: DR=value; break; case PdfDictionary.DS: DS=value; break; case PdfDictionary.E: E=value; break; case PdfDictionary.F: Fdict=value; break; case PdfDictionary.Fo: Fo=value; break; case PdfDictionary.FS: FS=value; break; case PdfDictionary.IF: IF=value; break; case PdfDictionary.IRT: IRT=value; break; case PdfDictionary.JS: JS=value; break; case PdfDictionary.K: K=value; break; //case PdfDictionary.I: //I=value; //break; case PdfDictionary.MK: MK=value; break; case PdfDictionary.N: Nobj=value; break; case PdfDictionary.Next: Next=value; break; case PdfDictionary.O: O=value; break; case PdfDictionary.OC: OC=value; break; case PdfDictionary.Off: Off=value; break; case PdfDictionary.On: On=value; break; case PdfDictionary.P: P=value; break; case PdfDictionary.PC: PC=value; break; case PdfDictionary.PI: PI=value; break; case PdfDictionary.PO: PO=value; break; case PdfDictionary.Popup: Popup=value; break; case PdfDictionary.PV: PV=value; break; case PdfDictionary.R: R=value; break; case PdfDictionary.RichMediaContent: RichMediaContent=value; break; case PdfDictionary.Sig: Sig=value; break; case PdfDictionary.Sound: Sound=value; break; case PdfDictionary.U: U=value; break; case PdfDictionary.V: V=value; break; case PdfDictionary.Win: Win=value; break; case PdfDictionary.WP: WP=value; break; case PdfDictionary.WS: WS=value; break; case PdfDictionary.X: X=value; break; case PdfDictionary.XFA: XFAasStream=value; break; default: super.setDictionary(id, value); } } @Override public int setConstant(final int pdfKeyType, final int keyStart, final int keyLength, final byte[] raw) { int PDFvalue =PdfDictionary.Unknown; int id=0,x=0,next; try{ //convert token to unique key which we can lookup for(int i2=keyLength-1;i2>-1;i2--){ next=raw[keyStart+i2]; //System.out.println((char)next); next -= 48; id += ((next)<6 && data[6]=='+'){ //lose ABCDEF+ if present final int length=len-7; final byte[] newData=new byte[length]; System.arraycopy(data, 7, newData, 0, length); return new String(newData); }else { return new String(data); } }else { return null; } default: throw new RuntimeException("Value not defined in getName(int,mode) in "+this); } } @Override public byte[][] getKeyArray(final int id) { switch(id){ case PdfDictionary.Kids: return deepCopy(Kids); default: return super.getKeyArray(id); } } @Override public void setKeyArray(final int id, final byte[][] value) { switch(id){ case PdfDictionary.Kids: Kids=value; break; default: super.setKeyArray(id, value); } } @Override public boolean decompressStreamWhenRead() { return true; } /** * read and setup the form flags for the Ff entry * field is the data to be used to setup the Ff flags */ protected void commandFf(final int flagValue) { /**use formObject.flags * to get flags representing field preferences the following are accessed by array address (bit position -1) * * bit positions * all * 1=readonly - if set there is no interaction * 2=required - if set the field must have a value when submit-form-action occures * 3=noexport - if set the field must not be exported by a submit-form-action * * Choice fields * 18=combo - set its a combobox, else a list box * 19=edit - defines a comboBox to be editable * 20=sort - defines list to be sorted alphabetically * 22=multiselect - if set more than one items can be selected, else only one * 23=donotspellcheck - (only used on editable combobox) don't spell check * 27=commitOnselchange - if set commit the action when selection changed, else commit when user exits field * * text fields * 13=multiline - uses multipul lines else uses a single line * 14=password - a password is intended * 21=fileselect -text in field represents a file pathname to be submitted * 23=donotspellcheck - don't spell check * 24=donotscroll - once the field is full don't enter anymore text. * 25=comb - (only if maxlen is present, (multiline, password and fileselect are CLEAR)), the text is justified across the field to MaxLen * 26=richtext - use richtext format specified by RV entry in field dictionary * * button fields * 15=notoggletooff - (use in radiobuttons only) if set one button must always be selected * 16=radio - if set is a set of radio buttons * 17=pushbutton - if set its a push button * if neither 16 nor 17 its a check box * 26=radiosinunison - if set all radio buttons with the same on state are turned on and off in unison (same behaviour as html browsers) */ //System.out.println("flag value="+flag); flags = new boolean[32]; /**/ flags[READONLY_ID] = (flagValue & READONLY_BIT) == READONLY_BIT; flags[REQUIRED_ID] = (flagValue & REQUIRED_BIT) == REQUIRED_BIT; flags[NOEXPORT_ID] = (flagValue & NOEXPORT_BIT) == NOEXPORT_BIT; flags[MULTILINE_ID] = (flagValue & MULTILINE_BIT) == MULTILINE_BIT; flags[PASSWORD_ID] = (flagValue & PASSWORD_BIT) == PASSWORD_BIT; flags[NOTOGGLETOOFF_ID] = (flagValue & NOTOGGLETOOFF_BIT) == NOTOGGLETOOFF_BIT; flags[RADIO_ID] = (flagValue & RADIO_BIT) == RADIO_BIT; flags[PUSHBUTTON_ID] = (flagValue & PUSHBUTTON_BIT) == PUSHBUTTON_BIT; flags[COMBO_ID] = (flagValue & COMBO_BIT) == COMBO_BIT; flags[EDIT_ID] = (flagValue & EDIT_BIT) == EDIT_BIT; flags[SORT_ID] = (flagValue & SORT_BIT) == SORT_BIT; flags[FILESELECT_ID] = (flagValue & FILESELECT_BIT) == FILESELECT_BIT; flags[MULTISELECT_ID] = (flagValue & MULTISELECT_BIT) == MULTISELECT_BIT; flags[DONOTSPELLCHECK_ID] = (flagValue & DONOTSPELLCHECK_BIT) == DONOTSPELLCHECK_BIT; flags[DONOTSCROLL_ID] = (flagValue & DONOTSCROLL_BIT) == DONOTSCROLL_BIT; flags[COMB_ID] = (flagValue & COMB_BIT) == COMB_BIT; flags[RICHTEXT_ID] = (flagValue & RICHTEXT_BIT) == RICHTEXT_BIT;//same as RADIOINUNISON flags[RADIOINUNISON_ID] = (flagValue & RADIOINUNISON_BIT) == RADIOINUNISON_BIT;//same as RICHTEXT flags[COMMITONSELCHANGE_ID] = (flagValue & COMMITONSELCHANGE_BIT) == COMMITONSELCHANGE_BIT; } /** * takes a value, and turns it into the color it represents * e.g. (0.5) represents gray (127,127,127) * grey = array length 1, with one value * rgb = array length 3, in the order of red,green,blue * cmyk = array length 4, in the reverse order, (ie. k, y, m, c) */ public static Color generateColor(final float[] toks) { // 0=transparant // 1=gray // 3=rgb // 4=cmyk int i=-1; if(toks!=null) { i = toks.length; } Color newColor = null; if(i==0){ //LogWriter.writeFormLog("{stream} CHECK transparent color",debugUnimplemented); newColor = new Color(0,0,0,0);//if num of tokens is 0 transparant, fourth variable my need to be 1 }else if(i==1){ final float tok0 = toks[0]; if(tok0<=1){ newColor = new Color(tok0,tok0,tok0); }else { newColor = new Color((int)tok0,(int)tok0,(int)tok0); } }else if(i==3){ if(debug) { System.out.println("rgb color=" + toks[0] + ' ' + toks[1] + ' ' + toks[2]); } final float tok0 = toks[0]; final float tok1 = toks[1]; final float tok2 = toks[2]; if(tok0<=1 && tok1<=1 && tok2<=1){ newColor = new Color(tok0,tok1,tok2); }else { newColor = new Color((int)tok0,(int)tok1,(int)tok2); } }else if(i==4){ final DeviceCMYKColorSpace cs=new DeviceCMYKColorSpace(); cs.setColor(new float[]{toks[3],toks[2],toks[1],toks[0]},4); newColor =(Color) cs.getColor(); } return newColor; } /** * returns true if this formObject represents an XFAObject */ public boolean isXFAObject(){ return isXFAObject; } @Override public PdfObject duplicate() { final FormObject newObject = new FormObject(); //newObject.formHandler=formHandler; //String newObject.AS = AS; newObject.contents = contents; newObject.Cert=Cert; newObject.ContactInfo = ContactInfo; newObject.contents = contents; newObject.Contents = Contents; newObject.DA=DA; newObject.Dstring=Dstring; newObject.DV=DV; newObject.Filter=Filter; newObject.Fstring=Fstring; newObject.H=H; newObject.JSString=JSString; newObject.layerName=layerName; newObject.Location=Location; newObject.M=M; newObject.N=N; newObject.NM=NM; newObject.normalOnState=normalOnState; //parentRef DO NOT SET newObject.Pstring=Pstring; newObject.ref = ref; newObject.RC=RC; newObject.Reason=Reason; newObject.S=S; newObject.selectedItem = selectedItem; newObject.SubFilter=SubFilter; newObject.Subj=Subj; newObject.T=T; newObject.TM=TM; newObject.TU=TU; newObject.textString = textString; newObject.URI=URI; newObject.Vstring=Vstring; //int newObject.F=F; newObject.Ff=Ff; newObject.formType=formType; newObject.FT=FT; newObject.MaxLen=MaxLen; newObject.pageNumber = pageNumber; newObject.popupFlag=popupFlag; newObject.Q=Q; newObject.rawRotation=rawRotation; newObject.SigFlags=SigFlags; newObject.StructParent=StructParent; newObject.textSize = textSize; newObject.TI=TI; newObject.W=W; //boolean newObject.appearancesUsed = appearancesUsed; newObject.offsetDownIcon = offsetDownIcon; newObject.noDownIcon = noDownIcon; newObject.invertDownIcon = invertDownIcon; newObject.show = show; newObject.H_Boolean=H_Boolean; newObject.NeedAppearances=NeedAppearances; newObject.isXFAObject=isXFAObject; newObject.Open=Open; //Font newObject.textFont = textFont; newObject.fontName = fontName; //Color newObject.cColor = cColor; //String[] newObject.OptString = (OptString==null) ? null : OptString.clone(); //boolean[] newObject.flags = flags==null ? null : flags.clone(); newObject.Farray=Farray==null ? null : Farray.clone(); //int[] newObject.selectionIndices = selectionIndices==null ? null : selectionIndices.clone(); //float[] newObject.C=C==null ? null : C.clone(); newObject.InkList=InkList==null ? null : InkList.clone(); newObject.QuadPoints=QuadPoints==null ? null : QuadPoints.clone(); newObject.Rect=Rect==null ? null : Rect.clone(); newObject.RD=RD==null ? null : RD.clone(); newObject.textColor = textColor==null ? null : textColor.clone(); //PdfObject newObject.A=A.duplicate(); newObject.AA=AA.duplicate(); newObject.AP=AP.duplicate(); newObject.BS=BS.duplicate(); newObject.BI=BI.duplicate(); newObject.Bl=Bl.duplicate(); newObject.Cdict=Cdict.duplicate(); newObject.D=D.duplicate(); newObject.DC=DC.duplicate(); newObject.DP=DP.duplicate(); newObject.DS=DS.duplicate(); newObject.E=E.duplicate(); newObject.Fdict=Fdict.duplicate(); newObject.Fo=Fo.duplicate(); newObject.FS=FS.duplicate(); newObject.IF=IF.duplicate(); newObject.JS=JS.duplicate(); newObject.K=K.duplicate(); newObject.MK=MK.duplicate(); newObject.Next=Next.duplicate(); newObject.Nobj=Nobj.duplicate(); newObject.O=O.duplicate(); newObject.OC=OC.duplicate(); newObject.Off=Off.duplicate(); newObject.On=On.duplicate(); newObject.P=P.duplicate(); //parentPdfObject Do NOT SET OR WE RECURSE INFINATLY newObject.PC=PC.duplicate(); newObject.PI=PI.duplicate(); newObject.PO=PO.duplicate(); newObject.Popup=Popup.duplicate(); newObject.PV=PV.duplicate(); newObject.R=R.duplicate(); newObject.Sig=Sig.duplicate(); newObject.Sound=Sound.duplicate(); newObject.U=U.duplicate(); newObject.V=V.duplicate(); newObject.Win=Win.duplicate(); newObject.WP=WP.duplicate(); newObject.WS=WS.duplicate(); newObject.X=X.duplicate(); newObject.XFAasStream=XFAasStream.duplicate(); //Object[] newObject.CO=CO==null ? null : CO.clone(); newObject.Opt=Opt==null ? null : Opt.clone(); newObject.Reference=Reference==null ? null : Reference.clone(); //byte[] newObject.rawAS=rawAS==null ? null : rawAS.clone(); newObject.rawCert=rawCert==null ? null : rawCert.clone(); newObject.rawContactInfo=rawContactInfo==null ? null : rawContactInfo.clone(); newObject.rawContents=rawContents==null ? null : rawContents.clone(); newObject.rawDA=rawDA==null ? null : rawDA.clone(); newObject.rawDstring=rawDstring==null ? null : rawDstring.clone(); newObject.rawDV=rawDV==null ? null : rawDV.clone(); newObject.rawEOPROPtype=rawEOPROPtype==null ? null : rawEOPROPtype.clone(); newObject.rawFilter=rawFilter==null ? null : rawFilter.clone(); newObject.rawFstring=rawFstring==null ? null : rawFstring.clone(); newObject.rawH=rawH==null ? null : rawH.clone(); newObject.rawJS=rawJS==null ? null : rawJS.clone(); newObject.rawLocation=rawLocation==null ? null : rawLocation.clone(); newObject.rawM=rawM==null ? null : rawM.clone(); newObject.rawN=rawN==null ? null : rawN.clone(); newObject.rawNM=rawNM==null ? null : rawNM.clone(); newObject.rawPstring=rawPstring==null ? null : rawPstring.clone(); newObject.rawRC=rawRC==null ? null : rawRC.clone(); newObject.rawReason=rawReason==null ? null : rawReason.clone(); newObject.rawS=rawS==null ? null : rawS.clone(); newObject.rawSubFilter=rawSubFilter==null ? null : rawSubFilter.clone(); newObject.rawSubj=rawSubj==null ? null : rawSubj.clone(); newObject.rawT=rawT==null ? null : rawT.clone(); newObject.rawTM=rawTM==null ? null : rawTM.clone(); newObject.rawTU=rawTU==null ? null : rawTU.clone(); newObject.rawURI=rawURI==null ? null : rawURI.clone(); newObject.rawV=rawV==null ? null : rawV.clone(); newObject.rawX=rawX==null ? null : rawX.clone(); //byte[][] newObject.Border = (Border==null ? null : ObjectCloneFactory.cloneDoubleArray(Border)); newObject.DmixedArray = (DmixedArray==null ? null : ObjectCloneFactory.cloneDoubleArray(DmixedArray)); newObject.Fields = (Fields==null ? null : ObjectCloneFactory.cloneDoubleArray(Fields)); newObject.rawXFAasArray=rawXFAasArray==null ? null : ObjectCloneFactory.cloneDoubleArray(rawXFAasArray); newObject.State=State==null ? null : ObjectCloneFactory.cloneDoubleArray(State); //BUfferedImage newObject.normalOffImage = ObjectCloneFactory.deepCopy(normalOffImage); newObject.normalOnImage = ObjectCloneFactory.deepCopy(normalOnImage); newObject.rolloverOffImage = ObjectCloneFactory.deepCopy(rolloverOffImage); newObject.rolloverOnImage = ObjectCloneFactory.deepCopy(rolloverOnImage); newObject.downOffImage = ObjectCloneFactory.deepCopy(downOffImage); newObject.downOnImage = ObjectCloneFactory.deepCopy(downOnImage); //Map newObject.OptValues = ObjectCloneFactory.cloneMap(OptValues); return newObject; } /** overwrites all the values on this form with any values from the parent*/ public void copyInheritedValuesFromParent(final FormObject parentObj) { if(parentObj==null) { return; } if(pageNumber==-1 && parentObj.pageNumber!=-1) { pageNumber = parentObj.pageNumber; } //formHandler=parentObj.formHandler; //byte[] if(rawAS==null) { rawAS = parentObj.rawAS; } if(rawDA==null) { rawDA = parentObj.rawDA; } if(rawDV==null) { rawDV = parentObj.rawDV; } if(rawJS==null) { rawJS = parentObj.rawJS; } if(rawNM==null) { rawNM = parentObj.rawNM; } if(rawTM==null) { rawTM = parentObj.rawTM; } if(rawTU==null) { rawTU = parentObj.rawTU; } if(rawV==null) { rawV = parentObj.rawV; } //before we copy the fieldName make sure the parent values are valid if(parentObj.T==null && parentObj.rawT!=null){ parentObj.T= StringUtils.getTextString(parentObj.rawT, false); } //copy fieldname, making sure to keep it fully qualified if(parentObj.T!=null) { if(T==null && rawT!=null) { T = StringUtils.getTextString(rawT, false); } if(T!=null && //make sure the parent name has not already been added to the name !T.contains(parentObj.T)){ T = parentObj.T+ '.' +T; rawT = StringUtils.toBytes(T); }//else we should already have the right name //NOTE dont just pass parent T and rawT values through as we read them vis getTextStreamValue(T) if needed } //PdfObject if(A==null) { A = parentObj.A; } if(AA==null) { AA = parentObj.AA; } if(AP==null) { AP = parentObj.AP; } if(D==null) { D = parentObj.D; } if(OC==null) { OC = parentObj.OC; } //float[] if(C==null) { C = (parentObj.C == null) ? null : parentObj.C.clone(); } if(QuadPoints==null) { QuadPoints = (parentObj.QuadPoints == null) ? null : parentObj.QuadPoints.clone(); } if(InkList==null) { InkList = (parentObj.InkList == null) ? null : parentObj.InkList.clone(); } if(Rect==null) { Rect = (parentObj.Rect == null) ? null : parentObj.Rect.clone(); } //int if(F==-1) { F = parentObj.F; } if(Ff==-1) { Ff = parentObj.Ff; } if(Q==-1) { Q = parentObj.Q; } if(MaxLen==-1) { MaxLen = parentObj.MaxLen; } if(FT==-1) { FT = parentObj.FT; } if(TI==-1) { TI = parentObj.TI; } //boolean[] if(flags==null) { flags = (parentObj.flags == null) ? null : parentObj.flags.clone(); } //Object[] if(Opt==null) { Opt = (parentObj.Opt == null) ? null : parentObj.Opt.clone(); } if(CO==null) { CO = (parentObj.CO == null) ? null : parentObj.CO.clone(); } //String if(textString==null) { textString = parentObj.textString; } if(OptString==null) { OptString = parentObj.OptString; } if(selectedItem==null) { selectedItem = parentObj.selectedItem; } } /** * returns the alignment (Q) */ public int getAlignment(){ if(Q==-1) { Q = JTextField.LEFT; } return Q; } /** * sets the text color for this form * */ public void setTextColor(float[] color) { //JS made public so that javascript can access it //check if is javascript and convert to our float if(color.length>0 && Float.isNaN(color[0])){//not-a-number final float[] tmp = new float[color.length-1]; System.arraycopy(color, 1, tmp, 0, color.length-1); color = tmp; } textColor = color; } /** * set the text font for this form */ public void setFontName(final String font) { fontName = font; } /** * set the text font for this form */ public void setTextFont(final Font font) { textFont = font; } /** * sets the text size for this form */ public void setTextSize(final int size) { textSize = size; } /** * sets the text value */ public void setTextValue(String text) { //use empty string so that the raw pdf value does not get recalled. if(text==null) { text = ""; } updateValue(text,false,true); } /** * sets the selected item * only applicable to the choices fields */ public void setSelection(final Object[] selectedValues, final String curValue, final int[] indices, final int index) { if(index!=selectionIndex){ this.selectedValues= selectedValues; selectedItem = curValue; selectionIndex=index; selectionIndices=indices; if (guiComp != null) { updateCombo(); } } } /** * sets the field name for this field (used by XFA) */ public void setFieldName(final String field) { T=null; //ensure we sync to low level value this.setTextStreamValue(PdfDictionary.T,StringUtils.toBytes(field)); } /** * sets the parent for this field */ public void setParent(final String parent) { setParent(parent,null,false); } /** sets the parent string for this field and stores the parent PDFObject passed * in to be accessed locally and from getParent() * BEWARE :- this method will copy all relevent values from the parent is copyValuesFromParent is true */ public void setParent(final String parent, final FormObject parentObj, final boolean copyValuesFromParent){ if(copyValuesFromParent){ //copy all values from the parent here, then they can be overwritten in future. copyInheritedValuesFromParent(parentObj); } this.parentRef = parent; if(parentObj!=null){ this.parentPdfObj = parentObj; } } public PdfObject getParentPdfObj(){ return parentPdfObj; } public void setParentPdfObj(final PdfObject parent){ parentPdfObj=parent; } /** * gets the parent for this field */ public String getParentRef() { //option to take from file as well if(parentRef==null && includeParent) { return getStringKey(PdfDictionary.Parent); } else { return parentRef; } } /** * return the characteristic type */ private static boolean[] calcFarray(final int flagValue) { if(flagValue==0) { return new boolean[10]; } final boolean[] Farray=new boolean[10]; final int[] pow={0,1,2,4,8,16,32,64,128,256,512}; for(int jj=1;jj<10;jj++){ if(((flagValue & pow[jj])==pow[jj])) { Farray[jj - 1] = true; } } return Farray; } /** * This method should be called only in tabbing functionality * @return */ public Rectangle2D getBounding2DRectangleForTabbing(){ final float[] coords=getFloatArray(PdfDictionary.Rect); if(coords!=null){ float x1=coords[0],y1=coords[1],x2=coords[2],y2=coords[3]; if(x1>x2){ final float tmp = x1; x1 = x2; x2 = tmp; } if(y1>y2){ final float tmp = y1; y1 = y2; y2 = tmp; } final double ix1 = (double)x1; //truncates to ensure form area fully contained final double iy1 = (double)y1; final double ix2 = x2 + ((x2 - x2 > 0) ? 1 : 0); final double iy2 = y2 + ((y2 - y2 > 0) ? 1 : 0); return new Rectangle2D.Double(ix1,iy1,ix2-ix1,iy2-iy1); } if(currentLocation!=null){ BBox.x += currentLocation.x; BBox.y += -currentLocation.y; } return BBox; } /** * return the bounding rectangle for this object */ public Rectangle getBoundingRectangle(){ final float[] coords=getFloatArray(PdfDictionary.Rect); if(coords!=null){ float x1=coords[0],y1=coords[1],x2=coords[2],y2=coords[3]; if(x1>x2){ final float tmp = x1; x1 = x2; x2 = tmp; } if(y1>y2){ final float tmp = y1; y1 = y2; y2 = tmp; } final int ix1 = (int)x1; //truncates to ensure form area fully contained final int iy1 = (int)y1; final int ix2 = (int)x2 + ((x2 - (int)x2 > 0) ? 1 : 0); //Always rounds up to ensure form area fully contained final int iy2 = (int)y2 + ((y2 - (int)y2 > 0) ? 1 : 0); BBox = new Rectangle(ix1,iy1,ix2-ix1,iy2-iy1); } // else // return BBox;//BBox = new Rectangle(0,0,0,0); if(currentLocation!=null){ BBox.x += currentLocation.x; BBox.y += -currentLocation.y; } return BBox; } /** * sets the type this form specifies */ public void setType(final int type, final boolean isXFA) { if(isXFA) { FT = type; } } /** * sets the flag pos to value of flag */ public void setFlag(final int pos, final boolean flag) { //@chris xfa this needs fixing, all references set wrong flag. if(flags==null){ flags = new boolean[32]; } flags[pos] = flag; } /** * returns the flags array (Ff in PDF) (indexs are the number listed) * * all *
1=readonly - if set there is no interaction *
2=required - if set the field must have a value when submit-form-action occures *
3=noexport - if set the field must not be exported by a submit-form-action *
*
Choice fields *
18=combo - set its a combobox, else a list box *
19=edit - defines a comboBox to be editable *
20=sort - defines list to be sorted alphabetically *
22=multiselect - if set more than one items can be selected, else only one *
23=donotspellcheck - (only used on editable combobox) don't spell check *
27=commitOnselchange - if set commit the action when selection changed, else commit when user exits field *
*
text fields *
13=multiline - uses multipul lines else uses a single line *
14=password - a password is intended *
21=fileselect -text in field represents a file pathname to be submitted *
23=donotspellcheck - don't spell check *
24=donotscroll - once the field is full don't enter anymore text. *
25=comb - (only if maxlen is present, (multiline, password and fileselect are CLEAR)), the text is justified across the field to MaxLen *
26=richtext - use richtext format specified by RV entry in field dictionary *
*
button fields *
15=notoggletooff - (use in radiobuttons only) if set one button must always be selected *
16=radio - if set is a set of radio buttons *
17=pushbutton - if set its a push button, * if neither 16 nor 17 its a check box *
26=radiosinunison - if set all radio buttons with the same on state are turned on and off in unison (same behaviour as html browsers) */ public boolean[] getFieldFlags() {//otherwise known as Ff flags if(flags==null) { flags = new boolean[32]; } return flags; } /** set the state which is defined as the On state for this form *
usually different for each child so that the selected child can be found by the state */ public void setNormalOnState(final String state){ normalOnState = state; } /** * @return whether or not appearances are used in this field */ public boolean isAppearanceUsed(){ return appearancesUsed; } public void setAppreancesUsed(final boolean used){ appearancesUsed = used; } /** * sets the image *
images are one of R rollover, N normal, D down and Off unselected, On selected *
for Normal selected the normal on state should also be set */ public void setAppearanceImage(BufferedImage image, final int imageType, final int status) { if(image==null) //if null use opaque image { image = getOpaqueImage(); } switch(imageType){ case PdfDictionary.D: if(status==PdfDictionary.On){ downOnImage = image; }else if(status==PdfDictionary.Off){ downOffImage = image; }else { throw new RuntimeException("Unknown status use PdfDictionary.On or PdfDictionary.Off"); } break; case PdfDictionary.N: if(status==PdfDictionary.On){ normalOnImage = image; }else if(status==PdfDictionary.Off){ normalOffImage=image; }else { throw new RuntimeException("Unknown status use PdfDictionary.On or PdfDictionary.Off"); } break; case PdfDictionary.R: if(status==PdfDictionary.On){ rolloverOnImage = image; }else if(status==PdfDictionary.Off){ rolloverOffImage=image; }else { throw new RuntimeException("Unknown status use PdfDictionary.On or PdfDictionary.Off"); } break; default: throw new RuntimeException("Unknown type use PdfDictionary.D, PdfDictionary.N or PdfDictionary.R"); } appearancesUsed=true; } /** * sets the border color */ public void setBorderColor(final String nextField) { if(nextField!=null) { getDictionary(PdfDictionary.MK).setFloatArray(PdfDictionary.BC, generateFloatFromString(nextField)); } } /** * sets the background color for this form */ public void setBackgroundColor(final String nextField) { if(nextField!=null) { getDictionary(PdfDictionary.MK).setFloatArray(PdfDictionary.BG, generateFloatFromString(nextField)); } } /** * takes a String colorString, and turns it into the color it represents * e.g. (0.5) represents gray (127,127,127) * cmyk = 4 tokens in the order c, m, y, k */ private static float[] generateFloatFromString(final String colorString) { // 0=transparant // 1=gray // 3=rgb // 4=cmyk if(debug) { System.out.println("CHECK generateColorFromString=" + colorString); } final StringTokenizer tokens = new StringTokenizer(colorString,"[()] ,"); final float[] toks = new float[tokens.countTokens()]; int i=0; while(tokens.hasMoreTokens()){ final String tok = tokens.nextToken(); if(debug) { System.out.println("token" + (i + 1) + '=' + tok + ' ' + colorString); } toks[i] = Float.parseFloat(tok); i++; } if(i==0) { return null; } else { return toks; } } /** * sets the normal caption for this form */ public void setNormalCaption(final String caption) { if(caption!=null){ getDictionary(PdfDictionary.MK).setTextStreamValue(PdfDictionary.CA, StringUtils.toBytes(caption)); } } /** * sets whether there should be a down looking icon */ protected void setOffsetDownApp() { offsetDownIcon = true; } /** * sets whether a down icon should be used */ protected void setNoDownIcon() { noDownIcon = true; } /** * sets whether to invert the normal icon for the down icon */ protected void setInvertForDownIcon() { invertDownIcon = true; } /** * returns to rotation of this field object, * currently in stamp annotations only * * deprecated use formObject.getDictionary(PdfDictionary.MK).getInt(PdfDictionary.R); * public int getRotation(){ return getDictionary(PdfDictionary.MK).getInt(PdfDictionary.R); }/**/ /** * returns true if has normal of image */ public boolean hasNormalOff() { return normalOffImage!=null; } /** * returns true if has rollover off image */ public boolean hasRolloverOff() { return rolloverOffImage!=null; } /** * returns true if has down off image */ public boolean hasDownOff() { return downOffImage!=null; } /** * returns true if has one or more down images set */ public boolean hasDownImage() { return (downOnImage!=null || hasDownOff()); } /** copy all values from form to this FormObject * WARNING overrites current data, so shoudl be called before the rest of the form is setup. */ public void overwriteWith(final FormObject form) { if (form == null) { return; } if (form.parentRef != null) { parentRef = form.parentRef; } if (form.flags != null) { flags = form.flags.clone(); } if (form.selectionIndices != null) { selectionIndices = form.selectionIndices.clone(); } if (form.selectedItem != null) { selectedItem = form.selectedItem; } if (form.ref != null) { ref = form.ref; } if (form.textColor != null) { textColor = form.textColor.clone(); } if (form.textFont != null) { textFont = form.textFont; } if (form.textSize != -1) { textSize = form.textSize; } if (form.textString!=null) { textString = form.textString; } if (form.appearancesUsed) { appearancesUsed = form.appearancesUsed; } if (form.offsetDownIcon) { offsetDownIcon = form.offsetDownIcon; } if (form.noDownIcon) { noDownIcon = form.noDownIcon; } if (form.invertDownIcon) { invertDownIcon = form.invertDownIcon; } if (form.normalOffImage != null) { normalOffImage = form.normalOffImage; } if (form.normalOnImage != null) { normalOnImage = form.normalOnImage; } if (form.rolloverOffImage != null) { rolloverOffImage = form.rolloverOffImage; } if (form.rolloverOnImage != null) { rolloverOnImage = form.rolloverOnImage; } if (form.downOffImage != null) { downOffImage = form.downOffImage; } if (form.downOnImage != null) { downOnImage = form.downOnImage; } if (form.pageNumber != -1) { pageNumber = form.pageNumber; } //annotations if (form.cColor != null) { cColor = form.cColor; } if (form.contents != null) { contents = form.contents; } if (form.show) { show = form.show; } //?? cloning AA=form.AA; AP=form.AP; BS=form.BS; D=form.D; OC=form.OC; C=(form.C==null) ? null : form.C.clone(); QuadPoints=(form.QuadPoints==null) ? null : form.QuadPoints.clone(); InkList=(form.InkList==null) ? null : form.InkList.clone(); F=form.F; Ff=form.Ff; CO=(form.CO==null) ? null : form.CO.clone(); Opt=(form.Opt==null) ? null : form.Opt.clone(); Q = form.Q; MaxLen=form.MaxLen; FT=form.FT; rawAS=(form.rawAS==null) ? null : form.rawAS.clone(); rawDA=(form.rawDA==null) ? null : form.rawDA.clone(); rawDV=(form.rawDV==null) ? null : form.rawDV.clone(); rawJS=(form.rawJS==null) ? null : form.rawJS.clone(); rawNM=(form.rawNM==null) ? null : form.rawNM.clone(); rawTM=(form.rawTM==null) ? null : form.rawTM.clone(); rawTU=(form.rawTU==null) ? null : form.rawTU.clone(); rawV=(form.rawV==null) ? null : form.rawV.clone(); //copy fieldname T=form.T; rawT=(form.rawT==null) ? null : form.rawT.clone(); Rect=(form.Rect==null) ? null : form.Rect.clone(); TI=form.TI; MK = (form.MK==null) ? null : (PdfObject)form.MK.clone(); //align any set values this.setSelected(form.isSelected); } /** * @return the characteristics for this field. *
* bit 1 is index 0 in [] * [0] 1 = invisible * [1] 2 = hidden - dont display or print * [2] 3 = print - print if set, dont if not * [3] 4 = nozoom * [4] 5= norotate * [5] 6= noview * [6] 7 = read only (ignored by wiget) * [7] 8 = locked * [8] 9 = togglenoview * as on pdf 1.7 this became 10 bits long * [9] 10 = LockedContents */ public boolean[] getCharacteristics() { //lazy initialisation if(Farray==null){ if(F==-1) { Farray = new boolean[10]; } else { Farray = calcFarray(F); } } return Farray; } /** * @return the default text size for this field */ public int getTextSize() { return textSize; } /** * @return the values map for this field, * map that references the display value from the export values */ public Map getValuesMap(final boolean keyFirst) { if(Opt!=null && OptValues==null){ final Object[] rawOpt=getObjectArray(PdfDictionary.Opt); if(rawOpt!=null){ String key,value; Object[] obj; for (final Object aRawOpt : rawOpt) { if (aRawOpt instanceof Object[]) { //2 items (see p678 in v1.6 PDF ref) obj = (Object[]) aRawOpt; if (keyFirst) { key = StringUtils.getTextString((byte[]) obj[0], false); value = StringUtils.getTextString((byte[]) obj[1], false); } else { key = StringUtils.getTextString((byte[]) obj[1], false); value = StringUtils.getTextString((byte[]) obj[0], false); } if (OptValues == null) { OptValues = new HashMap(); } OptValues.put(key, value); } } } } if(OptValues==null){ return null; }else{ return Collections.unmodifiableMap(OptValues); } } /** * @return the available items for this list or combo */ public String[] getItemsList() { if (OptString == null) { final Object[] rawOpt = getObjectArray(PdfDictionary.Opt); if (rawOpt != null) { final int count = rawOpt.length; OptString = new String[count]; for (int ii = 0; ii < count; ii++) { if (rawOpt[ii] instanceof Object[]) { //2 items (see p678 in v1.6 PDF ref) final Object[] obj = (Object[]) rawOpt[ii]; OptString[ii] = StringUtils.getTextString((byte[]) obj[1], false); } else if (rawOpt[ii] instanceof byte[]) { OptString[ii] = StringUtils.getTextString((byte[]) rawOpt[ii], false); } else if (rawOpt[ii] != null) { // } } } } return OptString; } /** * @return the selected Item for this field */ public String getSelectedItem() { if(selectedItem==null) { selectedItem = getTextStreamValue(PdfDictionary.V); } //if no value yet set but selection, use that if(selectedItem==null && selectionIndices!=null ){ final String[] items= this.getItemsList(); final int itemSelected=selectionIndices[0]; if(items!=null && itemSelected>-1 && itemSelected } } /**oldJs * defines the thickness of the border when stroking. */ public void setLineWidth(final int lineWidth){ if(BS==null) { BS = new FormObject(); } BS.setIntNumber(PdfDictionary.W, lineWidth); } /**oldJs * added for backward compatibility or old adobe files. */ public void setBorderWidth(final int width){ setLineWidth(width); } /** * Allows the user to set an offset for form components * This is mainly used for movable form components such as text popups * * @param offset : The offset from the components location from the pdf */ public void setUserSetOffset(final Point offset){ if(currentLocation==null){ currentLocation = new Point(); } currentLocation.x = (int)((offset.x / currentScaling)); currentLocation.y = (int)((offset.y / currentScaling)); } /** * Set the scaling for the formObject * this is only used for the locations of forms that can move * such as Text Popups * @param scale : Current scaling to be used */ public void setCurrentScaling(final float scale){ currentScaling = scale; } public float getCurrentScaling(){ return currentScaling; } /**oldJS * JS returns the normal caption associated to this button */ public String buttonGetCaption(){ return buttonGetCaption(0); } /**oldJS * returns the caption associated with this button, * @param nFace - * 0 normal caption (default) * 1 down caption * 2 rollover caption */ public String buttonGetCaption(final int nFace){ switch(nFace){ case 1: return getDictionary(PdfDictionary.MK).getTextStreamValue(PdfDictionary.AC); case 2: return getDictionary(PdfDictionary.MK).getTextStreamValue(PdfDictionary.RC); default: return getDictionary(PdfDictionary.MK).getTextStreamValue(PdfDictionary.CA); } } /**oldJS * sets this buttons normal caption to cCaption */ public void buttonSetCaption(final String cCaption){ buttonSetCaption(cCaption,0);} /**oldJS * sets this buttons caption to cCaption, it sets the caption defined by nFace. * @param nFace - * 0 (default) normal caption * 1 down caption * 2 rollover caption */ public void buttonSetCaption(final String cCaption, final int nFace){ switch(nFace){ case 1: getDictionary(PdfDictionary.MK).setTextStreamValue(PdfDictionary.AC, StringUtils.toBytes(cCaption)); break; case 2: getDictionary(PdfDictionary.MK).setTextStreamValue(PdfDictionary.RC, StringUtils.toBytes(cCaption)); break; default: getDictionary(PdfDictionary.MK).setTextStreamValue(PdfDictionary.CA, StringUtils.toBytes(cCaption)); } } /**oldJS * returns the background color for the annotation objects */ public Object getfillColor(){ return generateColor(getDictionary(PdfDictionary.MK).getFloatArray(PdfDictionary.BG)); } /**oldJS * sets our background color to the color specified */ public void setfillColor(float[] newColor){ if(newColor!=null){ if(newColor.length>0 && Float.isNaN(newColor[0])){//not-a-number final float[] tmp = new float[newColor.length-1]; System.arraycopy(newColor, 1, tmp, 0, newColor.length-1); newColor = tmp; } getDictionary(PdfDictionary.MK).setFloatArray(PdfDictionary.BG, newColor); } } /** oldJS * sets the fillcolor, or background color using the string defined from javascript rhino parser */ public void setfillColor(final Object newColor){ //added so that the fillColor NativeArray is called, this never seems to be called but //without it the NativeArray one will not work. // //code below should work if ever called. if(newColor!=null){ //convert javascript string to the appropriate color final float[] color = DisplayJavascriptActions.convertToColorFloatArray((String)newColor); //store color in our variable getDictionary(PdfDictionary.MK).setFloatArray(PdfDictionary.BG, color); } } public void setFormType(final int widgetType) { formType = widgetType; } /** * look at FormFactory.LIST etc for full list of types */ public int getFormType(){ return formType; } /** returns an Opaque BufferedImage for use when appearance Streams are null */ public static BufferedImage getOpaqueImage(){ return new BufferedImage(20,20,BufferedImage.TYPE_INT_ARGB); } public void setGUIComponent(final Object guiComp, final int guiType) { this.guiComp=guiComp; this.guiType = guiType; } public Object getGUIComponent() { return guiComp; } public boolean isReadOnly(){ boolean isReadOnly=false; final boolean[] flags = getFieldFlags(); final boolean[] characteristics = getCharacteristics(); if (((flags != null) && (flags[FormObject.READONLY_ID])) || (characteristics!=null && characteristics[9])//characteristics[9] = LockedContents //p609 PDF ref ver 1-7, characteristics 'locked' flag does allow contents to be edited, //but the 'LockedContents' flag stops content being changed. ){ isReadOnly=true; } return isReadOnly; } /** * allow us to update value (and sync to GUI version if exists */ public void updateValue(final Object value, final boolean isSelected, boolean sync) { if(isReadOnly()) { return; } if(GenericFormFactory.isTextForm(formType)){ textString= (String) value; //stop updating if value unchanged (and stops our legacy code failing in continuous loop if(textString!=null && textString.equals(lastTextString)){ sync=false; } //track last value lastTextString=textString; }else{ textString= (String) value; this.isSelected=isSelected; //stop updating if value unchanged (and stops our legacy code failing in continuous loop if(isSelected!=lastIsSelected && lastTextString!=null && textString!=null && textString.equals(lastTextString)){ sync=false; } //track last value lastTextString=textString; lastIsSelected=isSelected; } /** * update our Swing/ULC component if needed on correct thread */ if((sync && // if(cache!=null){ // cache.put(this.getObjectRefAsString(),value); // } guiType != FormFactory.ULC) &&//stop ULC for the moment! guiComp != null) { syncGUI(value); } } private void syncGUI(final Object value) { if(guiType == FormFactory.SWING){ if (SwingUtilities.isEventDispatchThread()) { setGUI(formType, value, guiComp, guiType); } else { final Runnable doPaintComponent = new Runnable() { @Override public void run() { setGUI(formType, value, guiComp, guiType); } }; SwingUtilities.invokeLater(doPaintComponent); } }else if(guiType == FormFactory.JAVAFX){ setGUI(formType, value, guiComp, guiType); } } private static void setGUI(final int formType, final Object value, final Object guiComp, final int guiType) { try{ if(guiType == FormFactory.JAVAFX){ if(fxSupport!=null){ fxSupport.renderGUIComponent(formType, value,guiComp, guiType); } }else if(guiType == FormFactory.SWING){ if (GenericFormFactory.isTextForm(formType)) { ((JTextComponent) guiComp).setText((String) value); }else if(formType==FormFactory.checkboxbutton){ ((JCheckBox) guiComp).setSelected(Boolean.valueOf((String) value)); }else if (GenericFormFactory.isButtonForm(formType)) { ((JRadioButton) guiComp).setText((String) value); ((JRadioButton) guiComp).setSelected(Boolean.valueOf((String) value)); }else if(formType==FormFactory.annotation && guiComp instanceof JButton){ ((JButton) guiComp).setSelected(Boolean.valueOf((String) value)); } } }catch(final Exception ee){ // if (LogWriter.isOutput()) { LogWriter.writeLog("Caught an Exception " + ee); } } } public boolean isSelected() { return isSelected; } public void setSelected(final boolean setSelected) { this.isSelected= setSelected; if (guiComp != null) { syncGUI(setSelected); } } public int getSelectedIndex() { return selectionIndex; } /** * update value if ComboBox * @param index */ public void setSelectedIndex(final int index){ if(index!=selectionIndex){ selectionIndex=index; selectionIndices=new int[1]; selectionIndices[0]=index; if (guiComp != null) { // Check if it's a JavaFX object, if not than use Swing // Might need to be on FX Thread if(guiType == FormFactory.JAVAFX){ if(fxSupport!=null){ selectedItem=fxSupport.getSelectedItem(guiComp,formType); } }else if (SwingUtilities.isEventDispatchThread()) { if(formType==FormFactory.combobox){ ((JComboBox) guiComp).setSelectedIndex(selectionIndex); selectedItem= (String) ((JComboBox) guiComp).getSelectedItem(); }else{ ((JList) guiComp).setSelectedIndex(selectionIndex); selectedItem= (String) ((JList) guiComp).getSelectedValue(); } } else { final Runnable doPaintComponent = new Runnable() { @Override public void run() { if(formType==FormFactory.combobox){ ((JComboBox) guiComp).setSelectedIndex(selectionIndex); selectedItem= (String) ((JComboBox) guiComp).getSelectedItem(); }else{ ((JList) guiComp).setSelectedIndex(selectionIndex); selectedItem= (String) ((JList) guiComp).getSelectedValue(); } } }; SwingUtilities.invokeLater(doPaintComponent); } } } } /** * update value if ComboBox * * @param value */ public void setSelectedItem(final String value) { selectedItem = value; if (guiComp != null) { updateCombo(); } } private void updateCombo() { if(formType==FormFactory.combobox || formType==FormFactory.list){ if(guiType == FormFactory.JAVAFX){ if(fxSupport!=null){ fxSupport.select(guiComp,selectedItem,formType); } }else if (SwingUtilities.isEventDispatchThread()) { if(formType==FormFactory.combobox){ ((JComboBox) guiComp).setSelectedItem(selectedItem); }else{ ((JList) guiComp).setSelectedValue(selectedItem, true); } } else { final Runnable doPaintComponent = new Runnable() { @Override public void run() { if(formType==FormFactory.combobox){ ((JComboBox) guiComp).setSelectedItem(selectedItem); }else{ ((JList) guiComp).setSelectedValue(selectedItem, true); } } }; SwingUtilities.invokeLater(doPaintComponent); } }else{ throw new RuntimeException("Unexpected type must be FormFactory.combobox or FormFactory.list"); } } private static final float baseFontSize = 12; /** * Method to get the font size to be used in the form component * This is currently only implemented for text pop-up forms * * @return The base size to be used in the form component */ @SuppressWarnings("MethodMayBeStatic") public float getFontSize(){ return baseFontSize; } public Object getFormValue() { final Object retValue; switch(formType){ case FormFactory.checkboxbutton: retValue = isSelected; break; case FormFactory.combobox: retValue = isSelected; break; case FormFactory.list: retValue = selectedValues; break; case FormFactory.radiobutton: retValue = isSelected; break; // case FormFactory.singlelinepassword: // case FormFactory.multilinepassword: // case FormFactory.multilinetext: // case FormFactory.singlelinetext: // // retValue=getTextString(); // // break; default: retValue=getTextString(); break; } return retValue; } /** * used by JS to reset * @return */ public String getLastValidValue() { return validValue; } /** * used by JS to reset */ public void setLastValidValue(final String value) { validValue=value; } public void setPageRotation(final int rotation) { rawRotation=rotation; } public void setVisible(final boolean isVisible) { if (guiComp != null) { if(guiType == FormFactory.JAVAFX){ if(fxSupport!=null){ fxSupport.setVisible(guiComp,isVisible); } }else{ ((JComponent)guiComp).setVisible(isVisible); } } } /** * @return the rotationOriginX */ public int getRotationOriginX() { return rotationOriginX; } /** * @param rotationOriginX the rotationOriginX to set */ public void setRotationOriginX(final int rotationOriginX) { this.rotationOriginX = rotationOriginX; } /** * @return the rotationOriginY */ public int getRotationOriginY() { return rotationOriginY; } /** * set the complete form rotation degree with reserve * value * @param rotationOriginY the rotationOriginY to set */ public void setRotationOriginY(final int rotationOriginY) { this.rotationOriginY = rotationOriginY; } /** * returns the complete form rotation degree with reserve * value * @return the elemRotationDegree */ public int getElemRotationDegree() { return elemRotationDegree; } /** * @param elemRotationDegree the elemRotationDegree to set */ public void setElemRotationDegree(final int elemRotationDegree) { this.elemRotationDegree = elemRotationDegree; } /** * set matte border details * if it is specified in pdf or xfa * @param matteDetails */ public void setMatteBorderDetails(final int[] matteDetails){ this.matteDetails = matteDetails; } /** * Method returns matte border details of * Form (not all surrounding element) * @return */ public int[] getMatteBorderDetails(){ return matteDetails; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy