From 00865174eae59e8eaff4e956cb7c6e566f5db4ac Mon Sep 17 00:00:00 2001
From: =?utf-8?q?I=C3=B1igo=20Mart=C3=ADnez?= <inigomartinez@gmail.com>
Date: Sat, 8 Dec 2007 21:17:11 +0100
Subject: [PATCH] Prepare code to Annotatio Subtype support.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Iñigo Martínez <inigomartinez@gmail.com>
---
 glib/poppler-page.cc |   11 +---
 poppler/Annot.cc     |  159 ++++++++++++++++++++++++++++++++++++--------------
 poppler/Annot.h      |   52 ++++++++++++++--
 poppler/Form.cc      |    6 ++-
 4 files changed, 165 insertions(+), 63 deletions(-)

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 5ca0f03..098267d 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -88,7 +88,6 @@ 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 +95,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 +180,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 +286,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 +305,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
@@ -301,12 +315,6 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
       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();
   if (dict->lookup("Rect", &obj1)->isArray() && obj1.arrayGetLength() == 4) {
@@ -507,9 +515,6 @@ Annot::~Annot() {
   if (modified)
     delete modified;
 
-  if (type) {
-    delete type;
-  }
   appearance.free();
   if (appearBuf) {
     delete appearBuf;
@@ -543,7 +548,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 +1670,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 +1679,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 +1710,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 +1728,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 cc8a038..0a9b934 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -168,9 +168,37 @@ 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);
@@ -189,11 +217,20 @@ 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);
@@ -217,7 +254,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
@@ -237,7 +275,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;
 
   double fontSize; 
@@ -270,6 +307,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 334e45c..4395a39 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();
-- 
1.5.2.5

