PDFBOX Same Stream with bold and normal text

12,776

I am trying to make something

Like: this (Having bold and normal text on the same line).

I've been using streams:

The preferable way for creating bold (or otherwise styled) text is to use a font variant which has been created explicitly for that variant. If no such font is available, though, it is possible to artificially emulate those styles:

  • artificially bold: use text rendering mode 2 to not only fill the letter area but also draw a line along its outline
  • artificially outlined: use text rendering mode 1 to draw a line along the outline of the letter instead of filling it
  • artificially italic (actually slanted: change the text matrix to skew the output.

In code:

PDRectangle rec = new PDRectangle(220, 120);
PDDocument document = null;
document = new PDDocument();

PDPage page = new PDPage(rec);
document.addPage(page);

PDPageContentStream content = new PDPageContentStream(document, page, true, true);

content.beginText();
content.moveTextPositionByAmount(7, 105);
content.setFont(PDType1Font.HELVETICA, 12);
content.drawString("Normal text and ");
content.setFont(PDType1Font.HELVETICA_BOLD, 12);
content.drawString("bold text");
content.moveTextPositionByAmount(0, -25);
content.setFont(PDType1Font.HELVETICA_OBLIQUE, 12);
content.drawString("Italic text and ");
content.setFont(PDType1Font.HELVETICA_BOLD_OBLIQUE, 12);
content.drawString("bold italic text");
content.endText();

content.setLineWidth(.5f);

content.beginText();
content.moveTextPositionByAmount(7, 55);
content.setFont(PDType1Font.HELVETICA, 12);
content.drawString("Normal text and ");
content.appendRawCommands("2 Tr\n");
content.drawString("artificially bold text");
content.appendRawCommands("0 Tr\n");
content.moveTextPositionByAmount(0, -25);
content.appendRawCommands("1 Tr\n");
content.drawString("Artificially outlined text");
content.appendRawCommands("0 Tr\n");
content.setTextMatrix(1, 0, .2f, 1, 7, 5);
content.drawString("Artificially italic text and ");
content.appendRawCommands("2 Tr\n");
content.drawString("bold italic text");
content.appendRawCommands("0 Tr\n");
content.endText();

content.close();

document.save("StyledTexts.pdf");
document.close();

The result:

Screenshot of StyledTexts.pdf

Share:
12,776
Frakcool
Author by

Frakcool

Sr Developer with 7+ years of experience Java Swing / Desktop apps fanatic Trying to become an iOS developer, have 1 year of experience on it and trying to increase that experience I love learning new things and working with new technologies. I really enjoy hard problems and challenges.

Updated on June 04, 2022

Comments

  • Frakcool
    Frakcool almost 2 years

    Well I've been working with PDFBox I still don't understand it at all, but I've read the Documentation, working with fonts, and some other places, but I've found how to get the text from the PDF and it's style, but I'm creating it, not reading it.

    I am trying to make something

    Like: this (Having bold and normal text on the same line).

    I've been using streams:

    Not sure if this is all the code needed to help me, 'cause I just joined this project but it had started when I joined.

    I would thank you all if you could help me implementing this code or maybe helping me with an idea or source where I could read the solution.

    I leave my code here:

    public void rCovernoteFooter(PDPageContentStream stream , float x, float y) throws IOException {
        y = y-20;
        String currentDate = df1.format(new Date());
        String[] issues = constants.issued().split("/");
        String issued = issues[0] + currentDate + issues[1];
        y = rText(stream, x, y, 90, 0, 10, issued, null);
        stream.setFont(PDType1Font.TIMES_ROMAN, 8);
        y = rText(stream, x, y - 50, 117, 0, 10, constants.terms(), null);
    }
    
    public float rText(PDPageContentStream cStream, float x, float y, int col1, int col2, int spc, String data1, String data2) throws IOException {
        float y1 = 0f;
        float y2 = 0f;
        if (data2 == null) {
            y = iterate(data1, col1, x, y, spc, cStream);
        } else {
            y1 = iterate(data1, col1, x, y, spc, cStream);
            y2 = iterate(data2, col2, x + 125, y, spc,  cStream);
            if (y1 >= y2) {
            return y2;
            } else {
            return y1;
            }
        }
        return y;
    }
    
    private float iterate(String text, int len, float x, float y, int space, PDPageContentStream stream) throws IOException {
        int rowHeight = 0;
        List<String> wordList = Lists.newArrayList();
        wordList = wordLines(text, len);
    
        stream.setFont(PDType1Font.TIMES_BOLD, 10);
        for (String word : wordList) {
            stream.beginText();
            stream.moveTextPositionByAmount(x, y - rowHeight);
            stream.drawString(word);
            stream.endText();
            if (wordList.size() != 1)
            rowHeight = rowHeight + 10;
        }
        if (rowHeight >= space) {
            y = y - (rowHeight + 10);
        } else {
            y = y - space;
            }
        return y;
    }
    

    Thanks in advice

  • Frakcool
    Frakcool about 10 years
    Thanks a lot, I'll read it and try to implement it; and btw thanks for the tip about the valid PDF I'll have it in mind
  • Frakcool
    Frakcool about 10 years
    btw could you teach me about how does "setTextMatrix(1, 0, .2f, 1, 7, 5);" works? just what does each parameter changes, I've been looking for it, but it only says: The Tm operator. Sets the text matrix to the given values. A current text matrix will be replaced with the new one. a - The a value of the matrix. thanks and sorry for asking such noob questions
  • mkl
    mkl about 10 years
    You might want to look at this answer and the sections of the PDF specification ISO 32000-1 referenced from there.
  • Dan King
    Dan King almost 8 years
    This is a really useful answer, but appendRawCommands() is deprecated in the latest version of PDFBox. Any idea how you would create "artificially bold text" without using the deprecated API?
  • mkl
    mkl almost 8 years
    @DanKing getOutput().write(text.getBytes(Charsets.US_ASCII)) should work as a replacement for appendRawCommands(text) in 2.0.x without deprecation warning. If that is what PDFBox development intended as replacement, I don't know.
  • Dan King
    Dan King almost 8 years
    Thanks mkl - but I can't see where that getOutput() method is coming from - it doesn't seem to exist on PDPageContentStream?
  • mkl
    mkl almost 8 years
    @DanKing In 2.0.x it's inherited from PDAbstractContentStream, base class of PDPageContentStream.
  • Dan King
    Dan King almost 8 years
    PDPageContentStream doesn't have a base class in pdfbox 2.0.2
  • mkl
    mkl almost 8 years
    Ah, sorry, I actually looked into the 2.1.0-SNAPSHOT development sources where PDPageContentStream has got a base class PDAbstractContentStream - the issue PDFBOX-3353 is cause of this change. Thus, I assume this base class will soon be part of the release.
  • mkl
    mkl almost 8 years
    @DanKing In the current 2.0.x I do not see an alternative to appendRawCommands.
  • Dan King
    Dan King almost 8 years
    :-( OK, thanks. It seems the PDFBox philosophy now is to move away from appending raw commands in favour of just using the API - which is fine as long as the API supports everything you want to be able to do...