1 /*
2  * Copyright 2005 by Paulo Soares.
3  *
4  * The contents of this file are subject to the Mozilla Public License Version 1.1
5  * (the "License"); you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the License.
11  *
12  * The Original Code is 'iText, a free JAVA-PDF library'.
13  *
14  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
15  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
16  * All Rights Reserved.
17  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
18  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
19  *
20  * Contributor(s): all the names of the contributors are added in the source code
21  * where applicable.
22  *
23  * Alternatively, the contents of this file may be used under the terms of the
24  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
25  * provisions of LGPL are applicable instead of those above.  If you wish to
26  * allow use of your version of this file only under the terms of the LGPL
27  * License and not to allow others to use your version of this file under
28  * the MPL, indicate your decision by deleting the provisions above and
29  * replace them with the notice and other provisions required by the LGPL.
30  * If you do not delete the provisions above, a recipient may use your version
31  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
32  *
33  * This library is free software; you can redistribute it and/or modify it
34  * under the terms of the MPL as stated above or under the terms of the GNU
35  * Library General Public License as published by the Free Software Foundation;
36  * either version 2 of the License, or any later version.
37  *
38  * This library is distributed in the hope that it will be useful, but WITHOUT
39  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
40  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
41  * details.
42  *
43  * If you didn't download this code from the following link, you should check if
44  * you aren't using an obsolete version:
45  * http://www.lowagie.com/iText/
46  */
47 package com.lowagie.text.pdf;
48 
49 import java.io.IOException;
50 import com.lowagie.text.error_messages.MessageLocalization;
51 
52 import com.lowagie.text.DocumentException;
53 import com.lowagie.text.Image;
54 import com.lowagie.text.Rectangle;
55 /**
56  * Creates a pushbutton field. It supports all the text and icon alignments.
57  * The icon may be an image or a template.
58  * <p>
59  * Example usage:
60  * <p>
61  * <PRE>
62  * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
63  * PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
64  * document.open();
65  * PdfContentByte cb = writer.getDirectContent();
66  * Image img = Image.getInstance("image.png");
67  * PushbuttonField bt = new PushbuttonField(writer, new Rectangle(100, 100, 200, 200), "Button1");
68  * bt.setText("My Caption");
69  * bt.setFontSize(0);
70  * bt.setImage(img);
71  * bt.setLayout(PushbuttonField.LAYOUT_ICON_TOP_LABEL_BOTTOM);
72  * bt.setBackgroundColor(Color.cyan);
73  * bt.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
74  * bt.setBorderColor(Color.red);
75  * bt.setBorderWidth(3);
76  * PdfFormField ff = bt.getField();
77  * PdfAction ac = PdfAction.createSubmitForm("http://www.submit-site.com", null, 0);
78  * ff.setAction(ac);
79  * writer.addAnnotation(ff);
80  * document.close();
81  * </PRE>
82  * @author Paulo Soares (psoares@consiste.pt)
83  */
84 public class PushbuttonField extends BaseField {
85 
86     /** A layout option */
87     public static final int LAYOUT_LABEL_ONLY = 1;
88     /** A layout option */
89     public static final int LAYOUT_ICON_ONLY = 2;
90     /** A layout option */
91     public static final int LAYOUT_ICON_TOP_LABEL_BOTTOM = 3;
92     /** A layout option */
93     public static final int LAYOUT_LABEL_TOP_ICON_BOTTOM = 4;
94     /** A layout option */
95     public static final int LAYOUT_ICON_LEFT_LABEL_RIGHT = 5;
96     /** A layout option */
97     public static final int LAYOUT_LABEL_LEFT_ICON_RIGHT = 6;
98     /** A layout option */
99     public static final int LAYOUT_LABEL_OVER_ICON = 7;
100     /** An icon scaling option */
101     public static final int SCALE_ICON_ALWAYS  = 1;
102     /** An icon scaling option */
103     public static final int SCALE_ICON_NEVER = 2;
104     /** An icon scaling option */
105     public static final int SCALE_ICON_IS_TOO_BIG = 3;
106     /** An icon scaling option */
107     public static final int SCALE_ICON_IS_TOO_SMALL = 4;
108 
109     /**
110      * Holds value of property layout.
111      */
112     private int layout = LAYOUT_LABEL_ONLY;
113 
114     /**
115      * Holds value of property image.
116      */
117     private Image image;
118 
119     /**
120      * Holds value of property template.
121      */
122     private PdfTemplate template;
123 
124     /**
125      * Holds value of property scaleIcon.
126      */
127     private int scaleIcon = SCALE_ICON_ALWAYS;
128 
129     /**
130      * Holds value of property proportionalIcon.
131      */
132     private boolean proportionalIcon = true;
133 
134     /**
135      * Holds value of property iconVerticalAdjustment.
136      */
137     private float iconVerticalAdjustment = 0.5f;
138 
139     /**
140      * Holds value of property iconHorizontalAdjustment.
141      */
142     private float iconHorizontalAdjustment = 0.5f;
143 
144     /**
145      * Holds value of property iconFitToBounds.
146      */
147     private boolean iconFitToBounds;
148 
149     private PdfTemplate tp;
150 
151     /**
152      * Creates a new instance of PushbuttonField
153      * @param writer the document <CODE>PdfWriter</CODE>
154      * @param box the field location and dimensions
155      * @param fieldName the field name. If <CODE>null</CODE> only the widget keys
156      * will be included in the field allowing it to be used as a kid field.
157      */
PushbuttonField(PdfWriter writer, Rectangle box, String fieldName)158     public PushbuttonField(PdfWriter writer, Rectangle box, String fieldName) {
159         super(writer, box, fieldName);
160     }
161 
162     /**
163      * Getter for property layout.
164      * @return Value of property layout.
165      */
getLayout()166     public int getLayout() {
167         return this.layout;
168     }
169 
170     /**
171      * Sets the icon and label layout. Possible values are <CODE>LAYOUT_LABEL_ONLY</CODE>,
172      * <CODE>LAYOUT_ICON_ONLY</CODE>, <CODE>LAYOUT_ICON_TOP_LABEL_BOTTOM</CODE>,
173      * <CODE>LAYOUT_LABEL_TOP_ICON_BOTTOM</CODE>, <CODE>LAYOUT_ICON_LEFT_LABEL_RIGHT</CODE>,
174      * <CODE>LAYOUT_LABEL_LEFT_ICON_RIGHT</CODE> and <CODE>LAYOUT_LABEL_OVER_ICON</CODE>.
175      * The default is <CODE>LAYOUT_LABEL_ONLY</CODE>.
176      * @param layout New value of property layout.
177      */
setLayout(int layout)178     public void setLayout(int layout) {
179         if (layout < LAYOUT_LABEL_ONLY || layout > LAYOUT_LABEL_OVER_ICON)
180             throw new IllegalArgumentException(MessageLocalization.getComposedMessage("layout.out.of.bounds"));
181         this.layout = layout;
182     }
183 
184     /**
185      * Getter for property image.
186      * @return Value of property image.
187      */
getImage()188     public Image getImage() {
189         return this.image;
190     }
191 
192     /**
193      * Sets the icon as an image.
194      * @param image the image
195      */
setImage(Image image)196     public void setImage(Image image) {
197         this.image = image;
198         template = null;
199     }
200 
201     /**
202      * Getter for property template.
203      * @return Value of property template.
204      */
getTemplate()205     public PdfTemplate getTemplate() {
206         return this.template;
207     }
208 
209     /**
210      * Sets the icon as a template.
211      * @param template the template
212      */
setTemplate(PdfTemplate template)213     public void setTemplate(PdfTemplate template) {
214         this.template = template;
215         image = null;
216     }
217 
218     /**
219      * Getter for property scaleIcon.
220      * @return Value of property scaleIcon.
221      */
getScaleIcon()222     public int getScaleIcon() {
223         return this.scaleIcon;
224     }
225 
226     /**
227      * Sets the way the icon will be scaled. Possible values are
228      * <CODE>SCALE_ICON_ALWAYS</CODE>, <CODE>SCALE_ICON_NEVER</CODE>,
229      * <CODE>SCALE_ICON_IS_TOO_BIG</CODE> and <CODE>SCALE_ICON_IS_TOO_SMALL</CODE>.
230      * The default is <CODE>SCALE_ICON_ALWAYS</CODE>.
231      * @param scaleIcon the way the icon will be scaled
232      */
setScaleIcon(int scaleIcon)233     public void setScaleIcon(int scaleIcon) {
234         if (scaleIcon < SCALE_ICON_ALWAYS || scaleIcon > SCALE_ICON_IS_TOO_SMALL)
235             scaleIcon = SCALE_ICON_ALWAYS;
236         this.scaleIcon = scaleIcon;
237     }
238 
239     /**
240      * Getter for property proportionalIcon.
241      * @return Value of property proportionalIcon.
242      */
isProportionalIcon()243     public boolean isProportionalIcon() {
244         return this.proportionalIcon;
245     }
246 
247     /**
248      * Sets the way the icon is scaled. If <CODE>true</CODE> the icon is scaled proportionally,
249      * if <CODE>false</CODE> the scaling is done anamorphicaly.
250      * @param proportionalIcon the way the icon is scaled
251      */
setProportionalIcon(boolean proportionalIcon)252     public void setProportionalIcon(boolean proportionalIcon) {
253         this.proportionalIcon = proportionalIcon;
254     }
255 
256     /**
257      * Getter for property iconVerticalAdjustment.
258      * @return Value of property iconVerticalAdjustment.
259      */
getIconVerticalAdjustment()260     public float getIconVerticalAdjustment() {
261         return this.iconVerticalAdjustment;
262     }
263 
264     /**
265      * A number between 0 and 1 indicating the fraction of leftover space to allocate at the bottom of the icon.
266      * A value of 0 positions the icon at the bottom of the annotation rectangle.
267      * A value of 0.5 centers it within the rectangle. The default is 0.5.
268      * @param iconVerticalAdjustment a number between 0 and 1 indicating the fraction of leftover space to allocate at the bottom of the icon
269      */
setIconVerticalAdjustment(float iconVerticalAdjustment)270     public void setIconVerticalAdjustment(float iconVerticalAdjustment) {
271         if (iconVerticalAdjustment < 0)
272             iconVerticalAdjustment = 0;
273         else if (iconVerticalAdjustment > 1)
274             iconVerticalAdjustment = 1;
275         this.iconVerticalAdjustment = iconVerticalAdjustment;
276     }
277 
278     /**
279      * Getter for property iconHorizontalAdjustment.
280      * @return Value of property iconHorizontalAdjustment.
281      */
getIconHorizontalAdjustment()282     public float getIconHorizontalAdjustment() {
283         return this.iconHorizontalAdjustment;
284     }
285 
286     /**
287      * A number between 0 and 1 indicating the fraction of leftover space to allocate at the left of the icon.
288      * A value of 0 positions the icon at the left of the annotation rectangle.
289      * A value of 0.5 centers it within the rectangle. The default is 0.5.
290      * @param iconHorizontalAdjustment a number between 0 and 1 indicating the fraction of leftover space to allocate at the left of the icon
291      */
setIconHorizontalAdjustment(float iconHorizontalAdjustment)292     public void setIconHorizontalAdjustment(float iconHorizontalAdjustment) {
293         if (iconHorizontalAdjustment < 0)
294             iconHorizontalAdjustment = 0;
295         else if (iconHorizontalAdjustment > 1)
296             iconHorizontalAdjustment = 1;
297         this.iconHorizontalAdjustment = iconHorizontalAdjustment;
298     }
299 
calculateFontSize(float w, float h)300     private float calculateFontSize(float w, float h) throws IOException, DocumentException {
301         BaseFont ufont = getRealFont();
302         float fsize = fontSize;
303         if (fsize == 0) {
304             float bw = ufont.getWidthPoint(text, 1);
305             if (bw == 0)
306                 fsize = 12;
307             else
308                 fsize = w / bw;
309             float nfsize = h / (1 - ufont.getFontDescriptor(BaseFont.DESCENT, 1));
310             fsize = Math.min(fsize, nfsize);
311             if (fsize < 4)
312                 fsize = 4;
313         }
314         return fsize;
315     }
316 
317     /**
318      * Gets the button appearance.
319      * @throws IOException on error
320      * @throws DocumentException on error
321      * @return the button appearance
322      */
getAppearance()323     public PdfAppearance getAppearance() throws IOException, DocumentException {
324         PdfAppearance app = getBorderAppearance();
325         Rectangle box = new Rectangle(app.getBoundingBox());
326         if ((text == null || text.length() == 0) && (layout == LAYOUT_LABEL_ONLY || (image == null && template == null && iconReference == null))) {
327             return app;
328         }
329         if (layout == LAYOUT_ICON_ONLY && image == null && template == null && iconReference == null)
330             return app;
331         BaseFont ufont = getRealFont();
332         boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
333         float h = box.getHeight() - borderWidth * 2;
334         float bw2 = borderWidth;
335         if (borderExtra) {
336             h -= borderWidth * 2;
337             bw2 *= 2;
338         }
339         float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
340         offsetX = Math.max(offsetX, 1);
341         float offX = Math.min(bw2, offsetX);
342         tp = null;
343         float textX = Float.NaN;
344         float textY = 0;
345         float fsize = fontSize;
346         float wt = box.getWidth() - 2 * offX - 2;
347         float ht = box.getHeight() - 2 * offX;
348         float adj = (iconFitToBounds ? 0 : offX + 1);
349         int nlayout = layout;
350         if (image == null && template == null && iconReference == null)
351             nlayout = LAYOUT_LABEL_ONLY;
352         Rectangle iconBox = null;
353         while (true) {
354             switch (nlayout) {
355                 case LAYOUT_LABEL_ONLY:
356                 case LAYOUT_LABEL_OVER_ICON:
357                     if (text != null && text.length() > 0 && wt > 0 && ht > 0) {
358                         fsize = calculateFontSize(wt, ht);
359                         textX = (box.getWidth() - ufont.getWidthPoint(text, fsize)) / 2;
360                         textY = (box.getHeight() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
361                     }
362                 case LAYOUT_ICON_ONLY:
363                     if (nlayout == LAYOUT_LABEL_OVER_ICON || nlayout == LAYOUT_ICON_ONLY)
364                         iconBox = new Rectangle(box.getLeft() + adj, box.getBottom() + adj, box.getRight() - adj, box.getTop() - adj);
365                     break;
366                 case LAYOUT_ICON_TOP_LABEL_BOTTOM:
367                     if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
368                         nlayout = LAYOUT_ICON_ONLY;
369                         continue;
370                     }
371                     float nht = box.getHeight() * 0.35f - offX;
372                     if (nht > 0)
373                         fsize = calculateFontSize(wt, nht);
374                     else
375                         fsize = 4;
376                     textX = (box.getWidth() - ufont.getWidthPoint(text, fsize)) / 2;
377                     textY = offX - ufont.getFontDescriptor(BaseFont.DESCENT, fsize);
378                     iconBox = new Rectangle(box.getLeft() + adj, textY + fsize, box.getRight() - adj, box.getTop() - adj);
379                     break;
380                 case LAYOUT_LABEL_TOP_ICON_BOTTOM:
381                     if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
382                         nlayout = LAYOUT_ICON_ONLY;
383                         continue;
384                     }
385                     nht = box.getHeight() * 0.35f - offX;
386                     if (nht > 0)
387                         fsize = calculateFontSize(wt, nht);
388                     else
389                         fsize = 4;
390                     textX = (box.getWidth() - ufont.getWidthPoint(text, fsize)) / 2;
391                     textY = box.getHeight() - offX - fsize;
392                     if (textY < offX)
393                         textY = offX;
394                     iconBox = new Rectangle(box.getLeft() + adj, box.getBottom() + adj, box.getRight() - adj, textY + ufont.getFontDescriptor(BaseFont.DESCENT, fsize));
395                     break;
396                 case LAYOUT_LABEL_LEFT_ICON_RIGHT:
397                     if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
398                         nlayout = LAYOUT_ICON_ONLY;
399                         continue;
400                     }
401                     float nw = box.getWidth() * 0.35f - offX;
402                     if (nw > 0)
403                         fsize = calculateFontSize(wt, nw);
404                     else
405                         fsize = 4;
406                     if (ufont.getWidthPoint(text, fsize) >= wt) {
407                         nlayout = LAYOUT_LABEL_ONLY;
408                         fsize = fontSize;
409                         continue;
410                     }
411                     textX = offX + 1;
412                     textY = (box.getHeight() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
413                     iconBox = new Rectangle(textX + ufont.getWidthPoint(text, fsize), box.getBottom() + adj, box.getRight() - adj, box.getTop() - adj);
414                     break;
415                 case LAYOUT_ICON_LEFT_LABEL_RIGHT:
416                     if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
417                         nlayout = LAYOUT_ICON_ONLY;
418                         continue;
419                     }
420                     nw = box.getWidth() * 0.35f - offX;
421                     if (nw > 0)
422                         fsize = calculateFontSize(wt, nw);
423                     else
424                         fsize = 4;
425                     if (ufont.getWidthPoint(text, fsize) >= wt) {
426                         nlayout = LAYOUT_LABEL_ONLY;
427                         fsize = fontSize;
428                         continue;
429                     }
430                     textX = box.getWidth() - ufont.getWidthPoint(text, fsize) - offX - 1;
431                     textY = (box.getHeight() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
432                     iconBox = new Rectangle(box.getLeft() + adj, box.getBottom() + adj, textX - 1, box.getTop() - adj);
433                     break;
434             }
435             break;
436         }
437         if (textY < box.getBottom() + offX)
438             textY = box.getBottom() + offX;
439         if (iconBox != null && (iconBox.getWidth() <= 0 || iconBox.getHeight() <= 0))
440             iconBox = null;
441         boolean haveIcon = false;
442         float boundingBoxWidth = 0;
443         float boundingBoxHeight = 0;
444         PdfArray matrix = null;
445         if (iconBox != null) {
446             if (image != null) {
447                 tp = new PdfTemplate(writer);
448                 tp.setBoundingBox(new Rectangle(image));
449                 writer.addDirectTemplateSimple(tp, PdfName.FRM);
450                 tp.addImage(image, image.getWidth(), 0, 0, image.getHeight(), 0, 0);
451                 haveIcon = true;
452                 boundingBoxWidth = tp.getBoundingBox().getWidth();
453                 boundingBoxHeight = tp.getBoundingBox().getHeight();
454             }
455             else if (template != null) {
456                 tp = new PdfTemplate(writer);
457                 tp.setBoundingBox(new Rectangle(template.getWidth(), template.getHeight()));
458                 writer.addDirectTemplateSimple(tp, PdfName.FRM);
459                 tp.addTemplate(template, template.getBoundingBox().getLeft(), template.getBoundingBox().getBottom());
460                 haveIcon = true;
461                 boundingBoxWidth = tp.getBoundingBox().getWidth();
462                 boundingBoxHeight = tp.getBoundingBox().getHeight();
463             }
464             else if (iconReference != null) {
465                 PdfDictionary dic = (PdfDictionary)PdfReader.getPdfObject(iconReference);
466                 if (dic != null) {
467                     Rectangle r2 = PdfReader.getNormalizedRectangle(dic.getAsArray(PdfName.BBOX));
468                     matrix = dic.getAsArray(PdfName.MATRIX);
469                     haveIcon = true;
470                     boundingBoxWidth = r2.getWidth();
471                     boundingBoxHeight = r2.getHeight();
472                 }
473             }
474         }
475         if (haveIcon) {
476             float icx = iconBox.getWidth() / boundingBoxWidth;
477             float icy = iconBox.getHeight() / boundingBoxHeight;
478             if (proportionalIcon) {
479                 switch (scaleIcon) {
480                     case SCALE_ICON_IS_TOO_BIG:
481                         icx = Math.min(icx, icy);
482                         icx = Math.min(icx, 1);
483                         break;
484                     case SCALE_ICON_IS_TOO_SMALL:
485                         icx = Math.min(icx, icy);
486                         icx = Math.max(icx, 1);
487                         break;
488                     case SCALE_ICON_NEVER:
489                         icx = 1;
490                         break;
491                     default:
492                         icx = Math.min(icx, icy);
493                         break;
494                 }
495                 icy = icx;
496             }
497             else {
498                 switch (scaleIcon) {
499                     case SCALE_ICON_IS_TOO_BIG:
500                         icx = Math.min(icx, 1);
501                         icy = Math.min(icy, 1);
502                         break;
503                     case SCALE_ICON_IS_TOO_SMALL:
504                         icx = Math.max(icx, 1);
505                         icy = Math.max(icy, 1);
506                         break;
507                     case SCALE_ICON_NEVER:
508                         icx = icy = 1;
509                         break;
510                     default:
511                         break;
512                 }
513             }
514             float xpos = iconBox.getLeft() + (iconBox.getWidth() - (boundingBoxWidth * icx)) * iconHorizontalAdjustment;
515             float ypos = iconBox.getBottom() + (iconBox.getHeight() - (boundingBoxHeight * icy)) * iconVerticalAdjustment;
516             app.saveState();
517             app.rectangle(iconBox.getLeft(), iconBox.getBottom(), iconBox.getWidth(), iconBox.getHeight());
518             app.clip();
519             app.newPath();
520             if (tp != null)
521                 app.addTemplate(tp, icx, 0, 0, icy, xpos, ypos);
522             else {
523                 float cox = 0;
524                 float coy = 0;
525                 if (matrix != null && matrix.size() == 6) {
526                     PdfNumber nm = matrix.getAsNumber(4);
527                     if (nm != null)
528                         cox = nm.floatValue();
529                     nm = matrix.getAsNumber(5);
530                     if (nm != null)
531                         coy = nm.floatValue();
532                 }
533                 app.addTemplateReference(iconReference, PdfName.FRM, icx, 0, 0, icy, xpos - cox * icx, ypos - coy * icy);
534             }
535             app.restoreState();
536         }
537         if (!Float.isNaN(textX)) {
538             app.saveState();
539             app.rectangle(offX, offX, box.getWidth() - 2 * offX, box.getHeight() - 2 * offX);
540             app.clip();
541             app.newPath();
542             if (textColor == null)
543                 app.resetGrayFill();
544             else
545                 app.setColorFill(textColor);
546             app.beginText();
547             app.setFontAndSize(ufont, fsize);
548             app.setTextMatrix(textX, textY);
549             app.showText(text);
550             app.endText();
551             app.restoreState();
552         }
553         return app;
554     }
555 
556     /**
557      * Gets the pushbutton field.
558      * @throws IOException on error
559      * @throws DocumentException on error
560      * @return the pushbutton field
561      */
getField()562     public PdfFormField getField() throws IOException, DocumentException {
563         PdfFormField field = PdfFormField.createPushButton(writer);
564         field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
565         if (fieldName != null) {
566             field.setFieldName(fieldName);
567             if ((options & READ_ONLY) != 0)
568                 field.setFieldFlags(PdfFormField.FF_READ_ONLY);
569             if ((options & REQUIRED) != 0)
570                 field.setFieldFlags(PdfFormField.FF_REQUIRED);
571         }
572         if (text != null)
573             field.setMKNormalCaption(text);
574         if (rotation != 0)
575             field.setMKRotation(rotation);
576         field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
577         PdfAppearance tpa = getAppearance();
578         field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tpa);
579         PdfAppearance da = (PdfAppearance)tpa.getDuplicate();
580         da.setFontAndSize(getRealFont(), fontSize);
581         if (textColor == null)
582             da.setGrayFill(0);
583         else
584             da.setColorFill(textColor);
585         field.setDefaultAppearanceString(da);
586         if (borderColor != null)
587             field.setMKBorderColor(borderColor);
588         if (backgroundColor != null)
589             field.setMKBackgroundColor(backgroundColor);
590         switch (visibility) {
591             case HIDDEN:
592                 field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
593                 break;
594             case VISIBLE_BUT_DOES_NOT_PRINT:
595                 break;
596             case HIDDEN_BUT_PRINTABLE:
597                 field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
598                 break;
599             default:
600                 field.setFlags(PdfAnnotation.FLAGS_PRINT);
601                 break;
602         }
603         if (tp != null)
604             field.setMKNormalIcon(tp);
605         field.setMKTextPosition(layout - 1);
606         PdfName scale = PdfName.A;
607         if (scaleIcon == SCALE_ICON_IS_TOO_BIG)
608             scale = PdfName.B;
609         else if (scaleIcon == SCALE_ICON_IS_TOO_SMALL)
610             scale = PdfName.S;
611         else if (scaleIcon == SCALE_ICON_NEVER)
612             scale = PdfName.N;
613         field.setMKIconFit(scale, proportionalIcon ? PdfName.P : PdfName.A, iconHorizontalAdjustment,
614             iconVerticalAdjustment, iconFitToBounds);
615         return field;
616     }
617 
618     /**
619      * Getter for property iconFitToBounds.
620      * @return Value of property iconFitToBounds.
621      */
isIconFitToBounds()622     public boolean isIconFitToBounds() {
623         return this.iconFitToBounds;
624     }
625 
626     /**
627      * If <CODE>true</CODE> the icon will be scaled to fit fully within the bounds of the annotation,
628      * if <CODE>false</CODE> the border width will be taken into account. The default
629      * is <CODE>false</CODE>.
630      * @param iconFitToBounds if <CODE>true</CODE> the icon will be scaled to fit fully within the bounds of the annotation,
631      * if <CODE>false</CODE> the border width will be taken into account
632      */
setIconFitToBounds(boolean iconFitToBounds)633     public void setIconFitToBounds(boolean iconFitToBounds) {
634         this.iconFitToBounds = iconFitToBounds;
635     }
636 
637     /**
638      * Holds value of property iconReference.
639      */
640     private PRIndirectReference iconReference;
641 
642     /**
643      * Gets the reference to an existing icon.
644      * @return the reference to an existing icon.
645      */
getIconReference()646     public PRIndirectReference getIconReference() {
647         return this.iconReference;
648     }
649 
650     /**
651      * Sets the reference to an existing icon.
652      * @param iconReference the reference to an existing icon
653      */
setIconReference(PRIndirectReference iconReference)654     public void setIconReference(PRIndirectReference iconReference) {
655         this.iconReference = iconReference;
656     }
657 
658 }
659