author | sandman <sandman> | 2002-05-23 23:51:52 (UTC) |
---|---|---|
committer | sandman <sandman> | 2002-05-23 23:51:52 (UTC) |
commit | 2f3bb7b07f833273d966d41813e68bfe8b9d8d76 (patch) (side-by-side diff) | |
tree | 00beb1bd9e7f4ba79e22334a0d258269b28f4564 | |
parent | 6e82b45dd416ceeba78765717b700e853c96a137 (diff) | |
download | opie-2f3bb7b07f833273d966d41813e68bfe8b9d8d76.zip opie-2f3bb7b07f833273d966d41813e68bfe8b9d8d76.tar.gz opie-2f3bb7b07f833273d966d41813e68bfe8b9d8d76.tar.bz2 |
Port to xpdf 1.01
69 files changed, 2086 insertions, 600 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 @@ -81,2 +81,9 @@ public: + // 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 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 @@ -3,3 +3,3 @@ 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 @@ -22,3 +22,3 @@ Changes in 20020408: -Changed in 20020413: +Changes in 20020413: - Fixed crash in find routine @@ -28,2 +28,9 @@ Changed in 20020413: +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 + @@ -54,22 +61,7 @@ ToDo: 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 + 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 @@ -78,7 +70,6 @@ Install: - 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) 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 @@ -24 +24,15 @@ static int mapUTF8 ( Unicode u, char *buf, int bufSize ) } + +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 @@ -18,3 +18,2 @@ #include <qpe/applnk.h> -#include <qpe/fileselector.h> #include <qpe/qcopenvelope_qws.h> @@ -24,2 +23,3 @@ #include <qtoolbar.h> +#include <qtoolbutton.h> #include <qmenubar.h> @@ -39,2 +39,8 @@ +#ifdef QPDF_QPE_ONLY +#include <qpe/fileselector.h> +#else +#include <opie/ofileselector.h> +#endif + @@ -83,3 +89,8 @@ QPdfDlg::QPdfDlg ( ) : QMainWindow ( ) +#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 ( ))); 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 @@ -7,2 +7,3 @@ +#define QPDF_QPE_ONLY 1 // ofileselector does not work right currently @@ -13,2 +14,3 @@ class DocLnk; class FileSelector; +class OFileSelector; class QWidgetStack; @@ -70,3 +72,8 @@ private: QPEOutputDev *m_outdev; + +#ifdef QPDF_QPE_ONLY FileSelector *m_filesel; +#else + OFileSelector *m_filesel; +#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 @@ -15,3 +15,3 @@ SOURCES = xpdf/Array.cc \ xpdf/FontEncodingTables.cc \ - xpdf/FormWidget.cc \ + xpdf/Annot.cc \ xpdf/Function.cc \ @@ -29,2 +29,3 @@ SOURCES = xpdf/Array.cc \ xpdf/Parser.cc \ + xpdf/PSTokenizer.cc \ xpdf/Stream.cc \ @@ -54,3 +55,3 @@ INCLUDEPATH += . \ -LIBS += -L $(OPIEDIR)/lib -lqpe +LIBS += -L $(OPIEDIR)/lib -lqpe -lopie 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 @@ -2,5 +2,5 @@ // -// FormWidget.cc +// Annot.cc // -// Copyright 2000 Derek B. Noonburg +// Copyright 2000-2002 Glyph & Cog, LLC // @@ -16,9 +16,9 @@ #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; @@ -79,3 +79,3 @@ FormWidget::FormWidget(XRef *xrefA, Dict *dict) { -FormWidget::~FormWidget() { +Annot::~Annot() { appearance.free(); @@ -83,3 +83,3 @@ FormWidget::~FormWidget() { -void FormWidget::draw(Gfx *gfx) { +void Annot::draw(Gfx *gfx) { Object obj; @@ -87,3 +87,3 @@ void FormWidget::draw(Gfx *gfx) { if (appearance.fetch(xref, &obj)->isStream()) { - gfx->doWidgetForm(&obj, xMin, yMin, xMax, yMax); + gfx->doAnnot(&obj, xMin, yMin, xMax, yMax); } @@ -93,7 +93,7 @@ void FormWidget::draw(Gfx *gfx) { //------------------------------------------------------------------------ -// FormWidgets +// Annots //------------------------------------------------------------------------ -FormWidgets::FormWidgets(XRef *xref, Object *annots) { - FormWidget *widget; +Annots::Annots(XRef *xref, Object *annotsObj) { + Annot *annot; Object obj1, obj2; @@ -102,9 +102,9 @@ FormWidgets::FormWidgets(XRef *xref, Object *annots) { - 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); @@ -112,12 +112,11 @@ FormWidgets::FormWidgets(XRef *xref, Object *annots) { 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; } @@ -131,9 +130,9 @@ FormWidgets::FormWidgets(XRef *xref, Object *annots) { -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 @@ -2,5 +2,5 @@ // -// FormWidget.h +// Annot.h // -// Copyright 2000 Derek B. Noonburg +// Copyright 2000-2002 Glyph & Cog, LLC // @@ -8,4 +8,4 @@ -#ifndef FORMWIDGET_H -#define FORMWIDGET_H +#ifndef ANNOT_H +#define ANNOT_H @@ -15,2 +15,4 @@ +#include <aconf.h> + class XRef; @@ -19,10 +21,10 @@ 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; } @@ -39,3 +41,3 @@ private: // for the normal appearance - fouble xMin, yMin, // widget rectangle + fouble xMin, yMin, // annotation rectangle xMax, yMax; @@ -45,16 +47,16 @@ private: //------------------------------------------------------------------------ -// 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]; } @@ -62,4 +64,4 @@ private: - FormWidget **widgets; - int nWidgets; + Annot **annots; + int nAnnots; }; 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // @@ -22,2 +22,3 @@ #include "GlobalParams.h" +#include "PSTokenizer.h" #include "CMap.h" @@ -36,2 +37,8 @@ struct CMapVectorEntry { +static int getCharFromFile(void *data) { + return fgetc((FILE *)data); +} + +//------------------------------------------------------------------------ + CMap *CMap::parse(CMapCache *cache, GString *collectionA, @@ -40,7 +47,6 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA, 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; @@ -63,46 +69,60 @@ CMap *CMap::parse(CMapCache *cache, GString *collectionA, - inCodeSpace = inCIDRange = gFalse; - while (getLine(buf, sizeof(buf), f)) { - tok1 = strtok(buf, " \t\r\n"); - if (!tok1 || tok1[0] == '%') { - continue; + 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); } - tok2 = strtok(NULL, " \t\r\n"); - tok3 = strtok(NULL, " \t\r\n"); - if (inCodeSpace) { + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok1, "/WMode")) { + cmap->wMode = atoi(tok2); + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincodespacerange")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { 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'; + 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); - n = (n - 2) / 2; - cmap->addCodeSpace(cmap->vector, start, end, n); + n1 = (n1 - 2) / 2; + cmap->addCodeSpace(cmap->vector, start, end, n1); } - } else if (inCIDRange) { + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincidrange")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { 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'; + 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); - n = (n - 2) / 2; - cmap->addCIDs(start, end, n, (CID)atoi(tok3)); + n1 = (n1 - 2) / 2; + cmap->addCIDs(start, end, n1, (CID)atoi(tok3)); } - } else if (tok2 && !strcmp(tok2, "usecmap")) { - if (tok1[0] == '/') { - cmap->useCMap(cache, tok1 + 1); } - } 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 { + strcpy(tok1, tok2); } } + delete pst; 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -148,3 +148,3 @@ GString *Catalog::readMetadata() { if (!dict->lookup("Subtype", &obj)->isName("XML")) { - error(-1, "Unknown Metadata type: '%s'\n", + error(-1, "Unknown Metadata type: '%s'", obj.isName() ? obj.getName() : "???"); @@ -267,6 +267,6 @@ LinkDest *Catalog::findDest(GString *name) { 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 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // @@ -20,2 +20,3 @@ #include "GlobalParams.h" +#include "PSTokenizer.h" #include "CharCodeToUnicode.h" @@ -34,2 +35,22 @@ struct CharCodeToUnicodeString { +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) { @@ -77,27 +98,2 @@ CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) { -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) { @@ -108,4 +104,3 @@ CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) { p = buf->getCString(); - ctu->parseCMap1((char *(*)(char *, int, void *))&getLineFromString, - &p, nBits); + ctu->parseCMap1(&getCharFromString, &p, nBits); return ctu; @@ -113,7 +108,6 @@ CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) { -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; @@ -128,19 +122,31 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), nDigits = nBits / 4; - inBFChar = inBFRange = gFalse; - while ((*getLineFunc)(buf, sizeof(buf), data)) { - tok1 = strtok(buf, " \t\r\n"); - if (!tok1 || tok1[0] == '%') { - continue; + 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()); } - tok2 = strtok(NULL, " \t\r\n"); - tok3 = strtok(NULL, " \t\r\n"); - if (inBFChar) { + delete name; + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "beginbfchar")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { if (!strcmp(tok1, "endbfchar")) { - inBFChar = gFalse; - } else if (tok2) { - n1 = strlen(tok1); - n2 = strlen(tok2); + 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; @@ -149,3 +155,3 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), 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; @@ -162,3 +168,3 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), 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; @@ -179,3 +185,3 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), 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"); } @@ -184,12 +190,16 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), } - } else { - error(-1, "Illegal bfchar block in ToUnicode CMap"); } - } else if (inBFRange) { + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "beginbfrange")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { if (!strcmp(tok1, "endbfrange")) { - inBFRange = gFalse; - } else if (tok2 && tok3) { - n1 = strlen(tok1); - n2 = strlen(tok2); - n3 = strlen(tok3); + 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] == '>' && @@ -197,3 +207,3 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), 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; @@ -203,3 +213,3 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), 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; @@ -216,3 +226,3 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), 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; @@ -236,3 +246,3 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), 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"); } @@ -243,23 +253,9 @@ void CharCodeToUnicode::parseCMap1(char *(*getLineFunc)(char *, int, void *), } - } 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); + pst->getToken(tok1, sizeof(tok1), &n1); } 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; + strcpy(tok1, tok2); } } + delete pst; } 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 @@ -6,3 +6,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // @@ -52,4 +52,3 @@ private: - void parseCMap1(char *(*getLineFunc)(char *, int, void *), - void *data, int nBits); + void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits); CharCodeToUnicode(GString *collectionA); 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // @@ -13,3 +13,3 @@ static struct { } displayFontTab[] = { -#if _NO_USE_FOR_QPE +#if 0 {"Courier", "-*-courier-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"}, @@ -29,3 +29,3 @@ static struct { #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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // @@ -417,3 +417,2 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) { ok = gFalse; - hasN = gFalse; @@ -427,2 +426,3 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) { } + hasN = hasRange; @@ -438,2 +438,3 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) { n = obj1.arrayGetLength(); + hasN = gTrue; } else if (obj1.arrayGetLength() != n) { @@ -458,2 +459,3 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) { n = obj1.arrayGetLength(); + hasN = gTrue; } else if (obj1.arrayGetLength() != n) { @@ -482,2 +484,9 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) { + // 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; 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -32,2 +32,7 @@ +// the MSVC math.h doesn't define this +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + //------------------------------------------------------------------------ @@ -42,2 +47,8 @@ +// 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) + //------------------------------------------------------------------------ @@ -376,2 +387,3 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, fouble dpi, xref = xrefA; + subPage = gFalse; printCommands = printCommandsA; @@ -407,5 +419,37 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, fouble dpi, -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()) { @@ -414,11 +458,12 @@ Gfx::~Gfx() { } + if (!subPage) { out->endPage(); + } while (res) { - resPtr = res->getNext(); - delete res; - res = resPtr; + popResources(); } - if (state) + if (state) { delete state; } +} @@ -451,3 +496,3 @@ void Gfx::go(GBool topLevel) { Object args[maxArgs]; - int numCmds, numArgs; + int numArgs; int i; @@ -455,3 +500,3 @@ void Gfx::go(GBool topLevel) { // scan a sequence of objects - numCmds = 0; + updateLevel = 0; numArgs = 0; @@ -478,5 +523,5 @@ void Gfx::go(GBool topLevel) { // periodically update display - if (++numCmds == 200) { + if (++updateLevel >= 20000) { out->dump(); - numCmds = 0; + updateLevel = 0; } @@ -521,3 +566,3 @@ void Gfx::go(GBool topLevel) { // update display - if (topLevel && numCmds > 0) { + if (topLevel && updateLevel > 0) { out->dump(); @@ -1140,3 +1185,3 @@ void Gfx::doPatternFill(GBool eoFill) { 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; @@ -1191,11 +1236,2 @@ void Gfx::doPatternFill(GBool eoFill) { - // 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 @@ -1333,2 +1369,5 @@ void Gfx::opShFill(Object args[], int numArgs) { break; + case 3: + doRadialShFill((GfxRadialShading *)shading); + break; } @@ -1345,5 +1384,2 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { fouble x0, y0, x1, y1; - fouble det; - fouble *ctm; - fouble ictm[6]; fouble dx, dy, mul; @@ -1359,50 +1395,4 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { - // 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); @@ -1621,2 +1611,198 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { +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() { @@ -1802,2 +1988,3 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) { Object obj; + int wMode; int i; @@ -1808,2 +1995,3 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) { } + wMode = state->getFont()->getWMode(); a = args[0].getArray(); @@ -1812,3 +2000,7 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) { 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()); @@ -1825,2 +2017,3 @@ void Gfx::doShowText(GString *s) { GfxFont *font; + int wMode; fouble riseX, riseY; @@ -1828,6 +2021,11 @@ void Gfx::doShowText(GString *s) { 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; @@ -1838,14 +2036,10 @@ void Gfx::doShowText(GString *s) { 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(); @@ -1869,2 +2063,4 @@ void Gfx::doShowText(GString *s) { state->textTransformDelta(0, state->getRise(), &riseX, &riseY); + curX = state->getCurX(); + curY = state->getCurY(); oldParser = parser; @@ -1876,4 +2072,10 @@ void Gfx::doShowText(GString *s) { &dx, &dy, &originX, &originY); - state->transform(state->getCurX() + riseX, state->getCurY() + riseY, - &x, &y); + 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->transform(curX + riseX, curY + riseY, &x, &y); out->saveState(state); @@ -1882,3 +2084,7 @@ void Gfx::doShowText(GString *s) { //~ out->updateCTM(???) + if (!out->beginType3Char(state, code, u, uLen)) { ((Gfx8BitFont *)font)->getCharProc(code, &charProc); + if ((resDict = ((Gfx8BitFont *)font)->getResources())) { + pushResources(resDict); + } if (charProc.isStream()) { @@ -1888,13 +2094,15 @@ void Gfx::doShowText(GString *s) { } - state = state->restore(); - out->restoreState(state); + out->endType3Char(state); + if (resDict) { + popResources(); + } 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 = 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; @@ -1903,10 +2111,5 @@ void Gfx::doShowText(GString *s) { 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(); @@ -1917,2 +2120,9 @@ void Gfx::doShowText(GString *s) { &dx, &dy, &originX, &originY); + 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(); @@ -1923,2 +2133,3 @@ void Gfx::doShowText(GString *s) { dy *= state->getFontSize(); + } state->textTransformDelta(dx, dy, &tdx, &tdy); @@ -1933,3 +2144,2 @@ void Gfx::doShowText(GString *s) { } - out->endString(state); @@ -1953,2 +2163,8 @@ void Gfx::doShowText(GString *s) { } + if (wMode) { + dx *= state->getFontSize(); + dy = dy * state->getFontSize() + + nChars * state->getCharSpace() + + nSpaces * state->getWordSpace(); + } else { dx = dx * state->getFontSize() @@ -1958,2 +2174,3 @@ void Gfx::doShowText(GString *s) { dy *= state->getFontSize(); + } state->textTransformDelta(dx, dy, &tdx, &tdy); @@ -1962,2 +2179,8 @@ void Gfx::doShowText(GString *s) { } + + if (out->useDrawChar()) { + out->endString(state); + } + + updateLevel += 10 * s->getLength(); } @@ -1969,3 +2192,3 @@ void Gfx::doShowText(GString *s) { void Gfx::opXObject(Object args[], int numArgs) { - Object obj1, obj2, refObj; + Object obj1, obj2, obj3, refObj; #if OPI_SUPPORT @@ -1995,2 +2218,6 @@ void Gfx::opXObject(Object args[], int numArgs) { 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()) { @@ -2150,2 +2377,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { + if ((i = width * height) > 1000) { + i = 1000; + } + updateLevel += i; + return; @@ -2217,3 +2449,3 @@ void Gfx::doForm(Object *str) { -void Gfx::doWidgetForm(Object *str, fouble xMin, fouble yMin, +void Gfx::doAnnot(Object *str, fouble xMin, fouble yMin, fouble xMax, fouble yMax) { @@ -2222,4 +2454,7 @@ void Gfx::doWidgetForm(Object *str, fouble xMin, fouble yMin, 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; @@ -2229,3 +2464,3 @@ void Gfx::doWidgetForm(Object *str, fouble xMin, fouble yMin, - // get bounding box + // get the form bounding box dict->lookup("BBox", &bboxObj); @@ -2243,3 +2478,3 @@ void Gfx::doWidgetForm(Object *str, fouble xMin, fouble yMin, - // get matrix + // get the form matrix dict->lookup("Matrix", &matrixObj); @@ -2258,12 +2493,60 @@ void Gfx::doWidgetForm(Object *str, fouble xMin, fouble yMin, - // 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]; - // translate to widget rectangle - m[4] += xMin; - m[5] += yMin; + // 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; + } + + // 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; @@ -2283,3 +2566,2 @@ void Gfx::doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox) { fouble oldBaseMatrix[6]; - GfxResources *resPtr; int i; @@ -2287,3 +2569,3 @@ void Gfx::doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox) { // push new resources on stack - res = new GfxResources(xref, resDict, res); + pushResources(resDict); @@ -2334,2 +2616,14 @@ void Gfx::doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox) { // pop resource stack + popResources(); + + return; +} + +void Gfx::pushResources(Dict *resDict) { + res = new GfxResources(xref, resDict, res); +} + +void Gfx::popResources() { + GfxResources *resPtr; + resPtr = res->getNext(); @@ -2337,4 +2631,2 @@ void Gfx::doForm1(Object *str, Dict *resDict, fouble *matrix, fouble *bbox) { res = resPtr; - - return; } @@ -2380,3 +2672,2 @@ Stream *Gfx::buildImageStream() { obj.free(); - parser->getObj(&obj); } else { @@ -2385,4 +2676,6 @@ Stream *Gfx::buildImageStream() { parser->getObj(&obj); - if (obj.isEOF() || obj.isError()) + if (obj.isEOF() || obj.isError()) { + gfree(key); break; + } dict.dictAdd(key, &obj); @@ -2391,5 +2684,9 @@ Stream *Gfx::buildImageStream() { } - if (obj.isEOF()) + if (obj.isEOF()) { error(getPos(), "End of file in inline image"); obj.free(); + dict.free(); + return NULL; + } + obj.free(); @@ -2415,3 +2712,3 @@ void Gfx::opEndImage(Object args[], int numArgs) { void Gfx::opSetCharWidth(Object args[], int numArgs) { - error(getPos(), "Encountered 'd0' operator in content stream"); + out->type3D0(state, args[0].getNum(), args[1].getNum()); } @@ -2419,3 +2716,5 @@ void Gfx::opSetCharWidth(Object args[], int numArgs) { 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()); } 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -29,2 +29,3 @@ class GfxShading; class GfxAxialShading; +class GfxRadialShading; class GfxState; @@ -99,3 +100,6 @@ public: - // Destructor. + // Constructor for a sub-page object. + Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, + PDFRectangle *box, GBool crop, PDFRectangle *cropBox); + ~Gfx(); @@ -105,5 +109,10 @@ public: - void doWidgetForm(Object *str, fouble xMin, fouble yMin, + // 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: @@ -112,4 +121,6 @@ private: 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; @@ -181,2 +192,3 @@ private: void doAxialShFill(GfxAxialShading *shading); + void doRadialShFill(GfxRadialShading *shading); void doEndPath(); 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 @@ -4,3 +4,3 @@ // -// Copyright 1996-2001 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -456,6 +456,14 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - // 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"); @@ -463,2 +471,5 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, } + if (!fontDict->lookup("Resources", &resources)->isDict()) { + resources.free(); + } } @@ -515,5 +526,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, // 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)) { @@ -526,8 +539,11 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, #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); } @@ -571,2 +587,3 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, if (obj2.isArray()) { + hasEncoding = gTrue; code = 0; @@ -638,4 +655,5 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, // 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()) { @@ -658,2 +676,5 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, code2 = atoi(charName+1); + } else if (n >= 4 && n <= 6 && + isdigit(charName[2]) && isdigit(charName[3])) { + code2 = atoi(charName+2); } @@ -686,2 +707,3 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, if (obj1.isArray()) { + flags |= fontFixedWidth; for (code = firstChar; code <= lastChar; ++code) { @@ -690,2 +712,5 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, widths[code] = obj2.getNum() * mul; + if (widths[code] != widths[firstChar]) { + flags &= ~fontFixedWidth; + } } @@ -754,2 +779,5 @@ Gfx8BitFont::~Gfx8BitFont() { } + if (resources.isDict()) { + resources.free(); + } } @@ -773,2 +801,6 @@ CharCodeToUnicode *Gfx8BitFont::getToUnicode() { +Dict *Gfx8BitFont::getCharProcs() { + return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL; +} + Object *Gfx8BitFont::getCharProc(int code, Object *proc) { @@ -782,2 +814,6 @@ Object *Gfx8BitFont::getCharProc(int code, Object *proc) { +Dict *Gfx8BitFont::getResources() { + return resources.isDict() ? resources.getDict() : (Dict *)NULL; +} + //------------------------------------------------------------------------ @@ -1188,2 +1224,6 @@ int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, +int GfxCIDFont::getWMode() { + return cMap ? cMap->getWMode() : 0; +} + CharCodeToUnicode *GfxCIDFont::getToUnicode() { @@ -1218,3 +1258,3 @@ GfxFontDict::GfxFontDict(XRef *xref, Dict *fontDict) { } else { - error(-1, "font resource is not a dictionary"); + error(-1, "font resource is not a dictionary reference"); fonts[i] = 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 @@ -4,3 +4,3 @@ // -// Copyright 1996-2001 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -115,4 +115,3 @@ public: // NULL if there is no embedded font. - char *getEmbeddedFontName() - { return embFontName ? embFontName->getCString() : (char *)NULL; } + GString *getEmbeddedFontName() { return embFontName; } @@ -139,2 +138,5 @@ public: + // Return the writing mode (0=horizontal, 1=vertical). + virtual int getWMode() { return 0; } + // Read an external or embedded font file into a buffer. @@ -157,3 +159,3 @@ protected: CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits); - void GfxFont::findExtFontFile(); + void findExtFontFile(); @@ -168,3 +170,3 @@ protected: 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 @@ -206,2 +208,5 @@ public: + // Return the Type 3 CharProc dictionary, or NULL if none. + Dict *getCharProcs(); + // Return the Type 3 CharProc for the character associated with <code>. @@ -209,2 +214,5 @@ public: + // Return the Type 3 Resources dictionary, or NULL if none. + Dict *getResources(); + private: @@ -218,2 +226,3 @@ private: Object charProcs; // Type3 CharProcs dictionary + Object resources; // Type 3 Resources dictionary }; @@ -238,2 +247,5 @@ public: + // Return the writing mode (0=horizontal, 1=vertical). + virtual int getWMode(); + // Return the Unicode map. 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -410,5 +410,18 @@ void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, fouble *gray) { 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); } @@ -1270,6 +1283,2 @@ GfxShading *GfxShading::parse(Object *obj) { obj1.free(); - if (typeA != 2) { - error(-1, "Unimplemented shading type %d", typeA); - goto err1; - } @@ -1319,3 +1328,13 @@ GfxShading *GfxShading::parse(Object *obj) { + 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; + } @@ -1459,2 +1478,124 @@ void GfxAxialShading::getColor(fouble t, GfxColor *color) { //------------------------------------------------------------------------ +// 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 @@ -1920,2 +2061,63 @@ GfxState::GfxState(GfxState *state) { +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) { @@ -1948,2 +2150,4 @@ void GfxState::setCTM(fouble a, fouble b, fouble c, fouble d, fouble e, fouble f) { + int i; + ctm[0] = a; @@ -1954,2 +2158,11 @@ void GfxState::setCTM(fouble a, fouble b, fouble c, 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); + } + } } @@ -1962,2 +2175,3 @@ void GfxState::concatCTM(fouble a, fouble b, fouble c, fouble d1 = ctm[3]; + int i; @@ -1969,2 +2183,11 @@ void GfxState::concatCTM(fouble a, fouble b, fouble c, 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); + } + } } @@ -2053,6 +2276,6 @@ void GfxState::clip() { -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; @@ -2097 +2320,2 @@ GfxState *GfxState::restore() { } + 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -570,2 +570,36 @@ private: //------------------------------------------------------------------------ +// 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 @@ -785,2 +819,3 @@ public: { *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; } + void getUserClipBBox(fouble *xMin, fouble *yMin, fouble *xMax, fouble *yMax); fouble getLineX() { return lineX; } @@ -867,3 +902,3 @@ public: { 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); 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // @@ -98,5 +98,8 @@ DisplayFontParam::~DisplayFontParam() { -PSFontParam::PSFontParam(GString *pdfFontNameA, GString *psFontNameA) { +PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA, + GString *psFontNameA, GString *encodingA) { pdfFontName = pdfFontNameA; + wMode = wModeA; psFontName = psFontNameA; + encoding = encodingA; } @@ -106,2 +109,5 @@ PSFontParam::~PSFontParam() { delete psFontName; + if (encoding) { + delete encoding; + } } @@ -117,7 +123,2 @@ GlobalParams::GlobalParams(char *cfgFileName) { FILE *f; - char buf[512]; - int line; - GList *tokens; - GString *cmd; - char *p1, *p2; int i; @@ -126,4 +127,6 @@ GlobalParams::GlobalParams(char *cfgFileName) { + // 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]) { @@ -141,2 +144,3 @@ GlobalParams::GlobalParams(char *cfgFileName) { displayCIDFonts = new GHash(); + displayNamedCIDFonts = new GHash(); #if HAVE_PAPER_H @@ -156,5 +160,10 @@ GlobalParams::GlobalParams(char *cfgFileName) { 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"); @@ -168,2 +177,3 @@ GlobalParams::GlobalParams(char *cfgFileName) { fontDirs = new GList(); + initialZoom = new GString("1"); t1libControl = fontRastAALow; @@ -195,2 +205,4 @@ GlobalParams::GlobalParams(char *cfgFileName) { residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("UCS-2", &mapUCS2); + residentUnicodeMaps->add(map->getEncodingName(), map); @@ -221,2 +233,3 @@ GlobalParams::GlobalParams(char *cfgFileName) { #if defined(WIN32) && !defined(__CYGWIN32__) + char buf[512]; i = GetModuleFileName(NULL, buf, sizeof(buf)); @@ -236,2 +249,15 @@ GlobalParams::GlobalParams(char *cfgFileName) { if (f) { + 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; @@ -260,3 +286,17 @@ GlobalParams::GlobalParams(char *cfgFileName) { cmd = (GString *)tokens->get(0); - if (!cmd->cmp("nameToUnicode")) { + 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, "Bad 'include' config file command (%s:%d)", + fileName->getCString(), line); + } + } else if (!cmd->cmp("nameToUnicode")) { parseNameToUnicode(tokens, fileName, line); @@ -271,9 +311,13 @@ GlobalParams::GlobalParams(char *cfgFileName) { } else if (!cmd->cmp("displayFontX")) { - parseDisplayFont(tokens, gFalse, displayFontX, fileName, line); + parseDisplayFont(tokens, displayFonts, displayFontX, fileName, line); } else if (!cmd->cmp("displayFontT1")) { - parseDisplayFont(tokens, gFalse, displayFontT1, fileName, line); + parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line); } else if (!cmd->cmp("displayFontTT")) { - parseDisplayFont(tokens, gFalse, displayFontTT, fileName, line); + parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line); } else if (!cmd->cmp("displayCIDFontX")) { - parseDisplayFont(tokens, gTrue, displayFontX, fileName, line); + parseDisplayFont(tokens, displayCIDFonts, + displayFontX, fileName, line); + } else if (!cmd->cmp("displayNamedCIDFontX")) { + parseDisplayFont(tokens, displayNamedCIDFonts, + displayFontX, fileName, line); } else if (!cmd->cmp("psFile")) { @@ -282,2 +326,7 @@ GlobalParams::GlobalParams(char *cfgFileName) { 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")) { @@ -288,9 +337,17 @@ GlobalParams::GlobalParams(char *cfgFileName) { parsePSLevel(tokens, fileName, line); - } else if (!cmd->cmp("psEmbedType1")) { + } else if (!cmd->cmp("psEmbedType1Fonts")) { parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line); - } else if (!cmd->cmp("psEmbedTrueType")) { + } 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")) { @@ -301,2 +358,4 @@ GlobalParams::GlobalParams(char *cfgFileName) { parseFontDir(tokens, fileName, line); + } else if (!cmd->cmp("initialZoom")) { + parseInitialZoom(tokens, fileName, line); } else if (!cmd->cmp("t1libControl")) { @@ -326,5 +385,2 @@ GlobalParams::GlobalParams(char *cfgFileName) { } - - delete fileName; - } } @@ -428,3 +484,3 @@ void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName, -void GlobalParams::parseDisplayFont(GList *tokens, GBool isCID, +void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash, DisplayFontParamKind kind, @@ -460,13 +516,6 @@ void GlobalParams::parseDisplayFont(GList *tokens, GBool isCID, - if (isCID) { - if ((old = (DisplayFontParam *)displayCIDFonts->remove(param->name))) { - delete old; - } - displayCIDFonts->add(param->name, param); - } else { - if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) { + if ((old = (DisplayFontParam *)fontHash->remove(param->name))) { delete old; } - displayFonts->add(param->name, param); - } + fontHash->add(param->name, param); return; @@ -476,3 +525,3 @@ void GlobalParams::parseDisplayFont(GList *tokens, GBool isCID, err1: - error(-1, "Bad 'displayFont...' config file command (%s:%d)", + error(-1, "Bad 'display*Font*' config file command (%s:%d)", fileName->getCString(), line); @@ -518,2 +567,6 @@ void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) { psLevel = psLevel2Sep; + } else if (!tok->cmp("level3")) { + psLevel = psLevel3; + } else if (!tok->cmp("level3Sep")) { + psLevel = psLevel3Sep; } else { @@ -544,4 +597,4 @@ void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) { } - 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); @@ -549,2 +602,30 @@ void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) { +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, @@ -590,6 +671,6 @@ void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) { -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); @@ -597,6 +678,4 @@ void GlobalParams::parseURLCommand(GList *tokens, GString *fileName, } - if (urlCommand) { - delete urlCommand; - } - urlCommand = ((GString *)tokens->get(1))->copy(); + delete initialZoom; + initialZoom = ((GString *)tokens->get(1))->copy(); } @@ -620,2 +699,15 @@ void GlobalParams::parseFontRastControl(char *cmdName, FontRastControl *val, +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, @@ -656,2 +748,3 @@ GlobalParams::~GlobalParams() { deleteGHash(displayCIDFonts, DisplayFontParam); + deleteGHash(displayNamedCIDFonts, DisplayFontParam); if (psFile) { @@ -660,4 +753,7 @@ GlobalParams::~GlobalParams() { deleteGHash(psFonts, PSFontParam); + deleteGList(psNamedFonts16, PSFontParam); + deleteGList(psFonts16, PSFontParam); delete textEncoding; deleteGList(fontDirs, GString); + delete initialZoom; if (urlCommand) { @@ -754,4 +850,11 @@ DisplayFontParam *GlobalParams::getDisplayFont(GString *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; } @@ -762,2 +865,31 @@ PSFontParam *GlobalParams::getPSFont(GString *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, @@ -868,2 +1000,10 @@ void GlobalParams::setPSEmbedTrueType(GBool embed) { +void GlobalParams::setPSEmbedCIDPostScript(GBool embed) { + psEmbedCIDPostScript = embed; +} + +void GlobalParams::setPSEmbedCIDTrueType(GBool embed) { + psEmbedCIDTrueType = embed; +} + void GlobalParams::setPSOPI(GBool opi) { @@ -872,2 +1012,6 @@ void GlobalParams::setPSOPI(GBool opi) { +void GlobalParams::setPSASCIIHex(GBool hex) { + psASCIIHex = hex; +} + void GlobalParams::setTextEncoding(char *encodingName) { @@ -890,2 +1034,7 @@ GBool GlobalParams::setTextEOL(char *s) { +void GlobalParams::setInitialZoom(char *s) { + delete initialZoom; + initialZoom = new GString(s); +} + GBool GlobalParams::setT1libControl(char *s) { 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // @@ -47,4 +47,5 @@ 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; @@ -81,6 +82,12 @@ 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(); @@ -94,3 +101,5 @@ enum PSLevel { psLevel2, - psLevel2Sep + psLevel2Sep, + psLevel3, + psLevel3Sep }; @@ -127,3 +136,3 @@ public: DisplayFontParam *getDisplayFont(GString *fontName); - DisplayFontParam *getDisplayCIDFont(GString *collection); + DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection); GString *getPSFile() { return psFile; } @@ -134,5 +143,9 @@ public: 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; } @@ -140,2 +153,3 @@ public: GString *findFontFile(GString *fontName, char *ext1, char *ext2); + GString *getInitialZoom() { return initialZoom; } FontRastControl getT1libControl() { return t1libControl; } @@ -161,5 +175,9 @@ public: 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); @@ -170,2 +188,3 @@ private: + void parseFile(GString *fileName, FILE *f); void parseNameToUnicode(GList *tokens, GString *fileName, int line); @@ -175,3 +194,4 @@ private: 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); @@ -181,2 +201,4 @@ private: 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); @@ -184,2 +206,3 @@ private: void parseFontDir(GList *tokens, GString *fileName, int line); + void parseInitialZoom(GList *tokens, GString *fileName, int line); void parseFontRastControl(char *cmdName, FontRastControl *val, @@ -214,2 +237,4 @@ private: // collection [DisplayFontParam] + GHash *displayNamedCIDFonts; // display CID font info, indexed by + // font name [DisplayFontParam] GString *psFile; // PostScript file or command (for xpdf) @@ -221,5 +246,10 @@ private: // 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 @@ -229,2 +259,3 @@ private: GList *fontDirs; // list of font dirs [GString] + GString *initialZoom; // initial zoom level FontRastControl t1libControl; // t1lib rasterization mode 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -53,9 +53,10 @@ public: - // 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); } 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -31,3 +31,3 @@ static GString *getFileSpecName(Object *fileSpecObj); -LinkDest::LinkDest(Array *a, GBool pageIsRefA) { +LinkDest::LinkDest(Array *a) { Object obj1, obj2; @@ -35,3 +35,2 @@ LinkDest::LinkDest(Array *a, GBool pageIsRefA) { // initialize fields - pageIsRef = pageIsRefA; left = bottom = right = top = zoom = 0; @@ -40,12 +39,11 @@ LinkDest::LinkDest(Array *a, GBool pageIsRefA) { // 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"); @@ -53,5 +51,3 @@ LinkDest::LinkDest(Array *a, GBool pageIsRefA) { } - pageNum = obj1.getInt() + 1; obj1.free(); - } @@ -223,3 +219,3 @@ LinkGoTo::LinkGoTo(Object *destObj) { } else if (destObj->isArray()) { - dest = new LinkDest(destObj->getArray(), gTrue); + dest = new LinkDest(destObj->getArray()); if (!dest->isOk()) { @@ -261,3 +257,3 @@ LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) { } else if (destObj->isArray()) { - dest = new LinkDest(destObj->getArray(), gFalse); + dest = new LinkDest(destObj->getArray()); if (!dest->isOk()) { @@ -448,3 +444,3 @@ Link::Link(Dict *dict, GString *baseURI) { // get border - borderW = 0; + borderW = 1; if (!dict->lookup("Border", &obj1)->isNull()) { @@ -584,3 +580,3 @@ LinkAction *Links::find(fouble x, fouble y) { - for (i = 0; i < numLinks; ++i) { + for (i = numLinks - 1; i >= 0; --i) { if (links[i]->inRect(x, y)) { 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -65,6 +65,4 @@ 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); 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -178,4 +178,4 @@ public: char *streamGetLine(char *buf, int size); - int streamGetPos(); - void streamSetPos(int pos); + Guint streamGetPos(); + void streamSetPos(Guint pos, int dir = 0); Dict *streamGetDict(); @@ -289,7 +289,7 @@ inline char *Object::streamGetLine(char *buf, int 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); } 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -61,2 +61,7 @@ void OutputDev::updateAll(GfxState *state) { +GBool OutputDev::beginType3Char(GfxState *state, + CharCode code, Unicode *u, int uLen) { + return gFalse; +} + void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -48,2 +48,6 @@ public: + // 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? @@ -121,2 +125,5 @@ public: virtual void drawString(GfxState *state, GString *s) {} + virtual GBool beginType3Char(GfxState *state, + CharCode code, Unicode *u, int uLen); + virtual void endType3Char(GfxState *state) {} @@ -136,2 +143,10 @@ public: + //----- 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: 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -26,2 +26,3 @@ #include "Error.h" +#include "ErrorCodes.h" #include "Lexer.h" @@ -45,2 +46,3 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, ok = gFalse; + errCode = errNone; @@ -59,2 +61,3 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, error(-1, "Couldn't open file '%s'", fileName->getCString()); + errCode = errOpenFile; return; @@ -70,2 +73,3 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, delete fileName2; + errCode = errOpenFile; return; @@ -79,3 +83,3 @@ PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, obj.initNull(); - str = new FileStream(file, 0, -1, &obj); + str = new FileStream(file, 0, gFalse, 0, &obj); @@ -87,2 +91,3 @@ PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, ok = gFalse; + errCode = errNone; fileName = NULL; @@ -105,2 +110,3 @@ GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) { error(-1, "Couldn't read xref table"); + errCode = xref->getErrorCode(); return gFalse; @@ -112,2 +118,3 @@ GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) { error(-1, "Couldn't read page catalog"); + errCode = errBadCatalog; return gFalse; @@ -206,4 +213,5 @@ GBool PDFDoc::isLinearized() { 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); 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -44,2 +44,5 @@ public: + // Get the error code (if isOk() returns false). + int getErrorCode() { return errCode; } + // Get file name. @@ -139,2 +142,3 @@ private: GBool ok; + int errCode; }; 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -22,3 +22,3 @@ #include "Gfx.h" -#include "FormWidget.h" +#include "Annot.h" #endif @@ -95,2 +95,10 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { + // 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 @@ -105,2 +113,8 @@ PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { PageAttrs::~PageAttrs() { + lastModified.free(); + boxColorInfo.free(); + group.free(); + metadata.free(); + pieceInfo.free(); + separationInfo.free(); resources.free(); @@ -211,3 +225,3 @@ void Page::display(OutputDev *out, fouble dpi, int rotate, int i; - FormWidgets *formWidgets; + Annots *annotList; @@ -249,16 +263,16 @@ void Page::display(OutputDev *out, fouble dpi, int rotate, - // 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"); + if (annotList->getNumAnnots() > 0) { + if (printCommands) { + printf("***** Annotations\n"); } - for (i = 0; i < formWidgets->getNumWidgets(); ++i) { - formWidgets->getWidget(i)->draw(gfx); + for (i = 0; i < annotList->getNumAnnots(); ++i) { + annotList->getAnnot(i)->draw(gfx); } - if (formWidgets->getNumWidgets() > 0) { out->dump(); } - delete formWidgets; + delete annotList; 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -53,2 +53,16 @@ public: 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() @@ -68,2 +82,8 @@ private: int rotate; + Object lastModified; + Object boxColorInfo; + Object group; + Object metadata; + Object pieceInfo; + Object separationInfo; Object resources; @@ -99,2 +119,8 @@ public: 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(); } 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -157,3 +157,3 @@ Stream *Parser::makeStream(Object *dict) { Stream *str; - int pos, endPos, length; + Guint pos, endPos, length; @@ -166,3 +166,3 @@ Stream *Parser::makeStream(Object *dict) { if (obj.isInt()) { - length = obj.getInt(); + length = (Guint)obj.getInt(); obj.free(); @@ -175,3 +175,3 @@ Stream *Parser::makeStream(Object *dict) { // check for length in damaged file - if ((endPos = xref->getStreamEnd(pos)) >= 0) { + if (xref->getStreamEnd(pos, &endPos)) { length = endPos - pos; @@ -180,3 +180,4 @@ Stream *Parser::makeStream(Object *dict) { // make base stream - str = lexer->getStream()->getBaseStream()->makeSubStream(pos, length, dict); + str = lexer->getStream()->getBaseStream()->makeSubStream(pos, gTrue, + length, dict); 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -6,3 +6,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -305,3 +305,3 @@ void FilterStream::close() { -void FilterStream::setPos(int pos) { +void FilterStream::setPos(Guint pos, int dir) { error(-1, "Internal: called setPos() on FilterStream"); @@ -556,3 +556,4 @@ GBool StreamPredictor::getNextLine() { -FileStream::FileStream(FILE *fA, int startA, int lengthA, Object *dictA): +FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA, + Guint lengthA, Object *dictA): BaseStream(dictA) { @@ -560,2 +561,3 @@ FileStream::FileStream(FILE *fA, int startA, int lengthA, Object *dictA): start = startA; + limited = limitedA; length = lengthA; @@ -563,3 +565,4 @@ FileStream::FileStream(FILE *fA, int startA, int lengthA, Object *dictA): bufPos = start; - savePos = -1; + savePos = 0; + saved = gFalse; } @@ -570,4 +573,5 @@ FileStream::~FileStream() { -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); } @@ -575,4 +579,10 @@ Stream *FileStream::makeSubStream(int startA, int lengthA, Object *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; @@ -586,5 +596,9 @@ void FileStream::reset() { 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; } @@ -600,6 +614,6 @@ GBool FileStream::fillBuf() { 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; @@ -623,13 +637,22 @@ GBool FileStream::fillBuf() { -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__ @@ -638,4 +661,9 @@ void FileStream::setPos(int pos) { #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 } @@ -651,2 +679,86 @@ void FileStream::moveStart(int delta) { //------------------------------------------------------------------------ +// 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 @@ -662,3 +774,4 @@ 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"); @@ -667,3 +780,3 @@ Stream *EmbedStream::makeSubStream(int start, int length, Object *dictA) { -void EmbedStream::setPos(int pos) { +void EmbedStream::setPos(Guint pos, int dir) { error(-1, "Internal: called setPos() on EmbedStream"); @@ -671,3 +784,3 @@ void EmbedStream::setPos(int pos) { -int EmbedStream::getStart() { +Guint EmbedStream::getStart() { error(-1, "Internal: called getStart() on EmbedStream"); @@ -676,3 +789,3 @@ int EmbedStream::getStart() { -void EmbedStream::moveStart(int start) { +void EmbedStream::moveStart(int delta) { error(-1, "Internal: called moveStart() on EmbedStream"); @@ -961,7 +1074,3 @@ void LZWStream::reset() { #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()); @@ -3289,2 +3398,52 @@ int FixedLengthEncoder::lookChar() { //------------------------------------------------------------------------ +// 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 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -80,4 +80,6 @@ public: - // 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; @@ -120,4 +122,5 @@ public: 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; } @@ -126,3 +129,3 @@ public: // 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; @@ -131,3 +134,4 @@ public: // 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 @@ -158,3 +162,3 @@ public: 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(); } @@ -244,5 +248,7 @@ 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; } @@ -255,5 +261,5 @@ public: 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); @@ -265,4 +271,5 @@ private: FILE *f; - int start; - int length; + Guint start; + GBool limited; + Guint length; char buf[fileStreamBufSize]; @@ -270,4 +277,42 @@ private: 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; }; @@ -289,3 +334,4 @@ public: 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(); } @@ -295,5 +341,5 @@ public: 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); @@ -661,2 +707,33 @@ private: //------------------------------------------------------------------------ +// 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 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 @@ -4,3 +4,3 @@ // -// Copyright 1997 Derek B. Noonburg +// Copyright 1997-2002 Glyph & Cog, LLC // @@ -50,2 +50,8 @@ TextString::TextString(GfxState *state, fouble 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; @@ -101,2 +107,3 @@ void TextPage::updateFont(GfxState *state) { int code; + fouble w; @@ -118,4 +125,7 @@ void TextPage::updateFont(GfxState *state) { if (code < 256) { + w = ((Gfx8BitFont *)font)->getWidth(code); + if (w != 0) { // 600 is a generic average 'm' width -- yes, this is a hack - fontSize *= ((Gfx8BitFont *)font)->getWidth(code) / 0.6; + fontSize *= w / 0.6; + } } @@ -156,4 +166,6 @@ void TextPage::addChar(GfxState *state, fouble x, fouble y, state->transformDelta(dx, dy, &w1, &h1); + if (uLen != 0) { w1 /= uLen; h1 /= uLen; + } for (i = 0; i < uLen; ++i) { @@ -431,3 +443,3 @@ GString *TextPage::getText(fouble xMin, fouble yMin, -void TextPage::dump(FILE *f) { +void TextPage::dump(void *outputStream, TextOutputFunc outputFunc) { UnicodeMap *uMap; @@ -500,5 +512,5 @@ void TextPage::dump(FILE *f) { #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, @@ -510,3 +522,3 @@ void TextPage::dump(FILE *f) { } - fprintf(f, "~~~~~~~~~~\n"); + fprintf((FILE *)outputStream, "~~~~~~~~~~\n"); #endif @@ -523,3 +535,3 @@ void TextPage::dump(FILE *f) { for (; col1 < str1->col; ++col1) { - fwrite(space, 1, spaceLen, f); + (*outputFunc)(outputStream, space, spaceLen); } @@ -530,3 +542,3 @@ void TextPage::dump(FILE *f) { if ((n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf))) > 0) { - fwrite(buf, 1, n, f); + (*outputFunc)(outputStream, buf, n); } @@ -549,3 +561,3 @@ void TextPage::dump(FILE *f) { // print a return - fwrite(eol, 1, eolLen, f); + (*outputFunc)(outputStream, eol, eolLen); @@ -575,3 +587,3 @@ void TextPage::dump(FILE *f) { for (; d > 0; --d) { - fwrite(eol, 1, eolLen, f); + (*outputFunc)(outputStream, eol, eolLen); } @@ -586,5 +598,5 @@ void TextPage::dump(FILE *f) { // 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); @@ -613,2 +625,6 @@ void TextPage::clear() { +static void outputToFile(void *stream, char *text, int len) { + fwrite(text, 1, len, (FILE *)stream); +} + TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { @@ -622,4 +638,4 @@ TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { 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; @@ -630,4 +646,5 @@ TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { } + outputFunc = &outputToFile; } else { - f = NULL; + outputStream = NULL; } @@ -638,2 +655,12 @@ TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { +TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream, + GBool rawOrderA) { + outputFunc = func; + outputStream = stream; + needClose = gFalse; + rawOrder = rawOrderA; + text = new TextPage(rawOrder); + ok = gTrue; +} + TextOutputDev::~TextOutputDev() { @@ -641,5 +668,5 @@ TextOutputDev::~TextOutputDev() { #ifdef MACOS - ICS_MapRefNumAndAssign((short)f->handle); + ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle); #endif - fclose(f); + fclose((FILE *)outputStream); } @@ -656,4 +683,4 @@ void TextOutputDev::endPage() { text->coalesce(); - if (f) { - text->dump(f); + if (outputStream) { + text->dump(outputStream, outputFunc); } 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 @@ -4,3 +4,3 @@ // -// Copyright 1997 Derek B. Noonburg +// Copyright 1997-2002 Glyph & Cog, LLC // @@ -24,2 +24,6 @@ class GString; //------------------------------------------------------------------------ + +typedef void (*TextOutputFunc)(void *stream, char *text, int len); + +//------------------------------------------------------------------------ // TextString @@ -99,3 +103,3 @@ public: // Dump contents of page to a file. - void dump(FILE *f); + void dump(void *outputStream, TextOutputFunc outputFunc); @@ -130,2 +134,6 @@ public: + // 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. @@ -145,2 +153,6 @@ public: + // 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? @@ -181,4 +193,6 @@ 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 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -6,3 +6,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // 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 @@ -4,3 +4,3 @@ // -// Copyright 2001 Derek B. Noonburg +// Copyright 2001-2002 Glyph & Cog, LLC // @@ -15,2 +15,4 @@ static UnicodeMapRange latin1UnicodeMapRanges[] = { { 0x00ae, 0x00ff, 0xae, 1 }, + { 0x010c, 0x010c, 0x43, 1 }, + { 0x010d, 0x010d, 0x63, 1 }, { 0x0131, 0x0131, 0x69, 1 }, @@ -43,2 +45,19 @@ static UnicodeMapRange latin1UnicodeMapRanges[] = { { 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 }, @@ -137,2 +156,41 @@ static UnicodeMapRange ascii7UnicodeMapRanges[] = { { 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 }, 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -27,2 +27,3 @@ #include "Error.h" +#include "ErrorCodes.h" #include "XRef.h" @@ -51,3 +52,3 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) { - int pos; + Guint pos; int i; @@ -55,2 +56,3 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) { ok = gTrue; + errCode = errNone; size = 0; @@ -69,2 +71,3 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) { if (!(ok = constructXRef())) { + errCode = errDamaged; return; @@ -76,3 +79,3 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) { for (i = 0; i < size; ++i) { - entries[i].offset = -1; + entries[i].offset = 0xffffffff; entries[i].used = gFalse; @@ -88,2 +91,3 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) { if (!(ok = constructXRef())) { + errCode = errDamaged; return; @@ -103,2 +107,3 @@ XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) { ok = gFalse; + errCode = errEncrypted; return; @@ -117,3 +122,3 @@ XRef::~XRef() { // first xref position. -int XRef::readTrailer() { +Guint XRef::readTrailer() { Parser *parser; @@ -121,3 +126,4 @@ int XRef::readTrailer() { char buf[xrefSearchSize+1]; - int n, pos, pos1; + int n; + Guint pos, pos1; char *p; @@ -127,3 +133,3 @@ int XRef::readTrailer() { // read last xrefSearchSize bytes - str->setPos(-xrefSearchSize); + str->setPos(xrefSearchSize, -1); for (n = 0; n < xrefSearchSize; ++n) { @@ -143,3 +149,3 @@ int XRef::readTrailer() { for (p = &buf[i+9]; isspace(*p); ++p) ; - pos = lastXRefPos = atoi(p); + pos = lastXRefPos = strToUnsigned(p); @@ -178,4 +184,5 @@ int XRef::readTrailer() { 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); @@ -206,3 +213,3 @@ int XRef::readTrailer() { // Read an xref table and the prev pointer from the trailer. -GBool XRef::readXRef(int *pos) { +GBool XRef::readXRef(Guint *pos) { Parser *parser; @@ -263,3 +270,3 @@ GBool XRef::readXRef(int *pos) { for (i = size; i < newSize; ++i) { - entries[i].offset = -1; + entries[i].offset = 0xffffffff; entries[i].used = gFalse; @@ -275,5 +282,5 @@ GBool XRef::readXRef(int *pos) { } - 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'; @@ -295,3 +302,3 @@ GBool XRef::readXRef(int *pos) { entries[0] = entries[1]; - entries[1].offset = -1; + entries[1].offset = 0xffffffff; } @@ -303,4 +310,5 @@ GBool XRef::readXRef(int *pos) { 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); @@ -316,3 +324,3 @@ GBool XRef::readXRef(int *pos) { if (obj2.isInt()) { - *pos = obj2.getInt(); + *pos = (Guint)obj2.getInt(); more = gTrue; @@ -339,3 +347,3 @@ GBool XRef::constructXRef() { char buf[256]; - int pos; + Guint pos; int num, gen; @@ -362,4 +370,5 @@ GBool XRef::constructXRef() { 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()) @@ -405,3 +414,3 @@ GBool XRef::constructXRef() { for (i = size; i < newSize; ++i) { - entries[i].offset = -1; + entries[i].offset = 0xffffffff; entries[i].used = gFalse; @@ -423,3 +432,4 @@ GBool XRef::constructXRef() { streamEndsSize += 64; - streamEnds = (int *)grealloc(streamEnds, streamEndsSize * sizeof(int)); + streamEnds = (Guint *)grealloc(streamEnds, + streamEndsSize * sizeof(int)); } @@ -582,6 +592,7 @@ Object *XRef::fetch(int num, int gen, Object *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); @@ -620,3 +631,3 @@ Object *XRef::getDocInfoNF(Object *obj) { -int XRef::getStreamEnd(int streamStart) { +GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) { int a, b, m; @@ -625,3 +636,3 @@ int XRef::getStreamEnd(int streamStart) { streamStart > streamEnds[streamEndsLen - 1]) { - return -1; + return gFalse; } @@ -639,3 +650,16 @@ int XRef::getStreamEnd(int streamStart) { } - 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 @@ -4,3 +4,3 @@ // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // @@ -26,3 +26,3 @@ class Stream; struct XRefEntry { - int offset; + Guint offset; int gen; @@ -43,2 +43,5 @@ public: + // Get the error code (if isOk() returns false). + int getErrorCode() { return errCode; } + // Is the file encrypted? @@ -70,3 +73,3 @@ public: // Return the offset of the last xref table. - int getLastXRefPos() { return lastXRefPos; } + Guint getLastXRefPos() { return lastXRefPos; } @@ -77,4 +80,4 @@ public: // 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); @@ -83,3 +86,3 @@ 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) @@ -89,5 +92,6 @@ private: 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 @@ -104,6 +108,7 @@ private: - int readTrailer(); - GBool readXRef(int *pos); + Guint readTrailer(); + GBool readXRef(Guint *pos); GBool constructXRef(); GBool checkEncrypted(GString *ownerPassword, GString *userPassword); + Guint strToUnsigned(char *s); }; |