8

I have to make a PDF with a Table. So far it work fine, but now I want to add a wrapping feature. So I need to insert a Linefeed.

contentStream.beginText();  
contentStream.moveTextPositionByAmount(x, y);  
contentStream.drawString("Some text to insert into a table.");  
contentStream.endText();  

I want to add a "\n" before "insert". I tried "\u000A" which is the hex value for linefeed, but Eclipse shows me an error.

Is it possible to add linefeed with drawString?

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
Francesco
  • 127
  • 1
  • 2
  • 9

3 Answers3

15

The PDF format allows line breaks, but PDFBox has no build in feature for line breaks.

To use line breaks in PDF you have to define the leading you want to use with the TL-operator. The T*-operator makes a line break. The '-operator writes the given text into the next line. (See PDF-spec for more details, chapter "Text". It´s not that much.)

Here are two code snippets. Both do the same, but the first snippet uses ' and the second snippet uses T*.

private void printMultipleLines(
    PDPageContentStream contentStream,
    List<String> lines,
    float x,
    float y) throws IOException {
  if (lines.size() == 0) {
    return;
  }
  final int numberOfLines = lines.size();
  final float fontHeight = getFontHeight();

  contentStream.beginText();
  contentStream.appendRawCommands(fontHeight + " TL\n");
  contentStream.moveTextPositionByAmount(x, y);
  contentStream.drawString(lines.get(0));
  for (int i = 1; i < numberOfLines; i++) {
    contentStream.appendRawCommands(escapeString(lines.get(i)));
    contentStream.appendRawCommands(" \'\n");
  }
  contentStream.endText();
}

private String escapeString(String text) throws IOException {
  try {
    COSString string = new COSString(text);
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    string.writePDF(buffer);
    return new String(buffer.toByteArray(), "ISO-8859-1");
  } catch (UnsupportedEncodingException e) {
    // every JVM must know ISO-8859-1
    throw new RuntimeException(e);
  }
}

Use T* for line break:

private void printMultipleLines(
    PDPageContentStream contentStream,
    List<String> lines,
    float x,
    float y) throws IOException {
  if (lines.size() == 0) {
    return;
  }
  final int numberOfLines = lines.size();
  final float fontHeight = getFontHeight();

  contentStream.beginText();
  contentStream.appendRawCommands(fontHeight + " TL\n");
  contentStream.moveTextPositionByAmount( x, y);
  for (int i = 0; i < numberOfLines; i++) {
    contentStream.drawString(lines.get(i));
    if (i < numberOfLines - 1) {
      contentStream.appendRawCommands("T*\n");
    }
  }
  contentStream.endText();
}

To get the height of the font you can use this command:

fontHeight = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;

You might want to multiply it whit some line pitch factor.

Lukas
  • 1,127
  • 1
  • 12
  • 18
  • 2
    Would there be a reason to still use the now deprecated [`drawString`](https://pdfbox.apache.org/docs/2.0.5/javadocs/org/apache/pdfbox/pdmodel/PDPageContentStream.html#drawString(java.lang.String)) + `appendRawCommands` instead of `showText` and [`newLine`](https://pdfbox.apache.org/docs/2.0.5/javadocs/org/apache/pdfbox/pdmodel/PDPageContentStream.html#newLine()) as outlined in https://www.tutorialspoint.com/pdfbox/pdfbox_adding_multiple_lines.htm? – Simon Sobisch Apr 30 '19 at 09:14
  • @Simon Sobisch thanks for that, the other comments are now nearly 10 yrs old and obselete, the tutorialspoint link is helpful. – user2677034 Sep 06 '20 at 18:21
8

The pdf format doesn't know line breaks. You have to split the string and move the text position to the next line, using moveTextPositionByAmount.

This is not a special "pdfbox-feature", it is due to the pdf format definition; so there is no way for drawString and there are also no other methods to be called that support linefeeds.

Erik
  • 3,777
  • 21
  • 27
  • 1
    @Erik: But what is with the `T*`- and `'`-operator? pdf-spec says to T*: "Move to the start of the next line". And to ': "Move to the next line and show a text string". But I could not find a way to use T* or ' in pdfBox. (And I´m not sure whether I understood the spec correct or not.) – Lukas Feb 20 '13 at 13:52
0

Because the PDF model often isn't the best model for the task at hand, it often makes sense to write a wrapper for it that adds support for whatever's "missing" in your case. This is true for both reading and writing.

Ed Staub
  • 15,480
  • 3
  • 61
  • 91