[poppler] poppler/poppler: Annot.cc, 1.2, 1.3 Annot.h, 1.1.1.1, 1.2 FontInfo.cc, 1.5, 1.6 PSOutputDev.cc, 1.5, 1.6 Page.cc, 1.5, 1.6

Albert Astals Cid aacid at freedesktop.org
Sun Oct 16 07:54:19 PDT 2005


Update of /cvs/poppler/poppler/poppler
In directory gabe:/tmp/cvs-serv952/poppler

Modified Files:
	Annot.cc Annot.h FontInfo.cc PSOutputDev.cc Page.cc 
Log Message:
Annot.[cc|h] and related merges from xpdf 3.01


Index: Annot.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Annot.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Annot.cc	27 Aug 2005 08:43:43 -0000	1.2
+++ Annot.cc	16 Oct 2005 14:54:17 -0000	1.3
@@ -12,47 +12,28 @@
 #pragma implementation
 #endif
 
+#include <stdlib.h>
 #include "goo/gmem.h"
 #include "Object.h"
+#include "Catalog.h"
 #include "Gfx.h"
+#include "Lexer.h"
 #include "Annot.h"
 
 //------------------------------------------------------------------------
 // Annot
 //------------------------------------------------------------------------
 
-Annot::Annot(XRef *xrefA, Dict *dictA) {
+Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict) {
   Object apObj, asObj, obj1, obj2;
+  GBool regen, isTextField;
   double t;
 
   ok = gFalse;
   xref = xrefA;
-  dict = dictA;
-  dict->incRef(); 
-
-  dictA->lookup("Subtype", &subtype); 
-  if (dictA->lookup("AP", &apObj)->isDict()) {
-    if (dictA->lookup("AS", &asObj)->isName()) {
-      if (apObj.dictLookup("N", &obj1)->isDict()) {
-	if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) {
-	  obj2.copy(&appearance);
-	  ok = gTrue;
-	}
-	obj2.free();
-      }
-      obj1.free();
-    } else {
-      if (apObj.dictLookupNF("N", &obj1)->isRef()) {
-	obj1.copy(&appearance);
-	ok = gTrue;
-      }
-      obj1.free();
-    }
-    asObj.free();
-  }
-  apObj.free();
+  appearBuf = NULL;
 
-  if (dictA->lookup("Rect", &obj1)->isArray() &&
+  if (dict->lookup("Rect", &obj1)->isArray() &&
       obj1.arrayGetLength() == 4) {
     //~ should check object types here
     obj1.arrayGet(0, &obj2);
@@ -79,10 +60,204 @@
     xMax = yMax = 1;
   }
   obj1.free();
+
+  // check if field apperances need to be regenerated
+  regen = gFalse;
+  if (acroForm) {
+    acroForm->lookup("NeedAppearances", &obj1);
+    if (obj1.isBool() && obj1.getBool()) {
+      regen = gTrue;
+    }
+    obj1.free();
+  }
+
+  // check for a text-type field
+  isTextField = dict->lookup("FT", &obj1)->isName("Tx");
+  obj1.free();
+
+#if 0 //~ appearance stream generation is not finished yet
+  if (regen && isTextField) {
+    generateAppearance(acroForm, dict);
+  } else {
+#endif
+    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;
+	    }
+	  }
+	  obj2.free();
+	}
+	obj1.free();
+      } else {
+	if (apObj.dictLookupNF("N", &obj1)->isRef()) {
+	  obj1.copy(&appearance);
+	  ok = gTrue;
+	}
+	obj1.free();
+      }
+      asObj.free();
+    }
+    apObj.free();
+#if 0 //~ appearance stream generation is not finished yet
+  }
+#endif
 }
 
 Annot::~Annot() {
   appearance.free();
+  if (appearBuf) {
+    delete appearBuf;
+  }
+}
+
+void Annot::generateAppearance(Dict *acroForm, Dict *dict) {
+  MemStream *appearStream;
+  Object daObj, vObj, drObj, appearDict, obj1, obj2;
+  GooString *daStr, *daStr1, *vStr, *s;
+  char buf[256];
+  double fontSize;
+  int c;
+  int i0, i1;
+
+  //~ DA can be inherited
+  if (dict->lookup("DA", &daObj)->isString()) {
+    daStr = daObj.getString();
+
+    // look for a font size
+    //~ may want to parse the DS entry in place of this (if it exists)
+    daStr1 = NULL;
+    fontSize = 10;
+    for (i1 = daStr->getLength() - 2; i1 >= 0; --i1) {
+      if (daStr->getChar(i1) == 'T' && daStr->getChar(i1+1) == 'f') {
+	for (--i1; i1 >= 0 && Lexer::isSpace(daStr->getChar(i1)); --i1) ;
+	for (i0 = i1; i0 >= 0 && !Lexer::isSpace(daStr->getChar(i0)); --i0) ;
+	if (i0 >= 0) {
+	  ++i0;
+	  ++i1;
+	  s = new GooString(daStr, i0, i1 - i0);
+	  fontSize = atof(s->getCString());
+	  delete s;
+
+	  // autosize the font
+	  if (fontSize == 0) {
+	    fontSize = 0.67 * (yMax - yMin);
+	    daStr1 = new GooString(daStr, 0, i0);
+	    sprintf(buf, "%.2f", fontSize);
+	    daStr1->append(buf);
+	    daStr1->append(daStr->getCString() + i1,
+			   daStr->getLength() - i1);
+	  }
+	}
+	break;
+      }
+    }
+
+    // build the appearance stream contents
+    appearBuf = new GooString();
+    appearBuf->append("/Tx BMC\n");
+    appearBuf->append("q BT\n");
+    appearBuf->append(daStr1 ? daStr1 : daStr)->append("\n");
+    if (dict->lookup("V", &vObj)->isString()) {
+      //~ handle quadding -- this requires finding the font and using
+      //~   the encoding and char widths
+      sprintf(buf, "1 0 0 1 %.2f %.2f Tm\n", 2.0, yMax - yMin - fontSize);
+      appearBuf->append(buf);
+      sprintf(buf, "%g TL\n", fontSize);
+      appearBuf->append(buf);
+      vStr = vObj.getString();
+      i0 = 0;
+      while (i0 < vStr->getLength()) {
+	for (i1 = i0;
+	     i1 < vStr->getLength() &&
+	       vStr->getChar(i1) != '\n' && vStr->getChar(i1) != '\r';
+	     ++i1) ;
+	if (i0 > 0) {
+	  appearBuf->append("T*\n");
+	}
+	appearBuf->append('(');
+	for (; i0 < i1; ++i0) {
+	  c = vStr->getChar(i0);
+	  if (c == '(' || c == ')' || c == '\\') {
+	    appearBuf->append('\\');
+	    appearBuf->append(c);
+	  } else if (c < 0x20 || c >= 0x80) {
+	    sprintf(buf, "\\%03o", c);
+	    appearBuf->append(buf);
+	  } else {
+	    appearBuf->append(c);
+	  }
+	}
+	appearBuf->append(") Tj\n");
+	if (i1 + 1 < vStr->getLength() &&
+	    vStr->getChar(i1) == '\r' && vStr->getChar(i1 + 1) == '\n') {
+	  i0 = i1 + 2;
+	} else {
+	  i0 = i1 + 1;
+	}
+      }
+    }
+    vObj.free();
+    appearBuf->append("ET Q\n");
+    appearBuf->append("EMC\n");
+
+    // build the appearance stream dictionary
+    appearDict.initDict(xref);
+    appearDict.dictAdd(copyString("Length"),
+		       obj1.initInt(appearBuf->getLength()));
+    appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form"));
+    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));
+    appearDict.dictAdd(copyString("BBox"), &obj1);
+
+    // find the resource dictionary
+    dict->lookup("DR", &drObj);
+    if (!drObj.isDict()) {
+      dict->lookup("Parent", &obj1);
+      while (obj1.isDict()) {
+	drObj.free();
+	obj1.dictLookup("DR", &drObj);
+	if (drObj.isDict()) {
+	  break;
+	}
+	obj1.dictLookup("Parent", &obj2);
+	obj1.free();
+	obj1 = obj2;
+      }
+      obj1.free();
+      if (!drObj.isDict()) {
+	if (acroForm) {
+	  drObj.free();
+	  acroForm->lookup("DR", &drObj);
+	}
+      }
+    }
+    if (drObj.isDict()) {
+      appearDict.dictAdd(copyString("Resources"), drObj.copy(&obj1));
+    }
+    drObj.free();
+
+    // build the appearance stream
+    appearStream = new MemStream(appearBuf->getCString(), 0,
+				 appearBuf->getLength(), &appearDict);
+    appearance.initStream(appearStream);
+    ok = gTrue;
+
+    if (daStr1) {
+      delete daStr1;
+    }
+  }
+  daObj.free();
 }
 
 void Annot::draw(Gfx *gfx) {
@@ -98,7 +273,8 @@
 // Annots
 //------------------------------------------------------------------------
 
-Annots::Annots(XRef *xref, Object *annotsObj) {
+Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
+  Dict *acroForm;
   Annot *annot;
   Object obj1;
   int size;
@@ -108,10 +284,12 @@
   size = 0;
   nAnnots = 0;
 
+  acroForm = catalog->getAcroForm()->isDict() ?
+               catalog->getAcroForm()->getDict() : NULL;
   if (annotsObj->isArray()) {
     for (i = 0; i < annotsObj->arrayGetLength(); ++i) {
       if (annotsObj->arrayGet(i, &obj1)->isDict()) {
-	annot = new Annot(xref, obj1.getDict());
+	annot = new Annot(xref, acroForm, obj1.getDict());
 	if (annot->isOk()) {
 	  if (nAnnots >= size) {
 	    size += 16;

Index: Annot.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Annot.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- Annot.h	3 Mar 2005 19:46:00 -0000	1.1.1.1
+++ Annot.h	16 Oct 2005 14:54:17 -0000	1.2
@@ -15,6 +15,7 @@
 
 class XRef;
 class Gfx;
+class Catalog;
 
 //------------------------------------------------------------------------
 // Annot
@@ -23,7 +24,7 @@
 class Annot {
 public:
 
-  Annot(XRef *xrefA, Dict *dict);
+  Annot(XRef *xrefA, Dict *acroForm, Dict *dict);
   ~Annot();
   GBool isOk() { return ok; }
 
@@ -32,23 +33,14 @@
   // Get appearance object.
   Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
 
-  // Get subtype object
-  Object *getSubtype(Object *obj) {return subtype.copy(obj); };
-
-  // Get dictionary
-  Dict *getDict() {return dict; };
-
-  // Get annot appearance ID
-  int getRefNum() {return appearance.getRefNum();};
-  int getRefGen() {return appearance.getRefGen();};
-  
 private:
 
+  void generateAppearance(Dict *acroForm, Dict *dict);
+
   XRef *xref;			// the xref table for this PDF file
-  Dict *dict;
-  Object subtype;
   Object appearance;		// a reference to the Form XObject stream
 				//   for the normal appearance
+  GooString *appearBuf;
   double xMin, yMin,		// annotation rectangle
          xMax, yMax;
   GBool ok;
@@ -62,7 +54,7 @@
 public:
 
   // Extract non-link annotations from array of annotations.
-  Annots(XRef *xref, Object *annotsObj);
+  Annots(XRef *xref, Catalog *catalog, Object *annotsObj);
 
   ~Annots();
 

Index: FontInfo.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/FontInfo.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- FontInfo.cc	4 Jul 2005 08:10:16 -0000	1.5
+++ FontInfo.cc	16 Oct 2005 14:54:17 -0000	1.6
@@ -48,7 +48,7 @@
     if ((resDict = page->getResourceDict())) {
       scanFonts(resDict, result);
     }
-    annots = new Annots(doc->getXRef(), page->getAnnots(&obj1));
+    annots = new Annots(doc->getXRef(), doc->getCatalog(), page->getAnnots(&obj1));
     obj1.free();
     for (i = 0; i < annots->getNumAnnots(); ++i) {
       if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {

Index: PSOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PSOutputDev.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- PSOutputDev.cc	14 Sep 2005 21:20:36 -0000	1.5
+++ PSOutputDev.cc	16 Oct 2005 14:54:17 -0000	1.6
@@ -1027,7 +1027,7 @@
     if ((resDict = page->getResourceDict())) {
       setupResources(resDict);
     }
-    annots = new Annots(xref, page->getAnnots(&obj1));
+    annots = new Annots(xref, catalog, page->getAnnots(&obj1));
     obj1.free();
     for (i = 0; i < annots->getNumAnnots(); ++i) {
       if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {

Index: Page.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Page.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Page.cc	29 Jun 2005 21:24:57 -0000	1.5
+++ Page.cc	16 Oct 2005 14:54:17 -0000	1.6
@@ -378,7 +378,7 @@
   }
 
   // draw non-link annotations
-  annotList = new Annots(xref, annots.fetch(xref, &obj));
+  annotList = new Annots(xref, catalog, annots.fetch(xref, &obj));
   obj.free();
 #ifdef USE_ANNOTS_VIEW
   if (annotList->getNumAnnots() > 0) {



More information about the poppler mailing list