Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move to the next line when adding text using Apache PDFBox

I've just started using Apache PDFBox and been experimenting with various examples I've found.

However, I haven't been able to find an easy way to move to the next line when adding text.

E.g.

PDPageContentStream content = new PDPageContentStream(document, page);
PDFont font = PDType1Font.HELVETICA;
content.beginText();
content.setFont(font, 12);
content.moveTextPositionByAmount(x, y);
content.drawString("Some text.");
content.endText();

To add another line of text underneath I had to repeatedly experiment with the value of y in moveTextPositionByAmount until it wasn't overwriting the previous line.

Is there a more intuitive way to figure out what the coordinates of the next line are?

TIA

like image 962
ksl Avatar asked Jan 08 '15 09:01

ksl


2 Answers

The PDFBox API allows low-level content generation. This implies that you have to do (but also that you are enabled to do) much of the layout work yourself, among that deciding how much to move down to get to the next baseline.

That distance (called leading in this context) depends on a number of factors:

  • the font size used (obviously)
  • how tightly or loosely spaced the text shall appear
  • the presence of elements on the lines involved positioned outside the regular line, e.g. superscripts, subscripts, formulas, ...

The standard is arranged so that the nominal height of tightly spaced lines of text is 1 unit for a font drawn at size 1. Thus, usually you will use a leading of 1..1.5 times the font size unless there is material on the line reaching beyond it.

BTW, if you have to forward to the next line by the same amount very often, you can use the combination of the PDPageContentStream methods setLeading and newLine instead of moveTextPositionByAmount:

content.setFont(font, 12);
content.setLeading(14.5f);
content.moveTextPositionByAmount(x, y);
content.drawString("Some text.");
content.newLine();
content.drawString("Some more text.");
content.newLine();
content.drawString("Still some more text.");

PS: It looks like moveTextPositionByAmount will be deprecated in the 2.0.0 version and be replaced by newLineAtOffset.

PPS: As the OP indicates in a comment,

There is no PDPageContentStream method called setLeading. I'm using PDFBox version 1.8.8.

Indeed, I was looking at the current 2.0.0-SNAPSHOT development version. They are currently implemented like this:

/**
 * Sets the text leading.
 *
 * @param leading The leading in unscaled text units.
 * @throws IOException If there is an error writing to the stream.
 */
public void setLeading(double leading) throws IOException
{
    writeOperand((float) leading);
    writeOperator("TL");
}

/**
 * Move to the start of the next line of text. Requires the leading to have been set.
 *
 * @throws IOException If there is an error writing to the stream.
 */
public void newLine() throws IOException
{
    if (!inTextMode)
    {
        throw new IllegalStateException("Must call beginText() before newLine()");
    }
    writeOperator("T*");
}

One can easily implement external helper methods doing the equivalent using appendRawCommands((float) leading); appendRawCommands(" TL"); and appendRawCommands("T*");

like image 69
mkl Avatar answered Oct 22 '22 07:10

mkl


add a new line with offset in y axis like this

PDPageContentStream content = new PDPageContentStream(document, page);
PDFont font = PDType1Font.HELVETICA;
content.beginText();
content.setFont(font, 12);
// by default y = 0 pdf text start in the left bottom corner 
//  so you may need to put y = 700 or something to see the new line below 
content.moveTextPositionByAmount(x, y);
content.drawString("Some text.");
content.newLineAtOffset(0, -15);
content.drawString("some text ");
content.endText();
like image 32
Giovanni Contreras Avatar answered Oct 22 '22 06:10

Giovanni Contreras