You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ms...@apache.org on 2015/05/20 12:34:07 UTC

svn commit: r1680516 - /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/

Author: msahyoun
Date: Wed May 20 10:34:07 2015
New Revision: 1680516

URL: http://svn.apache.org/r1680516
Log:
PDFBOX-2758: support additional annotation types and parameters in FDF

Added:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationTextMarkup.java   (with props)
Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotation.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCaret.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCircle.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationFreeText.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationHighlight.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationInk.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationLine.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolygon.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolyline.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquare.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquiggly.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStrikeOut.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationText.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationUnderline.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotation.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotation.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotation.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotation.java Wed May 20 10:34:07 2015
@@ -20,22 +20,36 @@ import java.awt.Color;
 import java.io.IOException;
 import java.util.Calendar;
 
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNumber;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.cos.COSString;
 import org.apache.pdfbox.pdmodel.common.COSObjectable;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDBorderEffectDictionary;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDBorderStyleDictionary;
 import org.apache.pdfbox.util.DateConverter;
 import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * This represents an FDF annotation that is part of the FDF document.
  *
  * @author Ben Litchfield
+ * @author Johanneke Lamberink
  * 
  * */
 public abstract class FDFAnnotation implements COSObjectable
@@ -77,10 +91,11 @@ public abstract class FDFAnnotation impl
         this();
 
         String page = element.getAttribute( "page" );
-        if( page != null )
+        if (page == null || page.isEmpty())
         {
-            setPage( Integer.parseInt( page ) );
+            throw new IOException("Error: missing required attribute 'page'");
         }
+        setPage(Integer.parseInt(page));
 
         String color = element.getAttribute("color");
         if (color != null && color.length() == 7 && color.charAt(0) == '#')
@@ -138,28 +153,122 @@ public abstract class FDFAnnotation impl
 
         setName( element.getAttribute( "name" ) );
 
-        String rect = element.getAttribute( "rect" );
-        if( rect != null )
+        String rect = element.getAttribute("rect");
+        if (rect == null)
         {
-            String[] rectValues = rect.split( "," );
-            float[] values = new float[ rectValues.length ];
-            for( int i=0; i<rectValues.length; i++ )
+            throw new IOException("Error: missing attribute 'rect'");
+        }
+        String[] rectValues = rect.split(",");
+        if (rectValues.length != 4)
+        {
+            throw new IOException("Error: wrong amount of numbers in attribute 'rect'");
+        }
+        float[] values = new float[4];
+        for (int i = 0; i < 4; i++)
+        {
+            values[i] = Float.parseFloat(rectValues[i]);
+        }
+        COSArray array = new COSArray();
+        array.setFloatArray(values);
+        setRectangle(new PDRectangle(array));
+
+        setTitle(element.getAttribute("title"));
+
+        /*
+         * Set the markup annotation attributes
+         */
+        setCreationDate(DateConverter.toCalendar(element.getAttribute("creationdate")));
+        String opac = element.getAttribute("opacity");
+        if (opac != null && !opac.isEmpty())
+        {
+            setOpacity(Float.parseFloat(opac));
+        }
+        setSubject(element.getAttribute("subject"));
+        setIntent(element.getAttribute("intent"));
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        try
+        {
+            setContents(xpath.evaluate("contents[1]", element));
+        }
+        catch (XPathExpressionException e)
+        {
+            LOG.debug("Error while evaluating XPath expression for richtext contents");
+        }
+
+        try
+        {
+            Node richContents = (Node) xpath.evaluate("contents-richtext[1]", element,
+                    XPathConstants.NODE);
+            if (richContents != null)
             {
-                values[i] = Float.parseFloat( rectValues[i] );
+                setRichContents(richContentsToString(richContents, true));
+                setContents(richContents.getTextContent().trim());
             }
-            COSArray array = new COSArray();
-            array.setFloatArray( values );
-            setRectangle( new PDRectangle( array ) );
+        }
+        catch (XPathExpressionException e)
+        {
+            LOG.debug("Error while evaluating XPath expression for richtext contents");
         }
 
-        setTitle( element.getAttribute( "title" ) );
-        setCreationDate( DateConverter.toCalendar( element.getAttribute( "creationdate" ) ) );
-        String opac = element.getAttribute( "opacity" );
-        if( opac != null )
+        PDBorderStyleDictionary borderStyle = new PDBorderStyleDictionary();
+        String width = element.getAttribute("width");
+        if (width != null && !width.isEmpty())
+        {
+            borderStyle.setWidth(Float.parseFloat(width));
+        }
+        if (borderStyle.getWidth() > 0)
         {
-            setOpacity( Float.parseFloat( opac ) );
+            String style = element.getAttribute("style");
+            if (style != null && !style.isEmpty())
+            {
+                if (style.equals("dash"))
+                {
+                    borderStyle.setStyle("D");
+                }
+                else if (style.equals("bevelled"))
+                {
+                    borderStyle.setStyle("B");
+                }
+                else if (style.equals("inset"))
+                {
+                    borderStyle.setStyle("I");
+                }
+                else if (style.equals("underline"))
+                {
+                    borderStyle.setStyle("U");
+                }
+                else if (style.equals("cloudy"))
+                {
+                    borderStyle.setStyle("S");
+                    PDBorderEffectDictionary borderEffect = new PDBorderEffectDictionary();
+                    borderEffect.setStyle("C");
+                    String intensity = element.getAttribute("intensity");
+                    if (intensity != null && !intensity.isEmpty())
+                    {
+                        borderEffect.setIntensity(Float.parseFloat(element
+                                .getAttribute("intensity")));
+                    }
+                    setBorderEffect(borderEffect);
+                }
+                else
+                {
+                    borderStyle.setStyle("S");
+                }
+            }
+            String dashes = element.getAttribute("dashes");
+            if (dashes != null && !dashes.isEmpty())
+            {
+                String[] dashesValues = dashes.split(",");
+                COSArray dashPattern = new COSArray();
+                for (int i = 0; i < dashesValues.length; i++)
+                {
+                    dashPattern.add(COSNumber.get(dashesValues[i]));
+                }
+                borderStyle.setDashStyle(dashPattern);
+            }
+            setBorderStyle(borderStyle);
         }
-        setSubject( element.getAttribute( "subject" ) );
     }
 
     /**
@@ -573,6 +682,26 @@ public abstract class FDFAnnotation impl
     }
 
     /**
+     * Set the contents, or a description, for an annotation.
+     *
+     * @param contents The annotation contents, or a description.
+     */
+    public void setContents(String contents)
+    {
+        annot.setString(COSName.CONTENTS, contents);
+    }
+
+    /**
+     * Get the text, or a description, of the annotation.
+     *
+     * @return The text, or a description, of the annotation.
+     */
+    public String getContents()
+    {
+        return annot.getString(COSName.CONTENTS);
+    }
+
+    /**
      * Set a unique title for an annotation.
      *
      * @param title The annotation title.
@@ -654,4 +783,177 @@ public abstract class FDFAnnotation impl
     {
         return annot.getString( COSName.SUBJ );
     }
+    
+    
+    /**
+     * The intent of the annotation.
+     * 
+     * @param intent The annotation's intent.
+     */
+    public void setIntent(String intent)
+    {
+        annot.setString(COSName.IT, intent);
+    }
+
+    /**
+     * Get the intent of the annotation.
+     * 
+     * @return The intent of the annotation.
+     */
+    public String getIntent()
+    {
+        return annot.getString(COSName.IT);
+    }
+
+    /**
+     * This will retrieve the rich text stream which is displayed in the popup window.
+     *
+     * @return the rich text stream.
+     */
+    public String getRichContents()
+    {
+        return getStringOrStream(annot.getDictionaryObject(COSName.RC));
+    }
+
+    /**
+     * This will set the rich text stream which is displayed in the popup window.
+     *
+     * @param rc the rich text stream.
+     */
+    public void setRichContents(String rc)
+    {
+        annot.setItem(COSName.RC, new COSString(rc));
+    }
+
+    /**
+     * This will set the border style dictionary, specifying the width and dash pattern used in drawing the annotation.
+     *
+     * @param bs the border style dictionary to set.
+     *
+     */
+    public void setBorderStyle(PDBorderStyleDictionary bs)
+    {
+        annot.setItem(COSName.BS, bs);
+    }
+
+    /**
+     * This will retrieve the border style dictionary, specifying the width and dash pattern used in drawing the
+     * annotation.
+     *
+     * @return the border style dictionary.
+     */
+    public PDBorderStyleDictionary getBorderStyle()
+    {
+        COSDictionary bs = (COSDictionary) annot.getDictionaryObject(COSName.BS);
+        if (bs != null)
+        {
+            return new PDBorderStyleDictionary(bs);
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    /**
+     * This will set the border effect dictionary, describing the effect applied to the border described by the BS
+     * entry.
+     *
+     * @param be the border effect dictionary to set.
+     *
+     */
+    public void setBorderEffect(PDBorderEffectDictionary be)
+    {
+        annot.setItem(COSName.BE, be);
+    }
+
+    /**
+     * This will retrieve the border style dictionary, describing the effect applied to the border described by the BS
+     * entry.
+     *
+     * @return the border effect dictionary.
+     */
+    public PDBorderEffectDictionary getBorderEffect()
+    {
+        COSDictionary be = (COSDictionary) annot.getDictionaryObject(COSName.BE);
+        if (be != null)
+        {
+            return new PDBorderEffectDictionary(be);
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    /**
+     * Get a text or text stream.
+     *
+     * Some dictionary entries allow either a text or a text stream.
+     *
+     * @param base the potential text or text stream
+     * @return the text stream
+     */
+    protected final String getStringOrStream(COSBase base)
+    {
+        if (base == null)
+        {
+            return "";
+        }
+        else if (base instanceof COSString)
+        {
+            return ((COSString)base).getString();
+        }
+        else if (base instanceof COSStream)
+        {
+            return ((COSStream)base).getString();
+        }
+        else
+        {
+            return "";
+        }
+    }
+    
+    
+    private String richContentsToString(Node node, boolean root)
+    {
+        String retval = "";
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        try
+        {
+            NodeList nodelist = (NodeList) xpath.evaluate("*", node, XPathConstants.NODESET);
+            String subString = "";
+            if (nodelist.getLength() == 0)
+            {
+                subString = node.getFirstChild().getNodeValue();
+            }
+            for (int i = 0; i < nodelist.getLength(); i++)
+            {
+                Node child = nodelist.item(i);
+                if (child instanceof Element)
+                {
+                    subString += richContentsToString(child, false);
+                }
+            }
+            NamedNodeMap attributes = node.getAttributes();
+            StringBuilder builder = new StringBuilder();
+            for (int i = 0; i < attributes.getLength(); i++)
+            {
+                Node attribute = attributes.item(i);
+                builder.append(String.format(" %s=\"%s\"", attribute.getNodeName(),
+                        attribute.getNodeValue()));
+            }
+            if (root)
+            {
+                return subString;
+            }
+            retval = String.format("<%s%s>%s</%s>", node.getNodeName(), builder.toString(),
+                    subString, node.getNodeName());
+        }
+        catch (XPathExpressionException e)
+        {
+            LOG.debug("Error while evaluating XPath expression for richtext contents");
+        }
+        return retval;
+    }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCaret.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCaret.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCaret.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCaret.java Wed May 20 10:34:07 2015
@@ -18,8 +18,10 @@ package org.apache.pdfbox.pdmodel.fdf;
 
 import java.io.IOException;
 
+import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.w3c.dom.Element;
 
 /**
@@ -56,13 +58,92 @@ public class FDFAnnotationCaret extends
     /**
      * Constructor.
      *
-     *  @param element An XFDF element.
+     * @param element An XFDF element.
      *
-     *  @throws IOException If there is an error extracting information from the element.
+     * @throws IOException If there is an error extracting information from the element.
      */
-    public FDFAnnotationCaret( Element element ) throws IOException
+    public FDFAnnotationCaret(Element element) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+
+        String fringe = element.getAttribute("fringe");
+        if (fringe != null && !fringe.isEmpty())
+        {
+            String[] fringeValues = fringe.split(",");
+            if (fringeValues.length != 4)
+            {
+                throw new IOException("Error: wrong amount of numbers in attribute 'fringe'");
+            }
+            float[] values = new float[4];
+            for (int i = 0; i < 4; i++)
+            {
+                values[i] = Float.parseFloat(fringeValues[i]);
+            }
+            COSArray array = new COSArray();
+            array.setFloatArray(values);
+            setFringe(new PDRectangle(array));
+        }
+
+        String symbol = element.getAttribute("symbol");
+        if (symbol != null && !symbol.isEmpty())
+        {
+            setSymbol(element.getAttribute("symbol"));
+        }
+    }
+
+    /**
+     * This will set the fringe rectangle. Giving the difference between the annotations rectangle and where the drawing
+     * occurs.
+     *
+     * @param fringe the fringe
+     */
+    public void setFringe(PDRectangle fringe)
+    {
+        annot.setItem(COSName.RD, fringe);
+    }
+
+    /**
+     * This will retrieve the fringe. Giving the difference between the annotations rectangle and where the drawing
+     * occurs.
+     *
+     * @return the rectangle difference
+     */
+    public PDRectangle getFringe()
+    {
+        COSArray rd = (COSArray) annot.getDictionaryObject(COSName.RD);
+        if (rd != null)
+        {
+            return new PDRectangle(rd);
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    /**
+     * This will set the symbol that shall be associated with the caret.
+     * 
+     * @param symbol the symbol
+     */
+    public void setSymbol(String symbol)
+    {
+        String newSymbol = "None";
+        if ("paragraph".equals(symbol))
+        {
+            newSymbol = "P";
+        }
+        annot.setString(COSName.SY, newSymbol);
+    }
+    
+    /**
+     * This will retrieve the symbol that shall be associated with the caret.
+     * 
+     * @return the symbol
+     */
+    public String getSymbol()
+    {
+        return annot.getString(COSName.SY);
     }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCircle.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCircle.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCircle.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationCircle.java Wed May 20 10:34:07 2015
@@ -1,6 +1,6 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
+ * contributor license agreements. See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
@@ -16,10 +16,13 @@
  */
 package org.apache.pdfbox.pdmodel.fdf;
 
+import java.awt.Color;
 import java.io.IOException;
 
+import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.w3c.dom.Element;
 
 /**
@@ -62,7 +65,99 @@ public class FDFAnnotationCircle extends
      */
     public FDFAnnotationCircle( Element element ) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+
+        String color = element.getAttribute("interior-color");
+        if (color != null && color.length() == 7 && color.charAt(0) == '#')
+        {
+            int colorValue = Integer.parseInt(color.substring(1, 7), 16);
+            setInteriorColor(new Color(colorValue));
+        }
+
+        String fringe = element.getAttribute("fringe");
+        if (fringe != null && !fringe.isEmpty())
+        {
+            String[] fringeValues = fringe.split(",");
+            if (fringeValues.length != 4)
+            {
+                throw new IOException("Error: wrong amount of numbers in attribute 'fringe'");
+            }
+            float[] values = new float[4];
+            for (int i = 0; i < 4; i++)
+            {
+                values[i] = Float.parseFloat(fringeValues[i]);
+            }
+            COSArray array = new COSArray();
+            array.setFloatArray(values);
+            setFringe(new PDRectangle(array));
+        }
+    }
+    
+    /**
+     * This will set interior color of the drawn area.
+     *
+     * @param color The interior color of the circle.
+     */
+    public void setInteriorColor(Color color)
+    {
+        COSArray array = null;
+        if (color != null)
+        {
+            float[] colors = color.getRGBColorComponents(null);
+            array = new COSArray();
+            array.setFloatArray(colors);
+        }
+        annot.setItem(COSName.IC, array);
+    }
+
+    /**
+     * This will retrieve the interior color of the drawn area.
+     *
+     * @return object representing the color.
+     */
+    public Color getInteriorColor()
+    {
+        Color retval = null;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.IC);
+        if (array != null)
+        {
+            float[] rgb = array.toFloatArray();
+            if (rgb.length >= 3)
+            {
+                retval = new Color(rgb[0], rgb[1], rgb[2]);
+            }
+        }
+        return retval;
+    }
+
+    /**
+     * This will set the fringe rectangle. Giving the difference between the annotations rectangle and where the drawing
+     * occurs. (To take account of any effects applied through the BE entry for example)
+     *
+     * @param fringe the fringe
+     */
+    public void setFringe(PDRectangle fringe)
+    {
+        annot.setItem(COSName.RD, fringe);
+    }
+
+    /**
+     * This will get the fringe. Giving the difference between the annotations rectangle and where the drawing occurs.
+     * (To take account of any effects applied through the BE entry for example)
+     *
+     * @return the rectangle difference
+     */
+    public PDRectangle getFringe()
+    {
+        COSArray rd = (COSArray) annot.getDictionaryObject(COSName.RD);
+        if (rd != null)
+        {
+            return new PDRectangle(rd);
+        }
+        else
+        {
+            return null;
+        }
     }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationFreeText.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationFreeText.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationFreeText.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationFreeText.java Wed May 20 10:34:07 2015
@@ -62,7 +62,64 @@ public class FDFAnnotationFreeText exten
      */
     public FDFAnnotationFreeText( Element element ) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+
+        setJustification(element.getAttribute("justification"));
+        String rotation = element.getAttribute("rotation");
+        if (rotation != null && !rotation.isEmpty())
+        {
+            setRotation(Integer.parseInt(rotation));
+        }
     }
+    
+    /**
+     * This will set the form of quadding (justification) of the annotation text.
+     * 
+     * @param justification The quadding of the text.
+     */
+    public void setJustification(String justification)
+    {
+        int quadding = 0;
+        if ("centered".equals(justification))
+        {
+            quadding = 1;
+        }
+        else if ("right".equals(justification))
+        {
+            quadding = 2;
+        }
+        annot.setInt(COSName.Q, quadding);
+    }
+
+    /**
+     * This will get the form of quadding (justification) of the annotation text.
+     * 
+     * @return The quadding of the text.
+     */
+    public String getJustification()
+    {
+        return "" + annot.getInt(COSName.Q, 0);
+    }
+
+    /**
+     * This will set the clockwise rotation in degrees.
+     * 
+     * @param rotation The number of degrees of clockwise rotation.
+     */
+    public void setRotation(int rotation)
+    {
+        annot.setInt(COSName.ROTATE, rotation);
+    }
+
+    /**
+     * This will get the clockwise rotation in degrees.
+     * 
+     * @return The number of degrees of clockwise rotation.
+     */
+    public String getRotation()
+    {
+        return annot.getString(COSName.ROTATE);
+    }
+
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationHighlight.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationHighlight.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationHighlight.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationHighlight.java Wed May 20 10:34:07 2015
@@ -27,7 +27,7 @@ import org.w3c.dom.Element;
  *
  * @author Ben Litchfield
  */
-public class FDFAnnotationHighlight extends FDFAnnotation
+public class FDFAnnotationHighlight extends FDFAnnotationTextMarkup
 {
     /**
      * COS Model value for SubType entry.

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationInk.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationInk.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationInk.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationInk.java Wed May 20 10:34:07 2015
@@ -17,10 +17,23 @@
 package org.apache.pdfbox.pdmodel.fdf;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * This represents a Ink FDF annotation.
@@ -29,6 +42,7 @@ import org.w3c.dom.Element;
  */
 public class FDFAnnotationInk extends FDFAnnotation
 {
+    private static final Log LOG = LogFactory.getLog(FDFAnnotationInk.class);
     /**
      * COS Model value for SubType entry.
      */
@@ -62,7 +76,83 @@ public class FDFAnnotationInk extends FD
      */
     public FDFAnnotationInk( Element element ) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        try
+        {
+            NodeList gestures = (NodeList) xpath.evaluate("inklist/gesture", element,
+                    XPathConstants.NODESET);
+            if (gestures.getLength() == 0)
+            {
+                throw new IOException("Error: missing element 'gesture'");
+            }
+            List<float[]> inklist = new ArrayList<float[]>();
+            for (int i = 0; i < gestures.getLength(); i++)
+            {
+                Node node = gestures.item(i);
+                if (node instanceof Element)
+                {
+                    String gesture = node.getFirstChild().getNodeValue();
+                    String[] gestureValues = gesture.split(",|;");
+                    float[] values = new float[gestureValues.length];
+                    for (int j = 0; j < gestureValues.length; j++)
+                    {
+                        values[j] = Float.parseFloat(gestureValues[j]);
+                    }
+                    inklist.add(values);
+                }
+            }
+        }
+        catch (XPathExpressionException e)
+        {
+            LOG.debug("Error while evaluating XPath expression for inklist gestures");
+        }
+    }
+    
+    /**
+     * Set the paths making up the freehand "scribble".
+     * 
+     * The ink annotation is made up of one ore more disjoint paths. Each array entry is an array 
+     * representing a stroked path, being a series of alternating horizontal and vertical coordinates
+     * in default user space.
+     * 
+     * @param inklist the List of arrays representing the paths.
+     */
+    public void setInkList(List<float[]> inklist)
+    {
+        COSArray newInklist = new COSArray();
+        for (float[] array : inklist)
+        {
+            COSArray newArray = new COSArray();
+            newArray.setFloatArray(array);
+            newInklist.add(newArray);
+        }
+        annot.setItem(COSName.INKLIST, newInklist);
+    }
+
+    /**
+     * Get the paths making up the freehand "scribble".
+     *
+     * @see #setInkList(List)
+     * @return the List of arrays representing the paths.
+     */
+    public List<float[]> getInkList()
+    {
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.INKLIST);
+        if (array != null)
+        {
+            List<float[]> retval = new ArrayList<float[]>();
+            for (COSBase entry : array)
+            {
+                retval.add(((COSArray) entry).toFloatArray());
+            }
+            return retval;
+        }
+        else
+        {
+            return null; // Should never happen as this is a required item
+        }
     }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationLine.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationLine.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationLine.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationLine.java Wed May 20 10:34:07 2015
@@ -16,16 +16,21 @@
  */
 package org.apache.pdfbox.pdmodel.fdf;
 
+import java.awt.Color;
 import java.io.IOException;
 
+import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSFloat;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLine;
 import org.w3c.dom.Element;
 
 /**
  * This represents a Line FDF annotation.
  *
  * @author Ben Litchfield
+ * @author Johanneke Lamberink
  */
 public class FDFAnnotationLine extends FDFAnnotation
 {
@@ -62,7 +67,414 @@ public class FDFAnnotationLine extends F
      */
     public FDFAnnotationLine( Element element ) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+
+        String startCoords = element.getAttribute("start");
+        if (startCoords == null || !startCoords.isEmpty())
+        {
+            throw new IOException("Error: missing attribute 'start'");
+        }
+        String endCoords = element.getAttribute("end");
+        if (endCoords == null || !endCoords.isEmpty())
+        {
+            throw new IOException("Error: missing attribute 'end'");
+        }
+        String line = startCoords + "," + endCoords;
+        String[] lineValues = line.split(",");
+        if (lineValues.length != 4)
+        {
+            throw new IOException("Error: wrong amount of line coordinates");
+        }
+        float[] values = new float[4];
+        for (int i = 0; i < 4; i++)
+        {
+            values[i] = Float.parseFloat(lineValues[i]);
+        }
+        setLine(values);
+
+        String leaderLine = element.getAttribute("leaderLength");
+        if (leaderLine != null && !leaderLine.isEmpty())
+        {
+            setLeaderLength(Float.parseFloat(leaderLine));
+        }
+
+        String leaderLineExtension = element.getAttribute("leaderExtend");
+        if (leaderLineExtension != null && !leaderLineExtension.isEmpty())
+        {
+            setLeaderExtend(Float.parseFloat(leaderLineExtension));
+        }
+
+        String leaderLineOffset = element.getAttribute("leaderOffset");
+        if (leaderLineOffset != null && !leaderLineOffset.isEmpty())
+        {
+            setLeaderOffset(Float.parseFloat(leaderLineOffset));
+        }
+
+        String startStyle = element.getAttribute("head");
+        if (startStyle != null && !startStyle.isEmpty())
+        {
+            setStartPointEndingStyle(startStyle);
+        }
+        String endStyle = element.getAttribute("tail");
+        if (endStyle != null && !endStyle.isEmpty())
+        {
+            setEndPointEndingStyle(endStyle);
+        }
+
+        String color = element.getAttribute("interior-color");
+        if (color != null && color.length() == 7 && color.charAt(0) == '#')
+        {
+            int colorValue = Integer.parseInt(color.substring(1, 7), 16);
+            setInteriorColor(new Color(colorValue));
+        }
+
+        String caption = element.getAttribute("caption");
+        if (caption != null && !caption.isEmpty())
+        {
+            setCaption("yes".equals(caption));
+        }
+
+        String captionH = element.getAttribute("caption-offset-h");
+        if (captionH != null && !captionH.isEmpty())
+        {
+            setCaptionHorizontalOffset(Float.parseFloat(captionH));
+        }
+
+        String captionV = element.getAttribute("caption-offset-v");
+        if (captionV != null && !captionV.isEmpty())
+        {
+            setCaptionVerticalOffset(Float.parseFloat(captionV));
+        }
+
+        String captionStyle = element.getAttribute("caption-style");
+        if (captionStyle != null && !captionStyle.isEmpty())
+        {
+            setCaptionStyle(captionStyle);
+        }
+    }
+    
+    /**
+     * This will set start and end coordinates of the line (or leader line if LL entry is set).
+     *
+     * @param line array of 4 floats [x1, y1, x2, y2] line start and end points in default user space.
+     */
+    public void setLine(float[] line)
+    {
+        COSArray newLine = new COSArray();
+        newLine.setFloatArray(line);
+        annot.setItem(COSName.L, newLine);
+    }
+
+    /**
+     * This will retrieve the start and end coordinates of the line (or leader line if LL entry is set).
+     *
+     * @return array of floats [x1, y1, x2, y2] line start and end points in default user space.
+     */
+    public float[] getLine()
+    {
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.L);
+        if (array != null)
+        {
+            return array.toFloatArray();
+        }
+        else
+        {
+            return null; // Should never happen as this is a required item
+        }
+    }
+
+    /**
+     * This will set the line ending style for the start point, see the LE_ constants for the possible values.
+     *
+     * @param style The new style.
+     */
+    public void setStartPointEndingStyle(String style)
+    {
+        if (style == null)
+        {
+            style = PDAnnotationLine.LE_NONE;
+        }
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.LE);
+        if (array == null)
+        {
+            array = new COSArray();
+            array.add(COSName.getPDFName(style));
+            array.add(COSName.getPDFName(PDAnnotationLine.LE_NONE));
+            annot.setItem(COSName.LE, array);
+        }
+        else
+        {
+            array.setName(0, style);
+        }
+    }
+
+    /**
+     * This will retrieve the line ending style for the start point, possible values shown in the LE_ constants section.
+     *
+     * @return The ending style for the start point.
+     */
+    public String getStartPointEndingStyle()
+    {
+        String retval = PDAnnotationLine.LE_NONE;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.LE);
+        if (array != null)
+        {
+            retval = array.getName(0);
+        }
+
+        return retval;
+    }
+
+    /**
+     * This will set the line ending style for the end point, see the LE_ constants for the possible values.
+     *
+     * @param style The new style.
+     */
+    public void setEndPointEndingStyle(String style)
+    {
+        if (style == null)
+        {
+            style = PDAnnotationLine.LE_NONE;
+        }
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.LE);
+        if (array == null)
+        {
+            array = new COSArray();
+            array.add(COSName.getPDFName(PDAnnotationLine.LE_NONE));
+            array.add(COSName.getPDFName(style));
+            annot.setItem(COSName.LE, array);
+        }
+        else
+        {
+            array.setName(1, style);
+        }
+    }
+
+    /**
+     * This will retrieve the line ending style for the end point, possible values shown in the LE_ constants section.
+     *
+     * @return The ending style for the end point.
+     */
+    public String getEndPointEndingStyle()
+    {
+        String retval = PDAnnotationLine.LE_NONE;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.LE);
+        if (array != null)
+        {
+            retval = array.getName(1);
+        }
+
+        return retval;
+    }
+
+    /**
+     * This will set interior color of the line endings defined in the LE entry.
+     *
+     * @param color The interior color of the line endings.
+     */
+    public void setInteriorColor(Color color)
+    {
+        COSArray array = null;
+        if (color != null)
+        {
+            float[] colors = color.getRGBColorComponents(null);
+            array = new COSArray();
+            array.setFloatArray(colors);
+        }
+        annot.setItem(COSName.IC, array);
+    }
+
+    /**
+     * This will retrieve the interior color of the line endings defined in the LE entry.
+     *
+     * @return object representing the color.
+     */
+    public Color getInteriorColor()
+    {
+        Color retval = null;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.IC);
+        if (array != null)
+        {
+            float[] rgb = array.toFloatArray();
+            if (rgb.length >= 3)
+            {
+                retval = new Color(rgb[0], rgb[1], rgb[2]);
+            }
+        }
+        return retval;
+    }
+
+    /**
+     * This will set if the contents are shown as a caption to the line.
+     *
+     * @param cap Boolean value.
+     */
+    public void setCaption(boolean cap)
+    {
+        annot.setBoolean(COSName.CAP, cap);
+    }
+
+    /**
+     * This will retrieve if the contents are shown as a caption or not.
+     *
+     * @return boolean if the content is shown as a caption.
+     */
+    public boolean getCaption()
+    {
+        return annot.getBoolean(COSName.CAP, false);
+    }
+
+    /**
+     * This will retrieve the length of the leader line.
+     * 
+     * @return the length of the leader line
+     */
+    public float getLeaderLength()
+    {
+        return annot.getFloat(COSName.LL);
+    }
+
+    /**
+     * This will set the length of the leader line.
+     * 
+     * @param leaderLength length of the leader line
+     */
+    public void setLeaderLength(float leaderLength)
+    {
+        annot.setFloat(COSName.LL, leaderLength);
+    }
+
+    /**
+     * This will retrieve the length of the leader line extensions.
+     * 
+     * @return the length of the leader line extensions
+     */
+    public float getLeaderExtend()
+    {
+        return annot.getFloat(COSName.LLE);
+    }
+
+    /**
+     * This will set the length of the leader line extensions.
+     * 
+     * @param leaderExtend length of the leader line extensions
+     */
+    public void setLeaderExtend(float leaderExtend)
+    {
+        annot.setFloat(COSName.LLE, leaderExtend);
+    }
+
+    /**
+     * This will retrieve the length of the leader line offset.
+     * 
+     * @return the length of the leader line offset
+     */
+    public float getLeaderOffset()
+    {
+        return annot.getFloat(COSName.LLO);
+    }
+
+    /**
+     * This will set the length of the leader line offset.
+     * 
+     * @param leaderOffset length of the leader line offset
+     */
+    public void setLeaderOffset(float leaderOffset)
+    {
+        annot.setFloat(COSName.LLO, leaderOffset);
+    }
+
+    /**
+     * This will retrieve the caption positioning.
+     * 
+     * @return the caption positioning
+     */
+    public String getCaptionStyle()
+    {
+        return annot.getString(COSName.CP);
+    }
+
+    /**
+     * This will set the caption positioning. Allowed values are: "Inline" and "Top"
+     * 
+     * @param captionStyle caption positioning
+     */
+    public void setCaptionStyle(String captionStyle)
+    {
+        annot.setString(COSName.CP, captionStyle);
+    }
+
+    /**
+     * This will set the horizontal offset of the caption.
+     * 
+     * @param offset the horizontal offset of the caption
+     */
+    public void setCaptionHorizontalOffset(float offset)
+    {
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.CO);
+        if (array == null)
+        {
+            array = new COSArray();
+            array.setFloatArray(new float[] { offset, 0.f });
+            annot.setItem(COSName.CO, array);
+        }
+        else
+        {
+            array.set(0, new COSFloat(offset));
+        }
+    }
+
+    /**
+     * This will retrieve the horizontal offset of the caption.
+     * 
+     * @return the horizontal offset of the caption
+     */
+    public float getCaptionHorizontalOffset()
+    {
+        float retval = 0.f;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.CO);
+        if (array != null)
+        {
+            retval = array.toFloatArray()[0];
+        }
+
+        return retval;
+    }
+
+    /**
+     * This will set the vertical offset of the caption.
+     * 
+     * @param offset vertical offset of the caption
+     */
+    public void setCaptionVerticalOffset(float offset)
+    {
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.CO);
+        if (array == null)
+        {
+            array = new COSArray();
+            array.setFloatArray(new float[] { 0.f, offset });
+            annot.setItem(COSName.CO, array);
+        }
+        else
+        {
+            array.set(1, new COSFloat(offset));
+        }
+    }
+
+    /**
+     * This will retrieve the vertical offset of the caption.
+     * 
+     * @return the vertical offset of the caption
+     */
+    public float getCaptionVerticalOffset()
+    {
+        float retval = 0.f;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.CO);
+        if (array != null)
+        {
+            retval = array.toFloatArray()[1];
+        }
+        return retval;
     }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolygon.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolygon.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolygon.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolygon.java Wed May 20 10:34:07 2015
@@ -16,8 +16,16 @@
  */
 package org.apache.pdfbox.pdmodel.fdf;
 
+import java.awt.Color;
 import java.io.IOException;
 
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.w3c.dom.Element;
@@ -26,9 +34,11 @@ import org.w3c.dom.Element;
  * This represents a Polygon FDF annotation.
  *
  * @author Ben Litchfield
+ * @author Johanneke Lamberink
  */
 public class FDFAnnotationPolygon extends FDFAnnotation
 {
+    private static final Log LOG = LogFactory.getLog(FDFAnnotationPolygon.class);
     /**
      * COS Model value for SubType entry.
      */
@@ -62,7 +72,101 @@ public class FDFAnnotationPolygon extend
      */
     public FDFAnnotationPolygon( Element element ) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        try
+        {
+            String vertices = xpath.evaluate("vertices", element);
+            if (vertices == null || !vertices.isEmpty())
+            {
+                throw new IOException("Error: missing element 'vertices'");
+            }
+            String[] verticesValues = vertices.split(",");
+            float[] values = new float[verticesValues.length];
+            for (int i = 0; i < verticesValues.length; i++)
+            {
+                values[i] = Float.parseFloat(verticesValues[i]);
+            }
+            setVertices(values);
+        }
+        catch (XPathExpressionException e)
+        {
+            LOG.debug("Error while evaluating XPath expression for polygon vertices");
+        }
+        String color = element.getAttribute("interior-color");
+        if (color != null && color.length() == 7 && color.charAt(0) == '#')
+        {
+            int colorValue = Integer.parseInt(color.substring(1, 7), 16);
+            setInteriorColor(new Color(colorValue));
+        }
+    }
+    
+    /**
+     * This will set the coordinates of the the vertices.
+     *
+     * @param vertices array of floats [x1, y1, x2, y2, ...] vertex coordinates in default user space.
+     */
+    public void setVertices(float[] vertices)
+    {
+        COSArray newVertices = new COSArray();
+        newVertices.setFloatArray(vertices);
+        annot.setItem(COSName.VERTICES, newVertices);
+    }
+
+    /**
+     * This will get the coordinates of the the vertices.
+     *
+     * @return array of floats [x1, y1, x2, y2, ...] vertex coordinates in default user space.
+     */
+    public float[] getVertices()
+    {
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.VERTICES);
+        if (array != null)
+        {
+            return array.toFloatArray();
+        }
+        else
+        {
+            return null; // Should never happen as this is a required item
+        }
+    }
+
+    /**
+     * This will set interior color of the drawn area.
+     *
+     * @param color The interior color of the drawn area.
+     */
+    public void setInteriorColor(Color color)
+    {
+        COSArray array = null;
+        if (color != null)
+        {
+            float[] colors = color.getRGBColorComponents(null);
+            array = new COSArray();
+            array.setFloatArray(colors);
+        }
+        annot.setItem(COSName.IC, array);
+    }
+
+    /**
+     * This will get interior color of the drawn area.
+     *
+     * @return object representing the color.
+     */
+    public Color getInteriorColor()
+    {
+        Color retval = null;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.IC);
+        if (array != null)
+        {
+            float[] rgb = array.toFloatArray();
+            if (rgb.length >= 3)
+            {
+                retval = new Color(rgb[0], rgb[1], rgb[2]);
+            }
+        }
+        return retval;
     }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolyline.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolyline.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolyline.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationPolyline.java Wed May 20 10:34:07 2015
@@ -16,19 +16,30 @@
  */
 package org.apache.pdfbox.pdmodel.fdf;
 
+import java.awt.Color;
 import java.io.IOException;
 
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLine;
 import org.w3c.dom.Element;
 
 /**
  * This represents a Polyline FDF annotation.
  *
  * @author Ben Litchfield
+ * @author Johanneke Lamberink
  */
 public class FDFAnnotationPolyline extends FDFAnnotation
 {
+    private static final Log LOG = LogFactory.getLog(FDFAnnotationPolyline.class);
     /**
      * COS Model value for SubType entry.
      */
@@ -62,7 +73,197 @@ public class FDFAnnotationPolyline exten
      */
     public FDFAnnotationPolyline( Element element ) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        try
+        {
+            String vertices = xpath.evaluate("vertices[1]", element);
+            if (vertices == null || !vertices.isEmpty())
+            {
+                throw new IOException("Error: missing element 'vertices'");
+            }
+            String[] verticesValues = vertices.split(",");
+            float[] values = new float[verticesValues.length];
+            for (int i = 0; i < verticesValues.length; i++)
+            {
+                values[i] = Float.parseFloat(verticesValues[i]);
+            }
+            setVertices(values);
+        }
+        catch (XPathExpressionException e)
+        {
+            LOG.debug("Error while evaluating XPath expression for polyline vertices");
+        }
+
+        String startStyle = element.getAttribute("head");
+        if (startStyle != null && !startStyle.isEmpty())
+        {
+            setStartPointEndingStyle(startStyle);
+        }
+        String endStyle = element.getAttribute("tail");
+        if (endStyle != null && !endStyle.isEmpty())
+        {
+            setEndPointEndingStyle(endStyle);
+        }
+
+        String color = element.getAttribute("interior-color");
+        if (color != null && color.length() == 7 && color.charAt(0) == '#')
+        {
+            int colorValue = Integer.parseInt(color.substring(1, 7), 16);
+            setInteriorColor(new Color(colorValue));
+        }
+    }
+    
+    /**
+     * This will set the coordinates of the the vertices.
+     *
+     * @param vertices array of floats [x1, y1, x2, y2, ...] vertex coordinates in default user space.
+     */
+    public void setVertices(float[] vertices)
+    {
+        COSArray newVertices = new COSArray();
+        newVertices.setFloatArray(vertices);
+        annot.setItem(COSName.VERTICES, newVertices);
+    }
+
+    /**
+     * This will get the coordinates of the the vertices.
+     *
+     * @return array of floats [x1, y1, x2, y2, ...] vertex coordinates in default user space.
+     */
+    public float[] getVertices()
+    {
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.VERTICES);
+        if (array != null)
+        {
+            return array.toFloatArray();
+        }
+        else
+        {
+            return null; // Should never happen as this is a required item
+        }
+    }
+
+    /**
+     * This will set the line ending style for the start point, see the LE_ constants for the possible values.
+     *
+     * @param style The new style.
+     */
+    public void setStartPointEndingStyle(String style)
+    {
+        if (style == null)
+        {
+            style = PDAnnotationLine.LE_NONE;
+        }
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.LE);
+        if (array == null)
+        {
+            array = new COSArray();
+            array.add(COSName.getPDFName(style));
+            array.add(COSName.getPDFName(PDAnnotationLine.LE_NONE));
+            annot.setItem(COSName.LE, array);
+        }
+        else
+        {
+            array.setName(0, style);
+        }
+    }
+
+    /**
+     * This will retrieve the line ending style for the start point, possible values shown in the LE_ constants section.
+     *
+     * @return The ending style for the start point.
+     */
+    public String getStartPointEndingStyle()
+    {
+        String retval = PDAnnotationLine.LE_NONE;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.LE);
+        if (array != null)
+        {
+            retval = array.getName(0);
+        }
+
+        return retval;
+    }
+
+    /**
+     * This will set the line ending style for the end point, see the LE_ constants for the possible values.
+     *
+     * @param style The new style.
+     */
+    public void setEndPointEndingStyle(String style)
+    {
+        if (style == null)
+        {
+            style = PDAnnotationLine.LE_NONE;
+        }
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.LE);
+        if (array == null)
+        {
+            array = new COSArray();
+            array.add(COSName.getPDFName(PDAnnotationLine.LE_NONE));
+            array.add(COSName.getPDFName(style));
+            annot.setItem(COSName.LE, array);
+        }
+        else
+        {
+            array.setName(1, style);
+        }
+    }
+
+    /**
+     * This will retrieve the line ending style for the end point, possible values shown in the LE_ constants section.
+     *
+     * @return The ending style for the end point.
+     */
+    public String getEndPointEndingStyle()
+    {
+        String retval = PDAnnotationLine.LE_NONE;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.LE);
+        if (array != null)
+        {
+            retval = array.getName(1);
+        }
+
+        return retval;
+    }
+
+    /**
+     * This will set interior color of the line endings defined in the LE entry.
+     *
+     * @param color The interior color of the line endings.
+     */
+    public void setInteriorColor(Color color)
+    {
+        COSArray array = null;
+        if (color != null)
+        {
+            float[] colors = color.getRGBColorComponents(null);
+            array = new COSArray();
+            array.setFloatArray(colors);
+        }
+        annot.setItem(COSName.IC, array);
+    }
+
+    /**
+     * This will retrieve the interior color of the line endings defined in the LE entry.
+     *
+     * @return object representing the color.
+     */
+    public Color getInteriorColor()
+    {
+        Color retval = null;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.IC);
+        if (array != null)
+        {
+            float[] rgb = array.toFloatArray();
+            if (rgb.length >= 3)
+            {
+                retval = new Color(rgb[0], rgb[1], rgb[2]);
+            }
+        }
+        return retval;
     }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquare.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquare.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquare.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquare.java Wed May 20 10:34:07 2015
@@ -16,16 +16,20 @@
  */
 package org.apache.pdfbox.pdmodel.fdf;
 
+import java.awt.Color;
 import java.io.IOException;
 
+import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.w3c.dom.Element;
 
 /**
  * This represents a Square FDF annotation.
  *
  * @author Ben Litchfield
+ * @author Johanneke Lamberink
  */
 public class FDFAnnotationSquare extends FDFAnnotation
 {
@@ -62,7 +66,99 @@ public class FDFAnnotationSquare extends
      */
     public FDFAnnotationSquare( Element element ) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+
+        String color = element.getAttribute("interior-color");
+        if (color != null && color.length() == 7 && color.charAt(0) == '#')
+        {
+            int colorValue = Integer.parseInt(color.substring(1, 7), 16);
+            setInteriorColor(new Color(colorValue));
+        }
+
+        String fringe = element.getAttribute("fringe");
+        if (fringe != null && !fringe.isEmpty())
+        {
+            String[] fringeValues = fringe.split(",");
+            if (fringeValues.length != 4)
+            {
+                throw new IOException("Error: wrong amount of numbers in attribute 'fringe'");
+            }
+            float[] values = new float[4];
+            for (int i = 0; i < 4; i++)
+            {
+                values[i] = Float.parseFloat(fringeValues[i]);
+            }
+            COSArray array = new COSArray();
+            array.setFloatArray(values);
+            setFringe(new PDRectangle(array));
+        }
+    }
+    
+    /**
+     * This will set interior color of the drawn area.
+     *
+     * @param color The interior color of the circle.
+     */
+    public void setInteriorColor(Color color)
+    {
+        COSArray array = null;
+        if (color != null)
+        {
+            float[] colors = color.getRGBColorComponents(null);
+            array = new COSArray();
+            array.setFloatArray(colors);
+        }
+        annot.setItem(COSName.IC, array);
+    }
+
+    /**
+     * This will retrieve the interior color of the drawn area.
+     *
+     * @return object representing the color.
+     */
+    public Color getInteriorColor()
+    {
+        Color retval = null;
+        COSArray array = (COSArray) annot.getDictionaryObject(COSName.IC);
+        if (array != null)
+        {
+            float[] rgb = array.toFloatArray();
+            if (rgb.length >= 3)
+            {
+                retval = new Color(rgb[0], rgb[1], rgb[2]);
+            }
+        }
+        return retval;
+    }
+
+    /**
+     * This will set the fringe rectangle. Giving the difference between the annotations rectangle and where the drawing
+     * occurs. (To take account of any effects applied through the BE entry for example)
+     *
+     * @param fringe the fringe
+     */
+    public void setFringe(PDRectangle fringe)
+    {
+        annot.setItem(COSName.RD, fringe);
+    }
+
+    /**
+     * This will get the fringe. Giving the difference between the annotations rectangle and where the drawing occurs.
+     * (To take account of any effects applied through the BE entry for example)
+     *
+     * @return the rectangle difference
+     */
+    public PDRectangle getFringe()
+    {
+        COSArray rd = (COSArray) annot.getDictionaryObject(COSName.RD);
+        if (rd != null)
+        {
+            return new PDRectangle(rd);
+        }
+        else
+        {
+            return null;
+        }
     }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquiggly.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquiggly.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquiggly.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationSquiggly.java Wed May 20 10:34:07 2015
@@ -27,7 +27,7 @@ import org.w3c.dom.Element;
  *
  * @author Ben Litchfield
  */
-public class FDFAnnotationSquiggly extends FDFAnnotation
+public class FDFAnnotationSquiggly extends FDFAnnotationTextMarkup
 {
     /**
      * COS Model value for SubType entry.

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStrikeOut.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStrikeOut.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStrikeOut.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStrikeOut.java Wed May 20 10:34:07 2015
@@ -27,7 +27,7 @@ import org.w3c.dom.Element;
  *
  * @author Ben Litchfield
  */
-public class FDFAnnotationStrikeOut extends FDFAnnotation
+public class FDFAnnotationStrikeOut extends FDFAnnotationTextMarkup
 {
     /**
      * COS Model value for SubType entry.

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationText.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationText.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationText.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationText.java Wed May 20 10:34:07 2015
@@ -20,12 +20,14 @@ import java.io.IOException;
 
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationText;
 import org.w3c.dom.Element;
 
 /**
  * This represents a Text FDF annotation.
  *
  * @author Ben Litchfield
+ * @author Johanneke Lamberink
  */
 public class FDFAnnotationText extends FDFAnnotation
 {
@@ -62,7 +64,84 @@ public class FDFAnnotationText extends F
      */
     public FDFAnnotationText( Element element ) throws IOException
     {
-        super( element );
-        annot.setName( COSName.SUBTYPE, SUBTYPE );
+        super(element);
+        annot.setName(COSName.SUBTYPE, SUBTYPE);
+        String icon = element.getAttribute("icon");
+        if (icon != null && !icon.isEmpty())
+        {
+            setIcon(element.getAttribute("icon"));
+        }
+        String state = element.getAttribute("state");
+        if (state != null && !state.isEmpty())
+        {
+            String statemodel = element.getAttribute("statemodel");
+            if (statemodel != null && !statemodel.isEmpty())
+            {
+                setState(element.getAttribute("state"));
+                setStateModel(element.getAttribute("statemodel"));
+            }
+        }
+    }
+    
+    /**
+     * This will set the icon (and hence appearance, AP taking precedence) For this annotation. See the
+     * PDAnnotationText.NAME_XXX constants for valid values.
+     *
+     * @param icon The name of the annotation
+     */
+    public void setIcon(String icon)
+    {
+        annot.setName(COSName.NAME, icon);
+    }
+
+    /**
+     * This will retrieve the icon (and hence appearance, AP taking precedence) For this annotation. The default is
+     * NOTE.
+     *
+     * @return The name of this annotation, see the PDAnnotationText.NAME_XXX constants.
+     */
+    public String getIcon()
+    {
+        return annot.getNameAsString(COSName.NAME, PDAnnotationText.NAME_NOTE);
+    }
+
+    /**
+     * This will retrieve the annotation state.
+     * 
+     * @return the annotation state
+     */
+    public String getState()
+    {
+        return annot.getString(COSName.STATE);
+    }
+
+    /**
+     * This will set the annotation state.
+     * 
+     * @param state the annotation state
+     */
+    public void setState(String state)
+    {
+        annot.setString(COSName.STATE, state);
+    }
+
+    /**
+     * This will retrieve the annotation state model.
+     * 
+     * @return the annotation state model
+     */
+    public String getStateModel()
+    {
+        return annot.getString(COSName.STATE_MODEL);
+    }
+
+    /**
+     * This will set the annotation state model. Allowed values are "Marked" and "Review"
+     * 
+     * @param stateModel the annotation state model
+     */
+    public void setStateModel(String stateModel)
+    {
+        annot.setString(COSName.STATE_MODEL, stateModel);
     }
 }

Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationTextMarkup.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationTextMarkup.java?rev=1680516&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationTextMarkup.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationTextMarkup.java Wed May 20 10:34:07 2015
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.pdmodel.fdf;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.w3c.dom.Element;
+
+/**
+ * This abstract class is used as a superclass for the different FDF annotations with text markup attributes.
+ * 
+ * @author Johanneke Lamberink
+ */
+public abstract class FDFAnnotationTextMarkup extends FDFAnnotation
+{
+    /**
+     * Default constructor.
+     */
+    public FDFAnnotationTextMarkup()
+    {
+        super();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param a An existing FDF Annotation.
+     */
+    public FDFAnnotationTextMarkup(COSDictionary a)
+    {
+        super(a);
+    }
+
+    /**
+     * Constructor.
+     *
+     *  @param element An XFDF element.
+     *
+     *  @throws IOException If there is an error extracting information from the element.
+     */
+    public FDFAnnotationTextMarkup(Element element) throws IOException
+    {
+        super(element);
+
+        String coords = element.getAttribute("coords");
+        if (coords == null || !coords.isEmpty())
+        {
+            throw new IOException("Error: missing attribute 'coords'");
+        }
+        String[] coordsValues = coords.split(",");
+        if (coordsValues.length < 8)
+        {
+            throw new IOException("Error: too little numbers in attribute 'coords'");
+        }
+        float[] values = new float[coordsValues.length];
+        for (int i = 0; i < coordsValues.length; i++)
+        {
+            values[i] = Float.parseFloat(coordsValues[i]);
+        }
+        setCoords(values);
+    }
+
+    
+    /**
+     * Set the coordinates of individual words or group of words.
+     * 
+     * The quadliterals shall encompasses a word or group of contiguous words in the text underlying the annotation.
+     * The coordinates for each quadrilateral shall be given in the order x1 y1 x2 y2 x3 y3 x4 y4.
+     *
+     * @param coords an array of 8 􏰍 n numbers specifying the coordinates of n quadrilaterals.
+     */
+    public void setCoords(float[] coords)
+    {
+        COSArray newQuadPoints = new COSArray();
+        newQuadPoints.setFloatArray(coords);
+        annot.setItem(COSName.QUADPOINTS, newQuadPoints);
+    }
+
+    /**
+     * Get the coordinates of individual words or group of words.
+     * @see #setCoords(float[])
+     * @return the array of 8 􏰍 n numbers specifying the coordinates of n quadrilaterals.
+     */
+    public float[] getCoords()
+    {
+        COSArray quadPoints = (COSArray) annot.getItem(COSName.QUADPOINTS);
+        if (quadPoints != null)
+        {
+            return quadPoints.toFloatArray();
+        }
+        else
+        {
+            return null; // Should never happen as this is a required item
+        }
+    }
+
+}

Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationTextMarkup.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationTextMarkup.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationUnderline.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationUnderline.java?rev=1680516&r1=1680515&r2=1680516&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationUnderline.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationUnderline.java Wed May 20 10:34:07 2015
@@ -27,7 +27,7 @@ import org.w3c.dom.Element;
  *
  * @author Ben Litchfield
  */
-public class FDFAnnotationUnderline extends FDFAnnotation
+public class FDFAnnotationUnderline extends FDFAnnotationTextMarkup
 {
     /**
      * COS Model value for SubType entry.