1 /*
2  * $Id: PdfAcroForm.java,v 1.44 2005/03/30 10:10:58 blowagie Exp $
3  * $Name:  $
4  *
5  * Copyright 2002 Bruno Lowagie
6  *
7  *
8  * The Original Code is 'iText, a free JAVA-PDF library'.
9  *
10  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
11  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
12  * All Rights Reserved.
13  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
14  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
15  *
16  * Contributor(s): all the names of the contributors are added in the source code
17  * where applicable.
18  *
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Library General Public
22  * License as published by the Free Software Foundation; either
23  * version 2 of the License, or (at your option) any later version.
24  *
25  * This library is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28  * Library General Public License for more details.
29  *
30  * You should have received a copy of the GNU Library General Public
31  * License along with this library; if not, write to the
32  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
33  * Boston, MA  02110-1301, USA.
34  *
35  *
36  * This library is free software; you can redistribute it and/or
37  * modify it under the terms of the GNU Library General Public
38  * License as published by the Free Software Foundation; either
39  * version 2 of the License, or (at your option) any later version.
40  *
41  * This library is distributed in the hope that it will be useful,
42  * but WITHOUT ANY WARRANTY; without even the implied warranty of
43  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
44  * Library General Public License for more details.
45  *
46  * You should have received a copy of the GNU Library General Public
47  * License along with this library; if not, write to the
48  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
49  * Boston, MA  02110-1301, USA.
50  *
51  *
52  * If you didn't download this code from the following link, you should check if
53  * you aren't using an obsolete version:
54  * http://www.lowagie.com/iText/
55  */
56 
57 package com.gitlab.pdftk_java.com.lowagie.text.pdf;
58 
59 import java.util.Iterator;
60 import java.util.HashMap;
61 
62 import com.gitlab.pdftk_java.com.lowagie.text.Rectangle;
63 import com.gitlab.pdftk_java.com.lowagie.text.ExceptionConverter;
64 
65 /**
66  * Each PDF document can contain maximum 1 AcroForm.
67  */
68 
69 public class PdfAcroForm extends PdfDictionary {
70 
71     private PdfWriter writer;
72 
73 
74     /** This is a map containing FieldTemplates. */
75     private HashMap fieldTemplates = new HashMap();
76 
77     /** This is an array containing DocumentFields. */
78     private PdfArray documentFields = new PdfArray();
79 
80     /** This is an array containing the calculationorder of the fields. */
81     private PdfArray calculationOrder = new PdfArray();
82 
83     /** Contains the signature flags. */
84     private int sigFlags = 0;
85 
86     /** Creates new PdfAcroForm
87      * @param writer*/
PdfAcroForm(PdfWriter writer)88     PdfAcroForm(PdfWriter writer) {
89         super();
90         this.writer = writer;
91     }
92 
93     /**
94      * Adds fieldTemplates.
95      * @param ft
96      */
97 
addFieldTemplates(HashMap ft)98     void addFieldTemplates(HashMap ft) {
99         fieldTemplates.putAll(ft);
100     }
101 
102     /**
103      * Adds documentFields.
104      * @param ref
105      */
106 
addDocumentField(PdfIndirectReference ref)107     void addDocumentField(PdfIndirectReference ref) {
108 	// ssteward; added test to support my code in PdfCopy
109 	if( !documentFields.contains(ref) )
110 	    documentFields.add(ref);
111     }
112 
113     /**
114      * Checks if the Acroform is valid
115      * @return true if the Acroform is valid
116      */
117 
isValid()118     boolean isValid() {
119         if (documentFields.size() == 0) return false;
120         put(PdfName.FIELDS, documentFields);
121         if (sigFlags != 0)
122             put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
123         if (calculationOrder.size() > 0)
124             put(PdfName.CO, calculationOrder);
125         if (fieldTemplates.size() == 0) return true;
126         PdfDictionary dic = new PdfDictionary();
127         for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
128             PdfTemplate template = (PdfTemplate)it.next();
129             PdfFormField.mergeResources(dic, (PdfDictionary)template.getResources());
130         }
131         put(PdfName.DR, dic);
132         PdfDictionary fonts = (PdfDictionary)dic.get(PdfName.FONT);
133         if (fonts != null) {
134             put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
135             writer.eliminateFontSubset(fonts);
136         }
137         return true;
138     }
139 
140     /**
141      * Adds an object to the calculationOrder.
142      * @param formField
143      */
144 
addCalculationOrder(PdfFormField formField)145     public void addCalculationOrder(PdfFormField formField) {
146         calculationOrder.add(formField.getIndirectReference());
147     }
148 
149     /**
150      * Sets the signature flags.
151      * @param f
152      */
153 
setSigFlags(int f)154     public void setSigFlags(int f) {
155         sigFlags |= f;
156     }
157 
158     /**
159      * Adds a formfield to the AcroForm.
160      * @param formField
161      */
162 
addFormField(PdfFormField formField)163     public void addFormField(PdfFormField formField) {
164         writer.addAnnotation(formField);
165     }
166 
167     /**
168      * @param name
169      * @param caption
170      * @param value
171      * @param url
172      * @param font
173      * @param fontSize
174      * @param llx
175      * @param lly
176      * @param urx
177      * @param ury
178      * @return a PdfFormField
179      */
addHtmlPostButton(String name, String caption, String value, String url, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)180     public PdfFormField addHtmlPostButton(String name, String caption, String value, String url, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
181         PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT);
182         PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
183         setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
184         drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
185         addFormField(button);
186 	return button;
187     }
188 
189     /**
190      * @param name
191      * @param caption
192      * @param value
193      * @param font
194      * @param fontSize
195      * @param llx
196      * @param lly
197      * @param urx
198      * @param ury
199      * @return a PdfFormField
200      */
addResetButton(String name, String caption, String value, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)201     public PdfFormField addResetButton(String name, String caption, String value, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
202         PdfAction action = PdfAction.createResetForm(null, 0);
203         PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
204         setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
205         drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
206         addFormField(button);
207         return button;
208     }
209 
210     /**
211      * @param name
212      * @param value
213      * @param url
214      * @param appearance
215      * @param llx
216      * @param lly
217      * @param urx
218      * @param ury
219      * @return a PdfFormField
220      */
addMap(String name, String value, String url, PdfContentByte appearance, float llx, float lly, float urx, float ury)221     public PdfFormField addMap(String name, String value, String url, PdfContentByte appearance, float llx, float lly, float urx, float ury) {
222         PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT | PdfAction.SUBMIT_COORDINATES);
223         PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
224         setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, null);
225         PdfContentByte cb = writer.getDirectContent();
226         PdfAppearance pa = cb.createAppearance(urx - llx, ury - lly);
227         pa.add(appearance);
228         button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
229         addFormField(button);
230         return button;
231     }
232 
233     /**
234      * @param button
235      * @param characteristics
236      * @param name
237      * @param value
238      */
setButtonParams(PdfFormField button, int characteristics, String name, String value)239     public void setButtonParams(PdfFormField button, int characteristics, String name, String value) {
240         button.setButton(characteristics);
241         button.setFlags(PdfAnnotation.FLAGS_PRINT);
242         button.setPage();
243         button.setFieldName(name);
244         if (value != null) button.setValueAsString(value);
245     }
246 
247     /**
248      * @param button
249      * @param caption
250      * @param font
251      * @param fontSize
252      * @param llx
253      * @param lly
254      * @param urx
255      * @param ury
256      */
drawButton(PdfFormField button, String caption, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)257     public void drawButton(PdfFormField button, String caption, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
258         PdfContentByte cb = writer.getDirectContent();
259         PdfAppearance pa = cb.createAppearance(urx - llx, ury - lly);
260         pa.drawButton(0f, 0f, urx - llx, ury - lly, caption, font, fontSize);
261         button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
262     }
263 
264     /**
265      * @param name
266      * @param value
267      * @return a PdfFormField
268      */
addHiddenField(String name, String value)269     public PdfFormField addHiddenField(String name, String value) {
270         PdfFormField hidden = PdfFormField.createEmpty(writer);
271         hidden.setFieldName(name);
272         hidden.setValueAsName(value);
273         addFormField(hidden);
274         return hidden;
275     }
276 
277     /**
278      * @param name
279      * @param text
280      * @param font
281      * @param fontSize
282      * @param llx
283      * @param lly
284      * @param urx
285      * @param ury
286      * @return a PdfFormField
287      */
addSingleLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)288     public PdfFormField addSingleLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
289         PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PLAINTEXT, 0);
290         setTextFieldParams(field, text, name, llx, lly, urx, ury);
291         drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
292         addFormField(field);
293         return field;
294     }
295 
296     /**
297      * @param name
298      * @param text
299      * @param font
300      * @param fontSize
301      * @param llx
302      * @param lly
303      * @param urx
304      * @param ury
305      * @return a PdfFormField
306      */
addMultiLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)307     public PdfFormField addMultiLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
308         PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.MULTILINE, PdfFormField.PLAINTEXT, 0);
309         setTextFieldParams(field, text, name, llx, lly, urx, ury);
310         drawMultiLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
311         addFormField(field);
312         return field;
313     }
314 
315     /**
316      * @param name
317      * @param text
318      * @param font
319      * @param fontSize
320      * @param llx
321      * @param lly
322      * @param urx
323      * @param ury
324      * @return PdfFormField
325      */
addSingleLinePasswordField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)326     public PdfFormField addSingleLinePasswordField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
327         PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PASSWORD, 0);
328         setTextFieldParams(field, text, name, llx, lly, urx, ury);
329         drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
330         addFormField(field);
331         return field;
332     }
333 
334     /**
335      * @param field
336      * @param text
337      * @param name
338      * @param llx
339      * @param lly
340      * @param urx
341      * @param ury
342      */
setTextFieldParams(PdfFormField field, String text, String name, float llx, float lly, float urx, float ury)343     public void setTextFieldParams(PdfFormField field, String text, String name, float llx, float lly, float urx, float ury) {
344         field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
345         field.setValueAsString(text);
346         field.setDefaultValueAsString(text);
347         field.setFieldName(name);
348         field.setFlags(PdfAnnotation.FLAGS_PRINT);
349         field.setPage();
350     }
351 
352     /**
353      * @param field
354      * @param text
355      * @param font
356      * @param fontSize
357      * @param llx
358      * @param lly
359      * @param urx
360      * @param ury
361      */
drawSingleLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)362     public void drawSingleLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
363         PdfContentByte cb = writer.getDirectContent();
364         PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
365         PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
366         tp2.setFontAndSize(font, fontSize);
367         tp2.resetRGBColorFill();
368         field.setDefaultAppearanceString(tp2);
369         tp.drawTextField(0f, 0f, urx - llx, ury - lly);
370         tp.beginVariableText();
371         tp.saveState();
372         tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
373         tp.clip();
374         tp.newPath();
375         tp.beginText();
376         tp.setFontAndSize(font, fontSize);
377         tp.resetRGBColorFill();
378         tp.setTextMatrix(4, (ury - lly) / 2 - (fontSize * 0.3f));
379         tp.showText(text);
380         tp.endText();
381         tp.restoreState();
382         tp.endVariableText();
383         field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
384     }
385 
386     /**
387      * @param field
388      * @param text
389      * @param font
390      * @param fontSize
391      * @param llx
392      * @param lly
393      * @param urx
394      * @param ury
395      */
drawMultiLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)396     public void drawMultiLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
397         PdfContentByte cb = writer.getDirectContent();
398         PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
399         PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
400         tp2.setFontAndSize(font, fontSize);
401         tp2.resetRGBColorFill();
402         field.setDefaultAppearanceString(tp2);
403         tp.drawTextField(0f, 0f, urx - llx, ury - lly);
404         tp.beginVariableText();
405         tp.saveState();
406         tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
407         tp.clip();
408         tp.newPath();
409         tp.beginText();
410         tp.setFontAndSize(font, fontSize);
411         tp.resetRGBColorFill();
412         tp.setTextMatrix(4, 5);
413         java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(text, "\n");
414         float yPos = ury - lly;
415         while (tokenizer.hasMoreTokens()) {
416             yPos -= fontSize * 1.2f;
417             tp.showTextAligned(PdfContentByte.ALIGN_LEFT, tokenizer.nextToken(), 3, yPos, 0);
418         }
419         tp.endText();
420         tp.restoreState();
421         tp.endVariableText();
422         field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
423     }
424 
425     /**
426      * @param name
427      * @param value
428      * @param status
429      * @param llx
430      * @param lly
431      * @param urx
432      * @param ury
433      * @return a PdfFormField
434      */
addCheckBox(String name, String value, boolean status, float llx, float lly, float urx, float ury)435     public PdfFormField addCheckBox(String name, String value, boolean status, float llx, float lly, float urx, float ury) {
436         PdfFormField field = PdfFormField.createCheckBox(writer);
437         setCheckBoxParams(field, name, value, status, llx, lly, urx, ury);
438         drawCheckBoxAppearences(field, value, llx, lly, urx, ury);
439         addFormField(field);
440         return field;
441     }
442 
443     /**
444      * @param field
445      * @param name
446      * @param value
447      * @param status
448      * @param llx
449      * @param lly
450      * @param urx
451      * @param ury
452      */
setCheckBoxParams(PdfFormField field, String name, String value, boolean status, float llx, float lly, float urx, float ury)453     public void setCheckBoxParams(PdfFormField field, String name, String value, boolean status, float llx, float lly, float urx, float ury) {
454         field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
455         field.setFieldName(name);
456         if (status) {
457             field.setValueAsName(value);
458             field.setAppearanceState(value);
459         }
460         else {
461             field.setValueAsName("Off");
462             field.setAppearanceState("Off");
463         }
464         field.setFlags(PdfAnnotation.FLAGS_PRINT);
465         field.setPage();
466         field.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
467     }
468 
469     /**
470      * @param field
471      * @param value
472      * @param llx
473      * @param lly
474      * @param urx
475      * @param ury
476      */
drawCheckBoxAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury)477     public void drawCheckBoxAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
478         BaseFont font = null;
479         try {
480             font = BaseFont.createFont(BaseFont.ZAPFDINGBATS, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
481         }
482         catch(Exception e) {
483             throw new ExceptionConverter(e);
484         }
485         float size = (ury - lly);
486         PdfContentByte cb = writer.getDirectContent();
487         PdfAppearance tpOn = cb.createAppearance(urx - llx, ury - lly);
488         PdfAppearance tp2 = (PdfAppearance)tpOn.getDuplicate();
489         tp2.setFontAndSize(font, size);
490         tp2.resetRGBColorFill();
491         field.setDefaultAppearanceString(tp2);
492         tpOn.drawTextField(0f, 0f, urx - llx, ury - lly);
493         tpOn.saveState();
494         tpOn.resetRGBColorFill();
495         tpOn.beginText();
496         tpOn.setFontAndSize(font, size);
497         tpOn.showTextAligned(PdfContentByte.ALIGN_CENTER, "4", (urx - llx) / 2, (ury - lly) / 2 - (size * 0.3f), 0);
498         tpOn.endText();
499         tpOn.restoreState();
500         field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
501         PdfAppearance tpOff = cb.createAppearance(urx - llx, ury - lly);
502         tpOff.drawTextField(0f, 0f, urx - llx, ury - lly);
503         field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
504     }
505 
506     /**
507      * @param name
508      * @param defaultValue
509      * @param noToggleToOff
510      * @return a PdfFormField
511      */
getRadioGroup(String name, String defaultValue, boolean noToggleToOff)512     public PdfFormField getRadioGroup(String name, String defaultValue, boolean noToggleToOff) {
513         PdfFormField radio = PdfFormField.createRadioButton(writer, noToggleToOff);
514         radio.setFieldName(name);
515         radio.setValueAsName(defaultValue);
516         return radio;
517     }
518 
519     /**
520      * @param radiogroup
521      */
addRadioGroup(PdfFormField radiogroup)522     public void addRadioGroup(PdfFormField radiogroup) {
523         addFormField(radiogroup);
524     }
525 
526     /**
527      * @param radiogroup
528      * @param value
529      * @param llx
530      * @param lly
531      * @param urx
532      * @param ury
533      * @return a PdfFormField
534      */
addRadioButton(PdfFormField radiogroup, String value, float llx, float lly, float urx, float ury)535     public PdfFormField addRadioButton(PdfFormField radiogroup, String value, float llx, float lly, float urx, float ury) {
536         PdfFormField radio = PdfFormField.createEmpty(writer);
537         radio.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
538         String name = ((PdfName)radiogroup.get(PdfName.V)).toString().substring(1);
539         if (name.equals(value)) {
540             radio.setAppearanceState(value);
541         }
542         else {
543             radio.setAppearanceState("Off");
544         }
545         drawRadioAppearences(radio, value, llx, lly, urx, ury);
546         radiogroup.addKid(radio);
547         return radio;
548     }
549 
550     /**
551      * @param field
552      * @param value
553      * @param llx
554      * @param lly
555      * @param urx
556      * @param ury
557      */
drawRadioAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury)558     public void drawRadioAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
559         PdfContentByte cb = writer.getDirectContent();
560         PdfAppearance tpOn = cb.createAppearance(urx - llx, ury - lly);
561         tpOn.drawRadioField(0f, 0f, urx - llx, ury - lly, true);
562         field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
563         PdfAppearance tpOff = cb.createAppearance(urx - llx, ury - lly);
564         tpOff.drawRadioField(0f, 0f, urx - llx, ury - lly, false);
565         field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
566     }
567 
568     /**
569      * @param name
570      * @param options
571      * @param defaultValue
572      * @param font
573      * @param fontSize
574      * @param llx
575      * @param lly
576      * @param urx
577      * @param ury
578      * @return a PdfFormField
579      */
addSelectList(String name, String[] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)580     public PdfFormField addSelectList(String name, String[] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
581         PdfFormField choice = PdfFormField.createList(writer, options, 0);
582         setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
583         StringBuffer text = new StringBuffer();
584         for (int i = 0; i < options.length; i++) {
585             text.append(options[i]).append("\n");
586         }
587         drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
588         addFormField(choice);
589         return choice;
590     }
591 
592     /**
593      * @param name
594      * @param options
595      * @param defaultValue
596      * @param font
597      * @param fontSize
598      * @param llx
599      * @param lly
600      * @param urx
601      * @param ury
602      * @return a PdfFormField
603      */
addSelectList(String name, String[][] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)604     public PdfFormField addSelectList(String name, String[][] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
605         PdfFormField choice = PdfFormField.createList(writer, options, 0);
606         setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
607         StringBuffer text = new StringBuffer();
608         for (int i = 0; i < options.length; i++) {
609             text.append(options[i][1]).append("\n");
610         }
611         drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
612         addFormField(choice);
613         return choice;
614     }
615 
616     /**
617      * @param name
618      * @param options
619      * @param defaultValue
620      * @param editable
621      * @param font
622      * @param fontSize
623      * @param llx
624      * @param lly
625      * @param urx
626      * @param ury
627      * @return a PdfFormField
628      */
addComboBox(String name, String[] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)629     public PdfFormField addComboBox(String name, String[] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
630         PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
631         setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
632         if (defaultValue == null) {
633             defaultValue = options[0];
634         }
635         drawSingleLineOfText(choice, defaultValue, font, fontSize, llx, lly, urx, ury);
636         addFormField(choice);
637         return choice;
638     }
639 
640     /**
641      * @param name
642      * @param options
643      * @param defaultValue
644      * @param editable
645      * @param font
646      * @param fontSize
647      * @param llx
648      * @param lly
649      * @param urx
650      * @param ury
651      * @return a PdfFormField
652      */
addComboBox(String name, String[][] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury)653     public PdfFormField addComboBox(String name, String[][] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
654         PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
655         setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
656         String value = null;
657         for (int i = 0; i < options.length; i++) {
658             if (options[i][0].equals(defaultValue)) {
659                 value = options[i][1];
660                 break;
661             }
662         }
663         if (value == null) {
664             value = options[0][1];
665         }
666         drawSingleLineOfText(choice, value, font, fontSize, llx, lly, urx, ury);
667         addFormField(choice);
668         return choice;
669     }
670 
671     /**
672      * @param field
673      * @param name
674      * @param defaultValue
675      * @param llx
676      * @param lly
677      * @param urx
678      * @param ury
679      */
setChoiceParams(PdfFormField field, String name, String defaultValue, float llx, float lly, float urx, float ury)680     public void setChoiceParams(PdfFormField field, String name, String defaultValue, float llx, float lly, float urx, float ury) {
681         field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
682         if (defaultValue != null) {
683             field.setValueAsString(defaultValue);
684             field.setDefaultValueAsString(defaultValue);
685         }
686         field.setFieldName(name);
687         field.setFlags(PdfAnnotation.FLAGS_PRINT);
688         field.setPage();
689         field.setBorderStyle(new PdfBorderDictionary(2, PdfBorderDictionary.STYLE_SOLID));
690     }
691 
692     /**
693      * @param name
694      * @param llx
695      * @param lly
696      * @param urx
697      * @param ury
698      * @return a PdfFormField
699      */
addSignature(String name, float llx, float lly, float urx, float ury)700     public PdfFormField addSignature(String name,
701                     float llx, float lly, float urx, float ury) {
702         PdfFormField signature = PdfFormField.createSignature(writer);
703         setSignatureParams(signature, name, llx, lly, urx, ury);
704         drawSignatureAppearences(signature, llx, lly, urx, ury);
705         addFormField(signature);
706         return signature;
707     }
708 
709     /**
710      * @param field
711      * @param name
712      * @param llx
713      * @param lly
714      * @param urx
715      * @param ury
716      */
setSignatureParams(PdfFormField field, String name, float llx, float lly, float urx, float ury)717     public void setSignatureParams(PdfFormField field, String name,
718                     float llx, float lly, float urx, float ury) {
719         field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
720         field.setFieldName(name);
721         field.setFlags(PdfAnnotation.FLAGS_PRINT);
722         field.setPage();
723         field.setMKBorderColor(java.awt.Color.black);
724         field.setMKBackgroundColor(java.awt.Color.white);
725     }
726 
727     /**
728      * @param field
729      * @param llx
730      * @param lly
731      * @param urx
732      * @param ury
733      */
drawSignatureAppearences(PdfFormField field, float llx, float lly, float urx, float ury)734     public void drawSignatureAppearences(PdfFormField field,
735                     float llx, float lly, float urx, float ury) {
736         PdfContentByte cb = writer.getDirectContent();
737         PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
738         tp.setGrayFill(1.0f);
739         tp.rectangle(0, 0, urx - llx, ury - lly);
740         tp.fill();
741         tp.setGrayStroke(0);
742         tp.setLineWidth(1);
743         tp.rectangle(0.5f, 0.5f, urx - llx - 0.5f, ury - lly - 0.5f);
744         tp.closePathStroke();
745         tp.saveState();
746         tp.rectangle(1, 1, urx - llx - 2, ury - lly - 2);
747         tp.clip();
748         tp.newPath();
749         tp.restoreState();
750         field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
751     }
752 }