
org.openpdf.renderer.annotation.MarkupAnnotation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openpdf-renderer Show documentation
Show all versions of openpdf-renderer Show documentation
PDF renderer implementation supporting the subset of PDF 1.4 specification.
The newest version!
package org.openpdf.renderer.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 org.openpdf.renderer.PDFCmd;
import org.openpdf.renderer.PDFImage;
import org.openpdf.renderer.PDFObject;
import org.openpdf.renderer.PDFPage;
import org.openpdf.renderer.PDFParseException;
import org.openpdf.renderer.PDFParser;
/*****************************************************************************
* PDF annotation describing a all kind of "markup" annotations which are visible
* in the PDF.
*
* @author Bernd Rosstauscher
****************************************************************************/
public class MarkupAnnotation extends PDFAnnotation {
private PDFObject onAppearance;
private PDFObject offAppearance;
private List onCmd;
private List offCmd;
private boolean appearanceStateOn;
private AnnotationBorderStyle borderStyle;
private String textLabel;
private PDFAnnotation popupAnnotation;
/*************************************************************************
* Constructor
* @param annotObject
* @throws IOException
************************************************************************/
public MarkupAnnotation(PDFObject annotObject, AnnotationType type) throws IOException {
super(annotObject, type);
this.textLabel = annotObject.getDictRefAsString("T");
// TODO more is missing here like CA, RC, ...
parsePopupAnnotation(annotObject.getDictRef("Popup"));
parseAP(annotObject.getDictRef("AP"));
parseBorderStyleDictionary(annotObject.getDictRef("BS"));
}
/**
* Parses the appearance stream into PDF commands
* @param dictRef
* @throws IOException
*/
protected 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;
}
parseOnOffCommands();
}
/**
* Parses the mouse On or Off appearance stream
* depending on which one is currently active.
* @throws IOException
*/
private void parseOnOffCommands() throws IOException {
if(onAppearance != null) {
onCmd = parseIntoPdfCommands(onAppearance);
}
if(offAppearance != null) {
offCmd = parseIntoPdfCommands(offAppearance);
}
}
/**
* Parses the border style dictionary
* @param bs
* @throws IOException
*/
protected void parseBorderStyleDictionary(PDFObject bs) throws IOException {
if (bs != null) {
this.borderStyle = AnnotationBorderStyle.parseFromDictionary(bs);
}
}
/**
* @return the border style or null if not specified.
*/
public AnnotationBorderStyle getBorderStyle() {
return borderStyle;
}
/**
* Parses the popup annotation
* @param popupObj
* @throws IOException
*/
private void parsePopupAnnotation(PDFObject popupObj) throws IOException {
this.popupAnnotation = (popupObj != null)?createAnnotation(popupObj):null;
}
private List parseIntoPdfCommands(PDFObject obj) throws IOException {
// TODO see also WidgetAnnotation.parseCommand which seems to be copied code
// We should merge these two
String type = obj.getDictRef("Subtype").getStringValue();
if (type == null) {
type = obj.getDictRef ("S").getStringValue ();
}
ArrayList result = new ArrayList();
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() , false);
result.add(PDFPage.createImageCmd(img));
} else if (type.equals("Form")) {
// rats. parse it.
PDFObject bobj = obj.getDictRef("BBox");
float xMin = bobj.getAt(0).getFloatValue();
float yMin = bobj.getAt(1).getFloatValue();
float xMax = bobj.getAt(2).getFloatValue();
float yMax = bobj.getAt(3).getFloatValue();
Float bbox = new Rectangle2D.Float(xMin,
yMin,
xMax - xMin,
yMax - yMin);
PDFPage formCmds = new PDFPage(bbox, 0);
// stamp annotation transformation
AffineTransform rectAt = getPositionTransformation();
formCmds.addXform(rectAt);
AffineTransform rectScaled = getScalingTransformation(bbox);
formCmds.addXform(rectScaled);
// 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 r = new HashMap(new HashMap());
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);
}
/**
* @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 getCurrentCommand() {
return appearanceStateOn?onCmd:offCmd;
}
@Override
public List getPageCommandsForAnnotation() {
List pageCommandsForAnnotation = super.getPageCommandsForAnnotation();
pageCommandsForAnnotation.addAll(getCurrentCommand());
return pageCommandsForAnnotation;
}
/**
* @return the popupAnnotation
*/
public PDFAnnotation getPopupAnnotation() {
return popupAnnotation;
}
public String getTextLabel() {
return textLabel;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy