001/*
002 * $Id: PushbuttonField.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf;
045
046import java.io.IOException;
047import com.itextpdf.text.error_messages.MessageLocalization;
048
049import com.itextpdf.text.DocumentException;
050import com.itextpdf.text.Image;
051import com.itextpdf.text.Rectangle;
052/**
053 * Creates a pushbutton field. It supports all the text and icon alignments.
054 * The icon may be an image or a template.
055 * <p>
056 * Example usage:
057 * <p>
058 * <PRE>
059 * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
060 * PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
061 * document.open();
062 * PdfContentByte cb = writer.getDirectContent();
063 * Image img = Image.getInstance("image.png");
064 * PushbuttonField bt = new PushbuttonField(writer, new Rectangle(100, 100, 200, 200), "Button1");
065 * bt.setText("My Caption");
066 * bt.setFontSize(0);
067 * bt.setImage(img);
068 * bt.setLayout(PushbuttonField.LAYOUT_ICON_TOP_LABEL_BOTTOM);
069 * bt.setBackgroundColor(Color.cyan);
070 * bt.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
071 * bt.setBorderColor(Color.red);
072 * bt.setBorderWidth(3);
073 * PdfFormField ff = bt.getField();
074 * PdfAction ac = PdfAction.createSubmitForm("http://www.submit-site.com", null, 0);
075 * ff.setAction(ac);
076 * writer.addAnnotation(ff);
077 * document.close();
078 * </PRE>
079 * @author Paulo Soares
080 */
081public class PushbuttonField extends BaseField {
082   
083    /** A layout option */    
084    public static final int LAYOUT_LABEL_ONLY = 1;
085    /** A layout option */    
086    public static final int LAYOUT_ICON_ONLY = 2;
087    /** A layout option */    
088    public static final int LAYOUT_ICON_TOP_LABEL_BOTTOM = 3;
089    /** A layout option */    
090    public static final int LAYOUT_LABEL_TOP_ICON_BOTTOM = 4;
091    /** A layout option */    
092    public static final int LAYOUT_ICON_LEFT_LABEL_RIGHT = 5;
093    /** A layout option */    
094    public static final int LAYOUT_LABEL_LEFT_ICON_RIGHT = 6;
095    /** A layout option */    
096    public static final int LAYOUT_LABEL_OVER_ICON = 7;
097    /** An icon scaling option */    
098    public static final int SCALE_ICON_ALWAYS  = 1;
099    /** An icon scaling option */    
100    public static final int SCALE_ICON_NEVER = 2;
101    /** An icon scaling option */    
102    public static final int SCALE_ICON_IS_TOO_BIG = 3;
103    /** An icon scaling option */    
104    public static final int SCALE_ICON_IS_TOO_SMALL = 4;
105
106    /**
107     * Holds value of property layout.
108     */
109    private int layout = LAYOUT_LABEL_ONLY;
110    
111    /**
112     * Holds value of property image.
113     */
114    private Image image;    
115    
116    /**
117     * Holds value of property template.
118     */
119    private PdfTemplate template;
120    
121    /**
122     * Holds value of property scaleIcon.
123     */
124    private int scaleIcon = SCALE_ICON_ALWAYS;
125    
126    /**
127     * Holds value of property proportionalIcon.
128     */
129    private boolean proportionalIcon = true;
130    
131    /**
132     * Holds value of property iconVerticalAdjustment.
133     */
134    private float iconVerticalAdjustment = 0.5f;
135    
136    /**
137     * Holds value of property iconHorizontalAdjustment.
138     */
139    private float iconHorizontalAdjustment = 0.5f;
140    
141    /**
142     * Holds value of property iconFitToBounds.
143     */
144    private boolean iconFitToBounds;
145    
146    private PdfTemplate tp;
147    
148    /**
149     * Creates a new instance of PushbuttonField
150     * @param writer the document <CODE>PdfWriter</CODE>
151     * @param box the field location and dimensions
152     * @param fieldName the field name. If <CODE>null</CODE> only the widget keys
153     * will be included in the field allowing it to be used as a kid field.
154     */
155    public PushbuttonField(PdfWriter writer, Rectangle box, String fieldName) {
156        super(writer, box, fieldName);
157    }
158    
159    /**
160     * Getter for property layout.
161     * @return Value of property layout.
162     */
163    public int getLayout() {
164        return this.layout;
165    }
166    
167    /**
168     * Sets the icon and label layout. Possible values are <CODE>LAYOUT_LABEL_ONLY</CODE>,
169     * <CODE>LAYOUT_ICON_ONLY</CODE>, <CODE>LAYOUT_ICON_TOP_LABEL_BOTTOM</CODE>,
170     * <CODE>LAYOUT_LABEL_TOP_ICON_BOTTOM</CODE>, <CODE>LAYOUT_ICON_LEFT_LABEL_RIGHT</CODE>,
171     * <CODE>LAYOUT_LABEL_LEFT_ICON_RIGHT</CODE> and <CODE>LAYOUT_LABEL_OVER_ICON</CODE>.
172     * The default is <CODE>LAYOUT_LABEL_ONLY</CODE>.
173     * @param layout New value of property layout.
174     */
175    public void setLayout(int layout) {
176        if (layout < LAYOUT_LABEL_ONLY || layout > LAYOUT_LABEL_OVER_ICON)
177            throw new IllegalArgumentException(MessageLocalization.getComposedMessage("layout.out.of.bounds"));
178        this.layout = layout;
179    }
180    
181    /**
182     * Getter for property image.
183     * @return Value of property image.
184     */
185    public Image getImage() {
186        return this.image;
187    }
188    
189    /**
190     * Sets the icon as an image.
191     * @param image the image
192     */
193    public void setImage(Image image) {
194        this.image = image;
195        template = null;
196    }
197    
198    /**
199     * Getter for property template.
200     * @return Value of property template.
201     */
202    public PdfTemplate getTemplate() {
203        return this.template;
204    }
205    
206    /**
207     * Sets the icon as a template.
208     * @param template the template
209     */
210    public void setTemplate(PdfTemplate template) {
211        this.template = template;
212        image = null;
213    }
214    
215    /**
216     * Getter for property scaleIcon.
217     * @return Value of property scaleIcon.
218     */
219    public int getScaleIcon() {
220        return this.scaleIcon;
221    }
222    
223    /**
224     * Sets the way the icon will be scaled. Possible values are
225     * <CODE>SCALE_ICON_ALWAYS</CODE>, <CODE>SCALE_ICON_NEVER</CODE>,
226     * <CODE>SCALE_ICON_IS_TOO_BIG</CODE> and <CODE>SCALE_ICON_IS_TOO_SMALL</CODE>.
227     * The default is <CODE>SCALE_ICON_ALWAYS</CODE>.
228     * @param scaleIcon the way the icon will be scaled
229     */
230    public void setScaleIcon(int scaleIcon) {
231        if (scaleIcon < SCALE_ICON_ALWAYS || scaleIcon > SCALE_ICON_IS_TOO_SMALL)
232            scaleIcon = SCALE_ICON_ALWAYS;
233        this.scaleIcon = scaleIcon;
234    }
235    
236    /**
237     * Getter for property proportionalIcon.
238     * @return Value of property proportionalIcon.
239     */
240    public boolean isProportionalIcon() {
241        return this.proportionalIcon;
242    }
243    
244    /**
245     * Sets the way the icon is scaled. If <CODE>true</CODE> the icon is scaled proportionally,
246     * if <CODE>false</CODE> the scaling is done anamorphicaly.
247     * @param proportionalIcon the way the icon is scaled
248     */
249    public void setProportionalIcon(boolean proportionalIcon) {
250        this.proportionalIcon = proportionalIcon;
251    }
252    
253    /**
254     * Getter for property iconVerticalAdjustment.
255     * @return Value of property iconVerticalAdjustment.
256     */
257    public float getIconVerticalAdjustment() {
258        return this.iconVerticalAdjustment;
259    }
260    
261    /**
262     * A number between 0 and 1 indicating the fraction of leftover space to allocate at the bottom of the icon.
263     * A value of 0 positions the icon at the bottom of the annotation rectangle.
264     * A value of 0.5 centers it within the rectangle. The default is 0.5.
265     * @param iconVerticalAdjustment a number between 0 and 1 indicating the fraction of leftover space to allocate at the bottom of the icon
266     */
267    public void setIconVerticalAdjustment(float iconVerticalAdjustment) {
268        if (iconVerticalAdjustment < 0)
269            iconVerticalAdjustment = 0;
270        else if (iconVerticalAdjustment > 1)
271            iconVerticalAdjustment = 1;
272        this.iconVerticalAdjustment = iconVerticalAdjustment;
273    }
274    
275    /**
276     * Getter for property iconHorizontalAdjustment.
277     * @return Value of property iconHorizontalAdjustment.
278     */
279    public float getIconHorizontalAdjustment() {
280        return this.iconHorizontalAdjustment;
281    }
282    
283    /**
284     * A number between 0 and 1 indicating the fraction of leftover space to allocate at the left of the icon.
285     * A value of 0 positions the icon at the left of the annotation rectangle.
286     * A value of 0.5 centers it within the rectangle. The default is 0.5.
287     * @param iconHorizontalAdjustment a number between 0 and 1 indicating the fraction of leftover space to allocate at the left of the icon
288     */
289    public void setIconHorizontalAdjustment(float iconHorizontalAdjustment) {
290        if (iconHorizontalAdjustment < 0)
291            iconHorizontalAdjustment = 0;
292        else if (iconHorizontalAdjustment > 1)
293            iconHorizontalAdjustment = 1;
294        this.iconHorizontalAdjustment = iconHorizontalAdjustment;
295    }
296    
297    private float calculateFontSize(float w, float h) throws IOException, DocumentException {
298        BaseFont ufont = getRealFont();
299        float fsize = fontSize;
300        if (fsize == 0) {
301            float bw = ufont.getWidthPoint(text, 1);
302            if (bw == 0)
303                fsize = 12;
304            else
305                fsize = w / bw;
306            float nfsize = h / (1 - ufont.getFontDescriptor(BaseFont.DESCENT, 1));
307            fsize = Math.min(fsize, nfsize);
308            if (fsize < 4)
309                fsize = 4;
310        }
311        return fsize;
312    }
313    
314    /**
315     * Gets the button appearance.
316     * @throws IOException on error
317     * @throws DocumentException on error
318     * @return the button appearance
319     */    
320    public PdfAppearance getAppearance() throws IOException, DocumentException {
321        PdfAppearance app = getBorderAppearance();
322        Rectangle box = new Rectangle(app.getBoundingBox());
323        if ((text == null || text.length() == 0) && (layout == LAYOUT_LABEL_ONLY || (image == null && template == null && iconReference == null))) {
324            return app;
325        }
326        if (layout == LAYOUT_ICON_ONLY && image == null && template == null && iconReference == null)
327            return app;
328        BaseFont ufont = getRealFont();
329        boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
330        float h = box.getHeight() - borderWidth * 2;
331        float bw2 = borderWidth;
332        if (borderExtra) {
333            h -= borderWidth * 2;
334            bw2 *= 2;
335        }
336        float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
337        offsetX = Math.max(offsetX, 1);
338        float offX = Math.min(bw2, offsetX);
339        tp = null;
340        float textX = Float.NaN;
341        float textY = 0;
342        float fsize = fontSize;
343        float wt = box.getWidth() - 2 * offX - 2;
344        float ht = box.getHeight() - 2 * offX;
345        float adj = (iconFitToBounds ? 0 : offX + 1);
346        int nlayout = layout;
347        if (image == null && template == null && iconReference == null)
348            nlayout = LAYOUT_LABEL_ONLY;
349        Rectangle iconBox = null;
350        while (true) {
351            switch (nlayout) {
352                case LAYOUT_LABEL_ONLY:
353                case LAYOUT_LABEL_OVER_ICON:
354                    if (text != null && text.length() > 0 && wt > 0 && ht > 0) {
355                        fsize = calculateFontSize(wt, ht);
356                        textX = (box.getWidth() - ufont.getWidthPoint(text, fsize)) / 2;
357                        textY = (box.getHeight() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
358                    }
359                case LAYOUT_ICON_ONLY:
360                    if (nlayout == LAYOUT_LABEL_OVER_ICON || nlayout == LAYOUT_ICON_ONLY)
361                        iconBox = new Rectangle(box.getLeft() + adj, box.getBottom() + adj, box.getRight() - adj, box.getTop() - adj);
362                    break;
363                case LAYOUT_ICON_TOP_LABEL_BOTTOM:
364                    if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
365                        nlayout = LAYOUT_ICON_ONLY;
366                        continue;
367                    }
368                    float nht = box.getHeight() * 0.35f - offX;
369                    if (nht > 0)
370                        fsize = calculateFontSize(wt, nht);
371                    else
372                        fsize = 4;
373                    textX = (box.getWidth() - ufont.getWidthPoint(text, fsize)) / 2;
374                    textY = offX - ufont.getFontDescriptor(BaseFont.DESCENT, fsize);
375                    iconBox = new Rectangle(box.getLeft() + adj, textY + fsize, box.getRight() - adj, box.getTop() - adj);
376                    break;
377                case LAYOUT_LABEL_TOP_ICON_BOTTOM:
378                    if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
379                        nlayout = LAYOUT_ICON_ONLY;
380                        continue;
381                    }
382                    nht = box.getHeight() * 0.35f - offX;
383                    if (nht > 0)
384                        fsize = calculateFontSize(wt, nht);
385                    else
386                        fsize = 4;
387                    textX = (box.getWidth() - ufont.getWidthPoint(text, fsize)) / 2;
388                    textY = box.getHeight() - offX - fsize;
389                    if (textY < offX)
390                        textY = offX;
391                    iconBox = new Rectangle(box.getLeft() + adj, box.getBottom() + adj, box.getRight() - adj, textY + ufont.getFontDescriptor(BaseFont.DESCENT, fsize));
392                    break;
393                case LAYOUT_LABEL_LEFT_ICON_RIGHT:
394                    if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
395                        nlayout = LAYOUT_ICON_ONLY;
396                        continue;
397                    }
398                    float nw = box.getWidth() * 0.35f - offX;
399                    if (nw > 0)
400                        fsize = calculateFontSize(wt, nw);
401                    else
402                        fsize = 4;
403                    if (ufont.getWidthPoint(text, fsize) >= wt) {
404                        nlayout = LAYOUT_LABEL_ONLY;
405                        fsize = fontSize;
406                        continue;
407                    }
408                    textX = offX + 1;
409                    textY = (box.getHeight() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
410                    iconBox = new Rectangle(textX + ufont.getWidthPoint(text, fsize), box.getBottom() + adj, box.getRight() - adj, box.getTop() - adj);
411                    break;
412                case LAYOUT_ICON_LEFT_LABEL_RIGHT:
413                    if (text == null || text.length() == 0 || wt <= 0 || ht <= 0) {
414                        nlayout = LAYOUT_ICON_ONLY;
415                        continue;
416                    }
417                    nw = box.getWidth() * 0.35f - offX;
418                    if (nw > 0)
419                        fsize = calculateFontSize(wt, nw);
420                    else
421                        fsize = 4;
422                    if (ufont.getWidthPoint(text, fsize) >= wt) {
423                        nlayout = LAYOUT_LABEL_ONLY;
424                        fsize = fontSize;
425                        continue;
426                    }
427                    textX = box.getWidth() - ufont.getWidthPoint(text, fsize) - offX - 1;
428                    textY = (box.getHeight() - ufont.getFontDescriptor(BaseFont.ASCENT, fsize)) / 2;
429                    iconBox = new Rectangle(box.getLeft() + adj, box.getBottom() + adj, textX - 1, box.getTop() - adj);
430                    break;
431            }
432            break;
433        }
434        if (textY < box.getBottom() + offX)
435            textY = box.getBottom() + offX;
436        if (iconBox != null && (iconBox.getWidth() <= 0 || iconBox.getHeight() <= 0))
437            iconBox = null;
438        boolean haveIcon = false;
439        float boundingBoxWidth = 0;
440        float boundingBoxHeight = 0;
441        PdfArray matrix = null;
442        if (iconBox != null) {
443            if (image != null) {
444                tp = new PdfTemplate(writer);
445                tp.setBoundingBox(new Rectangle(image));
446                writer.addDirectTemplateSimple(tp, PdfName.FRM);
447                tp.addImage(image, image.getWidth(), 0, 0, image.getHeight(), 0, 0);
448                haveIcon = true;
449                boundingBoxWidth = tp.getBoundingBox().getWidth();
450                boundingBoxHeight = tp.getBoundingBox().getHeight();
451            }
452            else if (template != null) {
453                tp = new PdfTemplate(writer);
454                tp.setBoundingBox(new Rectangle(template.getWidth(), template.getHeight()));
455                writer.addDirectTemplateSimple(tp, PdfName.FRM);
456                tp.addTemplate(template, template.getBoundingBox().getLeft(), template.getBoundingBox().getBottom());
457                haveIcon = true;
458                boundingBoxWidth = tp.getBoundingBox().getWidth();
459                boundingBoxHeight = tp.getBoundingBox().getHeight();
460            }
461            else if (iconReference != null) {
462                PdfDictionary dic = (PdfDictionary)PdfReader.getPdfObject(iconReference);
463                if (dic != null) {
464                    Rectangle r2 = PdfReader.getNormalizedRectangle(dic.getAsArray(PdfName.BBOX));
465                    matrix = dic.getAsArray(PdfName.MATRIX);
466                    haveIcon = true;
467                    boundingBoxWidth = r2.getWidth();
468                    boundingBoxHeight = r2.getHeight();
469                }
470            }
471        }
472        if (haveIcon) {
473            float icx = iconBox.getWidth() / boundingBoxWidth;
474            float icy = iconBox.getHeight() / boundingBoxHeight;
475            if (proportionalIcon) {
476                switch (scaleIcon) {
477                    case SCALE_ICON_IS_TOO_BIG:
478                        icx = Math.min(icx, icy);
479                        icx = Math.min(icx, 1);
480                        break;
481                    case SCALE_ICON_IS_TOO_SMALL:
482                        icx = Math.min(icx, icy);
483                        icx = Math.max(icx, 1);
484                        break;
485                    case SCALE_ICON_NEVER:
486                        icx = 1;
487                        break;
488                    default:
489                        icx = Math.min(icx, icy);
490                        break;
491                }
492                icy = icx;
493            }
494            else {
495                switch (scaleIcon) {
496                    case SCALE_ICON_IS_TOO_BIG:
497                        icx = Math.min(icx, 1);
498                        icy = Math.min(icy, 1);
499                        break;
500                    case SCALE_ICON_IS_TOO_SMALL:
501                        icx = Math.max(icx, 1);
502                        icy = Math.max(icy, 1);
503                        break;
504                    case SCALE_ICON_NEVER:
505                        icx = icy = 1;
506                        break;
507                    default:
508                        break;
509                }
510            }
511            float xpos = iconBox.getLeft() + (iconBox.getWidth() - (boundingBoxWidth * icx)) * iconHorizontalAdjustment;
512            float ypos = iconBox.getBottom() + (iconBox.getHeight() - (boundingBoxHeight * icy)) * iconVerticalAdjustment;
513            app.saveState();
514            app.rectangle(iconBox.getLeft(), iconBox.getBottom(), iconBox.getWidth(), iconBox.getHeight());
515            app.clip();
516            app.newPath();
517            if (tp != null)
518                app.addTemplate(tp, icx, 0, 0, icy, xpos, ypos);
519            else {
520                float cox = 0;
521                float coy = 0;
522                if (matrix != null && matrix.size() == 6) {
523                    PdfNumber nm = matrix.getAsNumber(4);
524                    if (nm != null)
525                        cox = nm.floatValue();
526                    nm = matrix.getAsNumber(5);
527                    if (nm != null)
528                        coy = nm.floatValue();
529                }
530                app.addTemplateReference(iconReference, PdfName.FRM, icx, 0, 0, icy, xpos - cox * icx, ypos - coy * icy);
531            }
532            app.restoreState();
533        }
534        if (!Float.isNaN(textX)) {
535            app.saveState();
536            app.rectangle(offX, offX, box.getWidth() - 2 * offX, box.getHeight() - 2 * offX);
537            app.clip();
538            app.newPath();
539            if (textColor == null)
540                app.resetGrayFill();
541            else
542                app.setColorFill(textColor);
543            app.beginText();
544            app.setFontAndSize(ufont, fsize);
545            app.setTextMatrix(textX, textY);
546            app.showText(text);
547            app.endText();
548            app.restoreState();
549        }
550        return app;
551    }
552
553    /**
554     * Gets the pushbutton field.
555     * @throws IOException on error
556     * @throws DocumentException on error
557     * @return the pushbutton field
558     */    
559    public PdfFormField getField() throws IOException, DocumentException {
560        PdfFormField field = PdfFormField.createPushButton(writer);
561        field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
562        if (fieldName != null) {
563            field.setFieldName(fieldName);
564            if ((options & READ_ONLY) != 0)
565                field.setFieldFlags(PdfFormField.FF_READ_ONLY);
566            if ((options & REQUIRED) != 0)
567                field.setFieldFlags(PdfFormField.FF_REQUIRED);
568        }
569        if (text != null)
570            field.setMKNormalCaption(text);
571        if (rotation != 0)
572            field.setMKRotation(rotation);
573        field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
574        PdfAppearance tpa = getAppearance();
575        field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tpa);
576        PdfAppearance da = (PdfAppearance)tpa.getDuplicate();
577        da.setFontAndSize(getRealFont(), fontSize);
578        if (textColor == null)
579            da.setGrayFill(0);
580        else
581            da.setColorFill(textColor);
582        field.setDefaultAppearanceString(da);
583        if (borderColor != null)
584            field.setMKBorderColor(borderColor);
585        if (backgroundColor != null)
586            field.setMKBackgroundColor(backgroundColor);
587        switch (visibility) {
588            case HIDDEN:
589                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
590                break;
591            case VISIBLE_BUT_DOES_NOT_PRINT:
592                break;
593            case HIDDEN_BUT_PRINTABLE:
594                field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
595                break;
596            default:
597                field.setFlags(PdfAnnotation.FLAGS_PRINT);
598                break;
599        }
600        if (tp != null)
601            field.setMKNormalIcon(tp);
602        field.setMKTextPosition(layout - 1);
603        PdfName scale = PdfName.A;
604        if (scaleIcon == SCALE_ICON_IS_TOO_BIG)
605            scale = PdfName.B;
606        else if (scaleIcon == SCALE_ICON_IS_TOO_SMALL)
607            scale = PdfName.S;
608        else if (scaleIcon == SCALE_ICON_NEVER)
609            scale = PdfName.N;
610        field.setMKIconFit(scale, proportionalIcon ? PdfName.P : PdfName.A, iconHorizontalAdjustment,
611            iconVerticalAdjustment, iconFitToBounds);
612        return field;
613    }
614    
615    /**
616     * Getter for property iconFitToBounds.
617     * @return Value of property iconFitToBounds.
618     */
619    public boolean isIconFitToBounds() {
620        return this.iconFitToBounds;
621    }
622    
623    /**
624     * If <CODE>true</CODE> the icon will be scaled to fit fully within the bounds of the annotation,
625     * if <CODE>false</CODE> the border width will be taken into account. The default
626     * is <CODE>false</CODE>.
627     * @param iconFitToBounds 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
629     */
630    public void setIconFitToBounds(boolean iconFitToBounds) {
631        this.iconFitToBounds = iconFitToBounds;
632    }
633
634    /**
635     * Holds value of property iconReference.
636     */
637    private PRIndirectReference iconReference;
638
639    /**
640     * Gets the reference to an existing icon.
641     * @return the reference to an existing icon.
642     */
643    public PRIndirectReference getIconReference() {
644        return this.iconReference;
645    }
646
647    /**
648     * Sets the reference to an existing icon.
649     * @param iconReference the reference to an existing icon
650     */
651    public void setIconReference(PRIndirectReference iconReference) {
652        this.iconReference = iconReference;
653    }
654    
655}