Faiyet
Faiyet

Reputation: 5471

Itext7 center text and fill both sides

I am trying to print text to a pdf and I have everything set-up and working so far. I have a line which is 6-inches wide, that is (6*72) 432 device pixels. What I am trying to do is print text to this line, center-aliened and fill both sides to occupy the full width of the line. Example ------Hello there, this is my Text------. Here is a snippet of my code where I am trying to estimate the space occupied by my text so I can the calculate how much characters to insert before and after.

PdfFont font = PdfFontFactory.createFont(FontConstants.HELVETICA);
canvas.setFontAndSize(font, 12);
System.out.println(font.getContentWidth(new PdfString("Hello there, this is my Text")));

This code produces a number in excess of two thousand which far more than 432. Not sure what is the returned units. How do I estimate the length of my string and center-Aline it within 432dp ? the extra space must be filled with a special character. Its very similar to the way a cheque is printed where the amount is stated in words and filled on both sides if there is space.

I looked at this post and this other post but I am not getting anywhere with this. Please advise.

Upvotes: 0

Views: 1000

Answers (1)

Bruno Lowagie
Bruno Lowagie

Reputation: 77528

Please take a look at the tags of the post you refer to: How can I find the maximum character limit for a text field? The last tag refers to iText 5, whereas you are using iText 7. In other words: you are looking at the wrong FAQ entry. The iText 7 FAQ entry for that question is: How can I find the maximum character limit for a text field? But that doesn't answer your question.

You should read How to choose the optimal size for a font?

The value you get when you measure text is expressed in glyph space:

PdfFont font = PdfFontFactory.createFont(FontConstants.HELVETICA);
float glyphWidth = font.getContentWidth(new PdfString("Hello there, this is my Text"));

It is normal that these lines are insufficient to get the width in user space (which is what you are looking for). Why is this normal? Because the font object has no idea of the font size you are going to use.

In your case, you are using a font of 12pt. Hence the width of the PdfString is:

float width = glyphWidth * 0.001f * 12f;

That is the width you are looking for.

Centering that text at an absolute position can be done using the showTextAligned() method. There are many alternative ways to achieve this. That could be the subject of another question, because you don't need to do all that Math.

You could just do this:

/*
 * Example written in answer to a question on StackOverflow.
 * http://stackoverflow.com/questions/39437838
 */
package com.itextpdf.sandbox.text;

import com.itextpdf.kernel.color.Color;
import com.itextpdf.kernel.geom.PageSize;
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.kernel.pdf.canvas.draw.ILineDrawer;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Tab;
import com.itextpdf.layout.element.TabStop;
import com.itextpdf.layout.property.TabAlignment;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author bruno
 */
public class CenterText {
    class MyLine implements ILineDrawer {
        private float lineWidth = 1;
        private float offset = 5;
        private Color color = Color.BLACK;
        @Override
        public void draw(PdfCanvas canvas, Rectangle drawArea) {
            canvas.saveState()
                .setStrokeColor(color)
                .setLineWidth(lineWidth)
                .moveTo(drawArea.getX(), drawArea.getY() + lineWidth / 2 + offset)
                .lineTo(drawArea.getX() + drawArea.getWidth(), drawArea.getY() + lineWidth / 2 + offset)
                .stroke()
                .restoreState();
        }

        @Override
        public float getLineWidth() {
            return lineWidth;
        }
        @Override
        public void setLineWidth(float lineWidth) {
            this.lineWidth = lineWidth;
        }
        @Override
        public Color getColor() {
            return color;
        }
        @Override
        public void setColor(Color color) {
            this.color = color;
        }
        public float getOffset() {
            return offset;
        }
        public void setOffset(float poffset) {
            this.offset = offset;
        }

    }

    public static final String DEST = "results/text/center_text.pdf";

    public static void main(String[] args) throws IOException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new CenterText().createPdf(DEST);
    }
    public void createPdf(String dest) throws IOException {
        PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
        PageSize pagesize = PageSize.A4;
        Document document = new Document(pdf, pagesize);
        float w = pagesize.getWidth() - document.getLeftMargin() - document.getRightMargin();
        MyLine line = new MyLine();
        List<TabStop> tabstops = new ArrayList();
        tabstops.add(new TabStop(w / 2, TabAlignment.CENTER, line));
        tabstops.add(new TabStop(w, TabAlignment.LEFT, line));
        Paragraph p = new Paragraph();
        p.addTabStops(tabstops);
        p.add(new Tab()).add("Text in the middle").add(new Tab());
        document.add(p);
        document.close();
    }
}

Upvotes: 2

Related Questions