📄 acrofields.java
字号:
/*
* Copyright 2003-2005 by Paulo Soares.
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the License.
*
* The Original Code is 'iText, a free JAVA-PDF library'.
*
* The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
* the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
* All Rights Reserved.
* Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
* are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
*
* Contributor(s): all the names of the contributors are added in the source code
* where applicable.
*
* Alternatively, the contents of this file may be used under the terms of the
* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
* provisions of LGPL are applicable instead of those above. If you wish to
* allow use of your version of this file only under the terms of the LGPL
* License and not to allow others to use your version of this file under
* the MPL, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the LGPL.
* If you do not delete the provisions above, a recipient may use your version
* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MPL as stated above or under the terms of the GNU
* Library General Public License as published by the Free Software Foundation;
* either version 2 of the License, or 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 Library general Public License for more
* details.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*/
package com.lowagie.text.pdf;
import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.w3c.dom.Node;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.ExceptionConverter;
import com.lowagie.text.Rectangle;
/** Query and change fields in existing documents either by method
* calls or by FDF merging.
* @author Paulo Soares (psoares@consiste.pt)
*/
public class AcroFields {
PdfReader reader;
PdfWriter writer;
HashMap fields;
private int topFirst;
private HashMap sigNames;
private boolean append;
public static final int DA_FONT = 0;
public static final int DA_SIZE = 1;
public static final int DA_COLOR = 2;
private HashMap extensionFonts = new HashMap();
private XfaForm xfa;
/**
* A field type invalid or not found.
*/
public static final int FIELD_TYPE_NONE = 0;
/**
* A field type.
*/
public static final int FIELD_TYPE_PUSHBUTTON = 1;
/**
* A field type.
*/
public static final int FIELD_TYPE_CHECKBOX = 2;
/**
* A field type.
*/
public static final int FIELD_TYPE_RADIOBUTTON = 3;
/**
* A field type.
*/
public static final int FIELD_TYPE_TEXT = 4;
/**
* A field type.
*/
public static final int FIELD_TYPE_LIST = 5;
/**
* A field type.
*/
public static final int FIELD_TYPE_COMBO = 6;
/**
* A field type.
*/
public static final int FIELD_TYPE_SIGNATURE = 7;
private boolean lastWasString;
/** Holds value of property generateAppearances. */
private boolean generateAppearances = true;
private HashMap localFonts = new HashMap();
private float extraMarginLeft;
private float extraMarginTop;
private ArrayList substitutionFonts;
AcroFields(PdfReader reader, PdfWriter writer) {
this.reader = reader;
this.writer = writer;
try {
xfa = new XfaForm(reader);
}
catch (Exception e) {
throw new ExceptionConverter(e);
}
if (writer instanceof PdfStamperImp) {
append = ((PdfStamperImp)writer).isAppend();
}
fill();
}
void fill() {
fields = new HashMap();
PdfDictionary top = (PdfDictionary)PdfReader.getPdfObjectRelease(reader.getCatalog().get(PdfName.ACROFORM));
if (top == null)
return;
PdfArray arrfds = (PdfArray)PdfReader.getPdfObjectRelease(top.get(PdfName.FIELDS));
if (arrfds == null || arrfds.size() == 0)
return;
arrfds = null;
for (int k = 1; k <= reader.getNumberOfPages(); ++k) {
PdfDictionary page = reader.getPageNRelease(k);
PdfArray annots = (PdfArray)PdfReader.getPdfObjectRelease(page.get(PdfName.ANNOTS), page);
if (annots == null)
continue;
ArrayList arr = annots.getArrayList();
for (int j = 0; j < arr.size(); ++j) {
PdfObject annoto = PdfReader.getPdfObject((PdfObject)arr.get(j), annots);
if (!(annoto instanceof PdfDictionary)) {
PdfReader.releaseLastXrefPartial((PdfObject)arr.get(j));
continue;
}
PdfDictionary annot = (PdfDictionary)annoto;
if (!PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE))) {
PdfReader.releaseLastXrefPartial((PdfObject)arr.get(j));
continue;
}
PdfDictionary widget = annot;
PdfDictionary dic = new PdfDictionary();
dic.putAll(annot);
String name = "";
PdfDictionary value = null;
PdfObject lastV = null;
while (annot != null) {
dic.mergeDifferent(annot);
PdfString t = (PdfString)PdfReader.getPdfObject(annot.get(PdfName.T));
if (t != null)
name = t.toUnicodeString() + "." + name;
if (lastV == null && annot.get(PdfName.V) != null)
lastV = PdfReader.getPdfObjectRelease(annot.get(PdfName.V));
if (value == null && t != null) {
value = annot;
if (annot.get(PdfName.V) == null && lastV != null)
value.put(PdfName.V, lastV);
}
annot = (PdfDictionary)PdfReader.getPdfObject(annot.get(PdfName.PARENT), annot);
}
if (name.length() > 0)
name = name.substring(0, name.length() - 1);
Item item = (Item)fields.get(name);
if (item == null) {
item = new Item();
fields.put(name, item);
}
if (value == null)
item.values.add(widget);
else
item.values.add(value);
item.widgets.add(widget);
item.widget_refs.add(arr.get(j)); // must be a reference
if (top != null)
dic.mergeDifferent(top);
item.merged.add(dic);
item.page.add(new Integer(k));
item.tabOrder.add(new Integer(j));
}
}
}
/** Gets the list of appearance names. Use it to get the names allowed
* with radio and checkbox fields. If the /Opt key exists the values will
* also be included. The name 'Off' may also be valid
* even if not returned in the list.
* @param fieldName the fully qualified field name
* @return the list of names or <CODE>null</CODE> if the field does not exist
*/
public String[] getAppearanceStates(String fieldName) {
Item fd = (Item)fields.get(fieldName);
if (fd == null)
return null;
HashMap names = new HashMap();
PdfDictionary vals = (PdfDictionary)fd.values.get(0);
PdfObject opts = PdfReader.getPdfObject(vals.get(PdfName.OPT));
if (opts != null) {
if (opts.isString())
names.put(((PdfString)opts).toUnicodeString(), null);
else if (opts.isArray()) {
ArrayList list = ((PdfArray)opts).getArrayList();
for (int k = 0; k < list.size(); ++k) {
PdfObject v = PdfReader.getPdfObject((PdfObject)list.get(k));
if (v != null && v.isString())
names.put(((PdfString)v).toUnicodeString(), null);
}
}
}
ArrayList wd = fd.widgets;
for (int k = 0; k < wd.size(); ++k) {
PdfDictionary dic = (PdfDictionary)wd.get(k);
dic = (PdfDictionary)PdfReader.getPdfObject(dic.get(PdfName.AP));
if (dic == null)
continue;
PdfObject ob = PdfReader.getPdfObject(dic.get(PdfName.N));
if (ob == null || !ob.isDictionary())
continue;
dic = (PdfDictionary)ob;
for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
String name = PdfName.decodeName(((PdfName)it.next()).toString());
names.put(name, null);
}
}
String out[] = new String[names.size()];
return (String[])names.keySet().toArray(out);
}
private String[] getListOption(String fieldName, int idx) {
Item fd = getFieldItem(fieldName);
if (fd == null)
return null;
PdfObject obj = PdfReader.getPdfObject(((PdfDictionary)fd.merged.get(0)).get(PdfName.OPT));
if (obj == null || !obj.isArray())
return null;
PdfArray ar = (PdfArray)obj;
String[] ret = new String[ar.size()];
ArrayList a = ar.getArrayList();
for (int k = 0; k < a.size(); ++k) {
obj = PdfReader.getPdfObject((PdfObject)a.get(k));
try {
if (obj.isArray()) {
obj = (PdfObject)((PdfArray)obj).getArrayList().get(idx);
}
if (obj.isString())
ret[k] = ((PdfString)obj).toUnicodeString();
else
ret[k] = obj.toString();
}
catch (Exception e) {
ret[k] = "";
}
}
return ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -