2

Based on the code posted in https://stackoverflow.com/a/51654691 I have been able to apply the highlight, underline and strikeout annotations to text in PDFs. Now I'm trying the conceptually similar squiggly annotation, and it doesn't seem to do anything (the text appears unaltered).

I can't find any examples specifically for this (and in the PDFBox JIRA no relevant issues come up regarding "squiggly"), so I'm stuck on how to use this annotation.

I could post the code I used, but it is essentially the same as the one linked above, except using SUB_TYPE_SQUIGGLY instead of SUB_TYPE_HIGHLIGHT.

Update: This is the code I'm testing this with in its most basic form.

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
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;

public class MainSourceSO {

    public static void main (String[] args) throws Exception {
        PDDocument document = PDDocument.load(new File("SO-example.pdf"));

        List<PDAnnotation> annotations = document.getPage(0).getAnnotations();
        PDColor color = new PDColor(new float[] { 1, 1 / 255F, 1 }, PDDeviceRGB.INSTANCE);

        PDAnnotationTextMarkup highlight = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_UNDERLINE);
        highlight.setRectangle(new PDRectangle(72, 400, 72, 18));
        highlight.setQuadPoints(new float[]{72.0f,418.0f,142.002f,418.0f,72.0f,400.0f,142.002f,400.0f});
        highlight.setColor(color);
        annotations.add(highlight);

        highlight = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);
        highlight.setRectangle(new PDRectangle(72, 500, 72, 18));
        highlight.setQuadPoints(new float[]{72.0f,518.0f,142.002f,518.0f,72.0f,500.0f,142.002f,500.0f});
        highlight.setColor(color);
        annotations.add(highlight);

        highlight = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_STRIKEOUT);
        highlight.setRectangle(new PDRectangle(72, 600, 72, 18));
        highlight.setQuadPoints(new float[]{72.0f,618.0f,142.002f,618.0f,72.0f,600.0f,142.002f,600.0f});
        highlight.setColor(color);
        annotations.add(highlight);

        highlight = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_SQUIGGLY);
        highlight.setRectangle(new PDRectangle(72, 700, 72, 18));
        highlight.setQuadPoints(new float[]{72.0f,718.0f,142.002f,718.0f,72.0f,700.0f,142.002f,700.0f});
        highlight.setColor(color);
        annotations.add(highlight);

        File file1 = new File("SO-example-2.pdf");
        document.save(file1);
    }
}
Didi
  • 43
  • 7

1 Answers1

2

This code worked for me:

PDDocument document = PDDocument.load(...);
List<PDAnnotation> annotations = document.getPage(0).getAnnotations();
PDAnnotationTextMarkup highlight = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_SQUIGGLY);
highlight.setRectangle(new PDRectangle(72, 500, 72, 18));
highlight.setQuadPoints(new float[]{72.0f,518.0f,142.002f,518.0f,72.0f,500.0f,142.002f,500.0f});
PDColor yellow = new PDColor(new float[] { 1, 1, 100 / 255F }, PDDeviceRGB.INSTANCE);
highlight.setColor(yellow);
annotations.add(highlight);
document.save(...);

I don't know what didn't work for you. Maybe it was the color (hard to see), maybe the rectangle, or maybe the quadpoints. (There is a bug in the PDF specification about the quadpoints, see here).

Tilman Hausherr
  • 17,731
  • 7
  • 58
  • 97
  • I've added the code I'm using in a basic form - it's basically the same as what you posted. Underline, strikeout and highlight show up, but squiggly doesn't. – Didi Dec 18 '18 at 09:04
  • Please check the size of your mediabox (page.getMediaBox()). If possible upload your result PDF to a sharehoster. – Tilman Hausherr Dec 18 '18 at 10:19
  • The mediabox of the page is [0.0,0.0,595.27563,841.8898]. I've put the source PDF and the annotated PDF, as well as the source code that creates both, at https://drive.google.com/drive/folders/1NF_aiIkZxbND1W2Bn8xw1fA6uSI-FICm. Thanks for looking into this! – Didi Dec 18 '18 at 11:11
  • It displays fine with Adobe Reader. It may be different with other viewers because of the missing appearance stream. What viewer did you use? – Tilman Hausherr Dec 18 '18 at 12:17
  • Preview on OS X. Also Chrome (but I guess that may use the same underlying PDF engine as Preview). Is there anything I can do about "the missing appearance stream"? – Didi Dec 18 '18 at 13:27
  • 1
    Chrome displays the squiggly on my system, although you have to scroll a bit. Creating the appearance stream is not much supported on 2.0. It is much better supported in the development trunk. You have to download from the svn repository and build from source. The classes are a bit different (squiggly has its own class `PDAnnotationSquiggly`), and you should call `constructAppearances()` on the annotation after the settings are done. – Tilman Hausherr Dec 18 '18 at 13:34
  • See here https://pdfbox.apache.org/building.html how to build from source. – Tilman Hausherr Dec 18 '18 at 13:46
  • My mistake, Chrome does indeed display it correctly. Calling `constructAppearances` with the 3.0 snapshot makes no difference, although I can now see the squiggle if I convert the PDF to an image using `PDFRenderer` (I uploaded both the PDF and the image to Google Drive - there's a discrepancy in how the highlight is displayed, round corners vs. rectangular corners, not sure if that's intentional). But I concur that it's an issue with Preview, so I consider the question answered. Many thanks for your help! – Didi Dec 18 '18 at 14:35
  • Glad I could help. The round corners is what Adobe is doing, so PDFBox is imitating that as closely as possible. However every viewer can decide how this is done, the specification does not tell any details. – Tilman Hausherr Dec 18 '18 at 18:53