1 50 51 package com.lowagie.text.pdf; 52 53 import java.awt.Color ; 54 import java.io.IOException ; 55 import java.util.ArrayList ; 56 import java.util.Arrays ; 57 import java.util.HashMap ; 58 import java.util.HashSet ; 59 import java.util.Iterator ; 60 import java.util.Map ; 61 import java.util.Set ; 62 import java.util.TreeMap ; 63 64 import com.lowagie.text.Anchor; 65 import com.lowagie.text.Annotation; 66 import com.lowagie.text.BadElementException; 67 import com.lowagie.text.Chunk; 68 import com.lowagie.text.Document; 69 import com.lowagie.text.DocumentException; 70 import com.lowagie.text.Element; 71 import com.lowagie.text.ExceptionConverter; 72 import com.lowagie.text.Font; 73 import com.lowagie.text.HeaderFooter; 74 import com.lowagie.text.Image; 75 import com.lowagie.text.List; 76 import com.lowagie.text.ListItem; 77 import com.lowagie.text.MarkedObject; 78 import com.lowagie.text.MarkedSection; 79 import com.lowagie.text.Meta; 80 import com.lowagie.text.Paragraph; 81 import com.lowagie.text.Phrase; 82 import com.lowagie.text.Rectangle; 83 import com.lowagie.text.Section; 84 import com.lowagie.text.SimpleTable; 85 import com.lowagie.text.Table; 86 import com.lowagie.text.pdf.collection.PdfCollection; 87 import com.lowagie.text.pdf.internal.PdfAnnotationsImp; 88 import com.lowagie.text.pdf.internal.PdfViewerPreferencesImp; 89 90 102 103 class PdfDocument extends Document { 104 105 114 115 public static class PdfInfo extends PdfDictionary { 116 117 120 121 PdfInfo() { 122 super(); 123 addProducer(); 124 addCreationDate(); 125 } 126 127 134 135 PdfInfo(String author, String title, String subject) { 136 this(); 137 addTitle(title); 138 addSubject(subject); 139 addAuthor(author); 140 } 141 142 147 148 void addTitle(String title) { 149 put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE)); 150 } 151 152 157 158 void addSubject(String subject) { 159 put(PdfName.SUBJECT, new PdfString(subject, PdfObject.TEXT_UNICODE)); 160 } 161 162 167 168 void addKeywords(String keywords) { 169 put(PdfName.KEYWORDS, new PdfString(keywords, PdfObject.TEXT_UNICODE)); 170 } 171 172 177 178 void addAuthor(String author) { 179 put(PdfName.AUTHOR, new PdfString(author, PdfObject.TEXT_UNICODE)); 180 } 181 182 187 188 void addCreator(String creator) { 189 put(PdfName.CREATOR, new PdfString(creator, PdfObject.TEXT_UNICODE)); 190 } 191 192 195 196 void addProducer() { 197 put(PdfName.PRODUCER, new PdfString(getVersion())); 198 } 199 200 203 204 void addCreationDate() { 205 PdfString date = new PdfDate(); 206 put(PdfName.CREATIONDATE, date); 207 put(PdfName.MODDATE, date); 208 } 209 210 void addkey(String key, String value) { 211 if (key.equals("Producer") || key.equals("CreationDate")) 212 return; 213 put(new PdfName(key), new PdfString(value, PdfObject.TEXT_UNICODE)); 214 } 215 } 216 217 230 231 static class PdfCatalog extends PdfDictionary { 232 233 234 PdfWriter writer; 235 236 242 243 PdfCatalog(PdfIndirectReference pages, PdfWriter writer) { 244 super(CATALOG); 245 this.writer = writer; 246 put(PdfName.PAGES, pages); 247 } 248 249 255 void addNames(TreeMap localDestinations, ArrayList documentJavaScript, HashMap documentFileAttachment, PdfWriter writer) { 256 if (localDestinations.isEmpty() && documentJavaScript.isEmpty() && documentFileAttachment.isEmpty()) 257 return; 258 try { 259 PdfDictionary names = new PdfDictionary(); 260 if (!localDestinations.isEmpty()) { 261 PdfArray ar = new PdfArray(); 262 for (Iterator i = localDestinations.entrySet().iterator(); i.hasNext();) { 263 Map.Entry entry = (Map.Entry ) i.next(); 264 String name = (String ) entry.getKey(); 265 Object obj[] = (Object []) entry.getValue(); 266 PdfIndirectReference ref = (PdfIndirectReference)obj[1]; 267 ar.add(new PdfString(name, null)); 268 ar.add(ref); 269 } 270 PdfDictionary dests = new PdfDictionary(); 271 dests.put(PdfName.NAMES, ar); 272 names.put(PdfName.DESTS, writer.addToBody(dests).getIndirectReference()); 273 } 274 if (!documentJavaScript.isEmpty()) { 275 String s[] = new String [documentJavaScript.size()]; 276 for (int k = 0; k < s.length; ++k) 277 s[k] = Integer.toHexString(k); 278 Arrays.sort(s); 279 PdfArray ar = new PdfArray(); 280 for (int k = 0; k < s.length; ++k) { 281 ar.add(new PdfString(s[k])); 282 ar.add((PdfIndirectReference)documentJavaScript.get(k)); 283 } 284 PdfDictionary js = new PdfDictionary(); 285 js.put(PdfName.NAMES, ar); 286 names.put(PdfName.JAVASCRIPT, writer.addToBody(js).getIndirectReference()); 287 } 288 if (!documentFileAttachment.isEmpty()) { 289 names.put(PdfName.EMBEDDEDFILES, writer.addToBody(PdfNameTree.writeTree(documentFileAttachment, writer)).getIndirectReference()); 290 } 291 put(PdfName.NAMES, writer.addToBody(names).getIndirectReference()); 292 } 293 catch (IOException e) { 294 throw new ExceptionConverter(e); 295 } 296 } 297 298 302 void setOpenAction(PdfAction action) { 303 put(PdfName.OPENACTION, action); 304 } 305 306 307 311 void setAdditionalActions(PdfDictionary actions) { 312 try { 313 put(PdfName.AA, writer.addToBody(actions).getIndirectReference()); 314 } catch (Exception e) { 315 throw new ExceptionConverter(e); 316 } 317 } 318 } 319 320 322 326 public PdfDocument() { 327 super(); 328 addProducer(); 329 addCreationDate(); 330 } 331 332 333 private PdfWriter writer; 334 335 342 public void addWriter(PdfWriter writer) throws DocumentException { 343 if (this.writer == null) { 344 this.writer = writer; 345 annotationsImp = new PdfAnnotationsImp(writer); 346 return; 347 } 348 throw new DocumentException("You can only add a writer to a PdfDocument once."); 349 } 350 351 353 355 356 private PdfContentByte text; 357 358 359 private PdfContentByte graphics; 360 361 362 private float leading = 0; 363 364 365 private int alignment = Element.ALIGN_LEFT; 366 367 368 private float currentHeight = 0; 369 370 371 private boolean isParagraph = true; 372 373 374 private PdfAction anchorAction = null; 375 376 383 public boolean add(Element element) throws DocumentException { 384 if (writer != null && writer.isPaused()) { 385 return false; 386 } 387 try { 388 switch(element.type()) { 389 case Element.HEADER: 391 info.addkey(((Meta)element).getName(), ((Meta)element).getContent()); 392 break; 393 case Element.TITLE: 394 info.addTitle(((Meta)element).getContent()); 395 break; 396 case Element.SUBJECT: 397 info.addSubject(((Meta)element).getContent()); 398 break; 399 case Element.KEYWORDS: 400 info.addKeywords(((Meta)element).getContent()); 401 break; 402 case Element.AUTHOR: 403 info.addAuthor(((Meta)element).getContent()); 404 break; 405 case Element.CREATOR: 406 info.addCreator(((Meta)element).getContent()); 407 break; 408 case Element.PRODUCER: 409 info.addProducer(); 411 break; 412 case Element.CREATIONDATE: 413 info.addCreationDate(); 415 break; 416 417 case Element.CHUNK: { 419 if (line == null) { 421 carriageReturn(); 422 } 423 424 PdfChunk chunk = new PdfChunk((Chunk) element, anchorAction); 426 { 428 PdfChunk overflow; 429 while ((overflow = line.add(chunk)) != null) { 430 carriageReturn(); 431 chunk = overflow; 432 chunk.trimFirstSpace(); 433 } 434 } 435 pageEmpty = false; 436 if (chunk.isAttribute(Chunk.NEWPAGE)) { 437 newPage(); 438 } 439 break; 440 } 441 case Element.ANCHOR: { 442 Anchor anchor = (Anchor) element; 443 String url = anchor.getReference(); 444 leading = anchor.getLeading(); 445 if (url != null) { 446 anchorAction = new PdfAction(url); 447 } 448 element.process(this); 450 anchorAction = null; 451 break; 452 } 453 case Element.ANNOTATION: { 454 if (line == null) { 455 carriageReturn(); 456 } 457 Annotation annot = (Annotation) element; 458 Rectangle rect = new Rectangle(0, 0); 459 if (line != null) 460 rect = new Rectangle(annot.llx(indentRight() - line.widthLeft()), annot.lly(indentTop() - currentHeight), annot.urx(indentRight() - line.widthLeft() + 20), annot.ury(indentTop() - currentHeight - 20)); 461 PdfAnnotation an = PdfAnnotationsImp.convertAnnotation(writer, annot, rect); 462 annotationsImp.addPlainAnnotation(an); 463 pageEmpty = false; 464 break; 465 } 466 case Element.PHRASE: { 467 leading = ((Phrase) element).getLeading(); 469 element.process(this); 471 break; 472 } 473 case Element.PARAGRAPH: { 474 Paragraph paragraph = (Paragraph) element; 476 477 addSpacing(paragraph.spacingBefore(), leading, paragraph.getFont()); 478 479 alignment = paragraph.getAlignment(); 481 leading = paragraph.getTotalLeading(); 482 carriageReturn(); 483 484 if (currentHeight + line.height() + leading > indentTop() - indentBottom()) { 486 newPage(); 487 } 488 489 indentation.indentLeft += paragraph.getIndentationLeft(); 490 indentation.indentRight += paragraph.getIndentationRight(); 491 carriageReturn(); 492 493 PdfPageEvent pageEvent = writer.getPageEvent(); 494 if (pageEvent != null && isParagraph) 495 pageEvent.onParagraph(writer, this, indentTop() - currentHeight); 496 497 if (paragraph.getKeepTogether()) { 499 PdfPTable table = new PdfPTable(1); 500 table.setWidthPercentage(100f); 501 PdfPCell cell = new PdfPCell(); 502 cell.addElement(paragraph); 503 cell.setBorder(Table.NO_BORDER); 504 table.addCell(cell); 505 this.add(table); 506 } 507 else { 508 indentation.paragraph += paragraph.getIndentationLeft(); 509 line.setExtraIndent(paragraph.getFirstLineIndent()); 510 element.process(this); 511 indentation.paragraph -= paragraph.getIndentationLeft(); 512 } 513 514 addSpacing(paragraph.spacingAfter(), paragraph.getTotalLeading(), paragraph.getFont()); 515 516 if (pageEvent != null && isParagraph) 517 pageEvent.onParagraphEnd(writer, this, indentTop() - currentHeight); 518 519 alignment = Element.ALIGN_LEFT; 520 indentation.indentLeft -= paragraph.getIndentationLeft(); 521 indentation.indentRight -= paragraph.getIndentationRight(); 522 carriageReturn(); 523 break; 524 } 525 case Element.SECTION: 526 case Element.CHAPTER: { 527 Section section = (Section) element; 530 531 boolean hasTitle = section.getTitle() != null; 532 533 if (section.isTriggerNewPage()) { 535 newPage(); 536 } 537 else { 539 newLine(); 540 } 541 542 if (hasTitle) { 543 float fith = indentTop() - currentHeight; 544 int rotation = pageSize.getRotation(); 545 if (rotation == 90 || rotation == 180) 546 fith = pageSize.getHeight() - fith; 547 PdfDestination destination = new PdfDestination(PdfDestination.FITH, fith); 548 while (currentOutline.level() >= section.getDepth()) { 549 currentOutline = currentOutline.parent(); 550 } 551 PdfOutline outline = new PdfOutline(currentOutline, destination, section.getBookmarkTitle(), section.isBookmarkOpen()); 552 currentOutline = outline; 553 } 554 555 carriageReturn(); 557 indentation.indentLeft += section.getIndentationLeft(); 558 indentation.indentRight += section.getIndentationRight(); 559 indentation.sectionIndentLeft += section.getIndentationLeft(); 560 indentation.sectionIndentRight += section.getIndentationRight(); 561 562 PdfPageEvent pageEvent = writer.getPageEvent(); 563 if (pageEvent != null) 564 if (element.type() == Element.CHAPTER) 565 pageEvent.onChapter(writer, this, indentTop() - currentHeight, section.getTitle()); 566 else 567 pageEvent.onSection(writer, this, indentTop() - currentHeight, section.getDepth(), section.getTitle()); 568 569 if (hasTitle) { 571 isParagraph = false; 572 add(section.getTitle()); 573 isParagraph = true; 574 } 575 indentation.indentLeft += section.getIndentation(); 576 indentation.sectionIndentLeft += section.getIndentation(); 577 element.process(this); 579 indentation.indentLeft -= section.getIndentationLeft() + section.getIndentation(); 581 indentation.indentRight -= section.getIndentationRight(); 582 indentation.sectionIndentLeft -= section.getIndentationLeft() + section.getIndentation(); 583 indentation.sectionIndentRight -= section.getIndentationRight(); 584 585 if (pageEvent != null) 586 if (element.type() == Element.CHAPTER) 587 pageEvent.onChapterEnd(writer, this, indentTop() - currentHeight); 588 else 589 pageEvent.onSectionEnd(writer, this, indentTop() - currentHeight); 590 591 break; 592 } 593 case Element.LIST: { 594 List list = (List ) element; 596 if (list.isAlignindent()) { 597 list.normalizeIndentation(); 598 } 599 indentation.listIndentLeft += list.getIndentationLeft(); 601 indentation.indentRight += list.getIndentationRight(); 602 element.process(this); 604 indentation.listIndentLeft -= list.getIndentationLeft(); 606 indentation.indentRight -= list.getIndentationRight(); 607 break; 608 } 609 case Element.LISTITEM: { 610 ListItem listItem = (ListItem) element; 612 613 addSpacing(listItem.spacingBefore(), leading, listItem.getFont()); 614 615 alignment = listItem.getAlignment(); 617 indentation.listIndentLeft += listItem.getIndentationLeft(); 618 indentation.indentRight += listItem.getIndentationRight(); 619 leading = listItem.getTotalLeading(); 620 carriageReturn(); 621 622 line.setListItem(listItem); 624 element.process(this); 626 627 addSpacing(listItem.spacingAfter(), listItem.getTotalLeading(), listItem.getFont()); 628 629 if (line.hasToBeJustified()) { 631 line.resetAlignment(); 632 } 633 carriageReturn(); 635 indentation.listIndentLeft -= listItem.getIndentationLeft(); 636 indentation.indentRight -= listItem.getIndentationRight(); 637 break; 638 } 639 case Element.RECTANGLE: { 640 Rectangle rectangle = (Rectangle) element; 641 graphics.rectangle(rectangle); 642 pageEmpty = false; 643 break; 644 } 645 case Element.PTABLE: { 646 PdfPTable ptable = (PdfPTable)element; 647 if (ptable.size() <= ptable.getHeaderRows()) 648 break; 650 652 indentation.indentLeft -= indentation.paragraph + indentation.sectionIndentLeft; 653 indentation.indentRight -= indentation.sectionIndentRight; 654 ensureNewLine(); 655 flushLines(); 656 indentation.indentLeft += indentation.paragraph + indentation.sectionIndentLeft; 657 indentation.indentRight += indentation.sectionIndentRight; 658 659 addPTable(ptable); 660 pageEmpty = false; 661 newLine(); 662 break; 663 } 664 case Element.MULTI_COLUMN_TEXT: { 665 ensureNewLine(); 666 flushLines(); 667 MultiColumnText multiText = (MultiColumnText) element; 668 float height = multiText.write(writer.getDirectContent(), this, indentTop() - currentHeight); 669 currentHeight += height; 670 text.moveText(0, -1f* height); 671 pageEmpty = false; 672 break; 673 } 674 case Element.TABLE : { 675 PdfTable table; 676 if (element instanceof PdfTable) { 677 table = (PdfTable)element; 679 table.updateRowAdditions(); 680 } else if (element instanceof SimpleTable) { 681 PdfPTable ptable = ((SimpleTable)element).createPdfPTable(); 682 if (ptable.size() <= ptable.getHeaderRows()) 683 break; 685 ensureNewLine(); 687 flushLines(); 688 addPTable(ptable); 689 pageEmpty = false; 690 break; 691 } else if (element instanceof Table) { 692 try { 693 PdfPTable ptable = ((Table)element).createPdfPTable(); 694 if (ptable.size() <= ptable.getHeaderRows()) 695 break; 697 ensureNewLine(); 699 flushLines(); 700 addPTable(ptable); 701 pageEmpty = false; 702 break; 703 } 704 catch(BadElementException bee) { 705 float offset = ((Table)element).getOffset(); 708 if (Float.isNaN(offset)) 709 offset = leading; 710 carriageReturn(); 711 lines.add(new PdfLine(indentLeft(), indentRight(), alignment, offset)); 712 currentHeight += offset; 713 table = getPdfTable((Table)element, false); 714 } 715 } else { 716 return false; 717 } 718 add(table, false); 719 break; 720 } 721 case Element.JPEG: 722 case Element.IMGRAW: 723 case Element.IMGTEMPLATE: { 724 add((Image) element); 726 break; 727 } 728 case Element.MARKED: { 729 MarkedObject mo; 730 if (element instanceof MarkedSection) { 731 mo = ((MarkedSection)element).title(); 732 if (mo != null) { 733 mo.process(this); 734 } 735 } 736 mo = (MarkedObject)element; 737 mo.process(this); 738 break; 739 } 740 default: 741 return false; 742 } 743 lastElementType = element.type(); 744 return true; 745 } 746 catch(Exception e) { 747 throw new DocumentException(e); 748 } 749 } 750 751 753 759 public void open() { 760 if (!open) { 761 super.open(); 762 writer.open(); 763 rootOutline = new PdfOutline(writer); 764 currentOutline = rootOutline; 765 } 766 try { 767 initPage(); 768 } 769 catch(DocumentException de) { 770 throw new ExceptionConverter(de); 771 } 772 } 773 774 776 782 public void close() { 783 if (close) { 784 return; 785 } 786 try { 787 boolean wasImage = (imageWait != null); 788 newPage(); 789 if (imageWait != null || wasImage) newPage(); 790 if (annotationsImp.hasUnusedAnnotations()) 791 throw new RuntimeException ("Not all annotations could be added to the document (the document doesn't have enough pages)."); 792 PdfPageEvent pageEvent = writer.getPageEvent(); 793 if (pageEvent != null) 794 pageEvent.onCloseDocument(writer, this); 795 super.close(); 796 797 writer.addLocalDestinations(localDestinations); 798 calculateOutlineCount(); 799 writeOutlines(); 800 } 801 catch(Exception e) { 802 throw new ExceptionConverter(e); 803 } 804 805 writer.close(); 806 } 807 808 810 private boolean isNewpage = false; 811 private int textEmptySize; 812 813 819 public boolean newPage() { 820 lastElementType = -1; 821 isNewpage = true; 822 if (writer == null || (writer.getDirectContent().size() == 0 && writer.getDirectContentUnder().size() == 0 && (pageEmpty || writer.isPaused()))) { 823 return false; 824 } 825 if (!open || close) { 826 throw new RuntimeException ("The document isn't open."); 827 } 828 PdfPageEvent pageEvent = writer.getPageEvent(); 829 if (pageEvent != null) 830 pageEvent.onEndPage(writer, this); 831 832 super.newPage(); 834 835 indentation.imageIndentLeft = 0; 837 indentation.imageIndentRight = 0; 838 839 try { 840 flushLines(); 842 843 845 int rotation = pageSize.getRotation(); 847 848 if (writer.isPdfX()) { 850 if (thisBoxSize.containsKey("art") && thisBoxSize.containsKey("trim")) 851 throw new PdfXConformanceException("Only one of ArtBox or TrimBox can exist in the page."); 852 if (!thisBoxSize.containsKey("art") && !thisBoxSize.containsKey("trim")) { 853 if (thisBoxSize.containsKey("crop")) 854 thisBoxSize.put("trim", thisBoxSize.get("crop")); 855 else 856 thisBoxSize.put("trim", new PdfRectangle(pageSize, pageSize.getRotation())); 857 } 858 } 859 860 pageResources.addDefaultColorDiff(writer.getDefaultColorspace()); 862 PdfDictionary resources = pageResources.getResources(); 863 864 866 PdfPage page = new PdfPage(new PdfRectangle(pageSize, rotation), thisBoxSize, resources, rotation); 867 868 870 if (this.transition!=null) { 872 page.put(PdfName.TRANS, this.transition.getTransitionDictionary()); 873 transition = null; 874 } 875 if (this.duration>0) { 876 page.put(PdfName.DUR,new PdfNumber(this.duration)); 877 duration = 0; 878 } 879 if (pageAA != null) { 880 page.put(PdfName.AA, writer.addToBody(pageAA).getIndirectReference()); 881 pageAA = null; 882 } 883 884 if (thumb != null) { 886 page.put(PdfName.THUMB, thumb); 887 thumb = null; 888 } 889 890 if (writer.getUserunit() > 0f) { 892 page.put(PdfName.USERUNIT, new PdfNumber(writer.getUserunit())); 893 } 894 895 if (annotationsImp.hasUnusedAnnotations()) { 897 PdfArray array = annotationsImp.rotateAnnotations(writer, pageSize); 898 if (array.size() != 0) 899 page.put(PdfName.ANNOTS, array); 900 } 901 902 if (writer.isTagged()) 904 page.put(PdfName.STRUCTPARENTS, new PdfNumber(writer.getCurrentPageNumber() - 1)); 905 906 if (text.size() > textEmptySize) 907 text.endText(); 908 else 909 text = null; 910 writer.add(page, new PdfContents(writer.getDirectContentUnder(), graphics, text, writer.getDirectContent(), pageSize)); 911 initPage(); 913 } 914 catch(DocumentException de) { 915 throw new ExceptionConverter(de); 917 } 918 catch (IOException ioe) { 919 throw new ExceptionConverter(ioe); 920 } 921 isNewpage = false; 922 return true; 923 } 924 925 927 933 public boolean setPageSize(Rectangle pageSize) { 934 if (writer != null && writer.isPaused()) { 935 return false; 936 } 937 nextPageSize = new Rectangle(pageSize); 938 return true; 939 } 940 941 943 944 protected float nextMarginLeft; 945 946 947 protected float nextMarginRight; 948 949 950 protected float nextMarginTop; 951 952 953 protected float nextMarginBottom; 954 955 964 public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) { 965 if (writer != null && writer.isPaused()) { 966 return false; 967 } 968 nextMarginLeft = marginLeft; 969 nextMarginRight = marginRight; 970 nextMarginTop = marginTop; 971 nextMarginBottom = marginBottom; 972 return true; 973 } 974 975 977 980 public boolean setMarginMirroring(boolean MarginMirroring) { 981 if (writer != null && writer.isPaused()) { 982 return false; 983 } 984 return super.setMarginMirroring(MarginMirroring); 985 } 986 987 989 994 public void setPageCount(int pageN) { 995 if (writer != null && writer.isPaused()) { 996 return; 997 } 998 super.setPageCount(pageN); 999 } 1000 1001 1003 1006 public void resetPageCount() { 1007 if (writer != null && writer.isPaused()) { 1008 return; 1009 } 1010 super.resetPageCount(); 1011 } 1012 1013 1015 1020 public void setHeader(HeaderFooter header) { 1021 if (writer != null && writer.isPaused()) { 1022 return; 1023 } 1024 super.setHeader(header); 1025 } 1026 1027 1029 1032 public void resetHeader() { 1033 if (writer != null && writer.isPaused()) { 1034 return; 1035 } 1036 super.resetHeader(); 1037 } 1038 1039 1041 1046 public void setFooter(HeaderFooter footer) { 1047 if (writer != null && writer.isPaused()) { 1048 return; 1049 } 1050 super.setFooter(footer); 1051 } 1052 1053 1055 1058 public void resetFooter() { 1059 if (writer != null && writer.isPaused()) { 1060 return; 1061 } 1062 super.resetFooter(); 1063 } 1064 1065 1067 1068 private boolean firstPageEvent = true; 1069 1070 1076 private void initPage() throws DocumentException { 1077 pageN++; 1079 1080 annotationsImp.resetAnnotations(); 1082 pageResources = new PageResources(); 1083 1084 writer.resetContent(); 1085 graphics = new PdfContentByte(writer); 1086 text = new PdfContentByte(writer); 1087 text.reset(); 1088 text.beginText(); 1089 textEmptySize = text.size(); 1090 1091 markPoint = 0; 1092 if (marginMirroring && (getPageNumber() & 1) == 0) { 1093 marginRight = nextMarginLeft; 1094 marginLeft = nextMarginRight; 1095 } 1096 else { 1097 marginLeft = nextMarginLeft; 1098 marginRight = nextMarginRight; 1099 } 1100 marginTop = nextMarginTop; 1101 marginBottom = nextMarginBottom; 1102 imageEnd = -1; 1103 indentation.imageIndentRight = 0; 1104 indentation.imageIndentLeft = 0; 1105 indentation.indentBottom = 0; 1106 indentation.indentTop = 0; 1107 currentHeight = 0; 1108 1109 pageSize = nextPageSize; 1111 thisBoxSize = new HashMap (boxSize); 1112 if (pageSize.getBackgroundColor() != null 1113 || pageSize.hasBorders() 1114 || pageSize.getBorderColor() != null) { 1115 add(pageSize); 1116 } 1117 1118 float oldleading = leading; 1119 int oldAlignment = alignment; 1120 doFooter(); 1122 text.moveText(left(), top()); 1124 doHeader(); 1125 pageEmpty = true; 1126 try { 1128 if (imageWait != null) { 1129 add(imageWait); 1130 imageWait = null; 1131 } 1132 } 1133 catch(Exception e) { 1134 throw new ExceptionConverter(e); 1135 } 1136 leading = oldleading; 1137 alignment = oldAlignment; 1138 carriageReturn(); 1139 1140 PdfPageEvent pageEvent = writer.getPageEvent(); 1141 if (pageEvent != null) { 1142 if (firstPageEvent) { 1143 pageEvent.onOpenDocument(writer, this); 1144 } 1145 pageEvent.onStartPage(writer, this); 1146 } 1147 firstPageEvent = false; 1148 } 1149 1150 1151 private PdfLine line = null; 1152 1153 private ArrayList lines = new ArrayList (); 1154 1155 1159 private void newLine() throws DocumentException { 1160 lastElementType = -1; 1161 carriageReturn(); 1162 if (lines != null && !lines.isEmpty()) { 1163 lines.add(line); 1164 currentHeight += line.height(); 1165 } 1166 line = new PdfLine(indentLeft(), indentRight(), alignment, leading); 1167 } 1168 1169 1174 private void carriageReturn() { 1175 if (lines == null) { 1177 lines = new ArrayList (); 1178 } 1179 if (line != null) { 1181 if (currentHeight + line.height() + leading < indentTop() - indentBottom()) { 1183 if (line.size() > 0) { 1185 currentHeight += line.height(); 1186 lines.add(line); 1187 pageEmpty = false; 1188 } 1189 } 1190 else { 1192 newPage(); 1193 } 1194 } 1195 if (imageEnd > -1 && currentHeight > imageEnd) { 1196 imageEnd = -1; 1197 indentation.imageIndentRight = 0; 1198 indentation.imageIndentLeft = 0; 1199 } 1200 line = new PdfLine(indentLeft(), indentRight(), alignment, leading); 1202 } 1203 1204 1211 public float getVerticalPosition(boolean ensureNewLine) { 1212 if (ensureNewLine) { 1214 ensureNewLine(); 1215 } 1216 return top() - currentHeight - indentation.indentTop; 1217 } 1218 1219 1220 private int lastElementType = -1; 1221 1222 1225 private void ensureNewLine() { 1226 try { 1227 if ((lastElementType == Element.PHRASE) || 1228 (lastElementType == Element.CHUNK)) { 1229 newLine(); 1230 flushLines(); 1231 } 1232 } catch (DocumentException ex) { 1233 throw new ExceptionConverter(ex); 1234 } 1235 } 1236 1237 1243 private float flushLines() throws DocumentException { 1244 if (lines == null) { 1246 return 0; 1247 } 1248 boolean newline=false; 1249 if (line != null && line.size() > 0) { 1251 lines.add(line); 1252 line = new PdfLine(indentLeft(), indentRight(), alignment, leading); 1253 newline=true; 1254 } 1255 1256 if (lines.isEmpty()) { 1258 return 0; 1259 } 1260 1261 Object currentValues[] = new Object [2]; 1263 PdfFont currentFont = null; 1264 float displacement = 0; 1265 PdfLine l; 1266 Float lastBaseFactor = new Float (0); 1267 currentValues[1] = lastBaseFactor; 1268 for (Iterator i = lines.iterator(); i.hasNext(); ) { 1270 1271 l = (PdfLine) i.next(); 1273 1274 if(isNewpage && newline) { newline=false; 1276 text.moveText(l.indentLeft() - indentLeft() + indentation.listIndentLeft + indentation.paragraph,-l.height()); 1277 } 1278 else { 1279 text.moveText(l.indentLeft() - indentLeft() + indentation.listIndentLeft, -l.height()); 1280 } 1281 1282 if (l.listSymbol() != null) { 1284 ColumnText.showTextAligned(graphics, Element.ALIGN_LEFT, new Phrase(l.listSymbol()), text.getXTLM() - l.listIndent(), text.getYTLM(), 0); 1285 } 1286 1287 currentValues[0] = currentFont; 1288 1289 writeLineToContent(l, text, graphics, currentValues, writer.getSpaceCharRatio()); 1290 1291 currentFont = (PdfFont)currentValues[0]; 1292 1293 displacement += l.height(); 1294 if (indentLeft() - indentation.listIndentLeft != l.indentLeft()) { 1295 text.moveText(indentLeft() - l.indentLeft() - indentation.listIndentLeft, 0); 1296 } 1297 1298 } 1299 lines = new ArrayList (); 1300 return displacement; 1301 } 1302 1303 1304 static final String hangingPunctuation = ".,;:'"; 1305 1306 1318 void writeLineToContent(PdfLine line, PdfContentByte text, PdfContentByte graphics, Object currentValues[], float ratio) throws DocumentException { 1319 PdfFont currentFont = (PdfFont)(currentValues[0]); 1320 float lastBaseFactor = ((Float )(currentValues[1])).floatValue(); 1321 PdfChunk chunk; 1322 int numberOfSpaces; 1323 int lineLen; 1324 boolean isJustified; 1325 float hangingCorrection = 0; 1326 float hScale = 1; 1327 float lastHScale = Float.NaN; 1328 float baseWordSpacing = 0; 1329 float baseCharacterSpacing = 0; 1330 1331 numberOfSpaces = line.numberOfSpaces(); 1332 lineLen = line.toString().length(); 1333 isJustified = line.hasToBeJustified() && (numberOfSpaces != 0 || lineLen > 1); 1335 if (isJustified) { 1336 if (line.isNewlineSplit() && line.widthLeft() >= (lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1))) { 1337 if (line.isRTL()) { 1338 text.moveText(line.widthLeft() - lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1), 0); 1339 } 1340 baseWordSpacing = ratio * lastBaseFactor; 1341 baseCharacterSpacing = lastBaseFactor; 1342 } 1343 else { 1344 float width = line.widthLeft(); 1345 PdfChunk last = line.getChunk(line.size() - 1); 1346 if (last != null) { 1347 String s = last.toString(); 1348 char c; 1349 if (s.length() > 0 && hangingPunctuation.indexOf((c = s.charAt(s.length() - 1))) >= 0) { 1350 float oldWidth = width; 1351 width += last.font().width(c) * 0.4f; 1352 hangingCorrection = width - oldWidth; 1353 } 1354 } 1355 float baseFactor = width / (ratio * numberOfSpaces + lineLen - 1); 1356 baseWordSpacing = ratio * baseFactor; 1357 baseCharacterSpacing = baseFactor; 1358 lastBaseFactor = baseFactor; 1359 } 1360 } 1361 1362 int lastChunkStroke = line.getLastStrokeChunk(); 1363 int chunkStrokeIdx = 0; 1364 float xMarker = text.getXTLM(); 1365 float baseXMarker = xMarker; 1366 float yMarker = text.getYTLM(); 1367 boolean adjustMatrix = false; 1368 1369 for (Iterator j = line.iterator(); j.hasNext(); ) { 1371 chunk = (PdfChunk) j.next(); 1372 Color color = chunk.color(); 1373 hScale = 1; 1374 1375 if (chunkStrokeIdx <= lastChunkStroke) { 1376 float width; 1377 if (isJustified) { 1378 width = chunk.getWidthCorrected(baseCharacterSpacing, baseWordSpacing); 1379 } 1380 else 1381 width = chunk.width(); 1382 if (chunk.isStroked()) { 1383 PdfChunk nextChunk = line.getChunk(chunkStrokeIdx + 1); 1384 if (chunk.isAttribute(Chunk.BACKGROUND)) { 1385 float subtract = lastBaseFactor; 1386 if (nextChunk != null && nextChunk.isAttribute(Chunk.BACKGROUND)) 1387 subtract = 0; 1388 if (nextChunk == null) 1389 subtract += hangingCorrection; 1390 float fontSize = chunk.font().size(); 1391 float ascender = chunk.font().getFont().getFontDescriptor(BaseFont.ASCENT, fontSize); 1392 float descender = chunk.font().getFont().getFontDescriptor(BaseFont.DESCENT, fontSize); 1393 Object bgr[] = (Object [])chunk.getAttribute(Chunk.BACKGROUND); 1394 graphics.setColorFill((Color )bgr[0]); 1395 float extra[] = (float[])bgr[1]; 1396 graphics.rectangle(xMarker - extra[0], 1397 yMarker + descender - extra[1] + chunk.getTextRise(), 1398 width - subtract + extra[0] + extra[2], 1399 ascender - descender + extra[1] + extra[3]); 1400 graphics.fill(); 1401 graphics.setGrayFill(0); 1402 } 1403 if (chunk.isAttribute(Chunk.UNDERLINE)) { 1404 float subtract = lastBaseFactor; 1405 if (nextChunk != null && nextChunk.isAttribute(Chunk.UNDERLINE)) 1406 subtract = 0; 1407 if (nextChunk == null) 1408 subtract += hangingCorrection; 1409 Object unders[][] = (Object [][])chunk.getAttribute(Chunk.UNDERLINE); 1410 Color scolor = null; 1411 for (int k = 0; k < unders.length; ++k) { 1412 Object obj[] = unders[k]; 1413 scolor = (Color )obj[0]; 1414 float ps[] = (float[])obj[1]; 1415 if (scolor == null) 1416 scolor = color; 1417 if (scolor != null) 1418 graphics.setColorStroke(scolor); 1419 float fsize = chunk.font().size(); 1420 graphics.setLineWidth(ps[0] + fsize * ps[1]); 1421 float shift = ps[2] + fsize * ps[3]; 1422 int cap2 = (int)ps[4]; 1423 if (cap2 != 0) 1424 graphics.setLineCap(cap2); 1425 graphics.moveTo(xMarker, yMarker + shift); 1426 graphics.lineTo(xMarker + width - subtract, yMarker + shift); 1427 graphics.stroke(); 1428 if (scolor != null) 1429 graphics.resetGrayStroke(); 1430 if (cap2 != 0) 1431 graphics.setLineCap(0); 1432 } 1433 graphics.setLineWidth(1); 1434 } 1435 if (chunk.isAttribute(Chunk.ACTION)) { 1436 float subtract = lastBaseFactor; 1437 if (nextChunk != null && nextChunk.isAttribute(Chunk.ACTION)) 1438 subtract = 0; 1439 if (nextChunk == null) 1440 subtract += hangingCorrection; 1441 text.addAnnotation(new PdfAnnotation(writer, xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size(), (PdfAction)chunk.getAttribute(Chunk.ACTION))); 1442 } 1443 if (chunk.isAttribute(Chunk.REMOTEGOTO)) { 1444 float subtract = lastBaseFactor; 1445 if (nextChunk != null && nextChunk.isAttribute(Chunk.REMOTEGOTO)) 1446 subtract = 0; 1447 if (nextChunk == null) 1448 subtract += hangingCorrection; 1449 Object obj[] = (Object [])chunk.getAttribute(Chunk.REMOTEGOTO); 1450 String filename = (String )obj[0]; 1451 if (obj[1] instanceof String ) 1452 remoteGoto(filename, (String )obj[1], xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size()); 1453 else 1454 remoteGoto(filename, ((Integer )obj[1]).intValue(), xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size()); 1455 } 1456 if (chunk.isAttribute(Chunk.LOCALGOTO)) { 1457 float subtract = lastBaseFactor; 1458 if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALGOTO)) 1459 subtract = 0; 1460 if (nextChunk == null) 1461 subtract += hangingCorrection; 1462 localGoto((String )chunk.getAttribute(Chunk.LOCALGOTO), xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size()); 1463 } 1464 if (chunk.isAttribute(Chunk.LOCALDESTINATION)) { 1465 float subtract = lastBaseFactor; 1466 if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALDESTINATION)) 1467 subtract = 0; 1468 if (nextChunk == null) 1469 subtract += hangingCorrection; 1470 localDestination((String )chunk.getAttribute(Chunk.LOCALDESTINATION), new PdfDestination(PdfDestination.XYZ, xMarker, yMarker + chunk.font().size(), 0)); 1471 } 1472 if (chunk.isAttribute(Chunk.GENERICTAG)) { 1473 float subtract = lastBaseFactor; 1474 if (nextChunk != null && nextChunk.isAttribute(Chunk.GENERICTAG)) 1475 subtract = 0; 1476 if (nextChunk == null) 1477 subtract += hangingCorrection; 1478 Rectangle rect = new Rectangle(xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size()); 1479 PdfPageEvent pev = writer.getPageEvent(); 1480 if (pev != null) 1481 pev.onGenericTag(writer, this, rect, (String )chunk.getAttribute(Chunk.GENERICTAG)); 1482 } 1483 if (chunk.isAttribute(Chunk.PDFANNOTATION)) { 1484 float subtract = lastBaseFactor; 1485 if (nextChunk != null && nextChunk.isAttribute(Chunk.PDFANNOTATION)) 1486 subtract = 0; 1487 if (nextChunk == null) 1488 subtract += hangingCorrection; 1489 float fontSize = chunk.font().size(); 1490 float ascender = chunk.font().getFont().getFontDescriptor(BaseFont.ASCENT, fontSize); 1491 float descender = chunk.font().getFont().getFontDescriptor(BaseFont.DESCENT, fontSize); 1492 PdfAnnotation annot = PdfFormField.shallowDuplicate((PdfAnnotation)chunk.getAttribute(Chunk.PDFANNOTATION)); 1493 annot.put(PdfName.RECT, new PdfRectangle(xMarker, yMarker + descender, xMarker + width - subtract, yMarker + ascender)); 1494 text.addAnnotation(annot); 1495 } 1496 float params[] = (float[])chunk.getAttribute(Chunk.SKEW); 1497 Float hs = (Float )chunk.getAttribute(Chunk.HSCALE); 1498 if (params != null || hs != null) { 1499 float b = 0, c = 0; 1500 if (params != null) { 1501 b = params[0]; 1502 c = params[1]; 1503 } 1504 if (hs != null) 1505 hScale = hs.floatValue(); 1506 text.setTextMatrix(hScale, b, c, 1, xMarker, yMarker); 1507 } 1508 if (chunk.isImage()) { 1509 Image image = chunk.getImage(); 1510 float matrix[] = image.matrix(); 1511 matrix[Image.CX] = xMarker + chunk.getImageOffsetX() - matrix[Image.CX]; 1512 matrix[Image.CY] = yMarker + chunk.getImageOffsetY() - matrix[Image.CY]; 1513 graphics.addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); 1514 text.moveText(xMarker + lastBaseFactor + image.getScaledWidth() - text.getXTLM(), 0); 1515 } 1516 } 1517 xMarker += width; 1518 ++chunkStrokeIdx; 1519 } 1520 1521 if (chunk.font().compareTo(currentFont) != 0) { 1522 currentFont = chunk.font(); 1523 text.setFontAndSize(currentFont.getFont(), currentFont.size()); 1524 } 1525 float rise = 0; 1526 Object textRender[] = (Object [])chunk.getAttribute(Chunk.TEXTRENDERMODE); 1527 int tr = 0; 1528 float strokeWidth = 1; 1529 Color strokeColor = null; 1530 Float fr = (Float )chunk.getAttribute(Chunk.SUBSUPSCRIPT); 1531 if (textRender != null) { 1532 tr = ((Integer )textRender[0]).intValue() & 3; 1533 if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL) 1534 text.setTextRenderingMode(tr); 1535 if (tr == PdfContentByte.TEXT_RENDER_MODE_STROKE || tr == PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE) { 1536 strokeWidth = ((Float )textRender[1]).floatValue(); 1537 if (strokeWidth != 1) 1538 text.setLineWidth(strokeWidth); 1539 strokeColor = (Color )textRender[2]; 1540 if (strokeColor == null) 1541 strokeColor = color; 1542 if (strokeColor != null) 1543 text.setColorStroke(strokeColor); 1544 } 1545 } 1546 if (fr != null) 1547 rise = fr.floatValue(); 1548 if (color != null) 1549 text.setColorFill(color); 1550 if (rise != 0) 1551 text.setTextRise(rise); 1552 if (chunk.isImage()) { 1553 adjustMatrix = true; 1554 } 1555 else if (isJustified && numberOfSpaces > 0 && chunk.isSpecialEncoding()) { 1558 if (hScale != lastHScale) { 1559 lastHScale = hScale; 1560 text.setWordSpacing(baseWordSpacing / hScale); 1561 text.setCharacterSpacing(baseCharacterSpacing / hScale); 1562 } 1563 String s = chunk.toString(); 1564 int idx = s.indexOf(' '); 1565 if (idx < 0) 1566 text.showText(chunk.toString()); 1567 else { 1568 float spaceCorrection = - baseWordSpacing * 1000f / chunk.font.size() / hScale; 1569 PdfTextArray textArray = new PdfTextArray(s.substring(0, idx)); 1570 int lastIdx = idx; 1571 while ((idx = s.indexOf(' ', lastIdx + 1)) >= 0) { 1572 textArray.add(spaceCorrection); 1573 textArray.add(s.substring(lastIdx, idx)); 1574 lastIdx = idx; 1575 } 1576 textArray.add(spaceCorrection); 1577 textArray.add(s.substring(lastIdx)); 1578 text.showText(textArray); 1579 } 1580 } 1581 else { 1582 if (isJustified && hScale != lastHScale) { 1583 lastHScale = hScale; 1584 text.setWordSpacing(baseWordSpacing / hScale); 1585 text.setCharacterSpacing(baseCharacterSpacing / hScale); 1586 } 1587 text.showText(chunk.toString()); 1588 } 1589 1590 if (rise != 0) 1591 text.setTextRise(0); 1592 if (color != null) 1593 text.resetRGBColorFill(); 1594 if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL) 1595 text.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL); 1596 if (strokeColor != null) 1597 text.resetRGBColorStroke(); 1598 if (strokeWidth != 1) 1599 text.setLineWidth(1); 1600 if (chunk.isAttribute(Chunk.SKEW) || chunk.isAttribute(Chunk.HSCALE)) { 1601 adjustMatrix = true; 1602 text.setTextMatrix(xMarker, yMarker); 1603 } 1604 } 1605 if (isJustified) { 1606 text.setWordSpacing(0); 1607 text.setCharacterSpacing(0); 1608 if (line.isNewlineSplit()) 1609 lastBaseFactor = 0; 1610 } 1611 if (adjustMatrix) 1612 text.moveText(baseXMarker - text.getXTLM(), 0); 1613 currentValues[0] = currentFont; 1614 currentValues[1] = new Float (lastBaseFactor); 1615 } 1616 1617 Indentation indentation = new Indentation(); 1618 public static class Indentation { 1619 1620 float paragraph = 0; 1621 1622 1623 private float indentLeft = 0; 1624 1625 1626 private float sectionIndentLeft = 0; 1627 1628 1629 private float listIndentLeft = 0; 1630 1631 1632 private float imageIndentLeft = 0; 1633 1634 1635 private float indentRight = 0; 1636 1637 1638 private float sectionIndentRight = 0; 1639 1640 1641 private float imageIndentRight = 0; 1642 1643 1644 private float indentTop = 0; 1645 1646 1647 private float indentBottom = 0; 1648 } 1649 1650 1655 1656 private float indentLeft() { 1657 return left(indentation.indentLeft + indentation.listIndentLeft + indentation.imageIndentLeft); 1658 } 1659 1660 1665 1666 private float indentRight() { 1667 return right(indentation.indentRight + indentation.imageIndentRight); 1668 } 1669 1670 1675 1676 private float indentTop() { 1677 return top(indentation.indentTop); 1678 } 1679 1680 1685 1686 float indentBottom() { 1687 return bottom(indentation.indentBottom); 1688 } 1689 1690 1694 private void addSpacing(float extraspace, float oldleading, Font f) { 1695 if (extraspace == 0) return; 1696 if (pageEmpty) return; 1697 if (currentHeight + line.height() + leading > indentTop() - indentBottom()) return; 1698 leading = extraspace; 1699 carriageReturn(); 1700 Chunk space = new Chunk(" ", f); 1701 space.process(this); 1702 carriageReturn(); 1703 leading = oldleading; 1704 } 1705 1706 1708 1709 private PdfInfo info = new PdfInfo(); 1710 1711 1716 1717 PdfInfo getInfo() { 1718 return info; 1719 } 1720 1721 1727 1728 PdfCatalog getCatalog(PdfIndirectReference pages) { 1729 PdfCatalog catalog = new PdfCatalog(pages, writer); 1730 1731 if (rootOutline.getKids().size() > 0) { 1733 catalog.put(PdfName.PAGEMODE, PdfName.USEOUTLINES); 1734 catalog.put(PdfName.OUTLINES, rootOutline.indirectReference()); 1735 } 1736 1737 writer.getPdfVersion().addToCatalog(catalog); 1739 1740 viewerPreferences.addToCatalog(catalog); 1742 1743 if (pageLabels != null) { 1745 catalog.put(PdfName.PAGELABELS, pageLabels.getDictionary()); 1746 } 1747 1748 catalog.addNames(localDestinations, documentJavaScript, documentFileAttachment, writer); 1750 1751 if (openActionName != null) { 1753 PdfAction action = getLocalGotoAction(openActionName); 1754 catalog.setOpenAction(action); 1755 } 1756 else if (openActionAction != null) 1757 catalog.setOpenAction(openActionAction); 1758 if (additionalActions != null) { 1759 catalog.setAdditionalActions(additionalActions); 1760 } 1761 1762 if (collection != null) { 1764 catalog.put(PdfName.COLLECTION, collection); 1765 } 1766 1767 if (annotationsImp.hasValidAcroForm()) { 1769 try { 1770 catalog.put(PdfName.ACROFORM, writer.addToBody(annotationsImp.getAcroForm()).getIndirectReference()); 1771 } 1772 catch (IOException e) { 1773 throw new ExceptionConverter(e); 1774 } 1775 } 1776 1777 return catalog; 1778 } 1779 1780 1782 1783 private PdfOutline rootOutline; 1784 1785 1786 private PdfOutline currentOutline; 1787 1788 1793 void addOutline(PdfOutline outline, String name) { 1794 localDestination(name, outline.getPdfDestination()); 1795 } 1796 1797 1802 public PdfOutline getRootOutline() { 1803 return rootOutline; 1804 } 1805 1806 1807 1810 void calculateOutlineCount() { 1811 if (rootOutline.getKids().size() == 0) 1812 return; 1813 traverseOutlineCount(rootOutline); 1814 } 1815 1816 1819 void traverseOutlineCount(PdfOutline outline) { 1820 ArrayList kids = outline.getKids(); 1821 PdfOutline parent = outline.parent(); 1822 if (kids.isEmpty()) { 1823 if (parent != null) { 1824 parent.setCount(parent.getCount() + 1); 1825 } 1826 } 1827 else { 1828 for (int k = 0; k < kids.size(); ++k) { 1829 traverseOutlineCount((PdfOutline)kids.get(k)); 1830 } 1831 if (parent != null) { 1832 if (outline.isOpen()) { 1833 parent.setCount(outline.getCount() + parent.getCount() + 1); 1834 } 1835 else { 1836 parent.setCount(parent.getCount() + 1); 1837 outline.setCount(-outline.getCount()); 1838 } 1839 } 1840 } 1841 } 1842 1843 1846 void writeOutlines() throws IOException { 1847 if (rootOutline.getKids().size() == 0) 1848 return; 1849 outlineTree(rootOutline); 1850 writer.addToBody(rootOutline, rootOutline.indirectReference()); 1851 } 1852 1853 1856 void outlineTree(PdfOutline outline) throws IOException { 1857 outline.setIndirectReference(writer.getPdfIndirectReference()); 1858 if (outline.parent() != null) 1859 outline.put(PdfName.PARENT, outline.parent().indirectReference()); 1860 ArrayList kids = outline.getKids(); 1861 int size = kids.size(); 1862 for (int k = 0; k < size; ++k) 1863 outlineTree((PdfOutline)kids.get(k)); 1864 for (int k = 0; k < size; ++k) { 1865 if (k > 0) 1866 ((PdfOutline)kids.get(k)).put(PdfName.PREV, ((PdfOutline)kids.get(k - 1)).indirectReference()); 1867 if (k < size - 1) 1868 ((PdfOutline)kids.get(k)).put(PdfName.NEXT, ((PdfOutline)kids.get(k + 1)).indirectReference()); 1869 } 1870 if (size > 0) { 1871 outline.put(PdfName.FIRST, ((PdfOutline)kids.get(0)).indirectReference()); 1872 outline.put(PdfName.LAST, ((PdfOutline)kids.get(size - 1)).indirectReference()); 1873 } 1874 for (int k = 0; k < size; ++k) { 1875 PdfOutline kid = (PdfOutline)kids.get(k); 1876 writer.addToBody(kid, kid.indirectReference()); 1877 } 1878 } 1879 1880 1882 1883 protected PdfViewerPreferencesImp viewerPreferences = new PdfViewerPreferencesImp(); 1884 1885 void setViewerPreferences(int preferences) { 1886 this.viewerPreferences.setViewerPreferences(preferences); 1887 } 1888 1889 1890 void addViewerPreference(PdfName key, PdfObject value) { 1891 this.viewerPreferences.addViewerPreference(key, value); 1892 } 1893 1894 1896 protected PdfPageLabels pageLabels; 1897 1901 void setPageLabels(PdfPageLabels pageLabels) { 1902 this.pageLabels = pageLabels; 1903 } 1904 1905 1907 1916 void localGoto(String name, float llx, float lly, float urx, float ury) { 1917 PdfAction action = getLocalGotoAction(name); 1918 annotationsImp.addPlainAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, action)); 1919 } 1920 1921 1930 void remoteGoto(String filename, String name, float llx, float lly, float urx, float ury) { 1931 annotationsImp.addPlainAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, new PdfAction(filename, name))); 1932 } 1933 1934 1943 void remoteGoto(String filename, int page, float llx, float lly, float urx, float ury) { 1944 addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, new PdfAction(filename, page))); 1945 } 1946 1947 1954 void setAction(PdfAction action, float llx, float lly, float urx, float ury) { 1955 addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, action)); 1956 } 1957 1958 1962 private TreeMap localDestinations = new TreeMap (); 1963 1964 PdfAction getLocalGotoAction(String name) { 1965 PdfAction action; 1966 Object obj[] = (Object [])localDestinations.get(name); 1967 if (obj == null) 1968 obj = new Object [3]; 1969 if (obj[0] == null) { 1970 if (obj[1] == null) { 1971 obj[1] = writer.getPdfIndirectReference(); 1972 } 1973 action = new PdfAction((PdfIndirectReference)obj[1]); 1974 obj[0] = action; 1975 localDestinations.put(name, obj); 1976 } 1977 else { 1978 action = (PdfAction)obj[0]; 1979 } 1980 return action; 1981 } 1982 1983 1992 boolean localDestination(String name, PdfDestination destination) { 1993 Object obj[] = (Object [])localDestinations.get(name); 1994 if (obj == null) 1995 obj = new Object [3]; 1996 if (obj[2] != null) 1997 return false; 1998 obj[2] = destination; 1999 localDestinations.put(name, obj); 2000 destination.addPage(writer.getCurrentPage()); 2001 return true; 2002 } 2003 2004 2007 private ArrayList documentJavaScript = new ArrayList (); 2008 void addJavaScript(PdfAction js) { 2009 if (js.get(PdfName.JS) == null) 2010 throw new RuntimeException ("Only JavaScript actions are allowed."); 2011 try { 2012 documentJavaScript.add(writer.addToBody(js).getIndirectReference()); 2013 } 2014 catch (IOException e) { 2015 throw new ExceptionConverter(e); 2016 } 2017 } 2018 2019 ArrayList getDocumentJavaScript() { 2020 return documentJavaScript; 2021 } 2022 2023 private HashMap documentFileAttachment = new HashMap (); 2024 2025 void addFileAttachment(String description, PdfFileSpecification fs) throws IOException { 2026 if (description == null) { 2027 PdfString desc = (PdfString)fs.get(PdfName.DESC); 2028 if (desc == null) { 2029 description = ""; 2030 } 2031 else { 2032 description = PdfEncodings.convertToString(desc.getBytes(), null); 2033 } 2034 } 2035 fs.addDescription(description, true); 2036 if (description.length() == 0) 2037 description = "Unnamed"; 2038 String fn = PdfEncodings.convertToString(new PdfString(description, PdfObject.TEXT_UNICODE).getBytes(), null); 2039 int k = 0; 2040 while (documentFileAttachment.containsKey(fn)) { 2041 ++k; 2042 fn = PdfEncodings.convertToString(new PdfString(description + " " + k, PdfObject.TEXT_UNICODE).getBytes(), null); 2043 } 2044 documentFileAttachment.put(fn, fs.getReference()); 2045 } 2046 2047 HashMap getDocumentFileAttachment() { 2048 return documentFileAttachment; 2049 } 2050 2051 2053 private String openActionName; 2054 2055 void setOpenAction(String name) { 2056 openActionName = name; 2057 openActionAction = null; 2058 } 2059 2060 private PdfAction openActionAction; 2061 void setOpenAction(PdfAction action) { 2062 openActionAction = action; 2063 openActionName = null; 2064 } 2065 2066 private PdfDictionary additionalActions; 2067 void addAdditionalAction(PdfName actionType, PdfAction action) { 2068 if (additionalActions == null) { 2069 additionalActions = new PdfDictionary(); 2070 } 2071 if (action == null) 2072 additionalActions.remove(actionType); 2073 else 2074 additionalActions.put(actionType, action); 2075 if (additionalActions.size() == 0) 2076 additionalActions = null; 2077 } 2078 2079 2081 private PdfCollection collection; 2082 2083 2087 public void setCollection(PdfCollection collection) { 2088 this.collection = collection; 2089 } 2090 2091 2093 PdfAnnotationsImp annotationsImp; 2094 2095 2099 PdfAcroForm getAcroForm() { 2100 return annotationsImp.getAcroForm(); 2101 } 2102 2103 void setSigFlags(int f) { 2104 annotationsImp.setSigFlags(f); 2105 } 2106 2107 void addCalculationOrder(PdfFormField formField) { 2108 annotationsImp.addCalculationOrder(formField); 2109 } 2110 2111 void addAnnotation(PdfAnnotation annot) { 2112 pageEmpty = false; 2113 annotationsImp.addAnnotation(annot); 2114 } 2115 2116 2118 protected int markPoint; 2119 2120 int getMarkPoint() { 2121 return markPoint; 2122 } 2123 2124 void incMarkPoint() { 2125 ++markPoint; 2126 } 2127 2128 2130 2131 protected Rectangle nextPageSize = null; 2132 2133 2134 protected HashMap thisBoxSize = new HashMap (); 2135 2136 2138 protected HashMap boxSize = new HashMap (); 2139 2140 void setCropBoxSize(Rectangle crop) { 2141 setBoxSize("crop", crop); 2142 } 2143 2144 void setBoxSize(String boxName, Rectangle size) { 2145 if (size == null) 2146 boxSize.remove(boxName); 2147 else 2148 boxSize.put(boxName, new PdfRectangle(size)); 2149 } 2150 2151 2155 Rectangle getBoxSize(String boxName) { 2156 PdfRectangle r = (PdfRectangle)thisBoxSize.get(boxName); 2157 if (r != null) return r.getRectangle(); 2158 return null; 2159 } 2160 2161 2163 2164 private boolean pageEmpty = true; 2165 2166 void setPageEmpty(boolean pageEmpty) { 2167 this.pageEmpty = pageEmpty; 2168 } 2169 2170 2172 2173 protected int duration=-1; 2175 2176 protected PdfTransition transition=null; 2177 2178 2182 void setDuration(int seconds) { 2183 if (seconds > 0) 2184 this.duration=seconds; 2185 else 2186 this.duration=-1; 2187 } 2188 2189 2193 void setTransition(PdfTransition transition) { 2194 this.transition=transition; 2195 } 2196 2197 protected PdfDictionary pageAA = null; 2198 void setPageAction(PdfName actionType, PdfAction action) { 2199 if (pageAA == null) { 2200 pageAA = new PdfDictionary(); 2201 } 2202 pageAA.put(actionType, action); 2203 } 2204 2205 2207 private PdfIndirectReference thumb; 2208 void setThumbnail(Image image) throws PdfException, DocumentException { 2209 thumb = writer.getImageReference(writer.addDirectImageSimple(image)); 2210 } 2211 2212 2214 2215 protected PageResources pageResources; 2216 2217 PageResources getPageResources() { 2218 return pageResources; 2219 } 2220 2221 2223 2224 private boolean strictImageSequence = false; 2225 2226 2230 boolean isStrictImageSequence() { 2231 return this.strictImageSequence; 2232 } 2233 2234 2238 void setStrictImageSequence(boolean strictImageSequence) { 2239 this.strictImageSequence = strictImageSequence; 2240 } 2241 2242 2243 private float imageEnd = -1; 2244 2245 2248 public void clearTextWrap() { 2249 float tmpHeight = imageEnd - currentHeight; 2250 if (line != null) { 2251 tmpHeight += line.height(); 2252 } 2253 if ((imageEnd > -1) && (tmpHeight > 0)) { 2254 carriageReturn(); 2255 currentHeight += tmpHeight; 2256 } 2257 } 2258 2259 2260 private Image imageWait = null; 2261 2262 2268 2269 private void add(Image image) throws PdfException, DocumentException { 2270 2271 if (image.hasAbsoluteY()) { 2272 graphics.addImage(image); 2273 pageEmpty = false; 2274 return; 2275 } 2276 2277 if (currentHeight != 0 && indentTop() - currentHeight - image.getScaledHeight() < indentBottom()) { 2279 if (!strictImageSequence && imageWait == null) { 2280 imageWait = image; 2281 return; 2282 } 2283 newPage(); 2284 if (currentHeight != 0 && indentTop() - currentHeight - image.getScaledHeight() < indentBottom()) { 2285 imageWait = image; 2286 return; 2287 } 2288 } 2289 pageEmpty = false; 2290 if (image == imageWait) 2292 imageWait = null; 2293 boolean textwrap = (image.getAlignment() & Image.TEXTWRAP) == Image.TEXTWRAP 2294 && !((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE); 2295 boolean underlying = (image.getAlignment() & Image.UNDERLYING) == Image.UNDERLYING; 2296 float diff = leading / 2; 2297 if (textwrap) { 2298 diff += leading; 2299 } 2300 float lowerleft = indentTop() - currentHeight - image.getScaledHeight() -diff; 2301 float mt[] = image.matrix(); 2302 float startPosition = indentLeft() - mt[4]; 2303 if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT) startPosition = indentRight() - image.getScaledWidth() - mt[4]; 2304 if ((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE) startPosition = indentLeft() + ((indentRight() - indentLeft() - image.getScaledWidth()) / 2) - mt[4]; 2305 if (image.hasAbsoluteX()) startPosition = image.getAbsoluteX(); 2306 if (textwrap) { 2307 if (imageEnd < 0 || imageEnd < currentHeight + image.getScaledHeight() + diff) { 2308 imageEnd = currentHeight + image.getScaledHeight() + diff; 2309 } 2310 if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT) { 2311 indentation.imageIndentRight += image.getScaledWidth() + image.getIndentationLeft(); 2313 } 2314 else { 2315 indentation.imageIndentLeft += image.getScaledWidth() + image.getIndentationRight(); 2317 } 2318 } 2319 else { 2320 if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT) startPosition -= image.getIndentationRight(); 2321 else if ((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE) startPosition += image.getIndentationLeft() - image.getIndentationRight(); 2322 else startPosition += image.getIndentationLeft(); 2323 } 2324 graphics.addImage(image, mt[0], mt[1], mt[2], mt[3], startPosition, lowerleft - mt[5]); 2325 if (!(textwrap || underlying)) { 2326 currentHeight += image.getScaledHeight() + diff; 2327 flushLines(); 2328 text.moveText(0, - (image.getScaledHeight() + diff)); 2329 newLine(); 2330 } 2331 } 2332 2333 2335 2339 void addPTable(PdfPTable ptable) throws DocumentException { 2340 ColumnText ct = new ColumnText(writer.getDirectContent()); 2341 if (currentHeight > 0) { 2342 Paragraph p = new Paragraph(); 2343 p.setLeading(0); 2344 ct.addElement(p); 2345 if (ptable.getKeepTogether() && !fitsPage(ptable, 0f)) { 2348 newPage(); 2349 } 2350 } 2351 ct.addElement(ptable); 2352 boolean he = ptable.isHeadersInEvent(); 2353 ptable.setHeadersInEvent(true); 2354 int loop = 0; 2355 while (true) { 2356 ct.setSimpleColumn(indentLeft(), indentBottom(), indentRight(), indentTop() - currentHeight); 2357 int status = ct.go(); 2358 if ((status & ColumnText.NO_MORE_TEXT) != 0) { 2359 text.moveText(0, ct.getYLine() - indentTop() + currentHeight); 2360 currentHeight = indentTop() - ct.getYLine(); 2361 break; 2362 } 2363 if (indentTop() - currentHeight == ct.getYLine()) 2364 ++loop; 2365 else 2366 loop = 0; 2367 if (loop == 3) { 2368 add(new Paragraph("ERROR: Infinite table loop")); 2369 break; 2370 } 2371 newPage(); 2372 } 2373 ptable.setHeadersInEvent(he); 2374 } 2375 2376 2383 2384 boolean fitsPage(PdfPTable table, float margin) { 2385 if (!table.isLockedWidth()) { 2386 float totalWidth = (indentRight() - indentLeft()) * table.getWidthPercentage() / 100; 2387 table.setTotalWidth(totalWidth); 2388 } 2389 ensureNewLine(); 2391 return table.getTotalHeight() <= indentTop() - currentHeight - indentBottom() - margin; 2392 } 2393 2394 2396 2404 2405 PdfTable getPdfTable(Table table, boolean supportRowAdditions) { 2406 return new PdfTable(table, indentLeft(), indentRight(), indentTop() - currentHeight, supportRowAdditions); 2407 } 2408 2409 2412 private static class RenderingContext { 2413 float pagetop = -1; 2414 float oldHeight = -1; 2415 2416 PdfContentByte cellGraphics = null; 2417 2418 float lostTableBottom; 2419 2420 float maxCellBottom; 2421 float maxCellHeight; 2422 2423 Map rowspanMap; 2424 Map pageMap = new HashMap (); 2425 2428 public PdfTable table; 2429 2430 2435 public int consumeRowspan(PdfCell c) { 2436 if (c.rowspan() == 1) { 2437 return 1; 2438 } 2439 2440 Integer i = (Integer ) rowspanMap.get(c); 2441 if (i == null) { 2442 i = new Integer (c.rowspan()); 2443 } 2444 2445 i = new Integer (i.intValue() - 1); 2446 rowspanMap.put(c, i); 2447 2448 if (i.intValue() < 1) { 2449 return 1; 2450 } 2451 return i.intValue(); 2452 } 2453 2454 2459 public int currentRowspan(PdfCell c) { 2460 Integer i = (Integer ) rowspanMap.get(c); 2461 if (i == null) { 2462 return c.rowspan(); 2463 } else { 2464 return i.intValue(); 2465 } 2466 } 2467 2468 public int cellRendered(PdfCell cell, int pageNumber) { 2469 Integer i = (Integer ) pageMap.get(cell); 2470 if (i == null) { 2471 i = new Integer (1); 2472 } else { 2473 i = new Integer (i.intValue() + 1); 2474 } 2475 pageMap.put(cell, i); 2476 2477 Integer pageInteger = new Integer (pageNumber); 2478 Set set = (Set ) pageMap.get(pageInteger); 2479 2480 if (set == null) { 2481 set = new HashSet (); 2482 pageMap.put(pageInteger, set); 2483 } 2484 2485 set.add(cell); 2486 2487 return i.intValue(); 2488 } 2489 2490 public int numCellRendered(PdfCell cell) { 2491 Integer i = (Integer ) pageMap.get(cell); 2492 if (i == null) { 2493 i = new Integer (0); 2494 } 2495 return i.intValue(); 2496 } 2497 2498 public boolean isCellRenderedOnPage(PdfCell cell, int pageNumber) { 2499 Integer pageInteger = new Integer (pageNumber); 2500 Set set = (Set ) pageMap.get(pageInteger); 2501 2502 if (set != null) { 2503 return set.contains(cell); 2504 } 2505 2506 return false; 2507 } 2508 }; 2509 2510 2516 private void add(PdfTable table, boolean onlyFirstPage) throws DocumentException { 2517 flushLines(); 2519 2520 RenderingContext ctx = new RenderingContext(); 2521 ctx.pagetop = indentTop(); 2522 ctx.oldHeight = currentHeight; 2523 ctx.cellGraphics = new PdfContentByte(writer); 2524 ctx.rowspanMap = new HashMap (); 2525 ctx.table = table; 2526 2527 PdfCell cell; 2529 2530 ArrayList dataCells = table.getCells(); 2532 2533 ArrayList headercells = table.getHeaderCells(); 2534 if (!headercells.isEmpty() && (dataCells.isEmpty() || dataCells.get(0) != headercells.get(0))) { 2536 ArrayList allCells = new ArrayList (dataCells.size()+headercells.size()); 2537 allCells.addAll(headercells); 2538 allCells.addAll(dataCells); 2539 dataCells = allCells; 2540 } 2541 2542 ArrayList cells = dataCells; 2543 ArrayList rows = extractRows(cells, ctx); 2544 boolean isContinue = false; 2545 while (!cells.isEmpty()) { 2546 ctx.lostTableBottom = 0; 2548 2549 boolean cellsShown = false; 2551 2552 Iterator iterator = rows.iterator(); 2554 2555 boolean atLeastOneFits = false; 2556 while (iterator.hasNext()) { 2557 ArrayList row = (ArrayList ) iterator.next(); 2558 analyzeRow(rows, ctx); 2559 renderCells(ctx, row, table.hasToFitPageCells() & atLeastOneFits); 2560 2561 if (!mayBeRemoved(row)) { 2562 break; 2563 } 2564 consumeRowspan(row, ctx); 2565 iterator.remove(); 2566 atLeastOneFits = true; 2567 } 2568 2569 cells.clear(); 2571 Set opt = new HashSet (); 2572 iterator = rows.iterator(); 2573 while (iterator.hasNext()) { 2574 ArrayList row = (ArrayList ) iterator.next(); 2575 2576 Iterator cellIterator = row.iterator(); 2577 while (cellIterator.hasNext()) { 2578 cell = (PdfCell) cellIterator.next(); 2579 2580 if (!opt.contains(cell)) { 2581 cells.add(cell); 2582 opt.add(cell); 2583 } 2584 } 2585 } 2586 2587 Rectangle tablerec = new Rectangle(table); 2589 tablerec.setBorder(table.getBorder()); 2590 tablerec.setBorderWidth(table.getBorderWidth()); 2591 tablerec.setBorderColor(table.getBorderColor()); 2592 tablerec.setBackgroundColor(table.getBackgroundColor()); 2593 PdfContentByte under = writer.getDirectContentUnder(); 2594 under.rectangle(tablerec.rectangle(top(), indentBottom())); 2595 under.add(ctx.cellGraphics); 2596 tablerec.setBackgroundColor(null); 2599 tablerec = tablerec.rectangle(top(), indentBottom()); 2600 tablerec.setBorder(table.getBorder()); 2601 under.rectangle(tablerec); 2602 2604 ctx.cellGraphics = new PdfContentByte(null); 2605 2607 if (!rows.isEmpty()) { 2608 isContinue = true; 2609 graphics.setLineWidth(table.getBorderWidth()); 2610 if (cellsShown && (table.getBorder() & Rectangle.BOTTOM) == Rectangle.BOTTOM) { 2611 2613 Color tColor = table.getBorderColor(); 2615 if (tColor != null) { 2616 graphics.setColorStroke(tColor); 2617 } 2618 graphics.moveTo(table.getLeft(), Math.max(table.getBottom(), indentBottom())); 2619 graphics.lineTo(table.getRight(), Math.max(table.getBottom(), indentBottom())); 2620 graphics.stroke(); 2621 if (tColor != null) { 2622 graphics.resetRGBColorStroke(); 2623 } 2624 } 2625 2626 pageEmpty = false; 2628 float difference = ctx.lostTableBottom; 2629 2630 newPage(); 2632 2633 float heightCorrection = 0; 2635 boolean somethingAdded = false; 2636 if (currentHeight > 0) { 2637 heightCorrection = 6; 2638 currentHeight += heightCorrection; 2639 somethingAdded = true; 2640 newLine(); 2641 flushLines(); 2642 indentation.indentTop = currentHeight - leading; 2643 currentHeight = 0; 2644 } 2645 else { 2646 flushLines(); 2647 } 2648 2649 int size = headercells.size(); 2651 if (size > 0) { 2652 cell = (PdfCell) headercells.get(0); 2654 float oldTop = cell.getTop(0); 2655 for (int i = 0; i < size; i++) { 2657 cell = (PdfCell) headercells.get(i); 2658 cell.setTop(indentTop() - oldTop + cell.getTop(0)); 2660 cell.setBottom(indentTop() - oldTop + cell.getBottom(0)); 2661 ctx.pagetop = cell.getBottom(); 2662 ctx.cellGraphics.rectangle(cell.rectangle(indentTop(), indentBottom())); 2664 ArrayList images = cell.getImages(indentTop(), indentBottom()); 2666 for (Iterator im = images.iterator(); im.hasNext();) { 2667 cellsShown = true; 2668 Image image = (Image) im.next(); 2669 graphics.addImage(image); 2670 } 2671 lines = cell.getLines(indentTop(), indentBottom()); 2672 float cellTop = cell.getTop(indentTop()); 2673 text.moveText(0, cellTop-heightCorrection); 2674 float cellDisplacement = flushLines() - cellTop+heightCorrection; 2675 text.moveText(0, cellDisplacement); 2676 } 2677 2678 currentHeight = indentTop() - ctx.pagetop + table.cellspacing(); 2679 text.moveText(0, ctx.pagetop - indentTop() - currentHeight); 2680 } 2681 else { 2682 if (somethingAdded) { 2683 ctx.pagetop = indentTop(); 2684 text.moveText(0, -table.cellspacing()); 2685 } 2686 } 2687 ctx.oldHeight = currentHeight - heightCorrection; 2688 2689 size = Math.min(cells.size(), table.columns()); 2691 int i = 0; 2692 while (i < size) { 2693 cell = (PdfCell) cells.get(i); 2694 if (cell.getTop(-table.cellspacing()) > ctx.lostTableBottom) { 2695 float newBottom = ctx.pagetop - difference + cell.getBottom(); 2696 float neededHeight = cell.remainingHeight(); 2697 if (newBottom > ctx.pagetop - neededHeight) { 2698 difference += newBottom - (ctx.pagetop - neededHeight); 2699 } 2700 } 2701 i++; 2702 } 2703 size = cells.size(); 2704 table.setTop(indentTop()); 2705 table.setBottom(ctx.pagetop - difference + table.getBottom(table.cellspacing())); 2706 for (i = 0; i < size; i++) { 2707 cell = (PdfCell) cells.get(i); 2708 float newBottom = ctx.pagetop - difference + cell.getBottom(); 2709 float newTop = ctx.pagetop - difference + cell.getTop(-table.cellspacing()); 2710 if (newTop > indentTop() - currentHeight) { 2711 newTop = indentTop() - currentHeight; 2712 } 2713 2714 cell.setTop(newTop ); 2715 cell.setBottom(newBottom ); 2716 } 2717 if (onlyFirstPage) { 2718 break; 2719 } 2720 } 2721 } 2722 2723 float tableHeight = table.getTop() - table.getBottom(); 2724 if (isContinue) { 2727 currentHeight = tableHeight; 2728 text.moveText(0, -(tableHeight - (ctx.oldHeight * 2))); 2729 } else { 2730 currentHeight = ctx.oldHeight + tableHeight; 2731 text.moveText(0, -tableHeight); 2732 } 2733 pageEmpty = false; 2735 } 2736 2737 private void analyzeRow(ArrayList rows, RenderingContext ctx) { 2738 ctx.maxCellBottom = indentBottom(); 2739 2740 int rowIndex = 0; 2742 2743 ArrayList row = (ArrayList ) rows.get(rowIndex); 2744 int maxRowspan = 1; 2745 Iterator iterator = row.iterator(); 2746 while (iterator.hasNext()) { 2747 PdfCell cell = (PdfCell) iterator.next(); 2748 maxRowspan = Math.max(ctx.currentRowspan(cell), maxRowspan); 2749 } 2750 rowIndex += maxRowspan; 2751 2752 boolean useTop = true; 2753 if (rowIndex == rows.size()) { 2754 rowIndex = rows.size() - 1; 2755 useTop = false; 2756 } 2757 2758 if (rowIndex < 0 || rowIndex >= rows.size()) return; 2759 2760 row = (ArrayList ) rows.get(rowIndex); 2761 iterator = row.iterator(); 2762 while (iterator.hasNext()) { 2763 PdfCell cell = (PdfCell) iterator.next(); 2764 Rectangle cellRect = cell.rectangle(ctx.pagetop, indentBottom()); 2765 if (useTop) { 2766 ctx.maxCellBottom = Math.max(ctx.maxCellBottom, cellRect.getTop()); 2767 } else { 2768 if (ctx.currentRowspan(cell) == 1) { 2769 ctx.maxCellBottom = Math.max(ctx.maxCellBottom, cellRect.getBottom()); 2770 } 2771 } 2772 } 2773 } 2774 2775 private boolean mayBeRemoved(ArrayList row) { 2776 Iterator iterator = row.iterator(); 2777 boolean mayBeRemoved = true; 2778 while (iterator.hasNext()) { 2779 PdfCell cell = (PdfCell) iterator.next(); 2780 2781 mayBeRemoved &= cell.mayBeRemoved(); 2782 } 2783 return mayBeRemoved; 2784 } 2785 2786 private void consumeRowspan(ArrayList row, RenderingContext ctx) { 2787 Iterator iterator = row.iterator(); 2788 while (iterator.hasNext()) { 2789 PdfCell c = (PdfCell) iterator.next(); 2790 ctx.consumeRowspan(c); 2791 } 2792 } 2793 2794 private ArrayList extractRows(ArrayList cells, RenderingContext ctx) { 2795 PdfCell cell; 2796 PdfCell previousCell = null; 2797 ArrayList rows = new ArrayList (); 2798 java.util.List rowCells = new ArrayList (); 2799 2800 Iterator iterator = cells.iterator(); 2801 while (iterator.hasNext()) { 2802 cell = (PdfCell) iterator.next(); 2803 2804 boolean isAdded = false; 2805 2806 boolean isEndOfRow = !iterator.hasNext(); 2807 boolean isCurrentCellPartOfRow = !iterator.hasNext(); 2808 2809 if (previousCell != null) { 2810 if (cell.getLeft() <= previousCell.getLeft()) { 2811 isEndOfRow = true; 2812 isCurrentCellPartOfRow = false; 2813 } 2814 } 2815 2816 if (isCurrentCellPartOfRow) { 2817 rowCells.add(cell); 2818 isAdded = true; 2819 } 2820 2821 if (isEndOfRow) { 2822 if (!rowCells.isEmpty()) { 2823 rows.add(rowCells); 2825 } 2826 2827 rowCells = new ArrayList (); 2829 } 2830 2831 if (!isAdded) { 2832 rowCells.add(cell); 2833 } 2834 2835 previousCell = cell; 2836 } 2837 2838 if (!rowCells.isEmpty()) { 2839 rows.add(rowCells); 2840 } 2841 2842 for (int i = rows.size() - 1; i >= 0; i--) { 2844 ArrayList row = (ArrayList ) rows.get(i); 2845 for (int j = 0; j < row.size(); j++) { 2847 PdfCell c = (PdfCell) row.get(j); 2848 int rowspan = c.rowspan(); 2849 for (int k = 1; k < rowspan && rows.size() <= i+k; k++) { 2851 ArrayList spannedRow = ((ArrayList ) rows.get(i + k)); 2852 if (spannedRow.size() > j) 2853 spannedRow.add(j, c); 2854 } 2855 } 2856 } 2857 2858 return rows; 2859 } 2860 2861 private void renderCells(RenderingContext ctx, java.util.List cells, boolean hasToFit) throws DocumentException { 2862 PdfCell cell; 2863 Iterator iterator; 2864 if (hasToFit) { 2865 iterator = cells.iterator(); 2866 while (iterator.hasNext()) { 2867 cell = (PdfCell) iterator.next(); 2868 if (!cell.isHeader()) { 2869 if (cell.getBottom() < indentBottom()) return; 2870 } 2871 } 2872 } 2873 iterator = cells.iterator(); 2874 2875 while (iterator.hasNext()) { 2876 cell = (PdfCell) iterator.next(); 2877 if (!ctx.isCellRenderedOnPage(cell, getPageNumber())) { 2878 2879 float correction = 0; 2880 if (ctx.numCellRendered(cell) >= 1) { 2881 correction = 1.0f; 2882 } 2883 2884 lines = cell.getLines(ctx.pagetop, indentBottom() - correction); 2885 2886 if (lines != null && !lines.isEmpty()) { 2888 2889 float cellTop = cell.getTop(ctx.pagetop - ctx.oldHeight); 2891 text.moveText(0, cellTop); 2892 float cellDisplacement = flushLines() - cellTop; 2893 2894 text.moveText(0, cellDisplacement); 2895 if (ctx.oldHeight + cellDisplacement > currentHeight) { 2896 currentHeight = ctx.oldHeight + cellDisplacement; 2897 } 2898 2899 ctx.cellRendered(cell, getPageNumber()); 2900 } 2901 float indentBottom = Math.max(cell.getBottom(), indentBottom()); 2902 Rectangle tableRect = ctx.table.rectangle(ctx.pagetop, indentBottom()); 2903 indentBottom = Math.max(tableRect.getBottom(), indentBottom); 2904 2905 Rectangle cellRect = cell.rectangle(tableRect.getTop(), indentBottom); 2907 if (cellRect.getHeight() > 0) { 2909 ctx.lostTableBottom = indentBottom; 2910 ctx.cellGraphics.rectangle(cellRect); 2911 } 2912 2913 ArrayList images = cell.getImages(ctx.pagetop, indentBottom()); 2915 for (Iterator i = images.iterator(); i.hasNext();) { 2916 Image image = (Image) i.next(); 2917 graphics.addImage(image); 2918 } 2919 2920 } 2921 } 2922 } 2923 2924 2932 2933 boolean breakTableIfDoesntFit(PdfTable table) throws DocumentException { 2934 table.updateRowAdditions(); 2935 if (!table.hasToFitPageTable() && table.getBottom() <= indentation.indentBottom) { 2937 add(table, true); 2939 return true; 2940 } 2941 return false; 2942 } 2943 2944 2951 2952 float bottom(Table table) { 2953 PdfTable tmp = getPdfTable(table, false); 2955 return tmp.getBottom(); 2956 } 2957 2958 private void doFooter() throws DocumentException { 2960 if (footer == null) return; 2961 float tmpIndentLeft = indentation.indentLeft; 2964 float tmpIndentRight = indentation.indentRight; 2965 float tmpListIndentLeft = indentation.listIndentLeft; 2967 float tmpImageIndentLeft = indentation.imageIndentLeft; 2968 float tmpImageIndentRight = indentation.imageIndentRight; 2969 2971 indentation.indentLeft = indentation.indentRight = 0; 2972 indentation.listIndentLeft = 0; 2974 indentation.imageIndentLeft = 0; 2975 indentation.imageIndentRight = 0; 2976 footer.setPageNumber(pageN); 2979 leading = footer.paragraph().getTotalLeading(); 2980 add(footer.paragraph()); 2981 indentation.indentBottom = currentHeight; 2983 text.moveText(left(), indentBottom()); 2984 flushLines(); 2985 text.moveText(-left(), -bottom()); 2986 footer.setTop(bottom(currentHeight)); 2987 footer.setBottom(bottom() - (0.75f * leading)); 2988 footer.setLeft(left()); 2989 footer.setRight(right()); 2990 graphics.rectangle(footer); 2991 indentation.indentBottom = currentHeight + leading * 2; 2992 currentHeight = 0; 2993 indentation.indentLeft = tmpIndentLeft; 2995 indentation.indentRight = tmpIndentRight; 2996 indentation.listIndentLeft = tmpListIndentLeft; 2998 indentation.imageIndentLeft = tmpImageIndentLeft; 2999 indentation.imageIndentRight = tmpImageIndentRight; 3000 } 3003 3004 private void doHeader() throws DocumentException { 3005 if (header == null) return; 3007 float tmpIndentLeft = indentation.indentLeft; 3010 float tmpIndentRight = indentation.indentRight; 3011 float tmpListIndentLeft = indentation.listIndentLeft; 3013 float tmpImageIndentLeft = indentation.imageIndentLeft; 3014 float tmpImageIndentRight = indentation.imageIndentRight; 3015 indentation.indentLeft = indentation.indentRight = 0; 3017 indentation.listIndentLeft = 0; 3019 indentation.imageIndentLeft = 0; 3020 indentation.imageIndentRight = 0; 3021 header.setPageNumber(pageN); 3024 leading = header.paragraph().getTotalLeading(); 3025 text.moveText(0, leading); 3026 add(header.paragraph()); 3027 newLine(); 3028 indentation.indentTop = currentHeight - leading; 3029 header.setTop(top() + leading); 3030 header.setBottom(indentTop() + leading * 2 / 3); 3031 header.setLeft(left()); 3032 header.setRight(right()); 3033 graphics.rectangle(header); 3034 flushLines(); 3035 currentHeight = 0; 3036 indentation.indentLeft = tmpIndentLeft; 3039 indentation.indentRight = tmpIndentRight; 3040 indentation.listIndentLeft = tmpListIndentLeft; 3042 indentation.imageIndentLeft = tmpImageIndentLeft; 3043 indentation.imageIndentRight = tmpImageIndentRight; 3044 } 3047} | Popular Tags |