I am using itextpdf 7 (7.2.0) to create a pdf file. However even though the TOC part is rendered very well, in the content part the text overflows. Here is my code that generates the pdf:
public class Main { public static void main(String[] args) throws IOException { PdfWriter writer = new PdfWriter("fiftyfourthPdf.pdf"); PdfDocument pdf = new PdfDocument(writer); Document document = new Document(pdf, PageSize.A4,false); //document.setMargins(30,10,36,10); // Create a PdfFont PdfFont font = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN,"Cp1254"); document .setTextAlignment(TextAlignment.JUSTIFIED) .setFont(font) .setFontSize(11); PdfOutline outline = null; java.util.List<AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<String, Integer>>> toc = new ArrayList<>(); for(int i=0;i<5000;i++){ String line = "This is paragraph " + String.valueOf(i+1)+ " "; line = line.concat(line).concat(line).concat(line).concat(line).concat(line); Paragraph p = new Paragraph(line); p.setKeepTogether(true); document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT)); //PROCESS FOR TOC String name = "para " + String.valueOf(i+1); outline = createOutline(outline,pdf,line ,name ); AbstractMap.SimpleEntry<String, Integer> titlePage = new AbstractMap.SimpleEntry(line, pdf.getNumberOfPages()); p .setFont(font) .setFontSize(12) //.setKeepWithNext(true) .setDestination(name) // Add the current page number to the table of contents list .setNextRenderer(new UpdatePageRenderer(p)); toc.add(new AbstractMap.SimpleEntry(name, titlePage)); } int contentPageNumber = pdf.getNumberOfPages(); for (int i = 1; i <= contentPageNumber; i++) { // Write aligned text to the specified by parameters point document.showTextAligned(new Paragraph(String.format("Sayfa %s / %s", i, contentPageNumber)).setFontSize(10), 559, 26, i, TextAlignment.RIGHT, VerticalAlignment.MIDDLE, 0); } //BEGINNING OF TOC document.add(new AreaBreak()); Paragraph p = new Paragraph("Table of Contents") .setFont(font) .setDestination("toc"); document.add(p); java.util.List<TabStop> tabStops = new ArrayList<>(); tabStops.add(new TabStop(580, TabAlignment.RIGHT, new DottedLine())); for (AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<String, Integer>> entry : toc) { AbstractMap.SimpleEntry<String, Integer> text = entry.getValue(); p = new Paragraph() .addTabStops(tabStops) .add(text.getKey()) .add(new Tab()) .add(String.valueOf(text.getValue())) .setAction(PdfAction.createGoTo(entry.getKey())); document.add(p); } // Move the table of contents to the first page int tocPageNumber = pdf.getNumberOfPages(); for (int i = 1; i <= tocPageNumber; i++) { // Write aligned text to the specified by parameters point document.showTextAligned(new Paragraph("n footer textn second linenthird line").setFontColor(ColorConstants.RED).setFontSize(8), 300, 26, i, TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0); } document.flush(); for(int z = 0; z< (tocPageNumber - contentPageNumber ); z++){ pdf.movePage(tocPageNumber,1); pdf.getPage(1).setPageLabel(PageLabelNumberingStyle.UPPERCASE_LETTERS, null, 1); } //pdf.movePage(tocPageNumber, 1); // Add page labels /*pdf.getPage(1).setPageLabel(PageLabelNumberingStyle.UPPERCASE_LETTERS, null, 1);*/ pdf.getPage(tocPageNumber - contentPageNumber + 1).setPageLabel(PageLabelNumberingStyle.DECIMAL_ARABIC_NUMERALS, null, 1); document.close(); } private static PdfOutline createOutline(PdfOutline outline, PdfDocument pdf, String title, String name) { if (outline == null) { outline = pdf.getOutlines(false); outline = outline.addOutline(title); outline.addDestination(PdfDestination.makeDestination(new PdfString(name))); } else { PdfOutline kid = outline.addOutline(title); kid.addDestination(PdfDestination.makeDestination(new PdfString(name))); } return outline; } private static class UpdatePageRenderer extends ParagraphRenderer { protected AbstractMap.SimpleEntry<String, Integer> entry; public UpdatePageRenderer(Paragraph modelElement, AbstractMap.SimpleEntry<String, Integer> entry) { super(modelElement); this.entry = entry; } public UpdatePageRenderer(Paragraph modelElement) { super(modelElement); } @Override public LayoutResult layout(LayoutContext layoutContext) { LayoutResult result = super.layout(layoutContext); //entry.setValue(layoutContext.getArea().getPageNumber()); if (result.getStatus() != LayoutResult.FULL) { if (null != result.getOverflowRenderer()) { result.getOverflowRenderer().setProperty( Property.LEADING, result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING)); } else { // if overflow renderer is null, that could mean that the whole renderer will overflow setProperty( Property.LEADING, result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING)); } } return result; } @Override // If not overriden, the default renderer will be used for the overflown part of the corresponding paragraph public IRenderer getNextRenderer() { return new UpdatePageRenderer((Paragraph) this.getModelElement()); } } }
Here are the screen shots of TOC part and content part :
TOC :
Content :
What am I missing? Thank you all for your help.
UPDATE
When I add the line below it renders with no overflow but the page margins of TOC and content part differ (the TOC margin is way more than the content margin). See the picture attached please :
document.setMargins(30,60,36,20);
Right Margin difference between TOC and content:
UPDATE 2 :
When I comment the line
document.setMargins(30,60,36,20);
and set the font size on line :
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
to 12 then it renders fine. What difference should possibly the font size cause for the page content and margins? Are not there standard page margins and page setups? Am I unknowingly (I am newbie to itextpdf) messing some standard implementations?
Advertisement
Answer
TL; DR: either remove setFontSize
in
p .setFont(font) .setFontSize(12) //.setKeepWithNext(true) .setDestination(name)
or change setFontSize(10)
-> setFontSize(12)
in
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
Explanation: You are setting the Document
to not immediately flush elements added to that document with the following line:
Document document = new Document(pdf, PageSize.A4,false);
Then you add an paragraph element with font size equal to 10 to the document with the following line:
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
What happens is that the element is being laid out (split in lines etc), but now drawn on the page. Then you do .setFontSize(12)
and this new font size is applied for draw
only, so iText calculated that X characters would fit into one line assuming the font size is 10 while in reality the font size is 12 and obviously fewer characters can fit into one line.
There is no sense in setting the font size two times to different values – just pick one value you want to see in the resultant document and set it once.