org.jpedal.objects.acroforms.AcroRenderer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of OpenViewerFX Show documentation
Show all versions of OpenViewerFX Show documentation
An Open Source JavaFX PDF Viewer
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-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
*
* ---------------
* AcroRenderer.java
* ---------------
*/
package org.jpedal.objects.acroforms;
import java.awt.image.BufferedImage;
import org.jpedal.exception.PdfException;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.objects.*;
import org.jpedal.objects.acroforms.actions.ActionHandler;
import org.jpedal.objects.acroforms.creation.FormFactory;
import org.jpedal.objects.acroforms.utils.FormUtils;
import org.jpedal.objects.raw.*;
import org.jpedal.utils.*;
import java.util.*;
import org.jpedal.external.ExternalHandlers;
import org.jpedal.objects.acroforms.creation.SwingFormCreator;
import org.jpedal.objects.layers.PdfLayerList;
import org.jpedal.parser.*;
/**
* Provides top level to forms handling, assisted by separate classes to
* decode widgets (FormDecoder - default implements Swing set)
* create Form widgets (implementation of FormFactory),
* store and render widgets (GUIData),
* handle Javascript and Actions (Javascript and ActionHandler)
* and support for Signature object
*/
public class AcroRenderer{
FormObject[] Fforms, Aforms;
private PdfObject AcroRes;
private float dpi=72f;
private Object[] CO;
PdfArrayIterator fieldList;
private PdfArrayIterator[] annotList;
/**
* flag to show we ignore forms
*/
private boolean ignoreForms;
private boolean alwaysUseXFA;
/**
* creates all GUI components from raw data in PDF and stores in GUIData instance
*/
public FormFactory formFactory;
/**holder for all data (implementations to support Swing and ULC)*/
public GUIData compData;
/**holds sig object so we can easily retrieve*/
private Set sigObject;
private Map sigKeys; //and allow us to trap multiple if in both Annot and Form
/**
* holds copy of object to access the mediaBox and cropBox values
*/
private PdfPageData pageData;
/**
* number of entries in acroFormDataList, each entry can have a button group of more that one button
* 'A' annot and 'F' form - A is per page, F is total hence 3 variables
*/
private int[] AfieldCount;
private int ATotalCount,FfieldCount;
/**
* number of pages in current PDF document
*/
int pageCount;
/**
* handle on object reader for decoding objects
*/
PdfObjectReader currentPdfFile;
/**
* parses and decodes PDF data into generic data for converting to widgets
*/
FormStream fDecoder;
/**
* handles events like URLS, EMAILS
*/
private ActionHandler formsActionHandler;
/**
* handles Javascript events
*/
private Javascript javascript;
/*flag to show if XFA or FDF*/
boolean hasXFA;
private boolean isContainXFAStream;
/**
* flag to show if we use XFA
*/
private boolean useXFA;
/**
* allow us to differentiate underlying PDF form type
*/
Enum PDFformType;
private SwingFormCreator formCreator;
/**
* used to create version without XFA support in XFA version.
* Should not be used otherwise.
* @param useXFA
*/
public AcroRenderer(){}
public void useXFAIfAvailable(final boolean useXFA) {
this.useXFA=useXFA;
}
/**
* reset handler (must be called Before page opened)
* - null Object resets to default
*/
public void resetHandler(final ActionHandler formsActionHandler, final float dpi, final Javascript javascript) {
this.formsActionHandler=formsActionHandler;
this.dpi=dpi;
this.javascript=javascript;
//pass values down
if (formFactory != null){
formFactory.reset(this.getFormResources(), formsActionHandler,pageData,currentPdfFile);
}
}
/**
* make all components invisible on all pages by removing from Display
*/
public void removeDisplayComponentsFromScreen() {
if(compData!=null) {
compData.removeAllComponentsFromScreen();
}
}
/**
* initialise holders and variables, data structures and get a handle on data object
*
*
*/
public int openFile(int pageCount, final int insetW, final int insetH, final PdfPageData pageData, final PdfObjectReader currentPdfFile, final PdfObject acroObj) {
this.pageCount = pageCount;
// if(newXFACode){
// pageCount = 1000;
// }
this.currentPdfFile = currentPdfFile;
this.pageData = pageData;
compData.flushFormData();
//explicitly flush
sigObject=null;
sigKeys=null;
//track inset on page
compData.setPageData(pageData,insetW,insetH);
if (acroObj == null) {
FfieldCount = 0;
fieldList=null;
} else{
//handle XFA
final PdfObject XFAasStream;
PdfArrayIterator XFAasArray = null;
XFAasStream=acroObj.getDictionary(PdfDictionary.XFA);
if(XFAasStream==null){
XFAasArray=acroObj.getMixedArray(PdfDictionary.XFA);
//empty array
if(XFAasArray!=null && XFAasArray.getTokenCount()==0) {
XFAasArray = null;
}
}
hasXFA= XFAasStream!=null || XFAasArray!=null;
isContainXFAStream = hasXFA;
/**
* now read the fields
**/
fieldList = acroObj.getMixedArray(PdfDictionary.Fields);
CO = acroObj.getObjectArray(PdfDictionary.CO);
if(fieldList!=null){
FfieldCount = fieldList.getTokenCount();
AcroRes=acroObj.getDictionary(PdfDictionary.DR);
if(AcroRes!=null) {
currentPdfFile.checkResolved(AcroRes);
}
}else{
FfieldCount=0;
AcroRes=null;
}
/**
* choose correct decoder for form data
*/
if (hasXFA && useXFA){
processXFAFields(acroObj, currentPdfFile, pageData);
}
//we need to read list if FDF
//or redo list if Legacy XFA
if(!hasXFA) {
resolveIndirectFieldList(false);
}
}
resetContainers(true);
return pageCount;
}
/**
* empty implementation in non-XFA AcroRenderer
*
* @param acroObj1
* @param currentPdfFile1
* @param pageData1
*/
void processXFAFields(final PdfObject acroObj1, final PdfObjectReader currentPdfFile1, final PdfPageData pageData1) {
throw new RuntimeException("This code (processXFAFields) should never be called");
}
void resolveIndirectFieldList(final boolean resolveParents){
//allow for indirect
while(FfieldCount==1){
//may have been read before so reset
fieldList.resetToStart();
final String key=fieldList.getNextValueAsString(false);
final FormObject kidObject = new FormObject(key);
currentPdfFile.readObject(kidObject);
final byte[][] childList =getKid(kidObject, resolveParents);
if(childList==null) {
break;
}
fieldList=new PdfArrayIterator(childList);
FfieldCount = fieldList.getTokenCount();
}
}
/**
* initialise holders and variables and get a handle on data object
*
* Complicated as Annotations stored on a PAGE basis whereas FORMS stored on
* a file basis
*/
public void resetAnnotData(final int insetW, final int insetH, final PdfPageData pageData, final int page,
final PdfObjectReader currentPdfFile, final byte[][] currentAnnotList) {
this.currentPdfFile = currentPdfFile;
this.pageData = pageData;
boolean resetToEmpty = true;
addedMissingPopup = false;
//track inset on page
compData.setPageData(pageData,insetW,insetH);
if (currentAnnotList==null) {
AfieldCount = null;
ATotalCount=0;
if(annotList!=null) {
annotList[page] = null;
}
annotList=null;
}else{
int pageCount=pageData.getPageCount()+1;
if(pageCount<=page) {
pageCount = page + 1;
}
if(annotList==null){
annotList=new PdfArrayIterator[pageCount];
AfieldCount=new int[pageCount];
}else if(page>=annotList.length){
final PdfArrayIterator[] tempList=annotList;
final int[] tempCount=AfieldCount;
AfieldCount=new int[pageCount];
annotList=new PdfArrayIterator[pageCount];
for(int ii=0;ii formsCreated=new HashMap();
//check if we want to flatten forms
final String s = System.getProperty("org.jpedal.flattenForm");
if(s!=null && s.equalsIgnoreCase("true")){
compData.setRasterizeForms(true);
}
/**see if already done*/
if (!compData.hasformsOnPageDecoded(page) || (formsRasterizedForDisplay() && current!=null)) {
/**ensure space for all values*/
compData.initParametersForPage(pageData,page,formFactory,dpi);
/**
* think this needs to be revised, and different approach maybe storing, and reuse if respecified in file,
* need to look at other files to work out solution.
* files :-
* lettreenvoi.pdf page 2+ no next page field
* costena.pdf checkboxes not changable
*
* maybe if its just reset on multipage files
*/
//list of forms done
final Map formsProcessed=new HashMap();
int Acount=0;
if(AfieldCount!=null && AfieldCount.length>page) {
Acount = AfieldCount[page];
}
Fforms = new FormObject[FfieldCount];
FormObject[] xfaFormList = null;
Aforms = new FormObject[Acount];
FormObject formObject;
String objRef;
int i, count;
if(hasXFA && useXFA){
xfaFormList=createXFADisplayComponentsForPage(xfaFormList,page);
}else{
//scan list for all relevant values and add to array if valid
//0 = forms, 1 = annots
final int decodeToForm = 2;
for(int forms=0;formspage && annotList[page]!=null && !isContainXFAStream){
annotList[page].resetToStart();
//create lookup and array for values to set order correctly in HTML
if(formFactory.getType()==FormFactory.HTML){
final Map annotOrder=new HashMap();
final int count2=annotList[page].getTokenCount();
String val;
for(int ii=0;ii-1; fieldNum--) {
objRef=null;
if(forms==0){
if(fieldList!=null) {
objRef = fieldList.getNextValueAsString(true);
}
}else{
if(addedMissingPopup && !annotList[page].hasMoreTokens()){
//Ignore this as we have added our own object that does not need reading
//with the PdfArrayIterator. Code positioned like this to explain.
//Test File : baseline_screens\cid2\SampleError.pdf
}else{
if(annotList.length>page && annotList[page]!=null) {
objRef = annotList[page].getNextValueAsString(true);
}
}
}
if(objRef==null || (objRef!=null && (formsProcessed.get(objRef)!=null || objRef.isEmpty()))) {
continue;
}
formObject=convertRefToFormObject(objRef,page);
/**
* Only allows Annotations if in Annots page stream
*/
if(forms==0 && formObject!=null && formObject.getFormType()==-1){
//storeSignatures(formObject, formObject.getParameterConstant(PdfDictionary.Subtype));
continue;
}
if(formObject.getParameterConstant(PdfDictionary.Subtype)==PdfDictionary.Text &&
formObject.getDictionary(PdfDictionary.Popup)==null){
final FormObject po = new FormObject(PdfDictionary.Annot);
po.setIntNumber(PdfDictionary.F, 24); //Bit Flag for bits 4+5 (No Zoom, No Rotate)
po.setBoolean(PdfDictionary.Open, formObject.getBoolean(PdfDictionary.Open));
po.setConstant(PdfDictionary.Subtype, PdfDictionary.Popup);
final float[] rect = formObject.getFloatArray(PdfDictionary.Rect);
if(pageData.getRotation(page)%180!=0) {
po.setFloatArray(PdfDictionary.Rect, new float[]{rect[2] - 160, -100, rect[2], 0});
} else {
po.setFloatArray(PdfDictionary.Rect, new float[]{pageData.getCropBoxWidth(page), rect[3] - 100, pageData.getCropBoxWidth(page) + 160, rect[3]});
}
po.setStringKey(PdfDictionary.Parent, formObject.getObjectRefAsString().getBytes());
po.setParentPdfObj(formObject);
po.setPageNumber(page);
formObject.setDictionary(PdfDictionary.Popup, po);
final FormObject[] newForms = new FormObject[Aforms.length+1];
for(int ii=0; ii!=Aforms.length; ii++){
newForms[ii] = Aforms[ii];
}
newForms[Aforms.length] = po;
Aforms = newForms;
AfieldCount[page]++;
addedMissingPopup = true;
}
final byte[][] kids=formObject.getKeyArray(PdfDictionary.Kids);
if(kids!=null) //not 'proper' kids so process here
{
i = flattenKids(page, formsProcessed, formObject, i, forms);
} else {
i = processFormObject(page, formsProcessed, formObject, objRef, i, forms);
}
}
}
}
final List unsortedForms= new ArrayList();
final List sortedForms = new ArrayList();
compData.setListForPage(page,unsortedForms,false);
compData.setListForPage(page, sortedForms, true);
//XFA, FDF FORMS then ANNOTS
final int readToForm = 3;
for(int forms=0;forms> tabMap = new HashMap>();
double maxY = 0;
for(final FormObject obj : Aforms){
if(obj!=null){
final int x = obj.getBoundingRectangle().x;
final Double y = obj.getBounding2DRectangleForTabbing().getY();
maxY = Math.max(y,maxY);
if(tabMap.containsKey(y)){
final ArrayList fList = tabMap.get(y);
int insertion = -1;
for(int z=0;z list = new ArrayList();
list.add(obj);
tabMap.put(y,list);
}
}
}
final FormObject [] finalList = new FormObject[Aforms.length];
int objCount = 0;
final Object[] keys = new Object[tabMap.size()];
int cc = 0;
for(final Object k : tabMap.keySet().toArray()){
keys[cc] = k;
cc++;
}
Arrays.sort(keys);
for(int k = keys.length;k>0;k--){
final ArrayList objList = tabMap.get(keys[k-1]);
if(objList != null){
for(final FormObject f :objList){
finalList[objCount] = f;
objCount++;
}
}
}
Aforms = finalList;
}
count=Aforms.length;
}
boolean firstPopup = true;
for (int k = 0; k ();
sigKeys=new HashMap();
}
if(!sigKeys.containsKey(formObject.getObjectRefAsString())) { //avoid duplicates
sigObject.add(formObject);
sigKeys.put(formObject.getObjectRefAsString(),"x");
}
}
}
private int flattenKids(final int page, final Map formsProcessed, final FormObject formObject, int i, final int forms) {
final byte[][] kidList=formObject.getKeyArray(PdfDictionary.Kids);
final int kidCount=kidList.length;
//resize to fit
if(forms==0){
final int oldCount=Fforms.length;
final FormObject[] temp=Fforms;
Fforms=new FormObject[oldCount+kidCount-1];
System.arraycopy(temp, 0, Fforms, 0, oldCount);
}else{
final int oldCount=Aforms.length;
final FormObject[] temp=Aforms;
Aforms=new FormObject[oldCount+kidCount-1];
System.arraycopy(temp, 0, Aforms, 0, oldCount);
}
for (final byte[] aKidList : kidList) { //iterate through all parts
final String key = new String(aKidList);
//now we have inherited values, read
final FormObject childObj = new FormObject(key);
//inherit values
if (formObject != null) {
childObj.copyInheritedValuesFromParent(formObject);
}
currentPdfFile.readObject(childObj);
//childObj.setPDFRef(key);
childObj.setRef(key);
if (childObj.getKeyArray(PdfDictionary.Kids) == null) {
if(!childObj.isAppearanceUsed()){
new FormStream().createAppearanceString(childObj, currentPdfFile);
}
i = processFormObject(page, formsProcessed, childObj, key, i, forms);
} else {
i = flattenKids(page, formsProcessed, childObj, i, forms);
}
}
return i;
}
private int processFormObject(final int page, final Map formsProcessed, final FormObject formObject, final String objRef, int i, final int forms) {
boolean isOnPage=false;
if(forms==0){ //check page
PdfObject pageObj=formObject.getDictionary(PdfDictionary.P);
byte[] pageRef=null;
if(pageObj!=null) {
pageRef = pageObj.getUnresolvedData();
}
if(pageRef==null || pageObj==null){
final String parent=formObject.getStringKey(PdfDictionary.Parent);
if(parent!=null){
final PdfObject parentObj = getParent(parent);
pageObj=parentObj.getDictionary(PdfDictionary.P);
if(pageObj!=null) {
pageRef = pageObj.getUnresolvedData();
}
}
}
if(pageRef==null){
final byte[][] kidList = getKid(formObject,false);
final boolean hasKids=kidList!=null && kidList.length>0;
if (hasKids) {
final int kidCount=kidList.length;
FormObject kidObject;
for(int jj=0;jj
}
private void initJSonFields(final Map formsCreated) {
//scan all fields for javascript actions
//boolean formsChanged=false;
for (final String ref : formsCreated.keySet()) {
final FormObject formObject = getFormObject(ref);
javascript.execute(formObject, PdfDictionary.K,ActionHandler.FOCUS_EVENT, ' ');
// if (result == ActionHandler.VALUESCHANGED) {
// formsChanged = true;
// }
}
// if we have some changed forms values then lets update them
//if(formsChanged)
// updateChangedForms();
}
/**
* create a widget to handle fields
*/
private void createField(final FormObject formObject) {
//
/**/
final Integer widgetType; //no value set
final Object retComponent=null;
final int subtype=formObject.getParameterConstant(PdfDictionary.Subtype);//FT
final int formFactoryType=formFactory.getType();
//if sig object set global sig object so we can access later
storeSignatures(formObject, subtype);
//check if a popup is associated
if(formObject.getDictionary(PdfDictionary.Popup)!=null){
formObject.setActionFlag(FormObject.POPUP);
}
//flags used to alter interactivity of all fields
final boolean readOnly;
final boolean required;
final boolean noexport;
final boolean[] flags = formObject.getFieldFlags();//Ff
if (flags != null) {
//noinspection UnusedAssignment
readOnly = flags[FormObject.READONLY_ID];
//noinspection UnusedAssignment
required = flags[FormObject.REQUIRED_ID];
//noinspection UnusedAssignment
noexport = flags[FormObject.NOEXPORT_ID];
/*
* boolean comb=flags[FormObject.COMB_ID];
* boolean comminOnSelChange=flags[FormObject.COMMITONSELCHANGE_ID];
* boolean donotScrole=flags[FormObject.DONOTSCROLL_ID];
* boolean doNotSpellCheck=flags[FormObject.DONOTSPELLCHECK_ID];
* boolean fileSelect=flags[FormObject.FILESELECT_ID];
* boolean isCombo=flags[FormObject.COMBO_ID];
* boolean isEditable=flags[FormObject.EDIT_ID];
* boolean isMultiline=flags[FormObject.MULTILINE_ID];
* boolean isPushButton=flags[FormObject.PUSHBUTTON_ID];
* boolean isRadio=flags[FormObject.RADIO_ID];
* boolean hasNoToggleToOff=flags[FormObject.NOTOGGLETOOFF_ID];
* boolean hasPassword=flags[FormObject.PASSWORD_ID];
* boolean multiSelect=flags[FormObject.MULTISELECT_ID];
* boolean radioinUnison=flags[FormObject.RADIOINUNISON_ID];
* boolean richtext=flags[FormObject.RICHTEXT_ID];
* boolean sort=flags[FormObject.SORT_ID];
*/
}
//hard-coded for HTML non-forms
if(!ExternalHandlers.isXFAPresent() && (formFactoryType==FormFactory.HTML || formFactoryType==FormFactory.SVG)){
widgetType=FormFactory.ANNOTATION;
}else if (subtype == PdfDictionary.Btn) {//----------------------------------- BUTTON ----------------------------------------
//flags used for button types
//20100212 (ms) Unused ones commented out
boolean isPushButton = false, isRadio = false;// hasNoToggleToOff = false, radioinUnison = false;
if (flags != null) {
isPushButton = flags[FormObject.PUSHBUTTON_ID];
isRadio = flags[FormObject.RADIO_ID];
//hasNoToggleToOff = flags[FormObject.NOTOGGLETOOFF_ID];
//radioinUnison = flags[FormObject.RADIOINUNISON_ID];
}
if (isPushButton) {
widgetType=FormFactory.PUSHBUTTON;
}else if(isRadio){
widgetType=FormFactory.RADIOBUTTON;
}else {
widgetType=FormFactory.CHECKBOXBUTTON;
}
} else {
if (subtype ==PdfDictionary.Tx) { //----------------------------------------------- TEXT --------------------------------------
//flags used for text types
// 20100212 (ms) commented out ones not used
boolean isMultiline = false, hasPassword = false;// doNotScroll = false, richtext = false, fileSelect = false, doNotSpellCheck = false;
if (flags != null) {
isMultiline = flags[FormObject.MULTILINE_ID];
hasPassword = flags[FormObject.PASSWORD_ID];
//doNotScroll = flags[FormObject.DONOTSCROLL_ID];
//richtext = flags[FormObject.RICHTEXT_ID];
//fileSelect = flags[FormObject.FILESELECT_ID];
//doNotSpellCheck = flags[FormObject.DONOTSPELLCHECK_ID];
}
if (isMultiline) {
if (hasPassword) {
widgetType=FormFactory.MULTILINEPASSWORD;
} else {
widgetType=FormFactory.MULTILINETEXT;
}
} else {//singleLine
if (hasPassword) {
widgetType=FormFactory.SINGLELINEPASSWORD;
} else {
widgetType=FormFactory.SINGLELINETEXT;
}
}
}else if (subtype==PdfDictionary.Ch) {//----------------------------------------- CHOICE ----------------------------------------------
//flags used for choice types
//20100212 (ms) Unused ones commented out
boolean isCombo = false;// multiSelect = false, sort = false, isEditable = false, doNotSpellCheck = false, comminOnSelChange = false;
if (flags != null) {
isCombo = flags[FormObject.COMBO_ID];
//multiSelect = flags[FormObject.MULTISELECT_ID];
//sort = flags[FormObject.SORT_ID];
//isEditable = flags[FormObject.EDIT_ID];
//doNotSpellCheck = flags[FormObject.DONOTSPELLCHECK_ID];
//comminOnSelChange = flags[FormObject.COMMITONSELCHANGE_ID];
}
if (isCombo) {// || (type==XFAFORM && ((XFAFormObject)formObject).choiceShown!=XFAFormObject.CHOICE_ALWAYS)){
widgetType=FormFactory.COMBOBOX;
} else {//it is a list
widgetType=FormFactory.LIST;
}
} else if (subtype == PdfDictionary.Sig) {
widgetType=FormFactory.SIGNATURE;
} else{//assume annotation if (formType == ANNOTATION) {
widgetType=FormFactory.ANNOTATION;
}
}
formObject.setFormType(widgetType);
if(formFactory.getType()==FormFactory.HTML || formFactory.getType()==FormFactory.SVG){
compData.checkGUIObjectResolved(formObject);
}else if(retComponent!=null && formFactory.getType()!=FormFactory.SWING){
formObject.setGUIComponent(retComponent,formFactory.getType());
compData.setGUIComp(formObject, retComponent);
}
}
/**
* If possible we recommend you work with the Form Objects rather than
* resolve GUI components
*
* null key will return all values
*
* if pageNumber is -1 it will process whole document, otherwise just that
* page
*
* For a full example of usage please see http://files.idrsolutions.com/samplecode/org/jpedal/examples/acroform/ExtractFormDataAsObject.java.html
*
* Object[] will vary depending on what ReturnValues enum is passed in and could contain String (Names), FormObject or Component
*/
public Object[] getFormComponents(final String objectName, final ReturnValues value, final int pageNumber) {
//if(formFactory.getType()!=FormFactory.ULC){
/**make sure all forms decoded*/
if(pageNumber==-1){
for (int p = 1; p < this.pageCount + 1; p++) //add init method and move scaling/rotation to it
{
createDisplayComponentsForPage(p, null);
}
}else{
createDisplayComponentsForPage(pageNumber, null);
}
//}
return compData.getFormComponents(objectName,value,pageNumber).toArray();
}
/**
* setup object which creates all GUI objects
*/
public void setFormFactory(final FormFactory newFormFactory) {
formFactory = newFormFactory;
/**
* allow user to create custom structure to hold data
*/
compData=formFactory.getCustomCompData();
}
/**
* get GUIData object with all widgets
*/
public GUIData getCompData() {
return compData;
}
/**return Signature as iterator with one or more objects or null*/
public Iterator getSignatureObjects() {
if(sigObject==null) {
return null;
} else {
return sigObject.iterator();
}
}
public ActionHandler getActionHandler() {
return formsActionHandler;
}
public FormFactory getFormFactory() {
return formFactory;
}
public void setIgnoreForms(final boolean ignoreForms) {
this.ignoreForms=ignoreForms;
}
public boolean ignoreForms() {
return ignoreForms;
}
public void dispose() {
AfieldCount = null;
fDecoder=null;
formsActionHandler=null;
//linkHandler=null;
javascript=null;
Fforms=null;
Aforms=null;
fieldList=null;
annotList=null;
formFactory=null;
compData.dispose();
compData=null;
sigObject=null;
sigKeys=null;
pageData=null;
currentPdfFile=null;
fDecoder=null;
}
/**
* get Iterator with list of all Annots on page or
* return null if no Annots - no longer needs
* call to decodePage beforehand as checks itself
*
* @deprecated - getFormComponents(String objectName, ReturnValues value,int pageNumber) recommended
* as much more flexible
*/
public PdfArrayIterator getAnnotsOnPage(final int page) {
//check annots decoded - will just return if done
createDisplayComponentsForPage(page,null);
if(annotList!=null && annotList.length>page && annotList[page]!=null){
annotList[page].resetToStart();
return annotList[page];
}else{
return null;
}
}
/**
* returns false if not XFA (or XFA in Legacy mode)
* and true if XFA using XFA data
* @return
*/
public boolean isXFA() {
return hasXFA;
}
public boolean useXFA() {
return useXFA;
}
public boolean hasFormsOnPage(final int page) {
final boolean hasAnnots=(annotList!=null && annotList.length>page && annotList[page]!=null);
final boolean hasForm=(hasXFA && useXFA && fDecoder.hasXFADataSet())||fieldList!=null;
return hasAnnots || hasForm;
}
public Object[] getFormResources() {
return new Object[]{AcroRes,CO};
}
public boolean formsRasterizedForDisplay() {
return compData.formsRasterizedForDisplay();
}
/**
* get FormObject
* @param ref
* @return
* In all modes except HTML,SVG,JavaFX will decode other forms on pages if not
* found
*/
public FormObject getFormObject(final String ref) {
FormObject obj = (FormObject) compData.getRawFormData().get(ref);
//if not found now decode all page and retry
if (obj == null && formFactory.getType()!=FormFactory.HTML && formFactory.getType()!=FormFactory.SVG) {
for (int ii = 1; ii < this.pageCount; ii++) {
createDisplayComponentsForPage(ii, null);
obj = (FormObject) compData.getRawFormData().get(ref);
if (obj != null) {
break;
}
}
}
return obj;
}
public void setInsets(final int width, final int height){
compData.setPageData(compData.pageData, width, height);
}
FormObject convertRefToFormObject(final String objRef, final int page) {
FormObject formObject = (FormObject) compData.getRawFormData().get(objRef);
if (formObject == null) {
formObject = new FormObject(objRef);
if(page!=-1) {
formObject.setPageRotation(pageData.getRotation(page));
}
//formObject.setPDFRef((String)objRef);
if (objRef.charAt(objRef.length() - 1) == 'R') {
currentPdfFile.readObject(formObject);
} else {
//changed by Mark as cover <<>> as well as 1 0 R
formObject.setStatus(PdfObject.UNDECODED_REF);
formObject.setUnresolvedData(StringUtils.toBytes(objRef), -1);
currentPdfFile.checkResolved(formObject);
}
compData.storeRawData(formObject);
}
return formObject;
}
/**
* Allow user to get ENUM to show type of form
* FormTypes (XFA_LEGACY, XFA_DYNAMIC, NON_XFA)
* @return
*/
public Enum getPDFformType() {
return PDFformType;
}
public void alwaysuseXFA(final boolean alwaysUseXFA) {
this.alwaysUseXFA=alwaysUseXFA;
}
public boolean alwaysuseXFA() {
return alwaysUseXFA;
}
public void init(SwingFormCreator formCreator) {
this.formCreator=formCreator;
compData=formCreator.getData();
}
public PdfStreamDecoder getStreamDecoder(PdfObjectReader currentPdfFile, boolean isHires, PdfLayerList layer,boolean isFirst) {
if(isFirst){
return new PdfStreamDecoder(currentPdfFile);
}else{
return new PdfStreamDecoder(currentPdfFile, isHires,layer);
}
}
public boolean showFormWarningMessage(int page) {
boolean warnOnceOnForms=false;
if(hasXFA){
warnOnceOnForms=true;
System.out.println("[WARNING] This file contains XFA forms that are not supported by this version of JPDF2HTML5. To convert into functional HTML forms and display non-legacy mode page content, JPDF2HTML5 Forms Edition must be used.");
}else if(hasFormsOnPage(page)){
warnOnceOnForms=true;
System.out.println("[WARNING] This file contains form components that have been rasterized. To convert into functional HTML forms, JPDF2HTML5 Forms Edition must be used.");
}
return warnOnceOnForms;
}
FormObject[] createXFADisplayComponentsForPage(FormObject[] xfaFormList, int page) {
throw new UnsupportedOperationException("createXFADisplayComponentsForPage should never be called");
}
public HashMap getPageMapXFA() {
throw new UnsupportedOperationException("getPageMapXFA should never be called");
}
public byte[] getXMLContentAsBytes(int dataType) {
return null;
}
public void outputJavascriptXFA(String path, String name) {
throw new UnsupportedOperationException("outputJavascriptXFA should never be called");
}
public PrintStreamDecoder getStreamDecoderForPrinting(PdfObjectReader currentPdfFile, boolean isHires, PdfLayerList pdfLayerList) {
//
return null;
/**/
}
public BufferedImage decode(PdfObject pdfObject, PdfObjectReader currentPdfFile, PdfObject XObject, int subtype, int width, int height, int offsetImage, float pageScaling) {
return null;//
}
public FormFlattener getFormFlattener() {
return new FormFlattener();
}
}