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

org.jpedal.objects.acroforms.AcroRenderer 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


 *
 * ---------------
 * 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; } try{ formObject=convertRefToFormObject(objRef,page); }catch(Exception e){ LogWriter.writeLog("Exception "+e+" with "+objRef); continue; } /** * 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 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) { // avoid creation of Swing widgets if we have 2 copies in play on ULC //noinspection PointlessBooleanExpression if(ExternalHandlers.isULCPresent() && formFactory.getType()==FormFactory.SWING){ //if(org.jpedal.examples.canoo.server.ULCViewer.formOption == org.jpedal.constants.SpecialOptions.ULC_WIDGETS_ON_SERVER && // formFactory.getType()==FormFactory.SWING){ return; } 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 new PdfStreamDecoderForPrinting(currentPdfFile, isHires, pdfLayerList); } 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(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy