summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Gryniewicz <dang@gentoo.org>2005-12-27 18:44:56 +0000
committerDaniel Gryniewicz <dang@gentoo.org>2005-12-27 18:44:56 +0000
commit3be06c796d68eff60befc00a351885d2be842dc6 (patch)
treef4f04f9581a136830b9cece0d6ab643d8b219071 /app-text/poppler/files
parentversion bump (diff)
downloadgentoo-2-3be06c796d68eff60befc00a351885d2be842dc6.tar.gz
gentoo-2-3be06c796d68eff60befc00a351885d2be842dc6.tar.bz2
gentoo-2-3be06c796d68eff60befc00a351885d2be842dc6.zip
Add non-X utilities to poppler to help resolve dependencies
(Portage version: 2.1_pre2)
Diffstat (limited to 'app-text/poppler/files')
-rw-r--r--app-text/poppler/files/digest-poppler-0.4.3-r11
-rw-r--r--app-text/poppler/files/poppler-0.4.3-utils.patch7859
2 files changed, 7860 insertions, 0 deletions
diff --git a/app-text/poppler/files/digest-poppler-0.4.3-r1 b/app-text/poppler/files/digest-poppler-0.4.3-r1
new file mode 100644
index 000000000000..737819686e59
--- /dev/null
+++ b/app-text/poppler/files/digest-poppler-0.4.3-r1
@@ -0,0 +1 @@
+MD5 791dc78d8366eb05580183fe85174555 poppler-0.4.3.tar.gz 779582
diff --git a/app-text/poppler/files/poppler-0.4.3-utils.patch b/app-text/poppler/files/poppler-0.4.3-utils.patch
new file mode 100644
index 000000000000..a3e5fcff92a6
--- /dev/null
+++ b/app-text/poppler/files/poppler-0.4.3-utils.patch
@@ -0,0 +1,7859 @@
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/configure.ac poppler-0.4.3/configure.ac
+--- poppler-0.4.3.orig/configure.ac 2005-12-12 17:46:00.000000000 -0500
++++ poppler-0.4.3/configure.ac 2005-12-26 21:28:15.000000000 -0500
+@@ -437,6 +437,7 @@
+ fofi/Makefile
+ splash/Makefile
+ poppler/Makefile
++utils/Makefile
+ glib/Makefile
+ test/Makefile
+ qt/Makefile
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/Makefile.am poppler-0.4.3/Makefile.am
+--- poppler-0.4.3.orig/Makefile.am 2005-06-28 06:00:09.000000000 -0400
++++ poppler-0.4.3/Makefile.am 2005-12-26 21:28:15.000000000 -0500
+@@ -22,7 +22,7 @@
+ qt4_pc_file = poppler-qt4.pc
+ endif
+
+-SUBDIRS = goo fofi $(splash_subdir) poppler $(glib_subdir) $(qt_subdir) test $(qt4_subdir)
++SUBDIRS = goo fofi $(splash_subdir) poppler utils $(glib_subdir) $(qt_subdir) test $(qt4_subdir)
+
+ EXTRA_DIST = \
+ README-XPDF \
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/GVector.h poppler-0.4.3/utils/GVector.h
+--- poppler-0.4.3.orig/utils/GVector.h 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/GVector.h 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,101 @@
++#ifndef _VECTOR_H
++#define _VECTOR_H
++#include "goo/gtypes.h"
++
++
++template<class T>
++class GVector{
++private:
++
++ int _size;
++ T* last;
++ T* storage;
++
++ void resize(){
++ if (_size==0) _size=2;else _size=2*_size;
++ T *tmp=new T[_size];
++ if (storage){
++ last=copy(storage,last,tmp);
++ delete [] storage;
++ }
++ else last=tmp;
++ storage=tmp;
++ }
++
++ T* copy(T* src1,T* scr2,T* dest){
++ T* tmp=src1;
++ T* d=dest;
++ while(tmp!=scr2){
++ *d=*tmp;
++ d++;tmp++;
++ }
++ return d;
++ }
++
++public:
++ typedef T* iterator;
++
++ GVector(){
++ _size=0;
++ last=0;
++ storage=0;
++}
++
++
++
++virtual ~GVector(){
++ delete[] storage ;
++}
++
++void reset(){
++ last=storage;
++}
++
++int size(){
++ return (last-storage);
++}
++void push_back(const T& elem){
++ if (!storage||(size() >=_size)) resize();
++ *last=elem;
++ last++;
++
++
++}
++
++
++T pop_back() {
++ if (last!=storage) last--;
++
++ return *last;
++}
++
++
++T operator[](unsigned int i){
++ return *(storage+i);
++}
++
++
++GBool isEmpty() const{
++ return !_size || (last==storage) ;
++}
++
++
++
++iterator begin() const{
++ return storage;
++}
++
++iterator end() const {
++ return last;
++}
++};
++#endif
++
++
++
++
++
++
++
++
++
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/HtmlFonts.cc poppler-0.4.3/utils/HtmlFonts.cc
+--- poppler-0.4.3.orig/utils/HtmlFonts.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/HtmlFonts.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,326 @@
++#include "HtmlFonts.h"
++#include "GlobalParams.h"
++#include "UnicodeMap.h"
++#include <stdio.h>
++
++ struct Fonts{
++ char *Fontname;
++ char *name;
++ };
++
++const int font_num=13;
++
++static Fonts fonts[font_num+1]={
++ {"Courier", "Courier" },
++ {"Courier-Bold", "Courier"},
++ {"Courier-BoldOblique", "Courier"},
++ {"Courier-Oblique", "Courier"},
++ {"Helvetica", "Helvetica"},
++ {"Helvetica-Bold", "Helvetica"},
++ {"Helvetica-BoldOblique", "Helvetica"},
++ {"Helvetica-Oblique", "Helvetica"},
++ {"Symbol", "Symbol" },
++ {"Times-Bold", "Times" },
++ {"Times-BoldItalic", "Times" },
++ {"Times-Italic", "Times" },
++ {"Times-Roman", "Times" },
++ {" " , "Times" },
++};
++
++#define xoutRound(x) ((int)(x + 0.5))
++extern GBool xml;
++
++GooString* HtmlFont::DefaultFont=new GooString("Times"); // Arial,Helvetica,sans-serif
++
++HtmlFontColor::HtmlFontColor(GfxRGB rgb){
++ r=static_cast<int>(255*rgb.r);
++ g=static_cast<int>(255*rgb.g);
++ b=static_cast<int>(255*rgb.b);
++ if (!(Ok(r)&&Ok(b)&&Ok(g))) {printf("Error : Bad color \n");r=0;g=0;b=0;}
++}
++
++GooString *HtmlFontColor::convtoX(unsigned int xcol) const{
++ GooString *xret=new GooString();
++ char tmp;
++ unsigned int k;
++ k = (xcol/16);
++ if ((k>=0)&&(k<10)) tmp=(char) ('0'+k); else tmp=(char)('a'+k-10);
++ xret->append(tmp);
++ k = (xcol%16);
++ if ((k>=0)&&(k<10)) tmp=(char) ('0'+k); else tmp=(char)('a'+k-10);
++ xret->append(tmp);
++ return xret;
++}
++
++GooString *HtmlFontColor::toString() const{
++ GooString *tmp=new GooString("#");
++ GooString *tmpr=convtoX(r);
++ GooString *tmpg=convtoX(g);
++ GooString *tmpb=convtoX(b);
++ tmp->append(tmpr);
++ tmp->append(tmpg);
++ tmp->append(tmpb);
++ delete tmpr;
++ delete tmpg;
++ delete tmpb;
++ return tmp;
++}
++
++HtmlFont::HtmlFont(GooString* ftname,int _size, GfxRGB rgb){
++ //if (col) color=HtmlFontColor(col);
++ //else color=HtmlFontColor();
++ color=HtmlFontColor(rgb);
++
++ GooString *fontname = NULL;
++
++ if( ftname ){
++ fontname = new GooString(ftname);
++ FontName=new GooString(ftname);
++ }
++ else {
++ fontname = NULL;
++ FontName = NULL;
++ }
++
++ lineSize = -1;
++
++ size=(_size-1);
++ italic = gFalse;
++ bold = gFalse;
++
++ if (fontname){
++ if (strstr(fontname->lowerCase()->getCString(),"bold")) bold=gTrue;
++
++ if (strstr(fontname->lowerCase()->getCString(),"italic")||
++ strstr(fontname->lowerCase()->getCString(),"oblique")) italic=gTrue;
++
++ int i=0;
++ while (strcmp(ftname->getCString(),fonts[i].Fontname)&&(i<font_num))
++ {
++ i++;
++ }
++ pos=i;
++ delete fontname;
++ }
++ if (!DefaultFont) DefaultFont=new GooString(fonts[font_num].name);
++
++}
++
++HtmlFont::HtmlFont(const HtmlFont& x){
++ size=x.size;
++ lineSize=x.lineSize;
++ italic=x.italic;
++ bold=x.bold;
++ pos=x.pos;
++ color=x.color;
++ if (x.FontName) FontName=new GooString(x.FontName);
++ }
++
++
++HtmlFont::~HtmlFont(){
++ if (FontName) delete FontName;
++}
++
++HtmlFont& HtmlFont::operator=(const HtmlFont& x){
++ if (this==&x) return *this;
++ size=x.size;
++ lineSize=x.lineSize;
++ italic=x.italic;
++ bold=x.bold;
++ pos=x.pos;
++ color=x.color;
++ if (FontName) delete FontName;
++ if (x.FontName) FontName=new GooString(x.FontName);
++ return *this;
++}
++
++void HtmlFont::clear(){
++ if(DefaultFont) delete DefaultFont;
++ DefaultFont = NULL;
++}
++
++
++
++/*
++ This function is used to compare font uniquily for insertion into
++ the list of all encountered fonts
++*/
++GBool HtmlFont::isEqual(const HtmlFont& x) const{
++ return ((size==x.size) &&
++ (lineSize==x.lineSize) &&
++ (pos==x.pos) && (bold==x.bold) && (italic==x.italic) &&
++ (color.isEqual(x.getColor())));
++}
++
++/*
++ This one is used to decide whether two pieces of text can be joined together
++ and therefore we don't care about bold/italics properties
++*/
++GBool HtmlFont::isEqualIgnoreBold(const HtmlFont& x) const{
++ return ((size==x.size) &&
++ (!strcmp(fonts[pos].name, fonts[x.pos].name)) &&
++ (color.isEqual(x.getColor())));
++}
++
++GooString* HtmlFont::getFontName(){
++ if (pos!=font_num) return new GooString(fonts[pos].name);
++ else return new GooString(DefaultFont);
++}
++
++GooString* HtmlFont::getFullName(){
++ if (FontName)
++ return new GooString(FontName);
++ else return new GooString(DefaultFont);
++}
++
++void HtmlFont::setDefaultFont(GooString* defaultFont){
++ if (DefaultFont) delete DefaultFont;
++ DefaultFont=new GooString(defaultFont);
++}
++
++
++GooString* HtmlFont::getDefaultFont(){
++ return DefaultFont;
++}
++
++// this method if plain wrong todo
++GooString* HtmlFont::HtmlFilter(Unicode* u, int uLen) {
++ GooString *tmp = new GooString();
++ UnicodeMap *uMap;
++ char buf[8];
++ int n;
++
++ // get the output encoding
++ if (!(uMap = globalParams->getTextEncoding())) {
++ return tmp;
++ }
++
++ for (int i = 0; i < uLen; ++i) {
++ switch (u[i])
++ {
++ case '"': tmp->append("&quot;"); break;
++ case '&': tmp->append("&amp;"); break;
++ case '<': tmp->append("&lt;"); break;
++ case '>': tmp->append("&gt;"); break;
++ default:
++ {
++ // convert unicode to string
++ if ((n = uMap->mapUnicode(u[i], buf, sizeof(buf))) > 0) {
++ tmp->append(buf, n);
++ }
++ }
++ }
++ }
++
++ uMap->decRefCnt();
++ return tmp;
++}
++
++GooString* HtmlFont::simple(HtmlFont* font, Unicode* content, int uLen){
++ GooString *cont=HtmlFilter (content, uLen);
++
++ /*if (font.isBold()) {
++ cont->insert(0,"<b>",3);
++ cont->append("</b>",4);
++ }
++ if (font.isItalic()) {
++ cont->insert(0,"<i>",3);
++ cont->append("</i>",4);
++ } */
++
++ return cont;
++}
++
++HtmlFontAccu::HtmlFontAccu(){
++ accu=new GVector<HtmlFont>();
++}
++
++HtmlFontAccu::~HtmlFontAccu(){
++ if (accu) delete accu;
++}
++
++int HtmlFontAccu::AddFont(const HtmlFont& font){
++ GVector<HtmlFont>::iterator i;
++ for (i=accu->begin();i!=accu->end();i++)
++ {
++ if (font.isEqual(*i))
++ {
++ return (int)(i-(accu->begin()));
++ }
++ }
++
++ accu->push_back(font);
++ return (accu->size()-1);
++}
++
++// get CSS font name for font #i
++GooString* HtmlFontAccu::getCSStyle(int i, GooString* content){
++ GooString *tmp;
++ GooString *iStr=GooString::fromInt(i);
++
++ if (!xml) {
++ tmp = new GooString("<span class=\"ft");
++ tmp->append(iStr);
++ tmp->append("\">");
++ tmp->append(content);
++ tmp->append("</span>");
++ } else {
++ tmp = new GooString("");
++ tmp->append(content);
++ }
++
++ delete iStr;
++ return tmp;
++}
++
++// get CSS font definition for font #i
++GooString* HtmlFontAccu::CSStyle(int i){
++ GooString *tmp=new GooString();
++ GooString *iStr=GooString::fromInt(i);
++
++ GVector<HtmlFont>::iterator g=accu->begin();
++ g+=i;
++ HtmlFont font=*g;
++ GooString *Size=GooString::fromInt(font.getSize());
++ GooString *colorStr=font.getColor().toString();
++ GooString *fontName=font.getFontName();
++ GooString *lSize;
++
++ if(!xml){
++ tmp->append(".ft");
++ tmp->append(iStr);
++ tmp->append("{font-size:");
++ tmp->append(Size);
++ if( font.getLineSize() != -1 )
++ {
++ lSize = GooString::fromInt(font.getLineSize());
++ tmp->append("px;line-height:");
++ tmp->append(lSize);
++ delete lSize;
++ }
++ tmp->append("px;font-family:");
++ tmp->append(fontName); //font.getFontName());
++ tmp->append(";color:");
++ tmp->append(colorStr);
++ tmp->append(";}");
++ }
++ if (xml) {
++ tmp->append("<fontspec id=\"");
++ tmp->append(iStr);
++ tmp->append("\" size=\"");
++ tmp->append(Size);
++ tmp->append("\" family=\"");
++ tmp->append(fontName); //font.getFontName());
++ tmp->append("\" color=\"");
++ tmp->append(colorStr);
++ tmp->append("\"/>");
++ }
++
++ delete fontName;
++ delete colorStr;
++ delete iStr;
++ delete Size;
++ return tmp;
++}
++
++
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/HtmlFonts.h poppler-0.4.3/utils/HtmlFonts.h
+--- poppler-0.4.3.orig/utils/HtmlFonts.h 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/HtmlFonts.h 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,85 @@
++#ifndef _HTML_FONTS_H
++#define _HTML_FONTS_H
++#include "GVector.h"
++#include "goo/GooString.h"
++#include "GfxState.h"
++#include "CharTypes.h"
++
++
++class HtmlFontColor{
++ private:
++ unsigned int r;
++ unsigned int g;
++ unsigned int b;
++ GBool Ok(unsigned int xcol){ return ((xcol<=255)&&(xcol>=0));}
++ GooString *convtoX(unsigned int xcol) const;
++ public:
++ HtmlFontColor():r(0),g(0),b(0){}
++ HtmlFontColor(GfxRGB rgb);
++ HtmlFontColor(const HtmlFontColor& x){r=x.r;g=x.g;b=x.b;}
++ HtmlFontColor& operator=(const HtmlFontColor &x){
++ r=x.r;g=x.g;b=x.b;
++ return *this;
++ }
++ ~HtmlFontColor(){};
++ GooString* toString() const;
++ GBool isEqual(const HtmlFontColor& col) const{
++ return ((r==col.r)&&(g==col.g)&&(b==col.b));
++ }
++} ;
++
++
++class HtmlFont{
++ private:
++ unsigned int size;
++ int lineSize;
++ GBool italic;
++ GBool bold;
++ int pos; // position of the font name in the fonts array
++ static GooString *DefaultFont;
++ GooString *FontName;
++ HtmlFontColor color;
++ static GooString* HtmlFilter(Unicode* u, int uLen); //char* s);
++public:
++
++ HtmlFont(){FontName=NULL;};
++ HtmlFont(GooString* fontname,int _size, GfxRGB rgb);
++ HtmlFont(const HtmlFont& x);
++ HtmlFont& operator=(const HtmlFont& x);
++ HtmlFontColor getColor() const {return color;}
++ ~HtmlFont();
++ static void clear();
++ GooString* getFullName();
++ GBool isItalic() const {return italic;}
++ GBool isBold() const {return bold;}
++ unsigned int getSize() const {return size;}
++ int getLineSize() const {return lineSize;}
++ void setLineSize(int _lineSize) { lineSize = _lineSize; }
++ GooString* getFontName();
++ static GooString* getDefaultFont();
++ static void setDefaultFont(GooString* defaultFont);
++ GBool isEqual(const HtmlFont& x) const;
++ GBool isEqualIgnoreBold(const HtmlFont& x) const;
++ static GooString* simple(HtmlFont *font, Unicode *content, int uLen);
++ void print() const {printf("font: %s %d %s%spos: %d\n", FontName->getCString(), size, bold ? "bold " : "", italic ? "italic " : "", pos);};
++};
++
++class HtmlFontAccu{
++private:
++ GVector<HtmlFont> *accu;
++
++public:
++ HtmlFontAccu();
++ ~HtmlFontAccu();
++ int AddFont(const HtmlFont& font);
++ HtmlFont* Get(int i){
++ GVector<HtmlFont>::iterator g=accu->begin();
++ g+=i;
++ return g;
++ }
++ GooString* getCSStyle (int i, GooString* content);
++ GooString* CSStyle(int i);
++ int size() const {return accu->size();}
++
++};
++#endif
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/HtmlLinks.cc poppler-0.4.3/utils/HtmlLinks.cc
+--- poppler-0.4.3.orig/utils/HtmlLinks.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/HtmlLinks.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,101 @@
++#include "HtmlLinks.h"
++
++HtmlLink::HtmlLink(const HtmlLink& x){
++ Xmin=x.Xmin;
++ Ymin=x.Ymin;
++ Xmax=x.Xmax;
++ Ymax=x.Ymax;
++ dest=new GooString(x.dest);
++}
++
++HtmlLink::HtmlLink(double xmin,double ymin,double xmax,double ymax,GooString * _dest)
++{
++ if (xmin < xmax) {
++ Xmin=xmin;
++ Xmax=xmax;
++ } else {
++ Xmin=xmax;
++ Xmax=xmin;
++ }
++ if (ymin < ymax) {
++ Ymin=ymin;
++ Ymax=ymax;
++ } else {
++ Ymin=ymax;
++ Ymax=ymin;
++ }
++ dest=new GooString(_dest);
++}
++
++HtmlLink::~HtmlLink(){
++ if (dest) delete dest;
++}
++
++GBool HtmlLink::isEqualDest(const HtmlLink& x) const{
++ return (!strcmp(dest->getCString(), x.dest->getCString()));
++}
++
++GBool HtmlLink::inLink(double xmin,double ymin,double xmax,double ymax) const {
++ double y=(ymin+ymax)/2;
++ if (y>Ymax) return gFalse;
++ return (y>Ymin)&&(xmin<Xmax)&&(xmax>Xmin);
++ }
++
++
++HtmlLink& HtmlLink::operator=(const HtmlLink& x){
++ if (this==&x) return *this;
++ if (dest) {delete dest;dest=NULL;}
++ Xmin=x.Xmin;
++ Ymin=x.Ymin;
++ Xmax=x.Xmax;
++ Ymax=x.Ymax;
++ dest=new GooString(x.dest);
++ return *this;
++}
++
++GooString* HtmlLink::getLinkStart() {
++ GooString *res = new GooString("<A href=\"");
++ res->append(dest);
++ res->append("\">");
++ return res;
++}
++
++/*GooString* HtmlLink::Link(GooString* content){
++ //GooString* _dest=new GooString(dest);
++ GooString *tmp=new GooString("<a href=\"");
++ tmp->append(dest);
++ tmp->append("\">");
++ tmp->append(content);
++ tmp->append("</a>");
++ //delete _dest;
++ return tmp;
++ }*/
++
++
++
++HtmlLinks::HtmlLinks(){
++ accu=new GVector<HtmlLink>();
++}
++
++HtmlLinks::~HtmlLinks(){
++ delete accu;
++ accu=NULL;
++}
++
++GBool HtmlLinks::inLink(double xmin,double ymin,double xmax,double ymax,int& p)const {
++
++ for(GVector<HtmlLink>::iterator i=accu->begin();i!=accu->end();i++){
++ if (i->inLink(xmin,ymin,xmax,ymax)) {
++ p=(i - accu->begin());
++ return 1;
++ }
++ }
++ return 0;
++}
++
++HtmlLink* HtmlLinks::getLink(int i) const{
++ GVector<HtmlLink>::iterator g=accu->begin();
++ g+=i;
++ return g;
++}
++
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/HtmlLinks.h poppler-0.4.3/utils/HtmlLinks.h
+--- poppler-0.4.3.orig/utils/HtmlLinks.h 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/HtmlLinks.h 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,47 @@
++#ifndef _HTML_LINKS
++#define _HTML_LINKS
++
++#include "GVector.h"
++#include "goo/GooString.h"
++
++class HtmlLink{
++
++private:
++ double Xmin;
++ double Ymin;
++ double Xmax;
++ double Ymax;
++ GooString* dest;
++
++public:
++ HtmlLink(){dest=NULL;}
++ HtmlLink(const HtmlLink& x);
++ HtmlLink& operator=(const HtmlLink& x);
++ HtmlLink(double xmin,double ymin,double xmax,double ymax,GooString *_dest);
++ ~HtmlLink();
++ GBool HtmlLink::isEqualDest(const HtmlLink& x) const;
++ GooString *getDest(){return new GooString(dest);}
++ double getX1() const {return Xmin;}
++ double getX2() const {return Xmax;}
++ double getY1() const {return Ymin;}
++ double getY2() const {return Ymax;}
++ GBool inLink(double xmin,double ymin,double xmax,double ymax) const ;
++ //GooString *Link(GooString *content);
++ GooString* getLinkStart();
++
++};
++
++class HtmlLinks{
++private:
++ GVector<HtmlLink> *accu;
++public:
++ HtmlLinks();
++ ~HtmlLinks();
++ void AddLink(const HtmlLink& x) {accu->push_back(x);}
++ GBool inLink(double xmin,double ymin,double xmax,double ymax,int& p) const;
++ HtmlLink* getLink(int i) const;
++
++};
++
++#endif
++
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/HtmlOutputDev.cc poppler-0.4.3/utils/HtmlOutputDev.cc
+--- poppler-0.4.3.orig/utils/HtmlOutputDev.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/HtmlOutputDev.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,1569 @@
++//========================================================================
++//
++// HtmlOutputDev.cc
++//
++// Copyright 1997-2002 Glyph & Cog, LLC
++//
++// Changed 1999-2000 by G.Ovtcharov
++//
++// Changed 2002 by Mikhail Kruk
++//
++//========================================================================
++
++#ifdef __GNUC__
++#pragma implementation
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <stddef.h>
++#include <ctype.h>
++#include <math.h>
++#include "goo/GooString.h"
++#include "goo/GooList.h"
++#include "UnicodeMap.h"
++#include "goo/gmem.h"
++#include "config.h"
++#include "Error.h"
++#include "GfxState.h"
++#include "DCTStream.h"
++#include "GlobalParams.h"
++#include "HtmlOutputDev.h"
++#include "HtmlFonts.h"
++
++int HtmlPage::pgNum=0;
++int HtmlOutputDev::imgNum=1;
++
++extern double scale;
++extern GBool complexMode;
++extern GBool ignore;
++extern GBool printCommands;
++extern GBool printHtml;
++extern GBool noframes;
++extern GBool stout;
++extern GBool xml;
++extern GBool showHidden;
++extern GBool noMerge;
++
++static GooString* basename(GooString* str){
++
++ char *p=str->getCString();
++ int len=str->getLength();
++ for (int i=len-1;i>=0;i--)
++ if (*(p+i)==SLASH)
++ return new GooString((p+i+1),len-i-1);
++ return new GooString(str);
++}
++
++static GooString* Dirname(GooString* str){
++
++ char *p=str->getCString();
++ int len=str->getLength();
++ for (int i=len-1;i>=0;i--)
++ if (*(p+i)==SLASH)
++ return new GooString(p,i+1);
++ return new GooString();
++}
++
++//------------------------------------------------------------------------
++// HtmlString
++//------------------------------------------------------------------------
++
++HtmlString::HtmlString(GfxState *state, double fontSize, HtmlFontAccu* fonts) {
++ GfxFont *font;
++ double x, y;
++
++ state->transform(state->getCurX(), state->getCurY(), &x, &y);
++ if ((font = state->getFont())) {
++ yMin = y - font->getAscent() * fontSize;
++ yMax = y - font->getDescent() * fontSize;
++ GfxRGB rgb;
++ state->getFillRGB(&rgb);
++ GooString *name = state->getFont()->getName();
++ if (!name) name = HtmlFont::getDefaultFont(); //new GooString("default");
++ HtmlFont hfont=HtmlFont(name, static_cast<int>(fontSize-1), rgb);
++ fontpos = fonts->AddFont(hfont);
++ } else {
++ // this means that the PDF file draws text without a current font,
++ // which should never happen
++ yMin = y - 0.95 * fontSize;
++ yMax = y + 0.35 * fontSize;
++ fontpos=0;
++ }
++ if (yMin == yMax) {
++ // this is a sanity check for a case that shouldn't happen -- but
++ // if it does happen, we want to avoid dividing by zero later
++ yMin = y;
++ yMax = y + 1;
++ }
++ col = 0;
++ text = NULL;
++ xRight = NULL;
++ link = NULL;
++ len = size = 0;
++ yxNext = NULL;
++ xyNext = NULL;
++ htext=new GooString();
++ dir = textDirUnknown;
++}
++
++
++HtmlString::~HtmlString() {
++ delete text;
++ delete htext;
++ gfree(xRight);
++}
++
++void HtmlString::addChar(GfxState *state, double x, double y,
++ double dx, double dy, Unicode u) {
++ if (dir == textDirUnknown) {
++ //dir = UnicodeMap::getDirection(u);
++ dir = textDirLeftRight;
++ }
++
++ if (len == size) {
++ size += 16;
++ text = (Unicode *)grealloc(text, size * sizeof(Unicode));
++ xRight = (double *)grealloc(xRight, size * sizeof(double));
++ }
++ text[len] = u;
++ if (len == 0) {
++ xMin = x;
++ }
++ xMax = xRight[len] = x + dx;
++//printf("added char: %f %f xright = %f\n", x, dx, x+dx);
++ ++len;
++}
++
++void HtmlString::endString()
++{
++ if( dir == textDirRightLeft && len > 1 )
++ {
++ //printf("will reverse!\n");
++ for (int i = 0; i < len / 2; i++)
++ {
++ Unicode ch = text[i];
++ text[i] = text[len - i - 1];
++ text[len - i - 1] = ch;
++ }
++ }
++}
++
++//------------------------------------------------------------------------
++// HtmlPage
++//------------------------------------------------------------------------
++
++HtmlPage::HtmlPage(GBool rawOrder, char *imgExtVal) {
++ this->rawOrder = rawOrder;
++ curStr = NULL;
++ yxStrings = NULL;
++ xyStrings = NULL;
++ yxCur1 = yxCur2 = NULL;
++ fonts=new HtmlFontAccu();
++ links=new HtmlLinks();
++ pageWidth=0;
++ pageHeight=0;
++ fontsPageMarker = 0;
++ DocName=NULL;
++ firstPage = -1;
++ imgExt = new GooString(imgExtVal);
++}
++
++HtmlPage::~HtmlPage() {
++ clear();
++ if (DocName) delete DocName;
++ if (fonts) delete fonts;
++ if (links) delete links;
++ if (imgExt) delete imgExt;
++}
++
++void HtmlPage::updateFont(GfxState *state) {
++ GfxFont *font;
++ double *fm;
++ char *name;
++ int code;
++ double w;
++
++ // adjust the font size
++ fontSize = state->getTransformedFontSize();
++ if ((font = state->getFont()) && font->getType() == fontType3) {
++ // This is a hack which makes it possible to deal with some Type 3
++ // fonts. The problem is that it's impossible to know what the
++ // base coordinate system used in the font is without actually
++ // rendering the font. This code tries to guess by looking at the
++ // width of the character 'm' (which breaks if the font is a
++ // subset that doesn't contain 'm').
++ for (code = 0; code < 256; ++code) {
++ if ((name = ((Gfx8BitFont *)font)->getCharName(code)) &&
++ name[0] == 'm' && name[1] == '\0') {
++ break;
++ }
++ }
++ if (code < 256) {
++ w = ((Gfx8BitFont *)font)->getWidth(code);
++ if (w != 0) {
++ // 600 is a generic average 'm' width -- yes, this is a hack
++ fontSize *= w / 0.6;
++ }
++ }
++ fm = font->getFontMatrix();
++ if (fm[0] != 0) {
++ fontSize *= fabs(fm[3] / fm[0]);
++ }
++ }
++}
++
++void HtmlPage::beginString(GfxState *state, GooString *s) {
++ curStr = new HtmlString(state, fontSize, fonts);
++}
++
++
++void HtmlPage::conv(){
++ HtmlString *tmp;
++
++ int linkIndex = 0;
++ HtmlFont* h;
++ for(tmp=yxStrings;tmp;tmp=tmp->yxNext){
++ int pos=tmp->fontpos;
++ // printf("%d\n",pos);
++ h=fonts->Get(pos);
++
++ if (tmp->htext) delete tmp->htext;
++ tmp->htext=HtmlFont::simple(h,tmp->text,tmp->len);
++
++ if (links->inLink(tmp->xMin,tmp->yMin,tmp->xMax,tmp->yMax, linkIndex)){
++ tmp->link = links->getLink(linkIndex);
++ /*GooString *t=tmp->htext;
++ tmp->htext=links->getLink(k)->Link(tmp->htext);
++ delete t;*/
++ }
++ }
++
++}
++
++
++void HtmlPage::addChar(GfxState *state, double x, double y,
++ double dx, double dy,
++ double ox, double oy, Unicode *u, int uLen) {
++ double x1, y1, w1, h1, dx2, dy2;
++ int n, i;
++ state->transform(x, y, &x1, &y1);
++ n = curStr->len;
++
++ // check that new character is in the same direction as current string
++ // and is not too far away from it before adding
++ //if ((UnicodeMap::getDirection(u[0]) != curStr->dir) ||
++ // XXX
++ if (
++ (n > 0 &&
++ fabs(x1 - curStr->xRight[n-1]) > 0.1 * (curStr->yMax - curStr->yMin))) {
++ endString();
++ beginString(state, NULL);
++ }
++ state->textTransformDelta(state->getCharSpace() * state->getHorizScaling(),
++ 0, &dx2, &dy2);
++ dx -= dx2;
++ dy -= dy2;
++ state->transformDelta(dx, dy, &w1, &h1);
++ if (uLen != 0) {
++ w1 /= uLen;
++ h1 /= uLen;
++ }
++ for (i = 0; i < uLen; ++i) {
++ curStr->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]);
++ }
++}
++
++void HtmlPage::endString() {
++ HtmlString *p1, *p2;
++ double h, y1, y2;
++
++ // throw away zero-length strings -- they don't have valid xMin/xMax
++ // values, and they're useless anyway
++ if (curStr->len == 0) {
++ delete curStr;
++ curStr = NULL;
++ return;
++ }
++
++ curStr->endString();
++
++#if 0 //~tmp
++ if (curStr->yMax - curStr->yMin > 20) {
++ delete curStr;
++ curStr = NULL;
++ return;
++ }
++#endif
++
++ // insert string in y-major list
++ h = curStr->yMax - curStr->yMin;
++ y1 = curStr->yMin + 0.5 * h;
++ y2 = curStr->yMin + 0.8 * h;
++ if (rawOrder) {
++ p1 = yxCur1;
++ p2 = NULL;
++ } else if ((!yxCur1 ||
++ (y1 >= yxCur1->yMin &&
++ (y2 >= yxCur1->yMax || curStr->xMax >= yxCur1->xMin))) &&
++ (!yxCur2 ||
++ (y1 < yxCur2->yMin ||
++ (y2 < yxCur2->yMax && curStr->xMax < yxCur2->xMin)))) {
++ p1 = yxCur1;
++ p2 = yxCur2;
++ } else {
++ for (p1 = NULL, p2 = yxStrings; p2; p1 = p2, p2 = p2->yxNext) {
++ if (y1 < p2->yMin || (y2 < p2->yMax && curStr->xMax < p2->xMin))
++ break;
++ }
++ yxCur2 = p2;
++ }
++ yxCur1 = curStr;
++ if (p1)
++ p1->yxNext = curStr;
++ else
++ yxStrings = curStr;
++ curStr->yxNext = p2;
++ curStr = NULL;
++}
++
++void HtmlPage::coalesce() {
++ HtmlString *str1, *str2;
++ HtmlFont *hfont1, *hfont2;
++ double space, horSpace, vertSpace, vertOverlap;
++ GBool addSpace, addLineBreak;
++ int n, i;
++ double curX, curY;
++
++#if 0 //~ for debugging
++ for (str1 = yxStrings; str1; str1 = str1->yxNext) {
++ printf("x=%f..%f y=%f..%f size=%2d '",
++ str1->xMin, str1->xMax, str1->yMin, str1->yMax,
++ (int)(str1->yMax - str1->yMin));
++ for (i = 0; i < str1->len; ++i) {
++ fputc(str1->text[i] & 0xff, stdout);
++ }
++ printf("'\n");
++ }
++ printf("\n------------------------------------------------------------\n\n");
++#endif
++ str1 = yxStrings;
++
++ if( !str1 ) return;
++
++ //----- discard duplicated text (fake boldface, drop shadows)
++ if( !complexMode )
++ { /* if not in complex mode get rid of duplicate strings */
++ HtmlString *str3;
++ GBool found;
++ while (str1)
++ {
++ double size = str1->yMax - str1->yMin;
++ double xLimit = str1->xMin + size * 0.2;
++ found = gFalse;
++ for (str2 = str1, str3 = str1->yxNext;
++ str3 && str3->xMin < xLimit;
++ str2 = str3, str3 = str2->yxNext)
++ {
++ if (str3->len == str1->len &&
++ !memcmp(str3->text, str1->text, str1->len * sizeof(Unicode)) &&
++ fabs(str3->yMin - str1->yMin) < size * 0.2 &&
++ fabs(str3->yMax - str1->yMax) < size * 0.2 &&
++ fabs(str3->xMax - str1->xMax) < size * 0.2)
++ {
++ found = gTrue;
++ //printf("found duplicate!\n");
++ break;
++ }
++ }
++ if (found)
++ {
++ str2->xyNext = str3->xyNext;
++ str2->yxNext = str3->yxNext;
++ delete str3;
++ }
++ else
++ {
++ str1 = str1->yxNext;
++ }
++ }
++ } /*- !complexMode */
++
++ str1 = yxStrings;
++
++ hfont1 = getFont(str1);
++ if( hfont1->isBold() )
++ str1->htext->insert(0,"<b>",3);
++ if( hfont1->isItalic() )
++ str1->htext->insert(0,"<i>",3);
++ if( str1->getLink() != NULL ) {
++ GooString *ls = str1->getLink()->getLinkStart();
++ str1->htext->insert(0, ls);
++ delete ls;
++ }
++ curX = str1->xMin; curY = str1->yMin;
++
++ while (str1 && (str2 = str1->yxNext)) {
++ hfont2 = getFont(str2);
++ space = str1->yMax - str1->yMin;
++ horSpace = str2->xMin - str1->xMax;
++ addLineBreak = !noMerge && (fabs(str1->xMin - str2->xMin) < 0.4);
++ vertSpace = str2->yMin - str1->yMax;
++
++//printf("coalesce %d %d %f? ", str1->dir, str2->dir, d);
++
++ if (str2->yMin >= str1->yMin && str2->yMin <= str1->yMax)
++ {
++ vertOverlap = str1->yMax - str2->yMin;
++ } else
++ if (str2->yMax >= str1->yMin && str2->yMax <= str1->yMax)
++ {
++ vertOverlap = str2->yMax - str1->yMin;
++ } else
++ {
++ vertOverlap = 0;
++ }
++
++ if (
++ (
++ (
++ (
++ (rawOrder && vertOverlap > 0.5 * space)
++ ||
++ (!rawOrder && str2->yMin < str1->yMax)
++ ) &&
++ (horSpace > -0.5 * space && horSpace < space)
++ ) ||
++ (vertSpace >= 0 && vertSpace < 0.5 * space && addLineBreak)
++ ) &&
++ (!complexMode || (hfont1->isEqualIgnoreBold(*hfont2))) && // in complex mode fonts must be the same, in other modes fonts do not metter
++ str1->dir == str2->dir // text direction the same
++ )
++ {
++// printf("yes\n");
++ n = str1->len + str2->len;
++ if ((addSpace = horSpace > 0.1 * space)) {
++ ++n;
++ }
++ if (addLineBreak) {
++ ++n;
++ }
++
++ str1->size = (n + 15) & ~15;
++ str1->text = (Unicode *)grealloc(str1->text,
++ str1->size * sizeof(Unicode));
++ str1->xRight = (double *)grealloc(str1->xRight,
++ str1->size * sizeof(double));
++ if (addSpace) {
++ str1->text[str1->len] = 0x20;
++ str1->htext->append(" ");
++ str1->xRight[str1->len] = str2->xMin;
++ ++str1->len;
++ }
++ if (addLineBreak) {
++ str1->text[str1->len] = '\n';
++ str1->htext->append("<br>");
++ str1->xRight[str1->len] = str2->xMin;
++ ++str1->len;
++ str1->yMin = str2->yMin;
++ str1->yMax = str2->yMax;
++ str1->xMax = str2->xMax;
++ int fontLineSize = hfont1->getLineSize();
++ int curLineSize = (int)(vertSpace + space);
++ if( curLineSize != fontLineSize )
++ {
++ HtmlFont *newfnt = new HtmlFont(*hfont1);
++ newfnt->setLineSize(curLineSize);
++ str1->fontpos = fonts->AddFont(*newfnt);
++ delete newfnt;
++ hfont1 = getFont(str1);
++ // we have to reget hfont2 because it's location could have
++ // changed on resize
++ hfont2 = getFont(str2);
++ }
++ }
++ for (i = 0; i < str2->len; ++i) {
++ str1->text[str1->len] = str2->text[i];
++ str1->xRight[str1->len] = str2->xRight[i];
++ ++str1->len;
++ }
++
++ /* fix <i> and <b> if str1 and str2 differ */
++ if( hfont1->isBold() && !hfont2->isBold() )
++ str1->htext->append("</b>", 4);
++ if( hfont1->isItalic() && !hfont2->isItalic() )
++ str1->htext->append("</i>", 4);
++ if( !hfont1->isBold() && hfont2->isBold() )
++ str1->htext->append("<b>", 3);
++ if( !hfont1->isItalic() && hfont2->isItalic() )
++ str1->htext->append("<i>", 3);
++
++ /* now handle switch of links */
++ HtmlLink *hlink1 = str1->getLink();
++ HtmlLink *hlink2 = str2->getLink();
++ if( !hlink1 || !hlink2 || !hlink1->isEqualDest(*hlink2) ) {
++ if(hlink1 != NULL )
++ str1->htext->append("</a>");
++ if(hlink2 != NULL ) {
++ GooString *ls = hlink2->getLinkStart();
++ str1->htext->append(ls);
++ delete ls;
++ }
++ }
++
++ str1->htext->append(str2->htext);
++ // str1 now contains href for link of str2 (if it is defined)
++ str1->link = str2->link;
++ hfont1 = hfont2;
++ if (str2->xMax > str1->xMax) {
++ str1->xMax = str2->xMax;
++ }
++ if (str2->yMax > str1->yMax) {
++ str1->yMax = str2->yMax;
++ }
++ str1->yxNext = str2->yxNext;
++ delete str2;
++ } else { // keep strings separate
++// printf("no\n");
++ if( hfont1->isBold() )
++ str1->htext->append("</b>",4);
++ if( hfont1->isItalic() )
++ str1->htext->append("</i>",4);
++ if(str1->getLink() != NULL )
++ str1->htext->append("</a>");
++
++ str1->xMin = curX; str1->yMin = curY;
++ str1 = str2;
++ curX = str1->xMin; curY = str1->yMin;
++ hfont1 = hfont2;
++ if( hfont1->isBold() )
++ str1->htext->insert(0,"<b>",3);
++ if( hfont1->isItalic() )
++ str1->htext->insert(0,"<i>",3);
++ if( str1->getLink() != NULL ) {
++ GooString *ls = str1->getLink()->getLinkStart();
++ str1->htext->insert(0, ls);
++ delete ls;
++ }
++ }
++ }
++ str1->xMin = curX; str1->yMin = curY;
++ if( hfont1->isBold() )
++ str1->htext->append("</b>",4);
++ if( hfont1->isItalic() )
++ str1->htext->append("</i>",4);
++ if(str1->getLink() != NULL )
++ str1->htext->append("</a>");
++
++#if 0 //~ for debugging
++ for (str1 = yxStrings; str1; str1 = str1->yxNext) {
++ printf("x=%3d..%3d y=%3d..%3d size=%2d ",
++ (int)str1->xMin, (int)str1->xMax, (int)str1->yMin, (int)str1->yMax,
++ (int)(str1->yMax - str1->yMin));
++ printf("'%s'\n", str1->htext->getCString());
++ }
++ printf("\n------------------------------------------------------------\n\n");
++#endif
++
++}
++
++void HtmlPage::dumpAsXML(FILE* f,int page){
++ fprintf(f, "<page number=\"%d\" position=\"absolute\"", page);
++ fprintf(f," top=\"0\" left=\"0\" height=\"%d\" width=\"%d\">\n", pageHeight,pageWidth);
++
++ for(int i=fontsPageMarker;i < fonts->size();i++) {
++ GooString *fontCSStyle = fonts->CSStyle(i);
++ fprintf(f,"\t%s\n",fontCSStyle->getCString());
++ delete fontCSStyle;
++ }
++
++ GooString *str, *str1;
++ for(HtmlString *tmp=yxStrings;tmp;tmp=tmp->yxNext){
++ if (tmp->htext){
++ str=new GooString(tmp->htext);
++ fprintf(f,"<text top=\"%d\" left=\"%d\" ",xoutRound(tmp->yMin),xoutRound(tmp->xMin));
++ fprintf(f,"width=\"%d\" height=\"%d\" ",xoutRound(tmp->xMax-tmp->xMin),xoutRound(tmp->yMax-tmp->yMin));
++ fprintf(f,"font=\"%d\">", tmp->fontpos);
++ if (tmp->fontpos!=-1){
++ str1=fonts->getCSStyle(tmp->fontpos, str);
++ }
++ fputs(str1->getCString(),f);
++ delete str;
++ delete str1;
++ fputs("</text>\n",f);
++ }
++ }
++ fputs("</page>\n",f);
++}
++
++
++void HtmlPage::dumpComplex(FILE *file, int page){
++ FILE* pageFile;
++ GooString* tmp;
++ char* htmlEncoding;
++
++ if( firstPage == -1 ) firstPage = page;
++
++ if( !noframes )
++ {
++ GooString* pgNum=GooString::fromInt(page);
++ tmp = new GooString(DocName);
++ tmp->append('-')->append(pgNum)->append(".html");
++ delete pgNum;
++
++ if (!(pageFile = fopen(getFileNameFromPath(tmp->getCString(),tmp->getLength()), "w"))) {
++ error(-1, "Couldn't open html file '%s'", tmp->getCString());
++ delete tmp;
++ return;
++ }
++ delete tmp;
++
++ fprintf(pageFile,"%s\n<HTML>\n<HEAD>\n<TITLE>Page %d</TITLE>\n\n",
++ DOCTYPE, page);
++
++ htmlEncoding = HtmlOutputDev::mapEncodingToHtml
++ (globalParams->getTextEncodingName());
++ fprintf(pageFile, "<META http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n", htmlEncoding);
++ }
++ else
++ {
++ pageFile = file;
++ fprintf(pageFile,"<!-- Page %d -->\n", page);
++ fprintf(pageFile,"<a name=\"%d\"></a>\n", page);
++ }
++
++ fprintf(pageFile,"<DIV style=\"position:relative;width:%d;height:%d;\">\n",
++ pageWidth, pageHeight);
++
++ tmp=basename(DocName);
++
++ fputs("<STYLE type=\"text/css\">\n<!--\n",pageFile);
++ for(int i=fontsPageMarker;i!=fonts->size();i++) {
++ GooString *fontCSStyle = fonts->CSStyle(i);
++ fprintf(pageFile,"\t%s\n",fontCSStyle->getCString());
++ delete fontCSStyle;
++ }
++
++ fputs("-->\n</STYLE>\n",pageFile);
++
++ if( !noframes )
++ {
++ fputs("</HEAD>\n<BODY bgcolor=\"#A0A0A0\" vlink=\"blue\" link=\"blue\">\n",pageFile);
++ }
++
++ if( !ignore )
++ {
++ fprintf(pageFile,
++ "<IMG width=\"%d\" height=\"%d\" src=\"%s%03d.%s\" alt=\"background image\">\n",
++ pageWidth, pageHeight, tmp->getCString(),
++ (page-firstPage+1), imgExt->getCString());
++ }
++
++ delete tmp;
++
++ GooString *str, *str1;
++ for(HtmlString *tmp1=yxStrings;tmp1;tmp1=tmp1->yxNext){
++ if (tmp1->htext){
++ str=new GooString(tmp1->htext);
++ fprintf(pageFile,
++ "<DIV style=\"position:absolute;top:%d;left:%d\">",
++ xoutRound(tmp1->yMin),
++ xoutRound(tmp1->xMin));
++ fputs("<nobr>",pageFile);
++ if (tmp1->fontpos!=-1){
++ str1=fonts->getCSStyle(tmp1->fontpos, str);
++ }
++ //printf("%s\n", str1->getCString());
++ fputs(str1->getCString(),pageFile);
++
++ delete str;
++ delete str1;
++ fputs("</nobr></DIV>\n",pageFile);
++ }
++ }
++
++ fputs("</DIV>\n", pageFile);
++
++ if( !noframes )
++ {
++ fputs("</BODY>\n</HTML>\n",pageFile);
++ fclose(pageFile);
++ }
++}
++
++
++void HtmlPage::dump(FILE *f, int pageNum)
++{
++ if (complexMode)
++ {
++ if (xml) dumpAsXML(f, pageNum);
++ if (!xml) dumpComplex(f, pageNum);
++ }
++ else
++ {
++ fprintf(f,"<A name=%d></a>",pageNum);
++ GooString* fName=basename(DocName);
++ for (int i=1;i<HtmlOutputDev::imgNum;i++)
++ fprintf(f,"<IMG src=\"%s-%d_%d.jpg\"><br>\n",fName->getCString(),pageNum,i);
++ HtmlOutputDev::imgNum=1;
++ delete fName;
++
++ GooString* str;
++ for(HtmlString *tmp=yxStrings;tmp;tmp=tmp->yxNext){
++ if (tmp->htext){
++ str=new GooString(tmp->htext);
++ fputs(str->getCString(),f);
++ delete str;
++ fputs("<br>\n",f);
++ }
++ }
++ fputs("<hr>\n",f);
++ }
++}
++
++
++
++void HtmlPage::clear() {
++ HtmlString *p1, *p2;
++
++ if (curStr) {
++ delete curStr;
++ curStr = NULL;
++ }
++ for (p1 = yxStrings; p1; p1 = p2) {
++ p2 = p1->yxNext;
++ delete p1;
++ }
++ yxStrings = NULL;
++ xyStrings = NULL;
++ yxCur1 = yxCur2 = NULL;
++
++ if( !noframes )
++ {
++ delete fonts;
++ fonts=new HtmlFontAccu();
++ fontsPageMarker = 0;
++ }
++ else
++ {
++ fontsPageMarker = fonts->size();
++ }
++
++ delete links;
++ links=new HtmlLinks();
++
++
++}
++
++void HtmlPage::setDocName(char *fname){
++ DocName=new GooString(fname);
++}
++
++//------------------------------------------------------------------------
++// HtmlMetaVar
++//------------------------------------------------------------------------
++
++HtmlMetaVar::HtmlMetaVar(char *_name, char *_content)
++{
++ name = new GooString(_name);
++ content = new GooString(_content);
++}
++
++HtmlMetaVar::~HtmlMetaVar()
++{
++ delete name;
++ delete content;
++}
++
++GooString* HtmlMetaVar::toString()
++{
++ GooString *result = new GooString("<META name=\"");
++ result->append(name);
++ result->append("\" content=\"");
++ result->append(content);
++ result->append("\">");
++ return result;
++}
++
++//------------------------------------------------------------------------
++// HtmlOutputDev
++//------------------------------------------------------------------------
++
++static char* HtmlEncodings[][2] = {
++ {"Latin1", "ISO-8859-1"},
++ {NULL, NULL}
++};
++
++
++char* HtmlOutputDev::mapEncodingToHtml(GooString* encoding)
++{
++ char* enc = encoding->getCString();
++ for(int i = 0; HtmlEncodings[i][0] != NULL; i++)
++ {
++ if( strcmp(enc, HtmlEncodings[i][0]) == 0 )
++ {
++ return HtmlEncodings[i][1];
++ }
++ }
++ return enc;
++}
++
++void HtmlOutputDev::doFrame(int firstPage){
++ GooString* fName=new GooString(Docname);
++ char* htmlEncoding;
++ fName->append(".html");
++
++ if (!(fContentsFrame = fopen(getFileNameFromPath(fName->getCString(),fName->getLength()), "w"))){
++ delete fName;
++ error(-1, "Couldn't open html file '%s'", fName->getCString());
++ return;
++ }
++
++ delete fName;
++
++ fName=basename(Docname);
++ fputs(DOCTYPE_FRAMES, fContentsFrame);
++ fputs("\n<HTML>",fContentsFrame);
++ fputs("\n<HEAD>",fContentsFrame);
++ fprintf(fContentsFrame,"\n<TITLE>%s</TITLE>",docTitle->getCString());
++ htmlEncoding = mapEncodingToHtml(globalParams->getTextEncodingName());
++ fprintf(fContentsFrame, "\n<META http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n", htmlEncoding);
++ dumpMetaVars(fContentsFrame);
++ fprintf(fContentsFrame, "</HEAD>\n");
++ fputs("<FRAMESET cols=\"100,*\">\n",fContentsFrame);
++ fprintf(fContentsFrame,"<FRAME name=\"links\" src=\"%s_ind.html\">\n",fName->getCString());
++ fputs("<FRAME name=\"contents\" src=",fContentsFrame);
++ if (complexMode)
++ fprintf(fContentsFrame,"\"%s-%d.html\"",fName->getCString(), firstPage);
++ else
++ fprintf(fContentsFrame,"\"%ss.html\"",fName->getCString());
++
++ fputs(">\n</FRAMESET>\n</HTML>\n",fContentsFrame);
++
++ delete fName;
++ fclose(fContentsFrame);
++}
++
++HtmlOutputDev::HtmlOutputDev(char *fileName, char *title,
++ char *author, char *keywords, char *subject, char *date,
++ char *extension,
++ GBool rawOrder, int firstPage, GBool outline)
++{
++ char *htmlEncoding;
++
++ fContentsFrame = NULL;
++ docTitle = new GooString(title);
++ pages = NULL;
++ dumpJPEG=gTrue;
++ //write = gTrue;
++ this->rawOrder = rawOrder;
++ this->doOutline = outline;
++ ok = gFalse;
++ imgNum=1;
++ //this->firstPage = firstPage;
++ //pageNum=firstPage;
++ // open file
++ needClose = gFalse;
++ pages = new HtmlPage(rawOrder, extension);
++
++ glMetaVars = new GooList();
++ glMetaVars->append(new HtmlMetaVar("generator", "pdftohtml 0.36"));
++ if( author ) glMetaVars->append(new HtmlMetaVar("author", author));
++ if( keywords ) glMetaVars->append(new HtmlMetaVar("keywords", keywords));
++ if( date ) glMetaVars->append(new HtmlMetaVar("date", date));
++ if( subject ) glMetaVars->append(new HtmlMetaVar("subject", subject));
++
++ maxPageWidth = 0;
++ maxPageHeight = 0;
++
++ pages->setDocName(fileName);
++ Docname=new GooString (fileName);
++
++ // for non-xml output (complex or simple) with frames generate the left frame
++ if(!xml && !noframes)
++ {
++ GooString* left=new GooString(fileName);
++ left->append("_ind.html");
++
++ doFrame(firstPage);
++
++ if (!(fContentsFrame = fopen(getFileNameFromPath(left->getCString(),left->getLength()), "w")))
++ {
++ error(-1, "Couldn't open html file '%s'", left->getCString());
++ delete left;
++ return;
++ }
++ delete left;
++ fputs(DOCTYPE, fContentsFrame);
++ fputs("<HTML>\n<HEAD>\n<TITLE></TITLE>\n</HEAD>\n<BODY>\n",fContentsFrame);
++
++ if (doOutline)
++ {
++ GooString *str = basename(Docname);
++ fprintf(fContentsFrame, "<A href=\"%s%s\" target=\"contents\">Outline</a><br>", str->getCString(), complexMode ? "-outline.html" : "s.html#outline");
++ delete str;
++ }
++
++ if (!complexMode)
++ { /* not in complex mode */
++
++ GooString* right=new GooString(fileName);
++ right->append("s.html");
++
++ if (!(page=fopen(getFileNameFromPath(right->getCString(),right->getLength()),"w"))){
++ error(-1, "Couldn't open html file '%s'", right->getCString());
++ delete right;
++ return;
++ }
++ delete right;
++ fputs(DOCTYPE, page);
++ fputs("<HTML>\n<HEAD>\n<TITLE></TITLE>\n</HEAD>\n<BODY>\n",page);
++ }
++ }
++
++ if (noframes) {
++ if (stout) page=stdout;
++ else {
++ GooString* right=new GooString(fileName);
++ if (!xml) right->append(".html");
++ if (xml) right->append(".xml");
++ if (!(page=fopen(getFileNameFromPath(right->getCString(),right->getLength()),"w"))){
++ delete right;
++ error(-1, "Couldn't open html file '%s'", right->getCString());
++ return;
++ }
++ delete right;
++ }
++
++ htmlEncoding = mapEncodingToHtml(globalParams->getTextEncodingName());
++ if (xml)
++ {
++ fprintf(page, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", htmlEncoding);
++ fputs("<!DOCTYPE pdf2xml SYSTEM \"pdf2xml.dtd\">\n\n", page);
++ fputs("<pdf2xml>\n",page);
++ }
++ else
++ {
++ fprintf(page,"%s\n<HTML>\n<HEAD>\n<TITLE>%s</TITLE>\n",
++ DOCTYPE, docTitle->getCString());
++
++ fprintf(page, "<META http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n", htmlEncoding);
++
++ dumpMetaVars(page);
++ fprintf(page,"</HEAD>\n");
++ fprintf(page,"<BODY bgcolor=\"#A0A0A0\" vlink=\"blue\" link=\"blue\">\n");
++ }
++ }
++ ok = gTrue;
++}
++
++HtmlOutputDev::~HtmlOutputDev() {
++ /*if (mode&&!xml){
++ int h=xoutRound(pages->pageHeight/scale);
++ int w=xoutRound(pages->pageWidth/scale);
++ fprintf(tin,"%s=%03d\n","PAPER_WIDTH",w);
++ fprintf(tin,"%s=%03d\n","PAPER_HEIGHT",h);
++ fclose(tin);
++ }*/
++
++ HtmlFont::clear();
++
++ delete Docname;
++ delete docTitle;
++
++ deleteGooList(glMetaVars, HtmlMetaVar);
++
++ if (fContentsFrame){
++ fputs("</BODY>\n</HTML>\n",fContentsFrame);
++ fclose(fContentsFrame);
++ }
++ if (xml) {
++ fputs("</pdf2xml>\n",page);
++ fclose(page);
++ } else
++ if ( !complexMode || xml || noframes )
++ {
++ fputs("</BODY>\n</HTML>\n",page);
++ fclose(page);
++ }
++ if (pages)
++ delete pages;
++}
++
++
++
++void HtmlOutputDev::startPage(int pageNum, GfxState *state) {
++ /*if (mode&&!xml){
++ if (write){
++ write=gFalse;
++ GooString* fname=Dirname(Docname);
++ fname->append("image.log");
++ if((tin=fopen(getFileNameFromPath(fname->getCString(),fname->getLength()),"w"))==NULL){
++ printf("Error : can not open %s",fname);
++ exit(1);
++ }
++ delete fname;
++ // if(state->getRotation()!=0)
++ // fprintf(tin,"ROTATE=%d rotate %d neg %d neg translate\n",state->getRotation(),state->getX1(),-state->getY1());
++ // else
++ fprintf(tin,"ROTATE=%d neg %d neg translate\n",state->getX1(),state->getY1());
++ }
++ }*/
++
++ this->pageNum = pageNum;
++ GooString *str=basename(Docname);
++ pages->clear();
++ if(!noframes)
++ {
++ if (fContentsFrame)
++ {
++ if (complexMode)
++ fprintf(fContentsFrame,"<A href=\"%s-%d.html\"",str->getCString(),pageNum);
++ else
++ fprintf(fContentsFrame,"<A href=\"%ss.html#%d\"",str->getCString(),pageNum);
++ fprintf(fContentsFrame," target=\"contents\" >Page %d</a><br>\n",pageNum);
++ }
++ }
++
++ pages->pageWidth=static_cast<int>(state->getPageWidth());
++ pages->pageHeight=static_cast<int>(state->getPageHeight());
++
++ delete str;
++}
++
++
++void HtmlOutputDev::endPage() {
++ pages->conv();
++ pages->coalesce();
++ pages->dump(page, pageNum);
++
++ // I don't yet know what to do in the case when there are pages of different
++ // sizes and we want complex output: running ghostscript many times
++ // seems very inefficient. So for now I'll just use last page's size
++ maxPageWidth = pages->pageWidth;
++ maxPageHeight = pages->pageHeight;
++
++ //if(!noframes&&!xml) fputs("<br>\n", fContentsFrame);
++ if(!stout && !globalParams->getErrQuiet()) printf("Page-%d\n",(pageNum));
++}
++
++void HtmlOutputDev::updateFont(GfxState *state) {
++ pages->updateFont(state);
++}
++
++void HtmlOutputDev::beginString(GfxState *state, GooString *s) {
++ pages->beginString(state, s);
++}
++
++void HtmlOutputDev::endString(GfxState *state) {
++ pages->endString();
++}
++
++void HtmlOutputDev::drawChar(GfxState *state, double x, double y,
++ double dx, double dy,
++ double originX, double originY,
++ CharCode code, Unicode *u, int uLen)
++{
++ if ( !showHidden && (state->getRender() & 3) == 3) {
++ return;
++ }
++ pages->addChar(state, x, y, dx, dy, originX, originY, u, uLen);
++}
++
++void HtmlOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GBool invert,
++ GBool inlineImg) {
++
++ int i, j;
++
++ if (ignore||complexMode) {
++ OutputDev::drawImageMask(state, ref, str, width, height, invert, inlineImg);
++ return;
++ }
++
++ FILE *f1;
++ int c;
++
++ int x0, y0; // top left corner of image
++ int w0, h0, w1, h1; // size of image
++ double xt, yt, wt, ht;
++ GBool rotate, xFlip, yFlip;
++ GBool dither;
++ int x, y;
++ int ix, iy;
++ int px1, px2, qx, dx;
++ int py1, py2, qy, dy;
++ Gulong pixel;
++ int nComps, nVals, nBits;
++ double r1, g1, b1;
++
++ // get image position and size
++ state->transform(0, 0, &xt, &yt);
++ state->transformDelta(1, 1, &wt, &ht);
++ if (wt > 0) {
++ x0 = xoutRound(xt);
++ w0 = xoutRound(wt);
++ } else {
++ x0 = xoutRound(xt + wt);
++ w0 = xoutRound(-wt);
++ }
++ if (ht > 0) {
++ y0 = xoutRound(yt);
++ h0 = xoutRound(ht);
++ } else {
++ y0 = xoutRound(yt + ht);
++ h0 = xoutRound(-ht);
++ }
++ state->transformDelta(1, 0, &xt, &yt);
++ rotate = fabs(xt) < fabs(yt);
++ if (rotate) {
++ w1 = h0;
++ h1 = w0;
++ xFlip = ht < 0;
++ yFlip = wt > 0;
++ } else {
++ w1 = w0;
++ h1 = h0;
++ xFlip = wt < 0;
++ yFlip = ht > 0;
++ }
++
++ // dump JPEG file
++ if (dumpJPEG && str->getKind() == strDCT) {
++ GooString *fName=new GooString(Docname);
++ fName->append("-");
++ GooString *pgNum=GooString::fromInt(pageNum);
++ GooString *imgnum=GooString::fromInt(imgNum);
++ // open the image file
++ fName->append(pgNum)->append("_")->append(imgnum)->append(".jpg");
++ ++imgNum;
++ if (!(f1 = fopen(getFileNameFromPath(fName->getCString(),fName->getLength()), "wb"))) {
++ error(-1, "Couldn't open image file '%s'", fName->getCString());
++ return;
++ }
++
++ // initialize stream
++ str = ((DCTStream *)str)->getRawStream();
++ str->reset();
++
++ // copy the stream
++ while ((c = str->getChar()) != EOF)
++ fputc(c, f1);
++
++ fclose(f1);
++
++ if (pgNum) delete pgNum;
++ if (imgnum) delete imgnum;
++ if (fName) delete fName;
++ }
++ else {
++ OutputDev::drawImageMask(state, ref, str, width, height, invert, inlineImg);
++ }
++}
++
++void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GfxImageColorMap *colorMap,
++ int *maskColors, GBool inlineImg) {
++
++ int i, j;
++
++ if (ignore||complexMode) {
++ OutputDev::drawImage(state, ref, str, width, height, colorMap,
++ maskColors, inlineImg);
++ return;
++ }
++
++ FILE *f1;
++ ImageStream *imgStr;
++ Guchar pixBuf[4];
++ GfxColor color;
++ int c;
++
++ int x0, y0; // top left corner of image
++ int w0, h0, w1, h1; // size of image
++ double xt, yt, wt, ht;
++ GBool rotate, xFlip, yFlip;
++ GBool dither;
++ int x, y;
++ int ix, iy;
++ int px1, px2, qx, dx;
++ int py1, py2, qy, dy;
++ Gulong pixel;
++ int nComps, nVals, nBits;
++ double r1, g1, b1;
++
++ // get image position and size
++ state->transform(0, 0, &xt, &yt);
++ state->transformDelta(1, 1, &wt, &ht);
++ if (wt > 0) {
++ x0 = xoutRound(xt);
++ w0 = xoutRound(wt);
++ } else {
++ x0 = xoutRound(xt + wt);
++ w0 = xoutRound(-wt);
++ }
++ if (ht > 0) {
++ y0 = xoutRound(yt);
++ h0 = xoutRound(ht);
++ } else {
++ y0 = xoutRound(yt + ht);
++ h0 = xoutRound(-ht);
++ }
++ state->transformDelta(1, 0, &xt, &yt);
++ rotate = fabs(xt) < fabs(yt);
++ if (rotate) {
++ w1 = h0;
++ h1 = w0;
++ xFlip = ht < 0;
++ yFlip = wt > 0;
++ } else {
++ w1 = w0;
++ h1 = h0;
++ xFlip = wt < 0;
++ yFlip = ht > 0;
++ }
++
++
++ /*if( !globalParams->getErrQuiet() )
++ printf("image stream of kind %d\n", str->getKind());*/
++ // dump JPEG file
++ if (dumpJPEG && str->getKind() == strDCT) {
++ GooString *fName=new GooString(Docname);
++ fName->append("-");
++ GooString *pgNum= GooString::fromInt(pageNum);
++ GooString *imgnum= GooString::fromInt(imgNum);
++
++ // open the image file
++ fName->append(pgNum)->append("_")->append(imgnum)->append(".jpg");
++ ++imgNum;
++
++ if (!(f1 = fopen(getFileNameFromPath(fName->getCString(),fName->getLength()), "wb"))) {
++ error(-1, "Couldn't open image file '%s'", fName->getCString());
++ return;
++ }
++
++ // initialize stream
++ str = ((DCTStream *)str)->getRawStream();
++ str->reset();
++
++ // copy the stream
++ while ((c = str->getChar()) != EOF)
++ fputc(c, f1);
++
++ fclose(f1);
++
++ delete fName;
++ delete pgNum;
++ delete imgnum;
++ }
++ else {
++ OutputDev::drawImage(state, ref, str, width, height, colorMap,
++ maskColors, inlineImg);
++ }
++}
++
++
++
++void HtmlOutputDev::drawLink(Link* link,Catalog *cat){
++ double _x1,_y1,_x2,_y2,w;
++ int x1,y1,x2,y2;
++
++ link->getRect(&_x1,&_y1,&_x2,&_y2);
++ w = link->getBorderStyle()->getWidth();
++ cvtUserToDev(_x1,_y1,&x1,&y1);
++
++ cvtUserToDev(_x2,_y2,&x2,&y2);
++
++
++ GooString* _dest=getLinkDest(link,cat);
++ HtmlLink t((double) x1,(double) y2,(double) x2,(double) y1,_dest);
++ pages->AddLink(t);
++ delete _dest;
++}
++
++GooString* HtmlOutputDev::getLinkDest(Link *link,Catalog* catalog){
++ char *p;
++ switch(link->getAction()->getKind())
++ {
++ case actionGoTo:
++ {
++ GooString* file=basename(Docname);
++ int page=1;
++ LinkGoTo *ha=(LinkGoTo *)link->getAction();
++ LinkDest *dest=NULL;
++ if (ha->getDest()==NULL)
++ dest=catalog->findDest(ha->getNamedDest());
++ else
++ dest=ha->getDest()->copy();
++ if (dest){
++ if (dest->isPageRef()){
++ Ref pageref=dest->getPageRef();
++ page=catalog->findPage(pageref.num,pageref.gen);
++ }
++ else {
++ page=dest->getPageNum();
++ }
++
++ delete dest;
++
++ GooString *str=GooString::fromInt(page);
++ /* complex simple
++ frames file-4.html files.html#4
++ noframes file.html#4 file.html#4
++ */
++ if (noframes)
++ {
++ file->append(".html#");
++ file->append(str);
++ }
++ else
++ {
++ if( complexMode )
++ {
++ file->append("-");
++ file->append(str);
++ file->append(".html");
++ }
++ else
++ {
++ file->append("s.html#");
++ file->append(str);
++ }
++ }
++
++ if (printCommands) printf(" link to page %d ",page);
++ delete str;
++ return file;
++ }
++ else
++ {
++ return new GooString();
++ }
++ }
++ case actionGoToR:
++ {
++ LinkGoToR *ha=(LinkGoToR *) link->getAction();
++ LinkDest *dest=NULL;
++ int page=1;
++ GooString *file=new GooString();
++ if (ha->getFileName()){
++ delete file;
++ file=new GooString(ha->getFileName()->getCString());
++ }
++ if (ha->getDest()!=NULL) dest=ha->getDest()->copy();
++ if (dest&&file){
++ if (!(dest->isPageRef())) page=dest->getPageNum();
++ delete dest;
++
++ if (printCommands) printf(" link to page %d ",page);
++ if (printHtml){
++ p=file->getCString()+file->getLength()-4;
++ if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")){
++ file->del(file->getLength()-4,4);
++ file->append(".html");
++ }
++ file->append('#');
++ file->append(GooString::fromInt(page));
++ }
++ }
++ if (printCommands) printf("filename %s\n",file->getCString());
++ return file;
++ }
++ case actionURI:
++ {
++ LinkURI *ha=(LinkURI *) link->getAction();
++ GooString* file=new GooString(ha->getURI()->getCString());
++ // printf("uri : %s\n",file->getCString());
++ return file;
++ }
++ case actionLaunch:
++ {
++ LinkLaunch *ha=(LinkLaunch *) link->getAction();
++ GooString* file=new GooString(ha->getFileName()->getCString());
++ if (printHtml) {
++ p=file->getCString()+file->getLength()-4;
++ if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")){
++ file->del(file->getLength()-4,4);
++ file->append(".html");
++ }
++ if (printCommands) printf("filename %s",file->getCString());
++
++ return file;
++
++ }
++ }
++ default:
++ return new GooString();
++ }
++}
++
++void HtmlOutputDev::dumpMetaVars(FILE *file)
++{
++ GooString *var;
++
++ for(int i = 0; i < glMetaVars->getLength(); i++)
++ {
++ HtmlMetaVar *t = (HtmlMetaVar*)glMetaVars->get(i);
++ var = t->toString();
++ fprintf(file, "%s\n", var->getCString());
++ delete var;
++ }
++}
++
++GBool HtmlOutputDev::dumpDocOutline(Catalog* catalog)
++{
++ FILE * output;
++ GBool bClose = gFalse;
++
++ if (!ok || xml)
++ return gFalse;
++
++ Object *outlines = catalog->getOutline();
++ if (!outlines->isDict())
++ return gFalse;
++
++ if (!complexMode && !xml)
++ {
++ output = page;
++ }
++ else if (complexMode && !xml)
++ {
++ if (noframes)
++ {
++ output = page;
++ fputs("<hr>\n", output);
++ }
++ else
++ {
++ GooString *str = basename(Docname);
++ str->append("-outline.html");
++ output = fopen(getFileNameFromPath(str->getCString(),str->getLength()), "w");
++ if (output == NULL)
++ return gFalse;
++ delete str;
++ bClose = gTrue;
++ fputs("<HTML>\n<HEAD>\n<TITLE>Document Outline</TITLE>\n</HEAD>\n<BODY>\n", output);
++ }
++ }
++
++ GBool done = newOutlineLevel(output, outlines, catalog);
++ if (done && !complexMode)
++ fputs("<hr>\n", output);
++
++ if (bClose)
++ {
++ fputs("</BODY>\n</HTML>\n", output);
++ fclose(output);
++ }
++ return done;
++}
++
++GBool HtmlOutputDev::newOutlineLevel(FILE *output, Object *node, Catalog* catalog, int level)
++{
++ Object curr, next;
++ GBool atLeastOne = gFalse;
++
++ if (node->dictLookup("First", &curr)->isDict()) {
++ if (level == 1)
++ {
++ fputs("<A name=\"outline\"></a>", output);
++ fputs("<h1>Document Outline</h1>\n", output);
++ }
++ fputs("<ul>",output);
++ do {
++ // get title, give up if not found
++ Object title;
++ if (curr.dictLookup("Title", &title)->isNull()) {
++ title.free();
++ break;
++ }
++ GooString *titleStr = new GooString(title.getString());
++ title.free();
++
++ // get corresponding link
++ // Note: some code duplicated from HtmlOutputDev::getLinkDest().
++ GooString *linkName = NULL;;
++ Object dest;
++ if (!curr.dictLookup("Dest", &dest)->isNull()) {
++ LinkGoTo *link = new LinkGoTo(&dest);
++ LinkDest *linkdest=NULL;
++ if (link->getDest()==NULL)
++ linkdest=catalog->findDest(link->getNamedDest());
++ else
++ linkdest=link->getDest()->copy();
++ delete link;
++ if (linkdest) {
++ int page;
++ if (linkdest->isPageRef()) {
++ Ref pageref=linkdest->getPageRef();
++ page=catalog->findPage(pageref.num,pageref.gen);
++ } else {
++ page=linkdest->getPageNum();
++ }
++ delete linkdest;
++
++ /* complex simple
++ frames file-4.html files.html#4
++ noframes file.html#4 file.html#4
++ */
++ linkName=basename(Docname);
++ GooString *str=GooString::fromInt(page);
++ if (noframes) {
++ linkName->append(".html#");
++ linkName->append(str);
++ } else {
++ if( complexMode ) {
++ linkName->append("-");
++ linkName->append(str);
++ linkName->append(".html");
++ } else {
++ linkName->append("s.html#");
++ linkName->append(str);
++ }
++ }
++ delete str;
++ }
++ }
++ dest.free();
++
++ fputs("<li>",output);
++ if (linkName)
++ fprintf(output,"<A href=\"%s\">", linkName->getCString());
++ fputs(titleStr->getCString(),output);
++ if (linkName) {
++ fputs("</A>",output);
++ delete linkName;
++ }
++ fputs("\n",output);
++ delete titleStr;
++ atLeastOne = gTrue;
++
++ newOutlineLevel(output, &curr, catalog, level+1);
++ curr.dictLookup("Next", &next);
++ curr.free();
++ curr = next;
++ } while(curr.isDict());
++ fputs("</ul>",output);
++ }
++ curr.free();
++
++ return atLeastOne;
++}
++
++char* getFileNameFromPath(char* c, int strlen) {
++ int last_slash_index = 0;
++ int i = 0;
++ char* res;
++
++ for (i=0;i<strlen;i++) {
++ if (*(c+i)=='/') {
++ /* printf("/ detected\n"); */
++ last_slash_index = i;
++ }
++ }
++ res = (char *)malloc(sizeof(char)*strlen-last_slash_index+1);
++ strcpy(res,c+last_slash_index+(last_slash_index?1:0));
++ /* printf("Fil: %s\n",res); */
++ return res;
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/HtmlOutputDev.h poppler-0.4.3/utils/HtmlOutputDev.h
+--- poppler-0.4.3.orig/utils/HtmlOutputDev.h 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/HtmlOutputDev.h 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,302 @@
++//========================================================================
++//
++// HtmlOutputDev.h
++//
++// Copyright 1997 Derek B. Noonburg
++//
++// Changed 1999 by G.Ovtcharov
++//========================================================================
++
++#ifndef HTMLOUTPUTDEV_H
++#define HTMLOUTPUTDEV_H
++
++#ifdef __GNUC__
++#pragma interface
++#endif
++
++#include <stdio.h>
++#include "goo/gtypes.h"
++#include "goo/GooList.h"
++#include "GfxFont.h"
++#include "OutputDev.h"
++#include "HtmlLinks.h"
++#include "HtmlFonts.h"
++#include "Link.h"
++#include "Catalog.h"
++#include "UnicodeMap.h"
++
++
++#ifdef WIN32
++# define SLASH '\\'
++#else
++# define SLASH '/'
++#endif
++
++#define xoutRound(x) ((int)(x + 0.5))
++
++#define DOCTYPE "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"
++#define DOCTYPE_FRAMES "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\"\n\"http://www.w3.org/TR/html4/frameset.dtd\">"
++
++class GfxState;
++class GooString;
++//------------------------------------------------------------------------
++// HtmlString
++//------------------------------------------------------------------------
++
++enum UnicodeTextDirection {
++ textDirUnknown,
++ textDirLeftRight,
++ textDirRightLeft,
++ textDirTopBottom
++};
++
++
++class HtmlString {
++public:
++
++ // Constructor.
++ HtmlString(GfxState *state, double fontSize, HtmlFontAccu* fonts);
++
++ // Destructor.
++ ~HtmlString();
++
++ // Add a character to the string.
++ void addChar(GfxState *state, double x, double y,
++ double dx, double dy,
++ Unicode u);
++ HtmlLink* getLink() { return link; }
++ void endString(); // postprocessing
++
++private:
++// aender die text variable
++ HtmlLink *link;
++ double xMin, xMax; // bounding box x coordinates
++ double yMin, yMax; // bounding box y coordinates
++ int col; // starting column
++ Unicode *text; // the text
++ double *xRight; // right-hand x coord of each char
++ HtmlString *yxNext; // next string in y-major order
++ HtmlString *xyNext; // next string in x-major order
++ int fontpos;
++ GooString* htext;
++ int len; // length of text and xRight
++ int size; // size of text and xRight arrays
++ UnicodeTextDirection dir; // direction (left to right/right to left)
++
++ friend class HtmlPage;
++
++};
++
++
++//------------------------------------------------------------------------
++// HtmlPage
++//------------------------------------------------------------------------
++
++
++
++class HtmlPage {
++public:
++
++ // Constructor.
++ HtmlPage(GBool rawOrder, char *imgExtVal);
++
++ // Destructor.
++ ~HtmlPage();
++
++ // Begin a new string.
++ void beginString(GfxState *state, GooString *s);
++
++ // Add a character to the current string.
++ void addChar(GfxState *state, double x, double y,
++ double dx, double dy,
++ double ox, double oy,
++ Unicode *u, int uLen); //Guchar c);
++
++ void updateFont(GfxState *state);
++
++ // End the current string, sorting it into the list of strings.
++ void endString();
++
++ // Coalesce strings that look like parts of the same line.
++ void coalesce();
++
++ // Find a string. If <top> is true, starts looking at top of page;
++ // otherwise starts looking at <xMin>,<yMin>. If <bottom> is true,
++ // stops looking at bottom of page; otherwise stops looking at
++ // <xMax>,<yMax>. If found, sets the text bounding rectange and
++ // returns true; otherwise returns false.
++
++
++ // new functions
++ void AddLink(const HtmlLink& x){
++ links->AddLink(x);
++ }
++
++ void dump(FILE *f, int pageNum);
++
++ // Clear the page.
++ void clear();
++
++ void conv();
++private:
++ HtmlFont* getFont(HtmlString *hStr) { return fonts->Get(hStr->fontpos); }
++
++ double fontSize; // current font size
++ GBool rawOrder; // keep strings in content stream order
++
++ HtmlString *curStr; // currently active string
++
++ HtmlString *yxStrings; // strings in y-major order
++ HtmlString *xyStrings; // strings in x-major order
++ HtmlString *yxCur1, *yxCur2; // cursors for yxStrings list
++
++ void setDocName(char* fname);
++ void dumpAsXML(FILE* f,int page);
++ void dumpComplex(FILE* f, int page);
++
++ // marks the position of the fonts that belong to current page (for noframes)
++ int fontsPageMarker;
++ HtmlFontAccu *fonts;
++ HtmlLinks *links;
++
++ GooString *DocName;
++ GooString *imgExt;
++ int pageWidth;
++ int pageHeight;
++ static int pgNum;
++ int firstPage; // used to begin the numeration of pages
++
++ friend class HtmlOutputDev;
++};
++
++//------------------------------------------------------------------------
++// HtmlMetaVar
++//------------------------------------------------------------------------
++class HtmlMetaVar {
++public:
++ HtmlMetaVar(char *_name, char *_content);
++ ~HtmlMetaVar();
++
++ GooString* toString();
++
++private:
++
++ GooString *name;
++ GooString *content;
++};
++
++//------------------------------------------------------------------------
++// HtmlOutputDev
++//------------------------------------------------------------------------
++
++class HtmlOutputDev: public OutputDev {
++public:
++
++ // Open a text output file. If <fileName> is NULL, no file is written
++ // (this is useful, e.g., for searching text). If <useASCII7> is true,
++ // text is converted to 7-bit ASCII; otherwise, text is converted to
++ // 8-bit ISO Latin-1. <useASCII7> should also be set for Japanese
++ // (EUC-JP) text. If <rawOrder> is true, the text is kept in content
++ // stream order.
++ HtmlOutputDev(char *fileName, char *title,
++ char *author,
++ char *keywords,
++ char *subject,
++ char *date,
++ char *extension,
++ GBool rawOrder,
++ int firstPage = 1,
++ GBool outline = 0);
++
++ // Destructor.
++ virtual ~HtmlOutputDev();
++
++ // Check if file was successfully created.
++ virtual GBool isOk() { return ok; }
++
++ //---- get info about output device
++
++ // Does this device use upside-down coordinates?
++ // (Upside-down means (0,0) is the top left corner of the page.)
++ virtual GBool upsideDown() { return gTrue; }
++
++ // Does this device use drawChar() or drawString()?
++ virtual GBool useDrawChar() { return gTrue; }
++
++ // Does this device use beginType3Char/endType3Char? Otherwise,
++ // text in Type 3 fonts will be drawn with drawChar/drawString.
++ virtual GBool interpretType3Chars() { return gFalse; }
++
++ // Does this device need non-text content?
++ virtual GBool needNonText() { return gFalse; }
++
++ //----- initialization and control
++
++ // Start a page.
++ virtual void startPage(int pageNum, GfxState *state);
++
++ // End a page.
++ virtual void endPage();
++
++ //----- update text state
++ virtual void updateFont(GfxState *state);
++
++ //----- text drawing
++ virtual void beginString(GfxState *state, GooString *s);
++ virtual void endString(GfxState *state);
++ virtual void drawChar(GfxState *state, double x, double y,
++ double dx, double dy,
++ double originX, double originY,
++ CharCode code, Unicode *u, int uLen);
++
++ virtual void drawImageMask(GfxState *state, Object *ref,
++ Stream *str,
++ int width, int height, GBool invert,
++ GBool inlineImg);
++ virtual void drawImage(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GfxImageColorMap *colorMap,
++ int *maskColors, GBool inlineImg);
++
++ //new feature
++ virtual int DevType() {return 1234;}
++ virtual void drawLink(Link *link,Catalog *cat);
++
++ int getPageWidth() { return maxPageWidth; }
++ int getPageHeight() { return maxPageHeight; }
++
++ GBool dumpDocOutline(Catalog* catalog);
++
++ /* char* getFileNameFromPath(char* c, int strlen); */
++
++private:
++ // convert encoding into a HTML standard, or encoding->getCString if not
++ // recognized
++ static char* mapEncodingToHtml(GooString* encoding);
++ GooString* getLinkDest(Link *link,Catalog *catalog);
++ void dumpMetaVars(FILE *);
++ void doFrame(int firstPage);
++ GBool newOutlineLevel(FILE *output, Object *node, Catalog* catalog, int level = 1);
++
++ FILE *fContentsFrame;
++ FILE *page; // html file
++ //FILE *tin; // image log file
++ //GBool write;
++ GBool needClose; // need to close the file?
++ HtmlPage *pages; // text for the current page
++ GBool rawOrder; // keep text in content stream order
++ GBool doOutline; // output document outline
++ GBool ok; // set up ok?
++ GBool dumpJPEG;
++ int pageNum;
++ int maxPageWidth;
++ int maxPageHeight;
++ static int imgNum;
++ GooString *Docname;
++ GooString *docTitle;
++ GooList *glMetaVars;
++ friend class HtmlPage;
++};
++
++char* getFileNameFromPath(char* c, int strlen);
++
++#endif
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/ImageOutputDev.cc poppler-0.4.3/utils/ImageOutputDev.cc
+--- poppler-0.4.3.orig/utils/ImageOutputDev.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/ImageOutputDev.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,195 @@
++//========================================================================
++//
++// ImageOutputDev.cc
++//
++// Copyright 1998-2003 Glyph & Cog, LLC
++//
++//========================================================================
++
++#include <poppler-config.h>
++
++#ifdef USE_GCC_PRAGMAS
++#pragma implementation
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stddef.h>
++#include <ctype.h>
++#include "goo/gmem.h"
++#include "config.h"
++#include "Error.h"
++#include "GfxState.h"
++#include "Object.h"
++#include "Stream.h"
++#include "DCTStream.h"
++#include "ImageOutputDev.h"
++
++ImageOutputDev::ImageOutputDev(char *fileRootA, GBool dumpJPEGA) {
++ fileRoot = copyString(fileRootA);
++ fileName = (char *)gmalloc(strlen(fileRoot) + 20);
++ dumpJPEG = dumpJPEGA;
++ imgNum = 0;
++ ok = gTrue;
++}
++
++ImageOutputDev::~ImageOutputDev() {
++ gfree(fileName);
++ gfree(fileRoot);
++}
++
++void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GBool invert,
++ GBool inlineImg) {
++ FILE *f;
++ int c;
++ int size, i;
++
++ // dump JPEG file
++ if (dumpJPEG && str->getKind() == strDCT && !inlineImg) {
++
++ // open the image file
++ sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum);
++ ++imgNum;
++ if (!(f = fopen(fileName, "wb"))) {
++ error(-1, "Couldn't open image file '%s'", fileName);
++ return;
++ }
++
++ // initialize stream
++ str = ((DCTStream *)str)->getRawStream();
++ str->reset();
++
++ // copy the stream
++ while ((c = str->getChar()) != EOF)
++ fputc(c, f);
++
++ str->close();
++ fclose(f);
++
++ // dump PBM file
++ } else {
++
++ // open the image file and write the PBM header
++ sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum);
++ ++imgNum;
++ if (!(f = fopen(fileName, "wb"))) {
++ error(-1, "Couldn't open image file '%s'", fileName);
++ return;
++ }
++ fprintf(f, "P4\n");
++ fprintf(f, "%d %d\n", width, height);
++
++ // initialize stream
++ str->reset();
++
++ // copy the stream
++ size = height * ((width + 7) / 8);
++ for (i = 0; i < size; ++i) {
++ fputc(str->getChar(), f);
++ }
++
++ str->close();
++ fclose(f);
++ }
++}
++
++void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
++ int width, int height,
++ GfxImageColorMap *colorMap,
++ int *maskColors, GBool inlineImg) {
++ FILE *f;
++ ImageStream *imgStr;
++ Guchar *p;
++ GfxRGB rgb;
++ int x, y;
++ int c;
++ int size, i;
++
++ // dump JPEG file
++ if (dumpJPEG && str->getKind() == strDCT &&
++ colorMap->getNumPixelComps() == 3 &&
++ !inlineImg) {
++
++ // open the image file
++ sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum);
++ ++imgNum;
++ if (!(f = fopen(fileName, "wb"))) {
++ error(-1, "Couldn't open image file '%s'", fileName);
++ return;
++ }
++
++ // initialize stream
++ str = ((DCTStream *)str)->getRawStream();
++ str->reset();
++
++ // copy the stream
++ while ((c = str->getChar()) != EOF)
++ fputc(c, f);
++
++ str->close();
++ fclose(f);
++
++ // dump PBM file
++ } else if (colorMap->getNumPixelComps() == 1 &&
++ colorMap->getBits() == 1) {
++
++ // open the image file and write the PBM header
++ sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum);
++ ++imgNum;
++ if (!(f = fopen(fileName, "wb"))) {
++ error(-1, "Couldn't open image file '%s'", fileName);
++ return;
++ }
++ fprintf(f, "P4\n");
++ fprintf(f, "%d %d\n", width, height);
++
++ // initialize stream
++ str->reset();
++
++ // copy the stream
++ size = height * ((width + 7) / 8);
++ for (i = 0; i < size; ++i) {
++ fputc(str->getChar() ^ 0xff, f);
++ }
++
++ str->close();
++ fclose(f);
++
++ // dump PPM file
++ } else {
++
++ // open the image file and write the PPM header
++ sprintf(fileName, "%s-%03d.ppm", fileRoot, imgNum);
++ ++imgNum;
++ if (!(f = fopen(fileName, "wb"))) {
++ error(-1, "Couldn't open image file '%s'", fileName);
++ return;
++ }
++ fprintf(f, "P6\n");
++ fprintf(f, "%d %d\n", width, height);
++ fprintf(f, "255\n");
++
++ // initialize stream
++ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
++ colorMap->getBits());
++ imgStr->reset();
++
++ // for each line...
++ for (y = 0; y < height; ++y) {
++
++ // write the line
++ p = imgStr->getLine();
++ for (x = 0; x < width; ++x) {
++ colorMap->getRGB(p, &rgb);
++ fputc((int)(rgb.r * 255 + 0.5), f);
++ fputc((int)(rgb.g * 255 + 0.5), f);
++ fputc((int)(rgb.b * 255 + 0.5), f);
++ p += colorMap->getNumPixelComps();
++ }
++ }
++ delete imgStr;
++
++ fclose(f);
++ }
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/ImageOutputDev.h poppler-0.4.3/utils/ImageOutputDev.h
+--- poppler-0.4.3.orig/utils/ImageOutputDev.h 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/ImageOutputDev.h 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,76 @@
++//========================================================================
++//
++// ImageOutputDev.h
++//
++// Copyright 1998-2003 Glyph & Cog, LLC
++//
++//========================================================================
++
++#ifndef IMAGEOUTPUTDEV_H
++#define IMAGEOUTPUTDEV_H
++
++#include <poppler-config.h>
++
++#ifdef USE_GCC_PRAGMAS
++#pragma interface
++#endif
++
++#include <stdio.h>
++#include "goo/gtypes.h"
++#include "OutputDev.h"
++
++class GfxState;
++
++//------------------------------------------------------------------------
++// ImageOutputDev
++//------------------------------------------------------------------------
++
++class ImageOutputDev: public OutputDev {
++public:
++
++ // Create an OutputDev which will write images to files named
++ // <fileRoot>-NNN.<type>. Normally, all images are written as PBM
++ // (.pbm) or PPM (.ppm) files. If <dumpJPEG> is set, JPEG images are
++ // written as JPEG (.jpg) files.
++ ImageOutputDev(char *fileRootA, GBool dumpJPEGA);
++
++ // Destructor.
++ virtual ~ImageOutputDev();
++
++ // Check if file was successfully created.
++ virtual GBool isOk() { return ok; }
++
++ // Does this device use beginType3Char/endType3Char? Otherwise,
++ // text in Type 3 fonts will be drawn with drawChar/drawString.
++ virtual GBool interpretType3Chars() { return gFalse; }
++
++ // Does this device need non-text content?
++ virtual GBool needNonText() { return gFalse; }
++
++ //---- get info about output device
++
++ // Does this device use upside-down coordinates?
++ // (Upside-down means (0,0) is the top left corner of the page.)
++ virtual GBool upsideDown() { return gTrue; }
++
++ // Does this device use drawChar() or drawString()?
++ virtual GBool useDrawChar() { return gFalse; }
++
++ //----- image drawing
++ virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GBool invert,
++ GBool inlineImg);
++ virtual void drawImage(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GfxImageColorMap *colorMap,
++ int *maskColors, GBool inlineImg);
++
++private:
++
++ char *fileRoot; // root of output file names
++ char *fileName; // buffer for output file names
++ GBool dumpJPEG; // set to dump native JPEG files
++ int imgNum; // current image number
++ GBool ok; // set up ok?
++};
++
++#endif
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/Makefile.am poppler-0.4.3/utils/Makefile.am
+--- poppler-0.4.3.orig/utils/Makefile.am 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/Makefile.am 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,26 @@
++
++INCLUDES = \
++ -I$(top_srcdir)
++
++LDADD = \
++ $(top_builddir)/poppler/libpoppler.la
++
++#pdftoppm_LDADD = \
++# $(top_builddir)/splash/libsplash.la
++
++poppler_includedir = $(includedir)/poppler
++
++bin_PROGRAMS = pdffonts pdfimages pdfinfo pdftops pdftotext pdftohtml
++
++man1_MANS = pdffonts.1 pdfimages.1 pdfinfo.1 pdftops.1 pdftotext.1 pdftohtml.1
++
++pdffonts_SOURCES = pdffonts.cc parseargs.c
++pdfimages_SOURCES = pdfimages.cc ImageOutputDev.cc parseargs.c
++pdfinfo_SOURCES = pdfinfo.cc parseargs.c
++pdftops_SOURCES = pdftops.cc parseargs.c
++pdftotext_SOURCES = pdftotext.cc parseargs.c
++pdftohtml_SOURCES = pdftohtml.cc parseargs.c \
++ HtmlFonts.cc HtmlLinks.cc HtmlOutputDev.cc
++
++#pdftoppm_SOURCES = pdftoppm.cc SplashOutputDev.cc parseargs.c
++#bin_PROGRAMS += pdftoppm
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/parseargs.c poppler-0.4.3/utils/parseargs.c
+--- poppler-0.4.3.orig/utils/parseargs.c 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/parseargs.c 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,190 @@
++/*
++ * parseargs.h
++ *
++ * Command line argument parser.
++ *
++ * Copyright 1996-2003 Glyph & Cog, LLC
++ */
++
++#include <stdio.h>
++#include <stddef.h>
++#include <string.h>
++#include <stdlib.h>
++#include <ctype.h>
++#include "parseargs.h"
++
++static ArgDesc *findArg(ArgDesc *args, char *arg);
++static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]);
++
++GBool parseArgs(ArgDesc *args, int *argc, char *argv[]) {
++ ArgDesc *arg;
++ int i, j;
++ GBool ok;
++
++ ok = gTrue;
++ i = 1;
++ while (i < *argc) {
++ if (!strcmp(argv[i], "--")) {
++ --*argc;
++ for (j = i; j < *argc; ++j)
++ argv[j] = argv[j+1];
++ break;
++ } else if ((arg = findArg(args, argv[i]))) {
++ if (!grabArg(arg, i, argc, argv))
++ ok = gFalse;
++ } else {
++ ++i;
++ }
++ }
++ return ok;
++}
++
++void printUsage(char *program, char *otherArgs, ArgDesc *args) {
++ ArgDesc *arg;
++ char *typ;
++ int w, w1;
++
++ w = 0;
++ for (arg = args; arg->arg; ++arg) {
++ if ((w1 = strlen(arg->arg)) > w)
++ w = w1;
++ }
++
++ fprintf(stderr, "Usage: %s [options]", program);
++ if (otherArgs)
++ fprintf(stderr, " %s", otherArgs);
++ fprintf(stderr, "\n");
++
++ for (arg = args; arg->arg; ++arg) {
++ fprintf(stderr, " %s", arg->arg);
++ w1 = 9 + w - strlen(arg->arg);
++ switch (arg->kind) {
++ case argInt:
++ case argIntDummy:
++ typ = " <int>";
++ break;
++ case argFP:
++ case argFPDummy:
++ typ = " <fp>";
++ break;
++ case argString:
++ case argStringDummy:
++ typ = " <string>";
++ break;
++ case argFlag:
++ case argFlagDummy:
++ default:
++ typ = "";
++ break;
++ }
++ fprintf(stderr, "%-*s", w1, typ);
++ if (arg->usage)
++ fprintf(stderr, ": %s", arg->usage);
++ fprintf(stderr, "\n");
++ }
++}
++
++static ArgDesc *findArg(ArgDesc *args, char *arg) {
++ ArgDesc *p;
++
++ for (p = args; p->arg; ++p) {
++ if (p->kind < argFlagDummy && !strcmp(p->arg, arg))
++ return p;
++ }
++ return NULL;
++}
++
++static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]) {
++ int n;
++ int j;
++ GBool ok;
++
++ ok = gTrue;
++ n = 0;
++ switch (arg->kind) {
++ case argFlag:
++ *(GBool *)arg->val = gTrue;
++ n = 1;
++ break;
++ case argInt:
++ if (i + 1 < *argc && isInt(argv[i+1])) {
++ *(int *)arg->val = atoi(argv[i+1]);
++ n = 2;
++ } else {
++ ok = gFalse;
++ n = 1;
++ }
++ break;
++ case argFP:
++ if (i + 1 < *argc && isFP(argv[i+1])) {
++ *(double *)arg->val = atof(argv[i+1]);
++ n = 2;
++ } else {
++ ok = gFalse;
++ n = 1;
++ }
++ break;
++ case argString:
++ if (i + 1 < *argc) {
++ strncpy((char *)arg->val, argv[i+1], arg->size - 1);
++ ((char *)arg->val)[arg->size - 1] = '\0';
++ n = 2;
++ } else {
++ ok = gFalse;
++ n = 1;
++ }
++ break;
++ default:
++ fprintf(stderr, "Internal error in arg table\n");
++ n = 1;
++ break;
++ }
++ if (n > 0) {
++ *argc -= n;
++ for (j = i; j < *argc; ++j)
++ argv[j] = argv[j+n];
++ }
++ return ok;
++}
++
++GBool isInt(char *s) {
++ if (*s == '-' || *s == '+')
++ ++s;
++ while (isdigit(*s))
++ ++s;
++ if (*s)
++ return gFalse;
++ return gTrue;
++}
++
++GBool isFP(char *s) {
++ int n;
++
++ if (*s == '-' || *s == '+')
++ ++s;
++ n = 0;
++ while (isdigit(*s)) {
++ ++s;
++ ++n;
++ }
++ if (*s == '.')
++ ++s;
++ while (isdigit(*s)) {
++ ++s;
++ ++n;
++ }
++ if (n > 0 && (*s == 'e' || *s == 'E')) {
++ ++s;
++ if (*s == '-' || *s == '+')
++ ++s;
++ n = 0;
++ if (!isdigit(*s))
++ return gFalse;
++ do {
++ ++s;
++ } while (isdigit(*s));
++ }
++ if (*s)
++ return gFalse;
++ return gTrue;
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/parseargs.h poppler-0.4.3/utils/parseargs.h
+--- poppler-0.4.3.orig/utils/parseargs.h 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/parseargs.h 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,71 @@
++/*
++ * parseargs.h
++ *
++ * Command line argument parser.
++ *
++ * Copyright 1996-2003 Glyph & Cog, LLC
++ */
++
++#ifndef PARSEARGS_H
++#define PARSEARGS_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#include "goo/gtypes.h"
++
++/*
++ * Argument kinds.
++ */
++typedef enum {
++ argFlag, /* flag (present / not-present) */
++ /* [val: GBool *] */
++ argInt, /* integer arg */
++ /* [val: int *] */
++ argFP, /* floating point arg */
++ /* [val: double *] */
++ argString, /* string arg */
++ /* [val: char *] */
++ /* dummy entries -- these show up in the usage listing only; */
++ /* useful for X args, for example */
++ argFlagDummy,
++ argIntDummy,
++ argFPDummy,
++ argStringDummy
++} ArgKind;
++
++/*
++ * Argument descriptor.
++ */
++typedef struct {
++ char *arg; /* the command line switch */
++ ArgKind kind; /* kind of arg */
++ void *val; /* place to store value */
++ int size; /* for argString: size of string */
++ char *usage; /* usage string */
++} ArgDesc;
++
++/*
++ * Parse command line. Removes all args which are found in the arg
++ * descriptor list <args>. Stops parsing if "--" is found (and removes
++ * it). Returns gFalse if there was an error.
++ */
++extern GBool parseArgs(ArgDesc *args, int *argc, char *argv[]);
++
++/*
++ * Print usage message, based on arg descriptor list.
++ */
++extern void printUsage(char *program, char *otherArgs, ArgDesc *args);
++
++/*
++ * Check if a string is a valid integer or floating point number.
++ */
++extern GBool isInt(char *s);
++extern GBool isFP(char *s);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdffonts.1 poppler-0.4.3/utils/pdffonts.1
+--- poppler-0.4.3.orig/utils/pdffonts.1 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdffonts.1 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,128 @@
++.\" Copyright 1999-2004 Glyph & Cog, LLC
++.TH pdffonts 1 "22 January 2004"
++.SH NAME
++pdffonts \- Portable Document Format (PDF) font analyzer (version
++3.00)
++.SH SYNOPSIS
++.B pdffonts
++[options]
++.RI [ PDF-file ]
++.SH DESCRIPTION
++.B Pdffonts
++lists the fonts used in a Portable Document Format (PDF) file along
++with various information for each font.
++.PP
++The following information is listed for each font:
++.TP
++.B name
++the font name, exactly as given in the PDF file (potentially including
++a subset prefix)
++.TP
++.B type
++the font type -- see below for details
++.TP
++.B emb
++"yes" if the font is embedded in the PDF file
++.TP
++.B sub
++"yes" if the font is a subset
++.TP
++.B uni
++"yes" if there is an explicit "ToUnicode" map in the PDF file (the
++absence of a ToUnicode map doesn't necessarily mean that the text
++can't be converted to Unicode)
++.TP
++.B object ID
++the font dictionary object ID (number and generation)
++.PP
++PDF files can contain the following types of fonts:
++.PP
++.RS
++Type 1
++.RE
++.RS
++Type 1C -- aka Compact Font Format (CFF)
++.RE
++.RS
++Type 3
++.RE
++.RS
++TrueType
++.RE
++.RS
++CID Type 0 -- 16-bit font with no specified type
++.RE
++.RS
++CID Type 0C -- 16-bit PostScript CFF font
++.RE
++.RS
++CID TrueType -- 16-bit TrueType font
++.RE
++.SH CONFIGURATION FILE
++Pdffonts reads a configuration file at startup. It first tries to
++find the user's private config file, ~/.xpdfrc. If that doesn't
++exist, it looks for a system-wide config file, /etc/xpdf/xpdfrc. See the
++.BR xpdfrc (5)
++man page for details.
++.SH OPTIONS
++Many of the following options can be set with configuration file
++commands. These are listed in square brackets with the description of
++the corresponding command line option.
++.TP
++.BI \-f " number"
++Specifies the first page to analyze.
++.TP
++.BI \-l " number"
++Specifies the last page to analyze.
++.TP
++.BI \-opw " password"
++Specify the owner password for the PDF file. Providing this will
++bypass all security restrictions.
++.TP
++.BI \-upw " password"
++Specify the user password for the PDF file.
++.TP
++.BI \-cfg " config-file"
++Read
++.I config-file
++in place of ~/.xpdfrc or the system-wide config file.
++.TP
++.B \-v
++Print copyright and version information.
++.TP
++.B \-h
++Print usage information.
++.RB ( \-help
++and
++.B \-\-help
++are equivalent.)
++.SH EXIT CODES
++The Xpdf tools use the following exit codes:
++.TP
++0
++No error.
++.TP
++1
++Error opening a PDF file.
++.TP
++2
++Error opening an output file.
++.TP
++3
++Error related to PDF permissions.
++.TP
++99
++Other error.
++.SH AUTHOR
++The pdffonts software and documentation are copyright 1996-2004 Glyph
++& Cog, LLC.
++.SH "SEE ALSO"
++.BR xpdf (1),
++.BR pdftops (1),
++.BR pdftotext (1),
++.BR pdfinfo (1),
++.BR pdftoppm (1),
++.BR pdfimages (1),
++.BR xpdfrc (5)
++.br
++.B http://www.foolabs.com/xpdf/
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdffonts.cc poppler-0.4.3/utils/pdffonts.cc
+--- poppler-0.4.3.orig/utils/pdffonts.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdffonts.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,292 @@
++//========================================================================
++//
++// pdffonts.cc
++//
++// Copyright 2001-2003 Glyph & Cog, LLC
++//
++//========================================================================
++
++#include <poppler-config.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stddef.h>
++#include <string.h>
++#include <math.h>
++#include "parseargs.h"
++#include "goo/GooString.h"
++#include "goo/gmem.h"
++#include "GlobalParams.h"
++#include "Error.h"
++#include "Object.h"
++#include "Dict.h"
++#include "GfxFont.h"
++#include "Annot.h"
++#include "PDFDoc.h"
++#include "config.h"
++
++static char *fontTypeNames[] = {
++ "unknown",
++ "Type 1",
++ "Type 1C",
++ "Type 3",
++ "TrueType",
++ "CID Type 0",
++ "CID Type 0C",
++ "CID TrueType"
++};
++
++static void scanFonts(Dict *resDict, PDFDoc *doc);
++static void scanFont(GfxFont *font, PDFDoc *doc);
++
++static int firstPage = 1;
++static int lastPage = 0;
++static char ownerPassword[33] = "\001";
++static char userPassword[33] = "\001";
++static char cfgFileName[256] = "";
++static GBool printVersion = gFalse;
++static GBool printHelp = gFalse;
++
++static ArgDesc argDesc[] = {
++ {"-f", argInt, &firstPage, 0,
++ "first page to examine"},
++ {"-l", argInt, &lastPage, 0,
++ "last page to examine"},
++ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
++ "owner password (for encrypted files)"},
++ {"-upw", argString, userPassword, sizeof(userPassword),
++ "user password (for encrypted files)"},
++ {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
++ "configuration file to use in place of .xpdfrc"},
++ {"-v", argFlag, &printVersion, 0,
++ "print copyright and version info"},
++ {"-h", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"--help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-?", argFlag, &printHelp, 0,
++ "print usage information"},
++ {NULL}
++};
++
++static Ref *fonts;
++static int fontsLen;
++static int fontsSize;
++
++int main(int argc, char *argv[]) {
++ PDFDoc *doc;
++ GooString *fileName;
++ GooString *ownerPW, *userPW;
++ GBool ok;
++ Page *page;
++ Dict *resDict;
++ Annots *annots;
++ Object obj1, obj2;
++ int pg, i;
++ int exitCode;
++
++ exitCode = 99;
++
++ // parse args
++ ok = parseArgs(argDesc, &argc, argv);
++ if (!ok || argc != 2 || printVersion || printHelp) {
++ fprintf(stderr, "pdffonts version %s\n", xpdfVersion);
++ fprintf(stderr, "%s\n", xpdfCopyright);
++ if (!printVersion) {
++ printUsage("pdffonts", "<PDF-file>", argDesc);
++ }
++ goto err0;
++ }
++ fileName = new GooString(argv[1]);
++
++ // read config file
++ globalParams = new GlobalParams(cfgFileName);
++
++ // open PDF file
++ if (ownerPassword[0] != '\001') {
++ ownerPW = new GooString(ownerPassword);
++ } else {
++ ownerPW = NULL;
++ }
++ if (userPassword[0] != '\001') {
++ userPW = new GooString(userPassword);
++ } else {
++ userPW = NULL;
++ }
++ doc = new PDFDoc(fileName, ownerPW, userPW);
++ if (userPW) {
++ delete userPW;
++ }
++ if (ownerPW) {
++ delete ownerPW;
++ }
++ if (!doc->isOk()) {
++ exitCode = 1;
++ goto err1;
++ }
++
++ // get page range
++ if (firstPage < 1) {
++ firstPage = 1;
++ }
++ if (lastPage < 1 || lastPage > doc->getNumPages()) {
++ lastPage = doc->getNumPages();
++ }
++
++ // scan the fonts
++ printf("name type emb sub uni object ID\n");
++ printf("------------------------------------ ------------ --- --- --- ---------\n");
++ fonts = NULL;
++ fontsLen = fontsSize = 0;
++ for (pg = firstPage; pg <= lastPage; ++pg) {
++ page = doc->getCatalog()->getPage(pg);
++ if ((resDict = page->getResourceDict())) {
++ scanFonts(resDict, doc);
++ }
++ annots = new Annots(doc->getXRef(), page->getAnnots(&obj1));
++ obj1.free();
++ for (i = 0; i < annots->getNumAnnots(); ++i) {
++ if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
++ obj1.streamGetDict()->lookup("Resources", &obj2);
++ if (obj2.isDict()) {
++ scanFonts(obj2.getDict(), doc);
++ }
++ obj2.free();
++ }
++ obj1.free();
++ }
++ delete annots;
++ }
++
++ exitCode = 0;
++
++ // clean up
++ gfree(fonts);
++ err1:
++ delete doc;
++ delete globalParams;
++ err0:
++
++ // check for memory leaks
++ Object::memCheck(stderr);
++ gMemReport(stderr);
++
++ return exitCode;
++}
++
++static void scanFonts(Dict *resDict, PDFDoc *doc) {
++ Object obj1, obj2, xObjDict, xObj, resObj;
++ Ref r;
++ GfxFontDict *gfxFontDict;
++ GfxFont *font;
++ int i;
++
++ // scan the fonts in this resource dictionary
++ gfxFontDict = NULL;
++ resDict->lookupNF("Font", &obj1);
++ if (obj1.isRef()) {
++ obj1.fetch(doc->getXRef(), &obj2);
++ if (obj2.isDict()) {
++ r = obj1.getRef();
++ gfxFontDict = new GfxFontDict(doc->getXRef(), &r, obj2.getDict());
++ }
++ obj2.free();
++ } else if (obj1.isDict()) {
++ gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict());
++ }
++ if (gfxFontDict) {
++ for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
++ if ((font = gfxFontDict->getFont(i))) {
++ scanFont(font, doc);
++ }
++ }
++ delete gfxFontDict;
++ }
++ obj1.free();
++
++ // recursively scan any resource dictionaries in objects in this
++ // resource dictionary
++ resDict->lookup("XObject", &xObjDict);
++ if (xObjDict.isDict()) {
++ for (i = 0; i < xObjDict.dictGetLength(); ++i) {
++ xObjDict.dictGetVal(i, &xObj);
++ if (xObj.isStream()) {
++ xObj.streamGetDict()->lookup("Resources", &resObj);
++ if (resObj.isDict()) {
++ scanFonts(resObj.getDict(), doc);
++ }
++ resObj.free();
++ }
++ xObj.free();
++ }
++ }
++ xObjDict.free();
++}
++
++static void scanFont(GfxFont *font, PDFDoc *doc) {
++ Ref fontRef, embRef;
++ Object fontObj, toUnicodeObj;
++ GooString *name;
++ GBool emb, subset, hasToUnicode;
++ int i;
++
++ fontRef = *font->getID();
++
++ // check for an already-seen font
++ for (i = 0; i < fontsLen; ++i) {
++ if (fontRef.num == fonts[i].num && fontRef.gen == fonts[i].gen) {
++ return;
++ }
++ }
++
++ // font name
++ name = font->getOrigName();
++
++ // check for an embedded font
++ if (font->getType() == fontType3) {
++ emb = gTrue;
++ } else {
++ emb = font->getEmbeddedFontID(&embRef);
++ }
++
++ // look for a ToUnicode map
++ hasToUnicode = gFalse;
++ if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
++ hasToUnicode = fontObj.dictLookup("ToUnicode", &toUnicodeObj)->isStream();
++ toUnicodeObj.free();
++ }
++ fontObj.free();
++
++ // check for a font subset name: capital letters followed by a '+'
++ // sign
++ subset = gFalse;
++ if (name) {
++ for (i = 0; i < name->getLength(); ++i) {
++ if (name->getChar(i) < 'A' || name->getChar(i) > 'Z') {
++ break;
++ }
++ }
++ subset = i > 0 && i < name->getLength() && name->getChar(i) == '+';
++ }
++
++ // print the font info
++ printf("%-36s %-12s %-3s %-3s %-3s",
++ name ? name->getCString() : "[none]",
++ fontTypeNames[font->getType()],
++ emb ? "yes" : "no",
++ subset ? "yes" : "no",
++ hasToUnicode ? "yes" : "no");
++ if (fontRef.gen >= 100000) {
++ printf(" [none]\n");
++ } else {
++ printf(" %6d %2d\n", fontRef.num, fontRef.gen);
++ }
++
++ // add this font to the list
++ if (fontsLen == fontsSize) {
++ fontsSize += 32;
++ fonts = (Ref *)grealloc(fonts, fontsSize * sizeof(Ref));
++ }
++ fonts[fontsLen++] = *font->getID();
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdfimages.1 poppler-0.4.3/utils/pdfimages.1
+--- poppler-0.4.3.orig/utils/pdfimages.1 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdfimages.1 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,96 @@
++.\" Copyright 1998-2004 Glyph & Cog, LLC
++.TH pdfimages 1 "22 January 2004"
++.SH NAME
++pdfimages \- Portable Document Format (PDF) image extractor
++(version 3.00)
++.SH SYNOPSIS
++.B pdfimages
++[options]
++.I PDF-file image-root
++.SH DESCRIPTION
++.B Pdfimages
++saves images from a Portable Document Format (PDF) file as Portable
++Pixmap (PPM), Portable Bitmap (PBM), or JPEG files.
++.PP
++Pdfimages reads the PDF file
++.IR PDF-file ,
++scans one or more pages, and writes one PPM, PBM, or JPEG file for each image,
++.IR image-root - nnn . xxx ,
++where
++.I nnn
++is the image number and
++.I xxx
++is the image type (.ppm, .pbm, .jpg).
++.SH CONFIGURATION FILE
++Pdfimages reads a configuration file at startup. It first tries to
++find the user's private config file, ~/.xpdfrc. If that doesn't
++exist, it looks for a system-wide config file, /etc/xpdf/xpdfrc. See the
++.BR xpdfrc (5)
++man page for details.
++.SH OPTIONS
++Many of the following options can be set with configuration file
++commands. These are listed in square brackets with the description of
++the corresponding command line option.
++.TP
++.BI \-f " number"
++Specifies the first page to scan.
++.TP
++.BI \-l " number"
++Specifies the last page to scan.
++.TP
++.B \-j
++Normally, all images are written as PBM (for monochrome images) or PPM
++(for non-monochrome images) files. With this option, images in DCT
++format are saved as JPEG files. All non-DCT images are saved in
++PBM/PPM format as usual.
++.TP
++.BI \-opw " password"
++Specify the owner password for the PDF file. Providing this will
++bypass all security restrictions.
++.TP
++.BI \-upw " password"
++Specify the user password for the PDF file.
++.TP
++.B \-q
++Don't print any messages or errors.
++.RB "[config file: " errQuiet ]
++.TP
++.B \-v
++Print copyright and version information.
++.TP
++.B \-h
++Print usage information.
++.RB ( \-help
++and
++.B \-\-help
++are equivalent.)
++.SH EXIT CODES
++The Xpdf tools use the following exit codes:
++.TP
++0
++No error.
++.TP
++1
++Error opening a PDF file.
++.TP
++2
++Error opening an output file.
++.TP
++3
++Error related to PDF permissions.
++.TP
++99
++Other error.
++.SH AUTHOR
++The pdfimages software and documentation are copyright 1998-2004 Glyph
++& Cog, LLC.
++.SH "SEE ALSO"
++.BR xpdf (1),
++.BR pdftops (1),
++.BR pdftotext (1),
++.BR pdfinfo (1),
++.BR pdffonts (1),
++.BR pdftoppm (1),
++.BR xpdfrc (5)
++.br
++.B http://www.foolabs.com/xpdf/
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdfimages.cc poppler-0.4.3/utils/pdfimages.cc
+--- poppler-0.4.3.orig/utils/pdfimages.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdfimages.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,158 @@
++//========================================================================
++//
++// pdfimages.cc
++//
++// Copyright 1998-2003 Glyph & Cog, LLC
++//
++// Modified for Debian by Hamish Moffatt, 22 May 2002.
++//
++//========================================================================
++
++#include <poppler-config.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stddef.h>
++#include <string.h>
++#include "parseargs.h"
++#include "goo/GooString.h"
++#include "goo/gmem.h"
++#include "GlobalParams.h"
++#include "Object.h"
++#include "Stream.h"
++#include "Array.h"
++#include "Dict.h"
++#include "XRef.h"
++#include "Catalog.h"
++#include "Page.h"
++#include "PDFDoc.h"
++#include "ImageOutputDev.h"
++#include "Error.h"
++#include "config.h"
++
++static int firstPage = 1;
++static int lastPage = 0;
++static GBool dumpJPEG = gFalse;
++static char ownerPassword[33] = "\001";
++static char userPassword[33] = "\001";
++static GBool quiet = gFalse;
++static char cfgFileName[256] = "";
++static GBool printVersion = gFalse;
++static GBool printHelp = gFalse;
++
++static ArgDesc argDesc[] = {
++ {"-f", argInt, &firstPage, 0,
++ "first page to convert"},
++ {"-l", argInt, &lastPage, 0,
++ "last page to convert"},
++ {"-j", argFlag, &dumpJPEG, 0,
++ "write JPEG images as JPEG files"},
++ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
++ "owner password (for encrypted files)"},
++ {"-upw", argString, userPassword, sizeof(userPassword),
++ "user password (for encrypted files)"},
++ {"-q", argFlag, &quiet, 0,
++ "don't print any messages or errors"},
++ {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
++ "configuration file to use in place of .xpdfrc"},
++ {"-v", argFlag, &printVersion, 0,
++ "print copyright and version info"},
++ {"-h", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"--help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-?", argFlag, &printHelp, 0,
++ "print usage information"},
++ {NULL}
++};
++
++int main(int argc, char *argv[]) {
++ PDFDoc *doc;
++ GooString *fileName;
++ char *imgRoot;
++ GooString *ownerPW, *userPW;
++ ImageOutputDev *imgOut;
++ GBool ok;
++ int exitCode;
++
++ exitCode = 99;
++
++ // parse args
++ ok = parseArgs(argDesc, &argc, argv);
++ if (!ok || argc != 3 || printVersion || printHelp) {
++ fprintf(stderr, "pdfimages version %s\n", xpdfVersion);
++ fprintf(stderr, "%s\n", xpdfCopyright);
++ if (!printVersion) {
++ printUsage("pdfimages", "<PDF-file> <image-root>", argDesc);
++ }
++ goto err0;
++ }
++ fileName = new GooString(argv[1]);
++ imgRoot = argv[2];
++
++ // read config file
++ globalParams = new GlobalParams(cfgFileName);
++ if (quiet) {
++ globalParams->setErrQuiet(quiet);
++ }
++
++ // open PDF file
++ if (ownerPassword[0] != '\001') {
++ ownerPW = new GooString(ownerPassword);
++ } else {
++ ownerPW = NULL;
++ }
++ if (userPassword[0] != '\001') {
++ userPW = new GooString(userPassword);
++ } else {
++ userPW = NULL;
++ }
++ doc = new PDFDoc(fileName, ownerPW, userPW);
++ if (userPW) {
++ delete userPW;
++ }
++ if (ownerPW) {
++ delete ownerPW;
++ }
++ if (!doc->isOk()) {
++ exitCode = 1;
++ goto err1;
++ }
++
++ // check for copy permission
++#ifdef ENFORCE_PERMISSIONS
++ if (!doc->okToCopy()) {
++ error(-1, "Copying of images from this document is not allowed.");
++ exitCode = 3;
++ goto err1;
++ }
++#endif
++
++ // get page range
++ if (firstPage < 1)
++ firstPage = 1;
++ if (lastPage < 1 || lastPage > doc->getNumPages())
++ lastPage = doc->getNumPages();
++
++ // write image files
++ imgOut = new ImageOutputDev(imgRoot, dumpJPEG);
++ if (imgOut->isOk()) {
++ doc->displayPages(imgOut, firstPage, lastPage, 72, 72, 0, gTrue, gFalse);
++ }
++ delete imgOut;
++
++ exitCode = 0;
++
++ // clean up
++ err1:
++ delete doc;
++ delete globalParams;
++ err0:
++
++ // check for memory leaks
++ Object::memCheck(stderr);
++ gMemReport(stderr);
++
++ return exitCode;
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdfinfo.1 poppler-0.4.3/utils/pdfinfo.1
+--- poppler-0.4.3.orig/utils/pdfinfo.1 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdfinfo.1 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,157 @@
++.\" Copyright 1999-2004 Glyph & Cog, LLC
++.TH pdfinfo 1 "22 January 2004"
++.SH NAME
++pdfinfo \- Portable Document Format (PDF) document information
++extractor (version 3.00)
++.SH SYNOPSIS
++.B pdfinfo
++[options]
++.RI [ PDF-file ]
++.SH DESCRIPTION
++.B Pdfinfo
++prints the contents of the \'Info' dictionary (plus some other useful
++information) from a Portable Document Format (PDF) file.
++.PP
++The \'Info' dictionary contains the following values:
++.PP
++.RS
++title
++.RE
++.RS
++subject
++.RE
++.RS
++keywords
++.RE
++.RS
++author
++.RE
++.RS
++creator
++.RE
++.RS
++producer
++.RE
++.RS
++creation date
++.RE
++.RS
++modification date
++.RE
++.PP
++In addition, the following information is printed:
++.PP
++.RS
++tagged (yes/no)
++.RE
++.RS
++page count
++.RE
++.RS
++encrypted flag (yes/no)
++.RE
++.RS
++print and copy permissions (if encrypted)
++.RE
++.RS
++page size
++.RE
++.RS
++file size
++.RE
++.RS
++linearized (yes/no)
++.RE
++.RS
++PDF version
++.RE
++.RS
++metadata (only if requested)
++.RE
++.SH CONFIGURATION FILE
++Pdfinfo reads a configuration file at startup. It first tries to find
++the user's private config file, ~/.xpdfrc. If that doesn't exist, it
++looks for a system-wide config file, /etc/xpdf/xpdfrc. See the
++.BR xpdfrc (5)
++man page for details.
++.SH OPTIONS
++Many of the following options can be set with configuration file
++commands. These are listed in square brackets with the description of
++the corresponding command line option.
++.TP
++.BI \-f " number"
++Specifies the first page to examine. If multiple pages are requested
++using the "-f" and "-l" options, the size of each requested page (and,
++optionally, the bounding boxes for each requested page) are printed.
++Otherwise, only page one is examined.
++.TP
++.BI \-l " number"
++Specifies the last page to examine.
++.TP
++.B \-box
++Prints the page box bounding boxes: MediaBox, CropBox, BleedBox,
++TrimBox, and ArtBox.
++.TP
++.B \-meta
++Prints document-level metadata. (This is the "Metadata" stream from
++the PDF file's Catalog object.)
++.TP
++.BI \-enc " encoding-name"
++Sets the encoding to use for text output. The
++.I encoding\-name
++must be defined with the unicodeMap command (see
++.BR xpdfrc (5)).
++This defaults to "Latin1" (which is a built-in encoding).
++.RB "[config file: " textEncoding ]
++.TP
++.BI \-opw " password"
++Specify the owner password for the PDF file. Providing this will
++bypass all security restrictions.
++.TP
++.BI \-upw " password"
++Specify the user password for the PDF file.
++.TP
++.BI \-cfg " config-file"
++Read
++.I config-file
++in place of ~/.xpdfrc or the system-wide config file.
++.TP
++.B \-v
++Print copyright and version information.
++.TP
++.B \-h
++Print usage information.
++.RB ( \-help
++and
++.B \-\-help
++are equivalent.)
++.SH EXIT CODES
++The Xpdf tools use the following exit codes:
++.TP
++0
++No error.
++.TP
++1
++Error opening a PDF file.
++.TP
++2
++Error opening an output file.
++.TP
++3
++Error related to PDF permissions.
++.TP
++99
++Other error.
++.SH AUTHOR
++The pdfinfo software and documentation are copyright 1996-2004 Glyph &
++Cog, LLC.
++.SH "SEE ALSO"
++.BR xpdf (1),
++.BR pdftops (1),
++.BR pdftotext (1),
++.BR pdffonts (1),
++.BR pdftoppm (1),
++.BR pdfimages (1),
++.BR xpdfrc (5)
++.br
++.B http://www.foolabs.com/xpdf/
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdfinfo.cc poppler-0.4.3/utils/pdfinfo.cc
+--- poppler-0.4.3.orig/utils/pdfinfo.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdfinfo.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,376 @@
++//========================================================================
++//
++// pdfinfo.cc
++//
++// Copyright 1998-2003 Glyph & Cog, LLC
++//
++//========================================================================
++
++#include <poppler-config.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stddef.h>
++#include <string.h>
++#include <time.h>
++#include <math.h>
++#include "parseargs.h"
++#include "goo/GooString.h"
++#include "goo/gmem.h"
++#include "GlobalParams.h"
++#include "Object.h"
++#include "Stream.h"
++#include "Array.h"
++#include "Dict.h"
++#include "XRef.h"
++#include "Catalog.h"
++#include "Page.h"
++#include "PDFDoc.h"
++#include "CharTypes.h"
++#include "UnicodeMap.h"
++#include "Error.h"
++#include "config.h"
++
++static void printInfoString(Dict *infoDict, char *key, char *text,
++ UnicodeMap *uMap);
++static void printInfoDate(Dict *infoDict, char *key, char *text);
++static void printBox(char *text, PDFRectangle *box);
++
++static int firstPage = 1;
++static int lastPage = 0;
++static GBool printBoxes = gFalse;
++static GBool printMetadata = gFalse;
++static char textEncName[128] = "";
++static char ownerPassword[33] = "\001";
++static char userPassword[33] = "\001";
++static char cfgFileName[256] = "";
++static GBool printVersion = gFalse;
++static GBool printHelp = gFalse;
++
++static ArgDesc argDesc[] = {
++ {"-f", argInt, &firstPage, 0,
++ "first page to convert"},
++ {"-l", argInt, &lastPage, 0,
++ "last page to convert"},
++ {"-box", argFlag, &printBoxes, 0,
++ "print the page bounding boxes"},
++ {"-meta", argFlag, &printMetadata, 0,
++ "print the document metadata (XML)"},
++ {"-enc", argString, textEncName, sizeof(textEncName),
++ "output text encoding name"},
++ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
++ "owner password (for encrypted files)"},
++ {"-upw", argString, userPassword, sizeof(userPassword),
++ "user password (for encrypted files)"},
++ {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
++ "configuration file to use in place of .xpdfrc"},
++ {"-v", argFlag, &printVersion, 0,
++ "print copyright and version info"},
++ {"-h", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"--help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-?", argFlag, &printHelp, 0,
++ "print usage information"},
++ {NULL}
++};
++
++int main(int argc, char *argv[]) {
++ PDFDoc *doc;
++ GooString *fileName;
++ GooString *ownerPW, *userPW;
++ UnicodeMap *uMap;
++ Page *page;
++ Object info;
++ char buf[256];
++ double w, h, wISO, hISO;
++ FILE *f;
++ GooString *metadata;
++ GBool ok;
++ int exitCode;
++ int pg, i;
++ GBool multiPage;
++
++ exitCode = 99;
++
++ // parse args
++ ok = parseArgs(argDesc, &argc, argv);
++ if (!ok || argc != 2 || printVersion || printHelp) {
++ fprintf(stderr, "pdfinfo version %s\n", xpdfVersion);
++ fprintf(stderr, "%s\n", xpdfCopyright);
++ if (!printVersion) {
++ printUsage("pdfinfo", "<PDF-file>", argDesc);
++ }
++ goto err0;
++ }
++ fileName = new GooString(argv[1]);
++
++ // read config file
++ globalParams = new GlobalParams(cfgFileName);
++ if (textEncName[0]) {
++ globalParams->setTextEncoding(textEncName);
++ }
++
++ // get mapping to output encoding
++ if (!(uMap = globalParams->getTextEncoding())) {
++ error(-1, "Couldn't get text encoding");
++ delete fileName;
++ goto err1;
++ }
++
++ // open PDF file
++ if (ownerPassword[0] != '\001') {
++ ownerPW = new GooString(ownerPassword);
++ } else {
++ ownerPW = NULL;
++ }
++ if (userPassword[0] != '\001') {
++ userPW = new GooString(userPassword);
++ } else {
++ userPW = NULL;
++ }
++ doc = new PDFDoc(fileName, ownerPW, userPW);
++ if (userPW) {
++ delete userPW;
++ }
++ if (ownerPW) {
++ delete ownerPW;
++ }
++ if (!doc->isOk()) {
++ exitCode = 1;
++ goto err2;
++ }
++
++ // get page range
++ if (firstPage < 1) {
++ firstPage = 1;
++ }
++ if (lastPage == 0) {
++ multiPage = gFalse;
++ lastPage = 1;
++ } else {
++ multiPage = gTrue;
++ }
++ if (lastPage < 1 || lastPage > doc->getNumPages()) {
++ lastPage = doc->getNumPages();
++ }
++
++ // print doc info
++ doc->getDocInfo(&info);
++ if (info.isDict()) {
++ printInfoString(info.getDict(), "Title", "Title: ", uMap);
++ printInfoString(info.getDict(), "Subject", "Subject: ", uMap);
++ printInfoString(info.getDict(), "Keywords", "Keywords: ", uMap);
++ printInfoString(info.getDict(), "Author", "Author: ", uMap);
++ printInfoString(info.getDict(), "Creator", "Creator: ", uMap);
++ printInfoString(info.getDict(), "Producer", "Producer: ", uMap);
++ printInfoDate(info.getDict(), "CreationDate", "CreationDate: ");
++ printInfoDate(info.getDict(), "ModDate", "ModDate: ");
++ }
++ info.free();
++
++ // print tagging info
++ printf("Tagged: %s\n",
++ doc->getStructTreeRoot()->isDict() ? "yes" : "no");
++
++ // print page count
++ printf("Pages: %d\n", doc->getNumPages());
++
++ // print encryption info
++ printf("Encrypted: ");
++ if (doc->isEncrypted()) {
++ printf("yes (print:%s copy:%s change:%s addNotes:%s)\n",
++ doc->okToPrint(gTrue) ? "yes" : "no",
++ doc->okToCopy(gTrue) ? "yes" : "no",
++ doc->okToChange(gTrue) ? "yes" : "no",
++ doc->okToAddNotes(gTrue) ? "yes" : "no");
++ } else {
++ printf("no\n");
++ }
++
++ // print page size
++ for (pg = firstPage; pg <= lastPage; ++pg) {
++ w = doc->getPageWidth(pg);
++ h = doc->getPageHeight(pg);
++ if (multiPage) {
++ printf("Page %4d size: %g x %g pts", pg, w, h);
++ } else {
++ printf("Page size: %g x %g pts", w, h);
++ }
++ if ((fabs(w - 612) < 0.1 && fabs(h - 792) < 0.1) ||
++ (fabs(w - 792) < 0.1 && fabs(h - 612) < 0.1)) {
++ printf(" (letter)");
++ } else {
++ hISO = sqrt(sqrt(2.0)) * 7200 / 2.54;
++ wISO = hISO / sqrt(2.0);
++ for (i = 0; i <= 6; ++i) {
++ if ((fabs(w - wISO) < 1 && fabs(h - hISO) < 1) ||
++ (fabs(w - hISO) < 1 && fabs(h - wISO) < 1)) {
++ printf(" (A%d)", i);
++ break;
++ }
++ hISO = wISO;
++ wISO /= sqrt(2.0);
++ }
++ }
++ printf("\n");
++ }
++
++ // print the boxes
++ if (printBoxes) {
++ if (multiPage) {
++ for (pg = firstPage; pg <= lastPage; ++pg) {
++ page = doc->getCatalog()->getPage(pg);
++ sprintf(buf, "Page %4d MediaBox: ", pg);
++ printBox(buf, page->getMediaBox());
++ sprintf(buf, "Page %4d CropBox: ", pg);
++ printBox(buf, page->getCropBox());
++ sprintf(buf, "Page %4d BleedBox: ", pg);
++ printBox(buf, page->getBleedBox());
++ sprintf(buf, "Page %4d TrimBox: ", pg);
++ printBox(buf, page->getTrimBox());
++ sprintf(buf, "Page %4d ArtBox: ", pg);
++ printBox(buf, page->getArtBox());
++ }
++ } else {
++ page = doc->getCatalog()->getPage(firstPage);
++ printBox("MediaBox: ", page->getMediaBox());
++ printBox("CropBox: ", page->getCropBox());
++ printBox("BleedBox: ", page->getBleedBox());
++ printBox("TrimBox: ", page->getTrimBox());
++ printBox("ArtBox: ", page->getArtBox());
++ }
++ }
++
++ // print file size
++#ifdef VMS
++ f = fopen(fileName->getCString(), "rb", "ctx=stm");
++#else
++ f = fopen(fileName->getCString(), "rb");
++#endif
++ if (f) {
++#if HAVE_FSEEKO
++ fseeko(f, 0, SEEK_END);
++ printf("File size: %u bytes\n", (Guint)ftello(f));
++#elif HAVE_FSEEK64
++ fseek64(f, 0, SEEK_END);
++ printf("File size: %u bytes\n", (Guint)ftell64(f));
++#else
++ fseek(f, 0, SEEK_END);
++ printf("File size: %d bytes\n", (int)ftell(f));
++#endif
++ fclose(f);
++ }
++
++ // print linearization info
++ printf("Optimized: %s\n", doc->isLinearized() ? "yes" : "no");
++
++ // print PDF version
++ printf("PDF version: %.1f\n", doc->getPDFVersion());
++
++ // print the metadata
++ if (printMetadata && (metadata = doc->readMetadata())) {
++ fputs("Metadata:\n", stdout);
++ fputs(metadata->getCString(), stdout);
++ fputc('\n', stdout);
++ delete metadata;
++ }
++
++ exitCode = 0;
++
++ // clean up
++ err2:
++ uMap->decRefCnt();
++ delete doc;
++ err1:
++ delete globalParams;
++ err0:
++
++ // check for memory leaks
++ Object::memCheck(stderr);
++ gMemReport(stderr);
++
++ return exitCode;
++}
++
++static void printInfoString(Dict *infoDict, char *key, char *text,
++ UnicodeMap *uMap) {
++ Object obj;
++ GooString *s1;
++ GBool isUnicode;
++ Unicode u;
++ char buf[8];
++ int i, n;
++
++ if (infoDict->lookup(key, &obj)->isString()) {
++ fputs(text, stdout);
++ s1 = obj.getString();
++ if ((s1->getChar(0) & 0xff) == 0xfe &&
++ (s1->getChar(1) & 0xff) == 0xff) {
++ isUnicode = gTrue;
++ i = 2;
++ } else {
++ isUnicode = gFalse;
++ i = 0;
++ }
++ while (i < obj.getString()->getLength()) {
++ if (isUnicode) {
++ u = ((s1->getChar(i) & 0xff) << 8) |
++ (s1->getChar(i+1) & 0xff);
++ i += 2;
++ } else {
++ u = s1->getChar(i) & 0xff;
++ ++i;
++ }
++ n = uMap->mapUnicode(u, buf, sizeof(buf));
++ fwrite(buf, 1, n, stdout);
++ }
++ fputc('\n', stdout);
++ }
++ obj.free();
++}
++
++static void printInfoDate(Dict *infoDict, char *key, char *text) {
++ Object obj;
++ char *s;
++ int year, mon, day, hour, min, sec;
++ struct tm tmStruct;
++ char buf[256];
++
++ if (infoDict->lookup(key, &obj)->isString()) {
++ fputs(text, stdout);
++ s = obj.getString()->getCString();
++ if (s[0] == 'D' && s[1] == ':') {
++ s += 2;
++ }
++ if (sscanf(s, "%4d%2d%2d%2d%2d%2d",
++ &year, &mon, &day, &hour, &min, &sec) == 6) {
++ tmStruct.tm_year = year - 1900;
++ tmStruct.tm_mon = mon - 1;
++ tmStruct.tm_mday = day;
++ tmStruct.tm_hour = hour;
++ tmStruct.tm_min = min;
++ tmStruct.tm_sec = sec;
++ tmStruct.tm_wday = -1;
++ tmStruct.tm_yday = -1;
++ tmStruct.tm_isdst = -1;
++ // compute the tm_wday and tm_yday fields
++ if (mktime(&tmStruct) != (time_t)-1 &&
++ strftime(buf, sizeof(buf), "%c", &tmStruct)) {
++ fputs(buf, stdout);
++ } else {
++ fputs(s, stdout);
++ }
++ } else {
++ fputs(s, stdout);
++ }
++ fputc('\n', stdout);
++ }
++ obj.free();
++}
++
++static void printBox(char *text, PDFRectangle *box) {
++ printf("%s%8.2f %8.2f %8.2f %8.2f\n",
++ text, box->x1, box->y1, box->x2, box->y2);
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdftohtml.1 poppler-0.4.3/utils/pdftohtml.1
+--- poppler-0.4.3.orig/utils/pdftohtml.1 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdftohtml.1 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,85 @@
++.TH PDFTOHTML 1
++.\" NAME should be all caps, SECTION should be 1-8, maybe w/ subsection
++.\" other parms are allowed: see man(7), man(1)
++.SH NAME
++pdftohtml \- program to convert pdf files into html, xml and png images
++.SH SYNOPSIS
++.B pdftohtml
++.I "[options] <PDF-file> [<html-file> <xml-file>]"
++.SH "DESCRIPTION"
++This manual page documents briefly the
++.BR pdftohtml
++command.
++This manual page was written for the Debian GNU/Linux distribution
++because the original program does not have a manual page.
++.PP
++.B pdftohtml
++is a program that converts pdf documents into html. It generates its output in
++the current working directory.
++.SH OPTIONS
++A summary of options are included below.
++.TP
++.B \-h, \-help
++Show summary of options.
++.TP
++.B \-f <int>
++first page to print
++.TP
++.B \-l <int>
++last page to print
++.TP
++.B \-q
++dont print any messages or errors
++.TP
++.B \-v
++print copyright and version info
++.TP
++.B \-p
++exchange .pdf links with .html
++.TP
++.B \-c
++generate complex output
++.TP
++.B \-i
++ignore images
++.TP
++.B \-noframes
++generate no frames. Not supported in complex output mode.
++.TP
++.B \-stdout
++use standard output
++.TP
++.B \-zoom <fp>
++zoom the pdf document (default 1.5)
++.TP
++.B \-xml
++output for XML post-processing
++.TP
++.B \-enc <string>
++output text encoding name
++.TP
++.B \-opw <string>
++owner password (for encrypted files)
++.TP
++.B \-upw <string>
++user password (for encrypted files)
++.TP
++.B \-hidden
++force hidden text extraction
++.TP
++.B \-dev
++output device name for Ghostscript (png16m, jpeg etc)
++.TP
++.B \-nomerge
++do not merge paragraphs
++.TP
++.B \-nodrm
++override document DRM settings
++
++.SH AUTHOR
++
++Pdftohtml was developed by Gueorgui Ovtcharov and Rainer Dorsch. It is
++based and benefits a lot from Derek Noonburg's xpdf package.
++
++This manual page was written by Søren Boll Overgaard <boll@debian.org>,
++for the Debian GNU/Linux system (but may be used by others).
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdftohtml.cc poppler-0.4.3/utils/pdftohtml.cc
+--- poppler-0.4.3.orig/utils/pdftohtml.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdftohtml.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,428 @@
++//========================================================================
++//
++// pdftohtml.cc
++//
++//
++// Copyright 1999-2000 G. Ovtcharov
++//========================================================================
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stddef.h>
++#include <string.h>
++#include <dirent.h>
++#include <poppler-config.h>
++#include <time.h>
++#include "parseargs.h"
++#include "goo/GooString.h"
++#include "goo/gmem.h"
++#include "Object.h"
++#include "Stream.h"
++#include "Array.h"
++#include "Dict.h"
++#include "XRef.h"
++#include "Catalog.h"
++#include "Page.h"
++#include "PDFDoc.h"
++#include "HtmlOutputDev.h"
++#include "PSOutputDev.h"
++#include "GlobalParams.h"
++#include "Error.h"
++#include "config.h"
++#include "goo/gfile.h"
++
++#ifndef GHOSTSCRIPT
++# define GHOSTSCRIPT "gs"
++#endif
++
++static int firstPage = 1;
++static int lastPage = 0;
++static GBool rawOrder = gTrue;
++GBool printCommands = gTrue;
++static GBool printHelp = gFalse;
++GBool printHtml = gFalse;
++GBool complexMode=gFalse;
++GBool ignore=gFalse;
++//char extension[5]=".png";
++double scale=1.5;
++GBool noframes=gFalse;
++GBool stout=gFalse;
++GBool xml=gFalse;
++GBool errQuiet=gFalse;
++GBool noDrm=gFalse;
++
++GBool showHidden = gFalse;
++GBool noMerge = gFalse;
++static char ownerPassword[33] = "";
++static char userPassword[33] = "";
++static char gsDevice[33] = "png16m";
++static GBool printVersion = gFalse;
++
++static GooString* getInfoString(Dict *infoDict, char *key);
++static GooString* getInfoDate(Dict *infoDict, char *key);
++
++static char textEncName[128] = "";
++
++static ArgDesc argDesc[] = {
++ {"-f", argInt, &firstPage, 0,
++ "first page to convert"},
++ {"-l", argInt, &lastPage, 0,
++ "last page to convert"},
++ /*{"-raw", argFlag, &rawOrder, 0,
++ "keep strings in content stream order"},*/
++ {"-q", argFlag, &errQuiet, 0,
++ "don't print any messages or errors"},
++ {"-h", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-p", argFlag, &printHtml, 0,
++ "exchange .pdf links by .html"},
++ {"-c", argFlag, &complexMode, 0,
++ "generate complex document"},
++ {"-i", argFlag, &ignore, 0,
++ "ignore images"},
++ {"-noframes", argFlag, &noframes, 0,
++ "generate no frames"},
++ {"-stdout" ,argFlag, &stout, 0,
++ "use standard output"},
++ {"-zoom", argFP, &scale, 0,
++ "zoom the pdf document (default 1.5)"},
++ {"-xml", argFlag, &xml, 0,
++ "output for XML post-processing"},
++ {"-hidden", argFlag, &showHidden, 0,
++ "output hidden text"},
++ {"-nomerge", argFlag, &noMerge, 0,
++ "do not merge paragraphs"},
++ {"-enc", argString, textEncName, sizeof(textEncName),
++ "output text encoding name"},
++ {"-dev", argString, gsDevice, sizeof(gsDevice),
++ "output device name for Ghostscript (png16m, jpeg etc)"},
++ {"-v", argFlag, &printVersion, 0,
++ "print copyright and version info"},
++ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
++ "owner password (for encrypted files)"},
++ {"-upw", argString, userPassword, sizeof(userPassword),
++ "user password (for encrypted files)"},
++ {"-nodrm", argFlag, &noDrm, 0,
++ "override document DRM settings"},
++ {NULL}
++};
++
++int main(int argc, char *argv[]) {
++ PDFDoc *doc = NULL;
++ GooString *fileName = NULL;
++ GooString *docTitle = NULL;
++ GooString *author = NULL, *keywords = NULL, *subject = NULL, *date = NULL;
++ GooString *htmlFileName = NULL;
++ GooString *psFileName = NULL;
++ HtmlOutputDev *htmlOut = NULL;
++ PSOutputDev *psOut = NULL;
++ GBool ok;
++ char *p;
++ char extension[16] = "png";
++ GooString *ownerPW, *userPW;
++ Object info;
++ char * extsList[] = {"png", "jpeg", "bmp", "pcx", "tiff", "pbm", NULL};
++
++ // parse args
++ ok = parseArgs(argDesc, &argc, argv);
++ if (!ok || argc < 2 || argc > 3 || printHelp || printVersion) {
++ fprintf(stderr, "pdftohtml version %s http://pdftohtml.sourceforge.net/, based on Xpdf version %s\n", "0.36", xpdfVersion);
++ fprintf(stderr, "%s\n", "Copyright 1999-2003 Gueorgui Ovtcharov and Rainer Dorsch");
++ fprintf(stderr, "%s\n\n", xpdfCopyright);
++ if (!printVersion) {
++ printUsage("pdftohtml", "<PDF-file> [<html-file> <xml-file>]", argDesc);
++ }
++ exit(1);
++ }
++
++ // init error file
++ //errorInit();
++
++ // read config file
++ globalParams = new GlobalParams("");
++
++ if (errQuiet) {
++ globalParams->setErrQuiet(errQuiet);
++ printCommands = gFalse; // I'm not 100% what is the differecne between them
++ }
++
++ if (textEncName[0]) {
++ globalParams->setTextEncoding(textEncName);
++ if( !globalParams->getTextEncoding() ) {
++ goto error;
++ }
++ }
++
++ // open PDF file
++ if (ownerPassword[0]) {
++ ownerPW = new GooString(ownerPassword);
++ } else {
++ ownerPW = NULL;
++ }
++ if (userPassword[0]) {
++ userPW = new GooString(userPassword);
++ } else {
++ userPW = NULL;
++ }
++
++ fileName = new GooString(argv[1]);
++
++ doc = new PDFDoc(fileName, ownerPW, userPW);
++ if (userPW) {
++ delete userPW;
++ }
++ if (ownerPW) {
++ delete ownerPW;
++ }
++ if (!doc->isOk()) {
++ goto error;
++ }
++
++ // check for copy permission
++ if (!doc->okToCopy()) {
++ if (!noDrm) {
++ error(-1, "Copying of text from this document is not allowed.");
++ goto error;
++ }
++ fprintf(stderr, "Document has copy-protection bit set.\n");
++ }
++
++ // construct text file name
++ if (argc == 3) {
++ GooString* tmp = new GooString(argv[2]);
++ p=tmp->getCString()+tmp->getLength()-5;
++ if (!xml)
++ if (!strcmp(p, ".html") || !strcmp(p, ".HTML"))
++ htmlFileName = new GooString(tmp->getCString(),
++ tmp->getLength() - 5);
++ else htmlFileName =new GooString(tmp);
++ else
++ if (!strcmp(p, ".xml") || !strcmp(p, ".XML"))
++ htmlFileName = new GooString(tmp->getCString(),
++ tmp->getLength() - 5);
++ else htmlFileName =new GooString(tmp);
++
++ delete tmp;
++ } else {
++ p = fileName->getCString() + fileName->getLength() - 4;
++ if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))
++ htmlFileName = new GooString(fileName->getCString(),
++ fileName->getLength() - 4);
++ else
++ htmlFileName = fileName->copy();
++ // htmlFileName->append(".html");
++ }
++
++ if (scale>3.0) scale=3.0;
++ if (scale<0.5) scale=0.5;
++
++ if (complexMode) {
++ //noframes=gFalse;
++ stout=gFalse;
++ }
++
++ if (stout) {
++ noframes=gTrue;
++ complexMode=gFalse;
++ }
++
++ if (xml)
++ {
++ complexMode = gTrue;
++ noframes = gTrue;
++ noMerge = gTrue;
++ }
++
++ // get page range
++ if (firstPage < 1)
++ firstPage = 1;
++ if (lastPage < 1 || lastPage > doc->getNumPages())
++ lastPage = doc->getNumPages();
++
++ doc->getDocInfo(&info);
++ if (info.isDict()) {
++ docTitle = getInfoString(info.getDict(), "Title");
++ author = getInfoString(info.getDict(), "Author");
++ keywords = getInfoString(info.getDict(), "Keywords");
++ subject = getInfoString(info.getDict(), "Subject");
++ date = getInfoDate(info.getDict(), "ModDate");
++ if( !date )
++ date = getInfoDate(info.getDict(), "CreationDate");
++ }
++ info.free();
++ if( !docTitle ) docTitle = new GooString(htmlFileName);
++
++ /* determine extensions of output backgroun images */
++ {int i;
++ for(i = 0; extsList[i]; i++)
++ {
++ if( strstr(gsDevice, extsList[i]) != (char *) NULL )
++ {
++ strncpy(extension, extsList[i], sizeof(extension));
++ break;
++ }
++ }}
++
++ rawOrder = complexMode; // todo: figure out what exactly rawOrder do :)
++
++ // write text file
++ htmlOut = new HtmlOutputDev(htmlFileName->getCString(),
++ docTitle->getCString(),
++ author ? author->getCString() : NULL,
++ keywords ? keywords->getCString() : NULL,
++ subject ? subject->getCString() : NULL,
++ date ? date->getCString() : NULL,
++ extension,
++ rawOrder,
++ firstPage,
++ doc->getCatalog()->getOutline()->isDict());
++ delete docTitle;
++ if( author )
++ {
++ delete author;
++ }
++ if( keywords )
++ {
++ delete keywords;
++ }
++ if( subject )
++ {
++ delete subject;
++ }
++ if( date )
++ {
++ delete date;
++ }
++
++ if (htmlOut->isOk())
++ {
++ doc->displayPages(htmlOut, firstPage, lastPage, 72, 72, static_cast<int>(72*scale), 0, gTrue);
++ if (!xml)
++ {
++ htmlOut->dumpDocOutline(doc->getCatalog());
++ }
++ }
++
++ if( complexMode && !xml && !ignore ) {
++ int h=xoutRound(htmlOut->getPageHeight()/scale);
++ int w=xoutRound(htmlOut->getPageWidth()/scale);
++ //int h=xoutRound(doc->getPageHeight(1)/scale);
++ //int w=xoutRound(doc->getPageWidth(1)/scale);
++
++ psFileName = new GooString(htmlFileName->getCString());
++ psFileName->append(".ps");
++
++ globalParams->setPSPaperWidth(w);
++ globalParams->setPSPaperHeight(h);
++ // XXX
++ // globalParams->setPSNoText(gTrue);
++ psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
++ doc->getCatalog(), firstPage, lastPage, psModePS);
++ doc->displayPages(psOut, firstPage, lastPage, 72, 72,
++ static_cast<int>(72*scale), 0, gFalse);
++ delete psOut;
++
++ /*sprintf(buf, "%s -sDEVICE=png16m -dBATCH -dNOPROMPT -dNOPAUSE -r72 -sOutputFile=%s%%03d.png -g%dx%d -q %s", GHOSTSCRIPT, htmlFileName->getCString(), w, h,
++ psFileName->getCString());*/
++
++ GooString *gsCmd = new GooString(GHOSTSCRIPT);
++ GooString *tw, *th, *sc;
++ gsCmd->append(" -sDEVICE=");
++ gsCmd->append(gsDevice);
++ gsCmd->append(" -dBATCH -dNOPROMPT -dNOPAUSE -r");
++ sc = GooString::fromInt(static_cast<int>(72*scale));
++ gsCmd->append(sc);
++ gsCmd->append(" -sOutputFile=");
++ gsCmd->append("\"");
++ gsCmd->append(htmlFileName);
++ gsCmd->append("%03d.");
++ gsCmd->append(extension);
++ gsCmd->append("\" -g");
++ tw = GooString::fromInt(static_cast<int>(scale*w));
++ gsCmd->append(tw);
++ gsCmd->append("x");
++ th = GooString::fromInt(static_cast<int>(scale*h));
++ gsCmd->append(th);
++ gsCmd->append(" -q \"");
++ gsCmd->append(psFileName);
++ gsCmd->append("\"");
++// printf("running: %s\n", gsCmd->getCString());
++ if( !executeCommand(gsCmd->getCString()) && !errQuiet) {
++ error(-1, "Failed to launch Ghostscript!\n");
++ }
++ unlink(psFileName->getCString());
++ delete tw;
++ delete th;
++ delete sc;
++ delete gsCmd;
++ delete psFileName;
++ }
++
++ delete htmlOut;
++
++ // clean up
++ error:
++ if(doc) delete doc;
++ if(globalParams) delete globalParams;
++
++ if(htmlFileName) delete htmlFileName;
++ HtmlFont::clear();
++
++ // check for memory leaks
++ Object::memCheck(stderr);
++ gMemReport(stderr);
++
++ return 0;
++}
++
++static GooString* getInfoString(Dict *infoDict, char *key) {
++ Object obj;
++ GooString *s1 = NULL;
++
++ if (infoDict->lookup(key, &obj)->isString()) {
++ s1 = new GooString(obj.getString());
++ }
++ obj.free();
++ return s1;
++}
++
++static GooString* getInfoDate(Dict *infoDict, char *key) {
++ Object obj;
++ char *s;
++ int year, mon, day, hour, min, sec;
++ struct tm tmStruct;
++ GooString *result = NULL;
++ char buf[256];
++
++ if (infoDict->lookup(key, &obj)->isString()) {
++ s = obj.getString()->getCString();
++ if (s[0] == 'D' && s[1] == ':') {
++ s += 2;
++ }
++ if (sscanf(s, "%4d%2d%2d%2d%2d%2d",
++ &year, &mon, &day, &hour, &min, &sec) == 6) {
++ tmStruct.tm_year = year - 1900;
++ tmStruct.tm_mon = mon - 1;
++ tmStruct.tm_mday = day;
++ tmStruct.tm_hour = hour;
++ tmStruct.tm_min = min;
++ tmStruct.tm_sec = sec;
++ tmStruct.tm_wday = -1;
++ tmStruct.tm_yday = -1;
++ tmStruct.tm_isdst = -1;
++ mktime(&tmStruct); // compute the tm_wday and tm_yday fields
++ if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S+00:00", &tmStruct)) {
++ result = new GooString(buf);
++ } else {
++ result = new GooString(s);
++ }
++ } else {
++ result = new GooString(s);
++ }
++ }
++ obj.free();
++ return result;
++}
++
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdftoppm.1 poppler-0.4.3/utils/pdftoppm.1
+--- poppler-0.4.3.orig/utils/pdftoppm.1 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdftoppm.1 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,113 @@
++.\" Copyright 2004 Glyph & Cog, LLC
++.TH pdftoppm 1 "22 January 2004"
++.SH NAME
++pdftoppm \- Portable Document Format (PDF) to Portable Pixmap (PPM)
++converter (version 3.00)
++.SH SYNOPSIS
++.B pdftoppm
++[options]
++.I PDF-file PPM-root
++.SH DESCRIPTION
++.B Pdftoppm
++converts Portable Document Format (PDF) files to color image files in
++Portable Pixmap (PPM) format, grayscale image files in Portable
++Graymap (PGM) format, or monochrome image files in Portable Bitmap
++(PBM) format.
++.PP
++Pdftoppm reads the PDF file,
++.IR PDF-file ,
++and writes one PPM file for each page,
++.IR PPM-root - nnnnnn .ppm,
++where
++.I nnnnnn
++is the page number.
++.SH CONFIGURATION FILE
++Pdftoppm reads a configuration file at startup. It first tries to
++find the user's private config file, ~/.xpdfrc. If that doesn't
++exist, it looks for a system-wide config file, /etc/xpdf/xpdfrc. See the
++.BR xpdfrc (5)
++man page for details.
++.SH OPTIONS
++Many of the following options can be set with configuration file
++commands. These are listed in square brackets with the description of
++the corresponding command line option.
++.TP
++.BI \-f " number"
++Specifies the first page to convert.
++.TP
++.BI \-l " number"
++Specifies the last page to convert.
++.TP
++.BI \-r " number"
++Specifies the resolution, in DPI. The default is 150 DPI.
++.TP
++.B \-mono
++Generate a monochrome PBM file (instead of a color PPM file).
++.TP
++.B \-gray
++Generate a grayscale PGM file (instead of a color PPM file).
++.TP
++.BI \-t1lib " yes | no"
++Enable or disable t1lib (a Type 1 font rasterizer). This defaults to
++"yes".
++.RB "[config file: " enableT1lib ]
++.TP
++.BI \-freetype " yes | no"
++Enable or disable FreeType (a TrueType / Type 1 font rasterizer).
++This defaults to "yes".
++.RB "[config file: " enableFreeType ]
++.TP
++.BI \-aa " yes | no"
++Enable or disable font anti-aliasing. This defaults to "yes".
++.RB "[config file: " antialias ]
++.TP
++.BI \-opw " password"
++Specify the owner password for the PDF file. Providing this will
++bypass all security restrictions.
++.TP
++.BI \-upw " password"
++Specify the user password for the PDF file.
++.TP
++.B \-q
++Don't print any messages or errors.
++.RB "[config file: " errQuiet ]
++.TP
++.B \-v
++Print copyright and version information.
++.TP
++.B \-h
++Print usage information.
++.RB ( \-help
++and
++.B \-\-help
++are equivalent.)
++.SH EXIT CODES
++The Xpdf tools use the following exit codes:
++.TP
++0
++No error.
++.TP
++1
++Error opening a PDF file.
++.TP
++2
++Error opening an output file.
++.TP
++3
++Error related to PDF permissions.
++.TP
++99
++Other error.
++.SH AUTHOR
++The pdftoppm software and documentation are copyright 1996-2004 Glyph
++& Cog, LLC.
++.SH "SEE ALSO"
++.BR xpdf (1),
++.BR pdftops (1),
++.BR pdftotext (1),
++.BR pdfinfo (1),
++.BR pdffonts (1),
++.BR pdfimages (1),
++.BR xpdfrc (5)
++.br
++.B http://www.foolabs.com/xpdf/
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdftoppm.cc poppler-0.4.3/utils/pdftoppm.cc
+--- poppler-0.4.3.orig/utils/pdftoppm.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdftoppm.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,189 @@
++//========================================================================
++//
++// pdftoppm.cc
++//
++// Copyright 2003 Glyph & Cog, LLC
++//
++//========================================================================
++
++#include <poppler-config.h>
++#include <stdio.h>
++#include "parseargs.h"
++#include "goo/gmem.h"
++#include "goo/GooString.h"
++#include "GlobalParams.h"
++#include "Object.h"
++#include "PDFDoc.h"
++#include "splash/SplashBitmap.h"
++#include "splash/Splash.h"
++#include "SplashOutputDev.h"
++#include "config.h"
++
++static int firstPage = 1;
++static int lastPage = 0;
++static int resolution = 150;
++static GBool mono = gFalse;
++static GBool gray = gFalse;
++static char enableT1libStr[16] = "";
++static char enableFreeTypeStr[16] = "";
++static char antialiasStr[16] = "";
++static char ownerPassword[33] = "";
++static char userPassword[33] = "";
++static GBool quiet = gFalse;
++static char cfgFileName[256] = "";
++static GBool printVersion = gFalse;
++static GBool printHelp = gFalse;
++
++static ArgDesc argDesc[] = {
++ {"-f", argInt, &firstPage, 0,
++ "first page to print"},
++ {"-l", argInt, &lastPage, 0,
++ "last page to print"},
++ {"-r", argInt, &resolution, 0,
++ "resolution, in DPI (default is 150)"},
++ {"-mono", argFlag, &mono, 0,
++ "generate a monochrome PBM file"},
++ {"-gray", argFlag, &gray, 0,
++ "generate a grayscale PGM file"},
++#if HAVE_T1LIB_H
++ {"-t1lib", argString, enableT1libStr, sizeof(enableT1libStr),
++ "enable t1lib font rasterizer: yes, no"},
++#endif
++#if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H
++ {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr),
++ "enable FreeType font rasterizer: yes, no"},
++#endif
++ {"-aa", argString, antialiasStr, sizeof(antialiasStr),
++ "enable font anti-aliasing: yes, no"},
++ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
++ "owner password (for encrypted files)"},
++ {"-upw", argString, userPassword, sizeof(userPassword),
++ "user password (for encrypted files)"},
++ {"-q", argFlag, &quiet, 0,
++ "don't print any messages or errors"},
++ {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
++ "configuration file to use in place of .xpdfrc"},
++ {"-v", argFlag, &printVersion, 0,
++ "print copyright and version info"},
++ {"-h", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"--help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-?", argFlag, &printHelp, 0,
++ "print usage information"},
++ {NULL}
++};
++
++int main(int argc, char *argv[]) {
++ PDFDoc *doc;
++ GooString *fileName;
++ char *ppmRoot;
++ char ppmFile[512];
++ GooString *ownerPW, *userPW;
++ SplashColor paperColor;
++ SplashOutputDev *splashOut;
++ GBool ok;
++ int exitCode;
++ int pg;
++
++ exitCode = 99;
++
++ // parse args
++ ok = parseArgs(argDesc, &argc, argv);
++ if (mono && gray) {
++ ok = gFalse;
++ }
++ if (!ok || argc != 3 || printVersion || printHelp) {
++ fprintf(stderr, "pdftoppm version %s\n", xpdfVersion);
++ fprintf(stderr, "%s\n", xpdfCopyright);
++ if (!printVersion) {
++ printUsage("pdftoppm", "<PDF-file> <PPM-root>", argDesc);
++ }
++ goto err0;
++ }
++ fileName = new GooString(argv[1]);
++ ppmRoot = argv[2];
++
++ // read config file
++ globalParams = new GlobalParams(cfgFileName);
++ globalParams->setupBaseFonts(NULL);
++ if (enableT1libStr[0]) {
++ if (!globalParams->setEnableT1lib(enableT1libStr)) {
++ fprintf(stderr, "Bad '-t1lib' value on command line\n");
++ }
++ }
++ if (enableFreeTypeStr[0]) {
++ if (!globalParams->setEnableFreeType(enableFreeTypeStr)) {
++ fprintf(stderr, "Bad '-freetype' value on command line\n");
++ }
++ }
++ if (antialiasStr[0]) {
++ if (!globalParams->setAntialias(antialiasStr)) {
++ fprintf(stderr, "Bad '-aa' value on command line\n");
++ }
++ }
++ if (quiet) {
++ globalParams->setErrQuiet(quiet);
++ }
++
++ // open PDF file
++ if (ownerPassword[0]) {
++ ownerPW = new GooString(ownerPassword);
++ } else {
++ ownerPW = NULL;
++ }
++ if (userPassword[0]) {
++ userPW = new GooString(userPassword);
++ } else {
++ userPW = NULL;
++ }
++ doc = new PDFDoc(fileName, ownerPW, userPW);
++ if (userPW) {
++ delete userPW;
++ }
++ if (ownerPW) {
++ delete ownerPW;
++ }
++ if (!doc->isOk()) {
++ exitCode = 1;
++ goto err1;
++ }
++
++ // get page range
++ if (firstPage < 1)
++ firstPage = 1;
++ if (lastPage < 1 || lastPage > doc->getNumPages())
++ lastPage = doc->getNumPages();
++
++ // write PPM files
++ paperColor.rgb8 = splashMakeRGB8(255, 255, 255);
++ splashOut = new SplashOutputDev(mono ? splashModeMono1 :
++ gray ? splashModeMono8 :
++ splashModeRGB8,
++ gFalse, paperColor);
++ splashOut->startDoc(doc->getXRef());
++ for (pg = firstPage; pg <= lastPage; ++pg) {
++ doc->displayPage(splashOut, pg, resolution, resolution, 0, gTrue, gFalse);
++ sprintf(ppmFile, "%.*s-%06d.%s",
++ (int)sizeof(ppmFile) - 32, ppmRoot, pg,
++ mono ? "pbm" : gray ? "pgm" : "ppm");
++ splashOut->getBitmap()->writePNMFile(ppmFile);
++ }
++ delete splashOut;
++
++ exitCode = 0;
++
++ // clean up
++ err1:
++ delete doc;
++ delete globalParams;
++ err0:
++
++ // check for memory leaks
++ Object::memCheck(stderr);
++ gMemReport(stderr);
++
++ return exitCode;
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdftops.1 poppler-0.4.3/utils/pdftops.1
+--- poppler-0.4.3.orig/utils/pdftops.1 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdftops.1 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,224 @@
++.\" Copyright 1996-2004 Glyph & Cog, LLC
++.TH pdftops 1 "22 January 2004"
++.SH NAME
++pdftops \- Portable Document Format (PDF) to PostScript converter
++(version 3.00)
++.SH SYNOPSIS
++.B pdftops
++[options]
++.RI [ PDF-file
++.RI [ PS-file ]]
++.SH DESCRIPTION
++.B Pdftops
++converts Portable Document Format (PDF) files to PostScript so they
++can be printed.
++.PP
++Pdftops reads the PDF file,
++.IR PDF-file ,
++and writes a PostScript file,
++.IR PS-file .
++If
++.I PS-file
++is not specified, pdftops converts
++.I file.pdf
++to
++.I file.ps
++(or
++.I file.eps
++with the -eps option). If
++.I PS-file
++is \'-', the PostScript is sent to stdout.
++.SH CONFIGURATION FILE
++Pdftops reads a configuration file at startup. It first tries to find
++the user's private config file, ~/.xpdfrc. If that doesn't exist, it
++looks for a system-wide config file, /etc/xpdf/xpdfrc. See the
++.BR xpdfrc (5)
++man page for details.
++.SH OPTIONS
++Many of the following options can be set with configuration file
++commands. These are listed in square brackets with the description of
++the corresponding command line option.
++.TP
++.BI \-f " number"
++Specifies the first page to print.
++.TP
++.BI \-l " number"
++Specifies the last page to print.
++.TP
++.B \-level1
++Generate Level 1 PostScript. The resulting PostScript files will be
++significantly larger (if they contain images), but will print on Level
++1 printers. This also converts all images to black and white. No
++more than one of the PostScript level options (-level1, -level1sep,
++-level2, -level2sep, -level3, -level3Sep) may be given.
++.RB "[config file: " psLevel ]
++.TP
++.B \-level1sep
++Generate Level 1 separable PostScript. All colors are converted to
++CMYK. Images are written with separate stream data for the four
++components.
++.RB "[config file: " psLevel ]
++.TP
++.B \-level2
++Generate Level 2 PostScript. Level 2 supports color images and image
++compression. This is the default setting.
++.RB "[config file: " psLevel ]
++.TP
++.B \-level2sep
++Generate Level 2 separable PostScript. All colors are converted to
++CMYK. The PostScript separation convention operators are used to
++handle custom (spot) colors.
++.RB "[config file: " psLevel ]
++.TP
++.B \-level3
++Generate Level 3 PostScript. This enables all Level 2 features plus
++CID font embedding.
++.RB "[config file: " psLevel ]
++.TP
++.B \-level3Sep
++Generate Level 3 separable PostScript. The separation handling is the
++same as for -level2Sep.
++.RB "[config file: " psLevel ]
++.TP
++.B \-eps
++Generate an Encapsulated PostScript (EPS) file. An EPS file contains
++a single image, so if you use this option with a multi-page PDF file,
++you must use -f and -l to specify a single page. No more than one of
++the mode options (-eps, -form) may be given.
++.TP
++.B \-form
++Generate a PostScript form which can be imported by software that
++understands forms. A form contains a single page, so if you use this
++option with a multi-page PDF file, you must use -f and -l to specify a
++single page. The -level1 option cannot be used with -form.
++.TP
++.B \-opi
++Generate OPI comments for all images and forms which have OPI
++information. (This option is only available if pdftops was compiled
++with OPI support.)
++.RB "[config file: " psOPI ]
++.TP
++.B \-noembt1
++By default, any Type 1 fonts which are embedded in the PDF file are
++copied into the PostScript file. This option causes pdftops to
++substitute base fonts instead. Embedded fonts make PostScript files
++larger, but may be necessary for readable output.
++.RB "[config file: " psEmbedType1Fonts ]
++.TP
++.B \-noembtt
++By default, any TrueType fonts which are embedded in the PDF file are
++copied into the PostScript file. This option causes pdftops to
++substitute base fonts instead. Embedded fonts make PostScript files
++larger, but may be necessary for readable output. Also, some
++PostScript interpreters do not have TrueType rasterizers.
++.RB "[config file: " psEmbedTrueTypeFonts ]
++.TP
++.B \-noembcidps
++By default, any CID PostScript fonts which are embedded in the PDF
++file are copied into the PostScript file. This option disables that
++embedding. No attempt is made to substitute for non-embedded CID
++PostScript fonts.
++.RB "[config file: " psEmbedCIDPostScriptFonts ]
++.TP
++.B \-noembcidtt
++By default, any CID TrueType fonts which are embedded in the PDF file
++are copied into the PostScript file. This option disables that
++embedding. No attempt is made to substitute for non-embedded CID
++TrueType fonts.
++.RB "[config file: " psEmbedCIDTrueTypeFonts ]
++.TP
++.BI \-paper " size"
++Set the paper size to one of "letter", "legal", "A4", or "A3". This
++can also be set to "match", which will set the paper size to match the
++size specified in the PDF file.
++.RB "[config file: " psPaperSize ]
++.TP
++.BI \-paperw " size"
++Set the paper width, in points.
++.RB "[config file: " psPaperSize ]
++.TP
++.BI \-paperh " size"
++Set the paper height, in points.
++.RB "[config file: " psPaperSize ]
++.TP
++.B \-nocrop
++By default, output is cropped to the CropBox specified in the PDF
++file. This option disables cropping.
++.RB "[config file: " psCrop ]
++.TP
++.B \-expand
++Expand PDF pages smaller than the paper to fill the paper. By
++default, these pages are not scaled.
++.RB "[config file: " psExpandSmaller ]
++.TP
++.B \-noshrink
++Don't scale PDF pages which are larger than the paper. By default,
++pages larger than the paper are shrunk to fit.
++.RB "[config file: " psShrinkLarger ]
++.TP
++.B \-nocenter
++By default, PDF pages smaller than the paper (after any scaling) are
++centered on the paper. This option causes them to be aligned to the
++lower-left corner of the paper instead.
++.RB "[config file: " psCenter ]
++.TP
++.B \-duplex
++Set the Duplex pagedevice entry in the PostScript file. This tells
++duplex-capable printers to enable duplexing.
++.RB "[config file: " psDuplex ]
++.TP
++.BI \-opw " password"
++Specify the owner password for the PDF file. Providing this will
++bypass all security restrictions.
++.TP
++.BI \-upw " password"
++Specify the user password for the PDF file.
++.TP
++.B \-q
++Don't print any messages or errors.
++.RB "[config file: " errQuiet ]
++.TP
++.BI \-cfg " config-file"
++Read
++.I config-file
++in place of ~/.xpdfrc or the system-wide config file.
++.TP
++.B \-v
++Print copyright and version information.
++.TP
++.B \-h
++Print usage information.
++.RB ( \-help
++and
++.B \-\-help
++are equivalent.)
++.SH EXIT CODES
++The Xpdf tools use the following exit codes:
++.TP
++0
++No error.
++.TP
++1
++Error opening a PDF file.
++.TP
++2
++Error opening an output file.
++.TP
++3
++Error related to PDF permissions.
++.TP
++99
++Other error.
++.SH AUTHOR
++The pdftops software and documentation are copyright 1996-2004 Glyph &
++Cog, LLC.
++.SH "SEE ALSO"
++.BR xpdf (1),
++.BR pdftotext (1),
++.BR pdfinfo (1),
++.BR pdffonts (1),
++.BR pdftoppm (1),
++.BR pdfimages (1),
++.BR xpdfrc (5)
++.br
++.B http://www.foolabs.com/xpdf/
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdftops.cc poppler-0.4.3/utils/pdftops.cc
+--- poppler-0.4.3.orig/utils/pdftops.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdftops.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,336 @@
++//========================================================================
++//
++// pdftops.cc
++//
++// Copyright 1996-2003 Glyph & Cog, LLC
++//
++// Modified for Debian by Hamish Moffatt, 22 May 2002.
++//
++//========================================================================
++
++#include <poppler-config.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stddef.h>
++#include <string.h>
++#include "parseargs.h"
++#include "goo/GooString.h"
++#include "goo/gmem.h"
++#include "GlobalParams.h"
++#include "Object.h"
++#include "Stream.h"
++#include "Array.h"
++#include "Dict.h"
++#include "XRef.h"
++#include "Catalog.h"
++#include "Page.h"
++#include "PDFDoc.h"
++#include "PSOutputDev.h"
++#include "Error.h"
++#include "config.h"
++
++static int firstPage = 1;
++static int lastPage = 0;
++static GBool level1 = gFalse;
++static GBool level1Sep = gFalse;
++static GBool level2 = gFalse;
++static GBool level2Sep = gFalse;
++static GBool level3 = gFalse;
++static GBool level3Sep = gFalse;
++static GBool doEPS = gFalse;
++static GBool doForm = gFalse;
++#if OPI_SUPPORT
++static GBool doOPI = gFalse;
++#endif
++static GBool noEmbedT1Fonts = gFalse;
++static GBool noEmbedTTFonts = gFalse;
++static GBool noEmbedCIDPSFonts = gFalse;
++static GBool noEmbedCIDTTFonts = gFalse;
++static char paperSize[15] = "";
++static int paperWidth = 0;
++static int paperHeight = 0;
++static GBool noCrop = gFalse;
++static GBool expand = gFalse;
++static GBool noShrink = gFalse;
++static GBool noCenter = gFalse;
++static GBool duplex = gFalse;
++static char ownerPassword[33] = "\001";
++static char userPassword[33] = "\001";
++static GBool quiet = gFalse;
++static char cfgFileName[256] = "";
++static GBool printVersion = gFalse;
++static GBool printHelp = gFalse;
++
++static ArgDesc argDesc[] = {
++ {"-f", argInt, &firstPage, 0,
++ "first page to print"},
++ {"-l", argInt, &lastPage, 0,
++ "last page to print"},
++ {"-level1", argFlag, &level1, 0,
++ "generate Level 1 PostScript"},
++ {"-level1sep", argFlag, &level1Sep, 0,
++ "generate Level 1 separable PostScript"},
++ {"-level2", argFlag, &level2, 0,
++ "generate Level 2 PostScript"},
++ {"-level2sep", argFlag, &level2Sep, 0,
++ "generate Level 2 separable PostScript"},
++ {"-level3", argFlag, &level3, 0,
++ "generate Level 3 PostScript"},
++ {"-level3sep", argFlag, &level3Sep, 0,
++ "generate Level 3 separable PostScript"},
++ {"-eps", argFlag, &doEPS, 0,
++ "generate Encapsulated PostScript (EPS)"},
++ {"-form", argFlag, &doForm, 0,
++ "generate a PostScript form"},
++#if OPI_SUPPORT
++ {"-opi", argFlag, &doOPI, 0,
++ "generate OPI comments"},
++#endif
++ {"-noembt1", argFlag, &noEmbedT1Fonts, 0,
++ "don't embed Type 1 fonts"},
++ {"-noembtt", argFlag, &noEmbedTTFonts, 0,
++ "don't embed TrueType fonts"},
++ {"-noembcidps", argFlag, &noEmbedCIDPSFonts, 0,
++ "don't embed CID PostScript fonts"},
++ {"-noembcidtt", argFlag, &noEmbedCIDTTFonts, 0,
++ "don't embed CID TrueType fonts"},
++ {"-paper", argString, paperSize, sizeof(paperSize),
++ "paper size (letter, legal, A4, A3, match)"},
++ {"-paperw", argInt, &paperWidth, 0,
++ "paper width, in points"},
++ {"-paperh", argInt, &paperHeight, 0,
++ "paper height, in points"},
++ {"-nocrop", argFlag, &noCrop, 0,
++ "don't crop pages to CropBox"},
++ {"-expand", argFlag, &expand, 0,
++ "expand pages smaller than the paper size"},
++ {"-noshrink", argFlag, &noShrink, 0,
++ "don't shrink pages larger than the paper size"},
++ {"-nocenter", argFlag, &noCenter, 0,
++ "don't center pages smaller than the paper size"},
++ {"-duplex", argFlag, &duplex, 0,
++ "enable duplex printing"},
++ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
++ "owner password (for encrypted files)"},
++ {"-upw", argString, userPassword, sizeof(userPassword),
++ "user password (for encrypted files)"},
++ {"-q", argFlag, &quiet, 0,
++ "don't print any messages or errors"},
++ {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
++ "configuration file to use in place of .xpdfrc"},
++ {"-v", argFlag, &printVersion, 0,
++ "print copyright and version info"},
++ {"-h", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"--help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-?", argFlag, &printHelp, 0,
++ "print usage information"},
++ {NULL}
++};
++
++int main(int argc, char *argv[]) {
++ PDFDoc *doc;
++ GooString *fileName;
++ GooString *psFileName;
++ PSLevel level;
++ PSOutMode mode;
++ GooString *ownerPW, *userPW;
++ PSOutputDev *psOut;
++ GBool ok;
++ char *p;
++ int exitCode;
++
++ exitCode = 99;
++
++ // parse args
++ ok = parseArgs(argDesc, &argc, argv);
++ if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
++ fprintf(stderr, "pdftops version %s\n", xpdfVersion);
++ fprintf(stderr, "%s\n", xpdfCopyright);
++ if (!printVersion) {
++ printUsage("pdftops", "<PDF-file> [<PS-file>]", argDesc);
++ }
++ exit(1);
++ }
++ if ((level1 ? 1 : 0) +
++ (level1Sep ? 1 : 0) +
++ (level2 ? 1 : 0) +
++ (level2Sep ? 1 : 0) +
++ (level3 ? 1 : 0) +
++ (level3Sep ? 1 : 0) > 1) {
++ fprintf(stderr, "Error: use only one of the 'level' options.\n");
++ exit(1);
++ }
++ if (doEPS && doForm) {
++ fprintf(stderr, "Error: use only one of -eps and -form\n");
++ exit(1);
++ }
++ if (level1) {
++ level = psLevel1;
++ } else if (level1Sep) {
++ level = psLevel1Sep;
++ } else if (level2Sep) {
++ level = psLevel2Sep;
++ } else if (level3) {
++ level = psLevel3;
++ } else if (level3Sep) {
++ level = psLevel3Sep;
++ } else {
++ level = psLevel2;
++ }
++ if (doForm && level < psLevel2) {
++ fprintf(stderr, "Error: forms are only available with Level 2 output.\n");
++ exit(1);
++ }
++ mode = doEPS ? psModeEPS
++ : doForm ? psModeForm
++ : psModePS;
++ fileName = new GooString(argv[1]);
++
++ // read config file
++ globalParams = new GlobalParams(cfgFileName);
++ if (paperSize[0]) {
++ if (!globalParams->setPSPaperSize(paperSize)) {
++ fprintf(stderr, "Invalid paper size\n");
++ delete fileName;
++ goto err0;
++ }
++ } else {
++ if (paperWidth) {
++ globalParams->setPSPaperWidth(paperWidth);
++ }
++ if (paperHeight) {
++ globalParams->setPSPaperHeight(paperHeight);
++ }
++ }
++ if (noCrop) {
++ globalParams->setPSCrop(gFalse);
++ }
++ if (expand) {
++ globalParams->setPSExpandSmaller(gTrue);
++ }
++ if (noShrink) {
++ globalParams->setPSShrinkLarger(gFalse);
++ }
++ if (noCenter) {
++ globalParams->setPSCenter(gFalse);
++ }
++ if (duplex) {
++ globalParams->setPSDuplex(duplex);
++ }
++ if (level1 || level1Sep || level2 || level2Sep || level3 || level3Sep) {
++ globalParams->setPSLevel(level);
++ }
++ if (noEmbedT1Fonts) {
++ globalParams->setPSEmbedType1(!noEmbedT1Fonts);
++ }
++ if (noEmbedTTFonts) {
++ globalParams->setPSEmbedTrueType(!noEmbedTTFonts);
++ }
++ if (noEmbedCIDPSFonts) {
++ globalParams->setPSEmbedCIDPostScript(!noEmbedCIDPSFonts);
++ }
++ if (noEmbedCIDTTFonts) {
++ globalParams->setPSEmbedCIDTrueType(!noEmbedCIDTTFonts);
++ }
++#if OPI_SUPPORT
++ if (doOPI) {
++ globalParams->setPSOPI(doOPI);
++ }
++#endif
++ if (quiet) {
++ globalParams->setErrQuiet(quiet);
++ }
++
++ // open PDF file
++ if (ownerPassword[0] != '\001') {
++ ownerPW = new GooString(ownerPassword);
++ } else {
++ ownerPW = NULL;
++ }
++ if (userPassword[0] != '\001') {
++ userPW = new GooString(userPassword);
++ } else {
++ userPW = NULL;
++ }
++ doc = new PDFDoc(fileName, ownerPW, userPW);
++ if (userPW) {
++ delete userPW;
++ }
++ if (ownerPW) {
++ delete ownerPW;
++ }
++ if (!doc->isOk()) {
++ exitCode = 1;
++ goto err1;
++ }
++
++#ifdef ENFORCE_PERMISSIONS
++ // check for print permission
++ if (!doc->okToPrint()) {
++ error(-1, "Printing this document is not allowed.");
++ exitCode = 3;
++ goto err1;
++ }
++#endif
++
++ // construct PostScript file name
++ if (argc == 3) {
++ psFileName = new GooString(argv[2]);
++ } else {
++ p = fileName->getCString() + fileName->getLength() - 4;
++ if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) {
++ psFileName = new GooString(fileName->getCString(),
++ fileName->getLength() - 4);
++ } else {
++ psFileName = fileName->copy();
++ }
++ psFileName->append(doEPS ? ".eps" : ".ps");
++ }
++
++ // get page range
++ if (firstPage < 1) {
++ firstPage = 1;
++ }
++ if (lastPage < 1 || lastPage > doc->getNumPages()) {
++ lastPage = doc->getNumPages();
++ }
++
++ // check for multi-page EPS or form
++ if ((doEPS || doForm) && firstPage != lastPage) {
++ error(-1, "EPS and form files can only contain one page.");
++ goto err2;
++ }
++
++ // write PostScript file
++ psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
++ doc->getCatalog(), firstPage, lastPage, mode);
++ if (psOut->isOk()) {
++ doc->displayPages(psOut, firstPage, lastPage, 72, 72,
++ 0, globalParams->getPSCrop(), gFalse);
++ } else {
++ delete psOut;
++ exitCode = 2;
++ goto err2;
++ }
++ delete psOut;
++
++ exitCode = 0;
++
++ // clean up
++ err2:
++ delete psFileName;
++ err1:
++ delete doc;
++ err0:
++ delete globalParams;
++
++ // check for memory leaks
++ Object::memCheck(stderr);
++ gMemReport(stderr);
++
++ return exitCode;
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdftotext.1 poppler-0.4.3/utils/pdftotext.1
+--- poppler-0.4.3.orig/utils/pdftotext.1 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdftotext.1 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,135 @@
++.\" Copyright 1997-2004 Glyph & Cog, LLC
++.TH pdftotext 1 "22 January 2004"
++.SH NAME
++pdftotext \- Portable Document Format (PDF) to text converter
++(version 3.00)
++.SH SYNOPSIS
++.B pdftotext
++[options]
++.RI [ PDF-file
++.RI [ text-file ]]
++.SH DESCRIPTION
++.B Pdftotext
++converts Portable Document Format (PDF) files to plain text.
++.PP
++Pdftotext reads the PDF file,
++.IR PDF-file ,
++and writes a text file,
++.IR text-file .
++If
++.I text-file
++is not specified, pdftotext converts
++.I file.pdf
++to
++.IR file.txt .
++If
++.I text-file
++is \'-', the text is sent to stdout.
++.SH CONFIGURATION FILE
++Pdftotext reads a configuration file at startup. It first tries to
++find the user's private config file, ~/.xpdfrc. If that doesn't
++exist, it looks for a system-wide config file, /etc/xpdf/xpdfrc. See the
++.BR xpdfrc (5)
++man page for details.
++.SH OPTIONS
++Many of the following options can be set with configuration file
++commands. These are listed in square brackets with the description of
++the corresponding command line option.
++.TP
++.BI \-f " number"
++Specifies the first page to convert.
++.TP
++.BI \-l " number"
++Specifies the last page to convert.
++.TP
++.B \-layout
++Maintain (as best as possible) the original physical layout of the
++text. The default is to \'undo' physical layout (columns,
++hyphenation, etc.) and output the text in reading order.
++.TP
++.B \-raw
++Keep the text in content stream order. This is a hack which often
++"undoes" column formatting, etc. Use of raw mode is no longer
++recommended.
++.TP
++.B \-htmlmeta
++Generate a simple HTML file, including the meta information. This
++simply wraps the text in <pre> and </pre> and prepends the meta
++headers.
++.TP
++.BI \-enc " encoding-name"
++Sets the encoding to use for text output. The
++.I encoding\-name
++must be defined with the unicodeMap command (see
++.BR xpdfrc (5)).
++The encoding name is case-sensitive. This defaults to "Latin1" (which
++is a built-in encoding).
++.RB "[config file: " textEncoding ]
++.TP
++.BI \-eol " unix | dos | mac"
++Sets the end-of-line convention to use for text output.
++.RB "[config file: " textEOL ]
++.TP
++.B \-nopgbrk
++Don't insert page breaks (form feed characters) between pages.
++.RB "[config file: " textPageBreaks ]
++.TP
++.BI \-opw " password"
++Specify the owner password for the PDF file. Providing this will
++bypass all security restrictions.
++.TP
++.BI \-upw " password"
++Specify the user password for the PDF file.
++.TP
++.B \-q
++Don't print any messages or errors.
++.RB "[config file: " errQuiet ]
++.TP
++.BI \-cfg " config-file"
++Read
++.I config-file
++in place of ~/.xpdfrc or the system-wide config file.
++.TP
++.B \-v
++Print copyright and version information.
++.TP
++.B \-h
++Print usage information.
++.RB ( \-help
++and
++.B \-\-help
++are equivalent.)
++.SH BUGS
++Some PDF files contain fonts whose encodings have been mangled beyond
++recognition. There is no way (short of OCR) to extract text from
++these files.
++.SH EXIT CODES
++The Xpdf tools use the following exit codes:
++.TP
++0
++No error.
++.TP
++1
++Error opening a PDF file.
++.TP
++2
++Error opening an output file.
++.TP
++3
++Error related to PDF permissions.
++.TP
++99
++Other error.
++.SH AUTHOR
++The pdftotext software and documentation are copyright 1996-2004 Glyph
++& Cog, LLC.
++.SH "SEE ALSO"
++.BR xpdf (1),
++.BR pdftops (1),
++.BR pdfinfo (1),
++.BR pdffonts (1),
++.BR pdftoppm (1),
++.BR pdfimages (1),
++.BR xpdfrc (5)
++.br
++.B http://www.foolabs.com/xpdf/
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/pdftotext.cc poppler-0.4.3/utils/pdftotext.cc
+--- poppler-0.4.3.orig/utils/pdftotext.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/pdftotext.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,336 @@
++//========================================================================
++//
++// pdftotext.cc
++//
++// Copyright 1997-2003 Glyph & Cog, LLC
++//
++// Modified for Debian by Hamish Moffatt, 22 May 2002.
++//
++//========================================================================
++
++#include <poppler-config.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stddef.h>
++#include <string.h>
++#include "parseargs.h"
++#include "goo/GooString.h"
++#include "goo/gmem.h"
++#include "GlobalParams.h"
++#include "Object.h"
++#include "Stream.h"
++#include "Array.h"
++#include "Dict.h"
++#include "XRef.h"
++#include "Catalog.h"
++#include "Page.h"
++#include "PDFDoc.h"
++#include "TextOutputDev.h"
++#include "CharTypes.h"
++#include "UnicodeMap.h"
++#include "Error.h"
++#include "config.h"
++
++static void printInfoString(FILE *f, Dict *infoDict, char *key,
++ char *text1, char *text2, UnicodeMap *uMap);
++static void printInfoDate(FILE *f, Dict *infoDict, char *key, char *fmt);
++
++static int firstPage = 1;
++static int lastPage = 0;
++static GBool physLayout = gFalse;
++static GBool rawOrder = gFalse;
++static GBool htmlMeta = gFalse;
++static char textEncName[128] = "";
++static char textEOL[16] = "";
++static GBool noPageBreaks = gFalse;
++static char ownerPassword[33] = "\001";
++static char userPassword[33] = "\001";
++static GBool quiet = gFalse;
++static char cfgFileName[256] = "";
++static GBool printVersion = gFalse;
++static GBool printHelp = gFalse;
++
++static ArgDesc argDesc[] = {
++ {"-f", argInt, &firstPage, 0,
++ "first page to convert"},
++ {"-l", argInt, &lastPage, 0,
++ "last page to convert"},
++ {"-layout", argFlag, &physLayout, 0,
++ "maintain original physical layout"},
++ {"-raw", argFlag, &rawOrder, 0,
++ "keep strings in content stream order"},
++ {"-htmlmeta", argFlag, &htmlMeta, 0,
++ "generate a simple HTML file, including the meta information"},
++ {"-enc", argString, textEncName, sizeof(textEncName),
++ "output text encoding name"},
++ {"-eol", argString, textEOL, sizeof(textEOL),
++ "output end-of-line convention (unix, dos, or mac)"},
++ {"-nopgbrk", argFlag, &noPageBreaks, 0,
++ "don't insert page breaks between pages"},
++ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
++ "owner password (for encrypted files)"},
++ {"-upw", argString, userPassword, sizeof(userPassword),
++ "user password (for encrypted files)"},
++ {"-q", argFlag, &quiet, 0,
++ "don't print any messages or errors"},
++ {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
++ "configuration file to use in place of .xpdfrc"},
++ {"-v", argFlag, &printVersion, 0,
++ "print copyright and version info"},
++ {"-h", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"--help", argFlag, &printHelp, 0,
++ "print usage information"},
++ {"-?", argFlag, &printHelp, 0,
++ "print usage information"},
++ {NULL}
++};
++
++int main(int argc, char *argv[]) {
++ PDFDoc *doc;
++ GooString *fileName;
++ GooString *textFileName;
++ GooString *ownerPW, *userPW;
++ TextOutputDev *textOut;
++ FILE *f;
++ UnicodeMap *uMap;
++ Object info;
++ GBool ok;
++ char *p;
++ int exitCode;
++
++ exitCode = 99;
++
++ // parse args
++ ok = parseArgs(argDesc, &argc, argv);
++ if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
++ fprintf(stderr, "pdftotext version %s\n", xpdfVersion);
++ fprintf(stderr, "%s\n", xpdfCopyright);
++ if (!printVersion) {
++ printUsage("pdftotext", "<PDF-file> [<text-file>]", argDesc);
++ }
++ goto err0;
++ }
++ fileName = new GooString(argv[1]);
++
++ // read config file
++ globalParams = new GlobalParams(cfgFileName);
++ if (textEncName[0]) {
++ globalParams->setTextEncoding(textEncName);
++ }
++ if (textEOL[0]) {
++ if (!globalParams->setTextEOL(textEOL)) {
++ fprintf(stderr, "Bad '-eol' value on command line\n");
++ }
++ }
++ if (noPageBreaks) {
++ globalParams->setTextPageBreaks(gFalse);
++ }
++ if (quiet) {
++ globalParams->setErrQuiet(quiet);
++ }
++
++ // get mapping to output encoding
++ if (!(uMap = globalParams->getTextEncoding())) {
++ error(-1, "Couldn't get text encoding");
++ delete fileName;
++ goto err1;
++ }
++
++ // open PDF file
++ if (ownerPassword[0] != '\001') {
++ ownerPW = new GooString(ownerPassword);
++ } else {
++ ownerPW = NULL;
++ }
++ if (userPassword[0] != '\001') {
++ userPW = new GooString(userPassword);
++ } else {
++ userPW = NULL;
++ }
++ doc = new PDFDoc(fileName, ownerPW, userPW);
++ if (userPW) {
++ delete userPW;
++ }
++ if (ownerPW) {
++ delete ownerPW;
++ }
++ if (!doc->isOk()) {
++ exitCode = 1;
++ goto err2;
++ }
++
++#ifdef ENFORCE_PERMISSIONS
++ // check for copy permission
++ if (!doc->okToCopy()) {
++ error(-1, "Copying of text from this document is not allowed.");
++ exitCode = 3;
++ goto err2;
++ }
++#endif
++
++ // construct text file name
++ if (argc == 3) {
++ textFileName = new GooString(argv[2]);
++ } else {
++ p = fileName->getCString() + fileName->getLength() - 4;
++ if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) {
++ textFileName = new GooString(fileName->getCString(),
++ fileName->getLength() - 4);
++ } else {
++ textFileName = fileName->copy();
++ }
++ textFileName->append(htmlMeta ? ".html" : ".txt");
++ }
++
++ // get page range
++ if (firstPage < 1) {
++ firstPage = 1;
++ }
++ if (lastPage < 1 || lastPage > doc->getNumPages()) {
++ lastPage = doc->getNumPages();
++ }
++
++ // write HTML header
++ if (htmlMeta) {
++ if (!textFileName->cmp("-")) {
++ f = stdout;
++ } else {
++ if (!(f = fopen(textFileName->getCString(), "wb"))) {
++ error(-1, "Couldn't open text file '%s'", textFileName->getCString());
++ exitCode = 2;
++ goto err3;
++ }
++ }
++ fputs("<html>\n", f);
++ fputs("<head>\n", f);
++ doc->getDocInfo(&info);
++ if (info.isDict()) {
++ printInfoString(f, info.getDict(), "Title", "<title>", "</title>\n",
++ uMap);
++ printInfoString(f, info.getDict(), "Subject",
++ "<meta name=\"Subject\" content=\"", "\">\n", uMap);
++ printInfoString(f, info.getDict(), "Keywords",
++ "<meta name=\"Keywords\" content=\"", "\">\n", uMap);
++ printInfoString(f, info.getDict(), "Author",
++ "<meta name=\"Author\" content=\"", "\">\n", uMap);
++ printInfoString(f, info.getDict(), "Creator",
++ "<meta name=\"Creator\" content=\"", "\">\n", uMap);
++ printInfoString(f, info.getDict(), "Producer",
++ "<meta name=\"Producer\" content=\"", "\">\n", uMap);
++ printInfoDate(f, info.getDict(), "CreationDate",
++ "<meta name=\"CreationDate\" content=\"\">\n");
++ printInfoDate(f, info.getDict(), "LastModifiedDate",
++ "<meta name=\"ModDate\" content=\"\">\n");
++ }
++ info.free();
++ fputs("</head>\n", f);
++ fputs("<body>\n", f);
++ fputs("<pre>\n", f);
++ if (f != stdout) {
++ fclose(f);
++ }
++ }
++
++ // write text file
++ textOut = new TextOutputDev(textFileName->getCString(),
++ physLayout, rawOrder, htmlMeta);
++ if (textOut->isOk()) {
++ doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0, gTrue, gFalse);
++ } else {
++ delete textOut;
++ exitCode = 2;
++ goto err3;
++ }
++ delete textOut;
++
++ // write end of HTML file
++ if (htmlMeta) {
++ if (!textFileName->cmp("-")) {
++ f = stdout;
++ } else {
++ if (!(f = fopen(textFileName->getCString(), "ab"))) {
++ error(-1, "Couldn't open text file '%s'", textFileName->getCString());
++ exitCode = 2;
++ goto err3;
++ }
++ }
++ fputs("</pre>\n", f);
++ fputs("</body>\n", f);
++ fputs("</html>\n", f);
++ if (f != stdout) {
++ fclose(f);
++ }
++ }
++
++ exitCode = 0;
++
++ // clean up
++ err3:
++ delete textFileName;
++ err2:
++ delete doc;
++ uMap->decRefCnt();
++ err1:
++ delete globalParams;
++ err0:
++
++ // check for memory leaks
++ Object::memCheck(stderr);
++ gMemReport(stderr);
++
++ return exitCode;
++}
++
++static void printInfoString(FILE *f, Dict *infoDict, char *key,
++ char *text1, char *text2, UnicodeMap *uMap) {
++ Object obj;
++ GooString *s1;
++ GBool isUnicode;
++ Unicode u;
++ char buf[8];
++ int i, n;
++
++ if (infoDict->lookup(key, &obj)->isString()) {
++ fputs(text1, f);
++ s1 = obj.getString();
++ if ((s1->getChar(0) & 0xff) == 0xfe &&
++ (s1->getChar(1) & 0xff) == 0xff) {
++ isUnicode = gTrue;
++ i = 2;
++ } else {
++ isUnicode = gFalse;
++ i = 0;
++ }
++ while (i < obj.getString()->getLength()) {
++ if (isUnicode) {
++ u = ((s1->getChar(i) & 0xff) << 8) |
++ (s1->getChar(i+1) & 0xff);
++ i += 2;
++ } else {
++ u = s1->getChar(i) & 0xff;
++ ++i;
++ }
++ n = uMap->mapUnicode(u, buf, sizeof(buf));
++ fwrite(buf, 1, n, f);
++ }
++ fputs(text2, f);
++ }
++ obj.free();
++}
++
++static void printInfoDate(FILE *f, Dict *infoDict, char *key, char *fmt) {
++ Object obj;
++ char *s;
++
++ if (infoDict->lookup(key, &obj)->isString()) {
++ s = obj.getString()->getCString();
++ if (s[0] == 'D' && s[1] == ':') {
++ s += 2;
++ }
++ fprintf(f, fmt, s);
++ }
++ obj.free();
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/SplashOutputDev.cc poppler-0.4.3/utils/SplashOutputDev.cc
+--- poppler-0.4.3.orig/utils/SplashOutputDev.cc 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/SplashOutputDev.cc 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,1387 @@
++//========================================================================
++//
++// SplashOutputDev.cc
++//
++// Copyright 2003 Glyph & Cog, LLC
++//
++//========================================================================
++
++#include <poppler-config.h>
++
++#ifdef USE_GCC_PRAGMAS
++#pragma implementation
++#endif
++
++#include <string.h>
++#include <math.h>
++#include <dirent.h>
++#include "goo/gtypes.h"
++#include "goo/gfile.h"
++#include "GlobalParams.h"
++#include "Error.h"
++#include "Object.h"
++#include "GfxState.h"
++#include "GfxFont.h"
++#include "Link.h"
++#include "CharCodeToUnicode.h"
++#include "FontEncodingTables.h"
++#include "fofi/FoFiTrueType.h"
++#include "splash/SplashBitmap.h"
++#include "splash/SplashGlyphBitmap.h"
++#include "splash/SplashPattern.h"
++#include "splash/SplashScreen.h"
++#include "splash/SplashPath.h"
++#include "splash/SplashState.h"
++#include "splash/SplashErrorCodes.h"
++#include "splash/SplashFontEngine.h"
++#include "splash/SplashFont.h"
++#include "splash/SplashFontFile.h"
++#include "splash/SplashFontFileID.h"
++#include "splash/Splash.h"
++#include "SplashOutputDev.h"
++
++//------------------------------------------------------------------------
++// Font substitutions
++//------------------------------------------------------------------------
++
++struct SplashOutFontSubst {
++ char *name;
++ double mWidth;
++};
++
++// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
++static SplashOutFontSubst splashOutSubstFonts[16] = {
++ {"Helvetica", 0.833},
++ {"Helvetica-Oblique", 0.833},
++ {"Helvetica-Bold", 0.889},
++ {"Helvetica-BoldOblique", 0.889},
++ {"Times-Roman", 0.788},
++ {"Times-Italic", 0.722},
++ {"Times-Bold", 0.833},
++ {"Times-BoldItalic", 0.778},
++ {"Courier", 0.600},
++ {"Courier-Oblique", 0.600},
++ {"Courier-Bold", 0.600},
++ {"Courier-BoldOblique", 0.600},
++ {"Symbol", 0.576},
++ {"Symbol", 0.576},
++ {"Symbol", 0.576},
++ {"Symbol", 0.576}
++};
++
++//------------------------------------------------------------------------
++
++#define soutRound(x) ((int)(x + 0.5))
++
++//------------------------------------------------------------------------
++// SplashOutFontFileID
++//------------------------------------------------------------------------
++
++class SplashOutFontFileID: public SplashFontFileID {
++public:
++
++ SplashOutFontFileID(Ref *rA) { r = *rA; substIdx = -1; }
++
++ ~SplashOutFontFileID() {}
++
++ GBool matches(SplashFontFileID *id) {
++ return ((SplashOutFontFileID *)id)->r.num == r.num &&
++ ((SplashOutFontFileID *)id)->r.gen == r.gen;
++ }
++
++ void setSubstIdx(int substIdxA) { substIdx = substIdxA; }
++ int getSubstIdx() { return substIdx; }
++
++private:
++
++ Ref r;
++ int substIdx;
++};
++
++//------------------------------------------------------------------------
++// T3FontCache
++//------------------------------------------------------------------------
++
++struct T3FontCacheTag {
++ Gushort code;
++ Gushort mru; // valid bit (0x8000) and MRU index
++};
++
++class T3FontCache {
++public:
++
++ T3FontCache(Ref *fontID, double m11A, double m12A,
++ double m21A, double m22A,
++ int glyphXA, int glyphYA, int glyphWA, int glyphHA,
++ GBool aa);
++ ~T3FontCache();
++ GBool matches(Ref *idA, double m11A, double m12A,
++ double m21A, double m22A)
++ { return fontID.num == idA->num && fontID.gen == idA->gen &&
++ m11 == m11A && m12 == m12A && m21 == m21A && m22 == m22A; }
++
++ Ref fontID; // PDF font ID
++ double m11, m12, m21, m22; // transform matrix
++ int glyphX, glyphY; // pixel offset of glyph bitmaps
++ int glyphW, glyphH; // size of glyph bitmaps, in pixels
++ int glyphSize; // size of glyph bitmaps, in bytes
++ int cacheSets; // number of sets in cache
++ int cacheAssoc; // cache associativity (glyphs per set)
++ Guchar *cacheData; // glyph pixmap cache
++ T3FontCacheTag *cacheTags; // cache tags, i.e., char codes
++};
++
++T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
++ double m21A, double m22A,
++ int glyphXA, int glyphYA, int glyphWA, int glyphHA,
++ GBool aa) {
++ int i;
++
++ fontID = *fontIDA;
++ m11 = m11A;
++ m12 = m12A;
++ m21 = m21A;
++ m22 = m22A;
++ glyphX = glyphXA;
++ glyphY = glyphYA;
++ glyphW = glyphWA;
++ glyphH = glyphHA;
++ if (aa) {
++ glyphSize = glyphW * glyphH;
++ } else {
++ glyphSize = ((glyphW + 7) >> 3) * glyphH;
++ }
++ cacheAssoc = 8;
++ if (glyphSize <= 256) {
++ cacheSets = 8;
++ } else if (glyphSize <= 512) {
++ cacheSets = 4;
++ } else if (glyphSize <= 1024) {
++ cacheSets = 2;
++ } else {
++ cacheSets = 1;
++ }
++ cacheData = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
++ cacheTags = (T3FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
++ sizeof(T3FontCacheTag));
++ for (i = 0; i < cacheSets * cacheAssoc; ++i) {
++ cacheTags[i].mru = i & (cacheAssoc - 1);
++ }
++}
++
++T3FontCache::~T3FontCache() {
++ gfree(cacheData);
++ gfree(cacheTags);
++}
++
++struct T3GlyphStack {
++ Gushort code; // character code
++ double x, y; // position to draw the glyph
++
++ //----- cache info
++ T3FontCache *cache; // font cache for the current font
++ T3FontCacheTag *cacheTag; // pointer to cache tag for the glyph
++ Guchar *cacheData; // pointer to cache data for the glyph
++
++ //----- saved state
++ SplashBitmap *origBitmap;
++ Splash *origSplash;
++ double origCTM4, origCTM5;
++
++ T3GlyphStack *next; // next object on stack
++};
++
++//------------------------------------------------------------------------
++// SplashOutputDev
++//------------------------------------------------------------------------
++
++SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
++ GBool reverseVideoA,
++ SplashColor paperColorA) {
++ colorMode = colorModeA;
++ reverseVideo = reverseVideoA;
++ paperColor = paperColorA;
++
++ xref = NULL;
++
++ bitmap = new SplashBitmap(1, 1, colorMode);
++ splash = new Splash(bitmap);
++ splash->clear(paperColor);
++
++ fontEngine = NULL;
++
++ nT3Fonts = 0;
++ t3GlyphStack = NULL;
++
++ font = NULL;
++ needFontUpdate = gFalse;
++ textClipPath = NULL;
++
++ underlayCbk = NULL;
++ underlayCbkData = NULL;
++}
++
++SplashOutputDev::~SplashOutputDev() {
++ int i;
++
++ for (i = 0; i < nT3Fonts; ++i) {
++ delete t3FontCache[i];
++ }
++ if (fontEngine) {
++ delete fontEngine;
++ }
++ if (splash) {
++ delete splash;
++ }
++ if (bitmap) {
++ delete bitmap;
++ }
++}
++
++void SplashOutputDev::startDoc(XRef *xrefA) {
++ int i;
++
++ xref = xrefA;
++ if (fontEngine) {
++ delete fontEngine;
++ }
++ fontEngine = new SplashFontEngine(
++#if HAVE_T1LIB_H
++ globalParams->getEnableT1lib(),
++#endif
++#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
++ globalParams->getEnableFreeType(),
++#endif
++ globalParams->getAntialias());
++ for (i = 0; i < nT3Fonts; ++i) {
++ delete t3FontCache[i];
++ }
++ nT3Fonts = 0;
++}
++
++void SplashOutputDev::startPage(int pageNum, GfxState *state) {
++ int w, h;
++ SplashColor color;
++
++ w = state ? (int)(state->getPageWidth() + 0.5) : 1;
++ h = state ? (int)(state->getPageHeight() + 0.5) : 1;
++ if (splash) {
++ delete splash;
++ }
++ if (!bitmap || w != bitmap->getWidth() || h != bitmap->getHeight()) {
++ if (bitmap) {
++ delete bitmap;
++ }
++ bitmap = new SplashBitmap(w, h, colorMode);
++ }
++ splash = new Splash(bitmap);
++ switch (colorMode) {
++ case splashModeMono1: color.mono1 = 0; break;
++ case splashModeMono8: color.mono8 = 0; break;
++ case splashModeRGB8: color.rgb8 = splashMakeRGB8(0, 0, 0); break;
++ case splashModeBGR8Packed: color.bgr8 = splashMakeBGR8(0, 0, 0); break;
++ }
++ splash->setStrokePattern(new SplashSolidColor(color));
++ splash->setFillPattern(new SplashSolidColor(color));
++ splash->setLineCap(splashLineCapButt);
++ splash->setLineJoin(splashLineJoinMiter);
++ splash->setLineDash(NULL, 0, 0);
++ splash->setMiterLimit(10);
++ splash->setFlatness(1);
++ splash->clear(paperColor);
++
++ if (underlayCbk) {
++ (*underlayCbk)(underlayCbkData);
++ }
++}
++
++void SplashOutputDev::endPage() {
++}
++
++void SplashOutputDev::drawLink(Link *link, Catalog *catalog) {
++ double x1, y1, x2, y2;
++ LinkBorderStyle *borderStyle;
++ GfxRGB rgb;
++ double gray;
++ double *dash;
++ int dashLength;
++ SplashCoord dashList[20];
++ SplashPath *path;
++ int x, y, i;
++
++ link->getRect(&x1, &y1, &x2, &y2);
++ borderStyle = link->getBorderStyle();
++ if (borderStyle->getWidth() > 0) {
++ borderStyle->getColor(&rgb.r, &rgb.g, &rgb.b);
++ gray = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b;
++ if (gray > 1) {
++ gray = 1;
++ }
++ splash->setStrokePattern(getColor(gray, &rgb));
++ splash->setLineWidth((SplashCoord)borderStyle->getWidth());
++ borderStyle->getDash(&dash, &dashLength);
++ if (borderStyle->getType() == linkBorderDashed && dashLength > 0) {
++ if (dashLength > 20) {
++ dashLength = 20;
++ }
++ for (i = 0; i < dashLength; ++i) {
++ dashList[i] = (SplashCoord)dash[i];
++ }
++ splash->setLineDash(dashList, dashLength, 0);
++ }
++ path = new SplashPath();
++ if (borderStyle->getType() == linkBorderUnderlined) {
++ cvtUserToDev(x1, y1, &x, &y);
++ path->moveTo((SplashCoord)x, (SplashCoord)y);
++ cvtUserToDev(x2, y1, &x, &y);
++ path->lineTo((SplashCoord)x, (SplashCoord)y);
++ } else {
++ cvtUserToDev(x1, y1, &x, &y);
++ path->moveTo((SplashCoord)x, (SplashCoord)y);
++ cvtUserToDev(x2, y1, &x, &y);
++ path->lineTo((SplashCoord)x, (SplashCoord)y);
++ cvtUserToDev(x2, y2, &x, &y);
++ path->lineTo((SplashCoord)x, (SplashCoord)y);
++ cvtUserToDev(x1, y2, &x, &y);
++ path->lineTo((SplashCoord)x, (SplashCoord)y);
++ path->close();
++ }
++ splash->stroke(path);
++ delete path;
++ }
++}
++
++void SplashOutputDev::saveState(GfxState *state) {
++ splash->saveState();
++}
++
++void SplashOutputDev::restoreState(GfxState *state) {
++ splash->restoreState();
++ needFontUpdate = gTrue;
++}
++
++void SplashOutputDev::updateAll(GfxState *state) {
++ updateLineDash(state);
++ updateLineJoin(state);
++ updateLineCap(state);
++ updateLineWidth(state);
++ updateFlatness(state);
++ updateMiterLimit(state);
++ updateFillColor(state);
++ updateStrokeColor(state);
++ needFontUpdate = gTrue;
++}
++
++void SplashOutputDev::updateCTM(GfxState *state, double m11, double m12,
++ double m21, double m22,
++ double m31, double m32) {
++ updateLineDash(state);
++ updateLineJoin(state);
++ updateLineCap(state);
++ updateLineWidth(state);
++}
++
++void SplashOutputDev::updateLineDash(GfxState *state) {
++ double *dashPattern;
++ int dashLength;
++ double dashStart;
++ SplashCoord dash[20];
++ SplashCoord phase;
++ int i;
++
++ state->getLineDash(&dashPattern, &dashLength, &dashStart);
++ if (dashLength > 20) {
++ dashLength = 20;
++ }
++ for (i = 0; i < dashLength; ++i) {
++ dash[i] = (SplashCoord)state->transformWidth(dashPattern[i]);
++ if (dash[i] < 1) {
++ dash[i] = 1;
++ }
++ }
++ phase = (SplashCoord)state->transformWidth(dashStart);
++ splash->setLineDash(dash, dashLength, phase);
++}
++
++void SplashOutputDev::updateFlatness(GfxState *state) {
++ splash->setFlatness(state->getFlatness());
++}
++
++void SplashOutputDev::updateLineJoin(GfxState *state) {
++ splash->setLineJoin(state->getLineJoin());
++}
++
++void SplashOutputDev::updateLineCap(GfxState *state) {
++ splash->setLineCap(state->getLineCap());
++}
++
++void SplashOutputDev::updateMiterLimit(GfxState *state) {
++ splash->setMiterLimit(state->getMiterLimit());
++}
++
++void SplashOutputDev::updateLineWidth(GfxState *state) {
++ splash->setLineWidth(state->getTransformedLineWidth());
++}
++
++void SplashOutputDev::updateFillColor(GfxState *state) {
++ double gray;
++ GfxRGB rgb;
++
++ state->getFillGray(&gray);
++ state->getFillRGB(&rgb);
++ splash->setFillPattern(getColor(gray, &rgb));
++}
++
++void SplashOutputDev::updateStrokeColor(GfxState *state) {
++ double gray;
++ GfxRGB rgb;
++
++ state->getStrokeGray(&gray);
++ state->getStrokeRGB(&rgb);
++ splash->setStrokePattern(getColor(gray, &rgb));
++}
++
++SplashPattern *SplashOutputDev::getColor(double gray, GfxRGB *rgb) {
++ SplashPattern *pattern;
++ SplashColor color0, color1;
++ double r, g, b;
++
++ if (reverseVideo) {
++ gray = 1 - gray;
++ r = 1 - rgb->r;
++ g = 1 - rgb->g;
++ b = 1 - rgb->b;
++ } else {
++ r = rgb->r;
++ g = rgb->g;
++ b = rgb->b;
++ }
++
++ pattern = NULL; // make gcc happy
++ switch (colorMode) {
++ case splashModeMono1:
++ color0.mono1 = 0;
++ color1.mono1 = 1;
++ pattern = new SplashHalftone(color0, color1,
++ splash->getScreen()->copy(),
++ (SplashCoord)gray);
++ break;
++ case splashModeMono8:
++ color1.mono8 = soutRound(255 * gray);
++ pattern = new SplashSolidColor(color1);
++ break;
++ case splashModeRGB8:
++ color1.rgb8 = splashMakeRGB8(soutRound(255 * r),
++ soutRound(255 * g),
++ soutRound(255 * b));
++ pattern = new SplashSolidColor(color1);
++ break;
++ case splashModeBGR8Packed:
++ color1.bgr8 = splashMakeBGR8(soutRound(255 * r),
++ soutRound(255 * g),
++ soutRound(255 * b));
++ pattern = new SplashSolidColor(color1);
++ break;
++ }
++
++ return pattern;
++}
++
++void SplashOutputDev::updateFont(GfxState *state) {
++ GfxFont *gfxFont;
++ GfxFontType fontType;
++ SplashOutFontFileID *id;
++ SplashFontFile *fontFile;
++ FoFiTrueType *ff;
++ Ref embRef;
++ Object refObj, strObj;
++ GooString *tmpFileName, *fileName, *substName;
++ FILE *tmpFile;
++ Gushort *codeToGID;
++ DisplayFontParam *dfp;
++ CharCodeToUnicode *ctu;
++ double m11, m12, m21, m22, w1, w2;
++ SplashCoord mat[4];
++ char *name;
++ Unicode uBuf[8];
++ int c, substIdx, n, code, cmap;
++
++ needFontUpdate = gFalse;
++ font = NULL;
++ tmpFileName = NULL;
++ substIdx = -1;
++ dfp = NULL;
++
++ if (!(gfxFont = state->getFont())) {
++ goto err1;
++ }
++ fontType = gfxFont->getType();
++ if (fontType == fontType3) {
++ goto err1;
++ }
++
++ // check the font file cache
++ id = new SplashOutFontFileID(gfxFont->getID());
++ if ((fontFile = fontEngine->getFontFile(id))) {
++ delete id;
++
++ } else {
++
++ // if there is an embedded font, write it to disk
++ if (gfxFont->getEmbeddedFontID(&embRef)) {
++ if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
++ error(-1, "Couldn't create temporary font file");
++ goto err2;
++ }
++ refObj.initRef(embRef.num, embRef.gen);
++ refObj.fetch(xref, &strObj);
++ refObj.free();
++ strObj.streamReset();
++ while ((c = strObj.streamGetChar()) != EOF) {
++ fputc(c, tmpFile);
++ }
++ strObj.streamClose();
++ strObj.free();
++ fclose(tmpFile);
++ fileName = tmpFileName;
++
++ // if there is an external font file, use it
++ } else if (!(fileName = gfxFont->getExtFontFile())) {
++
++ // look for a display font mapping or a substitute font
++ if (gfxFont->isCIDFont()) {
++ if (((GfxCIDFont *)gfxFont)->getCollection()) {
++ dfp = globalParams->
++ getDisplayCIDFont(gfxFont->getName(),
++ ((GfxCIDFont *)gfxFont)->getCollection());
++ }
++ } else {
++ if (gfxFont->getName()) {
++ dfp = globalParams->getDisplayFont(gfxFont->getName());
++ }
++ if (!dfp) {
++ // 8-bit font substitution
++ if (gfxFont->isFixedWidth()) {
++ substIdx = 8;
++ } else if (gfxFont->isSerif()) {
++ substIdx = 4;
++ } else {
++ substIdx = 0;
++ }
++ if (gfxFont->isBold()) {
++ substIdx += 2;
++ }
++ if (gfxFont->isItalic()) {
++ substIdx += 1;
++ }
++ substName = new GooString(splashOutSubstFonts[substIdx].name);
++ dfp = globalParams->getDisplayFont(substName);
++ delete substName;
++ id->setSubstIdx(substIdx);
++ }
++ }
++ if (!dfp) {
++ error(-1, "Couldn't find a font for '%s'",
++ gfxFont->getName() ? gfxFont->getName()->getCString()
++ : "(unnamed)");
++ goto err2;
++ }
++ switch (dfp->kind) {
++ case displayFontT1:
++ fileName = dfp->t1.fileName;
++ fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1;
++ break;
++ case displayFontTT:
++ fileName = dfp->tt.fileName;
++ fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
++ break;
++ }
++ }
++
++ // load the font file
++ switch (fontType) {
++ case fontType1:
++ if (!(fontFile = fontEngine->loadType1Font(
++ id,
++ fileName->getCString(),
++ fileName == tmpFileName,
++ ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
++ error(-1, "Couldn't create a font for '%s'",
++ gfxFont->getName() ? gfxFont->getName()->getCString()
++ : "(unnamed)");
++ goto err2;
++ }
++ break;
++ case fontType1C:
++ if (!(fontFile = fontEngine->loadType1CFont(
++ id,
++ fileName->getCString(),
++ fileName == tmpFileName,
++ ((Gfx8BitFont *)gfxFont)->getEncoding()))) {
++ error(-1, "Couldn't create a font for '%s'",
++ gfxFont->getName() ? gfxFont->getName()->getCString()
++ : "(unnamed)");
++ goto err2;
++ }
++ break;
++ case fontTrueType:
++ if (!(ff = FoFiTrueType::load(fileName->getCString()))) {
++ goto err2;
++ }
++ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
++ delete ff;
++ if (!(fontFile = fontEngine->loadTrueTypeFont(
++ id,
++ fileName->getCString(),
++ fileName == tmpFileName,
++ codeToGID, 256))) {
++ error(-1, "Couldn't create a font for '%s'",
++ gfxFont->getName() ? gfxFont->getName()->getCString()
++ : "(unnamed)");
++ goto err2;
++ }
++ break;
++ case fontCIDType0:
++ case fontCIDType0C:
++ if (!(fontFile = fontEngine->loadCIDFont(
++ id,
++ fileName->getCString(),
++ fileName == tmpFileName))) {
++ error(-1, "Couldn't create a font for '%s'",
++ gfxFont->getName() ? gfxFont->getName()->getCString()
++ : "(unnamed)");
++ goto err2;
++ }
++ break;
++ case fontCIDType2:
++ codeToGID = NULL;
++ n = 0;
++ if (dfp) {
++ // create a CID-to-GID mapping, via Unicode
++ if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) {
++ if ((ff = FoFiTrueType::load(fileName->getCString()))) {
++ // look for a Unicode cmap
++ for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
++ if ((ff->getCmapPlatform(cmap) == 3 &&
++ ff->getCmapEncoding(cmap) == 1) ||
++ ff->getCmapPlatform(cmap) == 0) {
++ break;
++ }
++ }
++ if (cmap < ff->getNumCmaps()) {
++ // map CID -> Unicode -> GID
++ n = ctu->getLength();
++ codeToGID = (Gushort *)gmalloc(n * sizeof(Gushort));
++ for (code = 0; code < n; ++code) {
++ if (ctu->mapToUnicode(code, uBuf, 8) > 0) {
++ codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]);
++ } else {
++ codeToGID[code] = 0;
++ }
++ }
++ }
++ delete ff;
++ }
++ ctu->decRefCnt();
++ } else {
++ error(-1, "Couldn't find a mapping to Unicode for font '%s'",
++ gfxFont->getName() ? gfxFont->getName()->getCString()
++ : "(unnamed)");
++ }
++ } else {
++ if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
++ n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
++ codeToGID = (Gushort *)gmalloc(n * sizeof(Gushort));
++ memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
++ n * sizeof(Gushort));
++ }
++ }
++ if (!(fontFile = fontEngine->loadTrueTypeFont(
++ id,
++ fileName->getCString(),
++ fileName == tmpFileName,
++ codeToGID, n))) {
++ error(-1, "Couldn't create a font for '%s'",
++ gfxFont->getName() ? gfxFont->getName()->getCString()
++ : "(unnamed)");
++ goto err2;
++ }
++ break;
++ default:
++ // this shouldn't happen
++ goto err2;
++ }
++ }
++
++ // get the font matrix
++ state->getFontTransMat(&m11, &m12, &m21, &m22);
++ m11 *= state->getHorizScaling();
++ m12 *= state->getHorizScaling();
++
++ // for substituted fonts: adjust the font matrix -- compare the
++ // width of 'm' in the original font and the substituted font
++ substIdx = ((SplashOutFontFileID *)fontFile->getID())->getSubstIdx();
++ if (substIdx >= 0) {
++ for (code = 0; code < 256; ++code) {
++ if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
++ name[0] == 'm' && name[1] == '\0') {
++ break;
++ }
++ }
++ if (code < 256) {
++ w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
++ w2 = splashOutSubstFonts[substIdx].mWidth;
++ if (!gfxFont->isSymbolic()) {
++ // if real font is substantially narrower than substituted
++ // font, reduce the font size accordingly
++ if (w1 > 0.01 && w1 < 0.9 * w2) {
++ w1 /= w2;
++ m11 *= w1;
++ m21 *= w1;
++ }
++ }
++ }
++ }
++
++ // create the scaled font
++ mat[0] = m11; mat[1] = -m12;
++ mat[2] = m21; mat[3] = -m22;
++ font = fontEngine->getFont(fontFile, mat);
++
++ if (tmpFileName) {
++ delete tmpFileName;
++ }
++ return;
++
++ err2:
++ delete id;
++ err1:
++ if (tmpFileName) {
++ delete tmpFileName;
++ }
++ return;
++}
++
++void SplashOutputDev::stroke(GfxState *state) {
++ SplashPath *path;
++
++ path = convertPath(state, state->getPath());
++ splash->stroke(path);
++ delete path;
++}
++
++void SplashOutputDev::fill(GfxState *state) {
++ SplashPath *path;
++
++ path = convertPath(state, state->getPath());
++ splash->fill(path, gFalse);
++ delete path;
++}
++
++void SplashOutputDev::eoFill(GfxState *state) {
++ SplashPath *path;
++
++ path = convertPath(state, state->getPath());
++ splash->fill(path, gTrue);
++ delete path;
++}
++
++void SplashOutputDev::clip(GfxState *state) {
++ SplashPath *path;
++
++ path = convertPath(state, state->getPath());
++ splash->clipToPath(path, gFalse);
++ delete path;
++}
++
++void SplashOutputDev::eoClip(GfxState *state) {
++ SplashPath *path;
++
++ path = convertPath(state, state->getPath());
++ splash->clipToPath(path, gTrue);
++ delete path;
++}
++
++SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path) {
++ SplashPath *sPath;
++ GfxSubpath *subpath;
++ double x1, y1, x2, y2, x3, y3;
++ int i, j;
++
++ sPath = new SplashPath();
++ for (i = 0; i < path->getNumSubpaths(); ++i) {
++ subpath = path->getSubpath(i);
++ if (subpath->getNumPoints() > 0) {
++ state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
++ sPath->moveTo((SplashCoord)x1, (SplashCoord)y1);
++ j = 1;
++ while (j < subpath->getNumPoints()) {
++ if (subpath->getCurve(j)) {
++ state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
++ state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
++ state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
++ sPath->curveTo((SplashCoord)x1, (SplashCoord)y1,
++ (SplashCoord)x2, (SplashCoord)y2,
++ (SplashCoord)x3, (SplashCoord)y3);
++ j += 3;
++ } else {
++ state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
++ sPath->lineTo((SplashCoord)x1, (SplashCoord)y1);
++ ++j;
++ }
++ }
++ if (subpath->isClosed()) {
++ sPath->close();
++ }
++ }
++ }
++ return sPath;
++}
++
++void SplashOutputDev::drawChar(GfxState *state, double x, double y,
++ double dx, double dy,
++ double originX, double originY,
++ CharCode code, Unicode *u, int uLen) {
++ double x1, y1;
++ SplashPath *path;
++ int render;
++
++ if (needFontUpdate) {
++ updateFont(state);
++ }
++ if (!font) {
++ return;
++ }
++
++ // check for invisible text -- this is used by Acrobat Capture
++ render = state->getRender();
++ if (render == 3) {
++ return;
++ }
++
++ x -= originX;
++ y -= originY;
++ state->transform(x, y, &x1, &y1);
++
++ // fill
++ if (!(render & 1)) {
++ splash->fillChar((SplashCoord)x1, (SplashCoord)y1, code, font);
++ }
++
++ // stroke
++ if ((render & 3) == 1 || (render & 3) == 2) {
++ if ((path = font->getGlyphPath(code))) {
++ path->offset((SplashCoord)x1, (SplashCoord)y1);
++ splash->stroke(path);
++ delete path;
++ }
++ }
++
++ // clip
++ if (render & 4) {
++ path = font->getGlyphPath(code);
++ path->offset((SplashCoord)x1, (SplashCoord)y1);
++ if (textClipPath) {
++ textClipPath->append(path);
++ delete path;
++ } else {
++ textClipPath = path;
++ }
++ }
++}
++
++GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y,
++ double dx, double dy,
++ CharCode code, Unicode *u, int uLen) {
++ GfxFont *gfxFont;
++ Ref *fontID;
++ double *ctm, *bbox;
++ T3FontCache *t3Font;
++ T3GlyphStack *t3gs;
++ double x1, y1, xMin, yMin, xMax, yMax, xt, yt;
++ int i, j;
++
++ if (!(gfxFont = state->getFont())) {
++ return gFalse;
++ }
++ fontID = gfxFont->getID();
++ ctm = state->getCTM();
++ state->transform(0, 0, &xt, &yt);
++
++ // is it the first (MRU) font in the cache?
++ if (!(nT3Fonts > 0 &&
++ t3FontCache[0]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3]))) {
++
++ // is the font elsewhere in the cache?
++ for (i = 1; i < nT3Fonts; ++i) {
++ if (t3FontCache[i]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3])) {
++ t3Font = t3FontCache[i];
++ for (j = i; j > 0; --j) {
++ t3FontCache[j] = t3FontCache[j - 1];
++ }
++ t3FontCache[0] = t3Font;
++ break;
++ }
++ }
++ if (i >= nT3Fonts) {
++
++ // create new entry in the font cache
++ if (nT3Fonts == splashOutT3FontCacheSize) {
++ delete t3FontCache[nT3Fonts - 1];
++ --nT3Fonts;
++ }
++ for (j = nT3Fonts; j > 0; --j) {
++ t3FontCache[j] = t3FontCache[j - 1];
++ }
++ ++nT3Fonts;
++ bbox = gfxFont->getFontBBox();
++ if (bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0) {
++ // broken bounding box -- just take a guess
++ xMin = xt - 5;
++ xMax = xMin + 30;
++ yMax = yt + 15;
++ yMin = yMax - 45;
++ } else {
++ state->transform(bbox[0], bbox[1], &x1, &y1);
++ xMin = xMax = x1;
++ yMin = yMax = y1;
++ state->transform(bbox[0], bbox[3], &x1, &y1);
++ if (x1 < xMin) {
++ xMin = x1;
++ } else if (x1 > xMax) {
++ xMax = x1;
++ }
++ if (y1 < yMin) {
++ yMin = y1;
++ } else if (y1 > yMax) {
++ yMax = y1;
++ }
++ state->transform(bbox[2], bbox[1], &x1, &y1);
++ if (x1 < xMin) {
++ xMin = x1;
++ } else if (x1 > xMax) {
++ xMax = x1;
++ }
++ if (y1 < yMin) {
++ yMin = y1;
++ } else if (y1 > yMax) {
++ yMax = y1;
++ }
++ state->transform(bbox[2], bbox[3], &x1, &y1);
++ if (x1 < xMin) {
++ xMin = x1;
++ } else if (x1 > xMax) {
++ xMax = x1;
++ }
++ if (y1 < yMin) {
++ yMin = y1;
++ } else if (y1 > yMax) {
++ yMax = y1;
++ }
++ }
++ t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3],
++ (int)floor(xMin - xt),
++ (int)floor(yMin - yt),
++ (int)ceil(xMax) - (int)floor(xMin) + 3,
++ (int)ceil(yMax) - (int)floor(yMin) + 3,
++ colorMode != splashModeMono1);
++ }
++ }
++ t3Font = t3FontCache[0];
++
++ // is the glyph in the cache?
++ i = (code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc;
++ for (j = 0; j < t3Font->cacheAssoc; ++j) {
++ if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
++ t3Font->cacheTags[i+j].code == code) {
++ drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
++ t3Font->cacheData + (i+j) * t3Font->glyphSize,
++ xt, yt);
++ return gTrue;
++ }
++ }
++
++ // push a new Type 3 glyph record
++ t3gs = new T3GlyphStack();
++ t3gs->next = t3GlyphStack;
++ t3GlyphStack = t3gs;
++ t3GlyphStack->code = code;
++ t3GlyphStack->x = xt;
++ t3GlyphStack->y = yt;
++ t3GlyphStack->cache = t3Font;
++ t3GlyphStack->cacheTag = NULL;
++ t3GlyphStack->cacheData = NULL;
++
++ return gFalse;
++}
++
++void SplashOutputDev::endType3Char(GfxState *state) {
++ T3GlyphStack *t3gs;
++ double *ctm;
++
++ if (t3GlyphStack->cacheTag) {
++ memcpy(t3GlyphStack->cacheData, bitmap->getDataPtr().mono8,
++ t3GlyphStack->cache->glyphSize);
++ delete bitmap;
++ delete splash;
++ bitmap = t3GlyphStack->origBitmap;
++ splash = t3GlyphStack->origSplash;
++ ctm = state->getCTM();
++ state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
++ t3GlyphStack->origCTM4, t3GlyphStack->origCTM5);
++ drawType3Glyph(t3GlyphStack->cache,
++ t3GlyphStack->cacheTag, t3GlyphStack->cacheData,
++ t3GlyphStack->x, t3GlyphStack->y);
++ }
++ t3gs = t3GlyphStack;
++ t3GlyphStack = t3gs->next;
++ delete t3gs;
++}
++
++void SplashOutputDev::type3D0(GfxState *state, double wx, double wy) {
++}
++
++void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
++ double llx, double lly, double urx, double ury) {
++ double *ctm;
++ T3FontCache *t3Font;
++ SplashColor color;
++ double xt, yt, xMin, xMax, yMin, yMax, x1, y1;
++ int i, j;
++
++ t3Font = t3GlyphStack->cache;
++
++ // check for a valid bbox
++ state->transform(0, 0, &xt, &yt);
++ state->transform(llx, lly, &x1, &y1);
++ xMin = xMax = x1;
++ yMin = yMax = y1;
++ state->transform(llx, ury, &x1, &y1);
++ if (x1 < xMin) {
++ xMin = x1;
++ } else if (x1 > xMax) {
++ xMax = x1;
++ }
++ if (y1 < yMin) {
++ yMin = y1;
++ } else if (y1 > yMax) {
++ yMax = y1;
++ }
++ state->transform(urx, lly, &x1, &y1);
++ if (x1 < xMin) {
++ xMin = x1;
++ } else if (x1 > xMax) {
++ xMax = x1;
++ }
++ if (y1 < yMin) {
++ yMin = y1;
++ } else if (y1 > yMax) {
++ yMax = y1;
++ }
++ state->transform(urx, ury, &x1, &y1);
++ if (x1 < xMin) {
++ xMin = x1;
++ } else if (x1 > xMax) {
++ xMax = x1;
++ }
++ if (y1 < yMin) {
++ yMin = y1;
++ } else if (y1 > yMax) {
++ yMax = y1;
++ }
++ if (xMin - xt < t3Font->glyphX ||
++ yMin - yt < t3Font->glyphY ||
++ xMax - xt > t3Font->glyphX + t3Font->glyphW ||
++ yMax - yt > t3Font->glyphY + t3Font->glyphH) {
++ error(-1, "Bad bounding box in Type 3 glyph");
++ return;
++ }
++
++ // allocate a cache entry
++ i = (t3GlyphStack->code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc;
++ for (j = 0; j < t3Font->cacheAssoc; ++j) {
++ if ((t3Font->cacheTags[i+j].mru & 0x7fff) == t3Font->cacheAssoc - 1) {
++ t3Font->cacheTags[i+j].mru = 0x8000;
++ t3Font->cacheTags[i+j].code = t3GlyphStack->code;
++ t3GlyphStack->cacheTag = &t3Font->cacheTags[i+j];
++ t3GlyphStack->cacheData = t3Font->cacheData + (i+j) * t3Font->glyphSize;
++ } else {
++ ++t3Font->cacheTags[i+j].mru;
++ }
++ }
++
++ // save state
++ t3GlyphStack->origBitmap = bitmap;
++ t3GlyphStack->origSplash = splash;
++ ctm = state->getCTM();
++ t3GlyphStack->origCTM4 = ctm[4];
++ t3GlyphStack->origCTM5 = ctm[5];
++
++ // create the temporary bitmap
++ if (colorMode == splashModeMono1) {
++ bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, splashModeMono1);
++ splash = new Splash(bitmap);
++ color.mono1 = 0;
++ splash->clear(color);
++ color.mono1 = 1;
++ } else {
++ bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, splashModeMono8);
++ splash = new Splash(bitmap);
++ color.mono8 = 0x00;
++ splash->clear(color);
++ color.mono8 = 0xff;
++ }
++ splash->setFillPattern(new SplashSolidColor(color));
++ splash->setStrokePattern(new SplashSolidColor(color));
++ //~ this should copy other state from t3GlyphStack->origSplash?
++ state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
++ -t3Font->glyphX, -t3Font->glyphY);
++}
++
++void SplashOutputDev::drawType3Glyph(T3FontCache *t3Font,
++ T3FontCacheTag *tag, Guchar *data,
++ double x, double y) {
++ SplashGlyphBitmap glyph;
++
++ glyph.x = -t3Font->glyphX;
++ glyph.y = -t3Font->glyphY;
++ glyph.w = t3Font->glyphW;
++ glyph.h = t3Font->glyphH;
++ glyph.aa = colorMode != splashModeMono1;
++ glyph.data = data;
++ glyph.freeData = gFalse;
++ splash->fillGlyph((SplashCoord)x, (SplashCoord)y, &glyph);
++}
++
++void SplashOutputDev::endTextObject(GfxState *state) {
++ if (textClipPath) {
++ splash->clipToPath(textClipPath, gFalse);
++ delete textClipPath;
++ textClipPath = NULL;
++ }
++}
++
++struct SplashOutImageMaskData {
++ ImageStream *imgStr;
++ int nPixels, idx;
++ GBool invert;
++};
++
++GBool SplashOutputDev::imageMaskSrc(void *data, SplashMono1 *pixel) {
++ SplashOutImageMaskData *imgMaskData = (SplashOutImageMaskData *)data;
++ Guchar pix;
++
++ if (imgMaskData->idx >= imgMaskData->nPixels) {
++ return gFalse;
++ }
++ //~ use getLine
++ imgMaskData->imgStr->getPixel(&pix);
++ if (!imgMaskData->invert) {
++ pix ^= 1;
++ }
++ *pixel = pix;
++ ++imgMaskData->idx;
++ return gTrue;
++}
++
++void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GBool invert,
++ GBool inlineImg) {
++ double *ctm;
++ SplashCoord mat[6];
++ SplashOutImageMaskData imgMaskData;
++ Guchar pix;
++
++ ctm = state->getCTM();
++ mat[0] = ctm[0];
++ mat[1] = ctm[1];
++ mat[2] = -ctm[2];
++ mat[3] = -ctm[3];
++ mat[4] = ctm[2] + ctm[4];
++ mat[5] = ctm[3] + ctm[5];
++
++ imgMaskData.imgStr = new ImageStream(str, width, 1, 1);
++ imgMaskData.imgStr->reset();
++ imgMaskData.nPixels = width * height;
++ imgMaskData.idx = 0;
++ imgMaskData.invert = invert;
++
++ splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat);
++ if (inlineImg) {
++ while (imageMaskSrc(&imgMaskData, &pix)) ;
++ }
++
++ delete imgMaskData.imgStr;
++}
++
++struct SplashOutImageData {
++ ImageStream *imgStr;
++ GfxImageColorMap *colorMap;
++ int *maskColors;
++ SplashOutputDev *out;
++ int nPixels, idx;
++};
++
++GBool SplashOutputDev::imageSrc(void *data, SplashColor *pixel,
++ Guchar *alpha) {
++ SplashOutImageData *imgData = (SplashOutImageData *)data;
++ Guchar pix[gfxColorMaxComps];
++ GfxRGB rgb;
++ double gray;
++ int i;
++
++ if (imgData->idx >= imgData->nPixels) {
++ return gFalse;
++ }
++
++ //~ use getLine
++ imgData->imgStr->getPixel(pix);
++ switch (imgData->out->colorMode) {
++ case splashModeMono1:
++ case splashModeMono8:
++ imgData->colorMap->getGray(pix, &gray);
++ pixel->mono8 = soutRound(255 * gray);
++ break;
++ case splashModeRGB8:
++ imgData->colorMap->getRGB(pix, &rgb);
++ pixel->rgb8 = splashMakeRGB8(soutRound(255 * rgb.r),
++ soutRound(255 * rgb.g),
++ soutRound(255 * rgb.b));
++ break;
++ case splashModeBGR8Packed:
++ imgData->colorMap->getRGB(pix, &rgb);
++ pixel->bgr8 = splashMakeBGR8(soutRound(255 * rgb.r),
++ soutRound(255 * rgb.g),
++ soutRound(255 * rgb.b));
++ break;
++ }
++
++ if (imgData->maskColors) {
++ *alpha = 0;
++ for (i = 0; i < imgData->colorMap->getNumPixelComps(); ++i) {
++ if (pix[i] < imgData->maskColors[2*i] ||
++ pix[i] > imgData->maskColors[2*i+1]) {
++ *alpha = 1;
++ break;
++ }
++ }
++ } else {
++ *alpha = 1;
++ }
++
++ ++imgData->idx;
++ return gTrue;
++}
++
++void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
++ int width, int height,
++ GfxImageColorMap *colorMap,
++ int *maskColors, GBool inlineImg) {
++ double *ctm;
++ SplashCoord mat[6];
++ SplashOutImageData imgData;
++ SplashColor pix;
++ Guchar alpha;
++
++ ctm = state->getCTM();
++ mat[0] = ctm[0];
++ mat[1] = ctm[1];
++ mat[2] = -ctm[2];
++ mat[3] = -ctm[3];
++ mat[4] = ctm[2] + ctm[4];
++ mat[5] = ctm[3] + ctm[5];
++
++ imgData.imgStr = new ImageStream(str, width,
++ colorMap->getNumPixelComps(),
++ colorMap->getBits());
++ imgData.imgStr->reset();
++ imgData.colorMap = colorMap;
++ imgData.maskColors = maskColors;
++ imgData.out = this;
++ imgData.nPixels = width * height;
++ imgData.idx = 0;
++
++ splash->drawImage(&imageSrc, &imgData,
++ (colorMode == splashModeMono1) ? splashModeMono8
++ : colorMode,
++ width, height, mat);
++ if (inlineImg) {
++ while (imageSrc(&imgData, &pix, &alpha)) ;
++ }
++
++ delete imgData.imgStr;
++}
++
++int SplashOutputDev::getBitmapWidth() {
++ return bitmap->getWidth();
++}
++
++int SplashOutputDev::getBitmapHeight() {
++ return bitmap->getHeight();
++}
++
++void SplashOutputDev::xorRectangle(int x0, int y0, int x1, int y1,
++ SplashPattern *pattern) {
++ SplashPath *path;
++
++ path = new SplashPath();
++ path->moveTo((SplashCoord)x0, (SplashCoord)y0);
++ path->lineTo((SplashCoord)x1, (SplashCoord)y0);
++ path->lineTo((SplashCoord)x1, (SplashCoord)y1);
++ path->lineTo((SplashCoord)x0, (SplashCoord)y1);
++ path->close();
++ splash->setFillPattern(pattern);
++ splash->xorFill(path, gTrue);
++ delete path;
++}
++
++void SplashOutputDev::setFillColor(int r, int g, int b) {
++ GfxRGB rgb;
++ double gray;
++
++ rgb.r = r / 255.0;
++ rgb.g = g / 255.0;
++ rgb.b = b / 255.0;
++ gray = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g;
++ splash->setFillPattern(getColor(gray, &rgb));
++}
++
++SplashFont *SplashOutputDev::getFont(GooString *name, double *mat) {
++ DisplayFontParam *dfp;
++ Ref ref;
++ SplashOutFontFileID *id;
++ SplashFontFile *fontFile;
++ SplashFont *fontObj;
++ int i;
++
++ for (i = 0; i < 16; ++i) {
++ if (!name->cmp(splashOutSubstFonts[i].name)) {
++ break;
++ }
++ }
++ if (i == 16) {
++ return NULL;
++ }
++ ref.num = i;
++ ref.gen = -1;
++ id = new SplashOutFontFileID(&ref);
++
++ // check the font file cache
++ if ((fontFile = fontEngine->getFontFile(id))) {
++ delete id;
++
++ // load the font file
++ } else {
++ dfp = globalParams->getDisplayFont(name);
++ if (dfp->kind != displayFontT1) {
++ return NULL;
++ }
++ fontFile = fontEngine->loadType1Font(id, dfp->t1.fileName->getCString(),
++ gFalse, winAnsiEncoding);
++ }
++
++ // create the scaled font
++ fontObj = fontEngine->getFont(fontFile, (SplashCoord *)mat);
++
++ return fontObj;
++}
+diff --exclude-from=/home/dang/.diffrc -u -ruN poppler-0.4.3.orig/utils/SplashOutputDev.h poppler-0.4.3/utils/SplashOutputDev.h
+--- poppler-0.4.3.orig/utils/SplashOutputDev.h 1969-12-31 19:00:00.000000000 -0500
++++ poppler-0.4.3/utils/SplashOutputDev.h 2005-12-26 21:28:15.000000000 -0500
+@@ -0,0 +1,195 @@
++//========================================================================
++//
++// SplashOutputDev.h
++//
++// Copyright 2003 Glyph & Cog, LLC
++//
++//========================================================================
++
++#ifndef SPLASHOUTPUTDEV_H
++#define SPLASHOUTPUTDEV_H
++
++#include <poppler-config.h>
++
++#ifdef USE_GCC_PRAGMAS
++#pragma interface
++#endif
++
++#include "goo/gtypes.h"
++#include "splash/SplashTypes.h"
++#include "config.h"
++#include "OutputDev.h"
++
++class GfxState;
++class GfxPath;
++class Gfx8BitFont;
++class SplashBitmap;
++class Splash;
++class SplashPath;
++class SplashPattern;
++class SplashFontEngine;
++class SplashFont;
++class T3FontCache;
++struct T3FontCacheTag;
++struct T3GlyphStack;
++struct GfxRGB;
++
++//------------------------------------------------------------------------
++
++// number of Type 3 fonts to cache
++#define splashOutT3FontCacheSize 8
++
++//------------------------------------------------------------------------
++// SplashOutputDev
++//------------------------------------------------------------------------
++
++class SplashOutputDev: public OutputDev {
++public:
++
++ // Constructor.
++ SplashOutputDev(SplashColorMode colorModeA, GBool reverseVideoA,
++ SplashColor paperColorA);
++
++ // Destructor.
++ virtual ~SplashOutputDev();
++
++ //----- get info about output device
++
++ // Does this device use upside-down coordinates?
++ // (Upside-down means (0,0) is the top left corner of the page.)
++ virtual GBool upsideDown() { return gTrue; }
++
++ // Does this device use drawChar() or drawString()?
++ virtual GBool useDrawChar() { return gTrue; }
++
++ // Does this device use beginType3Char/endType3Char? Otherwise,
++ // text in Type 3 fonts will be drawn with drawChar/drawString.
++ virtual GBool interpretType3Chars() { return gTrue; }
++
++ //----- initialization and control
++
++ // Start a page.
++ virtual void startPage(int pageNum, GfxState *state);
++
++ // 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);
++
++ //----- update graphics state
++ virtual void updateAll(GfxState *state);
++ virtual void updateCTM(GfxState *state, double m11, double m12,
++ double m21, double m22, double m31, double m32);
++ virtual void updateLineDash(GfxState *state);
++ virtual void updateFlatness(GfxState *state);
++ virtual void updateLineJoin(GfxState *state);
++ virtual void updateLineCap(GfxState *state);
++ virtual void updateMiterLimit(GfxState *state);
++ virtual void updateLineWidth(GfxState *state);
++ virtual void updateFillColor(GfxState *state);
++ virtual void updateStrokeColor(GfxState *state);
++
++ //----- update text state
++ virtual void updateFont(GfxState *state);
++
++ //----- path painting
++ virtual void stroke(GfxState *state);
++ virtual void fill(GfxState *state);
++ virtual void eoFill(GfxState *state);
++
++ //----- path clipping
++ virtual void clip(GfxState *state);
++ virtual void eoClip(GfxState *state);
++
++ //----- text drawing
++ virtual void drawChar(GfxState *state, double x, double y,
++ double dx, double dy,
++ double originX, double originY,
++ CharCode code, Unicode *u, int uLen);
++ virtual GBool beginType3Char(GfxState *state, double x, double y,
++ double dx, double dy,
++ CharCode code, Unicode *u, int uLen);
++ virtual void endType3Char(GfxState *state);
++ virtual void endTextObject(GfxState *state);
++
++ //----- image drawing
++ virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GBool invert,
++ GBool inlineImg);
++ virtual void drawImage(GfxState *state, Object *ref, Stream *str,
++ int width, int height, GfxImageColorMap *colorMap,
++ int *maskColors, GBool inlineImg);
++
++ //----- Type 3 font operators
++ virtual void type3D0(GfxState *state, double wx, double wy);
++ virtual void type3D1(GfxState *state, double wx, double wy,
++ double llx, double lly, double urx, double ury);
++
++ //----- special access
++
++ // Called to indicate that a new PDF document has been loaded.
++ void startDoc(XRef *xrefA);
++
++ GBool isReverseVideo() { return reverseVideo; }
++
++ // Get the bitmap and its size.
++ SplashBitmap *getBitmap() { return bitmap; }
++ int getBitmapWidth();
++ int getBitmapHeight();
++
++ // Get the Splash object.
++ Splash *getSplash() { return splash; }
++
++ // XOR a rectangular region in the bitmap with <pattern>. <pattern>
++ // is passed to Splash::setFillPattern, so it should not be used
++ // after calling this function.
++ void xorRectangle(int x0, int y0, int x1, int y1, SplashPattern *pattern);
++
++ // Set the Splash fill color.
++ void setFillColor(int r, int g, int b);
++
++ // Get a font object for a Base-14 font, using the Latin-1 encoding.
++ SplashFont *getFont(GooString *name, double *mat);
++
++ void setUnderlayCbk(void (*cbk)(void *data), void *data)
++ { underlayCbk = cbk; underlayCbkData = data; }
++
++private:
++
++ SplashPattern *getColor(double gray, GfxRGB *rgb);
++ SplashPath *convertPath(GfxState *state, GfxPath *path);
++ void drawType3Glyph(T3FontCache *t3Font,
++ T3FontCacheTag *tag, Guchar *data,
++ double x, double y);
++ static GBool imageMaskSrc(void *data, SplashMono1 *pixel);
++ static GBool imageSrc(void *data, SplashColor *pixel, Guchar *alpha);
++
++ SplashColorMode colorMode;
++ GBool reverseVideo; // reverse video mode
++ SplashColor paperColor; // paper color
++
++ XRef *xref; // xref table for current document
++
++ SplashBitmap *bitmap;
++ Splash *splash;
++ SplashFontEngine *fontEngine;
++
++ T3FontCache * // Type 3 font cache
++ t3FontCache[splashOutT3FontCacheSize];
++ int nT3Fonts; // number of valid entries in t3FontCache
++ T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack
++
++ SplashFont *font; // current font
++ GBool needFontUpdate; // set when the font needs to be updated
++ SplashPath *textClipPath; // clipping path built with text object
++
++ void (*underlayCbk)(void *data);
++ void *underlayCbkData;
++};
++
++#endif