1 47 48 package com.lowagie.text.pdf; 49 50 import java.awt.Color ; 51 import java.io.IOException ; 52 import java.util.ArrayList ; 53 54 import com.lowagie.text.Chunk; 55 import com.lowagie.text.DocumentException; 56 import com.lowagie.text.Element; 57 import com.lowagie.text.Font; 58 import com.lowagie.text.Phrase; 59 import com.lowagie.text.Rectangle; 60 61 65 public class TextField extends BaseField { 66 67 68 private String defaultText; 69 70 71 private String [] choices; 72 73 74 private String [] choiceExports; 75 76 77 private int choiceSelection; 78 79 private int topFirst; 80 81 private float extraMarginLeft; 82 private float extraMarginTop; 83 84 90 public TextField(PdfWriter writer, Rectangle box, String fieldName) { 91 super(writer, box, fieldName); 92 } 93 94 private static boolean checkRTL(String text) { 95 if (text == null || text.length() == 0) 96 return false; 97 char[] cc = text.toCharArray(); 98 for (int k = 0; k < cc.length; ++k) { 99 int c = (int)cc[k]; 100 if (c >= 0x590 && c < 0x0780) 101 return true; 102 } 103 return false; 104 } 105 106 private static void changeFontSize(Phrase p, float size) { 107 for (int k = 0; k < p.size(); ++k) { 108 ((Chunk)p.get(k)).getFont().setSize(size); 109 } 110 } 111 112 private Phrase composePhrase(String text, BaseFont ufont, Color color, float fontSize) { 113 Phrase phrase = null; 114 if (extensionFont == null && (substitutionFonts == null || substitutionFonts.isEmpty())) 115 phrase = new Phrase(new Chunk(text, new Font(ufont, fontSize, 0, color))); 116 else { 117 FontSelector fs = new FontSelector(); 118 fs.addFont(new Font(ufont, fontSize, 0, color)); 119 if (extensionFont != null) 120 fs.addFont(new Font(extensionFont, fontSize, 0, color)); 121 if (substitutionFonts != null) { 122 for (int k = 0; k < substitutionFonts.size(); ++k) { 123 fs.addFont(new Font((BaseFont)substitutionFonts.get(k), fontSize, 0, color)); 124 } 125 } 126 phrase = fs.process(text); 127 } 128 return phrase; 129 } 130 131 private static String removeCRLF(String text) { 132 if (text.indexOf('\n') >= 0 || text.indexOf('\r') >= 0) { 133 char[] p = text.toCharArray(); 134 StringBuffer sb = new StringBuffer (p.length); 135 for (int k = 0; k < p.length; ++k) { 136 char c = p[k]; 137 if (c == '\n') 138 sb.append(' '); 139 else if (c == '\r') { 140 sb.append(' '); 141 if (k < p.length - 1 && p[k + 1] == '\n') 142 ++k; 143 } 144 else 145 sb.append(c); 146 } 147 return sb.toString(); 148 } 149 return text; 150 } 151 152 public PdfAppearance getAppearance() throws IOException , DocumentException { 153 PdfAppearance app = getBorderAppearance(); 154 app.beginVariableText(); 155 if (text == null || text.length() == 0) { 156 app.endVariableText(); 157 return app; 158 } 159 BaseFont ufont = getRealFont(); 160 boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET; 161 float h = box.getHeight() - borderWidth * 2; 162 float bw2 = borderWidth; 163 if (borderExtra) { 164 h -= borderWidth * 2; 165 bw2 *= 2; 166 } 167 h -= extraMarginTop; 168 float offsetX = (borderExtra ? 2 * borderWidth : borderWidth); 169 offsetX = Math.max(offsetX, 1); 170 float offX = Math.min(bw2, offsetX); 171 app.saveState(); 172 app.rectangle(offX, offX, box.getWidth() - 2 * offX, box.getHeight() - 2 * offX); 173 app.clip(); 174 app.newPath(); 175 Color fcolor = (textColor == null) ? GrayColor.GRAYBLACK : textColor; 176 String ptext = text; if ((options & PASSWORD) != 0) { 178 char[] pchar = new char[text.length()]; 179 for (int i = 0; i < text.length(); i++) 180 pchar[i] = '*'; 181 ptext = new String (pchar); 182 } 183 int rtl = checkRTL(ptext) ? PdfWriter.RUN_DIRECTION_LTR : PdfWriter.RUN_DIRECTION_NO_BIDI; 184 if ((options & MULTILINE) == 0) { 185 ptext = removeCRLF(text); 186 } 187 Phrase phrase = composePhrase(ptext, ufont, fcolor, fontSize); 188 if ((options & MULTILINE) != 0) { 189 float usize = fontSize; 190 float width = box.getWidth() - 4 * offsetX - extraMarginLeft; 191 float factor = ufont.getFontDescriptor(BaseFont.BBOXURY, 1) - ufont.getFontDescriptor(BaseFont.BBOXLLY, 1); 192 ColumnText ct = new ColumnText(null); 193 if (usize == 0) { 194 usize = h / factor; 195 if (usize > 4) { 196 if (usize > 12) 197 usize = 12; 198 float step = Math.max((usize - 4) / 10, 0.2f); 199 ct.setSimpleColumn(0, -h, width, 0); 200 ct.setAlignment(alignment); 201 ct.setRunDirection(rtl); 202 for (; usize > 4; usize -= step) { 203 ct.setYLine(0); 204 changeFontSize(phrase, usize); 205 ct.setText(phrase); 206 ct.setLeading(factor * usize); 207 int status = ct.go(true); 208 if ((status & ColumnText.NO_MORE_COLUMN) == 0) 209 break; 210 } 211 } 212 if (usize < 4) { 213 usize = 4; 214 } 215 } 216 changeFontSize(phrase, usize); 217 ct.setCanvas(app); 218 float leading = usize * factor; 219 float offsetY = offsetX + h - ufont.getFontDescriptor(BaseFont.BBOXURY, usize); 220 ct.setSimpleColumn(extraMarginLeft + 2 * offsetX, -20000, box.getWidth() - 2 * offsetX, offsetY + leading); 221 ct.setLeading(leading); 222 ct.setAlignment(alignment); 223 ct.setRunDirection(rtl); 224 ct.setText(phrase); 225 ct.go(); 226 } 227 else { 228 float usize = fontSize; 229 if (usize == 0) { 230 float maxCalculatedSize = h / (ufont.getFontDescriptor(BaseFont.BBOXURX, 1) - ufont.getFontDescriptor(BaseFont.BBOXLLY, 1)); 231 changeFontSize(phrase, 1); 232 float wd = ColumnText.getWidth(phrase, rtl, 0); 233 if (wd == 0) 234 usize = maxCalculatedSize; 235 else 236 usize = (box.getWidth() - extraMarginLeft - 4 * offsetX) / wd; 237 if (usize > maxCalculatedSize) 238 usize = maxCalculatedSize; 239 if (usize < 4) 240 usize = 4; 241 } 242 changeFontSize(phrase, usize); 243 float offsetY = offX + ((box.getHeight() - 2*offX) - ufont.getFontDescriptor(BaseFont.ASCENT, usize)) / 2; 244 if (offsetY < offX) 245 offsetY = offX; 246 if (offsetY - offX < -ufont.getFontDescriptor(BaseFont.DESCENT, usize)) { 247 float ny = -ufont.getFontDescriptor(BaseFont.DESCENT, usize) + offX; 248 float dy = box.getHeight() - offX - ufont.getFontDescriptor(BaseFont.ASCENT, usize); 249 offsetY = Math.min(ny, Math.max(offsetY, dy)); 250 } 251 if ((options & COMB) != 0 && maxCharacterLength > 0) { 252 int textLen = Math.min(maxCharacterLength, ptext.length()); 253 int position = 0; 254 if (alignment == Element.ALIGN_RIGHT) { 255 position = maxCharacterLength - textLen; 256 } 257 else if (alignment == Element.ALIGN_CENTER) { 258 position = (maxCharacterLength - textLen) / 2; 259 } 260 float step = (box.getWidth() - extraMarginLeft) / maxCharacterLength; 261 float start = step / 2 + position * step; 262 if (textColor == null) 263 app.setGrayFill(0); 264 else 265 app.setColorFill(textColor); 266 app.beginText(); 267 for (int k = 0; k < phrase.size(); ++k) { 268 Chunk ck = (Chunk)phrase.get(k); 269 BaseFont bf = ck.getFont().getBaseFont(); 270 app.setFontAndSize(bf, usize); 271 StringBuffer sb = ck.append(""); 272 for (int j = 0; j < sb.length(); ++j) { 273 String c = sb.substring(j, j + 1); 274 float wd = bf.getWidthPoint(c, usize); 275 app.setTextMatrix(extraMarginLeft + start - wd / 2, offsetY - extraMarginTop); 276 app.showText(c); 277 start += step; 278 } 279 } 280 app.endText(); 281 } 282 else { 283 if (alignment == Element.ALIGN_RIGHT) { 284 ColumnText.showTextAligned(app, Element.ALIGN_RIGHT, phrase, extraMarginLeft + box.getWidth() - 2 * offsetX, offsetY - extraMarginTop, 0, rtl, 0); 285 } 286 else if (alignment == Element.ALIGN_CENTER) { 287 ColumnText.showTextAligned(app, Element.ALIGN_CENTER, phrase, extraMarginLeft + box.getWidth() / 2, offsetY - extraMarginTop, 0, rtl, 0); 288 } 289 else 290 ColumnText.showTextAligned(app, Element.ALIGN_LEFT, phrase, extraMarginLeft + 2 * offsetX, offsetY - extraMarginTop, 0, rtl, 0); 291 } 292 } 293 app.restoreState(); 294 app.endVariableText(); 295 return app; 296 } 297 298 PdfAppearance getListAppearance() throws IOException , DocumentException { 299 PdfAppearance app = getBorderAppearance(); 300 app.beginVariableText(); 301 if (choices == null || choices.length == 0) { 302 app.endVariableText(); 303 return app; 304 } 305 int topChoice = choiceSelection; 306 if (topChoice >= choices.length) { 307 topChoice = choices.length - 1; 308 } 309 if (topChoice < 0) 310 topChoice = 0; 311 BaseFont ufont = getRealFont(); 312 float usize = fontSize; 313 if (usize == 0) 314 usize = 12; 315 boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET; 316 float h = box.getHeight() - borderWidth * 2; 317 if (borderExtra) 318 h -= borderWidth * 2; 319 float offsetX = (borderExtra ? 2 * borderWidth : borderWidth); 320 float leading = ufont.getFontDescriptor(BaseFont.BBOXURY, usize) - ufont.getFontDescriptor(BaseFont.BBOXLLY, usize); 321 int maxFit = (int)(h / leading) + 1; 322 int first = 0; 323 int last = 0; 324 last = topChoice + maxFit / 2 + 1; 325 first = last - maxFit; 326 if (first < 0) { 327 last += first; 328 first = 0; 329 } 330 last = first + maxFit; 332 if (last > choices.length) 333 last = choices.length; 334 topFirst = first; 335 app.saveState(); 336 app.rectangle(offsetX, offsetX, box.getWidth() - 2 * offsetX, box.getHeight() - 2 * offsetX); 337 app.clip(); 338 app.newPath(); 339 Color fcolor = (textColor == null) ? GrayColor.GRAYBLACK : textColor; 340 app.setColorFill(new Color (10, 36, 106)); 341 app.rectangle(offsetX, offsetX + h - (topChoice - first + 1) * leading, box.getWidth() - 2 * offsetX, leading); 342 app.fill(); 343 float xp = offsetX * 2; 344 float yp = offsetX + h - ufont.getFontDescriptor(BaseFont.BBOXURY, usize); 345 for (int idx = first; idx < last; ++idx, yp -= leading) { 346 String ptext = choices[idx]; 347 int rtl = checkRTL(ptext) ? PdfWriter.RUN_DIRECTION_LTR : PdfWriter.RUN_DIRECTION_NO_BIDI; 348 ptext = removeCRLF(ptext); 349 Phrase phrase = composePhrase(ptext, ufont, (idx == topChoice) ? GrayColor.GRAYWHITE : fcolor, usize); 350 ColumnText.showTextAligned(app, Element.ALIGN_LEFT, phrase, xp, yp, 0, rtl, 0); 351 } 352 app.restoreState(); 353 app.endVariableText(); 354 return app; 355 } 356 357 362 public PdfFormField getTextField() throws IOException , DocumentException { 363 if (maxCharacterLength <= 0) 364 options &= ~COMB; 365 if ((options & COMB) != 0) 366 options &= ~MULTILINE; 367 PdfFormField field = PdfFormField.createTextField(writer, false, false, maxCharacterLength); 368 field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT); 369 switch (alignment) { 370 case Element.ALIGN_CENTER: 371 field.setQuadding(PdfFormField.Q_CENTER); 372 break; 373 case Element.ALIGN_RIGHT: 374 field.setQuadding(PdfFormField.Q_RIGHT); 375 break; 376 } 377 if (rotation != 0) 378 field.setMKRotation(rotation); 379 if (fieldName != null) { 380 field.setFieldName(fieldName); 381 if ((options & REQUIRED) == 0 && !"".equals(text)) 382 field.setValueAsString(text); 383 if (defaultText != null) 384 field.setDefaultValueAsString(defaultText); 385 if ((options & READ_ONLY) != 0) 386 field.setFieldFlags(PdfFormField.FF_READ_ONLY); 387 if ((options & REQUIRED) != 0) 388 field.setFieldFlags(PdfFormField.FF_REQUIRED); 389 if ((options & MULTILINE) != 0) 390 field.setFieldFlags(PdfFormField.FF_MULTILINE); 391 if ((options & DO_NOT_SCROLL) != 0) 392 field.setFieldFlags(PdfFormField.FF_DONOTSCROLL); 393 if ((options & PASSWORD) != 0) 394 field.setFieldFlags(PdfFormField.FF_PASSWORD); 395 if ((options & FILE_SELECTION) != 0) 396 field.setFieldFlags(PdfFormField.FF_FILESELECT); 397 if ((options & DO_NOT_SPELL_CHECK) != 0) 398 field.setFieldFlags(PdfFormField.FF_DONOTSPELLCHECK); 399 if ((options & COMB) != 0) 400 field.setFieldFlags(PdfFormField.FF_COMB); 401 } 402 field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3))); 403 PdfAppearance tp = getAppearance(); 404 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp); 405 PdfAppearance da = (PdfAppearance)tp.getDuplicate(); 406 da.setFontAndSize(getRealFont(), fontSize); 407 if (textColor == null) 408 da.setGrayFill(0); 409 else 410 da.setColorFill(textColor); 411 field.setDefaultAppearanceString(da); 412 if (borderColor != null) 413 field.setMKBorderColor(borderColor); 414 if (backgroundColor != null) 415 field.setMKBackgroundColor(backgroundColor); 416 switch (visibility) { 417 case HIDDEN: 418 field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN); 419 break; 420 case VISIBLE_BUT_DOES_NOT_PRINT: 421 break; 422 case HIDDEN_BUT_PRINTABLE: 423 field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW); 424 break; 425 default: 426 field.setFlags(PdfAnnotation.FLAGS_PRINT); 427 break; 428 } 429 return field; 430 } 431 432 437 public PdfFormField getComboField() throws IOException , DocumentException { 438 return getChoiceField(false); 439 } 440 441 446 public PdfFormField getListField() throws IOException , DocumentException { 447 return getChoiceField(true); 448 } 449 450 protected PdfFormField getChoiceField(boolean isList) throws IOException , DocumentException { 451 options &= (~MULTILINE) & (~COMB); 452 String uchoices[] = choices; 453 if (uchoices == null) 454 uchoices = new String [0]; 455 int topChoice = choiceSelection; 456 if (topChoice >= uchoices.length) 457 topChoice = uchoices.length - 1; 458 if (text == null) text = ""; if (topChoice >= 0) 460 text = uchoices[topChoice]; 461 if (topChoice < 0) 462 topChoice = 0; 463 PdfFormField field = null; 464 String mix[][] = null; 465 if (choiceExports == null) { 466 if (isList) 467 field = PdfFormField.createList(writer, uchoices, topChoice); 468 else 469 field = PdfFormField.createCombo(writer, (options & EDIT) != 0, uchoices, topChoice); 470 } 471 else { 472 mix = new String [uchoices.length][2]; 473 for (int k = 0; k < mix.length; ++k) 474 mix[k][0] = mix[k][1] = uchoices[k]; 475 int top = Math.min(uchoices.length, choiceExports.length); 476 for (int k = 0; k < top; ++k) { 477 if (choiceExports[k] != null) 478 mix[k][0] = choiceExports[k]; 479 } 480 if (isList) 481 field = PdfFormField.createList(writer, mix, topChoice); 482 else 483 field = PdfFormField.createCombo(writer, (options & EDIT) != 0, mix, topChoice); 484 } 485 field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT); 486 if (rotation != 0) 487 field.setMKRotation(rotation); 488 if (fieldName != null) { 489 field.setFieldName(fieldName); 490 if (uchoices.length > 0) { 491 if (mix != null) { 492 field.setValueAsString(mix[topChoice][0]); 493 field.setDefaultValueAsString(mix[topChoice][0]); 494 } 495 else { 496 field.setValueAsString(text); 497 field.setDefaultValueAsString(text); 498 } 499 } 500 if ((options & READ_ONLY) != 0) 501 field.setFieldFlags(PdfFormField.FF_READ_ONLY); 502 if ((options & REQUIRED) != 0) 503 field.setFieldFlags(PdfFormField.FF_REQUIRED); 504 if ((options & DO_NOT_SPELL_CHECK) != 0) 505 field.setFieldFlags(PdfFormField.FF_DONOTSPELLCHECK); 506 } 507 field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3))); 508 PdfAppearance tp; 509 if (isList) { 510 tp = getListAppearance(); 511 if (topFirst > 0) 512 field.put(PdfName.TI, new PdfNumber(topFirst)); 513 } 514 else 515 tp = getAppearance(); 516 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp); 517 PdfAppearance da = (PdfAppearance)tp.getDuplicate(); 518 da.setFontAndSize(getRealFont(), fontSize); 519 if (textColor == null) 520 da.setGrayFill(0); 521 else 522 da.setColorFill(textColor); 523 field.setDefaultAppearanceString(da); 524 if (borderColor != null) 525 field.setMKBorderColor(borderColor); 526 if (backgroundColor != null) 527 field.setMKBackgroundColor(backgroundColor); 528 switch (visibility) { 529 case HIDDEN: 530 field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN); 531 break; 532 case VISIBLE_BUT_DOES_NOT_PRINT: 533 break; 534 case HIDDEN_BUT_PRINTABLE: 535 field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW); 536 break; 537 default: 538 field.setFlags(PdfAnnotation.FLAGS_PRINT); 539 break; 540 } 541 return field; 542 } 543 544 547 public String getDefaultText() { 548 return this.defaultText; 549 } 550 551 554 public void setDefaultText(String defaultText) { 555 this.defaultText = defaultText; 556 } 557 558 562 public String [] getChoices() { 563 return this.choices; 564 } 565 566 570 public void setChoices(String [] choices) { 571 this.choices = choices; 572 } 573 574 577 public String [] getChoiceExports() { 578 return this.choiceExports; 579 } 580 581 586 public void setChoiceExports(String [] choiceExports) { 587 this.choiceExports = choiceExports; 588 } 589 590 593 public int getChoiceSelection() { 594 return this.choiceSelection; 595 } 596 597 600 public void setChoiceSelection(int choiceSelection) { 601 this.choiceSelection = choiceSelection; 602 } 603 604 int getTopFirst() { 605 return topFirst; 606 } 607 608 613 public void setExtraMargin(float extraMarginLeft, float extraMarginTop) { 614 this.extraMarginLeft = extraMarginLeft; 615 this.extraMarginTop = extraMarginTop; 616 } 617 618 621 private ArrayList substitutionFonts; 622 623 628 public ArrayList getSubstitutionFonts() { 629 return this.substitutionFonts; 630 } 631 632 637 public void setSubstitutionFonts(ArrayList substitutionFonts) { 638 this.substitutionFonts = substitutionFonts; 639 } 640 641 644 private BaseFont extensionFont; 645 646 651 public BaseFont getExtensionFont() { 652 return this.extensionFont; 653 } 654 655 660 public void setExtensionFont(BaseFont extensionFont) { 661 this.extensionFont = extensionFont; 662 } 663 } | Popular Tags |