setCharacterSpacing affecting centre alignment
Not sure if a bug or I'm doing something wrong but when I try and set the character spacing for some text added to a ColumnText, it's affecting the centre alignment I'm trying to achieve.
If I don't set setCharacterSpacing, the paragraph is correctly aligned in the centre.
How can I centre text on a page using ColumnText and setCharacterSpacing?
public class SimplePdf {
public static void main(String[] args) throws IOException {
String text = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Morbi ac nisl cursus, feugiat mauris nec, tempor ipsum.
Vivamus sodales bibendum urna in iaculis.
Vivamus porta at nisi a interdum.
Quisque vehicula ipsum sed leo tempus semper.
In ultrices mattis odio, non.""";
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("simple-output.pdf"));
Rectangle pageSize = document.getPageSize();
document.open();
PdfContentByte cb = writer.getDirectContent();
cb.beginText();
cb.setCharacterSpacing(3.04f);
cb.endText();
Paragraph paragraph = new Paragraph(text, new Font(BaseFont.createFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.EMBEDDED), 10f));
paragraph.setAlignment(Element.ALIGN_CENTER);
ColumnText ct = new ColumnText(cb);
ct.setSimpleColumn(paragraph, 0, pageSize.getHeight() - 300f, pageSize.getWidth(), pageSize.getHeight() - 170f, 16, Element.ALIGN_CENTER);
ct.go();
// Close everything
document.close();
writer.close();
}
}
Version: openpdf 2.0.3
You are experiencing this issue because of how OpenPDF currently works. If you highlight the text, you'll notice that the 'actual' text is visually correct, but lacks the character spacing.
To correctly render the text with the character spacing, you will have to manually adjust the position. I wrote a quick helper function to help with this.
private static Rectangle centerText(float pageWidth, float textWidth, float spacingWidth) {
float totalWidth = textWidth + spacingWidth;
float llx = (pageWidth - totalWidth) / 2;
float urx = llx + totalWidth;
Rectangle size = new Rectangle(llx, 0f, urx, 0f);
return size;
}
public static void centerParagraph(PdfContentByte cb, float pageWidth, Phrase phrase, float startY, float leading) {
float characterSpacing = 6f;
String[] lines = phrase.getContent().split("\n");
Font font = phrase.getFont();
BaseFont baseFont = font.getBaseFont();
float fontSize = font.getSize();
float y = startY + leading;
for(int i = 0; i < lines.length; i++) {
String line = lines[i];
float width = baseFont.getWidthPoint(line, fontSize) + (characterSpacing * (line.length() - 1));
Rectangle llxurx = centerText(pageWidth, width, 8f);
ColumnText ct = new ColumnText(cb);
Phrase newPhrase = new Phrase(line, font);
ct.setSimpleColumn(newPhrase, llxurx.getLeft(), y, llxurx.getRight(), y + fontSize, leading, Element.ALIGN_LEFT);
ct.go();
y -= fontSize + leading;
}
}
And you can use these functions like this
Rectangle pageSize = doc.getPageSize();
float fontSize = 12f;
float charSpacing = 6f;
String text = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Morbi ac nisl cursus, feugiat mauris nec, tempor ipsum.
Vivamus sodales bibendum urna in iaculis.
Vivamus porta at nisi a interdum.
Quisque vehicula ipsum sed leo tempus semper.
In ultrices mattis odio, non.""";
cb.beginText();
cb.setCharacterSpacing(charSpacing);
cb.endText();
Phrase phrase = new Phrase(text, new Font(BaseFont.createFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.EMBEDDED), fontSize));
centerParagraph(cb, pageSize.getWidth(), phrase, 500f, 6f);