001/* 002 * $Id: PdfAcroForm.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.util.HashSet; 047 048import com.itextpdf.text.BaseColor; 049import com.itextpdf.text.ExceptionConverter; 050import com.itextpdf.text.Rectangle; 051 052/** 053 * Each PDF document can contain maximum 1 AcroForm. 054 */ 055 056public class PdfAcroForm extends PdfDictionary { 057 058 private PdfWriter writer; 059 060 061 /** This is a map containing FieldTemplates. */ 062 private HashSet<PdfTemplate> fieldTemplates = new HashSet<PdfTemplate>(); 063 064 /** This is an array containing DocumentFields. */ 065 private PdfArray documentFields = new PdfArray(); 066 067 /** This is an array containing the calculationorder of the fields. */ 068 private PdfArray calculationOrder = new PdfArray(); 069 070 /** Contains the signature flags. */ 071 private int sigFlags = 0; 072 073 /** Creates new PdfAcroForm 074 * @param writer 075 */ 076 public PdfAcroForm(PdfWriter writer) { 077 super(); 078 this.writer = writer; 079 } 080 081 public void setNeedAppearances(boolean value) { 082 put(PdfName.NEEDAPPEARANCES, new PdfBoolean(value)); 083 } 084 085 /** 086 * Adds fieldTemplates. 087 * @param ft 088 */ 089 090 public void addFieldTemplates(HashSet<PdfTemplate> ft) { 091 fieldTemplates.addAll(ft); 092 } 093 094 /** 095 * Adds documentFields. 096 * @param ref 097 */ 098 099 public void addDocumentField(PdfIndirectReference ref) { 100 documentFields.add(ref); 101 } 102 103 /** 104 * Checks if the Acroform is valid 105 * @return true if the Acroform is valid 106 */ 107 108 public boolean isValid() { 109 if (documentFields.size() == 0) return false; 110 put(PdfName.FIELDS, documentFields); 111 if (sigFlags != 0) 112 put(PdfName.SIGFLAGS, new PdfNumber(sigFlags)); 113 if (calculationOrder.size() > 0) 114 put(PdfName.CO, calculationOrder); 115 if (fieldTemplates.isEmpty()) return true; 116 PdfDictionary dic = new PdfDictionary(); 117 for (PdfTemplate template: fieldTemplates) { 118 PdfFormField.mergeResources(dic, (PdfDictionary)template.getResources()); 119 } 120 put(PdfName.DR, dic); 121 put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g ")); 122 PdfDictionary fonts = (PdfDictionary)dic.get(PdfName.FONT); 123 if (fonts != null) { 124 writer.eliminateFontSubset(fonts); 125 } 126 return true; 127 } 128 129 /** 130 * Adds an object to the calculationOrder. 131 * @param formField 132 */ 133 134 public void addCalculationOrder(PdfFormField formField) { 135 calculationOrder.add(formField.getIndirectReference()); 136 } 137 138 /** 139 * Sets the signature flags. 140 * @param f 141 */ 142 143 public void setSigFlags(int f) { 144 sigFlags |= f; 145 } 146 147 /** 148 * Adds a formfield to the AcroForm. 149 * @param formField 150 */ 151 152 public void addFormField(PdfFormField formField) { 153 writer.addAnnotation(formField); 154 } 155 156 /** 157 * @param name 158 * @param caption 159 * @param value 160 * @param url 161 * @param font 162 * @param fontSize 163 * @param llx 164 * @param lly 165 * @param urx 166 * @param ury 167 * @return a PdfFormField 168 */ 169 public PdfFormField addHtmlPostButton(String name, String caption, String value, String url, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 170 PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT); 171 PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action); 172 setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value); 173 drawButton(button, caption, font, fontSize, llx, lly, urx, ury); 174 addFormField(button); 175 return button; 176 } 177 178 /** 179 * @param name 180 * @param caption 181 * @param value 182 * @param font 183 * @param fontSize 184 * @param llx 185 * @param lly 186 * @param urx 187 * @param ury 188 * @return a PdfFormField 189 */ 190 public PdfFormField addResetButton(String name, String caption, String value, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 191 PdfAction action = PdfAction.createResetForm(null, 0); 192 PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action); 193 setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value); 194 drawButton(button, caption, font, fontSize, llx, lly, urx, ury); 195 addFormField(button); 196 return button; 197 } 198 199 /** 200 * @param name 201 * @param value 202 * @param url 203 * @param appearance 204 * @param llx 205 * @param lly 206 * @param urx 207 * @param ury 208 * @return a PdfFormField 209 */ 210 public PdfFormField addMap(String name, String value, String url, PdfContentByte appearance, float llx, float lly, float urx, float ury) { 211 PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT | PdfAction.SUBMIT_COORDINATES); 212 PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action); 213 setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, null); 214 PdfAppearance pa = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 215 pa.add(appearance); 216 button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa); 217 addFormField(button); 218 return button; 219 } 220 221 /** 222 * @param button 223 * @param characteristics 224 * @param name 225 * @param value 226 */ 227 public void setButtonParams(PdfFormField button, int characteristics, String name, String value) { 228 button.setButton(characteristics); 229 button.setFlags(PdfAnnotation.FLAGS_PRINT); 230 button.setPage(); 231 button.setFieldName(name); 232 if (value != null) button.setValueAsString(value); 233 } 234 235 /** 236 * @param button 237 * @param caption 238 * @param font 239 * @param fontSize 240 * @param llx 241 * @param lly 242 * @param urx 243 * @param ury 244 */ 245 public void drawButton(PdfFormField button, String caption, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 246 PdfAppearance pa = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 247 pa.drawButton(0f, 0f, urx - llx, ury - lly, caption, font, fontSize); 248 button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa); 249 } 250 251 /** 252 * @param name 253 * @param value 254 * @return a PdfFormField 255 */ 256 public PdfFormField addHiddenField(String name, String value) { 257 PdfFormField hidden = PdfFormField.createEmpty(writer); 258 hidden.setFieldName(name); 259 hidden.setValueAsName(value); 260 addFormField(hidden); 261 return hidden; 262 } 263 264 /** 265 * @param name 266 * @param text 267 * @param font 268 * @param fontSize 269 * @param llx 270 * @param lly 271 * @param urx 272 * @param ury 273 * @return a PdfFormField 274 */ 275 public PdfFormField addSingleLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 276 PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PLAINTEXT, 0); 277 setTextFieldParams(field, text, name, llx, lly, urx, ury); 278 drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury); 279 addFormField(field); 280 return field; 281 } 282 283 /** 284 * @param name 285 * @param text 286 * @param font 287 * @param fontSize 288 * @param llx 289 * @param lly 290 * @param urx 291 * @param ury 292 * @return a PdfFormField 293 */ 294 public PdfFormField addMultiLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 295 PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.MULTILINE, PdfFormField.PLAINTEXT, 0); 296 setTextFieldParams(field, text, name, llx, lly, urx, ury); 297 drawMultiLineOfText(field, text, font, fontSize, llx, lly, urx, ury); 298 addFormField(field); 299 return field; 300 } 301 302 /** 303 * @param name 304 * @param text 305 * @param font 306 * @param fontSize 307 * @param llx 308 * @param lly 309 * @param urx 310 * @param ury 311 * @return PdfFormField 312 */ 313 public PdfFormField addSingleLinePasswordField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 314 PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PASSWORD, 0); 315 setTextFieldParams(field, text, name, llx, lly, urx, ury); 316 drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury); 317 addFormField(field); 318 return field; 319 } 320 321 /** 322 * @param field 323 * @param text 324 * @param name 325 * @param llx 326 * @param lly 327 * @param urx 328 * @param ury 329 */ 330 public void setTextFieldParams(PdfFormField field, String text, String name, float llx, float lly, float urx, float ury) { 331 field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT); 332 field.setValueAsString(text); 333 field.setDefaultValueAsString(text); 334 field.setFieldName(name); 335 field.setFlags(PdfAnnotation.FLAGS_PRINT); 336 field.setPage(); 337 } 338 339 /** 340 * @param field 341 * @param text 342 * @param font 343 * @param fontSize 344 * @param llx 345 * @param lly 346 * @param urx 347 * @param ury 348 */ 349 public void drawSingleLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 350 PdfAppearance tp = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 351 PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate(); 352 tp2.setFontAndSize(font, fontSize); 353 tp2.resetRGBColorFill(); 354 field.setDefaultAppearanceString(tp2); 355 tp.drawTextField(0f, 0f, urx - llx, ury - lly); 356 tp.beginVariableText(); 357 tp.saveState(); 358 tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f); 359 tp.clip(); 360 tp.newPath(); 361 tp.beginText(); 362 tp.setFontAndSize(font, fontSize); 363 tp.resetRGBColorFill(); 364 tp.setTextMatrix(4, (ury - lly) / 2 - fontSize * 0.3f); 365 tp.showText(text); 366 tp.endText(); 367 tp.restoreState(); 368 tp.endVariableText(); 369 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp); 370 } 371 372 /** 373 * @param field 374 * @param text 375 * @param font 376 * @param fontSize 377 * @param llx 378 * @param lly 379 * @param urx 380 * @param ury 381 */ 382 public void drawMultiLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 383 PdfAppearance tp = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 384 PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate(); 385 tp2.setFontAndSize(font, fontSize); 386 tp2.resetRGBColorFill(); 387 field.setDefaultAppearanceString(tp2); 388 tp.drawTextField(0f, 0f, urx - llx, ury - lly); 389 tp.beginVariableText(); 390 tp.saveState(); 391 tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f); 392 tp.clip(); 393 tp.newPath(); 394 tp.beginText(); 395 tp.setFontAndSize(font, fontSize); 396 tp.resetRGBColorFill(); 397 tp.setTextMatrix(4, 5); 398 java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(text, "\n"); 399 float yPos = ury - lly; 400 while (tokenizer.hasMoreTokens()) { 401 yPos -= fontSize * 1.2f; 402 tp.showTextAligned(PdfContentByte.ALIGN_LEFT, tokenizer.nextToken(), 3, yPos, 0); 403 } 404 tp.endText(); 405 tp.restoreState(); 406 tp.endVariableText(); 407 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp); 408 } 409 410 /** 411 * @param name 412 * @param value 413 * @param status 414 * @param llx 415 * @param lly 416 * @param urx 417 * @param ury 418 * @return a PdfFormField 419 */ 420 public PdfFormField addCheckBox(String name, String value, boolean status, float llx, float lly, float urx, float ury) { 421 PdfFormField field = PdfFormField.createCheckBox(writer); 422 setCheckBoxParams(field, name, value, status, llx, lly, urx, ury); 423 drawCheckBoxAppearences(field, value, llx, lly, urx, ury); 424 addFormField(field); 425 return field; 426 } 427 428 /** 429 * @param field 430 * @param name 431 * @param value 432 * @param status 433 * @param llx 434 * @param lly 435 * @param urx 436 * @param ury 437 */ 438 public void setCheckBoxParams(PdfFormField field, String name, String value, boolean status, float llx, float lly, float urx, float ury) { 439 field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE); 440 field.setFieldName(name); 441 if (status) { 442 field.setValueAsName(value); 443 field.setAppearanceState(value); 444 } 445 else { 446 field.setValueAsName("Off"); 447 field.setAppearanceState("Off"); 448 } 449 field.setFlags(PdfAnnotation.FLAGS_PRINT); 450 field.setPage(); 451 field.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID)); 452 } 453 454 /** 455 * @param field 456 * @param value 457 * @param llx 458 * @param lly 459 * @param urx 460 * @param ury 461 */ 462 public void drawCheckBoxAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) { 463 BaseFont font = null; 464 try { 465 font = BaseFont.createFont(BaseFont.ZAPFDINGBATS, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED); 466 } 467 catch(Exception e) { 468 throw new ExceptionConverter(e); 469 } 470 float size = ury - lly; 471 PdfAppearance tpOn = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 472 PdfAppearance tp2 = (PdfAppearance)tpOn.getDuplicate(); 473 tp2.setFontAndSize(font, size); 474 tp2.resetRGBColorFill(); 475 field.setDefaultAppearanceString(tp2); 476 tpOn.drawTextField(0f, 0f, urx - llx, ury - lly); 477 tpOn.saveState(); 478 tpOn.resetRGBColorFill(); 479 tpOn.beginText(); 480 tpOn.setFontAndSize(font, size); 481 tpOn.showTextAligned(PdfContentByte.ALIGN_CENTER, "4", (urx - llx) / 2, (ury - lly) / 2 - size * 0.3f, 0); 482 tpOn.endText(); 483 tpOn.restoreState(); 484 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn); 485 PdfAppearance tpOff = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 486 tpOff.drawTextField(0f, 0f, urx - llx, ury - lly); 487 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff); 488 } 489 490 /** 491 * @param name 492 * @param defaultValue 493 * @param noToggleToOff 494 * @return a PdfFormField 495 */ 496 public PdfFormField getRadioGroup(String name, String defaultValue, boolean noToggleToOff) { 497 PdfFormField radio = PdfFormField.createRadioButton(writer, noToggleToOff); 498 radio.setFieldName(name); 499 radio.setValueAsName(defaultValue); 500 return radio; 501 } 502 503 /** 504 * @param radiogroup 505 */ 506 public void addRadioGroup(PdfFormField radiogroup) { 507 addFormField(radiogroup); 508 } 509 510 /** 511 * @param radiogroup 512 * @param value 513 * @param llx 514 * @param lly 515 * @param urx 516 * @param ury 517 * @return a PdfFormField 518 */ 519 public PdfFormField addRadioButton(PdfFormField radiogroup, String value, float llx, float lly, float urx, float ury) { 520 PdfFormField radio = PdfFormField.createEmpty(writer); 521 radio.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE); 522 String name = ((PdfName)radiogroup.get(PdfName.V)).toString().substring(1); 523 if (name.equals(value)) { 524 radio.setAppearanceState(value); 525 } 526 else { 527 radio.setAppearanceState("Off"); 528 } 529 drawRadioAppearences(radio, value, llx, lly, urx, ury); 530 radiogroup.addKid(radio); 531 return radio; 532 } 533 534 /** 535 * @param field 536 * @param value 537 * @param llx 538 * @param lly 539 * @param urx 540 * @param ury 541 */ 542 public void drawRadioAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) { 543 PdfAppearance tpOn = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 544 tpOn.drawRadioField(0f, 0f, urx - llx, ury - lly, true); 545 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn); 546 PdfAppearance tpOff = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 547 tpOff.drawRadioField(0f, 0f, urx - llx, ury - lly, false); 548 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff); 549 } 550 551 /** 552 * @param name 553 * @param options 554 * @param defaultValue 555 * @param font 556 * @param fontSize 557 * @param llx 558 * @param lly 559 * @param urx 560 * @param ury 561 * @return a PdfFormField 562 */ 563 public PdfFormField addSelectList(String name, String[] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 564 PdfFormField choice = PdfFormField.createList(writer, options, 0); 565 setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury); 566 StringBuffer text = new StringBuffer(); 567 for (String option : options) { 568 text.append(option).append('\n'); 569 } 570 drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury); 571 addFormField(choice); 572 return choice; 573 } 574 575 /** 576 * @param name 577 * @param options 578 * @param defaultValue 579 * @param font 580 * @param fontSize 581 * @param llx 582 * @param lly 583 * @param urx 584 * @param ury 585 * @return a PdfFormField 586 */ 587 public PdfFormField addSelectList(String name, String[][] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 588 PdfFormField choice = PdfFormField.createList(writer, options, 0); 589 setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury); 590 StringBuffer text = new StringBuffer(); 591 for (String[] option : options) { 592 text.append(option[1]).append('\n'); 593 } 594 drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury); 595 addFormField(choice); 596 return choice; 597 } 598 599 /** 600 * @param name 601 * @param options 602 * @param defaultValue 603 * @param editable 604 * @param font 605 * @param fontSize 606 * @param llx 607 * @param lly 608 * @param urx 609 * @param ury 610 * @return a PdfFormField 611 */ 612 public PdfFormField addComboBox(String name, String[] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 613 PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0); 614 setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury); 615 if (defaultValue == null) { 616 defaultValue = options[0]; 617 } 618 drawSingleLineOfText(choice, defaultValue, font, fontSize, llx, lly, urx, ury); 619 addFormField(choice); 620 return choice; 621 } 622 623 /** 624 * @param name 625 * @param options 626 * @param defaultValue 627 * @param editable 628 * @param font 629 * @param fontSize 630 * @param llx 631 * @param lly 632 * @param urx 633 * @param ury 634 * @return a PdfFormField 635 */ 636 public PdfFormField addComboBox(String name, String[][] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) { 637 PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0); 638 setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury); 639 String value = null; 640 for (String[] option : options) { 641 if (option[0].equals(defaultValue)) { 642 value = option[1]; 643 break; 644 } 645 } 646 if (value == null) { 647 value = options[0][1]; 648 } 649 drawSingleLineOfText(choice, value, font, fontSize, llx, lly, urx, ury); 650 addFormField(choice); 651 return choice; 652 } 653 654 /** 655 * @param field 656 * @param name 657 * @param defaultValue 658 * @param llx 659 * @param lly 660 * @param urx 661 * @param ury 662 */ 663 public void setChoiceParams(PdfFormField field, String name, String defaultValue, float llx, float lly, float urx, float ury) { 664 field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT); 665 if (defaultValue != null) { 666 field.setValueAsString(defaultValue); 667 field.setDefaultValueAsString(defaultValue); 668 } 669 field.setFieldName(name); 670 field.setFlags(PdfAnnotation.FLAGS_PRINT); 671 field.setPage(); 672 field.setBorderStyle(new PdfBorderDictionary(2, PdfBorderDictionary.STYLE_SOLID)); 673 } 674 675 /** 676 * @param name 677 * @param llx 678 * @param lly 679 * @param urx 680 * @param ury 681 * @return a PdfFormField 682 */ 683 public PdfFormField addSignature(String name, 684 float llx, float lly, float urx, float ury) { 685 PdfFormField signature = PdfFormField.createSignature(writer); 686 setSignatureParams(signature, name, llx, lly, urx, ury); 687 drawSignatureAppearences(signature, llx, lly, urx, ury); 688 addFormField(signature); 689 return signature; 690 } 691 692 /** 693 * @param field 694 * @param name 695 * @param llx 696 * @param lly 697 * @param urx 698 * @param ury 699 */ 700 public void setSignatureParams(PdfFormField field, String name, 701 float llx, float lly, float urx, float ury) { 702 field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT); 703 field.setFieldName(name); 704 field.setFlags(PdfAnnotation.FLAGS_PRINT); 705 field.setPage(); 706 field.setMKBorderColor(BaseColor.BLACK); 707 field.setMKBackgroundColor(BaseColor.WHITE); 708 } 709 710 /** 711 * @param field 712 * @param llx 713 * @param lly 714 * @param urx 715 * @param ury 716 */ 717 public void drawSignatureAppearences(PdfFormField field, 718 float llx, float lly, float urx, float ury) { 719 PdfAppearance tp = PdfAppearance.createAppearance(writer, urx - llx, ury - lly); 720 tp.setGrayFill(1.0f); 721 tp.rectangle(0, 0, urx - llx, ury - lly); 722 tp.fill(); 723 tp.setGrayStroke(0); 724 tp.setLineWidth(1); 725 tp.rectangle(0.5f, 0.5f, urx - llx - 0.5f, ury - lly - 0.5f); 726 tp.closePathStroke(); 727 tp.saveState(); 728 tp.rectangle(1, 1, urx - llx - 2, ury - lly - 2); 729 tp.clip(); 730 tp.newPath(); 731 tp.restoreState(); 732 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp); 733 } 734}