package com.sun.pdfview.annotation; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D.Float; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import com.sun.pdfview.PDFCmd; import com.sun.pdfview.PDFImage; import com.sun.pdfview.PDFObject; import com.sun.pdfview.PDFPage; import com.sun.pdfview.PDFParseException; import com.sun.pdfview.PDFParser; /***************************************************************************** * PDF annotation describing a stamp * * @author Katja Sondermann * @since 26.03.2012 ****************************************************************************/ public class StampAnnotation extends PDFAnnotation { private String iconName; private PDFAnnotation popupAnnotation; private PDFObject onAppearance; private PDFObject offAppearance; private List<PDFCmd> onCmd; private List<PDFCmd> offCmd; private boolean appearanceStateOn; /************************************************************************* * Constructor * @param annotObject * @throws IOException ************************************************************************/ public StampAnnotation(PDFObject annotObject, ANNOTATION_TYPE type) throws IOException { super(annotObject, type); parsePopupAnnotation(annotObject.getDictRef("Popup")); parseAP(annotObject.getDictRef("AP")); } /************************************************************************* * Constructor * @param annotObject * @throws IOException ************************************************************************/ public StampAnnotation(PDFObject annotObject) throws IOException { this(annotObject, ANNOTATION_TYPE.STAMP); } private void parseAP(PDFObject dictRef) throws IOException { if(dictRef == null) { return; } PDFObject normalAP = dictRef.getDictRef("N"); if(normalAP == null) { return; } if(normalAP.getType() == PDFObject.DICTIONARY) { this.onAppearance = normalAP.getDictRef("On"); this.offAppearance = normalAP.getDictRef("Off"); PDFObject as = dictRef.getDictRef("AS"); this.appearanceStateOn = (as != null) && ("On".equals(as.getStringValue())); }else { this.onAppearance = normalAP; this.offAppearance = null; appearanceStateOn = true; } parseCommands(); } private void parseCommands() throws IOException { if(onAppearance != null) { onCmd = parseCommand(onAppearance); } if(offAppearance != null) { offCmd = parseCommand(offAppearance); } } private List<PDFCmd> parseCommand(PDFObject obj) throws IOException { String type = obj.getDictRef("Subtype").getStringValue(); if (type == null) { type = obj.getDictRef ("S").getStringValue (); } ArrayList<PDFCmd> result = new ArrayList<PDFCmd>(); result.add(PDFPage.createPushCmd()); result.add(PDFPage.createPushCmd()); if (type.equals("Image")) { // stamp annotation transformation AffineTransform rectAt = getPositionTransformation(); result.add(PDFPage.createXFormCmd(rectAt)); PDFImage img = PDFImage.createImage(obj, new HashMap<String, PDFObject>() , false); result.add(PDFPage.createImageCmd(img)); } else if (type.equals("Form")) { // rats. parse it. PDFObject bobj = obj.getDictRef("BBox"); Float bbox = new Rectangle2D.Float(bobj.getAt(0).getFloatValue(), bobj.getAt(1).getFloatValue(), bobj.getAt(2).getFloatValue(), bobj.getAt(3).getFloatValue()); PDFPage formCmds = new PDFPage(bbox, 0); // stamp annotation transformation AffineTransform rectAt = getPositionTransformation(); formCmds.addXform(rectAt); // form transformation AffineTransform at; PDFObject matrix = obj.getDictRef("Matrix"); if (matrix == null) { at = new AffineTransform(); } else { float elts[] = new float[6]; for (int i = 0; i < elts.length; i++) { elts[i] = (matrix.getAt(i)).getFloatValue(); } at = new AffineTransform(elts); } formCmds.addXform(at); HashMap<String,PDFObject> r = new HashMap<String,PDFObject>(new HashMap<String, PDFObject>()); PDFObject rsrc = obj.getDictRef("Resources"); if (rsrc != null) { r.putAll(rsrc.getDictionary()); } PDFParser form = new PDFParser(formCmds, obj.getStream(), r); form.go(true); result.addAll(formCmds.getCommands()); } else { throw new PDFParseException("Unknown XObject subtype: " + type); } result.add(PDFPage.createPopCmd()); result.add(PDFPage.createPopCmd()); return result; } /** * Transform to the position of the stamp annotation * @return */ private AffineTransform getPositionTransformation() { Float rect2 = getRect(); double[] f = new double[] {1, 0, 0, 1, rect2.getMinX(), rect2.getMinY()}; return new AffineTransform(f); } private void parsePopupAnnotation(PDFObject popupObj) throws IOException { this.popupAnnotation = (popupObj != null)?createAnnotation(popupObj):null; } /** * @return the iconName */ public String getIconName() { return iconName; } /** * @return the popupAnnotation */ public PDFAnnotation getPopupAnnotation() { return popupAnnotation; } /** * @return the onAppearance */ public PDFObject getOnAppearance() { return onAppearance; } /** * @return the offAppearance */ public PDFObject getOffAppearance() { return offAppearance; } /** * @return the appearanceStateOn */ public boolean isAppearanceStateOn() { return appearanceStateOn; } public void switchAppearance() { this.appearanceStateOn = !this.appearanceStateOn; } public PDFObject getCurrentAppearance() { return appearanceStateOn?onAppearance:offAppearance; } public List<PDFCmd> getCurrentCommand() { return appearanceStateOn?onCmd:offCmd; } @Override public List<PDFCmd> getPageCommandsForAnnotation() { List<PDFCmd> pageCommandsForAnnotation = super.getPageCommandsForAnnotation(); pageCommandsForAnnotation.addAll(getCurrentCommand()); return pageCommandsForAnnotation; } }