This is a slightly more advanced example of using the Apache PDFBox library. It demonstrates how to add some effects (called annotations in PDF terms) to text, namely highlighting, underlining, squiggly underlining and strikethrough. It's a bit tricky because these can't be applied to text as it's added to the document, but must be added later once a page is otherwise complete.

If you're new to PDFBox, start with the PdfBox example rather than this one.


import java.io.*;
import java.util.List;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;

public class SimpleAnnotation {

    // the text you want to highlight (or annotate, as it's called in PDF language)
    final static String[] texts = { "Underline""Strikeout""Squiggly""Highlight" };

    public static void main (String[] args) throws Exception {
        String outputFileName = "SimpleAnnotation.pdf";
        if (args.length > 0)
            outputFileName = args[0];

        // Create a document and add a page to it
        PDDocument document = new PDDocument();
        PDPage page = new PDPage(PDRectangle.A4);
            // PDRectangle.LETTER and others are also possible
        PDRectangle rect = page.getMediaBox();
            // rect can be used to get the page width and height
        document.addPage(page);

        // Start a new content stream which will hold the content of the page
        PDPageContentStream cos = new PDPageContentStream(document, page);

        // Define a text content stream using the selected font, move the cursor and draw some text
        cos.setFont(PDType1Font.HELVETICA, 14);

        int line = 0;

        // add some text so we have something to annotate
        for (String str : texts) {
            cos.beginText();
            cos.newLineAtOffset(100, rect.getHeight() - 50*(++line));
            cos.showText(str);
            cos.endText();
        }

        // Make sure that the content stream is closed:
        cos.close();

        // some ornamental extras for some of the text:
        // highlighting, strikethrough, underline and squiggly underline
        PDFTextStripper annotate = new MyAnnotator();
        annotate.setSortByPosition(true);
        annotate.setStartPage(0);
        annotate.setEndPage(document.getNumberOfPages());
        Writer dummy = new OutputStreamWriter(new ByteArrayOutputStream());
        annotate.writeText(document, dummy);

        // Save the results and ensure that the document is properly closed:
        document.save(outputFileName);
        document.close();
    }

    private static class MyAnnotator extends PDFTextStripper {

        public MyAnnotator() throws IOException {
            super();
        }

        @Override
        protected void writeString (String string, List<TextPosition> textPositions) throws IOException {
            float posXInit = 0, posXEnd = 0, posYInit = 0, posYEnd = 0, width = 0, height = 0, fontHeight = 0;

            int foundTextNo = -1;
            for (int i = 0; i < texts.length; i++) {
                if (string.contains(texts[i])) {
                    foundTextNo = i;
                    break;
                } 
            }
            if (foundTextNo != -1) {
                posXInit = textPositions.get(0).getXDirAdj();
                posXEnd  = textPositions.get(textPositions.size() - 1).getXDirAdj()
                           + textPositions.get(textPositions.size() - 1).getWidth();
                posYInit = textPositions.get(0).getPageHeight()
                           - textPositions.get(0).getYDirAdj();
                posYEnd  = textPositions.get(0).getPageHeight()
                           - textPositions.get(textPositions.size() - 1).getYDirAdj();
                width    = textPositions.get(0).getWidthDirAdj();
                height   = textPositions.get(0).getHeightDir();

                List<PDAnnotation> annotations = document.getPage(this.getCurrentPageNo() - 1).getAnnotations();
                PDAnnotationTextMarkup markup = null;
                // choose any color you want, they can be different for each annotation
                PDColor color = new PDColor(new float[]{ 11 / 255F1 }, PDDeviceRGB.INSTANCE);
                switch (foundTextNo) {
                    case 0:
                        markup = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_UNDERLINE);
                        break;
                    case 1:
                        markup = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_STRIKEOUT);
                        break;
                    case 2:
                        markup = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_SQUIGGLY);
                        break;
                    case 3:
                        markup = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);
                        break;
                }

                PDRectangle position = new PDRectangle();
                position.setLowerLeftX(posXInit);
                position.setLowerLeftY(posYEnd);
                position.setUpperRightX(posXEnd);
                position.setUpperRightY(posYEnd + height);
                markup.setRectangle(position);

                float quadPoints[] = {posXInit, posYEnd + height + 2,
                                      posXEnd, posYEnd + height + 2,
                                      posXInit, posYInit - 2,
                                      posXEnd, posYEnd - 2};
                markup.setQuadPoints(quadPoints);

                markup.setColor(color);
                annotations.add(markup);
            }
        }
    }
}


CodeSnippets