Skip to content

Instantly share code, notes, and snippets.

@JoelGeraci-Datalogics
Last active June 29, 2016 19:12
Show Gist options
  • Save JoelGeraci-Datalogics/e26ed9798557fb91909175d70d27d0fe to your computer and use it in GitHub Desktop.
Save JoelGeraci-Datalogics/e26ed9798557fb91909175d70d27d0fe to your computer and use it in GitHub Desktop.
/*
* Copyright Datalogics, Inc. 2015
*/
package pdfjt.cookbook.annotations;
import com.adobe.fontengine.font.Font;
import com.adobe.internal.io.ByteReader;
import com.adobe.internal.io.InputStreamByteReader;
import com.adobe.internal.io.LazyRandomAccessFileByteReader;
import com.adobe.pdfjt.core.fontset.PDFFontSet;
import com.adobe.pdfjt.core.types.ASDate;
import com.adobe.pdfjt.core.types.ASName;
import com.adobe.pdfjt.core.types.ASString;
import com.adobe.pdfjt.pdf.document.PDFCatalog;
import com.adobe.pdfjt.pdf.document.PDFDocument;
import com.adobe.pdfjt.pdf.document.PDFEmbeddedFile;
import com.adobe.pdfjt.pdf.document.PDFEmbeddedFileInfo;
import com.adobe.pdfjt.pdf.document.PDFFileSpecification;
import com.adobe.pdfjt.pdf.document.PDFOpenOptions;
import com.adobe.pdfjt.pdf.filters.PDFFilterFlate;
import com.adobe.pdfjt.pdf.graphics.PDFRectangle;
import com.adobe.pdfjt.pdf.graphics.font.PDFFont;
import com.adobe.pdfjt.pdf.graphics.xobject.PDFXObjectForm;
import com.adobe.pdfjt.pdf.interactive.PDFViewerPreferences;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationCaret;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationCircle;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationEnum;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationFileAttachment;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationFreeText;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationHighlight;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationInk;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationLine;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationPolyline;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationSquare;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationStamp;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationStrikeOut;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationText;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAnnotationUnderline;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFAppearance;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFBorder;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFBorderStyle;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFBorderStyle.Style;
import com.adobe.pdfjt.pdf.interactive.annotation.PDFInkList;
import com.adobe.pdfjt.pdf.page.PDFPage;
import com.adobe.pdfjt.pdf.page.PDFPageLayout;
import com.adobe.pdfjt.services.ap.AppearanceService;
import com.adobe.pdfjt.services.ap.TextFormatterImpl;
import com.adobe.pdfjt.services.ap.spi.APContext;
import com.adobe.pdfjt.services.ap.spi.APResources;
import com.adobe.pdfjt.services.fontresources.PDFFontSetUtil;
import com.adobe.pdfjt.services.manipulations.PMMTemplates;
import com.adobe.pdfjt.services.readingorder.ReadingOrderTextExtractor;
import com.adobe.pdfjt.services.textextraction.TextExtractionOptions;
import com.adobe.pdfjt.services.textextraction.Word;
import com.adobe.pdfjt.services.textextraction.WordsIterator;
import com.adobe.pdfjt.services.xobjhandler.PageContentXObject;
import com.adobe.pdfjt.services.xobjhandler.XObjectContentType;
import com.adobe.pdfjt.services.xobjhandler.XObjectUseOptions;
import com.datalogics.pdf.document.DocumentHelper;
import pdfjt.util.SampleFontLoaderUtil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.io.IOUtils;
/**
* This sample draws two stars on a PDF Page using two different techniques.
*/
public class AllCommentAnnotations {
private static final String inputPDFURL = "http://dev.datalogics.com/cookbook/annotations/AllAnnotations.pdf";
private static final String outputDir = "cookbook/Annotations/output/";
private static final double INCH = 72;
static public void main(String[] args) throws Exception {
// First read in the PDF file
URLConnection connection = new URL(inputPDFURL).openConnection();
connection.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
connection.connect();
InputStream fis = connection.getInputStream();
ByteReader byteReader = new InputStreamByteReader(fis);
PDFDocument pdfDocument = PDFDocument.newInstance(byteReader, PDFOpenOptions.newInstance());
/*
* Set the default view to single page and fit in window. This isn't
* absolutely necessary but will allow you to see all of the annotations
* without needing to scroll.
*/
PDFCatalog pdfCatalog = pdfDocument.requireCatalog();
pdfCatalog.setPageLayout(PDFPageLayout.SinglePage);
PDFViewerPreferences pdfViewerPreferences = PDFViewerPreferences.newInstance(pdfDocument);
pdfViewerPreferences.setFitWindow(true);
pdfCatalog.setViewerPreferences(pdfViewerPreferences);
/*
* Then get the first (and only) page in the file. We'll need this
* object in order to add annotations to it.
*/
PDFPage pdfPageOne = pdfDocument.requirePages().getPage(0);
/*
* We'll need the resources and context to create the annotation
* appearances so let's create those here.
*/
APResources apResources = new APResources(pdfDocument.getCosDocument().getOptions().getFontSet(),
pdfDocument.getCosDocument().getOptions().getDocLocale(), new HashMap<Font, PDFFont>());
APContext apContext = new APContext(apResources, true, null);
/*
* First we'll add a few note annotations. because the viewer should
* supply the appearance based on the icon name, we don't need to
* generate appearances. We can also use a single point for the
* rectangle since different viewers may have different sized icons for
* these annotation types..
*/
// Text Annotations: Sticky note in Acrobat / Note Icon
PDFRectangle annotLocation_Note = PDFRectangle.newInstance(pdfDocument, .5 * INCH, 10.5 * INCH, .5 * INCH, 10.5 * INCH);
String popupContent_Note = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
PDFAnnotationText pdfAnnotationText_Note = PDFAnnotationText.newInstance(pdfDocument, annotLocation_Note, popupContent_Note);
pdfAnnotationText_Note.setIconName("Note");
pdfAnnotationText_Note.setColor(new double[] { 1, 1, 0 });
pdfPageOne.addAnnotation(pdfAnnotationText_Note);
// Text Annotations: Sticky note in Acrobat / Help Icon
PDFRectangle annotLocation_Help = PDFRectangle.newInstance(pdfDocument, 1 * INCH, 10.5 * INCH, 1 * INCH, 10.5 * INCH);
String popupContent_Help = "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
PDFAnnotationText pdfAnnotationText_Help = PDFAnnotationText.newInstance(pdfDocument, annotLocation_Help, popupContent_Help);
pdfAnnotationText_Help.setIconName("Help");
pdfAnnotationText_Help.setColor(new double[] { 1, 1, 0 });
pdfPageOne.addAnnotation(pdfAnnotationText_Help);
// Text Annotations: Sticky note in Acrobat / Key Icon
PDFRectangle annotLocation_Key = PDFRectangle.newInstance(pdfDocument, 1.5 * INCH, 10.5 * INCH, 1.5 * INCH, 10.5 * INCH);
String popupContent_Key = "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.";
PDFAnnotationText pdfAnnotationText_Key = PDFAnnotationText.newInstance(pdfDocument, annotLocation_Key, popupContent_Key);
pdfAnnotationText_Key.setIconName("Key");
pdfAnnotationText_Key.setColor(new double[] { 0, 0, 1 });
pdfPageOne.addAnnotation(pdfAnnotationText_Key);
/*
* Now we're going to add some of the text markup annotations so we'll
* need to get some words from the document so we can use their quads to
* derive the annotation quads. However, the quad order for an
* annotation is different from the quad order for a word so I've the
* method wordsQuadsToAnnotQuads() is used to create the correct order
* based on the first and last word that we want to add our comment to.
*
* We add the words to an array so we can easily access just the ones we
* need.
*/
PDFFontSet sysFontSet = SampleFontLoaderUtil.loadSampleFontSet();
PDFFontSet fontset = PDFFontSetUtil.buildWorkingFontSet(pdfDocument, sysFontSet, pdfDocument.getDocumentLocale(), null);
TextExtractionOptions textExtractionOptions = TextExtractionOptions.newInstance();
textExtractionOptions.setUseStructure(true);
textExtractionOptions.setIgnoreArtifacts(true);
ReadingOrderTextExtractor readingOrderTextExtractor = ReadingOrderTextExtractor.newInstance(pdfDocument, fontset,
textExtractionOptions);
WordsIterator wordsIterator = readingOrderTextExtractor.getWordsIterator();
ArrayList<Word> wordsArrayList = new ArrayList<Word>();
while (wordsIterator.hasNext()) {
Word word = wordsIterator.next();
if (word.getBoundingQuads() != null) {
wordsArrayList.add(word);
}
}
// Create a Highlight annotation
PDFAnnotationHighlight pdfAnnotationHighlight = PDFAnnotationHighlight.newInstance(pdfDocument);
// Set the properties
double[] quadPoints = wordsQuadsToAnnotQuads(wordsArrayList.get(2), wordsArrayList.get(7));
pdfAnnotationHighlight.setQuadPoints(quadPoints);
pdfAnnotationHighlight.setColor(new double[] { 1, 0.8, 0 });
// Add it to the page
pdfPageOne.addAnnotation(pdfAnnotationHighlight);
// Generate it's appearance
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.Highlight));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
/*
* The steps for adding the text markup annotations are all the same
*/
// Create an Underline annotation
PDFAnnotationUnderline pdfAnnotationUnderline = PDFAnnotationUnderline.newInstance(pdfDocument);
quadPoints = wordsQuadsToAnnotQuads(wordsArrayList.get(9), wordsArrayList.get(13));
pdfAnnotationUnderline.setQuadPoints(quadPoints);
pdfAnnotationUnderline.setColor(new double[] { 0.40, 0.85, 0.15 }); // Matches
// the
// Acrobat
// default
pdfPageOne.addAnnotation(pdfAnnotationUnderline);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.Underline));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
// Create a Strikeout annotation
PDFAnnotationStrikeOut pdfAnnotationStrikeOut = PDFAnnotationStrikeOut.newInstance(pdfDocument);
quadPoints = wordsQuadsToAnnotQuads(wordsArrayList.get(14), wordsArrayList.get(18));
pdfAnnotationStrikeOut.setQuadPoints(quadPoints);
pdfAnnotationStrikeOut.setColor(new double[] { 1, 0, 0 });
pdfPageOne.addAnnotation(pdfAnnotationStrikeOut);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.StrikeOut));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
/*
* Add Caret - Insert Text at Cursor in Acrobat (approximates Acrobat
* positioning) The caret annotation is positioned using a rectangle
* that with the top left roughly 1/2 the font height up from the base
* line and 1/2 a character width to the left of the end of the word.
*/
PDFAnnotationCaret pdfAnnotationCaret = PDFAnnotationCaret.newInstance(pdfDocument);
Word word = wordsArrayList.get(20);
double wordHeight = word.topLeft().y() - word.bottomRight().y();
double llx = word.bottomRight().x() - (word.charWidth() / 2);
double lly = word.bottomRight().y() - (wordHeight / 4);
double urx = word.bottomRight().x() + (word.charWidth() / 2);// (wordHeight/4);
double ury = lly + (wordHeight / 2);
pdfAnnotationCaret.setRect(PDFRectangle.newInstance(pdfDocument, llx, lly, urx, ury));
pdfAnnotationCaret.setColor(new double[] { 0, 0, 1 });
pdfPageOne.addAnnotation(pdfAnnotationCaret);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.Caret));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
/*
* In Acrobat, there are three types of "Free Text" annotation tools.
* One without a border, sometimes referred to as the typewriter tool,
* one with a border called the text box tool, and one with an arrow
* attached to it referred to as a Callout. These are all the same
* annotation type in JT.
*
* When creating these types of annotations, you start with the basic
* PDFAnnotationFreeText and then set the appropriate properties that
* mimic the appropriate tool in Acrobat.
*
* Both the default Style and default Appearance (different from the
* annotation AP dictionary) must be set in order for a proper
* annotation appearance (the AP dictionary) to be generated.
*/
// Add Free Text / Typewriter Tool in Acrobat
PDFAnnotationFreeText pdfAnnotationFreeText_Comment = PDFAnnotationFreeText.newInstance(pdfDocument);
pdfAnnotationFreeText_Comment.setRect(PDFRectangle.newInstance(pdfDocument, 2 * INCH, 6 * INCH, 4 * INCH, 6.5 * INCH));
pdfAnnotationFreeText_Comment.setContents("Et harum quidem rerum facilis est et expedita distinctio.");
pdfAnnotationFreeText_Comment
.setDefaultStyle("font: Helvetica,sans-serif 10.0pt;font-stretch:Normal; text-align:left; color:#000000");
pdfAnnotationFreeText_Comment.setDefaultAppearance("13.75 TL /Helvetica 10 Tf"); // Helvetica
// 10/13.75
pdfAnnotationFreeText_Comment.setBorderStyle(PDFBorderStyle.newInstance(pdfDocument, 0, null, null));
pdfAnnotationFreeText_Comment.setIntent("FreeTextTypeWriter");
pdfPageOne.addAnnotation(pdfAnnotationFreeText_Comment);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.FreeText));
AppearanceService.generateAppearances(pdfDocument, apContext, new TextFormatterImpl(pdfDocument));
// Add Free Text / Text Box tool in Acrobat
PDFAnnotationFreeText pdfAnnotationFreeText_TextBox = PDFAnnotationFreeText.newInstance(pdfDocument);
pdfAnnotationFreeText_TextBox.setRect(PDFRectangle.newInstance(pdfDocument, 2 * INCH, 5 * INCH, 4 * INCH, 5.5 * INCH));
pdfAnnotationFreeText_TextBox.setContents("Et harum quidem rerum facilis est et expedita distinctio.");
pdfAnnotationFreeText_TextBox.setDefaultStyle("font: Helvetica,sans-serif 10.0pt; text-align:left; color:#FF0000 ");
pdfAnnotationFreeText_TextBox.setDefaultAppearance("1 0 0 rg 13.75 TL /Helvetica 10 Tf");
PDFBorderStyle pdfBorderStyle = PDFBorderStyle.newInstance(pdfDocument, 1, Style.Solid, null);
pdfAnnotationFreeText_TextBox.setBorderStyle(pdfBorderStyle);
pdfAnnotationFreeText_TextBox.setIntent("FreeText");
pdfPageOne.addAnnotation(pdfAnnotationFreeText_TextBox);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.FreeText));
AppearanceService.generateAppearances(pdfDocument, apContext, new TextFormatterImpl(pdfDocument));
// Add Text Callout / Arrow with Knee
PDFAnnotationFreeText pdfAnnotationFreeText_Callout1 = PDFAnnotationFreeText.newInstance(pdfDocument);
pdfAnnotationFreeText_Callout1.setRect(PDFRectangle.newInstance(pdfDocument, 2 * INCH, 4 * INCH, 4 * INCH, 4.5 * INCH));
pdfAnnotationFreeText_Callout1.setContents("Et harum quidem rerum facilis est et expedita distinctio.");
pdfAnnotationFreeText_Callout1.setDefaultStyle("font: Helvetica,sans-serif 10.0pt; text-align:left; color:#00FF00 ");
pdfAnnotationFreeText_Callout1.setDefaultAppearance("0 1 0 rg 13.75 TL /Helvetica 10 Tf");
pdfAnnotationFreeText_Callout1.setLineEnds(new PDFAnnotationLine.LineEnding[] { PDFAnnotationLine.LineEnding.OpenArrow });
double arrowHead_x = 1 * INCH;
double arrowHead_y = 5 * INCH;
double knee_x = 1.5 * INCH;
double knee_y = 4.25 * INCH;
double attachPoint_x = 2 * INCH;
double attachpoint_y = 4.25 * INCH;
pdfAnnotationFreeText_Callout1.setCalloutLine(arrowHead_x, arrowHead_y, knee_x, knee_y, attachPoint_x, attachpoint_y);
pdfAnnotationFreeText_Callout1.setIntent("FreeTextCallout");
pdfAnnotationFreeText_Callout1.setBorderStyle(pdfBorderStyle);
pdfPageOne.addAnnotation(pdfAnnotationFreeText_Callout1);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.FreeText));
AppearanceService.generateAppearances(pdfDocument, apContext, new TextFormatterImpl(pdfDocument));
/*
* Ink annotations, polyline annotations, and polygon annotations all
* use an array of vertices to describe the path that they form. An ink
* annotation will join the points using curves whereas polyline
* annotations are joined by straight lines.
*
* Polygon annotations are described in this Gist
* https://gist.github.com/JoelGeraci-Datalogics/
* fc4170b11492b7de4e972e7623a3db43
*/
// Add Ink annotation / Draw Free Form in Acrobat
PDFAnnotationInk pdfAnnotationInk = PDFAnnotationInk.newInstance(pdfDocument);
List<Number> inkList = Arrays.asList(new Number[] { 410, 365, 515, 370, 513, 450, 450, 450, 450, 400, 490, 400 });
PDFInkList pdfInkList = PDFInkList.newInstance(pdfDocument);
pdfInkList.addPath(inkList);
pdfAnnotationInk.setInkList(pdfInkList);
pdfAnnotationInk.setColor(new double[] { 1, 0, 0 });
pdfPageOne.addAnnotation(pdfAnnotationInk);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.Ink));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
PDFAnnotationPolyline pdfAnnotationPolyline = PDFAnnotationPolyline.newInstance(pdfDocument);
double[] vertices_Polyline = new double[] { 359.9, 661.3 - (6.5 * INCH), 341.9, 630 - (6.5 * INCH), 359.9, 598.7 - (6.5 * INCH),
396.1, 598.7 - (6.5 * INCH), 414.1, 630 - (6.5 * INCH) };
pdfAnnotationPolyline.setDictionaryArrayValue(ASName.k_Vertices, vertices_Polyline);
pdfAnnotationPolyline.setColor(new double[] { 1, 0, 0 });
PDFBorder pdfBorderPolyLine = PDFBorder.newInstance(pdfDocument);
pdfBorderPolyLine.setWidth(.5);
pdfAnnotationPolyline.setBorder(pdfBorderPolyLine);
pdfPageOne.addAnnotation(pdfAnnotationPolyline);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.PolyLine));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
/*
* To add a stamp to a PDF file, you must first open the stamp file,
* find the page that represents the stamp you want, wrap it in an
* XObject and then use that xObject as the appearance of the Stamp
* annotation.
*/
// Add Stamp / Static
String standardStampsPDF = "http://dev.datalogics.com/cookbook/stamps/StandardBusiness.pdf";
connection = new URL(standardStampsPDF).openConnection();
connection.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
connection.connect();
fis = connection.getInputStream();
byteReader = new InputStreamByteReader(fis);
PDFDocument stampsPDF = PDFDocument.newInstance(byteReader, PDFOpenOptions.newInstance());
/*
* Get the page with the template name that matches the "Confidential"
* stamp in the Acrobat UI.
*/
PMMTemplates pmmTemplates = new PMMTemplates(stampsPDF);
PDFPage confidentialStampPage = pmmTemplates.templateExistsForName(stampsPDF, "SBConfidential=Confidential");
/*
* We are going to use pages from the "StandardBusiness.pdf" that ships
* with Adobe Acrobat as the Stamp Appearance. We can pull content from
* other PDF files by encapsulating the page content stream (with the
* associated Resources dictionary) in an XObject. For Stamps we don't
* need any special kind of XObject type so we just use "General".
*/
XObjectUseOptions useOptions = new XObjectUseOptions();
XObjectContentType xObjectContentType = XObjectContentType.General;
useOptions.setContentType(xObjectContentType);
// Create the Stamp Annotation Object.
PDFAnnotationStamp pdfAnnotationStamp = PDFAnnotationStamp.newInstance(pdfDocument);
PDFAppearance pdfAppearance = PDFAppearance.newInstance(pdfDocument);
/*
* Create an XObject from the page that has the stamp that we want, and
* then set it as the normal appearance for the stamp annotation.
*/
PDFXObjectForm approvedStampXObjectForm = PageContentXObject.generateContentXObject(pdfDocument, confidentialStampPage, useOptions);
pdfAppearance.setNormalAppearance(approvedStampXObjectForm);
pdfAnnotationStamp.setAppearance(pdfAppearance);
/*
* Add a Title and Content for the Stamp Pop-Up. These strings will
* appear in the Acrobat Comments panel and when you roll over the
* Stamp.
*/
pdfAnnotationStamp.setTitle("Datalogics");
pdfAnnotationStamp.setContents("My Confidential Stamp");
double stampWidth = approvedStampXObjectForm.getBBox().width();
double stampHeight = approvedStampXObjectForm.getBBox().height();
double stamp_llx = 4.5 * INCH;
double stamp_lly = 4.5 * INCH - stampHeight;
double stamp_urx = llx + stampWidth;
double stamp_ury = 4.5 * INCH;
pdfAnnotationStamp.setRect(stamp_llx, stamp_lly, stamp_urx, stamp_ury);
// Add the Stamp Annotation to the page
pdfPageOne.addAnnotation(pdfAnnotationStamp);
/*
* Attachment annotations require that you embed the file you want to
* use as the attachment and then use that object when instantiating the
* new PDFAnnotationFileAttachment object.
*/
// Attachment Annotation
standardStampsPDF = "http://dev.datalogics.com/cookbook/stamps/StandardBusiness.pdf";
connection = new URL(standardStampsPDF).openConnection();
connection.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
connection.connect();
fis = connection.getInputStream();
File attachmentFile = new File("StandardBusiness.pdf");
OutputStream outputStream = new FileOutputStream(attachmentFile);
IOUtils.copy(fis, outputStream);
outputStream.close();
LazyRandomAccessFileByteReader attachment = new LazyRandomAccessFileByteReader(attachmentFile);
Calendar modCalendar = Calendar.getInstance();
modCalendar.setTimeInMillis(attachmentFile.lastModified());
ASDate modTime = new ASDate(modCalendar.getTime());
PDFEmbeddedFileInfo info = PDFEmbeddedFileInfo.newInstance(pdfDocument, (int) attachment.length(), modTime, modTime);
PDFEmbeddedFile pdfEmbeddedFile = PDFEmbeddedFile.newInstance(pdfDocument, info, attachment);
pdfEmbeddedFile.setFilter(PDFFilterFlate.newInstance(pdfDocument, null));
PDFFileSpecification fileSpecification = PDFFileSpecification.newInstance(pdfDocument, new ASString("StandardBusiness.pdf"),
pdfEmbeddedFile);
PDFRectangle annotLocation_Attachment = PDFRectangle.newInstance(pdfDocument, (2 * INCH) - 8, (10.5 * INCH) - 10, 2 * INCH,
10.5 * INCH);
PDFAnnotationFileAttachment pdfAnnotationFileAttachment = PDFAnnotationFileAttachment.newInstance(pdfDocument,
annotLocation_Attachment, fileSpecification);
pdfAnnotationFileAttachment.setColor(new double[] { 0.25, 0.33, 1 });
pdfAnnotationFileAttachment.setIconName("PaperclipTag");
pdfPageOne.addAnnotation(pdfAnnotationFileAttachment);
/*
* Line, arrow, rectangle, and circle annotations all use a lower left
* and upper right set of coordinates to draw their annotations. The
* specifics are in each set of properties.
*/
// Line / no arrows
double llx_line = 2 * INCH;
double lly_line = 3 * INCH;
double urx_line = 4 * INCH;
double ury_line = 3.5 * INCH;
PDFAnnotationLine pdfAnnotationLine = PDFAnnotationLine.newInstance(pdfDocument);
pdfAnnotationLine.setLineCoords(llx_line, lly_line, urx_line, ury_line);
pdfAnnotationLine.setColor(new double[] { 1, 0, 0 });
pdfPageOne.addAnnotation(pdfAnnotationLine);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.Line));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
// Line / Arrow 1
double llx_arrow_1 = 4.5 * INCH;
double lly_arrow_1 = 3 * INCH;
double urx_arrow_1 = 6.5 * INCH;
double ury_arrow_1 = 3.5 * INCH;
PDFAnnotationLine pdfAnnotationArrow_1 = PDFAnnotationLine.newInstance(pdfDocument);
pdfAnnotationArrow_1.setLineCoords(llx_arrow_1, lly_arrow_1, urx_arrow_1, ury_arrow_1);
pdfAnnotationArrow_1.setColor(new double[] { 1, 0, 0 });
// Change the order of the line ending array to set which end gets the
// arrow.
pdfAnnotationArrow_1.setLineEnds(
new PDFAnnotationLine.LineEnding[] { PDFAnnotationLine.LineEnding.OpenArrow, PDFAnnotationLine.LineEnding.None });
pdfPageOne.addAnnotation(pdfAnnotationArrow_1);
// Line / Arrow 2
double llx_arrow_2 = 5 * INCH;
double lly_arrow_2 = 3 * INCH;
double urx_arrow_2 = 7 * INCH;
double ury_arrow_2 = 3.5 * INCH;
PDFAnnotationLine pdfAnnotationArrow_2 = PDFAnnotationLine.newInstance(pdfDocument);
pdfAnnotationArrow_2.setLineCoords(llx_arrow_2, lly_arrow_2, urx_arrow_2, ury_arrow_2);
pdfAnnotationArrow_2.setColor(new double[] { 1, 0, 0 });
// Change the order of the line ending array to set which end gets the
// arrow.
pdfAnnotationArrow_2.setLineEnds(
new PDFAnnotationLine.LineEnding[] { PDFAnnotationLine.LineEnding.None, PDFAnnotationLine.LineEnding.OpenArrow });
pdfPageOne.addAnnotation(pdfAnnotationArrow_2);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.Line));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
// Rectangle
double llx_rect = 2 * INCH;
double lly_rect = 2 * INCH;
double urx_rect = 2.5 * INCH;
double ury_rect = 2.5 * INCH;
PDFAnnotationSquare pdfAnnotationSquare = PDFAnnotationSquare.newInstance(pdfDocument);
pdfAnnotationSquare.setRect(llx_rect, lly_rect, urx_rect, ury_rect);
PDFBorderStyle pdfBorderStyle_Square = PDFBorderStyle.newInstance(pdfDocument, 1, Style.Solid, null);
pdfAnnotationSquare.setBorderStyle(pdfBorderStyle_Square);
pdfAnnotationSquare.setColor(new double[] { 1, 0, 0 });
pdfPageOne.addAnnotation(pdfAnnotationSquare);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.Square));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
// Circle
double llx_oval = 2.75 * INCH;
double lly_oval = 2 * INCH;
double urx_oval = 3.25 * INCH;
double ury_oval = 2.5 * INCH;
PDFAnnotationCircle pdfAnnotationCircle = PDFAnnotationCircle.newInstance(pdfDocument);
pdfAnnotationCircle.setRect(llx_oval, lly_oval, urx_oval, ury_oval);
PDFBorderStyle pdfBorderStyle_Oval = PDFBorderStyle.newInstance(pdfDocument, 1, Style.Solid, null);
pdfAnnotationCircle.setBorderStyle(pdfBorderStyle_Oval);
pdfAnnotationCircle.setColor(new double[] { 1, 0, 0 });
pdfPageOne.addAnnotation(pdfAnnotationCircle);
apContext.setAnnotationsToBeProcessed(EnumSet.of(PDFAnnotationEnum.Circle));
AppearanceService.generateAppearances(pdfDocument, apContext, null);
// Save and close
DocumentHelper.saveFullAndClose(pdfDocument, outputDir + "AllAnnotations.pdf");
// Save the file.
System.out.println("Done!");
}
public static double[] wordsQuadsToAnnotQuads(Word wordA, Word wordB) throws Exception {
double[] quadPoints = new double[8];
// Order is not the same for an annotation as it is for a word
quadPoints[0] = wordA.getBoundingQuads().get(0).p4().x();
quadPoints[1] = wordA.getBoundingQuads().get(0).p4().y();
quadPoints[2] = wordB.getBoundingQuads().get(0).p3().x();
quadPoints[3] = wordB.getBoundingQuads().get(0).p3().y();
quadPoints[4] = wordA.getBoundingQuads().get(0).p1().x();
quadPoints[5] = wordA.getBoundingQuads().get(0).p1().y();
quadPoints[6] = wordB.getBoundingQuads().get(0).p2().x();
quadPoints[7] = wordB.getBoundingQuads().get(0).p2().y();
return quadPoints;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment