You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2018/05/25 18:53:38 UTC
svn commit: r1832267 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java
Author: tilman
Date: Fri May 25 18:53:38 2018
New Revision: 1832267
URL: http://svn.apache.org/viewvc?rev=1832267&view=rev
Log:
PDFBOX-3353: attempt at drawing the callout line
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java?rev=1832267&r1=1832266&r2=1832267&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java Fri May 25 18:53:38 2018
@@ -15,9 +15,17 @@
*/
package org.apache.pdfbox.pdmodel.interactive.annotation.handlers;
+import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.pdmodel.PDAppearanceContentStream;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationFreeText;
+import static org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLine.LE_NONE;
+import static org.apache.pdfbox.pdmodel.interactive.annotation.handlers.PDAbstractAppearanceHandler.SHORT_STYLES;
+import org.apache.pdfbox.util.Matrix;
public class PDFreeTextAppearanceHandler extends PDAbstractAppearanceHandler
{
@@ -39,7 +47,117 @@ public class PDFreeTextAppearanceHandler
@Override
public void generateNormalAppearance()
{
- // TODO to be implemented
+ PDAnnotationFreeText annotation = (PDAnnotationFreeText) getAnnotation();
+ PDRectangle rect = annotation.getRectangle();
+ float[] pathsArray = new float[0];
+ if ("FreeTextCallout".equals(annotation.getIntent()))
+ {
+ pathsArray = annotation.getCallout();
+ if (pathsArray == null || pathsArray.length != 4 && pathsArray.length != 6)
+ {
+ pathsArray = new float[0];
+ }
+ }
+ AnnotationBorder ab = AnnotationBorder.getAnnotationBorder(annotation, annotation.getBorderStyle());
+ PDColor color = annotation.getColor();
+ if (color == null || color.getComponents().length == 0 || Float.compare(ab.width, 0) == 0)
+ {
+ return;
+ }
+
+ if (pathsArray.length > 0)
+ {
+ // Adjust rectangle even if not empty
+ // CTAN-example-Annotations.pdf p1
+ //TODO in a class structure this should be overridable
+ float minX = Float.MAX_VALUE;
+ float minY = Float.MAX_VALUE;
+ float maxX = Float.MIN_VALUE;
+ float maxY = Float.MIN_VALUE;
+ for (int i = 0; i < pathsArray.length / 2; ++i)
+ {
+ float x = pathsArray[i * 2];
+ float y = pathsArray[i * 2 + 1];
+ minX = Math.min(minX, x);
+ minY = Math.min(minY, y);
+ maxX = Math.max(maxX, x);
+ maxY = Math.max(maxY, y);
+ }
+ // arrow length is 9 * width at about 30ð => 10 * width seems to be enough
+ rect.setLowerLeftX(Math.min(minX - ab.width * 10, rect.getLowerLeftX()));
+ rect.setLowerLeftY(Math.min(minY - ab.width * 10, rect.getLowerLeftY()));
+ rect.setUpperRightX(Math.max(maxX + ab.width * 10, rect.getUpperRightX()));
+ rect.setUpperRightY(Math.max(maxY + ab.width * 10, rect.getUpperRightY()));
+ annotation.setRectangle(rect);
+ }
+
+ try (PDAppearanceContentStream cs = getNormalAppearanceAsContentStream())
+ {
+ // The fill color is the /C entry, there is no /IC entry defined
+ boolean hasBackground = cs.setNonStrokingColorOnDemand(annotation.getColor());
+ setOpacity(cs, annotation.getConstantOpacity());
+
+ // in reality, Adobe uses the non stroking color from /DA as stroking color. WTF?
+ boolean hasStroke = cs.setStrokingColorOnDemand(color);
+ if (ab.dashArray != null)
+ {
+ cs.setLineDashPattern(ab.dashArray, 0);
+ }
+ cs.setLineWidth(ab.width);
+
+ for (int i = 0; i < pathsArray.length / 2; ++i)
+ {
+ float x = pathsArray[i * 2];
+ float y = pathsArray[i * 2 + 1];
+ if (i == 0)
+ {
+ if (SHORT_STYLES.contains(annotation.getLineEndingStyle()))
+ {
+ // modify coordinate to shorten the segment
+ // https://stackoverflow.com/questions/7740507/extend-a-line-segment-a-specific-distance
+ float x1 = pathsArray[2];
+ float y1 = pathsArray[3];
+ float len = (float) (Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2)));
+ if (Float.compare(len, 0) != 0)
+ {
+ x += (x1 - x) / len * ab.width;
+ y += (y1 - y) / len * ab.width;
+ }
+ }
+ cs.moveTo(x, y);
+ }
+ else
+ {
+ cs.lineTo(x, y);
+ }
+ }
+ cs.stroke();
+
+ // do a transform so that first "arm" is imagined flat, like in line handler
+ // the alternative would be to apply the transform to the LE shapes directly,
+ // which would be more work and produce code difficult to understand
+ // paint the styles here and after line(s) draw, to avoid line crossing a filled shape
+ if ("FreeTextCallout".equals(annotation.getIntent())
+ && !LE_NONE.equals(annotation.getLineEndingStyle())
+ && pathsArray.length >= 4)
+ {
+ // check only needed to avoid q cm Q if LE_NONE
+ float x2 = pathsArray[2];
+ float y2 = pathsArray[3];
+ float x1 = pathsArray[0];
+ float y1 = pathsArray[1];
+ double angle = Math.atan2(y2 - y1, x2 - x1);
+ cs.transform(Matrix.getRotateInstance(angle, x1, y1));
+ drawStyle(annotation.getLineEndingStyle(), cs, 0, 0, ab.width, hasStroke, hasBackground);
+ }
+
+ //TODO display border and text
+ // how to set the text color? Apparently red is the default.
+ }
+ catch (IOException ex)
+ {
+ LOG.error(ex);
+ }
}
@Override