summaryrefslogtreecommitdiff
path: root/noncore
Side-by-side diff
Diffstat (limited to 'noncore') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/QOutputDev.h7
-rw-r--r--noncore/unsupported/qpdf/README45
-rw-r--r--noncore/unsupported/qpdf/UTF8.h14
-rw-r--r--noncore/unsupported/qpdf/qpdf.cpp13
-rw-r--r--noncore/unsupported/qpdf/qpdf.h7
-rw-r--r--noncore/unsupported/qpdf/qpdf.pro5
-rw-r--r--noncore/unsupported/qpdf/xpdf/Annot.cc (renamed from noncore/unsupported/qpdf/xpdf/FormWidget.cc)53
-rw-r--r--noncore/unsupported/qpdf/xpdf/Annot.h (renamed from noncore/unsupported/qpdf/xpdf/FormWidget.h)40
-rw-r--r--noncore/unsupported/qpdf/xpdf/Array.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Array.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/BuiltinFont.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/CMap.cc104
-rw-r--r--noncore/unsupported/qpdf/xpdf/CMap.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Catalog.cc8
-rw-r--r--noncore/unsupported/qpdf/xpdf/Catalog.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc160
-rw-r--r--noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h5
-rw-r--r--noncore/unsupported/qpdf/xpdf/CharTypes.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Decrypt.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Decrypt.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Dict.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Dict.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/DisplayFontTable.h6
-rw-r--r--noncore/unsupported/qpdf/xpdf/Error.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Error.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/ErrorCodes.h24
-rw-r--r--noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/FontEncodingTables.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Function.cc13
-rw-r--r--noncore/unsupported/qpdf/xpdf/Function.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Gfx.cc589
-rw-r--r--noncore/unsupported/qpdf/xpdf/Gfx.h20
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxFont.cc62
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxFont.h24
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxState.cc246
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxState.h39
-rw-r--r--noncore/unsupported/qpdf/xpdf/GlobalParams.cc381
-rw-r--r--noncore/unsupported/qpdf/xpdf/GlobalParams.h49
-rw-r--r--noncore/unsupported/qpdf/xpdf/Lexer.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Lexer.h11
-rw-r--r--noncore/unsupported/qpdf/xpdf/Link.cc34
-rw-r--r--noncore/unsupported/qpdf/xpdf/Link.h8
-rw-r--r--noncore/unsupported/qpdf/xpdf/NameToCharCode.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/NameToCharCode.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Object.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Object.h12
-rw-r--r--noncore/unsupported/qpdf/xpdf/OutputDev.cc7
-rw-r--r--noncore/unsupported/qpdf/xpdf/OutputDev.h17
-rw-r--r--noncore/unsupported/qpdf/xpdf/PDFDoc.cc16
-rw-r--r--noncore/unsupported/qpdf/xpdf/PDFDoc.h6
-rw-r--r--noncore/unsupported/qpdf/xpdf/PSTokenizer.cc133
-rw-r--r--noncore/unsupported/qpdf/xpdf/PSTokenizer.h39
-rw-r--r--noncore/unsupported/qpdf/xpdf/Page.cc40
-rw-r--r--noncore/unsupported/qpdf/xpdf/Page.h28
-rw-r--r--noncore/unsupported/qpdf/xpdf/Parser.cc11
-rw-r--r--noncore/unsupported/qpdf/xpdf/Parser.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Stream-CCITT.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/Stream.cc215
-rw-r--r--noncore/unsupported/qpdf/xpdf/Stream.h113
-rw-r--r--noncore/unsupported/qpdf/xpdf/TextOutputDev.cc73
-rw-r--r--noncore/unsupported/qpdf/xpdf/TextOutputDev.h22
-rw-r--r--noncore/unsupported/qpdf/xpdf/UnicodeMap.cc2
-rw-r--r--noncore/unsupported/qpdf/xpdf/UnicodeMap.h2
-rw-r--r--noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h60
-rw-r--r--noncore/unsupported/qpdf/xpdf/XRef.cc80
-rw-r--r--noncore/unsupported/qpdf/xpdf/XRef.h25
69 files changed, 2201 insertions, 715 deletions
diff --git a/noncore/unsupported/qpdf/QOutputDev.h b/noncore/unsupported/qpdf/QOutputDev.h
index 2958062..f3c5a01 100644
--- a/noncore/unsupported/qpdf/QOutputDev.h
+++ b/noncore/unsupported/qpdf/QOutputDev.h
@@ -1,173 +1,180 @@
//========================================================================
//
// XOutputDev.h
//
// Copyright 1996 Derek B. Noonburg
//
//========================================================================
#ifndef QOUTPUTDEV_H
#define QOUTPUTDEV_H
#ifdef __GNUC__
#pragma interface
#endif
#include "aconf.h"
#include <stddef.h>
#include <qscrollview.h>
class Object;
#include "config.h"
#include "CharTypes.h"
#include "GlobalParams.h"
#include "OutputDev.h"
class GString;
class GList;
struct GfxRGB;
class GfxFont;
class GfxSubpath;
class TextPage;
class XOutputFontCache;
class Link;
class Catalog;
class DisplayFontParam;
class UnicodeMap;
class CharCodeToUnicode;
class QPainter;
class QPixmap;
class QPointArray;
typedef fouble fp_t;
//------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// Misc types
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// XOutputDev
//------------------------------------------------------------------------
class QOutputDev : public QScrollView, public OutputDev {
public:
// Constructor.
QOutputDev( QWidget *parent = 0, const char *name = 0, int flags = 0 );
// Destructor.
virtual ~QOutputDev();
//---- 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();
//----- 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, fp_t m11, fp_t m12,
fp_t m21, fp_t m22, fp_t m31, fp_t 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 beginString(GfxState *state, GString *s);
virtual void endString(GfxState *state);
virtual void drawChar(GfxState *state, fp_t x, fp_t y,
fp_t dx, fp_t dy,
fp_t originX, fp_t originY,
CharCode code, Unicode *u, int uLen);
//----- 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);
// Find a string. If <top> is true, starts looking at <l>,<t>;
// otherwise starts looking at top of page. If <bottom> is true,
// stops looking at <l+w-1>,<t+h-1>; otherwise stops looking at bottom
// of page. If found, sets the text bounding rectange and returns
// true; otherwise returns false.
GBool findText ( Unicode *s, int len, GBool top, GBool bottom, int *xMin, int *yMin, int *xMax, int *yMax );
//----- special QT access
bool findText ( const QString &str, int &l, int &t, int &w, int &h, bool top = 0, bool bottom = 0 );
bool findText ( const QString &str, QRect &r, bool top = 0, bool bottom = 0 );
// Get the text which is inside the specified rectangle.
QString getText ( int left, int top, int width, int height );
QString getText ( const QRect &r );
protected:
virtual void drawContents ( QPainter *p, int, int, int, int );
private:
QPixmap *m_pixmap; // pixmap to draw into
QPainter *m_painter;
TextPage *m_text; // text from the current page
private:
QFont matchFont ( GfxFont *, fp_t m11, fp_t m12, fp_t m21, fp_t m22 );
void updateLineAttrs ( GfxState *state, GBool updateDash );
void doFill ( GfxState *state, bool winding );
void doClip ( GfxState *state, bool winding );
int convertPath ( GfxState *state, QPointArray &points, QArray<int> &lengths );
int convertSubpath ( GfxState *state, GfxSubpath *subpath, QPointArray &points );
};
#endif
diff --git a/noncore/unsupported/qpdf/README b/noncore/unsupported/qpdf/README
index 36ce6bc..65e7aaf 100644
--- a/noncore/unsupported/qpdf/README
+++ b/noncore/unsupported/qpdf/README
@@ -1,89 +1,80 @@
QPDF - a PDF viewer for the Qtopia environment
-This tool is based on xpdf (currently 1.00). It uses the (mostly unmodified -
+This tool is based on xpdf (currently 1.01). It uses the (mostly unmodified -
see below) xpdf PDF rendering engine. The Qtopia adaption was done with a new
OutputDev which renders directly to a QPixmap via QPainter calls.
Changes in 20020406:
- Font substitution handling improved.
- Unknown characters are simply ignored now.
- Fullscreen view added.
Changes in 20020407:
- Crash with FontName == 0 fixed
- Cleanup
- Prepare for CVS import
Changes in 20020408:
- Progress indicator added
- Problems with type 3 fonts (not fully supported by XPDF) solved
- Heavy optimizations in the image rendering code
-Changed in 20020413:
+Changes in 20020413:
- Fixed crash in find routine
- Stylus selection reworked
- Cursor-key navigation added
- Various crashes related to recursive calling of XPDF fixed
+Changes in 20020417:
+ - Fixed crash in XPDF regarding 0-length strings.
+ - Fast sqrt, rint and fabs functions added.
+
+Changes in 20020524:
+ - Ported to xpdf 1.01
+
Changes to xpdf:
- xpdf calculates nearly everything with doubles. Since ARMs are not equipped
with a FPU, all doubles have been replaced with a C++ class "fouble" (fixed
double), which operates on 32bit integers with fixed point arithmetic.
This gave a speedup of up to 800% for image rendering.
- No Font handling anymore - This means no embedded, no true-type, no type1-
fonts. The task to choose the right font is up to the Qt QFont class.
This works pretty well -- only Symbol fonts give problems.
- Everything that should be rotated (fonts, images) is simply ignored, because
a) the Qtopia Qt/E config has QPainter transformations disabled
b) the transformation is awful slow
c) do you really need rotated images on your iPaq ? ;)
ToDo:
- Clipping has been deactivated, because Qt/E had problems with QPainter
save/restore's with active clipping regions. I need to investigate this
in detail.
- Links are currently simply ignored.
Install:
- - xpdf-1.00
- Get the tarball for xpdf, version 1.0, untar it and ./configure it.
- (No special flags are needed for ./configure - it simply has to run)
-
- - qpdf
- Make sure your QPEDIR / TMAKEPATH variables are correctly !
-
- cd into the xpdf directory (xpdf-1.00) and untar the qpdf tarball. This
- should create a subdirectory qpdf.
- cd into this directory and start the script "./setup-qpdf". This
- incorporates the above mentioned patches into xpdf.
-
- Now do a make.
-
- Copy the files qpdf, qpdf_icon.png and qpdf.desktop to the appropriate
- directories on your iPaq or:
- If you want a ipk, just run ./mkipkg
+ - Qpdf is now fully integrated into Opie. For compilation and installation
+ instructions see http://opie.handhelds.org.
- compress / uncompress
- If you run a normal familiar installation, it the standard gzip (I tested
- 1.2.4-33 ipkg) can handle the compression format used in PDF files, when
+ If you run a normal familiar installation, the standard gzip (I tested
+ 1.2.4-33 ipkg) can handle the compression format used in PDF files, when
called as uncompress. The BusyBox version of gzip can _not_ handle this
old format.
- If you do not have a working uncompress installed on your iPaq, you can
- simply use the one in the contrib directory of the tarball (make uncompress
- a link to compress).
- [I could not find an official tarball for compress -- this is the SuSE
- version cross-compiled for ARM]
-
+ If you do not have a working uncompress installed on your iPaq, you could
+ simply use the old compress package.
+ (I could not find an official tarball for compress -- I used the SuSE
+ version cross-compiled for ARM for myself, but I will make an ipk soon)
+
Have fun ;)
Robert (griebl@gmx.de)
\ No newline at end of file
diff --git a/noncore/unsupported/qpdf/UTF8.h b/noncore/unsupported/qpdf/UTF8.h
index aacf663..95adecf 100644
--- a/noncore/unsupported/qpdf/UTF8.h
+++ b/noncore/unsupported/qpdf/UTF8.h
@@ -1,24 +1,38 @@
//========================================================================
//
// UTF8.h
//
// Copyright 2001 Derek B. Noonburg
// Modified for QPE by Robert Griebl
//
//========================================================================
#include <qstring.h>
#include <string.h>
static int mapUTF8 ( Unicode u, char *buf, int bufSize )
{
QCString utf = QString ( QChar ( u )). utf8 ( );
int len = utf. length ( );
if ( len <= bufSize ) {
::memcpy ( buf, utf. data ( ), len );
return len;
}
else
return 0;
}
+
+static int mapUCS2 ( Unicode u, char *buf, int bufSize)
+{
+ if (u <= 0xffff) {
+ if (bufSize < 2)
+ return 0;
+
+ buf[0] = (char)((u >> 8) & 0xff);
+ buf[1] = (char)(u & 0xff);
+ return 2;
+ }
+ else
+ return 0;
+}
diff --git a/noncore/unsupported/qpdf/qpdf.cpp b/noncore/unsupported/qpdf/qpdf.cpp
index 6c268ec..f338509 100644
--- a/noncore/unsupported/qpdf/qpdf.cpp
+++ b/noncore/unsupported/qpdf/qpdf.cpp
@@ -1,180 +1,191 @@
//========================================================================
//
// qpdf.cc
//
// Copyright 2001 Robert Griebl
//
//========================================================================
#include "aconf.h"
#include "GString.h"
#include "PDFDoc.h"
#include "TextOutputDev.h"
#include "QPEOutputDev.h"
#include <qpe/qpeapplication.h>
#include <qpe/resource.h>
#include <qpe/applnk.h>
-#include <qpe/fileselector.h>
#include <qpe/qcopenvelope_qws.h>
#include <qclipboard.h>
#include <qtoolbar.h>
+#include <qtoolbutton.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qwidgetstack.h>
#include <qtimer.h>
#include <qfileinfo.h>
#include <qstring.h>
#include <qlineedit.h>
#include <qspinbox.h>
#include <qlayout.h>
#include <qdialog.h>
#include <qlabel.h>
#include <qmessagebox.h>
#include "qpdf.h"
+#ifdef QPDF_QPE_ONLY
+#include <qpe/fileselector.h>
+#else
+#include <opie/ofileselector.h>
+#endif
+
int main ( int argc, char **argv )
{
QPEApplication app ( argc, argv );
// read config file
globalParams = new GlobalParams ( "" );
globalParams-> setErrQuiet ( true );
QPdfDlg *dlg = new QPdfDlg ( );
app. showMainDocumentWidget ( dlg );
if (( app. argc ( ) == 3 ) && ( app. argv ( ) [1] == QCString ( "-f" )))
dlg-> openFile ( app. argv ( ) [2] );
return app. exec ( );
}
QPdfDlg::QPdfDlg ( ) : QMainWindow ( )
{
setCaption ( tr( "QPdf" ));
setIcon ( Resource::loadPixmap ( "qpdf_icon" ));
m_busy = false;
m_doc = 0;
m_pages = 0;
m_zoom = 72;
m_currentpage = 0;
m_fullscreen = false;
m_renderok = false;
setToolBarsMovable ( false );
m_stack = new QWidgetStack ( this );
m_stack-> setSizePolicy ( QSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Expanding ));
setCentralWidget ( m_stack );
m_outdev = new QPEOutputDev ( m_stack );
connect ( m_outdev, SIGNAL( selectionChanged ( const QRect & )), this, SLOT( copyToClipboard ( const QRect & )));
+#ifdef QPDF_QPE_ONLY
m_filesel = new FileSelector ( "application/pdf", m_stack, "fs", false, true );
+#else
+ m_filesel = new OFileSelector ( "application/pdf", m_stack, "fs", false, true );
+#endif
+
connect ( m_filesel, SIGNAL( closeMe ( )), this, SLOT( closeFileSelector ( )));
connect ( m_filesel, SIGNAL( fileSelected ( const DocLnk & )), this, SLOT( openFile ( const DocLnk & )));
m_tb_menu = new QToolBar ( this );
m_tb_menu-> setHorizontalStretchable ( true );
QMenuBar *mb = new QMenuBar ( m_tb_menu );
m_pm_zoom = new QPopupMenu ( mb );
m_pm_zoom-> setCheckable ( true );
mb-> insertItem ( tr( "Zoom" ), m_pm_zoom );
m_pm_zoom-> insertItem ( tr( "Fit to width" ), 1 );
m_pm_zoom-> insertItem ( tr( "Fit to page" ), 2 );
m_pm_zoom-> insertSeparator ( );
m_pm_zoom-> insertItem ( tr( "50%" ), 50 );
m_pm_zoom-> insertItem ( tr( "75%" ), 75 );
m_pm_zoom-> insertItem ( tr( "100%" ), 100 );
m_pm_zoom-> insertItem ( tr( "125%" ), 125 );
m_pm_zoom-> insertItem ( tr( "150%" ), 150 );
m_pm_zoom-> insertItem ( tr( "200%" ), 200 );
connect ( m_pm_zoom, SIGNAL( activated ( int )), this, SLOT( setZoom ( int )));
m_tb_tool = new QToolBar ( this );
new QToolButton ( Resource::loadIconSet ( "fileopen" ), tr( "Open..." ), QString::null, this, SLOT( openFile ( )), m_tb_tool, "open" );
m_tb_tool-> addSeparator ( );
m_to_find = new QToolButton ( Resource::loadIconSet ( "find" ), tr( "Find..." ), QString::null, this, SLOT( toggleFindBar ( )), m_tb_tool, "find" );
m_to_find-> setToggleButton ( true );
m_tb_tool-> addSeparator ( );
m_to_full = new QToolButton ( Resource::loadIconSet ( "fullscreen" ), tr( "Fullscreen" ), QString::null, this, SLOT( toggleFullscreen ( )), m_tb_tool, "fullscreen" );
m_to_full-> setToggleButton ( true );
m_tb_tool-> addSeparator ( );
new QToolButton ( Resource::loadIconSet ( "fastback" ), tr( "First page" ), QString::null, this, SLOT( firstPage ( )), m_tb_tool, "first" );
new QToolButton ( Resource::loadIconSet ( "back" ), tr( "Previous page" ), QString::null, this, SLOT( prevPage ( )), m_tb_tool, "prev" );
new QToolButton ( Resource::loadIconSet ( "down" ), tr( "Goto page..." ), QString::null, this, SLOT( gotoPageDialog ( )), m_tb_tool, "goto" );
new QToolButton ( Resource::loadIconSet ( "forward" ), tr( "Next page" ), QString::null, this, SLOT( nextPage ( )), m_tb_tool, "next" );
new QToolButton ( Resource::loadIconSet ( "fastforward" ), tr( "Last page" ), QString::null, this, SLOT( lastPage ( )), m_tb_tool, "last" );
m_tb_find = new QToolBar ( this );
addToolBar ( m_tb_find, "Search", QMainWindow::Top, true );
m_tb_find-> setHorizontalStretchable ( true );
m_tb_find-> hide ( );
m_findedit = new QLineEdit ( m_tb_find, "findedit" );
m_tb_find-> setStretchableWidget ( m_findedit );
connect ( m_findedit, SIGNAL( textChanged ( const QString & )), this, SLOT( findText ( const QString & )));
new QToolButton ( Resource::loadIconSet ( "next" ), tr( "Next" ), QString::null, this, SLOT( findText ( )), m_tb_find, "findnext" );
openFile ( );
}
QPdfDlg::~QPdfDlg ( )
{
delete m_doc;
}
// vv Fullscreen handling (for broken QT-lib) [David Hedbor, www.eongames.com]
void QPdfDlg::resizeEvent ( QResizeEvent * )
{
if ( m_fullscreen && ( size ( ) != qApp-> desktop ( )-> size ( )))
setFullscreen ( true );
}
void QPdfDlg::focusInEvent ( QFocusEvent * )
{
if ( m_fullscreen )
setFullscreen ( true );
}
void QPdfDlg::toggleFullscreen ( )
{
if ( m_to_full-> isOn ( ) == m_fullscreen )
m_to_full-> setOn ( !m_fullscreen );
m_fullscreen = !m_fullscreen;
setFullscreen ( m_fullscreen );
}
void QPdfDlg::setFullscreen ( bool b )
{
static QSize normalsize;
if ( b ) {
if ( !normalsize. isValid ( ))
normalsize = size ( );
setFixedSize ( qApp-> desktop ( )-> size ( ));
showNormal ( );
reparent ( 0, WStyle_Customize | WStyle_NoBorder, QPoint ( 0, 0 ));
showFullScreen ( );
}
diff --git a/noncore/unsupported/qpdf/qpdf.h b/noncore/unsupported/qpdf/qpdf.h
index b4ce554..8b3cff9 100644
--- a/noncore/unsupported/qpdf/qpdf.h
+++ b/noncore/unsupported/qpdf/qpdf.h
@@ -1,94 +1,101 @@
#ifndef __QPDF_H__
#define __QPDF_H__
#include "aconf.h"
#include <qmainwindow.h>
+#define QPDF_QPE_ONLY 1 // ofileselector does not work right currently
class QPEOutputDev;
class PDFDoc;
class DocLnk;
class FileSelector;
+class OFileSelector;
class QWidgetStack;
class QLineEdit;
class QPdfDlg : public QMainWindow {
Q_OBJECT
public:
QPdfDlg ( );
virtual ~QPdfDlg ( );
public slots:
void firstPage ( );
void prevPage ( );
void nextPage ( );
void lastPage ( );
void gotoPage ( int n );
void setZoom ( int z );
void gotoPageDialog ( );
void toggleFullscreen ( );
void toggleFindBar ( );
void findText ( const QString & );
void findText ( );
void openFile ( );
void openFile ( const QString & );
void openFile ( const DocLnk & );
void setDocument ( const QString & );
private slots:
void delayedInit ( );
void closeFileSelector ( );
void updateCaption ( );
void copyToClipboard ( const QRect & );
protected:
void setFullscreen ( bool b = true );
void setBusy ( bool b = true );
bool busy ( ) const;
void renderPage ( );
virtual void resizeEvent ( QResizeEvent *e );
virtual void focusInEvent ( QFocusEvent *e );
private:
QWidgetStack *m_stack;
QPEOutputDev *m_outdev;
+
+#ifdef QPDF_QPE_ONLY
FileSelector *m_filesel;
+#else
+ OFileSelector *m_filesel;
+#endif
QToolBar *m_tb_menu, *m_tb_tool, *m_tb_find;
QLineEdit *m_findedit;
QPopupMenu *m_pm_zoom;
QToolButton *m_to_find, *m_to_full;
bool m_fullscreen;
bool m_busy;
bool m_renderok;
int m_currentpage;
int m_pages;
int m_zoom;
PDFDoc *m_doc;
QString m_currentdoc;
};
#endif
diff --git a/noncore/unsupported/qpdf/qpdf.pro b/noncore/unsupported/qpdf/qpdf.pro
index 0c2e38b..fe5abfb 100644
--- a/noncore/unsupported/qpdf/qpdf.pro
+++ b/noncore/unsupported/qpdf/qpdf.pro
@@ -1,60 +1,61 @@
TEMPLATE = app
CONFIG *= qt embedded release warn_off
CONFIG -= warn_on
SOURCES = xpdf/Array.cc \
xpdf/BuiltinFont.cc \
xpdf/BuiltinFontTables.cc \
xpdf/CMap.cc \
xpdf/Catalog.cc \
xpdf/CharCodeToUnicode.cc \
xpdf/Decrypt.cc \
xpdf/Dict.cc \
xpdf/Error.cc \
xpdf/FontEncodingTables.cc \
- xpdf/FormWidget.cc \
+ xpdf/Annot.cc \
xpdf/Function.cc \
xpdf/Gfx.cc \
xpdf/GfxFont.cc \
xpdf/GfxState.cc \
xpdf/GlobalParams.cc \
xpdf/Lexer.cc \
xpdf/Link.cc \
xpdf/NameToCharCode.cc \
xpdf/Object.cc \
xpdf/OutputDev.cc \
xpdf/PDFDoc.cc \
xpdf/Page.cc \
xpdf/Parser.cc \
+ xpdf/PSTokenizer.cc \
xpdf/Stream.cc \
xpdf/TextOutputDev.cc \
xpdf/UnicodeMap.cc \
xpdf/XRef.cc \
goo/GHash.cc \
goo/GString.cc \
goo/GList.cc \
QOutputDev.cpp \
QPEOutputDev.cpp \
qpdf.cpp \
qbusybar.cpp \
gooStub.cpp
HEADERS = QOutputDev.h \
QPEOutputDev.h \
qbusybar.h \
qpdf.h
INCLUDEPATH += . \
.. \
xpdf \
$(OPIEDIR)/include \
../goo \
goo
-LIBS += -L $(OPIEDIR)/lib -lqpe
+LIBS += -L $(OPIEDIR)/lib -lqpe -lopie
DESTDIR = $(OPIEDIR)/bin
TARGET = qpdf
TRANSLATIONS = ../../i18n/de/qpdf.ts
diff --git a/noncore/unsupported/qpdf/xpdf/FormWidget.cc b/noncore/unsupported/qpdf/xpdf/Annot.cc
index 05c67a4..49ae50a 100644
--- a/noncore/unsupported/qpdf/xpdf/FormWidget.cc
+++ b/noncore/unsupported/qpdf/xpdf/Annot.cc
@@ -1,139 +1,138 @@
//========================================================================
//
-// FormWidget.cc
+// Annot.cc
//
-// Copyright 2000 Derek B. Noonburg
+// Copyright 2000-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include "gmem.h"
#include "Object.h"
#include "Gfx.h"
-#include "FormWidget.h"
+#include "Annot.h"
//------------------------------------------------------------------------
-// FormWidget
+// Annot
//------------------------------------------------------------------------
-FormWidget::FormWidget(XRef *xrefA, Dict *dict) {
+Annot::Annot(XRef *xrefA, Dict *dict) {
Object apObj, asObj, obj1, obj2;
fouble t;
ok = gFalse;
xref = xrefA;
if (dict->lookup("AP", &apObj)->isDict()) {
if (dict->lookup("AS", &asObj)->isName()) {
if (apObj.dictLookup("N", &obj1)->isDict()) {
if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) {
obj2.copy(&appearance);
ok = gTrue;
}
obj2.free();
}
obj1.free();
} else {
if (apObj.dictLookupNF("N", &obj1)->isRef()) {
obj1.copy(&appearance);
ok = gTrue;
}
obj1.free();
}
asObj.free();
}
apObj.free();
if (dict->lookup("Rect", &obj1)->isArray() &&
obj1.arrayGetLength() == 4) {
//~ should check object types here
obj1.arrayGet(0, &obj2);
xMin = obj2.getNum();
obj2.free();
obj1.arrayGet(1, &obj2);
yMin = obj2.getNum();
obj2.free();
obj1.arrayGet(2, &obj2);
xMax = obj2.getNum();
obj2.free();
obj1.arrayGet(3, &obj2);
yMax = obj2.getNum();
obj2.free();
if (xMin > xMax) {
t = xMin; xMin = xMax; xMax = t;
}
if (yMin > yMax) {
t = yMin; yMin = yMax; yMax = t;
}
} else {
//~ this should return an error
xMin = yMin = 0;
xMax = yMax = 1;
}
obj1.free();
}
-FormWidget::~FormWidget() {
+Annot::~Annot() {
appearance.free();
}
-void FormWidget::draw(Gfx *gfx) {
+void Annot::draw(Gfx *gfx) {
Object obj;
if (appearance.fetch(xref, &obj)->isStream()) {
- gfx->doWidgetForm(&obj, xMin, yMin, xMax, yMax);
+ gfx->doAnnot(&obj, xMin, yMin, xMax, yMax);
}
obj.free();
}
//------------------------------------------------------------------------
-// FormWidgets
+// Annots
//------------------------------------------------------------------------
-FormWidgets::FormWidgets(XRef *xref, Object *annots) {
- FormWidget *widget;
+Annots::Annots(XRef *xref, Object *annotsObj) {
+ Annot *annot;
Object obj1, obj2;
int size;
int i;
- widgets = NULL;
+ annots = NULL;
size = 0;
- nWidgets = 0;
+ nAnnots = 0;
- if (annots->isArray()) {
- for (i = 0; i < annots->arrayGetLength(); ++i) {
- if (annots->arrayGet(i, &obj1)->isDict()) {
+ if (annotsObj->isArray()) {
+ for (i = 0; i < annotsObj->arrayGetLength(); ++i) {
+ if (annotsObj->arrayGet(i, &obj1)->isDict()) {
obj1.dictLookup("Subtype", &obj2);
if (obj2.isName("Widget") ||
obj2.isName("Stamp")) {
- widget = new FormWidget(xref, obj1.getDict());
- if (widget->isOk()) {
- if (nWidgets >= size) {
+ annot = new Annot(xref, obj1.getDict());
+ if (annot->isOk()) {
+ if (nAnnots >= size) {
size += 16;
- widgets = (FormWidget **)grealloc(widgets,
- size * sizeof(FormWidget *));
+ annots = (Annot **)grealloc(annots, size * sizeof(Annot *));
}
- widgets[nWidgets++] = widget;
+ annots[nAnnots++] = annot;
} else {
- delete widget;
+ delete annot;
}
}
obj2.free();
}
obj1.free();
}
}
}
-FormWidgets::~FormWidgets() {
+Annots::~Annots() {
int i;
- for (i = 0; i < nWidgets; ++i) {
- delete widgets[i];
+ for (i = 0; i < nAnnots; ++i) {
+ delete annots[i];
}
- gfree(widgets);
+ gfree(annots);
}
diff --git a/noncore/unsupported/qpdf/xpdf/FormWidget.h b/noncore/unsupported/qpdf/xpdf/Annot.h
index 7f07889..0cc33dd 100644
--- a/noncore/unsupported/qpdf/xpdf/FormWidget.h
+++ b/noncore/unsupported/qpdf/xpdf/Annot.h
@@ -1,67 +1,69 @@
//========================================================================
//
-// FormWidget.h
+// Annot.h
//
-// Copyright 2000 Derek B. Noonburg
+// Copyright 2000-2002 Glyph & Cog, LLC
//
//========================================================================
-#ifndef FORMWIDGET_H
-#define FORMWIDGET_H
+#ifndef ANNOT_H
+#define ANNOT_H
#ifdef __GNUC__
#pragma interface
#endif
+#include <aconf.h>
+
class XRef;
class Gfx;
//------------------------------------------------------------------------
-// FormWidget
+// Annot
//------------------------------------------------------------------------
-class FormWidget {
+class Annot {
public:
- FormWidget(XRef *xrefA, Dict *dict);
- ~FormWidget();
+ Annot(XRef *xrefA, Dict *dict);
+ ~Annot();
GBool isOk() { return ok; }
void draw(Gfx *gfx);
// Get appearance object.
Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
private:
XRef *xref; // the xref table for this PDF file
Object appearance; // a reference to the Form XObject stream
// for the normal appearance
- fouble xMin, yMin, // widget rectangle
+ fouble xMin, yMin, // annotation rectangle
xMax, yMax;
GBool ok;
};
//------------------------------------------------------------------------
-// FormWidgets
+// Annots
//------------------------------------------------------------------------
-class FormWidgets {
+class Annots {
public:
- // Extract widgets from array of annotations.
- FormWidgets(XRef *xref, Object *annots);
+ // Extract non-link annotations from array of annotations.
+ Annots(XRef *xref, Object *annotsObj);
- ~FormWidgets();
+ ~Annots();
- // Iterate through list of widgets.
- int getNumWidgets() { return nWidgets; }
- FormWidget *getWidget(int i) { return widgets[i]; }
+ // Iterate through list of annotations.
+ int getNumAnnots() { return nAnnots; }
+ Annot *getAnnot(int i) { return annots[i]; }
private:
- FormWidget **widgets;
- int nWidgets;
+ Annot **annots;
+ int nAnnots;
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Array.cc b/noncore/unsupported/qpdf/xpdf/Array.cc
index 5743fe6..fbdde49 100644
--- a/noncore/unsupported/qpdf/xpdf/Array.cc
+++ b/noncore/unsupported/qpdf/xpdf/Array.cc
@@ -1,53 +1,53 @@
//========================================================================
//
// Array.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include "gmem.h"
#include "Object.h"
#include "Array.h"
//------------------------------------------------------------------------
// Array
//------------------------------------------------------------------------
Array::Array(XRef *xrefA) {
xref = xrefA;
elems = NULL;
size = length = 0;
ref = 1;
}
Array::~Array() {
int i;
for (i = 0; i < length; ++i)
elems[i].free();
gfree(elems);
}
void Array::add(Object *elem) {
if (length + 1 > size) {
size += 8;
elems = (Object *)grealloc(elems, size * sizeof(Object));
}
elems[length] = *elem;
++length;
}
Object *Array::get(int i, Object *obj) {
return elems[i].fetch(xref, obj);
}
Object *Array::getNF(int i, Object *obj) {
return elems[i].copy(obj);
}
diff --git a/noncore/unsupported/qpdf/xpdf/Array.h b/noncore/unsupported/qpdf/xpdf/Array.h
index 1616fc3..a118f68 100644
--- a/noncore/unsupported/qpdf/xpdf/Array.h
+++ b/noncore/unsupported/qpdf/xpdf/Array.h
@@ -1,56 +1,56 @@
//========================================================================
//
// Array.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef ARRAY_H
#define ARRAY_H
#ifdef __GNUC__
#pragma interface
#endif
#include "Object.h"
class XRef;
//------------------------------------------------------------------------
// Array
//------------------------------------------------------------------------
class Array {
public:
// Constructor.
Array(XRef *xrefA);
// Destructor.
~Array();
// Reference counting.
int incRef() { return ++ref; }
int decRef() { return --ref; }
// Get number of elements.
int getLength() { return length; }
// Add an element.
void add(Object *elem);
// Accessors.
Object *get(int i, Object *obj);
Object *getNF(int i, Object *obj);
private:
XRef *xref; // the xref table for this PDF file
Object *elems; // array of elements
int size; // size of <elems> array
int length; // number of elements in array
int ref; // reference count
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/BuiltinFont.h b/noncore/unsupported/qpdf/xpdf/BuiltinFont.h
index b4fa24c..a795311 100644
--- a/noncore/unsupported/qpdf/xpdf/BuiltinFont.h
+++ b/noncore/unsupported/qpdf/xpdf/BuiltinFont.h
@@ -1,55 +1,55 @@
//========================================================================
//
// BuiltinFont.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef BUILTINFONT_H
#define BUILTINFONT_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
struct BuiltinFont;
class BuiltinFontWidths;
//------------------------------------------------------------------------
struct BuiltinFont {
char *name;
char **defaultBaseEnc;
short ascent;
short descent;
short bbox[4];
BuiltinFontWidths *widths;
};
//------------------------------------------------------------------------
struct BuiltinFontWidth {
char *name;
Gushort width;
BuiltinFontWidth *next;
};
class BuiltinFontWidths {
public:
BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA);
~BuiltinFontWidths();
GBool getWidth(char *name, Gushort *width);
private:
int hash(char *name);
BuiltinFontWidth **tab;
int size;
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc b/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc
index 6833972..845abcd 100644
--- a/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc
+++ b/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// BuiltinFontTables.cc
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#include <aconf.h>
#include <stdlib.h>
#include "FontEncodingTables.h"
#include "BuiltinFontTables.h"
static BuiltinFontWidth courierWidthsTab[] = {
{ "Ntilde", 600, NULL },
{ "comma", 600, NULL },
{ "cedilla", 600, NULL },
{ "plusminus", 600, NULL },
{ "arrowup", 600, NULL },
{ "circumflex", 600, NULL },
{ "dotaccent", 600, NULL },
{ "LL", 600, NULL },
{ "asciitilde", 600, NULL },
{ "colon", 600, NULL },
{ "onehalf", 600, NULL },
{ "dollar", 600, NULL },
{ "ntilde", 600, NULL },
{ "left", 600, NULL },
{ "minus", 600, NULL },
{ "yen", 600, NULL },
{ "space", 600, NULL },
{ "questiondown", 600, NULL },
{ "emdash", 600, NULL },
{ "Agrave", 600, NULL },
{ "three", 600, NULL },
{ "numbersign", 600, NULL },
{ "A", 600, NULL },
{ "B", 600, NULL },
{ "C", 600, NULL },
{ "D", 600, NULL },
{ "E", 600, NULL },
{ "onequarter", 600, NULL },
{ "F", 600, NULL },
{ "G", 600, NULL },
{ "H", 600, NULL },
{ "I", 600, NULL },
{ "J", 600, NULL },
{ "K", 600, NULL },
{ "L", 600, NULL },
{ "backslash", 600, NULL },
{ "periodcentered", 600, NULL },
{ "M", 600, NULL },
{ "N", 600, NULL },
{ "O", 600, NULL },
{ "P", 600, NULL },
{ "Q", 600, NULL },
{ "R", 600, NULL },
{ "Aacute", 600, NULL },
{ "caron", 600, NULL },
{ "S", 600, NULL },
{ "T", 600, NULL },
{ "U", 600, NULL },
{ "agrave", 600, NULL },
{ "V", 600, NULL },
{ "tab", 600, NULL },
{ "W", 600, NULL },
{ "ll", 600, NULL },
{ "equal", 600, NULL },
{ "question", 600, NULL },
{ "X", 600, NULL },
{ "Y", 600, NULL },
{ "Z", 600, NULL },
{ "four", 600, NULL },
{ "a", 600, NULL },
{ "b", 600, NULL },
{ "c", 600, NULL },
{ "d", 600, NULL },
{ "e", 600, NULL },
{ "f", 600, NULL },
{ "g", 600, NULL },
{ "bullet", 600, NULL },
{ "h", 600, NULL },
{ "i", 600, NULL },
{ "Oslash", 600, NULL },
{ "dagger", 600, NULL },
{ "j", 600, NULL },
{ "k", 600, NULL },
{ "l", 600, NULL },
{ "m", 600, NULL },
{ "n", 600, NULL },
{ "o", 600, NULL },
{ "ordfeminine", 600, NULL },
{ "ring", 600, NULL },
{ "p", 600, NULL },
{ "q", 600, NULL },
{ "r", 600, NULL },
{ "twosuperior", 600, NULL },
{ "largebullet", 600, NULL },
{ "aacute", 600, NULL },
{ "s", 600, NULL },
{ "OE", 600, NULL },
diff --git a/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h b/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h
index 9a17ce9..3a8892e 100644
--- a/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h
+++ b/noncore/unsupported/qpdf/xpdf/BuiltinFontTables.h
@@ -1,23 +1,23 @@
//========================================================================
//
// BuiltinFontTables.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef BUILTINFONTTABLES_H
#define BUILTINFONTTABLES_H
#include "BuiltinFont.h"
#define nBuiltinFonts 14
#define nBuiltinFontSubsts 12
extern BuiltinFont builtinFonts[nBuiltinFonts];
extern BuiltinFont *builtinFontSubst[nBuiltinFontSubsts];
extern void initBuiltinFontTables();
extern void freeBuiltinFontTables();
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/CMap.cc b/noncore/unsupported/qpdf/xpdf/CMap.cc
index 57809f0..b49cffd 100644
--- a/noncore/unsupported/qpdf/xpdf/CMap.cc
+++ b/noncore/unsupported/qpdf/xpdf/CMap.cc
@@ -1,203 +1,223 @@
//========================================================================
//
// CMap.cc
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "gmem.h"
#include "gfile.h"
#include "GString.h"
#include "Error.h"
#include "GlobalParams.h"
+#include "PSTokenizer.h"
#include "CMap.h"
//------------------------------------------------------------------------
struct CMapVectorEntry {
GBool isVector;
union {
CMapVectorEntry *vector;
CID cid;
};
};
//------------------------------------------------------------------------
+static int getCharFromFile(void *data) {
+ return fgetc((FILE *)data);
+}
+
+//------------------------------------------------------------------------
+
CMap *CMap::parse(CMapCache *cache, GString *collectionA,
GString *cMapNameA) {
FILE *f;
CMap *cmap;
- char buf[256];
- GBool inCodeSpace, inCIDRange;
- char *tok1, *tok2, *tok3;
+ PSTokenizer *pst;
+ char tok1[256], tok2[256], tok3[256];
+ int n1, n2, n3;
Guint start, end;
- Guint n;
if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) {
// Check for an identity CMap.
if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) {
return new CMap(collectionA->copy(), cMapNameA->copy(), 0);
}
if (!cMapNameA->cmp("Identity-V")) {
return new CMap(collectionA->copy(), cMapNameA->copy(), 1);
}
error(-1, "Couldn't find '%s' CMap file for '%s' collection",
cMapNameA->getCString(), collectionA->getCString());
return NULL;
}
cmap = new CMap(collectionA->copy(), cMapNameA->copy());
- inCodeSpace = inCIDRange = gFalse;
- while (getLine(buf, sizeof(buf), f)) {
- tok1 = strtok(buf, " \t\r\n");
- if (!tok1 || tok1[0] == '%') {
- continue;
- }
- tok2 = strtok(NULL, " \t\r\n");
- tok3 = strtok(NULL, " \t\r\n");
- if (inCodeSpace) {
- if (!strcmp(tok1, "endcodespacerange")) {
- inCodeSpace = gFalse;
- } else if (tok2 && tok1[0] == '<' && tok2[0] == '<' &&
- (n = strlen(tok1)) == strlen(tok2) &&
- n >= 4 && (n & 1) == 0) {
- tok1[n - 1] = tok2[n - 1] = '\0';
- sscanf(tok1 + 1, "%x", &start);
- sscanf(tok2 + 1, "%x", &end);
- n = (n - 2) / 2;
- cmap->addCodeSpace(cmap->vector, start, end, n);
- }
- } else if (inCIDRange) {
- if (!strcmp(tok1, "endcidrange")) {
- inCIDRange = gFalse;
- } else if (tok2 && tok3 && tok1[0] == '<' && tok2[0] == '<' &&
- (n = strlen(tok1)) == strlen(tok2) &&
- n >= 4 && (n & 1) == 0) {
- tok1[n - 1] = tok2[n - 1] = '\0';
- sscanf(tok1 + 1, "%x", &start);
- sscanf(tok2 + 1, "%x", &end);
- n = (n - 2) / 2;
- cmap->addCIDs(start, end, n, (CID)atoi(tok3));
- }
- } else if (tok2 && !strcmp(tok2, "usecmap")) {
+ pst = new PSTokenizer(&getCharFromFile, f);
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ while (pst->getToken(tok2, sizeof(tok2), &n2)) {
+ if (!strcmp(tok2, "usecmap")) {
if (tok1[0] == '/') {
cmap->useCMap(cache, tok1 + 1);
}
+ pst->getToken(tok1, sizeof(tok1), &n1);
} else if (!strcmp(tok1, "/WMode")) {
cmap->wMode = atoi(tok2);
- } else if (tok2 && !strcmp(tok2, "begincodespacerange")) {
- inCodeSpace = gTrue;
- } else if (tok2 && !strcmp(tok2, "begincidrange")) {
- inCIDRange = gTrue;
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "begincodespacerange")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endcodespacerange")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endcodespacerange")) {
+ error(-1, "Illegal entry in codespacerange block in CMap");
+ break;
+ }
+ if (tok1[0] == '<' && tok2[0] == '<' &&
+ n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
+ tok1[n1 - 1] = tok2[n1 - 1] = '\0';
+ sscanf(tok1 + 1, "%x", &start);
+ sscanf(tok2 + 1, "%x", &end);
+ n1 = (n1 - 2) / 2;
+ cmap->addCodeSpace(cmap->vector, start, end, n1);
+ }
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "begincidrange")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endcidrange")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endcidrange") ||
+ !pst->getToken(tok3, sizeof(tok3), &n3) ||
+ !strcmp(tok3, "endcidrange")) {
+ error(-1, "Illegal entry in cidrange block in CMap");
+ break;
+ }
+ if (tok1[0] == '<' && tok2[0] == '<' &&
+ n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
+ tok1[n1 - 1] = tok2[n1 - 1] = '\0';
+ sscanf(tok1 + 1, "%x", &start);
+ sscanf(tok2 + 1, "%x", &end);
+ n1 = (n1 - 2) / 2;
+ cmap->addCIDs(start, end, n1, (CID)atoi(tok3));
+ }
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else {
+ strcpy(tok1, tok2);
}
}
+ delete pst;
fclose(f);
return cmap;
}
CMap::CMap(GString *collectionA, GString *cMapNameA) {
int i;
collection = collectionA;
cMapName = cMapNameA;
wMode = 0;
vector = (CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
for (i = 0; i < 256; ++i) {
vector[i].isVector = gFalse;
vector[i].cid = 0;
}
refCnt = 1;
}
CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) {
collection = collectionA;
cMapName = cMapNameA;
wMode = wModeA;
vector = NULL;
refCnt = 1;
}
void CMap::useCMap(CMapCache *cache, char *useName) {
GString *useNameStr;
CMap *subCMap;
useNameStr = new GString(useName);
subCMap = cache->getCMap(collection, useNameStr);
delete useNameStr;
if (!subCMap) {
return;
}
copyVector(vector, subCMap->vector);
subCMap->decRefCnt();
}
void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) {
int i, j;
for (i = 0; i < 256; ++i) {
if (src[i].isVector) {
if (!dest[i].isVector) {
dest[i].isVector = gTrue;
dest[i].vector =
(CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
for (j = 0; j < 256; ++j) {
dest[i].vector[j].isVector = gFalse;
dest[i].vector[j].cid = 0;
}
}
copyVector(dest[i].vector, src[i].vector);
} else {
if (dest[i].isVector) {
error(-1, "Collision in usecmap");
} else {
dest[i].cid = src[i].cid;
}
}
}
}
void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
Guint nBytes) {
Guint start2, end2;
int startByte, endByte, i, j;
if (nBytes > 1) {
startByte = (start >> (8 * (nBytes - 1))) & 0xff;
endByte = (end >> (8 * (nBytes - 1))) & 0xff;
start2 = start & ((1 << (8 * (nBytes - 1))) - 1);
end2 = end & ((1 << (8 * (nBytes - 1))) - 1);
for (i = startByte; i <= endByte; ++i) {
if (!vec[i].isVector) {
vec[i].isVector = gTrue;
vec[i].vector =
(CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
for (j = 0; j < 256; ++j) {
vec[i].vector[j].isVector = gFalse;
vec[i].vector[j].cid = 0;
}
}
addCodeSpace(vec[i].vector, start2, end2, nBytes - 1);
}
}
}
void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) {
CMapVectorEntry *vec;
CID cid;
int byte;
diff --git a/noncore/unsupported/qpdf/xpdf/CMap.h b/noncore/unsupported/qpdf/xpdf/CMap.h
index 8b29ef7..fe49acf 100644
--- a/noncore/unsupported/qpdf/xpdf/CMap.h
+++ b/noncore/unsupported/qpdf/xpdf/CMap.h
@@ -1,93 +1,93 @@
//========================================================================
//
// CMap.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef CMAP_H
#define CMAP_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
#include "CharTypes.h"
class GString;
struct CMapVectorEntry;
class CMapCache;
//------------------------------------------------------------------------
class CMap {
public:
// Create the CMap specified by <collection> and <cMapName>. Sets
// the initial reference count to 1. Returns NULL on failure.
static CMap *parse(CMapCache *cache, GString *collectionA,
GString *cMapNameA);
~CMap();
void incRefCnt();
void decRefCnt();
// Return collection name (<registry>-<ordering>).
GString *getCollection() { return collection; }
// Return true if this CMap matches the specified <collectionA>, and
// <cMapNameA>.
GBool match(GString *collectionA, GString *cMapNameA);
// Return the CID corresponding to the character code starting at
// <s>, which contains <len> bytes. Sets *<nUsed> to the number of
// bytes used by the char code.
CID getCID(char *s, int len, int *nUsed);
// Return the writing mode (0=horizontal, 1=vertical).
int getWMode() { return wMode; }
private:
CMap(GString *collectionA, GString *cMapNameA);
CMap(GString *collectionA, GString *cMapNameA, int wModeA);
void useCMap(CMapCache *cache, char *useName);
void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src);
void addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
Guint nBytes);
void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID);
void freeCMapVector(CMapVectorEntry *vec);
GString *collection;
GString *cMapName;
int wMode; // writing mode (0=horizontal, 1=vertical)
CMapVectorEntry *vector; // vector for first byte (NULL for
// identity CMap)
int refCnt;
};
//------------------------------------------------------------------------
#define cMapCacheSize 4
class CMapCache {
public:
CMapCache();
~CMapCache();
// Get the <cMapName> CMap for the specified character collection.
// Increments its reference count; there will be one reference for
// the cache plus one for the caller of this function. Returns NULL
// on failure.
CMap *getCMap(GString *collection, GString *cMapName);
private:
CMap *cache[cMapCacheSize];
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Catalog.cc b/noncore/unsupported/qpdf/xpdf/Catalog.cc
index 6a0c2d5..1212e2e 100644
--- a/noncore/unsupported/qpdf/xpdf/Catalog.cc
+++ b/noncore/unsupported/qpdf/xpdf/Catalog.cc
@@ -1,341 +1,341 @@
//========================================================================
//
// Catalog.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include "gmem.h"
#include "Object.h"
#include "XRef.h"
#include "Array.h"
#include "Dict.h"
#include "Page.h"
#include "Error.h"
#include "Link.h"
#include "Catalog.h"
//------------------------------------------------------------------------
// Catalog
//------------------------------------------------------------------------
Catalog::Catalog(XRef *xrefA, GBool printCommands) {
Object catDict, pagesDict;
Object obj, obj2;
int numPages0;
int i;
ok = gTrue;
xref = xrefA;
pages = NULL;
pageRefs = NULL;
numPages = pagesSize = 0;
baseURI = NULL;
xref->getCatalog(&catDict);
if (!catDict.isDict()) {
error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
goto err1;
}
// read page tree
catDict.dictLookup("Pages", &pagesDict);
// This should really be isDict("Pages"), but I've seen at least one
// PDF file where the /Type entry is missing.
if (!pagesDict.isDict()) {
error(-1, "Top-level pages object is wrong type (%s)",
pagesDict.getTypeName());
goto err2;
}
pagesDict.dictLookup("Count", &obj);
if (!obj.isInt()) {
error(-1, "Page count in top-level pages object is wrong type (%s)",
obj.getTypeName());
goto err3;
}
pagesSize = numPages0 = obj.getInt();
obj.free();
pages = (Page **)gmalloc(pagesSize * sizeof(Page *));
pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref));
for (i = 0; i < pagesSize; ++i) {
pages[i] = NULL;
pageRefs[i].num = -1;
pageRefs[i].gen = -1;
}
numPages = readPageTree(pagesDict.getDict(), NULL, 0, printCommands);
if (numPages != numPages0) {
error(-1, "Page count in top-level pages object is incorrect");
}
pagesDict.free();
// read named destination dictionary
catDict.dictLookup("Dests", &dests);
// read root of named destination tree
if (catDict.dictLookup("Names", &obj)->isDict())
obj.dictLookup("Dests", &nameTree);
else
nameTree.initNull();
obj.free();
// read base URI
if (catDict.dictLookup("URI", &obj)->isDict()) {
if (obj.dictLookup("Base", &obj2)->isString()) {
baseURI = obj2.getString()->copy();
}
obj2.free();
}
obj.free();
// get the metadata stream
catDict.dictLookup("Metadata", &metadata);
// get the structure tree root
catDict.dictLookup("StructTreeRoot", &structTreeRoot);
catDict.free();
return;
err3:
obj.free();
err2:
pagesDict.free();
err1:
catDict.free();
dests.initNull();
nameTree.initNull();
ok = gFalse;
}
Catalog::~Catalog() {
int i;
if (pages) {
for (i = 0; i < pagesSize; ++i) {
if (pages[i]) {
delete pages[i];
}
}
gfree(pages);
gfree(pageRefs);
}
dests.free();
nameTree.free();
if (baseURI) {
delete baseURI;
}
metadata.free();
structTreeRoot.free();
}
GString *Catalog::readMetadata() {
GString *s;
Dict *dict;
Object obj;
int c;
if (!metadata.isStream()) {
return NULL;
}
dict = metadata.streamGetDict();
if (!dict->lookup("Subtype", &obj)->isName("XML")) {
- error(-1, "Unknown Metadata type: '%s'\n",
+ error(-1, "Unknown Metadata type: '%s'",
obj.isName() ? obj.getName() : "???");
}
obj.free();
s = new GString();
metadata.streamReset();
while ((c = metadata.streamGetChar()) != EOF) {
s->append(c);
}
metadata.streamClose();
return s;
}
int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
GBool printCommands) {
Object kids;
Object kid;
Object kidRef;
PageAttrs *attrs1, *attrs2;
Page *page;
int i, j;
attrs1 = new PageAttrs(attrs, pagesDict);
pagesDict->lookup("Kids", &kids);
if (!kids.isArray()) {
error(-1, "Kids object (page %d) is wrong type (%s)",
start+1, kids.getTypeName());
goto err1;
}
for (i = 0; i < kids.arrayGetLength(); ++i) {
kids.arrayGet(i, &kid);
if (kid.isDict("Page")) {
attrs2 = new PageAttrs(attrs1, kid.getDict());
page = new Page(xref, start+1, kid.getDict(), attrs2, printCommands);
if (!page->isOk()) {
++start;
goto err3;
}
if (start >= pagesSize) {
pagesSize += 32;
pages = (Page **)grealloc(pages, pagesSize * sizeof(Page *));
pageRefs = (Ref *)grealloc(pageRefs, pagesSize * sizeof(Ref));
for (j = pagesSize - 32; j < pagesSize; ++j) {
pages[j] = NULL;
pageRefs[j].num = -1;
pageRefs[j].gen = -1;
}
}
pages[start] = page;
kids.arrayGetNF(i, &kidRef);
if (kidRef.isRef()) {
pageRefs[start].num = kidRef.getRefNum();
pageRefs[start].gen = kidRef.getRefGen();
}
kidRef.free();
++start;
// This should really be isDict("Pages"), but I've seen at least one
// PDF file where the /Type entry is missing.
} else if (kid.isDict()) {
if ((start = readPageTree(kid.getDict(), attrs1, start, printCommands))
< 0)
goto err2;
} else {
error(-1, "Kid object (page %d) is wrong type (%s)",
start+1, kid.getTypeName());
goto err2;
}
kid.free();
}
delete attrs1;
kids.free();
return start;
err3:
delete page;
err2:
kid.free();
err1:
kids.free();
delete attrs1;
ok = gFalse;
return -1;
}
int Catalog::findPage(int num, int gen) {
int i;
for (i = 0; i < numPages; ++i) {
if (pageRefs[i].num == num && pageRefs[i].gen == gen)
return i + 1;
}
return 0;
}
LinkDest *Catalog::findDest(GString *name) {
LinkDest *dest;
Object obj1, obj2;
GBool found;
// try named destination dictionary then name tree
found = gFalse;
if (dests.isDict()) {
if (!dests.dictLookup(name->getCString(), &obj1)->isNull())
found = gTrue;
else
obj1.free();
}
if (!found && nameTree.isDict()) {
if (!findDestInTree(&nameTree, name, &obj1)->isNull())
found = gTrue;
else
obj1.free();
}
if (!found)
return NULL;
// construct LinkDest
dest = NULL;
if (obj1.isArray()) {
- dest = new LinkDest(obj1.getArray(), gTrue);
+ dest = new LinkDest(obj1.getArray());
} else if (obj1.isDict()) {
if (obj1.dictLookup("D", &obj2)->isArray())
- dest = new LinkDest(obj2.getArray(), gTrue);
+ dest = new LinkDest(obj2.getArray());
else
error(-1, "Bad named destination value");
obj2.free();
} else {
error(-1, "Bad named destination value");
}
obj1.free();
return dest;
}
Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) {
Object names, name1;
Object kids, kid, limits, low, high;
GBool done, found;
int cmp, i;
// leaf node
if (tree->dictLookup("Names", &names)->isArray()) {
done = found = gFalse;
for (i = 0; !done && i < names.arrayGetLength(); i += 2) {
if (names.arrayGet(i, &name1)->isString()) {
cmp = name->cmp(name1.getString());
if (cmp == 0) {
names.arrayGet(i+1, obj);
found = gTrue;
done = gTrue;
} else if (cmp < 0) {
done = gTrue;
}
name1.free();
}
}
names.free();
if (!found)
obj->initNull();
return obj;
}
names.free();
// root or intermediate node
done = gFalse;
if (tree->dictLookup("Kids", &kids)->isArray()) {
for (i = 0; !done && i < kids.arrayGetLength(); ++i) {
if (kids.arrayGet(i, &kid)->isDict()) {
if (kid.dictLookup("Limits", &limits)->isArray()) {
if (limits.arrayGet(0, &low)->isString() &&
name->cmp(low.getString()) >= 0) {
if (limits.arrayGet(1, &high)->isString() &&
name->cmp(high.getString()) <= 0) {
findDestInTree(&kid, name, obj);
done = gTrue;
}
high.free();
}
low.free();
}
limits.free();
}
kid.free();
}
}
kids.free();
// name was outside of ranges of all kids
if (!done)
obj->initNull();
return obj;
}
diff --git a/noncore/unsupported/qpdf/xpdf/Catalog.h b/noncore/unsupported/qpdf/xpdf/Catalog.h
index 197f5b8..afad803 100644
--- a/noncore/unsupported/qpdf/xpdf/Catalog.h
+++ b/noncore/unsupported/qpdf/xpdf/Catalog.h
@@ -1,85 +1,85 @@
//========================================================================
//
// Catalog.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef CATALOG_H
#define CATALOG_H
#ifdef __GNUC__
#pragma interface
#endif
class XRef;
class Object;
class Page;
class PageAttrs;
struct Ref;
class LinkDest;
//------------------------------------------------------------------------
// Catalog
//------------------------------------------------------------------------
class Catalog {
public:
// Constructor.
Catalog(XRef *xrefA, GBool printCommands = gFalse);
// Destructor.
~Catalog();
// Is catalog valid?
GBool isOk() { return ok; }
// Get number of pages.
int getNumPages() { return numPages; }
// Get a page.
Page *getPage(int i) { return pages[i-1]; }
// Get the reference for a page object.
Ref *getPageRef(int i) { return &pageRefs[i-1]; }
// Return base URI, or NULL if none.
GString *getBaseURI() { return baseURI; }
// Return the contents of the metadata stream, or NULL if there is
// no metadata.
GString *readMetadata();
// Return the structure tree root object.
Object *getStructTreeRoot() { return &structTreeRoot; }
// Find a page, given its object ID. Returns page number, or 0 if
// not found.
int findPage(int num, int gen);
// Find a named destination. Returns the link destination, or
// NULL if <name> is not a destination.
LinkDest *findDest(GString *name);
private:
XRef *xref; // the xref table for this PDF file
Page **pages; // array of pages
Ref *pageRefs; // object ID for each page
int numPages; // number of pages
int pagesSize; // size of pages array
Object dests; // named destination dictionary
Object nameTree; // name tree
GString *baseURI; // base URI for URI-type links
Object metadata; // metadata stream
Object structTreeRoot; // structure tree root dictionary
GBool ok; // true if catalog is valid
int readPageTree(Dict *pages, PageAttrs *attrs, int start,
GBool printCommands);
Object *findDestInTree(Object *tree, GString *name, Object *obj);
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc b/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc
index 6793398..912981e 100644
--- a/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc
+++ b/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.cc
@@ -1,360 +1,356 @@
//========================================================================
//
// CharCodeToUnicode.cc
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <string.h>
#include "gmem.h"
#include "gfile.h"
#include "GString.h"
#include "Error.h"
#include "GlobalParams.h"
+#include "PSTokenizer.h"
#include "CharCodeToUnicode.h"
//------------------------------------------------------------------------
#define maxUnicodeString 8
struct CharCodeToUnicodeString {
CharCode c;
Unicode u[maxUnicodeString];
int len;
};
//------------------------------------------------------------------------
+static int getCharFromString(void *data) {
+ char *p;
+ int c;
+
+ p = *(char **)data;
+ if (*p) {
+ c = *p++;
+ *(char **)data = p;
+ } else {
+ c = EOF;
+ }
+ return c;
+}
+
+static int getCharFromFile(void *data) {
+ return fgetc((FILE *)data);
+}
+
+//------------------------------------------------------------------------
+
CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *collectionA) {
FILE *f;
Unicode *mapA;
CharCode size, mapLenA;
char buf[64];
Unicode u;
CharCodeToUnicode *ctu;
if (!(f = globalParams->getCIDToUnicodeFile(collectionA))) {
error(-1, "Couldn't find cidToUnicode file for the '%s' collection",
collectionA->getCString());
return NULL;
}
size = 32768;
mapA = (Unicode *)gmalloc(size * sizeof(Unicode));
mapLenA = 0;
while (getLine(buf, sizeof(buf), f)) {
if (mapLenA == size) {
size *= 2;
mapA = (Unicode *)grealloc(mapA, size * sizeof(Unicode));
}
if (sscanf(buf, "%x", &u) == 1) {
mapA[mapLenA] = u;
} else {
error(-1, "Bad line (%d) in cidToUnicode file for the '%s' collection",
(int)(mapLenA + 1), collectionA->getCString());
mapA[mapLenA] = 0;
}
++mapLenA;
}
ctu = new CharCodeToUnicode(collectionA->copy(), mapA, mapLenA, gTrue,
NULL, 0);
gfree(mapA);
return ctu;
}
CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) {
return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0);
}
-static char *getLineFromString(char *buf, int size, char **s) {
- char c;
- int i;
-
- i = 0;
- while (i < size - 1 && **s) {
- buf[i++] = c = *(*s)++;
- if (c == '\x0a') {
- break;
- }
- if (c == '\x0d') {
- if (**s == '\x0a' && i < size - 1) {
- buf[i++] = '\x0a';
- ++*s;
- }
- break;
- }
- }
- buf[i] = '\0';
- if (i == 0) {
- return NULL;
- }
- return buf;
-}
-
CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) {
CharCodeToUnicode *ctu;
char *p;
ctu = new CharCodeToUnicode(NULL);
p = buf->getCString();
- ctu->parseCMap1((char *(*)(char *, int, void *))&getLineFromString,
- &p, nBits);
+ ctu->parseCMap1(&getCharFromString, &p, nBits);
return ctu;
}
-void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *),
- void *data, int nBits) {
- char buf[256];
- GBool inBFChar, inBFRange;
- char *tok1, *tok2, *tok3;
+void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
+ int nBits) {
+ PSTokenizer *pst;
+ char tok1[256], tok2[256], tok3[256];
int nDigits, n1, n2, n3;
CharCode oldLen, i;
CharCode code1, code2;
Unicode u;
char uHex[5];
int j;
GString *name;
FILE *f;
nDigits = nBits / 4;
- inBFChar = inBFRange = gFalse;
- while ((*getLineFunc)(buf, sizeof(buf), data)) {
- tok1 = strtok(buf, " \t\r\n");
- if (!tok1 || tok1[0] == '%') {
- continue;
- }
- tok2 = strtok(NULL, " \t\r\n");
- tok3 = strtok(NULL, " \t\r\n");
- if (inBFChar) {
- if (!strcmp(tok1, "endbfchar")) {
- inBFChar = gFalse;
- } else if (tok2) {
- n1 = strlen(tok1);
- n2 = strlen(tok2);
+ pst = new PSTokenizer(getCharFunc, data);
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ while (pst->getToken(tok2, sizeof(tok2), &n2)) {
+ if (!strcmp(tok2, "usecmap")) {
+ if (tok1[0] == '/') {
+ name = new GString(tok1 + 1);
+ if ((f = globalParams->findToUnicodeFile(name))) {
+ parseCMap1(&getCharFromFile, f, nBits);
+ fclose(f);
+ } else {
+ error(-1, "Couldn't find ToUnicode CMap file for '%s'",
+ name->getCString());
+ }
+ delete name;
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "beginbfchar")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endbfchar")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endbfchar")) {
+ error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
+ break;
+ }
if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
tok2[0] == '<' && tok2[n2 - 1] == '>')) {
- error(-1, "Illegal line in bfchar block in ToUnicode CMap");
+ error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
continue;
}
tok1[n1 - 1] = tok2[n2 - 1] = '\0';
if (sscanf(tok1 + 1, "%x", &code1) != 1) {
- error(-1, "Illegal line in bfchar block in ToUnicode CMap");
+ error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
continue;
}
if (code1 >= mapLen) {
oldLen = mapLen;
mapLen = (code1 + 256) & ~255;
map = (Unicode *)grealloc(map, mapLen * sizeof(Unicode));
for (i = oldLen; i < mapLen; ++i) {
map[i] = 0;
}
}
if (n2 == 6) {
if (sscanf(tok2 + 1, "%x", &u) != 1) {
- error(-1, "Illegal line in bfchar block in ToUnicode CMap");
+ error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
continue;
}
map[code1] = u;
} else {
map[code1] = 0;
if (sMapLen == sMapSize) {
sMapSize += 8;
sMap = (CharCodeToUnicodeString *)
grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
}
sMap[sMapLen].c = code1;
sMap[sMapLen].len = (n2 - 2) / 4;
for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
strncpy(uHex, tok2 + 1 + j*4, 4);
uHex[4] = '\0';
if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
- error(-1, "Illegal line in bfchar block in ToUnicode CMap");
+ error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
}
}
++sMapLen;
}
- } else {
- error(-1, "Illegal bfchar block in ToUnicode CMap");
}
- } else if (inBFRange) {
- if (!strcmp(tok1, "endbfrange")) {
- inBFRange = gFalse;
- } else if (tok2 && tok3) {
- n1 = strlen(tok1);
- n2 = strlen(tok2);
- n3 = strlen(tok3);
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "beginbfrange")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endbfrange")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endbfrange") ||
+ !pst->getToken(tok3, sizeof(tok3), &n3) ||
+ !strcmp(tok3, "endbfrange")) {
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ break;
+ }
if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>' &&
tok3[0] == '<' && tok3[n3 - 1] == '>')) {
- error(-1, "Illegal line in bfrange block in ToUnicode CMap");
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
continue;
}
tok1[n1 - 1] = tok2[n2 - 1] = tok3[n3 - 1] = '\0';
if (sscanf(tok1 + 1, "%x", &code1) != 1 ||
sscanf(tok2 + 1, "%x", &code2) != 1) {
- error(-1, "Illegal line in bfrange block in ToUnicode CMap");
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
continue;
}
if (code2 >= mapLen) {
oldLen = mapLen;
mapLen = (code2 + 256) & ~255;
map = (Unicode *)grealloc(map, mapLen * sizeof(Unicode));
for (i = oldLen; i < mapLen; ++i) {
map[i] = 0;
}
}
if (n3 == 6) {
if (sscanf(tok3 + 1, "%x", &u) != 1) {
- error(-1, "Illegal line in bfrange block in ToUnicode CMap");
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
continue;
}
for (; code1 <= code2; ++code1) {
map[code1] = u++;
}
} else {
if (sMapLen + (int)(code2 - code1 + 1) > sMapSize) {
sMapSize = (sMapSize + (code2 - code1 + 1) + 7) & ~7;
sMap = (CharCodeToUnicodeString *)
grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
}
for (i = 0; code1 <= code2; ++code1, ++i) {
map[code1] = 0;
sMap[sMapLen].c = code1;
sMap[sMapLen].len = (n3 - 2) / 4;
for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
strncpy(uHex, tok3 + 1 + j*4, 4);
uHex[4] = '\0';
if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
- error(-1, "Illegal line in bfrange block in ToUnicode CMap");
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
}
}
sMap[sMapLen].u[sMap[sMapLen].len - 1] += i;
++sMapLen;
}
}
- } else {
- error(-1, "Illegal bfrange block in ToUnicode CMap");
}
- } else if (tok2 && !strcmp(tok2, "usecmap")) {
- if (tok1[0] == '/') {
- name = new GString(tok1 + 1);
- if ((f = globalParams->findToUnicodeFile(name))) {
- parseCMap1((char *(*)(char *, int, void *))&getLine, f, nBits);
- fclose(f);
- } else {
- error(-1, "Couldn't find ToUnicode CMap file for '%s'",
- name->getCString());
- }
- delete name;
- }
- } else if (tok2 && !strcmp(tok2, "beginbfchar")) {
- inBFChar = gTrue;
- } else if (tok2 && !strcmp(tok2, "beginbfrange")) {
- inBFRange = gTrue;
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else {
+ strcpy(tok1, tok2);
}
}
+ delete pst;
}
CharCodeToUnicode::CharCodeToUnicode(GString *collectionA) {
CharCode i;
collection = collectionA;
mapLen = 256;
map = (Unicode *)gmalloc(mapLen * sizeof(Unicode));
for (i = 0; i < mapLen; ++i) {
map[i] = 0;
}
sMap = NULL;
sMapLen = sMapSize = 0;
refCnt = 1;
}
CharCodeToUnicode::CharCodeToUnicode(GString *collectionA, Unicode *mapA,
CharCode mapLenA, GBool copyMap,
CharCodeToUnicodeString *sMapA,
int sMapLenA) {
collection = collectionA;
mapLen = mapLenA;
if (copyMap) {
map = (Unicode *)gmalloc(mapLen * sizeof(Unicode));
memcpy(map, mapA, mapLen * sizeof(Unicode));
} else {
map = mapA;
}
sMap = sMapA;
sMapLen = sMapSize = sMapLenA;
refCnt = 1;
}
CharCodeToUnicode::~CharCodeToUnicode() {
if (collection) {
delete collection;
}
gfree(map);
if (sMap) {
gfree(sMap);
}
}
void CharCodeToUnicode::incRefCnt() {
++refCnt;
}
void CharCodeToUnicode::decRefCnt() {
if (--refCnt == 0) {
delete this;
}
}
GBool CharCodeToUnicode::match(GString *collectionA) {
return collection && !collection->cmp(collectionA);
}
int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) {
int i, j;
if (c >= mapLen) {
return 0;
}
if (map[c]) {
u[0] = map[c];
return 1;
}
for (i = 0; i < sMapLen; ++i) {
if (sMap[i].c == c) {
for (j = 0; j < sMap[i].len && j < size; ++j) {
u[j] = sMap[i].u[j];
}
return j;
}
}
return 0;
}
//------------------------------------------------------------------------
CIDToUnicodeCache::CIDToUnicodeCache() {
int i;
for (i = 0; i < cidToUnicodeCacheSize; ++i) {
cache[i] = NULL;
}
}
CIDToUnicodeCache::~CIDToUnicodeCache() {
int i;
for (i = 0; i < cidToUnicodeCacheSize; ++i) {
if (cache[i]) {
cache[i]->decRefCnt();
}
}
diff --git a/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h b/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h
index c811d72..06916c8 100644
--- a/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h
+++ b/noncore/unsupported/qpdf/xpdf/CharCodeToUnicode.h
@@ -1,89 +1,88 @@
//========================================================================
//
// CharCodeToUnicode.h
//
// Mapping from character codes to Unicode.
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef CHARCODETOUNICODE_H
#define CHARCODETOUNICODE_H
#ifdef __GNUC__
#pragma interface
#endif
#include "CharTypes.h"
struct CharCodeToUnicodeString;
//------------------------------------------------------------------------
class CharCodeToUnicode {
public:
// Create the CID-to-Unicode mapping specified by <collection>.
// This reads a .cidToUnicode file from disk. Sets the initial
// reference count to 1. Returns NULL on failure.
static CharCodeToUnicode *parseCIDToUnicode(GString *collectionA);
// Create the CharCode-to-Unicode mapping for an 8-bit font.
// <toUnicode> is an array of 256 Unicode indexes. Sets the initial
// reference count to 1.
static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode);
// Parse a ToUnicode CMap for an 8- or 16-bit font.
static CharCodeToUnicode *parseCMap(GString *buf, int nBits);
~CharCodeToUnicode();
void incRefCnt();
void decRefCnt();
// Return true if this mapping matches the specified <collectionA>.
GBool match(GString *collectionA);
// Map a CharCode to Unicode.
int mapToUnicode(CharCode c, Unicode *u, int size);
private:
- void parseCMap1(char *(*getLineFunc)(char *, int, void *),
- void *data, int nBits);
+ void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits);
CharCodeToUnicode(GString *collectionA);
CharCodeToUnicode(GString *collectionA, Unicode *mapA,
CharCode mapLenA, GBool copyMap,
CharCodeToUnicodeString *sMapA, int sMapLenA);
GString *collection;
Unicode *map;
CharCode mapLen;
CharCodeToUnicodeString *sMap;
int sMapLen, sMapSize;
int refCnt;
};
//------------------------------------------------------------------------
#define cidToUnicodeCacheSize 4
class CIDToUnicodeCache {
public:
CIDToUnicodeCache();
~CIDToUnicodeCache();
// Get the CharCodeToUnicode object for <collection>. Increments
// its reference count; there will be one reference for the cache
// plus one for the caller of this function. Returns NULL on
// failure.
CharCodeToUnicode *getCIDToUnicode(GString *collection);
private:
CharCodeToUnicode *cache[cidToUnicodeCacheSize];
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/CharTypes.h b/noncore/unsupported/qpdf/xpdf/CharTypes.h
index 8938be5..bae2f26 100644
--- a/noncore/unsupported/qpdf/xpdf/CharTypes.h
+++ b/noncore/unsupported/qpdf/xpdf/CharTypes.h
@@ -1,24 +1,24 @@
//========================================================================
//
// CharTypes.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef CHARTYPES_H
#define CHARTYPES_H
// Unicode character.
typedef unsigned int Unicode;
// Character ID for CID character collections.
typedef unsigned int CID;
// This is large enough to hold any of the following:
// - 8-bit char code
// - 16-bit CID
// - Unicode
typedef unsigned int CharCode;
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Decrypt.cc b/noncore/unsupported/qpdf/xpdf/Decrypt.cc
index 2def802..8de4091 100644
--- a/noncore/unsupported/qpdf/xpdf/Decrypt.cc
+++ b/noncore/unsupported/qpdf/xpdf/Decrypt.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// Decrypt.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include "gmem.h"
#include "Decrypt.h"
static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
static void md5(Guchar *msg, int msgLen, Guchar *digest);
static Guchar passwordPad[32] = {
0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
};
//------------------------------------------------------------------------
// Decrypt
//------------------------------------------------------------------------
Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
int i;
// construct object key
for (i = 0; i < keyLength; ++i) {
objKey[i] = fileKey[i];
}
objKey[keyLength] = objNum & 0xff;
objKey[keyLength + 1] = (objNum >> 8) & 0xff;
objKey[keyLength + 2] = (objNum >> 16) & 0xff;
objKey[keyLength + 3] = objGen & 0xff;
objKey[keyLength + 4] = (objGen >> 8) & 0xff;
md5(objKey, keyLength + 5, objKey);
// set up for decryption
x = y = 0;
if ((objKeyLength = keyLength + 5) > 16) {
objKeyLength = 16;
}
rc4InitKey(objKey, objKeyLength, state);
}
void Decrypt::reset() {
x = y = 0;
rc4InitKey(objKey, objKeyLength, state);
}
Guchar Decrypt::decryptByte(Guchar c) {
return rc4DecryptByte(state, &x, &y, c);
}
GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
GString *ownerKey, GString *userKey,
int permissions, GString *fileID,
GString *ownerPassword, GString *userPassword,
Guchar *fileKey, GBool *ownerPasswordOk) {
Guchar test[32];
GString *userPassword2;
Guchar fState[256];
Guchar fx, fy;
int len, i;
// try using the supplied owner password to generate the user password
if (ownerPassword) {
len = ownerPassword->getLength();
if (len < 32) {
memcpy(test, ownerPassword->getCString(), len);
memcpy(test + len, passwordPad, 32 - len);
} else {
memcpy(test, ownerPassword->getCString(), 32);
}
} else {
memcpy(test, passwordPad, 32);
}
md5(test, 32, test);
if (encRevision == 3) {
for (i = 0; i < 50; ++i) {
md5(test, 16, test);
}
}
rc4InitKey(test, keyLength, fState);
fx = fy = 0;
for (i = 0; i < 32; ++i) {
test[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
}
userPassword2 = new GString((char *)test, 32);
if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
permissions, fileID, userPassword2, fileKey)) {
*ownerPasswordOk = gTrue;
delete userPassword2;
diff --git a/noncore/unsupported/qpdf/xpdf/Decrypt.h b/noncore/unsupported/qpdf/xpdf/Decrypt.h
index 1bdb2b7..52afb2f 100644
--- a/noncore/unsupported/qpdf/xpdf/Decrypt.h
+++ b/noncore/unsupported/qpdf/xpdf/Decrypt.h
@@ -1,59 +1,59 @@
//========================================================================
//
// Decrypt.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef DECRYPT_H
#define DECRYPT_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
#include "GString.h"
//------------------------------------------------------------------------
// Decrypt
//------------------------------------------------------------------------
class Decrypt {
public:
// Initialize the decryptor object.
Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen);
// Reset decryption.
void reset();
// Decrypt one byte.
Guchar decryptByte(Guchar c);
// Generate a file key. The <fileKey> buffer must have space for at
// least 16 bytes. Checks <ownerPassword> and then <userPassword>
// and returns true if either is correct. Sets <ownerPasswordOk> if
// the owner password was correct. Either or both of the passwords
// may be NULL, which is treated as an empty string.
static GBool makeFileKey(int encVersion, int encRevision, int keyLength,
GString *ownerKey, GString *userKey,
int permissions, GString *fileID,
GString *ownerPassword, GString *userPassword,
Guchar *fileKey, GBool *ownerPasswordOk);
private:
static GBool makeFileKey2(int encVersion, int encRevision, int keyLength,
GString *ownerKey, GString *userKey,
int permissions, GString *fileID,
GString *userPassword, Guchar *fileKey);
int objKeyLength;
Guchar objKey[21];
Guchar state[256];
Guchar x, y;
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Dict.cc b/noncore/unsupported/qpdf/xpdf/Dict.cc
index 1a49ca5..5eb077e 100644
--- a/noncore/unsupported/qpdf/xpdf/Dict.cc
+++ b/noncore/unsupported/qpdf/xpdf/Dict.cc
@@ -1,90 +1,90 @@
//========================================================================
//
// Dict.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include <string.h>
#include "gmem.h"
#include "Object.h"
#include "XRef.h"
#include "Dict.h"
//------------------------------------------------------------------------
// Dict
//------------------------------------------------------------------------
Dict::Dict(XRef *xrefA) {
xref = xrefA;
entries = NULL;
size = length = 0;
ref = 1;
}
Dict::~Dict() {
int i;
for (i = 0; i < length; ++i) {
gfree(entries[i].key);
entries[i].val.free();
}
gfree(entries);
}
void Dict::add(char *key, Object *val) {
if (length + 1 > size) {
size += 8;
entries = (DictEntry *)grealloc(entries, size * sizeof(DictEntry));
}
entries[length].key = key;
entries[length].val = *val;
++length;
}
inline DictEntry *Dict::find(char *key) {
int i;
for (i = 0; i < length; ++i) {
if (!strcmp(key, entries[i].key))
return &entries[i];
}
return NULL;
}
GBool Dict::is(char *type) {
DictEntry *e;
return (e = find("Type")) && e->val.isName(type);
}
Object *Dict::lookup(char *key, Object *obj) {
DictEntry *e;
return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull();
}
Object *Dict::lookupNF(char *key, Object *obj) {
DictEntry *e;
return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
}
char *Dict::getKey(int i) {
return entries[i].key;
}
Object *Dict::getVal(int i, Object *obj) {
return entries[i].val.fetch(xref, obj);
}
Object *Dict::getValNF(int i, Object *obj) {
return entries[i].val.copy(obj);
}
diff --git a/noncore/unsupported/qpdf/xpdf/Dict.h b/noncore/unsupported/qpdf/xpdf/Dict.h
index c4f1ea5..b994514 100644
--- a/noncore/unsupported/qpdf/xpdf/Dict.h
+++ b/noncore/unsupported/qpdf/xpdf/Dict.h
@@ -1,75 +1,75 @@
//========================================================================
//
// Dict.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef DICT_H
#define DICT_H
#ifdef __GNUC__
#pragma interface
#endif
#include "Object.h"
//------------------------------------------------------------------------
// Dict
//------------------------------------------------------------------------
struct DictEntry {
char *key;
Object val;
};
class Dict {
public:
// Constructor.
Dict(XRef *xrefA);
// Destructor.
~Dict();
// Reference counting.
int incRef() { return ++ref; }
int decRef() { return --ref; }
// Get number of entries.
int getLength() { return length; }
// Add an entry. NB: does not copy key.
void add(char *key, Object *val);
// Check if dictionary is of specified type.
GBool is(char *type);
// Look up an entry and return the value. Returns a null object
// if <key> is not in the dictionary.
Object *lookup(char *key, Object *obj);
Object *lookupNF(char *key, Object *obj);
// Iterative accessors.
char *getKey(int i);
Object *getVal(int i, Object *obj);
Object *getValNF(int i, Object *obj);
// Set the xref pointer. This is only used in one special case: the
// trailer dictionary, which is read before the xref table is
// parsed.
void setXRef(XRef *xrefA) { xref = xrefA; }
private:
XRef *xref; // the xref table for this PDF file
DictEntry *entries; // array of entries
int size; // size of <entries> array
int length; // number of entries in dictionary
int ref; // reference count
DictEntry *find(char *key);
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/DisplayFontTable.h b/noncore/unsupported/qpdf/xpdf/DisplayFontTable.h
index 048e25d..8e73486 100644
--- a/noncore/unsupported/qpdf/xpdf/DisplayFontTable.h
+++ b/noncore/unsupported/qpdf/xpdf/DisplayFontTable.h
@@ -1,31 +1,31 @@
//========================================================================
//
// DisplayFontTable.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
static struct {
char *name;
char *xlfd;
char *encoding;
} displayFontTab[] = {
-#if _NO_USE_FOR_QPE
+#if 0
{"Courier", "-*-courier-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Courier-Bold", "-*-courier-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Courier-BoldOblique", "-*-courier-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Courier-Oblique", "-*-courier-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Helvetica", "-*-helvetica-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Helvetica-Bold", "-*-helvetica-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Helvetica-BoldOblique", "-*-helvetica-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Helvetica-Oblique", "-*-helvetica-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Symbol", "-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", "Symbol"},
{"Times-Bold", "-*-times-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Times-BoldItalic", "-*-times-bold-i-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Times-Italic", "-*-times-medium-i-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"Times-Roman", "-*-times-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
{"ZapfDingbats", "-*-zapfdingbats-medium-r-normal-*-%s-*-*-*-*-*-*-*", "ZapfDingbats"},
#endif
- {NULL}
+ {NULL,0,0}
};
diff --git a/noncore/unsupported/qpdf/xpdf/Error.cc b/noncore/unsupported/qpdf/xpdf/Error.cc
index 8763846..3eae5c9 100644
--- a/noncore/unsupported/qpdf/xpdf/Error.cc
+++ b/noncore/unsupported/qpdf/xpdf/Error.cc
@@ -1,37 +1,37 @@
//========================================================================
//
// Error.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include "GlobalParams.h"
#include "Error.h"
void CDECL error(int pos, char *msg, ...) {
va_list args;
// NB: this can be called before the globalParams object is created
if (globalParams && globalParams->getErrQuiet()) {
return;
}
if (pos >= 0) {
fprintf(stderr, "Error (%d): ", pos);
} else {
fprintf(stderr, "Error: ");
}
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
fprintf(stderr, "\n");
fflush(stderr);
}
diff --git a/noncore/unsupported/qpdf/xpdf/Error.h b/noncore/unsupported/qpdf/xpdf/Error.h
index 151e961..77801c5 100644
--- a/noncore/unsupported/qpdf/xpdf/Error.h
+++ b/noncore/unsupported/qpdf/xpdf/Error.h
@@ -1,21 +1,21 @@
//========================================================================
//
// Error.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef ERROR_H
#define ERROR_H
#ifdef __GNUC__
#pragma interface
#endif
#include <stdio.h>
#include "config.h"
extern void CDECL error(int pos, char *msg, ...);
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/ErrorCodes.h b/noncore/unsupported/qpdf/xpdf/ErrorCodes.h
new file mode 100644
index 0000000..4e0d38a
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/ErrorCodes.h
@@ -0,0 +1,24 @@
+//========================================================================
+//
+// ErrorCodes.h
+//
+// Copyright 2002 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef ERRORCODES_H
+#define ERRORCODES_H
+
+#define errNone 0 // no error
+
+#define errOpenFile 1 // couldn't open the PDF file
+
+#define errBadCatalog 2 // couldn't read the page catalog
+
+#define errDamaged 3 // PDF file was damaged and couldn't be
+ // repaired
+
+#define errEncrypted 4 // file was encrypted and password was
+ // incorrect or not supplied
+
+#endif
diff --git a/noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc b/noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc
index 12a1a27..bd5f9cf 100644
--- a/noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc
+++ b/noncore/unsupported/qpdf/xpdf/FontEncodingTables.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// FontEncodingTables.cc
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#include <aconf.h>
#include <stdlib.h>
#include "FontEncodingTables.h"
char *macRomanEncoding[256] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"space",
"exclam",
"quotedbl",
"numbersign",
"dollar",
"percent",
"ampersand",
"quotesingle",
"parenleft",
"parenright",
"asterisk",
"plus",
"comma",
"hyphen",
"period",
"slash",
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"colon",
"semicolon",
"less",
"equal",
"greater",
"question",
"at",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
diff --git a/noncore/unsupported/qpdf/xpdf/FontEncodingTables.h b/noncore/unsupported/qpdf/xpdf/FontEncodingTables.h
index 4646a43..deee0a8 100644
--- a/noncore/unsupported/qpdf/xpdf/FontEncodingTables.h
+++ b/noncore/unsupported/qpdf/xpdf/FontEncodingTables.h
@@ -1,20 +1,20 @@
//========================================================================
//
// FontEncodingTables.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef FONTENCODINGTABLES_H
#define FONTENCODINGTABLES_H
extern char *macRomanEncoding[];
extern char *macExpertEncoding[];
extern char *winAnsiEncoding[];
extern char *standardEncoding[];
extern char *expertEncoding[];
extern char *symbolEncoding[];
extern char *zapfDingbatsEncoding[];
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Function.cc b/noncore/unsupported/qpdf/xpdf/Function.cc
index 815cc89..ebf3718 100644
--- a/noncore/unsupported/qpdf/xpdf/Function.cc
+++ b/noncore/unsupported/qpdf/xpdf/Function.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// Function.cc
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "gmem.h"
#include "Object.h"
#include "Dict.h"
#include "Stream.h"
#include "Error.h"
#include "Function.h"
//------------------------------------------------------------------------
// Function
//------------------------------------------------------------------------
Function::Function() {
}
Function::~Function() {
}
Function *Function::parse(Object *funcObj) {
Function *func;
Dict *dict;
int funcType;
Object obj1;
if (funcObj->isStream()) {
dict = funcObj->streamGetDict();
} else if (funcObj->isDict()) {
dict = funcObj->getDict();
} else if (funcObj->isName("Identity")) {
return new IdentityFunction();
} else {
error(-1, "Expected function dictionary or stream");
return NULL;
}
if (!dict->lookup("FunctionType", &obj1)->isInt()) {
error(-1, "Function type is missing or wrong type");
obj1.free();
return NULL;
}
funcType = obj1.getInt();
obj1.free();
if (funcType == 0) {
func = new SampledFunction(funcObj, dict);
} else if (funcType == 2) {
func = new ExponentialFunction(funcObj, dict);
} else if (funcType == 3) {
func = new StitchingFunction(funcObj, dict);
} else if (funcType == 4) {
func = new PostScriptFunction(funcObj, dict);
} else {
error(-1, "Unimplemented function type (%d)", funcType);
return NULL;
}
if (!func->isOk()) {
delete func;
return NULL;
}
return func;
}
GBool Function::init(Dict *dict) {
Object obj1, obj2;
int i;
//----- Domain
if (!dict->lookup("Domain", &obj1)->isArray()) {
error(-1, "Function is missing domain");
goto err2;
}
m = obj1.arrayGetLength() / 2;
if (m > funcMaxInputs) {
error(-1, "Functions with more than %d inputs are unsupported",
funcMaxInputs);
goto err2;
}
for (i = 0; i < m; ++i) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function domain array");
goto err1;
}
domain[i][0] = obj2.getNum();
@@ -322,257 +322,266 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
samples[i] = (fouble)s * sampleMul;
}
str->close();
ok = gTrue;
return;
err3:
obj2.free();
err2:
obj1.free();
err1:
return;
}
SampledFunction::~SampledFunction() {
if (samples) {
gfree(samples);
}
}
SampledFunction::SampledFunction(SampledFunction *func) {
int nSamples, i;
memcpy(this, func, sizeof(SampledFunction));
nSamples = n;
for (i = 0; i < m; ++i) {
nSamples *= sampleSize[i];
}
samples = (fouble *)gmalloc(nSamples * sizeof(fouble));
memcpy(samples, func->samples, nSamples * sizeof(fouble));
}
void SampledFunction::transform(fouble *in, fouble *out) {
fouble x;
int e[2][funcMaxInputs];
fouble efrac[funcMaxInputs];
fouble s0[1 << funcMaxInputs], s1[1 << funcMaxInputs];
int i, j, k, idx;
// map input values into sample array
for (i = 0; i < m; ++i) {
x = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
(encode[i][1] - encode[i][0]) + encode[i][0];
if (x < 0) {
x = 0;
} else if (x > sampleSize[i] - 1) {
x = sampleSize[i] - 1;
}
e[0][i] = (int)floor(x);
e[1][i] = (int)ceil(x);
efrac[i] = x - e[0][i];
}
// for each output, do m-linear interpolation
for (i = 0; i < n; ++i) {
// pull 2^m values out of the sample array
for (j = 0; j < (1<<m); ++j) {
idx = e[j & 1][m - 1];
for (k = m - 2; k >= 0; --k) {
idx = idx * sampleSize[k] + e[(j >> k) & 1][k];
}
idx = idx * n + i;
s0[j] = samples[idx];
}
// do m sets of interpolations
for (j = 0; j < m; ++j) {
for (k = 0; k < (1 << (m - j)); k += 2) {
s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1];
}
memcpy(s0, s1, (1 << (m - j - 1)) * sizeof(fouble));
}
// map output value to range
out[i] = s0[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
if (out[i] < range[i][0]) {
out[i] = range[i][0];
} else if (out[i] > range[i][1]) {
out[i] = range[i][1];
}
}
}
//------------------------------------------------------------------------
// ExponentialFunction
//------------------------------------------------------------------------
ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
Object obj1, obj2;
GBool hasN;
int i;
ok = gFalse;
- hasN = gFalse;
//----- initialize the generic stuff
if (!init(dict)) {
goto err1;
}
if (m != 1) {
error(-1, "Exponential function with more than one input");
goto err1;
}
+ hasN = hasRange;
//----- default values
for (i = 0; i < funcMaxOutputs; ++i) {
c0[i] = 0;
c1[i] = 1;
}
//----- C0
if (dict->lookup("C0", &obj1)->isArray()) {
if (!hasN) {
n = obj1.arrayGetLength();
+ hasN = gTrue;
} else if (obj1.arrayGetLength() != n) {
error(-1, "Function's C0 array is wrong length");
goto err2;
}
for (i = 0; i < n; ++i) {
obj1.arrayGet(i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function C0 array");
goto err3;
}
c0[i] = obj2.getNum();
obj2.free();
}
}
obj1.free();
//----- C1
if (dict->lookup("C1", &obj1)->isArray()) {
if (!hasN) {
n = obj1.arrayGetLength();
+ hasN = gTrue;
} else if (obj1.arrayGetLength() != n) {
error(-1, "Function's C1 array is wrong length");
goto err2;
}
for (i = 0; i < n; ++i) {
obj1.arrayGet(i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function C1 array");
goto err3;
}
c1[i] = obj2.getNum();
obj2.free();
}
}
obj1.free();
//----- N (exponent)
if (!dict->lookup("N", &obj1)->isNum()) {
error(-1, "Function has missing or invalid N");
goto err2;
}
e = obj1.getNum();
obj1.free();
+ // this isn't supposed to happen, but I've run into (broken) PDF
+ // files where it does
+ if (!hasN) {
+ error(-1, "Exponential function does not define number of output values");
+ n = 1;
+ }
+
ok = gTrue;
return;
err3:
obj2.free();
err2:
obj1.free();
err1:
return;
}
ExponentialFunction::~ExponentialFunction() {
}
ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
memcpy(this, func, sizeof(ExponentialFunction));
}
void ExponentialFunction::transform(fouble *in, fouble *out) {
fouble x;
int i;
if (in[0] < domain[0][0]) {
x = domain[0][0];
} else if (in[0] > domain[0][1]) {
x = domain[0][1];
} else {
x = in[0];
}
for (i = 0; i < n; ++i) {
out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
if (hasRange) {
if (out[i] < range[i][0]) {
out[i] = range[i][0];
} else if (out[i] > range[i][1]) {
out[i] = range[i][1];
}
}
}
return;
}
//------------------------------------------------------------------------
// StitchingFunction
//------------------------------------------------------------------------
StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
Object obj1, obj2;
int i;
ok = gFalse;
funcs = NULL;
bounds = NULL;
encode = NULL;
//----- initialize the generic stuff
if (!init(dict)) {
goto err1;
}
if (m != 1) {
error(-1, "Stitching function with more than one input");
goto err1;
}
//----- Functions
if (!dict->lookup("Functions", &obj1)->isArray()) {
error(-1, "Missing 'Functions' entry in stitching function");
goto err1;
}
k = obj1.arrayGetLength();
funcs = (Function **)gmalloc(k * sizeof(Function *));
bounds = (fouble *)gmalloc((k + 1) * sizeof(fouble));
encode = (fouble *)gmalloc(2 * k * sizeof(fouble));
for (i = 0; i < k; ++i) {
funcs[i] = NULL;
}
for (i = 0; i < k; ++i) {
if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) {
goto err2;
}
if (i > 0 && (funcs[i]->getInputSize() != 1 ||
funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
error(-1, "Incompatible subfunctions in stitching function");
goto err2;
}
obj2.free();
}
obj1.free();
//----- Bounds
if (!dict->lookup("Bounds", &obj1)->isArray() ||
obj1.arrayGetLength() != k - 1) {
error(-1, "Missing or invalid 'Bounds' entry in stitching function");
goto err1;
}
bounds[0] = domain[0][0];
diff --git a/noncore/unsupported/qpdf/xpdf/Function.h b/noncore/unsupported/qpdf/xpdf/Function.h
index a223359..deb4630 100644
--- a/noncore/unsupported/qpdf/xpdf/Function.h
+++ b/noncore/unsupported/qpdf/xpdf/Function.h
@@ -1,101 +1,101 @@
//========================================================================
//
// Function.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef FUNCTION_H
#define FUNCTION_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
#include "Object.h"
class Dict;
class Stream;
struct PSObject;
class PSStack;
//------------------------------------------------------------------------
// Function
//------------------------------------------------------------------------
#define funcMaxInputs 8
#define funcMaxOutputs 8
class Function {
public:
Function();
virtual ~Function();
// Construct a function. Returns NULL if unsuccessful.
static Function *parse(Object *funcObj);
// Initialize the entries common to all function types.
GBool init(Dict *dict);
virtual Function *copy() = 0;
// Return size of input and output tuples.
int getInputSize() { return m; }
int getOutputSize() { return n; }
// Transform an input tuple into an output tuple.
virtual void transform(fouble *in, fouble *out) = 0;
virtual GBool isOk() = 0;
protected:
int m, n; // size of input and output tuples
fouble // min and max values for function domain
domain[funcMaxInputs][2];
fouble // min and max values for function range
range[funcMaxOutputs][2];
GBool hasRange; // set if range is defined
};
//------------------------------------------------------------------------
// IdentityFunction
//------------------------------------------------------------------------
class IdentityFunction: public Function {
public:
IdentityFunction();
virtual ~IdentityFunction();
virtual Function *copy() { return new IdentityFunction(); }
virtual void transform(fouble *in, fouble *out);
virtual GBool isOk() { return gTrue; }
private:
};
//------------------------------------------------------------------------
// SampledFunction
//------------------------------------------------------------------------
class SampledFunction: public Function {
public:
SampledFunction(Object *funcObj, Dict *dict);
virtual ~SampledFunction();
virtual Function *copy() { return new SampledFunction(this); }
virtual void transform(fouble *in, fouble *out);
virtual GBool isOk() { return ok; }
private:
SampledFunction(SampledFunction *func);
int // number of samples for each domain element
sampleSize[funcMaxInputs];
fouble // min and max values for domain encoder
encode[funcMaxInputs][2];
diff --git a/noncore/unsupported/qpdf/xpdf/Gfx.cc b/noncore/unsupported/qpdf/xpdf/Gfx.cc
index c19971c..17d613e 100644
--- a/noncore/unsupported/qpdf/xpdf/Gfx.cc
+++ b/noncore/unsupported/qpdf/xpdf/Gfx.cc
@@ -1,138 +1,149 @@
//========================================================================
//
// Gfx.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include "gmem.h"
#include "CharTypes.h"
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "Stream.h"
#include "Lexer.h"
#include "Parser.h"
#include "GfxFont.h"
#include "GfxState.h"
#include "OutputDev.h"
#include "Page.h"
#include "Error.h"
#include "Gfx.h"
+// the MSVC math.h doesn't define this
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
//------------------------------------------------------------------------
// constants
//------------------------------------------------------------------------
// Max number of splits along the t axis for an axial shading fill.
#define axialMaxSplits 256
// Max delta allowed in any color component for an axial shading fill.
#define axialColorDelta (1 / 256.0)
+// Max number of splits along the t axis for a radial shading fill.
+#define radialMaxSplits 256
+
+// Max delta allowed in any color component for a radial shading fill.
+#define radialColorDelta (1 / 256.0)
+
//------------------------------------------------------------------------
// Operator table
//------------------------------------------------------------------------
Operator Gfx::opTab[] = {
{"\"", 3, {tchkNum, tchkNum, tchkString},
&Gfx::opMoveSetShowText},
{"'", 1, {tchkString},
&Gfx::opMoveShowText},
{"B", 0, {tchkNone},
&Gfx::opFillStroke},
{"B*", 0, {tchkNone},
&Gfx::opEOFillStroke},
{"BDC", 2, {tchkName, tchkProps},
&Gfx::opBeginMarkedContent},
{"BI", 0, {tchkNone},
&Gfx::opBeginImage},
{"BMC", 1, {tchkName},
&Gfx::opBeginMarkedContent},
{"BT", 0, {tchkNone},
&Gfx::opBeginText},
{"BX", 0, {tchkNone},
&Gfx::opBeginIgnoreUndef},
{"CS", 1, {tchkName},
&Gfx::opSetStrokeColorSpace},
{"DP", 2, {tchkName, tchkProps},
&Gfx::opMarkPoint},
{"Do", 1, {tchkName},
&Gfx::opXObject},
{"EI", 0, {tchkNone},
&Gfx::opEndImage},
{"EMC", 0, {tchkNone},
&Gfx::opEndMarkedContent},
{"ET", 0, {tchkNone},
&Gfx::opEndText},
{"EX", 0, {tchkNone},
&Gfx::opEndIgnoreUndef},
{"F", 0, {tchkNone},
&Gfx::opFill},
{"G", 1, {tchkNum},
&Gfx::opSetStrokeGray},
{"ID", 0, {tchkNone},
&Gfx::opImageData},
{"J", 1, {tchkInt},
&Gfx::opSetLineCap},
{"K", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
&Gfx::opSetStrokeCMYKColor},
{"M", 1, {tchkNum},
&Gfx::opSetMiterLimit},
{"MP", 1, {tchkName},
&Gfx::opMarkPoint},
{"Q", 0, {tchkNone},
&Gfx::opRestore},
{"RG", 3, {tchkNum, tchkNum, tchkNum},
&Gfx::opSetStrokeRGBColor},
{"S", 0, {tchkNone},
&Gfx::opStroke},
{"SC", -4, {tchkNum, tchkNum, tchkNum, tchkNum},
&Gfx::opSetStrokeColor},
{"SCN", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN,
tchkSCN},
&Gfx::opSetStrokeColorN},
{"T*", 0, {tchkNone},
&Gfx::opTextNextLine},
{"TD", 2, {tchkNum, tchkNum},
&Gfx::opTextMoveSet},
{"TJ", 1, {tchkArray},
&Gfx::opShowSpaceText},
{"TL", 1, {tchkNum},
&Gfx::opSetTextLeading},
{"Tc", 1, {tchkNum},
&Gfx::opSetCharSpacing},
{"Td", 2, {tchkNum, tchkNum},
&Gfx::opTextMove},
{"Tf", 2, {tchkName, tchkNum},
&Gfx::opSetFont},
{"Tj", 1, {tchkString},
&Gfx::opShowText},
{"Tm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
tchkNum, tchkNum},
&Gfx::opSetTextMatrix},
{"Tr", 1, {tchkInt},
&Gfx::opSetTextRender},
{"Ts", 1, {tchkNum},
&Gfx::opSetTextRise},
{"Tw", 1, {tchkNum},
&Gfx::opSetWordSpacing},
{"Tz", 1, {tchkNum},
&Gfx::opSetHorizScaling},
{"W", 0, {tchkNone},
&Gfx::opClip},
{"W*", 0, {tchkNone},
&Gfx::opEOClip},
{"b", 0, {tchkNone},
&Gfx::opCloseFillStroke},
{"b*", 0, {tchkNone},
@@ -281,338 +292,372 @@ GBool GfxResources::lookupXObject(char *name, Object *obj) {
}
error(-1, "XObject '%s' is unknown", name);
return gFalse;
}
GBool GfxResources::lookupXObjectNF(char *name, Object *obj) {
GfxResources *resPtr;
for (resPtr = this; resPtr; resPtr = resPtr->next) {
if (resPtr->xObjDict.isDict()) {
if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull())
return gTrue;
obj->free();
}
}
error(-1, "XObject '%s' is unknown", name);
return gFalse;
}
void GfxResources::lookupColorSpace(char *name, Object *obj) {
GfxResources *resPtr;
for (resPtr = this; resPtr; resPtr = resPtr->next) {
if (resPtr->colorSpaceDict.isDict()) {
if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) {
return;
}
obj->free();
}
}
obj->initNull();
}
GfxPattern *GfxResources::lookupPattern(char *name) {
GfxResources *resPtr;
GfxPattern *pattern;
Object obj;
for (resPtr = this; resPtr; resPtr = resPtr->next) {
if (resPtr->patternDict.isDict()) {
if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) {
pattern = GfxPattern::parse(&obj);
obj.free();
return pattern;
}
obj.free();
}
}
error(-1, "Unknown pattern '%s'", name);
return NULL;
}
GfxShading *GfxResources::lookupShading(char *name) {
GfxResources *resPtr;
GfxShading *shading;
Object obj;
for (resPtr = this; resPtr; resPtr = resPtr->next) {
if (resPtr->shadingDict.isDict()) {
if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) {
shading = GfxShading::parse(&obj);
obj.free();
return shading;
}
obj.free();
}
}
error(-1, "Unknown shading '%s'", name);
return NULL;
}
GBool GfxResources::lookupGState(char *name, Object *obj) {
GfxResources *resPtr;
for (resPtr = this; resPtr; resPtr = resPtr->next) {
if (resPtr->gStateDict.isDict()) {
if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) {
return gTrue;
}
obj->free();
}
}
error(-1, "ExtGState '%s' is unknown", name);
return gFalse;
}
//------------------------------------------------------------------------
// Gfx
//------------------------------------------------------------------------
Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, fouble dpi,
PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
GBool printCommandsA) {
int i;
xref = xrefA;
+ subPage = gFalse;
printCommands = printCommandsA;
// start the resource stack
res = new GfxResources(xref, resDict, NULL);
// initialize
out = outA;
state = new GfxState(dpi, box, rotate, out->upsideDown());
fontChanged = gFalse;
clip = clipNone;
ignoreUndef = 0;
out->startPage(pageNum, state);
out->setDefaultCTM(state->getCTM());
out->updateAll(state);
for (i = 0; i < 6; ++i) {
baseMatrix[i] = state->getCTM()[i];
}
// set crop box
if (crop) {
state->moveTo(cropBox->x1, cropBox->y1);
state->lineTo(cropBox->x2, cropBox->y1);
state->lineTo(cropBox->x2, cropBox->y2);
state->lineTo(cropBox->x1, cropBox->y2);
state->closePath();
state->clip();
out->clip(state);
state->clearPath();
}
}
-Gfx::~Gfx() {
- GfxResources *resPtr;
+Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
+ PDFRectangle *box, GBool crop, PDFRectangle *cropBox) {
+ int i;
+ xref = xrefA;
+ subPage = gTrue;
+ printCommands = gFalse;
+
+ // start the resource stack
+ res = new GfxResources(xref, resDict, NULL);
+
+ // initialize
+ out = outA;
+ state = new GfxState(72, box, 0, gFalse);
+ fontChanged = gFalse;
+ clip = clipNone;
+ ignoreUndef = 0;
+ for (i = 0; i < 6; ++i) {
+ baseMatrix[i] = state->getCTM()[i];
+ }
+
+ // set crop box
+ if (crop) {
+ state->moveTo(cropBox->x1, cropBox->y1);
+ state->lineTo(cropBox->x2, cropBox->y1);
+ state->lineTo(cropBox->x2, cropBox->y2);
+ state->lineTo(cropBox->x1, cropBox->y2);
+ state->closePath();
+ state->clip();
+ out->clip(state);
+ state->clearPath();
+ }
+}
+
+Gfx::~Gfx() {
while (state->hasSaves()) {
state = state->restore();
out->restoreState(state);
}
- out->endPage();
+ if (!subPage) {
+ out->endPage();
+ }
while (res) {
- resPtr = res->getNext();
- delete res;
- res = resPtr;
+ popResources();
}
- if (state)
+ if (state) {
delete state;
+ }
}
void Gfx::display(Object *obj, GBool topLevel) {
Object obj2;
int i;
if (obj->isArray()) {
for (i = 0; i < obj->arrayGetLength(); ++i) {
obj->arrayGet(i, &obj2);
if (!obj2.isStream()) {
error(-1, "Weird page contents");
obj2.free();
return;
}
obj2.free();
}
} else if (!obj->isStream()) {
error(-1, "Weird page contents");
return;
}
parser = new Parser(xref, new Lexer(xref, obj));
go(topLevel);
delete parser;
parser = NULL;
}
void Gfx::go(GBool topLevel) {
Object obj;
Object args[maxArgs];
- int numCmds, numArgs;
+ int numArgs;
int i;
// scan a sequence of objects
- numCmds = 0;
+ updateLevel = 0;
numArgs = 0;
parser->getObj(&obj);
while (!obj.isEOF()) {
// got a command - execute it
if (obj.isCmd()) {
if (printCommands) {
obj.print(stdout);
for (i = 0; i < numArgs; ++i) {
printf(" ");
args[i].print(stdout);
}
printf("\n");
fflush(stdout);
}
execOp(&obj, args, numArgs);
obj.free();
for (i = 0; i < numArgs; ++i)
args[i].free();
numArgs = 0;
// periodically update display
- if (++numCmds == 200) {
+ if (++updateLevel >= 20000) {
out->dump();
- numCmds = 0;
+ updateLevel = 0;
}
// got an argument - save it
} else if (numArgs < maxArgs) {
args[numArgs++] = obj;
// too many arguments - something is wrong
} else {
error(getPos(), "Too many args in content stream");
if (printCommands) {
printf("throwing away arg: ");
obj.print(stdout);
printf("\n");
fflush(stdout);
}
obj.free();
}
// grab the next object
parser->getObj(&obj);
}
obj.free();
// args at end with no command
if (numArgs > 0) {
error(getPos(), "Leftover args in content stream");
if (printCommands) {
printf("%d leftovers:", numArgs);
for (i = 0; i < numArgs; ++i) {
printf(" ");
args[i].print(stdout);
}
printf("\n");
fflush(stdout);
}
for (i = 0; i < numArgs; ++i)
args[i].free();
}
// update display
- if (topLevel && numCmds > 0) {
+ if (topLevel && updateLevel > 0) {
out->dump();
}
}
void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
Operator *op;
char *name;
int i;
// find operator
name = cmd->getName();
if (!(op = findOp(name))) {
if (ignoreUndef == 0)
error(getPos(), "Unknown operator '%s'", name);
return;
}
// type check args
if (op->numArgs >= 0) {
if (numArgs != op->numArgs) {
error(getPos(), "Wrong number (%d) of args to '%s' operator",
numArgs, name);
return;
}
} else {
if (numArgs > -op->numArgs) {
error(getPos(), "Too many (%d) args to '%s' operator",
numArgs, name);
return;
}
}
for (i = 0; i < numArgs; ++i) {
if (!checkArg(&args[i], op->tchk[i])) {
error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)",
i, name, args[i].getTypeName());
return;
}
}
// do it
(this->*op->func)(args, numArgs);
}
Operator *Gfx::findOp(char *name) {
int a, b, m, cmp;
a = -1;
b = numOps;
// invariant: opTab[a] < name < opTab[b]
while (b - a > 1) {
m = (a + b) / 2;
cmp = strcmp(opTab[m].name, name);
if (cmp < 0)
a = m;
else if (cmp > 0)
b = m;
else
a = b = m;
}
if (cmp != 0)
return NULL;
return &opTab[a];
}
GBool Gfx::checkArg(Object *arg, TchkType type) {
switch (type) {
case tchkBool: return arg->isBool();
case tchkInt: return arg->isInt();
case tchkNum: return arg->isNum();
case tchkString: return arg->isString();
case tchkName: return arg->isName();
case tchkArray: return arg->isArray();
case tchkProps: return arg->isDict() || arg->isName();
case tchkSCN: return arg->isNum() || arg->isName();
case tchkNone: return gFalse;
}
return gFalse;
}
int Gfx::getPos() {
return parser ? parser->getPos() : -1;
}
//------------------------------------------------------------------------
// graphics state operators
//------------------------------------------------------------------------
void Gfx::opSave(Object args[], int numArgs) {
out->saveState(state);
state = state->save();
}
void Gfx::opRestore(Object args[], int numArgs) {
state = state->restore();
out->restoreState(state);
}
@@ -1045,459 +1090,404 @@ void Gfx::opFill(Object args[], int numArgs) {
out->fill(state);
}
}
doEndPath();
}
void Gfx::opEOFill(Object args[], int numArgs) {
if (!state->isCurPt()) {
//error(getPos(), "No path in eofill");
return;
}
if (state->isPath()) {
if (state->getFillColorSpace()->getMode() == csPattern) {
doPatternFill(gTrue);
} else {
out->eoFill(state);
}
}
doEndPath();
}
void Gfx::opFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
//error(getPos(), "No path in fill/stroke");
return;
}
if (state->isPath()) {
if (state->getFillColorSpace()->getMode() == csPattern) {
doPatternFill(gFalse);
} else {
out->fill(state);
}
out->stroke(state);
}
doEndPath();
}
void Gfx::opCloseFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
//error(getPos(), "No path in closepath/fill/stroke");
return;
}
if (state->isPath()) {
state->closePath();
if (state->getFillColorSpace()->getMode() == csPattern) {
doPatternFill(gFalse);
} else {
out->fill(state);
}
out->stroke(state);
}
doEndPath();
}
void Gfx::opEOFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
//error(getPos(), "No path in eofill/stroke");
return;
}
if (state->isPath()) {
if (state->getFillColorSpace()->getMode() == csPattern) {
doPatternFill(gTrue);
} else {
out->eoFill(state);
}
out->stroke(state);
}
doEndPath();
}
void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
//error(getPos(), "No path in closepath/eofill/stroke");
return;
}
if (state->isPath()) {
state->closePath();
if (state->getFillColorSpace()->getMode() == csPattern) {
doPatternFill(gTrue);
} else {
out->eoFill(state);
}
out->stroke(state);
}
doEndPath();
}
void Gfx::doPatternFill(GBool eoFill) {
GfxPatternColorSpace *patCS;
GfxPattern *pattern;
GfxTilingPattern *tPat;
GfxColorSpace *cs;
fouble xMin, yMin, xMax, yMax, x, y, x1, y1;
fouble cxMin, cyMin, cxMax, cyMax;
int xi0, yi0, xi1, yi1, xi, yi;
fouble *ctm, *btm, *ptm;
- fouble m[6], ictm[6], m1[6], im[6], imb[6];
+ fouble m[6], ictm[6], m1[6], imb[6];
fouble det;
fouble xstep, ystep;
int i;
// this is a bit of a kludge -- patterns can be really slow, so we
// skip them if we're only doing text extraction, since they almost
// certainly don't contain any text
if (!out->needNonText()) {
return;
}
// get color space
patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
// get pattern
if (!(pattern = state->getFillPattern())) {
return;
}
if (pattern->getType() != 1) {
return;
}
tPat = (GfxTilingPattern *)pattern;
// construct a (pattern space) -> (current space) transform matrix
ctm = state->getCTM();
btm = baseMatrix;
ptm = tPat->getMatrix();
// iCTM = invert CTM
det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
ictm[0] = ctm[3] * det;
ictm[1] = -ctm[1] * det;
ictm[2] = -ctm[2] * det;
ictm[3] = ctm[0] * det;
ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
// m1 = PTM * BTM = PTM * base transform matrix
m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
// m = m1 * iCTM = (PTM * BTM) * (iCTM)
m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
- // construct a (current space) -> (pattern space) transform matrix
- det = 1 / (m[0] * m[3] - m[1] * m[2]);
- im[0] = m[3] * det;
- im[1] = -m[1] * det;
- im[2] = -m[2] * det;
- im[3] = m[0] * det;
- im[4] = (m[2] * m[5] - m[3] * m[4]) * det;
- im[5] = (m[1] * m[4] - m[0] * m[5]) * det;
-
// construct a (base space) -> (pattern space) transform matrix
det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]);
imb[0] = m1[3] * det;
imb[1] = -m1[1] * det;
imb[2] = -m1[2] * det;
imb[3] = m1[0] * det;
imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det;
imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
// save current graphics state
out->saveState(state);
state = state->save();
// set underlying color space (for uncolored tiling patterns)
if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
state->setFillColorSpace(cs->copy());
} else {
state->setFillColorSpace(new GfxDeviceGrayColorSpace());
}
state->setFillPattern(NULL);
out->updateFillColor(state);
// clip to current path
state->clip();
if (eoFill) {
out->eoClip(state);
} else {
out->clip(state);
}
state->clearPath();
// transform clip region bbox to pattern space
state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);
xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4];
yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5];
x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4];
y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5];
if (x1 < xMin) {
xMin = x1;
} else if (x1 > xMax) {
xMax = x1;
}
if (y1 < yMin) {
yMin = y1;
} else if (y1 > yMax) {
yMax = y1;
}
x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4];
y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5];
if (x1 < xMin) {
xMin = x1;
} else if (x1 > xMax) {
xMax = x1;
}
if (y1 < yMin) {
yMin = y1;
} else if (y1 > yMax) {
yMax = y1;
}
x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4];
y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5];
if (x1 < xMin) {
xMin = x1;
} else if (x1 > xMax) {
xMax = x1;
}
if (y1 < yMin) {
yMin = y1;
} else if (y1 > yMax) {
yMax = y1;
}
// draw the pattern
//~ this should treat negative steps differently -- start at right/top
//~ edge instead of left/bottom (?)
xstep = fabs(tPat->getXStep());
ystep = fabs(tPat->getYStep());
xi0 = (int)floor(xMin / xstep);
xi1 = (int)ceil(xMax / xstep);
yi0 = (int)floor(yMin / ystep);
yi1 = (int)ceil(yMax / ystep);
for (i = 0; i < 4; ++i) {
m1[i] = m[i];
}
for (yi = yi0; yi < yi1; ++yi) {
for (xi = xi0; xi < xi1; ++xi) {
x = xi * xstep;
y = yi * ystep;
m1[4] = x * m[0] + y * m[2] + m[4];
m1[5] = x * m[1] + y * m[3] + m[5];
doForm1(tPat->getContentStream(), tPat->getResDict(),
m1, tPat->getBBox());
}
}
// restore graphics state
state = state->restore();
out->restoreState(state);
}
void Gfx::opShFill(Object args[], int numArgs) {
GfxShading *shading;
fouble xMin, yMin, xMax, yMax;
if (!(shading = res->lookupShading(args[0].getName()))) {
return;
}
// save current graphics state
out->saveState(state);
state = state->save();
// clip to bbox
if (shading->getHasBBox()) {
shading->getBBox(&xMin, &yMin, &xMax, &yMax);
state->moveTo(xMin, yMin);
state->lineTo(xMax, yMin);
state->lineTo(xMax, yMax);
state->lineTo(xMin, yMax);
state->closePath();
state->clip();
out->clip(state);
state->clearPath();
}
// set the color space
state->setFillColorSpace(shading->getColorSpace()->copy());
// do shading type-specific operations
switch (shading->getType()) {
case 2:
doAxialShFill((GfxAxialShading *)shading);
break;
+ case 3:
+ doRadialShFill((GfxRadialShading *)shading);
+ break;
}
// restore graphics state
state = state->restore();
out->restoreState(state);
delete shading;
}
void Gfx::doAxialShFill(GfxAxialShading *shading) {
fouble xMin, yMin, xMax, yMax;
fouble x0, y0, x1, y1;
- fouble det;
- fouble *ctm;
- fouble ictm[6];
fouble dx, dy, mul;
fouble tMin, tMax, t, tx, ty;
fouble s[4], sMin, sMax, tmp;
fouble ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
fouble t0, t1, tt;
fouble ta[axialMaxSplits + 1];
int next[axialMaxSplits + 1];
GfxColor color0, color1;
int nComps;
int i, j, k, kk;
- // get clip region bbox and transform to current user space
- state->getClipBBox(&x0, &y0, &x1, &y1);
- ctm = state->getCTM();
- det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
- ictm[0] = ctm[3] * det;
- ictm[1] = -ctm[1] * det;
- ictm[2] = -ctm[2] * det;
- ictm[3] = ctm[0] * det;
- ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
- ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
- xMin = xMax = x0 * ictm[0] + y0 * ictm[2] + ictm[4];
- yMin = yMax = x0 * ictm[1] + y0 * ictm[3] + ictm[5];
- tx = x0 * ictm[0] + y1 * ictm[2] + ictm[4];
- ty = x0 * ictm[1] + y1 * ictm[3] + ictm[5];
- if (tx < xMin) {
- xMin = tx;
- } else if (tx > xMax) {
- xMax = tx;
- }
- if (ty < yMin) {
- yMin = ty;
- } else if (ty > yMax) {
- yMax = ty;
- }
- tx = x1 * ictm[0] + y0 * ictm[2] + ictm[4];
- ty = x1 * ictm[1] + y0 * ictm[3] + ictm[5];
- if (tx < xMin) {
- xMin = tx;
- } else if (tx > xMax) {
- xMax = tx;
- }
- if (ty < yMin) {
- yMin = ty;
- } else if (ty > yMax) {
- yMax = ty;
- }
- tx = x1 * ictm[0] + y1 * ictm[2] + ictm[4];
- ty = x1 * ictm[1] + y1 * ictm[3] + ictm[5];
- if (tx < xMin) {
- xMin = tx;
- } else if (tx > xMax) {
- xMax = tx;
- }
- if (ty < yMin) {
- yMin = ty;
- } else if (ty > yMax) {
- yMax = ty;
- }
+ // get the clip region bbox
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
// compute min and max t values, based on the four corners of the
// clip region bbox
shading->getCoords(&x0, &y0, &x1, &y1);
dx = x1 - x0;
dy = y1 - y0;
mul = 1 / (dx * dx + dy * dy);
tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
if (t < tMin) {
tMin = t;
} else if (t > tMax) {
tMax = t;
}
t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
if (t < tMin) {
tMin = t;
} else if (t > tMax) {
tMax = t;
}
t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
if (t < tMin) {
tMin = t;
} else if (t > tMax) {
tMax = t;
}
if (tMin < 0 && !shading->getExtend0()) {
tMin = 0;
}
if (tMax > 1 && !shading->getExtend1()) {
tMax = 1;
}
// get the function domain
t0 = shading->getDomain0();
t1 = shading->getDomain1();
// Traverse the t axis and do the shading.
//
// For each point (tx, ty) on the t axis, consider a line through
// that point perpendicular to the t axis:
//
// x(s) = tx + s * -dy --> s = (x - tx) / -dy
// y(s) = ty + s * dx --> s = (y - ty) / dx
//
// Then look at the intersection of this line with the bounding box
// (xMin, yMin, xMax, yMax). In the general case, there are four
// intersection points:
//
// s0 = (xMin - tx) / -dy
// s1 = (xMax - tx) / -dy
// s2 = (yMin - ty) / dx
// s3 = (yMax - ty) / dx
//
// and we want the middle two s values.
//
// In the case where dx = 0, take s0 and s1; in the case where dy =
// 0, take s2 and s3.
//
// Each filled polygon is bounded by two of these line segments
// perpdendicular to the t axis.
//
// The t axis is bisected into smaller regions until the color
// difference across a region is small enough, and then the region
// is painted with a single color.
// set up
nComps = shading->getColorSpace()->getNComps();
ta[0] = tMin;
ta[axialMaxSplits] = tMax;
next[0] = axialMaxSplits;
// compute the color at t = tMin
if (tMin < 0) {
tt = t0;
} else if (tMin > 1) {
tt = t1;
} else {
tt = t0 + (t1 - t0) * tMin;
}
shading->getColor(tt, &color0);
// compute the coordinates of the point on the t axis at t = tMin;
// then compute the intersection of the perpendicular line with the
// bounding box
tx = x0 + tMin * dx;
ty = y0 + tMin * dy;
if (dx == 0 && dy == 0) {
sMin = sMax = 0;
} if (dx == 0) {
sMin = (xMin - tx) / -dy;
sMax = (xMax - tx) / -dy;
if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
} else if (dy == 0) {
sMin = (yMin - ty) / dx;
sMax = (yMax - ty) / dx;
@@ -1526,936 +1516,1245 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
i = 0;
while (i < axialMaxSplits) {
// bisect until color difference is small enough or we hit the
// bisection limit
j = next[i];
while (j > i + 1) {
if (ta[j] < 0) {
tt = t0;
} else if (ta[j] > 1) {
tt = t1;
} else {
tt = t0 + (t1 - t0) * ta[j];
}
shading->getColor(tt, &color1);
for (k = 0; k < nComps; ++k) {
if (fabs(color1.c[k] - color0.c[k]) > axialColorDelta) {
break;
}
}
if (k == nComps) {
break;
}
k = (i + j) / 2;
ta[k] = 0.5 * (ta[i] + ta[j]);
next[i] = k;
next[k] = j;
j = k;
}
// use the average of the colors of the two sides of the region
for (k = 0; k < nComps; ++k) {
color0.c[k] = 0.5 * (color0.c[k] + color1.c[k]);
}
// compute the coordinates of the point on the t axis; then
// compute the intersection of the perpendicular line with the
// bounding box
tx = x0 + ta[j] * dx;
ty = y0 + ta[j] * dy;
if (dx == 0 && dy == 0) {
sMin = sMax = 0;
} if (dx == 0) {
sMin = (xMin - tx) / -dy;
sMax = (xMax - tx) / -dy;
if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
} else if (dy == 0) {
sMin = (yMin - ty) / dx;
sMax = (yMax - ty) / dx;
if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
} else {
s[0] = (yMin - ty) / dx;
s[1] = (yMax - ty) / dx;
s[2] = (xMin - tx) / -dy;
s[3] = (xMax - tx) / -dy;
for (j = 0; j < 3; ++j) {
kk = j;
for (k = j + 1; k < 4; ++k) {
if (s[k] < s[kk]) {
kk = k;
}
}
tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
}
sMin = s[1];
sMax = s[2];
}
ux1 = tx - sMin * dy;
uy1 = ty + sMin * dx;
vx1 = tx - sMax * dy;
vy1 = ty + sMax * dx;
// set the color
state->setFillColor(&color0);
out->updateFillColor(state);
// fill the region
state->moveTo(ux0, uy0);
state->lineTo(vx0, vy0);
state->lineTo(vx1, vy1);
state->lineTo(ux1, uy1);
state->closePath();
out->fill(state);
state->clearPath();
// set up for next region
ux0 = ux1;
uy0 = uy1;
vx0 = vx1;
vy0 = vy1;
color0 = color1;
i = next[i];
}
}
+void Gfx::doRadialShFill(GfxRadialShading *shading) {
+ fouble sMin, sMax, xMin, yMin, xMax, yMax;
+ fouble x0, y0, r0, x1, y1, r1, t0, t1;
+ int nComps;
+ GfxColor colorA, colorB;
+ fouble xa, ya, xb, yb, ra, rb;
+ fouble ta, tb, sa, sb;
+ int ia, ib, k, n;
+ fouble *ctm;
+ fouble angle, t;
+
+ // get the shading info
+ shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
+ t0 = shading->getDomain0();
+ t1 = shading->getDomain1();
+ nComps = shading->getColorSpace()->getNComps();
+
+ // compute the (possibly extended) s range
+ sMin = 0;
+ sMax = 1;
+ if (shading->getExtend0()) {
+ if (r0 < r1) {
+ // extend the smaller end
+ sMin = -r0 / (r1 - r0);
+ } else {
+ // extend the larger end
+ //~ this computes the diagonal of the bounding box -- we should
+ //~ really compute the intersection of the moving/expanding
+ //~ circles with each of the four corners and look for the max
+ //~ radius
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+ sMin = (sqrt((xMax - xMin) * (xMax - xMin) +
+ (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
+ if (sMin > 0) {
+ sMin = 0;
+ } else if (sMin < -20) {
+ // sanity check
+ sMin = -20;
+ }
+ }
+ }
+ if (shading->getExtend1()) {
+ if (r1 < r0) {
+ // extend the smaller end
+ sMax = -r0 / (r1 - r0);
+ } else if (r1 > r0) {
+ // extend the larger end
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+ sMax = (sqrt((xMax - xMin) * (xMax - xMin) +
+ (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
+ if (sMax < 1) {
+ sMin = 1;
+ } else if (sMax > 20) {
+ // sanity check
+ sMax = 20;
+ }
+ }
+ }
+
+ // compute the number of steps into which circles must be divided to
+ // achieve a curve flatness of 0.1 pixel in device space for the
+ // largest circle (note that "device space" is 72 dpi when generating
+ // PostScript, hence the relatively small 0.1 pixel accuracy)
+ ctm = state->getCTM();
+ t = fabs(ctm[0]);
+ if (fabs(ctm[1]) > t) {
+ t = fabs(ctm[1]);
+ }
+ if (fabs(ctm[2]) > t) {
+ t = fabs(ctm[2]);
+ }
+ if (fabs(ctm[3]) > t) {
+ t = fabs(ctm[3]);
+ }
+ if (r0 > r1) {
+ t *= r0;
+ } else {
+ t *= r1;
+ }
+ if (t < 1) {
+ n = 3;
+ } else {
+ n = (int)(M_PI / acos(1 - 0.1 / t));
+ if (n < 3) {
+ n = 3;
+ } else if (n > 200) {
+ n = 200;
+ }
+ }
+
+ // Traverse the t axis and do the shading.
+ //
+ // This generates and fills a series of rings. Each ring is defined
+ // by two circles:
+ // sa, ta, xa, ya, ra, colorA
+ // sb, tb, xb, yb, rb, colorB
+ //
+ // The s/t axis is divided into radialMaxSplits parts; these parts
+ // are combined as much as possible while respecting the
+ // radialColorDelta parameter.
+
+ // setup for the start circle
+ ia = 0;
+ sa = sMin;
+ ta = t0 + sa * (t1 - t0);
+ xa = x0 + sa * (x1 - x0);
+ ya = y0 + sa * (y1 - y0);
+ ra = r0 + sa * (r1 - r0);
+ if (ta < t0) {
+ shading->getColor(t0, &colorA);
+ } else if (ta > t1) {
+ shading->getColor(t1, &colorA);
+ } else {
+ shading->getColor(ta, &colorA);
+ }
+
+ while (ia < radialMaxSplits) {
+
+ // go as far along the t axis (toward t1) as we can, such that the
+ // color difference is within the tolerance (radialColorDelta) --
+ // this uses bisection (between the current value, t, and t1),
+ // limited to radialMaxSplits points along the t axis
+ ib = radialMaxSplits;
+ sb = sMin + ((fouble)ib / (fouble)radialMaxSplits) * (sMax - sMin);
+ tb = t0 + sb * (t1 - t0);
+ if (tb < t0) {
+ shading->getColor(t0, &colorB);
+ } else if (tb > t1) {
+ shading->getColor(t1, &colorB);
+ } else {
+ shading->getColor(tb, &colorB);
+ }
+ while (ib - ia > 1) {
+ for (k = 0; k < nComps; ++k) {
+ if (fabs(colorB.c[k] - colorA.c[k]) > radialColorDelta) {
+ break;
+ }
+ }
+ if (k == nComps) {
+ break;
+ }
+ ib = (ia + ib) / 2;
+ sb = sMin + ((fouble)ib / (fouble)radialMaxSplits) * (sMax - sMin);
+ tb = t0 + sb * (t1 - t0);
+ if (tb < t0) {
+ shading->getColor(t0, &colorB);
+ } else if (tb > t1) {
+ shading->getColor(t1, &colorB);
+ } else {
+ shading->getColor(tb, &colorB);
+ }
+ }
+
+ // compute center and radius of the circle
+ xb = x0 + sb * (x1 - x0);
+ yb = y0 + sb * (y1 - y0);
+ rb = r0 + sb * (r1 - r0);
+
+ // use the average of the colors at the two circles
+ for (k = 0; k < nComps; ++k) {
+ colorA.c[k] = 0.5 * (colorA.c[k] + colorB.c[k]);
+ }
+ state->setFillColor(&colorA);
+ out->updateFillColor(state);
+
+ // construct path for first circle
+ state->moveTo(xa + ra, ya);
+ for (k = 1; k < n; ++k) {
+ angle = ((fouble)k / (fouble)n) * 2 * M_PI;
+ state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
+ }
+ state->closePath();
+
+ // construct and append path for second circle
+ state->moveTo(xb + rb, yb);
+ for (k = 1; k < n; ++k) {
+ angle = ((fouble)k / (fouble)n) * 2 * M_PI;
+ state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
+ }
+ state->closePath();
+
+ // fill the ring
+ out->eoFill(state);
+ state->clearPath();
+
+ // step to the next value of t
+ ia = ib;
+ sa = sb;
+ ta = tb;
+ xa = xb;
+ ya = yb;
+ ra = rb;
+ colorA = colorB;
+ }
+}
+
void Gfx::doEndPath() {
if (state->isPath() && clip != clipNone) {
state->clip();
if (clip == clipNormal) {
out->clip(state);
} else {
out->eoClip(state);
}
}
clip = clipNone;
state->clearPath();
}
//------------------------------------------------------------------------
// path clipping operators
//------------------------------------------------------------------------
void Gfx::opClip(Object args[], int numArgs) {
clip = clipNormal;
}
void Gfx::opEOClip(Object args[], int numArgs) {
clip = clipEO;
}
//------------------------------------------------------------------------
// text object operators
//------------------------------------------------------------------------
void Gfx::opBeginText(Object args[], int numArgs) {
state->setTextMat(1, 0, 0, 1, 0, 0);
state->textMoveTo(0, 0);
out->updateTextMat(state);
out->updateTextPos(state);
fontChanged = gTrue;
}
void Gfx::opEndText(Object args[], int numArgs) {
}
//------------------------------------------------------------------------
// text state operators
//------------------------------------------------------------------------
void Gfx::opSetCharSpacing(Object args[], int numArgs) {
state->setCharSpace(args[0].getNum());
out->updateCharSpace(state);
}
void Gfx::opSetFont(Object args[], int numArgs) {
GfxFont *font;
if (!(font = res->lookupFont(args[0].getName()))) {
return;
}
if (printCommands) {
printf(" font: tag=%s name='%s' %g\n",
font->getTag()->getCString(),
font->getName() ? font->getName()->getCString() : "???",
args[1].getNum());
fflush(stdout);
}
state->setFont(font, args[1].getNum());
fontChanged = gTrue;
}
void Gfx::opSetTextLeading(Object args[], int numArgs) {
state->setLeading(args[0].getNum());
}
void Gfx::opSetTextRender(Object args[], int numArgs) {
state->setRender(args[0].getInt());
out->updateRender(state);
}
void Gfx::opSetTextRise(Object args[], int numArgs) {
state->setRise(args[0].getNum());
out->updateRise(state);
}
void Gfx::opSetWordSpacing(Object args[], int numArgs) {
state->setWordSpace(args[0].getNum());
out->updateWordSpace(state);
}
void Gfx::opSetHorizScaling(Object args[], int numArgs) {
state->setHorizScaling(args[0].getNum());
out->updateHorizScaling(state);
fontChanged = gTrue;
}
//------------------------------------------------------------------------
// text positioning operators
//------------------------------------------------------------------------
void Gfx::opTextMove(Object args[], int numArgs) {
fouble tx, ty;
tx = state->getLineX() + args[0].getNum();
ty = state->getLineY() + args[1].getNum();
state->textMoveTo(tx, ty);
out->updateTextPos(state);
}
void Gfx::opTextMoveSet(Object args[], int numArgs) {
fouble tx, ty;
tx = state->getLineX() + args[0].getNum();
ty = args[1].getNum();
state->setLeading(-ty);
ty += state->getLineY();
state->textMoveTo(tx, ty);
out->updateTextPos(state);
}
void Gfx::opSetTextMatrix(Object args[], int numArgs) {
state->setTextMat(args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
state->textMoveTo(0, 0);
out->updateTextMat(state);
out->updateTextPos(state);
fontChanged = gTrue;
}
void Gfx::opTextNextLine(Object args[], int numArgs) {
fouble tx, ty;
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
out->updateTextPos(state);
}
//------------------------------------------------------------------------
// text string operators
//------------------------------------------------------------------------
void Gfx::opShowText(Object args[], int numArgs) {
if (!state->getFont()) {
error(getPos(), "No font in show");
return;
}
doShowText(args[0].getString());
}
void Gfx::opMoveShowText(Object args[], int numArgs) {
fouble tx, ty;
if (!state->getFont()) {
error(getPos(), "No font in move/show");
return;
}
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
out->updateTextPos(state);
doShowText(args[0].getString());
}
void Gfx::opMoveSetShowText(Object args[], int numArgs) {
fouble tx, ty;
if (!state->getFont()) {
error(getPos(), "No font in move/set/show");
return;
}
state->setWordSpace(args[0].getNum());
state->setCharSpace(args[1].getNum());
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
out->updateWordSpace(state);
out->updateCharSpace(state);
out->updateTextPos(state);
doShowText(args[2].getString());
}
void Gfx::opShowSpaceText(Object args[], int numArgs) {
Array *a;
Object obj;
+ int wMode;
int i;
if (!state->getFont()) {
error(getPos(), "No font in show/space");
return;
}
+ wMode = state->getFont()->getWMode();
a = args[0].getArray();
for (i = 0; i < a->getLength(); ++i) {
a->get(i, &obj);
if (obj.isNum()) {
- state->textShift(-obj.getNum() * 0.001 * state->getFontSize());
+ if (wMode) {
+ state->textShift(0, -obj.getNum() * 0.001 * state->getFontSize());
+ } else {
+ state->textShift(-obj.getNum() * 0.001 * state->getFontSize(), 0);
+ }
out->updateTextShift(state, obj.getNum());
} else if (obj.isString()) {
doShowText(obj.getString());
} else {
error(getPos(), "Element of show/space array must be number or string");
}
obj.free();
}
}
void Gfx::doShowText(GString *s) {
GfxFont *font;
+ int wMode;
fouble riseX, riseY;
CharCode code;
Unicode u[8];
- fouble dx, dy, dx2, dy2, tdx, tdy;
+ fouble x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy;
fouble originX, originY, tOriginX, tOriginY;
+ fouble oldCTM[6], newCTM[6];
+ fouble *mat;
+ Object charProc;
+ Dict *resDict;
+ Parser *oldParser;
char *p;
- int len, n, uLen, nChars, nSpaces;
+ int len, n, uLen, nChars, nSpaces, i;
if (fontChanged) {
out->updateFont(state);
fontChanged = gFalse;
}
font = state->getFont();
+ wMode = font->getWMode();
-#if 0 //~type3
- fouble x, y;
- fouble oldCTM[6], newCTM[6];
- fouble *mat;
- Object charProc;
- Parser *oldParser;
- int i;
-
- //~ also check out->renderType3()
- if (font->getType() == fontType3) {
+ if (out->useDrawChar()) {
out->beginString(state, s);
+ }
+
+ // handle a Type 3 char
+ if (font->getType() == fontType3 && out->interpretType3Chars()) {
mat = state->getCTM();
for (i = 0; i < 6; ++i) {
oldCTM[i] = mat[i];
}
mat = state->getTextMat();
newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2];
newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3];
newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2];
newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3];
mat = font->getFontMatrix();
newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2];
newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3];
newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2];
newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3];
newCTM[0] *= state->getFontSize();
newCTM[3] *= state->getFontSize();
newCTM[0] *= state->getHorizScaling();
newCTM[2] *= state->getHorizScaling();
state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
+ curX = state->getCurX();
+ curY = state->getCurY();
oldParser = parser;
p = s->getCString();
len = s->getLength();
while (len > 0) {
n = font->getNextChar(p, len, &code,
u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
&dx, &dy, &originX, &originY);
- state->transform(state->getCurX() + riseX, state->getCurY() + riseY,
- &x, &y);
- out->saveState(state);
- state = state->save();
- state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
- //~ out->updateCTM(???)
- ((Gfx8BitFont *)font)->getCharProc(code, &charProc);
- if (charProc.isStream()) {
- display(&charProc, gFalse);
- } else {
- error(getPos(), "Missing or bad Type3 CharProc entry");
- }
- state = state->restore();
- out->restoreState(state);
- charProc.free();
dx = dx * state->getFontSize() + state->getCharSpace();
if (n == 1 && *p == ' ') {
dx += state->getWordSpace();
}
dx *= state->getHorizScaling();
dy *= state->getFontSize();
state->textTransformDelta(dx, dy, &tdx, &tdy);
- state->shift(tdx, tdy);
+ state->transform(curX + riseX, curY + riseY, &x, &y);
+ out->saveState(state);
+ state = state->save();
+ state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
+ //~ out->updateCTM(???)
+ if (!out->beginType3Char(state, code, u, uLen)) {
+ ((Gfx8BitFont *)font)->getCharProc(code, &charProc);
+ if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
+ pushResources(resDict);
+ }
+ if (charProc.isStream()) {
+ display(&charProc, gFalse);
+ } else {
+ error(getPos(), "Missing or bad Type3 CharProc entry");
+ }
+ out->endType3Char(state);
+ if (resDict) {
+ popResources();
+ }
+ charProc.free();
+ }
+ state = state->restore();
+ out->restoreState(state);
+ // GfxState::restore() does *not* restore the current position,
+ // so we track it here with (curX, curY)
+ curX += tdx;
+ curY += tdy;
+ state->moveTo(curX, curY);
p += n;
len -= n;
}
parser = oldParser;
- out->endString(state);
- return;
- }
-#endif
- if (out->useDrawChar()) {
+ } else if (out->useDrawChar()) {
state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
- out->beginString(state, s);
p = s->getCString();
len = s->getLength();
while (len > 0) {
n = font->getNextChar(p, len, &code,
u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
&dx, &dy, &originX, &originY);
- dx = dx * state->getFontSize() + state->getCharSpace();
- if (n == 1 && *p == ' ') {
- dx += state->getWordSpace();
+ if (wMode) {
+ dx *= state->getFontSize();
+ dy = dy * state->getFontSize() + state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dy += state->getWordSpace();
+ }
+ } else {
+ dx = dx * state->getFontSize() + state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dx += state->getWordSpace();
+ }
+ dx *= state->getHorizScaling();
+ dy *= state->getFontSize();
}
- dx *= state->getHorizScaling();
- dy *= state->getFontSize();
state->textTransformDelta(dx, dy, &tdx, &tdy);
originX *= state->getFontSize();
originY *= state->getFontSize();
state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
tdx, tdy, tOriginX, tOriginY, code, u, uLen);
state->shift(tdx, tdy);
p += n;
len -= n;
}
- out->endString(state);
} else {
dx = dy = 0;
p = s->getCString();
len = s->getLength();
nChars = nSpaces = 0;
while (len > 0) {
n = font->getNextChar(p, len, &code,
u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
&dx2, &dy2, &originX, &originY);
dx += dx2;
dy += dy2;
if (n == 1 && *p == ' ') {
++nSpaces;
}
++nChars;
p += n;
len -= n;
}
- dx = dx * state->getFontSize()
- + nChars * state->getCharSpace()
- + nSpaces * state->getWordSpace();
- dx *= state->getHorizScaling();
- dy *= state->getFontSize();
+ if (wMode) {
+ dx *= state->getFontSize();
+ dy = dy * state->getFontSize()
+ + nChars * state->getCharSpace()
+ + nSpaces * state->getWordSpace();
+ } else {
+ dx = dx * state->getFontSize()
+ + nChars * state->getCharSpace()
+ + nSpaces * state->getWordSpace();
+ dx *= state->getHorizScaling();
+ dy *= state->getFontSize();
+ }
state->textTransformDelta(dx, dy, &tdx, &tdy);
out->drawString(state, s);
state->shift(tdx, tdy);
}
+
+ if (out->useDrawChar()) {
+ out->endString(state);
+ }
+
+ updateLevel += 10 * s->getLength();
}
//------------------------------------------------------------------------
// XObject operators
//------------------------------------------------------------------------
void Gfx::opXObject(Object args[], int numArgs) {
- Object obj1, obj2, refObj;
+ Object obj1, obj2, obj3, refObj;
#if OPI_SUPPORT
Object opiDict;
#endif
if (!res->lookupXObject(args[0].getName(), &obj1)) {
return;
}
if (!obj1.isStream()) {
error(getPos(), "XObject '%s' is wrong type", args[0].getName());
obj1.free();
return;
}
#if OPI_SUPPORT
obj1.streamGetDict()->lookup("OPI", &opiDict);
if (opiDict.isDict()) {
out->opiBegin(state, opiDict.getDict());
}
#endif
obj1.streamGetDict()->lookup("Subtype", &obj2);
if (obj2.isName("Image")) {
res->lookupXObjectNF(args[0].getName(), &refObj);
doImage(&refObj, obj1.getStream(), gFalse);
refObj.free();
} else if (obj2.isName("Form")) {
doForm(&obj1);
+ } else if (obj2.isName("PS")) {
+ obj1.streamGetDict()->lookup("Level1", &obj3);
+ out->psXObject(obj1.getStream(),
+ obj3.isStream() ? obj3.getStream() : (Stream *)NULL);
} else if (obj2.isName()) {
error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
} else {
error(getPos(), "XObject subtype is missing or wrong type");
}
obj2.free();
#if OPI_SUPPORT
if (opiDict.isDict()) {
out->opiEnd(state, opiDict.getDict());
}
opiDict.free();
#endif
obj1.free();
}
void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
Dict *dict;
int width, height;
int bits;
GBool mask;
GBool invert;
GfxColorSpace *colorSpace;
GfxImageColorMap *colorMap;
Object maskObj;
GBool haveMask;
int maskColors[2*gfxColorMaxComps];
Object obj1, obj2;
int i;
// get stream dict
dict = str->getDict();
// get size
dict->lookup("Width", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("W", &obj1);
}
if (!obj1.isInt())
goto err2;
width = obj1.getInt();
obj1.free();
dict->lookup("Height", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("H", &obj1);
}
if (!obj1.isInt())
goto err2;
height = obj1.getInt();
obj1.free();
// image or mask?
dict->lookup("ImageMask", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("IM", &obj1);
}
mask = gFalse;
if (obj1.isBool())
mask = obj1.getBool();
else if (!obj1.isNull())
goto err2;
obj1.free();
// bit depth
dict->lookup("BitsPerComponent", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("BPC", &obj1);
}
if (!obj1.isInt())
goto err2;
bits = obj1.getInt();
obj1.free();
// display a mask
if (mask) {
// check for inverted mask
if (bits != 1)
goto err1;
invert = gFalse;
dict->lookup("Decode", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("D", &obj1);
}
if (obj1.isArray()) {
obj1.arrayGet(0, &obj2);
if (obj2.isInt() && obj2.getInt() == 1)
invert = gTrue;
obj2.free();
} else if (!obj1.isNull()) {
goto err2;
}
obj1.free();
// draw it
out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
} else {
// get color space and color map
dict->lookup("ColorSpace", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("CS", &obj1);
}
if (obj1.isName()) {
res->lookupColorSpace(obj1.getName(), &obj2);
if (!obj2.isNull()) {
obj1.free();
obj1 = obj2;
} else {
obj2.free();
}
}
colorSpace = GfxColorSpace::parse(&obj1);
obj1.free();
if (!colorSpace) {
goto err1;
}
dict->lookup("Decode", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("D", &obj1);
}
colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
obj1.free();
if (!colorMap->isOk()) {
delete colorMap;
goto err1;
}
// get the mask
haveMask = gFalse;
dict->lookup("Mask", &maskObj);
if (maskObj.isArray()) {
for (i = 0; i < maskObj.arrayGetLength(); ++i) {
maskObj.arrayGet(i, &obj1);
maskColors[i] = obj1.getInt();
obj1.free();
}
haveMask = gTrue;
}
// draw it
out->drawImage(state, ref, str, width, height, colorMap,
haveMask ? maskColors : (int *)NULL, inlineImg);
delete colorMap;
maskObj.free();
}
+ if ((i = width * height) > 1000) {
+ i = 1000;
+ }
+ updateLevel += i;
+
return;
err2:
obj1.free();
err1:
error(getPos(), "Bad image parameters");
}
void Gfx::doForm(Object *str) {
Dict *dict;
Object matrixObj, bboxObj;
fouble m[6], bbox[6];
Object resObj;
Dict *resDict;
Object obj1;
int i;
// get stream dict
dict = str->streamGetDict();
// check form type
dict->lookup("FormType", &obj1);
if (!(obj1.isInt() && obj1.getInt() == 1)) {
error(getPos(), "Unknown form type");
}
obj1.free();
// get bounding box
dict->lookup("BBox", &bboxObj);
if (!bboxObj.isArray()) {
matrixObj.free();
bboxObj.free();
error(getPos(), "Bad form bounding box");
return;
}
for (i = 0; i < 4; ++i) {
bboxObj.arrayGet(i, &obj1);
bbox[i] = obj1.getNum();
obj1.free();
}
bboxObj.free();
// get matrix
dict->lookup("Matrix", &matrixObj);
if (matrixObj.isArray()) {
for (i = 0; i < 6; ++i) {
matrixObj.arrayGet(i, &obj1);
m[i] = obj1.getNum();
obj1.free();
}
} else {
m[0] = 1; m[1] = 0;
m[2] = 0; m[3] = 1;
m[4] = 0; m[5] = 0;
}
matrixObj.free();
// get resources
dict->lookup("Resources", &resObj);
resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
// draw it
doForm1(str, resDict, m, bbox);
resObj.free();
}
-void Gfx::doWidgetForm(Object *str, fouble xMin, fouble yMin,
- fouble xMax, fouble yMax) {
+void Gfx::doAnnot(Object *str, fouble xMin, fouble yMin,
+ fouble xMax, fouble yMax) {
Dict *dict, *resDict;
Object matrixObj, bboxObj, resObj;
Object obj1;
- fouble m[6], bbox[6];
- fouble sx, sy;
+ fouble m[6], bbox[6], ictm[6];
+ fouble *ctm;
+ fouble formX0, formY0, formX1, formY1;
+ fouble annotX0, annotY0, annotX1, annotY1;
+ fouble det, x, y, sx, sy;
int i;
// get stream dict
dict = str->streamGetDict();
- // get bounding box
+ // get the form bounding box
dict->lookup("BBox", &bboxObj);
if (!bboxObj.isArray()) {
bboxObj.free();
error(getPos(), "Bad form bounding box");
return;
}
for (i = 0; i < 4; ++i) {
bboxObj.arrayGet(i, &obj1);
bbox[i] = obj1.getNum();
obj1.free();
}
bboxObj.free();
- // get matrix
+ // get the form matrix
dict->lookup("Matrix", &matrixObj);
if (matrixObj.isArray()) {
for (i = 0; i < 6; ++i) {
matrixObj.arrayGet(i, &obj1);
m[i] = obj1.getNum();
obj1.free();
}
} else {
m[0] = 1; m[1] = 0;
m[2] = 0; m[3] = 1;
m[4] = 0; m[5] = 0;
}
matrixObj.free();
- // scale form bbox to widget rectangle
- sx = fabs((xMax - xMin) / (bbox[2] - bbox[0]));
- sy = fabs((yMax - yMin) / (bbox[3] - bbox[1]));
- m[0] *= sx; m[1] *= sy;
- m[2] *= sx; m[3] *= sy;
- m[4] *= sx; m[5] *= sy;
+ // transform the form bbox from form space to user space
+ formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
+ formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
+ formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
+ formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
+
+ // transform the annotation bbox from default user space to user
+ // space: (bbox * baseMatrix) * iCTM
+ ctm = state->getCTM();
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+ x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4];
+ y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5];
+ annotX0 = ictm[0] * x + ictm[2] * y + ictm[4];
+ annotY0 = ictm[1] * x + ictm[3] * y + ictm[5];
+ x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4];
+ y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5];
+ annotX1 = ictm[0] * x + ictm[2] * y + ictm[4];
+ annotY1 = ictm[1] * x + ictm[3] * y + ictm[5];
+
+ // swap min/max coords
+ if (formX0 > formX1) {
+ x = formX0; formX0 = formX1; formX1 = x;
+ }
+ if (formY0 > formY1) {
+ y = formY0; formY0 = formY1; formY1 = y;
+ }
+ if (annotX0 > annotX1) {
+ x = annotX0; annotX0 = annotX1; annotX1 = x;
+ }
+ if (annotY0 > annotY1) {
+ y = annotY0; annotY0 = annotY1; annotY1 = y;
+ }
- // translate to widget rectangle
- m[4] += xMin;
- m[5] += yMin;
+ // scale the form to fit the annotation bbox
+ if (formX1 == formX0) {
+ // this shouldn't happen
+ sx = 1;
+ } else {
+ sx = (annotX1 - annotX0) / (formX1 - formX0);
+ }
+ if (formY1 == formY0) {
+ // this shouldn't happen
+ sy = 1;
+ } else {
+ sy = (annotY1 - annotY0) / (formY1 - formY0);
+ }
+ m[0] *= sx;
+ m[2] *= sx;
+ m[4] = (m[4] - formX0) * sx + annotX0;
+ m[1] *= sy;
+ m[3] *= sy;
+ m[5] = (m[5] - formY0) * sy + annotY0;
// get resources
dict->lookup("Resources", &resObj);
resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
// draw it
doForm1(str, resDict, m, bbox);
resObj.free();
bboxObj.free();
}
void Gfx::doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox) {
Parser *oldParser;
fouble oldBaseMatrix[6];
- GfxResources *resPtr;
int i;
// push new resources on stack
- res = new GfxResources(xref, resDict, res);
+ pushResources(resDict);
// save current graphics state
out->saveState(state);
state = state->save();
// save current parser
oldParser = parser;
// set form transformation matrix
state->concatCTM(matrix[0], matrix[1], matrix[2],
matrix[3], matrix[4], matrix[5]);
out->updateCTM(state, matrix[0], matrix[1], matrix[2],
matrix[3], matrix[4], matrix[5]);
// set new base matrix
for (i = 0; i < 6; ++i) {
oldBaseMatrix[i] = baseMatrix[i];
baseMatrix[i] = state->getCTM()[i];
}
// set form bounding box
state->moveTo(bbox[0], bbox[1]);
state->lineTo(bbox[2], bbox[1]);
state->lineTo(bbox[2], bbox[3]);
state->lineTo(bbox[0], bbox[3]);
state->closePath();
state->clip();
out->clip(state);
state->clearPath();
// draw the form
display(str, gFalse);
// restore base matrix
for (i = 0; i < 6; ++i) {
baseMatrix[i] = oldBaseMatrix[i];
}
// restore parser
parser = oldParser;
// restore graphics state
state = state->restore();
out->restoreState(state);
// pop resource stack
+ popResources();
+
+ return;
+}
+
+void Gfx::pushResources(Dict *resDict) {
+ res = new GfxResources(xref, resDict, res);
+}
+
+void Gfx::popResources() {
+ GfxResources *resPtr;
+
resPtr = res->getNext();
delete res;
res = resPtr;
-
- return;
}
//------------------------------------------------------------------------
// in-line image operators
//------------------------------------------------------------------------
void Gfx::opBeginImage(Object args[], int numArgs) {
Stream *str;
int c1, c2;
// build dict/stream
str = buildImageStream();
// display the image
if (str) {
doImage(NULL, str, gTrue);
// skip 'EI' tag
c1 = str->getBaseStream()->getChar();
c2 = str->getBaseStream()->getChar();
while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) {
c1 = c2;
c2 = str->getBaseStream()->getChar();
}
delete str;
}
}
Stream *Gfx::buildImageStream() {
Object dict;
Object obj;
char *key;
Stream *str;
// build dictionary
dict.initDict(xref);
parser->getObj(&obj);
while (!obj.isCmd("ID") && !obj.isEOF()) {
if (!obj.isName()) {
error(getPos(), "Inline image dictionary key must be a name object");
obj.free();
- parser->getObj(&obj);
} else {
key = copyString(obj.getName());
obj.free();
parser->getObj(&obj);
- if (obj.isEOF() || obj.isError())
+ if (obj.isEOF() || obj.isError()) {
+ gfree(key);
break;
+ }
dict.dictAdd(key, &obj);
}
parser->getObj(&obj);
}
- if (obj.isEOF())
+ if (obj.isEOF()) {
error(getPos(), "End of file in inline image");
+ obj.free();
+ dict.free();
+ return NULL;
+ }
obj.free();
// make stream
str = new EmbedStream(parser->getStream(), &dict);
str = str->addFilters(&dict);
return str;
}
void Gfx::opImageData(Object args[], int numArgs) {
error(getPos(), "Internal: got 'ID' operator");
}
void Gfx::opEndImage(Object args[], int numArgs) {
error(getPos(), "Internal: got 'EI' operator");
}
//------------------------------------------------------------------------
// type 3 font operators
//------------------------------------------------------------------------
void Gfx::opSetCharWidth(Object args[], int numArgs) {
- error(getPos(), "Encountered 'd0' operator in content stream");
+ out->type3D0(state, args[0].getNum(), args[1].getNum());
}
void Gfx::opSetCacheDevice(Object args[], int numArgs) {
- error(getPos(), "Encountered 'd1' operator in content stream");
+ out->type3D1(state, args[0].getNum(), args[1].getNum(),
+ args[2].getNum(), args[3].getNum(),
+ args[4].getNum(), args[5].getNum());
}
//------------------------------------------------------------------------
// compatibility operators
//------------------------------------------------------------------------
void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) {
++ignoreUndef;
}
void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
if (ignoreUndef > 0)
--ignoreUndef;
}
//------------------------------------------------------------------------
// marked content operators
//------------------------------------------------------------------------
void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
if (printCommands) {
printf(" marked content: %s ", args[0].getName());
if (numArgs == 2)
args[2].print(stdout);
printf("\n");
fflush(stdout);
}
}
void Gfx::opEndMarkedContent(Object args[], int numArgs) {
}
void Gfx::opMarkPoint(Object args[], int numArgs) {
if (printCommands) {
printf(" mark point: %s ", args[0].getName());
if (numArgs == 2)
args[2].print(stdout);
printf("\n");
fflush(stdout);
}
}
diff --git a/noncore/unsupported/qpdf/xpdf/Gfx.h b/noncore/unsupported/qpdf/xpdf/Gfx.h
index be5f2c2..2ecfb24 100644
--- a/noncore/unsupported/qpdf/xpdf/Gfx.h
+++ b/noncore/unsupported/qpdf/xpdf/Gfx.h
@@ -1,240 +1,252 @@
//========================================================================
//
// Gfx.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef GFX_H
#define GFX_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
class GString;
class XRef;
class Array;
class Stream;
class Parser;
class Dict;
class OutputDev;
class GfxFontDict;
class GfxFont;
class GfxPattern;
class GfxShading;
class GfxAxialShading;
+class GfxRadialShading;
class GfxState;
class Gfx;
struct PDFRectangle;
//------------------------------------------------------------------------
// Gfx
//------------------------------------------------------------------------
enum GfxClipType {
clipNone,
clipNormal,
clipEO
};
enum TchkType {
tchkBool, // boolean
tchkInt, // integer
tchkNum, // number (integer or real)
tchkString, // string
tchkName, // name
tchkArray, // array
tchkProps, // properties (dictionary or name)
tchkSCN, // scn/SCN args (number of name)
tchkNone // used to avoid empty initializer lists
};
#define maxArgs 8
struct Operator {
char name[4];
int numArgs;
TchkType tchk[maxArgs];
void (Gfx::*func)(Object args[], int numArgs);
};
class GfxResources {
public:
GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA);
~GfxResources();
GfxFont *lookupFont(char *name);
GBool lookupXObject(char *name, Object *obj);
GBool lookupXObjectNF(char *name, Object *obj);
void lookupColorSpace(char *name, Object *obj);
GfxPattern *lookupPattern(char *name);
GfxShading *lookupShading(char *name);
GBool lookupGState(char *name, Object *obj);
GfxResources *getNext() { return next; }
private:
GfxFontDict *fonts;
Object xObjDict;
Object colorSpaceDict;
Object patternDict;
Object shadingDict;
Object gStateDict;
GfxResources *next;
};
class Gfx {
public:
// Constructor for regular output.
Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, fouble dpi,
PDFRectangle *box, GBool crop, PDFRectangle *cropBox, int rotate,
GBool printCommandsA);
- // Destructor.
+ // Constructor for a sub-page object.
+ Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
+ PDFRectangle *box, GBool crop, PDFRectangle *cropBox);
+
~Gfx();
// Interpret a stream or array of streams.
void display(Object *obj, GBool topLevel = gTrue);
- void doWidgetForm(Object *str, fouble xMin, fouble yMin,
- fouble xMax, fouble yMax);
+ // Display an annotation, given its appearance (a Form XObject) and
+ // bounding box (in default user space).
+ void doAnnot(Object *str, fouble xMin, fouble yMin,
+ fouble xMax, fouble yMax);
+
+ void pushResources(Dict *resDict);
+ void popResources();
private:
XRef *xref; // the xref table for this PDF file
OutputDev *out; // output device
+ GBool subPage; // is this a sub-page object?
GBool printCommands; // print the drawing commands (for debugging)
GfxResources *res; // resource stack
+ int updateLevel;
GfxState *state; // current graphics state
GBool fontChanged; // set if font or text matrix has changed
GfxClipType clip; // do a clip?
int ignoreUndef; // current BX/EX nesting level
fouble baseMatrix[6]; // default matrix for most recent
// page/form/pattern
Parser *parser; // parser for page content stream(s)
static Operator opTab[]; // table of operators
void go(GBool topLevel);
void execOp(Object *cmd, Object args[], int numArgs);
Operator *findOp(char *name);
GBool checkArg(Object *arg, TchkType type);
int getPos();
// graphics state operators
void opSave(Object args[], int numArgs);
void opRestore(Object args[], int numArgs);
void opConcat(Object args[], int numArgs);
void opSetDash(Object args[], int numArgs);
void opSetFlat(Object args[], int numArgs);
void opSetLineJoin(Object args[], int numArgs);
void opSetLineCap(Object args[], int numArgs);
void opSetMiterLimit(Object args[], int numArgs);
void opSetLineWidth(Object args[], int numArgs);
void opSetExtGState(Object args[], int numArgs);
void opSetRenderingIntent(Object args[], int numArgs);
// color operators
void opSetFillGray(Object args[], int numArgs);
void opSetStrokeGray(Object args[], int numArgs);
void opSetFillCMYKColor(Object args[], int numArgs);
void opSetStrokeCMYKColor(Object args[], int numArgs);
void opSetFillRGBColor(Object args[], int numArgs);
void opSetStrokeRGBColor(Object args[], int numArgs);
void opSetFillColorSpace(Object args[], int numArgs);
void opSetStrokeColorSpace(Object args[], int numArgs);
void opSetFillColor(Object args[], int numArgs);
void opSetStrokeColor(Object args[], int numArgs);
void opSetFillColorN(Object args[], int numArgs);
void opSetStrokeColorN(Object args[], int numArgs);
// path segment operators
void opMoveTo(Object args[], int numArgs);
void opLineTo(Object args[], int numArgs);
void opCurveTo(Object args[], int numArgs);
void opCurveTo1(Object args[], int numArgs);
void opCurveTo2(Object args[], int numArgs);
void opRectangle(Object args[], int numArgs);
void opClosePath(Object args[], int numArgs);
// path painting operators
void opEndPath(Object args[], int numArgs);
void opStroke(Object args[], int numArgs);
void opCloseStroke(Object args[], int numArgs);
void opFill(Object args[], int numArgs);
void opEOFill(Object args[], int numArgs);
void opFillStroke(Object args[], int numArgs);
void opCloseFillStroke(Object args[], int numArgs);
void opEOFillStroke(Object args[], int numArgs);
void opCloseEOFillStroke(Object args[], int numArgs);
void doPatternFill(GBool eoFill);
void opShFill(Object args[], int numArgs);
void doAxialShFill(GfxAxialShading *shading);
+ void doRadialShFill(GfxRadialShading *shading);
void doEndPath();
// path clipping operators
void opClip(Object args[], int numArgs);
void opEOClip(Object args[], int numArgs);
// text object operators
void opBeginText(Object args[], int numArgs);
void opEndText(Object args[], int numArgs);
// text state operators
void opSetCharSpacing(Object args[], int numArgs);
void opSetFont(Object args[], int numArgs);
void opSetTextLeading(Object args[], int numArgs);
void opSetTextRender(Object args[], int numArgs);
void opSetTextRise(Object args[], int numArgs);
void opSetWordSpacing(Object args[], int numArgs);
void opSetHorizScaling(Object args[], int numArgs);
// text positioning operators
void opTextMove(Object args[], int numArgs);
void opTextMoveSet(Object args[], int numArgs);
void opSetTextMatrix(Object args[], int numArgs);
void opTextNextLine(Object args[], int numArgs);
// text string operators
void opShowText(Object args[], int numArgs);
void opMoveShowText(Object args[], int numArgs);
void opMoveSetShowText(Object args[], int numArgs);
void opShowSpaceText(Object args[], int numArgs);
void doShowText(GString *s);
// XObject operators
void opXObject(Object args[], int numArgs);
void doImage(Object *ref, Stream *str, GBool inlineImg);
void doForm(Object *str);
void doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox);
// in-line image operators
void opBeginImage(Object args[], int numArgs);
Stream *buildImageStream();
void opImageData(Object args[], int numArgs);
void opEndImage(Object args[], int numArgs);
// type 3 font operators
void opSetCharWidth(Object args[], int numArgs);
void opSetCacheDevice(Object args[], int numArgs);
// compatibility operators
void opBeginIgnoreUndef(Object args[], int numArgs);
void opEndIgnoreUndef(Object args[], int numArgs);
// marked content operators
void opBeginMarkedContent(Object args[], int numArgs);
void opEndMarkedContent(Object args[], int numArgs);
void opMarkPoint(Object args[], int numArgs);
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/GfxFont.cc b/noncore/unsupported/qpdf/xpdf/GfxFont.cc
index 518f97b..8d722d6 100644
--- a/noncore/unsupported/qpdf/xpdf/GfxFont.cc
+++ b/noncore/unsupported/qpdf/xpdf/GfxFont.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// GfxFont.cc
//
-// Copyright 1996-2001 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "gmem.h"
#include "Error.h"
#include "Object.h"
#include "Dict.h"
#include "GlobalParams.h"
#include "CMap.h"
#include "CharCodeToUnicode.h"
#include "FontEncodingTables.h"
#include "BuiltinFontTables.h"
#include "FontFile.h"
#include "GfxFont.h"
//------------------------------------------------------------------------
struct StdFontMapEntry {
char *altName;
char *properName;
};
static StdFontMapEntry stdFontMap[] = {
{ "Arial", "Helvetica" },
{ "Arial,Bold", "Helvetica-Bold" },
{ "Arial,BoldItalic", "Helvetica-BoldOblique" },
{ "Arial,Italic", "Helvetica-Oblique" },
{ "Arial-Bold", "Helvetica-Bold" },
{ "Arial-BoldItalic", "Helvetica-BoldOblique" },
{ "Arial-BoldItalicMT", "Helvetica-BoldOblique" },
{ "Arial-BoldMT", "Helvetica-Bold" },
{ "Arial-Italic", "Helvetica-Oblique" },
{ "Arial-ItalicMT", "Helvetica-Oblique" },
{ "ArialMT", "Helvetica" },
{ "Courier,Bold", "Courier-Bold" },
{ "Courier,Italic", "Courier-Oblique" },
{ "Courier,BoldItalic", "Courier-BoldOblique" },
{ "CourierNew", "Courier" },
{ "CourierNew,Bold", "Courier-Bold" },
{ "CourierNew,BoldItalic", "Courier-BoldOblique" },
{ "CourierNew,Italic", "Courier-Oblique" },
{ "CourierNew-Bold", "Courier-Bold" },
{ "CourierNew-BoldItalic", "Courier-BoldOblique" },
{ "CourierNew-Italic", "Courier-Oblique" },
{ "CourierNewPS-BoldItalicMT", "Courier-BoldOblique" },
{ "CourierNewPS-BoldMT", "Courier-Bold" },
{ "CourierNewPS-ItalicMT", "Courier-Oblique" },
{ "CourierNewPSMT", "Courier" },
{ "Helvetica,Bold", "Helvetica-Bold" },
{ "Helvetica,BoldItalic", "Helvetica-BoldOblique" },
{ "Helvetica,Italic", "Helvetica-Oblique" },
{ "Helvetica-BoldItalic", "Helvetica-BoldOblique" },
{ "Helvetica-Italic", "Helvetica-Oblique" },
{ "TimesNewRoman", "Times-Roman" },
{ "TimesNewRoman,Bold", "Times-Bold" },
{ "TimesNewRoman,BoldItalic", "Times-BoldItalic" },
{ "TimesNewRoman,Italic", "Times-Italic" },
{ "TimesNewRoman-Bold", "Times-Bold" },
{ "TimesNewRoman-BoldItalic", "Times-BoldItalic" },
{ "TimesNewRoman-Italic", "Times-Italic" },
{ "TimesNewRomanPS", "Times-Roman" },
{ "TimesNewRomanPS-Bold", "Times-Bold" },
{ "TimesNewRomanPS-BoldItalic", "Times-BoldItalic" },
{ "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" },
{ "TimesNewRomanPS-BoldMT", "Times-Bold" },
{ "TimesNewRomanPS-Italic", "Times-Italic" },
{ "TimesNewRomanPS-ItalicMT", "Times-Italic" },
{ "TimesNewRomanPSMT", "Times-Roman" }
};
//------------------------------------------------------------------------
// GfxFont
//------------------------------------------------------------------------
GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
GString *nameA;
GfxFont *font;
Object obj1;
// get base font name
nameA = NULL;
fontDict->lookup("BaseFont", &obj1);
if (obj1.isName()) {
nameA = new GString(obj1.getName());
}
obj1.free();
@@ -361,518 +361,554 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
return buf;
}
//------------------------------------------------------------------------
// Gfx8BitFont
//------------------------------------------------------------------------
Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
GfxFontType typeA, Dict *fontDict):
GfxFont(tagA, idA, nameA)
{
BuiltinFont *builtinFont;
char **baseEnc;
GBool baseEncFromFontFile;
char *buf;
int len;
FontFile *fontFile;
int code, code2;
char *charName;
GBool missing, hex;
Unicode toUnicode[256];
fouble mul;
int firstChar, lastChar;
Gushort w;
Object obj1, obj2, obj3;
int n, i, a, b, m;
type = typeA;
ctu = NULL;
// Acrobat 4.0 and earlier substituted Base14-compatible fonts
// without providing Widths and a FontDescriptor, so we munge the
// names into the proper Base14 names. (This table is from
// implementation note 44 in the PDF 1.4 spec.)
if (name) {
a = 0;
b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
// invariant: stdFontMap[a].altName <= name < stdFontMap[b].altName
while (b - a > 1) {
m = (a + b) / 2;
if (name->cmp(stdFontMap[m].altName) >= 0) {
a = m;
} else {
b = m;
}
}
if (!name->cmp(stdFontMap[a].altName)) {
delete name;
name = new GString(stdFontMap[a].properName);
}
}
// is it a built-in font?
builtinFont = NULL;
if (name) {
for (i = 0; i < nBuiltinFonts; ++i) {
if (!name->cmp(builtinFonts[i].name)) {
builtinFont = &builtinFonts[i];
break;
}
}
}
// default ascent/descent values
if (builtinFont) {
ascent = 0.001 * builtinFont->ascent;
descent = 0.001 * builtinFont->descent;
fontBBox[0] = 0.001 * builtinFont->bbox[0];
fontBBox[1] = 0.001 * builtinFont->bbox[1];
fontBBox[2] = 0.001 * builtinFont->bbox[2];
fontBBox[3] = 0.001 * builtinFont->bbox[3];
} else {
ascent = 0.95;
descent = -0.35;
fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
}
// get info from font descriptor
readFontDescriptor(xref, fontDict);
// look for an external font file
findExtFontFile();
// get font matrix
fontMat[0] = fontMat[3] = 1;
fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
if (obj1.arrayGet(i, &obj2)->isNum()) {
fontMat[i] = obj2.getNum();
}
obj2.free();
}
}
obj1.free();
- // get Type3 font definition
+ // get Type 3 bounding box, font definition, and resources
if (type == fontType3) {
- fontDict->lookup("CharProcs", &charProcs);
- if (!charProcs.isDict()) {
+ if (fontDict->lookup("FontBBox", &obj1)->isArray()) {
+ for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ fontBBox[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+ if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
charProcs.free();
}
+ if (!fontDict->lookup("Resources", &resources)->isDict()) {
+ resources.free();
+ }
}
//----- build the font encoding -----
// Encodings start with a base encoding, which can come from
// (in order of priority):
// 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
// - MacRoman / MacExpert / WinAnsi / Standard
// 2. embedded or external font file
// 3. default:
// - builtin --> builtin encoding
// - TrueType --> MacRomanEncoding
// - others --> StandardEncoding
// and then add a list of differences (if any) from
// FontDict.Encoding.Differences.
// check FontDict for base encoding
hasEncoding = gFalse;
baseEnc = NULL;
baseEncFromFontFile = gFalse;
fontDict->lookup("Encoding", &obj1);
if (obj1.isDict()) {
obj1.dictLookup("BaseEncoding", &obj2);
if (obj2.isName("MacRomanEncoding")) {
hasEncoding = gTrue;
baseEnc = macRomanEncoding;
} else if (obj2.isName("MacExpertEncoding")) {
hasEncoding = gTrue;
baseEnc = macExpertEncoding;
} else if (obj2.isName("WinAnsiEncoding")) {
hasEncoding = gTrue;
baseEnc = winAnsiEncoding;
} else if (obj2.isName("StandardEncoding")) {
hasEncoding = gTrue;
baseEnc = standardEncoding;
}
obj2.free();
} else if (obj1.isName("MacRomanEncoding")) {
hasEncoding = gTrue;
baseEnc = macRomanEncoding;
} else if (obj1.isName("MacExpertEncoding")) {
hasEncoding = gTrue;
baseEnc = macExpertEncoding;
} else if (obj1.isName("WinAnsiEncoding")) {
hasEncoding = gTrue;
baseEnc = winAnsiEncoding;
} else if (obj1.isName("StandardEncoding")) {
hasEncoding = gTrue;
baseEnc = standardEncoding;
}
// check embedded or external font file for base encoding
+ // (only for Type 1 fonts - trying to get an encoding out of a
+ // TrueType font is a losing proposition)
fontFile = NULL;
buf = NULL;
- if ((type == fontType1 || type == fontType1C || type == fontTrueType) &&
+ if ((type == fontType1 || type == fontType1C) &&
(extFontFile || embFontID.num >= 0)) {
if (extFontFile) {
buf = readExtFontFile(&len);
} else {
buf = readEmbFontFile(xref, &len);
}
if (buf) {
#if 0
+ if (type == fontType1C && !strncmp(buf, "%!", 2)) {
+ // various tools (including Adobe's) occasionally embed Type 1
+ // fonts but label them Type 1C
+ type = fontType1;
+ }
if (type == fontType1) {
fontFile = new Type1FontFile(buf, len);
- } else if (type == fontType1C) {
- fontFile = new Type1CFontFile(buf, len);
} else {
- fontFile = new TrueTypeFontFile(buf, len);
+ fontFile = new Type1CFontFile(buf, len);
}
if (fontFile->getName()) {
if (embFontName) {
delete embFontName;
}
embFontName = new GString(fontFile->getName());
}
if (!baseEnc) {
baseEnc = fontFile->getEncoding();
baseEncFromFontFile = gTrue;
}
#endif
gfree(buf);
}
}
// get default base encoding
if (!baseEnc) {
if (builtinFont) {
baseEnc = builtinFont->defaultBaseEnc;
} else if (type == fontTrueType) {
baseEnc = macRomanEncoding;
} else {
baseEnc = standardEncoding;
}
}
// copy the base encoding
for (i = 0; i < 256; ++i) {
enc[i] = baseEnc[i];
if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
enc[i] = copyString(baseEnc[i]);
}
}
// merge differences into encoding
if (obj1.isDict()) {
obj1.dictLookup("Differences", &obj2);
if (obj2.isArray()) {
+ hasEncoding = gTrue;
code = 0;
for (i = 0; i < obj2.arrayGetLength(); ++i) {
obj2.arrayGet(i, &obj3);
if (obj3.isInt()) {
code = obj3.getInt();
} else if (obj3.isName()) {
if (code < 256) {
if (encFree[code]) {
gfree(enc[code]);
}
enc[code] = copyString(obj3.getName());
encFree[code] = gTrue;
}
++code;
} else {
error(-1, "Wrong type in font encoding resource differences (%s)",
obj3.getTypeName());
}
obj3.free();
}
}
obj2.free();
}
obj1.free();
if (fontFile) {
delete fontFile;
}
//----- build the mapping to Unicode -----
// look for a ToUnicode CMap
if (!(ctu = readToUnicodeCMap(fontDict, 8))) {
// no ToUnicode CMap, so use the char names
// pass 1: use the name-to-Unicode mapping table
missing = hex = gFalse;
for (code = 0; code < 256; ++code) {
if ((charName = enc[code])) {
if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
strcmp(charName, ".notdef")) {
// if it wasn't in the name-to-Unicode table, check for a
// name that looks like 'Axx' or 'xx', where 'A' is any letter
// and 'xx' is two hex digits
if ((strlen(charName) == 3 &&
isalpha(charName[0]) &&
isxdigit(charName[1]) && isxdigit(charName[2]) &&
((charName[1] >= 'a' && charName[1] <= 'f') ||
(charName[1] >= 'A' && charName[1] <= 'F') ||
(charName[2] >= 'a' && charName[2] <= 'f') ||
(charName[2] >= 'A' && charName[2] <= 'F'))) ||
(strlen(charName) == 2 &&
isxdigit(charName[0]) && isxdigit(charName[1]) &&
((charName[0] >= 'a' && charName[0] <= 'f') ||
(charName[0] >= 'A' && charName[0] <= 'F') ||
(charName[1] >= 'a' && charName[1] <= 'f') ||
(charName[1] >= 'A' && charName[1] <= 'F')))) {
hex = gTrue;
}
missing = gTrue;
}
} else {
toUnicode[code] = 0;
}
}
// pass 2: try to fill in the missing chars, looking for names of
- // the form 'Axx', 'xx', 'Ann', or 'nn', where 'A' is any letter,
- // 'xx' is two hex digits, and 'nn' is 2-4 decimal digits
+ // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B'
+ // are any letters, 'xx' is two hex digits, and 'nn' is 2-4
+ // decimal digits
if (missing && globalParams->getMapNumericCharNames()) {
for (code = 0; code < 256; ++code) {
if ((charName = enc[code]) && !toUnicode[code] &&
strcmp(charName, ".notdef")) {
n = strlen(charName);
code2 = -1;
if (hex && n == 3 && isalpha(charName[0]) &&
isxdigit(charName[1]) && isxdigit(charName[2])) {
sscanf(charName+1, "%x", &code2);
} else if (hex && n == 2 &&
isxdigit(charName[0]) && isxdigit(charName[1])) {
sscanf(charName, "%x", &code2);
} else if (!hex && n >= 2 && n <= 4 &&
isdigit(charName[0]) && isdigit(charName[1])) {
code2 = atoi(charName);
} else if (n >= 3 && n <= 5 &&
isdigit(charName[1]) && isdigit(charName[2])) {
code2 = atoi(charName+1);
+ } else if (n >= 4 && n <= 6 &&
+ isdigit(charName[2]) && isdigit(charName[3])) {
+ code2 = atoi(charName+2);
}
if (code2 >= 0 && code2 <= 0xff) {
toUnicode[code] = (Unicode)code2;
}
}
}
}
ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
}
//----- get the character widths -----
// initialize all widths
for (code = 0; code < 256; ++code) {
widths[code] = missingWidth * 0.001;
}
// use widths from font dict, if present
fontDict->lookup("FirstChar", &obj1);
firstChar = obj1.isInt() ? obj1.getInt() : 0;
obj1.free();
fontDict->lookup("LastChar", &obj1);
lastChar = obj1.isInt() ? obj1.getInt() : 255;
obj1.free();
mul = (type == fontType3) ? fontMat[0] : fouble(0.001);
fontDict->lookup("Widths", &obj1);
if (obj1.isArray()) {
+ flags |= fontFixedWidth;
for (code = firstChar; code <= lastChar; ++code) {
obj1.arrayGet(code - firstChar, &obj2);
if (obj2.isNum()) {
widths[code] = obj2.getNum() * mul;
+ if (widths[code] != widths[firstChar]) {
+ flags &= ~fontFixedWidth;
+ }
}
obj2.free();
}
// use widths from built-in font
} else if (builtinFont) {
// this is a kludge for broken PDF files that encode char 32
// as .notdef
if (builtinFont->widths->getWidth("space", &w)) {
widths[32] = 0.001 * w;
}
for (code = 0; code < 256; ++code) {
if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
widths[code] = 0.001 * w;
}
}
// couldn't find widths -- use defaults
} else {
// this is technically an error -- the Widths entry is required
// for all but the Base-14 fonts -- but certain PDF generators
// apparently don't include widths for Arial and TimesNewRoman
if (isFixedWidth()) {
i = 0;
} else if (isSerif()) {
i = 8;
} else {
i = 4;
}
if (isBold()) {
i += 2;
}
if (isItalic()) {
i += 1;
}
builtinFont = builtinFontSubst[i];
// this is a kludge for broken PDF files that encode char 32
// as .notdef
if (builtinFont->widths->getWidth("space", &w)) {
widths[32] = 0.001 * w;
}
for (code = 0; code < 256; ++code) {
if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
widths[code] = 0.001 * w;
}
}
}
obj1.free();
ok = gTrue;
}
Gfx8BitFont::~Gfx8BitFont() {
int i;
for (i = 0; i < 256; ++i) {
if (encFree[i] && enc[i]) {
gfree(enc[i]);
}
}
ctu->decRefCnt();
if (charProcs.isDict()) {
charProcs.free();
}
+ if (resources.isDict()) {
+ resources.free();
+ }
}
int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code,
Unicode *u, int uSize, int *uLen,
fouble *dx, fouble *dy, fouble *ox, fouble *oy) {
CharCode c;
*code = c = (CharCode)(*s & 0xff);
*uLen = ctu->mapToUnicode(c, u, uSize);
*dx = widths[c];
*dy = *ox = *oy = 0;
return 1;
}
CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
ctu->incRefCnt();
return ctu;
}
+Dict *Gfx8BitFont::getCharProcs() {
+ return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
+}
+
Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
if (charProcs.isDict()) {
charProcs.dictLookup(enc[code], proc);
} else {
proc->initNull();
}
return proc;
}
+Dict *Gfx8BitFont::getResources() {
+ return resources.isDict() ? resources.getDict() : (Dict *)NULL;
+}
+
//------------------------------------------------------------------------
// GfxCIDFont
//------------------------------------------------------------------------
static int cmpWidthExcep(const void *w1, const void *w2) {
return ((GfxFontCIDWidthExcep *)w1)->first -
((GfxFontCIDWidthExcep *)w2)->first;
}
static int cmpWidthExcepV(const void *w1, const void *w2) {
return ((GfxFontCIDWidthExcepV *)w1)->first -
((GfxFontCIDWidthExcepV *)w2)->first;
}
GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
Dict *fontDict):
GfxFont(tagA, idA, nameA)
{
Dict *desFontDict;
GString *collection, *cMapName;
Object desFontDictObj;
Object obj1, obj2, obj3, obj4, obj5, obj6;
int c1, c2;
int excepsSize, i, j, k;
ascent = 0.95;
descent = -0.35;
fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
cMap = NULL;
ctu = NULL;
widths.defWidth = 1.0;
widths.defHeight = -1.0;
widths.defVY = 0.880;
widths.exceps = NULL;
widths.nExceps = 0;
widths.excepsV = NULL;
widths.nExcepsV = 0;
cidToGID = NULL;
cidToGIDLen = 0;
// get the descendant font
if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
error(-1, "Missing DescendantFonts entry in Type 0 font");
obj1.free();
goto err1;
}
if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
error(-1, "Bad descendant font in Type 0 font");
goto err3;
}
obj1.free();
desFontDict = desFontDictObj.getDict();
// font type
if (!desFontDict->lookup("Subtype", &obj1)) {
error(-1, "Missing Subtype entry in Type 0 descendant font");
goto err3;
}
if (obj1.isName("CIDFontType0")) {
type = fontCIDType0;
} else if (obj1.isName("CIDFontType2")) {
type = fontCIDType2;
} else {
error(-1, "Unknown Type 0 descendant font type '%s'",
obj1.isName() ? obj1.getName() : "???");
goto err3;
}
obj1.free();
// get info from font descriptor
readFontDescriptor(xref, desFontDict);
// look for an external font file
findExtFontFile();
//----- encoding info -----
// char collection
if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font");
goto err3;
}
obj1.dictLookup("Registry", &obj2);
obj1.dictLookup("Ordering", &obj3);
if (!obj2.isString() || !obj3.isString()) {
error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
goto err4;
}
collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
obj3.free();
obj2.free();
obj1.free();
// look for a ToUnicode CMap
if (!(ctu = readToUnicodeCMap(fontDict, 16))) {
@@ -1093,155 +1129,159 @@ GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
obj1.free();
err2:
desFontDictObj.free();
err1:;
}
GfxCIDFont::~GfxCIDFont() {
if (cMap) {
cMap->decRefCnt();
}
if (ctu) {
ctu->decRefCnt();
}
gfree(widths.exceps);
gfree(widths.excepsV);
if (cidToGID) {
gfree(cidToGID);
}
}
int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
Unicode *u, int uSize, int *uLen,
fouble *dx, fouble *dy, fouble *ox, fouble *oy) {
CID cid;
fouble w, h, vx, vy;
int n, a, b, m;
if (!cMap) {
*code = 0;
*uLen = 0;
*dx = *dy = 0;
return 1;
}
*code = (CharCode)(cid = cMap->getCID(s, len, &n));
if (ctu) {
*uLen = ctu->mapToUnicode(cid, u, uSize);
} else {
*uLen = 0;
}
// horizontal
if (cMap->getWMode() == 0) {
w = widths.defWidth;
h = vx = vy = 0;
if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
a = 0;
b = widths.nExceps;
// invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
while (b - a > 1) {
m = (a + b) / 2;
if (widths.exceps[m].first <= cid) {
a = m;
} else {
b = m;
}
}
if (cid <= widths.exceps[a].last) {
w = widths.exceps[a].width;
}
}
// vertical
} else {
w = 0;
h = widths.defHeight;
vx = widths.defWidth / 2;
vy = widths.defVY;
if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) {
a = 0;
b = widths.nExcepsV;
// invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first
while (b - a > 1) {
m = (a + b) / 2;
if (widths.excepsV[m].last <= cid) {
a = m;
} else {
b = m;
}
}
if (cid <= widths.excepsV[a].last) {
h = widths.excepsV[a].height;
vx = widths.excepsV[a].vx;
vy = widths.excepsV[a].vy;
}
}
}
*dx = w;
*dy = h;
*ox = vx;
*oy = vy;
return n;
}
+int GfxCIDFont::getWMode() {
+ return cMap ? cMap->getWMode() : 0;
+}
+
CharCodeToUnicode *GfxCIDFont::getToUnicode() {
ctu->incRefCnt();
return ctu;
}
GString *GfxCIDFont::getCollection() {
return cMap ? cMap->getCollection() : (GString *)NULL;
}
//------------------------------------------------------------------------
// GfxFontDict
//------------------------------------------------------------------------
GfxFontDict::GfxFontDict(XRef *xref, Dict *fontDict) {
int i;
Object obj1, obj2;
numFonts = fontDict->getLength();
fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *));
for (i = 0; i < numFonts; ++i) {
fontDict->getValNF(i, &obj1);
obj1.fetch(xref, &obj2);
if (obj1.isRef() && obj2.isDict()) {
fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
obj1.getRef(), obj2.getDict());
if (fonts[i] && !fonts[i]->isOk()) {
delete fonts[i];
fonts[i] = NULL;
}
} else {
- error(-1, "font resource is not a dictionary");
+ error(-1, "font resource is not a dictionary reference");
fonts[i] = NULL;
}
obj1.free();
obj2.free();
}
}
GfxFontDict::~GfxFontDict() {
int i;
for (i = 0; i < numFonts; ++i) {
if (fonts[i]) {
delete fonts[i];
}
}
gfree(fonts);
}
GfxFont *GfxFontDict::lookup(char *tag) {
int i;
for (i = 0; i < numFonts; ++i) {
if (fonts[i] && fonts[i]->matches(tag)) {
return fonts[i];
}
}
return NULL;
}
diff --git a/noncore/unsupported/qpdf/xpdf/GfxFont.h b/noncore/unsupported/qpdf/xpdf/GfxFont.h
index b1aa952..8e9fe38 100644
--- a/noncore/unsupported/qpdf/xpdf/GfxFont.h
+++ b/noncore/unsupported/qpdf/xpdf/GfxFont.h
@@ -1,286 +1,298 @@
//========================================================================
//
// GfxFont.h
//
-// Copyright 1996-2001 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef GFXFONT_H
#define GFXFONT_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
#include "GString.h"
#include "Object.h"
#include "CharTypes.h"
class Dict;
class CMap;
class CharCodeToUnicode;
struct GfxFontCIDWidths;
//------------------------------------------------------------------------
// GfxFontType
//------------------------------------------------------------------------
enum GfxFontType {
//----- Gfx8BitFont
fontUnknownType,
fontType1,
fontType1C,
fontType3,
fontTrueType,
//----- GfxCIDFont
fontCIDType0,
fontCIDType0C,
fontCIDType2
};
//------------------------------------------------------------------------
// GfxFontCIDWidths
//------------------------------------------------------------------------
struct GfxFontCIDWidthExcep {
CID first; // this record applies to
CID last; // CIDs <first>..<last>
fouble width; // char width
};
struct GfxFontCIDWidthExcepV {
CID first; // this record applies to
CID last; // CIDs <first>..<last>
fouble height; // char height
fouble vx, vy; // origin position
};
struct GfxFontCIDWidths {
fouble defWidth; // default char width
fouble defHeight; // default char height
fouble defVY; // default origin position
GfxFontCIDWidthExcep *exceps; // exceptions
int nExceps; // number of valid entries in exceps
GfxFontCIDWidthExcepV * // exceptions for vertical font
excepsV;
int nExcepsV; // number of valid entries in excepsV
};
//------------------------------------------------------------------------
// GfxFont
//------------------------------------------------------------------------
#define fontFixedWidth (1 << 0)
#define fontSerif (1 << 1)
#define fontSymbolic (1 << 2)
#define fontItalic (1 << 6)
#define fontBold (1 << 18)
class GfxFont {
public:
// Build a GfxFont object.
static GfxFont *makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict);
GfxFont(char *tagA, Ref idA, GString *nameA);
virtual ~GfxFont();
GBool isOk() { return ok; }
// Get font tag.
GString *getTag() { return tag; }
// Get font dictionary ID.
Ref *getID() { return &id; }
// Does this font match the tag?
GBool matches(char *tagA) { return !tag->cmp(tagA); }
// Get base font name.
GString *getName() { return name; }
// Get font type.
GfxFontType getType() { return type; }
virtual GBool isCIDFont() { return gFalse; }
// Get embedded font ID, i.e., a ref for the font file stream.
// Returns false if there is no embedded font.
GBool getEmbeddedFontID(Ref *embID)
{ *embID = embFontID; return embFontID.num >= 0; }
// Get the PostScript font name for the embedded font. Returns
// NULL if there is no embedded font.
- char *getEmbeddedFontName()
- { return embFontName ? embFontName->getCString() : (char *)NULL; }
+ GString *getEmbeddedFontName() { return embFontName; }
// Get the name of the external font file. Returns NULL if there
// is no external font file.
GString *getExtFontFile() { return extFontFile; }
// Get font descriptor flags.
GBool isFixedWidth() { return flags & fontFixedWidth; }
GBool isSerif() { return flags & fontSerif; }
GBool isSymbolic() { return flags & fontSymbolic; }
GBool isItalic() { return flags & fontItalic; }
GBool isBold() { return flags & fontBold; }
// Return the font matrix.
fouble *getFontMatrix() { return fontMat; }
// Return the font bounding box.
fouble *getFontBBox() { return fontBBox; }
// Return the ascent and descent values.
fouble getAscent() { return ascent; }
fouble getDescent() { return descent; }
+ // Return the writing mode (0=horizontal, 1=vertical).
+ virtual int getWMode() { return 0; }
+
// Read an external or embedded font file into a buffer.
char *readExtFontFile(int *len);
char *readEmbFontFile(XRef *xref, int *len);
// Get the next char from a string <s> of <len> bytes, returning the
// char <code>, its Unicode mapping <u>, its displacement vector
// (<dx>, <dy>), and its origin offset vector (<ox>, <oy>). <uSize>
// is the number of entries available in <u>, and <uLen> is set to
// the number actually used. Returns the number of bytes used by
// the char code.
virtual int getNextChar(char *s, int len, CharCode *code,
Unicode *u, int uSize, int *uLen,
fouble *dx, fouble *dy, fouble *ox, fouble *oy) = 0;
protected:
void readFontDescriptor(XRef *xref, Dict *fontDict);
CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits);
- void GfxFont::findExtFontFile();
+ void findExtFontFile();
GString *tag; // PDF font tag
Ref id; // reference (used as unique ID)
GString *name; // font name
GfxFontType type; // type of font
int flags; // font descriptor flags
GString *embFontName; // name of embedded font
Ref embFontID; // ref to embedded font file stream
GString *extFontFile; // external font file name
fouble fontMat[6]; // font matrix (Type 3 only)
- fouble fontBBox[4]; // font bounding box
+ fouble fontBBox[4]; // font bounding box (Type 3 only)
fouble missingWidth; // "default" width
fouble ascent; // max height above baseline
fouble descent; // max depth below baseline
GBool ok;
};
//------------------------------------------------------------------------
// Gfx8BitFont
//------------------------------------------------------------------------
class Gfx8BitFont: public GfxFont {
public:
Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
GfxFontType typeA, Dict *fontDict);
virtual ~Gfx8BitFont();
virtual int getNextChar(char *s, int len, CharCode *code,
Unicode *u, int uSize, int *uLen,
fouble *dx, fouble *dy, fouble *ox, fouble *oy);
// Return the encoding.
char **getEncoding() { return enc; }
// Return the Unicode map.
CharCodeToUnicode *getToUnicode();
// Return the character name associated with <code>.
char *getCharName(int code) { return enc[code]; }
// Returns true if the PDF font specified an encoding.
GBool getHasEncoding() { return hasEncoding; }
// Get width of a character or string.
fouble getWidth(Guchar c) { return widths[c]; }
+ // Return the Type 3 CharProc dictionary, or NULL if none.
+ Dict *getCharProcs();
+
// Return the Type 3 CharProc for the character associated with <code>.
Object *getCharProc(int code, Object *proc);
+ // Return the Type 3 Resources dictionary, or NULL if none.
+ Dict *getResources();
+
private:
char *enc[256]; // char code --> char name
char encFree[256]; // boolean for each char name: if set,
// the string is malloc'ed
CharCodeToUnicode *ctu; // char code --> Unicode
GBool hasEncoding;
fouble widths[256]; // character widths
- Object charProcs; // Type3 CharProcs dictionary
+ Object charProcs; // Type 3 CharProcs dictionary
+ Object resources; // Type 3 Resources dictionary
};
//------------------------------------------------------------------------
// GfxCIDFont
//------------------------------------------------------------------------
class GfxCIDFont: public GfxFont {
public:
GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
Dict *fontDict);
virtual ~GfxCIDFont();
virtual GBool isCIDFont() { return gTrue; }
virtual int getNextChar(char *s, int len, CharCode *code,
Unicode *u, int uSize, int *uLen,
fouble *dx, fouble *dy, fouble *ox, fouble *oy);
+ // Return the writing mode (0=horizontal, 1=vertical).
+ virtual int getWMode();
+
// Return the Unicode map.
CharCodeToUnicode *getToUnicode();
// Get the collection name (<registry>-<ordering>).
GString *getCollection();
// Return the CID-to-GID mapping table. These should only be called
// if type is fontCIDType2.
Gushort *getCIDToGID() { return cidToGID; }
int getCIDToGIDLen() { return cidToGIDLen; }
private:
CMap *cMap; // char code --> CID
CharCodeToUnicode *ctu; // CID --> Unicode
GfxFontCIDWidths widths; // character widths
Gushort *cidToGID; // CID --> GID mapping (for embedded
// TrueType fonts)
int cidToGIDLen;
};
//------------------------------------------------------------------------
// GfxFontDict
//------------------------------------------------------------------------
class GfxFontDict {
public:
// Build the font dictionary, given the PDF font dictionary.
GfxFontDict(XRef *xref, Dict *fontDict);
// Destructor.
~GfxFontDict();
// Get the specified font.
GfxFont *lookup(char *tag);
// Iterative access.
int getNumFonts() { return numFonts; }
GfxFont *getFont(int i) { return fonts[i]; }
private:
GfxFont **fonts; // list of fonts
int numFonts; // number of fonts
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/GfxState.cc b/noncore/unsupported/qpdf/xpdf/GfxState.cc
index af4e0d4..befd45a 100644
--- a/noncore/unsupported/qpdf/xpdf/GfxState.cc
+++ b/noncore/unsupported/qpdf/xpdf/GfxState.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// GfxState.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include <math.h>
#include <string.h> // for memcpy()
#include "gmem.h"
#include "Error.h"
#include "Object.h"
#include "Array.h"
#include "Page.h"
#include "GfxState.h"
//------------------------------------------------------------------------
static inline fouble clip01(fouble x) {
return (x < 0) ? fouble(0) : ((x > 1) ? fouble(1) : x);
}
//------------------------------------------------------------------------
// GfxColorSpace
//------------------------------------------------------------------------
GfxColorSpace::GfxColorSpace() {
}
GfxColorSpace::~GfxColorSpace() {
}
GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
GfxColorSpace *cs;
Object obj1;
cs = NULL;
if (csObj->isName()) {
if (csObj->isName("DeviceGray") || csObj->isName("G")) {
cs = new GfxDeviceGrayColorSpace();
} else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
cs = new GfxDeviceRGBColorSpace();
} else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
cs = new GfxDeviceCMYKColorSpace();
} else if (csObj->isName("Pattern")) {
cs = new GfxPatternColorSpace(NULL);
} else {
error(-1, "Bad color space '%s'", csObj->getName());
}
} else if (csObj->isArray()) {
csObj->arrayGet(0, &obj1);
if (obj1.isName("DeviceGray") || obj1.isName("G")) {
cs = new GfxDeviceGrayColorSpace();
} else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
cs = new GfxDeviceRGBColorSpace();
} else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
cs = new GfxDeviceCMYKColorSpace();
} else if (obj1.isName("CalGray")) {
cs = GfxCalGrayColorSpace::parse(csObj->getArray());
} else if (obj1.isName("CalRGB")) {
cs = GfxCalRGBColorSpace::parse(csObj->getArray());
} else if (obj1.isName("Lab")) {
cs = GfxLabColorSpace::parse(csObj->getArray());
} else if (obj1.isName("ICCBased")) {
cs = GfxICCBasedColorSpace::parse(csObj->getArray());
} else if (obj1.isName("Indexed") || obj1.isName("I")) {
cs = GfxIndexedColorSpace::parse(csObj->getArray());
} else if (obj1.isName("Separation")) {
cs = GfxSeparationColorSpace::parse(csObj->getArray());
} else if (obj1.isName("DeviceN")) {
cs = GfxDeviceNColorSpace::parse(csObj->getArray());
} else if (obj1.isName("Pattern")) {
cs = GfxPatternColorSpace::parse(csObj->getArray());
} else {
error(-1, "Bad color space '%s'", csObj->getName());
}
obj1.free();
} else {
error(-1, "Bad color space - expected name or array");
}
return cs;
}
void GfxColorSpace::getDefaultRanges(fouble *decodeLow, fouble *decodeRange,
int maxImgPixel) {
int i;
for (i = 0; i < getNComps(); ++i) {
decodeLow[i] = 0;
decodeRange[i] = 1;
}
}
//------------------------------------------------------------------------
@@ -315,195 +315,208 @@ GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
cs->whiteZ = obj3.getNum();
obj3.free();
}
obj2.free();
if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
obj2.arrayGetLength() == 3) {
obj2.arrayGet(0, &obj3);
cs->blackX = obj3.getNum();
obj3.free();
obj2.arrayGet(1, &obj3);
cs->blackY = obj3.getNum();
obj3.free();
obj2.arrayGet(2, &obj3);
cs->blackZ = obj3.getNum();
obj3.free();
}
obj2.free();
if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
obj2.arrayGetLength() == 3) {
obj2.arrayGet(0, &obj3);
cs->gammaR = obj3.getNum();
obj3.free();
obj2.arrayGet(1, &obj3);
cs->gammaG = obj3.getNum();
obj3.free();
obj2.arrayGet(2, &obj3);
cs->gammaB = obj3.getNum();
obj3.free();
}
obj2.free();
if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
obj2.arrayGetLength() == 9) {
for (i = 0; i < 9; ++i) {
obj2.arrayGet(i, &obj3);
cs->mat[i] = obj3.getNum();
obj3.free();
}
}
obj2.free();
obj1.free();
return cs;
}
void GfxCalRGBColorSpace::getGray(GfxColor *color, fouble *gray) {
*gray = clip01(0.299 * color->c[0] +
0.587 * color->c[1] +
0.114 * color->c[2]);
}
void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
rgb->r = clip01(color->c[0]);
rgb->g = clip01(color->c[1]);
rgb->b = clip01(color->c[2]);
}
void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
fouble c, m, y, k;
c = clip01(1 - color->c[0]);
m = clip01(1 - color->c[1]);
y = clip01(1 - color->c[2]);
k = c;
if (m < k) {
k = m;
}
if (y < k) {
k = y;
}
cmyk->c = c - k;
cmyk->m = m - k;
cmyk->y = y - k;
cmyk->k = k;
}
//------------------------------------------------------------------------
// GfxDeviceCMYKColorSpace
//------------------------------------------------------------------------
GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
}
GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
}
GfxColorSpace *GfxDeviceCMYKColorSpace::copy() {
return new GfxDeviceCMYKColorSpace();
}
void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, fouble *gray) {
*gray = clip01(1 - color->c[3]
- 0.299 * color->c[0]
- 0.587 * color->c[1]
- 0.114 * color->c[2]);
}
void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- rgb->r = clip01(1 - (color->c[0] + color->c[3]));
- rgb->g = clip01(1 - (color->c[1] + color->c[3]));
- rgb->b = clip01(1 - (color->c[2] + color->c[3]));
+ fouble c, m, y, aw, ac, am, ay, ar, ag, ab;
+
+ c = clip01(color->c[0] + color->c[3]);
+ m = clip01(color->c[1] + color->c[3]);
+ y = clip01(color->c[2] + color->c[3]);
+ aw = (1-c) * (1-m) * (1-y);
+ ac = c * (1-m) * (1-y);
+ am = (1-c) * m * (1-y);
+ ay = (1-c) * (1-m) * y;
+ ar = (1-c) * m * y;
+ ag = c * (1-m) * y;
+ ab = c * m * (1-y);
+ rgb->r = clip01(aw + 0.9137*am + 0.9961*ay + 0.9882*ar);
+ rgb->g = clip01(aw + 0.6196*ac + ay + 0.5176*ag);
+ rgb->b = clip01(aw + 0.7804*ac + 0.5412*am + 0.0667*ar + 0.2118*ag +
+ 0.4863*ab);
}
void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
cmyk->c = clip01(color->c[0]);
cmyk->m = clip01(color->c[1]);
cmyk->y = clip01(color->c[2]);
cmyk->k = clip01(color->c[3]);
}
//------------------------------------------------------------------------
// GfxLabColorSpace
//------------------------------------------------------------------------
// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
// Language Reference, Third Edition.
static fouble xyzrgb[3][3] = {
{ 3.240449, -1.537136, -0.498531 },
{ -0.969265, 1.876011, 0.041556 },
{ 0.055643, -0.204026, 1.057229 }
};
GfxLabColorSpace::GfxLabColorSpace() {
whiteX = whiteY = whiteZ = 1;
blackX = blackY = blackZ = 0;
aMin = bMin = -100;
aMax = bMax = 100;
}
GfxLabColorSpace::~GfxLabColorSpace() {
}
GfxColorSpace *GfxLabColorSpace::copy() {
GfxLabColorSpace *cs;
cs = new GfxLabColorSpace();
cs->whiteX = whiteX;
cs->whiteY = whiteY;
cs->whiteZ = whiteZ;
cs->blackX = blackX;
cs->blackY = blackY;
cs->blackZ = blackZ;
cs->aMin = aMin;
cs->aMax = aMax;
cs->bMin = bMin;
cs->bMax = bMax;
cs->kr = kr;
cs->kg = kg;
cs->kb = kb;
return cs;
}
GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
GfxLabColorSpace *cs;
Object obj1, obj2, obj3;
arr->get(1, &obj1);
if (!obj1.isDict()) {
error(-1, "Bad Lab color space");
obj1.free();
return NULL;
}
cs = new GfxLabColorSpace();
if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
obj2.arrayGetLength() == 3) {
obj2.arrayGet(0, &obj3);
cs->whiteX = obj3.getNum();
obj3.free();
obj2.arrayGet(1, &obj3);
cs->whiteY = obj3.getNum();
obj3.free();
obj2.arrayGet(2, &obj3);
cs->whiteZ = obj3.getNum();
obj3.free();
}
obj2.free();
if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
obj2.arrayGetLength() == 3) {
obj2.arrayGet(0, &obj3);
cs->blackX = obj3.getNum();
obj3.free();
obj2.arrayGet(1, &obj3);
cs->blackY = obj3.getNum();
obj3.free();
obj2.arrayGet(2, &obj3);
cs->blackZ = obj3.getNum();
obj3.free();
}
obj2.free();
if (obj1.dictLookup("Range", &obj2)->isArray() &&
obj2.arrayGetLength() == 4) {
obj2.arrayGet(0, &obj3);
cs->aMin = obj3.getNum();
obj3.free();
obj2.arrayGet(1, &obj3);
cs->aMax = obj3.getNum();
obj3.free();
@@ -1175,381 +1188,509 @@ GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
if (streamDict->lookup("BBox", &obj1)->isArray() &&
obj1.arrayGetLength() == 4) {
for (i = 0; i < 4; ++i) {
if (obj1.arrayGet(i, &obj2)->isNum()) {
bbox[i] = obj2.getNum();
}
obj2.free();
}
} else {
error(-1, "Invalid or missing BBox in pattern");
}
obj1.free();
if (streamDict->lookup("XStep", &obj1)->isNum()) {
xStep = obj1.getNum();
} else {
xStep = 1;
error(-1, "Invalid or missing XStep in pattern");
}
obj1.free();
if (streamDict->lookup("YStep", &obj1)->isNum()) {
yStep = obj1.getNum();
} else {
yStep = 1;
error(-1, "Invalid or missing YStep in pattern");
}
obj1.free();
if (!streamDict->lookup("Resources", &resDict)->isDict()) {
resDict.free();
resDict.initNull();
error(-1, "Invalid or missing Resources in pattern");
}
matrix[0] = 1; matrix[1] = 0;
matrix[2] = 0; matrix[3] = 1;
matrix[4] = 0; matrix[5] = 0;
if (streamDict->lookup("Matrix", &obj1)->isArray() &&
obj1.arrayGetLength() == 6) {
for (i = 0; i < 6; ++i) {
if (obj1.arrayGet(i, &obj2)->isNum()) {
matrix[i] = obj2.getNum();
}
obj2.free();
}
}
obj1.free();
stream->copy(&contentStream);
}
GfxTilingPattern::~GfxTilingPattern() {
resDict.free();
contentStream.free();
}
GfxPattern *GfxTilingPattern::copy() {
return new GfxTilingPattern(this);
}
GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
GfxPattern(1)
{
memcpy(this, pat, sizeof(GfxTilingPattern));
pat->resDict.copy(&resDict);
pat->contentStream.copy(&contentStream);
}
//------------------------------------------------------------------------
// GfxShading
//------------------------------------------------------------------------
GfxShading::GfxShading() {
}
GfxShading::~GfxShading() {
delete colorSpace;
}
GfxShading *GfxShading::parse(Object *obj) {
GfxShading *shading;
int typeA;
GfxColorSpace *colorSpaceA;
GfxColor backgroundA;
GBool hasBackgroundA;
fouble xMinA, yMinA, xMaxA, yMaxA;
GBool hasBBoxA;
Object obj1, obj2;
int i;
shading = NULL;
if (obj->isDict()) {
if (!obj->dictLookup("ShadingType", &obj1)->isInt()) {
error(-1, "Invalid ShadingType in shading dictionary");
obj1.free();
goto err1;
}
typeA = obj1.getInt();
obj1.free();
- if (typeA != 2) {
- error(-1, "Unimplemented shading type %d", typeA);
- goto err1;
- }
obj->dictLookup("ColorSpace", &obj1);
if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) {
error(-1, "Bad color space in shading dictionary");
obj1.free();
goto err1;
}
obj1.free();
for (i = 0; i < gfxColorMaxComps; ++i) {
backgroundA.c[i] = 0;
}
hasBackgroundA = gFalse;
if (obj->dictLookup("Background", &obj1)->isArray()) {
if (obj1.arrayGetLength() == colorSpaceA->getNComps()) {
hasBackgroundA = gTrue;
for (i = 0; i < colorSpaceA->getNComps(); ++i) {
backgroundA.c[i] = obj1.arrayGet(i, &obj2)->getNum();
obj2.free();
}
} else {
error(-1, "Bad Background in shading dictionary");
}
}
obj1.free();
xMinA = yMinA = xMaxA = yMaxA = 0;
hasBBoxA = gFalse;
if (obj->dictLookup("BBox", &obj1)->isArray()) {
if (obj1.arrayGetLength() == 4) {
hasBBoxA = gTrue;
xMinA = obj1.arrayGet(0, &obj2)->getNum();
obj2.free();
yMinA = obj1.arrayGet(1, &obj2)->getNum();
obj2.free();
xMaxA = obj1.arrayGet(2, &obj2)->getNum();
obj2.free();
yMaxA = obj1.arrayGet(3, &obj2)->getNum();
obj2.free();
} else {
error(-1, "Bad BBox in shading dictionary");
}
}
obj1.free();
- shading = GfxAxialShading::parse(obj->getDict());
+ switch (typeA) {
+ case 2:
+ shading = GfxAxialShading::parse(obj->getDict());
+ break;
+ case 3:
+ shading = GfxRadialShading::parse(obj->getDict());
+ break;
+ default:
+ error(-1, "Unimplemented shading type %d", typeA);
+ goto err1;
+ }
if (shading) {
shading->type = typeA;
shading->colorSpace = colorSpaceA;
shading->background = backgroundA;
shading->hasBackground = hasBackgroundA;
shading->xMin = xMinA;
shading->yMin = yMinA;
shading->xMax = xMaxA;
shading->yMax = yMaxA;
shading->hasBBox = hasBBoxA;
} else {
delete colorSpaceA;
}
}
return shading;
err1:
return NULL;
}
//------------------------------------------------------------------------
// GfxAxialShading
//------------------------------------------------------------------------
GfxAxialShading::GfxAxialShading(fouble x0A, fouble y0A,
fouble x1A, fouble y1A,
fouble t0A, fouble t1A,
Function **funcsA, int nFuncsA,
GBool extend0A, GBool extend1A) {
int i;
x0 = x0A;
y0 = y0A;
x1 = x1A;
y1 = y1A;
t0 = t0A;
t1 = t1A;
nFuncs = nFuncsA;
for (i = 0; i < nFuncs; ++i) {
funcs[i] = funcsA[i];
}
extend0 = extend0A;
extend1 = extend1A;
}
GfxAxialShading::~GfxAxialShading() {
int i;
for (i = 0; i < nFuncs; ++i) {
delete funcs[i];
}
}
GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
fouble x0A, y0A, x1A, y1A;
fouble t0A, t1A;
Function *funcsA[gfxColorMaxComps];
int nFuncsA;
GBool extend0A, extend1A;
Object obj1, obj2;
int i;
x0A = y0A = x1A = y1A = 0;
if (dict->lookup("Coords", &obj1)->isArray() &&
obj1.arrayGetLength() == 4) {
x0A = obj1.arrayGet(0, &obj2)->getNum();
obj2.free();
y0A = obj1.arrayGet(1, &obj2)->getNum();
obj2.free();
x1A = obj1.arrayGet(2, &obj2)->getNum();
obj2.free();
y1A = obj1.arrayGet(3, &obj2)->getNum();
obj2.free();
} else {
error(-1, "Missing or invalid Coords in shading dictionary");
goto err1;
}
obj1.free();
t0A = 0;
t1A = 1;
if (dict->lookup("Domain", &obj1)->isArray() &&
obj1.arrayGetLength() == 2) {
t0A = obj1.arrayGet(0, &obj2)->getNum();
obj2.free();
t1A = obj1.arrayGet(1, &obj2)->getNum();
obj2.free();
}
obj1.free();
dict->lookup("Function", &obj1);
if (obj1.isArray()) {
nFuncsA = obj1.arrayGetLength();
for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
if (!(funcsA[i] = Function::parse(&obj2))) {
obj1.free();
obj2.free();
goto err1;
}
obj2.free();
}
} else {
nFuncsA = 1;
if (!(funcsA[0] = Function::parse(&obj1))) {
obj1.free();
goto err1;
}
}
obj1.free();
extend0A = extend1A = gFalse;
if (dict->lookup("Extend", &obj1)->isArray() &&
obj1.arrayGetLength() == 2) {
extend0A = obj1.arrayGet(0, &obj2)->getBool();
obj2.free();
extend1A = obj1.arrayGet(1, &obj2)->getBool();
obj2.free();
}
obj1.free();
return new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
funcsA, nFuncsA, extend0A, extend1A);
err1:
return NULL;
}
void GfxAxialShading::getColor(fouble t, GfxColor *color) {
int i;
for (i = 0; i < nFuncs; ++i) {
funcs[i]->transform(&t, &color->c[i]);
}
}
//------------------------------------------------------------------------
+// GfxRadialShading
+//------------------------------------------------------------------------
+
+GfxRadialShading::GfxRadialShading(fouble x0A, fouble y0A, fouble r0A,
+ fouble x1A, fouble y1A, fouble r1A,
+ fouble t0A, fouble t1A,
+ Function **funcsA, int nFuncsA,
+ GBool extend0A, GBool extend1A) {
+ int i;
+
+ x0 = x0A;
+ y0 = y0A;
+ r0 = r0A;
+ x1 = x1A;
+ y1 = y1A;
+ r1 = r1A;
+ t0 = t0A;
+ t1 = t1A;
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
+ }
+ extend0 = extend0A;
+ extend1 = extend1A;
+}
+
+GfxRadialShading::~GfxRadialShading() {
+ int i;
+
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
+ }
+}
+
+GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
+ fouble x0A, y0A, r0A, x1A, y1A, r1A;
+ fouble t0A, t1A;
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ GBool extend0A, extend1A;
+ Object obj1, obj2;
+ int i;
+
+ x0A = y0A = r0A = x1A = y1A = r1A = 0;
+ if (dict->lookup("Coords", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ x0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ y0A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ r0A = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ x1A = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ y1A = obj1.arrayGet(4, &obj2)->getNum();
+ obj2.free();
+ r1A = obj1.arrayGet(5, &obj2)->getNum();
+ obj2.free();
+ } else {
+ error(-1, "Missing or invalid Coords in shading dictionary");
+ goto err1;
+ }
+ obj1.free();
+
+ t0A = 0;
+ t1A = 1;
+ if (dict->lookup("Domain", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ t0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ t1A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("Function", &obj1);
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ for (i = 0; i < nFuncsA; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ obj1.free();
+ obj2.free();
+ goto err1;
+ }
+ obj2.free();
+ }
+ } else {
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ obj1.free();
+ goto err1;
+ }
+ }
+ obj1.free();
+
+ extend0A = extend1A = gFalse;
+ if (dict->lookup("Extend", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ extend0A = obj1.arrayGet(0, &obj2)->getBool();
+ obj2.free();
+ extend1A = obj1.arrayGet(1, &obj2)->getBool();
+ obj2.free();
+ }
+ obj1.free();
+
+ return new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
+ funcsA, nFuncsA, extend0A, extend1A);
+
+ err1:
+ return NULL;
+}
+
+void GfxRadialShading::getColor(fouble t, GfxColor *color) {
+ int i;
+
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i]->transform(&t, &color->c[i]);
+ }
+}
+
+//------------------------------------------------------------------------
// GfxImageColorMap
//------------------------------------------------------------------------
GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
GfxColorSpace *colorSpaceA) {
GfxIndexedColorSpace *indexedCS;
GfxSeparationColorSpace *sepCS;
int maxPixel, indexHigh;
Guchar *lookup2;
Function *sepFunc;
Object obj;
fouble x[gfxColorMaxComps];
fouble y[gfxColorMaxComps];
int i, j, k;
ok = gTrue;
// bits per component and color space
bits = bitsA;
maxPixel = (1 << bits) - 1;
colorSpace = colorSpaceA;
// get decode map
if (decode->isNull()) {
nComps = colorSpace->getNComps();
colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
} else if (decode->isArray()) {
nComps = decode->arrayGetLength() / 2;
if (nComps != colorSpace->getNComps()) {
goto err1;
}
for (i = 0; i < nComps; ++i) {
decode->arrayGet(2*i, &obj);
if (!obj.isNum()) {
goto err2;
}
decodeLow[i] = obj.getNum();
obj.free();
decode->arrayGet(2*i+1, &obj);
if (!obj.isNum()) {
goto err2;
}
decodeRange[i] = obj.getNum() - decodeLow[i];
obj.free();
}
} else {
goto err1;
}
// Construct a lookup table -- this stores pre-computed decoded
// values for each component, i.e., the result of applying the
// decode mapping to each possible image pixel component value.
//
// Optimization: for Indexed and Separation color spaces (which have
// only one component), we store color values in the lookup table
// rather than component values.
colorSpace2 = NULL;
nComps2 = 0;
if (colorSpace->getMode() == csIndexed) {
// Note that indexHigh may not be the same as maxPixel --
// Distiller will remove unused palette entries, resulting in
// indexHigh < maxPixel.
indexedCS = (GfxIndexedColorSpace *)colorSpace;
colorSpace2 = indexedCS->getBase();
indexHigh = indexedCS->getIndexHigh();
nComps2 = colorSpace2->getNComps();
lookup = (fouble *)gmalloc((indexHigh + 1) * nComps2 * sizeof(fouble));
lookup2 = indexedCS->getLookup();
for (i = 0; i <= indexHigh; ++i) {
j = (int)(decodeLow[0] +(i * decodeRange[0]) / maxPixel + 0.5);
for (k = 0; k < nComps2; ++k) {
lookup[i*nComps2 + k] = lookup2[i*nComps2 + k] / 255.0;
}
}
} else if (colorSpace->getMode() == csSeparation) {
sepCS = (GfxSeparationColorSpace *)colorSpace;
colorSpace2 = sepCS->getAlt();
nComps2 = colorSpace2->getNComps();
lookup = (fouble *)gmalloc((maxPixel + 1) * nComps2 * sizeof(fouble));
sepFunc = sepCS->getFunc();
for (i = 0; i <= maxPixel; ++i) {
x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
sepFunc->transform(x, y);
for (k = 0; k < nComps2; ++k) {
lookup[i*nComps2 + k] = y[k];
}
}
} else {
lookup = (fouble *)gmalloc((maxPixel + 1) * nComps * sizeof(fouble));
for (i = 0; i <= maxPixel; ++i) {
for (k = 0; k < nComps; ++k) {
lookup[i*nComps + k] = decodeLow[k] +
(i * decodeRange[k]) / maxPixel;
}
}
}
@@ -1825,273 +1966,356 @@ GfxState::GfxState(fouble dpi, PDFRectangle *pageBox, int rotate,
ctm[1] = 0;
ctm[2] = 0;
ctm[3] = upsideDown ? -k : k;
ctm[4] = -k * px1;
ctm[5] = k * (upsideDown ? py2 : -py1);
pageWidth = k * (px2 - px1);
pageHeight = k * (py2 - py1);
}
fillColorSpace = new GfxDeviceGrayColorSpace();
strokeColorSpace = new GfxDeviceGrayColorSpace();
fillColor.c[0] = 0;
strokeColor.c[0] = 0;
fillPattern = NULL;
strokePattern = NULL;
fillOpacity = 1;
strokeOpacity = 1;
lineWidth = 1;
lineDash = NULL;
lineDashLength = 0;
lineDashStart = 0;
flatness = 0;
lineJoin = 0;
lineCap = 0;
miterLimit = 10;
font = NULL;
fontSize = 0;
textMat[0] = 1; textMat[1] = 0;
textMat[2] = 0; textMat[3] = 1;
textMat[4] = 0; textMat[5] = 0;
charSpace = 0;
wordSpace = 0;
horizScaling = 1;
leading = 0;
rise = 0;
render = 0;
path = new GfxPath();
curX = curY = 0;
lineX = lineY = 0;
clipXMin = 0;
clipYMin = 0;
clipXMax = pageWidth;
clipYMax = pageHeight;
saved = NULL;
}
GfxState::~GfxState() {
if (fillColorSpace) {
delete fillColorSpace;
}
if (strokeColorSpace) {
delete strokeColorSpace;
}
if (fillPattern) {
delete fillPattern;
}
if (strokePattern) {
delete strokePattern;
}
gfree(lineDash);
if (path) {
// this gets set to NULL by restore()
delete path;
}
if (saved) {
delete saved;
}
}
// Used for copy();
GfxState::GfxState(GfxState *state) {
memcpy(this, state, sizeof(GfxState));
if (fillColorSpace) {
fillColorSpace = state->fillColorSpace->copy();
}
if (strokeColorSpace) {
strokeColorSpace = state->strokeColorSpace->copy();
}
if (fillPattern) {
fillPattern = state->fillPattern->copy();
}
if (strokePattern) {
strokePattern = state->strokePattern->copy();
}
if (lineDashLength > 0) {
lineDash = (fouble *)gmalloc(lineDashLength * sizeof(fouble));
memcpy(lineDash, state->lineDash, lineDashLength * sizeof(fouble));
}
saved = NULL;
}
+void GfxState::getUserClipBBox(fouble *xMin, fouble *yMin,
+ fouble *xMax, fouble *yMax) {
+ fouble ictm[6];
+ fouble xMin1, yMin1, xMax1, yMax1, det, tx, ty;
+
+ // invert the CTM
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+
+ // transform all four corners of the clip bbox; find the min and max
+ // x and y values
+ xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4];
+ yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5];
+ tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4];
+ ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+ tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4];
+ ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+ tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4];
+ ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+
+ *xMin = xMin1;
+ *yMin = yMin1;
+ *xMax = xMax1;
+ *yMax = yMax1;
+}
+
fouble GfxState::transformWidth(fouble w) {
fouble x, y;
x = ctm[0] + ctm[2];
y = ctm[1] + ctm[3];
return w * sqrt(0.5 * (x * x + y * y));
}
fouble GfxState::getTransformedFontSize() {
fouble x1, y1, x2, y2;
x1 = textMat[2] * fontSize;
y1 = textMat[3] * fontSize;
x2 = ctm[0] * x1 + ctm[2] * y1;
y2 = ctm[1] * x1 + ctm[3] * y1;
return sqrt(x2 * x2 + y2 * y2);
}
void GfxState::getFontTransMat(fouble *m11, fouble *m12,
fouble *m21, fouble *m22) {
*m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
*m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
*m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
*m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
}
void GfxState::setCTM(fouble a, fouble b, fouble c,
fouble d, fouble e, fouble f) {
+ int i;
+
ctm[0] = a;
ctm[1] = b;
ctm[2] = c;
ctm[3] = d;
ctm[4] = e;
ctm[5] = f;
+
+ // avoid FP exceptions on badly messed up PDF files
+ for (i = 0; i < 6; ++i) {
+ if (ctm[i] > fouble(1e3)) {
+ ctm[i] = fouble(1e3);
+ } else if (ctm[i] < -fouble(1e3)) {
+ ctm[i] = -fouble(1e3);
+ }
+ }
}
void GfxState::concatCTM(fouble a, fouble b, fouble c,
fouble d, fouble e, fouble f) {
fouble a1 = ctm[0];
fouble b1 = ctm[1];
fouble c1 = ctm[2];
fouble d1 = ctm[3];
+ int i;
ctm[0] = a * a1 + b * c1;
ctm[1] = a * b1 + b * d1;
ctm[2] = c * a1 + d * c1;
ctm[3] = c * b1 + d * d1;
ctm[4] = e * a1 + f * c1 + ctm[4];
ctm[5] = e * b1 + f * d1 + ctm[5];
+
+ // avoid FP exceptions on badly messed up PDF files
+ for (i = 0; i < 6; ++i) {
+ if (ctm[i] > fouble(1e3)) {
+ ctm[i] = fouble(1e3);
+ } else if (ctm[i] < -fouble(1e3)) {
+ ctm[i] = -fouble(1e3);
+ }
+ }
}
void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
if (fillColorSpace) {
delete fillColorSpace;
}
fillColorSpace = colorSpace;
}
void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
if (strokeColorSpace) {
delete strokeColorSpace;
}
strokeColorSpace = colorSpace;
}
void GfxState::setFillPattern(GfxPattern *pattern) {
if (fillPattern) {
delete fillPattern;
}
fillPattern = pattern;
}
void GfxState::setStrokePattern(GfxPattern *pattern) {
if (strokePattern) {
delete strokePattern;
}
strokePattern = pattern;
}
void GfxState::setLineDash(fouble *dash, int length, fouble start) {
if (lineDash)
gfree(lineDash);
lineDash = dash;
lineDashLength = length;
lineDashStart = start;
}
void GfxState::clearPath() {
delete path;
path = new GfxPath();
}
void GfxState::clip() {
fouble xMin, yMin, xMax, yMax, x, y;
GfxSubpath *subpath;
int i, j;
xMin = xMax = yMin = yMax = 0; // make gcc happy
for (i = 0; i < path->getNumSubpaths(); ++i) {
subpath = path->getSubpath(i);
for (j = 0; j < subpath->getNumPoints(); ++j) {
transform(subpath->getX(j), subpath->getY(j), &x, &y);
if (i == 0 && j == 0) {
xMin = xMax = x;
yMin = yMax = y;
} else {
if (x < xMin) {
xMin = x;
} else if (x > xMax) {
xMax = x;
}
if (y < yMin) {
yMin = y;
} else if (y > yMax) {
yMax = y;
}
}
}
}
if (xMin > clipXMin) {
clipXMin = xMin;
}
if (yMin > clipYMin) {
clipYMin = yMin;
}
if (xMax < clipXMax) {
clipXMax = xMax;
}
if (yMax < clipYMax) {
clipYMax = yMax;
}
}
-void GfxState::textShift(fouble tx) {
+void GfxState::textShift(fouble tx, fouble ty) {
fouble dx, dy;
- textTransformDelta(tx, 0, &dx, &dy);
+ textTransformDelta(tx, ty, &dx, &dy);
curX += dx;
curY += dy;
}
void GfxState::shift(fouble dx, fouble dy) {
curX += dx;
curY += dy;
}
GfxState *GfxState::save() {
GfxState *newState;
newState = copy();
newState->saved = this;
return newState;
}
GfxState *GfxState::restore() {
GfxState *oldState;
if (saved) {
oldState = saved;
// these attributes aren't saved/restored by the q/Q operators
oldState->path = path;
oldState->curX = curX;
oldState->curY = curY;
oldState->lineX = lineX;
oldState->lineY = lineY;
path = NULL;
saved = NULL;
delete this;
} else {
oldState = this;
}
return oldState;
}
+
diff --git a/noncore/unsupported/qpdf/xpdf/GfxState.h b/noncore/unsupported/qpdf/xpdf/GfxState.h
index 7fe16ea..328f9a8 100644
--- a/noncore/unsupported/qpdf/xpdf/GfxState.h
+++ b/noncore/unsupported/qpdf/xpdf/GfxState.h
@@ -1,101 +1,101 @@
//========================================================================
//
// GfxState.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef GFXSTATE_H
#define GFXSTATE_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
#include "Object.h"
#include "Function.h"
class Array;
class GfxFont;
struct PDFRectangle;
//------------------------------------------------------------------------
// GfxColor
//------------------------------------------------------------------------
#define gfxColorMaxComps funcMaxOutputs
struct GfxColor {
fouble c[gfxColorMaxComps];
};
//------------------------------------------------------------------------
// GfxRGB
//------------------------------------------------------------------------
struct GfxRGB {
fouble r, g, b;
};
//------------------------------------------------------------------------
// GfxCMYK
//------------------------------------------------------------------------
struct GfxCMYK {
fouble c, m, y, k;
};
//------------------------------------------------------------------------
// GfxColorSpace
//------------------------------------------------------------------------
enum GfxColorSpaceMode {
csDeviceGray,
csCalGray,
csDeviceRGB,
csCalRGB,
csDeviceCMYK,
csLab,
csICCBased,
csIndexed,
csSeparation,
csDeviceN,
csPattern
};
class GfxColorSpace {
public:
GfxColorSpace();
virtual ~GfxColorSpace();
virtual GfxColorSpace *copy() = 0;
virtual GfxColorSpaceMode getMode() = 0;
// Construct a color space. Returns NULL if unsuccessful.
static GfxColorSpace *parse(Object *csObj);
// Convert to gray, RGB, or CMYK.
virtual void getGray(GfxColor *color, fouble *gray) = 0;
virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0;
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0;
// Return the number of color components.
virtual int getNComps() = 0;
// Return the default ranges for each component, assuming an image
// with a max pixel value of <maxImgPixel>.
virtual void getDefaultRanges(fouble *decodeLow, fouble *decodeRange,
int maxImgPixel);
private:
};
//------------------------------------------------------------------------
// GfxDeviceGrayColorSpace
//------------------------------------------------------------------------
class GfxDeviceGrayColorSpace: public GfxColorSpace {
public:
@@ -475,192 +475,226 @@ private:
class GfxTilingPattern: public GfxPattern {
public:
GfxTilingPattern(Dict *streamDict, Object *stream);
virtual ~GfxTilingPattern();
virtual GfxPattern *copy();
int getPaintType() { return paintType; }
int getTilingType() { return tilingType; }
fouble *getBBox() { return bbox; }
fouble getXStep() { return xStep; }
fouble getYStep() { return yStep; }
Dict *getResDict()
{ return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; }
fouble *getMatrix() { return matrix; }
Object *getContentStream() { return &contentStream; }
private:
GfxTilingPattern(GfxTilingPattern *pat);
int paintType;
int tilingType;
fouble bbox[4];
fouble xStep, yStep;
Object resDict;
fouble matrix[6];
Object contentStream;
};
//------------------------------------------------------------------------
// GfxShading
//------------------------------------------------------------------------
class GfxShading {
public:
GfxShading();
virtual ~GfxShading();
static GfxShading *parse(Object *obj);
int getType() { return type; }
GfxColorSpace *getColorSpace() { return colorSpace; }
GfxColor *getBackground() { return &background; }
GBool getHasBackground() { return hasBackground; }
void getBBox(fouble *xMinA, fouble *yMinA, fouble *xMaxA, fouble *yMaxA)
{ *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
GBool getHasBBox() { return hasBBox; }
private:
int type;
GfxColorSpace *colorSpace;
GfxColor background;
GBool hasBackground;
fouble xMin, yMin, xMax, yMax;
GBool hasBBox;
};
//------------------------------------------------------------------------
// GfxAxialShading
//------------------------------------------------------------------------
class GfxAxialShading: public GfxShading {
public:
GfxAxialShading(fouble x0A, fouble y0A,
fouble x1A, fouble y1A,
fouble t0A, fouble t1A,
Function **funcsA, int nFuncsA,
GBool extend0A, GBool extend1A);
virtual ~GfxAxialShading();
static GfxAxialShading *parse(Dict *dict);
void getCoords(fouble *x0A, fouble *y0A, fouble *x1A, fouble *y1A)
{ *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
fouble getDomain0() { return t0; }
fouble getDomain1() { return t1; }
void getColor(fouble t, GfxColor *color);
GBool getExtend0() { return extend0; }
GBool getExtend1() { return extend1; }
private:
fouble x0, y0, x1, y1;
fouble t0, t1;
Function *funcs[gfxColorMaxComps];
int nFuncs;
GBool extend0, extend1;
};
//------------------------------------------------------------------------
+// GfxRadialShading
+//------------------------------------------------------------------------
+
+class GfxRadialShading: public GfxShading {
+public:
+
+ GfxRadialShading(fouble x0A, fouble y0A, fouble r0A,
+ fouble x1A, fouble y1A, fouble r1A,
+ fouble t0A, fouble t1A,
+ Function **funcsA, int nFuncsA,
+ GBool extend0A, GBool extend1A);
+ virtual ~GfxRadialShading();
+
+ static GfxRadialShading *parse(Dict *dict);
+
+ void getCoords(fouble *x0A, fouble *y0A, fouble *r0A,
+ fouble *x1A, fouble *y1A, fouble *r1A)
+ { *x0A = x0; *y0A = y0; *r0A = r0; *x1A = x1; *y1A = y1; *r1A = r1; }
+ fouble getDomain0() { return t0; }
+ fouble getDomain1() { return t1; }
+ void getColor(fouble t, GfxColor *color);
+ GBool getExtend0() { return extend0; }
+ GBool getExtend1() { return extend1; }
+
+private:
+
+ fouble x0, y0, r0, x1, y1, r1;
+ fouble t0, t1;
+ Function *funcs[gfxColorMaxComps];
+ int nFuncs;
+ GBool extend0, extend1;
+};
+
+//------------------------------------------------------------------------
// GfxImageColorMap
//------------------------------------------------------------------------
class GfxImageColorMap {
public:
// Constructor.
GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA);
// Destructor.
~GfxImageColorMap();
// Is color map valid?
GBool isOk() { return ok; }
// Get the color space.
GfxColorSpace *getColorSpace() { return colorSpace; }
// Get stream decoding info.
int getNumPixelComps() { return nComps; }
int getBits() { return bits; }
// Get decode table.
fouble getDecodeLow(int i) { return decodeLow[i]; }
fouble getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; }
// Convert an image pixel to a color.
void getGray(Guchar *x, fouble *gray);
void getRGB(Guchar *x, GfxRGB *rgb);
void getCMYK(Guchar *x, GfxCMYK *cmyk);
private:
GfxColorSpace *colorSpace; // the image color space
int bits; // bits per component
int nComps; // number of components in a pixel
GfxColorSpace *colorSpace2; // secondary color space
int nComps2; // number of components in colorSpace2
fouble *lookup; // lookup table
fouble // minimum values for each component
decodeLow[gfxColorMaxComps];
fouble // max - min value for each component
decodeRange[gfxColorMaxComps];
GBool ok;
};
//------------------------------------------------------------------------
// GfxSubpath and GfxPath
//------------------------------------------------------------------------
class GfxSubpath {
public:
// Constructor.
GfxSubpath(fouble x1, fouble y1);
// Destructor.
~GfxSubpath();
// Copy.
GfxSubpath *copy() { return new GfxSubpath(this); }
// Get points.
int getNumPoints() { return n; }
fouble getX(int i) { return x[i]; }
fouble getY(int i) { return y[i]; }
GBool getCurve(int i) { return curve[i]; }
// Get last point.
fouble getLastX() { return x[n-1]; }
fouble getLastY() { return y[n-1]; }
// Add a line segment.
void lineTo(fouble x1, fouble y1);
// Add a Bezier curve.
void curveTo(fouble x1, fouble y1, fouble x2, fouble y2,
fouble x3, fouble y3);
// Close the subpath.
void close();
GBool isClosed() { return closed; }
private:
fouble *x, *y; // points
GBool *curve; // curve[i] => point i is a control point
// for a Bezier curve
int n; // number of points
int size; // size of x/y arrays
GBool closed; // set if path is closed
GfxSubpath(GfxSubpath *subpath);
};
class GfxPath {
@@ -690,233 +724,234 @@ public:
fouble getLastX() { return subpaths[n-1]->getLastX(); }
fouble getLastY() { return subpaths[n-1]->getLastY(); }
// Move the current point.
void moveTo(fouble x, fouble y);
// Add a segment to the last subpath.
void lineTo(fouble x, fouble y);
// Add a Bezier curve to the last subpath
void curveTo(fouble x1, fouble y1, fouble x2, fouble y2,
fouble x3, fouble y3);
// Close the last subpath.
void close();
private:
GBool justMoved; // set if a new subpath was just started
fouble firstX, firstY; // first point in new subpath
GfxSubpath **subpaths; // subpaths
int n; // number of subpaths
int size; // size of subpaths array
GfxPath(GBool justMoved1, fouble firstX1, fouble firstY1,
GfxSubpath **subpaths1, int n1, int size1);
};
//------------------------------------------------------------------------
// GfxState
//------------------------------------------------------------------------
class GfxState {
public:
// Construct a default GfxState, for a device with resolution <dpi>,
// page box <pageBox>, page rotation <rotate>, and coordinate system
// specified by <upsideDown>.
GfxState(fouble dpi, PDFRectangle *pageBox, int rotate,
GBool upsideDown);
// Destructor.
~GfxState();
// Copy.
GfxState *copy() { return new GfxState(this); }
// Accessors.
fouble *getCTM() { return ctm; }
fouble getX1() { return px1; }
fouble getY1() { return py1; }
fouble getX2() { return px2; }
fouble getY2() { return py2; }
fouble getPageWidth() { return pageWidth; }
fouble getPageHeight() { return pageHeight; }
GfxColor *getFillColor() { return &fillColor; }
GfxColor *getStrokeColor() { return &strokeColor; }
void getFillGray(fouble *gray)
{ fillColorSpace->getGray(&fillColor, gray); }
void getStrokeGray(fouble *gray)
{ strokeColorSpace->getGray(&fillColor, gray); }
void getFillRGB(GfxRGB *rgb)
{ fillColorSpace->getRGB(&fillColor, rgb); }
void getStrokeRGB(GfxRGB *rgb)
{ strokeColorSpace->getRGB(&strokeColor, rgb); }
void getFillCMYK(GfxCMYK *cmyk)
{ fillColorSpace->getCMYK(&fillColor, cmyk); }
void getStrokeCMYK(GfxCMYK *cmyk)
{ strokeColorSpace->getCMYK(&strokeColor, cmyk); }
GfxColorSpace *getFillColorSpace() { return fillColorSpace; }
GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; }
GfxPattern *getFillPattern() { return fillPattern; }
GfxPattern *getStrokePattern() { return strokePattern; }
fouble getFillOpacity() { return fillOpacity; }
fouble getStrokeOpacity() { return strokeOpacity; }
fouble getLineWidth() { return lineWidth; }
void getLineDash(fouble **dash, int *length, fouble *start)
{ *dash = lineDash; *length = lineDashLength; *start = lineDashStart; }
int getFlatness() { return flatness; }
int getLineJoin() { return lineJoin; }
int getLineCap() { return lineCap; }
fouble getMiterLimit() { return miterLimit; }
GfxFont *getFont() { return font; }
fouble getFontSize() { return fontSize; }
fouble *getTextMat() { return textMat; }
fouble getCharSpace() { return charSpace; }
fouble getWordSpace() { return wordSpace; }
fouble getHorizScaling() { return horizScaling; }
fouble getLeading() { return leading; }
fouble getRise() { return rise; }
int getRender() { return render; }
GfxPath *getPath() { return path; }
fouble getCurX() { return curX; }
fouble getCurY() { return curY; }
void getClipBBox(fouble *xMin, fouble *yMin, fouble *xMax, fouble *yMax)
{ *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; }
+ void getUserClipBBox(fouble *xMin, fouble *yMin, fouble *xMax, fouble *yMax);
fouble getLineX() { return lineX; }
fouble getLineY() { return lineY; }
// Is there a current point/path?
GBool isCurPt() { return path->isCurPt(); }
GBool isPath() { return path->isPath(); }
// Transforms.
void transform(fouble x1, fouble y1, fouble *x2, fouble *y2)
{ *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4];
*y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5]; }
void transformDelta(fouble x1, fouble y1, fouble *x2, fouble *y2)
{ *x2 = ctm[0] * x1 + ctm[2] * y1;
*y2 = ctm[1] * x1 + ctm[3] * y1; }
void textTransform(fouble x1, fouble y1, fouble *x2, fouble *y2)
{ *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4];
*y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; }
void textTransformDelta(fouble x1, fouble y1, fouble *x2, fouble *y2)
{ *x2 = textMat[0] * x1 + textMat[2] * y1;
*y2 = textMat[1] * x1 + textMat[3] * y1; }
fouble transformWidth(fouble w);
fouble getTransformedLineWidth()
{ return transformWidth(lineWidth); }
fouble getTransformedFontSize();
void getFontTransMat(fouble *m11, fouble *m12, fouble *m21, fouble *m22);
// Change state parameters.
void setCTM(fouble a, fouble b, fouble c,
fouble d, fouble e, fouble f);
void concatCTM(fouble a, fouble b, fouble c,
fouble d, fouble e, fouble f);
void setFillColorSpace(GfxColorSpace *colorSpace);
void setStrokeColorSpace(GfxColorSpace *colorSpace);
void setFillColor(GfxColor *color) { fillColor = *color; }
void setStrokeColor(GfxColor *color) { strokeColor = *color; }
void setFillPattern(GfxPattern *pattern);
void setStrokePattern(GfxPattern *pattern);
void setFillOpacity(fouble opac) { fillOpacity = opac; }
void setStrokeOpacity(fouble opac) { strokeOpacity = opac; }
void setLineWidth(fouble width) { lineWidth = width; }
void setLineDash(fouble *dash, int length, fouble start);
void setFlatness(int flatness1) { flatness = flatness1; }
void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
void setLineCap(int lineCap1) { lineCap = lineCap1; }
void setMiterLimit(fouble limit) { miterLimit = limit; }
void setFont(GfxFont *fontA, fouble fontSizeA)
{ font = fontA; fontSize = fontSizeA; }
void setTextMat(fouble a, fouble b, fouble c,
fouble d, fouble e, fouble f)
{ textMat[0] = a; textMat[1] = b; textMat[2] = c;
textMat[3] = d; textMat[4] = e; textMat[5] = f; }
void setCharSpace(fouble space)
{ charSpace = space; }
void setWordSpace(fouble space)
{ wordSpace = space; }
void setHorizScaling(fouble scale)
{ horizScaling = 0.01 * scale; }
void setLeading(fouble leadingA)
{ leading = leadingA; }
void setRise(fouble riseA)
{ rise = riseA; }
void setRender(int renderA)
{ render = renderA; }
// Add to path.
void moveTo(fouble x, fouble y)
{ path->moveTo(curX = x, curY = y); }
void lineTo(fouble x, fouble y)
{ path->lineTo(curX = x, curY = y); }
void curveTo(fouble x1, fouble y1, fouble x2, fouble y2,
fouble x3, fouble y3)
{ path->curveTo(x1, y1, x2, y2, curX = x3, curY = y3); }
void closePath()
{ path->close(); curX = path->getLastX(); curY = path->getLastY(); }
void clearPath();
// Update clip region.
void clip();
// Text position.
void textMoveTo(fouble tx, fouble ty)
{ lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); }
- void textShift(fouble tx);
+ void textShift(fouble tx, fouble ty);
void shift(fouble dx, fouble dy);
// Push/pop GfxState on/off stack.
GfxState *save();
GfxState *restore();
GBool hasSaves() { return saved != NULL; }
private:
fouble ctm[6]; // coord transform matrix
fouble px1, py1, px2, py2; // page corners (user coords)
fouble pageWidth, pageHeight; // page size (pixels)
GfxColorSpace *fillColorSpace; // fill color space
GfxColorSpace *strokeColorSpace; // stroke color space
GfxColor fillColor; // fill color
GfxColor strokeColor; // stroke color
GfxPattern *fillPattern; // fill pattern
GfxPattern *strokePattern; // stroke pattern
fouble fillOpacity; // fill opacity
fouble strokeOpacity; // stroke opacity
fouble lineWidth; // line width
fouble *lineDash; // line dash
int lineDashLength;
fouble lineDashStart;
int flatness; // curve flatness
int lineJoin; // line join style
int lineCap; // line cap style
fouble miterLimit; // line miter limit
GfxFont *font; // font
fouble fontSize; // font size
fouble textMat[6]; // text matrix
fouble charSpace; // character spacing
fouble wordSpace; // word spacing
fouble horizScaling; // horizontal scaling
fouble leading; // text leading
fouble rise; // text rise
int render; // text rendering mode
GfxPath *path; // array of path elements
fouble curX, curY; // current point (user coords)
fouble lineX, lineY; // start of current text line (text coords)
fouble clipXMin, clipYMin, // bounding box for clip region
clipXMax, clipYMax;
GfxState *saved; // next GfxState on stack
GfxState(GfxState *state);
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/GlobalParams.cc b/noncore/unsupported/qpdf/xpdf/GlobalParams.cc
index 8be58a3..0bc908e 100644
--- a/noncore/unsupported/qpdf/xpdf/GlobalParams.cc
+++ b/noncore/unsupported/qpdf/xpdf/GlobalParams.cc
@@ -1,916 +1,1065 @@
//========================================================================
//
// GlobalParams.cc
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <string.h>
#include <ctype.h>
#if HAVE_PAPER_H
#include <paper.h>
#endif
#include "gmem.h"
#include "GString.h"
#include "GList.h"
#include "GHash.h"
#include "gfile.h"
#include "Error.h"
#include "NameToCharCode.h"
#include "CharCodeToUnicode.h"
#include "UnicodeMap.h"
#include "CMap.h"
#include "BuiltinFontTables.h"
#include "FontEncodingTables.h"
#include "GlobalParams.h"
#include "NameToUnicodeTable.h"
#include "UnicodeMapTables.h"
#include "DisplayFontTable.h"
#include "UTF8.h"
//------------------------------------------------------------------------
GlobalParams *globalParams = NULL;
//------------------------------------------------------------------------
// DisplayFontParam
//------------------------------------------------------------------------
DisplayFontParam::DisplayFontParam(GString *nameA,
DisplayFontParamKind kindA) {
name = nameA;
kind = kindA;
switch (kind) {
case displayFontX:
x.xlfd = NULL;
x.encoding = NULL;
break;
case displayFontT1:
t1.fileName = NULL;
break;
case displayFontTT:
tt.fileName = NULL;
break;
}
}
DisplayFontParam::DisplayFontParam(char *nameA, char *xlfdA, char *encodingA) {
name = new GString(nameA);
kind = displayFontX;
x.xlfd = new GString(xlfdA);
x.encoding = new GString(encodingA);
}
DisplayFontParam::~DisplayFontParam() {
delete name;
switch (kind) {
case displayFontX:
if (x.xlfd) {
delete x.xlfd;
}
if (x.encoding) {
delete x.encoding;
}
break;
case displayFontT1:
if (t1.fileName) {
delete t1.fileName;
}
break;
case displayFontTT:
if (tt.fileName) {
delete tt.fileName;
}
break;
}
}
//------------------------------------------------------------------------
// PSFontParam
//------------------------------------------------------------------------
-PSFontParam::PSFontParam(GString *pdfFontNameA, GString *psFontNameA) {
+PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA,
+ GString *psFontNameA, GString *encodingA) {
pdfFontName = pdfFontNameA;
+ wMode = wModeA;
psFontName = psFontNameA;
+ encoding = encodingA;
}
PSFontParam::~PSFontParam() {
delete pdfFontName;
delete psFontName;
+ if (encoding) {
+ delete encoding;
+ }
}
//------------------------------------------------------------------------
// parsing
//------------------------------------------------------------------------
GlobalParams::GlobalParams(char *cfgFileName) {
UnicodeMap *map;
DisplayFontParam *dfp;
GString *fileName;
FILE *f;
- char buf[512];
- int line;
- GList *tokens;
- GString *cmd;
- char *p1, *p2;
int i;
initBuiltinFontTables();
+ // scan the encoding in reverse because we want the lowest-numbered
+ // index for each char name ('space' is encoded twice)
macRomanReverseMap = new NameToCharCode();
- for (i = 0; i < 256; ++i) {
+ for (i = 255; i >= 0; --i) {
if (macRomanEncoding[i]) {
macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
}
}
nameToUnicode = new NameToCharCode();
cidToUnicodes = new GHash(gTrue);
residentUnicodeMaps = new GHash();
unicodeMaps = new GHash(gTrue);
cMapDirs = new GHash(gTrue);
toUnicodeDirs = new GList();
displayFonts = new GHash();
displayCIDFonts = new GHash();
+ displayNamedCIDFonts = new GHash();
#if HAVE_PAPER_H
const struct paper *paperType;
paperinit();
paperType = paperinfo(systempapername());
psPaperWidth = (int)paperpswidth(paperType);
psPaperHeight = (int)paperpsheight(paperType);
paperdone();
#else
psPaperWidth = defPaperWidth;
psPaperHeight = defPaperHeight;
#endif
psDuplex = gFalse;
psLevel = psLevel2;
psFile = NULL;
psFonts = new GHash();
+ psNamedFonts16 = new GList();
+ psFonts16 = new GList();
psEmbedType1 = gTrue;
psEmbedTrueType = gTrue;
+ psEmbedCIDPostScript = gTrue;
+ psEmbedCIDTrueType = gTrue;
psOPI = gFalse;
+ psASCIIHex = gFalse;
textEncoding = new GString("Latin1");
#if defined(WIN32)
textEOL = eolDOS;
#elif defined(MACOS)
textEOL = eolMac;
#else
textEOL = eolUnix;
#endif
fontDirs = new GList();
+ initialZoom = new GString("1");
t1libControl = fontRastAALow;
freetypeControl = fontRastAALow;
urlCommand = NULL;
mapNumericCharNames = gTrue;
errQuiet = gFalse;
cidToUnicodeCache = new CIDToUnicodeCache();
unicodeMapCache = new UnicodeMapCache();
cMapCache = new CMapCache();
// set up the initial nameToUnicode table
for (i = 0; nameToUnicodeTab[i].name; ++i) {
nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
}
// set up the residentUnicodeMaps table
map = new UnicodeMap("Latin1", latin1UnicodeMapRanges, latin1UnicodeMapLen);
residentUnicodeMaps->add(map->getEncodingName(), map);
map = new UnicodeMap("ASCII7", ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
residentUnicodeMaps->add(map->getEncodingName(), map);
map = new UnicodeMap("Symbol", symbolUnicodeMapRanges, symbolUnicodeMapLen);
residentUnicodeMaps->add(map->getEncodingName(), map);
map = new UnicodeMap("ZapfDingbats", zapfDingbatsUnicodeMapRanges,
zapfDingbatsUnicodeMapLen);
residentUnicodeMaps->add(map->getEncodingName(), map);
map = new UnicodeMap("UTF-8", &mapUTF8);
residentUnicodeMaps->add(map->getEncodingName(), map);
+ map = new UnicodeMap("UCS-2", &mapUCS2);
+ residentUnicodeMaps->add(map->getEncodingName(), map);
// default displayFonts table
for (i = 0; displayFontTab[i].name; ++i) {
dfp = new DisplayFontParam(displayFontTab[i].name,
displayFontTab[i].xlfd,
displayFontTab[i].encoding);
displayFonts->add(dfp->name, dfp);
}
// look for a user config file, then a system-wide config file
f = NULL;
fileName = NULL;
if (cfgFileName && cfgFileName[0]) {
fileName = new GString(cfgFileName);
if (!(f = fopen(fileName->getCString(), "r"))) {
delete fileName;
}
}
if (!f) {
fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
if (!(f = fopen(fileName->getCString(), "r"))) {
delete fileName;
}
}
if (!f) {
#if defined(WIN32) && !defined(__CYGWIN32__)
+ char buf[512];
i = GetModuleFileName(NULL, buf, sizeof(buf));
if (i <= 0 || i >= sizeof(buf)) {
// error or path too long for buffer - just use the current dir
buf[i] = '\0';
}
fileName = grabPath(buf);
appendToPath(fileName, xpdfSysConfigFile);
#else
fileName = new GString(xpdfSysConfigFile);
#endif
if (!(f = fopen(fileName->getCString(), "r"))) {
delete fileName;
}
}
if (f) {
- line = 1;
- while (fgets(buf, sizeof(buf) - 1, f)) {
-
- // break the line into tokens
- tokens = new GList();
- p1 = buf;
- while (*p1) {
- for (; *p1 && isspace(*p1); ++p1) ;
- if (!*p1) {
- break;
- }
- if (*p1 == '"' || *p1 == '\'') {
- for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
- ++p1;
- } else {
- for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
- }
- tokens->append(new GString(p1, p2 - p1));
- p1 = p2 + 1;
+ parseFile(fileName, f);
+ delete fileName;
+ }
+}
+
+void GlobalParams::parseFile(GString *fileName, FILE *f) {
+ int line;
+ GList *tokens;
+ GString *cmd, *incFile;
+ char *p1, *p2;
+ char buf[512];
+ FILE *f2;
+
+ line = 1;
+ while (fgets(buf, sizeof(buf) - 1, f)) {
+
+ // break the line into tokens
+ tokens = new GList();
+ p1 = buf;
+ while (*p1) {
+ for (; *p1 && isspace(*p1); ++p1) ;
+ if (!*p1) {
+ break;
+ }
+ if (*p1 == '"' || *p1 == '\'') {
+ for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
+ ++p1;
+ } else {
+ for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
}
+ tokens->append(new GString(p1, p2 - p1));
+ p1 = p2 + 1;
+ }
- if (tokens->getLength() > 0 &&
- ((GString *)tokens->get(0))->getChar(0) != '#') {
- cmd = (GString *)tokens->get(0);
- if (!cmd->cmp("nameToUnicode")) {
- parseNameToUnicode(tokens, fileName, line);
- } else if (!cmd->cmp("cidToUnicode")) {
- parseCIDToUnicode(tokens, fileName, line);
- } else if (!cmd->cmp("unicodeMap")) {
- parseUnicodeMap(tokens, fileName, line);
- } else if (!cmd->cmp("cMapDir")) {
- parseCMapDir(tokens, fileName, line);
- } else if (!cmd->cmp("toUnicodeDir")) {
- parseToUnicodeDir(tokens, fileName, line);
- } else if (!cmd->cmp("displayFontX")) {
- parseDisplayFont(tokens, gFalse, displayFontX, fileName, line);
- } else if (!cmd->cmp("displayFontT1")) {
- parseDisplayFont(tokens, gFalse, displayFontT1, fileName, line);
- } else if (!cmd->cmp("displayFontTT")) {
- parseDisplayFont(tokens, gFalse, displayFontTT, fileName, line);
- } else if (!cmd->cmp("displayCIDFontX")) {
- parseDisplayFont(tokens, gTrue, displayFontX, fileName, line);
- } else if (!cmd->cmp("psFile")) {
- parsePSFile(tokens, fileName, line);
- } else if (!cmd->cmp("psFont")) {
- parsePSFont(tokens, fileName, line);
- } else if (!cmd->cmp("psPaperSize")) {
- parsePSPaperSize(tokens, fileName, line);
- } else if (!cmd->cmp("psDuplex")) {
- parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
- } else if (!cmd->cmp("psLevel")) {
- parsePSLevel(tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedType1")) {
- parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
- } else if (!cmd->cmp("psEmbedTrueType")) {
- parseYesNo("psEmbedTrueType", &psEmbedTrueType,
- tokens, fileName, line);
- } else if (!cmd->cmp("psOPI")) {
- parseYesNo("psOPI", &psOPI, tokens, fileName, line);
- } else if (!cmd->cmp("textEncoding")) {
- parseTextEncoding(tokens, fileName, line);
- } else if (!cmd->cmp("textEOL")) {
- parseTextEOL(tokens, fileName, line);
- } else if (!cmd->cmp("fontDir")) {
- parseFontDir(tokens, fileName, line);
- } else if (!cmd->cmp("t1libControl")) {
- parseFontRastControl("t1libControl", &t1libControl,
- tokens, fileName, line);
- } else if (!cmd->cmp("freetypeControl")) {
- parseFontRastControl("freetypeControl", &freetypeControl,
- tokens, fileName, line);
- } else if (!cmd->cmp("urlCommand")) {
- parseURLCommand(tokens, fileName, line);
- } else if (!cmd->cmp("mapNumericCharNames")) {
- parseYesNo("mapNumericCharNames", &mapNumericCharNames,
- tokens, fileName, line);
- } else if (!cmd->cmp("errQuiet")) {
- parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
- } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
- error(-1, "Unknown config file command");
- error(-1, "-- the config file format has changed since Xpdf 0.9x");
+ if (tokens->getLength() > 0 &&
+ ((GString *)tokens->get(0))->getChar(0) != '#') {
+ cmd = (GString *)tokens->get(0);
+ if (!cmd->cmp("include")) {
+ if (tokens->getLength() == 2) {
+ incFile = (GString *)tokens->get(1);
+ if ((f2 = fopen(incFile->getCString(), "r"))) {
+ parseFile(incFile, f2);
+ fclose(f2);
+ } else {
+ error(-1, "Couldn't find included config file: '%s' (%s:%d)",
+ incFile->getCString(), fileName->getCString(), line);
+ }
} else {
- error(-1, "Unknown config file command '%s' (%s:%d)",
- cmd->getCString(), fileName->getCString(), line);
+ error(-1, "Bad 'include' config file command (%s:%d)",
+ fileName->getCString(), line);
}
+ } else if (!cmd->cmp("nameToUnicode")) {
+ parseNameToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("cidToUnicode")) {
+ parseCIDToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("unicodeMap")) {
+ parseUnicodeMap(tokens, fileName, line);
+ } else if (!cmd->cmp("cMapDir")) {
+ parseCMapDir(tokens, fileName, line);
+ } else if (!cmd->cmp("toUnicodeDir")) {
+ parseToUnicodeDir(tokens, fileName, line);
+ } else if (!cmd->cmp("displayFontX")) {
+ parseDisplayFont(tokens, displayFonts, displayFontX, fileName, line);
+ } else if (!cmd->cmp("displayFontT1")) {
+ parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayFontTT")) {
+ parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
+ } else if (!cmd->cmp("displayCIDFontX")) {
+ parseDisplayFont(tokens, displayCIDFonts,
+ displayFontX, fileName, line);
+ } else if (!cmd->cmp("displayNamedCIDFontX")) {
+ parseDisplayFont(tokens, displayNamedCIDFonts,
+ displayFontX, fileName, line);
+ } else if (!cmd->cmp("psFile")) {
+ parsePSFile(tokens, fileName, line);
+ } else if (!cmd->cmp("psFont")) {
+ parsePSFont(tokens, fileName, line);
+ } else if (!cmd->cmp("psNamedFont16")) {
+ parsePSFont16("psNamedFont16", psNamedFonts16,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psFont16")) {
+ parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
+ } else if (!cmd->cmp("psPaperSize")) {
+ parsePSPaperSize(tokens, fileName, line);
+ } else if (!cmd->cmp("psDuplex")) {
+ parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
+ } else if (!cmd->cmp("psLevel")) {
+ parsePSLevel(tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedType1Fonts")) {
+ parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
+ parseYesNo("psEmbedTrueType", &psEmbedTrueType,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
+ parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
+ parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psOPI")) {
+ parseYesNo("psOPI", &psOPI, tokens, fileName, line);
+ } else if (!cmd->cmp("psASCIIHex")) {
+ parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
+ } else if (!cmd->cmp("textEncoding")) {
+ parseTextEncoding(tokens, fileName, line);
+ } else if (!cmd->cmp("textEOL")) {
+ parseTextEOL(tokens, fileName, line);
+ } else if (!cmd->cmp("fontDir")) {
+ parseFontDir(tokens, fileName, line);
+ } else if (!cmd->cmp("initialZoom")) {
+ parseInitialZoom(tokens, fileName, line);
+ } else if (!cmd->cmp("t1libControl")) {
+ parseFontRastControl("t1libControl", &t1libControl,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("freetypeControl")) {
+ parseFontRastControl("freetypeControl", &freetypeControl,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("urlCommand")) {
+ parseURLCommand(tokens, fileName, line);
+ } else if (!cmd->cmp("mapNumericCharNames")) {
+ parseYesNo("mapNumericCharNames", &mapNumericCharNames,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("errQuiet")) {
+ parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
+ } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
+ error(-1, "Unknown config file command");
+ error(-1, "-- the config file format has changed since Xpdf 0.9x");
+ } else {
+ error(-1, "Unknown config file command '%s' (%s:%d)",
+ cmd->getCString(), fileName->getCString(), line);
}
-
- deleteGList(tokens, GString);
- ++line;
}
- delete fileName;
+ deleteGList(tokens, GString);
+ ++line;
}
}
void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
int line) {
GString *name;
char *tok1, *tok2;
FILE *f;
char buf[256];
int line2;
Unicode u;
if (tokens->getLength() != 2) {
error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
name = (GString *)tokens->get(1);
if (!(f = fopen(name->getCString(), "r"))) {
error(-1, "Couldn't open 'nameToUnicode' file '%s'",
name->getCString());
return;
}
line2 = 1;
while (fgets(buf, sizeof(buf), f)) {
tok1 = strtok(buf, " \t\r\n");
tok2 = strtok(NULL, " \t\r\n");
if (tok1 && tok2) {
sscanf(tok1, "%x", &u);
nameToUnicode->add(tok2, u);
} else {
error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
}
++line2;
}
fclose(f);
}
void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
int line) {
GString *collection, *name, *old;
if (tokens->getLength() != 3) {
error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
collection = (GString *)tokens->get(1);
name = (GString *)tokens->get(2);
if ((old = (GString *)cidToUnicodes->remove(collection))) {
delete old;
}
cidToUnicodes->add(collection->copy(), name->copy());
}
void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
int line) {
GString *encodingName, *name, *old;
if (tokens->getLength() != 3) {
error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
encodingName = (GString *)tokens->get(1);
name = (GString *)tokens->get(2);
if ((old = (GString *)unicodeMaps->remove(encodingName))) {
delete old;
}
unicodeMaps->add(encodingName->copy(), name->copy());
}
void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
GString *collection, *dir;
GList *list;
if (tokens->getLength() != 3) {
error(-1, "Bad 'cMapDir' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
collection = (GString *)tokens->get(1);
dir = (GString *)tokens->get(2);
if (!(list = (GList *)cMapDirs->lookup(collection))) {
list = new GList();
cMapDirs->add(collection->copy(), list);
}
list->append(dir->copy());
}
void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
int line) {
if (tokens->getLength() != 2) {
error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
}
-void GlobalParams::parseDisplayFont(GList *tokens, GBool isCID,
+void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
DisplayFontParamKind kind,
GString *fileName, int line) {
DisplayFontParam *param, *old;
if (tokens->getLength() < 2) {
goto err1;
}
param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
switch (kind) {
case displayFontX:
if (tokens->getLength() != 4) {
goto err2;
}
param->x.xlfd = ((GString *)tokens->get(2))->copy();
param->x.encoding = ((GString *)tokens->get(3))->copy();
break;
case displayFontT1:
if (tokens->getLength() != 3) {
goto err2;
}
param->t1.fileName = ((GString *)tokens->get(2))->copy();
break;
case displayFontTT:
if (tokens->getLength() != 3) {
goto err2;
}
param->tt.fileName = ((GString *)tokens->get(2))->copy();
break;
}
- if (isCID) {
- if ((old = (DisplayFontParam *)displayCIDFonts->remove(param->name))) {
- delete old;
- }
- displayCIDFonts->add(param->name, param);
- } else {
- if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
- delete old;
- }
- displayFonts->add(param->name, param);
+ if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
+ delete old;
}
+ fontHash->add(param->name, param);
return;
err2:
delete param;
err1:
- error(-1, "Bad 'displayFont...' config file command (%s:%d)",
+ error(-1, "Bad 'display*Font*' config file command (%s:%d)",
fileName->getCString(), line);
}
void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
int line) {
GString *tok;
if (tokens->getLength() == 2) {
tok = (GString *)tokens->get(1);
if (!setPSPaperSize(tok->getCString())) {
error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
fileName->getCString(), line);
}
} else if (tokens->getLength() == 3) {
tok = (GString *)tokens->get(1);
psPaperWidth = atoi(tok->getCString());
tok = (GString *)tokens->get(2);
psPaperHeight = atoi(tok->getCString());
} else {
error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
fileName->getCString(), line);
}
}
void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
GString *tok;
if (tokens->getLength() != 2) {
error(-1, "Bad 'psLevel' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
tok = (GString *)tokens->get(1);
if (!tok->cmp("level1")) {
psLevel = psLevel1;
} else if (!tok->cmp("level1sep")) {
psLevel = psLevel1Sep;
} else if (!tok->cmp("level2")) {
psLevel = psLevel2;
} else if (!tok->cmp("level2sep")) {
psLevel = psLevel2Sep;
+ } else if (!tok->cmp("level3")) {
+ psLevel = psLevel3;
+ } else if (!tok->cmp("level3Sep")) {
+ psLevel = psLevel3Sep;
} else {
error(-1, "Bad 'psLevel' config file command (%s:%d)",
fileName->getCString(), line);
}
}
void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
if (tokens->getLength() != 2) {
error(-1, "Bad 'psFile' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
if (psFile) {
delete psFile;
}
psFile = ((GString *)tokens->get(1))->copy();
}
void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
PSFontParam *param;
if (tokens->getLength() != 3) {
error(-1, "Bad 'psFont' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
- param = new PSFontParam(((GString *)tokens->get(1))->copy(),
- ((GString *)tokens->get(2))->copy());
+ param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
+ ((GString *)tokens->get(2))->copy(), NULL);
psFonts->add(param->pdfFontName, param);
}
+void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
+ GList *tokens, GString *fileName, int line) {
+ PSFontParam *param;
+ int wMode;
+ GString *tok;
+
+ if (tokens->getLength() != 5) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(2);
+ if (!tok->cmp("H")) {
+ wMode = 0;
+ } else if (!tok->cmp("V")) {
+ wMode = 1;
+ } else {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ param = new PSFontParam(((GString *)tokens->get(1))->copy(),
+ wMode,
+ ((GString *)tokens->get(3))->copy(),
+ ((GString *)tokens->get(4))->copy());
+ fontList->append(param);
+}
+
void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
int line) {
if (tokens->getLength() != 2) {
error(-1, "Bad 'textEncoding' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
delete textEncoding;
textEncoding = ((GString *)tokens->get(1))->copy();
}
void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
GString *tok;
if (tokens->getLength() != 2) {
error(-1, "Bad 'textEOL' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
tok = (GString *)tokens->get(1);
if (!tok->cmp("unix")) {
textEOL = eolUnix;
} else if (!tok->cmp("dos")) {
textEOL = eolDOS;
} else if (!tok->cmp("mac")) {
textEOL = eolMac;
} else {
error(-1, "Bad 'textEOL' config file command (%s:%d)",
fileName->getCString(), line);
}
}
void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
if (tokens->getLength() != 2) {
error(-1, "Bad 'fontDir' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
fontDirs->append(((GString *)tokens->get(1))->copy());
}
-void GlobalParams::parseURLCommand(GList *tokens, GString *fileName,
- int line) {
+void GlobalParams::parseInitialZoom(GList *tokens,
+ GString *fileName, int line) {
if (tokens->getLength() != 2) {
- error(-1, "Bad 'urlCommand' config file command (%s:%d)",
+ error(-1, "Bad 'initialZoom' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
- if (urlCommand) {
- delete urlCommand;
- }
- urlCommand = ((GString *)tokens->get(1))->copy();
+ delete initialZoom;
+ initialZoom = ((GString *)tokens->get(1))->copy();
}
void GlobalParams::parseFontRastControl(char *cmdName, FontRastControl *val,
GList *tokens, GString *fileName,
int line) {
GString *tok;
if (tokens->getLength() != 2) {
error(-1, "Bad '%s' config file command (%s:%d)",
cmdName, fileName->getCString(), line);
return;
}
tok = (GString *)tokens->get(1);
if (!setFontRastControl(val, tok->getCString())) {
error(-1, "Bad '%s' config file command (%s:%d)",
cmdName, fileName->getCString(), line);
}
}
+void GlobalParams::parseURLCommand(GList *tokens, GString *fileName,
+ int line) {
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'urlCommand' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ if (urlCommand) {
+ delete urlCommand;
+ }
+ urlCommand = ((GString *)tokens->get(1))->copy();
+}
+
void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
GList *tokens, GString *fileName, int line) {
GString *tok;
if (tokens->getLength() != 2) {
error(-1, "Bad '%s' config file command (%s:%d)",
cmdName, fileName->getCString(), line);
return;
}
tok = (GString *)tokens->get(1);
if (!tok->cmp("yes")) {
*flag = gTrue;
} else if (!tok->cmp("no")) {
*flag = gFalse;
} else {
error(-1, "Bad '%s' config file command (%s:%d)",
cmdName, fileName->getCString(), line);
}
}
GlobalParams::~GlobalParams() {
GHashIter *iter;
GString *key;
GList *list;
freeBuiltinFontTables();
delete macRomanReverseMap;
delete nameToUnicode;
deleteGHash(cidToUnicodes, GString);
deleteGHash(residentUnicodeMaps, UnicodeMap);
deleteGHash(unicodeMaps, GString);
deleteGList(toUnicodeDirs, GString);
deleteGHash(displayFonts, DisplayFontParam);
deleteGHash(displayCIDFonts, DisplayFontParam);
+ deleteGHash(displayNamedCIDFonts, DisplayFontParam);
if (psFile) {
delete psFile;
}
deleteGHash(psFonts, PSFontParam);
+ deleteGList(psNamedFonts16, PSFontParam);
+ deleteGList(psFonts16, PSFontParam);
delete textEncoding;
deleteGList(fontDirs, GString);
+ delete initialZoom;
if (urlCommand) {
delete urlCommand;
}
cMapDirs->startIter(&iter);
while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
deleteGList(list, GString);
}
delete cMapDirs;
delete cidToUnicodeCache;
delete unicodeMapCache;
delete cMapCache;
}
//------------------------------------------------------------------------
// accessors
//------------------------------------------------------------------------
CharCode GlobalParams::getMacRomanCharCode(char *charName) {
return macRomanReverseMap->lookup(charName);
}
Unicode GlobalParams::mapNameToUnicode(char *charName) {
return nameToUnicode->lookup(charName);
}
FILE *GlobalParams::getCIDToUnicodeFile(GString *collection) {
GString *fileName;
if (!(fileName = (GString *)cidToUnicodes->lookup(collection))) {
return NULL;
}
return fopen(fileName->getCString(), "r");
}
UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
return (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
}
FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
GString *fileName;
if (!(fileName = (GString *)unicodeMaps->lookup(encodingName))) {
return NULL;
}
return fopen(fileName->getCString(), "r");
}
FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
GList *list;
GString *dir;
GString *fileName;
FILE *f;
int i;
if (!(list = (GList *)cMapDirs->lookup(collection))) {
return NULL;
}
for (i = 0; i < list->getLength(); ++i) {
dir = (GString *)list->get(i);
fileName = appendToPath(dir->copy(), cMapName->getCString());
f = fopen(fileName->getCString(), "r");
delete fileName;
if (f) {
return f;
}
}
return NULL;
}
FILE *GlobalParams::findToUnicodeFile(GString *name) {
GString *dir, *fileName;
FILE *f;
int i;
for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
dir = (GString *)toUnicodeDirs->get(i);
fileName = appendToPath(dir->copy(), name->getCString());
f = fopen(fileName->getCString(), "r");
delete fileName;
if (f) {
return f;
}
}
return NULL;
}
DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
return (DisplayFontParam *)displayFonts->lookup(fontName);
}
-DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *collection) {
- return (DisplayFontParam *)displayCIDFonts->lookup(collection);
+DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
+ GString *collection) {
+ DisplayFontParam *dfp;
+
+ if (!fontName ||
+ !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
+ dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
+ }
+ return dfp;
}
PSFontParam *GlobalParams::getPSFont(GString *fontName) {
return (PSFontParam *)psFonts->lookup(fontName);
}
+PSFontParam *GlobalParams::getPSFont16(GString *fontName,
+ GString *collection, int wMode) {
+ PSFontParam *p;
+ int i;
+
+ p = NULL;
+ if (fontName) {
+ for (i = 0; i < psNamedFonts16->getLength(); ++i) {
+ p = (PSFontParam *)psNamedFonts16->get(i);
+ if (!p->pdfFontName->cmp(fontName) &&
+ p->wMode == wMode) {
+ break;
+ }
+ p = NULL;
+ }
+ }
+ if (!p && collection) {
+ for (i = 0; i < psFonts16->getLength(); ++i) {
+ p = (PSFontParam *)psFonts16->get(i);
+ if (!p->pdfFontName->cmp(collection) &&
+ p->wMode == wMode) {
+ break;
+ }
+ p = NULL;
+ }
+ }
+ return p;
+}
+
GString *GlobalParams::findFontFile(GString *fontName,
char *ext1, char *ext2) {
GString *dir, *fileName;
FILE *f;
int i;
for (i = 0; i < fontDirs->getLength(); ++i) {
dir = (GString *)fontDirs->get(i);
if (ext1) {
fileName = appendToPath(dir->copy(), fontName->getCString());
fileName->append(ext1);
if ((f = fopen(fileName->getCString(), "r"))) {
fclose(f);
return fileName;
}
delete fileName;
}
if (ext2) {
fileName = appendToPath(dir->copy(), fontName->getCString());
fileName->append(ext2);
if ((f = fopen(fileName->getCString(), "r"))) {
fclose(f);
return fileName;
}
delete fileName;
}
}
return NULL;
}
CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
return cidToUnicodeCache->getCIDToUnicode(collection);
}
UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
UnicodeMap *map;
if ((map = getResidentUnicodeMap(encodingName))) {
map->incRefCnt();
return map;
}
return unicodeMapCache->getUnicodeMap(encodingName);
}
CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
return cMapCache->getCMap(collection, cMapName);
}
UnicodeMap *GlobalParams::getTextEncoding() {
return getUnicodeMap(textEncoding);
}
//------------------------------------------------------------------------
// functions to set parameters
//------------------------------------------------------------------------
void GlobalParams::setPSFile(char *file) {
if (psFile) {
delete psFile;
}
psFile = new GString(file);
}
GBool GlobalParams::setPSPaperSize(char *size) {
if (!strcmp(size, "letter")) {
psPaperWidth = 612;
psPaperHeight = 792;
} else if (!strcmp(size, "legal")) {
psPaperWidth = 612;
psPaperHeight = 1008;
} else if (!strcmp(size, "A4")) {
psPaperWidth = 595;
psPaperHeight = 842;
} else if (!strcmp(size, "A3")) {
psPaperWidth = 842;
psPaperHeight = 1190;
} else {
return gFalse;
}
return gTrue;
}
void GlobalParams::setPSPaperWidth(int width) {
psPaperWidth = width;
}
void GlobalParams::setPSPaperHeight(int height) {
psPaperHeight = height;
}
void GlobalParams::setPSDuplex(GBool duplex) {
psDuplex = duplex;
}
void GlobalParams::setPSLevel(PSLevel level) {
psLevel = level;
}
void GlobalParams::setPSEmbedType1(GBool embed) {
psEmbedType1 = embed;
}
void GlobalParams::setPSEmbedTrueType(GBool embed) {
psEmbedTrueType = embed;
}
+void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
+ psEmbedCIDPostScript = embed;
+}
+
+void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
+ psEmbedCIDTrueType = embed;
+}
+
void GlobalParams::setPSOPI(GBool opi) {
psOPI = opi;
}
+void GlobalParams::setPSASCIIHex(GBool hex) {
+ psASCIIHex = hex;
+}
+
void GlobalParams::setTextEncoding(char *encodingName) {
delete textEncoding;
textEncoding = new GString(encodingName);
}
GBool GlobalParams::setTextEOL(char *s) {
if (!strcmp(s, "unix")) {
textEOL = eolUnix;
} else if (!strcmp(s, "dos")) {
textEOL = eolDOS;
} else if (!strcmp(s, "mac")) {
textEOL = eolMac;
} else {
return gFalse;
}
return gTrue;
}
+void GlobalParams::setInitialZoom(char *s) {
+ delete initialZoom;
+ initialZoom = new GString(s);
+}
+
GBool GlobalParams::setT1libControl(char *s) {
return setFontRastControl(&t1libControl, s);
}
GBool GlobalParams::setFreeTypeControl(char *s) {
return setFontRastControl(&freetypeControl, s);
}
GBool GlobalParams::setFontRastControl(FontRastControl *val, char *s) {
if (!strcmp(s, "none")) {
*val = fontRastNone;
} else if (!strcmp(s, "plain")) {
*val = fontRastPlain;
} else if (!strcmp(s, "low")) {
*val = fontRastAALow;
} else if (!strcmp(s, "high")) {
*val = fontRastAAHigh;
} else {
return gFalse;
}
return gTrue;
}
void GlobalParams::setErrQuiet(GBool errQuietA) {
errQuiet = errQuietA;
}
diff --git a/noncore/unsupported/qpdf/xpdf/GlobalParams.h b/noncore/unsupported/qpdf/xpdf/GlobalParams.h
index ecbb5fc..b651110 100644
--- a/noncore/unsupported/qpdf/xpdf/GlobalParams.h
+++ b/noncore/unsupported/qpdf/xpdf/GlobalParams.h
@@ -1,242 +1,273 @@
//========================================================================
//
// GlobalParams.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef GLOBALPARAMS_H
#define GLOBALPARAMS_H
#ifdef __GNUC__
#pragma interface
#endif
#include <stdio.h>
#include "gtypes.h"
#include "CharTypes.h"
class GString;
class GList;
class GHash;
class NameToCharCode;
class CharCodeToUnicode;
class CIDToUnicodeCache;
class UnicodeMap;
class UnicodeMapCache;
class CMap;
class CMapCache;
class GlobalParams;
//------------------------------------------------------------------------
// The global parameters object.
extern GlobalParams *globalParams;
//------------------------------------------------------------------------
enum DisplayFontParamKind {
displayFontX,
displayFontT1,
displayFontTT
};
class DisplayFontParam {
public:
- GString *name; // font name for 8-bit fonts;
- // collection name for CID fonts
+ GString *name; // font name for 8-bit fonts and named
+ // CID fonts; collection name for
+ // generic CID fonts
DisplayFontParamKind kind;
union {
struct {
GString *xlfd;
GString *encoding;
} x;
struct {
GString *fileName;
} t1;
struct {
GString *fileName;
} tt;
};
DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
DisplayFontParam(char *nameA, char *xlfdA, char *encodingA);
~DisplayFontParam();
};
// Font rasterizer control.
enum FontRastControl {
fontRastNone, // don't use this rasterizer
fontRastPlain, // use it, without anti-aliasing
fontRastAALow, // use it, with low-level anti-aliasing
fontRastAAHigh // use it, with high-level anti-aliasing
};
//------------------------------------------------------------------------
class PSFontParam {
public:
- GString *pdfFontName;
- GString *psFontName;
+ GString *pdfFontName; // PDF font name for 8-bit fonts and
+ // named 16-bit fonts; char collection
+ // name for generic 16-bit fonts
+ int wMode; // writing mode (0=horiz, 1=vert) for
+ // 16-bit fonts
+ GString *psFontName; // PostScript font name
+ GString *encoding; // encoding, for 16-bit fonts only
- PSFontParam(GString *pdfFontNameA, GString *psFontNameA);
+ PSFontParam(GString *pdfFontNameA, int wModeA,
+ GString *psFontNameA, GString *encodingA);
~PSFontParam();
};
//------------------------------------------------------------------------
enum PSLevel {
psLevel1,
psLevel1Sep,
psLevel2,
- psLevel2Sep
+ psLevel2Sep,
+ psLevel3,
+ psLevel3Sep
};
//------------------------------------------------------------------------
enum EndOfLineKind {
eolUnix, // LF
eolDOS, // CR+LF
eolMac // CR
};
//------------------------------------------------------------------------
class GlobalParams {
public:
// Initialize the global parameters by attempting to read a config
// file.
GlobalParams(char *cfgFileName);
~GlobalParams();
//----- accessors
CharCode getMacRomanCharCode(char *charName);
Unicode mapNameToUnicode(char *charName);
FILE *getCIDToUnicodeFile(GString *collection);
UnicodeMap *getResidentUnicodeMap(GString *encodingName);
FILE *getUnicodeMapFile(GString *encodingName);
FILE *findCMapFile(GString *collection, GString *cMapName);
FILE *findToUnicodeFile(GString *name);
DisplayFontParam *getDisplayFont(GString *fontName);
- DisplayFontParam *getDisplayCIDFont(GString *collection);
+ DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection);
GString *getPSFile() { return psFile; }
int getPSPaperWidth() { return psPaperWidth; }
int getPSPaperHeight() { return psPaperHeight; }
GBool getPSDuplex() { return psDuplex; }
PSLevel getPSLevel() { return psLevel; }
PSFontParam *getPSFont(GString *fontName);
+ PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode);
GBool getPSEmbedType1() { return psEmbedType1; }
GBool getPSEmbedTrueType() { return psEmbedTrueType; }
+ GBool getPSEmbedCIDPostScript() { return psEmbedCIDPostScript; }
+ GBool getPSEmbedCIDTrueType() { return psEmbedCIDTrueType; }
GBool getPSOPI() { return psOPI; }
+ GBool getPSASCIIHex() { return psASCIIHex; }
GString *getTextEncodingName() { return textEncoding; }
EndOfLineKind getTextEOL() { return textEOL; }
GString *findFontFile(GString *fontName, char *ext1, char *ext2);
+ GString *getInitialZoom() { return initialZoom; }
FontRastControl getT1libControl() { return t1libControl; }
FontRastControl getFreeTypeControl() { return freetypeControl; }
GString *getURLCommand() { return urlCommand; }
GBool getMapNumericCharNames() { return mapNumericCharNames; }
GBool getErrQuiet() { return errQuiet; }
CharCodeToUnicode *getCIDToUnicode(GString *collection);
UnicodeMap *getUnicodeMap(GString *encodingName);
CMap *getCMap(GString *collection, GString *cMapName);
UnicodeMap *getTextEncoding();
//----- functions to set parameters
void setPSFile(char *file);
GBool setPSPaperSize(char *size);
void setPSPaperWidth(int width);
void setPSPaperHeight(int height);
void setPSDuplex(GBool duplex);
void setPSLevel(PSLevel level);
void setPSEmbedType1(GBool embed);
void setPSEmbedTrueType(GBool embed);
+ void setPSEmbedCIDPostScript(GBool embed);
+ void setPSEmbedCIDTrueType(GBool embed);
void setPSOPI(GBool opi);
+ void setPSASCIIHex(GBool hex);
void setTextEncoding(char *encodingName);
GBool setTextEOL(char *s);
+ void setInitialZoom(char *s);
GBool setT1libControl(char *s);
GBool setFreeTypeControl(char *s);
void setErrQuiet(GBool errQuietA);
private:
+ void parseFile(GString *fileName, FILE *f);
void parseNameToUnicode(GList *tokens, GString *fileName, int line);
void parseCIDToUnicode(GList *tokens, GString *fileName, int line);
void parseUnicodeMap(GList *tokens, GString *fileName, int line);
void parseCMapDir(GList *tokens, GString *fileName, int line);
void parseToUnicodeDir(GList *tokens, GString *fileName, int line);
- void parseDisplayFont(GList *tokens, GBool isCID, DisplayFontParamKind kind,
+ void parseDisplayFont(GList *tokens, GHash *fontHash,
+ DisplayFontParamKind kind,
GString *fileName, int line);
void parsePSFile(GList *tokens, GString *fileName, int line);
void parsePSPaperSize(GList *tokens, GString *fileName, int line);
void parsePSLevel(GList *tokens, GString *fileName, int line);
void parsePSFont(GList *tokens, GString *fileName, int line);
+ void parsePSFont16(char *cmdName, GList *fontList,
+ GList *tokens, GString *fileName, int line);
void parseTextEncoding(GList *tokens, GString *fileName, int line);
void parseTextEOL(GList *tokens, GString *fileName, int line);
void parseFontDir(GList *tokens, GString *fileName, int line);
+ void parseInitialZoom(GList *tokens, GString *fileName, int line);
void parseFontRastControl(char *cmdName, FontRastControl *val,
GList *tokens, GString *fileName, int line);
void parseURLCommand(GList *tokens, GString *fileName, int line);
void parseYesNo(char *cmdName, GBool *flag,
GList *tokens, GString *fileName, int line);
GBool setFontRastControl(FontRastControl *val, char *s);
//----- static tables
NameToCharCode * // mapping from char name to
macRomanReverseMap; // MacRomanEncoding index
//----- user-modifiable settings
NameToCharCode * // mapping from char name to Unicode
nameToUnicode;
GHash *cidToUnicodes; // files for mappings from char collections
// to Unicode, indexed by collection name
// [GString]
GHash *residentUnicodeMaps; // mappings from Unicode to char codes,
// indexed by encoding name [UnicodeMap]
GHash *unicodeMaps; // files for mappings from Unicode to char
// codes, indexed by encoding name [GString]
GHash *cMapDirs; // list of CMap dirs, indexed by collection
// name [GList[GString]]
GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString]
GHash *displayFonts; // display font info, indexed by font name
// [DisplayFontParam]
GHash *displayCIDFonts; // display CID font info, indexed by
// collection [DisplayFontParam]
+ GHash *displayNamedCIDFonts; // display CID font info, indexed by
+ // font name [DisplayFontParam]
GString *psFile; // PostScript file or command (for xpdf)
int psPaperWidth; // paper size, in PostScript points, for
int psPaperHeight; // PostScript output
GBool psDuplex; // enable duplexing in PostScript?
PSLevel psLevel; // PostScript level to generate
GHash *psFonts; // PostScript font info, indexed by PDF
// font name [PSFontParam]
+ GList *psNamedFonts16; // named 16-bit fonts [PSFontParam]
+ GList *psFonts16; // generic 16-bit fonts [PSFontParam]
GBool psEmbedType1; // embed Type 1 fonts?
GBool psEmbedTrueType; // embed TrueType fonts?
+ GBool psEmbedCIDPostScript; // embed CID PostScript fonts?
+ GBool psEmbedCIDTrueType; // embed CID TrueType fonts?
GBool psOPI; // generate PostScript OPI comments?
+ GBool psASCIIHex; // use ASCIIHex instead of ASCII85?
GString *textEncoding; // encoding (unicodeMap) to use for text
// output
EndOfLineKind textEOL; // type of EOL marker to use for text
// output
GList *fontDirs; // list of font dirs [GString]
+ GString *initialZoom; // initial zoom level
FontRastControl t1libControl; // t1lib rasterization mode
FontRastControl // FreeType rasterization mode
freetypeControl;
GString *urlCommand; // command executed for URL links
GBool mapNumericCharNames; // map numeric char names (from font subsets)?
GBool errQuiet; // suppress error messages?
CIDToUnicodeCache *cidToUnicodeCache;
UnicodeMapCache *unicodeMapCache;
CMapCache *cMapCache;
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Lexer.cc b/noncore/unsupported/qpdf/xpdf/Lexer.cc
index fff4bcb..a258950 100644
--- a/noncore/unsupported/qpdf/xpdf/Lexer.cc
+++ b/noncore/unsupported/qpdf/xpdf/Lexer.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// Lexer.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include "Lexer.h"
#include "Error.h"
//------------------------------------------------------------------------
// A '1' in this array means the character is white space. A '1' or
// '2' means the character ends a name or command.
static char specialChars[256] = {
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
};
//------------------------------------------------------------------------
// Lexer
//------------------------------------------------------------------------
Lexer::Lexer(XRef *xref, Stream *str) {
Object obj;
curStr.initStream(str);
streams = new Array(xref);
streams->add(curStr.copy(&obj));
strPtr = 0;
freeArray = gTrue;
curStr.streamReset();
}
Lexer::Lexer(XRef *xref, Object *obj) {
Object obj2;
if (obj->isStream()) {
streams = new Array(xref);
freeArray = gTrue;
streams->add(obj->copy(&obj2));
} else {
streams = obj->getArray();
freeArray = gFalse;
}
strPtr = 0;
if (streams->getLength() > 0) {
streams->get(strPtr, &curStr);
curStr.streamReset();
}
}
Lexer::~Lexer() {
if (!curStr.isNone()) {
curStr.streamClose();
curStr.free();
}
if (freeArray) {
delete streams;
}
}
int Lexer::getChar() {
int c;
c = EOF;
while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) {
curStr.streamClose();
curStr.free();
++strPtr;
if (strPtr < streams->getLength()) {
streams->get(strPtr, &curStr);
curStr.streamReset();
}
}
return c;
}
diff --git a/noncore/unsupported/qpdf/xpdf/Lexer.h b/noncore/unsupported/qpdf/xpdf/Lexer.h
index 5edbeda..8a01ab2 100644
--- a/noncore/unsupported/qpdf/xpdf/Lexer.h
+++ b/noncore/unsupported/qpdf/xpdf/Lexer.h
@@ -1,74 +1,75 @@
//========================================================================
//
// Lexer.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef LEXER_H
#define LEXER_H
#ifdef __GNUC__
#pragma interface
#endif
#include "Object.h"
#include "Stream.h"
class XRef;
#define tokBufSize 128 // size of token buffer
//------------------------------------------------------------------------
// Lexer
//------------------------------------------------------------------------
class Lexer {
public:
// Construct a lexer for a single stream. Deletes the stream when
// lexer is deleted.
Lexer(XRef *xref, Stream *str);
// Construct a lexer for a stream or array of streams (assumes obj
// is either a stream or array of streams).
Lexer(XRef *xref, Object *obj);
// Destructor.
~Lexer();
// Get the next object from the input stream.
Object *getObj(Object *obj);
// Skip to the beginning of the next line in the input stream.
void skipToNextLine();
// Skip over one character.
void skipChar() { getChar(); }
// Get stream.
Stream *getStream()
{ return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); }
- // Get current position in file.
+ // Get current position in file. This is only used for error
+ // messages, so it returns an int instead of a Guint.
int getPos()
- { return curStr.isNone() ? -1 : curStr.streamGetPos(); }
+ { return curStr.isNone() ? -1 : (int)curStr.streamGetPos(); }
// Set position in file.
- void setPos(int pos)
- { if (!curStr.isNone()) curStr.streamSetPos(pos); }
+ void setPos(Guint pos, int dir = 0)
+ { if (!curStr.isNone()) curStr.streamSetPos(pos, dir); }
private:
int getChar();
int lookChar();
Array *streams; // array of input streams
int strPtr; // index of current stream
Object curStr; // current stream
GBool freeArray; // should lexer free the streams array?
char tokBuf[tokBufSize]; // temporary token buffer
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Link.cc b/noncore/unsupported/qpdf/xpdf/Link.cc
index 79a5f6e..c25ec43 100644
--- a/noncore/unsupported/qpdf/xpdf/Link.cc
+++ b/noncore/unsupported/qpdf/xpdf/Link.cc
@@ -1,634 +1,630 @@
//========================================================================
//
// Link.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include <string.h>
#include "gmem.h"
#include "GString.h"
#include "Error.h"
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "Link.h"
//------------------------------------------------------------------------
static GString *getFileSpecName(Object *fileSpecObj);
//------------------------------------------------------------------------
// LinkDest
//------------------------------------------------------------------------
-LinkDest::LinkDest(Array *a, GBool pageIsRefA) {
+LinkDest::LinkDest(Array *a) {
Object obj1, obj2;
// initialize fields
- pageIsRef = pageIsRefA;
left = bottom = right = top = zoom = 0;
ok = gFalse;
// get page
- if (pageIsRef) {
- if (!a->getNF(0, &obj1)->isRef()) {
- error(-1, "Bad annotation destination");
- goto err2;
- }
+ a->getNF(0, &obj1);
+ if (obj1.isInt()) {
+ pageNum = obj1.getInt() + 1;
+ pageIsRef = gFalse;
+ } else if (obj1.isRef()) {
pageRef.num = obj1.getRefNum();
pageRef.gen = obj1.getRefGen();
- obj1.free();
+ pageIsRef = gTrue;
} else {
- if (!a->get(0, &obj1)->isInt()) {
- error(-1, "Bad annotation destination");
- goto err2;
- }
- pageNum = obj1.getInt() + 1;
- obj1.free();
+ error(-1, "Bad annotation destination");
+ goto err2;
}
+ obj1.free();
// get destination type
a->get(1, &obj1);
// XYZ link
if (obj1.isName("XYZ")) {
kind = destXYZ;
a->get(2, &obj2);
if (obj2.isNull()) {
changeLeft = gFalse;
} else if (obj2.isNum()) {
changeLeft = gTrue;
left = obj2.getNum();
} else {
error(-1, "Bad annotation destination position");
goto err1;
}
obj2.free();
a->get(3, &obj2);
if (obj2.isNull()) {
changeTop = gFalse;
} else if (obj2.isNum()) {
changeTop = gTrue;
top = obj2.getNum();
} else {
error(-1, "Bad annotation destination position");
goto err1;
}
obj2.free();
a->get(4, &obj2);
if (obj2.isNull()) {
changeZoom = gFalse;
} else if (obj2.isNum()) {
changeZoom = gTrue;
zoom = obj2.getNum();
} else {
error(-1, "Bad annotation destination position");
goto err1;
}
obj2.free();
// Fit link
} else if (obj1.isName("Fit")) {
kind = destFit;
// FitH link
} else if (obj1.isName("FitH")) {
kind = destFitH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
goto err1;
}
top = obj2.getNum();
obj2.free();
// FitV link
} else if (obj1.isName("FitV")) {
kind = destFitV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
goto err1;
}
left = obj2.getNum();
obj2.free();
// FitR link
} else if (obj1.isName("FitR")) {
kind = destFitR;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
goto err1;
}
left = obj2.getNum();
obj2.free();
if (!a->get(3, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
goto err1;
}
bottom = obj2.getNum();
obj2.free();
if (!a->get(4, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
goto err1;
}
right = obj2.getNum();
obj2.free();
if (!a->get(5, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
goto err1;
}
top = obj2.getNum();
obj2.free();
// FitB link
} else if (obj1.isName("FitB")) {
kind = destFitB;
// FitBH link
} else if (obj1.isName("FitBH")) {
kind = destFitBH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
goto err1;
}
top = obj2.getNum();
obj2.free();
// FitBV link
} else if (obj1.isName("FitBV")) {
kind = destFitBV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
goto err1;
}
left = obj2.getNum();
obj2.free();
// unknown link kind
} else {
error(-1, "Unknown annotation destination type");
goto err2;
}
obj1.free();
ok = gTrue;
return;
err1:
obj2.free();
err2:
obj1.free();
}
LinkDest::LinkDest(LinkDest *dest) {
kind = dest->kind;
pageIsRef = dest->pageIsRef;
if (pageIsRef)
pageRef = dest->pageRef;
else
pageNum = dest->pageNum;
left = dest->left;
bottom = dest->bottom;
right = dest->right;
top = dest->top;
zoom = dest->zoom;
changeLeft = dest->changeLeft;
changeTop = dest->changeTop;
changeZoom = dest->changeZoom;
ok = gTrue;
}
//------------------------------------------------------------------------
// LinkGoTo
//------------------------------------------------------------------------
LinkGoTo::LinkGoTo(Object *destObj) {
dest = NULL;
namedDest = NULL;
// named destination
if (destObj->isName()) {
namedDest = new GString(destObj->getName());
} else if (destObj->isString()) {
namedDest = destObj->getString()->copy();
// destination dictionary
} else if (destObj->isArray()) {
- dest = new LinkDest(destObj->getArray(), gTrue);
+ dest = new LinkDest(destObj->getArray());
if (!dest->isOk()) {
delete dest;
dest = NULL;
}
// error
} else {
error(-1, "Illegal annotation destination");
}
}
LinkGoTo::~LinkGoTo() {
if (dest)
delete dest;
if (namedDest)
delete namedDest;
}
//------------------------------------------------------------------------
// LinkGoToR
//------------------------------------------------------------------------
LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
dest = NULL;
namedDest = NULL;
// get file name
fileName = getFileSpecName(fileSpecObj);
// named destination
if (destObj->isName()) {
namedDest = new GString(destObj->getName());
} else if (destObj->isString()) {
namedDest = destObj->getString()->copy();
// destination dictionary
} else if (destObj->isArray()) {
- dest = new LinkDest(destObj->getArray(), gFalse);
+ dest = new LinkDest(destObj->getArray());
if (!dest->isOk()) {
delete dest;
dest = NULL;
}
// error
} else {
error(-1, "Illegal annotation destination");
}
}
LinkGoToR::~LinkGoToR() {
if (fileName)
delete fileName;
if (dest)
delete dest;
if (namedDest)
delete namedDest;
}
//------------------------------------------------------------------------
// LinkLaunch
//------------------------------------------------------------------------
LinkLaunch::LinkLaunch(Object *actionObj) {
Object obj1, obj2;
fileName = NULL;
params = NULL;
if (actionObj->isDict()) {
if (!actionObj->dictLookup("F", &obj1)->isNull()) {
fileName = getFileSpecName(&obj1);
} else {
obj1.free();
//~ This hasn't been defined by Adobe yet, so assume it looks
//~ just like the Win dictionary until they say otherwise.
if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
obj1.dictLookup("F", &obj2);
fileName = getFileSpecName(&obj2);
obj2.free();
if (obj1.dictLookup("P", &obj2)->isString())
params = obj2.getString()->copy();
obj2.free();
} else {
error(-1, "Bad launch-type link action");
}
}
obj1.free();
}
}
LinkLaunch::~LinkLaunch() {
if (fileName)
delete fileName;
if (params)
delete params;
}
//------------------------------------------------------------------------
// LinkURI
//------------------------------------------------------------------------
LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
GString *uri2;
int n;
char c;
uri = NULL;
if (uriObj->isString()) {
uri2 = uriObj->getString()->copy();
if (baseURI) {
n = strcspn(uri2->getCString(), "/:");
if (n == uri2->getLength() || uri2->getChar(n) == '/') {
uri = baseURI->copy();
c = uri->getChar(uri->getLength() - 1);
if (c == '/' || c == '?') {
if (uri2->getChar(0) == '/') {
uri2->del(0);
}
} else {
if (uri2->getChar(0) != '/') {
uri->append('/');
}
}
uri->append(uri2);
delete uri2;
} else {
uri = uri2;
}
} else {
uri = uri2;
}
} else {
error(-1, "Illegal URI-type link");
}
}
LinkURI::~LinkURI() {
if (uri)
delete uri;
}
//------------------------------------------------------------------------
// LinkNamed
//------------------------------------------------------------------------
LinkNamed::LinkNamed(Object *nameObj) {
name = NULL;
if (nameObj->isName()) {
name = new GString(nameObj->getName());
}
}
LinkNamed::~LinkNamed() {
if (name) {
delete name;
}
}
//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
LinkUnknown::LinkUnknown(char *actionA) {
action = new GString(actionA);
}
LinkUnknown::~LinkUnknown() {
delete action;
}
//------------------------------------------------------------------------
// Link
//------------------------------------------------------------------------
Link::Link(Dict *dict, GString *baseURI) {
Object obj1, obj2, obj3, obj4;
fouble t;
action = NULL;
ok = gFalse;
// get rectangle
if (!dict->lookup("Rect", &obj1)->isArray()) {
error(-1, "Annotation rectangle is wrong type");
goto err2;
}
if (!obj1.arrayGet(0, &obj2)->isNum()) {
error(-1, "Bad annotation rectangle");
goto err1;
}
x1 = obj2.getNum();
obj2.free();
if (!obj1.arrayGet(1, &obj2)->isNum()) {
error(-1, "Bad annotation rectangle");
goto err1;
}
y1 = obj2.getNum();
obj2.free();
if (!obj1.arrayGet(2, &obj2)->isNum()) {
error(-1, "Bad annotation rectangle");
goto err1;
}
x2 = obj2.getNum();
obj2.free();
if (!obj1.arrayGet(3, &obj2)->isNum()) {
error(-1, "Bad annotation rectangle");
goto err1;
}
y2 = obj2.getNum();
obj2.free();
obj1.free();
if (x1 > x2) {
t = x1;
x1 = x2;
x2 = t;
}
if (y1 > y2) {
t = y1;
y1 = y2;
y2 = t;
}
// get border
- borderW = 0;
+ borderW = 1;
if (!dict->lookup("Border", &obj1)->isNull()) {
if (obj1.isArray() && obj1.arrayGetLength() >= 3) {
if (obj1.arrayGet(2, &obj2)->isNum()) {
borderW = obj2.getNum();
} else {
error(-1, "Bad annotation border");
}
obj2.free();
}
}
obj1.free();
// look for destination
if (!dict->lookup("Dest", &obj1)->isNull()) {
action = new LinkGoTo(&obj1);
// look for action
} else {
obj1.free();
if (dict->lookup("A", &obj1)->isDict()) {
obj1.dictLookup("S", &obj2);
// GoTo action
if (obj2.isName("GoTo")) {
obj1.dictLookup("D", &obj3);
action = new LinkGoTo(&obj3);
obj3.free();
// GoToR action
} else if (obj2.isName("GoToR")) {
obj1.dictLookup("F", &obj3);
obj1.dictLookup("D", &obj4);
action = new LinkGoToR(&obj3, &obj4);
obj3.free();
obj4.free();
// Launch action
} else if (obj2.isName("Launch")) {
action = new LinkLaunch(&obj1);
// URI action
} else if (obj2.isName("URI")) {
obj1.dictLookup("URI", &obj3);
action = new LinkURI(&obj3, baseURI);
obj3.free();
// Named action
} else if (obj2.isName("Named")) {
obj1.dictLookup("N", &obj3);
action = new LinkNamed(&obj3);
obj3.free();
// unknown action
} else if (obj2.isName()) {
action = new LinkUnknown(obj2.getName());
// action is missing or wrong type
} else {
error(-1, "Bad annotation action");
action = NULL;
}
obj2.free();
} else {
error(-1, "Missing annotation destination/action");
action = NULL;
}
}
obj1.free();
// check for bad action
if (action && action->isOk())
ok = gTrue;
return;
err1:
obj2.free();
err2:
obj1.free();
}
Link::~Link() {
if (action)
delete action;
}
//------------------------------------------------------------------------
// Links
//------------------------------------------------------------------------
Links::Links(Object *annots, GString *baseURI) {
Link *link;
Object obj1, obj2;
int size;
int i;
links = NULL;
size = 0;
numLinks = 0;
if (annots->isArray()) {
for (i = 0; i < annots->arrayGetLength(); ++i) {
if (annots->arrayGet(i, &obj1)->isDict()) {
if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
link = new Link(obj1.getDict(), baseURI);
if (link->isOk()) {
if (numLinks >= size) {
size += 16;
links = (Link **)grealloc(links, size * sizeof(Link *));
}
links[numLinks++] = link;
} else {
delete link;
}
}
obj2.free();
}
obj1.free();
}
}
}
Links::~Links() {
int i;
for (i = 0; i < numLinks; ++i)
delete links[i];
gfree(links);
}
LinkAction *Links::find(fouble x, fouble y) {
int i;
- for (i = 0; i < numLinks; ++i) {
+ for (i = numLinks - 1; i >= 0; --i) {
if (links[i]->inRect(x, y)) {
return links[i]->getAction();
}
}
return NULL;
}
GBool Links::onLink(fouble x, fouble y) {
int i;
for (i = 0; i < numLinks; ++i) {
if (links[i]->inRect(x, y))
return gTrue;
}
return gFalse;
}
//------------------------------------------------------------------------
// Extract a file name from a file specification (string or dictionary).
static GString *getFileSpecName(Object *fileSpecObj) {
GString *name;
Object obj1;
name = NULL;
// string
if (fileSpecObj->isString()) {
name = fileSpecObj->getString()->copy();
// dictionary
} else if (fileSpecObj->isDict()) {
if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
obj1.free();
fileSpecObj->dictLookup("F", &obj1);
}
if (obj1.isString())
name = obj1.getString()->copy();
else
error(-1, "Illegal file spec in link");
obj1.free();
// error
} else {
error(-1, "Illegal file spec in link");
}
return name;
}
diff --git a/noncore/unsupported/qpdf/xpdf/Link.h b/noncore/unsupported/qpdf/xpdf/Link.h
index 0ad4581..7b5ba86 100644
--- a/noncore/unsupported/qpdf/xpdf/Link.h
+++ b/noncore/unsupported/qpdf/xpdf/Link.h
@@ -1,165 +1,163 @@
//========================================================================
//
// Link.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef LINK_H
#define LINK_H
#ifdef __GNUC__
#pragma interface
#endif
#include "Object.h"
class GString;
class Array;
class Dict;
//------------------------------------------------------------------------
// LinkAction
//------------------------------------------------------------------------
enum LinkActionKind {
actionGoTo, // go to destination
actionGoToR, // go to destination in new file
actionLaunch, // launch app (or open document)
actionURI, // URI
actionNamed, // named action
actionUnknown // anything else
};
class LinkAction {
public:
// Destructor.
virtual ~LinkAction() {}
// Was the LinkAction created successfully?
virtual GBool isOk() = 0;
// Check link action type.
virtual LinkActionKind getKind() = 0;
};
//------------------------------------------------------------------------
// LinkDest
//------------------------------------------------------------------------
enum LinkDestKind {
destXYZ,
destFit,
destFitH,
destFitV,
destFitR,
destFitB,
destFitBH,
destFitBV
};
class LinkDest {
public:
- // Build a LinkDest from the array. If <pageIsRef> is true, the
- // page is specified by an object reference; otherwise the page is
- // specified by a (zero-relative) page number.
- LinkDest(Array *a, GBool pageIsRef1);
+ // Build a LinkDest from the array.
+ LinkDest(Array *a);
// Copy a LinkDest.
LinkDest *copy() { return new LinkDest(this); }
// Was the LinkDest created successfully?
GBool isOk() { return ok; }
// Accessors.
LinkDestKind getKind() { return kind; }
GBool isPageRef() { return pageIsRef; }
int getPageNum() { return pageNum; }
Ref getPageRef() { return pageRef; }
fouble getLeft() { return left; }
fouble getBottom() { return bottom; }
fouble getRight() { return right; }
fouble getTop() { return top; }
fouble getZoom() { return zoom; }
GBool getChangeLeft() { return changeLeft; }
GBool getChangeTop() { return changeTop; }
GBool getChangeZoom() { return changeZoom; }
private:
LinkDestKind kind; // destination type
GBool pageIsRef; // is the page a reference or number?
union {
Ref pageRef; // reference to page
int pageNum; // one-relative page number
};
fouble left, bottom; // position
fouble right, top;
fouble zoom; // zoom factor
GBool changeLeft, changeTop; // for destXYZ links, which position
GBool changeZoom; // components to change
GBool ok; // set if created successfully
LinkDest(LinkDest *dest);
};
//------------------------------------------------------------------------
// LinkGoTo
//------------------------------------------------------------------------
class LinkGoTo: public LinkAction {
public:
// Build a LinkGoTo from a destination (dictionary, name, or string).
LinkGoTo(Object *destObj);
// Destructor.
virtual ~LinkGoTo();
// Was the LinkGoTo created successfully?
virtual GBool isOk() { return dest || namedDest; }
// Accessors.
virtual LinkActionKind getKind() { return actionGoTo; }
LinkDest *getDest() { return dest; }
GString *getNamedDest() { return namedDest; }
private:
LinkDest *dest; // regular destination (NULL for remote
// link with bad destination)
GString *namedDest; // named destination (only one of dest and
// and namedDest may be non-NULL)
};
//------------------------------------------------------------------------
// LinkGoToR
//------------------------------------------------------------------------
class LinkGoToR: public LinkAction {
public:
// Build a LinkGoToR from a file spec (dictionary) and destination
// (dictionary, name, or string).
LinkGoToR(Object *fileSpecObj, Object *destObj);
// Destructor.
virtual ~LinkGoToR();
// Was the LinkGoToR created successfully?
virtual GBool isOk() { return fileName && (dest || namedDest); }
// Accessors.
virtual LinkActionKind getKind() { return actionGoToR; }
GString *getFileName() { return fileName; }
LinkDest *getDest() { return dest; }
GString *getNamedDest() { return namedDest; }
private:
GString *fileName; // file name
LinkDest *dest; // regular destination (NULL for remote
// link with bad destination)
diff --git a/noncore/unsupported/qpdf/xpdf/NameToCharCode.cc b/noncore/unsupported/qpdf/xpdf/NameToCharCode.cc
index 06be2f4..b9cde77 100644
--- a/noncore/unsupported/qpdf/xpdf/NameToCharCode.cc
+++ b/noncore/unsupported/qpdf/xpdf/NameToCharCode.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// NameToCharCode.cc
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <string.h>
#include "gmem.h"
#include "NameToCharCode.h"
//------------------------------------------------------------------------
struct NameToCharCodeEntry {
char *name;
CharCode c;
};
//------------------------------------------------------------------------
NameToCharCode::NameToCharCode() {
int i;
size = 31;
len = 0;
tab = (NameToCharCodeEntry *)gmalloc(size * sizeof(NameToCharCodeEntry));
for (i = 0; i < size; ++i) {
tab[i].name = NULL;
}
}
NameToCharCode::~NameToCharCode() {
int i;
for (i = 0; i < size; ++i) {
if (tab[i].name) {
gfree(tab[i].name);
}
}
gfree(tab);
}
void NameToCharCode::add(char *name, CharCode c) {
NameToCharCodeEntry *oldTab;
int h, i, oldSize;
// expand the table if necessary
if (len >= size / 2) {
oldSize = size;
oldTab = tab;
size = 2*size + 1;
tab = (NameToCharCodeEntry *)gmalloc(size * sizeof(NameToCharCodeEntry));
for (h = 0; h < size; ++h) {
tab[h].name = NULL;
}
for (i = 0; i < oldSize; ++i) {
if (oldTab[i].name) {
h = hash(oldTab[i].name);
while (tab[h].name) {
if (++h == size) {
h = 0;
}
}
tab[h] = oldTab[i];
}
}
gfree(oldTab);
}
// add the new name
h = hash(name);
while (tab[h].name && strcmp(tab[h].name, name)) {
if (++h == size) {
h = 0;
}
}
if (!tab[h].name) {
tab[h].name = copyString(name);
}
tab[h].c = c;
++len;
}
CharCode NameToCharCode::lookup(char *name) {
int h;
h = hash(name);
while (tab[h].name) {
if (!strcmp(tab[h].name, name)) {
return tab[h].c;
}
if (++h == size) {
h = 0;
}
diff --git a/noncore/unsupported/qpdf/xpdf/NameToCharCode.h b/noncore/unsupported/qpdf/xpdf/NameToCharCode.h
index 9f9b1c3..22e41b6 100644
--- a/noncore/unsupported/qpdf/xpdf/NameToCharCode.h
+++ b/noncore/unsupported/qpdf/xpdf/NameToCharCode.h
@@ -1,40 +1,40 @@
//========================================================================
//
// NameToCharCode.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef NAMETOCHARCODE_H
#define NAMETOCHARCODE_H
#ifdef __GNUC__
#pragma interface
#endif
#include "CharTypes.h"
struct NameToCharCodeEntry;
//------------------------------------------------------------------------
class NameToCharCode {
public:
NameToCharCode();
~NameToCharCode();
void add(char *name, CharCode c);
CharCode lookup(char *name);
private:
int hash(char *name);
NameToCharCodeEntry *tab;
int size;
int len;
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h b/noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h
index 7ca635e..432fafb 100644
--- a/noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h
+++ b/noncore/unsupported/qpdf/xpdf/NameToUnicodeTable.h
@@ -1,101 +1,101 @@
//========================================================================
//
// NameToUnicodeTable.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
static struct {
Unicode u;
char *name;
} nameToUnicodeTab[] = {
{0x0041, "A"},
{0x00c6, "AE"},
{0x01fc, "AEacute"},
{0x00c6, "AEsmall"},
{0x00c1, "Aacute"},
{0x00c1, "Aacutesmall"},
{0x0102, "Abreve"},
{0x00c2, "Acircumflex"},
{0x00c2, "Acircumflexsmall"},
{0xf6c9, "Acute"},
{0xf6c9, "Acutesmall"},
{0x00c4, "Adieresis"},
{0x00c4, "Adieresissmall"},
{0x00c0, "Agrave"},
{0x00c0, "Agravesmall"},
{0x0391, "Alpha"},
{0x0386, "Alphatonos"},
{0x0100, "Amacron"},
{0x0104, "Aogonek"},
{0x00c5, "Aring"},
{0x01fa, "Aringacute"},
{0x00c5, "Aringsmall"},
{0x0041, "Asmall"},
{0x00c3, "Atilde"},
{0x00c3, "Atildesmall"},
{0x0042, "B"},
{0x0392, "Beta"},
{0xf6f4, "Brevesmall"},
{0x0042, "Bsmall"},
{0x0043, "C"},
{0x0106, "Cacute"},
{0xf6ca, "Caron"},
{0xf6ca, "Caronsmall"},
{0x010c, "Ccaron"},
{0x00c7, "Ccedilla"},
{0x00c7, "Ccedillasmall"},
{0x0108, "Ccircumflex"},
{0x010a, "Cdotaccent"},
{0xf7b8, "Cedillasmall"},
{0x03a7, "Chi"},
{0xf6f6, "Circumflexsmall"},
{0x0043, "Csmall"},
{0x0044, "D"},
{0x010e, "Dcaron"},
{0x0110, "Dcroat"},
{0x2206, "Delta"},
{0xf6cb, "Dieresis"},
{0xf6cc, "DieresisAcute"},
{0xf6cd, "DieresisGrave"},
{0xf6cb, "Dieresissmall"},
{0xf6f7, "Dotaccentsmall"},
{0x0044, "Dsmall"},
{0x0045, "E"},
{0x00c9, "Eacute"},
{0x00c9, "Eacutesmall"},
{0x0114, "Ebreve"},
{0x011a, "Ecaron"},
{0x00ca, "Ecircumflex"},
{0x00ca, "Ecircumflexsmall"},
{0x00cb, "Edieresis"},
{0x00cb, "Edieresissmall"},
{0x0116, "Edotaccent"},
{0x00c8, "Egrave"},
{0x00c8, "Egravesmall"},
{0x0112, "Emacron"},
{0x014a, "Eng"},
{0x0118, "Eogonek"},
{0x0395, "Epsilon"},
{0x0388, "Epsilontonos"},
{0x0045, "Esmall"},
{0x0397, "Eta"},
{0x0389, "Etatonos"},
{0x00d0, "Eth"},
{0x00d0, "Ethsmall"},
{0x20ac, "Euro"},
{0x0046, "F"},
{0x0046, "Fsmall"},
{0x0047, "G"},
{0x0393, "Gamma"},
{0x011e, "Gbreve"},
{0x01e6, "Gcaron"},
{0x011c, "Gcircumflex"},
{0x0122, "Gcommaaccent"},
{0x0120, "Gdotaccent"},
{0xf6ce, "Grave"},
{0xf6ce, "Gravesmall"},
{0x0047, "Gsmall"},
{0x0048, "H"},
{0x25cf, "H18533"},
diff --git a/noncore/unsupported/qpdf/xpdf/Object.cc b/noncore/unsupported/qpdf/xpdf/Object.cc
index 5ecade3..6d92c6a 100644
--- a/noncore/unsupported/qpdf/xpdf/Object.cc
+++ b/noncore/unsupported/qpdf/xpdf/Object.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// Object.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "Error.h"
#include "Stream.h"
#include "XRef.h"
//------------------------------------------------------------------------
// Object
//------------------------------------------------------------------------
char *objTypeNames[numObjTypes] = {
"boolean",
"integer",
"real",
"string",
"name",
"null",
"array",
"dictionary",
"stream",
"ref",
"cmd",
"error",
"eof",
"none"
};
#ifdef DEBUG_MEM
int Object::numAlloc[numObjTypes] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
#endif
Object *Object::initArray(XRef *xref) {
initObj(objArray);
array = new Array(xref);
return this;
}
Object *Object::initDict(XRef *xref) {
initObj(objDict);
dict = new Dict(xref);
return this;
}
Object *Object::initStream(Stream *streamA) {
initObj(objStream);
stream = streamA;
return this;
}
Object *Object::copy(Object *obj) {
*obj = *this;
switch (type) {
case objString:
obj->string = string->copy();
break;
case objName:
obj->name = copyString(name);
break;
case objArray:
array->incRef();
break;
case objDict:
dict->incRef();
break;
case objStream:
stream->incRef();
break;
case objCmd:
obj->cmd = copyString(cmd);
break;
default:
break;
}
#ifdef DEBUG_MEM
++numAlloc[type];
#endif
return obj;
}
Object *Object::fetch(XRef *xref, Object *obj) {
return (type == objRef && xref) ?
xref->fetch(ref.num, ref.gen, obj) : copy(obj);
}
void Object::free() {
diff --git a/noncore/unsupported/qpdf/xpdf/Object.h b/noncore/unsupported/qpdf/xpdf/Object.h
index 000ffa0..7a67a7d 100644
--- a/noncore/unsupported/qpdf/xpdf/Object.h
+++ b/noncore/unsupported/qpdf/xpdf/Object.h
@@ -1,299 +1,299 @@
//========================================================================
//
// Object.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef OBJECT_H
#define OBJECT_H
#ifdef __GNUC__
#pragma interface
#endif
#include <stdio.h>
#include <string.h>
#include "gtypes.h"
#include "gmem.h"
#include "GString.h"
class XRef;
class Array;
class Dict;
class Stream;
//------------------------------------------------------------------------
// Ref
//------------------------------------------------------------------------
struct Ref {
int num; // object number
int gen; // generation number
};
//------------------------------------------------------------------------
// object types
//------------------------------------------------------------------------
enum ObjType {
// simple objects
objBool, // boolean
objInt, // integer
objReal, // real
objString, // string
objName, // name
objNull, // null
// complex objects
objArray, // array
objDict, // dictionary
objStream, // stream
objRef, // indirect reference
// special objects
objCmd, // command name
objError, // error return from Lexer
objEOF, // end of file return from Lexer
objNone // uninitialized object
};
#define numObjTypes 14 // total number of object types
//------------------------------------------------------------------------
// Object
//------------------------------------------------------------------------
#ifdef DEBUG_MEM
#define initObj(t) ++numAlloc[type = t]
#else
#define initObj(t) type = t
#endif
class Object {
public:
// Default constructor.
Object():
type(objNone) {}
// Initialize an object.
Object *initBool(GBool boolnA)
{ initObj(objBool); booln = boolnA; return this; }
Object *initInt(int intgA)
{ initObj(objInt); intg = intgA; return this; }
Object *initReal(fouble realA)
{ initObj(objReal); real = realA; return this; }
Object *initString(GString *stringA)
{ initObj(objString); string = stringA; return this; }
Object *initName(char *nameA)
{ initObj(objName); name = copyString(nameA); return this; }
Object *initNull()
{ initObj(objNull); return this; }
Object *initArray(XRef *xref);
Object *initDict(XRef *xref);
Object *initStream(Stream *streamA);
Object *initRef(int numA, int genA)
{ initObj(objRef); ref.num = numA; ref.gen = genA; return this; }
Object *initCmd(char *cmdA)
{ initObj(objCmd); cmd = copyString(cmdA); return this; }
Object *initError()
{ initObj(objError); return this; }
Object *initEOF()
{ initObj(objEOF); return this; }
// Copy an object.
Object *copy(Object *obj);
// If object is a Ref, fetch and return the referenced object.
// Otherwise, return a copy of the object.
Object *fetch(XRef *xref, Object *obj);
// Free object contents.
void free();
// Type checking.
ObjType getType() { return type; }
GBool isBool() { return type == objBool; }
GBool isInt() { return type == objInt; }
GBool isReal() { return type == objReal; }
GBool isNum() { return type == objInt || type == objReal; }
GBool isString() { return type == objString; }
GBool isName() { return type == objName; }
GBool isNull() { return type == objNull; }
GBool isArray() { return type == objArray; }
GBool isDict() { return type == objDict; }
GBool isStream() { return type == objStream; }
GBool isRef() { return type == objRef; }
GBool isCmd() { return type == objCmd; }
GBool isError() { return type == objError; }
GBool isEOF() { return type == objEOF; }
GBool isNone() { return type == objNone; }
// Special type checking.
GBool isName(char *nameA)
{ return type == objName && !strcmp(name, nameA); }
GBool isDict(char *dictType);
GBool isStream(char *dictType);
GBool isCmd(char *cmdA)
{ return type == objCmd && !strcmp(cmd, cmdA); }
// Accessors. NB: these assume object is of correct type.
GBool getBool() { return booln; }
int getInt() { return intg; }
fouble getReal() { return real; }
fouble getNum() { return type == objInt ? (fouble)intg : real; }
GString *getString() { return string; }
char *getName() { return name; }
Array *getArray() { return array; }
Dict *getDict() { return dict; }
Stream *getStream() { return stream; }
Ref getRef() { return ref; }
int getRefNum() { return ref.num; }
int getRefGen() { return ref.gen; }
// Array accessors.
int arrayGetLength();
void arrayAdd(Object *elem);
Object *arrayGet(int i, Object *obj);
Object *arrayGetNF(int i, Object *obj);
// Dict accessors.
int dictGetLength();
void dictAdd(char *key, Object *val);
GBool dictIs(char *dictType);
Object *dictLookup(char *key, Object *obj);
Object *dictLookupNF(char *key, Object *obj);
char *dictGetKey(int i);
Object *dictGetVal(int i, Object *obj);
Object *dictGetValNF(int i, Object *obj);
// Stream accessors.
GBool streamIs(char *dictType);
void streamReset();
void streamClose();
int streamGetChar();
int streamLookChar();
char *streamGetLine(char *buf, int size);
- int streamGetPos();
- void streamSetPos(int pos);
+ Guint streamGetPos();
+ void streamSetPos(Guint pos, int dir = 0);
Dict *streamGetDict();
// Output.
char *getTypeName();
void print(FILE *f = stdout);
// Memory testing.
static void memCheck(FILE *f);
private:
ObjType type; // object type
fouble real; // real
union { // value for each type:
GBool booln; // boolean
int intg; // integer
GString *string; // string
char *name; // name
Array *array; // array
Dict *dict; // dictionary
Stream *stream; // stream
Ref ref; // indirect reference
char *cmd; // command
};
#ifdef DEBUG_MEM
static int // number of each type of object
numAlloc[numObjTypes]; // currently allocated
#endif
};
//------------------------------------------------------------------------
// Array accessors.
//------------------------------------------------------------------------
#include "Array.h"
inline int Object::arrayGetLength()
{ return array->getLength(); }
inline void Object::arrayAdd(Object *elem)
{ array->add(elem); }
inline Object *Object::arrayGet(int i, Object *obj)
{ return array->get(i, obj); }
inline Object *Object::arrayGetNF(int i, Object *obj)
{ return array->getNF(i, obj); }
//------------------------------------------------------------------------
// Dict accessors.
//------------------------------------------------------------------------
#include "Dict.h"
inline int Object::dictGetLength()
{ return dict->getLength(); }
inline void Object::dictAdd(char *key, Object *val)
{ dict->add(key, val); }
inline GBool Object::dictIs(char *dictType)
{ return dict->is(dictType); }
inline GBool Object::isDict(char *dictType)
{ return type == objDict && dictIs(dictType); }
inline Object *Object::dictLookup(char *key, Object *obj)
{ return dict->lookup(key, obj); }
inline Object *Object::dictLookupNF(char *key, Object *obj)
{ return dict->lookupNF(key, obj); }
inline char *Object::dictGetKey(int i)
{ return dict->getKey(i); }
inline Object *Object::dictGetVal(int i, Object *obj)
{ return dict->getVal(i, obj); }
inline Object *Object::dictGetValNF(int i, Object *obj)
{ return dict->getValNF(i, obj); }
//------------------------------------------------------------------------
// Stream accessors.
//------------------------------------------------------------------------
#include "Stream.h"
inline GBool Object::streamIs(char *dictType)
{ return stream->getDict()->is(dictType); }
inline GBool Object::isStream(char *dictType)
{ return type == objStream && streamIs(dictType); }
inline void Object::streamReset()
{ stream->reset(); }
inline void Object::streamClose()
{ stream->close(); }
inline int Object::streamGetChar()
{ return stream->getChar(); }
inline int Object::streamLookChar()
{ return stream->lookChar(); }
inline char *Object::streamGetLine(char *buf, int size)
{ return stream->getLine(buf, size); }
-inline int Object::streamGetPos()
+inline Guint Object::streamGetPos()
{ return stream->getPos(); }
-inline void Object::streamSetPos(int pos)
- { stream->setPos(pos); }
+inline void Object::streamSetPos(Guint pos, int dir)
+ { stream->setPos(pos, dir); }
inline Dict *Object::streamGetDict()
{ return stream->getDict(); }
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/OutputDev.cc b/noncore/unsupported/qpdf/xpdf/OutputDev.cc
index 3c02835..1004f0f 100644
--- a/noncore/unsupported/qpdf/xpdf/OutputDev.cc
+++ b/noncore/unsupported/qpdf/xpdf/OutputDev.cc
@@ -1,97 +1,102 @@
//========================================================================
//
// OutputDev.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Stream.h"
#include "GfxState.h"
#include "OutputDev.h"
//------------------------------------------------------------------------
// OutputDev
//------------------------------------------------------------------------
void OutputDev::setDefaultCTM(fouble *ctm) {
int i;
fouble det;
for (i = 0; i < 6; ++i) {
defCTM[i] = ctm[i];
}
det = 1 / (defCTM[0] * defCTM[3] - defCTM[1] * defCTM[2]);
defICTM[0] = defCTM[3] * det;
defICTM[1] = -defCTM[1] * det;
defICTM[2] = -defCTM[2] * det;
defICTM[3] = defCTM[0] * det;
defICTM[4] = (defCTM[2] * defCTM[5] - defCTM[3] * defCTM[4]) * det;
defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det;
}
void OutputDev::cvtDevToUser(int dx, int dy, fouble *ux, fouble *uy) {
*ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4];
*uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5];
}
void OutputDev::cvtUserToDev(fouble ux, fouble uy, int *dx, int *dy) {
*dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5);
*dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5);
}
void OutputDev::updateAll(GfxState *state) {
updateLineDash(state);
updateFlatness(state);
updateLineJoin(state);
updateLineCap(state);
updateMiterLimit(state);
updateLineWidth(state);
updateFillColor(state);
updateStrokeColor(state);
updateFont(state);
}
+GBool OutputDev::beginType3Char(GfxState *state,
+ CharCode code, Unicode *u, int uLen) {
+ return gFalse;
+}
+
void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg) {
int i, j;
if (inlineImg) {
str->reset();
j = height * ((width + 7) / 8);
for (i = 0; i < j; ++i)
str->getChar();
str->close();
}
}
void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg) {
int i, j;
if (inlineImg) {
str->reset();
j = height * ((width * colorMap->getNumPixelComps() *
colorMap->getBits() + 7) / 8);
for (i = 0; i < j; ++i)
str->getChar();
str->close();
}
}
#if OPI_SUPPORT
void OutputDev::opiBegin(GfxState *state, Dict *opiDict) {
}
void OutputDev::opiEnd(GfxState *state, Dict *opiDict) {
}
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/OutputDev.h b/noncore/unsupported/qpdf/xpdf/OutputDev.h
index 04cbace..398c035 100644
--- a/noncore/unsupported/qpdf/xpdf/OutputDev.h
+++ b/noncore/unsupported/qpdf/xpdf/OutputDev.h
@@ -1,143 +1,158 @@
//========================================================================
//
// OutputDev.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef OUTPUTDEV_H
#define OUTPUTDEV_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
#include "CharTypes.h"
class GString;
class GfxState;
class GfxColorSpace;
class GfxImageColorMap;
class Stream;
class Link;
class Catalog;
//------------------------------------------------------------------------
// OutputDev
//------------------------------------------------------------------------
class OutputDev {
public:
// Constructor.
OutputDev() {}
// Destructor.
virtual ~OutputDev() {}
//----- 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() = 0;
// Does this device use drawChar() or drawString()?
virtual GBool useDrawChar() = 0;
+ // Does this device use beginType3Char/endType3Char? Otherwise,
+ // text in Type 3 fonts will be drawn with drawChar/drawString.
+ virtual GBool interpretType3Chars() = 0;
+
// Does this device need non-text content?
virtual GBool needNonText() { return gTrue; }
//----- initialization and control
// Set default transform matrix.
virtual void setDefaultCTM(fouble *ctm);
// Start a page.
virtual void startPage(int pageNum, GfxState *state) {}
// End a page.
virtual void endPage() {}
// Dump page contents to display.
virtual void dump() {}
//----- coordinate conversion
// Convert between device and user coordinates.
virtual void cvtDevToUser(int dx, int dy, fouble *ux, fouble *uy);
virtual void cvtUserToDev(fouble ux, fouble uy, int *dx, int *dy);
//----- 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, fouble m11, fouble m12,
fouble m21, fouble m22, fouble m31, fouble 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) {}
virtual void updateFillOpacity(GfxState *state) {}
virtual void updateStrokeOpacity(GfxState *state) {}
//----- update text state
virtual void updateFont(GfxState *state) {}
virtual void updateTextMat(GfxState *state) {}
virtual void updateCharSpace(GfxState *state) {}
virtual void updateRender(GfxState *state) {}
virtual void updateRise(GfxState *state) {}
virtual void updateWordSpace(GfxState *state) {}
virtual void updateHorizScaling(GfxState *state) {}
virtual void updateTextPos(GfxState *state) {}
virtual void updateTextShift(GfxState *state, fouble shift) {}
//----- 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 beginString(GfxState *state, GString *s) {}
virtual void endString(GfxState *state) {}
virtual void drawChar(GfxState *state, fouble x, fouble y,
fouble dx, fouble dy,
fouble originX, fouble originY,
CharCode code, Unicode *u, int uLen) {}
virtual void drawString(GfxState *state, GString *s) {}
+ virtual GBool beginType3Char(GfxState *state,
+ CharCode code, Unicode *u, int uLen);
+ virtual void endType3Char(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);
#if OPI_SUPPORT
//----- OPI functions
virtual void opiBegin(GfxState *state, Dict *opiDict);
virtual void opiEnd(GfxState *state, Dict *opiDict);
#endif
+ //----- Type 3 font operators
+ virtual void type3D0(GfxState *state, fouble wx, fouble wy) {}
+ virtual void type3D1(GfxState *state, fouble wx, fouble wy,
+ fouble llx, fouble lly, fouble urx, fouble ury) {}
+
+ //----- PostScript XObjects
+ virtual void psXObject(Stream *psStream, Stream *level1Stream) {}
+
private:
fouble defCTM[6]; // default coordinate transform matrix
fouble defICTM[6]; // inverse of default CTM
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/PDFDoc.cc b/noncore/unsupported/qpdf/xpdf/PDFDoc.cc
index 4bbe9b7..97dfa55 100644
--- a/noncore/unsupported/qpdf/xpdf/PDFDoc.cc
+++ b/noncore/unsupported/qpdf/xpdf/PDFDoc.cc
@@ -1,251 +1,259 @@
//========================================================================
//
// PDFDoc.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "GString.h"
#include "config.h"
#include "Page.h"
#include "Catalog.h"
#include "Stream.h"
#include "XRef.h"
#include "Link.h"
#include "OutputDev.h"
#include "Error.h"
+#include "ErrorCodes.h"
#include "Lexer.h"
#include "Parser.h"
#include "PDFDoc.h"
//------------------------------------------------------------------------
#define headerSearchSize 1024 // read this many bytes at beginning of
// file to look for '%PDF'
//------------------------------------------------------------------------
// PDFDoc
//------------------------------------------------------------------------
PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
GString *userPassword, GBool printCommandsA) {
Object obj;
GString *fileName2;
ok = gFalse;
+ errCode = errNone;
file = NULL;
str = NULL;
xref = NULL;
catalog = NULL;
links = NULL;
printCommands = printCommandsA;
// try to open file
fileName = fileNameA;
fileName2 = NULL;
#ifdef VMS
if (!(file = fopen(fileName->getCString(), "rb", "ctx=stm"))) {
error(-1, "Couldn't open file '%s'", fileName->getCString());
+ errCode = errOpenFile;
return;
}
#else
if (!(file = fopen(fileName->getCString(), "rb"))) {
fileName2 = fileName->copy();
fileName2->lowerCase();
if (!(file = fopen(fileName2->getCString(), "rb"))) {
fileName2->upperCase();
if (!(file = fopen(fileName2->getCString(), "rb"))) {
error(-1, "Couldn't open file '%s'", fileName->getCString());
delete fileName2;
+ errCode = errOpenFile;
return;
}
}
delete fileName2;
}
#endif
// create stream
obj.initNull();
- str = new FileStream(file, 0, -1, &obj);
+ str = new FileStream(file, 0, gFalse, 0, &obj);
ok = setup(ownerPassword, userPassword);
}
PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
GString *userPassword, GBool printCommandsA) {
ok = gFalse;
+ errCode = errNone;
fileName = NULL;
file = NULL;
str = strA;
xref = NULL;
catalog = NULL;
links = NULL;
printCommands = printCommandsA;
ok = setup(ownerPassword, userPassword);
}
GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
// check header
checkHeader();
// read xref table
xref = new XRef(str, ownerPassword, userPassword);
if (!xref->isOk()) {
error(-1, "Couldn't read xref table");
+ errCode = xref->getErrorCode();
return gFalse;
}
// read catalog
catalog = new Catalog(xref, printCommands);
if (!catalog->isOk()) {
error(-1, "Couldn't read page catalog");
+ errCode = errBadCatalog;
return gFalse;
}
// done
return gTrue;
}
PDFDoc::~PDFDoc() {
if (catalog) {
delete catalog;
}
if (xref) {
delete xref;
}
if (str) {
delete str;
}
if (file) {
fclose(file);
}
if (fileName) {
delete fileName;
}
if (links) {
delete links;
}
}
// Check for a PDF header on this stream. Skip past some garbage
// if necessary.
void PDFDoc::checkHeader() {
char hdrBuf[headerSearchSize+1];
char *p;
int i;
pdfVersion = 0;
for (i = 0; i < headerSearchSize; ++i) {
hdrBuf[i] = str->getChar();
}
hdrBuf[headerSearchSize] = '\0';
for (i = 0; i < headerSearchSize - 5; ++i) {
if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
break;
}
}
if (i >= headerSearchSize - 5) {
error(-1, "May not be a PDF file (continuing anyway)");
return;
}
str->moveStart(i);
p = strtok(&hdrBuf[i+5], " \t\n\r");
pdfVersion = atof(p);
if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
pdfVersion > supportedPDFVersionNum + 0.0001) {
error(-1, "PDF version %s -- xpdf supports version %s"
" (continuing anyway)", p, supportedPDFVersionStr);
}
}
void PDFDoc::displayPage(OutputDev *out, int page, fouble zoom,
int rotate, GBool doLinks) {
Page *p;
if (printCommands) {
printf("***** page %d *****\n", page);
}
p = catalog->getPage(page);
if (doLinks) {
if (links) {
delete links;
}
getLinks(p);
p->display(out, zoom, rotate, links, catalog);
} else {
p->display(out, zoom, rotate, NULL, catalog);
}
}
void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
int zoom, int rotate, GBool doLinks) {
int page;
for (page = firstPage; page <= lastPage; ++page) {
displayPage(out, page, zoom, rotate, doLinks);
}
}
GBool PDFDoc::isLinearized() {
Parser *parser;
Object obj1, obj2, obj3, obj4, obj5;
GBool lin;
lin = gFalse;
obj1.initNull();
- parser = new Parser(xref, new Lexer(xref, str->makeSubStream(str->getStart(),
- -1, &obj1)));
+ parser = new Parser(xref,
+ new Lexer(xref,
+ str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
parser->getObj(&obj4);
if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
obj4.isDict()) {
obj4.dictLookup("Linearized", &obj5);
if (obj5.isNum() && obj5.getNum() > 0) {
lin = gTrue;
}
obj5.free();
}
obj4.free();
obj3.free();
obj2.free();
obj1.free();
delete parser;
return lin;
}
GBool PDFDoc::saveAs(GString *name) {
FILE *f;
int c;
if (!(f = fopen(name->getCString(), "wb"))) {
error(-1, "Couldn't open file '%s'", name->getCString());
return gFalse;
}
str->reset();
while ((c = str->getChar()) != EOF) {
fputc(c, f);
}
str->close();
fclose(f);
return gTrue;
}
void PDFDoc::getLinks(Page *page) {
Object obj;
links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
obj.free();
}
diff --git a/noncore/unsupported/qpdf/xpdf/PDFDoc.h b/noncore/unsupported/qpdf/xpdf/PDFDoc.h
index 592095e..3157683 100644
--- a/noncore/unsupported/qpdf/xpdf/PDFDoc.h
+++ b/noncore/unsupported/qpdf/xpdf/PDFDoc.h
@@ -1,142 +1,146 @@
//========================================================================
//
// PDFDoc.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef PDFDOC_H
#define PDFDOC_H
#ifdef __GNUC__
#pragma interface
#endif
#include <stdio.h>
#include "XRef.h"
#include "Link.h"
#include "Catalog.h"
#include "Page.h"
class GString;
class BaseStream;
class OutputDev;
class Links;
class LinkAction;
class LinkDest;
//------------------------------------------------------------------------
// PDFDoc
//------------------------------------------------------------------------
class PDFDoc {
public:
PDFDoc(GString *fileNameA, GString *ownerPassword = NULL,
GString *userPassword = NULL, GBool printCommandsA = gFalse);
PDFDoc(BaseStream *strA, GString *ownerPassword = NULL,
GString *userPassword = NULL, GBool printCommandsA = gFalse);
~PDFDoc();
// Was PDF document successfully opened?
GBool isOk() { return ok; }
+ // Get the error code (if isOk() returns false).
+ int getErrorCode() { return errCode; }
+
// Get file name.
GString *getFileName() { return fileName; }
// Get the xref table.
XRef *getXRef() { return xref; }
// Get catalog.
Catalog *getCatalog() { return catalog; }
// Get base stream.
BaseStream *getBaseStream() { return str; }
// Get page parameters.
fouble getPageWidth(int page)
{ return catalog->getPage(page)->getWidth(); }
fouble getPageHeight(int page)
{ return catalog->getPage(page)->getHeight(); }
int getPageRotate(int page)
{ return catalog->getPage(page)->getRotate(); }
// Get number of pages.
int getNumPages() { return catalog->getNumPages(); }
// Return the contents of the metadata stream, or NULL if there is
// no metadata.
GString *readMetadata() { return catalog->readMetadata(); }
// Return the structure tree root object.
Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); }
// Display a page.
void displayPage(OutputDev *out, int page, fouble zoom,
int rotate, GBool doLinks);
// Display a range of pages.
void displayPages(OutputDev *out, int firstPage, int lastPage,
int zoom, int rotate, GBool doLinks);
// Find a page, given its object ID. Returns page number, or 0 if
// not found.
int findPage(int num, int gen) { return catalog->findPage(num, gen); }
// If point <x>,<y> is in a link, return the associated action;
// else return NULL.
LinkAction *findLink(fouble x, fouble y) { return links->find(x, y); }
// Return true if <x>,<y> is in a link.
GBool onLink(fouble x, fouble y) { return links->onLink(x, y); }
// Find a named destination. Returns the link destination, or
// NULL if <name> is not a destination.
LinkDest *findDest(GString *name)
{ return catalog->findDest(name); }
// Is the file encrypted?
GBool isEncrypted() { return xref->isEncrypted(); }
// Check various permissions.
GBool okToPrint(GBool ignoreOwnerPW = gFalse)
{ return xref->okToPrint(ignoreOwnerPW); }
GBool okToChange(GBool ignoreOwnerPW = gFalse)
{ return xref->okToChange(ignoreOwnerPW); }
GBool okToCopy(GBool ignoreOwnerPW = gFalse)
{ return xref->okToCopy(ignoreOwnerPW); }
GBool okToAddNotes(GBool ignoreOwnerPW = gFalse)
{ return xref->okToAddNotes(ignoreOwnerPW); }
// Is this document linearized?
GBool isLinearized();
// Return the document's Info dictionary (if any).
Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); }
// Return the PDF version specified by the file.
fouble getPDFVersion() { return pdfVersion; }
// Save this file with another name.
GBool saveAs(GString *name);
private:
GBool setup(GString *ownerPassword, GString *userPassword);
void checkHeader();
void getLinks(Page *page);
GString *fileName;
FILE *file;
BaseStream *str;
fouble pdfVersion;
XRef *xref;
Catalog *catalog;
Links *links;
GBool printCommands;
GBool ok;
+ int errCode;
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/PSTokenizer.cc b/noncore/unsupported/qpdf/xpdf/PSTokenizer.cc
new file mode 100644
index 0000000..8d654bd
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/PSTokenizer.cc
@@ -0,0 +1,133 @@
+//========================================================================
+//
+// PSTokenizer.cc
+//
+// Copyright 2002 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "PSTokenizer.h"
+
+//------------------------------------------------------------------------
+
+// A '1' in this array means the character is white space. A '1' or
+// '2' means the character ends a name or command.
+static char specialChars[256] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
+ 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
+};
+
+//------------------------------------------------------------------------
+
+PSTokenizer::PSTokenizer(int (*getCharFuncA)(void *), void *dataA) {
+ getCharFunc = getCharFuncA;
+ data = dataA;
+ charBuf = -1;
+}
+
+PSTokenizer::~PSTokenizer() {
+}
+
+GBool PSTokenizer::getToken(char *buf, int size, int *length) {
+ GBool comment, backslash;
+ int c;
+ int i;
+
+ // skip whitespace and comments
+ comment = gFalse;
+ while (1) {
+ if ((c = getChar()) == EOF) {
+ buf[0] = '\0';
+ *length = 0;
+ return gFalse;
+ }
+ if (comment) {
+ if (c == '\x0a' || c == '\x0d') {
+ comment = gFalse;
+ }
+ } else if (c == '%') {
+ comment = gTrue;
+ } else if (specialChars[c] != 1) {
+ break;
+ }
+ }
+
+ // read a token
+ i = 0;
+ buf[i++] = c;
+ if (c == '(') {
+ backslash = gFalse;
+ while ((c = lookChar()) != EOF) {
+ if (i < size - 1) {
+ buf[i++] = c;
+ }
+ getChar();
+ if (c == '\\') {
+ backslash = gTrue;
+ } else if (!backslash && c == ')') {
+ break;
+ } else {
+ backslash = gFalse;
+ }
+ }
+ } else if (c == '<') {
+ while ((c = lookChar()) != EOF) {
+ getChar();
+ if (i < size - 1) {
+ buf[i++] = c;
+ }
+ if (c == '>') {
+ break;
+ }
+ }
+ } else if (c != '[' && c != ']') {
+ while ((c = lookChar()) != EOF && !specialChars[c]) {
+ getChar();
+ if (i < size - 1) {
+ buf[i++] = c;
+ }
+ }
+ }
+ buf[i] = '\0';
+ *length = i;
+
+ return gTrue;
+}
+
+int PSTokenizer::lookChar() {
+ if (charBuf < 0) {
+ charBuf = (*getCharFunc)(data);
+ }
+ return charBuf;
+}
+
+int PSTokenizer::getChar() {
+ int c;
+
+ if (charBuf < 0) {
+ charBuf = (*getCharFunc)(data);
+ }
+ c = charBuf;
+ charBuf = -1;
+ return c;
+}
diff --git a/noncore/unsupported/qpdf/xpdf/PSTokenizer.h b/noncore/unsupported/qpdf/xpdf/PSTokenizer.h
new file mode 100644
index 0000000..1053c67
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/PSTokenizer.h
@@ -0,0 +1,39 @@
+//========================================================================
+//
+// PSTokenizer.h
+//
+// Copyright 2002 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef PSTOKENIZER_H
+#define PSTOKENIZER_H
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+
+class PSTokenizer {
+public:
+
+ PSTokenizer(int (*getCharFuncA)(void *), void *dataA);
+ ~PSTokenizer();
+
+ // Get the next PostScript token. Returns false at end-of-stream.
+ GBool getToken(char *buf, int size, int *length);
+
+private:
+
+ int lookChar();
+ int getChar();
+
+ int (*getCharFunc)(void *);
+ void *data;
+ int charBuf;
+};
+
+#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Page.cc b/noncore/unsupported/qpdf/xpdf/Page.cc
index 17c4481..9cc08c4 100644
--- a/noncore/unsupported/qpdf/xpdf/Page.cc
+++ b/noncore/unsupported/qpdf/xpdf/Page.cc
@@ -1,267 +1,281 @@
//========================================================================
//
// Page.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "XRef.h"
#include "Link.h"
#include "OutputDev.h"
#ifndef PDF_PARSER_ONLY
#include "Gfx.h"
-#include "FormWidget.h"
+#include "Annot.h"
#endif
#include "Error.h"
#include "Page.h"
//------------------------------------------------------------------------
// PageAttrs
//------------------------------------------------------------------------
PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
Object obj1;
fouble w, h;
// get old/default values
if (attrs) {
mediaBox = attrs->mediaBox;
cropBox = attrs->cropBox;
haveCropBox = attrs->haveCropBox;
rotate = attrs->rotate;
attrs->resources.copy(&resources);
} else {
// set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
// but some (non-compliant) PDF files don't specify a MediaBox
mediaBox.x1 = 0;
mediaBox.y1 = 0;
mediaBox.x2 = 612;
mediaBox.y2 = 792;
cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
haveCropBox = gFalse;
rotate = 0;
resources.initNull();
}
// media box
readBox(dict, "MediaBox", &mediaBox);
// crop box
cropBox = mediaBox;
haveCropBox = readBox(dict, "CropBox", &cropBox);
// if the MediaBox is excessively larger than the CropBox,
// just use the CropBox
limitToCropBox = gFalse;
if (haveCropBox) {
w = 0.25 * (cropBox.x2 - cropBox.x1);
h = 0.25 * (cropBox.y2 - cropBox.y1);
if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w ||
(cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) {
limitToCropBox = gTrue;
}
}
// other boxes
bleedBox = cropBox;
readBox(dict, "BleedBox", &bleedBox);
trimBox = cropBox;
readBox(dict, "TrimBox", &trimBox);
artBox = cropBox;
readBox(dict, "ArtBox", &artBox);
// rotate
dict->lookup("Rotate", &obj1);
if (obj1.isInt()) {
rotate = obj1.getInt();
}
obj1.free();
while (rotate < 0) {
rotate += 360;
}
while (rotate >= 360) {
rotate -= 360;
}
+ // misc attributes
+ dict->lookup("LastModified", &lastModified);
+ dict->lookup("BoxColorInfo", &boxColorInfo);
+ dict->lookup("Group", &group);
+ dict->lookup("Metadata", &metadata);
+ dict->lookup("PieceInfo", &pieceInfo);
+ dict->lookup("SeparationInfo", &separationInfo);
+
// resource dictionary
dict->lookup("Resources", &obj1);
if (obj1.isDict()) {
resources.free();
obj1.copy(&resources);
}
obj1.free();
}
PageAttrs::~PageAttrs() {
+ lastModified.free();
+ boxColorInfo.free();
+ group.free();
+ metadata.free();
+ pieceInfo.free();
+ separationInfo.free();
resources.free();
}
GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
PDFRectangle tmp;
Object obj1, obj2;
GBool ok;
dict->lookup(key, &obj1);
if (obj1.isArray() && obj1.arrayGetLength() == 4) {
ok = gTrue;
obj1.arrayGet(0, &obj2);
if (obj2.isNum()) {
tmp.x1 = obj2.getNum();
} else {
ok = gFalse;
}
obj2.free();
obj1.arrayGet(1, &obj2);
if (obj2.isNum()) {
tmp.y1 = obj2.getNum();
} else {
ok = gFalse;
}
obj2.free();
obj1.arrayGet(2, &obj2);
if (obj2.isNum()) {
tmp.x2 = obj2.getNum();
} else {
ok = gFalse;
}
obj2.free();
obj1.arrayGet(3, &obj2);
if (obj2.isNum()) {
tmp.y2 = obj2.getNum();
} else {
ok = gFalse;
}
obj2.free();
if (ok) {
*box = tmp;
}
} else {
ok = gFalse;
}
obj1.free();
return ok;
}
//------------------------------------------------------------------------
// Page
//------------------------------------------------------------------------
Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
GBool printCommandsA) {
ok = gTrue;
xref = xrefA;
num = numA;
printCommands = printCommandsA;
// get attributes
attrs = attrsA;
// annotations
pageDict->lookupNF("Annots", &annots);
if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
error(-1, "Page annotations object (page %d) is wrong type (%s)",
num, annots.getTypeName());
annots.free();
goto err2;
}
// contents
pageDict->lookupNF("Contents", &contents);
if (!(contents.isRef() || contents.isArray() ||
contents.isNull())) {
error(-1, "Page contents object (page %d) is wrong type (%s)",
num, contents.getTypeName());
contents.free();
goto err1;
}
return;
err2:
annots.initNull();
err1:
contents.initNull();
ok = gFalse;
}
Page::~Page() {
delete attrs;
annots.free();
contents.free();
}
void Page::display(OutputDev *out, fouble dpi, int rotate,
Links *links, Catalog *catalog) {
#ifndef PDF_PARSER_ONLY
PDFRectangle *box, *cropBox;
Gfx *gfx;
Object obj;
Link *link;
int i;
- FormWidgets *formWidgets;
+ Annots *annotList;
box = getBox();
cropBox = getCropBox();
if (printCommands) {
printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
box->x1, box->y1, box->x2, box->y2);
if (isCropped()) {
printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
}
printf("***** Rotate = %d\n", attrs->getRotate());
}
rotate += getRotate();
if (rotate >= 360) {
rotate -= 360;
} else if (rotate < 0) {
rotate += 360;
}
gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
dpi, box, isCropped(), cropBox, rotate, printCommands);
contents.fetch(xref, &obj);
if (!obj.isNull()) {
gfx->display(&obj);
}
obj.free();
// draw links
if (links) {
for (i = 0; i < links->getNumLinks(); ++i) {
link = links->getLink(i);
out->drawLink(link, catalog);
}
out->dump();
}
- // draw AcroForm widgets
+ // draw non-link annotations
//~ need to reset CTM ???
- formWidgets = new FormWidgets(xref, annots.fetch(xref, &obj));
+ annotList = new Annots(xref, annots.fetch(xref, &obj));
obj.free();
- if (printCommands && formWidgets->getNumWidgets() > 0) {
- printf("***** AcroForm widgets\n");
- }
- for (i = 0; i < formWidgets->getNumWidgets(); ++i) {
- formWidgets->getWidget(i)->draw(gfx);
- }
- if (formWidgets->getNumWidgets() > 0) {
+ if (annotList->getNumAnnots() > 0) {
+ if (printCommands) {
+ printf("***** Annotations\n");
+ }
+ for (i = 0; i < annotList->getNumAnnots(); ++i) {
+ annotList->getAnnot(i)->draw(gfx);
+ }
out->dump();
}
- delete formWidgets;
+ delete annotList;
delete gfx;
#endif
}
diff --git a/noncore/unsupported/qpdf/xpdf/Page.h b/noncore/unsupported/qpdf/xpdf/Page.h
index 203878f..57e802a 100644
--- a/noncore/unsupported/qpdf/xpdf/Page.h
+++ b/noncore/unsupported/qpdf/xpdf/Page.h
@@ -1,125 +1,151 @@
//========================================================================
//
// Page.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef PAGE_H
#define PAGE_H
#ifdef __GNUC__
#pragma interface
#endif
#include "Object.h"
class Dict;
class XRef;
class OutputDev;
class Links;
class Catalog;
//------------------------------------------------------------------------
struct PDFRectangle {
fouble x1, y1, x2, y2;
};
//------------------------------------------------------------------------
// PageAttrs
//------------------------------------------------------------------------
class PageAttrs {
public:
// Construct a new PageAttrs object by merging a dictionary
// (of type Pages or Page) into another PageAttrs object. If
// <attrs> is NULL, uses defaults.
PageAttrs(PageAttrs *attrs, Dict *dict);
// Destructor.
~PageAttrs();
// Accessors.
PDFRectangle *getBox() { return limitToCropBox ? &cropBox : &mediaBox; }
PDFRectangle *getMediaBox() { return &mediaBox; }
PDFRectangle *getCropBox() { return &cropBox; }
GBool isCropped() { return haveCropBox; }
PDFRectangle *getBleedBox() { return &bleedBox; }
PDFRectangle *getTrimBox() { return &trimBox; }
PDFRectangle *getArtBox() { return &artBox; }
int getRotate() { return rotate; }
+ GString *getLastModified()
+ { return lastModified.isString()
+ ? lastModified.getString() : (GString *)NULL; }
+ Dict *getBoxColorInfo()
+ { return boxColorInfo.isDict() ? boxColorInfo.getDict() : (Dict *)NULL; }
+ Dict *getGroup()
+ { return group.isDict() ? group.getDict() : (Dict *)NULL; }
+ Stream *getMetadata()
+ { return metadata.isStream() ? metadata.getStream() : (Stream *)NULL; }
+ Dict *getPieceInfo()
+ { return pieceInfo.isDict() ? pieceInfo.getDict() : (Dict *)NULL; }
+ Dict *getSeparationInfo()
+ { return separationInfo.isDict()
+ ? separationInfo.getDict() : (Dict *)NULL; }
Dict *getResourceDict()
{ return resources.isDict() ? resources.getDict() : (Dict *)NULL; }
private:
GBool readBox(Dict *dict, char *key, PDFRectangle *box);
PDFRectangle mediaBox;
PDFRectangle cropBox;
GBool haveCropBox;
GBool limitToCropBox;
PDFRectangle bleedBox;
PDFRectangle trimBox;
PDFRectangle artBox;
int rotate;
+ Object lastModified;
+ Object boxColorInfo;
+ Object group;
+ Object metadata;
+ Object pieceInfo;
+ Object separationInfo;
Object resources;
};
//------------------------------------------------------------------------
// Page
//------------------------------------------------------------------------
class Page {
public:
// Constructor.
Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA,
GBool printCommandsA);
// Destructor.
~Page();
// Is page valid?
GBool isOk() { return ok; }
// Get page parameters.
PDFRectangle *getBox() { return attrs->getBox(); }
PDFRectangle *getMediaBox() { return attrs->getMediaBox(); }
PDFRectangle *getCropBox() { return attrs->getCropBox(); }
GBool isCropped() { return attrs->isCropped(); }
fouble getWidth() { return attrs->getBox()->x2 - attrs->getBox()->x1; }
fouble getHeight() { return attrs->getBox()->y2 - attrs->getBox()->y1; }
PDFRectangle *getBleedBox() { return attrs->getBleedBox(); }
PDFRectangle *getTrimBox() { return attrs->getTrimBox(); }
PDFRectangle *getArtBox() { return attrs->getArtBox(); }
int getRotate() { return attrs->getRotate(); }
+ GString *getLastModified() { return attrs->getLastModified(); }
+ Dict *getBoxColorInfo() { return attrs->getBoxColorInfo(); }
+ Dict *getGroup() { return attrs->getGroup(); }
+ Stream *getMetadata() { return attrs->getMetadata(); }
+ Dict *getPieceInfo() { return attrs->getPieceInfo(); }
+ Dict *getSeparationInfo() { return attrs->getSeparationInfo(); }
// Get resource dictionary.
Dict *getResourceDict() { return attrs->getResourceDict(); }
// Get annotations array.
Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
// Get contents.
Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
// Display a page.
void display(OutputDev *out, fouble dpi, int rotate,
Links *links, Catalog *catalog);
private:
XRef *xref; // the xref table for this PDF file
int num; // page number
PageAttrs *attrs; // page attributes
Object annots; // annotations array
Object contents; // page contents
GBool printCommands; // print the drawing commands (for debugging)
GBool ok; // true if page is valid
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Parser.cc b/noncore/unsupported/qpdf/xpdf/Parser.cc
index a98753d..4df53c9 100644
--- a/noncore/unsupported/qpdf/xpdf/Parser.cc
+++ b/noncore/unsupported/qpdf/xpdf/Parser.cc
@@ -1,213 +1,214 @@
//========================================================================
//
// Parser.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stddef.h>
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "Parser.h"
#include "XRef.h"
#include "Error.h"
#ifndef NO_DECRYPTION
#include "Decrypt.h"
#endif
Parser::Parser(XRef *xrefA, Lexer *lexerA) {
xref = xrefA;
lexer = lexerA;
inlineImg = 0;
lexer->getObj(&buf1);
lexer->getObj(&buf2);
}
Parser::~Parser() {
buf1.free();
buf2.free();
delete lexer;
}
#ifndef NO_DECRYPTION
Object *Parser::getObj(Object *obj,
Guchar *fileKey, int keyLength,
int objNum, int objGen) {
#else
Object *Parser::getObj(Object *obj) {
#endif
char *key;
Stream *str;
Object obj2;
int num;
#ifndef NO_DECRYPTION
Decrypt *decrypt;
GString *s;
char *p;
int i;
#endif
// refill buffer after inline image data
if (inlineImg == 2) {
buf1.free();
buf2.free();
lexer->getObj(&buf1);
lexer->getObj(&buf2);
inlineImg = 0;
}
// array
if (buf1.isCmd("[")) {
shift();
obj->initArray(xref);
while (!buf1.isCmd("]") && !buf1.isEOF())
#ifndef NO_DECRYPTION
obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
#else
obj->arrayAdd(getObj(&obj2));
#endif
if (buf1.isEOF())
error(getPos(), "End of file inside array");
shift();
// dictionary or stream
} else if (buf1.isCmd("<<")) {
shift();
obj->initDict(xref);
while (!buf1.isCmd(">>") && !buf1.isEOF()) {
if (!buf1.isName()) {
error(getPos(), "Dictionary key must be a name object");
shift();
} else {
key = copyString(buf1.getName());
shift();
if (buf1.isEOF() || buf1.isError())
break;
#ifndef NO_DECRYPTION
obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
#else
obj->dictAdd(key, getObj(&obj2));
#endif
}
}
if (buf1.isEOF())
error(getPos(), "End of file inside dictionary");
if (buf2.isCmd("stream")) {
if ((str = makeStream(obj))) {
obj->initStream(str);
#ifndef NO_DECRYPTION
if (fileKey) {
str->getBaseStream()->doDecryption(fileKey, keyLength,
objNum, objGen);
}
#endif
} else {
obj->free();
obj->initError();
}
} else {
shift();
}
// indirect reference or integer
} else if (buf1.isInt()) {
num = buf1.getInt();
shift();
if (buf1.isInt() && buf2.isCmd("R")) {
obj->initRef(num, buf1.getInt());
shift();
shift();
} else {
obj->initInt(num);
}
#ifndef NO_DECRYPTION
// string
} else if (buf1.isString() && fileKey) {
buf1.copy(obj);
s = obj->getString();
decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
for (i = 0, p = obj->getString()->getCString();
i < s->getLength();
++i, ++p) {
*p = decrypt->decryptByte(*p);
}
delete decrypt;
shift();
#endif
// simple object
} else {
buf1.copy(obj);
shift();
}
return obj;
}
Stream *Parser::makeStream(Object *dict) {
Object obj;
Stream *str;
- int pos, endPos, length;
+ Guint pos, endPos, length;
// get stream start position
lexer->skipToNextLine();
pos = lexer->getPos();
// get length
dict->dictLookup("Length", &obj);
if (obj.isInt()) {
- length = obj.getInt();
+ length = (Guint)obj.getInt();
obj.free();
} else {
error(getPos(), "Bad 'Length' attribute in stream");
obj.free();
return NULL;
}
// check for length in damaged file
- if ((endPos = xref->getStreamEnd(pos)) >= 0) {
+ if (xref->getStreamEnd(pos, &endPos)) {
length = endPos - pos;
}
// make base stream
- str = lexer->getStream()->getBaseStream()->makeSubStream(pos, length, dict);
+ str = lexer->getStream()->getBaseStream()->makeSubStream(pos, gTrue,
+ length, dict);
// get filters
str = str->addFilters(dict);
// skip over stream data
lexer->setPos(pos + length);
// refill token buffers and check for 'endstream'
shift(); // kill '>>'
shift(); // kill 'stream'
if (buf1.isCmd("endstream"))
shift();
else
error(getPos(), "Missing 'endstream'");
return str;
}
void Parser::shift() {
if (inlineImg > 0) {
++inlineImg;
} else if (buf2.isCmd("ID")) {
lexer->skipChar(); // skip char after 'ID' command
inlineImg = 1;
}
buf1.free();
buf1 = buf2;
if (inlineImg > 0) // don't buffer inline image data
buf2.initNull();
else
lexer->getObj(&buf2);
}
diff --git a/noncore/unsupported/qpdf/xpdf/Parser.h b/noncore/unsupported/qpdf/xpdf/Parser.h
index 463d998..c11475b 100644
--- a/noncore/unsupported/qpdf/xpdf/Parser.h
+++ b/noncore/unsupported/qpdf/xpdf/Parser.h
@@ -1,58 +1,58 @@
//========================================================================
//
// Parser.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef PARSER_H
#define PARSER_H
#ifdef __GNUC__
#pragma interface
#endif
#include "Lexer.h"
//------------------------------------------------------------------------
// Parser
//------------------------------------------------------------------------
class Parser {
public:
// Constructor.
Parser(XRef *xrefA, Lexer *lexerA);
// Destructor.
~Parser();
// Get the next object from the input stream.
#ifndef NO_DECRYPTION
Object *getObj(Object *obj,
Guchar *fileKey = NULL, int keyLength = 0,
int objNum = 0, int objGen = 0);
#else
Object *getObj(Object *obj);
#endif
// Get stream.
Stream *getStream() { return lexer->getStream(); }
// Get current position in file.
int getPos() { return lexer->getPos(); }
private:
XRef *xref; // the xref table for this PDF file
Lexer *lexer; // input stream
Object buf1, buf2; // next two tokens
int inlineImg; // set when inline image data is encountered
Stream *makeStream(Object *dict);
void shift();
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/Stream-CCITT.h b/noncore/unsupported/qpdf/xpdf/Stream-CCITT.h
index 1af8742..f5a77b0 100644
--- a/noncore/unsupported/qpdf/xpdf/Stream-CCITT.h
+++ b/noncore/unsupported/qpdf/xpdf/Stream-CCITT.h
@@ -1,103 +1,103 @@
//========================================================================
//
// Stream-CCITT.h
//
// Tables for CCITT Fax decoding.
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
struct CCITTCode {
short bits;
short n;
};
#define ccittEOL -2
//------------------------------------------------------------------------
// 2D codes
//------------------------------------------------------------------------
#define twoDimPass 0
#define twoDimHoriz 1
#define twoDimVert0 2
#define twoDimVertR1 3
#define twoDimVertL1 4
#define twoDimVertR2 5
#define twoDimVertL2 6
#define twoDimVertR3 7
#define twoDimVertL3 8
// 1-7 bit codes
static CCITTCode twoDimTab1[128] = {
{-1, -1}, {-1, -1}, // 000000x
{7, twoDimVertL3}, // 0000010
{7, twoDimVertR3}, // 0000011
{6, twoDimVertL2}, {6, twoDimVertL2}, // 000010x
{6, twoDimVertR2}, {6, twoDimVertR2}, // 000011x
{4, twoDimPass}, {4, twoDimPass}, // 0001xxx
{4, twoDimPass}, {4, twoDimPass},
{4, twoDimPass}, {4, twoDimPass},
{4, twoDimPass}, {4, twoDimPass},
{3, twoDimHoriz}, {3, twoDimHoriz}, // 001xxxx
{3, twoDimHoriz}, {3, twoDimHoriz},
{3, twoDimHoriz}, {3, twoDimHoriz},
{3, twoDimHoriz}, {3, twoDimHoriz},
{3, twoDimHoriz}, {3, twoDimHoriz},
{3, twoDimHoriz}, {3, twoDimHoriz},
{3, twoDimHoriz}, {3, twoDimHoriz},
{3, twoDimHoriz}, {3, twoDimHoriz},
{3, twoDimVertL1}, {3, twoDimVertL1}, // 010xxxx
{3, twoDimVertL1}, {3, twoDimVertL1},
{3, twoDimVertL1}, {3, twoDimVertL1},
{3, twoDimVertL1}, {3, twoDimVertL1},
{3, twoDimVertL1}, {3, twoDimVertL1},
{3, twoDimVertL1}, {3, twoDimVertL1},
{3, twoDimVertL1}, {3, twoDimVertL1},
{3, twoDimVertL1}, {3, twoDimVertL1},
{3, twoDimVertR1}, {3, twoDimVertR1}, // 011xxxx
{3, twoDimVertR1}, {3, twoDimVertR1},
{3, twoDimVertR1}, {3, twoDimVertR1},
{3, twoDimVertR1}, {3, twoDimVertR1},
{3, twoDimVertR1}, {3, twoDimVertR1},
{3, twoDimVertR1}, {3, twoDimVertR1},
{3, twoDimVertR1}, {3, twoDimVertR1},
{3, twoDimVertR1}, {3, twoDimVertR1},
{1, twoDimVert0}, {1, twoDimVert0}, // 1xxxxxx
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0},
{1, twoDimVert0}, {1, twoDimVert0}
};
//------------------------------------------------------------------------
// white run lengths
//------------------------------------------------------------------------
diff --git a/noncore/unsupported/qpdf/xpdf/Stream.cc b/noncore/unsupported/qpdf/xpdf/Stream.cc
index 18490d4..c558478 100644
--- a/noncore/unsupported/qpdf/xpdf/Stream.cc
+++ b/noncore/unsupported/qpdf/xpdf/Stream.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// Stream.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <string.h>
#include <ctype.h>
#include "gmem.h"
#include "gfile.h"
#include "config.h"
#include "Error.h"
#include "Object.h"
#ifndef NO_DECRYPTION
#include "Decrypt.h"
#endif
#include "Stream.h"
#include "Stream-CCITT.h"
#ifdef __DJGPP__
static GBool setDJSYSFLAGS = gFalse;
#endif
#ifdef VMS
#if (__VMS_VER < 70000000)
extern "C" int unlink(char *filename);
#endif
#ifdef __GNUC__
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
#endif
#ifdef MACOS
#include "StuffItEngineLib.h"
#endif
//------------------------------------------------------------------------
// Stream (base class)
//------------------------------------------------------------------------
Stream::Stream() {
ref = 1;
}
Stream::~Stream() {
}
void Stream::close() {
}
int Stream::getRawChar() {
error(-1, "Internal: called getRawChar() on non-predictor stream");
return EOF;
}
char *Stream::getLine(char *buf, int size) {
int i;
int c;
if (lookChar() == EOF)
return NULL;
for (i = 0; i < size - 1; ++i) {
c = getChar();
if (c == EOF || c == '\n')
break;
if (c == '\r') {
if ((c = lookChar()) == '\n')
getChar();
break;
}
buf[i] = c;
}
buf[i] = '\0';
return buf;
}
GString *Stream::getPSFilter(char *indent) {
return new GString();
}
Stream *Stream::addFilters(Object *dict) {
Object obj, obj2;
Object params, params2;
Stream *str;
int i;
@@ -210,193 +210,193 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
if (obj.isInt()) {
columns = obj.getInt();
}
obj.free();
params->dictLookup("Rows", &obj);
if (obj.isInt()) {
rows = obj.getInt();
}
obj.free();
params->dictLookup("EndOfBlock", &obj);
if (obj.isBool()) {
endOfBlock = obj.getBool();
}
obj.free();
params->dictLookup("BlackIs1", &obj);
if (obj.isBool()) {
black = obj.getBool();
}
obj.free();
}
str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
columns, rows, endOfBlock, black);
} else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
str = new DCTStream(str);
} else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
pred = 1;
columns = 1;
colors = 1;
bits = 8;
if (params->isDict()) {
params->dictLookup("Predictor", &obj);
if (obj.isInt())
pred = obj.getInt();
obj.free();
params->dictLookup("Columns", &obj);
if (obj.isInt())
columns = obj.getInt();
obj.free();
params->dictLookup("Colors", &obj);
if (obj.isInt())
colors = obj.getInt();
obj.free();
params->dictLookup("BitsPerComponent", &obj);
if (obj.isInt())
bits = obj.getInt();
obj.free();
}
str = new FlateStream(str, pred, columns, colors, bits);
} else {
error(getPos(), "Unknown filter '%s'", name);
str = new EOFStream(str);
}
return str;
}
//------------------------------------------------------------------------
// BaseStream
//------------------------------------------------------------------------
BaseStream::BaseStream(Object *dictA) {
dict = *dictA;
#ifndef NO_DECRYPTION
decrypt = NULL;
#endif
}
BaseStream::~BaseStream() {
dict.free();
#ifndef NO_DECRYPTION
if (decrypt)
delete decrypt;
#endif
}
#ifndef NO_DECRYPTION
void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
int objNum, int objGen) {
decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
}
#endif
//------------------------------------------------------------------------
// FilterStream
//------------------------------------------------------------------------
FilterStream::FilterStream(Stream *strA) {
str = strA;
}
FilterStream::~FilterStream() {
}
void FilterStream::close() {
str->close();
}
-void FilterStream::setPos(int pos) {
+void FilterStream::setPos(Guint pos, int dir) {
error(-1, "Internal: called setPos() on FilterStream");
}
//------------------------------------------------------------------------
// ImageStream
//------------------------------------------------------------------------
ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
int imgLineSize;
str = strA;
width = widthA;
nComps = nCompsA;
nBits = nBitsA;
nVals = width * nComps;
if (nBits == 1) {
imgLineSize = (nVals + 7) & ~7;
} else {
imgLineSize = nVals;
}
imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
imgIdx = nVals;
}
ImageStream::~ImageStream() {
gfree(imgLine);
}
void ImageStream::reset() {
str->reset();
}
GBool ImageStream::getPixel(Guchar *pix) {
Gulong buf, bitMask;
int bits;
int c;
int i;
if (imgIdx >= nVals) {
// read one line of image pixels
if (nBits == 1) {
for (i = 0; i < nVals; i += 8) {
c = str->getChar();
imgLine[i+0] = (Guchar)((c >> 7) & 1);
imgLine[i+1] = (Guchar)((c >> 6) & 1);
imgLine[i+2] = (Guchar)((c >> 5) & 1);
imgLine[i+3] = (Guchar)((c >> 4) & 1);
imgLine[i+4] = (Guchar)((c >> 3) & 1);
imgLine[i+5] = (Guchar)((c >> 2) & 1);
imgLine[i+6] = (Guchar)((c >> 1) & 1);
imgLine[i+7] = (Guchar)(c & 1);
}
} else if (nBits == 8) {
for (i = 0; i < nVals; ++i) {
imgLine[i] = str->getChar();
}
} else {
bitMask = (1 << nBits) - 1;
buf = 0;
bits = 0;
for (i = 0; i < nVals; ++i) {
if (bits < nBits) {
buf = (buf << 8) | (str->getChar() & 0xff);
bits += 8;
}
imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
bits -= nBits;
}
}
// reset to start of line
imgIdx = 0;
}
for (i = 0; i < nComps; ++i)
pix[i] = imgLine[imgIdx++];
return gTrue;
}
void ImageStream::skipLine() {
int n, i;
n = (nVals * nBits + 7) >> 3;
for (i = 0; i < n; ++i) {
str->getChar();
}
}
//------------------------------------------------------------------------
// StreamPredictor
//------------------------------------------------------------------------
StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
int widthA, int nCompsA, int nBitsA) {
@@ -461,313 +461,426 @@ GBool StreamPredictor::getNextLine() {
upLeftBuf[3] = upLeftBuf[2];
upLeftBuf[2] = upLeftBuf[1];
upLeftBuf[1] = upLeftBuf[0];
upLeftBuf[0] = predLine[i];
if ((c = str->getRawChar()) == EOF) {
break;
}
switch (curPred) {
case 11: // PNG sub
predLine[i] = predLine[i - pixBytes] + (Guchar)c;
break;
case 12: // PNG up
predLine[i] = predLine[i] + (Guchar)c;
break;
case 13: // PNG average
predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
(Guchar)c;
break;
case 14: // PNG Paeth
left = predLine[i - pixBytes];
up = predLine[i];
upLeft = upLeftBuf[pixBytes];
p = left + up - upLeft;
if ((pa = p - left) < 0)
pa = -pa;
if ((pb = p - up) < 0)
pb = -pb;
if ((pc = p - upLeft) < 0)
pc = -pc;
if (pa <= pb && pa <= pc)
predLine[i] = left + (Guchar)c;
else if (pb <= pc)
predLine[i] = up + (Guchar)c;
else
predLine[i] = upLeft + (Guchar)c;
break;
case 10: // PNG none
default: // no predictor or TIFF predictor
predLine[i] = (Guchar)c;
break;
}
}
// apply TIFF (component) predictor
//~ this is completely untested
if (predictor == 2) {
if (nBits == 1) {
inBuf = predLine[pixBytes - 1];
for (i = pixBytes; i < rowBytes; i += 8) {
// 1-bit add is just xor
inBuf = (inBuf << 8) | predLine[i];
predLine[i] ^= inBuf >> nComps;
}
} else if (nBits == 8) {
for (i = pixBytes; i < rowBytes; ++i) {
predLine[i] += predLine[i - nComps];
}
} else {
upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
bitMask = (1 << nBits) - 1;
inBuf = outBuf = 0;
inBits = outBits = 0;
j = k = pixBytes;
for (i = 0; i < nVals; ++i) {
if (inBits < nBits) {
inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
inBits += 8;
}
upLeftBuf[3] = upLeftBuf[2];
upLeftBuf[2] = upLeftBuf[1];
upLeftBuf[1] = upLeftBuf[0];
upLeftBuf[0] = (upLeftBuf[nComps] +
(inBuf >> (inBits - nBits))) & bitMask;
outBuf = (outBuf << nBits) | upLeftBuf[0];
inBits -= nBits;
outBits += nBits;
if (outBits > 8) {
predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
}
}
if (outBits > 0) {
predLine[k++] = (Guchar)(outBuf << (8 - outBits));
}
}
}
// reset to start of line
predIdx = pixBytes;
return gTrue;
}
//------------------------------------------------------------------------
// FileStream
//------------------------------------------------------------------------
-FileStream::FileStream(FILE *fA, int startA, int lengthA, Object *dictA):
+FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA):
BaseStream(dictA) {
f = fA;
start = startA;
+ limited = limitedA;
length = lengthA;
bufPtr = bufEnd = buf;
bufPos = start;
- savePos = -1;
+ savePos = 0;
+ saved = gFalse;
}
FileStream::~FileStream() {
close();
}
-Stream *FileStream::makeSubStream(int startA, int lengthA, Object *dictA) {
- return new FileStream(f, startA, lengthA, dictA);
+Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA) {
+ return new FileStream(f, startA, limitedA, lengthA, dictA);
}
void FileStream::reset() {
- savePos = (int)ftell(f);
+#if HAVE_FSEEK64
+ savePos = (Guint)ftell64(f);
+ fseek64(f, start, SEEK_SET);
+#else
+ savePos = (Guint)ftell(f);
fseek(f, start, SEEK_SET);
+#endif
+ saved = gTrue;
bufPtr = bufEnd = buf;
bufPos = start;
#ifndef NO_DECRYPTION
if (decrypt)
decrypt->reset();
#endif
}
void FileStream::close() {
- if (savePos >= 0) {
+ if (saved) {
+#if HAVE_FSEEK64
+ fseek64(f, savePos, SEEK_SET);
+#else
fseek(f, savePos, SEEK_SET);
- savePos = -1;
+#endif
+ saved = gFalse;
}
}
GBool FileStream::fillBuf() {
int n;
#ifndef NO_DECRYPTION
char *p;
#endif
bufPos += bufEnd - buf;
bufPtr = bufEnd = buf;
- if (length >= 0 && bufPos >= start + length) {
+ if (limited && bufPos >= start + length) {
return gFalse;
}
- if (length >= 0 && bufPos + fileStreamBufSize > start + length) {
+ if (limited && bufPos + fileStreamBufSize > start + length) {
n = start + length - bufPos;
} else {
n = fileStreamBufSize;
}
n = fread(buf, 1, n, f);
bufEnd = buf + n;
if (bufPtr >= bufEnd) {
return gFalse;
}
#ifndef NO_DECRYPTION
if (decrypt) {
for (p = buf; p < bufEnd; ++p) {
*p = (char)decrypt->decryptByte((Guchar)*p);
}
}
#endif
return gTrue;
}
-void FileStream::setPos(int pos) {
- long size;
+void FileStream::setPos(Guint pos, int dir) {
+ Guint size;
- if (pos >= 0) {
+ if (dir >= 0) {
+#if HAVE_FSEEK64
+ fseek64(f, pos, SEEK_SET);
+#else
fseek(f, pos, SEEK_SET);
+#endif
bufPos = pos;
} else {
+#if HAVE_FSEEK64
+ fseek64(f, 0, SEEK_END);
+ size = (Guint)ftell64(f);
+#else
fseek(f, 0, SEEK_END);
- size = ftell(f);
- if (pos < -size)
- pos = (int)(-size);
+ size = (Guint)ftell(f);
+#endif
+ if (pos > size)
+ pos = (Guint)size;
#ifdef __CYGWIN32__
//~ work around a bug in cygwin's implementation of fseek
rewind(f);
#endif
- fseek(f, pos, SEEK_END);
- bufPos = (int)ftell(f);
+#if HAVE_FSEEK64
+ fseek64(f, -(int)pos, SEEK_END);
+ bufPos = (Guint)ftell64(f);
+#else
+ fseek(f, -(int)pos, SEEK_END);
+ bufPos = (Guint)ftell(f);
+#endif
}
bufPtr = bufEnd = buf;
}
void FileStream::moveStart(int delta) {
start += delta;
bufPtr = bufEnd = buf;
bufPos = start;
}
//------------------------------------------------------------------------
+// MemStream
+//------------------------------------------------------------------------
+
+MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
+ BaseStream(dictA) {
+ buf = bufA;
+ needFree = gFalse;
+ length = lengthA;
+ bufEnd = buf + length;
+ bufPtr = buf;
+}
+
+MemStream::~MemStream() {
+ if (needFree) {
+ gfree(buf);
+ }
+}
+
+Stream *MemStream::makeSubStream(Guint start, GBool limited,
+ Guint lengthA, Object *dictA) {
+ Guint newLength;
+
+ if (!limited || start + lengthA > length) {
+ newLength = length - start;
+ } else {
+ newLength = lengthA;
+ }
+ return new MemStream(buf + start, newLength, dictA);
+}
+
+void MemStream::reset() {
+ bufPtr = buf;
+#ifndef NO_DECRYPTION
+ if (decrypt) {
+ decrypt->reset();
+ }
+#endif
+}
+
+void MemStream::close() {
+}
+
+void MemStream::setPos(Guint pos, int dir) {
+ if (dir >= 0) {
+ if (pos > length) {
+ bufPtr = bufEnd;
+ } else {
+ bufPtr = buf + pos;
+ }
+ } else {
+ if (pos > length) {
+ bufPtr = buf;
+ } else {
+ bufPtr = bufEnd - pos;
+ }
+ }
+}
+
+void MemStream::moveStart(int delta) {
+ buf += delta;
+ bufPtr = buf;
+}
+
+#ifndef NO_DECRYPTION
+void MemStream::doDecryption(Guchar *fileKey, int keyLength,
+ int objNum, int objGen) {
+ char *newBuf;
+ char *p, *q;
+
+ this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
+ if (decrypt) {
+ newBuf = (char *)gmalloc(bufEnd - buf);
+ for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
+ *q = (char)decrypt->decryptByte((Guchar)*p);
+ }
+ bufEnd = newBuf + (bufEnd - buf);
+ bufPtr = newBuf + (bufPtr - buf);
+ buf = newBuf;
+ needFree = gTrue;
+ }
+}
+#endif
+
+//------------------------------------------------------------------------
// EmbedStream
//------------------------------------------------------------------------
EmbedStream::EmbedStream(Stream *strA, Object *dictA):
BaseStream(dictA) {
str = strA;
}
EmbedStream::~EmbedStream() {
}
-Stream *EmbedStream::makeSubStream(int start, int length, Object *dictA) {
+Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
+ Guint length, Object *dictA) {
error(-1, "Internal: called makeSubStream() on EmbedStream");
return NULL;
}
-void EmbedStream::setPos(int pos) {
+void EmbedStream::setPos(Guint pos, int dir) {
error(-1, "Internal: called setPos() on EmbedStream");
}
-int EmbedStream::getStart() {
+Guint EmbedStream::getStart() {
error(-1, "Internal: called getStart() on EmbedStream");
return 0;
}
-void EmbedStream::moveStart(int start) {
+void EmbedStream::moveStart(int delta) {
error(-1, "Internal: called moveStart() on EmbedStream");
}
//------------------------------------------------------------------------
// ASCIIHexStream
//------------------------------------------------------------------------
ASCIIHexStream::ASCIIHexStream(Stream *strA):
FilterStream(strA) {
buf = EOF;
eof = gFalse;
}
ASCIIHexStream::~ASCIIHexStream() {
delete str;
}
void ASCIIHexStream::reset() {
str->reset();
buf = EOF;
eof = gFalse;
}
int ASCIIHexStream::lookChar() {
int c1, c2, x;
if (buf != EOF)
return buf;
if (eof) {
buf = EOF;
return EOF;
}
do {
c1 = str->getChar();
} while (isspace(c1));
if (c1 == '>') {
eof = gTrue;
buf = EOF;
return buf;
}
do {
c2 = str->getChar();
} while (isspace(c2));
if (c2 == '>') {
eof = gTrue;
c2 = '0';
}
if (c1 >= '0' && c1 <= '9') {
x = (c1 - '0') << 4;
} else if (c1 >= 'A' && c1 <= 'F') {
x = (c1 - 'A' + 10) << 4;
} else if (c1 >= 'a' && c1 <= 'f') {
x = (c1 - 'a' + 10) << 4;
} else if (c1 == EOF) {
eof = gTrue;
x = 0;
} else {
error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
x = 0;
}
if (c2 >= '0' && c2 <= '9') {
x += c2 - '0';
} else if (c2 >= 'A' && c2 <= 'F') {
x += c2 - 'A' + 10;
} else if (c2 >= 'a' && c2 <= 'f') {
x += c2 - 'a' + 10;
} else if (c2 == EOF) {
eof = gTrue;
x = 0;
} else {
error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
}
buf = x & 0xff;
return buf;
}
GString *ASCIIHexStream::getPSFilter(char *indent) {
GString *s;
if (!(s = str->getPSFilter(indent))) {
return NULL;
}
s->append(indent)->append("/ASCIIHexDecode filter\n");
return s;
}
GBool ASCIIHexStream::isBinary(GBool last) {
return str->isBinary(gFalse);
}
//------------------------------------------------------------------------
// ASCII85Stream
//------------------------------------------------------------------------
ASCII85Stream::ASCII85Stream(Stream *strA):
FilterStream(strA) {
@@ -866,197 +979,193 @@ LZWStream::~LZWStream() {
pclose(zPipe);
#else
fclose(zPipe);
#endif
zPipe = NULL;
unlink(zName->getCString());
delete zName;
}
if (pred) {
delete pred;
}
delete str;
}
int LZWStream::getChar() {
if (pred) {
return pred->getChar();
}
return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
}
int LZWStream::lookChar() {
if (pred) {
return pred->lookChar();
}
return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
}
int LZWStream::getRawChar() {
return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
}
void LZWStream::reset() {
FILE *f;
GString *zCmd;
//----- close old LZW stream
if (zPipe) {
#ifdef HAVE_POPEN
pclose(zPipe);
#else
fclose(zPipe);
#endif
zPipe = NULL;
unlink(zName->getCString());
delete zName;
}
//----- tell Delorie runtime to spawn a new instance of COMMAND.COM
// to run gzip
#if __DJGPP__
if (!setDJSYSFLAGS) {
setenv("DJSYSFLAGS", "0x0002", 0);
setDJSYSFLAGS = gTrue;
}
#endif
//----- create the .Z file
if (!openTempFile(&zName, &f, "wb", ".Z")) {
error(getPos(), "Couldn't create temporary file for LZW stream");
return;
}
dumpFile(f);
fclose(f);
//----- execute uncompress / gzip
zCmd = new GString(uncompressCmd);
zCmd->append(' ');
zCmd->append(zName);
#if defined(MACOS)
long magicCookie;
// first we open the engine up
OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
// if we found it - let's use it!
if (!err && magicCookie) {
// make sure we have the correct version of the Engine
if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
FSSpec myFSS;
Str255 pName;
strcpy((char *)pName, zName->getCString());
c2pstr((char *)pName);
FSMakeFSSpec(0, 0, pName, &myFSS);
short ftype = DetermineFileType(magicCookie, &myFSS);
OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
NULL, NULL, kCreateFolderNever,
kDeleteOriginal, kTextConvertSmart);
}
}
#elif defined(HAVE_POPEN)
if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
unlink(zName->getCString());
delete zName;
return;
}
#else // HAVE_POPEN
-#ifdef VMS
- if (!system(zCmd->getCString())) {
-#else
- if (system(zCmd->getCString())) {
-#endif
+ if (!executeCommand(zCmd->getCString())) {
error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
unlink(zName->getCString());
delete zName;
return;
}
zName->del(zName->getLength() - 2, 2);
if (!(zPipe = fopen(zName->getCString(), "rb"))) {
error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
unlink(zName->getCString());
delete zName;
return;
}
#endif // HAVE_POPEN
//----- clean up
delete zCmd;
//----- initialize buffer
bufPtr = bufEnd = buf;
}
void LZWStream::dumpFile(FILE *f) {
int outCodeBits; // size of output code
int outBits; // max output code
int outBuf[8]; // output buffer
int outData; // temporary output buffer
int inCode, outCode; // input and output codes
int nextCode; // next code index
GBool eof; // set when EOF is reached
GBool clear; // set if table needs to be cleared
GBool first; // indicates first code word after clear
int i, j;
str->reset();
// magic number
fputc(0x1f, f);
fputc(0x9d, f);
// max code length, block mode flag
fputc(0x8c, f);
// init input side
inCodeBits = 9;
inputBuf = 0;
inputBits = 0;
eof = gFalse;
// init output side
outCodeBits = 9;
// clear table
first = gTrue;
nextCode = 258;
clear = gFalse;
do {
for (i = 0; i < 8; ++i) {
// check for table overflow
if (nextCode + early > 0x1001) {
inCode = 256;
// read input code
} else {
do {
inCode = getCode();
if (inCode == EOF) {
eof = gTrue;
inCode = 0;
}
} while (first && inCode == 256);
}
// compute output code
if (inCode < 256) {
outCode = inCode;
} else if (inCode == 256) {
outCode = 256;
clear = gTrue;
} else if (inCode == 257) {
outCode = 0;
eof = gTrue;
} else {
outCode = inCode - 1;
}
outBuf[i] = outCode;
// next code index
if (first)
first = gFalse;
else
++nextCode;
// check input code size
if (nextCode + early == 0x200)
inCodeBits = 10;
@@ -3194,192 +3303,242 @@ int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
int code;
int c;
int i, j;
code = 0;
for (len = 1; len <= flateMaxHuffman; ++len) {
// add a bit to the code
if (codeSize == 0) {
if ((c = str->getChar()) == EOF)
return EOF;
codeBuf = c & 0xff;
codeSize = 8;
}
code = (code << 1) | (codeBuf & 1);
codeBuf >>= 1;
--codeSize;
// look for code
i = tab->start[len];
j = tab->start[len + 1];
if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
i += code - tab->codes[i].code;
return tab->codes[i].val;
}
}
// not found
error(getPos(), "Bad code (%04x) in flate stream", code);
return EOF;
}
int FlateStream::getCodeWord(int bits) {
int c;
while (codeSize < bits) {
if ((c = str->getChar()) == EOF)
return EOF;
codeBuf |= (c & 0xff) << codeSize;
codeSize += 8;
}
c = codeBuf & ((1 << bits) - 1);
codeBuf >>= bits;
codeSize -= bits;
return c;
}
//------------------------------------------------------------------------
// EOFStream
//------------------------------------------------------------------------
EOFStream::EOFStream(Stream *strA):
FilterStream(strA) {
}
EOFStream::~EOFStream() {
delete str;
}
//------------------------------------------------------------------------
// FixedLengthEncoder
//------------------------------------------------------------------------
FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
FilterStream(strA) {
length = lengthA;
count = 0;
}
FixedLengthEncoder::~FixedLengthEncoder() {
if (str->isEncoder())
delete str;
}
void FixedLengthEncoder::reset() {
str->reset();
count = 0;
}
void FixedLengthEncoder::close() {
}
int FixedLengthEncoder::getChar() {
if (length >= 0 && count >= length)
return EOF;
++count;
return str->getChar();
}
int FixedLengthEncoder::lookChar() {
if (length >= 0 && count >= length)
return EOF;
return str->getChar();
}
//------------------------------------------------------------------------
+// ASCIIHexEncoder
+//------------------------------------------------------------------------
+
+ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
+ FilterStream(strA) {
+ bufPtr = bufEnd = buf;
+ lineLen = 0;
+ eof = gFalse;
+}
+
+ASCIIHexEncoder::~ASCIIHexEncoder() {
+ if (str->isEncoder()) {
+ delete str;
+ }
+}
+
+void ASCIIHexEncoder::reset() {
+ str->reset();
+ bufPtr = bufEnd = buf;
+ lineLen = 0;
+ eof = gFalse;
+}
+
+void ASCIIHexEncoder::close() {
+}
+
+GBool ASCIIHexEncoder::fillBuf() {
+ static char *hex = "0123456789abcdef";
+ int c;
+
+ if (eof) {
+ return gFalse;
+ }
+ bufPtr = bufEnd = buf;
+ if ((c = str->getChar()) == EOF) {
+ *bufEnd++ = '>';
+ eof = gTrue;
+ } else {
+ if (lineLen >= 64) {
+ *bufEnd++ = '\n';
+ lineLen = 0;
+ }
+ *bufEnd++ = hex[(c >> 4) & 0x0f];
+ *bufEnd++ = hex[c & 0x0f];
+ lineLen += 2;
+ }
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
// ASCII85Encoder
//------------------------------------------------------------------------
ASCII85Encoder::ASCII85Encoder(Stream *strA):
FilterStream(strA) {
bufPtr = bufEnd = buf;
lineLen = 0;
eof = gFalse;
}
ASCII85Encoder::~ASCII85Encoder() {
if (str->isEncoder())
delete str;
}
void ASCII85Encoder::reset() {
str->reset();
bufPtr = bufEnd = buf;
lineLen = 0;
eof = gFalse;
}
void ASCII85Encoder::close() {
}
GBool ASCII85Encoder::fillBuf() {
Gulong t;
char buf1[5];
int c;
int n, i;
if (eof)
return gFalse;
t = 0;
for (n = 0; n < 4; ++n) {
if ((c = str->getChar()) == EOF)
break;
t = (t << 8) + c;
}
bufPtr = bufEnd = buf;
if (n > 0) {
if (n == 4 && t == 0) {
*bufEnd++ = 'z';
if (++lineLen == 65) {
*bufEnd++ = '\n';
lineLen = 0;
}
} else {
if (n < 4)
t <<= 8 * (4 - n);
for (i = 4; i >= 0; --i) {
buf1[i] = (char)(t % 85 + 0x21);
t /= 85;
}
for (i = 0; i <= n; ++i) {
*bufEnd++ = buf1[i];
if (++lineLen == 65) {
*bufEnd++ = '\n';
lineLen = 0;
}
}
}
}
if (n < 4) {
*bufEnd++ = '~';
*bufEnd++ = '>';
eof = gTrue;
}
return bufPtr < bufEnd;
}
//------------------------------------------------------------------------
// RunLengthEncoder
//------------------------------------------------------------------------
RunLengthEncoder::RunLengthEncoder(Stream *strA):
FilterStream(strA) {
bufPtr = bufEnd = nextEnd = buf;
eof = gFalse;
}
RunLengthEncoder::~RunLengthEncoder() {
if (str->isEncoder())
delete str;
}
void RunLengthEncoder::reset() {
str->reset();
bufPtr = bufEnd = nextEnd = buf;
eof = gFalse;
}
void RunLengthEncoder::close() {
}
//
diff --git a/noncore/unsupported/qpdf/xpdf/Stream.h b/noncore/unsupported/qpdf/xpdf/Stream.h
index 1f9c561..3319dcc 100644
--- a/noncore/unsupported/qpdf/xpdf/Stream.h
+++ b/noncore/unsupported/qpdf/xpdf/Stream.h
@@ -1,394 +1,440 @@
//========================================================================
//
// Stream.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef STREAM_H
#define STREAM_H
#ifdef __GNUC__
#pragma interface
#endif
#include <stdio.h>
#include "gtypes.h"
#include "Object.h"
#ifndef NO_DECRYPTION
class Decrypt;
#endif
class BaseStream;
//------------------------------------------------------------------------
enum StreamKind {
strFile,
strASCIIHex,
strASCII85,
strLZW,
strRunLength,
strCCITTFax,
strDCT,
strFlate,
strWeird // internal-use stream types
};
//------------------------------------------------------------------------
// Stream (base class)
//------------------------------------------------------------------------
class Stream {
public:
// Constructor.
Stream();
// Destructor.
virtual ~Stream();
// Reference counting.
int incRef() { return ++ref; }
int decRef() { return --ref; }
// Get kind of stream.
virtual StreamKind getKind() = 0;
// Reset stream to beginning.
virtual void reset() = 0;
// Close down the stream.
virtual void close();
// Get next char from stream.
virtual int getChar() = 0;
// Peek at next char in stream.
virtual int lookChar() = 0;
// Get next char from stream without using the predictor.
// This is only used by StreamPredictor.
virtual int getRawChar();
// Get next line from stream.
virtual char *getLine(char *buf, int size);
// Get current position in file.
virtual int getPos() = 0;
- // Go to a position in the stream.
- virtual void setPos(int pos) = 0;
+ // Go to a position in the stream. If <dir> is negative, the
+ // position is from the end of the file; otherwise the position is
+ // from the start of the file.
+ virtual void setPos(Guint pos, int dir = 0) = 0;
// Get PostScript command for the filter(s).
virtual GString *getPSFilter(char *indent);
// Does this stream type potentially contain non-printable chars?
virtual GBool isBinary(GBool last = gTrue) = 0;
// Get the BaseStream or EmbedStream of this stream.
virtual BaseStream *getBaseStream() = 0;
// Get the dictionary associated with this stream.
virtual Dict *getDict() = 0;
// Is this an encoding filter?
virtual GBool isEncoder() { return gFalse; }
// Add filters to this stream according to the parameters in <dict>.
// Returns the new stream.
Stream *addFilters(Object *dict);
private:
Stream *makeFilter(char *name, Stream *str, Object *params);
int ref; // reference count
};
//------------------------------------------------------------------------
// BaseStream
//
// This is the base class for all streams that read directly from a file.
//------------------------------------------------------------------------
class BaseStream: public Stream {
public:
BaseStream(Object *dictA);
virtual ~BaseStream();
- virtual Stream *makeSubStream(int start, int length, Object *dict) = 0;
- virtual void setPos(int pos) = 0;
+ virtual Stream *makeSubStream(Guint start, GBool limited,
+ Guint length, Object *dict) = 0;
+ virtual void setPos(Guint pos, int dir = 0) = 0;
virtual BaseStream *getBaseStream() { return this; }
virtual Dict *getDict() { return dict.getDict(); }
// Get/set position of first byte of stream within the file.
- virtual int getStart() = 0;
+ virtual Guint getStart() = 0;
virtual void moveStart(int delta) = 0;
#ifndef NO_DECRYPTION
// Set decryption for this stream.
- void doDecryption(Guchar *fileKey, int keyLength, int objNum, int objGen);
+ virtual void doDecryption(Guchar *fileKey, int keyLength,
+ int objNum, int objGen);
#endif
#ifndef NO_DECRYPTION
protected:
Decrypt *decrypt;
#endif
private:
Object dict;
};
//------------------------------------------------------------------------
// FilterStream
//
// This is the base class for all streams that filter another stream.
//------------------------------------------------------------------------
class FilterStream: public Stream {
public:
FilterStream(Stream *strA);
virtual ~FilterStream();
virtual void close();
virtual int getPos() { return str->getPos(); }
- virtual void setPos(int pos);
+ virtual void setPos(Guint pos, int dir = 0);
virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
virtual Dict *getDict() { return str->getDict(); }
protected:
Stream *str;
};
//------------------------------------------------------------------------
// ImageStream
//------------------------------------------------------------------------
class ImageStream {
public:
// Create an image stream object for an image with the specified
// parameters. Note that these are the actual image parameters,
// which may be different from the predictor parameters.
ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
~ImageStream();
// Reset the stream.
void reset();
// Gets the next pixel from the stream. <pix> should be able to hold
// at least nComps elements. Returns false at end of file.
GBool getPixel(Guchar *pix);
// Skip an entire line from the image.
void skipLine();
private:
Stream *str; // base stream
int width; // pixels per line
int nComps; // components per pixel
int nBits; // bits per component
int nVals; // components per line
Guchar *imgLine; // line buffer
int imgIdx; // current index in imgLine
};
//------------------------------------------------------------------------
// StreamPredictor
//------------------------------------------------------------------------
class StreamPredictor {
public:
// Create a predictor object. Note that the parameters are for the
// predictor, and may not match the actual image parameters.
StreamPredictor(Stream *strA, int predictorA,
int widthA, int nCompsA, int nBitsA);
~StreamPredictor();
int lookChar();
int getChar();
private:
GBool getNextLine();
Stream *str; // base stream
int predictor; // predictor
int width; // pixels per line
int nComps; // components per pixel
int nBits; // bits per component
int nVals; // components per line
int pixBytes; // bytes per pixel
int rowBytes; // bytes per line
Guchar *predLine; // line buffer
int predIdx; // current index in predLine
};
//------------------------------------------------------------------------
// FileStream
//------------------------------------------------------------------------
#define fileStreamBufSize 256
class FileStream: public BaseStream {
public:
- FileStream(FILE *fA, int startA, int lengthA, Object *dictA);
+ FileStream(FILE *fA, Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA);
virtual ~FileStream();
- virtual Stream *makeSubStream(int startA, int lengthA, Object *dictA);
+ virtual Stream *makeSubStream(Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return strFile; }
virtual void reset();
virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
virtual int getPos() { return bufPos + (bufPtr - buf); }
- virtual void setPos(int pos);
+ virtual void setPos(Guint pos, int dir = 0);
virtual GBool isBinary(GBool last = gTrue) { return last; }
- virtual int getStart() { return start; }
+ virtual Guint getStart() { return start; }
virtual void moveStart(int delta);
private:
GBool fillBuf();
FILE *f;
- int start;
- int length;
+ Guint start;
+ GBool limited;
+ Guint length;
char buf[fileStreamBufSize];
char *bufPtr;
char *bufEnd;
- int bufPos;
+ Guint bufPos;
int savePos;
+ GBool saved;
+};
+
+//------------------------------------------------------------------------
+// MemStream
+//------------------------------------------------------------------------
+
+class MemStream: public BaseStream {
+public:
+
+ MemStream(char *bufA, Guint lengthA, Object *dictA);
+ virtual ~MemStream();
+ virtual Stream *makeSubStream(Guint start, GBool limited,
+ Guint lengthA, Object *dictA);
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual void close();
+ virtual int getChar()
+ { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
+ virtual int lookChar()
+ { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
+ virtual int getPos() { return bufPtr - buf; }
+ virtual void setPos(Guint pos, int dir = 0);
+ virtual GBool isBinary(GBool last = gTrue) { return last; }
+ virtual Guint getStart() { return 0; }
+ virtual void moveStart(int delta);
+#ifndef NO_DECRYPTION
+ virtual void doDecryption(Guchar *fileKey, int keyLength,
+ int objNum, int objGen);
+#endif
+
+private:
+
+ char *buf;
+ Guint length;
+ GBool needFree;
+ char *bufEnd;
+ char *bufPtr;
};
//------------------------------------------------------------------------
// EmbedStream
//
// This is a special stream type used for embedded streams (inline
// images). It reads directly from the base stream -- after the
// EmbedStream is deleted, reads from the base stream will proceed where
// the BaseStream left off. Note that this is very different behavior
// that creating a new FileStream (using makeSubStream).
//------------------------------------------------------------------------
class EmbedStream: public BaseStream {
public:
EmbedStream(Stream *strA, Object *dictA);
virtual ~EmbedStream();
- virtual Stream *makeSubStream(int start, int length, Object *dictA);
+ virtual Stream *makeSubStream(Guint start, GBool limited,
+ Guint length, Object *dictA);
virtual StreamKind getKind() { return str->getKind(); }
virtual void reset() {}
virtual int getChar() { return str->getChar(); }
virtual int lookChar() { return str->lookChar(); }
virtual int getPos() { return str->getPos(); }
- virtual void setPos(int pos);
+ virtual void setPos(Guint pos, int dir = 0);
virtual GBool isBinary(GBool last = gTrue) { return last; }
- virtual int getStart();
+ virtual Guint getStart();
virtual void moveStart(int delta);
private:
Stream *str;
};
//------------------------------------------------------------------------
// ASCIIHexStream
//------------------------------------------------------------------------
class ASCIIHexStream: public FilterStream {
public:
ASCIIHexStream(Stream *strA);
virtual ~ASCIIHexStream();
virtual StreamKind getKind() { return strASCIIHex; }
virtual void reset();
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
virtual GString *getPSFilter(char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
int buf;
GBool eof;
};
//------------------------------------------------------------------------
// ASCII85Stream
//------------------------------------------------------------------------
class ASCII85Stream: public FilterStream {
public:
ASCII85Stream(Stream *strA);
virtual ~ASCII85Stream();
virtual StreamKind getKind() { return strASCII85; }
virtual void reset();
virtual int getChar()
{ int ch = lookChar(); ++index; return ch; }
virtual int lookChar();
virtual GString *getPSFilter(char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
int c[5];
int b[4];
int index, n;
GBool eof;
};
//------------------------------------------------------------------------
// LZWStream
//------------------------------------------------------------------------
class LZWStream: public FilterStream {
public:
LZWStream(Stream *strA, int predictor, int columns, int colors,
int bits, int earlyA);
virtual ~LZWStream();
virtual StreamKind getKind() { return strLZW; }
virtual void reset();
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
virtual GString *getPSFilter(char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
StreamPredictor *pred; // predictor
int early; // early parameter
FILE *zPipe; // uncompress pipe
GString *zName; // .Z file name
int inputBuf; // input buffer
int inputBits; // number of bits in input buffer
int inCodeBits; // size of input code
char buf[256]; // buffer
char *bufPtr; // next char to read
char *bufEnd; // end of buffer
void dumpFile(FILE *f);
int getCode();
GBool fillBuf();
};
//------------------------------------------------------------------------
// RunLengthStream
//------------------------------------------------------------------------
class RunLengthStream: public FilterStream {
@@ -566,158 +612,189 @@ struct FlateHuffmanTab {
// Decoding info for length and distance code words
struct FlateDecode {
int bits; // # extra bits
int first; // first length/distance
};
class FlateStream: public FilterStream {
public:
FlateStream(Stream *strA, int predictor, int columns,
int colors, int bits);
virtual ~FlateStream();
virtual StreamKind getKind() { return strFlate; }
virtual void reset();
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
virtual GString *getPSFilter(char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
StreamPredictor *pred; // predictor
Guchar buf[flateWindow]; // output data buffer
int index; // current index into output buffer
int remain; // number valid bytes in output buffer
int codeBuf; // input buffer
int codeSize; // number of bits in input buffer
FlateCode // literal and distance codes
allCodes[flateMaxLitCodes + flateMaxDistCodes];
FlateHuffmanTab litCodeTab; // literal code table
FlateHuffmanTab distCodeTab; // distance code table
GBool compressedBlock; // set if reading a compressed block
int blockLen; // remaining length of uncompressed block
GBool endOfBlock; // set when end of block is reached
GBool eof; // set when end of stream is reached
static int // code length code reordering
codeLenCodeMap[flateMaxCodeLenCodes];
static FlateDecode // length decoding info
lengthDecode[flateMaxLitCodes-257];
static FlateDecode // distance decoding info
distDecode[flateMaxDistCodes];
void readSome();
GBool startBlock();
void loadFixedCodes();
GBool readDynamicCodes();
void compHuffmanCodes(FlateHuffmanTab *tab, int n);
int getHuffmanCodeWord(FlateHuffmanTab *tab);
int getCodeWord(int bits);
};
//------------------------------------------------------------------------
// EOFStream
//------------------------------------------------------------------------
class EOFStream: public FilterStream {
public:
EOFStream(Stream *strA);
virtual ~EOFStream();
virtual StreamKind getKind() { return strWeird; }
virtual void reset() {}
virtual int getChar() { return EOF; }
virtual int lookChar() { return EOF; }
virtual GString *getPSFilter(char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
};
//------------------------------------------------------------------------
// FixedLengthEncoder
//------------------------------------------------------------------------
class FixedLengthEncoder: public FilterStream {
public:
FixedLengthEncoder(Stream *strA, int lengthA);
~FixedLengthEncoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
virtual void close();
virtual int getChar();
virtual int lookChar();
virtual GString *getPSFilter(char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
private:
int length;
int count;
};
//------------------------------------------------------------------------
+// ASCIIHexEncoder
+//------------------------------------------------------------------------
+
+class ASCIIHexEncoder: public FilterStream {
+public:
+
+ ASCIIHexEncoder(Stream *strA);
+ virtual ~ASCIIHexEncoder();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual void close();
+ virtual int getChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+ virtual int lookChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+ virtual GString *getPSFilter(char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+ char buf[4];
+ char *bufPtr;
+ char *bufEnd;
+ int lineLen;
+ GBool eof;
+
+ GBool fillBuf();
+};
+
+//------------------------------------------------------------------------
// ASCII85Encoder
//------------------------------------------------------------------------
class ASCII85Encoder: public FilterStream {
public:
ASCII85Encoder(Stream *strA);
virtual ~ASCII85Encoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
virtual GString *getPSFilter(char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
private:
char buf[8];
char *bufPtr;
char *bufEnd;
int lineLen;
GBool eof;
GBool fillBuf();
};
//------------------------------------------------------------------------
// RunLengthEncoder
//------------------------------------------------------------------------
class RunLengthEncoder: public FilterStream {
public:
RunLengthEncoder(Stream *strA);
virtual ~RunLengthEncoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
virtual GString *getPSFilter(char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
virtual GBool isEncoder() { return gTrue; }
private:
char buf[131];
char *bufPtr;
char *bufEnd;
char *nextEnd;
GBool eof;
GBool fillBuf();
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc b/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc
index aa9366a..d3b0137 100644
--- a/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc
+++ b/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc
@@ -1,254 +1,266 @@
//========================================================================
//
// TextOutputDev.cc
//
-// Copyright 1997 Derek B. Noonburg
+// Copyright 1997-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
#include <ctype.h>
#include "GString.h"
#include "gmem.h"
#include "config.h"
#include "Error.h"
#include "GlobalParams.h"
#include "UnicodeMap.h"
#include "GfxState.h"
#include "TextOutputDev.h"
#ifdef MACOS
// needed for setting type/creator of MacOS files
#include "ICSupport.h"
#endif
//------------------------------------------------------------------------
// TextString
//------------------------------------------------------------------------
TextString::TextString(GfxState *state, fouble fontSize) {
GfxFont *font;
fouble x, y;
state->transform(state->getCurX(), state->getCurY(), &x, &y);
if ((font = state->getFont())) {
yMin = y - font->getAscent() * fontSize;
yMax = y - font->getDescent() * fontSize;
} 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;
}
+ 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;
len = size = 0;
yxNext = NULL;
xyNext = NULL;
}
TextString::~TextString() {
gfree(text);
gfree(xRight);
}
void TextString::addChar(GfxState *state, fouble x, fouble y,
fouble dx, fouble dy, Unicode u) {
if (len == size) {
size += 16;
text = (Unicode *)grealloc(text, size * sizeof(Unicode));
xRight = (fouble *)grealloc(xRight, size * sizeof(fouble));
}
text[len] = u;
if (len == 0) {
xMin = x;
}
xMax = xRight[len] = x + dx;
++len;
}
//------------------------------------------------------------------------
// TextPage
//------------------------------------------------------------------------
TextPage::TextPage(GBool rawOrderA) {
rawOrder = rawOrderA;
curStr = NULL;
fontSize = 0;
yxStrings = NULL;
xyStrings = NULL;
yxCur1 = yxCur2 = NULL;
nest = 0;
}
TextPage::~TextPage() {
clear();
}
void TextPage::updateFont(GfxState *state) {
GfxFont *font;
fouble *fm;
char *name;
int code;
+ fouble 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) {
- // 600 is a generic average 'm' width -- yes, this is a hack
- fontSize *= ((Gfx8BitFont *)font)->getWidth(code) / 0.6;
+ 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 TextPage::beginString(GfxState *state) {
// This check is needed because Type 3 characters can contain
// text-drawing operations.
if (curStr) {
++nest;
return;
}
curStr = new TextString(state, fontSize);
}
void TextPage::addChar(GfxState *state, fouble x, fouble y,
fouble dx, fouble dy, Unicode *u, int uLen) {
fouble x1, y1, w1, h1, dx2, dy2;
int n, i;
state->transform(x, y, &x1, &y1);
n = curStr->len;
if (n > 0 &&
x1 - curStr->xRight[n-1] > 0.1 * (curStr->yMax - curStr->yMin)) {
endString();
beginString(state);
}
state->textTransformDelta(state->getCharSpace() * state->getHorizScaling(),
0, &dx2, &dy2);
dx -= dx2;
dy -= dy2;
state->transformDelta(dx, dy, &w1, &h1);
- w1 /= uLen;
- h1 /= uLen;
+ 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 TextPage::endString() {
TextString *p1, *p2;
fouble h, y1, y2;
// This check is needed because Type 3 characters can contain
// text-drawing operations.
if (nest > 0) {
--nest;
return;
}
// 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;
}
// 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 TextPage::coalesce() {
TextString *str1, *str2;
fouble space, d;
GBool addSpace;
int n, i;
#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));
for (i = 0; i < str1->len; ++i) {
fputc(str1->text[i] & 0xff, stdout);
}
printf("'\n");
}
printf("\n------------------------------------------------------------\n\n");
#endif
str1 = yxStrings;
while (str1 && (str2 = str1->yxNext)) {
space = str1->yMax - str1->yMin;
d = str2->xMin - str1->xMax;
if (((rawOrder &&
((str2->yMin >= str1->yMin && str2->yMin <= str1->yMax) ||
(str2->yMax >= str1->yMin && str2->yMax <= str1->yMax))) ||
(!rawOrder && str2->yMin < str1->yMax)) &&
d > -0.5 * space && d < space) {
n = str1->len + str2->len;
if ((addSpace = d > 0.1 * space)) {
++n;
}
str1->size = (n + 15) & ~15;
str1->text = (Unicode *)grealloc(str1->text,
str1->size * sizeof(Unicode));
str1->xRight = (fouble *)grealloc(str1->xRight,
str1->size * sizeof(fouble));
if (addSpace) {
str1->text[str1->len] = 0x20;
str1->xRight[str1->len] = str2->xMin;
@@ -336,351 +348,366 @@ GBool TextPage::findText(Unicode *s, int len,
if (u1 != u2) {
break;
}
}
// found it
if (j == len) {
*xMin = (i == 0) ? str->xMin : str->xRight[i-1];
*xMax = str->xRight[i + len - 1];
*yMin = str->yMin;
*yMax = str->yMax;
return gTrue;
}
}
}
return gFalse;
}
GString *TextPage::getText(fouble xMin, fouble yMin,
fouble xMax, fouble yMax) {
GString *s;
UnicodeMap *uMap;
char space[8], eol[16], buf[8];
int spaceLen, eolLen, n;
TextString *str1;
fouble x0, x1, x2, y;
fouble xPrev, yPrev;
int i1, i2, i;
GBool multiLine;
s = new GString();
if (!(uMap = globalParams->getTextEncoding())) {
return s;
}
spaceLen = uMap->mapUnicode(0x20, space, sizeof(space));
eolLen = 0; // make gcc happy
switch (globalParams->getTextEOL()) {
case eolUnix:
eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol));
break;
case eolDOS:
eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen);
break;
case eolMac:
eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
break;
}
xPrev = yPrev = 0;
multiLine = gFalse;
for (str1 = yxStrings; str1; str1 = str1->yxNext) {
y = 0.5 * (str1->yMin + str1->yMax);
if (y > yMax) {
break;
}
if (y > yMin && str1->xMin < xMax && str1->xMax > xMin) {
x0 = x1 = x2 = str1->xMin;
for (i1 = 0; i1 < str1->len; ++i1) {
x0 = (i1==0) ? str1->xMin : str1->xRight[i1-1];
x1 = str1->xRight[i1];
if (0.5 * (x0 + x1) >= xMin) {
break;
}
}
for (i2 = str1->len - 1; i2 > i1; --i2) {
x1 = (i2==0) ? str1->xMin : str1->xRight[i2-1];
x2 = str1->xRight[i2];
if (0.5 * (x1 + x2) <= xMax) {
break;
}
}
if (s->getLength() > 0) {
if (x0 < xPrev || str1->yMin > yPrev) {
s->append(eol, eolLen);
multiLine = gTrue;
} else {
for (i = 0; i < 4; ++i) {
s->append(space, spaceLen);
}
}
}
for (i = i1; i <= i2; ++i) {
n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf));
s->append(buf, n);
}
xPrev = x2;
yPrev = str1->yMax;
}
}
if (multiLine) {
s->append(eol, eolLen);
}
uMap->decRefCnt();
return s;
}
-void TextPage::dump(FILE *f) {
+void TextPage::dump(void *outputStream, TextOutputFunc outputFunc) {
UnicodeMap *uMap;
char space[8], eol[16], eop[8], buf[8];
int spaceLen, eolLen, eopLen, n;
TextString *str1, *str2, *str3;
fouble yMin, yMax;
int col1, col2, d, i;
// get the output encoding
if (!(uMap = globalParams->getTextEncoding())) {
return;
}
spaceLen = uMap->mapUnicode(0x20, space, sizeof(space));
eolLen = 0; // make gcc happy
switch (globalParams->getTextEOL()) {
case eolUnix:
eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol));
break;
case eolDOS:
eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen);
break;
case eolMac:
eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol));
break;
}
eopLen = uMap->mapUnicode(0x0c, eop, sizeof(eop));
// build x-major list
xyStrings = NULL;
for (str1 = yxStrings; str1; str1 = str1->yxNext) {
for (str2 = NULL, str3 = xyStrings;
str3;
str2 = str3, str3 = str3->xyNext) {
if (str1->xMin < str3->xMin ||
(str1->xMin == str3->xMin && str1->yMin < str3->yMin)) {
break;
}
}
if (str2) {
str2->xyNext = str1;
} else {
xyStrings = str1;
}
str1->xyNext = str3;
}
// do column assignment
for (str1 = xyStrings; str1; str1 = str1->xyNext) {
col1 = 0;
for (str2 = xyStrings; str2 != str1; str2 = str2->xyNext) {
if (str1->xMin >= str2->xMax) {
col2 = str2->col + str2->len + 4;
if (col2 > col1) {
col1 = col2;
}
} else if (str1->xMin > str2->xMin) {
col2 = str2->col +
(int)(((str1->xMin - str2->xMin) / (str2->xMax - str2->xMin)) *
str2->len);
if (col2 > col1) {
col1 = col2;
}
}
}
str1->col = col1;
}
#if 0 //~ for debugging
- fprintf(f, "~~~~~~~~~~\n");
+ fprintf((FILE *)outputStream, "~~~~~~~~~~\n");
for (str1 = yxStrings; str1; str1 = str1->yxNext) {
- fprintf(f, "(%4d,%4d) - (%4d,%4d) [%3d] '",
+ fprintf((FILE *)outputStream, "(%4d,%4d) - (%4d,%4d) [%3d] '",
(int)str1->xMin, (int)str1->yMin,
(int)str1->xMax, (int)str1->yMax, str1->col);
for (i = 0; i < str1->len; ++i) {
fputc(str1->text[i] & 0xff, stdout);
}
printf("'\n");
}
- fprintf(f, "~~~~~~~~~~\n");
+ fprintf((FILE *)outputStream, "~~~~~~~~~~\n");
#endif
// output
col1 = 0;
yMax = yxStrings ? yxStrings->yMax : fouble(0);
for (str1 = yxStrings; str1; str1 = str1->yxNext) {
// line this string up with the correct column
if (rawOrder && col1 == 0) {
col1 = str1->col;
} else {
for (; col1 < str1->col; ++col1) {
- fwrite(space, 1, spaceLen, f);
+ (*outputFunc)(outputStream, space, spaceLen);
}
}
// print the string
for (i = 0; i < str1->len; ++i) {
if ((n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf))) > 0) {
- fwrite(buf, 1, n, f);
+ (*outputFunc)(outputStream, buf, n);
}
}
// increment column
col1 += str1->len;
// update yMax for this line
if (str1->yMax > yMax) {
yMax = str1->yMax;
}
// if we've hit the end of the line...
if (!(str1->yxNext &&
!(rawOrder && str1->yxNext->yMax < str1->yMin) &&
str1->yxNext->yMin < 0.2*str1->yMin + 0.8*str1->yMax &&
str1->yxNext->xMin >= str1->xMax)) {
// print a return
- fwrite(eol, 1, eolLen, f);
+ (*outputFunc)(outputStream, eol, eolLen);
// print extra vertical space if necessary
if (str1->yxNext) {
// find yMin for next line
yMin = str1->yxNext->yMin;
for (str2 = str1->yxNext; str2; str2 = str2->yxNext) {
if (str2->yMin < yMin) {
yMin = str2->yMin;
}
if (!(str2->yxNext && str2->yxNext->yMin < str2->yMax &&
str2->yxNext->xMin >= str2->xMax))
break;
}
// print the space
d = (int)((yMin - yMax) / (str1->yMax - str1->yMin) + 0.5);
// various things (weird font matrices) can result in bogus
// values here, so do a sanity check
if (rawOrder && d > 2) {
d = 2;
} else if (!rawOrder && d > 5) {
d = 5;
}
for (; d > 0; --d) {
- fwrite(eol, 1, eolLen, f);
+ (*outputFunc)(outputStream, eol, eolLen);
}
}
// set up for next line
col1 = 0;
yMax = str1->yxNext ? str1->yxNext->yMax : fouble(0);
}
}
// end of page
- fwrite(eol, 1, eolLen, f);
- fwrite(eop, 1, eopLen, f);
- fwrite(eol, 1, eolLen, f);
+ (*outputFunc)(outputStream, eol, eolLen);
+ (*outputFunc)(outputStream, eop, eopLen);
+ (*outputFunc)(outputStream, eol, eolLen);
uMap->decRefCnt();
}
void TextPage::clear() {
TextString *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;
}
//------------------------------------------------------------------------
// TextOutputDev
//------------------------------------------------------------------------
+static void outputToFile(void *stream, char *text, int len) {
+ fwrite(text, 1, len, (FILE *)stream);
+}
+
TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) {
text = NULL;
rawOrder = rawOrderA;
ok = gTrue;
// open file
needClose = gFalse;
if (fileName) {
if (!strcmp(fileName, "-")) {
- f = stdout;
- } else if ((f = fopen(fileName, append ? "a" : "w"))) {
+ outputStream = stdout;
+ } else if ((outputStream = fopen(fileName, append ? "ab" : "wb"))) {
needClose = gTrue;
} else {
error(-1, "Couldn't open text file '%s'", fileName);
ok = gFalse;
return;
}
+ outputFunc = &outputToFile;
} else {
- f = NULL;
+ outputStream = NULL;
}
// set up text object
text = new TextPage(rawOrder);
}
+TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream,
+ GBool rawOrderA) {
+ outputFunc = func;
+ outputStream = stream;
+ needClose = gFalse;
+ rawOrder = rawOrderA;
+ text = new TextPage(rawOrder);
+ ok = gTrue;
+}
+
TextOutputDev::~TextOutputDev() {
if (needClose) {
#ifdef MACOS
- ICS_MapRefNumAndAssign((short)f->handle);
+ ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle);
#endif
- fclose(f);
+ fclose((FILE *)outputStream);
}
if (text) {
delete text;
}
}
void TextOutputDev::startPage(int pageNum, GfxState *state) {
text->clear();
}
void TextOutputDev::endPage() {
text->coalesce();
- if (f) {
- text->dump(f);
+ if (outputStream) {
+ text->dump(outputStream, outputFunc);
}
}
void TextOutputDev::updateFont(GfxState *state) {
text->updateFont(state);
}
void TextOutputDev::beginString(GfxState *state, GString *s) {
text->beginString(state);
}
void TextOutputDev::endString(GfxState *state) {
text->endString();
}
void TextOutputDev::drawChar(GfxState *state, fouble x, fouble y,
fouble dx, fouble dy,
fouble originX, fouble originY,
CharCode c, Unicode *u, int uLen) {
text->addChar(state, x, y, dx, dy, u, uLen);
}
GBool TextOutputDev::findText(Unicode *s, int len,
GBool top, GBool bottom,
fouble *xMin, fouble *yMin,
fouble *xMax, fouble *yMax) {
return text->findText(s, len, top, bottom, xMin, yMin, xMax, yMax);
}
diff --git a/noncore/unsupported/qpdf/xpdf/TextOutputDev.h b/noncore/unsupported/qpdf/xpdf/TextOutputDev.h
index 4c71e5e..f0f238e 100644
--- a/noncore/unsupported/qpdf/xpdf/TextOutputDev.h
+++ b/noncore/unsupported/qpdf/xpdf/TextOutputDev.h
@@ -1,189 +1,203 @@
//========================================================================
//
// TextOutputDev.h
//
-// Copyright 1997 Derek B. Noonburg
+// Copyright 1997-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef TEXTOUTPUTDEV_H
#define TEXTOUTPUTDEV_H
#ifdef __GNUC__
#pragma interface
#endif
#include <stdio.h>
#include "gtypes.h"
#include "GfxFont.h"
#include "OutputDev.h"
class GfxState;
class GString;
//------------------------------------------------------------------------
+
+typedef void (*TextOutputFunc)(void *stream, char *text, int len);
+
+//------------------------------------------------------------------------
// TextString
//------------------------------------------------------------------------
class TextString {
public:
// Constructor.
TextString(GfxState *state, fouble fontSize);
// Destructor.
~TextString();
// Add a character to the string.
void addChar(GfxState *state, fouble x, fouble y,
fouble dx, fouble dy, Unicode u);
private:
fouble xMin, xMax; // bounding box x coordinates
fouble yMin, yMax; // bounding box y coordinates
int col; // starting column
Unicode *text; // the text
fouble *xRight; // right-hand x coord of each char
int len; // length of text and xRight
int size; // size of text and xRight arrays
TextString *yxNext; // next string in y-major order
TextString *xyNext; // next string in x-major order
friend class TextPage;
};
//------------------------------------------------------------------------
// TextPage
//------------------------------------------------------------------------
class TextPage {
public:
// Constructor.
TextPage(GBool rawOrderA);
// Destructor.
~TextPage();
// Update the current font.
void updateFont(GfxState *state);
// Begin a new string.
void beginString(GfxState *state);
// Add a character to the current string.
void addChar(GfxState *state, fouble x, fouble y,
fouble dx, fouble dy, Unicode *u, int uLen);
// 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.
GBool findText(Unicode *s, int len,
GBool top, GBool bottom,
fouble *xMin, fouble *yMin,
fouble *xMax, fouble *yMax);
// Get the text which is inside the specified rectangle.
GString *getText(fouble xMin, fouble yMin,
fouble xMax, fouble yMax);
// Dump contents of page to a file.
- void dump(FILE *f);
+ void dump(void *outputStream, TextOutputFunc outputFunc);
// Clear the page.
void clear();
private:
GBool rawOrder; // keep strings in content stream order
TextString *curStr; // currently active string
fouble fontSize; // current font size
TextString *yxStrings; // strings in y-major order
TextString *xyStrings; // strings in x-major order
TextString *yxCur1, *yxCur2; // cursors for yxStrings list
int nest; // current nesting level (for Type 3 fonts)
};
//------------------------------------------------------------------------
// TextOutputDev
//------------------------------------------------------------------------
class TextOutputDev: 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
// <rawOrder> is true, the text is kept in content stream order.
TextOutputDev(char *fileName, GBool rawOrderA, GBool append);
+ // Create a TextOutputDev which will write to a generic stream. If
+ // <rawOrder> is true, the text is kept in content stream order.
+ TextOutputDev(TextOutputFunc func, void *stream, GBool rawOrderA);
+
// Destructor.
virtual ~TextOutputDev();
// 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, GString *s);
virtual void endString(GfxState *state);
virtual void drawChar(GfxState *state, fouble x, fouble y,
fouble dx, fouble dy,
fouble originX, fouble originY,
CharCode c, Unicode *u, int uLen);
//----- special access
// 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.
GBool findText(Unicode *s, int len,
GBool top, GBool bottom,
fouble *xMin, fouble *yMin,
fouble *xMax, fouble *yMax);
private:
- FILE *f; // text file
- GBool needClose; // need to close the file?
+ TextOutputFunc outputFunc; // output function
+ void *outputStream; // output stream
+ GBool needClose; // need to close the output file?
+ // (only if outputStream is a FILE*)
TextPage *text; // text for the current page
GBool rawOrder; // keep text in content stream order
GBool ok; // set up ok?
};
#endif
diff --git a/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc b/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc
index ab823b1..75f23d2 100644
--- a/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc
+++ b/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc
@@ -1,101 +1,101 @@
//========================================================================
//
// UnicodeMap.cc
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <string.h>
#include "gmem.h"
#include "gfile.h"
#include "GString.h"
#include "GList.h"
#include "Error.h"
#include "GlobalParams.h"
#include "UnicodeMap.h"
//------------------------------------------------------------------------
#define maxExtCode 16
struct UnicodeMapExt {
Unicode u; // Unicode char
char code[maxExtCode];
Guint nBytes;
};
//------------------------------------------------------------------------
UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
FILE *f;
UnicodeMap *map;
UnicodeMapRange *range;
UnicodeMapExt *eMap;
int size, eMapsSize;
char buf[256];
int line, nBytes, i, x;
char *tok1, *tok2, *tok3;
if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
encodingNameA->getCString());
return NULL;
}
map = new UnicodeMap(encodingNameA->copy());
size = 8;
map->ranges = (UnicodeMapRange *)gmalloc(size * sizeof(UnicodeMapRange));
eMapsSize = 0;
line = 1;
while (getLine(buf, sizeof(buf), f)) {
if ((tok1 = strtok(buf, " \t\r\n")) &&
(tok2 = strtok(NULL, " \t\r\n"))) {
if (!(tok3 = strtok(NULL, " \t\r\n"))) {
tok3 = tok2;
tok2 = tok1;
}
nBytes = strlen(tok3) / 2;
if (nBytes <= 4) {
if (map->len == size) {
size *= 2;
map->ranges = (UnicodeMapRange *)
grealloc(map->ranges, size * sizeof(UnicodeMapRange));
}
range = &map->ranges[map->len];
sscanf(tok1, "%x", &range->start);
sscanf(tok2, "%x", &range->end);
sscanf(tok3, "%x", &range->code);
range->nBytes = nBytes;
++map->len;
} else if (tok2 == tok1) {
if (map->eMapsLen == eMapsSize) {
eMapsSize += 16;
map->eMaps = (UnicodeMapExt *)
grealloc(map->eMaps, eMapsSize * sizeof(UnicodeMapExt));
}
eMap = &map->eMaps[map->eMapsLen];
sscanf(tok1, "%x", &eMap->u);
for (i = 0; i < nBytes; ++i) {
sscanf(tok3 + i*2, "%2x", &x);
eMap->code[i] = (char)x;
}
eMap->nBytes = nBytes;
++map->eMapsLen;
} else {
error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
line, encodingNameA->getCString());
}
} else {
error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
line, encodingNameA->getCString());
}
++line;
diff --git a/noncore/unsupported/qpdf/xpdf/UnicodeMap.h b/noncore/unsupported/qpdf/xpdf/UnicodeMap.h
index 4d982c8..274c447 100644
--- a/noncore/unsupported/qpdf/xpdf/UnicodeMap.h
+++ b/noncore/unsupported/qpdf/xpdf/UnicodeMap.h
@@ -1,103 +1,103 @@
//========================================================================
//
// UnicodeMap.h
//
// Mapping from Unicode to an encoding.
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef UNICODEMAP_H
#define UNICODEMAP_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
#include "CharTypes.h"
class GString;
//------------------------------------------------------------------------
enum UnicodeMapKind {
unicodeMapUser, // read from a file
unicodeMapResident, // static list of ranges
unicodeMapFunc // function pointer
};
typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize);
struct UnicodeMapRange {
Unicode start, end; // range of Unicode chars
Guint code, nBytes; // first output code
};
struct UnicodeMapExt;
//------------------------------------------------------------------------
class UnicodeMap {
public:
// Create the UnicodeMap specified by <encodingName>. Sets the
// initial reference count to 1. Returns NULL on failure.
static UnicodeMap *parse(GString *encodingNameA);
// Create a resident UnicodeMap.
UnicodeMap(char *encodingNameA,
UnicodeMapRange *rangesA, int lenA);
// Create a resident UnicodeMap that uses a function instead of a
// list of ranges.
UnicodeMap(char *encodingNameA, UnicodeMapFunc funcA);
~UnicodeMap();
void incRefCnt();
void decRefCnt();
GString *getEncodingName() { return encodingName; }
// Return true if this UnicodeMap matches the specified
// <encodingNameA>.
GBool match(GString *encodingNameA);
// Map Unicode to the target encoding. Fills in <buf> with the
// output and returns the number of bytes used. Output will be
// truncated at <bufSize> bytes. No string terminator is written.
// Returns 0 if no mapping is found.
int mapUnicode(Unicode u, char *buf, int bufSize);
private:
UnicodeMap(GString *encodingNameA);
GString *encodingName;
UnicodeMapKind kind;
union {
UnicodeMapRange *ranges; // (user, resident)
UnicodeMapFunc func; // (func)
};
int len; // (user, resident)
UnicodeMapExt *eMaps; // (user)
int eMapsLen; // (user)
int refCnt;
};
//------------------------------------------------------------------------
#define unicodeMapCacheSize 4
class UnicodeMapCache {
public:
UnicodeMapCache();
~UnicodeMapCache();
// Get the UnicodeMap for <encodingName>. Increments its reference
// count; there will be one reference for the cache plus one for the
// caller of this function. Returns NULL on failure.
UnicodeMap *getUnicodeMap(GString *encodingName);
diff --git a/noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h b/noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h
index 6fcd44e..51dee98 100644
--- a/noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h
+++ b/noncore/unsupported/qpdf/xpdf/UnicodeMapTables.h
@@ -1,233 +1,291 @@
//========================================================================
//
// UnicodeMapTables.h
//
-// Copyright 2001 Derek B. Noonburg
+// Copyright 2001-2002 Glyph & Cog, LLC
//
//========================================================================
static UnicodeMapRange latin1UnicodeMapRanges[] = {
{ 0x000a, 0x000a, 0x0a, 1 },
{ 0x000c, 0x000d, 0x0c, 1 },
{ 0x0020, 0x007e, 0x20, 1 },
{ 0x00a0, 0x00a0, 0x20, 1 },
{ 0x00a1, 0x00ac, 0xa1, 1 },
{ 0x00ae, 0x00ff, 0xae, 1 },
+ { 0x010c, 0x010c, 0x43, 1 },
+ { 0x010d, 0x010d, 0x63, 1 },
{ 0x0131, 0x0131, 0x69, 1 },
{ 0x0141, 0x0141, 0x4c, 1 },
{ 0x0142, 0x0142, 0x6c, 1 },
{ 0x0152, 0x0152, 0x4f45, 2 },
{ 0x0153, 0x0153, 0x6f65, 2 },
{ 0x0160, 0x0160, 0x53, 1 },
{ 0x0161, 0x0161, 0x73, 1 },
{ 0x0178, 0x0178, 0x59, 1 },
{ 0x017d, 0x017d, 0x5a, 1 },
{ 0x017e, 0x017e, 0x7a, 1 },
{ 0x02c6, 0x02c6, 0x5e, 1 },
{ 0x02da, 0x02da, 0xb0, 1 },
{ 0x02dc, 0x02dc, 0x7e, 1 },
{ 0x2013, 0x2013, 0xad, 1 },
{ 0x2014, 0x2014, 0x2d2d, 2 },
{ 0x2018, 0x2018, 0x60, 1 },
{ 0x2019, 0x2019, 0x27, 1 },
{ 0x201a, 0x201a, 0x2c, 1 },
{ 0x201c, 0x201c, 0x22, 1 },
{ 0x201d, 0x201d, 0x22, 1 },
{ 0x201e, 0x201e, 0x2c2c, 2 },
{ 0x2022, 0x2022, 0xb7, 1 },
{ 0x2026, 0x2026, 0x2e2e2e, 3 },
{ 0x2039, 0x2039, 0x3c, 1 },
{ 0x203a, 0x203a, 0x3e, 1 },
{ 0x2044, 0x2044, 0x2f, 1 },
{ 0x2122, 0x2122, 0x544d, 2 },
{ 0x2212, 0x2212, 0x2d, 1 },
+ { 0xf6f9, 0xf6f9, 0x4c, 1 },
+ { 0xf6fa, 0xf6fa, 0x4f45, 2 },
+ { 0xf6fc, 0xf6fc, 0xb0, 1 },
+ { 0xf6fd, 0xf6fd, 0x53, 1 },
+ { 0xf6fe, 0xf6fe, 0x7e, 1 },
+ { 0xf6ff, 0xf6ff, 0x5a, 1 },
+ { 0xf721, 0xf721, 0x21, 1 },
+ { 0xf724, 0xf724, 0x24, 1 },
+ { 0xf726, 0xf726, 0x26, 1 },
+ { 0xf730, 0xf739, 0x30, 1 },
+ { 0xf73f, 0xf73f, 0x3f, 1 },
+ { 0xf761, 0xf77a, 0x41, 1 },
+ { 0xf7a1, 0xf7a2, 0xa1, 1 },
+ { 0xf7bf, 0xf7bf, 0xbf, 1 },
+ { 0xf7e0, 0xf7f6, 0xc0, 1 },
+ { 0xf7f8, 0xf7fe, 0xd8, 1 },
+ { 0xf7ff, 0xf7ff, 0x59, 1 },
{ 0xfb00, 0xfb00, 0x6666, 2 },
{ 0xfb01, 0xfb01, 0x6669, 2 },
{ 0xfb02, 0xfb02, 0x666c, 2 },
{ 0xfb03, 0xfb03, 0x666669, 3 },
{ 0xfb04, 0xfb04, 0x66666c, 3 }
};
#define latin1UnicodeMapLen (sizeof(latin1UnicodeMapRanges) / sizeof(UnicodeMapRange))
static UnicodeMapRange ascii7UnicodeMapRanges[] = {
{ 0x000a, 0x000a, 0x0a, 1 },
{ 0x000c, 0x000d, 0x0c, 1 },
{ 0x0020, 0x005f, 0x20, 1 },
{ 0x0061, 0x007e, 0x61, 1 },
{ 0x00a6, 0x00a6, 0x7c, 1 },
{ 0x00a9, 0x00a9, 0x286329, 3 },
{ 0x00ae, 0x00ae, 0x285229, 3 },
{ 0x00b7, 0x00b7, 0x2a, 1 },
{ 0x00bc, 0x00bc, 0x312f34, 3 },
{ 0x00bd, 0x00bd, 0x312f32, 3 },
{ 0x00be, 0x00be, 0x332f34, 3 },
{ 0x00c0, 0x00c0, 0x41, 1 },
{ 0x00c1, 0x00c1, 0x41, 1 },
{ 0x00c2, 0x00c2, 0x41, 1 },
{ 0x00c3, 0x00c3, 0x41, 1 },
{ 0x00c4, 0x00c4, 0x41, 1 },
{ 0x00c5, 0x00c5, 0x41, 1 },
{ 0x00c6, 0x00c6, 0x4145, 2 },
{ 0x00c7, 0x00c7, 0x43, 1 },
{ 0x00c8, 0x00c8, 0x45, 1 },
{ 0x00c9, 0x00c9, 0x45, 1 },
{ 0x00ca, 0x00ca, 0x45, 1 },
{ 0x00cb, 0x00cb, 0x45, 1 },
{ 0x00cc, 0x00cc, 0x49, 1 },
{ 0x00cd, 0x00cd, 0x49, 1 },
{ 0x00ce, 0x00ce, 0x49, 1 },
{ 0x00cf, 0x00cf, 0x49, 1 },
{ 0x00d1, 0x00d2, 0x4e, 1 },
{ 0x00d3, 0x00d3, 0x4f, 1 },
{ 0x00d4, 0x00d4, 0x4f, 1 },
{ 0x00d5, 0x00d5, 0x4f, 1 },
{ 0x00d6, 0x00d6, 0x4f, 1 },
{ 0x00d7, 0x00d7, 0x78, 1 },
{ 0x00d8, 0x00d8, 0x4f, 1 },
{ 0x00d9, 0x00d9, 0x55, 1 },
{ 0x00da, 0x00da, 0x55, 1 },
{ 0x00db, 0x00db, 0x55, 1 },
{ 0x00dc, 0x00dc, 0x55, 1 },
{ 0x00dd, 0x00dd, 0x59, 1 },
{ 0x00e0, 0x00e0, 0x61, 1 },
{ 0x00e1, 0x00e1, 0x61, 1 },
{ 0x00e2, 0x00e2, 0x61, 1 },
{ 0x00e3, 0x00e3, 0x61, 1 },
{ 0x00e4, 0x00e4, 0x61, 1 },
{ 0x00e5, 0x00e5, 0x61, 1 },
{ 0x00e6, 0x00e6, 0x6165, 2 },
{ 0x00e7, 0x00e7, 0x63, 1 },
{ 0x00e8, 0x00e8, 0x65, 1 },
{ 0x00e9, 0x00e9, 0x65, 1 },
{ 0x00ea, 0x00ea, 0x65, 1 },
{ 0x00eb, 0x00eb, 0x65, 1 },
{ 0x00ec, 0x00ec, 0x69, 1 },
{ 0x00ed, 0x00ed, 0x69, 1 },
{ 0x00ee, 0x00ee, 0x69, 1 },
{ 0x00ef, 0x00ef, 0x69, 1 },
{ 0x00f1, 0x00f2, 0x6e, 1 },
{ 0x00f3, 0x00f3, 0x6f, 1 },
{ 0x00f4, 0x00f4, 0x6f, 1 },
{ 0x00f5, 0x00f5, 0x6f, 1 },
{ 0x00f6, 0x00f6, 0x6f, 1 },
{ 0x00f7, 0x00f7, 0x2f, 1 },
{ 0x00f8, 0x00f8, 0x6f, 1 },
{ 0x00f9, 0x00f9, 0x75, 1 },
{ 0x00fa, 0x00fa, 0x75, 1 },
{ 0x00fb, 0x00fb, 0x75, 1 },
{ 0x00fc, 0x00fc, 0x75, 1 },
{ 0x00fd, 0x00fd, 0x79, 1 },
{ 0x00ff, 0x00ff, 0x79, 1 },
{ 0x0131, 0x0131, 0x69, 1 },
{ 0x0141, 0x0141, 0x4c, 1 },
{ 0x0152, 0x0152, 0x4f45, 2 },
{ 0x0153, 0x0153, 0x6f65, 2 },
{ 0x0160, 0x0160, 0x53, 1 },
{ 0x0178, 0x0178, 0x59, 1 },
{ 0x017d, 0x017d, 0x5a, 1 },
{ 0x2013, 0x2013, 0x2d, 1 },
{ 0x2014, 0x2014, 0x2d2d, 2 },
{ 0x2018, 0x2018, 0x60, 1 },
{ 0x2019, 0x2019, 0x27, 1 },
{ 0x201c, 0x201c, 0x22, 1 },
{ 0x201d, 0x201d, 0x22, 1 },
{ 0x2022, 0x2022, 0x2a, 1 },
{ 0x2026, 0x2026, 0x2e2e2e, 3 },
{ 0x2122, 0x2122, 0x544d, 2 },
{ 0x2212, 0x2212, 0x2d, 1 },
+ { 0xf6f9, 0xf6f9, 0x4c, 1 },
+ { 0xf6fa, 0xf6fa, 0x4f45, 2 },
+ { 0xf6fd, 0xf6fd, 0x53, 1 },
+ { 0xf6fe, 0xf6fe, 0x7e, 1 },
+ { 0xf6ff, 0xf6ff, 0x5a, 1 },
+ { 0xf721, 0xf721, 0x21, 1 },
+ { 0xf724, 0xf724, 0x24, 1 },
+ { 0xf726, 0xf726, 0x26, 1 },
+ { 0xf730, 0xf739, 0x30, 1 },
+ { 0xf73f, 0xf73f, 0x3f, 1 },
+ { 0xf761, 0xf77a, 0x41, 1 },
+ { 0xf7e0, 0xf7e0, 0x41, 1 },
+ { 0xf7e1, 0xf7e1, 0x41, 1 },
+ { 0xf7e2, 0xf7e2, 0x41, 1 },
+ { 0xf7e3, 0xf7e3, 0x41, 1 },
+ { 0xf7e4, 0xf7e4, 0x41, 1 },
+ { 0xf7e5, 0xf7e5, 0x41, 1 },
+ { 0xf7e6, 0xf7e6, 0x4145, 2 },
+ { 0xf7e7, 0xf7e7, 0x43, 1 },
+ { 0xf7e8, 0xf7e8, 0x45, 1 },
+ { 0xf7e9, 0xf7e9, 0x45, 1 },
+ { 0xf7ea, 0xf7ea, 0x45, 1 },
+ { 0xf7eb, 0xf7eb, 0x45, 1 },
+ { 0xf7ec, 0xf7ec, 0x49, 1 },
+ { 0xf7ed, 0xf7ed, 0x49, 1 },
+ { 0xf7ee, 0xf7ee, 0x49, 1 },
+ { 0xf7ef, 0xf7ef, 0x49, 1 },
+ { 0xf7f1, 0xf7f2, 0x4e, 1 },
+ { 0xf7f3, 0xf7f3, 0x4f, 1 },
+ { 0xf7f4, 0xf7f4, 0x4f, 1 },
+ { 0xf7f5, 0xf7f5, 0x4f, 1 },
+ { 0xf7f6, 0xf7f6, 0x4f, 1 },
+ { 0xf7f8, 0xf7f8, 0x4f, 1 },
+ { 0xf7f9, 0xf7f9, 0x55, 1 },
+ { 0xf7fa, 0xf7fa, 0x55, 1 },
+ { 0xf7fb, 0xf7fb, 0x55, 1 },
+ { 0xf7fc, 0xf7fc, 0x55, 1 },
+ { 0xf7fd, 0xf7fd, 0x59, 1 },
+ { 0xf7ff, 0xf7ff, 0x59, 1 },
{ 0xfb00, 0xfb00, 0x6666, 2 },
{ 0xfb01, 0xfb01, 0x6669, 2 },
{ 0xfb02, 0xfb02, 0x666c, 2 },
{ 0xfb03, 0xfb03, 0x666669, 3 },
{ 0xfb04, 0xfb04, 0x66666c, 3 }
};
#define ascii7UnicodeMapLen (sizeof(ascii7UnicodeMapRanges) / sizeof(UnicodeMapRange))
static UnicodeMapRange symbolUnicodeMapRanges[] = {
{ 0x0020, 0x0021, 0x20, 1 },
{ 0x0023, 0x0023, 0x23, 1 },
{ 0x0025, 0x0026, 0x25, 1 },
{ 0x0028, 0x0029, 0x28, 1 },
{ 0x002b, 0x002c, 0x2b, 1 },
{ 0x002e, 0x003f, 0x2e, 1 },
{ 0x005b, 0x005b, 0x5b, 1 },
{ 0x005d, 0x005d, 0x5d, 1 },
{ 0x005f, 0x005f, 0x5f, 1 },
{ 0x007b, 0x007d, 0x7b, 1 },
{ 0x00ac, 0x00ac, 0xd8, 1 },
{ 0x00b0, 0x00b1, 0xb0, 1 },
{ 0x00b5, 0x00b5, 0x6d, 1 },
{ 0x00d7, 0x00d7, 0xb4, 1 },
{ 0x00f7, 0x00f7, 0xb8, 1 },
{ 0x0192, 0x0192, 0xa6, 1 },
{ 0x0391, 0x0392, 0x41, 1 },
{ 0x0393, 0x0393, 0x47, 1 },
{ 0x0395, 0x0395, 0x45, 1 },
{ 0x0396, 0x0396, 0x5a, 1 },
{ 0x0397, 0x0397, 0x48, 1 },
{ 0x0398, 0x0398, 0x51, 1 },
{ 0x0399, 0x0399, 0x49, 1 },
{ 0x039a, 0x039d, 0x4b, 1 },
{ 0x039e, 0x039e, 0x58, 1 },
{ 0x039f, 0x03a0, 0x4f, 1 },
{ 0x03a1, 0x03a1, 0x52, 1 },
{ 0x03a3, 0x03a5, 0x53, 1 },
{ 0x03a6, 0x03a6, 0x46, 1 },
{ 0x03a7, 0x03a7, 0x43, 1 },
{ 0x03a8, 0x03a8, 0x59, 1 },
{ 0x03b1, 0x03b2, 0x61, 1 },
{ 0x03b3, 0x03b3, 0x67, 1 },
{ 0x03b4, 0x03b5, 0x64, 1 },
{ 0x03b6, 0x03b6, 0x7a, 1 },
{ 0x03b7, 0x03b7, 0x68, 1 },
{ 0x03b8, 0x03b8, 0x71, 1 },
{ 0x03b9, 0x03b9, 0x69, 1 },
{ 0x03ba, 0x03bb, 0x6b, 1 },
{ 0x03bd, 0x03bd, 0x6e, 1 },
{ 0x03be, 0x03be, 0x78, 1 },
{ 0x03bf, 0x03c0, 0x6f, 1 },
{ 0x03c1, 0x03c1, 0x72, 1 },
{ 0x03c2, 0x03c2, 0x56, 1 },
{ 0x03c3, 0x03c5, 0x73, 1 },
{ 0x03c6, 0x03c6, 0x66, 1 },
{ 0x03c7, 0x03c7, 0x63, 1 },
{ 0x03c8, 0x03c8, 0x79, 1 },
{ 0x03c9, 0x03c9, 0x77, 1 },
{ 0x03d1, 0x03d1, 0x4a, 1 },
{ 0x03d2, 0x03d2, 0xa1, 1 },
{ 0x03d5, 0x03d5, 0x6a, 1 },
{ 0x03d6, 0x03d6, 0x76, 1 },
{ 0x2022, 0x2022, 0xb7, 1 },
{ 0x2026, 0x2026, 0xbc, 1 },
{ 0x2032, 0x2032, 0xa2, 1 },
{ 0x2033, 0x2033, 0xb2, 1 },
{ 0x2044, 0x2044, 0xa4, 1 },
{ 0x2111, 0x2111, 0xc1, 1 },
{ 0x2118, 0x2118, 0xc3, 1 },
{ 0x211c, 0x211c, 0xc2, 1 },
{ 0x2126, 0x2126, 0x57, 1 },
{ 0x2135, 0x2135, 0xc0, 1 },
{ 0x2190, 0x2193, 0xac, 1 },
{ 0x2194, 0x2194, 0xab, 1 },
{ 0x21b5, 0x21b5, 0xbf, 1 },
{ 0x21d0, 0x21d3, 0xdc, 1 },
{ 0x21d4, 0x21d4, 0xdb, 1 },
{ 0x2200, 0x2200, 0x22, 1 },
{ 0x2202, 0x2202, 0xb6, 1 },
{ 0x2203, 0x2203, 0x24, 1 },
{ 0x2205, 0x2205, 0xc6, 1 },
{ 0x2206, 0x2206, 0x44, 1 },
{ 0x2207, 0x2207, 0xd1, 1 },
{ 0x2208, 0x2209, 0xce, 1 },
{ 0x220b, 0x220b, 0x27, 1 },
{ 0x220f, 0x220f, 0xd5, 1 },
{ 0x2211, 0x2211, 0xe5, 1 },
{ 0x2212, 0x2212, 0x2d, 1 },
{ 0x2217, 0x2217, 0x2a, 1 },
{ 0x221a, 0x221a, 0xd6, 1 },
{ 0x221d, 0x221d, 0xb5, 1 },
{ 0x221e, 0x221e, 0xa5, 1 },
{ 0x2220, 0x2220, 0xd0, 1 },
{ 0x2227, 0x2228, 0xd9, 1 },
{ 0x2229, 0x222a, 0xc7, 1 },
{ 0x222b, 0x222b, 0xf2, 1 },
diff --git a/noncore/unsupported/qpdf/xpdf/XRef.cc b/noncore/unsupported/qpdf/xpdf/XRef.cc
index 5d526e9..0e1bbc9 100644
--- a/noncore/unsupported/qpdf/xpdf/XRef.cc
+++ b/noncore/unsupported/qpdf/xpdf/XRef.cc
@@ -1,641 +1,665 @@
//========================================================================
//
// XRef.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include "gmem.h"
#include "Object.h"
#include "Stream.h"
#include "Lexer.h"
#include "Parser.h"
#include "Dict.h"
#ifndef NO_DECRYPTION
#include "Decrypt.h"
#endif
#include "Error.h"
+#include "ErrorCodes.h"
#include "XRef.h"
//------------------------------------------------------------------------
#define xrefSearchSize 1024 // read this many bytes at end of file
// to look for 'startxref'
#ifndef NO_DECRYPTION
//------------------------------------------------------------------------
// Permission bits
//------------------------------------------------------------------------
#define permPrint (1<<2)
#define permChange (1<<3)
#define permCopy (1<<4)
#define permNotes (1<<5)
#define defPermFlags 0xfffc
#endif
//------------------------------------------------------------------------
// XRef
//------------------------------------------------------------------------
XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
- int pos;
+ Guint pos;
int i;
ok = gTrue;
+ errCode = errNone;
size = 0;
entries = NULL;
streamEnds = NULL;
streamEndsLen = 0;
// read the trailer
str = strA;
start = str->getStart();
pos = readTrailer();
// if there was a problem with the trailer,
// try to reconstruct the xref table
if (pos == 0) {
if (!(ok = constructXRef())) {
+ errCode = errDamaged;
return;
}
// trailer is ok - read the xref table
} else {
entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry));
for (i = 0; i < size; ++i) {
- entries[i].offset = -1;
+ entries[i].offset = 0xffffffff;
entries[i].used = gFalse;
}
while (readXRef(&pos)) ;
// if there was a problem with the xref table,
// try to reconstruct it
if (!ok) {
gfree(entries);
size = 0;
entries = NULL;
if (!(ok = constructXRef())) {
+ errCode = errDamaged;
return;
}
}
}
// now set the trailer dictionary's xref pointer so we can fetch
// indirect objects from it
trailerDict.getDict()->setXRef(this);
// check for encryption
#ifndef NO_DECRYPTION
encrypted = gFalse;
#endif
if (checkEncrypted(ownerPassword, userPassword)) {
ok = gFalse;
+ errCode = errEncrypted;
return;
}
}
XRef::~XRef() {
gfree(entries);
trailerDict.free();
if (streamEnds) {
gfree(streamEnds);
}
}
// Read startxref position, xref table size, and root. Returns
// first xref position.
-int XRef::readTrailer() {
+Guint XRef::readTrailer() {
Parser *parser;
Object obj;
char buf[xrefSearchSize+1];
- int n, pos, pos1;
+ int n;
+ Guint pos, pos1;
char *p;
int c;
int i;
// read last xrefSearchSize bytes
- str->setPos(-xrefSearchSize);
+ str->setPos(xrefSearchSize, -1);
for (n = 0; n < xrefSearchSize; ++n) {
if ((c = str->getChar()) == EOF)
break;
buf[n] = c;
}
buf[n] = '\0';
// find startxref
for (i = n - 9; i >= 0; --i) {
if (!strncmp(&buf[i], "startxref", 9))
break;
}
if (i < 0)
return 0;
for (p = &buf[i+9]; isspace(*p); ++p) ;
- pos = lastXRefPos = atoi(p);
+ pos = lastXRefPos = strToUnsigned(p);
// find trailer dict by looking after first xref table
// (NB: we can't just use the trailer dict at the end of the file --
// this won't work for linearized files.)
str->setPos(start + pos);
for (i = 0; i < 4; ++i)
buf[i] = str->getChar();
if (strncmp(buf, "xref", 4))
return 0;
pos1 = pos + 4;
while (1) {
str->setPos(start + pos1);
for (i = 0; i < 35; ++i) {
if ((c = str->getChar()) == EOF)
return 0;
buf[i] = c;
}
if (!strncmp(buf, "trailer", 7))
break;
p = buf;
while (isspace(*p)) ++p;
while ('0' <= *p && *p <= '9') ++p;
while (isspace(*p)) ++p;
n = atoi(p);
while ('0' <= *p && *p <= '9') ++p;
while (isspace(*p)) ++p;
if (p == buf)
return 0;
pos1 += (p - buf) + n * 20;
}
pos1 += 7;
// read trailer dict
obj.initNull();
- parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(start + pos1,
- -1, &obj)));
+ parser = new Parser(NULL,
+ new Lexer(NULL,
+ str->makeSubStream(start + pos1, gFalse, 0, &obj)));
parser->getObj(&trailerDict);
if (trailerDict.isDict()) {
trailerDict.dictLookupNF("Size", &obj);
if (obj.isInt())
size = obj.getInt();
else
pos = 0;
obj.free();
trailerDict.dictLookupNF("Root", &obj);
if (obj.isRef()) {
rootNum = obj.getRefNum();
rootGen = obj.getRefGen();
} else {
pos = 0;
}
obj.free();
} else {
pos = 0;
}
delete parser;
// return first xref position
return pos;
}
// Read an xref table and the prev pointer from the trailer.
-GBool XRef::readXRef(int *pos) {
+GBool XRef::readXRef(Guint *pos) {
Parser *parser;
Object obj, obj2;
char s[20];
GBool more;
int first, newSize, n, i, j;
int c;
// seek to xref in stream
str->setPos(start + *pos);
// make sure it's an xref table
while ((c = str->getChar()) != EOF && isspace(c)) ;
s[0] = (char)c;
s[1] = (char)str->getChar();
s[2] = (char)str->getChar();
s[3] = (char)str->getChar();
if (!(s[0] == 'x' && s[1] == 'r' && s[2] == 'e' && s[3] == 'f')) {
goto err2;
}
// read xref
while (1) {
while ((c = str->lookChar()) != EOF && isspace(c)) {
str->getChar();
}
if (c == 't') {
break;
}
for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
s[i] = (char)c;
}
if (i == 0) {
goto err2;
}
s[i] = '\0';
first = atoi(s);
while ((c = str->lookChar()) != EOF && isspace(c)) {
str->getChar();
}
for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
s[i] = (char)c;
}
if (i == 0) {
goto err2;
}
s[i] = '\0';
n = atoi(s);
while ((c = str->lookChar()) != EOF && isspace(c)) {
str->getChar();
}
// check for buggy PDF files with an incorrect (too small) xref
// table size
if (first + n > size) {
newSize = size + 256;
entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
for (i = size; i < newSize; ++i) {
- entries[i].offset = -1;
+ entries[i].offset = 0xffffffff;
entries[i].used = gFalse;
}
size = newSize;
}
for (i = first; i < first + n; ++i) {
for (j = 0; j < 20; ++j) {
if ((c = str->getChar()) == EOF) {
goto err2;
}
s[j] = (char)c;
}
- if (entries[i].offset < 0) {
+ if (entries[i].offset == 0xffffffff) {
s[10] = '\0';
- entries[i].offset = atoi(s);
+ entries[i].offset = strToUnsigned(s);
s[16] = '\0';
entries[i].gen = atoi(&s[11]);
if (s[17] == 'n') {
entries[i].used = gTrue;
} else if (s[17] == 'f') {
entries[i].used = gFalse;
} else {
goto err2;
}
// PDF files of patents from the IBM Intellectual Property
// Network have a bug: the xref table claims to start at 1
// instead of 0.
if (i == 1 && first == 1 &&
entries[1].offset == 0 && entries[1].gen == 65535 &&
!entries[1].used) {
i = first = 0;
entries[0] = entries[1];
- entries[1].offset = -1;
+ entries[1].offset = 0xffffffff;
}
}
}
}
// read prev pointer from trailer dictionary
obj.initNull();
- parser = new Parser(NULL, new Lexer(NULL, str->makeSubStream(str->getPos(),
- -1, &obj)));
+ parser = new Parser(NULL,
+ new Lexer(NULL,
+ str->makeSubStream(str->getPos(), gFalse, 0, &obj)));
parser->getObj(&obj);
if (!obj.isCmd("trailer")) {
goto err1;
}
obj.free();
parser->getObj(&obj);
if (!obj.isDict()) {
goto err1;
}
obj.getDict()->lookupNF("Prev", &obj2);
if (obj2.isInt()) {
- *pos = obj2.getInt();
+ *pos = (Guint)obj2.getInt();
more = gTrue;
} else {
more = gFalse;
}
obj.free();
obj2.free();
delete parser;
return more;
err1:
obj.free();
err2:
ok = gFalse;
return gFalse;
}
// Attempt to construct an xref table for a damaged file.
GBool XRef::constructXRef() {
Parser *parser;
Object obj;
char buf[256];
- int pos;
+ Guint pos;
int num, gen;
int newSize;
int streamEndsSize;
char *p;
int i;
GBool gotRoot;
error(0, "PDF file is damaged - attempting to reconstruct xref table...");
gotRoot = gFalse;
streamEndsLen = streamEndsSize = 0;
str->reset();
while (1) {
pos = str->getPos();
if (!str->getLine(buf, 256)) {
break;
}
p = buf;
// got trailer dictionary
if (!strncmp(p, "trailer", 7)) {
obj.initNull();
- parser = new Parser(NULL, new Lexer(NULL,
- str->makeSubStream(start + pos + 7, -1, &obj)));
+ parser = new Parser(NULL,
+ new Lexer(NULL,
+ str->makeSubStream(start + pos + 7, gFalse, 0, &obj)));
if (!trailerDict.isNone())
trailerDict.free();
parser->getObj(&trailerDict);
if (trailerDict.isDict()) {
trailerDict.dictLookupNF("Root", &obj);
if (obj.isRef()) {
rootNum = obj.getRefNum();
rootGen = obj.getRefGen();
gotRoot = gTrue;
}
obj.free();
} else {
pos = 0;
}
delete parser;
// look for object
} else if (isdigit(*p)) {
num = atoi(p);
do {
++p;
} while (*p && isdigit(*p));
if (isspace(*p)) {
do {
++p;
} while (*p && isspace(*p));
if (isdigit(*p)) {
gen = atoi(p);
do {
++p;
} while (*p && isdigit(*p));
if (isspace(*p)) {
do {
++p;
} while (*p && isspace(*p));
if (!strncmp(p, "obj", 3)) {
if (num >= size) {
newSize = (num + 1 + 255) & ~255;
entries = (XRefEntry *)
grealloc(entries, newSize * sizeof(XRefEntry));
for (i = size; i < newSize; ++i) {
- entries[i].offset = -1;
+ entries[i].offset = 0xffffffff;
entries[i].used = gFalse;
}
size = newSize;
}
if (!entries[num].used || gen >= entries[num].gen) {
entries[num].offset = pos - start;
entries[num].gen = gen;
entries[num].used = gTrue;
}
}
}
}
}
} else if (!strncmp(p, "endstream", 9)) {
if (streamEndsLen == streamEndsSize) {
streamEndsSize += 64;
- streamEnds = (int *)grealloc(streamEnds, streamEndsSize * sizeof(int));
+ streamEnds = (Guint *)grealloc(streamEnds,
+ streamEndsSize * sizeof(int));
}
streamEnds[streamEndsLen++] = pos;
}
}
if (gotRoot)
return gTrue;
error(-1, "Couldn't find trailer dictionary");
return gFalse;
}
#ifndef NO_DECRYPTION
GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
Object encrypt, filterObj, versionObj, revisionObj, lengthObj;
Object ownerKey, userKey, permissions, fileID, fileID1;
GBool encrypted1;
GBool ret;
ret = gFalse;
permFlags = defPermFlags;
trailerDict.dictLookup("Encrypt", &encrypt);
if ((encrypted1 = encrypt.isDict())) {
ret = gTrue;
encrypt.dictLookup("Filter", &filterObj);
if (filterObj.isName("Standard")) {
encrypt.dictLookup("V", &versionObj);
encrypt.dictLookup("R", &revisionObj);
encrypt.dictLookup("Length", &lengthObj);
encrypt.dictLookup("O", &ownerKey);
encrypt.dictLookup("U", &userKey);
encrypt.dictLookup("P", &permissions);
trailerDict.dictLookup("ID", &fileID);
if (versionObj.isInt() &&
revisionObj.isInt() &&
ownerKey.isString() && ownerKey.getString()->getLength() == 32 &&
userKey.isString() && userKey.getString()->getLength() == 32 &&
permissions.isInt() &&
fileID.isArray()) {
encVersion = versionObj.getInt();
encRevision = revisionObj.getInt();
if (lengthObj.isInt()) {
keyLength = lengthObj.getInt() / 8;
} else {
keyLength = 5;
}
permFlags = permissions.getInt();
if (encVersion >= 1 && encVersion <= 2 &&
encRevision >= 2 && encRevision <= 3) {
fileID.arrayGet(0, &fileID1);
if (fileID1.isString()) {
if (Decrypt::makeFileKey(encVersion, encRevision, keyLength,
ownerKey.getString(), userKey.getString(),
permFlags, fileID1.getString(),
ownerPassword, userPassword, fileKey,
&ownerPasswordOk)) {
if (ownerPassword && !ownerPasswordOk) {
error(-1, "Incorrect owner password");
}
ret = gFalse;
} else {
error(-1, "Incorrect password");
}
} else {
error(-1, "Weird encryption info");
}
fileID1.free();
} else {
error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
encVersion, encRevision);
}
} else {
error(-1, "Weird encryption info");
}
fileID.free();
permissions.free();
userKey.free();
ownerKey.free();
lengthObj.free();
revisionObj.free();
versionObj.free();
} else {
error(-1, "Unknown security handler '%s'",
filterObj.isName() ? filterObj.getName() : "???");
}
filterObj.free();
}
encrypt.free();
// this flag has to be set *after* we read the O/U/P strings
encrypted = encrypted1;
return ret;
}
#else
GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
Object obj;
GBool encrypted;
trailerDict.dictLookup("Encrypt", &obj);
if ((encrypted = !obj.isNull())) {
error(-1, "PDF file is encrypted and this version of the Xpdf tools");
error(-1, "was built without decryption support.");
}
obj.free();
return encrypted;
}
#endif
GBool XRef::okToPrint(GBool ignoreOwnerPW) {
#ifndef NO_DECRYPTION
if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permPrint)) {
return gFalse;
}
#endif
return gTrue;
}
GBool XRef::okToChange(GBool ignoreOwnerPW) {
#ifndef NO_DECRYPTION
if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permChange)) {
return gFalse;
}
#endif
return gTrue;
}
GBool XRef::okToCopy(GBool ignoreOwnerPW) {
#ifndef NO_DECRYPTION
if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permCopy)) {
return gFalse;
}
#endif
return gTrue;
}
GBool XRef::okToAddNotes(GBool ignoreOwnerPW) {
#ifndef NO_DECRYPTION
if ((ignoreOwnerPW || !ownerPasswordOk) && !(permFlags & permNotes)) {
return gFalse;
}
#endif
return gTrue;
}
Object *XRef::fetch(int num, int gen, Object *obj) {
XRefEntry *e;
Parser *parser;
Object obj1, obj2, obj3;
// check for bogus ref - this can happen in corrupted PDF files
if (num < 0 || num >= size) {
obj->initNull();
return obj;
}
e = &entries[num];
- if (e->gen == gen && e->offset >= 0) {
+ if (e->gen == gen && e->offset != 0xffffffff) {
obj1.initNull();
- parser = new Parser(this, new Lexer(this,
- str->makeSubStream(start + e->offset, -1, &obj1)));
+ parser = new Parser(this,
+ new Lexer(this,
+ str->makeSubStream(start + e->offset, gFalse, 0, &obj1)));
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
if (obj1.isInt() && obj1.getInt() == num &&
obj2.isInt() && obj2.getInt() == gen &&
obj3.isCmd("obj")) {
#ifndef NO_DECRYPTION
parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
num, gen);
#else
parser->getObj(obj);
#endif
} else {
obj->initNull();
}
obj1.free();
obj2.free();
obj3.free();
delete parser;
} else {
obj->initNull();
}
return obj;
}
Object *XRef::getDocInfo(Object *obj) {
return trailerDict.dictLookup("Info", obj);
}
// Added for the pdftex project.
Object *XRef::getDocInfoNF(Object *obj) {
return trailerDict.dictLookupNF("Info", obj);
}
-int XRef::getStreamEnd(int streamStart) {
+GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) {
int a, b, m;
if (streamEndsLen == 0 ||
streamStart > streamEnds[streamEndsLen - 1]) {
- return -1;
+ return gFalse;
}
a = -1;
b = streamEndsLen - 1;
// invariant: streamEnds[a] < streamStart <= streamEnds[b]
while (b - a > 1) {
m = (a + b) / 2;
if (streamStart <= streamEnds[m]) {
b = m;
} else {
a = m;
}
}
- return streamEnds[b];
+ *streamEnd = streamEnds[b];
+ return gTrue;
+}
+
+Guint XRef::strToUnsigned(char *s) {
+ Guint x;
+ char *p;
+ int i;
+
+ x = 0;
+ for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) {
+ x = 10 * x + (*p - '0');
+ }
+ return x;
}
diff --git a/noncore/unsupported/qpdf/xpdf/XRef.h b/noncore/unsupported/qpdf/xpdf/XRef.h
index a44c495..7876fa6 100644
--- a/noncore/unsupported/qpdf/xpdf/XRef.h
+++ b/noncore/unsupported/qpdf/xpdf/XRef.h
@@ -1,111 +1,116 @@
//========================================================================
//
// XRef.h
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifndef XREF_H
#define XREF_H
#ifdef __GNUC__
#pragma interface
#endif
#include "gtypes.h"
#include "Object.h"
class Dict;
class Stream;
//------------------------------------------------------------------------
// XRef
//------------------------------------------------------------------------
struct XRefEntry {
- int offset;
+ Guint offset;
int gen;
GBool used;
};
class XRef {
public:
// Constructor. Read xref table from stream.
XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword);
// Destructor.
~XRef();
// Is xref table valid?
GBool isOk() { return ok; }
+ // Get the error code (if isOk() returns false).
+ int getErrorCode() { return errCode; }
+
// Is the file encrypted?
#ifndef NO_DECRYPTION
GBool isEncrypted() { return encrypted; }
#else
GBool isEncrypted() { return gFalse; }
#endif
// Check various permissions.
GBool okToPrint(GBool ignoreOwnerPW = gFalse);
GBool okToChange(GBool ignoreOwnerPW = gFalse);
GBool okToCopy(GBool ignoreOwnerPW = gFalse);
GBool okToAddNotes(GBool ignoreOwnerPW = gFalse);
// Get catalog object.
Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); }
// Fetch an indirect reference.
Object *fetch(int num, int gen, Object *obj);
// Return the document's Info dictionary (if any).
Object *getDocInfo(Object *obj);
Object *getDocInfoNF(Object *obj);
// Return the number of objects in the xref table.
int getNumObjects() { return size; }
// Return the offset of the last xref table.
- int getLastXRefPos() { return lastXRefPos; }
+ Guint getLastXRefPos() { return lastXRefPos; }
// Return the catalog object reference.
int getRootNum() { return rootNum; }
int getRootGen() { return rootGen; }
// Get end position for a stream in a damaged file.
- // Returns -1 if unknown or file is not damaged.
- int getStreamEnd(int streamStart);
+ // Returns false if unknown or file is not damaged.
+ GBool getStreamEnd(Guint streamStart, Guint *streamEnd);
private:
BaseStream *str; // input stream
- int start; // offset in file (to allow for garbage
+ Guint start; // offset in file (to allow for garbage
// at beginning of file)
XRefEntry *entries; // xref entries
int size; // size of <entries> array
int rootNum, rootGen; // catalog dict
GBool ok; // true if xref table is valid
+ int errCode; // error code (if <ok> is false)
Object trailerDict; // trailer dictionary
- int lastXRefPos; // offset of last xref table
- int *streamEnds; // 'endstream' positions - only used in
+ Guint lastXRefPos; // offset of last xref table
+ Guint *streamEnds; // 'endstream' positions - only used in
// damaged files
int streamEndsLen; // number of valid entries in streamEnds
#ifndef NO_DECRYPTION
GBool encrypted; // true if file is encrypted
int encVersion; // encryption algorithm
int encRevision; // security handler revision
int keyLength; // length of key, in bytes
int permFlags; // permission bits
Guchar fileKey[16]; // file decryption key
GBool ownerPasswordOk; // true if owner password is correct
#endif
- int readTrailer();
- GBool readXRef(int *pos);
+ Guint readTrailer();
+ GBool readXRef(Guint *pos);
GBool constructXRef();
GBool checkEncrypted(GString *ownerPassword, GString *userPassword);
+ Guint strToUnsigned(char *s);
};
#endif