
org.jpedal.objects.raw.FormObject 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
*
* ---------------
* 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 javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.control.*;
//
import javax.swing.*;
import javax.swing.text.JTextComponent;
import org.jpedal.color.DeviceCMYKColorSpace;
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 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;
}
/** oldJS */
private void setTextColor(final Object jscolor) {
//
//code below should work if ever called.
if(jscolor!=null){
//convert javascript string to the appropriate color
textColor = DisplayJavascriptActions.convertToColorFloatArray((String)jscolor);
}
}
/**
* 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){
if(Platform.isFxApplicationThread()){
setGUI(formType, value, guiComp, guiType);
}else{
Platform.runLater(new Runnable() {
@Override public void run() {
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(GenericFormFactory.isTextForm(formType)){
((TextInputControl)guiComp).setText((String) value);
}else if (formType == FormFactory.checkboxbutton){
((ToggleButton)guiComp).setSelected(Boolean.valueOf((String)value));
}else if(GenericFormFactory.isButtonForm(formType)){
((ToggleButton)guiComp).setText((String)value);
((ToggleButton)guiComp).setSelected(Boolean.valueOf((String)value));
}else if (formType == FormFactory.annotation &&
guiComp instanceof ToggleButton){
((ToggleButton)guiComp).setSelected(Boolean.valueOf((String)value));
}
}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));
}
} else { //ulc
}
}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(formType==FormFactory.combobox){
selectedItem=(String) ((ComboBox)guiComp).getSelectionModel().getSelectedItem();
}else{
selectedItem=(String) ((ListView)guiComp).getSelectionModel().getSelectedItem();
}
}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(formType == FormFactory.combobox){
((ComboBox)guiComp).getSelectionModel().select(selectedItem);
}else{
((ListView)guiComp).getSelectionModel().select(selectedItem);
}
}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){
((Node)guiComp).setVisible(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 - 2025 Weber Informatics LLC | Privacy Policy