Here is a sample Java program showing how to create and add annotations such as square, rubber stamp, typewriter, callout and free text to a PDF document using Qoppa’s PDF library jPDFProcess.

The annotations are added to the first page of a PDF document. A first PDF is saved with all the annotations and a second PDF is saved after the annotations have been flattened into the content of the PDF.

package jPDFProcessSamples;
 
import java.awt.Color;
import java.awt.Font;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.List;
import java.util.Vector;
 
import com.qoppa.pdf.TextPosition;
import com.qoppa.pdf.annotations.Callout;
import com.qoppa.pdf.annotations.Circle;
import com.qoppa.pdf.annotations.FileAttachment;
import com.qoppa.pdf.annotations.FreeText;
import com.qoppa.pdf.annotations.IAnnotationFactory;
import com.qoppa.pdf.annotations.Ink;
import com.qoppa.pdf.annotations.Line;
import com.qoppa.pdf.annotations.Link;
import com.qoppa.pdf.annotations.Polygon;
import com.qoppa.pdf.annotations.Redaction;
import com.qoppa.pdf.annotations.RubberStamp;
import com.qoppa.pdf.annotations.Sound;
import com.qoppa.pdf.annotations.Square;
import com.qoppa.pdf.annotations.Text;
import com.qoppa.pdf.annotations.TextMarkup;
import com.qoppa.pdf.annotations.Vertices;
import com.qoppa.pdfProcess.PDFDocument;
import com.qoppa.pdfProcess.PDFPage;
 
public class AnnotationSample
{
	public static void main(String[] args)
	{
		try
		{
			// Load the document
			PDFDocument pdfDoc = new PDFDocument("input.pdf", null);
 
			// Page size is assumed to be 8.5 x 11 in.
			PDFPage page = pdfDoc.getPage(0);
 
			IAnnotationFactory annotFactory = pdfDoc.getAnnotationFactory();
 
			// Callout
			Callout callout = annotFactory.createCallout("callout text");
			callout.setRectangle(new Rectangle2D.Double(50, 50, 100, 100));
			callout.setBorderColor(Color.red);
			callout.setInnerRect(new Rectangle2D.Double(0, 0, 50, 50));
			callout.setArrow(new double[] { 100, 75, 25, 75, 25, 50 });
			callout.setPDFFont("Times-BoldItalic", 12f);
			page.addAnnotation(callout);
 
			// Circle
			Circle circle = annotFactory.createCircle("");
			circle.setRectangle(new Rectangle2D.Double(200, 50, 100, 100));
			circle.setColor(Color.blue);
			page.addAnnotation(circle);
 
			// File Attachment
			FileAttachment attach = annotFactory.createFileAttachment();
			attach.setRectangle(new Rectangle2D.Double(375, 75, 24, 24));
			attach.setColor(Color.green);
			attach.setIconName(FileAttachment.ICON_PUSHPIN);
			page.addAnnotation(attach);
 
			// Free Text
			FreeText freeText = annotFactory.createFreeText("freetext text");
			freeText.setRectangle(new Rectangle2D.Double(50, 200, 100, 100));
			freeText.setBorderColor(Color.orange);
			freeText.setPDFFont("Courier-BoldOblique", 12f);
			page.addAnnotation(freeText);
 
			// Ink
			List<Vertices> inkList = new Vector<Vertices>(2);
			Vertices vertices = new Vertices();
			for (int i = 0; i <= 100; i++)
			{
				vertices.addVertex(200 + i, 200 + i);
			}
			inkList.add(vertices);
			vertices = new Vertices();
			for (int i = 0; i <= 100; i++)
			{
				vertices.addVertex(200 + i, 300 - i);
			}
			inkList.add(vertices);
			Ink ink = annotFactory.createInk("", inkList);
			ink.setRectangle(new Rectangle2D.Double(200, 200, 100, 100));
			ink.setColor(Color.magenta);
			page.addAnnotation(ink);
 
			// Line
			Line line = annotFactory.createLine("", 350, 200, 450, 300);
			line.setRectangle(new Rectangle2D.Double(350, 200, 100, 100));
			line.setLineEndStyle("OpenArrow");
			line.setColor(Color.red);
			page.addAnnotation(line);
 
			// Link
			Link link = annotFactory.createLink();
			link.setRectangle(new Rectangle2D.Double(50, 375, 100, 25));
			link.setColor(Color.blue);
			link.setBorderWidth(.5);
			page.addAnnotation(link);
 
			// Polygon
			vertices = new Vertices();
			vertices.addVertex(205, 445);
			vertices.addVertex(233, 355);
			vertices.addVertex(266, 445);
			vertices.addVertex(295, 355);
			Polygon polygon = annotFactory.createPolygon("", vertices, null);
			polygon.setRectangle(new Rectangle2D.Double(200, 350, 100, 100));
			polygon.setColor(Color.cyan);
			page.addAnnotation(polygon);
 
			// Redaction
			Redaction redact = annotFactory.createRedaction("");
			redact.setRectangle(new Rectangle2D.Double(350, 350, 100, 100));
			redact.setColor(Color.green);
			redact.setInternalColor(Color.blue);
			redact.setBorderWidth(2.0);
			redact.setOverlayFont("Helvetica", 12f);
			redact.setOverlayText("Redaction Overlay");
			redact.setOverlayTextColor(Color.yellow);
			page.addAnnotation(redact);
 
			// Rubber Stamp
			RubberStamp rStamp = annotFactory.createRubberStamp("Rubber Stamp", Color.blue);
			rStamp.setRectangle(new Rectangle2D.Double(50, 500, 100, 50));
			page.addAnnotation(rStamp);
 
			// Sound
			Sound sound = annotFactory.createSound(null);
			sound.setRectangle(new Rectangle2D.Double(250, 525, 24, 24));
			sound.setColor(Color.red);
			page.addAnnotation(sound);
 
			// Square
			Square square = annotFactory.createSquare("");
			square.setRectangle(new Rectangle2D.Double(350, 500, 100, 100));
			square.setColor(Color.magenta);
			square.setInternalColor(Color.cyan);
			square.setBorderWidth(2.0);
			page.addAnnotation(square);
 
			// Sticky Note
			Text text = annotFactory.createText("sticky note", false, Text.ICON_COMMENT);
			text.setRectangle(new Rectangle2D.Double(100, 650, 24, 24));
			text.setColor(Color.orange);
			page.addAnnotation(text);
 
			// Draw some text to highlight
			page.drawText("Text to highlight", new Font("helvetica", Font.PLAIN, 12), Color.black, 200, 650, new AffineTransform());
 
			// Text Markup
                        List<TextPosition> searchResults = page.findText("Text to highlight", false, false);
			if (searchResults.size() > 0)
			{
				Vector<Point2D[]> quadList = new Vector<Point2D[]>();
				quadList.add(searchResults.get(0).getQuadrilateral());
				// Subtype can be Highlight, Underline, StrikeOut, Squiggly
                                TextMarkup textMarkup = annotFactory.createTextMarkup("", quadList, "Highlight");
				textMarkup.setColor(Color.YELLOW);
				page.addAnnotation(textMarkup);
			}
 
			// Typewriter
			FreeText typeWriter = annotFactory.createTypeWriter("typewriter text");
			typeWriter.setRectangle(new Rectangle2D.Double(350, 650, 100, 25));
			typeWriter.setPDFFont("Helvetica-BoldOblique", 12f);
			page.addAnnotation(typeWriter);
 
			// Save the document
			pdfDoc.saveDocument("annotation_output.pdf")
 
			// flatten the annotations
			pdfDoc.flattenAnnotations(false);
 
			// save flattened document
			pdfDoc.saveDocument("annotations_flatten.pdf");
 
			System.out.println("Annotations Created!");
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
	}
 
}

jPDFProcess is a Java library that can be used on the server side. Qoppa also produces a PDF visual component called jPDFNotes that allows to view PDF documents as well as create and add PDF annotations through a friendly user interface.