
org.openpdf.renderer.annotation.WidgetAnnotation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openpdf-renderer Show documentation
Show all versions of openpdf-renderer Show documentation
PDF renderer implementation supporting the subset of PDF 1.4 specification.
The newest version!
package org.openpdf.renderer.annotation;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Rectangle2D.Float;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.openpdf.renderer.PDFCmd;
import org.openpdf.renderer.PDFImage;
import org.openpdf.renderer.PDFObject;
import org.openpdf.renderer.PDFPage;
import org.openpdf.renderer.PDFParseException;
import org.openpdf.renderer.PDFParser;
/**
* PDF annotation describing a widget.
* @since Aug 20, 2010
*/
public class WidgetAnnotation extends PDFAnnotation {
private String fieldValue;
private FieldType fieldType;
private String fieldName;
private PDFObject fieldValueRef;
private List cmd;
/**
* Type for PDF form elements
* @version $Id: WidgetAnnotation.java,v 1.2 2010-09-30 10:34:44 xphc Exp $
* @author xphc
* @since Aug 20, 2010
*/
public enum FieldType {
/** Button Field */
Button("Btn"),
/** Text Field */
Text("Tx"),
/** Choice Field */
Choice("Ch"),
/** Signature Field */
Signature("Sig");
private final String typeCode;
FieldType(String typeCode) {
this.typeCode = typeCode;
}
static FieldType getByCode(String typeCode) {
FieldType[] values = values();
for (FieldType value : values) {
if (value.typeCode.equals(typeCode))
return value;
}
return null;
}
}
public WidgetAnnotation(PDFObject annotObject) throws IOException {
super(annotObject, AnnotationType.WIDGET);
// The type of field that this dictionary describes. Field type is
// present for terminal fields but is inherited from parent if absent
// (see PDF Reference 1.7 table 8.69)
PDFObject fieldTypeRef = annotObject.getDictRef("FT");
if (fieldTypeRef != null) {
// terminal field
this.fieldType = FieldType.getByCode(fieldTypeRef.getStringValue());
}
else {
// must check parent since field type is inherited
PDFObject parent = annotObject.getDictRef("Parent");
while (parent != null && parent.isIndirect()) {
parent = parent.dereference();
}
if (parent != null) {
fieldTypeRef = parent.getDictRef("FT");
this.fieldType = FieldType.getByCode(fieldTypeRef.getStringValue());
}
}
// Name defined for the field
PDFObject fieldNameRef = annotObject.getDictRef("T");
if (fieldNameRef != null) {
this.fieldName = fieldNameRef.getTextStringValue();
}
this.fieldValueRef = annotObject.getDictRef("V");
if (this.fieldValueRef != null) {
this.fieldValue = this.fieldValueRef.getTextStringValue();
}
parseAP(annotObject.getDictRef("AP"));
}
private void parseAP(PDFObject dictRef) throws IOException {
if(dictRef == null) {
return;
}
PDFObject normalAP = dictRef.getDictRef("N");
if(normalAP == null) {
return;
}
cmd = parseCommand(normalAP);
}
/**
* @param obj
* @return
* @throws IOException
*/
private List parseCommand(PDFObject obj) throws IOException {
// TODO see also MarkupAnnotation.parseIntoPdfCommands() which seems to be copied code
// We should merge these two
PDFObject dictRefSubType = obj.getDictRef("Subtype");
String type = null;
if(dictRefSubType != null) {
type = dictRefSubType.getStringValue();
}
if (type == null) {
PDFObject dictRefS = obj.getDictRef("S");
if(dictRefS != null) {
type = dictRefS.getStringValue();
}
}
//if type is still null, check for AcroForm, if AcroForm is available the PDF could be not compatible
//with the PDF specification, anyway check if obj is in AcroForm, if so, proceed as for a good PDF
if(type == null) {
PDFObject acroForm = obj.getRoot().getDictRef("AcroForm");
PDFObject fields = acroForm.getDictRef("Fields");
PDFObject[] arrayFields = fields.getArray();
for (PDFObject pdfObject : arrayFields) {
PDFObject dictRefAP = pdfObject.getDictRef("AP");
if(dictRefAP != null) {
PDFObject dictRefN = dictRefAP.getDictRef("N");
if(dictRefN.equals(obj)) {
PDFObject dictRefAS = pdfObject.getDictRef("AS");
if(dictRefAS != null) { //this is a combobox
PDFObject dictRef = dictRefN.getDictRef(dictRefAS.getStringValue());
obj = dictRef;
}
type = "Form";
break;
}
}
}
if(type == null) { //check for radiobutton
PDFObject dictRef = obj.getDictRef("Off");
if(dictRef != null) {
for (PDFObject pdfObject : arrayFields) {
PDFObject dictRefT = pdfObject.getDictRef("T");
if(dictRefT != null && dictRefT.getStringValue().contains("Group")) {
PDFObject kids = pdfObject.getDictRef("Kids");
PDFObject[] arrayKids = kids.getArray();
for (PDFObject kid : arrayKids) {
PDFObject kidAP = kid.getDictRef("AP");
PDFObject kidN = kidAP.getDictRef("N");
if(kidN.equals(obj)) {
PDFObject kidAS = kid.getDictRef("AS");
if(kidAS != null) {
PDFObject kidRef = kidN.getDictRef(kidAS.getStringValue());
obj = kidRef;
}
type = "Form";
break;
}
}
}
}
}
}
}
ArrayList result = new ArrayList();
result.add(PDFPage.createPushCmd());
result.add(PDFPage.createPushCmd());
if ("Image".equals(type)) {
// stamp annotation transformation
AffineTransform rectAt = getPositionTransformation();
result.add(PDFPage.createXFormCmd(rectAt));
PDFImage img = PDFImage.createImage(obj, new HashMap() , false);
result.add(PDFPage.createImageCmd(img));
} else if ("Form".equals(type)) {
// rats. parse it.
PDFObject bobj = obj.getDictRef("BBox");
Float bbox = new Rectangle2D.Float(bobj.getAt(0).getFloatValue(),
bobj.getAt(1).getFloatValue(),
bobj.getAt(2).getFloatValue(),
bobj.getAt(3).getFloatValue());
PDFPage formCmds = new PDFPage(bbox, 0);
// stamp annotation transformation
AffineTransform rectAt = getPositionTransformation();
formCmds.addXform(rectAt);
AffineTransform rectScaled = getScalingTransformation(bbox);
formCmds.addXform(rectScaled);
// form transformation
AffineTransform at;
PDFObject matrix = obj.getDictRef("Matrix");
if (matrix == null) {
at = new AffineTransform();
} else {
float elts[] = new float[6];
for (int i = 0; i < elts.length; i++) {
elts[i] = (matrix.getAt(i)).getFloatValue();
}
at = new AffineTransform(elts);
}
formCmds.addXform(at);
HashMap r = new HashMap(new HashMap());
PDFObject rsrc = obj.getDictRef("Resources");
if (rsrc != null) {
r.putAll(rsrc.getDictionary());
}
PDFParser form = new PDFParser(formCmds, obj.getStream(), r);
form.go(true);
result.addAll(formCmds.getCommands());
} else {
throw new PDFParseException("Unknown XObject subtype: " + type);
}
result.add(PDFPage.createPopCmd());
result.add(PDFPage.createPopCmd());
return result;
}
/**
* Transform to the position of the stamp annotation
* @return
*/
private AffineTransform getPositionTransformation() {
Float rect2 = getRect();
double[] f = new double[] {1,
0,
0,
1,
rect2.getMinX(),
rect2.getMinY()};
return new AffineTransform(f);
}
/**
* Returns the type of the field
* @return Field type
*/
public FieldType getFieldType() {
return this.fieldType;
}
/**
* The field's value as a string. Might be {@code null}.
* @return The field value or {@code null}.
*/
public String getFieldValue() {
return this.fieldValue;
}
/**
* Sets the field value for a text field. Note: this doesn't actually change
* the PDF file yet.
*
* @param fieldValue
* The new value for the text field
*/
public void setFieldValue(String fieldValue) {
this.fieldValue = fieldValue;
}
/**
* Name for this widget.
* @return Widget name
*/
public String getFieldName() {
return this.fieldName;
}
@Override
public List getPageCommandsForAnnotation() {
List pageCommandsForAnnotation = super.getPageCommandsForAnnotation();
// cmd might be null if there is no AP (appearance dictionary)
// AP is optional see PDF Reference 1.7 table 8.15
if (this.cmd != null) {
pageCommandsForAnnotation.addAll(this.cmd);
}
return pageCommandsForAnnotation;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy