How to restrict the number of characters on a single line?

Category: 
Tags: fontsmeasure textfont widthiText 5

I am using iText to generate PDFs. In these PDFs, I need to add two Strings on one line.

The first String (string1) length is between 1 and 10. The length of the second String (string2) is unknown, but the combined length of string1 and string2 should not exceed 10 characters.

How can I add these strings to a single line that is underlined?

Posted on StackOverflow on Dec 22, 2013 by Rajkumar Chilukuri

Please take a look at the UnderlineParagraphWithTwoParts example and allow me to explain which problems are solved in this example.

First problem: you want to make sure that 100 characters fit on one line. I've made this 101 characters because I assume that you want some space between string1 and string2 (if not, it should be easy to adapt the example).

As you don't know the content of string1 and string2 in advance, I've chosen a font of which all the glyphs have the same width: Courier (this is a fixed width or monospaced font). If you want to use a proportional font (such as Arial), you will have a very hard time calculating the font size, in the sense that you will have to calculate the font size separately for every string1 and string2 combination. This will result in a very odd-looking document where each line has a different font size.

This is the code to calculate the font size, based on the width of a single character in the font COURIER, the fact that we want to add 101 characters on one line that has a width equal to the space available between the right and left margin of the page:

BaseFont bf = BaseFont.createFont(
    BaseFont.COURIER, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
float charWidth = bf.getWidth(" ");
int charactersPerLine = 101;
float pageWidth = document.right() - document.left();
float fontSize = (1000 * (pageWidth / (charWidth * charactersPerLine)));
fontSize = ((int)(fontSize * 100)) / 100f;
Font font = new Font(bf, fontSize);

Note that I round the value of the float. If you don't do this, you may experience problems due to rounding errors inherent to using float values.

Problem2: Now we want to add two string to a single line and underline them. From your question, it isn't clear how you want to align these strings.

This is the simple situation, where string1 and string2 are separated by a single space:

public void addParagraphWithTwoParts2(
        Document document, Font font, String string1, String string2)
    throws DocumentException {
    if (string1 == null) string1 = "";
    if (string1.length() > 10)
        string1 = string1.substring(0, 10);
    if (string2 == null) string2 = "";
    if (string1.length() + string2.length() > 100)
        string2 = string2.substring(0, 100 - string1.length());
    Paragraph p = new Paragraph(string1 + " " + string2, font);
    LineSeparator line = new LineSeparator();
    line.setOffset(-2);
    p.add(line);
    document.add(p);
}

This is a more complex situation, where you right-align string2:

public void addParagraphWithTwoParts1(
        Document document, Font font, String string1, String string2)
    throws DocumentException {
    if (string1 == null) string1 = "";
    if (string1.length() > 10)
        string1 = string1.substring(0, 10);
    Chunk chunk1 = new Chunk(string1, font);
    if (string2 == null) string2 = "";
    if (string1.length() + string2.length() > 100)
        string2 = string2.substring(0, 100 - string1.length());
    Chunk chunk2 = new Chunk(string2, font);
    Paragraph p = new Paragraph();
    p.add(chunk1);
    p.add(GLUE);
    p.add(chunk2);
    LineSeparator line = new LineSeparator();
    line.setOffset(-2);
    p.add(line);
    document.add(p);
}

As you can see, we do not have to add any spaces, we just use a GLUE chunk that is defined like this:

public static final Chunk GLUE = new Chunk(new VerticalPositionMark());

I've created an example where string1 and string2 consist of numbers. This is what the result looks like:

Underlined paragraphs
Underlined paragraphs

In this screen shot, you see examples where string2 is right aligned as well as examples where string2 is added right after string1 (but separated from it with a single space character).