iText pdf library
Website search

Positioning different text snippets on a page

CenterColumnVertically.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2020 iText Group NV
    Authors: iText Software.
 
    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.sandbox.objects;
 
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.layout.LayoutArea;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.layout.LayoutResult;
import com.itextpdf.layout.renderer.IRenderer;
 
import java.io.File;
import java.io.IOException;
 
public class CenterColumnVertically {
    public static final String DEST = "./target/sandbox/objects/center_column_vertically.pdf";
 
    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new CenterColumnVertically().manipulatePdf(DEST);
    }
 
    protected void manipulatePdf(String dest) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc);
 
        float llx = 50;
        float lly = 650;
        float urx = 400;
        float ury = 800;
 
        Rectangle rect = new Rectangle(llx, lly, urx - llx, ury - lly);
        PdfCanvas canvas = new PdfCanvas(pdfDoc.addNewPage());
        canvas.setStrokeColor(ColorConstants.RED)
                .setLineWidth(0.5f)
                .rectangle(rect)
                .stroke();
 
        Paragraph p = new Paragraph("This text is centered vertically. "
                + "It is rendered in the middle of the red rectangle.");
        float width = resolveTextHeight(doc, rect, p);
        new Canvas(canvas, pdfDoc, rect)
                .add(p.setFixedPosition(llx, (ury + lly) / 2 - width / 2, urx - llx).setMargin(0));
 
        doc.close();
    }
 
    private static float resolveTextHeight(Document doc, Rectangle rect, Paragraph p) {
        IRenderer pRenderer = p.createRendererSubTree().setParent(doc.getRenderer());
        LayoutResult pLayoutResult = pRenderer.layout(new LayoutContext(new LayoutArea(0, rect)));
 
        Rectangle pBBox = pLayoutResult.getOccupiedArea().getBBox();
        return pBBox.getHeight();
    }
}
CenterVertically.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2020 iText Group NV
    Authors: iText Software.
 
    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
/**
 * This example was written by Bruno Lowagie in answer to the following question:
 * http://stackoverflow.com/questions/27834540/generating-pdf-structure-on-dynamic-inputs
 */
package com.itextpdf.samples.sandbox.objects;
 
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.layout.LayoutArea;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.layout.LayoutResult;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;
 
import java.io.File;
import java.io.IOException;
 
public class CenterVertically {
    public static final String DEST = "./target/sandbox/objects/center_vertically.pdf";
 
    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new CenterVertically().manipulatePdf(DEST);
    }
 
    protected void manipulatePdf(String dest) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc);
 
        Cell cell = new Cell();
        for (int i = 1; i <= 5; i++) {
            cell.add(new Paragraph("Line " + i));
        }
 
        Table table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
        table.addCell(cell);
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.setNextRenderer(new CustomTableRenderer(table, resolveTableRect(doc, table)));
        doc.add(table);
        doc.add(new AreaBreak());
 
        table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.addCell(cell.clone(true));
        table.setNextRenderer(new CustomTableRenderer(table, resolveTableRect(doc, table)));
        doc.add(table);
 
        doc.close();
    }
 
    private static Rectangle resolveTableRect(Document doc, Table table) {
        Rectangle pageDimension = new Rectangle(36, 36, 523, 770);
        IRenderer tableRenderer = table.createRendererSubTree().setParent(doc.getRenderer());
        LayoutResult tableLayoutResult = tableRenderer.layout(new LayoutContext(new LayoutArea(0, pageDimension)));
 
        Rectangle resultRect;
        if (LayoutResult.PARTIAL == tableLayoutResult.getStatus()) {
            resultRect = pageDimension;
        } else {
            Rectangle tableBBox = tableLayoutResult.getOccupiedArea().getBBox();
            resultRect = new Rectangle(pageDimension.getX(), ((tableBBox.getBottom() + pageDimension.getX()) / 2),
                    pageDimension.getWidth(), tableBBox.getHeight());
        }
        return resultRect;
    }
 
    protected class CustomTableRenderer extends TableRenderer {
        protected Rectangle rect;
 
        public CustomTableRenderer(Table modelElement, Rectangle rect) {
            super(modelElement);
            this.rect = new Rectangle(rect);
        }
 
        // If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
        // If getNextRenderer isn't overridden, the default method will be used and thus a default rather than custom
        // renderer will be created
        @Override
        public IRenderer getNextRenderer() {
            return new CustomTableRenderer((Table) modelElement, rect);
        }
 
        @Override
        public LayoutResult layout(LayoutContext layoutContext) {
            return super.layout(new LayoutContext(new LayoutArea(layoutContext.getArea().getPageNumber(), rect)));
        }
    }
}
ColumnTextPhrase.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2020 iText Group NV
    Authors: iText Software.
 
    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
/**
 * This example was written by Bruno Lowagie in answer to the following question:
 * http://stackoverflow.com/questions/27989754/itext-failure-with-adding-elements-with-5-5-4
 */
package com.itextpdf.samples.sandbox.objects;
 
import com.itextpdf.io.font.constants.StandardFonts;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Paragraph;
 
import java.io.File;
import java.io.IOException;
 
public class ColumnTextPhrase {
    public static final String DEST = "./target/sandbox/objects/column_text_phrase.pdf";
    public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
 
    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new ColumnTextPhrase().manipulatePdf(DEST);
    }
 
    protected void manipulatePdf(String dest) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest));
 
        PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA_BOLD, PdfEncodings.CP1252, true);
        Paragraph pz = new Paragraph("Hello World!").setFont(font).setFontSize(13);
        new Canvas(new PdfCanvas(pdfDoc.getFirstPage()), pdfDoc, new Rectangle(120, 48, 80, 580))
                .add(pz);
 
        // The Leading is used in this paragraph, the Leading is a spacing between lines of text
        font = PdfFontFactory.createFont(StandardFonts.HELVETICA);
        pz = new Paragraph("Hello World!").setFont(font).setFixedLeading(20);
        new Canvas(new PdfCanvas(pdfDoc.getFirstPage()), pdfDoc, new Rectangle(120, 48, 80, 480))
                .add(pz);
 
        pdfDoc.close();
    }
}
DrawRectangleAroundText.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2020 iText Group NV
    Authors: iText Software.
 
    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
/**
 * This example was written by Bruno Lowagie in answer to the following question:
 * http://stackoverflow.com/questions/29037981/how-to-draw-a-rectangle-around-multiline-text
 */
package com.itextpdf.samples.sandbox.objects;
 
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.layout.LayoutArea;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.renderer.ParagraphRenderer;
 
import java.io.File;
import java.io.IOException;
 
public class DrawRectangleAroundText {
    public static final String DEST = "./target/sandbox/objects/draw_rectangle_around_text.pdf";
    public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
 
    public static void main(String[] args) throws IOException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new DrawRectangleAroundText().manipulatePdf(DEST);
    }
 
    protected void manipulatePdf(String dest) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest));
        Document doc = new Document(pdfDoc);
 
        PdfCanvas canvas = new PdfCanvas(pdfDoc.getFirstPage());
        Paragraph p = new Paragraph("This is a long paragraph that doesn't"
                + "fit the width we defined for the simple column of the"
                + "ColumnText object, so it will be distributed over several"
                + "lines (and we don't know in advance how many).");
 
        Rectangle firstRect = new Rectangle(120, 500, 130, 280);
        new Canvas(canvas, pdfDoc, firstRect)
                .add(p);
        canvas.rectangle(firstRect);
        canvas.stroke();
 
        // In the lines below the comment we try to reproduce the iText5 method to achieve the result
        // However it's much more simple to use the next line
        // p.setBorder(new SolidBorder(1));
        // Or you can implement your own ParagraphRenderer and change the behaviour of drawBorder(DrawContext)
        // or draw(DrawContext)
        Rectangle secRect = new Rectangle(300, 500, 130, 280);
        ParagraphRenderer renderer = (ParagraphRenderer) p.createRendererSubTree().setParent(doc.getRenderer());
        float height = renderer.layout(new LayoutContext(new LayoutArea(0, secRect)))
                .getOccupiedArea().getBBox().getHeight();
 
        new Canvas(canvas, pdfDoc, secRect)
                .add(p);
        canvas.rectangle(secRect.getX(), secRect.getY() + secRect.getHeight() - height, secRect.getWidth(), height);
        canvas.stroke();
 
        doc.close();
    }
}
ThreeParts.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2020 iText Group NV
    Authors: iText Software.
 
    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
/**
 * Example written by Bruno Lowagie in answer to:
 * http://stackoverflow.com/questions/28502315/divide-page-in-2-parts-so-we-can-fill-each-with-different-source
 */
package com.itextpdf.samples.sandbox.events;
 
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.layout.LayoutArea;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.layout.LayoutResult;
import com.itextpdf.layout.renderer.DocumentRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.ParagraphRenderer;
 
import java.io.File;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.IOException;
 
public class ThreeParts {
    public static final String DEST = "./target/sandbox/events/three_parts.pdf";
 
    public static final String SRC_LA = "./src/test/resources/txt/liber1_%s_la.txt";
    public static final String SRC_EN = "./src/test/resources/txt/liber1_%s_en.txt";
    public static final String SRC_FR = "./src/test/resources/txt/liber1_%s_fr.txt";
 
    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
 
        new ThreeParts().manipulatePdf(DEST);
    }
 
    protected void manipulatePdf(String dest) throws Exception {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        int firstPageNumber = 1;
 
        for (int i = 0; i < 3; i++) {
 
            // latin
            addSection(pdfDoc, readAndCreateParagraph(String.format(SRC_LA, i + 1)),
                    firstPageNumber, 0);
 
            // english
            addSection(pdfDoc, readAndCreateParagraph(String.format(SRC_EN, i + 1)),
                    firstPageNumber, 1);
 
            // french
            addSection(pdfDoc, readAndCreateParagraph(String.format(SRC_FR, i + 1)),
                    firstPageNumber, 2);
 
            firstPageNumber = pdfDoc.getNumberOfPages() + 1;
        }
 
        pdfDoc.close();
    }
 
    private static void addSection(PdfDocument pdfDoc, Paragraph paragraph, int pageNumber, int sectionNumber) {
        Document doc = new Document(pdfDoc);
        ParagraphRenderer renderer = (ParagraphRenderer) paragraph.createRendererSubTree();
        renderer.setParent(new DocumentRenderer(doc));
 
        float pageHeight = pdfDoc.getDefaultPageSize().getHeight();
        float pageWidth = pdfDoc.getDefaultPageSize().getWidth();
        Rectangle textSectionRectangle = new Rectangle(
                doc.getLeftMargin(),
                doc.getBottomMargin() + ((pageHeight - doc.getTopMargin() - doc.getBottomMargin()) / 3) * sectionNumber,
                pageWidth - doc.getLeftMargin() - doc.getRightMargin(),
                (pageHeight - doc.getTopMargin() - doc.getBottomMargin()) / 3);
 
        // Simulate the positioning of the renderer to find out how much space the text section will occupy.
        LayoutResult layoutResult = renderer
                .layout(new LayoutContext(new LayoutArea(pageNumber, textSectionRectangle)));
 
        /* Fill the current page section with the content.
         * If the content isn't fully placed in the current page section,
         * it will be split and drawn in the next page section.
         */
        while (layoutResult.getStatus() != LayoutResult.FULL) {
            if (pdfDoc.getNumberOfPages() < pageNumber) {
                pdfDoc.addNewPage();
            }
 
            pageNumber++;
 
            layoutResult.getSplitRenderer().draw(new DrawContext(pdfDoc,
                    new PdfCanvas(pdfDoc.getPage(pageNumber - 1)), false));
 
            renderer = (ParagraphRenderer) layoutResult.getOverflowRenderer();
 
            layoutResult = renderer
                    .layout(new LayoutContext(new LayoutArea(pageNumber, textSectionRectangle)));
        }
 
        if (pdfDoc.getNumberOfPages() < pageNumber) {
            pdfDoc.addNewPage();
        }
 
        renderer.draw(new DrawContext(pdfDoc, new PdfCanvas(pdfDoc.getPage(pageNumber)), false));
    }
 
    private static Paragraph readAndCreateParagraph(String path) throws IOException {
        Paragraph p = new Paragraph();
        StringBuffer buffer = new StringBuffer();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"))) {
            String line = reader.readLine();
            while (null != line) {
                buffer.append(line);
                line = reader.readLine();
            }
        }
 
        p.setBorder(new SolidBorder(ColorConstants.RED, 1));
        p.add(buffer.toString());
        return p;
    }
}
AddRotatedTemplate.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2020 iText Group NV
    Authors: iText Software.
 
    For more information, please contact iText Software at this address:
    sales@itextpdf.com
*/
 
/**
 * Example written by Bruno Lowagie in answer to the following question:
 * http://stackoverflow.com/questions/25808367/rotate-multiline-text-with-columntext-itextsharp
 */
 
package com.itextpdf.samples.sandbox.stamper;
 
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Paragraph;
 
import java.io.File;
 
public class AddRotatedTemplate {
    public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
    public static final String DEST = "./target/sandbox/stamper/add_rotated_template.pdf";
 
    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
 
        new AddRotatedTemplate().manipulatePdf(DEST);
    }
 
    protected void manipulatePdf(String dest) throws Exception {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest));
 
        // Add content to the template without rotation
        PdfFormXObject formXObject = new PdfFormXObject(new Rectangle(80, 120));
        new Canvas(formXObject, pdfDoc)
                .add(new Paragraph("Some long text that needs to be distributed over several lines."));
 
        // Add template to the pdf document page applying rotation
        PdfCanvas canvas = new PdfCanvas(pdfDoc.getFirstPage());
        canvas.addXObject(formXObject, 36, 600);
        double angle = Math.PI / 4;
        canvas.addXObject(formXObject,
                (float) Math.cos(angle), -(float) Math.sin(angle),
                (float) Math.cos(angle), (float) Math.sin(angle),
                150, 600);
 
        pdfDoc.close();
    }
}

Click the following link to see the legacy example for iText 5. Except for security fixes, iText 5 is no longer being developed.



Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now