Hi:

Here goes another patch that does parse a little more annotation data
and does clean a little appearance parsing, but it still needs more work
(appearance was something i didn't understand correctly (XObject
streams)).

I'm sending again yesterdays PDFRectangle patch, there was a line
missing (PDFRectangle should be deleted on the Annot destructor).

Bye,

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 2e09848..40ff968 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
@@ -104,7 +105,6 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
   double *borderDash;
   int borderDashLength;
   double borderR, borderG, borderB;
-  double t;
 
   ok = gTrue;
   xref = xrefA;
@@ -129,34 +129,37 @@ 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();
-  
+
   //----- get the flags
   if (dict->lookup("F", &obj1)->isInt()) {
     flags = obj1.getInt();
@@ -320,6 +323,14 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
       borderR, borderG, borderB);
 }
 
+double Annot::getXMin() {
+  return rect->x1;
+}
+
+double Annot::getYMin() {
+  return rect->y1;
+}
+
 void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
   Object valueObject;
 
@@ -334,6 +345,8 @@ void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
 }
 
 Annot::~Annot() {
+  delete rect;
+
   if (type) {
     delete type;
   }
@@ -392,7 +405,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();
   }
@@ -417,8 +430,8 @@ void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
         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();
@@ -554,8 +567,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 +717,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
@@ -911,12 +924,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 * border - 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 +955,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) {
@@ -980,10 +993,10 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
           x = border + 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 - border - 2 - w;
           break;
       }
 
@@ -1005,11 +1018,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 * border) / comb;
 
       // compute font autosize
       if (fontSize == 0) {
-        fontSize = yMax - yMin - 2 * border;
+        fontSize = rect->y2 - rect->y1 - 2 * border;
         if (w < fontSize) {
           fontSize = w;
         }
@@ -1034,7 +1047,7 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
           x = border + 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 +1099,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 * border;
+        fontSize2 = (rect->x2 - rect->x1 - 4 - 2 * border) / w;
         if (fontSize2 < fontSize) {
           fontSize = fontSize2;
         }
@@ -1107,13 +1120,13 @@ void Annot::drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
           x = border + 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 - border - 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) {
@@ -1237,8 +1250,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 * border;
+    fontSize2 = (rect->x2 - rect->x1 - 4 - 2 * border) / wMax;
     if (fontSize2 < fontSize) {
       fontSize = fontSize2;
     }
@@ -1250,7 +1263,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");
@@ -1261,7 +1274,7 @@ void Annot::drawListBox(GooString **text, GBool *selection,
       appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} re f\n",
           border,
           y - 0.2 * fontSize,
-          xMax - xMin - 2 * border,
+          rect->x2 - rect->x1 - 2 * border,
           1.1 * fontSize);
     }
 
@@ -1287,10 +1300,10 @@ void Annot::drawListBox(GooString **text, GBool *selection,
         x = border + 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 - border - 2 - w;
         break;
     }
 
@@ -1495,7 +1508,7 @@ void Annot::draw(Gfx *gfx, GBool printing) {
   isLink = type && !type->cmp("Link");
   appearance.fetch(xref, &obj);
   gfx->drawAnnot(&obj, isLink ? borderStyle : (AnnotBorderStyle *)NULL,
-      xMin, yMin, xMax, yMax);
+      rect->x1, rect->y1, rect->x2, rect->y2);
   obj.free();
 }
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 50f5bfb..5b7c2b5 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -20,6 +20,7 @@ class CharCodeToUnicode;
 class GfxFont;
 class GfxFontDict;
 class FormWidget;
+class PDFRectangle;
 
 //------------------------------------------------------------------------
 // AnnotBorderStyle
@@ -82,13 +83,14 @@ public:
 
   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; }
+  
 private:
   void setColor(Array *a, GBool fill, int adjust);
   void drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
@@ -110,6 +112,9 @@ private:
 
   void initialize (XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
 
+  // required data
+  PDFRectangle *rect;           // Rect
+  
   XRef *xref;			// the xref table for this PDF file
   Ref ref;                      // object ref identifying this annotation
   FormWidget *widget;           // FormWidget object for this annotation
@@ -118,8 +123,6 @@ private:
 				//   for the normal appearance
   GooString *appearBuf;
   Guint flags;
-  double xMin, yMin,		// annotation rectangle
-         xMax, yMax;
   AnnotBorderStyle *borderStyle;
   double fontSize; 
   GBool ok;
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 2e09848..5933986 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -89,11 +89,13 @@ Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, const Ref& aref, Catalog*
 {
   hasRef = true;
   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);
 }
 
@@ -157,19 +159,43 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
   }
   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,39 +211,46 @@ 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;
+
+      appearState = new GooString(obj2.getName());
+      if (obj1.dictLookup("N", &obj3)->isDict()) {
+        Object obj4;
 
-  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();
+        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
 
@@ -318,6 +351,22 @@ void Annot::initialize(XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog
   borderStyle = new AnnotBorderStyle(borderType, borderWidth,
       borderDash, borderDashLength,
       borderR, borderG, borderB);
+
+  if (dict->lookup("StructParent", &obj1)->isInt()) {
+    treeKey = obj1.getInt();
+  } else {
+    treeKey = 0;
+  }
+  obj1.free();
+
+  /* TODO: optional content should be parsed
+  if (dict->lookup("OC", &obj1)->isDict()) {
+    optionalContent = NULL;
+  } else {
+    optionalContent = NULL;
+  }
+  obj1.free();
+  */
 }
 
 void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
@@ -334,6 +383,18 @@ void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
 }
 
 Annot::~Annot() {
+  if (contents)
+    delete contents;
+
+  if (pageDict)
+    delete pageDict;
+
+  if(name)
+    delete name;
+
+  if (modified)
+    delete modified;
+
   if (type) {
     delete type;
   }
@@ -342,9 +403,15 @@ Annot::~Annot() {
     delete appearBuf;
   }
 
+  if(appearState)
+    delete appearState;
+
   if (borderStyle) {
     delete borderStyle;
   }
+
+  if (optionalContent)
+    delete optionalContent;
 }
 
 void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 50f5bfb..d25f32b 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -63,6 +63,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);
@@ -110,14 +123,24 @@ private:
 
   void initialize (XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
 
+  // 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;
@@ -127,7 +150,6 @@ private:
   GBool isMultiline, isListbox;
   
   bool hasRef;
-  bool hidden;
 };
 
 //------------------------------------------------------------------------

Attachment: signature.asc
Description: Esta parte del mensaje está firmada digitalmente

_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to