[poppler] poppler/poppler: ABWOutputDev.cc, 1.2, 1.3 ABWOutputDev.h, 1.1, 1.2 Annot.cc, 1.9, 1.10 Annot.h, 1.5, 1.6 ArthurOutputDev.cc, 1.12, 1.13 Catalog.cc, 1.19, 1.20 Catalog.h, 1.11, 1.12 CharCodeToUnicode.cc, 1.5, 1.6 DCTStream.cc, 1.5, 1.6 DCTStream.h, 1.6, 1.7 Decrypt.cc, 1.3, 1.4 Decrypt.h, 1.2, 1.3 Dict.cc, 1.6, 1.7 Dict.h, 1.5, 1.6 FontInfo.cc, 1.11, 1.12 Form.cc, 1.3, 1.4 Form.h, 1.2, 1.3 Function.cc, 1.6, 1.7 Function.h, 1.2, 1.3 Gfx.cc, 1.14, 1.15 Gfx.h, 1.3, 1.4 GfxFont.cc, 1.10, 1.11 GfxFont.h, 1.5, 1.6 GfxState.cc, 1.14, 1.15 GfxState.h, 1.6, 1.7 GlobalParams.cc, 1.19, 1.20 GlobalParams.h, 1.8, 1.9 JBIG2Stream.cc, 1.9, 1.10 JBIG2Stream.h, 1.2, 1.3 JPXStream.cc, 1.6, 1.7 JPXStream.h, 1.2, 1.3 Lexer.cc, 1.5, 1.6 Link.cc, 1.5, 1.6 Link.h, 1.3, 1.4 Makefile.am, 1.30, 1.31 Object.cc, 1.3, 1.4 Object.h, 1.4, 1.5 Outline.cc, 1.5, 1.6 OutputDev.cc, 1.4, 1.5 OutputDev.h, 1.5, 1.6 PDFDoc.cc, 1.10, 1.11 PDFDoc.h, 1.7, 1.8 PSOutputDev.cc, 1.14, 1.15 PSOutputDev.h, 1.7, 1.8 PSTokenizer.cc, 1.2, 1.3 Page.cc, 1.17, 1.18 Page.h, 1.8, 1.9 PageLabelInfo.cc, 1.7, 1.8 Parser.cc, 1.7, 1.8 Parser.h, 1.3, 1.4 PreScanOutputDev.cc, 1.1, 1.2 PreScanOutputDev.h, 1.1, 1.2 SecurityHandler.cc, 1.2, 1.3 SecurityHandler.h, 1.1, 1.2 SplashOutputDev.cc, 1.12, 1.13 SplashOutputDev.h, 1.4, 1.5 Stream.cc, 1.15, 1.16 Stream.h, 1.11, 1.12 TextOutputDev.cc, 1.22, 1.23 TextOutputDev.h, 1.12, 1.13 UGooString.cc, 1.5, NONE UGooString.h, 1.2, NONE XRef.cc, 1.14, 1.15 XRef.h, 1.7, 1.8

Albert Astals Cid aacid at kemper.freedesktop.org
Wed Apr 25 12:59:22 PDT 2007


Update of /cvs/poppler/poppler/poppler
In directory kemper:/tmp/cvs-serv1447/poppler

Modified Files:
	ABWOutputDev.cc ABWOutputDev.h Annot.cc Annot.h 
	ArthurOutputDev.cc Catalog.cc Catalog.h CharCodeToUnicode.cc 
	DCTStream.cc DCTStream.h Decrypt.cc Decrypt.h Dict.cc Dict.h 
	FontInfo.cc Form.cc Form.h Function.cc Function.h Gfx.cc Gfx.h 
	GfxFont.cc GfxFont.h GfxState.cc GfxState.h GlobalParams.cc 
	GlobalParams.h JBIG2Stream.cc JBIG2Stream.h JPXStream.cc 
	JPXStream.h Lexer.cc Link.cc Link.h Makefile.am Object.cc 
	Object.h Outline.cc OutputDev.cc OutputDev.h PDFDoc.cc 
	PDFDoc.h PSOutputDev.cc PSOutputDev.h PSTokenizer.cc Page.cc 
	Page.h PageLabelInfo.cc Parser.cc Parser.h SecurityHandler.cc 
	SecurityHandler.h SplashOutputDev.cc SplashOutputDev.h 
	Stream.cc Stream.h TextOutputDev.cc TextOutputDev.h XRef.cc 
	XRef.h 
Added Files:
	PreScanOutputDev.cc PreScanOutputDev.h 
Removed Files:
	UGooString.cc UGooString.h 
Log Message:
Merge xpdf302branch in HEAD as noone vetoed it.
Testing more than welcome


Index: ABWOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/ABWOutputDev.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- ABWOutputDev.cc	6 Apr 2007 15:27:52 -0000	1.2
+++ ABWOutputDev.cc	25 Apr 2007 19:59:10 -0000	1.3
@@ -27,7 +27,6 @@
 #include "GfxState.h"
 #include "GlobalParams.h"
 #include "ABWOutputDev.h"
-#include "UGooString.h"
 #include "PDFDoc.h"
 
 #include <libxml/parser.h>

Index: ABWOutputDev.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/ABWOutputDev.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ABWOutputDev.h	4 Apr 2007 02:42:29 -0000	1.1
+++ ABWOutputDev.h	25 Apr 2007 19:59:10 -0000	1.2
@@ -18,7 +18,6 @@
 #include "goo/GooList.h"
 #include "GfxFont.h"
 #include "OutputDev.h"
-#include "Link.h"
 #include "Catalog.h"
 #include "UnicodeMap.h"
 #include "PDFDoc.h"

Index: Annot.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Annot.cc,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- Annot.cc	6 Mar 2007 22:27:18 -0000	1.9
+++ Annot.cc	25 Apr 2007 19:59:10 -0000	1.10
@@ -13,18 +13,74 @@
 #endif
 
 #include <stdlib.h>
+#include <math.h>
 #include "goo/gmem.h"
+#include "GooList.h"
+#include "Error.h"
 #include "Object.h"
 #include "Catalog.h"
 #include "Gfx.h"
 #include "Lexer.h"
[...1782 lines suppressed...]
+    }
+    obj1.free();
+  }
+}
+
+Annot *Annots::findAnnot(Ref *ref) {
+  int i;
+
+  for (i = 0; i < nAnnots; ++i) {
+    if (annots[i]->match(ref)) {
+      return annots[i];
+    }
+  }
+  return NULL;
+}
+
+
 Annots::~Annots() {
   int i;
 

Index: Annot.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Annot.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Annot.h	25 Feb 2007 00:34:21 -0000	1.5
+++ Annot.h	25 Apr 2007 19:59:10 -0000	1.6
@@ -18,7 +18,43 @@
 class Catalog;
 class CharCodeToUnicode;
 class GfxFont;
-class FormWidget;
+class GfxFontDict;
+
+//------------------------------------------------------------------------
+// AnnotBorderStyle
+//------------------------------------------------------------------------
+
+enum AnnotBorderType {
+  annotBorderSolid,
+  annotBorderDashed,
+  annotBorderBeveled,
+  annotBorderInset,
+  annotBorderUnderlined
+};
+
+class AnnotBorderStyle {
+public:
+
+  AnnotBorderStyle(AnnotBorderType typeA, double widthA,
+		   double *dashA, int dashLengthA,
+		   double rA, double gA, double bA);
+  ~AnnotBorderStyle();
+
+  AnnotBorderType getType() { return type; }
+  double getWidth() { return width; }
+  void getDash(double **dashA, int *dashLengthA)
+    { *dashA = dash; *dashLengthA = dashLength; }
+  void getColor(double *rA, double *gA, double *bA)
+    { *rA = r; *gA = g; *bA = b; }
+
+private:
+
+  AnnotBorderType type;
+  double width;
+  double *dash;
+  int dashLength;
+  double r, g, b;
+};
 
 //------------------------------------------------------------------------
 // Annot
@@ -32,30 +68,57 @@
   ~Annot();
   GBool isOk() { return ok; }
 
-  void draw(Gfx *gfx);
+  void draw(Gfx *gfx, GBool printing);
 
   // Get appearance object.
   Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
   GBool textField() { return isTextField; }
 
+  AnnotBorderStyle *getBorderStyle () { return borderStyle; }
+
+  GBool match(Ref *refA)
+    { return ref.num == refA->num && ref.gen == refA->gen; }
+
+  void generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm);
+
   double getXMin() { return xMin; }
   double getYMin() { return yMin; }
 
   double getFontSize() { return fontSize; }
 
 private:
-  void writeTextString (GooString* vStr, CharCodeToUnicode* ccToUnicode, GooString* appearBuf, GfxFont* font);
-  void generateAppearance(Dict *acroForm, Dict *dict);
+//  void writeTextString (GooString* vStr, CharCodeToUnicode* ccToUnicode, GooString* appearBuf, GfxFont* font);
+//  void generateAppearance(Dict *acroForm, Dict *dict);
+  void setColor(Array *a, GBool fill, int adjust);
+  void drawText(GooString *text, GooString *da, GfxFontDict *fontDict,
+		GBool multiline, int comb, int quadding,
+		GBool txField, GBool forceZapfDingbats);
+  void drawListBox(GooString **text, GBool *selection,
+		   int nOptions, int topIdx,
+		   GooString *da, GfxFontDict *fontDict, GBool quadding);
+  void getNextLine(GooString *text, int start,
+		   GfxFont *font, double fontSize, double wMax,
+		   int *end, double *width, int *next);
+  void drawCircle(double cx, double cy, double r, GBool fill);
+  void drawCircleTopLeft(double cx, double cy, double r);
+  void drawCircleBottomRight(double cx, double cy, double r);
+  Object *fieldLookup(Dict *field, char *key, Object *obj);
   void readArrayNum(Object *pdfArray, int key, double *value);
+  // write vStr[i:j[ in appearBuf
+  void writeTextString (GooString *text, GooString *appearBuf, int *i, int j, CharCodeToUnicode *ccToUnicode); 
 
   void initialize (XRef *xrefA, Dict *acroForm, Dict *dict, Catalog *catalog);
 
   XRef *xref;			// the xref table for this PDF file
+  Ref ref; // object ref identifying 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;
   double fontSize; 
   GBool ok;
   GBool regen, isTextField;
@@ -63,8 +126,6 @@
   
   bool hasRef;
   bool hidden;
-  Ref ref;
-  FormWidget* widget;
 };
 
 //------------------------------------------------------------------------
@@ -74,7 +135,7 @@
 class Annots {
 public:
 
-  // Extract non-link annotations from array of annotations.
+  // Build a list of Annot objects.
   Annots(XRef *xref, Catalog *catalog, Object *annotsObj);
 
   ~Annots();
@@ -83,7 +144,15 @@
   int getNumAnnots() { return nAnnots; }
   Annot *getAnnot(int i) { return annots[i]; }
 
+  // (Re)generate the appearance streams for all annotations belonging
+  // to a form field.
+  void generateAppearances(Dict *acroForm);
+
+
 private:
+  void scanFieldAppearances(Dict *node, Ref *ref, Dict *parent,
+			    Dict *acroForm);
+  Annot *findAnnot(Ref *ref);
 
   Annot **annots;
   int nAnnots;

Index: ArthurOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/ArthurOutputDev.cc,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- ArthurOutputDev.cc	13 Nov 2006 19:16:44 -0000	1.12
+++ ArthurOutputDev.cc	25 Apr 2007 19:59:10 -0000	1.13
@@ -241,6 +241,8 @@
 
 void ArthurOutputDev::updateFont(GfxState *state)
 {
+#warning fix this, probably update with updated code from SplashOutputdev
+/*
   GfxFont *gfxFont;
   GfxFontType fontType;
   SplashOutFontFileID *id;
@@ -403,7 +405,7 @@
 
  err2:
   delete id;
- err1:
+ err1:*/
   return;
 }
 
@@ -513,9 +515,12 @@
 	  qPath.quadTo(x0+fontPath->pts[i].x, y0+fontPath->pts[i].y,
 		       x0+fontPath->pts[i+1].x, y0+fontPath->pts[i+1].y);
 	  ++i;
-	} else if (fontPath->flags[i] & splashPathArcCW) {
-	  qDebug() << "Need to implement arc";
-	} else {
+	}
+#warning FIX THIS
+// 	else if (fontPath->flags[i] & splashPathArcCW) {
+// 	  qDebug() << "Need to implement arc";
+// 	}
+	else {
 	  qPath.lineTo(x0+fontPath->pts[i].x, y0+fontPath->pts[i].y);
 	}
 	if (fontPath->flags[i] & splashPathLast) {

Index: Catalog.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Catalog.cc,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- Catalog.cc	24 Feb 2007 23:32:23 -0000	1.19
+++ Catalog.cc	25 Apr 2007 19:59:10 -0000	1.20
@@ -2,7 +2,7 @@
 //
 // Catalog.cc
 //
-// Copyright 1996-2003 Glyph & Cog, LLC
+// Copyright 1996-2007 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -23,23 +23,17 @@
 #include "Error.h"
 #include "Link.h"
 #include "PageLabelInfo.h"
-#include "UGooString.h"
 #include "Catalog.h"
 #include "Form.h"
 
-// This define is used to limit the depth of recursive readPageTree calls
-// This is needed because the page tree nodes can reference their parents
-// leaving us in an infinite loop
-// Most sane pdf documents don't have a call depth higher than 10
-#define MAX_CALL_DEPTH 1000
-
 //------------------------------------------------------------------------
 // Catalog
 //------------------------------------------------------------------------
 
 Catalog::Catalog(XRef *xrefA) {
-  Object catDict, pagesDict;
+  Object catDict, pagesDict, pagesDictRef;
   Object obj, obj2;
+  char *alreadyRead;
   int numPages0;
   int i;
 
@@ -91,7 +85,16 @@
     pageRefs[i].num = -1;
     pageRefs[i].gen = -1;
   }
-  numPages = readPageTree(pagesDict.getDict(), NULL, 0, 0);
+  alreadyRead = (char *)gmalloc(xref->getNumObjects());
+  memset(alreadyRead, 0, xref->getNumObjects());
+  if (catDict.dictLookupNF("Pages", &pagesDictRef)->isRef() &&
+      pagesDictRef.getRefNum() >= 0 &&
+      pagesDictRef.getRefNum() < xref->getNumObjects()) {
+    alreadyRead[pagesDictRef.getRefNum()] = 1;
+  }
+  pagesDictRef.free();
+  numPages = readPageTree(pagesDict.getDict(), NULL, 0, alreadyRead);
+  gfree(alreadyRead);
   if (numPages != numPages0) {
     error(-1, "Page count in top-level pages object is incorrect");
   }
@@ -234,7 +237,8 @@
   return s;
 }
 
-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start, int callDepth) {
+int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
+			  char *alreadyRead) {
   Object kids;
   Object kid;
   Object kidRef;
@@ -250,6 +254,17 @@
     goto err1;
   }
   for (i = 0; i < kids.arrayGetLength(); ++i) {
+    kids.arrayGetNF(i, &kidRef);
+    if (kidRef.isRef() &&
+	kidRef.getRefNum() >= 0 &&
+	kidRef.getRefNum() < xref->getNumObjects()) {
+      if (alreadyRead[kidRef.getRefNum()]) {
+	error(-1, "Loop in Pages tree");
+	kidRef.free();
+	continue;
+      }
+      alreadyRead[kidRef.getRefNum()] = 1;
+    }
     kids.arrayGet(i, &kid);
     if (kid.isDict("Page")) {
       attrs2 = new PageAttrs(attrs1, kid.getDict());
@@ -269,28 +284,23 @@
 	}
       }
       pages[start] = page;
-      kids.arrayGetNF(i, &kidRef);
       if (kidRef.isRef()) {
 	pageRefs[start].num = kidRef.getRefNum();
 	pageRefs[start].gen = kidRef.getRefGen();
       }
-      kidRef.free();
       ++start;
     // This should really be isDict("Pages"), but I've seen at least one
     // PDF file where the /Type entry is missing.
     } else if (kid.isDict()) {
-      if (callDepth > MAX_CALL_DEPTH) {
-        error(-1, "Limit of %d recursive calls reached while reading the page tree. If your document is correct and not a test to try to force a crash, please report a bug.", MAX_CALL_DEPTH);
-      } else {
-        if ((start = readPageTree(kid.getDict(), attrs1, start, callDepth + 1))
-	    < 0)
-	  goto err2;
-      }
+      if ((start = readPageTree(kid.getDict(), attrs1, start, alreadyRead))
+	  < 0)
+	goto err2;
     } else {
       error(-1, "Kid object (page %d) is wrong type (%s)",
 	    start+1, kid.getTypeName());
     }
     kid.free();
+    kidRef.free();
   }
   delete attrs1;
   kids.free();
@@ -317,7 +327,7 @@
   return 0;
 }
 
-LinkDest *Catalog::findDest(UGooString *name) {
+LinkDest *Catalog::findDest(GooString *name) {
   LinkDest *dest;
   Object obj1, obj2;
   GBool found;
@@ -325,7 +335,7 @@
   // try named destination dictionary then name tree
   found = gFalse;
   if (dests.isDict()) {
-    if (!dests.dictLookup(*name, &obj1)->isNull())
+    if (!dests.dictLookup(name->getCString(), &obj1)->isNull())
       found = gTrue;
     else
       obj1.free();
@@ -377,7 +387,7 @@
     delete[] descString;
     GooString *createDate = new GooString();
     GooString *modDate = new GooString();
-    Stream *efStream;
+    Stream *efStream = NULL;
     if (obj.isRef()) {
 	if (obj.fetch(xref, &efDict)->isDict()) {
 	    // efDict matches Table 3.40 in the PDF1.6 spec
@@ -452,7 +462,7 @@
     return embeddedFile;
 }
 
-NameTree::NameTree(void)
+NameTree::NameTree()
 {
   size = 0;
   length = 0;
@@ -460,23 +470,20 @@
 }
 
 NameTree::Entry::Entry(Array *array, int index) {
-    GooString n;
-    if (!array->getString(index, &n) || !array->getNF(index + 1, &value)) {
+    if (!array->getString(index, &name) || !array->getNF(index + 1, &value)) {
       Object aux;
       array->get(index, &aux);
       if (aux.isString() && array->getNF(index + 1, &value) )
       {
-        n.append(aux.getString());
+        name.append(aux.getString());
       }
       else
         error(-1, "Invalid page tree");
     }
-    name = new UGooString(n);
 }
 
 NameTree::Entry::~Entry() {
   value.free();
-  delete name;
 }
 
 void NameTree::addEntry(Entry *entry)
@@ -531,13 +538,13 @@
 
 int NameTree::Entry::cmp(const void *voidKey, const void *voidEntry)
 {
-  UGooString *key = (UGooString *) voidKey;
+  GooString *key = (GooString *) voidKey;
   Entry *entry = *(NameTree::Entry **) voidEntry;
 
-  return key->cmp(entry->name);
+  return key->cmp(&entry->name);
 }
 
-GBool NameTree::lookup(UGooString *name, Object *obj)
+GBool NameTree::lookup(GooString *name, Object *obj)
 {
   Entry **entry;
   char *cname;
@@ -548,9 +555,7 @@
     (*entry)->value.fetch(xref, obj);
     return gTrue;
   } else {
-    cname = name->getCString();
-    printf("failed to look up %s\n", cname);
-    delete[] cname;
+    printf("failed to look up %s\n", name->getCString());
     obj->initNull();
     return gFalse;
   }
@@ -565,10 +570,10 @@
   }
 }
 
-UGooString *NameTree::getName(int index)
+GooString *NameTree::getName(int index)
 {
     if (index < length) {
-	return entries[index]->name;
+	return &entries[index]->name;
     } else {
 	return NULL;
     }

Index: Catalog.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Catalog.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- Catalog.h	24 Feb 2007 23:32:23 -0000	1.11
+++ Catalog.h	25 Apr 2007 19:59:10 -0000	1.12
@@ -2,7 +2,7 @@
 //
 // Catalog.h
 //
-// Copyright 1996-2003 Glyph & Cog, LLC
+// Copyright 1996-2007 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -19,7 +19,6 @@
 class PageAttrs;
 struct Ref;
 class LinkDest;
-class UGooString;
 class PageLabelInfo;
 class Form;
 
@@ -32,18 +31,18 @@
   NameTree();
   void init(XRef *xref, Object *tree);
   void parse(Object *tree);
-  GBool lookup(UGooString *name, Object *obj);
+  GBool lookup(GooString *name, Object *obj);
   void free();
   int numEntries() { return length; };
   // iterator accessor
   Object getValue(int i);
-  UGooString *getName(int i);
+  GooString *getName(int i);
 
 private:
   struct Entry {
     Entry(Array *array, int index);
     ~Entry();
-    UGooString *name;
+    GooString name;
     Object value;
     void free();
     static int cmp(const void *key, const void *entry);
@@ -136,7 +135,9 @@
 
   // Find a named destination.  Returns the link destination, or
   // NULL if <name> is not a destination.
-  LinkDest *findDest(UGooString *name);
+  LinkDest *findDest(GooString *name);
+
+  Object *getDests() { return &dests; }
 
   // Get the number of embedded files
   int numEmbeddedFiles() { return embeddedFileNameTree.numEntries(); }
@@ -197,7 +198,8 @@
   PageMode pageMode;		// page mode
   PageLayout pageLayout;	// page layout
 
-  int readPageTree(Dict *pages, PageAttrs *attrs, int start, int callDepth);
+  int readPageTree(Dict *pages, PageAttrs *attrs, int start,
+		   char *alreadyRead);
   Object *findDestInTree(Object *tree, GooString *name, Object *obj);
 };
 

Index: CharCodeToUnicode.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/CharCodeToUnicode.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- CharCodeToUnicode.cc	24 Feb 2007 23:32:23 -0000	1.5
+++ CharCodeToUnicode.cc	25 Apr 2007 19:59:10 -0000	1.6
@@ -243,18 +243,8 @@
 	}
 	if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
 	      tok2[0] == '<' && tok2[n2 - 1] == '>')) {
-	  
-	  // check there was no line jump inside the token and so the length is 
-	  // longer than it should be
-	  int countAux = 0;
-	  for (int k = 0; k < n1; k++)
-	    if (tok1[k] != '\n' && tok1[k] != '\r') countAux++;
-	
-	  if (!(countAux == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
-	      tok2[0] == '<' && tok2[n2 - 1] == '>')) {
-	    error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
-	    continue;
-	  }
+	  error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
+	  continue;
 	}
 	tok1[n1 - 1] = tok2[n2 - 1] = '\0';
 	if (sscanf(tok1 + 1, "%x", &code1) != 1) {
@@ -278,21 +268,8 @@
 	}
 	if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
 	      n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) {
-	  // check there was no line jump inside the token and so the length is 
-	  // longer than it should be
-	  int countAux = 0;
-	  for (int k = 0; k < n1; k++)
-	    if (tok1[k] != '\n' && tok1[k] != '\r') countAux++;
-	  
-	  int countAux2 = 0;
-	  for (int k = 0; k < n1; k++)
-	    if (tok2[k] != '\n' && tok2[k] != '\r') countAux++;
-	  
-	  if (!(countAux == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
-	      countAux2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) {
-	    error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
-	    continue;
-	  }
+	  error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+	  continue;
 	}
 	tok1[n1 - 1] = tok2[n2 - 1] = '\0';
 	if (sscanf(tok1 + 1, "%x", &code1) != 1 ||

Index: DCTStream.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/DCTStream.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- DCTStream.cc	28 Jun 2006 19:23:52 -0000	1.5
+++ DCTStream.cc	25 Apr 2007 19:59:10 -0000	1.6
@@ -52,7 +52,7 @@
 {
 }
 
-DCTStream::DCTStream(Stream *strA):
+DCTStream::DCTStream(Stream *strA, int colorXformA) :
   FilterStream(strA) {
   init();
 }

Index: DCTStream.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/DCTStream.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- DCTStream.h	28 Jun 2006 19:23:52 -0000	1.6
+++ DCTStream.h	25 Apr 2007 19:59:10 -0000	1.7
@@ -50,7 +50,7 @@
 class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *strA);
+  DCTStream(Stream *strA, int colorXformA);
   virtual ~DCTStream();
   virtual StreamKind getKind() { return strDCT; }
   virtual void reset();
@@ -70,4 +70,4 @@
   JSAMPARRAY row_buffer;
 };
 
-#endif
+#endif 

Index: Decrypt.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Decrypt.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Decrypt.cc	16 Sep 2005 18:29:18 -0000	1.3
+++ Decrypt.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -18,6 +18,9 @@
 
 static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
 static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
+static void aesKeyExpansion(DecryptAESState *s,
+			    Guchar *objKey, int objKeyLen);
+static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last);
 static void md5(Guchar *msg, int msgLen, Guchar *digest);
 
 static Guchar passwordPad[32] = {
@@ -31,37 +34,6 @@
 // Decrypt
 //------------------------------------------------------------------------
 
-Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
-  int i;
-
-  // construct object key
-  for (i = 0; i < keyLength; ++i) {
-    objKey[i] = fileKey[i];
-  }
-  objKey[keyLength] = objNum & 0xff;
-  objKey[keyLength + 1] = (objNum >> 8) & 0xff;
-  objKey[keyLength + 2] = (objNum >> 16) & 0xff;
-  objKey[keyLength + 3] = objGen & 0xff;
-  objKey[keyLength + 4] = (objGen >> 8) & 0xff;
-  md5(objKey, keyLength + 5, objKey);
-
-  // set up for decryption
-  x = y = 0;
-  if ((objKeyLength = keyLength + 5) > 16) {
-    objKeyLength = 16;
-  }
-  rc4InitKey(objKey, objKeyLength, state);
-}
-
-void Decrypt::reset() {
-  x = y = 0;
-  rc4InitKey(objKey, objKeyLength, state);
-}
-
-Guchar Decrypt::decryptByte(Guchar c) {
-  return rc4DecryptByte(state, &x, &y, c);
-}
-
 GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
 			   GooString *ownerKey, GooString *userKey,
 			   int permissions, GooString *fileID,
@@ -206,6 +178,144 @@
 }
 
 //------------------------------------------------------------------------
+// DecryptStream
+//------------------------------------------------------------------------
+
+DecryptStream::DecryptStream(Stream *strA, Guchar *fileKey,
+			     CryptAlgorithm algoA, int keyLength,
+			     int objNum, int objGen):
+  FilterStream(strA)
+{
+  int n, i;
+
+  algo = algoA;
+
+  // construct object key
+  for (i = 0; i < keyLength; ++i) {
+    objKey[i] = fileKey[i];
+  }
+  objKey[keyLength] = objNum & 0xff;
+  objKey[keyLength + 1] = (objNum >> 8) & 0xff;
+  objKey[keyLength + 2] = (objNum >> 16) & 0xff;
+  objKey[keyLength + 3] = objGen & 0xff;
+  objKey[keyLength + 4] = (objGen >> 8) & 0xff;
+  if (algo == cryptAES) {
+    objKey[keyLength + 5] = 0x73; // 's'
+    objKey[keyLength + 6] = 0x41; // 'A'
+    objKey[keyLength + 7] = 0x6c; // 'l'
+    objKey[keyLength + 8] = 0x54; // 'T'
+    n = keyLength + 9;
+  } else {
+    n = keyLength + 5;
+  }
+  md5(objKey, n, objKey);
+  if ((objKeyLength = keyLength + 5) > 16) {
+    objKeyLength = 16;
+  }
+}
+
+DecryptStream::~DecryptStream() {
+  delete str;
+}
+
+void DecryptStream::reset() {
+  int i;
+
+  str->reset();
+  switch (algo) {
+  case cryptRC4:
+    state.rc4.x = state.rc4.y = 0;
+    rc4InitKey(objKey, objKeyLength, state.rc4.state);
+    state.rc4.buf = EOF;
+    break;
+  case cryptAES:
+    aesKeyExpansion(&state.aes, objKey, objKeyLength);
+    for (i = 0; i < 16; ++i) {
+      state.aes.cbc[i] = str->getChar();
+    }
+    state.aes.bufIdx = 16;
+    break;
+  }
+}
+
+int DecryptStream::getChar() {
+  Guchar in[16];
+  int c, i;
+
+  c = EOF; // make gcc happy
+  switch (algo) {
+  case cryptRC4:
+    if (state.rc4.buf == EOF) {
+      c = str->getChar();
+      if (c != EOF) {
+	state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x,
+				       &state.rc4.y, (Guchar)c);
+      }
+    }
+    c = state.rc4.buf;
+    state.rc4.buf = EOF;
+    break;
+  case cryptAES:
+    if (state.aes.bufIdx == 16) {
+      for (i = 0; i < 16; ++i) {
+	if ((c = str->getChar()) == EOF) {
+	  return EOF;
+	}
+	in[i] = (Guchar)c;
+      }
+      aesDecryptBlock(&state.aes, in, str->lookChar() == EOF);
+    }
+    if (state.aes.bufIdx == 16) {
+      c = EOF;
+    } else {
+      c = state.aes.buf[state.aes.bufIdx++];
+    }
+    break;
+  }
+  return c;
+}
+
+int DecryptStream::lookChar() {
+  Guchar in[16];
+  int c, i;
+
+  c = EOF; // make gcc happy
+  switch (algo) {
+  case cryptRC4:
+    if (state.rc4.buf == EOF) {
+      c = str->getChar();
+      if (c != EOF) {
+	state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x,
+				       &state.rc4.y, (Guchar)c);
+      }
+    }
+    c = state.rc4.buf;
+    break;
+  case cryptAES:
+    if (state.aes.bufIdx == 16) {
+      for (i = 0; i < 16; ++i) {
+	if ((c = str->getChar()) == EOF) {
+	  return EOF;
+	}
+	in[i] = c;
+      }
+      aesDecryptBlock(&state.aes, in, str->lookChar() == EOF);
+    }
+    if (state.aes.bufIdx == 16) {
+      c = EOF;
+    } else {
+      c = state.aes.buf[state.aes.bufIdx];
+    }
+    break;
+  }
+  return c;
+}
+
+GBool DecryptStream::isBinary(GBool last) {
+  return str->isBinary(last);
+}
+
+//------------------------------------------------------------------------
 // RC4-compatible decryption
 //------------------------------------------------------------------------
 
@@ -239,6 +349,261 @@
 }
 
 //------------------------------------------------------------------------
+// AES decryption
+//------------------------------------------------------------------------
+
+static Guchar sbox[256] = {
+  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+  0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+  0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+  0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+  0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+  0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+  0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+  0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+  0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+static Guchar invSbox[256] = {
+  0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+  0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+  0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+  0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+  0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+  0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+  0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+  0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+  0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+  0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+  0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+  0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+  0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+  0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+  0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+  0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+};
+
+static Guint rcon[11] = {
+  0x00000000, // unused
+  0x01000000,
+  0x02000000,
+  0x04000000,
+  0x08000000,
+  0x10000000,
+  0x20000000,
+  0x40000000,
+  0x80000000,
+  0x1b000000,
+  0x36000000
+};
+
+static inline Guint subWord(Guint x) {
+  return (sbox[x >> 24] << 24)
+         | (sbox[(x >> 16) & 0xff] << 16)
+         | (sbox[(x >> 8) & 0xff] << 8)
+         | sbox[x & 0xff];
+}
+
+static inline Guint rotWord(Guint x) {
+  return ((x << 8) & 0xffffffff) | (x >> 24);
+}
+
+static inline void invSubBytes(Guchar *state) {
+  int i;
+
+  for (i = 0; i < 16; ++i) {
+    state[i] = invSbox[state[i]];
+  }
+}
+
+static inline void invShiftRows(Guchar *state) {
+  Guchar t;
+
+  t = state[7];
+  state[7] = state[6];
+  state[6] = state[5];
+  state[5] = state[4];
+  state[4] = t;
+
+  t = state[8];
+  state[8] = state[10];
+  state[10] = t;
+  t = state[9];
+  state[9] = state[11];
+  state[11] = t;
+
+  t = state[12];
+  state[12] = state[13];
+  state[13] = state[14];
+  state[14] = state[15];
+  state[15] = t;
+}
+
+// {09} \cdot s
+static inline Guchar mul09(Guchar s) {
+  Guchar s2, s4, s8;
+
+  s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
+  s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
+  s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
+  return s ^ s8;
+}
+
+// {0b} \cdot s
+static inline Guchar mul0b(Guchar s) {
+  Guchar s2, s4, s8;
+
+  s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
+  s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
+  s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
+  return s ^ s2 ^ s8;
+}
+
+// {0d} \cdot s
+static inline Guchar mul0d(Guchar s) {
+  Guchar s2, s4, s8;
+
+  s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
+  s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
+  s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
+  return s ^ s4 ^ s8;
+}
+
+// {0e} \cdot s
+static inline Guchar mul0e(Guchar s) {
+  Guchar s2, s4, s8;
+
+  s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1);
+  s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1);
+  s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1);
+  return s2 ^ s4 ^ s8;
+}
+
+static inline void invMixColumns(Guchar *state) {
+  int c;
+  Guchar s0, s1, s2, s3;
+
+  for (c = 0; c < 4; ++c) {
+    s0 = state[c];
+    s1 = state[4+c];
+    s2 = state[8+c];
+    s3 = state[12+c];
+    state[c] =    mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3);
+    state[4+c] =  mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3);
+    state[8+c] =  mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3);
+    state[12+c] = mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3);
+  }
+}
+
+static inline void invMixColumnsW(Guint *w) {
+  int c;
+  Guchar s0, s1, s2, s3;
+
+  for (c = 0; c < 4; ++c) {
+    s0 = w[c] >> 24;
+    s1 = w[c] >> 16;
+    s2 = w[c] >> 8;
+    s3 = w[c];
+    w[c] = ((mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3)) << 24)
+           | ((mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3)) << 16)
+           | ((mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3)) << 8)
+           | (mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3));
+  }
+}
+
+static inline void addRoundKey(Guchar *state, Guint *w) {
+  int c;
+
+  for (c = 0; c < 4; ++c) {
+    state[c] ^= w[c] >> 24;
+    state[4+c] ^= w[c] >> 16;
+    state[8+c] ^= w[c] >> 8;
+    state[12+c] ^= w[c];
+  }
+}
+
+static void aesKeyExpansion(DecryptAESState *s,
+			    Guchar *objKey, int /*objKeyLen*/) {
+  Guint temp;
+  int i, round;
+
+  //~ this assumes objKeyLen == 16
+
+  for (i = 0; i < 4; ++i) {
+    s->w[i] = (objKey[4*i] << 24) + (objKey[4*i+1] << 16) +
+              (objKey[4*i+2] << 8) + objKey[4*i+3];
+  }
+  for (i = 4; i < 44; ++i) {
+    temp = s->w[i-1];
+    if (!(i & 3)) {
+      temp = subWord(rotWord(temp)) ^ rcon[i/4];
+    }
+    s->w[i] = s->w[i-4] ^ temp;
+  }
+  for (round = 1; round <= 9; ++round) {
+    invMixColumnsW(&s->w[round * 4]);
+  }
+}
+
+static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) {
+  int c, round, n, i;
+
+  // initial state
+  for (c = 0; c < 4; ++c) {
+    s->state[c] = in[4*c];
+    s->state[4+c] = in[4*c+1];
+    s->state[8+c] = in[4*c+2];
+    s->state[12+c] = in[4*c+3];
+  }
+
+  // round 0
+  addRoundKey(s->state, &s->w[10 * 4]);
+
+  // rounds 1-9
+  for (round = 9; round >= 1; --round) {
+    invSubBytes(s->state);
+    invShiftRows(s->state);
+    invMixColumns(s->state);
+    addRoundKey(s->state, &s->w[round * 4]);
+  }
+
+  // round 10
+  invSubBytes(s->state);
+  invShiftRows(s->state);
+  addRoundKey(s->state, &s->w[0]);
+
+  // CBC
+  for (c = 0; c < 4; ++c) {
+    s->buf[4*c] = s->state[c] ^ s->cbc[4*c];
+    s->buf[4*c+1] = s->state[4+c] ^ s->cbc[4*c+1];
+    s->buf[4*c+2] = s->state[8+c] ^ s->cbc[4*c+2];
+    s->buf[4*c+3] = s->state[12+c] ^ s->cbc[4*c+3];
+  }
+
+  // save the input block for the next CBC
+  for (i = 0; i < 16; ++i) {
+    s->cbc[i] = in[i];
+  }
+
+  // remove padding
+  s->bufIdx = 0;
+  if (last) {
+    n = s->buf[15];
+    for (i = 15; i >= n; --i) {
+      s->buf[i] = s->buf[i-n];
+    }
+    s->bufIdx = n;
+  }
+}
+
+//------------------------------------------------------------------------
 // MD5 message digest
 //------------------------------------------------------------------------
 

Index: Decrypt.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Decrypt.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Decrypt.h	16 Sep 2005 18:29:18 -0000	1.2
+++ Decrypt.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -15,6 +15,8 @@
 
 #include "goo/gtypes.h"
 #include "goo/GooString.h"
+#include "Object.h"
+#include "Stream.h"
 
 //------------------------------------------------------------------------
 // Decrypt
@@ -23,15 +25,6 @@
 class Decrypt {
 public:
 
-  // Initialize the decryptor object.
-  Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen);
-
-  // Reset decryption.
-  void reset();
-
-  // Decrypt one byte.
-  Guchar decryptByte(Guchar c);
-
   // Generate a file key.  The <fileKey> buffer must have space for at
   // least 16 bytes.  Checks <ownerPassword> and then <userPassword>
   // and returns true if either is correct.  Sets <ownerPasswordOk> if
@@ -51,11 +44,50 @@
 			    int permissions, GooString *fileID,
 			    GooString *userPassword, Guchar *fileKey,
 			    GBool encryptMetadata);
+};
 
-  int objKeyLength;
-  Guchar objKey[21];
+//------------------------------------------------------------------------
+// DecryptStream
+//------------------------------------------------------------------------
+
+struct DecryptRC4State {
   Guchar state[256];
   Guchar x, y;
+  int buf;
+};
+
+struct DecryptAESState {
+  Guint w[44];
+  Guchar state[16];
+  Guchar cbc[16];
+  Guchar buf[16];
+  int bufIdx;
+};
+
+class DecryptStream: public FilterStream {
+public:
+
+  DecryptStream(Stream *strA, Guchar *fileKey,
+		CryptAlgorithm algoA, int keyLength,
+		int objNum, int objGen);
+  virtual ~DecryptStream();
+  virtual StreamKind getKind() { return strWeird; }
+  virtual void reset();
+  virtual int getChar();
+  virtual int lookChar();
+  virtual GBool isBinary(GBool last);
+  virtual Stream *getUndecodedStream() { return this; }
+
+private:
+
+  CryptAlgorithm algo;
+  int objKeyLength;
+  Guchar objKey[16 + 9];
+
+  union {
+    DecryptRC4State rc4;
+    DecryptAESState aes;
+  } state;
 };
 
 #endif

Index: Dict.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Dict.cc,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Dict.cc	24 Feb 2007 23:32:23 -0000	1.6
+++ Dict.cc	25 Apr 2007 19:59:10 -0000	1.7
@@ -16,7 +16,6 @@
 #include <string.h>
 #include "goo/gmem.h"
 #include "Object.h"
-#include "UGooString.h"
 #include "XRef.h"
 #include "Dict.h"
 
@@ -35,13 +34,13 @@
   int i;
 
   for (i = 0; i < length; ++i) {
-    delete entries[i].key;
+    gfree(entries[i].key);
     entries[i].val.free();
   }
   gfree(entries);
 }
 
-void Dict::addOwnKeyVal(UGooString *key, Object *val) {
+void Dict::add(char *key, Object *val) {
   if (length == size) {
     if (length == 0) {
       size = 8;
@@ -55,24 +54,24 @@
   ++length;
 }
 
-inline DictEntry *Dict::find(const UGooString &key) {
+inline DictEntry *Dict::find(char *key) {
   int i;
 
   for (i = 0; i < length; ++i) {
-    if (!key.cmp(entries[i].key))
+    if (!strcmp(key, entries[i].key))
       return &entries[i];
   }
   return NULL;
 }
 
-void Dict::remove(const UGooString &key) {
+void Dict::remove(char *key) {
   int i; 
   bool found = false;
   DictEntry tmp;
   if(length == 0) return;
 
   for(i=0; i<length; i++) {
-    if (!key.cmp(entries[i].key)) {
+    if (!strcmp(key, entries[i].key)) {
       found = true;
       break;
     }
@@ -85,14 +84,14 @@
     entries[i] = tmp;
 }
 
-void Dict::set(const UGooString &key, Object *val) {
+void Dict::set(char *key, Object *val) {
   DictEntry *e;
   e = find (key);
   if (e) {
     e->val.free();
     e->val = *val;
   } else {
-    add (key, val);
+    add (copyString(key), val);
   }
 }
 
@@ -103,13 +102,13 @@
   return (e = find("Type")) && e->val.isName(type);
 }
 
-Object *Dict::lookup(const UGooString &key, Object *obj) {
+Object *Dict::lookup(char *key, Object *obj) {
   DictEntry *e;
 
   return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull();
 }
 
-Object *Dict::lookupNF(const UGooString &key, Object *obj) {
+Object *Dict::lookupNF(char *key, Object *obj) {
   DictEntry *e;
 
   return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
@@ -135,7 +134,7 @@
   return success;
 }
 
-UGooString *Dict::getKey(int i) {
+char *Dict::getKey(int i) {
   return entries[i].key;
 }
 

Index: Dict.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Dict.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Dict.h	24 Feb 2007 23:32:23 -0000	1.5
+++ Dict.h	25 Apr 2007 19:59:10 -0000	1.6
@@ -14,14 +14,13 @@
 #endif
 
 #include "Object.h"
-#include "UGooString.h"
 
 //------------------------------------------------------------------------
 // Dict
 //------------------------------------------------------------------------
 
 struct DictEntry {
-  UGooString *key;
+  char *key;
   Object val;
 };
 
@@ -41,31 +40,25 @@
   // Get number of entries.
   int getLength() { return length; }
 
-  // Add an entry
-  void addOwnKeyVal(UGooString *key, Object *val);
-  // FIXME: should also be renamed to addOwnVal()
-  void add(const UGooString &key, Object *val) {
-    addOwnKeyVal(new UGooString(key), val);
-  }
-  void addOwnVal(const char *key, Object *val) {
-    addOwnKeyVal(new UGooString(key), val);
-  }
+  // Add an entry.  NB: does not copy key.
+  void add(char *key, Object *val);
+
   // Update the value of an existing entry, otherwise create it
-  void set(const UGooString &key, Object *val);
+  void set(char *key, Object *val);
   // Remove an entry. This invalidate indexes
-  void remove(const UGooString &key);
+  void remove(char *key);
 
   // Check if dictionary is of specified type.
   GBool is(char *type);
 
   // Look up an entry and return the value.  Returns a null object
   // if <key> is not in the dictionary.
-  Object *lookup(const UGooString &key, Object *obj);
-  Object *lookupNF(const UGooString &key, Object *obj);
+  Object *lookup(char *key, Object *obj);
+  Object *lookupNF(char *key, Object *obj);
   GBool lookupInt(const char *key, const char *alt_key, int *value);
 
   // Iterative accessors.
-  UGooString *getKey(int i);
+  char *getKey(int i);
   Object *getVal(int i, Object *obj);
   Object *getValNF(int i, Object *obj);
 
@@ -82,7 +75,7 @@
   int length;			// number of entries in dictionary
   int ref;			// reference count
 
-  DictEntry *find(const UGooString &key);
+  DictEntry *find(char *key);
 };
 
 #endif

Index: FontInfo.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/FontInfo.cc,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- FontInfo.cc	14 May 2006 16:11:54 -0000	1.11
+++ FontInfo.cc	25 Apr 2007 19:59:10 -0000	1.12
@@ -12,7 +12,6 @@
 #include "Annot.h"
 #include "PDFDoc.h"
 #include "FontInfo.h"
-#include "UGooString.h"
 
 FontInfoScanner::FontInfoScanner(PDFDoc *docA) {
   doc = docA;

Index: Form.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Form.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Form.cc	6 Mar 2007 22:27:18 -0000	1.3
+++ Form.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -21,7 +21,6 @@
 #include "Array.h"
 #include "Dict.h"
 #include "Form.h"
-#include "UGooString.h"
 #include "XRef.h"
 #include "PDFDocEncoding.h"
 #include "Annot.h"
@@ -202,9 +201,9 @@
           for(int j=0; j<length2; j++) {
             Object obj3;
             tmpDict2->getVal(j, &obj3);
-            UGooString *key = tmpDict2->getKey(j);
-            if(strcmp(key->getCString(), "Off")) { //if we don't have Off, we have the name of the "on" state
-              onStr = strdup(key->getCString());
+            char *key = tmpDict2->getKey(j);
+            if(strcmp(key, "Off")) { //if we don't have Off, we have the name of the "on" state
+              onStr = strdup(key);
             }
             obj3.free();
           }
@@ -1066,7 +1065,7 @@
     oref.free();
   }
 
-  checkForNeedAppearances(); 
+  checkForNeedAppearances(acroForm); 
 }
 
 Form::~Form() {
@@ -1076,21 +1075,19 @@
   delete [] rootFields;
 }
 
-void Form::checkForNeedAppearances ()
+void Form::checkForNeedAppearances (Object *acroForm)
 {
   //NeedAppearances needs to be set to 'true' in the AcroForm entry of the Catalog to enable dynamic appearance generation
   Object* catalog = new Object();
-  Object acroForm;
   Ref catRef;
   catRef.gen = xref->getRootGen();
   catRef.num = xref->getRootNum();
   catalog = xref->getCatalog(catalog);
-  catalog->dictLookup("AcroForm", &acroForm);
+  catalog->dictLookup("AcroForm", acroForm);
   Object obj1;
   obj1.initBool(true);
-  acroForm.dictSet("NeedAppearances", &obj1);
-  obj1.free();
-  catalog->dictSet("AcroForm", &acroForm);
+  acroForm->dictSet("NeedAppearances", &obj1);
+  catalog->dictSet("AcroForm", acroForm);
   xref->setModifiedObject(catalog, catRef);
 }
 

Index: Form.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Form.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Form.h	25 Feb 2007 00:34:21 -0000	1.2
+++ Form.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -436,7 +436,7 @@
   void createFieldFromDict (Object* obj, FormField** ptr, XRef *xref, const Ref& aref);
 
   void postWidgetsLoad();
-  void checkForNeedAppearances ();
+  void checkForNeedAppearances (Object *acroForm);
 private:
   FormField** rootFields;
   int numFields;

Index: Function.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Function.cc,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Function.cc	10 Dec 2006 05:24:56 -0000	1.6
+++ Function.cc	25 Apr 2007 19:59:10 -0000	1.7
@@ -22,7 +22,6 @@
 #include "Stream.h"
 #include "Error.h"
 #include "Function.h"
-#include "UGooString.h"
 
 //------------------------------------------------------------------------
 // Function
@@ -191,10 +190,11 @@
   Object obj1, obj2;
   Guint buf, bitMask;
   int bits;
-  int s;
+  Guint s;
   int i;
 
   samples = NULL;
+  sBuf = NULL;
   ok = gFalse;
 
   //----- initialize the generic stuff
@@ -205,6 +205,14 @@
     error(-1, "Type 0 function is missing range");
     goto err1;
   }
+  if (m > sampledFuncMaxInputs) {
+    error(-1, "Sampled functions with more than %d inputs are unsupported",
+	  sampledFuncMaxInputs);
+    goto err1;
+  }
+
+  //----- buffer
+  sBuf = (double *)gmallocn(1 << m, sizeof(double));
 
   //----- get the stream
   if (!funcObj->isStream()) {
@@ -240,7 +248,7 @@
     goto err2;
   }
   sampleBits = obj1.getInt();
-  sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
+  sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1);
   obj1.free();
 
   //----- Encode
@@ -348,12 +356,16 @@
   if (samples) {
     gfree(samples);
   }
+  if (sBuf) {
+    gfree(sBuf);
+  }
 }
 
 SampledFunction::SampledFunction(SampledFunction *func) {
   memcpy(this, func, sizeof(SampledFunction));
   samples = (double *)gmallocn(nSamples, sizeof(double));
   memcpy(samples, func->samples, nSamples * sizeof(double));
+  sBuf = (double *)gmallocn(1 << m, sizeof(double));
 }
 
 void SampledFunction::transform(double *in, double *out) {
@@ -361,7 +373,6 @@
   int e[funcMaxInputs][2];
   double efrac0[funcMaxInputs];
   double efrac1[funcMaxInputs];
-  double s[1 << funcMaxInputs];
   int i, j, k, idx, t;
 
   // map input values into sample array
@@ -390,18 +401,18 @@
       for (k = 0, t = j; k < m; ++k, t >>= 1) {
 	idx += idxMul[k] * (e[k][t & 1]);
       }
-      if (idx >= 0 && idx < nSamples) s[j] = samples[idx];
+      sBuf[j] = samples[idx];
     }
 
     // do m sets of interpolations
     for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) {
       for (k = 0; k < t; k += 2) {
-	s[k >> 1] = efrac0[j] * s[k] + efrac1[j] * s[k+1];
+	sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1];
       }
     }
 
     // map output value to range
-    out[i] = s[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
+    out[i] = sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
     if (out[i] < range[i][0]) {
       out[i] = range[i][0];
     } else if (out[i] > range[i][1]) {
@@ -541,6 +552,7 @@
   funcs = NULL;
   bounds = NULL;
   encode = NULL;
+  scale = NULL;
 
   //----- initialize the generic stuff
   if (!init(dict)) {
@@ -560,6 +572,7 @@
   funcs = (Function **)gmallocn(k, sizeof(Function *));
   bounds = (double *)gmallocn(k + 1, sizeof(double));
   encode = (double *)gmallocn(2 * k, sizeof(double));
+  scale = (double *)gmallocn(k, sizeof(double));
   for (i = 0; i < k; ++i) {
     funcs[i] = NULL;
   }
@@ -610,6 +623,17 @@
   }
   obj1.free();
 
+  //----- pre-compute the scale factors
+  for (i = 0; i < k; ++i) {
+    if (bounds[i] == bounds[i+1]) {
+      // avoid a divide-by-zero -- in this situation, function i will
+      // never be used anyway
+      scale[i] = 0;
+    } else {
+      scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]);
+    }
+  }
+
   ok = gTrue;
   return;
 
@@ -631,6 +655,8 @@
   memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
   encode = (double *)gmallocn(2 * k, sizeof(double));
   memcpy(encode, func->encode, 2 * k * sizeof(double));
+  scale = (double *)gmallocn(k, sizeof(double));
+  memcpy(scale, func->scale, k * sizeof(double));
   ok = gTrue;
 }
 
@@ -647,6 +673,7 @@
   gfree(funcs);
   gfree(bounds);
   gfree(encode);
+  gfree(scale);
 }
 
 void StitchingFunction::transform(double *in, double *out) {
@@ -665,8 +692,7 @@
       break;
     }
   }
-  x = encode[2*i] + ((x - bounds[i]) / (bounds[i+1] - bounds[i])) *
-                    (encode[2*i+1] - encode[2*i]);
+  x = encode[2*i] + (x - bounds[i]) * scale[i];
   funcs[i]->transform(&x, out);
 }
 
@@ -1182,14 +1208,25 @@
 GooString *PostScriptFunction::getToken(Stream *str) {
   GooString *s;
   int c;
+  GBool comment;
 
   s = new GooString();
-  do {
-    c = str->getChar();
-    if (c != EOF) {
-      codeString->append(c);
+  comment = gFalse;
+  while (1) {
+    if ((c = str->getChar()) == EOF) {
+      break;
     }
-  } while (c != EOF && isspace(c));
+    codeString->append(c);
+    if (comment) {
+      if (c == '\x0a' || c == '\x0d') {
+	comment = gFalse;
+      }
+    } else if (c == '%') {
+      comment = gTrue;
+    } else if (!isspace(c)) {
+      break;
+    }
+  }
   if (c == '{' || c == '}') {
     s->append((char)c);
   } else if (isdigit(c) || c == '.' || c == '-') {

Index: Function.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Function.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Function.h	16 Oct 2005 14:58:14 -0000	1.2
+++ Function.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -25,8 +25,9 @@
 // Function
 //------------------------------------------------------------------------
 
-#define funcMaxInputs   8
-#define funcMaxOutputs 32
+#define funcMaxInputs        32
+#define funcMaxOutputs       32
+#define sampledFuncMaxInputs 16
 
 class Function {
 public:
@@ -129,6 +130,7 @@
   int idxMul[funcMaxInputs];	// sample array index multipliers
   double *samples;		// the samples
   int nSamples;			// size of the samples array
+  double *sBuf;			// buffer for the transform function
   GBool ok;
 };
 
@@ -178,6 +180,7 @@
   Function *getFunc(int i) { return funcs[i]; }
   double *getBounds() { return bounds; }
   double *getEncode() { return encode; }
+  double *getScale() { return scale; }
 
 private:
 
@@ -187,6 +190,7 @@
   Function **funcs;
   double *bounds;
   double *encode;
+  double *scale;
   GBool ok;
 };
 

Index: Gfx.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Gfx.cc,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- Gfx.cc	22 Mar 2007 20:56:25 -0000	1.14
+++ Gfx.cc	25 Apr 2007 19:59:10 -0000	1.15
@@ -32,10 +32,10 @@
 #include "GfxState.h"
 #include "OutputDev.h"
 #include "Page.h"
+#include "Annot.h"
 #include "Error.h"
 #include "Gfx.h"
 #include "ProfileData.h"
-#include "UGooString.h"
 
 // the MSVC math.h doesn't define this
 #ifndef M_PI
[...1760 lines suppressed...]
+      }
+      state->setLineDash(dash2, dashLength, 0);
+      out->updateLineDash(state);
+    }
+    //~ this doesn't currently handle the beveled and engraved styles
+    state->clearPath();
+    state->moveTo(annotX0, out->upsideDown() ? annotY1 : annotY0);
+    state->lineTo(annotX1, out->upsideDown() ? annotY1 : annotY0);
+    if (borderStyle->getType() != annotBorderUnderlined) {
+      state->lineTo(annotX1, out->upsideDown() ? annotY0 : annotY1);
+      state->lineTo(annotX0, out->upsideDown() ? annotY0 : annotY1);
+      state->closePath();
+    }
+    out->stroke(state);
+  }
+}
+
 void Gfx::saveState() {
   out->saveState(state);
   state = state->save();

Index: Gfx.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Gfx.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Gfx.h	30 Oct 2005 20:29:05 -0000	1.3
+++ Gfx.h	25 Apr 2007 19:59:10 -0000	1.4
@@ -22,6 +22,7 @@
 class Stream;
 class Parser;
 class Dict;
+class Function;
 class OutputDev;
 class GfxFontDict;
 class GfxFont;
@@ -37,12 +38,12 @@
 struct GfxPatch;
 class GfxState;
 struct GfxColor;
+class GfxColorSpace;
 class Gfx;
 class PDFRectangle;
+class AnnotBorderStyle;
 
 //------------------------------------------------------------------------
-// Gfx
-//------------------------------------------------------------------------
 
 enum GfxClipType {
   clipNone,
@@ -62,7 +63,7 @@
   tchkNone			// used to avoid empty initializer lists
 };
 
-#define maxArgs 8
+#define maxArgs 33
 
 struct Operator {
   char name[4];
@@ -71,6 +72,8 @@
   void (Gfx::*func)(Object args[], int numArgs);
 };
 
+//------------------------------------------------------------------------
+
 class GfxResources {
 public:
 
@@ -98,6 +101,10 @@
   GfxResources *next;
 };
 
+//------------------------------------------------------------------------
+// Gfx
+//------------------------------------------------------------------------
+
 class Gfx {
 public:
 
@@ -119,10 +126,10 @@
   // Interpret a stream or array of streams.
   void display(Object *obj, GBool topLevel = gTrue);
 
-  // Display an annotation, given its appearance (a Form XObject) and
-  // bounding box (in default user space).
-  void doAnnot(Object *str, double xMin, double yMin,
-	       double xMax, double yMax);
+  // Display an annotation, given its appearance (a Form XObject),
+  // border style, and bounding box (in default user space).
+  void drawAnnot(Object *str, AnnotBorderStyle *borderStyle,
+		 double xMin, double yMin, double xMax, double yMax);
 
   // Save graphics state.
   void saveState();
@@ -176,6 +183,10 @@
   void opSetMiterLimit(Object args[], int numArgs);
   void opSetLineWidth(Object args[], int numArgs);
   void opSetExtGState(Object args[], int numArgs);
+  void doSoftMask(Object *str, GBool alpha,
+		  GfxColorSpace *blendingColorSpace,
+		  GBool isolated, GBool knockout,
+		  Function *transferFunc, GfxColor *backdropColor);
   void opSetRenderingIntent(Object args[], int numArgs);
 
   // color operators
@@ -212,8 +223,11 @@
   void opEOFillStroke(Object args[], int numArgs);
   void opCloseEOFillStroke(Object args[], int numArgs);
   void doPatternFill(GBool eoFill);
-  void doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill);
-  void doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill);
+  void doPatternStroke();
+  void doTilingPatternFill(GfxTilingPattern *tPat,
+			   GBool stroke, GBool eoFill);
+  void doShadingPatternFill(GfxShadingPattern *sPat,
+			    GBool stroke, GBool eoFill);
   void opShFill(Object args[], int numArgs);
   void doFunctionShFill(GfxFunctionShading *shading);
   void doFunctionShFill1(GfxFunctionShading *shading,
@@ -265,7 +279,12 @@
   void opXObject(Object args[], int numArgs);
   void doImage(Object *ref, Stream *str, GBool inlineImg);
   void doForm(Object *str);
-  void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox);
+  void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox,
+	       GBool transpGroup = gFalse, GBool softMask = gFalse,
+	       GfxColorSpace *blendingColorSpace = NULL,
+	       GBool isolated = gFalse, GBool knockout = gFalse,
+	       GBool alpha = gFalse, Function *transferFunc = NULL,
+	       GfxColor *backdropColor = NULL);
 
   // in-line image operators
   void opBeginImage(Object args[], int numArgs);

Index: GfxFont.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/GfxFont.cc,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- GfxFont.cc	24 Feb 2007 23:32:23 -0000	1.10
+++ GfxFont.cc	25 Apr 2007 19:59:10 -0000	1.11
@@ -28,7 +28,6 @@
 #include <fofi/FoFiType1.h>
 #include <fofi/FoFiType1C.h>
 #include <fofi/FoFiTrueType.h>
-#include "UGooString.h"
 #include "GfxFont.h"
 
 //------------------------------------------------------------------------
@@ -264,29 +263,42 @@
       if (obj2.fetch(xref, &obj3)->isStream()) {
 	obj3.streamGetDict()->lookup("Subtype", &obj4);
 	if (obj4.isName("Type1")) {
-	    embFontID = obj2.getRef();
+	  embFontID = obj2.getRef();
 	  if (type != fontType1) {
 	    error(-1, "Mismatch between font type and embedded font file");
 	    type = fontType1;
 	  }
 	} else if (obj4.isName("Type1C")) {
-	    embFontID = obj2.getRef();
+	  embFontID = obj2.getRef();
 	  if (type != fontType1 && type != fontType1C) {
 	    error(-1, "Mismatch between font type and embedded font file");
 	  }
 	  type = fontType1C;
 	} else if (obj4.isName("TrueType")) {
-	    embFontID = obj2.getRef();
+	  embFontID = obj2.getRef();
 	  if (type != fontTrueType) {
 	    error(-1, "Mismatch between font type and embedded font file");
 	    type = fontTrueType;
 	  }
 	} else if (obj4.isName("CIDFontType0C")) {
-	    embFontID = obj2.getRef();
+	  embFontID = obj2.getRef();
 	  if (type != fontCIDType0) {
 	    error(-1, "Mismatch between font type and embedded font file");
 	  }
 	  type = fontCIDType0C;
+	} else if (obj4.isName("OpenType")) {
+	  embFontID = obj2.getRef();
+	  if (type == fontTrueType) {
+	    type = fontTrueTypeOT;
+	  } else if (type == fontType1) {
+	    type = fontType1COT;
+	  } else if (type == fontCIDType0) {
+	    type = fontCIDType0COT;
+	  } else if (type == fontCIDType2) {
+	    type = fontCIDType2OT;
+	  } else {
+	    error(-1, "Mismatch between font type and embedded font file");
+	  }
 	} else {
 	  error(-1, "Unknown embedded font type '%s'",
 		obj4.isName() ? obj4.getName() : "???");
@@ -804,6 +816,15 @@
 	}
       }
     }
+
+  // if the 'mapUnknownCharNames' flag is set, do a simple pass-through
+  // mapping for unknown character names
+  } else if (missing && globalParams->getMapUnknownCharNames()) {
+    for (code = 0; code < 256; ++code) {
+      if (!toUnicode[code]) {
+	toUnicode[code] = code;
+      }
+    }
   }
 
   // construct the char code -> Unicode mapping object
@@ -1026,10 +1047,10 @@
       useMacRoman = gTrue;
     }
   } else {
-    if (macRomanCmap >= 0) {
-      cmap = macRomanCmap;
-    } else if (msSymbolCmap >= 0) {
+    if (msSymbolCmap >= 0) {
       cmap = msSymbolCmap;
+    } else if (macRomanCmap >= 0) {
+      cmap = macRomanCmap;
     }
   }
 
@@ -1215,9 +1236,9 @@
 	  n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
 	  if (n >= 1) {
 	    ctu->setMapping(c, uBuf, n);
+	  }
+	}
       }
-    }
-  }
       utu->decRefCnt();
     } else {
       ctu = utu;
@@ -1637,10 +1658,8 @@
 	  r.gen = 999999;
 	}
       }
-      char *aux = fontDict->getKey(i)->getCString();
-      fonts[i] = GfxFont::makeFont(xref, aux,
+      fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
 				   r, obj2.getDict());
-      delete[] aux;
       if (fonts[i] && !fonts[i]->isOk()) {
 	delete fonts[i];
 	fonts[i] = NULL;

Index: GfxFont.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/GfxFont.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- GfxFont.h	24 Feb 2007 23:32:23 -0000	1.5
+++ GfxFont.h	25 Apr 2007 19:59:10 -0000	1.6
@@ -33,12 +33,16 @@
   fontUnknownType,
   fontType1,
   fontType1C,
+  fontType1COT,
   fontType3,
   fontTrueType,
+  fontTrueTypeOT,
   //----- GfxCIDFont
   fontCIDType0,
   fontCIDType0C,
-  fontCIDType2
+  fontCIDType0COT,
+  fontCIDType2,
+  fontCIDType2OT
 };
 
 //------------------------------------------------------------------------
@@ -161,6 +165,7 @@
   GooString *getExtFontFile() { return extFontFile; }
 
   // Get font descriptor flags.
+  int getFlags() { return flags; }
   GBool isFixedWidth() { return flags & fontFixedWidth; }
   GBool isSerif() { return flags & fontSerif; }
   GBool isSymbolic() { return flags & fontSymbolic; }

Index: GfxState.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/GfxState.cc,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- GfxState.cc	30 Jul 2006 20:31:31 -0000	1.14
+++ GfxState.cc	25 Apr 2007 19:59:10 -0000	1.15
@@ -22,7 +22,6 @@
 #include "Page.h"
 #include "GfxState.h"
 #include "GfxFont.h"
-#include "UGooString.h"
 
 //------------------------------------------------------------------------
 
@@ -62,12 +61,12 @@
 
 //------------------------------------------------------------------------
 
-struct gfxBlendModeName {
+struct GfxBlendModeInfo {
   char *name;
   GfxBlendMode mode;
 };
 
-static gfxBlendModeName gfxBlendModeNames[] = {
+static GfxBlendModeInfo gfxBlendModeNames[] = {
   { "Normal",     gfxBlendNormal },
   { "Compatible", gfxBlendNormal },
   { "Multiply",   gfxBlendMultiply },
@@ -88,7 +87,7 @@
 };
 
 #define nGfxBlendModeNames \
-          ((int)((sizeof(gfxBlendModeNames) / sizeof(gfxBlendModeName))))
+          ((int)((sizeof(gfxBlendModeNames) / sizeof(GfxBlendModeInfo))))
 	 
 //------------------------------------------------------------------------
 // 
@@ -264,6 +263,10 @@
   cmyk->k = clip01(gfxColorComp1 - color->c[0]);
 }
 
+void GfxDeviceGrayColorSpace::getDefaultColor(GfxColor *color) {
+  color->c[0] = 0;
+}
+
 //------------------------------------------------------------------------
 // GfxCalGrayColorSpace
 //------------------------------------------------------------------------
@@ -361,6 +364,10 @@
   cmyk->k = clip01(gfxColorComp1 - color->c[0]);
 }
 
+void GfxCalGrayColorSpace::getDefaultColor(GfxColor *color) {
+  color->c[0] = 0;
+}
+
 //------------------------------------------------------------------------
 // GfxDeviceRGBColorSpace
 //------------------------------------------------------------------------
@@ -426,6 +433,12 @@
   cmyk->k = k;
 }
 
+void GfxDeviceRGBColorSpace::getDefaultColor(GfxColor *color) {
+  color->c[0] = 0;
+  color->c[1] = 0;
+  color->c[2] = 0;
+}
+
 //------------------------------------------------------------------------
 // GfxCalRGBColorSpace
 //------------------------------------------------------------------------
@@ -577,6 +590,12 @@
   cmyk->k = k;
 }
 
+void GfxCalRGBColorSpace::getDefaultColor(GfxColor *color) {
+  color->c[0] = 0;
+  color->c[1] = 0;
+  color->c[2] = 0;
+}
+
 //------------------------------------------------------------------------
 // GfxDeviceCMYKColorSpace
 //------------------------------------------------------------------------
@@ -667,6 +686,13 @@
   cmyk->k = clip01(color->c[3]);
 }
 
+void GfxDeviceCMYKColorSpace::getDefaultColor(GfxColor *color) {
+  color->c[0] = 0;
+  color->c[1] = 0;
+  color->c[2] = 0;
+  color->c[3] = gfxColorComp1;
+}
+
 //------------------------------------------------------------------------
 // GfxLabColorSpace
 //------------------------------------------------------------------------
@@ -782,7 +808,7 @@
 
   getRGB(color, &rgb);
   *gray = clip01((GfxColorComp)(0.299 * rgb.r +
-		 0.587 * rgb.g +
+				0.587 * rgb.g +
 				0.114 * rgb.b + 0.5));
 }
 
@@ -844,6 +870,24 @@
   cmyk->k = k;
 }
 
+void GfxLabColorSpace::getDefaultColor(GfxColor *color) {
+  color->c[0] = 0;
+  if (aMin > 0) {
+    color->c[1] = dblToCol(aMin);
+  } else if (aMax < 0) {
+    color->c[1] = dblToCol(aMax);
+  } else {
+    color->c[1] = 0;
+  }
+  if (bMin > 0) {
+    color->c[2] = dblToCol(bMin);
+  } else if (bMax < 0) {
+    color->c[2] = dblToCol(bMax);
+  } else {
+    color->c[2] = 0;
+  }
+}
+
 void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
 					int maxImgPixel) {
   decodeLow[0] = 0;
@@ -974,6 +1018,20 @@
   alt->getCMYK(color, cmyk);
 }
 
+void GfxICCBasedColorSpace::getDefaultColor(GfxColor *color) {
+  int i;
+
+  for (i = 0; i < nComps; ++i) {
+    if (rangeMin[i] > 0) {
+      color->c[i] = dblToCol(rangeMin[i]);
+    } else if (rangeMax[i] < 0) {
+      color->c[i] = dblToCol(rangeMax[i]);
+    } else {
+      color->c[i] = 0;
+    }
+  }
+}
+
 void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
 					     double *decodeRange,
 					     int maxImgPixel) {
@@ -1142,6 +1200,10 @@
   base->getCMYK(mapColorToBase(color, &color2), cmyk);
 }
 
+void GfxIndexedColorSpace::getDefaultColor(GfxColor *color) {
+  color->c[0] = 0;
+}
+
 void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
 					    double *decodeRange,
 					    int maxImgPixel) {
@@ -1159,6 +1221,7 @@
   name = nameA;
   alt = altA;
   func = funcA;
+  nonMarking = !name->cmp("None");
 }
 
 GfxSeparationColorSpace::~GfxSeparationColorSpace() {
@@ -1255,6 +1318,10 @@
   alt->getCMYK(&color2, cmyk);
 }
 
+void GfxSeparationColorSpace::getDefaultColor(GfxColor *color) {
+  color->c[0] = gfxColorComp1;
+}
+
 //------------------------------------------------------------------------
 // GfxDeviceNColorSpace
 //------------------------------------------------------------------------
@@ -1265,6 +1332,7 @@
   nComps = nCompsA;
   alt = altA;
   func = funcA;
+  nonMarking = gFalse;
 }
 
 GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
@@ -1285,6 +1353,7 @@
   for (i = 0; i < nComps; ++i) {
     cs->names[i] = names[i]->copy();
   }
+  cs->nonMarking = nonMarking;
   return cs;
 }
 
@@ -1334,8 +1403,12 @@
   }
   obj1.free();
   cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
+  cs->nonMarking = gTrue;
   for (i = 0; i < nCompsA; ++i) {
     cs->names[i] = namesA[i];
+    if (namesA[i]->cmp("None")) {
+      cs->nonMarking = gFalse;
+    }
   }
   return cs;
 
@@ -1396,6 +1469,14 @@
   alt->getCMYK(&color2, cmyk);
 }
 
+void GfxDeviceNColorSpace::getDefaultColor(GfxColor *color) {
+  int i;
+
+  for (i = 0; i < nComps; ++i) {
+    color->c[i] = gfxColorComp1;
+  }
+}
+
 //------------------------------------------------------------------------
 // GfxPatternColorSpace
 //------------------------------------------------------------------------
@@ -1451,6 +1532,10 @@
   cmyk->k = 1;
 }
 
+void GfxPatternColorSpace::getDefaultColor(GfxColor * /*color*/) {
+  // not used
+}
+
 //------------------------------------------------------------------------
 // Pattern
 //------------------------------------------------------------------------
@@ -3265,6 +3350,11 @@
   maxPixel = (1 << bits) - 1;
   colorSpace = colorSpaceA;
 
+  // initialize
+  for (k = 0; k < gfxColorMaxComps; ++k) {
+    lookup[k] = NULL;
+  }
+
   // get decode map
   if (decode->isNull()) {
     nComps = colorSpace->getNComps();
@@ -3299,9 +3389,6 @@
   // Optimization: for Indexed and Separation color spaces (which have
   // only one component), we store color values in the lookup table
   // rather than component values.
-  for (k = 0; k < gfxColorMaxComps; ++k) {
-    lookup[k] = NULL;
-  }
   colorSpace2 = NULL;
   nComps2 = 0;
   if (colorSpace->getMode() == csIndexed) {
@@ -3371,9 +3458,6 @@
   obj.free();
  err1:
   ok = gFalse;
-  for (k = 0; k < gfxColorMaxComps; ++k) {
-    lookup[k] = NULL;
-  }
   byte_lookup = NULL;
 }
 
@@ -3741,10 +3825,12 @@
 // GfxState
 //------------------------------------------------------------------------
 
-GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
+GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox,
 		   int rotateA, GBool upsideDown) {
   double kx, ky;
 
+  hDPI = hDPIA;
+  vDPI = vDPIA;
   rotate = rotateA;
   px1 = pageBox->x1;
   py1 = pageBox->y1;
@@ -3801,6 +3887,7 @@
   strokeOpacity = 1;
   fillOverprint = gFalse;
   strokeOverprint = gFalse;
+  transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL;
 
   lineWidth = 1;
   lineDash = NULL;
@@ -3810,6 +3897,7 @@
   lineJoin = 0;
   lineCap = 0;
   miterLimit = 10;
+  strokeAdjust = gFalse;
 
   font = NULL;
   fontSize = 0;
@@ -3836,6 +3924,8 @@
 }
 
 GfxState::~GfxState() {
+  int i;
+
   if (fillColorSpace) {
     delete fillColorSpace;
   }
@@ -3848,6 +3938,11 @@
   if (strokePattern) {
     delete strokePattern;
   }
+  for (i = 0; i < 4; ++i) {
+    if (transfer[i]) {
+      delete transfer[i];
+    }
+  }
   gfree(lineDash);
   if (path) {
     // this gets set to NULL by restore()
@@ -3863,6 +3958,8 @@
 
 // Used for copy();
 GfxState::GfxState(GfxState *state) {
+  int i;
+
   memcpy(this, state, sizeof(GfxState));
   if (fillColorSpace) {
     fillColorSpace = state->fillColorSpace->copy();
@@ -3876,6 +3973,11 @@
   if (strokePattern) {
     strokePattern = state->strokePattern->copy();
   }
+  for (i = 0; i < 4; ++i) {
+    if (transfer[i]) {
+      transfer[i] = state->transfer[i]->copy();
+    }
+  }
   if (lineDashLength > 0) {
     lineDash = (double *)gmallocn(lineDashLength, sizeof(double));
     memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
@@ -4024,6 +4126,15 @@
   }
 }
 
+void GfxState::shiftCTM(double tx, double ty) {
+  ctm[4] += tx;
+  ctm[5] += ty;
+  clipXMin += tx;
+  clipYMin += ty;
+  clipXMax += tx;
+  clipYMax += ty;
+}
+
 void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
   if (fillColorSpace) {
     delete fillColorSpace;
@@ -4060,6 +4171,17 @@
   fontSize = fontSizeA;
 }
 
+void GfxState::setTransfer(Function **funcs) {
+  int i;
+
+  for (i = 0; i < 4; ++i) {
+    if (transfer[i]) {
+      delete transfer[i];
+    }
+    transfer[i] = funcs[i];
+  }
+}
+
 void GfxState::setLineDash(double *dash, int length, double start) {
   if (lineDash)
     gfree(lineDash);
@@ -4114,6 +4236,69 @@
   }
 }
 
+void GfxState::clipToStrokePath() {
+  double xMin, yMin, xMax, yMax, x, y, t0, t1;
+  GfxSubpath *subpath;
+  int i, j;
+
+  xMin = xMax = yMin = yMax = 0; // make gcc happy
+  for (i = 0; i < path->getNumSubpaths(); ++i) {
+    subpath = path->getSubpath(i);
+    for (j = 0; j < subpath->getNumPoints(); ++j) {
+      transform(subpath->getX(j), subpath->getY(j), &x, &y);
+      if (i == 0 && j == 0) {
+	xMin = xMax = x;
+	yMin = yMax = y;
+      } else {
+	if (x < xMin) {
+	  xMin = x;
+	} else if (x > xMax) {
+	  xMax = x;
+	}
+	if (y < yMin) {
+	  yMin = y;
+	} else if (y > yMax) {
+	  yMax = y;
+	}
+      }
+    }
+  }
+
+  // allow for the line width
+  //~ miter joins can extend farther than this
+  t0 = fabs(ctm[0]);
+  t1 = fabs(ctm[2]);
+  if (t0 > t1) {
+    xMin -= 0.5 * lineWidth * t0;
+    xMax += 0.5 * lineWidth * t0;
+  } else {
+    xMin -= 0.5 * lineWidth * t1;
+    xMax += 0.5 * lineWidth * t1;
+  }
+  t0 = fabs(ctm[0]);
+  t1 = fabs(ctm[3]);
+  if (t0 > t1) {
+    yMin -= 0.5 * lineWidth * t0;
+    yMax += 0.5 * lineWidth * t0;
+  } else {
+    yMin -= 0.5 * lineWidth * t1;
+    yMax += 0.5 * lineWidth * t1;
+  }
+
+  if (xMin > clipXMin) {
+    clipXMin = xMin;
+  }
+  if (yMin > clipYMin) {
+    clipYMin = yMin;
+  }
+  if (xMax < clipXMax) {
+    clipXMax = xMax;
+  }
+  if (yMax < clipYMax) {
+    clipYMax = yMax;
+  }
+}
+
 void GfxState::textShift(double tx, double ty) {
   double dx, dy;
 

Index: GfxState.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/GfxState.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- GfxState.h	13 May 2006 16:01:57 -0000	1.6
+++ GfxState.h	25 Apr 2007 19:59:10 -0000	1.7
@@ -156,11 +156,18 @@
   // Return the number of color components.
   virtual int getNComps() = 0;
 
+  // Get this color space's default color.
+  virtual void getDefaultColor(GfxColor *color) = 0;
+
   // Return the default ranges for each component, assuming an image
   // with a max pixel value of <maxImgPixel>.
   virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
 				int maxImgPixel);
 
+  // Returns true if painting operations in this color space never
+  // mark the page (e.g., the "None" colorant).
+  virtual GBool isNonMarking() { return gFalse; }
+
   // Return the number of color space modes
   static int getNumColorSpaceModes();
 
@@ -189,6 +196,7 @@
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
 
   virtual int getNComps() { return 1; }
+  virtual void getDefaultColor(GfxColor *color);
 
 private:
 };
@@ -215,6 +223,7 @@
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
 
   virtual int getNComps() { return 1; }
+  virtual void getDefaultColor(GfxColor *color);
 
   // CalGray-specific access.
   double getWhiteX() { return whiteX; }
@@ -251,6 +260,7 @@
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
 
   virtual int getNComps() { return 3; }
+  virtual void getDefaultColor(GfxColor *color);
 
 private:
 };
@@ -277,6 +287,7 @@
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
 
   virtual int getNComps() { return 3; }
+  virtual void getDefaultColor(GfxColor *color);
 
   // CalRGB-specific access.
   double getWhiteX() { return whiteX; }
@@ -295,7 +306,7 @@
   double whiteX, whiteY, whiteZ;    // white point
   double blackX, blackY, blackZ;    // black point
   double gammaR, gammaG, gammaB;    // gamma values
-  double mat[9];		// ABC -> XYZ transform matrix
+  double mat[9];		    // ABC -> XYZ transform matrix
 };
 
 //------------------------------------------------------------------------
@@ -315,6 +326,7 @@
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
 
   virtual int getNComps() { return 4; }
+  virtual void getDefaultColor(GfxColor *color);
 
 private:
 };
@@ -339,6 +351,7 @@
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
 
   virtual int getNComps() { return 3; }
+  virtual void getDefaultColor(GfxColor *color);
 
   virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
 				int maxImgPixel);
@@ -385,6 +398,7 @@
 
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
   virtual int getNComps() { return nComps; }
+  virtual void getDefaultColor(GfxColor *color);
 
   virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
 				int maxImgPixel);
@@ -422,6 +436,7 @@
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
 
   virtual int getNComps() { return 1; }
+  virtual void getDefaultColor(GfxColor *color);
 
   virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
 				int maxImgPixel);
@@ -460,6 +475,9 @@
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
 
   virtual int getNComps() { return 1; }
+  virtual void getDefaultColor(GfxColor *color);
+
+  virtual GBool isNonMarking() { return nonMarking; }
 
   // Separation-specific access.
   GooString *getName() { return name; }
@@ -471,6 +489,7 @@
   GooString *name;		// colorant name
   GfxColorSpace *alt;		// alternate color space
   Function *func;		// tint transform (into alternate color space)
+  GBool nonMarking;
 };
 
 //------------------------------------------------------------------------
@@ -493,6 +512,9 @@
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
 
   virtual int getNComps() { return nComps; }
+  virtual void getDefaultColor(GfxColor *color);
+
+  virtual GBool isNonMarking() { return nonMarking; }
 
   // DeviceN-specific access.
   GooString *getColorantName(int i) { return names[i]; }
@@ -506,6 +528,7 @@
     *names[gfxColorMaxComps];
   GfxColorSpace *alt;		// alternate color space
   Function *func;		// tint transform (into alternate color space)
+  GBool nonMarking;
 };
 
 //------------------------------------------------------------------------
@@ -528,6 +551,7 @@
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
 
   virtual int getNComps() { return 0; }
+  virtual void getDefaultColor(GfxColor *color);
 
   // Pattern-specific access.
   GfxColorSpace *getUnder() { return under; }
@@ -1014,7 +1038,7 @@
   // Construct a default GfxState, for a device with resolution <hDPI>
   // x <vDPI>, page box <pageBox>, page rotation <rotateA>, and
   // coordinate system specified by <upsideDown>.
-  GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
+  GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox,
 	   int rotateA, GBool upsideDown);
 
   // Destructor.
@@ -1024,6 +1048,8 @@
   GfxState *copy() { return new GfxState(this); }
 
   // Accessors.
+  double getHDPI() { return hDPI; }
+  double getVDPI() { return vDPI; }
   double *getCTM() { return ctm; }
   void getCTM(Matrix *m) { memcpy (m->m, ctm, sizeof m->m); }
   double getX1() { return px1; }
@@ -1056,6 +1082,7 @@
   double getStrokeOpacity() { return strokeOpacity; }
   GBool getFillOverprint() { return fillOverprint; }
   GBool getStrokeOverprint() { return strokeOverprint; }
+  Function **getTransfer() { return transfer; }
   double getLineWidth() { return lineWidth; }
   void getLineDash(double **dash, int *length, double *start)
     { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; }
@@ -1063,6 +1090,7 @@
   int getLineJoin() { return lineJoin; }
   int getLineCap() { return lineCap; }
   double getMiterLimit() { return miterLimit; }
+  GBool getStrokeAdjust() { return strokeAdjust; }
   GfxFont *getFont() { return font; }
   double getFontSize() { return fontSize; }
   double *getTextMat() { return textMat; }
@@ -1110,6 +1138,7 @@
 	      double d, double e, double f);
   void concatCTM(double a, double b, double c,
 		 double d, double e, double f);
+  void shiftCTM(double tx, double ty);
   void setFillColorSpace(GfxColorSpace *colorSpace);
   void setStrokeColorSpace(GfxColorSpace *colorSpace);
   void setFillColor(GfxColor *color) { fillColor = *color; }
@@ -1121,12 +1150,14 @@
   void setStrokeOpacity(double opac) { strokeOpacity = opac; }
   void setFillOverprint(GBool op) { fillOverprint = op; }
   void setStrokeOverprint(GBool op) { strokeOverprint = op; }
+  void setTransfer(Function **funcs);
   void setLineWidth(double width) { lineWidth = width; }
   void setLineDash(double *dash, int length, double start);
   void setFlatness(int flatness1) { flatness = flatness1; }
   void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
   void setLineCap(int lineCap1) { lineCap = lineCap1; }
   void setMiterLimit(double limit) { miterLimit = limit; }
+  void setStrokeAdjust(GBool sa) { strokeAdjust = sa; }
   void setFont(GfxFont *fontA, double fontSizeA);
   void setTextMat(double a, double b, double c,
 		  double d, double e, double f)
@@ -1159,6 +1190,7 @@
 
   // Update clip region.
   void clip();
+  void clipToStrokePath();
 
   // Text position.
   void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; }
@@ -1177,6 +1209,7 @@
 
 private:
 
+  double hDPI, vDPI;		// resolution
   double ctm[6];		// coord transform matrix
   double px1, py1, px2, py2;	// page corners (user coords)
   double pageWidth, pageHeight;	// page size (pixels)
@@ -1193,6 +1226,10 @@
   double strokeOpacity;		// stroke opacity
   GBool fillOverprint;		// fill overprint
   GBool strokeOverprint;	// stroke overprint
+  Function *transfer[4];	// transfer function (entries may be: all
+				//   NULL = identity; last three NULL =
+				//   single function; all four non-NULL =
+				//   R,G,B,gray functions)
 
   double lineWidth;		// line width
   double *lineDash;		// line dash
@@ -1202,6 +1239,7 @@
   int lineJoin;			// line join style
   int lineCap;			// line cap style
   double miterLimit;		// line miter limit
+  GBool strokeAdjust;		// stroke adjustment
 
   GfxFont *font;		// font
   double fontSize;		// font size

Index: GlobalParams.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/GlobalParams.cc,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- GlobalParams.cc	24 Feb 2007 23:43:35 -0000	1.19
+++ GlobalParams.cc	25 Apr 2007 19:59:10 -0000	1.20
@@ -42,6 +42,10 @@
 #include "GlobalParams.h"
 #include "GfxFont.h"
 
+#ifdef WIN32
+#  define strcasecmp stricmp
+#endif
+
 #if MULTITHREADED
 #  define lockGlobalParams            gLockMutex(&mutex)
 #  define lockUnicodeMapCache         gLockMutex(&unicodeMapCacheMutex)
@@ -115,6 +119,251 @@
   }
 }
 
+#ifdef WIN32
+
+//------------------------------------------------------------------------
+// WinFontInfo
+//------------------------------------------------------------------------
+
+class WinFontInfo: public DisplayFontParam {
+public:
+
+  GBool bold, italic;
+
+  static WinFontInfo *make(GString *nameA, GBool boldA, GBool italicA,
+			   HKEY regKey, char *winFontDir);
+  WinFontInfo(GString *nameA, GBool boldA, GBool italicA,
+	      GString *fileNameA);
+  virtual ~WinFontInfo();
+  GBool equals(WinFontInfo *fi);
+};
+
+WinFontInfo *WinFontInfo::make(GString *nameA, GBool boldA, GBool italicA,
+			       HKEY regKey, char *winFontDir) {
+  GString *regName;
+  GString *fileNameA;
+  char buf[MAX_PATH];
+  DWORD n;
+  char c;
+  int i;
+
+  //----- find the font file
+  fileNameA = NULL;
+  regName = nameA->copy();
+  if (boldA) {
+    regName->append(" Bold");
+  }
+  if (italicA) {
+    regName->append(" Italic");
+  }
+  regName->append(" (TrueType)");
+  n = sizeof(buf);
+  if (RegQueryValueEx(regKey, regName->getCString(), NULL, NULL,
+		      (LPBYTE)buf, &n) == ERROR_SUCCESS) {
+    fileNameA = new GString(winFontDir);
+    fileNameA->append('\\')->append(buf);
+  }
+  delete regName;
+  if (!fileNameA) {
+    delete nameA;
+    return NULL;
+  }
+
+  //----- normalize the font name
+  i = 0;
+  while (i < nameA->getLength()) {
+    c = nameA->getChar(i);
+    if (c == ' ' || c == ',' || c == '-') {
+      nameA->del(i);
+    } else {
+      ++i;
+    }
+  }
+
+  return new WinFontInfo(nameA, boldA, italicA, fileNameA);
+}
+
+WinFontInfo::WinFontInfo(GString *nameA, GBool boldA, GBool italicA,
+			 GString *fileNameA):
+  DisplayFontParam(nameA, displayFontTT)
+{
+  bold = boldA;
+  italic = italicA;
+  tt.fileName = fileNameA;
+}
+
+WinFontInfo::~WinFontInfo() {
+}
+
+GBool WinFontInfo::equals(WinFontInfo *fi) {
+  return !name->cmp(fi->name) && bold == fi->bold && italic == fi->italic;
+}
+
+//------------------------------------------------------------------------
+// WinFontList
+//------------------------------------------------------------------------
+
+class WinFontList {
+public:
+
+  WinFontList(char *winFontDirA);
+  ~WinFontList();
+  WinFontInfo *find(GString *font);
+
+private:
+
+  void add(WinFontInfo *fi);
+  static int CALLBACK enumFunc1(CONST LOGFONT *font,
+				CONST TEXTMETRIC *metrics,
+				DWORD type, LPARAM data);
+  static int CALLBACK enumFunc2(CONST LOGFONT *font,
+				CONST TEXTMETRIC *metrics,
+				DWORD type, LPARAM data);
+
+  GList *fonts;			// [WinFontInfo]
+  HDC dc;			// (only used during enumeration)
+  HKEY regKey;			// (only used during enumeration)
+  char *winFontDir;		// (only used during enumeration)
+};
+
+WinFontList::WinFontList(char *winFontDirA) {
+  OSVERSIONINFO version;
+  char *path;
+
+  fonts = new GList();
+  dc = GetDC(NULL);
+  winFontDir = winFontDirA;
+  version.dwOSVersionInfoSize = sizeof(version);
+  GetVersionEx(&version);
+  if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+    path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\";
+  } else {
+    path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\";
+  }
+  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0,
+		   KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
+		   &regKey) == ERROR_SUCCESS) {
+    EnumFonts(dc, NULL, &WinFontList::enumFunc1, (LPARAM)this);
+    RegCloseKey(regKey);
+  }
+  ReleaseDC(NULL, dc);
+}
+
+WinFontList::~WinFontList() {
+  deleteGList(fonts, WinFontInfo);
+}
+
+void WinFontList::add(WinFontInfo *fi) {
+  int i;
+
+  for (i = 0; i < fonts->getLength(); ++i) {
+    if (((WinFontInfo *)fonts->get(i))->equals(fi)) {
+      delete fi;
+      return;
+    }
+  }
+  fonts->append(fi);
+}
+
+WinFontInfo *WinFontList::find(GString *font) {
+  GString *name;
+  GBool bold, italic;
+  WinFontInfo *fi;
+  char c;
+  int n, i;
+
+  name = font->copy();
+
+  // remove space, comma, dash chars
+  i = 0;
+  while (i < name->getLength()) {
+    c = name->getChar(i);
+    if (c == ' ' || c == ',' || c == '-') {
+      name->del(i);
+    } else {
+      ++i;
+    }
+  }
+  n = name->getLength();
+
+  // remove trailing "MT" (Foo-MT, Foo-BoldMT, etc.)
+  if (!strcmp(name->getCString() + n - 2, "MT")) {
+    name->del(n - 2, 2);
+    n -= 2;
+  }
+
+  // look for "Italic"
+  if (!strcmp(name->getCString() + n - 6, "Italic")) {
+    name->del(n - 6, 6);
+    italic = gTrue;
+    n -= 6;
+  } else {
+    italic = gFalse;
+  }
+
+  // look for "Bold"
+  if (!strcmp(name->getCString() + n - 4, "Bold")) {
+    name->del(n - 4, 4);
+    bold = gTrue;
+    n -= 4;
+  } else {
+    bold = gFalse;
+  }
+
+  // remove trailing "MT" (FooMT-Bold, etc.)
+  if (!strcmp(name->getCString() + n - 2, "MT")) {
+    name->del(n - 2, 2);
+    n -= 2;
+  }
+
+  // remove trailing "PS"
+  if (!strcmp(name->getCString() + n - 2, "PS")) {
+    name->del(n - 2, 2);
+    n -= 2;
+  }
+
+  // search for the font
+  fi = NULL;
+  for (i = 0; i < fonts->getLength(); ++i) {
+    fi = (WinFontInfo *)fonts->get(i);
+    if (!fi->name->cmp(name) && fi->bold == bold && fi->italic == italic) {
+      break;
+    }
+    fi = NULL;
+  }
+
+  delete name;
+  return fi;
+}
+
+int CALLBACK WinFontList::enumFunc1(CONST LOGFONT *font,
+				    CONST TEXTMETRIC *metrics,
+				    DWORD type, LPARAM data) {
+  WinFontList *fl = (WinFontList *)data;
+
+  EnumFonts(fl->dc, font->lfFaceName, &WinFontList::enumFunc2, (LPARAM)fl);
+  return 1;
+}
+
+int CALLBACK WinFontList::enumFunc2(CONST LOGFONT *font,
+				    CONST TEXTMETRIC *metrics,
+				    DWORD type, LPARAM data) {
+  WinFontList *fl = (WinFontList *)data;
+  WinFontInfo *fi;
+
+  if (type & TRUETYPE_FONTTYPE) {
+    if ((fi = WinFontInfo::make(new GString(font->lfFaceName),
+				font->lfWeight >= 600,
+				font->lfItalic ? gTrue : gFalse,
+				fl->regKey, fl->winFontDir))) {
+      fl->add(fi);
+    }
+  }
+  return 1;
+}
+
+#endif // WIN32
+
 //------------------------------------------------------------------------
 // PSFontParam
 //------------------------------------------------------------------------
@@ -330,6 +579,7 @@
   psEmbedTrueType = gTrue;
   psEmbedCIDPostScript = gTrue;
   psEmbedCIDTrueType = gTrue;
+  psPreload = gFalse;
   psOPI = gFalse;
   psASCIIHex = gFalse;
   textEncoding = new GooString("UTF-8");
@@ -345,7 +595,16 @@
   fontDirs = new GooList();
   enableFreeType = gTrue;
   antialias = gTrue;
+  vectorAntialias = gTrue;
+  strokeAdjust = gTrue;
+  screenType = screenUnset;
+  screenSize = -1;
+  screenDotRadius = -1;
+  screenGamma = 1.0;
+  screenBlackThreshold = 0.0;
+  screenWhiteThreshold = 1.0;
   mapNumericCharNames = gTrue;
+  mapUnknownCharNames = gFalse;
   printCommands = gFalse;
   profileCommands = gFalse;
   errQuiet = gFalse;
@@ -356,6 +615,10 @@
   unicodeMapCache = new UnicodeMapCache();
   cMapCache = new CMapCache();
 
+#ifdef WIN32
+  winFontList = NULL;
+#endif
+
 #ifdef ENABLE_PLUGINS
   plugins = new GooList();
   securityHandlers = new GooList();
@@ -508,6 +771,11 @@
   deleteGooHash(unicodeMaps, GooString);
   deleteGooList(toUnicodeDirs, GooString);
   deleteGooHash(displayFonts, DisplayFontParam);
+#ifdef WIN32
+  if (winFontList) {
+    delete winFontList;
+  }
+#endif
   deleteGooHash(psFonts, PSFontParam);
   deleteGooList(psNamedFonts16, PSFontParam);
   deleteGooList(psFonts16, PSFontParam);
@@ -542,6 +810,12 @@
 void GlobalParams::setBaseDir(char *dir) {
   delete baseDir;
   baseDir = new GooString(dir);
+
+#ifdef WIN32
+  if (winFontDir[0]) {
+    winFontList = new WinFontList(winFontDir);
+  }
+#endif
 }
 
 //------------------------------------------------------------------------
@@ -970,6 +1244,15 @@
   return e;
 }
 
+GBool GlobalParams::getPSPreload() {
+  GBool preload;
+
+  lockGlobalParams;
+  preload = psPreload;
+  unlockGlobalParams;
+  return preload;
+}
+
 GBool GlobalParams::getPSOPI() {
   GBool opi;
 
@@ -1067,6 +1350,78 @@
   return f;
 }
 
+GBool GlobalParams::getVectorAntialias() {
+  GBool f;
+
+  lockGlobalParams;
+  f = vectorAntialias;
+  unlockGlobalParams;
+  return f;
+}
+
+GBool GlobalParams::getStrokeAdjust() {
+  GBool f;
+
+  lockGlobalParams;
+  f = strokeAdjust;
+  unlockGlobalParams;
+  return f;
+}
+
+ScreenType GlobalParams::getScreenType() {
+  ScreenType t;
+
+  lockGlobalParams;
+  t = screenType;
+  unlockGlobalParams;
+  return t;
+}
+
+int GlobalParams::getScreenSize() {
+  int size;
+
+  lockGlobalParams;
+  size = screenSize;
+  unlockGlobalParams;
+  return size;
+}
+
+int GlobalParams::getScreenDotRadius() {
+  int r;
+
+  lockGlobalParams;
+  r = screenDotRadius;
+  unlockGlobalParams;
+  return r;
+}
+
+double GlobalParams::getScreenGamma() {
+  double gamma;
+
+  lockGlobalParams;
+  gamma = screenGamma;
+  unlockGlobalParams;
+  return gamma;
+}
+
+double GlobalParams::getScreenBlackThreshold() {
+  double thresh;
+
+  lockGlobalParams;
+  thresh = screenBlackThreshold;
+  unlockGlobalParams;
+  return thresh;
+}
+
+double GlobalParams::getScreenWhiteThreshold() {
+  double thresh;
+
+  lockGlobalParams;
+  thresh = screenWhiteThreshold;
+  unlockGlobalParams;
+  return thresh;
+}
+
 GBool GlobalParams::getMapNumericCharNames() {
   GBool map;
 
@@ -1076,6 +1431,15 @@
   return map;
 }
 
+GBool GlobalParams::getMapUnknownCharNames() {
+  GBool map;
+
+  lockGlobalParams;
+  map = mapUnknownCharNames;
+  unlockGlobalParams;
+  return map;
+}
+
 GBool GlobalParams::getPrintCommands() {
   GBool p;
 
@@ -1095,12 +1459,9 @@
 }
 
 GBool GlobalParams::getErrQuiet() {
-  GBool q;
-
-  lockGlobalParams;
-  q = errQuiet;
-  unlockGlobalParams;
-  return q;
+  // no locking -- this function may get called from inside a locked
+  // section
+  return errQuiet;
 }
 
 CharCodeToUnicode *GlobalParams::getCIDToUnicode(GooString *collection) {
@@ -1226,6 +1587,12 @@
   unlockGlobalParams;
 }
 
+void GlobalParams::setPSPreload(GBool preload) {
+  lockGlobalParams;
+  psPreload = preload;
+  unlockGlobalParams;
+}
+
 void GlobalParams::setPSOPI(GBool opi) {
   lockGlobalParams;
   psOPI = opi;
@@ -1292,12 +1659,27 @@
   return ok;
 }
 
+GBool GlobalParams::setVectorAntialias(char *s) {
+  GBool ok;
+
+  lockGlobalParams;
+  ok = parseYesNo2(s, &vectorAntialias);
+  unlockGlobalParams;
+  return ok;
+}
+
 void GlobalParams::setMapNumericCharNames(GBool map) {
   lockGlobalParams;
   mapNumericCharNames = map;
   unlockGlobalParams;
 }
 
+void GlobalParams::setMapUnknownCharNames(GBool map) {
+  lockGlobalParams;
+  mapUnknownCharNames = map;
+  unlockGlobalParams;
+}
+
 void GlobalParams::setPrintCommands(GBool printCommandsA) {
   lockGlobalParams;
   printCommands = printCommandsA;
@@ -1332,7 +1714,7 @@
   lockGlobalParams;
   for (i = 0; i < securityHandlers->getLength(); ++i) {
     hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
-    if (!stricmp(hdlr->name, name)) {
+    if (!strcasecmp(hdlr->name, name)) {
       unlockGlobalParams;
       return hdlr;
     }
@@ -1342,6 +1724,7 @@
   if (!loadPlugin("security", name)) {
     return NULL;
   }
+  deleteGList(keyBindings, KeyBinding);
 
   lockGlobalParams;
   for (i = 0; i < securityHandlers->getLength(); ++i) {
@@ -1352,6 +1735,8 @@
     }
   }
   unlockGlobalParams;
+#else
+  (void)name;
 #endif
 
   return NULL;

Index: GlobalParams.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/GlobalParams.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- GlobalParams.h	24 Feb 2007 23:43:35 -0000	1.8
+++ GlobalParams.h	25 Apr 2007 19:59:10 -0000	1.9
@@ -36,6 +36,9 @@
 struct XpdfSecurityHandler;
 class GlobalParams;
 class GfxFont;
+#ifdef WIN32
+class WinFontList;
+#endif
 
 //------------------------------------------------------------------------
 
@@ -71,7 +74,7 @@
   };
 
   DisplayFontParam(GooString *nameA, DisplayFontParamKind kindA);
-  ~DisplayFontParam();
+  virtual ~DisplayFontParam();
 };
 
 //------------------------------------------------------------------------
@@ -113,6 +116,15 @@
 
 //------------------------------------------------------------------------
 
+enum ScreenType {
+  screenUnset,
+  screenDispersed,
+  screenClustered,
+  screenStochasticClustered
+};
+
+//------------------------------------------------------------------------
+
 class GlobalParams {
 public:
 
@@ -145,6 +157,7 @@
   GBool getPSEmbedTrueType();
   GBool getPSEmbedCIDPostScript();
   GBool getPSEmbedCIDTrueType();
+  GBool getPSPreload();
   GBool getPSOPI();
   GBool getPSASCIIHex();
   GooString *getTextEncodingName();
@@ -154,7 +167,16 @@
   GooString *findFontFile(GooString *fontName, char **exts);
   GBool getEnableFreeType();
   GBool getAntialias();
+  GBool getVectorAntialias();
+  GBool getStrokeAdjust();
+  ScreenType getScreenType();
+  int getScreenSize();
+  int getScreenDotRadius();
+  double getScreenGamma();
+  double getScreenBlackThreshold();
+  double getScreenWhiteThreshold();
   GBool getMapNumericCharNames();
+  GBool getMapUnknownCharNames();
   GBool getPrintCommands();
   GBool getProfileCommands();
   GBool getErrQuiet();
@@ -177,6 +199,7 @@
   void setPSEmbedTrueType(GBool embed);
   void setPSEmbedCIDPostScript(GBool embed);
   void setPSEmbedCIDTrueType(GBool embed);
+  void setPSPreload(GBool preload);
   void setPSOPI(GBool opi);
   void setPSASCIIHex(GBool hex);
   void setTextEncoding(char *encodingName);
@@ -185,7 +208,9 @@
   void setTextKeepTinyChars(GBool keep);
   GBool setEnableFreeType(char *s);
   GBool setAntialias(char *s);
+  GBool setVectorAntialias(char *s);
   void setMapNumericCharNames(GBool map);
+  void setMapUnknownCharNames(GBool map);
   void setPrintCommands(GBool printCommandsA);
   void setProfileCommands(GBool profileCommandsA);
   void setErrQuiet(GBool errQuietA);
@@ -230,6 +255,9 @@
   GooList *toUnicodeDirs;		// list of ToUnicode CMap dirs [GooString]
   GooHash *displayFonts;		// display font info, indexed by font name
 				//   [DisplayFontParam]
+#ifdef WIN32
+  WinFontList *winFontList;	// system TrueType fonts
+#endif
   GBool psExpandSmaller;	// expand smaller pages to fill paper
   GBool psShrinkLarger;		// shrink larger pages to fit paper
   GBool psCenter;		// center pages on the paper
@@ -242,6 +270,8 @@
   GBool psEmbedTrueType;	// embed TrueType fonts?
   GBool psEmbedCIDPostScript;	// embed CID PostScript fonts?
   GBool psEmbedCIDTrueType;	// embed CID TrueType fonts?
+  GBool psPreload;		// preload PostScript images and forms into
+				//   memory
   GBool psOPI;			// generate PostScript OPI comments?
   GBool psASCIIHex;		// use ASCIIHex instead of ASCII85?
   GooString *textEncoding;	// encoding (unicodeMap) to use for text
@@ -253,7 +283,16 @@
   GooList *fontDirs;		// list of font dirs [GooString]
   GBool enableFreeType;		// FreeType enable flag
   GBool antialias;		// anti-aliasing enable flag
+  GBool vectorAntialias;	// vector anti-aliasing enable flag
+  GBool strokeAdjust;		// stroke adjustment enable flag
+  ScreenType screenType;	// halftone screen type
+  int screenSize;		// screen matrix size
+  int screenDotRadius;		// screen dot radius
+  double screenGamma;		// screen gamma correction
+  double screenBlackThreshold;	// screen black clamping threshold
+  double screenWhiteThreshold;	// screen white clamping threshold
   GBool mapNumericCharNames;	// map numeric char names (from font subsets)?
+  GBool mapUnknownCharNames;	// map unknown char names?
   GBool printCommands;		// print the drawing commands
   GBool profileCommands;	// profile the drawing commands
   GBool errQuiet;		// suppress error messages?

Index: JBIG2Stream.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/JBIG2Stream.cc,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- JBIG2Stream.cc	29 Apr 2006 15:23:41 -0000	1.9
+++ JBIG2Stream.cc	25 Apr 2007 19:59:10 -0000	1.10
@@ -1106,7 +1106,7 @@
 // JBIG2Stream
 //------------------------------------------------------------------------
 
-JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
+JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA):
   FilterStream(strA)
 {
   pageBitmap = NULL;
@@ -1131,22 +1131,15 @@
   huffDecoder = new JBIG2HuffmanDecoder();
   mmrDecoder = new JBIG2MMRDecoder();
 
-  segments = globalSegments = new GooList();
-  if (globalsStream->isStream()) {
-    curStr = globalsStream->getStream();
-    curStr->reset();
-    arithDecoder->setStream(curStr);
-    huffDecoder->setStream(curStr);
-    mmrDecoder->setStream(curStr);
-    readSegments();
-  }
-
-  segments = NULL;
+  globalsStreamA->copy(&globalsStream);
+  segments = globalSegments = NULL;
   curStr = NULL;
   dataPtr = dataEnd = NULL;
 }
 
 JBIG2Stream::~JBIG2Stream() {
+  close();
+  globalsStream.free();
   delete arithDecoder;
   delete genericRegionStats;
   delete refinementRegionStats;
@@ -1166,28 +1159,25 @@
   delete iaidStats;
   delete huffDecoder;
   delete mmrDecoder;
-  if (pageBitmap) {
-    delete pageBitmap;
-  }
-  if (segments) {
-    deleteGooList(segments, JBIG2Segment);
-  }
-  if (globalSegments) {
-    deleteGooList(globalSegments, JBIG2Segment);
-  }
   delete str;
 }
 
 void JBIG2Stream::reset() {
-  if (pageBitmap) {
-    delete pageBitmap;
-    pageBitmap = NULL;
-  }
-  if (segments) {
-    deleteGooList(segments, JBIG2Segment);
+  // read the globals stream
+  globalSegments = new GooList();
+  if (globalsStream.isStream()) {
+    segments = globalSegments;
+    curStr = globalsStream.getStream();
+    curStr->reset();
+    arithDecoder->setStream(curStr);
+    huffDecoder->setStream(curStr);
+    mmrDecoder->setStream(curStr);
+    readSegments();
+    curStr->close();
   }
-  segments = new GooList();
 
+  // read the main stream
+  segments = new GooList();
   curStr = str;
   curStr->reset();
   arithDecoder->setStream(curStr);
@@ -1199,10 +1189,27 @@
     dataPtr = pageBitmap->getDataPtr();
     dataEnd = dataPtr + pageBitmap->getDataSize();
   } else {
-    dataPtr = NULL;
+    dataPtr = dataEnd = NULL;
   }
 }
 
+void JBIG2Stream::close() {
+  if (pageBitmap) {
+    delete pageBitmap;
+    pageBitmap = NULL;
+  }
+  if (segments) {
+    deleteGooList(segments, JBIG2Segment);
+    segments = NULL;
+  }
+  if (globalSegments) {
+    deleteGooList(globalSegments, JBIG2Segment);
+    globalSegments = NULL;
+  }
+  dataPtr = dataEnd = NULL;
+  FilterStream::close();
+}
+
 int JBIG2Stream::getChar() {
   if (dataPtr && dataPtr < dataEnd) {
     return (*dataPtr++ ^ 0xff) & 0xff;
@@ -2361,6 +2368,14 @@
     error(getPos(), "Bad grid size in JBIG2 halftone segment");
     return;
   }
+  if (w == 0 || h == 0 || w >= INT_MAX / h) {
+    error(getPos(), "Bad bitmap size in JBIG2 halftone segment");
+    return;
+  }
+  if (gridH == 0 || gridW >= INT_MAX / gridH) {
+    error(getPos(), "Bad grid size in JBIG2 halftone segment");
+    return;
+  }
 
   // get pattern dictionary
   if (nRefSegs != 1) {
@@ -2372,14 +2387,6 @@
     error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
     return;
   }
-  if (gridH == 0 || gridW >= INT_MAX / gridH) {
-    error(getPos(), "Bad size in JBIG2 halftone segment");
-    return;
-  }
-  if (w == 0 || h >= INT_MAX / w) {
-     error(getPos(), "Bad size in JBIG2 bitmap segment");
-    return;
-  }
 
   patternDict = (JBIG2PatternDict *)seg;
   bpp = 0;
@@ -2411,9 +2418,9 @@
     skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
     skipBitmap->clearToZero();
     for (m = 0; m < gridH; ++m) {
-      xx = gridX + m * stepY;
-      yy = gridY + m * stepX;
       for (n = 0; n < gridW; ++n) {
+	xx = gridX + m * stepY + n * stepX;
+	yy = gridY + m * stepX - n * stepY;
 	if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
 	    ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
 	  skipBitmap->setPixel(n, m);
@@ -2459,8 +2466,10 @@
     }
   }
 
-  delete skipBitmap;
   gfree(grayImg);
+  if (skipBitmap) {
+    delete skipBitmap;
+  }
 
   // combine the region bitmap into the page bitmap
   if (imm) {
@@ -3013,11 +3022,6 @@
   JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
   int x, y, pix;
 
-  if (w < 0 || h <= 0 || w >= INT_MAX / h) {
-    error(-1, "invalid width/height");
-    return NULL;
-  }
-
   bitmap = new JBIG2Bitmap(0, w, h);
   bitmap->clearToZero();
 
@@ -3396,7 +3400,7 @@
   iardwStats->reset();
   iardhStats->reset();
   iariStats->reset();
-  if (iaidStats->getContextSize() == symCodeLen + 1) {
+  if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) {
     iaidStats->reset();
   } else {
     delete iaidStats;

Index: JBIG2Stream.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/JBIG2Stream.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- JBIG2Stream.h	31 Aug 2005 09:51:41 -0000	1.2
+++ JBIG2Stream.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -31,10 +31,11 @@
 class JBIG2Stream: public FilterStream {
 public:
 
-  JBIG2Stream(Stream *strA, Object *globalsStream);
+  JBIG2Stream(Stream *strA, Object *globalsStreamA);
   virtual ~JBIG2Stream();
   virtual StreamKind getKind() { return strJBIG2; }
   virtual void reset();
+  virtual void close();
   virtual int getChar();
   virtual int lookChar();
   virtual GooString *getPSFilter(int psLevel, char *indent);
@@ -107,6 +108,7 @@
   GBool readULong(Guint *x);
   GBool readLong(int *x);
 
+  Object globalsStream;
   Guint pageW, pageH, curPageH;
   Guint pageDefPixel;
   JBIG2Bitmap *pageBitmap;

Index: JPXStream.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/JPXStream.cc,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- JPXStream.cc	21 Dec 2005 22:09:47 -0000	1.6
+++ JPXStream.cc	25 Apr 2007 19:59:10 -0000	1.7
@@ -177,6 +177,59 @@
 
 //------------------------------------------------------------------------
 
+#if 1 //----- disable coverage tracking
+
+#define cover(idx)
+
+#else //----- enable coverage tracking
+
+class JPXCover {
+public:
+
+  JPXCover(int sizeA);
+  ~JPXCover();
+  void incr(int idx);
+
+private:
+
+  int size, used;
+  int *data;
+};
+
+JPXCover::JPXCover(int sizeA) {
+  size = sizeA;
+  used = -1;
+  data = (int *)gmallocn(size, sizeof(int));
+  memset(data, 0, size * sizeof(int));
+}
+
+JPXCover::~JPXCover() {
+  int i;
+
+  printf("JPX coverage:\n");
+  for (i = 0; i <= used; ++i) {
+    printf("  %4d: %8d\n", i, data[i]);
+  }
+  gfree(data);
+}
+
+void JPXCover::incr(int idx) {
+  if (idx < size) {
+    ++data[idx];
+    if (idx > used) {
+      used = idx;
+    }
+  }
+}
+
+JPXCover jpxCover(150);
+
+#define cover(idx) jpxCover.incr(idx)
+
+#endif //----- coverage tracking
+
+//------------------------------------------------------------------------
+
 JPXStream::JPXStream(Stream *strA):
   FilterStream(strA)
 {
@@ -196,6 +249,24 @@
 }
 
 JPXStream::~JPXStream() {
+  close();
+  delete str;
+}
+
+void JPXStream::reset() {
+  str->reset();
+  if (readBoxes()) {
+    curY = img.yOffset;
+  } else {
+    // readBoxes reported an error, so we go immediately to EOF
+    curY = img.ySize;
+  }
+  curX = img.xOffset;
+  curComp = 0;
+  readBufLen = 0;
+}
+
+void JPXStream::close() {
   JPXTile *tile;
   JPXTileComp *tileComp;
   JPXResLevel *resLevel;
@@ -205,19 +276,23 @@
   Guint comp, i, k, r, pre, sb;
 
   gfree(bpc);
+  bpc = NULL;
   if (havePalette) {
     gfree(palette.bpc);
     gfree(palette.c);
+    havePalette = gFalse;
   }
   if (haveCompMap) {
     gfree(compMap.comp);
     gfree(compMap.type);
     gfree(compMap.pComp);
+    haveCompMap = gFalse;
   }
   if (haveChannelDefn) {
     gfree(channelDefn.idx);
     gfree(channelDefn.type);
     gfree(channelDefn.assoc);
+    haveChannelDefn = gFalse;
   }
 
   if (img.tiles) {
@@ -236,7 +311,7 @@
 		for (pre = 0; pre < 1; ++pre) {
 		  precinct = &resLevel->precincts[pre];
 		  if (precinct->subbands) {
-		    for (sb = 0; sb < (r == 0 ? 1 : 3); ++sb) {
+		    for (sb = 0; sb < (Guint)(r == 0 ? 1 : 3); ++sb) {
 		      subband = &precinct->subbands[sb];
 		      gfree(subband->inclusion);
 		      gfree(subband->zeroBitPlane);
@@ -267,21 +342,9 @@
       }
     }
     gfree(img.tiles);
+    img.tiles = NULL;
   }
-  delete str;
-}
-
-void JPXStream::reset() {
-  str->reset();
-  if (readBoxes()) {
-    curY = img.yOffset;
-  } else {
-    // readBoxes reported an error, so we go immediately to EOF
-    curY = img.ySize;
-  }
-  curX = img.xOffset;
-  curComp = 0;
-  readBufLen = 0;
+  FilterStream::close();
 }
 
 int JPXStream::getChar() {
@@ -394,8 +457,10 @@
   } else {
     while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
       if (boxType == 0x6a703268) { // JP2 header
+	cover(0);
 	// skip the superbox
       } else if (boxType == 0x69686472) { // image header
+	cover(1);
 	if (readULong(&dummy) &&
 	    readULong(&dummy) &&
 	    readUWord(&dummy) &&
@@ -407,6 +472,7 @@
 	  haveBPC = gTrue;
 	}
       } else if (boxType == 0x636F6C72) { // color specification
+	cover(2);
 	if (readByte(&csMeth) &&
 	    readByte(&csPrec1) &&
 	    readByte(&dummy2)) {
@@ -440,11 +506,13 @@
 	  }
 	}
       } else if (boxType == 0x6A703263) { // codestream
+	cover(3);
 	if (!(haveBPC && haveCSMode)) {
 	  getImageParams2(bitsPerComponent, csMode);
 	}
 	break;
       } else {
+	cover(4);
 	for (i = 0; i < dataLen; ++i) {
 	  str->getChar();
 	}
@@ -462,6 +530,7 @@
 
   while (readMarkerHdr(&segType, &segLen)) {
     if (segType == 0x51) { // SIZ - image and tile size
+      cover(5);
       if (readUWord(&dummy) &&
 	  readULong(&dummy) &&
 	  readULong(&dummy) &&
@@ -485,6 +554,7 @@
       }
       break;
     } else {
+      cover(6);
       if (segLen > 2) {
 	for (i = 0; i < segLen - 2; ++i) {
 	  str->getChar();
@@ -505,6 +575,7 @@
   // wrapper) -- this appears to be a violation of the PDF spec, but
   // Acrobat allows it
   if (str->lookChar() == 0xff) {
+    cover(7);
     error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
     readCodestream(0);
     nComps = img.nComps;
@@ -525,8 +596,10 @@
       // some things which should be subboxes of the JP2 header box
       // show up outside of it - so we simply ignore the JP2 header
       // box
+      cover(8);
       break;
     case 0x69686472:		// image header
+      cover(9);
       if (!readULong(&height) ||
 	  !readULong(&width) ||
 	  !readUWord(&nComps) ||
@@ -548,6 +621,7 @@
       haveImgHdr = gTrue;
       break;
     case 0x62706363:		// bits per component
+      cover(10);
       if (!haveImgHdr) {
 	error(getPos(), "Found bits per component box before image header box in JPX stream");
 	return gFalse;
@@ -564,11 +638,13 @@
       }
       break;
     case 0x636F6C72:		// color specification
+      cover(11);
       if (!readColorSpecBox(dataLen)) {
 	return gFalse;
       }
       break;
     case 0x70636c72:		// palette
+      cover(12);
       if (!readUWord(&palette.nEntries) ||
 	  !readUByte(&palette.nComps)) {
 	error(getPos(), "Unexpected EOF in JPX stream");
@@ -597,6 +673,7 @@
       havePalette = gTrue;
       break;
     case 0x636d6170:		// component mapping
+      cover(13);
       compMap.nChannels = dataLen / 4;
       compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
       compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
@@ -612,6 +689,7 @@
       haveCompMap = gTrue;
       break;
     case 0x63646566:		// channel definition
+      cover(14);
       if (!readUWord(&channelDefn.nChannels)) {
 	error(getPos(), "Unexpected EOF in JPX stream");
 	return gFalse;
@@ -633,6 +711,7 @@
       haveChannelDefn = gTrue;
       break;
     case 0x6A703263:		// contiguous codestream
+      cover(15);
       if (!bpc) {
 	error(getPos(), "JPX stream is missing the image header box");
       }
@@ -644,6 +723,7 @@
       }
       break;
     default:
+      cover(16);
       for (i = 0; i < dataLen; ++i) {
 	if (str->getChar() == EOF) {
 	  error(getPos(), "Unexpected EOF in JPX stream");
@@ -670,6 +750,7 @@
   }
   switch (newCS.meth) {
   case 1:			// enumerated colorspace
+    cover(17);
     if (!readULong(&csEnum)) {
       goto err;
     }
@@ -712,6 +793,7 @@
 	}
       } else if (dataLen == 7) {
 	//~ this assumes the 8-bit case
+	cover(92);
 	newCS.enumerated.cieLab.rl = 100;
 	newCS.enumerated.cieLab.ol = 0;
 	newCS.enumerated.cieLab.ra = 255;
@@ -758,6 +840,7 @@
   case 2:			// restricted ICC profile
   case 3: 			// any ICC profile (JPX)
   case 4:			// vendor color (JPX)
+    cover(18);
     for (i = 0; i < dataLen - 3; ++i) {
       if (str->getChar() == EOF) {
 	goto err;
@@ -784,7 +867,7 @@
   int segType;
   GBool haveSIZ, haveCOD, haveQCD, haveSOT;
   Guint precinctSize, style;
-  Guint segLen, capabilities, nTiles, comp, i, j, r;
+  Guint segLen, capabilities, comp, i, j, r;
 
   //----- main header
   haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
@@ -796,8 +879,10 @@
     switch (segType) {
     case 0x4f:			// SOC - start of codestream
       // marker only
+      cover(19);
       break;
     case 0x51:			// SIZ - image and tile size
+      cover(20);
       if (!readUWord(&capabilities) ||
 	  !readULong(&img.xSize) ||
 	  !readULong(&img.ySize) ||
@@ -819,13 +904,14 @@
 	            / img.xTileSize;
       img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
 	            / img.yTileSize;
-      nTiles = img.nXTiles * img.nYTiles;
       // check for overflow before allocating memory
-      if (nTiles == 0 || nTiles / img.nXTiles != img.nYTiles) {
+      if (img.nXTiles <= 0 || img.nYTiles <= 0 ||
+	  img.nXTiles >= INT_MAX / img.nYTiles) {
 	error(getPos(), "Bad tile count in JPX SIZ marker segment");
 	return gFalse;
       }
-      img.tiles = (JPXTile *)gmallocn(nTiles, sizeof(JPXTile));
+      img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles,
+				      sizeof(JPXTile));
       for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
 	img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps,
 							 sizeof(JPXTileComp));
@@ -854,6 +940,7 @@
       haveSIZ = gTrue;
       break;
     case 0x52:			// COD - coding style default
+      cover(21);
       if (!readUByte(&img.tiles[0].tileComps[0].style) ||
 	  !readUByte(&img.tiles[0].progOrder) ||
 	  !readUWord(&img.tiles[0].nLayers) ||
@@ -900,6 +987,7 @@
       }
       for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) {
 	if (img.tiles[0].tileComps[0].style & 0x01) {
+	  cover(91);
 	  if (!readUByte(&precinctSize)) {
 	    error(getPos(), "Error in JPX COD marker segment");
 	    return gFalse;
@@ -928,6 +1016,7 @@
       haveCOD = gTrue;
       break;
     case 0x53:			// COC - coding style component
+      cover(22);
       if (!haveCOD) {
 	error(getPos(), "JPX COC marker segment before COD segment");
 	return gFalse;
@@ -997,6 +1086,7 @@
       }
       break;
     case 0x5c:			// QCD - quantization default
+      cover(23);
       if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
 	error(getPos(), "Error in JPX QCD marker segment");
 	return gFalse;
@@ -1060,6 +1150,7 @@
       haveQCD = gTrue;
       break;
     case 0x5d:			// QCC - quantization component
+      cover(24);
       if (!haveQCD) {
 	error(getPos(), "JPX QCC marker segment before QCD segment");
 	return gFalse;
@@ -1127,6 +1218,7 @@
       }
       break;
     case 0x5e:			// RGN - region of interest
+      cover(25);
 #if 1 //~ ROI is unimplemented
       fprintf(stderr, "RGN\n");
       for (i = 0; i < segLen - 2; ++i) {
@@ -1147,6 +1239,7 @@
 #endif
       break;
     case 0x5f:			// POC - progression order change
+      cover(26);
 #if 1 //~ progression order changes are unimplemented
       fprintf(stderr, "POC\n");
       for (i = 0; i < segLen - 2; ++i) {
@@ -1174,6 +1267,7 @@
 #endif
       break;
     case 0x60:			// PPM - packed packet headers, main header
+      cover(27);
 #if 1 //~ packed packet headers are unimplemented
       fprintf(stderr, "PPM\n");
       for (i = 0; i < segLen - 2; ++i) {
@@ -1186,6 +1280,7 @@
       break;
     case 0x55:			// TLM - tile-part lengths
       // skipped
+      cover(28);
       for (i = 0; i < segLen - 2; ++i) {
 	if (str->getChar() == EOF) {
 	  error(getPos(), "Error in JPX TLM marker segment");
@@ -1195,6 +1290,7 @@
       break;
     case 0x57:			// PLM - packet length, main header
       // skipped
+      cover(29);
       for (i = 0; i < segLen - 2; ++i) {
 	if (str->getChar() == EOF) {
 	  error(getPos(), "Error in JPX PLM marker segment");
@@ -1204,6 +1300,7 @@
       break;
     case 0x63:			// CRG - component registration
       // skipped
+      cover(30);
       for (i = 0; i < segLen - 2; ++i) {
 	if (str->getChar() == EOF) {
 	  error(getPos(), "Error in JPX CRG marker segment");
@@ -1213,6 +1310,7 @@
       break;
     case 0x64:			// COM - comment
       // skipped
+      cover(31);
       for (i = 0; i < segLen - 2; ++i) {
 	if (str->getChar() == EOF) {
 	  error(getPos(), "Error in JPX COM marker segment");
@@ -1221,9 +1319,11 @@
       }
       break;
     case 0x90:			// SOT - start of tile
+      cover(32);
       haveSOT = gTrue;
       break;
     default:
+      cover(33);
       error(getPos(), "Unknown marker segment %02x in JPX stream", segType);
       for (i = 0; i < segLen - 2; ++i) {
 	if (str->getChar() == EOF) {
@@ -1324,6 +1424,7 @@
     tilePartLen -= 2 + segLen;
     switch (segType) {
     case 0x52:			// COD - coding style default
+      cover(34);
       if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) ||
 	  !readUByte(&img.tiles[tileIdx].progOrder) ||
 	  !readUWord(&img.tiles[tileIdx].nLayers) ||
@@ -1391,6 +1492,7 @@
       }
       break;
     case 0x53:			// COC - coding style component
+      cover(35);
       if ((img.nComps > 256 && !readUWord(&comp)) ||
 	  (img.nComps <= 256 && !readUByte(&comp)) ||
 	  comp >= img.nComps ||
@@ -1432,6 +1534,7 @@
       }
       break;
     case 0x5c:			// QCD - quantization default
+      cover(36);
       if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
 	error(getPos(), "Error in JPX QCD marker segment");
 	return gFalse;
@@ -1491,6 +1594,7 @@
       }
       break;
     case 0x5d:			// QCC - quantization component
+      cover(37);
       if ((img.nComps > 256 && !readUWord(&comp)) ||
 	  (img.nComps <= 256 && !readUByte(&comp)) ||
 	  comp >= img.nComps ||
@@ -1542,6 +1646,7 @@
       }
       break;
     case 0x5e:			// RGN - region of interest
+      cover(38);
 #if 1 //~ ROI is unimplemented
       fprintf(stderr, "RGN\n");
       for (i = 0; i < segLen - 2; ++i) {
@@ -1562,6 +1667,7 @@
 #endif
       break;
     case 0x5f:			// POC - progression order change
+      cover(39);
 #if 1 //~ progression order changes are unimplemented
       fprintf(stderr, "POC\n");
       for (i = 0; i < segLen - 2; ++i) {
@@ -1589,6 +1695,7 @@
 #endif
       break;
     case 0x61:			// PPT - packed packet headers, tile-part hdr
+      cover(40);
 #if 1 //~ packed packet headers are unimplemented
       fprintf(stderr, "PPT\n");
       for (i = 0; i < segLen - 2; ++i) {
@@ -1600,6 +1707,7 @@
 #endif
     case 0x58:			// PLT - packet length, tile-part header
       // skipped
+      cover(41);
       for (i = 0; i < segLen - 2; ++i) {
 	if (str->getChar() == EOF) {
 	  error(getPos(), "Error in JPX PLT marker segment");
@@ -1609,6 +1717,7 @@
       break;
     case 0x64:			// COM - comment
       // skipped
+      cover(42);
       for (i = 0; i < segLen - 2; ++i) {
 	if (str->getChar() == EOF) {
 	  error(getPos(), "Error in JPX COM marker segment");
@@ -1617,9 +1726,11 @@
       }
       break;
     case 0x93:			// SOD - start of data
+      cover(43);
       haveSOD = gTrue;
       break;
     default:
+      cover(44);
       error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
 	    segType);
       for (i = 0; i < segLen - 2; ++i) {
@@ -1817,6 +1928,7 @@
   while (1) {
     if (tilePartToEOC) {
       //~ peek for an EOC marker
+      cover(93);
     } else if (tilePartLen == 0) {
       break;
     }
@@ -1827,13 +1939,17 @@
 
     //----- packet header
 
+    // setup
+    startBitBuf(tilePartLen);
+
     // zero-length flag
     if (!readBits(1, &bits)) {
       goto err;
     }
     if (!bits) {
       // packet is empty -- clear all code-block inclusion flags
-      for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
+      cover(45);
+      for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) {
 	subband = &precinct->subbands[sb];
 	for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
 	  for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
@@ -1844,7 +1960,7 @@
       }
     } else {
 
-      for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
+      for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) {
 	subband = &precinct->subbands[sb];
 	for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
 	  for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
@@ -1852,16 +1968,19 @@
 
 	    // skip code-blocks with no coefficients
 	    if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) {
+	      cover(46);
 	      cb->included = gFalse;
 	      continue;
 	    }
 
 	    // code-block inclusion
 	    if (cb->seen) {
+	      cover(47);
 	      if (!readBits(1, &cb->included)) {
 		goto err;
 	      }
 	    } else {
+	      cover(48);
 	      ttVal = 0;
 	      i = 0;
 	      for (level = subband->maxTTLevel; level >= 0; --level) {
@@ -1895,9 +2014,11 @@
 	    }
 
 	    if (cb->included) {
+	      cover(49);
 
 	      // zero bit-plane count
 	      if (!cb->seen) {
+		cover(50);
 		ttVal = 0;
 		i = 0;
 		for (level = subband->maxTTLevel; level >= 0; --level) {
@@ -1931,26 +2052,33 @@
 		goto err;
 	      }
 	      if (bits == 0) {
+		cover(51);
 		cb->nCodingPasses = 1;
 	      } else {
 		if (!readBits(1, &bits)) {
 		  goto err;
 		}
 		if (bits == 0) {
+		  cover(52);
 		  cb->nCodingPasses = 2;
 		} else {
+		  cover(53);
 		  if (!readBits(2, &bits)) {
 		    goto err;
 		  }
 		  if (bits < 3) {
+		    cover(54);
 		    cb->nCodingPasses = 3 + bits;
 		  } else {
+		    cover(55);
 		    if (!readBits(5, &bits)) {
 		      goto err;
 		    }
 		    if (bits < 31) {
+		      cover(56);
 		      cb->nCodingPasses = 6 + bits;
 		    } else {
+		      cover(57);
 		      if (!readBits(7, &bits)) {
 			goto err;
 		      }
@@ -1984,12 +2112,11 @@
 	}
       }
     }
-    tilePartLen -= byteCount;
-    clearBitBuf();
+    tilePartLen = finishBitBuf();
 
     //----- packet data
 
-    for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
+    for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) {
       subband = &precinct->subbands[sb];
       for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
 	for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
@@ -2010,6 +2137,7 @@
 
     switch (tile->progOrder) {
     case 0: // layer, resolution level, component, precinct
+      cover(58);
       if (++tile->comp == img.nComps) {
 	tile->comp = 0;
 	if (++tile->res == tile->maxNDecompLevels + 1) {
@@ -2021,6 +2149,7 @@
       }
       break;
     case 1: // resolution level, layer, component, precinct
+      cover(59);
       if (++tile->comp == img.nComps) {
 	tile->comp = 0;
 	if (++tile->layer == tile->nLayers) {
@@ -2033,6 +2162,7 @@
       break;
     case 2: // resolution level, precinct, component, layer
       //~ this isn't correct -- see B.12.1.3
+      cover(60);
       if (++tile->layer == tile->nLayers) {
 	tile->layer = 0;
 	if (++tile->comp == img.nComps) {
@@ -2045,6 +2175,7 @@
       break;
     case 3: // precinct, component, resolution level, layer
       //~ this isn't correct -- see B.12.1.4
+      cover(61);
       if (++tile->layer == tile->nLayers) {
 	tile->layer = 0;
 	if (++tile->res == tile->maxNDecompLevels + 1) {
@@ -2057,6 +2188,7 @@
       break;
     case 4: // component, precinct, resolution level, layer
       //~ this isn't correct -- see B.12.1.5
+      cover(62);
       if (++tile->layer == tile->nLayers) {
 	tile->layer = 0;
 	if (++tile->res == tile->maxNDecompLevels + 1) {
@@ -2089,8 +2221,10 @@
   Guint i, x, y0, y1, y2;
 
   if (cb->arithDecoder) {
+    cover(63);
     cb->arithDecoder->restart(cb->dataLen);
   } else {
+    cover(64);
     cb->arithDecoder = new JArithmeticDecoder();
     cb->arithDecoder->setStream(str, cb->dataLen);
     cb->arithDecoder->start();
@@ -2105,6 +2239,7 @@
 
     //----- significance propagation pass
     case jpxPassSigProp:
+      cover(65);
       for (y0 = cb->y0, coeff0 = cb->coeffs;
 	   y0 < cb->y1;
 	   y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
@@ -2182,6 +2317,7 @@
 
     //----- magnitude refinement pass
     case jpxPassMagRef:
+      cover(66);
       for (y0 = cb->y0, coeff0 = cb->coeffs;
 	   y0 < cb->y1;
 	   y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
@@ -2243,6 +2379,7 @@
 
     //----- cleanup pass
     case jpxPassCleanup:
+      cover(67);
       for (y0 = cb->y0, coeff0 = cb->coeffs;
 	   y0 < cb->y1;
 	   y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
@@ -2404,6 +2541,8 @@
   Guint nx0, ny0, nx1, ny1;
   Guint r, cbX, cbY, x, y;
 
+  cover(68);
+
   //----- (NL)LL subband (resolution level 0)
 
   resLevel = &tileComp->resLevels[0];
@@ -2414,14 +2553,17 @@
   qStyle = tileComp->quantStyle & 0x1f;
   guard = (tileComp->quantStyle >> 5) & 7;
   if (qStyle == 0) {
+    cover(69);
     eps = (tileComp->quantSteps[0] >> 3) & 0x1f;
     shift = guard + eps - 1;
     mu = 0; // make gcc happy
   } else {
+    cover(70);
     shift = guard - 1 + tileComp->prec;
     mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0;
   }
   if (tileComp->transform == 0) {
+    cover(71);
     shift += fracBits;
   }
 
@@ -2441,18 +2583,24 @@
 	  if (val != 0) {
 	    shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
 	    if (shift2 > 0) {
+	      cover(94);
 	      val = (val << shift2) + (1 << (shift2 - 1));
 	    } else {
+	      cover(95);
 	      val >>= -shift2;
 	    }
 	    if (qStyle == 0) {
+	      cover(96);
 	      if (tileComp->transform == 0) {
+		cover(97);
 		val &= -1 << fracBits;
 	      }
 	    } else {
+	      cover(98);
 	      val = (int)((double)val * mu);
 	    }
 	    if (coeff->flags & jpxCoeffSign) {
+	      cover(99);
 	      val = -val;
 	    }
 	  }
@@ -2473,11 +2621,13 @@
     // and inverse transform to get (n-1)LL, which will be stored
     // in the upper-left corner of the tile-component data array
     if (r == tileComp->nDecompLevels) {
+      cover(72);
       nx0 = tileComp->x0;
       ny0 = tileComp->y0;
       nx1 = tileComp->x1;
       ny1 = tileComp->y1;
     } else {
+      cover(73);
       nx0 = tileComp->resLevels[r+1].x0;
       ny0 = tileComp->resLevels[r+1].y0;
       nx1 = tileComp->resLevels[r+1].x1;
@@ -2530,18 +2680,22 @@
 
     // i-quant parameters
     if (qStyle == 0) {
+      cover(100);
       eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f;
       shift = guard + eps - 1;
       mu = 0; // make gcc happy
     } else {
+      cover(101);
       shift = guard + tileComp->prec;
       if (sb == 2) {
+	cover(102);
 	++shift;
       }
       t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)];
       mu = (double)(0x800 + (t & 0x7ff)) / 2048.0;
     }
     if (tileComp->transform == 0) {
+      cover(103);
       shift += fracBits;
     }
 
@@ -2564,18 +2718,23 @@
 	    if (val != 0) {
 	      shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
 	      if (shift2 > 0) {
+		cover(74);
 		val = (val << shift2) + (1 << (shift2 - 1));
 	      } else {
+		cover(75);
 		val >>= -shift2;
 	      }
 	      if (qStyle == 0) {
+		cover(76);
 		if (tileComp->transform == 0) {
 		  val &= -1 << fracBits;
 		}
 	      } else {
+		cover(77);
 		val = (int)((double)val * mu);
 	      }
 	      if (coeff->flags & jpxCoeffSign) {
+		cover(78);
 		val = -val;
 	      }
 	    }
@@ -2612,11 +2771,14 @@
 
   //----- special case for length = 1
   if (i1 - i0 == 1) {
+    cover(79);
     if (i0 & 1) {
+      cover(104);
       *data >>= 1;
     }
 
   } else {
+    cover(80);
 
     // choose an offset: this makes even buf[] indexes correspond to
     // odd values of i, and vice versa
@@ -2632,19 +2794,25 @@
     //----- extend right
     buf[end] = buf[end - 2];
     if (i1 - i0 == 2) {
+      cover(81);
       buf[end+1] = buf[offset + 1];
       buf[end+2] = buf[offset];
       buf[end+3] = buf[offset + 1];
     } else {
+      cover(82);
       buf[end+1] = buf[end - 3];
       if (i1 - i0 == 3) {
+	cover(105);
 	buf[end+2] = buf[offset + 1];
 	buf[end+3] = buf[offset + 2];
       } else {
+	cover(106);
 	buf[end+2] = buf[end - 4];
 	if (i1 - i0 == 4) {
+	  cover(107);
 	  buf[end+3] = buf[offset + 1];
 	} else {
+	  cover(108);
 	  buf[end+3] = buf[end - 5];
 	}
       }
@@ -2655,12 +2823,14 @@
     buf[offset - 2] = buf[offset + 2];
     buf[offset - 3] = buf[offset + 3];
     if (offset == 4) {
+      cover(83);
       buf[0] = buf[offset + 4];
     }
 
     //----- 9-7 irreversible filter
 
     if (tileComp->transform == 0) {
+      cover(84);
       // step 1 (even)
       for (i = 1; i <= end + 2; i += 2) {
 	buf[i] = (int)(idwtKappa * buf[i]);
@@ -2689,6 +2859,7 @@
     //----- 5-3 reversible filter
 
     } else {
+      cover(85);
       // step 1 (even)
       for (i = 3; i <= end; i += 2) {
 	buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2;
@@ -2717,6 +2888,7 @@
   //----- inverse multi-component transform
 
   if (tile->multiComp == 1) {
+    cover(86);
     if (img.nComps < 3 ||
 	tile->tileComps[0].hSep != tile->tileComps[1].hSep ||
 	tile->tileComps[0].vSep != tile->tileComps[1].vSep ||
@@ -2727,6 +2899,7 @@
 
     // inverse irreversible multiple component transform
     if (tile->tileComps[0].transform == 0) {
+      cover(87);
       j = 0;
       for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
 	for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
@@ -2743,6 +2916,7 @@
 
     // inverse reversible multiple component transform
     } else {
+      cover(88);
       j = 0;
       for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
 	for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
@@ -2764,6 +2938,7 @@
 
     // signed: clip
     if (tileComp->sgned) {
+      cover(89);
       minVal = -(1 << (tileComp->prec - 1));
       maxVal = (1 << (tileComp->prec - 1)) - 1;
       dataPtr = tileComp->data;
@@ -2771,11 +2946,14 @@
 	for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
 	  coeff = *dataPtr;
 	  if (tileComp->transform == 0) {
+	    cover(109);
 	    coeff >>= fracBits;
 	  }
 	  if (coeff < minVal) {
+	    cover(110);
 	    coeff = minVal;
 	  } else if (coeff > maxVal) {
+	    cover(111);
 	    coeff = maxVal;
 	  }
 	  *dataPtr++ = coeff;
@@ -2784,6 +2962,7 @@
 
     // unsigned: inverse DC level shift and clip
     } else {
+      cover(90);
       maxVal = (1 << tileComp->prec) - 1;
       zeroVal = 1 << (tileComp->prec - 1);
       dataPtr = tileComp->data;
@@ -2791,12 +2970,15 @@
 	for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
 	  coeff = *dataPtr;
 	  if (tileComp->transform == 0) {
+	    cover(112);
 	    coeff >>= fracBits;
 	  }
 	  coeff += zeroVal;
 	  if (coeff < 0) {
+	    cover(113);
 	    coeff = 0;
 	  } else if (coeff > maxVal) {
+	    cover(114);
 	    coeff = maxVal;
 	  }
 	  *dataPtr++ = coeff;
@@ -2929,10 +3111,10 @@
   int c;
 
   while (bitBufLen < nBits) {
-    if ((c = str->getChar()) == EOF) {
+    if (byteCount == 0 || (c = str->getChar()) == EOF) {
       return gFalse;
     }
-    ++byteCount;
+    --byteCount;
     if (bitBufSkip) {
       bitBuf = (bitBuf << 7) | (c & 0x7f);
       bitBufLen += 7;
@@ -2947,8 +3129,16 @@
   return gTrue;
 }
 
-void JPXStream::clearBitBuf() {
+void JPXStream::startBitBuf(Guint byteCountA) {
   bitBufLen = 0;
   bitBufSkip = gFalse;
-  byteCount = 0;
+  byteCount = byteCountA;
+}
+
+Guint JPXStream::finishBitBuf() {
+  if (bitBufSkip) {
+    str->getChar();
+    --byteCount;
+  }
+  return byteCount;
 }

Index: JPXStream.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/JPXStream.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- JPXStream.h	31 Aug 2005 15:28:46 -0000	1.2
+++ JPXStream.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -17,6 +17,7 @@
 #include "Object.h"
 #include "Stream.h"
 
+class JArithmeticDecoder;
 class JArithmeticDecoderStats;
 
 //------------------------------------------------------------------------
@@ -275,6 +276,7 @@
   virtual ~JPXStream();
   virtual StreamKind getKind() { return strJPX; }
   virtual void reset();
+  virtual void close();
   virtual int getChar();
   virtual int lookChar();
   virtual GooString *getPSFilter(int psLevel, char *indent);
@@ -315,7 +317,8 @@
   GBool readULong(Guint *x);
   GBool readNBytes(int nBytes, GBool signd, int *x);
   GBool readBits(int nBits, Guint *x);
-  void clearBitBuf();
+  void startBitBuf(Guint byteCountA);
+  Guint finishBitBuf();
 
   Guint nComps;			// number of components
   Guint *bpc;			// bits per component, for each component
@@ -336,8 +339,7 @@
   int bitBufLen;		// number of bits in bitBuf
   GBool bitBufSkip;		// true if next bit should be skipped
 				//   (for bit stuffing)
-  Guint byteCount;		// number of bytes read since last call
-				//   to clearBitBuf
+  Guint byteCount;		// number of available bytes left
 
   Guint curX, curY, curComp;	// current position for lookChar/getChar
   Guint readBuf;		// read buffer

Index: Lexer.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Lexer.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Lexer.cc	4 Feb 2007 00:16:43 -0000	1.5
+++ Lexer.cc	25 Apr 2007 19:59:10 -0000	1.6
@@ -319,11 +319,13 @@
 	  // we are growing see if the document is not malformed and we are growing too much
 	  if (objNum != -1)
 	  {
-	    int newObjNum = xref->getNumEntry(getPos());
+	    int newObjNum = xref->getNumEntry(curStr.streamGetPos());
 	    if (newObjNum != objNum)
 	    {
 	      error(getPos(), "Unterminated string");
 	      done = gTrue;
+	      delete s;
+	      n = -2;
 	    }
 	  }
 	}
@@ -331,11 +333,15 @@
 	++n;
       }
     } while (!done);
-    if (!s)
-      s = new GooString(tokBuf, n);
-    else
-      s->append(tokBuf, n);
-    obj->initString(s);
+    if (n >= 0) {
+      if (!s)
+        s = new GooString(tokBuf, n);
+      else
+        s->append(tokBuf, n);
+      obj->initString(s);
+    } else {
+      obj->initEOF();
+    }
     break;
 
   // name

Index: Link.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Link.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Link.cc	8 Oct 2006 20:38:47 -0000	1.5
+++ Link.cc	25 Apr 2007 19:59:10 -0000	1.6
@@ -22,7 +22,6 @@
 #include "Dict.h"
 #include "Link.h"
 #include "Sound.h"
-#include "UGooString.h"
 
 //------------------------------------------------------------------------
 // LinkAction
@@ -296,7 +295,7 @@
     kind = destFitH;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
-      goto err1;
+      kind = destFit;
     }
     top = obj2.getNum();
     obj2.free();
@@ -310,7 +309,7 @@
     kind = destFitV;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
-      goto err1;
+      kind = destFit;
     }
     left = obj2.getNum();
     obj2.free();
@@ -324,25 +323,25 @@
     kind = destFitR;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
-      goto err1;
+      kind = destFit;
     }
     left = obj2.getNum();
     obj2.free();
     if (!a->get(3, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
-      goto err1;
+      kind = destFit;
     }
     bottom = obj2.getNum();
     obj2.free();
     if (!a->get(4, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
-      goto err1;
+      kind = destFit;
     }
     right = obj2.getNum();
     obj2.free();
     if (!a->get(5, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
-      goto err1;
+      kind = destFit;
     }
     top = obj2.getNum();
     obj2.free();
@@ -364,7 +363,7 @@
     kind = destFitBH;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
-      goto err1;
+      kind = destFit;
     }
     top = obj2.getNum();
     obj2.free();
@@ -378,7 +377,7 @@
     kind = destFitBV;
     if (!a->get(2, &obj2)->isNum()) {
       error(-1, "Bad annotation destination position");
-      goto err1;
+      kind = destFit;
     }
     left = obj2.getNum();
     obj2.free();
@@ -427,9 +426,9 @@
 
   // named destination
   if (destObj->isName()) {
-    namedDest = new UGooString(destObj->getName());
+    namedDest = new GooString(destObj->getName());
   } else if (destObj->isString()) {
-    namedDest = new UGooString(*destObj->getString());
+    namedDest = destObj->getString()->copy();
 
   // destination dictionary
   } else if (destObj->isArray()) {
@@ -465,9 +464,9 @@
 
   // named destination
   if (destObj->isName()) {
-    namedDest = new UGooString(destObj->getName());
+    namedDest = new GooString(destObj->getName());
   } else if (destObj->isString()) {
-    namedDest = new UGooString(*destObj->getString());
+    namedDest = destObj->getString()->copy();
 
   // destination dictionary
   } else if (destObj->isArray()) {
@@ -691,42 +690,13 @@
 }
 
 //------------------------------------------------------------------------
-// LinkBorderStyle
-//------------------------------------------------------------------------
-
-LinkBorderStyle::LinkBorderStyle(LinkBorderType typeA, double widthA,
-				 double *dashA, int dashLengthA,
-				 double rA, double gA, double bA) {
-  type = typeA;
-  width = widthA;
-  dash = dashA;
-  dashLength = dashLengthA;
-  r = rA;
-  g = gA;
-  b = bA;
-}
-
-LinkBorderStyle::~LinkBorderStyle() {
-  if (dash) {
-    gfree(dash);
-  }
-}
-
-//------------------------------------------------------------------------
 // Link
 //------------------------------------------------------------------------
 
 Link::Link(Dict *dict, GooString *baseURI) {
-  Object obj1, obj2, obj3;
-  LinkBorderType borderType;
-  double borderWidth;
-  double *borderDash;
-  int borderDashLength;
-  double borderR, borderG, borderB;
+  Object obj1, obj2;
   double t;
-  int i;
 
-  borderStyle = NULL;
   action = NULL;
   ok = gFalse;
 
@@ -771,97 +741,6 @@
     y2 = t;
   }
 
-  // get the border style info
-  borderType = linkBorderSolid;
-  borderWidth = 1;
-  borderDash = NULL;
-  borderDashLength = 0;
-  borderR = 0;
-  borderG = 0;
-  borderB = 1;
-  if (dict->lookup("BS", &obj1)->isDict()) {
-    if (obj1.dictLookup("S", &obj2)->isName()) {
-      if (obj2.isName("S")) {
-	borderType = linkBorderSolid;
-      } else if (obj2.isName("D")) {
-	borderType = linkBorderDashed;
-      } else if (obj2.isName("B")) {
-	borderType = linkBorderEmbossed;
-      } else if (obj2.isName("I")) {
-	borderType = linkBorderEngraved;
-      } else if (obj2.isName("U")) {
-	borderType = linkBorderUnderlined;
-      }
-    }
-    obj2.free();
-    if (obj1.dictLookup("W", &obj2)->isNum()) {
-      borderWidth = obj2.getNum();
-    }
-    obj2.free();
-    if (obj1.dictLookup("D", &obj2)->isArray()) {
-      borderDashLength = obj2.arrayGetLength();
-      borderDash = (double *)gmallocn(borderDashLength, sizeof(double));
-      for (i = 0; i < borderDashLength; ++i) {
-	if (obj2.arrayGet(i, &obj3)->isNum()) {
-	  borderDash[i] = obj3.getNum();
-	} else {
-	  borderDash[i] = 1;
-	}
-	obj3.free();
-      }
-    }
-    obj2.free();
-  } else {
-    obj1.free();
-    if (dict->lookup("Border", &obj1)->isArray()) {
-      if (obj1.arrayGetLength() >= 3) {
-	if (obj1.arrayGet(2, &obj2)->isNum()) {
-	  borderWidth = obj2.getNum();
-	}
-	obj2.free();
-	if (obj1.arrayGetLength() >= 4) {
-	  if (obj1.arrayGet(3, &obj2)->isArray()) {
-	    borderType = linkBorderDashed;
-	    borderDashLength = obj2.arrayGetLength();
-	    borderDash = (double *)gmallocn(borderDashLength, sizeof(double));
-	    for (i = 0; i < borderDashLength; ++i) {
-	      if (obj2.arrayGet(i, &obj3)->isNum()) {
-		borderDash[i] = obj3.getNum();
-	      } else {
-		borderDash[i] = 1;
-	      }
-	      obj3.free();
-	    }
-	  } else {
-	    // Adobe draws no border at all if the last element is of
-	    // the wrong type.
-	    borderWidth = 0;
-	  }
-	  obj2.free();
-	}
-      }
-    }
-  }
-  obj1.free();
-  if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) {
-    if (obj1.arrayGet(0, &obj2)->isNum()) {
-      borderR = obj2.getNum();
-    }
-    obj1.free();
-    if (obj1.arrayGet(1, &obj2)->isNum()) {
-      borderG = obj2.getNum();
-    }
-    obj1.free();
-    if (obj1.arrayGet(2, &obj2)->isNum()) {
-      borderB = obj2.getNum();
-    }
-    obj1.free();
-  }
-  obj1.free();
-  borderStyle = new LinkBorderStyle(borderType, borderWidth,
-				    borderDash, borderDashLength,
-				    borderR, borderG, borderB);
-
   // look for destination
   if (!dict->lookup("Dest", &obj1)->isNull()) {
     action = LinkAction::parseDest(&obj1);
@@ -889,9 +768,6 @@
 }
 
 Link::~Link() {
-  if (borderStyle) {
-    delete borderStyle;
-  }
   if (action) {
     delete action;
   }

Index: Link.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Link.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Link.h	8 Oct 2006 20:38:47 -0000	1.3
+++ Link.h	25 Apr 2007 19:59:10 -0000	1.4
@@ -16,7 +16,6 @@
 #include "Object.h"
 
 class GooString;
-class UGooString;
 class Array;
 class Dict;
 class Sound;
@@ -137,13 +136,13 @@
   // Accessors.
   virtual LinkActionKind getKind() { return actionGoTo; }
   LinkDest *getDest() { return dest; }
-  UGooString *getNamedDest() { return namedDest; }
+  GooString *getNamedDest() { return namedDest; }
 
 private:
 
   LinkDest *dest;		// regular destination (NULL for remote
 				//   link with bad destination)
-  UGooString *namedDest;	// named destination (only one of dest and
+  GooString *namedDest;	// named destination (only one of dest and
 				//   and namedDest may be non-NULL)
 };
 
@@ -168,14 +167,14 @@
   virtual LinkActionKind getKind() { return actionGoToR; }
   GooString *getFileName() { return fileName; }
   LinkDest *getDest() { return dest; }
-  UGooString *getNamedDest() { return namedDest; }
+  GooString *getNamedDest() { return namedDest; }
 
 private:
 
   GooString *fileName;		// file name
   LinkDest *dest;		// regular destination (NULL for remote
 				//   link with bad destination)
-  UGooString *namedDest;	// named destination (only one of dest and
+  GooString *namedDest;	// named destination (only one of dest and
 				//   and namedDest may be non-NULL)
 };
 
@@ -333,42 +332,6 @@
 };
 
 //------------------------------------------------------------------------
-// LinkBorderStyle
-//------------------------------------------------------------------------
-
-enum LinkBorderType {
-  linkBorderSolid,
-  linkBorderDashed,
-  linkBorderEmbossed,
-  linkBorderEngraved,
-  linkBorderUnderlined
-};
-
-class LinkBorderStyle {
-public:
-
-  LinkBorderStyle(LinkBorderType typeA, double widthA,
-		  double *dashA, int dashLengthA,
-		  double rA, double gA, double bA);
-  ~LinkBorderStyle();
-
-  LinkBorderType getType() { return type; }
-  double getWidth() { return width; }
-  void getDash(double **dashA, int *dashLengthA)
-    { *dashA = dash; *dashLengthA = dashLength; }
-  void getColor(double *rA, double *gA, double *bA)
-    { *rA = r; *gA = g; *bA = b; }
-
-private:
-
-  LinkBorderType type;
-  double width;
-  double *dash;
-  int dashLength;
-  double r, g, b;
-};
-
-//------------------------------------------------------------------------
 // Link
 //------------------------------------------------------------------------
 
@@ -395,14 +358,10 @@
   void getRect(double *xa1, double *ya1, double *xa2, double *ya2)
     { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; }
 
-  // Get the border style info.
-  LinkBorderStyle *getBorderStyle() { return borderStyle; }
-
 private:
 
   double x1, y1;		// lower left corner
   double x2, y2;		// upper right corner
-  LinkBorderStyle *borderStyle;	// border style
   LinkAction *action;		// action
   GBool ok;			// is link valid?
 };

Index: Makefile.am
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Makefile.am,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- Makefile.am	4 Apr 2007 02:42:29 -0000	1.30
+++ Makefile.am	25 Apr 2007 19:59:10 -0000	1.31
@@ -154,6 +154,7 @@
 	PDFDoc.h		\
 	PDFDocEncoding.h	\
 	ProfileData.h		\
+	PreScanOutputDev.h	\
 	PSTokenizer.h		\
 	Stream-CCITT.h		\
 	Stream.h		\
@@ -171,7 +172,6 @@
 	PSOutputDev.h		\
 	TextOutputDev.h		\
 	SecurityHandler.h	\
-	UGooString.h		\
 	UTF8.h			\
 	XpdfPluginAPI.h		\
 	Sound.h			\
@@ -218,6 +218,7 @@
 	PDFDoc.cc 		\
 	PDFDocEncoding.cc	\
 	ProfileData.cc		\
+	PreScanOutputDev.cc \
 	PSTokenizer.cc		\
 	Stream.cc 		\
 	UnicodeMap.cc		\
@@ -228,7 +229,6 @@
 	PageLabelInfo.h		\
 	PageLabelInfo.cc	\
 	SecurityHandler.cc	\
-	UGooString.cc	 	\
 	Sound.cc		\
 	XpdfPluginAPI.cc
 

Index: Object.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Object.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Object.cc	25 Feb 2006 12:30:30 -0000	1.3
+++ Object.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -18,7 +18,6 @@
 #include "Dict.h"
 #include "Error.h"
 #include "Stream.h"
-#include "UGooString.h"
 #include "XRef.h"
 
 //------------------------------------------------------------------------
@@ -185,7 +184,7 @@
   case objDict:
     fprintf(f, "<<");
     for (i = 0; i < dictGetLength(); ++i) {
-      fprintf(f, " /%s ", dictGetKey(i)->getCString());
+      fprintf(f, " /%s ", dictGetKey(i));
       dictGetValNF(i, &obj);
       obj.print(f);
       obj.free();
@@ -228,5 +227,7 @@
 	fprintf(f, "  %-20s: %6d\n", objTypeNames[i], numAlloc[i]);
     }
   }
+#else
+  (void)f;
 #endif
 }

Index: Object.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Object.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Object.h	24 Feb 2007 23:32:23 -0000	1.4
+++ Object.h	25 Apr 2007 19:59:10 -0000	1.5
@@ -23,7 +23,6 @@
 class Array;
 class Dict;
 class Stream;
-class UGooString;
 
 //------------------------------------------------------------------------
 // Ref
@@ -168,14 +167,12 @@
 
   // Dict accessors.
   int dictGetLength();
-  void dictAddOwnKeyVal(UGooString *key, Object *val);
-  void dictAdd(const UGooString &key, Object *val);
-  void dictAddOwnVal(const char *key, Object *val);
-  void dictSet(const UGooString &key, Object *val);
+  void dictAdd(char *key, Object *val);
+  void dictSet(char *key, Object *val);
   GBool dictIs(char *dictType);
-  Object *dictLookup(const UGooString &key, Object *obj);
-  Object *dictLookupNF(const UGooString &key, Object *obj);
-  UGooString *dictGetKey(int i);
+  Object *dictLookup(char *key, Object *obj);
+  Object *dictLookupNF(char *key, Object *obj);
+  char *dictGetKey(int i);
   Object *dictGetVal(int i, Object *obj);
   Object *dictGetValNF(int i, Object *obj);
 
@@ -246,16 +243,10 @@
 inline int Object::dictGetLength()
   { return dict->getLength(); }
 
-inline void Object::dictAdd(const UGooString &key, Object *val)
+inline void Object::dictAdd(char *key, Object *val)
   { dict->add(key, val); }
 
-inline void Object::dictAddOwnVal(const char *key, Object *val)
-  { dict->addOwnVal(key, val); }
-
-inline void Object::dictAddOwnKeyVal(UGooString *key, Object *val)
-  { dict->addOwnKeyVal(key, val); }
-
-inline void Object::dictSet(const UGooString &key, Object *val)
+inline void Object::dictSet(char *key, Object *val)
  	{ dict->set(key, val); }
 
 inline GBool Object::dictIs(char *dictType)
@@ -264,13 +255,13 @@
 inline GBool Object::isDict(char *dictType)
   { return type == objDict && dictIs(dictType); }
 
-inline Object *Object::dictLookup(const UGooString &key, Object *obj)
+inline Object *Object::dictLookup(char *key, Object *obj)
   { return dict->lookup(key, obj); }
 
-inline Object *Object::dictLookupNF(const UGooString &key, Object *obj)
+inline Object *Object::dictLookupNF(char *key, Object *obj)
   { return dict->lookupNF(key, obj); }
 
-inline UGooString *Object::dictGetKey(int i)
+inline char *Object::dictGetKey(int i)
   { return dict->getKey(i); }
 
 inline Object *Object::dictGetVal(int i, Object *obj)

Index: Outline.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Outline.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- Outline.cc	18 Jan 2006 22:32:13 -0000	1.5
+++ Outline.cc	25 Apr 2007 19:59:10 -0000	1.6
@@ -18,7 +18,6 @@
 #include "Link.h"
 #include "PDFDocEncoding.h"
 #include "Outline.h"
-#include "UGooString.h"
 
 //------------------------------------------------------------------------
 

Index: OutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/OutputDev.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- OutputDev.cc	4 Feb 2006 21:10:41 -0000	1.4
+++ OutputDev.cc	25 Apr 2007 19:59:10 -0000	1.5
@@ -56,6 +56,7 @@
   updateLineCap(state);
   updateMiterLimit(state);
   updateLineWidth(state);
+  updateStrokeAdjust(state);
   updateFillColorSpace(state);
   updateFillColor(state);
   updateStrokeColorSpace(state);
@@ -65,6 +66,7 @@
   updateStrokeOpacity(state);
   updateFillOverprint(state);
   updateStrokeOverprint(state);
+  updateTransfer(state);
   updateFont(state);
 }
 

Index: OutputDev.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/OutputDev.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- OutputDev.h	4 Feb 2006 21:10:41 -0000	1.5
+++ OutputDev.h	25 Apr 2007 19:59:10 -0000	1.6
@@ -21,14 +21,18 @@
 class GooHash;
 class GooString;
 class GfxState;
+struct GfxColor;
 class GfxColorSpace;
 class GfxImageColorMap;
 class GfxFunctionShading;
 class GfxAxialShading;
 class GfxRadialShading;
 class Stream;
+class Links;
 class Link;
 class Catalog;
+class Page;
+class Function;
 
 //------------------------------------------------------------------------
 // OutputDev
@@ -62,6 +66,10 @@
   // will be reduced to a series of other drawing operations.
   virtual GBool useShadedFills() { return gFalse; }
 
+  // Does this device use drawForm()?  If this returns false,
+  // form-type XObjects will be interpreted (i.e., unrolled).
+  virtual GBool useDrawForm() { return gFalse; }
+
   // Does this device use beginType3Char/endType3Char?  Otherwise,
   // text in Type 3 fonts will be drawn with drawChar/drawString.
   virtual GBool interpretType3Chars() = 0;
@@ -74,8 +82,20 @@
   // Set default transform matrix.
   virtual void setDefaultCTM(double *ctm);
 
+  // Check to see if a page slice should be displayed.  If this
+  // returns false, the page display is aborted.  Typically, an
+  // OutputDev will use some alternate means to display the page
+  // before returning false.
+  virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI,
+			       int rotate, GBool useMediaBox, GBool crop,
+			       int sliceX, int sliceY, int sliceW, int sliceH,
+			       GBool printing, Catalog * catalog,
+			       GBool (* abortCheckCbk)(void *data) = NULL,
+			       void * abortCheckCbkData = NULL)
+    { return gTrue; }
+
   // Start a page.
-  virtual void startPage(int /*pageNum*/, GfxState * /*state*/) {}
+  virtual void startPage(int pageNum, GfxState *state) {}
 
   // End a page.
   virtual void endPage() {}
@@ -92,9 +112,6 @@
   double *getDefCTM() { return defCTM; }
   double *getDefICTM() { return defICTM; }
 
-  //----- link borders
-  virtual void drawLink(Link * /*link*/, Catalog * /*catalog*/) {}
-
   //----- save/restore graphics state
   virtual void saveState(GfxState * /*state*/) {}
   virtual void restoreState(GfxState * /*state*/) {}
@@ -109,6 +126,7 @@
   virtual void updateLineCap(GfxState * /*state*/) {}
   virtual void updateMiterLimit(GfxState * /*state*/) {}
   virtual void updateLineWidth(GfxState * /*state*/) {}
+  virtual void updateStrokeAdjust(GfxState * /*state*/) {}
   virtual void updateFillColorSpace(GfxState * /*state*/) {}
   virtual void updateStrokeColorSpace(GfxState * /*state*/) {}
   virtual void updateFillColor(GfxState * /*state*/) {}
@@ -118,6 +136,7 @@
   virtual void updateStrokeOpacity(GfxState * /*state*/) {}
   virtual void updateFillOverprint(GfxState * /*state*/) {}
   virtual void updateStrokeOverprint(GfxState * /*state*/) {}
+  virtual void updateTransfer(GfxState * /*state*/) {}
 
   //----- update text state
   virtual void updateFont(GfxState * /*state*/) {}
@@ -139,14 +158,18 @@
 				 double * /*mat*/, double * /*bbox*/,
 				 int /*x0*/, int /*y0*/, int /*x1*/, int /*y1*/,
 				 double /*xStep*/, double /*yStep*/) {}
-  virtual void functionShadedFill(GfxState * /*state*/,
-				  GfxFunctionShading * /*shading*/) {}
-  virtual void axialShadedFill(GfxState * /*state*/, GfxAxialShading * /*shading*/) {}
-  virtual void radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/) {}
+  virtual GBool functionShadedFill(GfxState * /*state*/,
+				   GfxFunctionShading * /*shading*/)
+    { return gFalse; }
+  virtual GBool axialShadedFill(GfxState * /*state*/, GfxAxialShading * /*shading*/)
+    { return gFalse; }
+  virtual GBool radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/)
+    { return gFalse; }
 
   //----- path clipping
   virtual void clip(GfxState * /*state*/) {}
   virtual void eoClip(GfxState * /*state*/) {}
+  virtual void clipToStrokePath(GfxState * /*state*/) {}
 
   //----- text drawing
   virtual void beginStringOp(GfxState * /*state*/) {}
@@ -204,6 +227,9 @@
   virtual void type3D1(GfxState * /*state*/, double /*wx*/, double /*wy*/,
 		       double /*llx*/, double /*lly*/, double /*urx*/, double /*ury*/) {}
 
+  //----- form XObjects
+  virtual void drawForm(Ref /*id*/) {}
+
   //----- PostScript XObjects
   virtual void psXObject(Stream * /*psStream*/, Stream * /*level1Stream*/) {}
 
@@ -212,7 +238,25 @@
   virtual GooHash *getProfileHash() {return profileHash; }
   virtual GooHash *endProfile();
 
-  
+  //----- transparency groups and soft masks
+  virtual void beginTransparencyGroup(GfxState * /*state*/, double * /*bbox*/,
+				      GfxColorSpace * /*blendingColorSpace*/,
+				      GBool /*isolated*/, GBool /*knockout*/,
+				      GBool /*forSoftMask*/) {}
+  virtual void endTransparencyGroup(GfxState * /*state*/) {}
+  virtual void paintTransparencyGroup(GfxState * /*state*/, double * /*bbox*/) {}
+  virtual void setSoftMask(GfxState * /*state*/, double * /*bbox*/, GBool /*alpha*/,
+			   Function * /*transferFunc*/, GfxColor * /*backdropColor*/) {}
+  virtual void clearSoftMask(GfxState * /*state*/) {}
+
+  //----- links
+  virtual void processLink(Link * /*link*/, Catalog * /*catalog*/) {}
+
+#if 1 //~tmp: turn off anti-aliasing temporarily
+  virtual GBool getVectorAntialias() { return gFalse; }
+  virtual void setVectorAntialias(GBool /*vaa*/) {}
+#endif
+
 private:
 
   double defCTM[6];		// default coordinate transform matrix

Index: PDFDoc.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PDFDoc.cc,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- PDFDoc.cc	18 Jan 2006 22:32:13 -0000	1.10
+++ PDFDoc.cc	25 Apr 2007 19:59:10 -0000	1.11
@@ -38,7 +38,6 @@
 #include "Outline.h"
 #endif
 #include "PDFDoc.h"
-#include "UGooString.h"
 
 //------------------------------------------------------------------------
 
@@ -63,7 +62,6 @@
   str = NULL;
   xref = NULL;
   catalog = NULL;
-  links = NULL;
 #ifndef DISABLE_OUTLINE
   outline = NULL;
 #endif
@@ -121,7 +119,6 @@
   str = NULL;
   xref = NULL;
   catalog = NULL;
-  links = NULL;
 #ifndef DISABLE_OUTLINE
   outline = NULL;
 #endif
@@ -166,12 +163,15 @@
   ok = gFalse;
   errCode = errNone;
   guiData = guiDataA;
-  fileName = NULL;
+  if (strA->getFileName()) {
+    fileName = strA->getFileName()->copy();
+  } else {
+    fileName = NULL;
+  }
   file = NULL;
   str = strA;
   xref = NULL;
   catalog = NULL;
-  links = NULL;
 #ifndef DISABLE_OUTLINE
   outline = NULL;
 #endif
@@ -239,9 +239,6 @@
   if (fileName) {
     delete fileName;
   }
-  if (links) {
-    delete links;
-  }
 }
 
 
@@ -330,7 +327,8 @@
 			    secHdlr->getFileKey(),
 			    secHdlr->getFileKeyLength(),
 			    secHdlr->getEncVersion(),
-			    secHdlr->getEncRevision());
+			    secHdlr->getEncRevision(),
+			    secHdlr->getEncAlgorithm());
 	ret = gTrue;
       } else {
 	// authorization failed
@@ -349,36 +347,25 @@
   return ret;
 }
 
-void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
-			 int rotate, GBool useMediaBox, GBool crop, GBool doLinks,
+void PDFDoc::displayPage(OutputDev *out, int page,
+			 double hDPI, double vDPI, int rotate,
+			 GBool useMediaBox, GBool crop, GBool printing,
 			 GBool (*abortCheckCbk)(void *data),
 			 void *abortCheckCbkData,
                          GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
                          void *annotDisplayDecideCbkData) {
-  Page *p;
-
   if (globalParams->getPrintCommands()) {
     printf("***** page %d *****\n", page);
   }
-  p = catalog->getPage(page);
-  if (doLinks) {
-    if (links) {
-      delete links;
-    }
-    getLinks(p);
-    p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, links, catalog,
-	       abortCheckCbk, abortCheckCbkData,
-               annotDisplayDecideCbk, annotDisplayDecideCbkData);
-  } else {
-    p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, NULL, catalog,
-	       abortCheckCbk, abortCheckCbkData,
-               annotDisplayDecideCbk, annotDisplayDecideCbkData);
-  }
+  catalog->getPage(page)->display(out, hDPI, vDPI,
+				  rotate, useMediaBox, crop, printing, catalog,
+				  abortCheckCbk, abortCheckCbkData,
+				  annotDisplayDecideCbk, annotDisplayDecideCbkData);
 }
 
 void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
-			  double hDPI, double vDPI, int rotate, GBool useMediaBox,
-			  GBool crop, GBool doLinks,
+			  double hDPI, double vDPI, int rotate,
+			  GBool useMediaBox, GBool crop, GBool printing,
 			  GBool (*abortCheckCbk)(void *data),
 			  void *abortCheckCbkData,
                           GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
@@ -386,49 +373,34 @@
   int page;
 
   for (page = firstPage; page <= lastPage; ++page) {
-    displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, doLinks,
+    displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, printing,
 		abortCheckCbk, abortCheckCbkData,
                 annotDisplayDecideCbk, annotDisplayDecideCbkData);
   }
 }
 
 void PDFDoc::displayPageSlice(OutputDev *out, int page,
-			      double hDPI, double vDPI,
-			      int rotate, GBool useMediaBox, GBool crop, GBool doLinks,
+			      double hDPI, double vDPI, int rotate,
+			      GBool useMediaBox, GBool crop, GBool printing,
 			      int sliceX, int sliceY, int sliceW, int sliceH,
 			      GBool (*abortCheckCbk)(void *data),
 			      void *abortCheckCbkData,
                               GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
                               void *annotDisplayDecideCbkData) {
-  Page *p;
-
-  p = catalog->getPage(page);
-  if (doLinks)
-  {
-    if (links) {
-      delete links;
-    }
-    getLinks(p);
-    p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
-		  sliceX, sliceY, sliceW, sliceH,
-		  links, catalog,
-                  abortCheckCbk, abortCheckCbkData,
-                  annotDisplayDecideCbk, annotDisplayDecideCbkData);
-  } else {
-    p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
-                  sliceX, sliceY, sliceW, sliceH,
-	          NULL, catalog,
-	          abortCheckCbk, abortCheckCbkData,
-	          annotDisplayDecideCbk, annotDisplayDecideCbkData);
-  } 
+  catalog->getPage(page)->displaySlice(out, hDPI, vDPI,
+				       rotate, useMediaBox, crop,
+				       sliceX, sliceY, sliceW, sliceH,
+				       printing, catalog,
+				       abortCheckCbk, abortCheckCbkData,
+				       annotDisplayDecideCbk, annotDisplayDecideCbkData);
 }
 
-Links *PDFDoc::takeLinks() {
-  Links *ret;
-
-  ret = links;
-  links = NULL;
-  return ret;
+Links *PDFDoc::getLinks(int page) {
+  return catalog->getPage(page)->getLinks(catalog);
+}
+  
+void PDFDoc::processLinks(OutputDev *out, int page) {
+  catalog->getPage(page)->processLinks(out, catalog);
 }
 
 GBool PDFDoc::isLinearized() {
@@ -440,7 +412,8 @@
   obj1.initNull();
   parser = new Parser(xref,
 	     new Lexer(xref,
-	       str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
+	       str->makeSubStream(str->getStart(), gFalse, 0, &obj1)),
+	     gTrue);
   parser->getObj(&obj1);
   parser->getObj(&obj2);
   parser->getObj(&obj3);
@@ -477,10 +450,3 @@
   fclose(f);
   return gTrue;
 }
-
-void PDFDoc::getLinks(Page *page) {
-  Object obj;
-
-  links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
-  obj.free();
-}

Index: PDFDoc.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PDFDoc.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- PDFDoc.h	18 Jan 2006 22:32:13 -0000	1.7
+++ PDFDoc.h	25 Apr 2007 19:59:10 -0000	1.8
@@ -87,8 +87,9 @@
   Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); }
 
   // Display a page.
-  void displayPage(OutputDev *out, int page, double hDPI, double vDPI,
-		   int rotate, GBool useMediaBox, GBool crop, GBool doLinks,
+  void displayPage(OutputDev *out, int page,
+		   double hDPI, double vDPI, int rotate,
+		   GBool useMediaBox, GBool crop, GBool printing,
 		   GBool (*abortCheckCbk)(void *data) = NULL,
 		   void *abortCheckCbkData = NULL,
                    GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
@@ -97,7 +98,7 @@
   // Display a range of pages.
   void displayPages(OutputDev *out, int firstPage, int lastPage,
 		    double hDPI, double vDPI, int rotate,
-		    GBool useMediaBox, GBool crop, GBool doLinks,
+		    GBool useMediaBox, GBool crop, GBool printing,
 		    GBool (*abortCheckCbk)(void *data) = NULL,
 		    void *abortCheckCbkData = NULL,
                     GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
@@ -105,8 +106,8 @@
 
   // Display part of a page.
   void displayPageSlice(OutputDev *out, int page,
-			double hDPI, double vDPI,
-			int rotate, GBool useMediaBox, GBool crop, GBool doLinks,
+			double hDPI, double vDPI, int rotate, 
+			GBool useMediaBox, GBool crop, GBool printing,
 			int sliceX, int sliceY, int sliceW, int sliceH,
 			GBool (*abortCheckCbk)(void *data) = NULL,
 			void *abortCheckCbkData = NULL,
@@ -119,13 +120,17 @@
 
   // Returns the links for the current page, transferring ownership to
   // the caller.
-  Links *takeLinks();
+  Links *getLinks(int page);
 
   // Find a named destination.  Returns the link destination, or
   // NULL if <name> is not a destination.
-  LinkDest *findDest(UGooString *name)
+  LinkDest *findDest(GooString *name)
     { return catalog->findDest(name); }
 
+  // Process the links for a page.
+  void processLinks(OutputDev *out, int page);
+
+
 #ifndef DISABLE_OUTLINE
   // Return the outline object.
   Outline *getOutline() { return outline; }
@@ -175,7 +180,6 @@
   GBool checkFooter();
   void checkHeader();
   GBool checkEncryption(GooString *ownerPassword, GooString *userPassword);
-  void getLinks(Page *page);
 
   GooString *fileName;
   FILE *file;
@@ -184,7 +188,6 @@
   double pdfVersion;
   XRef *xref;
   Catalog *catalog;
-  Links *links;
 #ifndef DISABLE_OUTLINE
   Outline *outline;
 #endif

Index: PSOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PSOutputDev.cc,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- PSOutputDev.cc	5 Apr 2007 12:13:51 -0000	1.14
+++ PSOutputDev.cc	25 Apr 2007 19:59:10 -0000	1.15
@@ -34,14 +34,30 @@
 #include "Page.h"
 #include "Stream.h"
 #include "Annot.h"
+#include "XRef.h"
+#include "PreScanOutputDev.h"
+#if HAVE_SPLASH
+#  include "splash/Splash.h"
+#  include "splash/SplashBitmap.h"
+#  include "SplashOutputDev.h"
+#endif
 #include "PSOutputDev.h"
[...3957 lines suppressed...]
+    step = 2;
+  } else {
+    i = 0;
+    step = 1;
+  }
+  for (j = 0; i < s->getLength() && j < 200; i += step) {
+    c = s->getChar(i) & 0xff;
+    if (c == '\\') {
+      writePS("\\\\");
+      j += 2;
+    } else if (c < 0x20 || c > 0x7e || (j == 0 && c == '(')) {
+      writePSFmt("\\{0:03o}", c);
+      j += 4;
+    } else {
+      writePSChar(c);
+      ++j;
+    }
+  }
+  writePS("\n");
+}

Index: PSOutputDev.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PSOutputDev.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- PSOutputDev.h	1 Jun 2006 06:42:25 -0000	1.7
+++ PSOutputDev.h	25 Apr 2007 19:59:10 -0000	1.8
@@ -24,6 +24,7 @@
 class GfxColorSpace;
 class GfxSeparationColorSpace;
 class PDFRectangle;
+struct PSFont8Info;
 struct PSFont16Enc;
 class PSOutCustomColor;
 class Function;
@@ -93,7 +94,11 @@
   // radialShadedFill()?  If this returns false, these shaded fills
   // will be reduced to a series of other drawing operations.
   virtual GBool useShadedFills()
-    { return level == psLevel2 || level == psLevel3; }
+    { return level >= psLevel2; }
+
+  // Does this device use drawForm()?  If this returns false,
+  // form-type XObjects will be interpreted (i.e., unrolled).
+  virtual GBool useDrawForm() { return preload; }
 
   // Does this device use beginType3Char/endType3Char?  Otherwise,
   // text in Type 3 fonts will be drawn with drawChar/drawString.
@@ -120,6 +125,17 @@
 
   //----- initialization and control
 
+  // Check to see if a page slice should be displayed.  If this
+  // returns false, the page display is aborted.  Typically, an
+  // OutputDev will use some alternate means to display the page
+  // before returning false.
+  virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI,
+			       int rotate, GBool useMediaBox, GBool crop,
+			       int sliceX, int sliceY, int sliceW, int sliceH,
+			       GBool printing, Catalog *catalog,
+			       GBool (*abortCheckCbk)(void *data) = NULL,
+			       void *abortCheckCbkData = NULL);
+
   // Start a page.
   virtual void startPage(int pageNum, GfxState *state);
 
@@ -145,6 +161,7 @@
   virtual void updateStrokeColor(GfxState *state);
   virtual void updateFillOverprint(GfxState *state);
   virtual void updateStrokeOverprint(GfxState *state);
+  virtual void updateTransfer(GfxState *state);
 
   //----- update text state
   virtual void updateFont(GfxState *state);
@@ -166,14 +183,15 @@
 				 double *mat, double *bbox,
 				 int x0, int y0, int x1, int y1,
 				 double xStep, double yStep);
-  virtual void functionShadedFill(GfxState *state,
-				  GfxFunctionShading *shading);
-  virtual void axialShadedFill(GfxState *state, GfxAxialShading *shading);
-  virtual void radialShadedFill(GfxState *state, GfxRadialShading *shading);
+  virtual GBool functionShadedFill(GfxState *state,
+				   GfxFunctionShading *shading);
+  virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading);
+  virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading);
 
   //----- path clipping
   virtual void clip(GfxState *state);
   virtual void eoClip(GfxState *state);
+  virtual void clipToStrokePath(GfxState *state);
 
   //----- text drawing
   virtual void drawString(GfxState *state, GooString *s);
@@ -203,6 +221,9 @@
   virtual void type3D1(GfxState *state, double wx, double wy,
 		       double llx, double lly, double urx, double ury);
 
+  //----- form XObjects
+  virtual void drawForm(Ref ref);
+
   //----- PostScript XObjects
   virtual void psXObject(Stream *psStream, Stream *level1Stream);
 
@@ -236,15 +257,19 @@
   void setupEmbeddedType1Font(Ref *id, GooString *psName);
   void setupExternalType1Font(GooString *fileName, GooString *psName);
   void setupEmbeddedType1CFont(GfxFont *font, Ref *id, GooString *psName);
+  void setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, GooString *psName);
   void setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, GooString *psName);
   GooString *setupExternalTrueTypeFont(GfxFont *font);
   void setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, GooString *psName);
   void setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, GooString *psName,
 				    GBool needVerticalMetrics);
+  void setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, GooString *psName);
   GooString *setupExternalCIDTrueTypeFont(GfxFont *font, GooString *fileName, int faceIndex = 0);
   void setupType3Font(GfxFont *font, GooString *psName, Dict *parentResDict);
   void setupImages(Dict *resDict);
   void setupImage(Ref id, Stream *str);
+  void setupForms(Dict *resDict);
+  void setupForm(Ref id, Object *strObj);
   void addProcessColor(double c, double m, double y, double k);
   void addCustomColor(GfxSeparationColorSpace *sepCS);
   void doPath(GfxPath *path);
@@ -259,8 +284,14 @@
 		 Stream *str, int width, int height, int len,
 		 int *maskColors, Stream *maskStr,
 		 int maskWidth, int maskHeight, GBool maskInvert);
+  void doImageL3(Object *ref, GfxImageColorMap *colorMap,
+		 GBool invert, GBool inlineImg,
+		 Stream *str, int width, int height, int len,
+		 int *maskColors, Stream *maskStr,
+		 int maskWidth, int maskHeight, GBool maskInvert);
   void dumpColorSpaceL2(GfxColorSpace *colorSpace,
-			GBool genXform, GBool updateColors);
+			GBool genXform, GBool updateColors,
+			GBool map01);
 #if OPI_SUPPORT
   void opiBegin20(GfxState *state, Dict *dict);
   void opiBegin13(GfxState *state, Dict *dict);
@@ -271,10 +302,11 @@
   void cvtFunction(Function *func);
   void writePSChar(char c);
   void writePS(char *s);
-  void writePSFmt(const char *fmt, ...) GCC_PRINTF_FORMAT(2, 3);
+  void writePSFmt(const char *fmt, ...);
   void writePSString(GooString *s);
   void writePSName(char *s);
   GooString *filterPSName(GooString *name);
+  void writePSTextLine(GooString *s);
 
   PSLevel level;		// PostScript level (1, 2, separation)
   PSOutMode mode;		// PostScript mode (PS, EPS, form)
@@ -282,6 +314,8 @@
   int paperHeight;		// height of paper, in pts
   int imgLLX, imgLLY,		// imageable area, in pts
       imgURX, imgURY;
+  GBool preload;		// load all images into memory, and
+				//   predefine forms
 
   PSOutputFunc outputFunc;
   void *outputStream;
@@ -307,9 +341,18 @@
   int fontFileNameSize;		// size of fontFileNames array
   int nextTrueTypeNum;		// next unique number to append to a TrueType
 				//   font name
+  PSFont8Info *font8Info;	// info for 8-bit fonts
+  int font8InfoLen;		// number of entries in font8Info array
+  int font8InfoSize;		// size of font8Info array
   PSFont16Enc *font16Enc;	// encodings for substitute 16-bit fonts
   int font16EncLen;		// number of entries in font16Enc array
   int font16EncSize;		// size of font16Enc array
+  Ref *imgIDs;			// list of image IDs for in-memory images
+  int imgIDLen;			// number of entries in imgIDs array
+  int imgIDSize;		// size of imgIDs array
+  Ref *formIDs;			// list of IDs for predefined forms
+  int formIDLen;		// number of entries in formIDs array
+  int formIDSize;		// size of formIDs array
   GooList *xobjStack;		// stack of XObject dicts currently being
 				//   processed
   int numSaves;			// current number of gsaves
@@ -341,6 +384,7 @@
   double t3WX, t3WY,		// Type 3 character parameters
          t3LLX, t3LLY, t3URX, t3URY;
   GBool t3Cacheable;		// cleared if char is not cacheable
+  GBool t3NeedsRestore;		// set if a 'q' operator was issued
 
 #if OPI_SUPPORT
   int opi13Nest;		// nesting level of OPI 1.3 objects

Index: PSTokenizer.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PSTokenizer.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- PSTokenizer.cc	23 Dec 2006 13:12:14 -0000	1.2
+++ PSTokenizer.cc	25 Apr 2007 19:59:10 -0000	1.3
@@ -98,7 +98,7 @@
   } else if (c == '<') {
     while ((c = lookChar()) != EOF) {
       consumeChar();
-      if (i < size) {
+      if (i < size && specialChars[c] != 1) {
 	buf[i++] = c;
       }
       if (c == '>') {

Index: Page.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Page.cc,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- Page.cc	7 Mar 2007 19:15:32 -0000	1.17
+++ Page.cc	25 Apr 2007 19:59:10 -0000	1.18
@@ -2,7 +2,7 @@
 //
 // Page.cc
 //
-// Copyright 1996-2003 Glyph & Cog, LLC
+// Copyright 1996-2007 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -30,10 +30,37 @@
 #endif
 #include "Error.h"
 #include "Page.h"
-#include "UGooString.h"
+#include "Catalog.h"
 #include "Form.h"
 
 //------------------------------------------------------------------------
+// PDFRectangle
+//------------------------------------------------------------------------
+
+void PDFRectangle::clipTo(PDFRectangle *rect) {
+  if (x1 < rect->x1) {
+    x1 = rect->x1;
+  } else if (x1 > rect->x2) {
+    x1 = rect->x2;
+  }
+  if (x2 < rect->x1) {
+    x2 = rect->x1;
+  } else if (x2 > rect->x2) {
+    x2 = rect->x2;
+  }
+  if (y1 < rect->y1) {
+    y1 = rect->y1;
+  } else if (y1 > rect->y2) {
+    y1 = rect->y2;
+  }
+  if (y2 < rect->y1) {
+    y2 = rect->y1;
+  } else if (y2 > rect->y2) {
+    y2 = rect->y2;
+  }
+}
+
+//------------------------------------------------------------------------
 // PageAttrs
 //------------------------------------------------------------------------
 
@@ -96,6 +123,12 @@
   artBox = cropBox;
   readBox(dict, "ArtBox", &artBox);
 
+  // clip all other boxes to the media box
+  cropBox.clipTo(&mediaBox);
+  bleedBox.clipTo(&mediaBox);
+  trimBox.clipTo(&mediaBox);
+  artBox.clipTo(&mediaBox);
+
   // rotate
   dict->lookup("Rotate", &obj1);
   if (obj1.isInt()) {
@@ -280,14 +313,23 @@
   contents.free();
 }
 
+Links *Page::getLinks(Catalog *catalog) {
+  Links *links;
+  Object obj;
+
+  links = new Links(getAnnots(&obj), catalog->getBaseURI());
+  obj.free();
+  return links;
+}
+
 void Page::display(OutputDev *out, double hDPI, double vDPI,
 		   int rotate, GBool useMediaBox, GBool crop,
-		   Links *links, Catalog *catalog,
+		   GBool printing, Catalog *catalog,
 		   GBool (*abortCheckCbk)(void *data),
 		   void *abortCheckCbkData,
                    GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
                    void *annotDisplayDecideCbkData) {
-  displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, -1, -1, -1, -1, links, catalog,
+  displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, -1, -1, -1, -1, printing, catalog,
 	       abortCheckCbk, abortCheckCbkData,
                annotDisplayDecideCbk, annotDisplayDecideCbkData);
 }
@@ -295,15 +337,14 @@
 Gfx *Page::createGfx(OutputDev *out, double hDPI, double vDPI,
 		     int rotate, GBool useMediaBox, GBool crop,
 		     int sliceX, int sliceY, int sliceW, int sliceH,
-		     Links *links, Catalog *catalog,
+		     GBool printing, Catalog *catalog,
 		     GBool (*abortCheckCbk)(void *data),
 		     void *abortCheckCbkData,
 		     GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
 		     void *annotDisplayDecideCbkData) {
-  PDFRectangle *mediaBox, *cropBox, *baseBox;
+  PDFRectangle *mediaBox, *cropBox;
   PDFRectangle box;
   Gfx *gfx;
-  double kx, ky;
 
   rotate += getRotate();
   if (rotate >= 360) {
@@ -312,59 +353,9 @@
     rotate += 360;
   }
 
-  mediaBox = getMediaBox();
+  makeBox(hDPI, vDPI, rotate, useMediaBox, out->upsideDown(),
+	  sliceX, sliceY, sliceW, sliceH, &box, &crop);
   cropBox = getCropBox();
-  if (sliceW >= 0 && sliceH >= 0) {
-    baseBox =  useMediaBox ? mediaBox : cropBox;
-    kx = 72.0 / hDPI;
-    ky = 72.0 / vDPI;
-    if (rotate == 90) {
-      if (out->upsideDown()) {
-	box.x1 = baseBox->x1 + ky * sliceY;
-	box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
-      } else {
-	box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
-	box.x2 = baseBox->x2 - ky * sliceY;
-      }
-      box.y1 = baseBox->y1 + kx * sliceX;
-      box.y2 = baseBox->y1 + kx * (sliceX + sliceW);
-    } else if (rotate == 180) {
-      box.x1 = baseBox->x2 - kx * (sliceX + sliceW);
-      box.x2 = baseBox->x2 - kx * sliceX;
-      if (out->upsideDown()) {
-	box.y1 = baseBox->y1 + ky * sliceY;
-	box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
-      } else {
-	box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
-	box.y2 = baseBox->y2 - ky * sliceY;
-      }
-    } else if (rotate == 270) {
-      if (out->upsideDown()) {
-	box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
-	box.x2 = baseBox->x2 - ky * sliceY;
-      } else {
-	box.x1 = baseBox->x1 + ky * sliceY;
-	box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
-      }
-      box.y1 = baseBox->y2 - kx * (sliceX + sliceW);
-      box.y2 = baseBox->y2 - kx * sliceX;
-    } else {
-      box.x1 = baseBox->x1 + kx * sliceX;
-      box.x2 = baseBox->x1 + kx * (sliceX + sliceW);
-      if (out->upsideDown()) {
-	box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
-	box.y2 = baseBox->y2 - ky * sliceY;
-      } else {
-	box.y1 = baseBox->y1 + ky * sliceY;
-	box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
-      }
-    }
-  } else if (useMediaBox) {
-    box = *mediaBox;
-  } else {
-    box = *cropBox;
-    crop = gFalse;
-  }
 
   if (globalParams->getPrintCommands()) {
     printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
@@ -384,20 +375,27 @@
 void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
 			int rotate, GBool useMediaBox, GBool crop,
 			int sliceX, int sliceY, int sliceW, int sliceH,
-			Links *links, Catalog *catalog,
+			GBool printing, Catalog *catalog,
 			GBool (*abortCheckCbk)(void *data),
 			void *abortCheckCbkData,
                         GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
                         void *annotDisplayDecideCbkData) {
   Gfx *gfx;
   Object obj;
-  Link *link;
   Annots *annotList;
+  Dict *acroForm;
   int i;
+  
+  if (!out->checkPageSlice(this, hDPI, vDPI, rotate, useMediaBox, crop,
+			   sliceX, sliceY, sliceW, sliceH,
+			   printing, catalog,
+			   abortCheckCbk, abortCheckCbkData)) {
+    return;
+  }
 
   gfx = createGfx(out, hDPI, vDPI, rotate, useMediaBox, crop,
 		  sliceX, sliceY, sliceW, sliceH,
-		  links, catalog,
+		  printing, catalog,
 		  abortCheckCbk, abortCheckCbkData,
 		  annotDisplayDecideCbk, annotDisplayDecideCbkData);
 
@@ -409,20 +407,20 @@
   }
   obj.free();
 
-  // draw links
-  if (links) {
-    gfx->saveState();
-    for (i = 0; i < links->getNumLinks(); ++i) {
-      link = links->getLink(i);
-      out->drawLink(link, catalog);
-    }
-    gfx->restoreState();
-    out->dump();
-  }
 
-  // draw non-link annotations
-  annotList = new Annots(xref, catalog, annots.fetch(xref, &obj));
+  // draw annotations
+  annotList = new Annots(xref, catalog, getAnnots(&obj));
   obj.free();
+  acroForm = catalog->getAcroForm()->isDict() ?
+               catalog->getAcroForm()->getDict() : NULL;
+  if (acroForm) {
+    if (acroForm->lookup("NeedAppearances", &obj)) {
+      if (obj.isBool() && obj.getBool()) {
+      	annotList->generateAppearances(acroForm);
+      }
+    }
+    obj.free();
+  }
   if (annotList->getNumAnnots() > 0) {
     if (globalParams->getPrintCommands()) {
       printf("***** Annotations\n");
@@ -432,7 +430,7 @@
         if ((annotDisplayDecideCbk &&
              (*annotDisplayDecideCbk)(annot, annotDisplayDecideCbkData)) || 
             !annotDisplayDecideCbk) {
-          annot->draw(gfx); 
+             annotList->getAnnot(i)->draw(gfx, printing);
     }
     }
     out->dump();
@@ -560,8 +558,81 @@
   return success;
 }
 
+void Page::makeBox(double hDPI, double vDPI, int rotate,
+		   GBool useMediaBox, GBool upsideDown,
+		   double sliceX, double sliceY, double sliceW, double sliceH,
+		   PDFRectangle *box, GBool *crop) {
+  PDFRectangle *mediaBox, *cropBox, *baseBox;
+  double kx, ky;
+
+  mediaBox = getMediaBox();
+  cropBox = getCropBox();
+  if (sliceW >= 0 && sliceH >= 0) {
+    baseBox = useMediaBox ? mediaBox : cropBox;
+    kx = 72.0 / hDPI;
+    ky = 72.0 / vDPI;
+    if (rotate == 90) {
+      if (upsideDown) {
+	box->x1 = baseBox->x1 + ky * sliceY;
+	box->x2 = baseBox->x1 + ky * (sliceY + sliceH);
+      } else {
+	box->x1 = baseBox->x2 - ky * (sliceY + sliceH);
+	box->x2 = baseBox->x2 - ky * sliceY;
+      }
+      box->y1 = baseBox->y1 + kx * sliceX;
+      box->y2 = baseBox->y1 + kx * (sliceX + sliceW);
+    } else if (rotate == 180) {
+      box->x1 = baseBox->x2 - kx * (sliceX + sliceW);
+      box->x2 = baseBox->x2 - kx * sliceX;
+      if (upsideDown) {
+	box->y1 = baseBox->y1 + ky * sliceY;
+	box->y2 = baseBox->y1 + ky * (sliceY + sliceH);
+      } else {
+	box->y1 = baseBox->y2 - ky * (sliceY + sliceH);
+	box->y2 = baseBox->y2 - ky * sliceY;
+      }
+    } else if (rotate == 270) {
+      if (upsideDown) {
+	box->x1 = baseBox->x2 - ky * (sliceY + sliceH);
+	box->x2 = baseBox->x2 - ky * sliceY;
+      } else {
+	box->x1 = baseBox->x1 + ky * sliceY;
+	box->x2 = baseBox->x1 + ky * (sliceY + sliceH);
+      }
+      box->y1 = baseBox->y2 - kx * (sliceX + sliceW);
+      box->y2 = baseBox->y2 - kx * sliceX;
+    } else {
+      box->x1 = baseBox->x1 + kx * sliceX;
+      box->x2 = baseBox->x1 + kx * (sliceX + sliceW);
+      if (upsideDown) {
+	box->y1 = baseBox->y2 - ky * (sliceY + sliceH);
+	box->y2 = baseBox->y2 - ky * sliceY;
+      } else {
+	box->y1 = baseBox->y1 + ky * sliceY;
+	box->y2 = baseBox->y1 + ky * (sliceY + sliceH);
+      }
+    }
+  } else if (useMediaBox) {
+    *box = *mediaBox;
+  } else {
+    *box = *cropBox;
+    *crop = gFalse;
+  }
+}
+
+void Page::processLinks(OutputDev *out, Catalog *catalog) {
+  Links *links;
+  int i;
+
+  links = getLinks(catalog);
+  for (i = 0; i < links->getNumLinks(); ++i) {
+    out->processLink(links->getLink(i), catalog);
+  }
+  delete links;
+}
+
 void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI,
-			 int rotate, GBool upsideDown) {
+			 int rotate, GBool useMediaBox, GBool upsideDown) {
   GfxState *state;
   int i;
   rotate += getRotate();
@@ -570,7 +641,9 @@
   } else if (rotate < 0) {
     rotate += 360;
   }
-  state = new GfxState(hDPI, vDPI, getMediaBox(), rotate, upsideDown);
+  state = new GfxState(hDPI, vDPI,
+		       useMediaBox ? getMediaBox() : getCropBox(),
+		       rotate, upsideDown);
   for (i = 0; i < 6; ++i) {
     ctm[i] = state->getCTM()[i];
   }

Index: Page.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Page.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- Page.h	24 Feb 2007 23:32:23 -0000	1.8
+++ Page.h	25 Apr 2007 19:59:10 -0000	1.9
@@ -36,6 +36,7 @@
   PDFRectangle(double x1A, double y1A, double x2A, double y2A)
     { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; }
   GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
+  void clipTo(PDFRectangle *rect);
 };
 
 //------------------------------------------------------------------------
@@ -115,6 +116,7 @@
   GBool isOk() { return ok; }
 
   // Get page parameters.
+  int getNum() { return num; }
   PDFRectangle *getMediaBox() { return attrs->getMediaBox(); }
   PDFRectangle *getCropBox() { return attrs->getCropBox(); }
   GBool isCropped() { return attrs->isCropped(); }
@@ -143,6 +145,9 @@
   // Get annotations array.
   Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
 
+  // Return a list of links.
+  Links *getLinks(Catalog *catalog);
+
   // Get contents.
   Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
 
@@ -167,7 +172,7 @@
   Gfx *createGfx(OutputDev *out, double hDPI, double vDPI,
 		 int rotate, GBool useMediaBox, GBool crop,
 		 int sliceX, int sliceY, int sliceW, int sliceH,
-		 Links *links, Catalog *catalog,
+		 GBool printing, Catalog *catalog,
 		 GBool (*abortCheckCbk)(void *data),
 		 void *abortCheckCbkData,
 		 GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
@@ -176,7 +181,7 @@
   // Display a page.
   void display(OutputDev *out, double hDPI, double vDPI,
 	       int rotate, GBool useMediaBox, GBool crop,
-	       Links *links, Catalog *catalog,
+	       GBool printing, Catalog *catalog,
 	       GBool (*abortCheckCbk)(void *data) = NULL,
 	       void *abortCheckCbkData = NULL,
                GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
@@ -186,17 +191,24 @@
   void displaySlice(OutputDev *out, double hDPI, double vDPI,
 		    int rotate, GBool useMediaBox, GBool crop,
 		    int sliceX, int sliceY, int sliceW, int sliceH,
-		    Links *links, Catalog *catalog,
+		    GBool printing, Catalog *catalog,
 		    GBool (*abortCheckCbk)(void *data) = NULL,
 		    void *abortCheckCbkData = NULL,
                     GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
                     void *annotDisplayDecideCbkData = NULL);
 
   void display(Gfx *gfx);
-  
+
+  void makeBox(double hDPI, double vDPI, int rotate,
+	       GBool useMediaBox, GBool upsideDown,
+	       double sliceX, double sliceY, double sliceW, double sliceH,
+	       PDFRectangle *box, GBool *crop);
+
+  void processLinks(OutputDev *out, Catalog *catalog);
+
   // Get the page's default CTM.
   void getDefaultCTM(double *ctm, double hDPI, double vDPI,
-		     int rotate, GBool upsideDown);
+		     int rotate, GBool useMediaBox, GBool upsideDown);
 
 private:
 

Index: PageLabelInfo.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/PageLabelInfo.cc,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- PageLabelInfo.cc	28 Dec 2006 15:51:44 -0000	1.7
+++ PageLabelInfo.cc	25 Apr 2007 19:59:10 -0000	1.8
@@ -3,7 +3,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <assert.h>
-#include "UGooString.h"
 
 #include "PageLabelInfo.h"
 

Index: Parser.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Parser.cc,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- Parser.cc	28 Dec 2006 15:51:44 -0000	1.7
+++ Parser.cc	25 Apr 2007 19:59:10 -0000	1.8
@@ -16,16 +16,16 @@
 #include "Object.h"
 #include "Array.h"
 #include "Dict.h"
+#include "Decrypt.h"
 #include "Parser.h"
 #include "XRef.h"
 #include "Error.h"
-#include "Decrypt.h"
-#include "UGooString.h"
 
-Parser::Parser(XRef *xrefA, Lexer *lexerA) {
+Parser::Parser(XRef *xrefA, Lexer *lexerA, GBool allowStreamsA) {
   xref = xrefA;
   lexer = lexerA;
   inlineImg = 0;
+  allowStreams = allowStreamsA;
   lexer->getObj(&buf1);
   lexer->getObj(&buf2);
 }
@@ -36,17 +36,16 @@
   delete lexer;
 }
 
-Object *Parser::getObj(Object *obj,
-		       Guchar *fileKey, int keyLength,
+Object *Parser::getObj(Object *obj, Guchar *fileKey,
+		       CryptAlgorithm encAlgorithm, int keyLength,
 		       int objNum, int objGen) {
-  UGooString key;
+  char *key;
   Stream *str;
   Object obj2;
   int num;
-  Decrypt *decrypt;
-  GooString *s;
-  char *p;
-  int i;
+  DecryptStream *decrypt;
+  GooString *s, *s2;
+  int c;
 
   // refill buffer after inline image data
   if (inlineImg == 2) {
@@ -62,7 +61,8 @@
     shift();
     obj->initArray(xref);
     while (!buf1.isCmd("]") && !buf1.isEOF())
-      obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
+      obj->arrayAdd(getObj(&obj2, fileKey, encAlgorithm, keyLength,
+			   objNum, objGen));
     if (buf1.isEOF())
       error(getPos(), "End of file inside array");
     shift();
@@ -77,23 +77,23 @@
 	shift();
       } else {
 	// buf1 might go away in shift(), so construct the key
-	key.Set(buf1.getName());
+	key = copyString(buf1.getName());
 	shift();
 	if (buf1.isEOF() || buf1.isError()) {
+	  gfree(key);
 	  break;
 	}
-	obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
+	obj->dictAdd(key, getObj(&obj2, fileKey, encAlgorithm, keyLength, objNum, objGen));
       }
     }
     if (buf1.isEOF())
       error(getPos(), "End of file inside dictionary");
-    if (buf2.isCmd("stream")) {
-      if ((str = makeStream(obj))) {
+    // stream objects are not allowed inside content streams or
+    // object streams
+    if (allowStreams && buf2.isCmd("stream")) {
+      if ((str = makeStream(obj, fileKey, encAlgorithm, keyLength,
+			    objNum, objGen))) {
 	obj->initStream(str);
-	if (fileKey) {
-	  str->getBaseStream()->doDecryption(fileKey, keyLength,
-					     objNum, objGen);
-	}
       } else {
 	obj->free();
 	obj->initError();
@@ -116,15 +116,19 @@
 
   // string
   } else if (buf1.isString() && fileKey) {
-    buf1.copy(obj);
-    s = obj->getString();
-    decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
-    for (i = 0, p = obj->getString()->getCString();
-      i < s->getLength();
-      ++i, ++p) {
-      *p = decrypt->decryptByte(*p);
+    s = buf1.getString();
+    s2 = new GooString();
+    obj2.initNull();
+    decrypt = new DecryptStream(new MemStream(s->getCString(), 0,
+					      s->getLength(), &obj2),
+				fileKey, encAlgorithm, keyLength,
+				objNum, objGen);
+    decrypt->reset();
+    while ((c = decrypt->getChar()) != EOF) {
+      s2->append((char)c);
     }
     delete decrypt;
+    obj->initString(s2);
     shift();
 
   // simple object
@@ -140,7 +144,9 @@
   return obj;
 }
 
-Stream *Parser::makeStream(Object *dict) {
+Stream *Parser::makeStream(Object *dict, Guchar *fileKey,
+			   CryptAlgorithm encAlgorithm, int keyLength,
+			   int objNum, int objGen) {
   Object obj;
   BaseStream *baseStr;
   Stream *str;
@@ -196,6 +202,12 @@
   // make base stream
   str = baseStr->makeSubStream(pos, gTrue, length, dict);
 
+  // handle decryption
+  if (fileKey) {
+    str = new DecryptStream(str, fileKey, encAlgorithm, keyLength,
+			    objNum, objGen);
+  }
+
   // get filters
   str = str->addFilters(dict);
 

Index: Parser.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Parser.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Parser.h	17 Jan 2006 21:35:31 -0000	1.3
+++ Parser.h	25 Apr 2007 19:59:10 -0000	1.4
@@ -23,14 +23,14 @@
 public:
 
   // Constructor.
-  Parser(XRef *xrefA, Lexer *lexerA);
+  Parser(XRef *xrefA, Lexer *lexerA, GBool allowStreamsA);
 
   // Destructor.
   ~Parser();
 
   // Get the next object from the input stream.
-  Object *getObj(Object *obj,
-		 Guchar *fileKey = NULL, int keyLength = 0,
+  Object *getObj(Object *obj, Guchar *fileKey = NULL,
+		 CryptAlgorithm encAlgorithm = cryptRC4, int keyLength = 0,
 		 int objNum = 0, int objGen = 0);
 
   // Get stream.
@@ -43,10 +43,13 @@
 
   XRef *xref;			// the xref table for this PDF file
   Lexer *lexer;			// input stream
+  GBool allowStreams;		// parse stream objects?
   Object buf1, buf2;		// next two tokens
   int inlineImg;		// set when inline image data is encountered
 
-  Stream *makeStream(Object *dict);
+  Stream *makeStream(Object *dict, Guchar *fileKey,
+		     CryptAlgorithm encAlgorithm, int keyLength,
+		     int objNum, int objGen);
   void shift(int objNum = -1);
 };
 



Index: SecurityHandler.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/SecurityHandler.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SecurityHandler.cc	18 Jan 2006 22:32:13 -0000	1.2
+++ SecurityHandler.cc	25 Apr 2007 19:59:10 -0000	1.3
@@ -26,7 +26,6 @@
 #  include "XpdfPluginAPI.h"
 #endif
 #include "SecurityHandler.h"
-#include "UGooString.h"
 
 //------------------------------------------------------------------------
 // SecurityHandler
@@ -35,7 +34,9 @@
 SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) {
   Object filterObj;
   SecurityHandler *secHdlr;
+#ifdef ENABLE_PLUGINS
   XpdfSecurityHandler *xsh;
+#endif
 
   encryptDictA->dictLookup("Filter", &filterObj);
   if (filterObj.isName("Standard")) {
@@ -152,6 +153,7 @@
       permObj.isInt()) {
     encVersion = versionObj.getInt();
     encRevision = revisionObj.getInt();
+    encAlgorithm = cryptRC4;
     // revision 2 forces a 40-bit key - some buggy PDF generators
     // set the Length value incorrectly
     if (encRevision == 2 || !lengthObj.isInt()) {
@@ -171,7 +173,8 @@
 	  !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) {
 	if (cryptFiltersObj.dictLookup(streamFilterObj.getName(),
 				       &cryptFilterObj)->isDict()) {
-	  if (cryptFilterObj.dictLookup("CFM", &cfmObj)->isName("V2")) {
+	  cryptFilterObj.dictLookup("CFM", &cfmObj);
+	  if (cfmObj.isName("V2")) {
 	    encVersion = 2;
 	    encRevision = 3;
 	    if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
@@ -179,6 +182,15 @@
 	      fileKeyLength = cfLengthObj.getInt();
 	    }
 	    cfLengthObj.free();
+	  } else if (cfmObj.isName("AESV2")) {
+	    encVersion = 2;
+	    encRevision = 3;
+	    encAlgorithm = cryptAES;
+	    if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
+	      //~ according to the spec, this should be cfLengthObj / 8
+	      fileKeyLength = cfLengthObj.getInt();
+	    }
+	    cfLengthObj.free();
 	  }
 	  cfmObj.free();
 	}
@@ -311,6 +323,7 @@
 {
   encryptDictA->copy(&encryptDict);
   xsh = xshA;
+  encAlgorithm = cryptRC4; //~ this should be obtained via getKey
   ok = gFalse;
 
   if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA,

Index: SecurityHandler.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/SecurityHandler.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- SecurityHandler.h	16 Sep 2005 18:29:18 -0000	1.1
+++ SecurityHandler.h	25 Apr 2007 19:59:10 -0000	1.2
@@ -75,6 +75,7 @@
   virtual int getFileKeyLength() = 0;
   virtual int getEncVersion() = 0;
   virtual int getEncRevision() = 0;
+  virtual CryptAlgorithm getEncAlgorithm() = 0;
 
 protected:
 
@@ -102,6 +103,7 @@
   virtual int getFileKeyLength() { return fileKeyLength; }
   virtual int getEncVersion() { return encVersion; }
   virtual int getEncRevision() { return encRevision; }
+  virtual CryptAlgorithm getEncAlgorithm() { return encAlgorithm; }
 
 private:
 
@@ -112,6 +114,7 @@
   int encVersion;
   int encRevision;
   GBool encryptMetadata;
+  CryptAlgorithm encAlgorithm;
 
   GooString *ownerKey, *userKey;
   GooString *fileID;
@@ -140,6 +143,7 @@
   virtual Guchar *getFileKey() { return fileKey; }
   virtual int getFileKeyLength() { return fileKeyLength; }
   virtual int getEncVersion() { return encVersion; }
+  virtual CryptAlgorithm getEncAlgorithm() { return encAlgorithm; }
 
 private:
 
@@ -150,6 +154,7 @@
   Guchar fileKey[16];
   int fileKeyLength;
   int encVersion;
+  CryptAlgorithm encAlgorithm;
   GBool ok;
 };
 #endif // ENABLE_PLUGINS

Index: SplashOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/SplashOutputDev.cc,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- SplashOutputDev.cc	19 Dec 2006 20:27:55 -0000	1.12
+++ SplashOutputDev.cc	25 Apr 2007 19:59:10 -0000	1.13
@@ -37,6 +37,19 @@
 #include "splash/Splash.h"
 #include "SplashOutputDev.h"
 
+#ifdef VMS
+#if (__VMS_VER < 70000000)
+extern "C" int unlink(char *filename);
+#endif
+#endif
+
+//------------------------------------------------------------------------
+
[...2325 lines suppressed...]
   ret = bitmap;
-  bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode, bitmapTopDown);
+  bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode,
+			    colorMode != splashModeMono1, bitmapTopDown);
   return ret;
 }
 
@@ -2508,3 +2699,12 @@
 #endif
 }
 
+#if 1 //~tmp: turn off anti-aliasing temporarily
+GBool SplashOutputDev::getVectorAntialias() {
+  return splash->getVectorAntialias();
+}
+
+void SplashOutputDev::setVectorAntialias(GBool vaa) {
+  splash->setVectorAntialias(vaa);
+}
+#endif

Index: SplashOutputDev.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/SplashOutputDev.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- SplashOutputDev.h	30 Oct 2005 20:29:05 -0000	1.4
+++ SplashOutputDev.h	25 Apr 2007 19:59:10 -0000	1.5
@@ -29,6 +29,7 @@
 class T3FontCache;
 struct T3FontCacheTag;
 struct T3GlyphStack;
+struct SplashTransparencyGroup;
 
 //------------------------------------------------------------------------
 
@@ -72,9 +73,6 @@
   // End a page.
   virtual void endPage();
 
-  //----- link borders
-  virtual void drawLink(Link *link, Catalog *catalog);
-
   //----- save/restore graphics state
   virtual void saveState(GfxState *state);
   virtual void restoreState(GfxState *state);
@@ -89,6 +87,7 @@
   virtual void updateLineCap(GfxState *state);
   virtual void updateMiterLimit(GfxState *state);
   virtual void updateLineWidth(GfxState *state);
+  virtual void updateStrokeAdjust(GfxState *state);
   virtual void updateFillColor(GfxState *state);
   virtual void updateStrokeColor(GfxState *state);
   virtual void updateBlendMode(GfxState *state);
@@ -106,6 +105,7 @@
   //----- path clipping
   virtual void clip(GfxState *state);
   virtual void eoClip(GfxState *state);
+  virtual void clipToStrokePath(GfxState *state);
 
   //----- text drawing
   virtual void drawChar(GfxState *state, double x, double y,
@@ -142,6 +142,17 @@
   virtual void type3D1(GfxState *state, double wx, double wy,
 		       double llx, double lly, double urx, double ury);
 
+  //----- transparency groups and soft masks
+  virtual void beginTransparencyGroup(GfxState *state, double *bbox,
+				      GfxColorSpace *blendingColorSpace,
+				      GBool isolated, GBool knockout,
+				      GBool forSoftMask);
+  virtual void endTransparencyGroup(GfxState *state);
+  virtual void paintTransparencyGroup(GfxState *state, double *bbox);
+  virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha,
+			   Function *transferFunc, GfxColor *backdropColor);
+  virtual void clearSoftMask(GfxState *state);
+
   //----- special access
 
   // Called to indicate that a new PDF document has been loaded.
@@ -175,28 +186,39 @@
 
   SplashFont *getCurrentFont() { return font; }
 
+#if 1 //~tmp: turn off anti-aliasing temporarily
+  virtual GBool getVectorAntialias();
+  virtual void setVectorAntialias(GBool vaa);
+#endif
+
 private:
 
+  void setupScreenParams(double hDPI, double vDPI);
 #if SPLASH_CMYK
   SplashPattern *getColor(GfxGray gray, GfxRGB *rgb, GfxCMYK *cmyk);
 #else
   SplashPattern *getColor(GfxGray gray, GfxRGB *rgb);
 #endif
   SplashPath *convertPath(GfxState *state, GfxPath *path);
+  void doUpdateFont(GfxState *state);
   void drawType3Glyph(T3FontCache *t3Font,
-		      T3FontCacheTag *tag, Guchar *data,
-		      double x, double y);
+		      T3FontCacheTag *tag, Guchar *data);
   static GBool imageMaskSrc(void *data, SplashColorPtr line);
-  static GBool imageSrc(void *data, SplashColorPtr line);
-  static GBool alphaImageSrc(void *data, SplashColorPtr line);
-  static GBool maskedImageSrc(void *data, SplashColorPtr line);
+  static GBool imageSrc(void *data, SplashColorPtr colorLine,
+			Guchar *alphaLine);
+  static GBool alphaImageSrc(void *data, SplashColorPtr line,
+			     Guchar *alphaLine);
+  static GBool maskedImageSrc(void *data, SplashColorPtr line,
+			      Guchar *alphaLine);
 
   SplashColorMode colorMode;
   int bitmapRowPad;
   GBool bitmapTopDown;
   GBool allowAntialias;
+  GBool vectorAntialias;
   GBool reverseVideo;		// reverse video mode
   SplashColor paperColor;	// paper color
+  SplashScreenParams screenParams;
 
   XRef *xref;			// xref table for current document
 
@@ -212,6 +234,9 @@
   SplashFont *font;		// current font
   GBool needFontUpdate;		// set when the font needs to be updated
   SplashPath *textClipPath;	// clipping path built with text object
+
+  SplashTransparencyGroup *	// transparency group stack
+    transpGroupStack;
 };
 
 #endif

Index: Stream.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Stream.cc,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- Stream.cc	13 Jan 2007 23:19:21 -0000	1.15
+++ Stream.cc	25 Apr 2007 19:59:10 -0000	1.16
@@ -27,13 +27,11 @@
 #include "Error.h"
 #include "Object.h"
 #include "Lexer.h"
-#include "Decrypt.h"
 #include "GfxState.h"
 #include "Stream.h"
 #include "JBIG2Stream.h"
 #include "JPXStream.h"
 #include "Stream-CCITT.h"
-#include "UGooString.h"
 
 #ifdef ENABLE_LIBJPEG
 #include "DCTStream.h"
@@ -151,6 +149,7 @@
   int encoding;
   GBool endOfLine, byteAlign, endOfBlock, black;
   int columns, rows;
+  int colorXform;
   Object globals, obj;
 
   if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
@@ -236,7 +235,14 @@
     str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
 			     columns, rows, endOfBlock, black);
   } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
-    str = new DCTStream(str);
+    colorXform = -1;
+    if (params->isDict()) {
+      if (params->dictLookup("ColorTransform", &obj)->isInt()) {
+	colorXform = obj.getInt();
+      }
+      obj.free();
+    }
+    str = new DCTStream(str, colorXform);
   } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
     pred = 1;
     columns = 1;
@@ -282,18 +288,10 @@
 
 BaseStream::BaseStream(Object *dictA) {
   dict = *dictA;
-  decrypt = NULL;
 }
 
 BaseStream::~BaseStream() {
   dict.free();
-  if (decrypt)
-    delete decrypt;
-}
-
-void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
-			      int objNum, int objGen) {
-  decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
 }
 
 //------------------------------------------------------------------------
@@ -411,8 +409,6 @@
 
 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
 				 int widthA, int nCompsA, int nBitsA) {
-  int totalBits;
-
   str = strA;
   predictor = predictorA;
   width = widthA;
@@ -428,15 +424,9 @@
       nVals * nBits + 7 < 0) {
     return;
   }
-  totalBits = nVals * nBits;
-  if (totalBits == 0 ||
-      (totalBits / nBits) / nComps != width ||
-      totalBits + 7 < 0) {
-    return;
-  }
   pixBytes = (nComps * nBits + 7) >> 3;
-  rowBytes = ((totalBits + 7) >> 3) + pixBytes;
-  if (rowBytes < 0) {
+  rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
+  if (rowBytes <= 0) {
     return;
   }
   predLine = (Guchar *)gmalloc(rowBytes);
@@ -560,17 +550,17 @@
       j = k = pixBytes;
       for (i = 0; i < width; ++i) {
 	for (kk = 0; kk < nComps; ++kk) {
-	if (inBits < nBits) {
-	  inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
-	  inBits += 8;
-	}
-	  upLeftBuf[kk] = (upLeftBuf[kk] +
-			(inBuf >> (inBits - nBits))) & bitMask;
-	inBits -= nBits;
+	  if (inBits < nBits) {
+	    inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
+	    inBits += 8;
+	  }
+	  upLeftBuf[kk] = (Guchar)((upLeftBuf[kk] +
+				    (inBuf >> (inBits - nBits))) & bitMask);
+	  inBits -= nBits;
 	  outBuf = (outBuf << nBits) | upLeftBuf[kk];
-	outBits += nBits;
+	  outBits += nBits;
 	  if (outBits >= 8) {
-	  predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
+	    predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
 	    outBits -= 8;
 	  }
 	}
@@ -628,8 +618,6 @@
   saved = gTrue;
   bufPtr = bufEnd = buf;
   bufPos = start;
-  if (decrypt)
-    decrypt->reset();
 }
 
 void FileStream::close() {
@@ -647,7 +635,6 @@
 
 GBool FileStream::fillBuf() {
   int n;
-  char *p;
 
   bufPos += bufEnd - buf;
   bufPtr = bufEnd = buf;
@@ -664,11 +651,6 @@
   if (bufPtr >= bufEnd) {
     return gFalse;
   }
-  if (decrypt) {
-    for (p = buf; p < bufEnd; ++p) {
-      *p = (char)decrypt->decryptByte((Guchar)*p);
-    }
-  }
   return gTrue;
 }
 
@@ -757,9 +739,6 @@
 
 void MemStream::reset() {
   bufPtr = buf + start;
-  if (decrypt) {
-    decrypt->reset();
-  }
 }
 
 void MemStream::close() {
@@ -787,25 +766,6 @@
   bufPtr = buf + start;
 }
 
-void MemStream::doDecryption(Guchar *fileKey, int keyLength,
-			     int objNum, int objGen) {
-  char *newBuf;
-  char *p, *q;
-
-  this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
-  if (decrypt) {
-    newBuf = (char *)gmalloc(length);
-    for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
-      *q = (char)decrypt->decryptByte((Guchar)*p);
-    }
-    bufEnd = newBuf + length;
-    bufPtr = newBuf + (bufPtr - (buf + start));
-    start = 0;
-    buf = newBuf;
-    needFree = gTrue;
-  }
-}
-
 //------------------------------------------------------------------------
 // EmbedStream
 //------------------------------------------------------------------------
@@ -1291,14 +1251,17 @@
   endOfLine = endOfLineA;
   byteAlign = byteAlignA;
   columns = columnsA;
-  if (columns + 3 < 1 || columns + 4 < 1 || columns < 1) {
+  if (columns < 1) {
     columns = 1;
   }
+  if (columns + 4 <= 0) {
+    columns = INT_MAX - 4;
+  }
   rows = rowsA;
   endOfBlock = endOfBlockA;
   black = blackA;
-  refLine = (short *)gmallocn(columns + 4, sizeof(short));
-  codingLine = (short *)gmallocn(columns + 3, sizeof(short));
+  refLine = (short *)gmallocn(columns + 3, sizeof(short));
+  codingLine = (short *)gmallocn(columns + 2, sizeof(short));
 
   eof = gFalse;
   row = 0;
@@ -1326,7 +1289,7 @@
   nextLine2D = encoding < 0;
   inputBits = 0;
   codingLine[0] = 0;
-  codingLine[1] = refLine[2] = columns;
+  codingLine[1] = columns;
   a0 = 1;
   buf = EOF;
 
@@ -1362,8 +1325,27 @@
 
     // 2-D encoding
     if (nextLine2D) {
-      for (i = 0; codingLine[i] < columns; ++i)
+      // state:
+      //   a0New = current position in coding line (0 <= a0New <= columns)
+      //   codingLine[a0] = last change in coding line
+      //                    (black-to-white if a0 is even,
+      //                     white-to-black if a0 is odd)
+      //   refLine[b1] = next change in reference line of opposite color
+      //                 to a0
+      // invariants:
+      //   0 <= codingLine[a0] <= a0New
+      //           <= refLine[b1] <= refLine[b1+1] <= columns
+      //   0 <= a0 <= columns+1
+      //   refLine[0] = 0
+      //   refLine[n] = refLine[n+1] = columns
+      //     -- for some 1 <= n <= columns+1
+      // end condition:
+      //   0 = codingLine[0] <= codingLine[1] < codingLine[2] < ...
+      //     < codingLine[n-1] < codingLine[n] = columns
+      //     -- where 1 <= n <= columns+1
+      for (i = 0; codingLine[i] < columns; ++i) {
 	refLine[i] = codingLine[i];
+      }
       refLine[i] = refLine[i + 1] = columns;
       b1 = 1;
       a0New = codingLine[a0 = 0] = 0;
@@ -1395,68 +1377,93 @@
 	    } while (code3 >= 64);
 	  }
 	  if (code1 > 0 || code2 > 0) {
-	    codingLine[a0 + 1] = a0New + code1;
+	    if (a0New + code1 <= columns) {
+	      codingLine[a0 + 1] = a0New + code1;
+	    } else {
+	      codingLine[a0 + 1] = columns;
+	    }
 	    ++a0;
-	    a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
+	    if (codingLine[a0] + code2 <= columns) {
+	      codingLine[a0 + 1] = codingLine[a0] + code2;
+	    } else {
+	      codingLine[a0 + 1] = columns;
+	    }
 	    ++a0;
-	    while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+	    a0New = codingLine[a0];
+	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
 	      b1 += 2;
+	    }
 	  }
 	  break;
 	case twoDimVert0:
-	  a0New = codingLine[++a0] = refLine[b1];
 	  if (refLine[b1] < columns) {
+	    a0New = codingLine[++a0] = refLine[b1];
 	    ++b1;
-	    while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
 	      b1 += 2;
+	    }
+	  } else {
+	    a0New = codingLine[++a0] = columns;
 	  }
 	  break;
 	case twoDimVertR1:
-	  a0New = codingLine[++a0] = refLine[b1] + 1;
-	  if (refLine[b1] < columns) {
+	  if (refLine[b1] + 1 < columns) {
+	    a0New = codingLine[++a0] = refLine[b1] + 1;
 	    ++b1;
-	    while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
 	      b1 += 2;
+	    }
+	  } else {
+	    a0New = codingLine[++a0] = columns;
 	  }
 	  break;
 	case twoDimVertL1:
-	  if (a0 == 0 || refLine[b1] - 1 > a0New) {
-	  a0New = codingLine[++a0] = refLine[b1] - 1;
-	  --b1;
-	  while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-	    b1 += 2;
+	  if (refLine[b1] - 1 > a0New || (a0 == 0 && refLine[b1] == 1)) {
+	    a0New = codingLine[++a0] = refLine[b1] - 1;
+	    --b1;
+	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
+	      b1 += 2;
+	    }
 	  }
 	  break;
 	case twoDimVertR2:
-	  a0New = codingLine[++a0] = refLine[b1] + 2;
-	  if (refLine[b1] < columns) {
+	  if (refLine[b1] + 2 < columns) {
+	    a0New = codingLine[++a0] = refLine[b1] + 2;
 	    ++b1;
-	    while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
 	      b1 += 2;
+	    }
+	  } else {
+	    a0New = codingLine[++a0] = columns;
 	  }
 	  break;
 	case twoDimVertL2:
-	  if (a0 == 0 || refLine[b1] - 2 > a0New) {
-	  a0New = codingLine[++a0] = refLine[b1] - 2;
-	  --b1;
-	  while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-	    b1 += 2;
+	  if (refLine[b1] - 2 > a0New || (a0 == 0 && refLine[b1] == 2)) {
+	    a0New = codingLine[++a0] = refLine[b1] - 2;
+	    --b1;
+	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
+	      b1 += 2;
+	    }
 	  }
 	  break;
 	case twoDimVertR3:
-	  a0New = codingLine[++a0] = refLine[b1] + 3;
-	  if (refLine[b1] < columns) {
+	  if (refLine[b1] + 3 < columns) {
+	    a0New = codingLine[++a0] = refLine[b1] + 3;
 	    ++b1;
-	    while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
 	      b1 += 2;
+	    }
+	  } else {
+	    a0New = codingLine[++a0] = columns;
 	  }
 	  break;
 	case twoDimVertL3:
-	  if (a0 == 0 || refLine[b1] - 3 > a0New) {
-	  a0New = codingLine[++a0] = refLine[b1] - 3;
-	  --b1;
-	  while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
-	    b1 += 2;
+	  if (refLine[b1] - 3 > a0New || (a0 == 0 && refLine[b1] == 3)) {
+	    a0New = codingLine[++a0] = refLine[b1] - 3;
+	    --b1;
+	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
+	      b1 += 2;
+	    }
 	  }
 	  break;
 	case EOF:
@@ -1480,16 +1487,18 @@
 	} while (code3 >= 64);
 	codingLine[a0+1] = codingLine[a0] + code1;
 	++a0;
-	if (codingLine[a0] >= columns)
+	if (codingLine[a0] >= columns) {
 	  break;
+	}
 	code2 = 0;
 	do {
 	  code2 += code3 = getBlackCode();
 	} while (code3 >= 64);
 	codingLine[a0+1] = codingLine[a0] + code2;
 	++a0;
-	if (codingLine[a0] >= columns)
+	if (codingLine[a0] >= columns) {
 	  break;
+	}
       }
     }
 
@@ -1826,6 +1835,7 @@
   return str->isBinary(gTrue);
 }
 
+#warning LIBJPEG DCTSTream is broken, fix it
 #ifndef ENABLE_LIBJPEG
 
 //------------------------------------------------------------------------
@@ -1872,10 +1882,11 @@
   63
 };
 
-DCTStream::DCTStream(Stream *strA):
+DCTStream::DCTStream(Stream *strA, GBool colorXformA):
     FilterStream(strA) {
   int i, j;
 
+  colorXform = colorXformA;
   progressive = interleaved = gFalse;
   width = height = 0;
   mcuWidth = mcuHeight = 0;
@@ -1901,20 +1912,8 @@
 }
 
 DCTStream::~DCTStream() {
-  int i, j;
-
+  close();
   delete str;
-  if (progressive || !interleaved) {
-    for (i = 0; i < numComps; ++i) {
-      gfree(frameBuf[i]);
-    }
-  } else {
-    for (i = 0; i < numComps; ++i) {
-      for (j = 0; j < mcuHeight; ++j) {
-	gfree(rowBuf[i][j]);
-      }
-    }
-  }
 }
 
 void DCTStream::reset() {
@@ -1928,7 +1927,6 @@
   numQuantTables = 0;
   numDCHuffTables = 0;
   numACHuffTables = 0;
-  colorXform = 0;
   gotJFIFMarker = gFalse;
   gotAdobeMarker = gFalse;
   restartInterval = 0;
@@ -1950,20 +1948,24 @@
     }
     if (compInfo[i].vSample > mcuHeight) {
       mcuHeight = compInfo[i].vSample;
-  }
+    }
   }
   mcuWidth *= 8;
   mcuHeight *= 8;
 
   // figure out color transform
-  if (!gotAdobeMarker && numComps == 3) {
-    if (gotJFIFMarker) {
-      colorXform = 1;
-    } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
-	       compInfo[2].id == 66) { // ASCII "RGB"
-      colorXform = 0;
+  if (colorXform == -1) {
+    if (numComps == 3) {
+      if (gotJFIFMarker) {
+	colorXform = 1;
+      } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
+		 compInfo[2].id == 66) { // ASCII "RGB"
+	colorXform = 0;
+      } else {
+	colorXform = 1;
+      }
     } else {
-      colorXform = 1;
+      colorXform = 0;
     }
   }
 
@@ -2013,6 +2015,20 @@
   }
 }
 
+void DCTStream::close() {
+  int i, j;
+
+  for (i = 0; i < 4; ++i) {
+    for (j = 0; j < 32; ++j) {
+      gfree(rowBuf[i][j]);
+      rowBuf[i][j] = NULL;
+    }
+    gfree(frameBuf[i]);
+    frameBuf[i] = NULL;
+  }
+  FilterStream::close();
+}
+
 int DCTStream::getChar() {
   int c;
 
@@ -2937,8 +2953,8 @@
   width = read16();
   numComps = str->getChar();
   if (numComps <= 0 || numComps > 4) {
-    numComps = 0;
     error(getPos(), "Bad number of components in DCT stream");
+    numComps = 0;
     return gFalse;
   }
   if (prec != 8) {
@@ -2990,8 +3006,8 @@
   length = read16() - 2;
   scanInfo.numComps = str->getChar();
   if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
-    scanInfo.numComps = 0;
     error(getPos(), "Bad number of components in DCT stream");
+    scanInfo.numComps = 0;
     return gFalse;
   }
   --length;
@@ -3053,14 +3069,14 @@
       if (prec) {
 	quantTables[index][dctZigZag[i]] = read16();
       } else {
-      quantTables[index][dctZigZag[i]] = str->getChar();
+	quantTables[index][dctZigZag[i]] = str->getChar();
       }
     }
     if (prec) {
       length -= 129;
     } else {
-    length -= 65;
-  }
+      length -= 65;
+    }
   }
   return gTrue;
 }
@@ -3078,12 +3094,12 @@
   while (length > 0) {
     index = str->getChar();
     --length;
-    if ((index & ~0x10) >= 4 || (index & ~0x10) < 0) {
+    if ((index & 0x0f) >= 4) {
       error(getPos(), "Bad DCT Huffman table");
       return gFalse;
     }
     if (index & 0x10) {
-      index &= 0x03;
+      index &= 0x0f;
       if (index >= numACHuffTables)
 	numACHuffTables = index+1;
       tbl = &acHuffTables[index];
@@ -3887,14 +3903,15 @@
   }
   litCodeTab.codes = NULL;
   distCodeTab.codes = NULL;
+  memset(buf, 0, flateWindow);
 }
 
 FlateStream::~FlateStream() {
   if (litCodeTab.codes != fixedLitCodeTab.codes) {
-  gfree(litCodeTab.codes);
+    gfree(litCodeTab.codes);
   }
   if (distCodeTab.codes != fixedDistCodeTab.codes) {
-  gfree(distCodeTab.codes);
+    gfree(distCodeTab.codes);
   }
   if (pred) {
     delete pred;
@@ -4073,11 +4090,11 @@
 
   // free the code tables from the previous block
   if (litCodeTab.codes != fixedLitCodeTab.codes) {
-  gfree(litCodeTab.codes);
+    gfree(litCodeTab.codes);
   }
   litCodeTab.codes = NULL;
   if (distCodeTab.codes != fixedDistCodeTab.codes) {
-  gfree(distCodeTab.codes);
+    gfree(distCodeTab.codes);
   }
   distCodeTab.codes = NULL;
 
@@ -4446,35 +4463,63 @@
 }
 
 GBool ASCII85Encoder::fillBuf() {
-  Gulong t;
+  Guint t;
   char buf1[5];
-  int c;
+  int c0, c1, c2, c3;
   int n, i;
 
-  if (eof)
+  if (eof) {
     return gFalse;
-  t = 0;
-  for (n = 0; n < 4; ++n) {
-    if ((c = str->getChar()) == EOF)
-      break;
-    t = (t << 8) + c;
   }
+  c0 = str->getChar();
+  c1 = str->getChar();
+  c2 = str->getChar();
+  c3 = str->getChar();
   bufPtr = bufEnd = buf;
-  if (n > 0) {
-    if (n == 4 && t == 0) {
+  if (c3 == EOF) {
+    if (c0 == EOF) {
+      n = 0;
+      t = 0;
+    } else {
+      if (c1 == EOF) {
+	n = 1;
+	t = c0 << 24;
+      } else if (c2 == EOF) {
+	n = 2;
+	t = (c0 << 24) | (c1 << 16);
+      } else {
+	n = 3;
+	t = (c0 << 24) | (c1 << 16) | (c2 << 8);
+      }
+      for (i = 4; i >= 0; --i) {
+	buf1[i] = (char)(t % 85 + 0x21);
+	t /= 85;
+      }
+      for (i = 0; i <= n; ++i) {
+	*bufEnd++ = buf1[i];
+	if (++lineLen == 65) {
+	  *bufEnd++ = '\n';
+	  lineLen = 0;
+	}
+      }
+    }
+    *bufEnd++ = '~';
+    *bufEnd++ = '>';
+    eof = gTrue;
+  } else {
+    t = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
+    if (t == 0) {
       *bufEnd++ = 'z';
       if (++lineLen == 65) {
 	*bufEnd++ = '\n';
 	lineLen = 0;
       }
     } else {
-      if (n < 4)
-	t <<= 8 * (4 - n);
       for (i = 4; i >= 0; --i) {
 	buf1[i] = (char)(t % 85 + 0x21);
 	t /= 85;
       }
-      for (i = 0; i <= n; ++i) {
+      for (i = 0; i <= 4; ++i) {
 	*bufEnd++ = buf1[i];
 	if (++lineLen == 65) {
 	  *bufEnd++ = '\n';
@@ -4483,12 +4528,7 @@
       }
     }
   }
-  if (n < 4) {
-    *bufEnd++ = '~';
-    *bufEnd++ = '>';
-    eof = gTrue;
-  }
-  return bufPtr < bufEnd;
+  return gTrue;
 }
 
 //------------------------------------------------------------------------

Index: Stream.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Stream.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- Stream.h	13 Jan 2007 23:19:21 -0000	1.11
+++ Stream.h	25 Apr 2007 19:59:10 -0000	1.12
@@ -17,7 +17,6 @@
 #include "goo/gtypes.h"
 #include "Object.h"
 
-class Decrypt;
 class BaseStream;
 
 //------------------------------------------------------------------------
@@ -44,6 +43,15 @@
 };
 
 //------------------------------------------------------------------------
+
+// This is in Stream.h instead of Decrypt.h to avoid really annoying
+// include file dependency loops.
+enum CryptAlgorithm {
+  cryptRC4,
+  cryptAES
+};
+
+//------------------------------------------------------------------------
 // Stream (base class)
 //------------------------------------------------------------------------
 
@@ -99,6 +107,10 @@
   // Get the BaseStream of this stream.
   virtual BaseStream *getBaseStream() = 0;
 
+  // Get the stream after the last decoder (this may be a BaseStream
+  // or a DecryptStream).
+  virtual Stream *getUndecodedStream() = 0;
+
   // Get the dictionary associated with this stream.
   virtual Dict *getDict() = 0;
 
@@ -109,6 +121,9 @@
   virtual void getImageParams(int * /*bitsPerComponent*/,
 			      StreamColorSpaceMode * /*csMode*/) {}
 
+  // Return the next stream in the "stack".
+  virtual Stream *getNextStream() { return NULL; }
+
   // Add filters to this stream according to the parameters in <dict>.
   // Returns the new stream.
   Stream *addFilters(Object *dict);
@@ -136,20 +151,14 @@
   virtual void setPos(Guint pos, int dir = 0) = 0;
   virtual GBool isBinary(GBool last = gTrue) { return last; }
   virtual BaseStream *getBaseStream() { return this; }
+  virtual Stream *getUndecodedStream() { return this; }
   virtual Dict *getDict() { return dict.getDict(); }
+  virtual GooString *getFileName() { return NULL; }
 
   // Get/set position of first byte of stream within the file.
   virtual Guint getStart() = 0;
   virtual void moveStart(int delta) = 0;
 
-  // Set decryption for this stream.
-  virtual void doDecryption(Guchar *fileKey, int keyLength,
-			    int objNum, int objGen);
-
-protected:
-
-  Decrypt *decrypt;
-
 private:
 
   Object dict;
@@ -170,7 +179,9 @@
   virtual int getPos() { return str->getPos(); }
   virtual void setPos(Guint pos, int dir = 0);
   virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
+  virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); }
   virtual Dict *getDict() { return str->getDict(); }
+  virtual Stream *getNextStream() { return str; }
 
 protected:
 
@@ -316,8 +327,6 @@
   virtual void setPos(Guint pos, int dir = 0);
   virtual Guint getStart() { return start; }
   virtual void moveStart(int delta);
-  virtual void doDecryption(Guchar *fileKey, int keyLength,
-			    int objNum, int objGen);
 
 private:
 
@@ -565,10 +574,11 @@
 class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *strA);
+  DCTStream(Stream *strA, int colorXformA);
   virtual ~DCTStream();
   virtual StreamKind getKind() { return strDCT; }
   virtual void reset();
+  virtual void close();
   virtual int getChar();
   virtual int lookChar();
   virtual GooString *getPSFilter(int psLevel, char *indent);
@@ -585,7 +595,9 @@
   DCTCompInfo compInfo[4];	// info for each component
   DCTScanInfo scanInfo;		// info for the current scan
   int numComps;			// number of components in image
-  int colorXform;		// need YCbCr-to-RGB transform?
+  int colorXform;		// color transform: -1 = unspecified
+				//                   0 = none
+				//                   1 = YUV/YUVK -> RGB/CMYK
   GBool gotJFIFMarker;		// set if APP0 JFIF marker was present
   GBool gotAdobeMarker;		// set if APP14 Adobe marker was present
   int restartInterval;		// restart interval, in MCUs
@@ -632,6 +644,7 @@
   int readMarker();
   int read16();
 };
+
 #endif
 
 #ifndef ENABLE_ZLIB

Index: TextOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/TextOutputDev.cc,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- TextOutputDev.cc	20 Sep 2006 20:22:19 -0000	1.22
+++ TextOutputDev.cc	25 Apr 2007 19:59:10 -0000	1.23
@@ -29,6 +29,7 @@
 #include "GlobalParams.h"
 #include "UnicodeMap.h"
 #include "UnicodeTypeTable.h"
+#include "Link.h"
 #include "TextOutputDev.h"
 #include "Page.h"
 
@@ -106,12 +107,64 @@
 // multiplied by this constant.
 #define maxWideCharSpacingMul 1.3
 
+// Upper limit on spacing between characters in a word.
+#define maxWideCharSpacing 0.4
+
 // Max difference in primary,secondary coordinates (as a fraction of
 // the font size) allowed for duplicated text (fake boldface, drop
 // shadows) which is to be discarded.
 #define dupMaxPriDelta 0.1
 #define dupMaxSecDelta 0.2
 
+// Max width of underlines (in points).
+#define maxUnderlineWidth 3
+
+// Min distance between baseline and underline (in points).
+//~ this should be font-size-dependent
+#define minUnderlineGap -2
+
+// Max distance between baseline and underline (in points).
+//~ this should be font-size-dependent
+#define maxUnderlineGap 4
+
+// Max horizontal distance between edge of word and start of underline
+// (in points).
+//~ this should be font-size-dependent
+#define underlineSlack 1
+
+// Max distance between edge of text and edge of link border
+#define hyperlinkSlack 2
+
+//------------------------------------------------------------------------
+// TextUnderline
+//------------------------------------------------------------------------
+
+class TextUnderline {
+public:
+
+  TextUnderline(double x0A, double y0A, double x1A, double y1A)
+    { x0 = x0A; y0 = y0A; x1 = x1A; y1 = y1A; horiz = y0 == y1; }
+  ~TextUnderline() {}
+
+  double x0, y0, x1, y1;
+  GBool horiz;
+};
+
+//------------------------------------------------------------------------
+// TextLink
+//------------------------------------------------------------------------
+
+class TextLink {
+public:
+
+  TextLink(int xMinA, int yMinA, int xMaxA, int yMaxA, Link *linkA)
+    { xMin = xMinA; yMin = yMinA; xMax = xMaxA; yMax = yMaxA; link = linkA; }
+  ~TextLink() {}
+
+  int xMin, yMin, xMax, yMax;
+  Link *link;
+};
+
 //------------------------------------------------------------------------
 // TextFontInfo
 //------------------------------------------------------------------------
@@ -124,6 +177,7 @@
   fontName = (gfxFont && gfxFont->getOrigName())
                  ? gfxFont->getOrigName()->copy()
                  : (GooString *)NULL;
+  flags = gfxFont ? gfxFont->getFlags() : 0;
 #endif
 }
 
@@ -230,6 +284,9 @@
   colorG = colToDbl(rgb.g);
   colorB = colToDbl(rgb.b);
 #endif
+
+  underlined = gFalse;
+  link = NULL;
 }
 
 TextWord::~TextWord() {
@@ -386,6 +443,39 @@
   return s;
 }
 
+void TextWord::getCharBBox(int charIdx, double *xMinA, double *yMinA,
+			   double *xMaxA, double *yMaxA) {
+  if (charIdx < 0 || charIdx >= len) {
+    return;
+  }
+  switch (rot) {
+  case 0:
+    *xMinA = edge[charIdx];
+    *xMaxA = edge[charIdx + 1];
+    *yMinA = yMin;
+    *yMaxA = yMax;
+    break;
+  case 1:
+    *xMinA = xMin;
+    *xMaxA = xMax;
+    *yMinA = edge[charIdx];
+    *yMaxA = edge[charIdx + 1];
+    break;
+  case 2:
+    *xMinA = edge[charIdx + 1];
+    *xMaxA = edge[charIdx];
+    *yMinA = yMin;
+    *yMaxA = yMax;
+    break;
+  case 3:
+    *xMinA = xMin;
+    *xMaxA = xMax;
+    *yMinA = edge[charIdx + 1];
+    *yMaxA = edge[charIdx];
+    break;
+  }
+}
+
 #endif // TEXTOUT_WORD_LIST
 
 //------------------------------------------------------------------------
@@ -651,6 +741,9 @@
       space = maxCharSpacing * words->fontSize;
     } else {
       space = maxWideCharSpacingMul * minSpace;
+      if (space > maxWideCharSpacing * words->fontSize) {
+	space = maxWideCharSpacing * words->fontSize;
+      }
     }
 
     // merge words
@@ -662,8 +755,9 @@
 	word0 = word1;
 	word1 = word1->next;
       } else if (word0->font == word1->font &&
+		 word0->underlined == word1->underlined &&
 		 fabs(word0->fontSize - word1->fontSize) <
-		 maxWordFontSizeDelta * words->fontSize &&
+		   maxWordFontSizeDelta * words->fontSize &&
 		 word1->charPos == word0->charPos + word0->charLen) {
 	word0->merge(word1);
 	word0->next = word1->next;
@@ -740,6 +834,8 @@
   static int cmpYXPrimaryRot(const void *p1, const void *p2);
   static int cmpYXLineRot(const void *p1, const void *p2);
   static int cmpXYLineRot(const void *p1, const void *p2);
+  static int cmpXYColumnPrimaryRot(const void *p1, const void *p2);
+  static int cmpXYColumnLineRot(const void *p1, const void *p2);
 };
 
 void TextLineFrag::init(TextLine *lineA, int startA, int lenA) {
@@ -971,6 +1067,54 @@
   return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
 }
 
+int TextLineFrag::cmpXYColumnPrimaryRot(const void *p1, const void *p2) {
+  TextLineFrag *frag1 = (TextLineFrag *)p1;
+  TextLineFrag *frag2 = (TextLineFrag *)p2;
+  double cmp;
+
+  // if columns overlap, compare y values
+  if (frag1->col < frag2->col + (frag2->line->col[frag2->start + frag2->len] -
+				 frag2->line->col[frag2->start]) &&
+      frag2->col < frag1->col + (frag1->line->col[frag1->start + frag1->len] -
+				 frag1->line->col[frag1->start])) {
+    cmp = 0; // make gcc happy
+    switch (frag1->line->blk->page->primaryRot) {
+    case 0: cmp = frag1->yMin - frag2->yMin; break;
+    case 1: cmp = frag2->xMax - frag1->xMax; break;
+    case 2: cmp = frag2->yMin - frag1->yMin; break;
+    case 3: cmp = frag1->xMax - frag2->xMax; break;
+    }
+    return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
+  }
+
+  // otherwise, compare starting column
+  return frag1->col - frag2->col;
+}
+
+int TextLineFrag::cmpXYColumnLineRot(const void *p1, const void *p2) {
+  TextLineFrag *frag1 = (TextLineFrag *)p1;
+  TextLineFrag *frag2 = (TextLineFrag *)p2;
+  double cmp;
+
+  // if columns overlap, compare y values
+  if (frag1->col < frag2->col + (frag2->line->col[frag2->start + frag2->len] -
+				 frag2->line->col[frag2->start]) &&
+      frag2->col < frag1->col + (frag1->line->col[frag1->start + frag1->len] -
+				 frag1->line->col[frag1->start])) {
+    cmp = 0; // make gcc happy
+    switch (frag1->line->rot) {
+    case 0: cmp = frag1->yMin - frag2->yMin; break;
+    case 1: cmp = frag2->xMax - frag1->xMax; break;
+    case 2: cmp = frag2->yMin - frag1->yMin; break;
+    case 3: cmp = frag1->xMax - frag2->xMax; break;
+    }
+    return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
+  }
+
+  // otherwise, compare starting column
+  return frag1->col - frag2->col;
+}
+
 //------------------------------------------------------------------------
 // TextBlock
 //------------------------------------------------------------------------
@@ -1629,6 +1773,8 @@
   fonts = new GooList();
   lastFindXMin = lastFindYMin = 0;
   haveLastFind = gFalse;
+  underlines = new GooList();
+  links = new GooList();
 }
 
 TextPage::~TextPage() {
@@ -1641,6 +1787,8 @@
     }
   }
   delete fonts;
+  deleteGooList(underlines, TextUnderline);
+  deleteGooList(links, TextLink);
 }
 
 void TextPage::startPage(GfxState *state) {
@@ -1815,14 +1963,6 @@
   GBool overlap;
   int i;
 
-  // throw away chars that aren't inside the page bounds
-  state->transform(x, y, &x1, &y1);
-  if (x1 < 0 || x1 > pageWidth ||
-      y1 < 0 || y1 > pageHeight) {
-    charPos += nBytes;
-    return;
-  }
-
   // subtract char and word spacing from the dx,dy values
   sp = state->getCharSpace();
   if (c == (CharCode)0x20) {
@@ -1833,6 +1973,16 @@
   dy -= dy2;
   state->transformDelta(dx, dy, &w1, &h1);
 
+  // throw away chars that aren't inside the page bounds
+  // (and also do a sanity check on the character size)
+  state->transform(x, y, &x1, &y1);
+  if (x1 + w1 < 0 || x1 > pageWidth ||
+      y1 + h1 < 0 || y1 > pageHeight ||
+      w1 > pageWidth || h1 > pageHeight) {
+    charPos += nBytes;
+    return;
+  }
+
   // check the tiny chars limit
   if (!globalParams->getTextKeepTinyChars() &&
       fabs(w1) < 3 && fabs(h1) < 3) {
@@ -1845,7 +1995,7 @@
   // break words at space character
   if (uLen == 1 && u[0] == (Unicode)0x20) {
     if (curWord) {
-    ++curWord->charLen;
+      ++curWord->charLen;
     }
     charPos += nBytes;
     endWord();
@@ -1859,7 +2009,8 @@
   //     and secondary axes), or
   // (2) this character overlaps the previous one (duplicated text), or
   // (3) the previous character was an overlap (we want each duplicated
-  //     character to be in a word by itself at this stage)
+  //     character to be in a word by itself at this stage),
+  // (4) the font size has changed
   if (curWord && curWord->len > 0) {
     base = sp = delta = 0; // make gcc happy
     switch (curWord->rot) {
@@ -1889,7 +2040,8 @@
     if (overlap || lastCharOverlap ||
 	sp < -minDupBreakOverlap * curWord->fontSize ||
 	sp > minWordBreakSpace * curWord->fontSize ||
-	fabs(base - curWord->base) > 0.5) {
+	fabs(base - curWord->base) > 0.5 ||
+	curFontSize != curWord->fontSize) {
       endWord();
     }
     lastCharOverlap = overlap;
@@ -1966,7 +2118,15 @@
   }
 }
 
-void TextPage::coalesce(GBool physLayout) {
+void TextPage::addUnderline(double x0, double y0, double x1, double y1) {
+  underlines->append(new TextUnderline(x0, y0, x1, y1));
+}
+
+void TextPage::addLink(int xMin, int yMin, int xMax, int yMax, Link *link) {
+  links->append(new TextLink(xMin, yMin, xMax, yMax, link));
+}
+
+void TextPage::coalesce(GBool physLayout, GBool doHTML) {
   UnicodeMap *uMap;
   TextPool *pool;
   TextWord *word0, *word1, *word2;
@@ -1974,7 +2134,9 @@
   TextBlock *blkList, *blkStack, *blk, *lastBlk, *blk0, *blk1;
   TextBlock **blkArray;
   TextFlow *flow, *lastFlow;
-  int rot, poolMinBaseIdx, baseIdx, startBaseIdx;
+  TextUnderline *underline;
+  TextLink *link;
+  int rot, poolMinBaseIdx, baseIdx, startBaseIdx, endBaseIdx;
   double minBase, maxBase, newMinBase, newMaxBase;
   double fontSize, colSpace1, colSpace2, lineSpace, intraLineSpace, blkSpace;
   GBool found;
@@ -2002,9 +2164,9 @@
     pool = pools[rot];
     for (baseIdx = pool->minBaseIdx; baseIdx <= pool->maxBaseIdx; ++baseIdx) {
       for (word0 = pool->getPool(baseIdx); word0; word0 = word0->next) {
-	printf("    word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f rot=%d '",
+	printf("    word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f rot=%d link=%p '",
 	       word0->xMin, word0->xMax, word0->yMin, word0->yMax,
-	       word0->base, word0->fontSize, rot*90);
+	       word0->base, word0->fontSize, rot*90, word0->link);
 	for (i = 0; i < word0->len; ++i) {
 	  fputc(word0->text[i] & 0xff, stdout);
 	}
@@ -2015,6 +2177,150 @@
   printf("\n");
 #endif
 
+#if 0 //~ for debugging
+  for (i = 0; i < underlines->getLength(); ++i) {
+    underline = (TextUnderline *)underlines->get(i);
+    printf("underline: x=%g..%g y=%g..%g horiz=%d\n",
+	   underline->x0, underline->x1, underline->y0, underline->y1,
+	   underline->horiz);
+  }
+#endif
+
+  if (doHTML) {
+
+    //----- handle underlining
+    for (i = 0; i < underlines->getLength(); ++i) {
+      underline = (TextUnderline *)underlines->get(i);
+      if (underline->horiz) {
+	// rot = 0
+	if (pools[0]->minBaseIdx <= pools[0]->maxBaseIdx) {
+	  startBaseIdx = pools[0]->getBaseIdx(underline->y0 + minUnderlineGap);
+	  endBaseIdx = pools[0]->getBaseIdx(underline->y0 + maxUnderlineGap);
+	  for (j = startBaseIdx; j <= endBaseIdx; ++j) {
+	    for (word0 = pools[0]->getPool(j); word0; word0 = word0->next) {
+	      //~ need to check the y value against the word baseline
+	      if (underline->x0 < word0->xMin + underlineSlack &&
+		  word0->xMax - underlineSlack < underline->x1) {
+		word0->underlined = gTrue;
+	      }
+	    }
+	  }
+	}
+
+	// rot = 2
+	if (pools[2]->minBaseIdx <= pools[2]->maxBaseIdx) {
+	  startBaseIdx = pools[2]->getBaseIdx(underline->y0 - maxUnderlineGap);
+	  endBaseIdx = pools[2]->getBaseIdx(underline->y0 - minUnderlineGap);
+	  for (j = startBaseIdx; j <= endBaseIdx; ++j) {
+	    for (word0 = pools[2]->getPool(j); word0; word0 = word0->next) {
+	      if (underline->x0 < word0->xMin + underlineSlack &&
+		  word0->xMax - underlineSlack < underline->x1) {
+		word0->underlined = gTrue;
+	      }
+	    }
+	  }
+	}
+      } else {
+	// rot = 1
+	if (pools[1]->minBaseIdx <= pools[1]->maxBaseIdx) {
+	  startBaseIdx = pools[1]->getBaseIdx(underline->x0 - maxUnderlineGap);
+	  endBaseIdx = pools[1]->getBaseIdx(underline->x0 - minUnderlineGap);
+	  for (j = startBaseIdx; j <= endBaseIdx; ++j) {
+	    for (word0 = pools[1]->getPool(j); word0; word0 = word0->next) {
+	      if (underline->y0 < word0->yMin + underlineSlack &&
+		  word0->yMax - underlineSlack < underline->y1) {
+		word0->underlined = gTrue;
+	      }
+	    }
+	  }
+	}
+
+	// rot = 3
+	if (pools[3]->minBaseIdx <= pools[3]->maxBaseIdx) {
+	  startBaseIdx = pools[3]->getBaseIdx(underline->x0 + minUnderlineGap);
+	  endBaseIdx = pools[3]->getBaseIdx(underline->x0 + maxUnderlineGap);
+	  for (j = startBaseIdx; j <= endBaseIdx; ++j) {
+	    for (word0 = pools[3]->getPool(j); word0; word0 = word0->next) {
+	      if (underline->y0 < word0->yMin + underlineSlack &&
+		  word0->yMax - underlineSlack < underline->y1) {
+		word0->underlined = gTrue;
+	      }
+	    }
+	  }
+	}
+      }
+    }
+
+    //----- handle links
+    for (i = 0; i < links->getLength(); ++i) {
+      link = (TextLink *)links->get(i);
+
+      // rot = 0
+      if (pools[0]->minBaseIdx <= pools[0]->maxBaseIdx) {
+	startBaseIdx = pools[0]->getBaseIdx(link->yMin);
+	endBaseIdx = pools[0]->getBaseIdx(link->yMax);
+	for (j = startBaseIdx; j <= endBaseIdx; ++j) {
+	  for (word0 = pools[0]->getPool(j); word0; word0 = word0->next) {
+	    if (link->xMin < word0->xMin + hyperlinkSlack &&
+		word0->xMax - hyperlinkSlack < link->xMax &&
+		link->yMin < word0->yMin + hyperlinkSlack &&
+		word0->yMax - hyperlinkSlack < link->yMax) {
+	      word0->link = link->link;
+	    }
+	  }
+	}
+      }
+
+      // rot = 2
+      if (pools[2]->minBaseIdx <= pools[2]->maxBaseIdx) {
+	startBaseIdx = pools[2]->getBaseIdx(link->yMin);
+	endBaseIdx = pools[2]->getBaseIdx(link->yMax);
+	for (j = startBaseIdx; j <= endBaseIdx; ++j) {
+	  for (word0 = pools[2]->getPool(j); word0; word0 = word0->next) {
+	    if (link->xMin < word0->xMin + hyperlinkSlack &&
+		word0->xMax - hyperlinkSlack < link->xMax &&
+		link->yMin < word0->yMin + hyperlinkSlack &&
+		word0->yMax - hyperlinkSlack < link->yMax) {
+	      word0->link = link->link;
+	    }
+	  }
+	}
+      }
+
+      // rot = 1
+      if (pools[1]->minBaseIdx <= pools[1]->maxBaseIdx) {
+	startBaseIdx = pools[1]->getBaseIdx(link->xMin);
+	endBaseIdx = pools[1]->getBaseIdx(link->xMax);
+	for (j = startBaseIdx; j <= endBaseIdx; ++j) {
+	  for (word0 = pools[1]->getPool(j); word0; word0 = word0->next) {
+	    if (link->yMin < word0->yMin + hyperlinkSlack &&
+		word0->yMax - hyperlinkSlack < link->yMax &&
+		link->xMin < word0->xMin + hyperlinkSlack &&
+		word0->xMax - hyperlinkSlack < link->xMax) {
+	      word0->link = link->link;
+	    }
+	  }
+	}
+      }
+
+      // rot = 3
+      if (pools[3]->minBaseIdx <= pools[3]->maxBaseIdx) {
+	startBaseIdx = pools[3]->getBaseIdx(link->xMin);
+	endBaseIdx = pools[3]->getBaseIdx(link->xMax);
+	for (j = startBaseIdx; j <= endBaseIdx; ++j) {
+	  for (word0 = pools[3]->getPool(j); word0; word0 = word0->next) {
+	    if (link->yMin < word0->yMin + hyperlinkSlack &&
+		word0->yMax - hyperlinkSlack < link->yMax &&
+		link->xMin < word0->xMin + hyperlinkSlack &&
+		word0->xMax - hyperlinkSlack < link->xMax) {
+	      word0->link = link->link;
+	    }
+	  }
+	}
+      }
+    }
+  }
+
   //----- assemble the blocks
 
   //~ add an outer loop for writing mode (vertical text)
@@ -2803,21 +3109,21 @@
 	      }
 	    }
 	  } else {
-	  if ((startAtTop ||
-	       yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) &&
-	      (stopAtBottom ||
+	    if ((startAtTop ||
+		 yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) &&
+		(stopAtBottom ||
 		 yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) {
 	      if (!found ||
 		  yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) {
-	      xMin0 = xMin1;
-	      xMax0 = xMax1;
-	      yMin0 = yMin1;
-	      yMax0 = yMax1;
-	      found = gTrue;
+		xMin0 = xMin1;
+		xMax0 = xMax1;
+		yMin0 = yMin1;
+		yMax0 = yMax1;
+		found = gTrue;
+	      }
 	    }
 	  }
 	}
-      }
 	if (backward) {
 	  --j;
 	  --p;
@@ -2861,7 +3167,7 @@
   char space[8], eol[16];
   int spaceLen, eolLen;
   int lastRot;
-  double x, y;
+  double x, y, delta;
   int col, idx0, idx1, i, j;
   GBool multiLine, oneRot;
 
@@ -3028,6 +3334,17 @@
       qsort(frags, nFrags, sizeof(TextLineFrag),
 	    &TextLineFrag::cmpYXPrimaryRot);
     }
+    i = 0;
+    while (i < nFrags) {
+      delta = maxIntraLineDelta * frags[i].line->words->fontSize;
+      for (j = i+1;
+	   j < nFrags && fabs(frags[j].base - frags[i].base) < delta;
+	   ++j) ;
+      qsort(frags + i, j - i, sizeof(TextLineFrag),
+	    oneRot ? &TextLineFrag::cmpXYColumnLineRot
+	           : &TextLineFrag::cmpXYColumnPrimaryRot);
+      i = j;
+    }
 
     col = 0;
     multiLine = gFalse;
@@ -3744,7 +4061,8 @@
   int spaceLen, eolLen, eopLen;
   GBool pageBreaks;
   GooString *s;
-  int col, i, d, n;
+  double delta;
+  int col, i, j, d, n;
 
   // get the output encoding
   if (!(uMap = globalParams->getTextEncoding())) {
@@ -3809,6 +4127,16 @@
       }
     }
     qsort(frags, nFrags, sizeof(TextLineFrag), &TextLineFrag::cmpYXPrimaryRot);
+    i = 0;
+    while (i < nFrags) {
+      delta = maxIntraLineDelta * frags[i].line->words->fontSize;
+      for (j = i+1;
+	   j < nFrags && fabs(frags[j].base - frags[i].base) < delta;
+	   ++j) ;
+      qsort(frags + i, j - i, sizeof(TextLineFrag),
+	    &TextLineFrag::cmpXYColumnPrimaryRot);
+      i = j;
+    }
 
 #if 0 // for debugging
     printf("*** line fragments ***\n");
@@ -4094,7 +4422,7 @@
 // TextOutputDev
 //------------------------------------------------------------------------
 
-static void outputToFile(void *stream, char *text, int len) {
+static void TextOutputDev_outputToFile(void *stream, char *text, int len) {
   fwrite(text, 1, len, (FILE *)stream);
 }
 
@@ -4103,6 +4431,7 @@
   text = NULL;
   physLayout = physLayoutA;
   rawOrder = rawOrderA;
+  doHTML = gFalse;
   ok = gTrue;
 
   // open file
@@ -4121,7 +4450,7 @@
       ok = gFalse;
       return;
     }
-    outputFunc = &outputToFile;
+    outputFunc = &TextOutputDev_outputToFile;
   } else {
     outputStream = NULL;
   }
@@ -4137,6 +4466,7 @@
   needClose = gFalse;
   physLayout = physLayoutA;
   rawOrder = rawOrderA;
+  doHTML = gFalse;
   text = new TextPage(rawOrderA);
   ok = gTrue;
 }
@@ -4159,7 +4489,7 @@
 
 void TextOutputDev::endPage() {
   text->endPage();
-  text->coalesce(physLayout);
+  text->coalesce(physLayout, doHTML);
   if (outputStream) {
     text->dump(outputStream, outputFunc, physLayout);
   }
@@ -4182,6 +4512,153 @@
   text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen);
 }
 
+void TextOutputDev::stroke(GfxState *state) {
+  GfxPath *path;
+  GfxSubpath *subpath;
+  double x[2], y[2];
+
+  if (!doHTML) {
+    return;
+  }
+  path = state->getPath();
+  if (path->getNumSubpaths() != 1) {
+    return;
+  }
+  subpath = path->getSubpath(0);
+  if (subpath->getNumPoints() != 2) {
+    return;
+  }
+  state->transform(subpath->getX(0), subpath->getY(0), &x[0], &y[0]);
+  state->transform(subpath->getX(1), subpath->getY(1), &x[1], &y[1]);
+
+  // look for a vertical or horizontal line
+  if (x[0] == x[1] || y[0] == y[1]) {
+    text->addUnderline(x[0], y[0], x[1], y[1]);
+  }
+}
+
+void TextOutputDev::fill(GfxState *state) {
+  GfxPath *path;
+  GfxSubpath *subpath;
+  double x[5], y[5];
+  double rx0, ry0, rx1, ry1, t;
+  int i;
+
+  if (!doHTML) {
+    return;
+  }
+  path = state->getPath();
+  if (path->getNumSubpaths() != 1) {
+    return;
+  }
+  subpath = path->getSubpath(0);
+  if (subpath->getNumPoints() != 5) {
+    return;
+  }
+  for (i = 0; i < 5; ++i) {
+    if (subpath->getCurve(i)) {
+      return;
+    }
+    state->transform(subpath->getX(i), subpath->getY(i), &x[i], &y[i]);
+  }
+
+  // look for a rectangle
+  if (x[0] == x[1] && y[1] == y[2] && x[2] == x[3] && y[3] == y[4] &&
+      x[0] == x[4] && y[0] == y[4]) {
+    rx0 = x[0];
+    ry0 = y[0];
+    rx1 = x[2];
+    ry1 = y[1];
+  } else if (y[0] == y[1] && x[1] == x[2] && y[2] == y[3] && x[3] == x[4] &&
+	     x[0] == x[4] && y[0] == y[4]) {
+    rx0 = x[0];
+    ry0 = y[0];
+    rx1 = x[1];
+    ry1 = y[2];
+  } else {
+    return;
+  }
+  if (rx1 < rx0) {
+    t = rx0;
+    rx0 = rx1;
+    rx1 = t;
+  }
+  if (ry1 < ry0) {
+    t = ry0;
+    ry0 = ry1;
+    ry1 = t;
+  }
+
+  // skinny horizontal rectangle
+  if (ry1 - ry0 < rx1 - rx0) {
+    if (ry1 - ry0 < maxUnderlineWidth) {
+      ry0 = 0.5 * (ry0 + ry1);
+      text->addUnderline(rx0, ry0, rx1, ry0);
+    }
+
+  // skinny vertical rectangle
+  } else {
+    if (rx1 - rx0 < maxUnderlineWidth) {
+      rx0 = 0.5 * (rx0 + rx1);
+      text->addUnderline(rx0, ry0, rx0, ry1);
+    }
+  }
+}
+
+void TextOutputDev::eoFill(GfxState *state) {
+  if (!doHTML) {
+    return;
+  }
+  fill(state);
+}
+
+void TextOutputDev::processLink(Link *link, Catalog * /*catalog*/) {
+  double x1, y1, x2, y2;
+  int xMin, yMin, xMax, yMax, x, y;
+
+  if (!doHTML) {
+    return;
+  }
+  link->getRect(&x1, &y1, &x2, &y2);
+  cvtUserToDev(x1, y1, &x, &y);
+  xMin = xMax = x;
+  yMin = yMax = y;
+  cvtUserToDev(x1, y2, &x, &y);
+  if (x < xMin) {
+    xMin = x;
+  } else if (x > xMax) {
+    xMax = x;
+  }
+  if (y < yMin) {
+    yMin = y;
+  } else if (y > yMax) {
+    yMax = y;
+  }
+  cvtUserToDev(x2, y1, &x, &y);
+  if (x < xMin) {
+    xMin = x;
+  } else if (x > xMax) {
+    xMax = x;
+  }
+  if (y < yMin) {
+    yMin = y;
+  } else if (y > yMax) {
+    yMax = y;
+  }
+  cvtUserToDev(x2, y2, &x, &y);
+  if (x < xMin) {
+    xMin = x;
+  } else if (x > xMax) {
+    xMax = x;
+  }
+  if (y < yMin) {
+    yMin = y;
+  } else if (y > yMax) {
+    yMax = y;
+  }
+  text->addLink(xMin, yMin, xMax, yMax, link);
+}
+
 GBool TextOutputDev::findText(Unicode *s, int len,
 			      GBool startAtTop, GBool stopAtBottom,
 			      GBool startAtLast, GBool stopAtLast,

Index: TextOutputDev.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/TextOutputDev.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- TextOutputDev.h	19 May 2006 22:04:17 -0000	1.12
+++ TextOutputDev.h	25 Apr 2007 19:59:10 -0000	1.13
@@ -26,6 +26,7 @@
 class GfxFont;
 class GfxState;
 class UnicodeMap;
+class Link;
 
 class TextWord;
 class TextPool;
@@ -53,11 +54,24 @@
 
   GBool matches(GfxState *state);
 
+#if TEXTOUT_WORD_LIST
+  // Get the font name (which may be NULL).
+  GooString *getFontName() { return fontName; }
+
+  // Get font descriptor flags.
+  GBool isFixedWidth() { return flags & fontFixedWidth; }
+  GBool isSerif() { return flags & fontSerif; }
+  GBool isSymbolic() { return flags & fontSymbolic; }
+  GBool isItalic() { return flags & fontItalic; }
+  GBool isBold() { return flags & fontBold; }
+#endif
+
 private:
 
   GfxFont *gfxFont;
 #if TEXTOUT_WORD_LIST
   GooString *fontName;
+  int flags;
 #endif
 
   friend class TextWord;
@@ -99,6 +113,12 @@
   void visitSelection(TextSelectionVisitor *visitor,
 		      PDFRectangle *selection);
 
+  // Get the TextFontInfo object associated with this word.
+  TextFontInfo *getFontInfo() { return font; }
+
+  // Get the next TextWord on the linked list.
+  TextWord *getNext() { return next; }
+
 #if TEXTOUT_WORD_LIST
   int getLength() { return len; }
   const Unicode *getChar(int idx) { return &text[idx]; }
@@ -108,11 +128,16 @@
     { *r = colorR; *g = colorG; *b = colorB; }
   void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA)
     { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
+  void getCharBBox(int charIdx, double *xMinA, double *yMinA,
+		   double *xMaxA, double *yMaxA);
   double getFontSize() { return fontSize; }
   int getRotation() { return rot; }
   int getCharPos() { return charPos; }
   int getCharLen() { return charLen; }
+  GBool getSpaceAfter() { return spaceAfter; }
 #endif
+  GBool isUnderlined() { return underlined; }
+  Link *getLink() { return link; }
   double getEdge(int i) { return edge[i]; }
   double getBaseline () { return base; }
   GBool hasSpaceAfter  () { return spaceAfter; }
@@ -145,6 +170,9 @@
          colorB;
 #endif
 
+  GBool underlined;
+  Link *link;
+
   friend class TextPool;
   friend class TextLine;
   friend class TextBlock;
@@ -222,6 +250,15 @@
   void visitSelection(TextSelectionVisitor *visitor,
 		      PDFRectangle *selection);
 
+  // Get the head of the linked list of TextWords.
+  TextWord *getWords() { return words; }
+
+  // Get the next TextLine on the linked list.
+  TextLine *getNext() { return next; }
+
+  // Returns true if the last char of the line is a hyphen.
+  GBool isHyphenated() { return hyphenated; }
+
 private:
 
   TextBlock *blk;		// parent block
@@ -287,6 +324,12 @@
   void visitSelection(TextSelectionVisitor *visitor,
 		      PDFRectangle *selection);
 
+  // Get the head of the linked list of TextLines.
+  TextLine *getLines() { return lines; }
+
+  // Get the next TextBlock on the linked list.
+  TextBlock *getNext() { return next; }
+
 private:
 
   TextPage *page;		// the parent page
@@ -334,6 +377,12 @@
   // primary axis.
   GBool blockFits(TextBlock *blk, TextBlock *prevBlk);
 
+  // Get the head of the linked list of TextBlocks.
+  TextBlock *getBlocks() { return blocks; }
+
+  // Get the next TextFlow on the linked list.
+  TextFlow *getNext() { return next; }
+
 private:
 
   TextPage *page;		// the parent page
@@ -373,7 +422,7 @@
 
 private:
 
-  GooList *words;
+  GooList *words;			// [TextWord]
 };
 
 #endif // TEXTOUT_WORD_LIST
@@ -414,8 +463,14 @@
   // Add a word, sorting it into the list of words.
   void addWord(TextWord *word);
 
+  // Add a (potential) underline.
+  void addUnderline(double x0, double y0, double x1, double y1);
+
+  // Add a hyperlink.
+  void addLink(int xMin, int yMin, int xMax, int yMax, Link *link);
+
   // Coalesce strings that look like parts of the same line.
-  void coalesce(GBool physLayout);
+  void coalesce(GBool physLayout, GBool doHTML);
 
   // Find a string.  If <startAtTop> is true, starts looking at the
   // top of the page; else if <startAtLast> is true, starts looking
@@ -459,6 +514,9 @@
   void dump(void *outputStream, TextOutputFunc outputFunc,
 	    GBool physLayout);
 
+  // Get the head of the linked list of TextFlows.
+  TextFlow *getFlows() { return flows; }
+
 #if TEXTOUT_WORD_LIST
   // Build a flat word list, in content stream order (if
   // this->rawOrder is true), physical layout order (if <physLayout>
@@ -504,6 +562,9 @@
          lastFindYMin;
   GBool haveLastFind;
 
+  GooList *underlines;		// [TextUnderline]
+  GooList *links;		// [TextLink]
+
   friend class TextLine;
   friend class TextLineFrag;
   friend class TextBlock;
@@ -576,6 +637,14 @@
 			double originX, double originY,
 			CharCode c, int nBytes, Unicode *u, int uLen);
 
+  //----- path painting
+  virtual void stroke(GfxState *state);
+  virtual void fill(GfxState *state);
+  virtual void eoFill(GfxState *state);
+
+  //----- link borders
+  virtual void processLink(Link *link, Catalog *catalog);
+
   //----- special access
 
   // Find a string.  If <startAtTop> is true, starts looking at the
@@ -623,6 +692,9 @@
   // transferring ownership to the caller.
   TextPage *takeText();
 
+  // Turn extra processing for HTML conversion on or off.
+  void enableHTMLExtras(GBool doHTMLA) { doHTML = doHTMLA; }
+
 private:
 
   TextOutputFunc outputFunc;	// output function
@@ -633,6 +705,7 @@
   GBool physLayout;		// maintain original physical layout when
 				//   dumping text
   GBool rawOrder;		// keep text in content stream order
+  GBool doHTML;			// extra processing for HTML conversion
   GBool ok;			// set up ok?
 };
 

--- UGooString.cc DELETED ---

--- UGooString.h DELETED ---

Index: XRef.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/XRef.cc,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- XRef.cc	24 Feb 2007 23:32:23 -0000	1.14
+++ XRef.cc	25 Apr 2007 19:59:10 -0000	1.15
@@ -24,7 +24,6 @@
 #include "Dict.h"
 #include "Error.h"
 #include "ErrorCodes.h"
-#include "UGooString.h"
 #include "XRef.h"
 
 //------------------------------------------------------------------------
@@ -124,7 +123,7 @@
   objStr.streamReset();
   obj1.initNull();
   str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first);
-  parser = new Parser(xref, new Lexer(xref, str));
+  parser = new Parser(xref, new Lexer(xref, str), gFalse);
   for (i = 0; i < nObjects; ++i) {
     parser->getObj(&obj1);
     parser->getObj(&obj2);
@@ -165,7 +164,7 @@
       str = new EmbedStream(objStr.getStream(), &obj1, gTrue,
 			    offsets[i+1] - offsets[i]);
     }
-    parser = new Parser(xref, new Lexer(xref, str));
+    parser = new Parser(xref, new Lexer(xref, str), gFalse);
     parser->getObj(&objs[i]);
     while (str->getChar() != EOF) ;
     delete parser;
@@ -331,7 +330,8 @@
   obj.initNull();
   parser = new Parser(NULL,
 	     new Lexer(NULL,
-	       str->makeSubStream(start + *pos, gFalse, 0, &obj)));
+	       str->makeSubStream(start + *pos, gFalse, 0, &obj)),
+	     gTrue);
   parser->getObj(&obj);
 
   // parse an old-style xref table
@@ -689,7 +689,7 @@
   size = 0;
   entries = NULL;
 
-  error(0, "PDF file is damaged - attempting to reconstruct xref table...");
+  error(-1, "PDF file is damaged - attempting to reconstruct xref table...");
   gotRoot = gFalse;
   streamEndsLen = streamEndsSize = 0;
 
@@ -701,12 +701,16 @@
     }
     p = buf;
 
+    // skip whitespace
+    while (*p && Lexer::isSpace(*p & 0xff)) ++p;
+
     // got trailer dictionary
     if (!strncmp(p, "trailer", 7)) {
       obj.initNull();
       parser = new Parser(NULL,
 		 new Lexer(NULL,
-		   str->makeSubStream(pos + 7, gFalse, 0, &obj)));
+		   str->makeSubStream(pos + 7, gFalse, 0, &obj)),
+		 gFalse);
       parser->getObj(&newTrailerDict);
       if (newTrailerDict.isDict()) {
 	newTrailerDict.dictLookupNF("Root", &obj);
@@ -799,7 +803,8 @@
 
 void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA,
 			 Guchar *fileKeyA, int keyLengthA,
-			 int encVersionA, int encRevisionA) {
+			 int encVersionA, int encRevisionA,
+			 CryptAlgorithm encAlgorithmA) {
   int i;
 
   encrypted = gTrue;
@@ -815,6 +820,7 @@
   }
   encVersion = encVersionA;
   encRevision = encRevisionA;
+  encAlgorithm = encAlgorithmA;
 }
 
 GBool XRef::okToPrint(GBool ignoreOwnerPW) {
@@ -883,7 +889,8 @@
     obj1.initNull();
     parser = new Parser(this,
 	       new Lexer(this,
-		 str->makeSubStream(start + e->offset, gFalse, 0, &obj1)));
+		 str->makeSubStream(start + e->offset, gFalse, 0, &obj1)),
+	       gTrue);
     parser->getObj(&obj1);
     parser->getObj(&obj2);
     parser->getObj(&obj3);
@@ -896,8 +903,8 @@
       delete parser;
       goto err;
     }
-    parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
-		   num, gen);
+    parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL,
+		   encAlgorithm, keyLength, num, gen);
     obj1.free();
     obj2.free();
     obj3.free();
@@ -959,7 +966,7 @@
   return gTrue;
 }
 
-int XRef::getNumEntry(int offset) const
+int XRef::getNumEntry(Guint offset) const
 {
   if (size > 0)
   {

Index: XRef.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/XRef.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- XRef.h	24 Feb 2007 23:32:23 -0000	1.7
+++ XRef.h	25 Apr 2007 19:59:10 -0000	1.8
@@ -59,7 +59,8 @@
   // Set the encryption parameters.
   void setEncryption(int permFlagsA, GBool ownerPasswordOkA,
 		     Guchar *fileKeyA, int keyLengthA,
-		     int encVersionA, int encRevisionA);
+		     int encVersionA, int encRevisionA,
+		     CryptAlgorithm encAlgorithmA);
 
   // Is the file encrypted?
   GBool isEncrypted() { return encrypted; }
@@ -99,7 +100,7 @@
   GBool getStreamEnd(Guint streamStart, Guint *streamEnd);
 
   // Retuns the entry that belongs to the offset
-  int getNumEntry(int offset) const;
+  int getNumEntry(Guint offset) const;
 
   // Direct access.
   int getSize() { return size; }
@@ -130,6 +131,7 @@
   GBool encrypted;		// true if file is encrypted
   int encRevision;		
   int encVersion;		// encryption algorithm
+  CryptAlgorithm encAlgorithm;	// encryption algorithm
   int keyLength;		// length of key, in bytes
   int permFlags;		// permission bits
   Guchar fileKey[16];		// file decryption key



More information about the poppler mailing list