I am a creating acrofields in java with a stamper (As shown below) and I am wanting to find a way to know the length of a acrofield. I want to be able to determine the length of a string I am going to input in the acrofield and if it is too long then I will split that string and put it in a overflow acrofield. Is this possible to do? To find out how many characters I can put in a specific arcofield?
OutputStream output = FacesContext.getCurrentInstance().getExternalContext().getResponseOutputStream();
PdfStamper stamper = new PdfStamper(pdfTemplate, output);
stamper.setFormFlattening(true);
AcroFields fields = stamper.getAcroFields();
setFields(document, fields);
I also use fields.setField("AcroFieldName","Value"); to set the values.
There are lots of alternatives for your request:
1.) Do you know that fields offer autosizing of fonts? If you set the fontsize to 0 the font will be automatically sized to fit a field.
2.) Do you know that text form fields can contain multiple lines? (multiline textfield Ff bit position 13)
3.) There is the maxlen
attribute, so you can define by yourself how much can be written into a field. It is defined as follows:
MaxLen (integer) - The maximum length of the field’s text, in characters.
4.) If that all doesn't fit your needs it is possible to do what you want. You have to do three things:
a.) Get the length of the field. Key for that is the method getFieldPositions()
. An array of positioning information is returned where you basically do:
upperRightX coordinate - lowerLeftX coordinate
Here's the code which prints out all lengths of all fields:
AcroFields fields = stamper.getAcroFields();
Map<String, AcroFields.Item> fields = acroFields.getFields();
Iterator<Entry<String,Item>> it = fields.entrySet().iterator();
//iterate over form fields
while(it.hasNext()){
Entry<String,Item> entry = it.next();
float[] position = acroFields.getFieldPositions(entry.getKey());
int pageNumber = (int) position[0];
float lowerLeftX = position[1];
float lowerLeftY = position[2];
float upperRightX = position[3];
float upperRightY = position[4];
float fieldLength = Math.abs(upperRightX-lowerLeftX)
}
b.) Get the font and the fontsize out of the fields appearance (/DA)
//code within the above while()
PdfDictionary d = entry.getValue().getMerged(0);
PdfString fieldDA = d.getAsString(PdfName.DA);
//in case of no form field default appearance create a default one
if(fieldDA==null) ...
Object[] infos = AcroFields.splitDAelements(fieldDA.toString());
if(infos[0]!=null) String fontName = (String)infos[0];
if(infos[1]!=null) float fontSize= (((Float)infos[1]).floatValue());
c) Calculate the width of your string with the font and the fontsize:
Font font = new Font(fontName,Font.PLAIN,fontSize);
FontMetrics fm = new Canvas().getFontMetrics(font);
int stringWidth = fm.stringWidth("yourString");
Now if you compare both values you know whether the string fits into your field or not.
Update: MKL is right - in the case where the Font is embedded and not available in the operating system you can't do 4.) since you are not able to extract the font definition file out of the PDF (for legal and technical reasons)
Update II: You mean that you already have multiline textfields? In that case also measure the height:
fontMaxHeight = fm.getMaxAscent()+fm.getMaxDescent()+fm.getLeading();
and the height of the text field:
float fieldHeight = Math.abs(upperRightY-lowerLeftY)
Then you know how many lines fit into the textfield...