[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