[poppler] 7 commits - poppler/Annot.cc poppler/Annot.h test/.gitignore

Albert Astals Cid aacid at kemper.freedesktop.org
Sat Jan 19 05:10:31 PST 2008


 poppler/Annot.cc |  955 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 poppler/Annot.h  |  418 ++++++++++++++++++++++++
 test/.gitignore  |    1 
 3 files changed, 1310 insertions(+), 64 deletions(-)

New commits:
commit 37ae465775d9a53e7c06cf51aa215439214fd79c
Author: Albert Astals Cid <tsdgeos at bluebox.localdomain>
Date:   Sat Jan 19 14:00:31 2008 +0100

    ignore pdf-fullrewrite binary

diff --git a/test/.gitignore b/test/.gitignore
index b9022f4..e6bc1c8 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -10,4 +10,5 @@ gtk-cairo-test
 gtk-splash-test
 pdf_inspector
 perf-test
+pdf-fullrewrite
 *~
commit 1d160935ea4c1116b745c584ed7f1fd03fbbfb46
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Sat Jan 19 13:59:46 2008 +0100

    AnnotWidget support and few fixes

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 48dd1d6..196485d 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -227,49 +227,49 @@ AnnotQuadrilaterals::~AnnotQuadrilaterals() {
 
 double AnnotQuadrilaterals::getX1(int quadrilateral) {
   if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
-    return quadrilaterals[quadrilateral]->getX1();
+    return quadrilaterals[quadrilateral]->x1;
   return 0;
 }
 
 double AnnotQuadrilaterals::getY1(int quadrilateral) {
   if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
-    return quadrilaterals[quadrilateral]->getY1();
+    return quadrilaterals[quadrilateral]->y1;
   return 0;
 }
 
 double AnnotQuadrilaterals::getX2(int quadrilateral) {
   if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
-    return quadrilaterals[quadrilateral]->getX2();
+    return quadrilaterals[quadrilateral]->x2;
   return 0;
 }
 
 double AnnotQuadrilaterals::getY2(int quadrilateral) {
   if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
-    return quadrilaterals[quadrilateral]->getY2();
+    return quadrilaterals[quadrilateral]->y2;
   return 0;
 }
 
 double AnnotQuadrilaterals::getX3(int quadrilateral) {
   if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
-    return quadrilaterals[quadrilateral]->getX3();
+    return quadrilaterals[quadrilateral]->x3;
   return 0;
 }
 
 double AnnotQuadrilaterals::getY3(int quadrilateral) {
   if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
-    return quadrilaterals[quadrilateral]->getY3();
+    return quadrilaterals[quadrilateral]->y3;
   return 0;
 }
 
 double AnnotQuadrilaterals::getX4(int quadrilateral) {
   if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
-    return quadrilaterals[quadrilateral]->getX4();
+    return quadrilaterals[quadrilateral]->x4;
   return 0;
 }
 
 double AnnotQuadrilaterals::getY4(int quadrilateral) {
   if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
-    return quadrilaterals[quadrilateral]->getY4();
+    return quadrilaterals[quadrilateral]->y4;
   return 0;
 }
 
@@ -525,6 +525,155 @@ AnnotBorderStyle::~AnnotBorderStyle() {
 }
 
 //------------------------------------------------------------------------
+// AnnotIconFit
+//------------------------------------------------------------------------
+
+AnnotIconFit::AnnotIconFit(Dict* dict) {
+  Object obj1;
+
+  if (dict->lookup("SW", &obj1)->isName()) {
+    GooString *scaleName = new GooString(obj1.getName());
+
+    if(!scaleName->cmp("B")) {
+      scaleWhen = scaleBigger;
+    } else if(!scaleName->cmp("S")) {
+      scaleWhen = scaleSmaller;
+    } else if(!scaleName->cmp("N")) {
+      scaleWhen = scaleNever;
+    } else {
+      scaleWhen = scaleAlways;
+    }
+    delete scaleName;
+  } else {
+    scaleWhen = scaleAlways;
+  }
+  obj1.free();
+
+  if (dict->lookup("S", &obj1)->isName()) {
+    GooString *scaleName = new GooString(obj1.getName());
+
+    if(!scaleName->cmp("A")) {
+      scale = scaleAnamorphic;
+    } else {
+      scale = scaleProportional;
+    }
+    delete scaleName;
+  } else {
+    scale = scaleProportional;
+  }
+  obj1.free();
+
+  if (dict->lookup("A", &obj1)->isArray() && obj1.arrayGetLength() == 2) {
+    Object obj2;
+    (obj1.arrayGet(0, &obj2)->isNum() ? left = obj2.getNum() : left = 0);
+    obj2.free();
+    (obj1.arrayGet(1, &obj2)->isNum() ? bottom = obj2.getNum() : bottom = 0);
+    obj2.free();
+
+    if (left < 0 || left > 1)
+      left = 0.5;
+
+    if (bottom < 0 || bottom > 1)
+      bottom = 0.5;
+
+  } else {
+    left = bottom = 0.5;
+  }
+  obj1.free();
+
+  if (dict->lookup("FB", &obj1)->isBool()) {
+    fullyBounds = obj1.getBool();
+  } else {
+    fullyBounds = gFalse;
+  }
+  obj1.free();
+}
+
+//------------------------------------------------------------------------
+// AnnotAppearanceCharacs
+//------------------------------------------------------------------------
+
+AnnotAppearanceCharacs::AnnotAppearanceCharacs(Dict *dict) {
+  Object obj1;
+
+  if (dict->lookup("R", &obj1)->isInt()) {
+    rotation = obj1.getInt();
+  } else {
+    rotation = 0;
+  }
+  obj1.free();
+
+  if (dict->lookup("BC", &obj1)->isArray()) {
+    borderColor = new AnnotColor(obj1.getArray());
+  } else {
+    borderColor = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("BG", &obj1)->isArray()) {
+    backColor = new AnnotColor(obj1.getArray());
+  } else {
+    backColor = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("CA", &obj1)->isName()) {
+    normalCaption = new GooString(obj1.getName());
+  } else {
+    normalCaption = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("RC", &obj1)->isName()) {
+    rolloverCaption = new GooString(obj1.getName());
+  } else {
+    rolloverCaption = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("AC", &obj1)->isName()) {
+    alternateCaption = new GooString(obj1.getName());
+  } else {
+    alternateCaption = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("IF", &obj1)->isDict()) {
+    iconFit = new AnnotIconFit(obj1.getDict());
+  } else {
+    iconFit = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("TP", &obj1)->isInt()) {
+    position = (AnnotAppearanceCharacsTextPos) obj1.getInt();
+  } else {
+    position = captionNoIcon;
+  }
+  obj1.free();
+}
+
+AnnotAppearanceCharacs::~AnnotAppearanceCharacs() {
+  if (borderColor)
+    delete borderColor;
+
+  if (backColor)
+    delete backColor;
+
+  if (normalCaption)
+    delete normalCaption;
+
+  if (rolloverCaption)
+    delete rolloverCaption;
+
+  if (alternateCaption)
+    delete alternateCaption;
+
+  if (iconFit)
+    delete iconFit;
+}
+
+//------------------------------------------------------------------------
 // Annot
 //------------------------------------------------------------------------
 
@@ -2616,6 +2765,80 @@ AnnotTextMarkup::~AnnotTextMarkup() {
 }
 
 //------------------------------------------------------------------------
+// AnnotWidget
+//------------------------------------------------------------------------
+
+AnnotWidget::AnnotWidget(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj) :
+    Annot(xrefA, acroForm, dict, catalog, obj) {
+  type = typeWidget;
+  initialize(xrefA, catalog, dict);
+}
+
+AnnotWidget::~AnnotWidget() {
+  if (appearCharacs)
+    delete appearCharacs;
+  
+  if (action)
+    delete action;
+    
+  if (additionActions)
+    delete additionActions;
+    
+  if (parent)
+    delete parent;
+}
+
+void AnnotWidget::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
+  Object obj1;
+
+  if(dict->lookup("H", &obj1)->isName()) {
+    GooString *modeName = new GooString(obj1.getName());
+
+    if(modeName->cmp("N")) {
+      mode = highlightModeNone;
+    } else if(modeName->cmp("O")) {
+      mode = highlightModeOutline;
+    } else if(modeName->cmp("P") || modeName->cmp("T")) {
+      mode = highlightModePush;
+    } else {
+      mode = highlightModeInvert;
+    }
+    delete modeName;
+  } else {
+    mode = highlightModeInvert;
+  }
+  obj1.free();
+
+  if(dict->lookup("MK", &obj1)->isDict()) {
+    appearCharacs = new AnnotAppearanceCharacs(obj1.getDict());
+  } else {
+    appearCharacs = NULL;
+  }
+  obj1.free();
+
+  if(dict->lookup("A", &obj1)->isDict()) {
+    action = NULL;
+  } else {
+    action = NULL;
+  }
+  obj1.free();
+
+  if(dict->lookup("AA", &obj1)->isDict()) {
+    additionActions = NULL;
+  } else {
+    additionActions = NULL;
+  }
+  obj1.free();
+
+  if(dict->lookup("Parent", &obj1)->isDict()) {
+    parent = NULL;
+  } else {
+    parent = NULL;
+  }
+  obj1.free();
+}
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
@@ -2671,7 +2894,7 @@ Annot *Annots::createAnnot(XRef *xref, Dict *acroForm, Dict* dict, Catalog *cata
     } else if (!typeName->cmp("FreeText")) {
       annot = new AnnotFreeText(xref, acroForm, dict, catalog, obj);
     } else if (!typeName->cmp("Line")) {
-      annot = new Annot(xref, acroForm, dict, catalog, obj);
+      annot = new AnnotLine(xref, acroForm, dict, catalog, obj);
     } else if (!typeName->cmp("Square")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
     } else if (!typeName->cmp("Circle")) {
@@ -2701,7 +2924,7 @@ Annot *Annots::createAnnot(XRef *xref, Dict *acroForm, Dict* dict, Catalog *cata
     } 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);
+      annot = new AnnotWidget(xref, acroForm, dict, catalog, obj);
     } else if (!typeName->cmp("Screen")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
     } else if (!typeName->cmp("PrinterMark")) {
diff --git a/poppler/Annot.h b/poppler/Annot.h
index e787fee..0ae07e8 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -111,16 +111,6 @@ class AnnotQuadrilaterals {
     AnnotQuadrilateral(double x1, double y1, double x2, double y2, double x3,
       double y3, double x4, double y4);
 
-    double getX1() const { return x1; }
-    double getY1() const { return y1; }
-    double getX2() const { return x2; }
-    double getY2() const { return y2; }
-    double getX3() const { return x3; }
-    double getY3() const { return y3; }
-    double getX4() const { return x4; }
-    double getY4() const { return y4; }
-
-  protected:
     double x1, y1, x2, y2, x3, y3, x4, y4;
   };
 
@@ -295,6 +285,102 @@ private:
 };
 
 //------------------------------------------------------------------------
+// AnnotIconFit
+//------------------------------------------------------------------------
+
+class AnnotIconFit {
+public:
+
+  enum AnnotIconFitScaleWhen {
+    scaleAlways,  // A
+    scaleBigger,  // B
+    scaleSmaller, // S
+    scaleNever    // N
+  };
+
+  enum AnnotIconFitScale {
+    scaleAnamorphic,  // A
+    scaleProportional // P
+  };
+
+  AnnotIconFit(Dict *dict);
+
+  AnnotIconFitScaleWhen getScaleWhen() { return scaleWhen; }
+  AnnotIconFitScale getScale() { return scale; }
+  double getLeft() { return left; }
+  double getBottom() { return bottom; }
+  bool getFullyBounds() { return fullyBounds; }
+
+protected:
+
+  AnnotIconFitScaleWhen scaleWhen;  // SW (Default A)
+  AnnotIconFitScale scale;          // S  (Default P)
+  double left;                      // A  (Default [0.5 0.5]
+  double bottom;                    // Only if scale is P
+  bool fullyBounds;                 // FB (Default false)
+};
+
+//------------------------------------------------------------------------
+// AnnotAppearance
+//------------------------------------------------------------------------
+
+class AnnotAppearance {
+public:
+
+  enum AnnotAppearanceType {
+    appearNormal,
+    appearRollover,
+    appearDown
+  };
+
+  AnnotAppearance(Dict *dict);
+};
+
+//------------------------------------------------------------------------
+// AnnotAppearanceCharacs
+//------------------------------------------------------------------------
+
+class AnnotAppearanceCharacs {
+public:
+
+  enum AnnotAppearanceCharacsTextPos {
+    captionNoIcon,    // 0
+    captionNoCaption, // 1
+    captionBelow,     // 2
+    captionAbove,     // 3
+    captionRight,     // 4
+    captionLeft,      // 5
+    captionOverlaid   // 6
+  };
+
+  AnnotAppearanceCharacs(Dict *dict);
+  ~AnnotAppearanceCharacs();
+
+  int getRotation() { return rotation; }
+  AnnotColor *getBorderColor() { return borderColor; }
+  AnnotColor *getBackColor() { return backColor; }
+  GooString *getNormalCaption() { return normalCaption; }
+  GooString *getRolloverCaption() { return rolloverCaption; }
+  GooString *getAlternateCaption() { return alternateCaption; }
+  AnnotIconFit *getIconFit() { return iconFit; }
+  AnnotAppearanceCharacsTextPos getPosition() { return position; }
+
+protected:
+
+  int rotation;                           // R  (Default 0)
+  AnnotColor *borderColor;                // BC
+  AnnotColor *backColor;                  // BG
+  GooString *normalCaption;               // CA
+  GooString *rolloverCaption;             // RC
+  GooString *alternateCaption;            // AC
+  // I
+  // RI
+  // IX
+  AnnotIconFit *iconFit;                  // IF
+  AnnotAppearanceCharacsTextPos position; // TP (Default 0)
+};
+
+//------------------------------------------------------------------------
 // Annot
 //------------------------------------------------------------------------
 
@@ -711,6 +797,42 @@ protected:
 };
 
 //------------------------------------------------------------------------
+// AnnotWidget
+//------------------------------------------------------------------------
+
+class AnnotWidget: public Annot {
+public:
+
+  enum AnnotWidgetHighlightMode {
+    highlightModeNone,    // N
+    highlightModeInvert,  // I
+    highlightModeOutline, // O
+    highlightModePush     // P,T
+  };
+
+  AnnotWidget(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+  virtual ~AnnotWidget();
+
+  AnnotWidgetHighlightMode getMode() { return mode; }
+  AnnotAppearanceCharacs *getAppearCharacs() { return appearCharacs; }
+  Dict *getAction() { return action; }
+  Dict *getAdditionActions() { return additionActions; }
+  Dict *getParent() { return parent; }
+
+protected:
+
+  void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
+  
+  AnnotWidgetHighlightMode mode;          // H  (Default I)
+  AnnotAppearanceCharacs *appearCharacs;  // MK
+  Dict *action;                           // A
+  Dict *additionActions;                  // AA
+  // inherited  from Annot
+  // AnnotBorderBS border;                // BS
+  Dict *parent;                           // Parent
+};
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
commit 0e91a3973e525d65236d15930a8ea0e5bbb6a6cc
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Sat Jan 19 13:59:25 2008 +0100

    AnnotTextMarkup support and improved AnnotQuadrilaterals

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 723aade..48dd1d6 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -163,7 +163,117 @@ AnnotCalloutMultiLine::AnnotCalloutMultiLine(double x1, double y1, double x2,
 // AnnotQuadrilateral
 //------------------------------------------------------------------------
 
-AnnotQuadrilateral::AnnotQuadrilateral(double x1, double y1,
+AnnotQuadrilaterals::AnnotQuadrilaterals(Array *array, PDFRectangle *rect) {
+  int arrayLength = array->getLength();
+  GBool correct = gTrue;
+  int quadsLength = 0;
+  AnnotQuadrilateral **quads;
+  double *quadArray;
+
+  // default values
+  quadrilaterals = NULL;
+  quadrilateralsLength = 0;
+
+  if ((arrayLength % 8) == 0) {
+    int i = 0;
+
+    quadsLength = arrayLength / 8;
+    quads = (AnnotQuadrilateral **) gmallocn
+        ((quadsLength), sizeof(AnnotQuadrilateral *));
+    quadArray = (double *) gmallocn (8, sizeof(double));
+
+    while (i < (quadsLength) && correct) {
+      for (int j = 0; j < 8 && correct; j++) {
+        Object obj;
+        if (array->get(i * 8 + j, &obj)->isNum()) {
+          quadArray[j] = obj.getNum();
+          if (quadArray[j] < rect->x1 || quadArray[j] > rect->x2 ||
+              quadArray[j] < rect->y1 || quadArray[j] < rect->y2)
+            correct = gFalse;
+        } else {
+            correct = gFalse;
+        }
+      }
+
+      if (correct)
+        quads[i] = new AnnotQuadrilateral(quadArray[0], quadArray[1],
+                                          quadArray[2], quadArray[3],
+                                          quadArray[4], quadArray[5],
+                                          quadArray[6], quadArray[7]);
+      i++;
+    }
+
+    gfree (quadArray);
+
+    if (correct) {
+      quadrilateralsLength = quadsLength;
+      quadrilaterals = quads;
+    } else {
+      for (int j = 0; j < i; j++)
+        delete quads[j];
+      gfree (quads);
+    }
+  }
+}
+
+AnnotQuadrilaterals::~AnnotQuadrilaterals() {
+  if (quadrilaterals) {
+    for(int i = 0; i < quadrilateralsLength; i++)
+      delete quadrilaterals[i];
+
+    gfree (quadrilaterals);
+  }
+}
+
+double AnnotQuadrilaterals::getX1(int quadrilateral) {
+  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
+    return quadrilaterals[quadrilateral]->getX1();
+  return 0;
+}
+
+double AnnotQuadrilaterals::getY1(int quadrilateral) {
+  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
+    return quadrilaterals[quadrilateral]->getY1();
+  return 0;
+}
+
+double AnnotQuadrilaterals::getX2(int quadrilateral) {
+  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
+    return quadrilaterals[quadrilateral]->getX2();
+  return 0;
+}
+
+double AnnotQuadrilaterals::getY2(int quadrilateral) {
+  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
+    return quadrilaterals[quadrilateral]->getY2();
+  return 0;
+}
+
+double AnnotQuadrilaterals::getX3(int quadrilateral) {
+  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
+    return quadrilaterals[quadrilateral]->getX3();
+  return 0;
+}
+
+double AnnotQuadrilaterals::getY3(int quadrilateral) {
+  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
+    return quadrilaterals[quadrilateral]->getY3();
+  return 0;
+}
+
+double AnnotQuadrilaterals::getX4(int quadrilateral) {
+  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
+    return quadrilaterals[quadrilateral]->getX4();
+  return 0;
+}
+
+double AnnotQuadrilaterals::getY4(int quadrilateral) {
+  if (quadrilateral >= 0  && quadrilateral < quadrilateralsLength)
+    return quadrilaterals[quadrilateral]->getY4();
+  return 0;
+}
+
+AnnotQuadrilaterals::AnnotQuadrilateral::AnnotQuadrilateral(double x1, double y1,
         double x2, double y2, double x3, double y3, double x4, double y4) {
   this->x1 = x1;
   this->y1 = y1;
@@ -2129,12 +2239,8 @@ AnnotLink::~AnnotLink() {
   if (uriAction)
     delete uriAction;
   */
-  if (quadrilaterals) {
-    for(int i = 0; i < quadrilateralsLength; i++)
-      delete quadrilaterals[i];
-
-    gfree (quadrilaterals);
-  }
+  if (quadrilaterals)
+    delete quadrilaterals;
 }
 
 void AnnotLink::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
@@ -2174,74 +2280,14 @@ void AnnotLink::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
   }
   obj1.free();
   */
-  /*
-   * TODO:
-   * QuadPoints should be ignored if any coordinate in the array lies outside
-   * the region specified by Rect.
-   */
   if (dict->lookup("QuadPoints", &obj1)->isArray()) {
-    parseQuadPointsArray(obj1.getArray());
+    quadrilaterals = new AnnotQuadrilaterals(obj1.getArray(), rect);
   } else {
     quadrilaterals = NULL;
   }
   obj1.free();
 }
 
-GBool AnnotLink::parseQuadPointsArray(Array *array) {
-  int arrayLength = array->getLength();
-  GBool correct = gTrue;
-  int quadsLength = 0, i = 0;
-  AnnotQuadrilateral **quads;
-  double *quadArray;
-
-  // default values
-  quadrilaterals = NULL;
-  quadrilateralsLength = 0;
-
-  if ((arrayLength % 8) != 0)
-    return gFalse;
-
-  quadsLength = arrayLength / 8;
-  quads = (AnnotQuadrilateral **) gmallocn
-      ((quadsLength), sizeof(AnnotQuadrilateral *));
-  quadArray = (double *) gmallocn (8, sizeof(double));
-
-  while (i < (quadsLength) && correct) {
-    for (int j = 0; j < 8 && correct; j++) {
-      Object obj;
-      if (array->get(i * 8 + j, &obj)->isNum()) {
-        quadArray[j] = obj.getNum();
-        if (quadArray[j] < rect->x1 || quadArray[j] > rect->x2 ||
-            quadArray[j] < rect->y1 || quadArray[j] < rect->y2)
-          correct = gFalse;
-      } else {
-          correct = gFalse;
-      }
-    }
-
-    if (correct)
-      quads[i] = new AnnotQuadrilateral(quadArray[0], quadArray[1],
-                                        quadArray[2], quadArray[3],
-                                        quadArray[4], quadArray[5],
-                                        quadArray[6], quadArray[7]);
-    i++;
-  }
-
-  gfree (quadArray);
-
-  if (!correct) {
-    for (int j = 0; j < i; j++)
-      delete quads[j];
-    gfree (quads);
-    return gFalse;
-  }
-
-  quadrilateralsLength = quadsLength;
-  quadrilaterals = quads;
-
-  return gTrue;
-}
-
 //------------------------------------------------------------------------
 // AnnotFreeText
 //------------------------------------------------------------------------
@@ -2396,6 +2442,180 @@ void AnnotFreeText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
 }
 
 //------------------------------------------------------------------------
+// AnnotLine
+//------------------------------------------------------------------------
+
+AnnotLine::AnnotLine(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj) :
+    Annot(xrefA, acroForm, dict, catalog, obj), AnnotMarkup(xref, acroForm, dict, catalog, obj) {
+  type = typeLine;
+  initialize(xrefA, catalog, dict);
+}
+
+AnnotLine::~AnnotLine() {
+  if (interiorColor)
+    delete interiorColor;
+
+  if (measure)
+    delete measure;
+}
+
+void AnnotLine::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
+  Object obj1;
+
+  if (dict->lookup("L", &obj1)->isArray() && obj1.arrayGetLength() == 4) {
+    Object obj2;
+
+    (obj1.arrayGet(0, &obj2)->isNum() ? x1 = obj2.getNum() : x1 = 0);
+    obj2.free();
+    (obj1.arrayGet(1, &obj2)->isNum() ? y1 = obj2.getNum() : y1 = 0);
+    obj2.free();
+    (obj1.arrayGet(2, &obj2)->isNum() ? x2 = obj2.getNum() : x2 = 0);
+    obj2.free();
+    (obj1.arrayGet(3, &obj2)->isNum() ? y2 = obj2.getNum() : y2 = 0);
+    obj2.free();
+
+  } else {
+    x1 = y1 = x2 = y2 = 0;
+  }
+  obj1.free();
+
+  if (dict->lookup("LE", &obj1)->isArray() && obj1.arrayGetLength() == 2) {
+    Object obj2;
+
+    if(obj1.arrayGet(0, &obj2)->isString())
+      startStyle = parseAnnotLineEndingStyle(obj2.getString());
+    else
+      startStyle = annotLineEndingNone;
+    obj2.free();
+
+    if(obj1.arrayGet(1, &obj2)->isString())
+      endStyle = parseAnnotLineEndingStyle(obj2.getString());
+    else
+      endStyle = annotLineEndingNone;
+    obj2.free();
+
+  } else {
+    startStyle = endStyle = annotLineEndingNone;
+  }
+  obj1.free();
+
+  if (dict->lookup("IC", &obj1)->isArray()) {
+    interiorColor = new AnnotColor(obj1.getArray());
+  } else {
+    interiorColor = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("LL", &obj1)->isNum()) {
+    leaderLineLength = obj1.getNum();
+  } else {
+    leaderLineLength = 0;
+  }
+  obj1.free();
+
+  if (dict->lookup("LLE", &obj1)->isNum()) {
+    leaderLineExtension = obj1.getNum();
+
+    if (leaderLineExtension < 0)
+      leaderLineExtension = 0;
+  } else {
+    leaderLineExtension = 0;
+  }
+  obj1.free();
+
+  if (dict->lookup("Cap", &obj1)->isBool()) {
+    caption = obj1.getBool();
+  } else {
+    caption = gFalse;
+  }
+  obj1.free();
+
+  if (dict->lookup("IT", &obj1)->isName()) {
+    GooString *intentName = new GooString(obj1.getName());
+
+    if(!intentName->cmp("LineArrow")) {
+      intent = intentLineArrow;
+    } else if(!intentName->cmp("LineDimension")) {
+      intent = intentLineDimension;
+    } else {
+      intent = intentLineArrow;
+    }
+    delete intentName;
+  } else {
+    intent = intentLineArrow;
+  }
+  obj1.free();
+
+  if (dict->lookup("LLO", &obj1)->isNum()) {
+    leaderLineOffset = obj1.getNum();
+
+    if (leaderLineOffset < 0)
+      leaderLineOffset = 0;
+  } else {
+    leaderLineOffset = 0;
+  }
+  obj1.free();
+
+  if (dict->lookup("CP", &obj1)->isName()) {
+    GooString *captionName = new GooString(obj1.getName());
+
+    if(!captionName->cmp("Inline")) {
+      captionPos = captionPosInline;
+    } else if(!captionName->cmp("Top")) {
+      captionPos = captionPosTop;
+    } else {
+      captionPos = captionPosInline;
+    }
+    delete captionName;
+  } else {
+    captionPos = captionPosInline;
+  }
+  obj1.free();
+
+  if (dict->lookup("Measure", &obj1)->isDict()) {
+    measure = NULL;
+  } else {
+    measure = NULL;
+  }
+  obj1.free();
+
+  if ((dict->lookup("CO", &obj1)->isArray()) && (obj1.arrayGetLength() == 2)) {
+    Object obj2;
+
+    (obj1.arrayGet(0, &obj2)->isNum() ? captionTextHorizontal = obj2.getNum() :
+      captionTextHorizontal = 0);
+    obj2.free();
+    (obj1.arrayGet(1, &obj2)->isNum() ? captionTextVertical = obj2.getNum() :
+      captionTextVertical = 0);
+    obj2.free();
+  } else {
+    captionTextHorizontal = captionTextVertical = 0;
+  }
+  obj1.free();
+}
+
+//------------------------------------------------------------------------
+// AnnotTextMarkup
+//------------------------------------------------------------------------
+
+void AnnotTextMarkup::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
+  Object obj1;
+
+  if(dict->lookup("QuadPoints", &obj1)->isArray()) {
+    quadrilaterals = new AnnotQuadrilaterals(obj1.getArray(), rect);
+  } else {
+    quadrilaterals = NULL;
+  }
+  obj1.free();
+}
+
+AnnotTextMarkup::~AnnotTextMarkup() {
+  if(quadrilaterals) {
+    delete quadrilaterals;
+  }
+}
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index b6fdf5e..e787fee 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -105,23 +105,43 @@ private:
 // AnnotQuadrilateral
 //------------------------------------------------------------------------
 
-class AnnotQuadrilateral {
-public:
-
-  AnnotQuadrilateral(double x1, double y1, double x2, double y2, double x3,
+class AnnotQuadrilaterals {
+  class AnnotQuadrilateral {
+  public:
+    AnnotQuadrilateral(double x1, double y1, double x2, double y2, double x3,
       double y3, double x4, double y4);
 
-  double getX1() const { return x1; }
-  double getY1() const { return y1; }
-  double getX2() const { return x2; }
-  double getY2() const { return y2; }
-  double getX3() const { return x3; }
-  double getY3() const { return y3; }
-  double getX4() const { return x4; }
-  double getY4() const { return y4; }
+    double getX1() const { return x1; }
+    double getY1() const { return y1; }
+    double getX2() const { return x2; }
+    double getY2() const { return y2; }
+    double getX3() const { return x3; }
+    double getY3() const { return y3; }
+    double getX4() const { return x4; }
+    double getY4() const { return y4; }
+
+  protected:
+    double x1, y1, x2, y2, x3, y3, x4, y4;
+  };
 
+public:
+
+  AnnotQuadrilaterals(Array *array, PDFRectangle *rect);
+  virtual ~AnnotQuadrilaterals();
+
+  double getX1(int quadrilateral);
+  double getY1(int quadrilateral);
+  double getX2(int quadrilateral);
+  double getY2(int quadrilateral);
+  double getX3(int quadrilateral);
+  double getY3(int quadrilateral);
+  double getX4(int quadrilateral);
+  double getY4(int quadrilateral);
+  int getQuadrilateralsLength() const { return quadrilateralsLength; }
 protected:
-  double x1, y1, x2, y2, x3, y3, x4, y4;
+
+  AnnotQuadrilateral** quadrilaterals;
+  int quadrilateralsLength;
 };
 
 //------------------------------------------------------------------------
@@ -546,21 +566,18 @@ public:
   // getDest
   AnnotLinkEffect getLinkEffect() const { return linkEffect; }
   Dict *getUriAction() const { return uriAction; }
-  AnnotQuadrilateral **getQuadrilaterals() const { return quadrilaterals; }
-  int getQuadrilateralsLength() const { return quadrilateralsLength; }
+  AnnotQuadrilaterals *getQuadrilaterals() const { return quadrilaterals; }
 
 protected:
 
   void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
-  GBool parseQuadPointsArray(Array *array);
 
   Dict *actionDict;                    // A
   //Dest
   AnnotLinkEffect linkEffect;          // H          (Default I)
   Dict *uriAction;                     // PA
 
-  AnnotQuadrilateral **quadrilaterals; // QuadPoints
-  int quadrilateralsLength;
+  AnnotQuadrilaterals *quadrilaterals; // QuadPoints
 };
 
 //------------------------------------------------------------------------
@@ -617,6 +634,83 @@ protected:
 };
 
 //------------------------------------------------------------------------
+// AnnotLine
+//------------------------------------------------------------------------
+
+class AnnotLine: public Annot, public AnnotMarkup {
+public:
+
+  enum AnnotLineIntent {
+    intentLineArrow,    // LineArrow
+    intentLineDimension // LineDimension
+  };
+
+  enum AnnotLineCaptionPos {
+    captionPosInline, // Inline
+    captionPosTop     // Top
+  };
+
+  AnnotLine(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+  virtual ~AnnotLine();
+
+  // getters
+  AnnotLineEndingStyle getStartStyle() const { return startStyle; }
+  AnnotLineEndingStyle getEndStyle() const { return endStyle; }
+  AnnotColor *getInteriorColor() const { return interiorColor; }
+  double getLeaderLineLength() const { return leaderLineLength; }
+  double getLeaderLineExtension() const { return leaderLineExtension; }
+  bool getCaption() const { return caption; }
+  AnnotLineIntent getIntent() const { return intent; }
+  double  getLeaderLineOffset() const { return leaderLineOffset; }
+  AnnotLineCaptionPos getCaptionPos() const { return captionPos; }
+  Dict *getMeasure() const { return measure; }
+  double getCaptionTextHorizontal() const { return captionTextHorizontal; }
+  double getCaptionTextVertical() const { return captionTextVertical; }
+
+protected:
+
+  void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
+
+  // required
+  double x1, y1, x2, y2;            // L
+  
+  // optional
+  // inherited  from Annot
+  // AnnotBorderBS border;          // BS
+  AnnotLineEndingStyle startStyle;  // LE       (Default [/None /None])
+  AnnotLineEndingStyle endStyle;    //
+  AnnotColor *interiorColor;        // IC
+  double leaderLineLength;          // LL       (Default 0)
+  double leaderLineExtension;       // LLE      (Default 0)
+  bool caption;                     // Cap      (Default false)
+  AnnotLineIntent intent;           // IT
+  double leaderLineOffset;          // LLO
+  AnnotLineCaptionPos captionPos;   // CP       (Default Inline)
+  Dict *measure;                    // Measure
+  double captionTextHorizontal;     // CO       (Default [0, 0])
+  double captionTextVertical;       //
+};
+
+//------------------------------------------------------------------------
+// AnnotTextMarkup
+//------------------------------------------------------------------------
+
+class AnnotTextMarkup: public Annot, public AnnotMarkup {
+public:
+
+  AnnotTextMarkup(XRef *xrefA, Catalog *catalog, Dict *dict);
+  virtual ~AnnotTextMarkup();
+
+  AnnotQuadrilaterals *getQuadrilaterals() const { return quadrilaterals; }
+
+protected:
+
+  void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
+  
+  AnnotQuadrilaterals *quadrilaterals; // QuadPoints
+};
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
commit c13952cd56a40bad14a1bf28699b137f65162f10
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Sat Jan 19 13:59:02 2008 +0100

    Changed AnnotQuadrilateral parsing inside AnnotLink

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index b21e2f1..723aade 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -62,24 +62,24 @@
 #define bezierCircle 0.55228475
 
 AnnotLineEndingStyle parseAnnotLineEndingStyle(GooString *string) {
-  if(string != NULL) {
-    if(string->cmp("Square")) {
+  if (string != NULL) {
+    if (string->cmp("Square")) {
       return annotLineEndingSquare;
-    } else if(string->cmp("Circle")) {
+    } else if (string->cmp("Circle")) {
       return annotLineEndingCircle;
-    } else if(string->cmp("Diamond")) {
+    } else if (string->cmp("Diamond")) {
       return annotLineEndingDiamond;
-    } else if(string->cmp("OpenArrow")) {
+    } else if (string->cmp("OpenArrow")) {
       return annotLineEndingOpenArrow;
-    } else if(string->cmp("ClosedArrow")) {
+    } else if (string->cmp("ClosedArrow")) {
       return annotLineEndingClosedArrow;
-    } else if(string->cmp("Butt")) {
+    } else if (string->cmp("Butt")) {
       return annotLineEndingButt;
-    } else if(string->cmp("ROpenArrow")) {
+    } else if (string->cmp("ROpenArrow")) {
       return annotLineEndingROpenArrow;
-    } else if(string->cmp("RClosedArrow")) {
+    } else if (string->cmp("RClosedArrow")) {
       return annotLineEndingRClosedArrow;
-    } else if(string->cmp("Slash")) {
+    } else if (string->cmp("Slash")) {
       return annotLineEndingSlash;
     } else {
       return annotLineEndingNone;
@@ -96,7 +96,7 @@ AnnotExternalDataType parseAnnotExternalData(Dict* dict) {
   if (dict->lookup("Subtype", &obj1)->isName()) {
     GooString *typeName = new GooString(obj1.getName());
 
-    if(!typeName->cmp("Markup3D")) {
+    if (!typeName->cmp("Markup3D")) {
       type = annotExternalDataMarkup3D;
     } else {
       type = annotExternalDataMarkupUnknown;
@@ -120,7 +120,7 @@ AnnotBorderEffect::AnnotBorderEffect(Dict *dict) {
   if (dict->lookup("S", &obj1)->isName()) {
     GooString *effectName = new GooString(obj1.getName());
 
-    if(!effectName->cmp("C"))
+    if (!effectName->cmp("C"))
       effectType = borderEffectCloudy;
     else
       effectType = borderEffectNoEffect;
@@ -160,11 +160,11 @@ AnnotCalloutMultiLine::AnnotCalloutMultiLine(double x1, double y1, double x2,
 }
 
 //------------------------------------------------------------------------
-// AnnotQuadPoints
+// AnnotQuadrilateral
 //------------------------------------------------------------------------
 
-AnnotQuadPoints::AnnotQuadPoints(double x1, double y1, double x2, double y2,
-    double x3, double y3, double x4, double y4) {
+AnnotQuadrilateral::AnnotQuadrilateral(double x1, double y1,
+        double x2, double y2, double x3, double y3, double x4, double y4) {
   this->x1 = x1;
   this->y1 = y1;
   this->x2 = x2;
@@ -222,27 +222,27 @@ AnnotBorderArray::AnnotBorderArray(Array *array) {
   if (arrayLength >= 3) {
     // implementation note 81 in Appendix H.
 
-    if(array->get(0, &obj1)->isNum())
+    if (array->get(0, &obj1)->isNum())
       horizontalCorner = obj1.getNum();
     obj1.free();
 
-    if(array->get(1, &obj1)->isNum())
+    if (array->get(1, &obj1)->isNum())
       verticalCorner = obj1.getNum();
     obj1.free();
 
-    if(array->get(2, &obj1)->isNum())
+    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) {
+    if (arrayLength > 3) {
       GBool correct = gTrue;
       int tempLength = array->getLength() - 3;
       double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
 
       for(int i = 0; i < tempLength && i < DASH_LIMIT && correct; i++) {
 
-        if(array->get((i + 3), &obj1)->isNum()) {
+        if (array->get((i + 3), &obj1)->isNum()) {
           tempDash[i] = obj1.getNum();
 
           if (tempDash[i] < 0)
@@ -288,15 +288,15 @@ AnnotBorderBS::AnnotBorderBS(Dict *dict) {
 
     width = obj1.getNum();
 
-    if(!styleName->cmp("S")) {
+    if (!styleName->cmp("S")) {
       style = borderSolid;
-    } else if(!styleName->cmp("D")) {
+    } else if (!styleName->cmp("D")) {
       style = borderDashed;
-    } else if(!styleName->cmp("B")) {
+    } else if (!styleName->cmp("B")) {
       style = borderBeveled;
-    } else if(!styleName->cmp("I")) {
+    } else if (!styleName->cmp("I")) {
       style = borderInset;
-    } else if(!styleName->cmp("U")) {
+    } else if (!styleName->cmp("U")) {
       style = borderUnderlined;
     } else {
       style = borderSolid;
@@ -317,10 +317,10 @@ AnnotBorderBS::AnnotBorderBS(Dict *dict) {
     for(int i = 0; i < tempLength && correct; i++) {
       Object obj2;
 
-      if(obj1.arrayGet(i, &obj2)->isNum()) {
+      if (obj1.arrayGet(i, &obj2)->isNum()) {
         tempDash[i] = obj2.getNum();
 
-        if(tempDash[i] < 0)
+        if (tempDash[i] < 0)
           correct = gFalse;
       } else {
         correct = gFalse;
@@ -364,7 +364,7 @@ AnnotColor::AnnotColor(Array *array) {
     for(int i = 0; i < length; i++) {  
       Object obj1;
 
-      if(array->get(i, &obj1)->isNum()) {
+      if (array->get(i, &obj1)->isNum()) {
         values[i] = obj1.getNum();
 
         if (values[i] < 0 || values[i] > 1)
@@ -382,13 +382,13 @@ AnnotColor::AnnotColorSpace AnnotColor::getSpace() const {
 }
 
 double AnnotColor::getValue(int i) const {
-  if(i >= 0 && i < length) 
+  if (i >= 0 && i < length) 
     return values[i];
   return 0;
 }
 
 AnnotColor::~AnnotColor() {
-  if(values)
+  if (values)
     gfree (values);
 }
 
@@ -653,7 +653,7 @@ Annot::~Annot() {
   if (pageDict)
     delete pageDict;
 
-  if(name)
+  if (name)
     delete name;
 
   if (modified)
@@ -661,7 +661,7 @@ Annot::~Annot() {
 
   appearance.free();
 
-  if(appearState)
+  if (appearState)
     delete appearState;
 
   if (border)
@@ -1880,14 +1880,14 @@ AnnotPopup::~AnnotPopup() {
 void AnnotPopup::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog) {
   Object obj1;
   /*
-  if(dict->lookup("Parent", &obj1)->isDict()) {
+  if (dict->lookup("Parent", &obj1)->isDict()) {
     parent = NULL;
   } else {
     parent = NULL;
   }
   obj1.free();
   */
-  if(dict->lookup("Open", &obj1)->isBool()) {
+  if (dict->lookup("Open", &obj1)->isBool()) {
     open = obj1.getBool();
   } else {
     open = gFalse;
@@ -1968,9 +1968,9 @@ void AnnotMarkup::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *c
   if (dict->lookup("RT", &obj1)->isName()) {
     GooString *replyName = new GooString(obj1.getName());
 
-    if(!replyName->cmp("R")) {
+    if (!replyName->cmp("R")) {
       replyTo = replyTypeR;
-    } else if(!replyName->cmp("Group")) {
+    } else if (!replyName->cmp("Group")) {
       replyTo = replyTypeGroup;
     } else {
       replyTo = replyTypeR;
@@ -2002,7 +2002,7 @@ AnnotText::AnnotText(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog,
 }
 
 void AnnotText::setModified(GooString *date) {
-  if(date) {
+  if (date) {
     delete modified;
     modified = new GooString(date);
   }
@@ -2020,17 +2020,17 @@ void AnnotText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
   if (dict->lookup("Name", &obj1)->isName()) {
     GooString *iconName = new GooString(obj1.getName());
 
-    if(!iconName->cmp("Comment")) {
+    if (!iconName->cmp("Comment")) {
       icon = iconComment;
-    } else if(!iconName->cmp("Key")) {
+    } else if (!iconName->cmp("Key")) {
       icon = iconKey;
-    } else if(!iconName->cmp("Help")) {
+    } else if (!iconName->cmp("Help")) {
       icon = iconHelp;
-    } else if(!iconName->cmp("NewParagraph")) {
+    } else if (!iconName->cmp("NewParagraph")) {
       icon = iconNewParagraph;
-    } else if(!iconName->cmp("Paragraph")) {
+    } else if (!iconName->cmp("Paragraph")) {
       icon = iconParagraph;
-    } else if(!iconName->cmp("Insert")) {
+    } else if (!iconName->cmp("Insert")) {
       icon = iconInsert;
     } else {
       icon = iconNote;
@@ -2048,19 +2048,19 @@ void AnnotText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     if (dict->lookup("State", &obj2)->isString()) {
       GooString *stateName = obj2.getString();
 
-      if(!stateName->cmp("Marked")) {
+      if (!stateName->cmp("Marked")) {
         state = stateMarked;
-      } else if(!stateName->cmp("Unmarked")) {
+      } else if (!stateName->cmp("Unmarked")) {
         state = stateUnmarked;
-      } else if(!stateName->cmp("Accepted")) {
+      } else if (!stateName->cmp("Accepted")) {
         state = stateAccepted;
-      } else if(!stateName->cmp("Rejected")) {
+      } else if (!stateName->cmp("Rejected")) {
         state = stateRejected;
-      } else if(!stateName->cmp("Cancelled")) {
+      } else if (!stateName->cmp("Cancelled")) {
         state = stateCancelled;
-      } else if(!stateName->cmp("Completed")) {
+      } else if (!stateName->cmp("Completed")) {
         state = stateCompleted;
-      } else if(!stateName->cmp("None")) {
+      } else if (!stateName->cmp("None")) {
         state = stateNone;
       } else {
         state = stateUnknown;
@@ -2072,7 +2072,7 @@ void AnnotText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     }
     obj2.free();
 
-    if(!modelName->cmp("Marked")) {
+    if (!modelName->cmp("Marked")) {
       switch (state) {
         case stateUnknown:
           state = stateMarked;
@@ -2087,7 +2087,7 @@ void AnnotText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
         default:
           break;
       }
-    } else if(!modelName->cmp("Review")) {
+    } else if (!modelName->cmp("Review")) {
       switch (state) {
         case stateUnknown:
           state = stateNone;
@@ -2129,7 +2129,7 @@ AnnotLink::~AnnotLink() {
   if (uriAction)
     delete uriAction;
   */
-  if(quadrilaterals) {
+  if (quadrilaterals) {
     for(int i = 0; i < quadrilateralsLength; i++)
       delete quadrilaterals[i];
 
@@ -2179,47 +2179,69 @@ void AnnotLink::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
    * QuadPoints should be ignored if any coordinate in the array lies outside
    * the region specified by Rect.
    */
-  if(dict->lookup("QuadPoints", &obj1)->isArray()) {
-    quadrilateralsLength = obj1.arrayGetLength();
-    if((quadrilateralsLength % 8) == 0) {
-      Object obj2;
-
-      quadrilaterals = (AnnotQuadPoints **) gmallocn
-        ((quadrilateralsLength / 8), sizeof(AnnotQuadPoints *));
-      for(int i = 0; i < quadrilateralsLength; i += 8) {
-        double x1, y1, x2, y2, x3, y3, x4, y4;
-
-        (obj1.arrayGet(i, &obj2)->isNum() ? x1 = obj2.getNum() : x1 = 0);
-        obj2.free();
-        (obj1.arrayGet((i + 1), &obj2)->isNum() ? y1 = obj2.getNum() : y1 = 0);
-        obj2.free();
-        (obj1.arrayGet((i + 2), &obj2)->isNum() ? x2 = obj2.getNum() : x2 = 0);
-        obj2.free();
-        (obj1.arrayGet((i + 3), &obj2)->isNum() ? y2 = obj2.getNum() : y2 = 0);
-        obj2.free();
-        (obj1.arrayGet((i + 4), &obj2)->isNum() ? x3 = obj2.getNum() : x3 = 0);
-        obj2.free();
-        (obj1.arrayGet((i + 5), &obj2)->isNum() ? y3 = obj2.getNum() : y3 = 0);
-        obj2.free();
-        (obj1.arrayGet((i + 6), &obj2)->isNum() ? x4 = obj2.getNum() : x4 = 0);
-        obj2.free();
-        (obj1.arrayGet((i + 7), &obj2)->isNum() ? y4 = obj2.getNum() : y4 = 0);
-        obj2.free();
-
-        quadrilaterals[i / 8] =
-          new AnnotQuadPoints(x1, y1, x2, y2, x3, y3, x4, y4);
-      }
-      quadrilateralsLength /= 8;
-    } else {
-      quadrilaterals = NULL;
-      quadrilateralsLength = 0;
-    }
+  if (dict->lookup("QuadPoints", &obj1)->isArray()) {
+    parseQuadPointsArray(obj1.getArray());
   } else {
     quadrilaterals = NULL;
   }
   obj1.free();
 }
 
+GBool AnnotLink::parseQuadPointsArray(Array *array) {
+  int arrayLength = array->getLength();
+  GBool correct = gTrue;
+  int quadsLength = 0, i = 0;
+  AnnotQuadrilateral **quads;
+  double *quadArray;
+
+  // default values
+  quadrilaterals = NULL;
+  quadrilateralsLength = 0;
+
+  if ((arrayLength % 8) != 0)
+    return gFalse;
+
+  quadsLength = arrayLength / 8;
+  quads = (AnnotQuadrilateral **) gmallocn
+      ((quadsLength), sizeof(AnnotQuadrilateral *));
+  quadArray = (double *) gmallocn (8, sizeof(double));
+
+  while (i < (quadsLength) && correct) {
+    for (int j = 0; j < 8 && correct; j++) {
+      Object obj;
+      if (array->get(i * 8 + j, &obj)->isNum()) {
+        quadArray[j] = obj.getNum();
+        if (quadArray[j] < rect->x1 || quadArray[j] > rect->x2 ||
+            quadArray[j] < rect->y1 || quadArray[j] < rect->y2)
+          correct = gFalse;
+      } else {
+          correct = gFalse;
+      }
+    }
+
+    if (correct)
+      quads[i] = new AnnotQuadrilateral(quadArray[0], quadArray[1],
+                                        quadArray[2], quadArray[3],
+                                        quadArray[4], quadArray[5],
+                                        quadArray[6], quadArray[7]);
+    i++;
+  }
+
+  gfree (quadArray);
+
+  if (!correct) {
+    for (int j = 0; j < i; j++)
+      delete quads[j];
+    gfree (quads);
+    return gFalse;
+  }
+
+  quadrilateralsLength = quadsLength;
+  quadrilaterals = quads;
+
+  return gTrue;
+}
+
 //------------------------------------------------------------------------
 // AnnotFreeText
 //------------------------------------------------------------------------
@@ -2285,7 +2307,7 @@ void AnnotFreeText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     (obj1.arrayGet(3, &obj2)->isNum() ? y2 = obj2.getNum() : y2 = 0);
     obj2.free();
 
-    if(obj1.arrayGetLength() == 6) {
+    if (obj1.arrayGetLength() == 6) {
       double x3, y3;
       (obj1.arrayGet(4, &obj2)->isNum() ? x3 = obj2.getNum() : x3 = 0);
       obj2.free();
@@ -2424,51 +2446,51 @@ Annot *Annots::createAnnot(XRef *xref, Dict *acroForm, Dict* dict, Catalog *cata
 
     if (!typeName->cmp("Text")) {
       annot = new AnnotText(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Link")) {
+    } else if (!typeName->cmp("Link")) {
       annot = new AnnotLink(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("FreeText")) {
+    } else if (!typeName->cmp("FreeText")) {
       annot = new AnnotFreeText(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Line")) {
+    } else if (!typeName->cmp("Line")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Square")) {
+    } else if (!typeName->cmp("Square")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Circle")) {
+    } else if (!typeName->cmp("Circle")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Polygon")) {
+    } else if (!typeName->cmp("Polygon")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("PolyLine")) {
+    } else if (!typeName->cmp("PolyLine")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Highlight")) {
+    } else if (!typeName->cmp("Highlight")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Underline")) {
+    } else if (!typeName->cmp("Underline")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Squiggly")) {
+    } else if (!typeName->cmp("Squiggly")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("StrikeOut")) {
+    } else if (!typeName->cmp("StrikeOut")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Stamp")) {
+    } else if (!typeName->cmp("Stamp")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Caret")) {
+    } else if (!typeName->cmp("Caret")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Ink")) {
+    } else if (!typeName->cmp("Ink")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("FileAttachment")) {
+    } else if (!typeName->cmp("FileAttachment")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Sound")) {
+    } else if (!typeName->cmp("Sound")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Movie")) {
+    } else if (!typeName->cmp("Movie")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Widget")) {
+    } else if (!typeName->cmp("Widget")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Screen")) {
+    } else if (!typeName->cmp("Screen")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("PrinterMark")) {
+    } else if (!typeName->cmp("PrinterMark")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("TrapNet")) {
+    } else if (!typeName->cmp("TrapNet")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("Watermark")) {
+    } else if (!typeName->cmp("Watermark")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
-    } else if(!typeName->cmp("3D")) {
+    } else if (!typeName->cmp("3D")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
     } else {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 92a3661..b6fdf5e 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -102,13 +102,13 @@ private:
 };
 
 //------------------------------------------------------------------------
-// AnnotQuadPoints
+// AnnotQuadrilateral
 //------------------------------------------------------------------------
 
-class AnnotQuadPoints {
+class AnnotQuadrilateral {
 public:
-  
-  AnnotQuadPoints(double x1, double y1, double x2, double y2, double x3,
+
+  AnnotQuadrilateral(double x1, double y1, double x2, double y2, double x3,
       double y3, double x4, double y4);
 
   double getX1() const { return x1; }
@@ -546,19 +546,20 @@ public:
   // getDest
   AnnotLinkEffect getLinkEffect() const { return linkEffect; }
   Dict *getUriAction() const { return uriAction; }
-  AnnotQuadPoints **getQuadrilaterals() const { return quadrilaterals; }
+  AnnotQuadrilateral **getQuadrilaterals() const { return quadrilaterals; }
   int getQuadrilateralsLength() const { return quadrilateralsLength; }
 
 protected:
 
   void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
+  GBool parseQuadPointsArray(Array *array);
 
-  Dict *actionDict;                 // A
+  Dict *actionDict;                    // A
   //Dest
-  AnnotLinkEffect linkEffect;       // H          (Default I)
-  Dict *uriAction;                  // PA
+  AnnotLinkEffect linkEffect;          // H          (Default I)
+  Dict *uriAction;                     // PA
 
-  AnnotQuadPoints **quadrilaterals; // QuadPoints
+  AnnotQuadrilateral **quadrilaterals; // QuadPoints
   int quadrilateralsLength;
 };
 
commit 2f821f10fbbba9363405201c86494cd861cec2b2
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Sat Jan 19 13:49:43 2008 +0100

    Add AnnotQuadPoints class

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 542f11f..b21e2f1 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -176,6 +176,22 @@ AnnotQuadPoints::AnnotQuadPoints(double x1, double y1, double x2, double y2,
 }
 
 //------------------------------------------------------------------------
+// AnnotQuadPoints
+//------------------------------------------------------------------------
+
+AnnotQuadPoints::AnnotQuadPoints(double x1, double y1, double x2, double y2,
+    double x3, double y3, double x4, double y4) {
+  this->x1 = x1;
+  this->y1 = y1;
+  this->x2 = x2;
+  this->y2 = y2;
+  this->x3 = x3;
+  this->y3 = y3;
+  this->x4 = x4;
+  this->y4 = y4;
+}
+
+//------------------------------------------------------------------------
 // AnnotBorder
 //------------------------------------------------------------------------
 AnnotBorder::AnnotBorder() {
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 5e5f475..92a3661 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -125,6 +125,29 @@ protected:
 };
 
 //------------------------------------------------------------------------
+// AnnotQuadPoints
+//------------------------------------------------------------------------
+
+class AnnotQuadPoints {
+public:
+  
+  AnnotQuadPoints(double x1, double y1, double x2, double y2, double x3,
+      double y3, double x4, double y4);
+
+  double getX1() const { return x1; }
+  double getY1() const { return y1; }
+  double getX2() const { return x2; }
+  double getY2() const { return y2; }
+  double getX3() const { return x3; }
+  double getY3() const { return y3; }
+  double getX4() const { return x4; }
+  double getY4() const { return y4; }
+
+protected:
+  double x1, y1, x2, y2, x3, y3, x4, y4;
+};
+
+//------------------------------------------------------------------------
 // AnnotBorder
 //------------------------------------------------------------------------
 
commit de4c8fa6607e55c199bede1dc731227692ef4f53
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Sun Dec 30 21:21:56 2007 +0100

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

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 7f2a375..542f11f 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -61,6 +61,34 @@
 // = (4 * (sqrt(2) - 1) / 3) * r
 #define bezierCircle 0.55228475
 
+AnnotLineEndingStyle parseAnnotLineEndingStyle(GooString *string) {
+  if(string != NULL) {
+    if(string->cmp("Square")) {
+      return annotLineEndingSquare;
+    } else if(string->cmp("Circle")) {
+      return annotLineEndingCircle;
+    } else if(string->cmp("Diamond")) {
+      return annotLineEndingDiamond;
+    } else if(string->cmp("OpenArrow")) {
+      return annotLineEndingOpenArrow;
+    } else if(string->cmp("ClosedArrow")) {
+      return annotLineEndingClosedArrow;
+    } else if(string->cmp("Butt")) {
+      return annotLineEndingButt;
+    } else if(string->cmp("ROpenArrow")) {
+      return annotLineEndingROpenArrow;
+    } else if(string->cmp("RClosedArrow")) {
+      return annotLineEndingRClosedArrow;
+    } else if(string->cmp("Slash")) {
+      return annotLineEndingSlash;
+    } else {
+      return annotLineEndingNone;
+    }
+  } else {
+    return annotLineEndingNone;
+  }  
+}
+
 AnnotExternalDataType parseAnnotExternalData(Dict* dict) {
   Object obj1;
   AnnotExternalDataType type;
@@ -83,6 +111,55 @@ AnnotExternalDataType parseAnnotExternalData(Dict* dict) {
 }
 
 //------------------------------------------------------------------------
+// AnnotBorderEffect
+//------------------------------------------------------------------------
+
+AnnotBorderEffect::AnnotBorderEffect(Dict *dict) {
+  Object obj1;
+
+  if (dict->lookup("S", &obj1)->isName()) {
+    GooString *effectName = new GooString(obj1.getName());
+
+    if(!effectName->cmp("C"))
+      effectType = borderEffectCloudy;
+    else
+      effectType = borderEffectNoEffect;
+    delete effectName;
+  } else {
+    effectType = borderEffectNoEffect;
+  }
+  obj1.free();
+
+  if ((dict->lookup("I", &obj1)->isNum()) && effectType == borderEffectCloudy) {
+    intensity = obj1.getNum();
+  } else {
+    intensity = 0;
+  }
+  obj1.free();
+}
+
+//------------------------------------------------------------------------
+// AnnotCalloutLine
+//------------------------------------------------------------------------
+
+AnnotCalloutLine::AnnotCalloutLine(double x1, double y1, double x2, double y2) {
+  this->x1 = x1;
+  this->y1 = y1;
+  this->x2 = x2;
+  this->y2 = y2;
+}
+
+//------------------------------------------------------------------------
+// AnnotCalloutMultiLine
+//------------------------------------------------------------------------
+
+AnnotCalloutMultiLine::AnnotCalloutMultiLine(double x1, double y1, double x2,
+    double y2, double x3, double y3) : AnnotCalloutLine(x1, y1, x2, y2) {
+  this->x3 = x3;
+  this->y3 = y3;
+}
+
+//------------------------------------------------------------------------
 // AnnotQuadPoints
 //------------------------------------------------------------------------
 
@@ -2128,6 +2205,159 @@ void AnnotLink::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
 }
 
 //------------------------------------------------------------------------
+// AnnotFreeText
+//------------------------------------------------------------------------
+
+AnnotFreeText::AnnotFreeText(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj) :
+    Annot(xrefA, acroForm, dict, catalog, obj), AnnotMarkup(xref, acroForm, dict, catalog, obj) {
+  type = typeFreeText;
+  initialize(xrefA, catalog, dict);
+}
+
+AnnotFreeText::~AnnotFreeText() {
+  delete appearanceString;
+
+  if (styleString)
+    delete styleString;
+
+  if (calloutLine)
+    delete calloutLine;
+
+  if (borderEffect)
+    delete borderEffect;
+
+  if (rectangle)
+    delete rectangle;
+}
+
+void AnnotFreeText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
+  Object obj1;
+
+  if (dict->lookup("DA", &obj1)->isString()) {
+    appearanceString = obj1.getString()->copy();
+  } else {
+    appearanceString = new GooString();
+    error(-1, "Bad appearance for annotation");
+    ok = gFalse;
+  }
+  obj1.free();
+
+  if (dict->lookup("Q", &obj1)->isInt()) {
+    quadding = (AnnotFreeTextQuadding) obj1.getInt();
+  } else {
+    quadding = quaddingLeftJustified;
+  }
+  obj1.free();
+
+  if (dict->lookup("DS", &obj1)->isString()) {
+    styleString = obj1.getString()->copy();
+  } else {
+    styleString = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("CL", &obj1)->isArray() && obj1.arrayGetLength() >= 4) {
+    double x1, y1, x2, y2;
+    Object obj2;
+
+    (obj1.arrayGet(0, &obj2)->isNum() ? x1 = obj2.getNum() : x1 = 0);
+    obj2.free();
+    (obj1.arrayGet(1, &obj2)->isNum() ? y1 = obj2.getNum() : y1 = 0);
+    obj2.free();
+    (obj1.arrayGet(2, &obj2)->isNum() ? x2 = obj2.getNum() : x2 = 0);
+    obj2.free();
+    (obj1.arrayGet(3, &obj2)->isNum() ? y2 = obj2.getNum() : y2 = 0);
+    obj2.free();
+
+    if(obj1.arrayGetLength() == 6) {
+      double x3, y3;
+      (obj1.arrayGet(4, &obj2)->isNum() ? x3 = obj2.getNum() : x3 = 0);
+      obj2.free();
+      (obj1.arrayGet(5, &obj2)->isNum() ? y3 = obj2.getNum() : y3 = 0);
+      obj2.free();
+      calloutLine = new AnnotCalloutMultiLine(x1, y1, x2, y2, x3, y3);
+    } else {
+      calloutLine = new AnnotCalloutLine(x1, y1, x2, y2);
+    }
+  } else {
+    calloutLine = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("IT", &obj1)->isName()) {
+    GooString *intentName = new GooString(obj1.getName());
+
+    if (!intentName->cmp("FreeText")) {
+      intent = intentFreeText;
+    } else if (!intentName->cmp("FreeTextCallout")) {
+      intent = intentFreeTextCallout;
+    } else if (!intentName->cmp("FreeTextTypeWriter")) {
+      intent = intentFreeTextTypeWriter;
+    } else {
+      intent = intentFreeText;
+    }
+    delete intentName;
+  } else {
+    intent = intentFreeText;
+  }
+  obj1.free();
+
+  if (dict->lookup("BE", &obj1)->isDict()) {
+    borderEffect = new AnnotBorderEffect(obj1.getDict());
+  } else {
+    borderEffect = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("RD", &obj1)->isArray() && obj1.arrayGetLength() == 4) {
+    Object obj2;
+    rectangle = new PDFRectangle();
+
+    (obj1.arrayGet(0, &obj2)->isNum() ? rectangle->x1 = obj2.getNum() :
+      rectangle->x1 = 0);
+    obj2.free();
+    (obj1.arrayGet(1, &obj2)->isNum() ? rectangle->y1 = obj2.getNum() :
+      rectangle->y1 = 0);
+    obj2.free();
+    (obj1.arrayGet(2, &obj2)->isNum() ? rectangle->x2 = obj2.getNum() :
+      rectangle->x2 = 1);
+    obj2.free();
+    (obj1.arrayGet(3, &obj2)->isNum() ? rectangle->y2 = obj2.getNum() :
+      rectangle->y2 = 1);
+    obj2.free();
+
+    if (rectangle->x1 > rectangle->x2) {
+      double t = rectangle->x1;
+      rectangle->x1 = rectangle->x2;
+      rectangle->x2 = t;
+    }
+    if (rectangle->y1 > rectangle->y2) {
+      double t = rectangle->y1;
+      rectangle->y1 = rectangle->y2;
+      rectangle->y2 = t;
+    }
+
+    if ((rectangle->x1 + rectangle->x2) > (rect->x2 - rect->x1))
+      rectangle->x1 = rectangle->x2 = 0;
+
+    if ((rectangle->y1 + rectangle->y2) > (rect->y2 - rect->y1))
+      rectangle->y1 = rectangle->y2 = 0;
+  } else {
+    rectangle = NULL;
+  }
+  obj1.free();
+
+  if (dict->lookup("LE", &obj1)->isName()) {
+    GooString *styleName = new GooString(obj1.getName());
+    endStyle = parseAnnotLineEndingStyle(styleName);
+    delete styleName;
+  } else {
+    endStyle = annotLineEndingNone;
+  }
+  obj1.free();
+}
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
@@ -2181,7 +2411,7 @@ Annot *Annots::createAnnot(XRef *xref, Dict *acroForm, Dict* dict, Catalog *cata
     } else if(!typeName->cmp("Link")) {
       annot = new AnnotLink(xref, acroForm, dict, catalog, obj);
     } else if(!typeName->cmp("FreeText")) {
-      annot = new Annot(xref, acroForm, dict, catalog, obj);
+      annot = new AnnotFreeText(xref, acroForm, dict, catalog, obj);
     } else if(!typeName->cmp("Line")) {
       annot = new Annot(xref, acroForm, dict, catalog, obj);
     } else if(!typeName->cmp("Square")) {
diff --git a/poppler/Annot.h b/poppler/Annot.h
index a133fa4..5e5f475 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -22,12 +22,86 @@ class GfxFontDict;
 class FormWidget;
 class PDFRectangle;
 
+enum AnnotLineEndingStyle {
+  annotLineEndingSquare,        // Square
+  annotLineEndingCircle,        // Circle
+  annotLineEndingDiamond,       // Diamond
+  annotLineEndingOpenArrow,     // OpenArrow
+  annotLineEndingClosedArrow,   // ClosedArrow
+  annotLineEndingNone,          // None
+  annotLineEndingButt,          // Butt
+  annotLineEndingROpenArrow,    // ROpenArrow
+  annotLineEndingRClosedArrow,  // RClosedArrow
+  annotLineEndingSlash          // Slash
+};
+
 enum AnnotExternalDataType {
   annotExternalDataMarkupUnknown,
   annotExternalDataMarkup3D       // Markup3D
 };
 
 //------------------------------------------------------------------------
+// AnnotCalloutLine
+//------------------------------------------------------------------------
+
+class AnnotCalloutLine {
+public:
+
+  AnnotCalloutLine(double x1, double y1, double x2, double y2);
+  virtual ~AnnotCalloutLine() { }
+
+  double getX1() const { return x1; }
+  double getY1() const { return y1; }
+  double getX2() const { return x2; }
+  double getY2() const { return y2; }
+  
+protected:
+
+  double x1, y1, x2, y2;
+};
+
+//------------------------------------------------------------------------
+// AnnotCalloutMultiLine
+//------------------------------------------------------------------------
+
+class AnnotCalloutMultiLine: public AnnotCalloutLine {
+public:
+
+  AnnotCalloutMultiLine(double x1, double y1, double x2, double y2,
+    double x3, double y3);
+
+  double getX3() const { return x3; }
+  double getY3() const { return y3; }
+
+protected:
+
+  double x3, y3;
+};
+
+//------------------------------------------------------------------------
+// AnnotBorderEffect
+//------------------------------------------------------------------------
+
+class AnnotBorderEffect {
+public:
+
+  enum AnnotBorderEffectType {
+    borderEffectNoEffect, // S
+    borderEffectCloudy    // C
+  };
+
+  AnnotBorderEffect(Dict *dict);
+
+  AnnotBorderEffectType getEffectType() const { return effectType; }
+  double getIntensity() const { return intensity; }
+
+private:
+
+  AnnotBorderEffectType effectType; // S  (Default S)
+  double intensity;                 // I  (Default 0)
+};
+
+//------------------------------------------------------------------------
 // AnnotQuadPoints
 //------------------------------------------------------------------------
 
@@ -466,6 +540,59 @@ protected:
 };
 
 //------------------------------------------------------------------------
+// AnnotFreeText
+//------------------------------------------------------------------------
+
+class AnnotFreeText: public Annot, public AnnotMarkup {
+public:
+
+  enum AnnotFreeTextQuadding {
+    quaddingLeftJustified,  // 0
+    quaddingCentered,       // 1
+    quaddingRightJustified  // 2
+  };
+
+  enum AnnotFreeTextIntent {
+    intentFreeText,           // FreeText
+    intentFreeTextCallout,    // FreeTextCallout
+    intentFreeTextTypeWriter  // FreeTextTypeWriter
+  };
+
+  AnnotFreeText(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+  virtual ~AnnotFreeText();
+
+  // getters
+  GooString *getAppearanceString() const { return appearanceString; }
+  AnnotFreeTextQuadding getQuadding() const { return quadding; }
+  // return rc
+  GooString *getStyleString() const { return styleString; }
+  AnnotCalloutLine *getCalloutLine() const {  return calloutLine; }
+  AnnotFreeTextIntent getIntent() const { return intent; }
+  AnnotBorderEffect *getBorderEffect() const { return borderEffect; }
+  PDFRectangle *getRectangle() const { return rectangle; }
+  AnnotLineEndingStyle getEndStyle() const { return endStyle; }
+
+protected:
+
+  void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
+
+  // required
+  GooString *appearanceString;      // DA
+
+  // optional
+  AnnotFreeTextQuadding quadding;   // Q  (Default 0)
+  // RC
+  GooString *styleString;           // DS
+  AnnotCalloutLine *calloutLine;    // CL
+  AnnotFreeTextIntent intent;       // IT
+  AnnotBorderEffect *borderEffect;  // BE
+  PDFRectangle *rectangle;          // RD
+  // inherited  from Annot
+  // AnnotBorderBS border;          // BS
+  AnnotLineEndingStyle endStyle;    // LE (Default None)
+};
+
+//------------------------------------------------------------------------
 // Annots
 //------------------------------------------------------------------------
 
commit c3504a87933ae1516b1ef05e527fd1c039091235
Author: Iñigo Martínez <inigomartinez at gmail.com>
Date:   Sun Dec 30 19:37:18 2007 +0100

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

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 60a83a8..7f2a375 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -83,6 +83,22 @@ AnnotExternalDataType parseAnnotExternalData(Dict* dict) {
 }
 
 //------------------------------------------------------------------------
+// AnnotQuadPoints
+//------------------------------------------------------------------------
+
+AnnotQuadPoints::AnnotQuadPoints(double x1, double y1, double x2, double y2,
+    double x3, double y3, double x4, double y4) {
+  this->x1 = x1;
+  this->y1 = y1;
+  this->x2 = x2;
+  this->y2 = y2;
+  this->x3 = x3;
+  this->y3 = y3;
+  this->x4 = x4;
+  this->y4 = y4;
+}
+
+//------------------------------------------------------------------------
 // AnnotBorder
 //------------------------------------------------------------------------
 AnnotBorder::AnnotBorder() {
@@ -2009,6 +2025,106 @@ AnnotLink::AnnotLink(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog,
     Annot(xrefA, acroForm, dict, catalog, obj) {
 
   type = typeLink;
+  initialize (xrefA, catalog, dict);
+}
+
+AnnotLink::~AnnotLink() {
+  /*
+  if (actionDict)
+    delete actionDict;
+
+  if (uriAction)
+    delete uriAction;
+  */
+  if(quadrilaterals) {
+    for(int i = 0; i < quadrilateralsLength; i++)
+      delete quadrilaterals[i];
+
+    gfree (quadrilaterals);
+  }
+}
+
+void AnnotLink::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
+  Object obj1;
+  /*
+  if (dict->lookup("A", &obj1)->isDict()) {
+    actionDict = NULL;
+  } else {
+    actionDict = NULL;
+  }
+  obj1.free();
+  */
+  if (dict->lookup("H", &obj1)->isName()) {
+    GooString *effect = new GooString(obj1.getName());
+
+    if (!effect->cmp("N")) {
+      linkEffect = effectNone;
+    } else if (!effect->cmp("I")) {
+      linkEffect = effectInvert;
+    } else if (!effect->cmp("O")) {
+      linkEffect = effectOutline;
+    } else if (!effect->cmp("P")) {
+      linkEffect = effectPush;
+    } else {
+      linkEffect = effectInvert;
+    }
+    delete effect;
+  } else {
+    linkEffect = effectInvert;
+  }
+  obj1.free();
+  /*
+  if (dict->lookup("PA", &obj1)->isDict()) {
+    uriAction = NULL;
+  } else {
+    uriAction = NULL;
+  }
+  obj1.free();
+  */
+  /*
+   * TODO:
+   * QuadPoints should be ignored if any coordinate in the array lies outside
+   * the region specified by Rect.
+   */
+  if(dict->lookup("QuadPoints", &obj1)->isArray()) {
+    quadrilateralsLength = obj1.arrayGetLength();
+    if((quadrilateralsLength % 8) == 0) {
+      Object obj2;
+
+      quadrilaterals = (AnnotQuadPoints **) gmallocn
+        ((quadrilateralsLength / 8), sizeof(AnnotQuadPoints *));
+      for(int i = 0; i < quadrilateralsLength; i += 8) {
+        double x1, y1, x2, y2, x3, y3, x4, y4;
+
+        (obj1.arrayGet(i, &obj2)->isNum() ? x1 = obj2.getNum() : x1 = 0);
+        obj2.free();
+        (obj1.arrayGet((i + 1), &obj2)->isNum() ? y1 = obj2.getNum() : y1 = 0);
+        obj2.free();
+        (obj1.arrayGet((i + 2), &obj2)->isNum() ? x2 = obj2.getNum() : x2 = 0);
+        obj2.free();
+        (obj1.arrayGet((i + 3), &obj2)->isNum() ? y2 = obj2.getNum() : y2 = 0);
+        obj2.free();
+        (obj1.arrayGet((i + 4), &obj2)->isNum() ? x3 = obj2.getNum() : x3 = 0);
+        obj2.free();
+        (obj1.arrayGet((i + 5), &obj2)->isNum() ? y3 = obj2.getNum() : y3 = 0);
+        obj2.free();
+        (obj1.arrayGet((i + 6), &obj2)->isNum() ? x4 = obj2.getNum() : x4 = 0);
+        obj2.free();
+        (obj1.arrayGet((i + 7), &obj2)->isNum() ? y4 = obj2.getNum() : y4 = 0);
+        obj2.free();
+
+        quadrilaterals[i / 8] =
+          new AnnotQuadPoints(x1, y1, x2, y2, x3, y3, x4, y4);
+      }
+      quadrilateralsLength /= 8;
+    } else {
+      quadrilaterals = NULL;
+      quadrilateralsLength = 0;
+    }
+  } else {
+    quadrilaterals = NULL;
+  }
+  obj1.free();
 }
 
 //------------------------------------------------------------------------
diff --git a/poppler/Annot.h b/poppler/Annot.h
index c7c90c1..a133fa4 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -28,6 +28,29 @@ enum AnnotExternalDataType {
 };
 
 //------------------------------------------------------------------------
+// AnnotQuadPoints
+//------------------------------------------------------------------------
+
+class AnnotQuadPoints {
+public:
+  
+  AnnotQuadPoints(double x1, double y1, double x2, double y2, double x3,
+      double y3, double x4, double y4);
+
+  double getX1() const { return x1; }
+  double getY1() const { return y1; }
+  double getX2() const { return x2; }
+  double getY2() const { return y2; }
+  double getX3() const { return x3; }
+  double getY3() const { return y3; }
+  double getX4() const { return x4; }
+  double getY4() const { return y4; }
+
+protected:
+  double x1, y1, x2, y2, x3, y3, x4, y4;
+};
+
+//------------------------------------------------------------------------
 // AnnotBorder
 //------------------------------------------------------------------------
 
@@ -411,7 +434,35 @@ private:
 class AnnotLink: public Annot {
 public:
 
+  enum AnnotLinkEffect {
+    effectNone,     // N
+    effectInvert,   // I
+    effectOutline,  // O
+    effectPush      // P
+  };
+
   AnnotLink(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog, Object *obj);
+  virtual ~AnnotLink();
+
+  // getters
+  Dict *getActionDict() const { return actionDict; }
+  // getDest
+  AnnotLinkEffect getLinkEffect() const { return linkEffect; }
+  Dict *getUriAction() const { return uriAction; }
+  AnnotQuadPoints **getQuadrilaterals() const { return quadrilaterals; }
+  int getQuadrilateralsLength() const { return quadrilateralsLength; }
+
+protected:
+
+  void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
+
+  Dict *actionDict;                 // A
+  //Dest
+  AnnotLinkEffect linkEffect;       // H          (Default I)
+  Dict *uriAction;                  // PA
+
+  AnnotQuadPoints **quadrilaterals; // QuadPoints
+  int quadrilateralsLength;
 };
 
 //------------------------------------------------------------------------


More information about the poppler mailing list