[poppler] 6 commits - glib/poppler-page.cc poppler/Annot.cc poppler/Annot.h poppler/Form.cc poppler/Gfx.cc poppler/Gfx.h

Albert Astals Cid aacid at kemper.freedesktop.org
Thu Dec 13 15:13:42 PST 2007


 glib/poppler-page.cc |   11 
 poppler/Annot.cc     | 1003 ++++++++++++++++++++++++++++++++++++++-------------
 poppler/Annot.h      |  311 ++++++++++++++-
 poppler/Form.cc      |    6 
 poppler/Gfx.cc       |   21 -
 poppler/Gfx.h        |    5 
 6 files changed, 1077 insertions(+), 280 deletions(-)

New commits:
commit 0fb42a2f557d5ec83b42326eb6b0be41622ca328
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Wed Dec 12 01:02:31 2007 +0100

    Changed getters to const
    
    Signed-off-by: Iñigo Martínez <inigomartinez at gmail.com>

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 3d1a7eb..70b8409 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -124,7 +124,7 @@ AnnotBorderArray::AnnotBorderArray(Array *array) {
 
     // TODO: check not all zero ? (Line Dash Pattern Page 217 PDF 8.1)
     if(arrayLength > 3) {
-      bool correct = true;
+      GBool correct = gTrue;
       int tempLength = array->getLength() - 3;
       double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
 
@@ -134,10 +134,10 @@ AnnotBorderArray::AnnotBorderArray(Array *array) {
           tempDash[i] = obj1.getNum();
 
           if (tempDash[i] < 0)
-            correct = false;
+            correct = gFalse;
 
         } else {
-          correct = false;
+          correct = gFalse;
         }
         obj1.free();
       }
@@ -147,7 +147,7 @@ AnnotBorderArray::AnnotBorderArray(Array *array) {
         dash = tempDash;
         style = borderDashed;
       } else {
-        delete tempDash;
+        gfree (tempDash);
       }
     }
   }
@@ -202,7 +202,7 @@ AnnotBorderBS::AnnotBorderBS(Dict *dict) {
 
   // TODO: check not all zero (Line Dash Pattern Page 217 PDF 8.1)
   if (dict->lookup("D", &obj1)->isArray()) {
-    bool correct = true;
+    GBool correct = gTrue;
     int tempLength = obj1.arrayGetLength();
     double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
 
@@ -213,9 +213,9 @@ AnnotBorderBS::AnnotBorderBS(Dict *dict) {
         tempDash[i] = obj2.getNum();
 
         if(tempDash[i] < 0)
-          correct = false;
+          correct = gFalse;
       } else {
-        correct = false;
+        correct = gFalse;
       }
       obj2.free();
     }
@@ -225,7 +225,7 @@ AnnotBorderBS::AnnotBorderBS(Dict *dict) {
       dash = tempDash;
       style = borderDashed;
     } else {
-      delete tempDash;
+      gfree (tempDash);
     }
 
   } else {
@@ -267,11 +267,11 @@ AnnotColor::AnnotColor(Array *array) {
   }
 }
 
-AnnotColor::AnnotColorSpace AnnotColor::getSpace() {
+AnnotColor::AnnotColorSpace AnnotColor::getSpace() const {
   return (AnnotColor::AnnotColorSpace) length;
 }
 
-double AnnotColor::getValue(int i) {
+double AnnotColor::getValue(int i) const {
   if(i >= 0 && i < length) 
     return values[i];
   return 0;
@@ -310,10 +310,10 @@ AnnotBorderStyle::~AnnotBorderStyle() {
 
 Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog* catalog, Object *obj) {
   if (obj->isRef()) {
-    hasRef = true;
+    hasRef = gTrue;
     ref = obj->getRef();
   } else {
-    hasRef = false;
+    hasRef = gFalse;
   }
   flags = flagUnknown;
   type = typeUnknown;
@@ -1848,7 +1848,7 @@ AnnotText::AnnotText(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog,
   initialize (xrefA, catalog, dict);
 }
 
-void AnnotText::setModified(GooString* date) {
+void AnnotText::setModified(GooString *date) {
   if(date) {
     delete modified;
     modified = new GooString(date);
@@ -1912,7 +1912,7 @@ void AnnotText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
       } else {
         state = stateUnknown;
       }
-      
+
       delete stateName;
     } else {
       state = stateUnknown;
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 09faec3..a08ff96 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -43,10 +43,10 @@ public:
 
   virtual ~AnnotBorder();
 
-  virtual double getWidth() { return width; }
-  virtual int getDashLength() { return dashLength; }
-  virtual double *getDash() { return dash; }
-  virtual AnnotBorderStyle getStyle() { return style; }
+  virtual double getWidth() const { return width; }
+  virtual int getDashLength() const { return dashLength; }
+  virtual double *getDash() const { return dash; }
+  virtual AnnotBorderStyle getStyle() const { return style; }
 
 protected:
   double width;
@@ -64,8 +64,8 @@ public:
   AnnotBorderArray();
   AnnotBorderArray(Array *array);
 
-  virtual double getHorizontalCorner() { return horizontalCorner; }
-  virtual double getVerticalCorner() { return verticalCorner; }
+  virtual double getHorizontalCorner() const { return horizontalCorner; }
+  virtual double getVerticalCorner() const { return verticalCorner; }
 
 protected:
   static const int DASH_LIMIT = 10; // implementation note 82 in Appendix H.
@@ -108,8 +108,8 @@ public:
   AnnotColor(Array *array);
   ~AnnotColor();
 
-  AnnotColorSpace getSpace();
-  double getValue(int i);
+  AnnotColorSpace getSpace() const;
+  double getValue(int i) const;
 
 private:
 
@@ -222,19 +222,19 @@ public:
   double getFontSize() { return fontSize; }
 
   // getters
-  AnnotSubtype getType() { return type; }
-  PDFRectangle *getRect() { return rect; }
-  GooString *getContents() { return contents; }
-  Dict *getPageDict() { return pageDict; }
-  GooString *getName() { return name; }
-  GooString *getModified() { return modified; }
-  Guint getFlags() { return flags; }
-  /*Dict *getAppearDict() { return appearDict; }*/
-  GooString *getAppearState() { return appearState; }
-  AnnotBorder *getBorder() { return border; }
-  AnnotColor *getColor() { return color; }
-  int getTreeKey() { return treeKey; }
-  Dict *getOptionalContent() { return optionalContent; }
+  AnnotSubtype getType() const { return type; }
+  PDFRectangle *getRect() const { return rect; }
+  GooString *getContents() const { return contents; }
+  Dict *getPageDict() const { return pageDict; }
+  GooString *getName() const { return name; }
+  GooString *getModified() const { return modified; }
+  Guint getFlags() const { return flags; }
+  /*Dict *getAppearDict() const { return appearDict; }*/
+  GooString *getAppearState() const { return appearState; }
+  AnnotBorder *getBorder() const { return border; }
+  AnnotColor *getColor() const { return color; }
+  int getTreeKey() const { return treeKey; }
+  Dict *getOptionalContent() const { return optionalContent; }
 
 private:
   void setColor(Array *a, GBool fill, int adjust);
@@ -298,14 +298,14 @@ public:
   AnnotPopup(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
   virtual ~AnnotPopup();
 
-  Dict *getParent() { return parent; }
-  bool getOpen() { return open; }
+  Dict *getParent() const { return parent; }
+  GBool getOpen() const { return open; }
 
 protected:
   void initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
 
   Dict *parent; // Parent
-  bool open;    // Open
+  GBool open;   // Open
 };
 
 //------------------------------------------------------------------------
@@ -323,15 +323,15 @@ public:
   virtual ~AnnotMarkup();
 
   // getters
-  GooString *getLabel() { return label; }
-  AnnotPopup *getPopup() { return popup; }
-  double getOpacity() { return opacity; }
+  GooString *getLabel() const { return label; }
+  AnnotPopup *getPopup() const { return popup; }
+  double getOpacity() const { return opacity; }
   // getRC
-  GooString *getDate() { return date; }
-  Dict *getInReplyTo() { return inReplyTo; }
-  GooString *getSubject() { return subject; }
-  AnnotMarkupReplyType getReplyTo() { return replyTo; }
-  AnnotExternalDataType getExData() { return exData; }
+  GooString *getDate() const { return date; }
+  Dict *getInReplyTo() const { return inReplyTo; }
+  GooString *getSubject() const { return subject; }
+  AnnotMarkupReplyType getReplyTo() const { return replyTo; }
+  AnnotExternalDataType getExData() const { return exData; }
 
 protected:
   GooString *label;             // T            (Default autor)
@@ -383,9 +383,9 @@ public:
   AnnotText(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
 
   // getters
-  bool getOpen() { return open; }
-  AnnotTextIcon getIcon() { return icon; }
-  AnnotTextState getState() { return state; }
+  GBool getOpen() const { return open; }
+  AnnotTextIcon getIcon() const { return icon; }
+  AnnotTextState getState() const { return state; }
 
   // setters
   void setModified(GooString *date);
@@ -394,7 +394,7 @@ private:
 
   void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
 
-  bool open;                        // Open       (Default false)
+  GBool open;                       // Open       (Default false)
   AnnotTextIcon icon;               // Name       (Default Note)
   AnnotTextState state;             // State      (Default Umarked if
                                     //             StateModel Marked
commit 29d39a8ae120e6045a16a7aa0944c36560b42508
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Mon Dec 10 17:56:44 2007 +0100

    AnnotText support.
    
    Signed-off-by: Iñigo Martínez <inigomartinez at gmail.com>

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 96dc8fe..3d1a7eb 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -1837,6 +1837,127 @@ void AnnotMarkup::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *c
 }
 
 //------------------------------------------------------------------------
+// AnnotText
+//------------------------------------------------------------------------
+
+AnnotText::AnnotText(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj) :
+    Annot(xrefA, acroForm, dict, catalog, obj), AnnotMarkup(xref, acroForm, dict, catalog, obj) {
+
+  type = typeText;
+  flags |= flagNoZoom & flagNoRotate;
+  initialize (xrefA, catalog, dict);
+}
+
+void AnnotText::setModified(GooString* date) {
+  if(date) {
+    delete modified;
+    modified = new GooString(date);
+  }
+}
+
+void AnnotText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
+  Object obj1;
+
+  if (dict->lookup("Open", &obj1)->isBool())
+    open = obj1.getBool();
+  else
+    open = gFalse;
+  obj1.free();
+
+  if (dict->lookup("Name", &obj1)->isName()) {
+    GooString *iconName = new GooString(obj1.getName());
+
+    if(!iconName->cmp("Comment")) {
+      icon = iconComment;
+    } else if(!iconName->cmp("Key")) {
+      icon = iconKey;
+    } else if(!iconName->cmp("Help")) {
+      icon = iconHelp;
+    } else if(!iconName->cmp("NewParagraph")) {
+      icon = iconNewParagraph;
+    } else if(!iconName->cmp("Paragraph")) {
+      icon = iconParagraph;
+    } else if(!iconName->cmp("Insert")) {
+      icon = iconInsert;
+    } else {
+      icon = iconNote;
+    }
+    delete iconName;
+  } else {
+    icon = iconNote;
+  }
+  obj1.free();
+
+  if (dict->lookup("StateModel", &obj1)->isString()) {
+    Object obj2;
+    GooString *modelName = obj1.getString();
+
+    if (dict->lookup("State", &obj2)->isString()) {
+      GooString *stateName = obj2.getString();
+
+      if(!stateName->cmp("Marked")) {
+        state = stateMarked;
+      } else if(!stateName->cmp("Unmarked")) {
+        state = stateUnmarked;
+      } else if(!stateName->cmp("Accepted")) {
+        state = stateAccepted;
+      } else if(!stateName->cmp("Rejected")) {
+        state = stateRejected;
+      } else if(!stateName->cmp("Cancelled")) {
+        state = stateCancelled;
+      } else if(!stateName->cmp("Completed")) {
+        state = stateCompleted;
+      } else if(!stateName->cmp("None")) {
+        state = stateNone;
+      } else {
+        state = stateUnknown;
+      }
+      
+      delete stateName;
+    } else {
+      state = stateUnknown;
+    }
+    obj2.free();
+
+    if(!modelName->cmp("Marked")) {
+      switch (state) {
+        case stateUnknown:
+          state = stateMarked;
+          break;
+        case stateAccepted:
+        case stateRejected:
+        case stateCancelled:
+        case stateCompleted:
+        case stateNone:
+          state = stateUnknown;
+          break;
+        default:
+          break;
+      }
+    } else if(!modelName->cmp("Review")) {
+      switch (state) {
+        case stateUnknown:
+          state = stateNone;
+          break;
+        case stateMarked:
+        case stateUnmarked:
+          state = stateUnknown;
+          break;
+        default:
+          break;
+      }
+    } else {
+      state = stateUnknown;
+    }
+
+    delete modelName;
+  } else {
+    state = stateUnknown;
+  }
+  obj1.free();
+}
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
@@ -1886,7 +2007,7 @@ Annot *Annots::createAnnot(XRef *xref, Dict *acroForm, Dict* dict, Catalog *cata
     GooString *typeName = new GooString(obj1.getName());
 
     if (!typeName->cmp("Text")) {
-      annot = new Annot(xref, acroForm, dict, catalog, obj);
+      annot = new AnnotText(xref, acroForm, dict, catalog, obj);
     } else if(!typeName->cmp("Link")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
     } else if(!typeName->cmp("FreeText")) {
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 18416c5..09faec3 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -40,7 +40,7 @@ public:
     borderInset,      // Inset
     borderUnderlined, // Underlined
   };
-	  
+
   virtual ~AnnotBorder();
 
   virtual double getWidth() { return width; }
@@ -80,7 +80,7 @@ protected:
 
 class AnnotBorderBS: public AnnotBorder {
 public:
-  
+
   AnnotBorderBS();
   AnnotBorderBS(Dict *dict);
 
@@ -103,7 +103,7 @@ public:
     colorRGB         = 3,
     colorCMYK        = 4
   };
-  
+
   AnnotColor();
   AnnotColor(Array *array);
   ~AnnotColor();
@@ -285,7 +285,7 @@ protected:
   GBool ok;
   GBool regen, isTextField;
   GBool isMultiline, isListbox;
-  
+
   bool hasRef;
 };
 
@@ -295,7 +295,6 @@ protected:
 
 class AnnotPopup: public Annot {
 public:
-
   AnnotPopup(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
   virtual ~AnnotPopup();
 
@@ -303,9 +302,8 @@ public:
   bool getOpen() { return open; }
 
 protected:
-
   void initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
-  
+
   Dict *parent; // Parent
   bool open;    // Open
 };
@@ -336,7 +334,6 @@ public:
   AnnotExternalDataType getExData() { return exData; }
 
 protected:
-
   GooString *label;             // T            (Default autor)
   AnnotPopup *popup;            // Popup
   double opacity;               // CA           (Default 1.0)
@@ -351,11 +348,60 @@ protected:
   AnnotExternalDataType exData; // ExData
 
 private:
-
   void initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
 };
 
 //------------------------------------------------------------------------
+// AnnotText
+//------------------------------------------------------------------------
+
+class AnnotText: public Annot, public AnnotMarkup {
+public:
+  enum AnnotTextIcon {
+    iconComment,      // Comment
+    iconKey,          // Key
+    iconNote,         // Note
+    iconHelp,         // Help
+    iconNewParagraph, // NewParagraph
+    iconParagraph,    // Paragraph
+    iconInsert        // Insert
+  };
+
+  enum AnnotTextState {
+    stateUnknown,
+    // Marked state model
+    stateMarked,    // Marked
+    stateUnmarked,  // Unmarked
+    // Review state model
+    stateAccepted,  // Accepted
+    stateRejected,  // Rejected
+    stateCancelled, // Cancelled
+    stateCompleted, // Completed
+    stateNone       // None
+  };
+
+  AnnotText(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+
+  // getters
+  bool getOpen() { return open; }
+  AnnotTextIcon getIcon() { return icon; }
+  AnnotTextState getState() { return state; }
+
+  // setters
+  void setModified(GooString *date);
+
+private:
+
+  void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
+
+  bool open;                        // Open       (Default false)
+  AnnotTextIcon icon;               // Name       (Default Note)
+  AnnotTextState state;             // State      (Default Umarked if
+                                    //             StateModel Marked
+                                    //             None if StareModel Review)
+};
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
@@ -375,7 +421,6 @@ public:
   // to a form field.
   void generateAppearances(Dict *acroForm);
 
-
 private:
   Annot* createAnnot(XRef *xref, Dict *acroForm, Dict* dict, Catalog *catalog, Object *obj);
   void scanFieldAppearances(Dict *node, Ref *ref, Dict *parent,
commit 2acecde458122bd67487cc302478befa78bf6fbe
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Mon Dec 10 16:45:46 2007 +0100

    AnnotMarkup support.
    
    Signed-off-by: Iñigo Martínez <inigomartinez at gmail.com>

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 7ba7510..96dc8fe 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -60,6 +60,27 @@
 // = (4 * (sqrt(2) - 1) / 3) * r
 #define bezierCircle 0.55228475
 
+AnnotExternalDataType parseAnnotExternalData(Dict* dict) {
+  Object obj1;
+  AnnotExternalDataType type;
+
+  if (dict->lookup("Subtype", &obj1)->isName()) {
+    GooString *typeName = new GooString(obj1.getName());
+
+    if(!typeName->cmp("Markup3D")) {
+      type = annotExternalDataMarkup3D;
+    } else {
+      type = annotExternalDataMarkupUnknown;
+    }
+    delete typeName;
+  } else {
+    type = annotExternalDataMarkupUnknown;
+  }
+  obj1.free();
+
+  return type;
+}
+
 //------------------------------------------------------------------------
 // AnnotBorder
 //------------------------------------------------------------------------
@@ -1722,6 +1743,100 @@ void AnnotPopup::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *ca
 }
 
 //------------------------------------------------------------------------
+// AnnotMarkup
+//------------------------------------------------------------------------
+ 
+AnnotMarkup::AnnotMarkup(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj) {
+  initialize(xrefA, acroForm, dict, catalog, obj);
+}
+
+AnnotMarkup::~AnnotMarkup() {
+  if (label)
+    delete label;
+
+  if (popup)
+    delete popup;
+
+  if (date)
+    delete date;
+
+  if (inReplyTo)
+    delete inReplyTo;
+
+  if (subject)
+    delete subject;
+}
+
+void AnnotMarkup::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj) {
+  Object obj1;
+
+  if (dict->lookup("T", &obj1)->isString()) {
+    label = obj1.getString()->copy();
+  } else {
+    label = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("Popup", &obj1)->isDict()) {
+    popup = new AnnotPopup(xrefA, acroForm, obj1.getDict(), catalog, obj);
+  } else {
+    popup = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("CA", &obj1)->isNum()) {
+    opacity = obj1.getNum();
+  } else {
+    opacity = 1.0;
+  }
+  obj1.free();
+
+  if (dict->lookup("CreationDate", &obj1)->isString()) {
+    date = obj1.getString()->copy();
+  } else {
+    date = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("IRT", &obj1)->isDict()) {
+    inReplyTo = obj1.getDict();
+  } else {
+    inReplyTo = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("Subj", &obj1)->isString()) {
+    subject = obj1.getString()->copy();
+  } else {
+    subject = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("RT", &obj1)->isName()) {
+    GooString *replyName = new GooString(obj1.getName());
+
+    if(!replyName->cmp("R")) {
+      replyTo = replyTypeR;
+    } else if(!replyName->cmp("Group")) {
+      replyTo = replyTypeGroup;
+    } else {
+      replyTo = replyTypeR;
+    }
+    delete replyName;
+  } else {
+    replyTo = replyTypeR;
+  }
+  obj1.free();
+
+  if (dict->lookup("ExData", &obj1)->isDict()) {
+    exData = parseAnnotExternalData(obj1.getDict());
+  } else {
+    exData = annotExternalDataMarkupUnknown;
+  }
+  obj1.free();
+}
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 26611d2..18416c5 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -22,6 +22,11 @@ class GfxFontDict;
 class FormWidget;
 class PDFRectangle;
 
+enum AnnotExternalDataType {
+  annotExternalDataMarkupUnknown,
+  annotExternalDataMarkup3D       // Markup3D
+};
+
 //------------------------------------------------------------------------
 // AnnotBorder
 //------------------------------------------------------------------------
@@ -252,6 +257,7 @@ private:
 
   void initialize (XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
 
+protected:
   // required data
   AnnotSubtype type;                // Annotation type
   PDFRectangle *rect;               // Rect
@@ -305,6 +311,51 @@ protected:
 };
 
 //------------------------------------------------------------------------
+// AnnotMarkup
+//------------------------------------------------------------------------
+
+class AnnotMarkup {
+public:
+  enum  AnnotMarkupReplyType {
+    replyTypeR,     // R
+    replyTypeGroup  // Group
+  };
+
+  AnnotMarkup(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+  virtual ~AnnotMarkup();
+
+  // getters
+  GooString *getLabel() { return label; }
+  AnnotPopup *getPopup() { return popup; }
+  double getOpacity() { return opacity; }
+  // getRC
+  GooString *getDate() { return date; }
+  Dict *getInReplyTo() { return inReplyTo; }
+  GooString *getSubject() { return subject; }
+  AnnotMarkupReplyType getReplyTo() { return replyTo; }
+  AnnotExternalDataType getExData() { return exData; }
+
+protected:
+
+  GooString *label;             // T            (Default autor)
+  AnnotPopup *popup;            // Popup
+  double opacity;               // CA           (Default 1.0)
+  // RC
+  GooString *date;              // CreationDate
+  Dict *inReplyTo;              // IRT
+  GooString *subject;           // Subj
+  AnnotMarkupReplyType replyTo; // RT           (Default R)
+  // this object is overrided by the custom intent fields defined in some
+  // annotation types.
+  //GooString *intent;          // IT
+  AnnotExternalDataType exData; // ExData
+
+private:
+
+  void initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+};
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
commit 1f8c1fe34e04688d2ba200f1166cfdd1ffe563f0
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Mon Dec 10 16:34:01 2007 +0100

    AnnotPopup support.
    
    Signed-off-by: Iñigo Martínez <inigomartinez at gmail.com>

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 48f3248..7ba7510 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -1686,6 +1686,40 @@ void Annot::draw(Gfx *gfx, GBool printing) {
   obj.free();
 }
 
+//------------------------------------------------------------------------
+// AnnotPopup
+//------------------------------------------------------------------------
+
+AnnotPopup::AnnotPopup(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj) :
+    Annot(xrefA, acroForm, dict, catalog, obj) {
+  type = typePopup;
+  initialize(xrefA, acroForm, dict, catalog);
+}
+
+AnnotPopup::~AnnotPopup() {
+  /*
+  if (parent)
+    delete parent;
+  */
+}
+
+void AnnotPopup::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog) {
+  Object obj1;
+  /*
+  if(dict->lookup("Parent", &obj1)->isDict()) {
+    parent = NULL;
+  } else {
+    parent = NULL;
+  }
+  obj1.free();
+  */
+  if(dict->lookup("Open", &obj1)->isBool()) {
+    open = obj1.getBool();
+  } else {
+    open = gFalse;
+  }
+  obj1.free();
+}
 
 //------------------------------------------------------------------------
 // Annots
diff --git a/poppler/Annot.h b/poppler/Annot.h
index bdd8839..26611d2 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -284,6 +284,27 @@ private:
 };
 
 //------------------------------------------------------------------------
+// AnnotPopup
+//------------------------------------------------------------------------
+
+class AnnotPopup: public Annot {
+public:
+
+  AnnotPopup(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+  virtual ~AnnotPopup();
+
+  Dict *getParent() { return parent; }
+  bool getOpen() { return open; }
+
+protected:
+
+  void initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
+  
+  Dict *parent; // Parent
+  bool open;    // Open
+};
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
commit 6c83e06fb2eb77d0dbefd1ebfbcac3e5f0cbb622
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Mon Dec 10 16:24:38 2007 +0100

    Prepare code to Annotation Subtype support.
    
    Signed-off-by: Iñigo Martínez <inigomartinez at gmail.com>

diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index 34098f9..13d639a 100644
--- a/glib/poppler-page.cc
+++ b/glib/poppler-page.cc
@@ -409,16 +409,7 @@ poppler_page_copy_to_pixbuf(PopplerPage *page,
 static GBool
 poppler_print_annot_cb (Annot *annot, void *user_data)
 {
-  GooString *annot_type;
-
-  annot_type = annot->getType ();
-  if (!annot_type)
-    return gFalse;
-  
-  if (annot_type->cmp ("Widget") == 0)
-    return gTrue;
-
-  return gFalse;
+  return (annot->getType() == Annot::typeWidget);
 }
 
 #if defined (HAVE_CAIRO)
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 54527c0..48f3248 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -88,7 +88,7 @@ AnnotBorderArray::AnnotBorderArray(Array *array) {
 
   if (arrayLength >= 3) {
     // implementation note 81 in Appendix H.
-    /*
+
     if(array->get(0, &obj1)->isNum())
       horizontalCorner = obj1.getNum();
     obj1.free();
@@ -96,30 +96,38 @@ AnnotBorderArray::AnnotBorderArray(Array *array) {
     if(array->get(1, &obj1)->isNum())
       verticalCorner = obj1.getNum();
     obj1.free();
-    */
+
     if(array->get(2, &obj1)->isNum())
       width = obj1.getNum();
     obj1.free();
 
     // TODO: check not all zero ? (Line Dash Pattern Page 217 PDF 8.1)
     if(arrayLength > 3) {
-      style = borderDashed;
-      dashLength = array->getLength() - 3;
-      dash = (double *) gmallocn (dashLength, sizeof (double));
+      bool correct = true;
+      int tempLength = array->getLength() - 3;
+      double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
 
-      for(int i = 0; i < dashLength && i < DASH_LIMIT; i++) {
+      for(int i = 0; i < tempLength && i < DASH_LIMIT && correct; i++) {
 
         if(array->get((i + 3), &obj1)->isNum()) {
-          dash[i] = obj1.getNum();
+          tempDash[i] = obj1.getNum();
 
-          if (dash[i] < 0)
-            dash[i] = 0;
+          if (tempDash[i] < 0)
+            correct = false;
 
         } else {
-          dash[i] = 0;
+          correct = false;
         }
         obj1.free();
       }
+
+      if (correct) {
+        dashLength = tempLength;
+        dash = tempDash;
+        style = borderDashed;
+      } else {
+        delete tempDash;
+      }
     }
   }
 }
@@ -173,22 +181,32 @@ AnnotBorderBS::AnnotBorderBS(Dict *dict) {
 
   // TODO: check not all zero (Line Dash Pattern Page 217 PDF 8.1)
   if (dict->lookup("D", &obj1)->isArray()) {
-    dashLength = obj1.arrayGetLength();
-    dash = (double *) gmallocn (dashLength, sizeof (double));
+    bool correct = true;
+    int tempLength = obj1.arrayGetLength();
+    double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
 
-    for(int i = 0; i < dashLength; i++) {
+    for(int i = 0; i < tempLength && correct; i++) {
       Object obj2;
 
       if(obj1.arrayGet(i, &obj2)->isNum()) {
-        dash[i] = obj2.getNum();
+        tempDash[i] = obj2.getNum();
 
-        if(dash[i] < 0)
-          dash[i] = 0;
+        if(tempDash[i] < 0)
+          correct = false;
       } else {
-        dash[i] = 0;
+        correct = false;
       }
       obj2.free();
     }
+
+    if (correct) {
+      dashLength = tempLength;
+      dash = tempDash;
+      style = borderDashed;
+    } else {
+      delete tempDash;
+    }
+
   } else {
     dashLength = 1;
     dash = (double *) gmallocn (dashLength, sizeof (double));
@@ -269,17 +287,15 @@ AnnotBorderStyle::~AnnotBorderStyle() {
 // Annot
 //------------------------------------------------------------------------
 
-Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, const Ref& aref, Catalog* catalog)
-{
-  hasRef = true;
-  ref = aref;
-  flags = flagUnknown;
-  initialize (xrefA, acroForm, dict, catalog);
-}
-
-Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog* catalog) {
-  hasRef = false;
+Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog* catalog, Object *obj) {
+  if (obj->isRef()) {
+    hasRef = true;
+    ref = obj->getRef();
+  } else {
+    hasRef = false;
+  }
   flags = flagUnknown;
+  type = typeUnknown;
   initialize (xrefA, acroForm, dict, catalog);
 }
 
@@ -290,7 +306,6 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
   xref = xrefA;
   appearBuf = NULL;
   fontSize = 0;
-  type = NULL;
   widget = NULL;
 
   //----- get the FormWidget
@@ -300,12 +315,6 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
     if (form)
       widget = form->findWidgetByRef (ref);
   }
-  
-  //----- parse the type
-  if (dict->lookup("Subtype", &obj1)->isName()) {
-    type = new GooString(obj1.getName());
-  }
-  obj1.free();
 
   //----- parse the rectangle
   rect = new PDFRectangle();
@@ -507,9 +516,6 @@ Annot::~Annot() {
   if (modified)
     delete modified;
 
-  if (type) {
-    delete type;
-  }
   appearance.free();
   if (appearBuf) {
     delete appearBuf;
@@ -543,7 +549,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
   GBool modified;
 
   // must be a Widget annotation
-  if (type->cmp("Widget")) {
+  if (type == typeWidget) {
     return;
   }
 
@@ -1665,7 +1671,6 @@ void Annot::drawCircleBottomRight(double cx, double cy, double r) {
 
 void Annot::draw(Gfx *gfx, GBool printing) {
   Object obj;
-  GBool isLink;
 
   // check the flags
   if ((flags & annotFlagHidden) ||
@@ -1675,9 +1680,8 @@ void Annot::draw(Gfx *gfx, GBool printing) {
   }
 
   // draw the appearance stream
-  isLink = type && !type->cmp("Link");
   appearance.fetch(xref, &obj);
-  gfx->drawAnnot(&obj, isLink ? border : (AnnotBorder *)NULL, color,
+  gfx->drawAnnot(&obj, (type == typeLink) ? border : (AnnotBorder *)NULL, color,
       rect->x1, rect->y1, rect->x2, rect->y2);
   obj.free();
 }
@@ -1707,10 +1711,8 @@ Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
       //form widget
       Object obj2;
       if (annotsObj->arrayGet(i, &obj1)->isDict()) {
-        if (annotsObj->arrayGetNF(i, &obj2)->isRef())
-          annot = new Annot(xref, acroForm, obj1.getDict(), obj2.getRef(), catalog);
-        else 
-          annot = new Annot(xref, acroForm, obj1.getDict(), catalog);
+        annotsObj->arrayGetNF(i, &obj2);
+        annot = createAnnot (xref, acroForm, obj1.getDict(), catalog, &obj2);
         if (annot->isOk()) {
           if (nAnnots >= size) {
             size += 16;
@@ -1727,6 +1729,74 @@ Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
   }
 }
 
+Annot *Annots::createAnnot(XRef *xref, Dict *acroForm, Dict* dict, Catalog *catalog, Object *obj) {
+  Annot *annot;
+  Object obj1;
+
+  if (dict->lookup("Subtype", &obj1)->isName()) {
+    GooString *typeName = new GooString(obj1.getName());
+
+    if (!typeName->cmp("Text")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Link")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("FreeText")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Line")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Square")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Circle")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Polygon")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("PolyLine")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Highlight")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Underline")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Squiggly")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("StrikeOut")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Stamp")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Caret")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Ink")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("FileAttachment")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Sound")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Movie")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Widget")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Screen")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("PrinterMark")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("TrapNet")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("Watermark")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else if(!typeName->cmp("3D")) {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    } else {
+      annot = new Annot(xref, acroForm, dict, catalog, obj);
+    }
+
+    delete typeName;
+  } else {
+    annot = NULL;
+  }
+  obj1.free();
+
+  return annot;
+}
+
 void Annots::generateAppearances(Dict *acroForm) {
   Object obj1, obj2;
   Ref ref;
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 64181e6..bdd8839 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -168,13 +168,40 @@ public:
     flagLockedContents = 0x0200
   };
 
-  Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
-  Annot(XRef *xrefA, Dict *acroForm, Dict *dict, const Ref& aref, Catalog *catalog);
-  ~Annot();
+  enum AnnotSubtype {
+    typeUnknown,        //                 0
+    typeText,           // Text            1
+    typeLink,           // Link            2
+    typeFreeText,       // FreeText        3
+    typeLine,           // Line            4
+    typeSquare,         // Square          5
+    typeCircle,         // Circle          6
+    typePolygon,        // Polygon         7
+    typePolyLine,       // PolyLine        8
+    typeHighlight,      // Highlight       9
+    typeUnderline,      // Underline      10
+    typeSquiggly,       // Squiggly       11
+    typeStrikeOut,      // StrikeOut      12
+    typeStamp,          // Stamp          13
+    typeCaret,          // Caret          14
+    typeInk,            // Ink            15
+    typePopup,          // Popup          16
+    typeFileAttachment, // FileAttachment 17
+    typeSound,          // Sound          18
+    typeMovie,          // Movie          19
+    typeWidget,         // Widget         20
+    typeScreen,         // Screen         21
+    typePrinterMark,    // PrinterMark    22
+    typeTrapNet,        // TrapNet        23
+    typeWatermark,      // Watermark      24
+    type3D              // 3D             25
+  };
+
+  Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+  virtual ~Annot();
   GBool isOk() { return ok; }
 
   void draw(Gfx *gfx, GBool printing);
-
   // Get appearance object.
   Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
   GBool textField() { return isTextField; }
@@ -189,11 +216,21 @@ public:
 
   double getFontSize() { return fontSize; }
 
-  GooString *getType() { return type; }
+  // getters
+  AnnotSubtype getType() { return type; }
   PDFRectangle *getRect() { return rect; }
+  GooString *getContents() { return contents; }
+  Dict *getPageDict() { return pageDict; }
+  GooString *getName() { return name; }
+  GooString *getModified() { return modified; }
+  Guint getFlags() { return flags; }
+  /*Dict *getAppearDict() { return appearDict; }*/
+  GooString *getAppearState() { return appearState; }
   AnnotBorder *getBorder() { return border; }
   AnnotColor *getColor() { return color; }
-  
+  int getTreeKey() { return treeKey; }
+  Dict *getOptionalContent() { return optionalContent; }
+
 private:
   void setColor(Array *a, GBool fill, int adjust);
   void drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
@@ -216,7 +253,8 @@ private:
   void initialize (XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
 
   // required data
-  PDFRectangle *rect;           // Rect
+  AnnotSubtype type;                // Annotation type
+  PDFRectangle *rect;               // Rect
 
   // optional data
   GooString *contents;              // Contents
@@ -234,7 +272,6 @@ private:
   XRef *xref;			// the xref table for this PDF file
   Ref ref;                      // object ref identifying this annotation
   FormWidget *widget;           // FormWidget object for this annotation
-  GooString *type;              // annotation type
   GooString *appearBuf;
   AnnotBorder *border;          // Border, BS
   AnnotColor *color;            // C
@@ -268,6 +305,7 @@ public:
 
 
 private:
+  Annot* createAnnot(XRef *xref, Dict *acroForm, Dict* dict, Catalog *catalog, Object *obj);
   void scanFieldAppearances(Dict *node, Ref *ref, Dict *parent,
 			    Dict *acroForm);
   Annot *findAnnot(Ref *ref);
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 5cb4b87..a0fcfa1 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -1213,8 +1213,12 @@ FormPageWidgets::FormPageWidgets (XRef *xrefA, Object* annots, unsigned int page
         //create a temporary Annot to get the font size
         Object obj2;
         if (annots->arrayGet(i, &obj2)->isDict()) {
-          Annot* ann = new Annot(xref, NULL ,obj2.getDict(), NULL);
+          Annot *ann;
+          Object obj3;
+          annots->arrayGetNF(i, &obj3);
+          ann = new Annot(xref, NULL ,obj2.getDict(), NULL, &obj3);
           tmp->setFontSize(ann->getFontSize());
+          obj3.free();
           delete ann;
         }
         obj2.free();
commit fa0bb5bbea5bf2769c8b3084f78770b7781002eb
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Mon Dec 10 15:41:38 2007 +0100

    Various Annot improvements
    
    Signed-off-by: Iñigo Martínez <inigomartinez at gmail.com>

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 2e09848..54527c0 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -26,6 +26,7 @@
 #include "CharCodeToUnicode.h"
 #include "Form.h"
 #include "Error.h"
+#include "Page.h"
 
 #define annotFlagHidden    0x0002
 #define annotFlagPrint     0x0004
@@ -60,6 +61,189 @@
 #define bezierCircle 0.55228475
 
 //------------------------------------------------------------------------
+// AnnotBorder
+//------------------------------------------------------------------------
+ 
+AnnotBorder::~AnnotBorder() { 
+  if (dash)
+    gfree (dash); 
+}
+  
+//------------------------------------------------------------------------
+// AnnotBorderArray
+//------------------------------------------------------------------------
+
+AnnotBorderArray::AnnotBorderArray() {
+  horizontalCorner = 0;
+  verticalCorner = 0;
+  width = 1;
+  dashLength = 0;
+  dash = NULL;
+  style = borderSolid;
+}
+
+AnnotBorderArray::AnnotBorderArray(Array *array) {
+  Object obj1;
+  int arrayLength = array->getLength();
+
+  if (arrayLength >= 3) {
+    // implementation note 81 in Appendix H.
+    /*
+    if(array->get(0, &obj1)->isNum())
+      horizontalCorner = obj1.getNum();
+    obj1.free();
+
+    if(array->get(1, &obj1)->isNum())
+      verticalCorner = obj1.getNum();
+    obj1.free();
+    */
+    if(array->get(2, &obj1)->isNum())
+      width = obj1.getNum();
+    obj1.free();
+
+    // TODO: check not all zero ? (Line Dash Pattern Page 217 PDF 8.1)
+    if(arrayLength > 3) {
+      style = borderDashed;
+      dashLength = array->getLength() - 3;
+      dash = (double *) gmallocn (dashLength, sizeof (double));
+
+      for(int i = 0; i < dashLength && i < DASH_LIMIT; i++) {
+
+        if(array->get((i + 3), &obj1)->isNum()) {
+          dash[i] = obj1.getNum();
+
+          if (dash[i] < 0)
+            dash[i] = 0;
+
+        } else {
+          dash[i] = 0;
+        }
+        obj1.free();
+      }
+    }
+  }
+}
+
+//------------------------------------------------------------------------
+// AnnotBorderBS
+//------------------------------------------------------------------------
+
+AnnotBorderBS::AnnotBorderBS() {
+  width = 1;
+  dashLength = 0;
+  dash = NULL;
+  style = borderSolid;
+}
+
+AnnotBorderBS::AnnotBorderBS(Dict *dict) {
+  Object obj1, obj2;
+
+  // acroread 8 seems to need both W and S entries for
+  // any border to be drawn, even though the spec
+  // doesn't claim anything of that sort. We follow
+  // that behaviour by veryifying both entries exist
+  // otherwise we set the borderWidth to 0
+  // --jrmuizel
+  dict->lookup("W", &obj1);
+  dict->lookup("S", &obj2);
+  if (obj1.isNum() && obj2.isName()) {
+    GooString *styleName = new GooString(obj2.getName());
+
+    width = obj1.getNum();
+
+    if(!styleName->cmp("S")) {
+      style = borderSolid;
+    } else if(!styleName->cmp("D")) {
+      style = borderDashed;
+    } else if(!styleName->cmp("B")) {
+      style = borderBeveled;
+    } else if(!styleName->cmp("I")) {
+      style = borderInset;
+    } else if(!styleName->cmp("U")) {
+      style = borderUnderlined;
+    } else {
+      style = borderSolid;
+    }
+    delete styleName;
+  } else {
+    width = 0;
+  }
+  obj2.free();
+  obj1.free();
+
+  // TODO: check not all zero (Line Dash Pattern Page 217 PDF 8.1)
+  if (dict->lookup("D", &obj1)->isArray()) {
+    dashLength = obj1.arrayGetLength();
+    dash = (double *) gmallocn (dashLength, sizeof (double));
+
+    for(int i = 0; i < dashLength; i++) {
+      Object obj2;
+
+      if(obj1.arrayGet(i, &obj2)->isNum()) {
+        dash[i] = obj2.getNum();
+
+        if(dash[i] < 0)
+          dash[i] = 0;
+      } else {
+        dash[i] = 0;
+      }
+      obj2.free();
+    }
+  } else {
+    dashLength = 1;
+    dash = (double *) gmallocn (dashLength, sizeof (double));
+    dash[0] = 3;
+  }
+  obj1.free();
+}
+
+//------------------------------------------------------------------------
+// AnnotColor
+//------------------------------------------------------------------------
+
+AnnotColor::AnnotColor() {
+  length = 0;
+  values = NULL;
+}
+
+AnnotColor::AnnotColor(Array *array) {
+  // TODO: check what Acrobat does in the case of having more than 5 numbers.
+  if (array->getLength() < 5) {
+    length = array->getLength();
+    values = (double *) gmallocn (length, sizeof(double));
+
+    for(int i = 0; i < length; i++) {  
+      Object obj1;
+
+      if(array->get(i, &obj1)->isNum()) {
+        values[i] = obj1.getNum();
+
+        if (values[i] < 0 || values[i] > 1)
+          values[i] = 0;
+      } else {
+        values[i] = 0;
+      }
+      obj1.free();
+    }
+  }
+}
+
+AnnotColor::AnnotColorSpace AnnotColor::getSpace() {
+  return (AnnotColor::AnnotColorSpace) length;
+}
+
+double AnnotColor::getValue(int i) {
+  if(i >= 0 && i < length) 
+    return values[i];
+  return 0;
+}
+
+AnnotColor::~AnnotColor() {
+  if(values)
+    gfree (values);
+}
+
+//------------------------------------------------------------------------
 // AnnotBorderStyle
 //------------------------------------------------------------------------
 
@@ -88,23 +272,19 @@ AnnotBorderStyle::~AnnotBorderStyle() {
 Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, const Ref& aref, Catalog* catalog)
 {
   hasRef = true;
-  ref = aref; 
+  ref = aref;
+  flags = flagUnknown;
   initialize (xrefA, acroForm, dict, catalog);
 }
 
 Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog* catalog) {
   hasRef = false;
+  flags = flagUnknown;
   initialize (xrefA, acroForm, dict, catalog);
 }
 
 void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog) {
   Object apObj, asObj, obj1, obj2, obj3;
-  AnnotBorderType borderType;
-  double borderWidth;
-  double *borderDash;
-  int borderDashLength;
-  double borderR, borderG, borderB;
-  double t;
 
   ok = gTrue;
   xref = xrefA;
@@ -112,7 +292,6 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
   fontSize = 0;
   type = NULL;
   widget = NULL;
-  borderStyle = NULL;
 
   //----- get the FormWidget
   if (hasRef) {
@@ -129,47 +308,74 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
   obj1.free();
 
   //----- parse the rectangle
+  rect = new PDFRectangle();
+  if (dict->lookup("Rect", &obj1)->isArray() && obj1.arrayGetLength() == 4) {
+    Object obj2;
+    (obj1.arrayGet(0, &obj2)->isNum() ? rect->x1 = obj2.getNum() : rect->x1 = 0);
+    obj2.free();
+    (obj1.arrayGet(1, &obj2)->isNum() ? rect->y1 = obj2.getNum() : rect->y1 = 0);
+    obj2.free();
+    (obj1.arrayGet(2, &obj2)->isNum() ? rect->x2 = obj2.getNum() : rect->x2 = 1);
+    obj2.free();
+    (obj1.arrayGet(3, &obj2)->isNum() ? rect->y2 = obj2.getNum() : rect->y2 = 1);
+    obj2.free();
 
-  if (dict->lookup("Rect", &obj1)->isArray() &&
-      obj1.arrayGetLength() == 4) {
-    readArrayNum(&obj1, 0, &xMin);
-    readArrayNum(&obj1, 1, &yMin);
-    readArrayNum(&obj1, 2, &xMax);
-    readArrayNum(&obj1, 3, &yMax);
-    if (ok) {
-      if (xMin > xMax) {
-        t = xMin; xMin = xMax; xMax = t;
-      }
-      if (yMin > yMax) {
-        t = yMin; yMin = yMax; yMax = t;
-      }
-    } else {
-      xMin = yMin = 0;
-      xMax = yMax = 1;
-      error(-1, "Bad bounding box for annotation");
-      ok = gFalse;
+    if (rect->x1 > rect->x2) {
+      double t = rect->x1;
+      rect->x1 = rect->x2;
+      rect->x2 = t;
+    }
+
+    if (rect->y1 > rect->y2) {
+      double t = rect->y1;
+      rect->y1 = rect->y2;
+      rect->y2 = t;
     }
   } else {
-    xMin = yMin = 0;
-    xMax = yMax = 1;
+    rect->x1 = rect->y1 = 0;
+    rect->x2 = rect->y2 = 1;
     error(-1, "Bad bounding box for annotation");
     ok = gFalse;
   }
   obj1.free();
-  
+
+  if (dict->lookup("Contents", &obj1)->isString()) {
+    contents = obj1.getString()->copy();
+  } else {
+    contents = NULL;
+  }
+  obj1.free();
+
+  /* TODO: Page Object indirect reference (should be parsed ?)
+  if (dict->lookup("P", &obj1)->isDict()) {
+    pageDict = NULL;
+  } else {
+    pageDict = NULL;
+  }
+  obj1.free();
+  */
+
+  if (dict->lookup("NM", &obj1)->isString()) {
+    name = obj1.getString()->copy();
+  } else {
+    name = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("M", &obj1)->isString()) {
+    modified = obj1.getString()->copy();
+  } else {
+    modified = NULL;
+  }
+  obj1.free();
+
   //----- get the flags
   if (dict->lookup("F", &obj1)->isInt()) {
-    flags = obj1.getInt();
+    flags |= obj1.getInt();
   } else {
-    flags = 0;
+    flags = flagUnknown;
   }
-  obj1.free ();
-
-  //check for hidden annot
-  if (flags & 0x2)
-    hidden = true;
-  else
-    hidden = false;
+  obj1.free();
 
   // check if field apperances need to be regenerated
   // Only text or choice fields needs to have appearance regenerated
@@ -185,139 +391,92 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
       obj1.free();
     }
   }
+  obj3.free();
+
+  if (dict->lookup("AP", &obj1)->isDict()) {
+    Object obj2;
+
+    if (dict->lookup("AS", &obj2)->isName()) {
+      Object obj3;
 
-  if (dict->lookup("AP", &apObj)->isDict()) {
-    if (dict->lookup("AS", &asObj)->isName()) {
-      if (apObj.dictLookup("N", &obj1)->isDict()) {
-        if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) {
-	  obj2.copy(&appearance);
-	  ok = gTrue;
-	} else {
-	  obj2.free();
-	  if (obj1.dictLookupNF("Off", &obj2)->isRef()) {
-	    obj2.copy(&appearance);
-	    ok = gTrue;
-	  } else
-	    regen = gTrue;
-	} 
-	obj2.free();
+      appearState = new GooString(obj2.getName());
+      if (obj1.dictLookup("N", &obj3)->isDict()) {
+        Object obj4;
+
+        if (obj3.dictLookupNF(appearState->getCString(), &obj4)->isRef()) {
+          obj4.copy(&appearance);
+        } else {
+          obj4.free();
+          if (obj3.dictLookupNF("Off", &obj4)->isRef()) {
+            obj4.copy(&appearance);
+          } else
+            regen = gTrue;
+        } 
+        obj4.free();
       }
-      obj1.free();
+      obj3.free();
     } else {
-      if (apObj.dictLookupNF("N", &obj1)->isRef()) {
-        obj1.copy(&appearance);
-	ok = gTrue;
+      obj2.free();
+
+      appearState = NULL;
+      if (obj1.dictLookupNF("N", &obj2)->isRef()) {
+        obj2.copy(&appearance);
       } else
         regen = gTrue;
-      obj1.free();
     }
-    asObj.free();
+    obj2.free();
   } else {
+    appearState = NULL;
     // If field doesn't have an AP we'll have to generate it
     regen = gTrue;
   }
-  apObj.free();
-  obj3.free();
+  obj1.free();
 
   //----- parse the border style
-
-  borderType = annotBorderSolid;
-  borderWidth = 1;
-  borderDash = NULL;
-  borderDashLength = 0;
-  borderR = 0;
-  borderG = 0;
-  borderB = 1;
   if (dict->lookup("BS", &obj1)->isDict()) {
-    if (obj1.dictLookup("S", &obj2)->isName()) {
-      if (obj2.isName("S")) {
-        borderType = annotBorderSolid;
-      } else if (obj2.isName("D")) {
-        borderType = annotBorderDashed;
-      } else if (obj2.isName("B")) {
-        borderType = annotBorderBeveled;
-      } else if (obj2.isName("I")) {
-        borderType = annotBorderInset;
-      } else if (obj2.isName("U")) {
-        borderType = annotBorderUnderlined;
-      }
-    }
-    if (obj1.dictLookup("W", &obj3)->isNum()) {
-      borderWidth = obj3.getNum();
-    }
-    // acroread 8 seems to need both W and S entries for
-    // any border to be drawn, even though the spec
-    // doesn't claim anything of that sort. We follow
-    // that behaviour by veryifying both entries exist
-    // otherwise we set the borderWidth to 0
-    // --jrmuizel
-    if (!obj2.isName() || !obj3.isNum()) {
-      borderWidth = 0;
-    }
-    obj3.free();
-    obj2.free();
-    if (obj1.dictLookup("D", &obj2)->isArray()) {
-      borderDashLength = obj2.arrayGetLength();
-      borderDash = (double *)gmallocn(borderDashLength, sizeof(double));
-      for (int i = 0; i < borderDashLength; ++i) {
-        if (obj2.arrayGet(i, &obj3)->isNum()) {
-          borderDash[i] = obj3.getNum();
-        } else {
-          borderDash[i] = 1;
-        }
-        obj3.free();
-      }
-    }
-    obj2.free();
+    border = new AnnotBorderBS(obj1.getDict());
   } else {
     obj1.free();
-    if (dict->lookup("Border", &obj1)->isArray()) {
-      if (obj1.arrayGetLength() >= 3) {
-        if (obj1.arrayGet(2, &obj2)->isNum()) {
-          borderWidth = obj2.getNum();
-        }
-        obj2.free();
-        if (obj1.arrayGetLength() >= 4) {
-          if (obj1.arrayGet(3, &obj2)->isArray()) {
-            borderType = annotBorderDashed;
-            borderDashLength = obj2.arrayGetLength();
-            borderDash = (double *)gmallocn(borderDashLength, sizeof(double));
-            for (int i = 0; i < borderDashLength; ++i) {
-              if (obj2.arrayGet(i, &obj3)->isNum()) {
-                borderDash[i] = obj3.getNum();
-              } else {
-                borderDash[i] = 1;
-              }
-              obj3.free();
-            }
-          } else {
-            // Adobe draws no border at all if the last element is of
-            // the wrong type.
-            borderWidth = 0;
-          }
-        }
-      }
-    }
-    obj1.free();
+
+    if (dict->lookup("Border", &obj1)->isArray())
+      border = new AnnotBorderArray(obj1.getArray());
+    else
+      // Adobe draws no border at all if the last element is of
+      // the wrong type.
+      border = NULL;
   }
-  if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) {
-    if (obj1.arrayGet(0, &obj2)->isNum()) {
-      borderR = obj2.getNum();
-    }
-    obj1.free();
-    if (obj1.arrayGet(1, &obj2)->isNum()) {
-      borderG = obj2.getNum();
-    }
-    obj1.free();
-    if (obj1.arrayGet(2, &obj2)->isNum()) {
-      borderB = obj2.getNum();
-    }
-    obj1.free();
+  obj1.free();
+
+  if (dict->lookup("C", &obj1)->isArray()) {
+    color = new AnnotColor(obj1.getArray());
+  } else {
+    color = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("StructParent", &obj1)->isInt()) {
+    treeKey = obj1.getInt();
+  } else {
+    treeKey = 0;
   }
   obj1.free();
-  borderStyle = new AnnotBorderStyle(borderType, borderWidth,
-      borderDash, borderDashLength,
-      borderR, borderG, borderB);
+
+  /* TODO: optional content should be parsed
+  if (dict->lookup("OC", &obj1)->isDict()) {
+    optionalContent = NULL;
+  } else {
+    optionalContent = NULL;
+  }
+  obj1.free();
+  */
+}
+
+double Annot::getXMin() {
+  return rect->x1;
+}
+
+double Annot::getYMin() {
+  return rect->y1;
 }
 
 void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
@@ -334,6 +493,20 @@ void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
 }
 
 Annot::~Annot() {
+  delete rect;
+
+  if (contents)
+    delete contents;
+
+  if (pageDict)
+    delete pageDict;
+
+  if(name)
+    delete name;
+
+  if (modified)
+    delete modified;
+
   if (type) {
     delete type;
   }
@@ -342,9 +515,17 @@ Annot::~Annot() {
     delete appearBuf;
   }
 
-  if (borderStyle) {
-    delete borderStyle;
-  }
+  if(appearState)
+    delete appearState;
+
+  if (border)
+    delete border;
+
+  if (color)
+    delete color;
+
+  if (optionalContent)
+    delete optionalContent;
 }
 
 void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
@@ -392,7 +573,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
         obj1.arrayGetLength() > 0) {
       setColor(obj1.getArray(), gTrue, 0);
       appearBuf->appendf("0 0 {0:.2f} {1:.2f} re f\n",
-          xMax - xMin, yMax - yMin);
+          rect->x2 - rect->x1, rect->y2 - rect->y1);
     }
     obj1.free();
   }
@@ -409,71 +590,73 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
   obj1.free();
 
   // draw the border
-  if (mkDict) {
-    w = borderStyle->getWidth();
+  if (mkDict && border) {
+    w = border->getWidth();
     if (w > 0) {
       mkDict->lookup("BC", &obj1);
       if (!(obj1.isArray() && obj1.arrayGetLength() > 0)) {
         mkDict->lookup("BG", &obj1);
       }
       if (obj1.isArray() && obj1.arrayGetLength() > 0) {
-        dx = xMax - xMin;
-        dy = yMax - yMin;
+        dx = rect->x2 - rect->x1;
+        dy = rect->y2 - rect->y1;
 
         // radio buttons with no caption have a round border
         hasCaption = mkDict->lookup("CA", &obj2)->isString();
         obj2.free();
         if (ftObj.isName("Btn") && (ff & fieldFlagRadio) && !hasCaption) {
           r = 0.5 * (dx < dy ? dx : dy);
-          switch (borderStyle->getType()) {
-            case annotBorderDashed:
+          switch (border->getStyle()) {
+            case AnnotBorder::borderDashed:
               appearBuf->append("[");
-              borderStyle->getDash(&dash, &dashLength);
+              dashLength = border->getDashLength();
+              dash = border->getDash();
               for (i = 0; i < dashLength; ++i) {
                 appearBuf->appendf(" {0:.2f}", dash[i]);
               }
               appearBuf->append("] 0 d\n");
               // fall through to the solid case
-            case annotBorderSolid:
-            case annotBorderUnderlined:
+            case AnnotBorder::borderSolid:
+            case AnnotBorder::borderUnderlined:
               appearBuf->appendf("{0:.2f} w\n", w);
               setColor(obj1.getArray(), gFalse, 0);
               drawCircle(0.5 * dx, 0.5 * dy, r - 0.5 * w, gFalse);
               break;
-            case annotBorderBeveled:
-            case annotBorderInset:
+            case AnnotBorder::borderBeveled:
+            case AnnotBorder::borderInset:
               appearBuf->appendf("{0:.2f} w\n", 0.5 * w);
               setColor(obj1.getArray(), gFalse, 0);
               drawCircle(0.5 * dx, 0.5 * dy, r - 0.25 * w, gFalse);
               setColor(obj1.getArray(), gFalse,
-                  borderStyle->getType() == annotBorderBeveled ? 1 : -1);
+                  border->getStyle() == AnnotBorder::borderBeveled ? 1 : -1);
               drawCircleTopLeft(0.5 * dx, 0.5 * dy, r - 0.75 * w);
               setColor(obj1.getArray(), gFalse,
-                  borderStyle->getType() == annotBorderBeveled ? -1 : 1);
+                  border->getStyle() == AnnotBorder::borderBeveled ? -1 : 1);
               drawCircleBottomRight(0.5 * dx, 0.5 * dy, r - 0.75 * w);
               break;
           }
 
         } else {
-          switch (borderStyle->getType()) {
-            case annotBorderDashed:
+          switch (border->getStyle()) {
+            case AnnotBorder::borderDashed:
               appearBuf->append("[");
-              borderStyle->getDash(&dash, &dashLength);
+              dashLength = border->getDashLength();
+              dash = border->getDash();
               for (i = 0; i < dashLength; ++i) {
                 appearBuf->appendf(" {0:.2f}", dash[i]);
               }
               appearBuf->append("] 0 d\n");
               // fall through to the solid case
-            case annotBorderSolid:
+            case AnnotBorder::borderSolid:
               appearBuf->appendf("{0:.2f} w\n", w);
               setColor(obj1.getArray(), gFalse, 0);
               appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re s\n",
                   0.5 * w, dx - w, dy - w);
               break;
-            case annotBorderBeveled:
-            case annotBorderInset:
+            case AnnotBorder::borderBeveled:
+            case AnnotBorder::borderInset:
               setColor(obj1.getArray(), gTrue,
-                  borderStyle->getType() == annotBorderBeveled ? 1 : -1);
+                  border->getStyle() == AnnotBorder::borderBeveled ? 1 : -1);
               appearBuf->append("0 0 m\n");
               appearBuf->appendf("0 {0:.2f} l\n", dy);
               appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy);
@@ -482,7 +665,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
               appearBuf->appendf("{0:.2f} {0:.2f} l\n", w);
               appearBuf->append("f\n");
               setColor(obj1.getArray(), gTrue,
-                  borderStyle->getType() == annotBorderBeveled ? -1 : 1);
+                  border->getStyle() == AnnotBorder::borderBeveled ? -1 : 1);
               appearBuf->append("0 0 m\n");
               appearBuf->appendf("{0:.2f} 0 l\n", dx);
               appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy);
@@ -491,7 +674,7 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
               appearBuf->appendf("{0:.2f} {0:.2f} l\n", w);
               appearBuf->append("f\n");
               break;
-            case annotBorderUnderlined:
+            case AnnotBorder::borderUnderlined:
               appearBuf->appendf("{0:.2f} w\n", w);
               setColor(obj1.getArray(), gFalse, 0);
               appearBuf->appendf("0 0 m {0:.2f} 0 l s\n", dx);
@@ -554,8 +737,8 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
             if (mkDict) {
               if (mkDict->lookup("BC", &obj3)->isArray() &&
                   obj3.arrayGetLength() > 0) {
-                dx = xMax - xMin;
-                dy = yMax - yMin;
+                dx = rect->x2 - rect->x1;
+                dy = rect->y2 - rect->y1;
                 setColor(obj3.getArray(), gTrue, 0);
                 drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy),
                     gTrue);
@@ -704,8 +887,8 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
   obj1.initArray(xref);
   obj1.arrayAdd(obj2.initReal(0));
   obj1.arrayAdd(obj2.initReal(0));
-  obj1.arrayAdd(obj2.initReal(xMax - xMin));
-  obj1.arrayAdd(obj2.initReal(yMax - yMin));
+  obj1.arrayAdd(obj2.initReal(rect->x2 - rect->x1));
+  obj1.arrayAdd(obj2.initReal(rect->y2 - rect->y1));
   appearDict.dictAdd(copyString("BBox"), &obj1);
 
   // set the resource dictionary
@@ -831,7 +1014,7 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
   GooList *daToks;
   GooString *tok;
   GfxFont *font;
-  double fontSize, fontSize2, border, x, xPrev, y, w, w2, wMax;
+  double fontSize, fontSize2, borderWidth, x, xPrev, y, w, w2, wMax;
   int tfPos, tmPos, i, j, k;
 
   //~ if there is no MK entry, this should use the existing content stream,
@@ -899,7 +1082,7 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
   }
 
   // get the border width
-  border = borderStyle->getWidth();
+  borderWidth = border->getWidth();
 
   // setup
   if (txField) {
@@ -911,12 +1094,12 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
   if (multiline) {
     // note: the comb flag is ignored in multiline mode
 
-    wMax = xMax - xMin - 2 * border - 4;
+    wMax = rect->x2 - rect->x1 - 2 * borderWidth - 4;
 
     // compute font autosize
     if (fontSize == 0) {
       for (fontSize = 20; fontSize > 1; --fontSize) {
-        y = yMax - yMin;
+        y = rect->y2 - rect->y1;
         w2 = 0;
         i = 0;
         while (i < text->getLength()) {
@@ -942,7 +1125,7 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
     // starting y coordinate
     // (note: each line of text starts with a Td operator that moves
     // down a line)
-    y = yMax - yMin;
+    y = rect->y2 - rect->y1;
 
     // set the font matrix
     if (tmPos >= 0) {
@@ -977,13 +1160,13 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
       switch (quadding) {
         case fieldQuadLeft:
         default:
-          x = border + 2;
+          x = borderWidth + 2;
           break;
         case fieldQuadCenter:
-          x = (xMax - xMin - w) / 2;
+          x = (rect->x2 - rect->x1 - w) / 2;
           break;
         case fieldQuadRight:
-          x = xMax - xMin - border - 2 - w;
+          x = rect->x2 - rect->x1 - borderWidth - 2 - w;
           break;
       }
 
@@ -1005,11 +1188,11 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
     // comb formatting
     if (comb > 0) {
       // compute comb spacing
-      w = (xMax - xMin - 2 * border) / comb;
+      w = (rect->x2 - rect->x1 - 2 * borderWidth) / comb;
 
       // compute font autosize
       if (fontSize == 0) {
-        fontSize = yMax - yMin - 2 * border;
+        fontSize = rect->y2 - rect->y1 - 2 * borderWidth;
         if (w < fontSize) {
           fontSize = w;
         }
@@ -1025,16 +1208,16 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
       switch (quadding) {
         case fieldQuadLeft:
         default:
-          x = border + 2;
+          x = borderWidth + 2;
           break;
         case fieldQuadCenter:
-          x = border + 2 + 0.5 * (comb - text->getLength()) * w;
+          x = borderWidth + 2 + 0.5 * (comb - text->getLength()) * w;
           break;
         case fieldQuadRight:
-          x = border + 2 + (comb - text->getLength()) * w;
+          x = borderWidth + 2 + (comb - text->getLength()) * w;
           break;
       }
-      y = 0.5 * (yMax - yMin) - 0.4 * fontSize;
+      y = 0.5 * (rect->y2 - rect->y1) - 0.4 * fontSize;
 
       // set the font matrix
       if (tmPos >= 0) {
@@ -1086,8 +1269,8 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
 
       // compute font autosize
       if (fontSize == 0) {
-        fontSize = yMax - yMin - 2 * border;
-        fontSize2 = (xMax - xMin - 4 - 2 * border) / w;
+        fontSize = rect->y2 - rect->y1 - 2 * borderWidth;
+        fontSize2 = (rect->x2 - rect->x1 - 4 - 2 * borderWidth) / w;
         if (fontSize2 < fontSize) {
           fontSize = fontSize2;
         }
@@ -1104,16 +1287,16 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
       switch (quadding) {
         case fieldQuadLeft:
         default:
-          x = border + 2;
+          x = borderWidth + 2;
           break;
         case fieldQuadCenter:
-          x = (xMax - xMin - w) / 2;
+          x = (rect->x2 - rect->x1 - w) / 2;
           break;
         case fieldQuadRight:
-          x = xMax - xMin - border - 2 - w;
+          x = rect->x2 - rect->x1 - borderWidth - 2 - w;
           break;
       }
-      y = 0.5 * (yMax - yMin) - 0.4 * fontSize;
+      y = 0.5 * (rect->y2 - rect->y1) - 0.4 * fontSize;
 
       // set the font matrix
       if (tmPos >= 0) {
@@ -1161,7 +1344,7 @@ void Annot::drawListBox(GooString **text, GBool *selection,
   GooList *daToks;
   GooString *tok;
   GfxFont *font;
-  double fontSize, fontSize2, border, x, y, w, wMax;
+  double fontSize, fontSize2, borderWidth, x, y, w, wMax;
   int tfPos, tmPos, i, j;
 
   //~ if there is no MK entry, this should use the existing content stream,
@@ -1218,7 +1401,7 @@ void Annot::drawListBox(GooString **text, GBool *selection,
   }
 
   // get the border width
-  border = borderStyle->getWidth();
+  borderWidth = border->getWidth();
 
   // compute font autosize
   if (fontSize == 0) {
@@ -1237,8 +1420,8 @@ void Annot::drawListBox(GooString **text, GBool *selection,
         wMax = w;
       }
     }
-    fontSize = yMax - yMin - 2 * border;
-    fontSize2 = (xMax - xMin - 4 - 2 * border) / wMax;
+    fontSize = rect->y2 - rect->y1 - 2 * borderWidth;
+    fontSize2 = (rect->x2 - rect->x1 - 4 - 2 * borderWidth) / wMax;
     if (fontSize2 < fontSize) {
       fontSize = fontSize2;
     }
@@ -1250,7 +1433,7 @@ void Annot::drawListBox(GooString **text, GBool *selection,
     }
   }
   // draw the text
-  y = yMax - yMin - 1.1 * fontSize;
+  y = rect->y2 - rect->y1 - 1.1 * fontSize;
   for (i = topIdx; i < nOptions; ++i) {
     // setup
     appearBuf->append("q\n");
@@ -1259,9 +1442,9 @@ void Annot::drawListBox(GooString **text, GBool *selection,
     if (selection[i]) {
       appearBuf->append("0 g f\n");
       appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} re f\n",
-          border,
+          borderWidth,
           y - 0.2 * fontSize,
-          xMax - xMin - 2 * border,
+          rect->x2 - rect->x1 - 2 * borderWidth,
           1.1 * fontSize);
     }
 
@@ -1284,13 +1467,13 @@ void Annot::drawListBox(GooString **text, GBool *selection,
     switch (quadding) {
       case fieldQuadLeft:
       default:
-        x = border + 2;
+        x = borderWidth + 2;
         break;
       case fieldQuadCenter:
-        x = (xMax - xMin - w) / 2;
+        x = (rect->x2 - rect->x1 - w) / 2;
         break;
       case fieldQuadRight:
-        x = xMax - xMin - border - 2 - w;
+        x = rect->x2 - rect->x1 - borderWidth - 2 - w;
         break;
     }
 
@@ -1494,8 +1677,8 @@ void Annot::draw(Gfx *gfx, GBool printing) {
   // draw the appearance stream
   isLink = type && !type->cmp("Link");
   appearance.fetch(xref, &obj);
-  gfx->drawAnnot(&obj, isLink ? borderStyle : (AnnotBorderStyle *)NULL,
-      xMin, yMin, xMax, yMax);
+  gfx->drawAnnot(&obj, isLink ? border : (AnnotBorder *)NULL, color,
+      rect->x1, rect->y1, rect->x2, rect->y2);
   obj.free();
 }
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 50f5bfb..64181e6 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -20,6 +20,97 @@ class CharCodeToUnicode;
 class GfxFont;
 class GfxFontDict;
 class FormWidget;
+class PDFRectangle;
+
+//------------------------------------------------------------------------
+// AnnotBorder
+//------------------------------------------------------------------------
+
+class AnnotBorder {
+public:
+  enum AnnotBorderStyle {
+    borderSolid,      // Solid
+    borderDashed,     // Dashed
+    borderBeveled,    // Beveled
+    borderInset,      // Inset
+    borderUnderlined, // Underlined
+  };
+	  
+  virtual ~AnnotBorder();
+
+  virtual double getWidth() { return width; }
+  virtual int getDashLength() { return dashLength; }
+  virtual double *getDash() { return dash; }
+  virtual AnnotBorderStyle getStyle() { return style; }
+
+protected:
+  double width;
+  int dashLength;
+  double *dash;
+  AnnotBorderStyle style;
+};
+
+//------------------------------------------------------------------------
+// AnnotBorderArray
+//------------------------------------------------------------------------
+
+class AnnotBorderArray: public AnnotBorder {
+public:
+  AnnotBorderArray();
+  AnnotBorderArray(Array *array);
+
+  virtual double getHorizontalCorner() { return horizontalCorner; }
+  virtual double getVerticalCorner() { return verticalCorner; }
+
+protected:
+  static const int DASH_LIMIT = 10; // implementation note 82 in Appendix H.
+  double horizontalCorner;          // (Default 0)
+  double verticalCorner;            // (Default 0)
+  // double width;                  // (Default 1)  (inherited from AnnotBorder)
+};
+
+//------------------------------------------------------------------------
+// AnnotBorderBS
+//------------------------------------------------------------------------
+
+class AnnotBorderBS: public AnnotBorder {
+public:
+  
+  AnnotBorderBS();
+  AnnotBorderBS(Dict *dict);
+
+private:
+  // double width;           // W  (Default 1)   (inherited from AnnotBorder)
+  // AnnotBorderStyle style; // S  (Default S)   (inherited from AnnotBorder)
+  // double *dash;           // D  (Default [3]) (inherited from AnnotBorder)
+};
+
+//------------------------------------------------------------------------
+// AnnotColor
+//------------------------------------------------------------------------
+
+class AnnotColor {
+public:
+
+  enum AnnotColorSpace {
+    colorTransparent = 0,
+    colorGray        = 1,
+    colorRGB         = 3,
+    colorCMYK        = 4
+  };
+  
+  AnnotColor();
+  AnnotColor(Array *array);
+  ~AnnotColor();
+
+  AnnotColorSpace getSpace();
+  double getValue(int i);
+
+private:
+
+  double *values;
+  int length;
+};
 
 //------------------------------------------------------------------------
 // AnnotBorderStyle
@@ -63,6 +154,19 @@ private:
 
 class Annot {
 public:
+  enum AnnotFlag {
+    flagUnknown        = 0x0000,
+    flagInvisible      = 0x0001,
+    flagHidden         = 0x0002,
+    flagPrint          = 0x0004,
+    flagNoZoom         = 0x0008,
+    flagNoRotate       = 0x0010,
+    flagNoView         = 0x0020,
+    flagReadOnly       = 0x0040,
+    flagLocked         = 0x0080,
+    flagToggleNoView   = 0x0100,
+    flagLockedContents = 0x0200
+  };
 
   Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
   Annot(XRef *xrefA, Dict *acroForm, Dict *dict, const Ref& aref, Catalog *catalog);
@@ -75,20 +179,21 @@ public:
   Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
   GBool textField() { return isTextField; }
 
-  AnnotBorderStyle *getBorderStyle () { return borderStyle; }
-
   GBool match(Ref *refA)
     { return ref.num == refA->num && ref.gen == refA->gen; }
 
   void generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm);
 
-  double getXMin() { return xMin; }
-  double getYMin() { return yMin; }
+  double getXMin();
+  double getYMin();
 
   double getFontSize() { return fontSize; }
 
   GooString *getType() { return type; }
-
+  PDFRectangle *getRect() { return rect; }
+  AnnotBorder *getBorder() { return border; }
+  AnnotColor *getColor() { return color; }
+  
 private:
   void setColor(Array *a, GBool fill, int adjust);
   void drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
@@ -110,24 +215,35 @@ private:
 
   void initialize (XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
 
+  // required data
+  PDFRectangle *rect;           // Rect
+
+  // optional data
+  GooString *contents;              // Contents
+  Dict *pageDict;                   // P
+  GooString *name;                  // NM
+  GooString *modified;              // M
+  Guint flags;                      // F (must be a 32 bit unsigned int)
+  //Dict *appearDict;                 // AP (should be correctly parsed)
+  Object appearance;     // a reference to the Form XObject stream
+                         //   for the normal appearance
+  GooString *appearState;           // AS
+  int treeKey;                      // Struct Parent;
+  Dict *optionalContent;            // OC
+
   XRef *xref;			// the xref table for this PDF file
   Ref ref;                      // object ref identifying this annotation
   FormWidget *widget;           // FormWidget object for this annotation
   GooString *type;              // annotation type
-  Object appearance;		// a reference to the Form XObject stream
-				//   for the normal appearance
   GooString *appearBuf;
-  Guint flags;
-  double xMin, yMin,		// annotation rectangle
-         xMax, yMax;
-  AnnotBorderStyle *borderStyle;
+  AnnotBorder *border;          // Border, BS
+  AnnotColor *color;            // C
   double fontSize; 
   GBool ok;
   GBool regen, isTextField;
   GBool isMultiline, isListbox;
   
   bool hasRef;
-  bool hidden;
 };
 
 //------------------------------------------------------------------------
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 78bb640..037f1ac 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -4060,7 +4060,7 @@ void Gfx::opMarkPoint(Object args[], int numArgs) {
 // misc
 //------------------------------------------------------------------------
 
-void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
+void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor,
 		    double xMin, double yMin, double xMax, double yMax) {
   Dict *dict, *resDict;
   Object matrixObj, bboxObj, resObj;
@@ -4182,13 +4182,19 @@ void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
   }
 
   // draw the border
-  if (borderStyle && borderStyle->getWidth() > 0) {
+  if (border && border->getWidth() > 0) {
     if (state->getStrokeColorSpace()->getMode() != csDeviceRGB) {
       state->setStrokePattern(NULL);
       state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
       out->updateStrokeColorSpace(state);
     }
-    borderStyle->getColor(&r, &g, &b);
+    if (aColor && (aColor->getSpace() == AnnotColor::colorRGB)) {
+      r = aColor->getValue(0);
+      g = aColor->getValue(1);
+      b = aColor->getValue(2);
+    } else {
+      r = g = b = 0;
+    };
     color.c[0] = dblToCol(r);
     color.c[1] = dblToCol(g);
     color.c[2] = dblToCol(b);
@@ -4201,10 +4207,11 @@ void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
     y = (baseMatrix[0] + baseMatrix[2]) * ictm[1] +
         (baseMatrix[1] + baseMatrix[3]) * ictm[3];
     x = sqrt(0.5 * (x * x + y * y));
-    state->setLineWidth(x * borderStyle->getWidth());
+    state->setLineWidth(x * border->getWidth());
     out->updateLineWidth(state);
-    borderStyle->getDash(&dash, &dashLength);
-    if (borderStyle->getType() == annotBorderDashed && dashLength > 0) {
+    dashLength = border->getDashLength();
+    dash = border->getDash();
+    if (border->getStyle() == AnnotBorder::borderDashed && dashLength > 0) {
       dash2 = (double *)gmallocn(dashLength, sizeof(double));
       for (i = 0; i < dashLength; ++i) {
 	dash2[i] = x * dash[i];
@@ -4216,7 +4223,7 @@ void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
     state->clearPath();
     state->moveTo(annotX0, out->upsideDown() ? annotY1 : annotY0);
     state->lineTo(annotX1, out->upsideDown() ? annotY1 : annotY0);
-    if (borderStyle->getType() != annotBorderUnderlined) {
+    if (border->getStyle() != AnnotBorder::borderUnderlined) {
       state->lineTo(annotX1, out->upsideDown() ? annotY0 : annotY1);
       state->lineTo(annotX0, out->upsideDown() ? annotY0 : annotY1);
       state->closePath();
diff --git a/poppler/Gfx.h b/poppler/Gfx.h
index 28d8a3d..2c86105 100644
--- a/poppler/Gfx.h
+++ b/poppler/Gfx.h
@@ -41,7 +41,8 @@ struct GfxColor;
 class GfxColorSpace;
 class Gfx;
 class PDFRectangle;
-class AnnotBorderStyle;
+class AnnotBorder;
+class AnnotColor;
 
 //------------------------------------------------------------------------
 
@@ -128,7 +129,7 @@ public:
 
   // Display an annotation, given its appearance (a Form XObject),
   // border style, and bounding box (in default user space).
-  void drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
+  void drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor,
 		 double xMin, double yMin, double xMax, double yMax);
 
   // Save graphics state.


More information about the poppler mailing list