diff options
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf')
114 files changed, 3229 insertions, 1552 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc index 7b2b9855669..33534dafd60 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <math.h> #include "gmem.h" @@ -343,8 +339,12 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { AcroForm *acroForm; AcroFormField *field; Object xfaObj, fieldsObj, annotsObj, annotRef, annotObj, obj1, obj2; + char *touchedObjs; int pageNum, i, j; + touchedObjs = (char *)gmalloc(docA->getXRef()->getNumObjects()); + memset(touchedObjs, 0, docA->getXRef()->getNumObjects()); + // this is the normal case: acroFormObj is a dictionary, as expected if (acroFormObjA->isDict()) { acroForm = new AcroForm(docA, acroFormObjA); @@ -372,11 +372,12 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { } obj1.free(); delete acroForm; + gfree(touchedObjs); return NULL; } for (i = 0; i < obj1.arrayGetLength(); ++i) { obj1.arrayGetNF(i, &obj2); - acroForm->scanField(&obj2); + acroForm->scanField(&obj2, touchedObjs); obj2.free(); } obj1.free(); @@ -400,7 +401,7 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { annotRef.fetch(acroForm->doc->getXRef(), &annotObj); if (annotObj.isDict()) { if (annotObj.dictLookup("Subtype", &obj1)->isName("Widget")) { - acroForm->scanField(&annotRef); + acroForm->scanField(&annotRef, touchedObjs); } obj1.free(); } @@ -431,7 +432,7 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { annotRef.fetch(acroForm->doc->getXRef(), &annotObj); if (annotObj.isDict()) { if (annotObj.dictLookup("Subtype", &obj1)->isName("Widget")) { - acroForm->scanField(&annotRef); + acroForm->scanField(&annotRef, touchedObjs); } obj1.free(); } @@ -449,6 +450,8 @@ AcroForm *AcroForm::load(PDFDoc *docA, Catalog *catalog, Object *acroFormObjA) { } } + gfree(touchedObjs); + return acroForm; } @@ -512,12 +515,22 @@ int AcroForm::lookupAnnotPage(Object *annotRef) { return 0; } -void AcroForm::scanField(Object *fieldRef) { +void AcroForm::scanField(Object *fieldRef, char *touchedObjs) { AcroFormField *field; Object fieldObj, kidsObj, kidRef, kidObj, subtypeObj; GBool isTerminal; int i; + // check for an object loop + if (fieldRef->isRef()) { + if (fieldRef->getRefNum() < 0 || + fieldRef->getRefNum() >= doc->getXRef()->getNumObjects() || + touchedObjs[fieldRef->getRefNum()]) { + return; + } + touchedObjs[fieldRef->getRefNum()] = 1; + } + fieldRef->fetch(doc->getXRef(), &fieldObj); if (!fieldObj.isDict()) { error(errSyntaxError, -1, "AcroForm field object is wrong type"); @@ -545,7 +558,7 @@ void AcroForm::scanField(Object *fieldRef) { if (!isTerminal) { for (i = 0; !isTerminal && i < kidsObj.arrayGetLength(); ++i) { kidsObj.arrayGetNF(i, &kidRef); - scanField(&kidRef); + scanField(&kidRef, touchedObjs); kidRef.free(); } } @@ -2033,21 +2046,18 @@ void AcroFormField::drawText(GString *text, GString *da, GfxFontDict *fontDict, wMax = dx - 2 * border - 4; -#if 1 //~tmp // this is a kludge that appears to match Adobe's behavior if (height > 15) { topBorder = 5; } else { topBorder = 2; } -#else - topBorder = 5; -#endif // compute font autosize if (fontSize == 0) { for (fontSize = 10; fontSize > 1; --fontSize) { yy = dy - topBorder; + w = 0; i = 0; while (i < text2->getLength()) { getNextLine(text2, i, font, fontSize, wMax, &j, &w, &k); @@ -3183,7 +3193,7 @@ GBool AcroFormField::unicodeStringEqual(Unicode *u, int unicodeLength, return gFalse; } for (int i = 0; i < unicodeLength; ++i) { - if ((s->getChar(i) & 0xff) != u[i]) { + if ((Unicode)(s->getChar(i) & 0xff) != u[i]) { return gFalse; } } @@ -3193,7 +3203,7 @@ GBool AcroFormField::unicodeStringEqual(Unicode *u, int unicodeLength, GBool AcroFormField::unicodeStringEqual(Unicode *u, int unicodeLength, const char *s) { for (int i = 0; i < unicodeLength; ++i) { - if (!s[i] || (s[i] & 0xff) != u[i]) { + if (!s[i] || (Unicode)(s[i] & 0xff) != u[i]) { return gFalse; } } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.h b/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.h index 7678d46dbc8..0e922d17afc 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/AcroForm.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - class TextString; class Gfx; class GfxFont; @@ -47,7 +43,7 @@ private: AcroForm(PDFDoc *docA, Object *acroFormObjA); void buildAnnotPageList(Catalog *catalog); int lookupAnnotPage(Object *annotRef); - void scanField(Object *fieldRef); + void scanField(Object *fieldRef, char *touchedObjs); PDFDoc *doc; Object acroFormObj; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc index 82ef600be73..465bda6194a 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc @@ -2,18 +2,15 @@ // // Annot.cc // -// Copyright 2000-2003 Glyph & Cog, LLC +// Copyright 2000-2022 Glyph & Cog, LLC // //======================================================================== #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <math.h> +#include <limits.h> #include "gmem.h" #include "gmempp.h" #include "GList.h" @@ -278,6 +275,8 @@ Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) { obj3.free(); } else if (obj2.isRef()) { obj2.copy(&appearance); + } else if (obj2.isStream()) { + obj2.copy(&appearance); } obj1.free(); obj2.free(); @@ -306,29 +305,48 @@ Annot::~Annot() { ocObj.free(); } -void Annot::generateAnnotAppearance() { +void Annot::generateAnnotAppearance(Object *annotObj) { Object obj; - appearance.fetch(doc->getXRef(), &obj); - if (!obj.isStream()) { - if (type) { - if (!type->cmp("Line")) { - generateLineAppearance(); - } else if (!type->cmp("PolyLine")) { - generatePolyLineAppearance(); - } else if (!type->cmp("Polygon")) { - generatePolygonAppearance(); - } else if (!type->cmp("FreeText")) { - generateFreeTextAppearance(); - } - } - } + GBool alreadyHaveAppearance = obj.isStream(); obj.free(); + if (alreadyHaveAppearance) { + return; + } + + if (!type || (type->cmp("Line") && + type->cmp("PolyLine") && + type->cmp("Polygon") && + type->cmp("FreeText"))) { + return; + } + + Object annotObj2; + if (!annotObj) { + getObject(&annotObj2); + annotObj = &annotObj2; + } + if (!annotObj->isDict()) { + annotObj2.free(); + return; + } + + if (!type->cmp("Line")) { + generateLineAppearance(annotObj); + } else if (!type->cmp("PolyLine")) { + generatePolyLineAppearance(annotObj); + } else if (!type->cmp("Polygon")) { + generatePolygonAppearance(annotObj); + } else if (!type->cmp("FreeText")) { + generateFreeTextAppearance(annotObj); + } + + annotObj2.free(); } //~ this doesn't draw the caption -void Annot::generateLineAppearance() { - Object annotObj, gfxStateDict, appearDict, obj1, obj2; +void Annot::generateLineAppearance(Object *annotObj) { + Object gfxStateDict, appearDict, obj1, obj2; MemStream *appearStream; double x1, y1, x2, y2, dx, dy, len, w; double lx1, ly1, lx2, ly2; @@ -339,15 +357,10 @@ void Annot::generateLineAppearance() { AnnotLineEndType lineEnd1, lineEnd2; GBool fill; - if (!getObject(&annotObj)->isDict()) { - annotObj.free(); - return; - } - appearBuf = new GString(); //----- check for transparency - if (annotObj.dictLookup("CA", &obj1)->isNum()) { + if (annotObj->dictLookup("CA", &obj1)->isNum()) { gfxStateDict.initDict(doc->getXRef()); gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); appearBuf->append("/GS1 gs\n"); @@ -358,7 +371,7 @@ void Annot::generateLineAppearance() { setLineStyle(borderStyle, &w); setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps()); fill = gFalse; - if (annotObj.dictLookup("IC", &obj1)->isArray()) { + if (annotObj->dictLookup("IC", &obj1)->isArray()) { if (setFillColor(&obj1)) { fill = gTrue; } @@ -366,14 +379,14 @@ void Annot::generateLineAppearance() { obj1.free(); //----- get line properties - if (annotObj.dictLookup("L", &obj1)->isArray() && + if (annotObj->dictLookup("L", &obj1)->isArray() && obj1.arrayGetLength() == 4) { if (obj1.arrayGet(0, &obj2)->isNum()) { x1 = obj2.getNum(); } else { obj2.free(); obj1.free(); - goto err1; + return; } obj2.free(); if (obj1.arrayGet(1, &obj2)->isNum()) { @@ -381,7 +394,7 @@ void Annot::generateLineAppearance() { } else { obj2.free(); obj1.free(); - goto err1; + return; } obj2.free(); if (obj1.arrayGet(2, &obj2)->isNum()) { @@ -389,7 +402,7 @@ void Annot::generateLineAppearance() { } else { obj2.free(); obj1.free(); - goto err1; + return; } obj2.free(); if (obj1.arrayGet(3, &obj2)->isNum()) { @@ -397,16 +410,16 @@ void Annot::generateLineAppearance() { } else { obj2.free(); obj1.free(); - goto err1; + return; } obj2.free(); } else { obj1.free(); - goto err1; + return; } obj1.free(); lineEnd1 = lineEnd2 = annotLineEndNone; - if (annotObj.dictLookup("LE", &obj1)->isArray() && + if (annotObj->dictLookup("LE", &obj1)->isArray() && obj1.arrayGetLength() == 2) { lineEnd1 = parseLineEndType(obj1.arrayGet(0, &obj2)); obj2.free(); @@ -414,19 +427,19 @@ void Annot::generateLineAppearance() { obj2.free(); } obj1.free(); - if (annotObj.dictLookup("LL", &obj1)->isNum()) { + if (annotObj->dictLookup("LL", &obj1)->isNum()) { leaderLen = obj1.getNum(); } else { leaderLen = 0; } obj1.free(); - if (annotObj.dictLookup("LLE", &obj1)->isNum()) { + if (annotObj->dictLookup("LLE", &obj1)->isNum()) { leaderExtLen = obj1.getNum(); } else { leaderExtLen = 0; } obj1.free(); - if (annotObj.dictLookup("LLO", &obj1)->isNum()) { + if (annotObj->dictLookup("LLO", &obj1)->isNum()) { leaderOffLen = obj1.getNum(); } else { leaderOffLen = 0; @@ -513,27 +526,19 @@ void Annot::generateLineAppearance() { appearBuf->getLength(), &appearDict); appearance.free(); appearance.initStream(appearStream); - - err1: - annotObj.free(); } //~ this doesn't handle line ends (arrows) -void Annot::generatePolyLineAppearance() { - Object annotObj, gfxStateDict, appearDict, obj1, obj2; +void Annot::generatePolyLineAppearance(Object *annotObj) { + Object gfxStateDict, appearDict, obj1, obj2; MemStream *appearStream; double x1, y1, w; int i; - if (!getObject(&annotObj)->isDict()) { - annotObj.free(); - return; - } - appearBuf = new GString(); //----- check for transparency - if (annotObj.dictLookup("CA", &obj1)->isNum()) { + if (annotObj->dictLookup("CA", &obj1)->isNum()) { gfxStateDict.initDict(doc->getXRef()); gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); appearBuf->append("/GS1 gs\n"); @@ -544,7 +549,7 @@ void Annot::generatePolyLineAppearance() { setLineStyle(borderStyle, &w); setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps()); // fill = gFalse; - // if (annotObj.dictLookup("IC", &obj1)->isArray()) { + // if (annotObj->dictLookup("IC", &obj1)->isArray()) { // if (setFillColor(&obj1)) { // fill = gTrue; // } @@ -552,22 +557,22 @@ void Annot::generatePolyLineAppearance() { // obj1.free(); //----- draw line - if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) { + if (!annotObj->dictLookup("Vertices", &obj1)->isArray()) { obj1.free(); - goto err1; + return; } for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) { if (!obj1.arrayGet(i, &obj2)->isNum()) { obj2.free(); obj1.free(); - goto err1; + return; } x1 = obj2.getNum(); obj2.free(); if (!obj1.arrayGet(i+1, &obj2)->isNum()) { obj2.free(); obj1.free(); - goto err1; + return; } y1 = obj2.getNum(); obj2.free(); @@ -606,26 +611,18 @@ void Annot::generatePolyLineAppearance() { appearBuf->getLength(), &appearDict); appearance.free(); appearance.initStream(appearStream); - - err1: - annotObj.free(); } -void Annot::generatePolygonAppearance() { - Object annotObj, gfxStateDict, appearDict, obj1, obj2; +void Annot::generatePolygonAppearance(Object *annotObj) { + Object gfxStateDict, appearDict, obj1, obj2; MemStream *appearStream; double x1, y1; int i; - if (!getObject(&annotObj)->isDict()) { - annotObj.free(); - return; - } - appearBuf = new GString(); //----- check for transparency - if (annotObj.dictLookup("CA", &obj1)->isNum()) { + if (annotObj->dictLookup("CA", &obj1)->isNum()) { gfxStateDict.initDict(doc->getXRef()); gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); appearBuf->append("/GS1 gs\n"); @@ -633,30 +630,30 @@ void Annot::generatePolygonAppearance() { obj1.free(); //----- set fill color - if (!annotObj.dictLookup("IC", &obj1)->isArray() || + if (!annotObj->dictLookup("IC", &obj1)->isArray() || !setFillColor(&obj1)) { obj1.free(); - goto err1; + return; } obj1.free(); //----- fill polygon - if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) { + if (!annotObj->dictLookup("Vertices", &obj1)->isArray()) { obj1.free(); - goto err1; + return; } for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) { if (!obj1.arrayGet(i, &obj2)->isNum()) { obj2.free(); obj1.free(); - goto err1; + return; } x1 = obj2.getNum(); obj2.free(); if (!obj1.arrayGet(i+1, &obj2)->isNum()) { obj2.free(); obj1.free(); - goto err1; + return; } y1 = obj2.getNum(); obj2.free(); @@ -695,31 +692,23 @@ void Annot::generatePolygonAppearance() { appearBuf->getLength(), &appearDict); appearance.free(); appearance.initStream(appearStream); - - err1: - annotObj.free(); } //~ this doesn't handle rich text //~ this doesn't handle the callout //~ this doesn't handle the RD field -void Annot::generateFreeTextAppearance() { - Object annotObj, gfxStateDict, appearDict, obj1, obj2; +void Annot::generateFreeTextAppearance(Object *annotObj) { + Object gfxStateDict, appearDict, obj1, obj2; Object resources, gsResources, fontResources, defaultFont; GString *text, *da; double lineWidth; int quadding, rot; MemStream *appearStream; - if (!getObject(&annotObj)->isDict()) { - annotObj.free(); - return; - } - appearBuf = new GString(); //----- check for transparency - if (annotObj.dictLookup("CA", &obj1)->isNum()) { + if (annotObj->dictLookup("CA", &obj1)->isNum()) { gfxStateDict.initDict(doc->getXRef()); gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2)); appearBuf->append("/GS1 gs\n"); @@ -727,19 +716,19 @@ void Annot::generateFreeTextAppearance() { obj1.free(); //----- draw the text - if (annotObj.dictLookup("Contents", &obj1)->isString()) { + if (annotObj->dictLookup("Contents", &obj1)->isString()) { text = obj1.getString()->copy(); } else { text = new GString(); } obj1.free(); - if (annotObj.dictLookup("Q", &obj1)->isInt()) { + if (annotObj->dictLookup("Q", &obj1)->isInt()) { quadding = obj1.getInt(); } else { quadding = 0; } obj1.free(); - if (annotObj.dictLookup("DA", &obj1)->isString()) { + if (annotObj->dictLookup("DA", &obj1)->isString()) { da = obj1.getString()->copy(); } else { da = new GString(); @@ -747,7 +736,7 @@ void Annot::generateFreeTextAppearance() { obj1.free(); // the "Rotate" field is not defined in the PDF spec, but Acrobat // looks at it - if (annotObj.dictLookup("Rotate", &obj1)->isInt()) { + if (annotObj->dictLookup("Rotate", &obj1)->isInt()) { rot = obj1.getInt(); } else { rot = 0; @@ -797,8 +786,6 @@ void Annot::generateFreeTextAppearance() { appearBuf->getLength(), &appearDict); appearance.free(); appearance.initStream(appearStream); - - annotObj.free(); } void Annot::setLineStyle(AnnotBorderStyle *bs, double *lineWidth) { @@ -1344,105 +1331,192 @@ Object *Annot::getObject(Object *obj) { } //------------------------------------------------------------------------ -// Annots +// PageAnnots //------------------------------------------------------------------------ -Annots::Annots(PDFDoc *docA, Object *annotsObj) { - Annot *annot; - Object obj1, obj2; - Ref ref; - GBool drawWidgetAnnots; - int size; - int i; +class PageAnnots { +public: + + PageAnnots(); + ~PageAnnots(); + + GList *annots; // list of annots on the page [Annot] + GBool appearancesGenerated; // set after appearances have been generated +}; + +PageAnnots::PageAnnots() { + annots = new GList(); + appearancesGenerated = gFalse; +} + +PageAnnots::~PageAnnots() { + deleteGList(annots, Annot); +} +//------------------------------------------------------------------------ +// Annots +//------------------------------------------------------------------------ + +Annots::Annots(PDFDoc *docA) { doc = docA; - annots = NULL; - size = 0; - nAnnots = 0; - - if (annotsObj->isArray()) { - // Kludge: some PDF files define an empty AcroForm, but still - // include Widget-type annotations -- in that case, we want to - // draw the widgets (since the form code won't). This really - // ought to look for Widget-type annotations that are not included - // in any form field. - drawWidgetAnnots = !doc->getCatalog()->getForm() || - doc->getCatalog()->getForm()->getNumFields() == 0; - for (i = 0; i < annotsObj->arrayGetLength(); ++i) { - if (annotsObj->arrayGetNF(i, &obj1)->isRef()) { - ref = obj1.getRef(); - obj1.free(); - annotsObj->arrayGet(i, &obj1); - } else { - ref.num = ref.gen = -1; - } - if (obj1.isDict()) { - if (drawWidgetAnnots || - !obj1.dictLookup("Subtype", &obj2)->isName("Widget")) { - annot = new Annot(doc, obj1.getDict(), &ref); - if (annot->isOk()) { - if (nAnnots >= size) { - size += 16; - annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); - } - annots[nAnnots++] = annot; - } else { - delete annot; - } - } - obj2.free(); - } - obj1.free(); - } + pageAnnots = (PageAnnots **)gmallocn(doc->getNumPages(), sizeof(PageAnnots*)); + for (int page = 1; page <= doc->getNumPages(); ++page) { + pageAnnots[page - 1] = NULL; } + formFieldRefsSize = 0; + formFieldRefs = NULL; } Annots::~Annots() { - int i; + for (int page = 1; page <= doc->getNumPages(); ++page) { + delete pageAnnots[page - 1]; + } + gfree(pageAnnots); + gfree(formFieldRefs); +} + +void Annots::loadAnnots(int page) { + if (pageAnnots[page - 1]) { + return; + } + + pageAnnots[page - 1] = new PageAnnots(); + + Object annotsObj; + doc->getCatalog()->getPage(page)->getAnnots(&annotsObj); + if (!annotsObj.isArray()) { + annotsObj.free(); + return; + } + + loadFormFieldRefs(); + + for (int i = 0; i < annotsObj.arrayGetLength(); ++i) { + Object annotObj; + Ref annotRef; + if (annotsObj.arrayGetNF(i, &annotObj)->isRef()) { + annotRef = annotObj.getRef(); + annotObj.free(); + annotsObj.arrayGet(i, &annotObj); + } else { + annotRef.num = annotRef.gen = -1; + } + if (!annotObj.isDict()) { + annotObj.free(); + continue; + } + + // skip any annotations which are used as AcroForm fields -- + // they'll be rendered by the AcroForm module + if (annotRef.num >= 0 && annotRef.num < formFieldRefsSize && + formFieldRefs[annotRef.num]) { + annotObj.free(); + continue; + } + + Annot *annot = new Annot(doc, annotObj.getDict(), &annotRef); + annotObj.free(); + if (annot->isOk()) { + pageAnnots[page - 1]->annots->append(annot); + } else { + delete annot; + } + } + + annotsObj.free(); +} + +// Build a set of object refs for AcroForm fields. +void Annots::loadFormFieldRefs() { + if (formFieldRefs) { + return; + } - for (i = 0; i < nAnnots; ++i) { - delete annots[i]; + AcroForm *form = doc->getCatalog()->getForm(); + if (!form) { + return; + } + + int newFormFieldRefsSize = 256; + for (int i = 0; i < form->getNumFields(); ++i) { + AcroFormField *field = form->getField(i); + Object fieldRef; + field->getFieldRef(&fieldRef); + if (fieldRef.getRefNum() >= formFieldRefsSize) { + while (fieldRef.getRefNum() >= newFormFieldRefsSize && + newFormFieldRefsSize <= INT_MAX / 2) { + newFormFieldRefsSize *= 2; + } + if (fieldRef.getRefNum() >= newFormFieldRefsSize) { + continue; + } + formFieldRefs = (char *)grealloc(formFieldRefs, newFormFieldRefsSize); + for (int j = formFieldRefsSize; j < newFormFieldRefsSize; ++j) { + formFieldRefs[j] = (char)0; + } + formFieldRefsSize = newFormFieldRefsSize; + } + formFieldRefs[fieldRef.getRefNum()] = (char)1; + fieldRef.free(); } - gfree(annots); } -Annot *Annots::find(double x, double y) { - int i; +int Annots::getNumAnnots(int page) { + loadAnnots(page); + return pageAnnots[page - 1]->annots->getLength(); +} + +Annot *Annots::getAnnot(int page, int idx) { + loadAnnots(page); + return (Annot *)pageAnnots[page - 1]->annots->get(idx); +} - for (i = nAnnots - 1; i >= 0; --i) { - if (annots[i]->inRect(x, y)) { - return annots[i]; +Annot *Annots::find(int page, double x, double y) { + loadAnnots(page); + PageAnnots *pa = pageAnnots[page - 1]; + for (int i = pa->annots->getLength() - 1; i >= 0; --i) { + Annot *annot = (Annot *)pa->annots->get(i); + if (annot->inRect(x, y)) { + return annot; } } return NULL; } -int Annots::findIdx(double x, double y) { - int i; - - for (i = nAnnots - 1; i >= 0; --i) { - if (annots[i]->inRect(x, y)) { +int Annots::findIdx(int page, double x, double y) { + loadAnnots(page); + PageAnnots *pa = pageAnnots[page - 1]; + for (int i = pa->annots->getLength() - 1; i >= 0; --i) { + Annot *annot = (Annot *)pa->annots->get(i); + if (annot->inRect(x, y)) { return i; } } return -1; } -void Annots::generateAnnotAppearances() { - int i; - - for (i = 0; i < nAnnots; ++i) { - annots[i]->generateAnnotAppearance(); +void Annots::add(int page, Object *annotObj) { + if (!annotObj->isDict()) { + return; + } + Ref annotRef = {-1, -1}; + Annot *annot = new Annot(doc, annotObj->getDict(), &annotRef); + if (annot->isOk()) { + annot->generateAnnotAppearance(annotObj); + pageAnnots[page - 1]->annots->append(annot); + } else { + delete annot; } } -Annot *Annots::findAnnot(Ref *ref) { - int i; - - for (i = 0; i < nAnnots; ++i) { - if (annots[i]->match(ref)) { - return annots[i]; +void Annots::generateAnnotAppearances(int page) { + loadAnnots(page); + PageAnnots *pa = pageAnnots[page - 1]; + if (!pa->appearancesGenerated) { + for (int i = 0; i < pa->annots->getLength(); ++i) { + Annot *annot = (Annot *)pa->annots->get(i); + annot->generateAnnotAppearance(NULL); } + pa->appearancesGenerated = gTrue; } - return NULL; } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.h index 6ba5ff490da..168061fc262 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.h @@ -2,7 +2,7 @@ // // Annot.h // -// Copyright 2000-2003 Glyph & Cog, LLC +// Copyright 2000-2022 Glyph & Cog, LLC // //======================================================================== @@ -11,15 +11,12 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - class XRef; class Catalog; class Gfx; class GfxFontDict; class PDFDoc; +class PageAnnots; //------------------------------------------------------------------------ // AnnotBorderStyle @@ -105,14 +102,14 @@ public: GBool match(Ref *refA) { return ref.num == refA->num && ref.gen == refA->gen; } - void generateAnnotAppearance(); + void generateAnnotAppearance(Object *annotObj); private: - void generateLineAppearance(); - void generatePolyLineAppearance(); - void generatePolygonAppearance(); - void generateFreeTextAppearance(); + void generateLineAppearance(Object *annotObj); + void generatePolyLineAppearance(Object *annotObj); + void generatePolygonAppearance(Object *annotObj); + void generateFreeTextAppearance(Object *annotObj); void setLineStyle(AnnotBorderStyle *bs, double *lineWidth); void setStrokeColor(double *color, int nComps); GBool setFillColor(Object *colorObj); @@ -152,34 +149,35 @@ private: class Annots { public: - // Build a list of Annot objects. - Annots(PDFDoc *docA, Object *annotsObj); + Annots(PDFDoc *docA); ~Annots(); - // Iterate through list of annotations. - int getNumAnnots() { return nAnnots; } - Annot *getAnnot(int i) { return annots[i]; } + // Iterate over annotations on a specific page. + int getNumAnnots(int page); + Annot *getAnnot(int page, int idx); - // If point <x>,<y> is in an annotation, return the associated - // annotation; else return NULL. - Annot *find(double x, double y); - int findIdx(double x, double y); + // If point (<x>,<y>) is in an annotation, return the associated + // annotation (or annotation index); else return NULL (or -1). + Annot *find(int page, double x, double y); + int findIdx(int page, double x, double y); + + // Add an annotation [annotObj] on page [page]. + void add(int page, Object *annotObj); // Generate an appearance stream for any non-form-field annotation - // that is missing it. - void generateAnnotAppearances(); + // on the specified page that is missing an appearance. + void generateAnnotAppearances(int page); private: - void scanFieldAppearances(Dict *node, Ref *ref, Dict *parent, - Dict *acroForm); - - Annot *findAnnot(Ref *ref); + void loadAnnots(int page); + void loadFormFieldRefs(); PDFDoc *doc; - Annot **annots; - int nAnnots; + PageAnnots **pageAnnots; // list of annots for each page + int formFieldRefsSize; // number of entries in formFieldRefs[] + char *formFieldRefs; // set of AcroForm field refs }; #endif diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Array.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Array.cc index 2bf948ec65c..2771186152a 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Array.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Array.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <stddef.h> #include "gmem.h" @@ -53,7 +49,7 @@ void Array::add(Object *elem) { Object *Array::get(int i, Object *obj, int recursion) { if (i < 0 || i >= length) { -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM abort(); #else return obj->initNull(); @@ -64,7 +60,7 @@ Object *Array::get(int i, Object *obj, int recursion) { Object *Array::getNF(int i, Object *obj) { if (i < 0 || i >= length) { -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM abort(); #else return obj->initNull(); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Array.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Array.h index 8d10eadc8dd..9a887f41e46 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Array.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Array.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #if MULTITHREADED #include "GMutex.h" #endif diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc index d2f875e45fd..51c2d33b3f9 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <string.h> #include "gmem.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.h b/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.h index f24cbf98f9f..042e4e0d634 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/BuiltinFont.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" struct BuiltinFont; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/CMap.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/CMap.cc index 12632c5992c..c898ac5737d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/CMap.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/CMap.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/CMap.h b/Build/source/libs/xpdf/xpdf-src/xpdf/CMap.h index 55692b4f337..5731ef09f01 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/CMap.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/CMap.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "CharTypes.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc index ddcbad55f07..7a9b0701ca3 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <string.h> #include <stddef.h> #include <limits.h> @@ -526,7 +522,10 @@ GBool Catalog::readPageTree(Object *catDict) { // because other code tries to fetch pages 1 through n. // In both cases: ignore the given page count and scan the tree // instead. - numPages = countPageTree(&topPagesObj); + char *touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); + numPages = countPageTree(&topPagesRef, touchedObjs); + gfree(touchedObjs); } } else { // assume we got a Page node instead of a Pages node @@ -553,30 +552,53 @@ GBool Catalog::readPageTree(Object *catDict) { return gTrue; } -int Catalog::countPageTree(Object *pagesObj) { - Object kids, kid; - int n, n2, i; - - if (!pagesObj->isDict()) { +int Catalog::countPageTree(Object *pagesNodeRef, char *touchedObjs) { + // check for invalid reference + if (pagesNodeRef->isRef() && + (pagesNodeRef->getRefNum() < 0 || + pagesNodeRef->getRefNum() >= xref->getNumObjects())) { return 0; } - if (pagesObj->dictLookup("Kids", &kids)->isArray()) { - n = 0; - for (i = 0; i < kids.arrayGetLength(); ++i) { - kids.arrayGet(i, &kid); - n2 = countPageTree(&kid); - if (n2 < INT_MAX - n) { - n += n2; - } else { - error(errSyntaxError, -1, "Page tree contains too many pages"); - n = INT_MAX; - } - kid.free(); + + // check for a page tree loop; fetch the node object + Object pagesNode; + if (pagesNodeRef->isRef()) { + if (touchedObjs[pagesNodeRef->getRefNum()]) { + error(errSyntaxError, -1, "Loop in Pages tree"); + return 0; } + touchedObjs[pagesNodeRef->getRefNum()] = 1; + xref->fetch(pagesNodeRef->getRefNum(), pagesNodeRef->getRefGen(), + &pagesNode); } else { - n = 1; + pagesNodeRef->copy(&pagesNode); + } + + // count the subtree + int n = 0; + if (pagesNode.isDict()) { + Object kids; + if (pagesNode.dictLookup("Kids", &kids)->isArray()) { + for (int i = 0; i < kids.arrayGetLength(); ++i) { + Object kid; + kids.arrayGetNF(i, &kid); + int n2 = countPageTree(&kid, touchedObjs); + if (n2 < INT_MAX - n) { + n += n2; + } else { + error(errSyntaxError, -1, "Page tree contains too many pages"); + n = INT_MAX; + } + kid.free(); + } + } else { + n = 1; + } + kids.free(); } - kids.free(); + + pagesNode.free(); + return n; } @@ -738,37 +760,55 @@ void Catalog::readEmbeddedFileList(Dict *catDict) { Object obj1, obj2; char *touchedObjs; + touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); + // read the embedded file name tree if (catDict->lookup("Names", &obj1)->isDict()) { - if (obj1.dictLookup("EmbeddedFiles", &obj2)->isDict()) { - readEmbeddedFileTree(&obj2); - } + obj1.dictLookupNF("EmbeddedFiles", &obj2); + readEmbeddedFileTree(&obj2, touchedObjs); obj2.free(); } obj1.free(); // look for file attachment annotations - touchedObjs = (char *)gmalloc(xref->getNumObjects()); - memset(touchedObjs, 0, xref->getNumObjects()); readFileAttachmentAnnots(catDict->lookupNF("Pages", &obj1), touchedObjs); obj1.free(); + gfree(touchedObjs); } -void Catalog::readEmbeddedFileTree(Object *node) { - Object kidsObj, kidObj; +void Catalog::readEmbeddedFileTree(Object *nodeRef, char *touchedObjs) { + Object node, kidsObj, kidObj; Object namesObj, nameObj, fileSpecObj; int i; - if (node->dictLookup("Kids", &kidsObj)->isArray()) { + // check for an object loop + if (nodeRef->isRef()) { + if (nodeRef->getRefNum() < 0 || + nodeRef->getRefNum() >= xref->getNumObjects() || + touchedObjs[nodeRef->getRefNum()]) { + return; + } + touchedObjs[nodeRef->getRefNum()] = 1; + xref->fetch(nodeRef->getRefNum(), nodeRef->getRefGen(), &node); + } else { + nodeRef->copy(&node); + } + + if (!node.isDict()) { + node.free(); + return; + } + + if (node.dictLookup("Kids", &kidsObj)->isArray()) { for (i = 0; i < kidsObj.arrayGetLength(); ++i) { - if (kidsObj.arrayGet(i, &kidObj)->isDict()) { - readEmbeddedFileTree(&kidObj); - } + kidsObj.arrayGetNF(i, &kidObj); + readEmbeddedFileTree(&kidObj, touchedObjs); kidObj.free(); } } else { - if (node->dictLookup("Names", &namesObj)->isArray()) { + if (node.dictLookup("Names", &namesObj)->isArray()) { for (i = 0; i+1 < namesObj.arrayGetLength(); ++i) { namesObj.arrayGet(i, &nameObj); namesObj.arrayGet(i+1, &fileSpecObj); @@ -780,6 +820,8 @@ void Catalog::readEmbeddedFileTree(Object *node) { namesObj.free(); } kidsObj.free(); + + node.free(); } void Catalog::readFileAttachmentAnnots(Object *pageNodeRef, @@ -788,8 +830,9 @@ void Catalog::readFileAttachmentAnnots(Object *pageNodeRef, int i; // check for an invalid object reference (e.g., in a damaged PDF file) - if (pageNodeRef->getRefNum() < 0 || - pageNodeRef->getRefNum() >= xref->getNumObjects()) { + if (pageNodeRef->isRef() && + (pageNodeRef->getRefNum() < 0 || + pageNodeRef->getRefNum() >= xref->getNumObjects())) { return; } @@ -901,10 +944,14 @@ Object *Catalog::getEmbeddedFileStreamObj(int idx, Object *strObj) { void Catalog::readPageLabelTree(Object *root) { PageLabelNode *label0, *label1; + char *touchedObjs; int i; + touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); pageLabels = new GList(); - readPageLabelTree2(root); + readPageLabelTree2(root, touchedObjs); + gfree(touchedObjs); if (pageLabels->getLength() == 0) { deleteGList(pageLabels, PageLabelNode); @@ -922,15 +969,29 @@ void Catalog::readPageLabelTree(Object *root) { label0->lastPage = numPages; } -void Catalog::readPageLabelTree2(Object *node) { - Object nums, num, labelObj, kids, kid; +void Catalog::readPageLabelTree2(Object *nodeRef, char *touchedObjs) { + Object node, nums, num, labelObj, kids, kid; int i; - if (!node->isDict()) { + // check for an object loop + if (nodeRef->isRef()) { + if (nodeRef->getRefNum() < 0 || + nodeRef->getRefNum() >= xref->getNumObjects() || + touchedObjs[nodeRef->getRefNum()]) { + return; + } + touchedObjs[nodeRef->getRefNum()] = 1; + xref->fetch(nodeRef->getRefNum(), nodeRef->getRefGen(), &node); + } else { + nodeRef->copy(&node); + } + + if (!node.isDict()) { + node.free(); return; } - if (node->dictLookup("Nums", &nums)->isArray()) { + if (node.dictLookup("Nums", &nums)->isArray()) { for (i = 0; i < nums.arrayGetLength() - 1; i += 2) { if (nums.arrayGet(i, &num)->isInt()) { if (nums.arrayGet(i+1, &labelObj)->isDict()) { @@ -944,14 +1005,16 @@ void Catalog::readPageLabelTree2(Object *node) { } nums.free(); - if (node->dictLookup("Kids", &kids)->isArray()) { + if (node.dictLookup("Kids", &kids)->isArray()) { for (i = 0; i < kids.arrayGetLength(); ++i) { - kids.arrayGet(i, &kid); - readPageLabelTree2(&kid); + kids.arrayGetNF(i, &kid); + readPageLabelTree2(&kid, touchedObjs); kid.free(); } } kids.free(); + + node.free(); } TextString *Catalog::getPageLabel(int pageNum) { @@ -1195,3 +1258,130 @@ GBool Catalog::convertPageLabelToInt(TextString *pageLabel, int prefixLength, } return gFalse; } + +GBool Catalog::usesJavaScript() { + Object catDict; + if (!xref->getCatalog(&catDict)->isDict()) { + catDict.free(); + return gFalse; + } + + GBool usesJS = gFalse; + + // check for Catalog.Names.JavaScript + Object namesObj; + if (catDict.dictLookup("Names", &namesObj)->isDict()) { + Object jsNamesObj; + namesObj.dictLookup("JavaScript", &jsNamesObj); + if (jsNamesObj.isDict()) { + usesJS = gTrue; + } + jsNamesObj.free(); + } + namesObj.free(); + + // look for JavaScript actionas in Page.AA + if (!usesJS) { + char *touchedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(touchedObjs, 0, xref->getNumObjects()); + Object pagesObj; + usesJS = scanPageTreeForJavaScript(catDict.dictLookupNF("Pages", &pagesObj), + touchedObjs); + pagesObj.free(); + gfree(touchedObjs); + } + + catDict.free(); + + return usesJS; +} + +GBool Catalog::scanPageTreeForJavaScript(Object *pageNodeRef, + char *touchedObjs) { + // check for an invalid object reference (e.g., in a damaged PDF file) + if (pageNodeRef->isRef() && + (pageNodeRef->getRefNum() < 0 || + pageNodeRef->getRefNum() >= xref->getNumObjects())) { + return gFalse; + } + + // check for a page tree loop + Object pageNode; + if (pageNodeRef->isRef()) { + if (touchedObjs[pageNodeRef->getRefNum()]) { + return gFalse; + } + touchedObjs[pageNodeRef->getRefNum()] = 1; + xref->fetch(pageNodeRef->getRefNum(), pageNodeRef->getRefGen(), &pageNode); + } else { + pageNodeRef->copy(&pageNode); + } + + // scan the page tree node + GBool usesJS = gFalse; + if (pageNode.isDict()) { + Object kids; + if (pageNode.dictLookup("Kids", &kids)->isArray()) { + for (int i = 0; i < kids.arrayGetLength() && !usesJS; ++i) { + Object kid; + if (scanPageTreeForJavaScript(kids.arrayGetNF(i, &kid), touchedObjs)) { + usesJS = gTrue; + } + kid.free(); + } + } else { + + // scan Page.AA + Object pageAA; + if (pageNode.dictLookup("AA", &pageAA)->isDict()) { + if (scanAAForJavaScript(&pageAA)) { + usesJS = gTrue; + } + } + pageAA.free(); + + // scanPage.Annots + if (!usesJS) { + Object annots; + if (pageNode.dictLookup("Annots", &annots)->isArray()) { + for (int i = 0; i < annots.arrayGetLength() && !usesJS; ++i) { + Object annot; + if (annots.arrayGet(i, &annot)->isDict()) { + Object annotAA; + if (annot.dictLookup("AA", &annotAA)->isDict()) { + if (scanAAForJavaScript(&annotAA)) { + usesJS = gTrue; + } + } + annotAA.free(); + } + annot.free(); + } + } + annots.free(); + } + } + kids.free(); + } + + pageNode.free(); + + return usesJS; +} + +GBool Catalog::scanAAForJavaScript(Object *aaObj) { + GBool usesJS = gFalse; + for (int i = 0; i < aaObj->dictGetLength() && !usesJS; ++i) { + Object action; + if (aaObj->dictGetVal(i, &action)->isDict()) { + Object js; + if (!action.dictLookupNF("JS", &js)->isNull()) { + usesJS = gTrue; + } + js.free(); + } + action.free(); + } + return usesJS; +} + diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h index 0acdd2d1574..91597e54137 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #if MULTITHREADED #include "GMutex.h" #endif @@ -118,6 +114,9 @@ public: Object *getViewerPreferences() { return &viewerPrefs; } + // Return true if the document uses JavaScript. + GBool usesJavaScript(); + private: PDFDoc *doc; @@ -146,21 +145,23 @@ private: Object *findDestInTree(Object *tree, GString *name, Object *obj); GBool readPageTree(Object *catDict); - int countPageTree(Object *pagesObj); + int countPageTree(Object *pagesNodeRef, char *touchedObjs); void loadPage(int pg); void loadPage2(int pg, int relPg, PageTreeNode *node); void readEmbeddedFileList(Dict *catDict); - void readEmbeddedFileTree(Object *node); + void readEmbeddedFileTree(Object *nodeRef, char *touchedObjs); void readFileAttachmentAnnots(Object *pageNodeRef, char *touchedObjs); void readEmbeddedFile(Object *fileSpec, Object *name1); void readPageLabelTree(Object *root); - void readPageLabelTree2(Object *node); + void readPageLabelTree2(Object *node, char *touchedObjs); PageLabelNode *findPageLabel(int pageNum); GString *makeRomanNumeral(int num, GBool uppercase); GString *makeLetterLabel(int num, GBool uppercase); GBool convertPageLabelToInt(TextString *pageLabel, int prefixLength, char style, int *n); + GBool scanPageTreeForJavaScript(Object *pageNodeRef, char *touchedObjs); + GBool scanAAForJavaScript(Object *aaObj); }; #endif diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc index 0a2100fde9b..83720069e64 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <string.h> #include "gmem.h" @@ -274,7 +270,18 @@ GBool CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, pst = new PSTokenizer(getCharFunc, data); pst->getToken(tok1, sizeof(tok1), &n1); while (pst->getToken(tok2, sizeof(tok2), &n2)) { - if (!strcmp(tok2, "usecmap")) { + if (!strcmp(tok1, "begincodespacerange")) { + if (globalParams->getIgnoreWrongSizeToUnicode() && + tok2[0] == '<' && tok2[n2 - 1] == '>' && + n2 - 2 != nBits / 4) { + error(errSyntaxWarning, -1, + "Incorrect character size in ToUnicode CMap"); + ok = gFalse; + break; + } + while (pst->getToken(tok1, sizeof(tok1), &n1) && + strcmp(tok1, "endcodespacerange")) ; + } else if (!strcmp(tok2, "usecmap")) { if (tok1[0] == '/') { name = new GString(tok1 + 1); if ((f = globalParams->findToUnicodeFile(name))) { @@ -465,6 +472,7 @@ GBool CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, pst->getToken(tok1, sizeof(tok1), &n1); } else { strcpy(tok1, tok2); + n1 = n2; } } delete pst; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h b/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h index be9025107aa..7bbc97f834e 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/CharCodeToUnicode.h @@ -13,10 +13,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "CharTypes.h" #if MULTITHREADED diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Decrypt.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Decrypt.cc index d4f8d4ec336..d36626dc344 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Decrypt.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Decrypt.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <string.h> #include "gmem.h" #include "gmempp.h" @@ -1492,14 +1488,14 @@ static void sha512(Guchar *msg, int msgLen, Guchar *hash) { SHA512Uint64 H[8]; int blkLen, i; - H[0] = 0x6a09e667f3bcc908LL; - H[1] = 0xbb67ae8584caa73bLL; - H[2] = 0x3c6ef372fe94f82bLL; - H[3] = 0xa54ff53a5f1d36f1LL; - H[4] = 0x510e527fade682d1LL; - H[5] = 0x9b05688c2b3e6c1fLL; - H[6] = 0x1f83d9abfb41bd6bLL; - H[7] = 0x5be0cd19137e2179LL; + H[0] = 0x6a09e667f3bcc908ULL; + H[1] = 0xbb67ae8584caa73bULL; + H[2] = 0x3c6ef372fe94f82bULL; + H[3] = 0xa54ff53a5f1d36f1ULL; + H[4] = 0x510e527fade682d1ULL; + H[5] = 0x9b05688c2b3e6c1fULL; + H[6] = 0x1f83d9abfb41bd6bULL; + H[7] = 0x5be0cd19137e2179ULL; blkLen = 0; for (i = 0; i + 128 <= msgLen; i += 128) { @@ -1558,14 +1554,14 @@ static void sha384(Guchar *msg, int msgLen, Guchar *hash) { SHA512Uint64 H[8]; int blkLen, i; - H[0] = 0xcbbb9d5dc1059ed8LL; - H[1] = 0x629a292a367cd507LL; - H[2] = 0x9159015a3070dd17LL; - H[3] = 0x152fecd8f70e5939LL; - H[4] = 0x67332667ffc00b31LL; - H[5] = 0x8eb44a8768581511LL; - H[6] = 0xdb0c2e0d64f98fa7LL; - H[7] = 0x47b5481dbefa4fa4LL; + H[0] = 0xcbbb9d5dc1059ed8ULL; + H[1] = 0x629a292a367cd507ULL; + H[2] = 0x9159015a3070dd17ULL; + H[3] = 0x152fecd8f70e5939ULL; + H[4] = 0x67332667ffc00b31ULL; + H[5] = 0x8eb44a8768581511ULL; + H[6] = 0xdb0c2e0d64f98fa7ULL; + H[7] = 0x47b5481dbefa4fa4ULL; blkLen = 0; for (i = 0; i + 128 <= msgLen; i += 128) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Decrypt.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Decrypt.h index 2b10abd050b..d0f38409109 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Decrypt.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Decrypt.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "GString.h" #include "Object.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Dict.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Dict.cc index c8c29736fe9..71ea377f8a7 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Dict.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Dict.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stddef.h> #include <string.h> #include "gmem.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Dict.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Dict.h index b05f729e0a8..804fcdf1312 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Dict.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Dict.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #if MULTITHREADED #include "GMutex.h" #endif diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/DisplayState.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/DisplayState.cc index e0d306857ca..f1e8dcffeac 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/DisplayState.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/DisplayState.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include "gmempp.h" #include "GString.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/DisplayState.h b/Build/source/libs/xpdf/xpdf-src/xpdf/DisplayState.h index 12c8170f0b3..a078c757d33 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/DisplayState.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/DisplayState.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "SplashTypes.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Error.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Error.cc index aec27dc5099..111f277d3c2 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Error.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Error.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stddef.h> #include <stdarg.h> diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Error.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Error.h index 39e7613e4e6..574330f6446 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Error.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Error.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stdio.h> #include "config.h" #include "gfile.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc index 82f32b9dd93..966a3155c50 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Function.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <string.h> #include <ctype.h> diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Function.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Function.h index bf1f25e51cc..73c92abe30c 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Function.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Function.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "Object.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc index 1539b8404bc..ea7951a75fc 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <stdio.h> #include <stddef.h> @@ -536,6 +532,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, out = outA; state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); fontChanged = gFalse; + haveSavedClipPath = gFalse; clip = clipNone; ignoreUndef = 0; out->startPage(pageNum, state); @@ -584,6 +581,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, out = outA; state = new GfxState(72, 72, box, 0, gFalse); fontChanged = gFalse; + haveSavedClipPath = gFalse; clip = clipNone; ignoreUndef = 0; for (i = 0; i < 6; ++i) { @@ -1829,15 +1827,20 @@ void Gfx::opFillStroke(Object args[], int numArgs) { } if (state->isPath()) { if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gFalse); } } } @@ -1852,15 +1855,20 @@ void Gfx::opCloseFillStroke(Object args[], int numArgs) { if (state->isPath()) { state->closePath(); if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gFalse); } } } @@ -1874,15 +1882,20 @@ void Gfx::opEOFillStroke(Object args[], int numArgs) { } if (state->isPath()) { if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gTrue); } } } @@ -1897,15 +1910,20 @@ void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { if (state->isPath()) { state->closePath(); if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gTrue); } } } @@ -1966,7 +1984,7 @@ void Gfx::doPatternStroke() { } } -void Gfx::doPatternText() { +void Gfx::doPatternText(GBool stroke) { GfxPattern *pattern; // this is a bit of a kludge -- patterns can be really slow, so we @@ -1976,7 +1994,8 @@ void Gfx::doPatternText() { return; } - if (!(pattern = state->getFillPattern())) { + pattern = stroke ? state->getStrokePattern() : state->getFillPattern(); + if (!pattern) { return; } switch (pattern->getType()) { @@ -2193,16 +2212,30 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, if (bbox[1] > bbox[3]) { t = bbox[1]; bbox[1] = bbox[3]; bbox[3] = t; } - xstep = fabs(tPat->getXStep()); - ystep = fabs(tPat->getYStep()); - xi0 = (int)ceil((xMin - bbox[2]) / xstep); - xi1 = (int)floor((xMax - bbox[0]) / xstep) + 1; - yi0 = (int)ceil((yMin - bbox[3]) / ystep); - yi1 = (int)floor((yMax - bbox[1]) / ystep) + 1; + xstep = tPat->getXStep(); + ystep = tPat->getYStep(); + if (xstep == 0 || ystep == 0) { + error(errSyntaxError, getPos(), "Zero x or y step in tiling pattern fill"); + goto err; + } + if (xstep > 0) { + xi0 = (int)ceil((xMin - bbox[2]) / xstep); + xi1 = (int)floor((xMax - bbox[0]) / xstep) + 1; + } else { + xi0 = (int)ceil((xMax - bbox[0]) / xstep); + xi1 = (int)floor((xMin - bbox[2]) / xstep) + 1; + } + if (ystep > 0) { + yi0 = (int)ceil((yMin - bbox[3]) / ystep); + yi1 = (int)floor((yMax - bbox[1]) / ystep) + 1; + } else { + yi0 = (int)ceil((yMax - bbox[1]) / ystep); + yi1 = (int)floor((yMin - bbox[3]) / ystep) + 1; + } for (i = 0; i < 4; ++i) { m1[i] = m[i]; } - if (out->useTilingPatternFill()) { + if (out->useTilingPatternFill() && !tPat->usesBlendMode(xref)) { m1[4] = m[4]; m1[5] = m[5]; out->tilingPatternFill(state, this, tPat->getContentStreamRef(), @@ -3521,12 +3554,16 @@ void Gfx::fillPatch(GfxPatch *patch, GfxPatchMeshShading *shading, int depth) { } void Gfx::doEndPath() { - if (state->isCurPt() && clip != clipNone) { - state->clip(); - if (clip == clipNormal) { - out->clip(state); + if (clip != clipNone) { + if (state->isCurPt()) { + state->clip(); + if (clip == clipNormal) { + out->clip(state); + } else { + out->eoClip(state); + } } else { - out->eoClip(state); + error(errSyntaxError, getPos(), "Empty path in clip"); } } clip = clipNone; @@ -3555,9 +3592,15 @@ void Gfx::opBeginText(Object args[], int numArgs) { out->updateTextMat(state); out->updateTextPos(state); fontChanged = gTrue; + haveSavedClipPath = gFalse; } void Gfx::opEndText(Object args[], int numArgs) { + if (haveSavedClipPath) { + out->clipToSavedClipPath(state); + haveSavedClipPath = gFalse; + } + out->endTextObject(state); } @@ -3786,27 +3829,8 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) { } void Gfx::doShowText(GString *s) { - GfxFont *font; - int wMode; - double riseX, riseY; - CharCode code; - Unicode u[8]; - double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, ddx, ddy; - double originX, originY, tOriginX, tOriginY; - double x0, y0, x1, y1; - double oldCTM[6], newCTM[6]; - double *mat; - Object charProcRef, charProc; - Dict *resDict; - Parser *oldParser; - GfxState *savedState; - char *p; - int render; - GBool patternFill; - int len, n, uLen, nChars, nSpaces, i; - - font = state->getFont(); - wMode = font->getWMode(); + GfxFont *font = state->getFont(); + int wMode = font->getWMode(); if (globalParams->isDroppedFont(font->getName() ? font->getName()->getCString() : "")) { @@ -3818,35 +3842,63 @@ void Gfx::doShowText(GString *s) { out->beginString(state, s); } - // if we're doing a pattern fill, set up clipping - render = state->getRender(); - if (!(render & 1) && - state->getFillColorSpace()->getMode() == csPattern) { - patternFill = gTrue; - saveState(); - // disable fill, enable clipping, leave stroke unchanged - if ((render ^ (render >> 1)) & 1) { - render = 5; + // figure out the drawing mode + // note: clipping, pattern fill, and pattern stroke are all handled + // by saving the path and then performing the appropriate + // actions in opEndText() + GBool doFill = gFalse; + GBool doStroke = gFalse; + GBool doMakePath = gFalse; + int render = state->getRender() & 7; + switch (render & 7) { + case 0: // fill + if (state->getFillColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; } else { - render = 7; + doFill = gTrue; } - state->setRender(render); - out->updateRender(state); - } else { - patternFill = gFalse; + break; + case 1: // stroke + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; + } else { + doStroke = gTrue; + } + break; + case 2: // fill + stroke + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; + } else { + doFill = gTrue; + doStroke = gTrue; + } + break; + case 3: // invisible + // nothing + break; + case 4: // fill + clip + case 5: // stroke + clip + case 6: // fill + stroke + clip + case 7: // clip + doMakePath = gTrue; + break; } + double riseX, riseY; state->textTransformDelta(0, state->getRise(), &riseX, &riseY); - x0 = state->getCurX() + riseX; - y0 = state->getCurY() + riseY; + double xMin = state->getCurX() + riseX; + double yMin = state->getCurY() + riseY; // handle a Type 3 char if (font->getType() == fontType3 && out->interpretType3Chars()) { - mat = state->getCTM(); - for (i = 0; i < 6; ++i) { + double *mat = state->getCTM(); + double oldCTM[6]; + for (int i = 0; i < 6; ++i) { oldCTM[i] = mat[i]; } mat = state->getTextMat(); + double newCTM[6]; newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2]; newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3]; newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2]; @@ -3862,24 +3914,29 @@ void Gfx::doShowText(GString *s) { newCTM[3] *= state->getFontSize(); newCTM[0] *= state->getHorizScaling(); newCTM[1] *= state->getHorizScaling(); - curX = state->getCurX(); - curY = state->getCurY(); - oldParser = parser; - p = s->getCString(); - len = s->getLength(); + double curX = state->getCurX(); + double curY = state->getCurY(); + Parser *oldParser = parser; + char *p = s->getCString(); + int len = s->getLength(); while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx, dy, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); dx = dx * state->getFontSize() + state->getCharSpace(); if (n == 1 && *p == ' ') { dx += state->getWordSpace(); } dx *= state->getHorizScaling(); dy *= state->getFontSize(); + double tdx, tdy, ddx, ddy, x, y; state->textTransformDelta(dx, dy, &tdx, &tdy); state->transform(curX + riseX, curY + riseY, &x, &y); - savedState = saveStateStack(); + GfxState *savedState = saveStateStack(); state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); //~ the CTM concat values here are wrong (but never used) out->updateCTM(state, 1, 0, 0, 1, 0, 0); @@ -3899,9 +3956,11 @@ void Gfx::doShowText(GString *s) { #endif if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy, code, u, uLen)) { + Object charProcRef, charProc; ((Gfx8BitFont *)font)->getCharProcNF(code, &charProcRef); charProcRef.fetch(xref, &charProc); - if ((resDict = ((Gfx8BitFont *)font)->getResources())) { + Dict *resDict = ((Gfx8BitFont *)font)->getResources(); + if (resDict) { pushResources(resDict); } if (charProc.isStream()) { @@ -3927,12 +3986,16 @@ void Gfx::doShowText(GString *s) { parser = oldParser; } else if (out->useDrawChar()) { - p = s->getCString(); - len = s->getLength(); + char *p = s->getCString(); + int len = s->getLength(); while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx, dy, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); if (wMode) { dx *= state->getFontSize(); dy = dy * state->getFontSize() + state->getCharSpace(); @@ -3947,26 +4010,32 @@ void Gfx::doShowText(GString *s) { dx *= state->getHorizScaling(); dy *= state->getFontSize(); } + double tdx, tdy, tOriginX, tOriginY; state->textTransformDelta(dx, dy, &tdx, &tdy); originX *= state->getFontSize(); originY *= state->getFontSize(); state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY, - tdx, tdy, tOriginX, tOriginY, code, n, u, uLen); + tdx, tdy, tOriginX, tOriginY, code, n, u, uLen, + doFill, doStroke, doMakePath); state->shift(tdx, tdy); p += n; len -= n; } } else { - dx = dy = 0; - p = s->getCString(); - len = s->getLength(); - nChars = nSpaces = 0; + double dx = 0, dy = 0; + char *p = s->getCString(); + int len = s->getLength(); + int nChars = 0, nSpaces = 0; while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx2, &dy2, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx2, dy2, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx2, &dy2, &originX, &originY); dx += dx2; dy += dy2; if (n == 1 && *p == ' ') { @@ -3988,8 +4057,9 @@ void Gfx::doShowText(GString *s) { dx *= state->getHorizScaling(); dy *= state->getFontSize(); } + double tdx, tdy; state->textTransformDelta(dx, dy, &tdx, &tdy); - out->drawString(state, s); + out->drawString(state, s, doFill, doStroke, doMakePath); state->shift(tdx, tdy); } @@ -3997,40 +4067,70 @@ void Gfx::doShowText(GString *s) { out->endString(state); } - if (patternFill) { - out->saveTextPos(state); - // tell the OutputDev to do the clipping - out->endTextObject(state); - // set up a clipping bbox so doPatternText will work -- assume + if (doMakePath) { + // compute the clipping bbox for the saved text path -- assume // that the text bounding box does not extend past the baseline in // any direction by more than twice the font size - x1 = state->getCurX() + riseX; - y1 = state->getCurY() + riseY; - if (x0 > x1) { - x = x0; x0 = x1; x1 = x; + double xMax = state->getCurX() + riseX; + double yMax = state->getCurY() + riseY; + double t; + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; } - if (y0 > y1) { - y = y0; y0 = y1; y1 = y; + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; } - state->textTransformDelta(0, state->getFontSize(), &dx, &dy); + double dx1, dy1, dx2, dy2; + state->textTransformDelta(0, state->getFontSize(), &dx1, &dy1); state->textTransformDelta(state->getFontSize(), 0, &dx2, &dy2); - dx = fabs(dx); + dx1 = fabs(dx1); dx2 = fabs(dx2); - if (dx2 > dx) { - dx = dx2; + if (dx2 > dx1) { + dx1 = dx2; } - dy = fabs(dy); + dy1 = fabs(dy1); dy2 = fabs(dy2); - if (dy2 > dy) { - dy = dy2; - } - state->clipToRect(x0 - 2 * dx, y0 - 2 * dy, x1 + 2 * dx, y1 + 2 * dy); - // set render mode to fill-only - state->setRender(0); - out->updateRender(state); - doPatternText(); - restoreState(); - out->restoreTextPos(state); + if (dy2 > dy1) { + dy1 = dy2; + } + xMin -= 2 * dx1; + yMin -= 2 * dy1; + xMax += 2 * dx1; + yMax += 2 * dy1; + + //--- fill + if ((render & 3) == 0 || (render & 3) == 2) { + if (state->getFillColorSpace()->getMode() == csPattern) { + saveState(); + state->clipToRect(xMin, yMin, xMax, yMax); + out->clipToTextPath(state); + doPatternText(gFalse); + restoreState(); + } else { + out->fillTextPath(state); + } + } + + //--- stroke + if ((render & 3) == 1 || (render & 3) == 2) { + if (state->getStrokeColorSpace()->getMode() == csPattern) { + saveState(); + state->clipToRect(xMin, yMin, xMax, yMax); + out->clipToTextStrokePath(state); + doPatternText(gTrue); + restoreState(); + } else { + out->strokeTextPath(state); + } + } + + //--- clip + if (render & 4) { + out->addTextPathToSavedClipPath(state); + haveSavedClipPath = gTrue; + } else { + out->clearTextPath(state); + } } opCounter += 10 * s->getLength(); @@ -4116,6 +4216,7 @@ void Gfx::opXObject(Object args[], int numArgs) { xObj.streamGetDict()->lookup("Level1", &obj3); out->psXObject(xObj.getStream(), obj3.isStream() ? obj3.getStream() : (Stream *)NULL); + obj3.free(); } } else if (obj2.isName()) { error(errSyntaxError, getPos(), @@ -4191,10 +4292,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("W", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + width = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image width"); + width = (int)obj1.getReal(); + } else { goto err2; } - width = obj1.getInt(); obj1.free(); if (width <= 0) { goto err1; @@ -4204,10 +4309,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("H", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + height = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image height"); + height = (int)obj1.getReal(); + } else { goto err2; } - height = obj1.getInt(); obj1.free(); if (height <= 0) { goto err1; @@ -4233,8 +4342,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("BPC", &obj1); } - if (obj1.isInt()) { - bits = obj1.getInt(); + if (obj1.isNum()) { + if (obj1.isInt()) { + bits = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), + "Non-integer image bits per component"); + bits = (int)obj1.getReal(); + } if (bits < 1 || bits > 16) { goto err2; } @@ -4377,26 +4492,34 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("W", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskWidth = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask width"); + maskWidth = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskWidth = obj1.getInt(); obj1.free(); maskDict->lookup("Height", &obj1); if (obj1.isNull()) { obj1.free(); maskDict->lookup("H", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskHeight = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask height"); + maskHeight = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskHeight = obj1.getInt(); obj1.free(); if (maskWidth <= 0 || maskHeight <= 0) { delete colorMap; @@ -4409,13 +4532,18 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("BPC", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskBits = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), + "Non-integer image mask bits per component"); + maskBits = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskBits = obj1.getInt(); obj1.free(); if (maskBits < 1 || maskBits > 16) { delete colorMap; @@ -4512,6 +4640,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } } else if (maskObj.isStream()) { // explicit mask + haveExplicitMask = gTrue; if (inlineImg) { delete colorMap; maskObj.free(); @@ -4526,32 +4655,31 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("W", &obj1); } - if (!obj1.isInt()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + if (obj1.isInt()) { + maskWidth = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask width"); + maskWidth = (int)obj1.getReal(); + } else { + haveExplicitMask = gFalse; } - maskWidth = obj1.getInt(); obj1.free(); maskDict->lookup("Height", &obj1); if (obj1.isNull()) { obj1.free(); maskDict->lookup("H", &obj1); } - if (!obj1.isInt()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + if (obj1.isInt()) { + maskHeight = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask height"); + maskHeight = (int)obj1.getReal(); + } else { + haveExplicitMask = gFalse; } - maskHeight = obj1.getInt(); obj1.free(); if (maskWidth <= 0 || maskHeight <= 0) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } maskDict->lookup("ImageMask", &obj1); if (obj1.isNull()) { @@ -4559,10 +4687,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskDict->lookup("IM", &obj1); } if (!obj1.isBool() || !obj1.getBool()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } obj1.free(); maskInvert = gFalse; @@ -4576,13 +4701,12 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskInvert = obj2.isNum() && obj2.getNum() == 1; obj2.free(); } else if (!obj1.isNull()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } obj1.free(); - haveExplicitMask = gTrue; + if (!haveExplicitMask) { + error(errSyntaxError, getPos(), "Bad image parameters"); + } } // if drawing is disabled, skip over inline image data @@ -4768,6 +4892,8 @@ void Gfx::drawForm(Object *strRef, Dict *resDict, double oldBaseMatrix[6]; int i; + out->startStream(strRef->getRef(), state); + // push new resources on stack pushResources(resDict); @@ -4897,7 +5023,7 @@ void Gfx::drawForm(Object *strRef, Dict *resDict, delete blendingColorSpace; } - return; + out->endStream(strRef->getRef()); } void Gfx::takeContentStreamStack(Gfx *oldGfx) { @@ -4936,7 +5062,9 @@ void Gfx::opBeginImage(Object args[], int numArgs) { // if we have the stream length, skip to end-of-stream and then // skip 'EI' in the original stream } else if (haveLength) { - while ((c1 = str->getChar()) != EOF) ; + // NB: getUndecodedStream() returns the EmbedStream created by + // buildImageStream() + while ((c1 = str->getUndecodedStream()->getChar()) != EOF) ; delete str; str = parser->getStream(); c1 = str->getChar(); @@ -5091,15 +5219,28 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) { } obj.free(); mcKind = gfxMCOptionalContent; - } else if (args[0].isName("Span") && numArgs == 2 && args[1].isDict()) { - if (args[1].dictLookup("ActualText", &obj)->isString()) { - s = new TextString(obj.getString()); - out->beginActualText(state, s->getUnicode(), s->getLength()); - delete s; - mcKind = gfxMCActualText; + } else if (numArgs == 2 && args[1].isDict()) { + if (args[0].isName("Span")) { + if (args[1].dictLookup("ActualText", &obj)->isString()) { + s = new TextString(obj.getString()); + out->beginActualText(state, s->getUnicode(), s->getLength()); + delete s; + mcKind = gfxMCActualText; + } + obj.free(); + } + if (args[1].dictLookup("MCID", &obj)->isInt()) { + out->beginStructureItem(args[0].getName(), obj.getInt(), + args[1].getDict()); + if (mcKind == gfxMCActualText) { + mcKind = gfxMCStructureItemAndActualText; + } else { + mcKind = gfxMCStructureItem; + } } obj.free(); } + mc = new GfxMarkedContent(mcKind, ocState); markedContentStack->append(mc); } @@ -5123,6 +5264,11 @@ void Gfx::opEndMarkedContent(Object args[], int numArgs) { } } else if (mcKind == gfxMCActualText) { out->endActualText(state); + } else if (mcKind == gfxMCStructureItem) { + out->endStructureItem(); + } else if (mcKind == gfxMCStructureItemAndActualText) { + out->endStructureItem(); + out->endActualText(state); } } else { error(errSyntaxWarning, getPos(), "Mismatched EMC operator"); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h index 14d7a608438..0f288cf3b9d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "gfile.h" #include "GfxState.h" @@ -106,6 +102,8 @@ private: enum GfxMarkedContentKind { gfxMCOptionalContent, gfxMCActualText, + gfxMCStructureItem, + gfxMCStructureItemAndActualText, gfxMCOther }; @@ -194,6 +192,7 @@ private: GfxState *state; // current graphics state GBool fontChanged; // set if font or text matrix has changed + GBool haveSavedClipPath; GfxClipType clip; // do a clip? int ignoreUndef; // current BX/EX nesting level double baseMatrix[6]; // default matrix for most recent @@ -273,7 +272,7 @@ private: void opCloseEOFillStroke(Object args[], int numArgs); void doPatternFill(GBool eoFill); void doPatternStroke(); - void doPatternText(); + void doPatternText(GBool stroke); void doPatternImageMask(Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg, GBool interpolate); void doTilingPatternFill(GfxTilingPattern *tPat, diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc index 30e8bd1c79c..c3db4e8651b 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -307,26 +303,10 @@ GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) { obj2.initNull(); } + // NB: the PDF spec doesn't say anything about precedence, but Adobe + // uses FontFile3 over FontFile2 if both are present. if (fontDict2->lookup("FontDescriptor", &fontDesc)->isDict()) { - if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) { - *embID = obj3.getRef(); - if (expectedType != fontType1) { - err = gTrue; - } - } - obj3.free(); - if (embID->num == -1 && - fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) { - *embID = obj3.getRef(); - if (isType0) { - expectedType = fontCIDType2; - } else if (expectedType != fontTrueType) { - err = gTrue; - } - } - obj3.free(); - if (embID->num == -1 && - fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) { + if (fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) { *embID = obj3.getRef(); if (obj3.fetch(xref, &obj4)->isStream()) { obj4.streamGetDict()->lookup("Subtype", &subtype); @@ -375,6 +355,26 @@ GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) { obj4.free(); } obj3.free(); + if (embID->num == -1) { + if (fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) { + *embID = obj3.getRef(); + if (isType0) { + expectedType = fontCIDType2; + } else if (expectedType != fontTrueType) { + err = gTrue; + } + } + obj3.free(); + } + if (embID->num == -1) { + if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) { + *embID = obj3.getRef(); + if (expectedType != fontType1) { + err = gTrue; + } + } + obj3.free(); + } } fontDesc.free(); @@ -533,6 +533,33 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { } obj1.free(); + + // scan font name for bold/italic tags and update the flags + if (name) { + i = name->getLength(); + if (i > 2 && !strncmp(name->getCString() + i - 2, "MT", 2)) { + i -= 2; + } + if (i > 6 && !strncmp(name->getCString() + i - 6, "Italic", 6)) { + flags |= fontItalic; + i -= 6; + } else if (i > 2 && !strncmp(name->getCString() + i - 2, "It", 2)) { + flags |= fontItalic; + i -= 2; + } else if (i > 7 && !strncmp(name->getCString() + i - 7, "Oblique", 7)) { + flags |= fontItalic; + i -= 7; + } + char c = name->getChar(i-1); + if (!((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9'))) { + --i; + } + if (i > 4 && !strncmp(name->getCString() + i - 4, "Bold", 4)) { + flags |= fontBold; + } + } } CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, @@ -1436,7 +1463,7 @@ CharCodeToUnicode *Gfx8BitFont::getToUnicode() { int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { int *map; int cmapPlatform, cmapEncoding; - int unicodeCmap, macRomanCmap, msSymbolCmap, cmap; + int unicodeCmap, macRomanCmap, macUnicodeCmap, msSymbolCmap, cmap; GBool nonsymbolic, useMacRoman, useUnicode; char *charName; Unicode u; @@ -1450,15 +1477,16 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { // This is based on the cmap/encoding selection algorithm in the PDF // 2.0 spec, but with some differences to match up with Adobe's // behavior. - unicodeCmap = macRomanCmap = msSymbolCmap = -1; + unicodeCmap = macRomanCmap = macUnicodeCmap = msSymbolCmap = -1; for (i = 0; i < ff->getNumCmaps(); ++i) { cmapPlatform = ff->getCmapPlatform(i); cmapEncoding = ff->getCmapEncoding(i); - if ((cmapPlatform == 3 && cmapEncoding == 1) || - (cmapPlatform == 0 && cmapEncoding <= 4)) { + if (cmapPlatform == 3 && cmapEncoding == 1) { unicodeCmap = i; } else if (cmapPlatform == 1 && cmapEncoding == 0) { macRomanCmap = i; + } else if (cmapPlatform == 0 && cmapEncoding <= 4) { + macUnicodeCmap = i; } else if (cmapPlatform == 3 && cmapEncoding == 0) { msSymbolCmap = i; } @@ -1466,24 +1494,25 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { useMacRoman = gFalse; useUnicode = gFalse; nonsymbolic = !(flags & fontSymbolic); - if (usesMacRomanEnc && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } else if (embFontID.num < 0 && hasEncoding && unicodeCmap >= 0) { + if (embFontID.num < 0 && hasEncoding && unicodeCmap >= 0) { cmap = unicodeCmap; useUnicode = gTrue; - } else if (nonsymbolic && unicodeCmap >= 0) { - cmap = unicodeCmap; - useUnicode = gTrue; - } else if (nonsymbolic && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } else if (msSymbolCmap >= 0) { + } else if (!nonsymbolic && msSymbolCmap >= 0) { cmap = msSymbolCmap; } else if (unicodeCmap >= 0) { cmap = unicodeCmap; + useUnicode = nonsymbolic; + } else if (usesMacRomanEnc && macRomanCmap >= 0) { + // MacRoman cmap has higher precedence than Mac Unicode only if + // the font uses the MacRoman encoding + cmap = macRomanCmap; + useMacRoman = gTrue; + } else if (macUnicodeCmap >= 0) { + cmap = macUnicodeCmap; + useUnicode = nonsymbolic; } else if (macRomanCmap >= 0) { cmap = macRomanCmap; + useMacRoman = nonsymbolic; } else { cmap = 0; } @@ -2229,75 +2258,99 @@ GBool GfxCIDFont::problematicForUnicode() { // GfxFontDict //------------------------------------------------------------------------ -GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) { - GfxFont *font; - char *tag; - Object obj1, obj2; - Ref r; - int i; +class GfxFontDictEntry { +public: + + GfxFontDictEntry(Ref refA, Object *fontObjA); + ~GfxFontDictEntry(); + void load(GfxFont *fontA); + GBool loaded; + Ref ref; + Object fontObj; // valid if unloaded + GfxFont *font; // valid if loaded +}; + +GfxFontDictEntry::GfxFontDictEntry(Ref refA, Object *fontObjA) { + loaded = gFalse; + ref = refA; + fontObjA->copy(&fontObj); + font = NULL; +} + +GfxFontDictEntry::~GfxFontDictEntry() { + // NB: If the font has been loaded, font is non-NULL and is owned by + // GfxFontDict.uniqueFonts. + if (!loaded) { + fontObj.free(); + } +} + +void GfxFontDictEntry::load(GfxFont *fontA) { + loaded = gTrue; + font = fontA; + fontObj.free(); +} + +GfxFontDict::GfxFontDict(XRef *xrefA, Ref *fontDictRef, Dict *fontDict) { + xref = xrefA; fonts = new GHash(gTrue); uniqueFonts = new GList(); - for (i = 0; i < fontDict->getLength(); ++i) { - tag = fontDict->getKey(i); - fontDict->getValNF(i, &obj1); - obj1.fetch(xref, &obj2); - if (!obj2.isDict()) { - error(errSyntaxError, -1, "font resource is not a dictionary"); - } else if (obj1.isRef() && (font = lookupByRef(obj1.getRef()))) { - fonts->add(new GString(tag), font); + + for (int i = 0; i < fontDict->getLength(); ++i) { + char *tag = fontDict->getKey(i); + Object fontObj; + fontDict->getValNF(i, &fontObj); + Ref r; + if (fontObj.isRef()) { + r = fontObj.getRef(); + } else if (fontDictRef) { + // legal generation numbers are five digits, so we use a + // 6-digit number here + r.gen = 100000 + fontDictRef->num; + r.num = i; } else { - if (obj1.isRef()) { - r = obj1.getRef(); - } else if (fontDictRef) { - // legal generation numbers are five digits, so we use a - // 6-digit number here - r.gen = 100000 + fontDictRef->num; - r.num = i; - } else { - // no indirect reference for this font, or for the containing - // font dict, so hash the font and use that - r.gen = 100000; - r.num = hashFontObject(&obj2); - } - if ((font = GfxFont::makeFont(xref, tag, r, obj2.getDict()))) { - if (!font->isOk()) { - delete font; - } else { - uniqueFonts->append(font); - fonts->add(new GString(tag), font); - } - } + // no indirect reference for this font, or for the containing + // font dict, so hash the font and use that + r.gen = 100000; + r.num = hashFontObject(&fontObj); } - obj1.free(); - obj2.free(); + fonts->add(new GString(tag), new GfxFontDictEntry(r, &fontObj)); + fontObj.free(); } } GfxFontDict::~GfxFontDict() { deleteGList(uniqueFonts, GfxFont); - delete fonts; + deleteGHash(fonts, GfxFontDictEntry); } GfxFont *GfxFontDict::lookup(char *tag) { - return (GfxFont *)fonts->lookup(tag); + GfxFontDictEntry *entry = (GfxFontDictEntry *)fonts->lookup(tag); + if (!entry) { + return NULL; + } + load(tag, entry); + return entry->font; } GfxFont *GfxFontDict::lookupByRef(Ref ref) { - GfxFont *font; - int i; - - for (i = 0; i < uniqueFonts->getLength(); ++i) { - font = (GfxFont *)uniqueFonts->get(i); - if (font->getID()->num == ref.num && - font->getID()->gen == ref.gen) { - return font; + GHashIter *iter; + GString *tag; + GfxFontDictEntry *entry; + fonts->startIter(&iter); + while (fonts->getNext(&iter, &tag, (void **)&entry)) { + if (entry->ref.num == ref.num && entry->ref.gen == ref.gen) { + fonts->killIter(&iter); + load(tag->getCString(), entry); + return entry->font; } } return NULL; } int GfxFontDict::getNumFonts() { + loadAll(); return uniqueFonts->getLength(); } @@ -2305,6 +2358,52 @@ GfxFont *GfxFontDict::getFont(int i) { return (GfxFont *)uniqueFonts->get(i); } +void GfxFontDict::loadAll() { + GHashIter *iter; + GString *tag; + GfxFontDictEntry *entry; + fonts->startIter(&iter); + while (fonts->getNext(&iter, &tag, (void **)&entry)) { + load(tag->getCString(), entry); + } +} + +void GfxFontDict::load(char *tag, GfxFontDictEntry *entry) { + if (entry->loaded) { + return; + } + + // check for a duplicate that has already been loaded + // (don't do this for "synthetic" refs) + if (entry->fontObj.isRef()) { + for (int i = 0; i < uniqueFonts->getLength(); ++i) { + GfxFont *font = (GfxFont *)uniqueFonts->get(i); + if (font->getID()->num == entry->ref.num && + font->getID()->gen == entry->ref.gen) { + entry->load(font); + return; + } + } + } + + GfxFont *font = NULL; + Object obj; + entry->fontObj.fetch(xref, &obj); + if (obj.isDict()) { + font = GfxFont::makeFont(xref, tag, entry->ref, obj.getDict()); + if (font->isOk()) { + uniqueFonts->append(font); + } else { + delete font; + font = NULL; + } + } else { + error(errSyntaxError, -1, "font resource is not a dictionary"); + } + obj.free(); + entry->load(font); +} + // FNV-1a hash class FNVHash { public: diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h index e752ded62f8..ec6d3c3d246 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "GString.h" #include "Object.h" @@ -29,6 +25,7 @@ class FoFiTrueType; class FoFiType1C; struct GfxFontCIDWidths; struct Base14FontMapEntry; +class GfxFontDictEntry; class FNVHash; //------------------------------------------------------------------------ @@ -388,7 +385,7 @@ class GfxFontDict { public: // Build the font dictionary, given the PDF font dictionary. - GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict); + GfxFontDict(XRef *xrefA, Ref *fontDictRef, Dict *fontDict); // Destructor. ~GfxFontDict(); @@ -405,13 +402,18 @@ private: friend class GfxFont; + void loadAll(); + void load(char *tag, GfxFontDictEntry *entry); static int hashFontObject(Object *obj); static void hashFontObject1(Object *obj, FNVHash *h); - GHash *fonts; // hash table of fonts -- this may - // include duplicates, i.e., when - // two tags map to the same font + XRef *xref; + GHash *fonts; // hash table of fonts, mapping from + // tag to GfxFontDictEntry; this may + // contain duplicates, i.e., two + // tags that map to the same font GList *uniqueFonts; // list of all unique font objects (no dups) + // that have been loaded }; #endif diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc index 43503aaedb8..9aed7345ad2 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stddef.h> #include <math.h> #include <string.h> @@ -936,15 +932,15 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, } nCompsA = obj2.getInt(); obj2.free(); - if (nCompsA > 4) { - error(errSyntaxError, -1, - "ICCBased color space with too many ({0:d} > 4) components", - nCompsA); - nCompsA = 4; - } - if (dict->lookup("Alternate", &obj2)->isNull() || - !(altA = GfxColorSpace::parse(&obj2, - recursion + 1))) { + if (!dict->lookup("Alternate", &obj2)->isNull() && + (altA = GfxColorSpace::parse(&obj2, + recursion + 1))) { + if (altA->getNComps() != nCompsA) { + error(errSyntaxError, -1, + "Number of components in ICCBased color space doesn't match alternate color space"); + nCompsA = altA->getNComps(); + } + } else { switch (nCompsA) { case 1: altA = GfxColorSpace::create(csDeviceGray); @@ -1784,6 +1780,258 @@ GfxPattern *GfxTilingPattern::copy() { &resDict, matrix, &contentStreamRef); } +GBool GfxTilingPattern::usesBlendMode(XRef *xref) { + char *scannedObjs = (char *)gmalloc(xref->getNumObjects()); + memset(scannedObjs, 0, xref->getNumObjects()); + GBool ret = scanResourcesForBlendMode(&resDict, scannedObjs, xref); + gfree(scannedObjs); + return ret; +} + +GBool GfxTilingPattern::scanResourcesForBlendMode(Object *resDict2, + char *scannedObjs, + XRef *xref) { + Object ref1, obj1, obj2; + + if (!resDict2->isDict()) { + return gFalse; + } + + //----- ExtGStates + resDict2->dictLookupNF("ExtGState", &ref1); + if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() && + !scannedObjs[ref1.getRefNum()])) { + if (ref1.isRef()) { + scannedObjs[ref1.getRefNum()] = 1; + ref1.fetch(xref, &obj1); + } else { + ref1.copy(&obj1); + } + if (obj1.isDict()) { + for (int i = 0; i < obj1.dictGetLength(); ++i) { + if (scanExtGStateForBlendMode(obj1.dictGetValNF(i, &obj2), + scannedObjs, xref)) { + obj2.free(); + obj1.free(); + ref1.free(); + return gTrue; + } + obj2.free(); + } + } + obj1.free(); + } + ref1.free(); + + //----- patterns + resDict2->dictLookupNF("Pattern", &ref1); + if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() && + !scannedObjs[ref1.getRefNum()])) { + if (ref1.isRef()) { + scannedObjs[ref1.getRefNum()] = 1; + ref1.fetch(xref, &obj1); + } else { + ref1.copy(&obj1); + } + if (obj1.isDict()) { + for (int i = 0; i < obj1.dictGetLength(); ++i) { + if (scanPatternForBlendMode(obj1.dictGetValNF(i, &obj2), + scannedObjs, xref)) { + obj2.free(); + obj1.free(); + ref1.free(); + return gTrue; + } + obj2.free(); + } + } + obj1.free(); + } + ref1.free(); + + //----- XObjects + resDict2->dictLookupNF("XObject", &ref1); + if (!ref1.isRef() || (ref1.getRefNum() < xref->getNumObjects() && + !scannedObjs[ref1.getRefNum()])) { + if (ref1.isRef()) { + scannedObjs[ref1.getRefNum()] = 1; + ref1.fetch(xref, &obj1); + } else { + ref1.copy(&obj1); + } + if (obj1.isDict()) { + for (int i = 0; i < obj1.dictGetLength(); ++i) { + if (scanXObjectForBlendMode(obj1.dictGetValNF(i, &obj2), + scannedObjs, xref)) { + obj2.free(); + obj1.free(); + ref1.free(); + return gTrue; + } + obj2.free(); + } + } + obj1.free(); + } + ref1.free(); + + return gFalse; +} + +GBool GfxTilingPattern::scanExtGStateForBlendMode(Object *gsObj, + char *scannedObjs, + XRef *xref) { + Object gsDict, obj1; + + if (gsObj->isRef()) { + if (gsObj->getRefNum() >= xref->getNumObjects() || + scannedObjs[gsObj->getRefNum()]) { + return gFalse; + } + scannedObjs[gsObj->getRefNum()] = 1; + gsObj->fetch(xref, &gsDict); + } else { + gsObj->copy(&gsDict); + } + if (!gsDict.isDict()) { + gsDict.free(); + return gFalse; + } + + gsDict.dictLookup("BM", &obj1); + if (obj1.isName() && !obj1.isName("Normal")) { + obj1.free(); + gsDict.free(); + return gTrue; + } + obj1.free(); + + if (!gsDict.dictLookupNF("SMask", &obj1)->isNull()) { + if (scanSoftMaskForBlendMode(&obj1, scannedObjs, xref)) { + obj1.free(); + gsDict.free(); + return gTrue; + } + } + obj1.free(); + + gsDict.free(); + + return gFalse; +} + +GBool GfxTilingPattern::scanSoftMaskForBlendMode(Object *softMaskObj, + char *scannedObjs, + XRef *xref) { + Object softMaskDict, obj1; + + if (softMaskObj->isRef()) { + if (softMaskObj->getRefNum() >= xref->getNumObjects() || + scannedObjs[softMaskObj->getRefNum()]) { + return gFalse; + } + scannedObjs[softMaskObj->getRefNum()] = 1; + softMaskObj->fetch(xref, &softMaskDict); + } else { + softMaskObj->copy(&softMaskDict); + } + if (!softMaskDict.isDict()) { + softMaskDict.free(); + return gFalse; + } + + if (!softMaskDict.dictLookupNF("G", &obj1)->isNull()) { + if (scanXObjectForBlendMode(&obj1, scannedObjs, xref)) { + obj1.free(); + softMaskDict.free(); + return gTrue; + } + } + obj1.free(); + + softMaskDict.free(); + + return gFalse; +} + +GBool GfxTilingPattern::scanPatternForBlendMode(Object *patternObj, + char *scannedObjs, + XRef *xref) { + Object patternObj2, obj1; + Dict *patternDict; + + if (patternObj->isRef()) { + if (patternObj->getRefNum() >= xref->getNumObjects() || + scannedObjs[patternObj->getRefNum()]) { + return gFalse; + } + scannedObjs[patternObj->getRefNum()] = 1; + patternObj->fetch(xref, &patternObj2); + } else { + patternObj->copy(&patternObj2); + } + if (patternObj2.isDict()) { + patternDict = patternObj2.getDict(); + } else if (patternObj2.isStream()) { + patternDict = patternObj2.streamGetDict(); + } else { + patternObj2.free(); + return gFalse; + } + + if (!patternDict->lookupNF("Resources", &obj1)->isNull()) { + if (scanResourcesForBlendMode(&obj1, scannedObjs, xref)) { + obj1.free(); + patternObj2.free(); + return gTrue; + } + } + obj1.free(); + + patternObj2.free(); + + return gFalse; +} + +GBool GfxTilingPattern::scanXObjectForBlendMode(Object *xObj, + char *scannedObjs, + XRef *xref) { + Object xObj2, obj1; + Dict *dict; + + if (xObj->isRef()) { + if (xObj->getRefNum() >= xref->getNumObjects() || + scannedObjs[xObj->getRefNum()]) { + return gFalse; + } + scannedObjs[xObj->getRefNum()] = 1; + xObj->fetch(xref, &xObj2); + } else { + xObj->copy(&xObj2); + } + if (xObj2.isDict()) { + dict = xObj2.getDict(); + } else if (xObj2.isStream()) { + dict = xObj2.streamGetDict(); + } else { + xObj2.free(); + return gFalse; + } + + if (!dict->lookupNF("Resources", &obj1)->isNull()) { + if (scanResourcesForBlendMode(&obj1, scannedObjs, xref)) { + obj1.free(); + xObj2.free(); + return gTrue; + } + } + obj1.free(); + + xObj2.free(); + + return gFalse; +} + //------------------------------------------------------------------------ // GfxShadingPattern //------------------------------------------------------------------------ @@ -2963,8 +3211,8 @@ void GfxGouraudTriangleShading::getTriangle( } } -void GfxGouraudTriangleShading::getBBox(double *xMin, double *yMin, - double *xMax, double *yMax) { +void GfxGouraudTriangleShading::getBBox(double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA) { double xxMin = 0; double yyMin = 0; double xxMax = 0; @@ -2985,10 +3233,10 @@ void GfxGouraudTriangleShading::getBBox(double *xMin, double *yMin, yyMax = vertices[i].y; } } - *xMin = xxMin; - *yMin = yyMin; - *xMax = xxMax; - *yMax = yyMax; + *xMinA = xxMin; + *yMinA = yyMin; + *xMaxA = xxMax; + *yMaxA = yyMax; } void GfxGouraudTriangleShading::getColor(double *in, GfxColor *out) { @@ -3621,8 +3869,8 @@ GfxShading *GfxPatchMeshShading::copy() { return new GfxPatchMeshShading(this); } -void GfxPatchMeshShading::getBBox(double *xMin, double *yMin, - double *xMax, double *yMax) { +void GfxPatchMeshShading::getBBox(double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA) { double xxMin = 0; double yyMin = 0; double xxMax = 0; @@ -3647,10 +3895,10 @@ void GfxPatchMeshShading::getBBox(double *xMin, double *yMin, } } } - *xMin = xxMin; - *yMin = yyMin; - *xMax = xxMax; - *yMax = yyMax; + *xMinA = xxMin; + *yMinA = yyMin; + *xMaxA = xxMax; + *yMaxA = yyMax; } void GfxPatchMeshShading::getColor(double *in, GfxColor *out) { @@ -4651,35 +4899,36 @@ void GfxState::clipToStrokePath() { // There are two cases for each point on the path: // (1) miter join, under miter limit => compute the miter point // (2) all other joins and caps => use the path point +/- 0.5 * line width - double xMin = 0, yMin = 0, xMax = 0, yMax = 0; + double uxMin = 0, uyMin = 0, uxMax = 0, uyMax = 0; double w = 0.5 * lineWidth; for (int i = 0; i < path->getNumSubpaths(); ++i) { GfxSubpath *subpath = path->getSubpath(i); - for (int j = 0; j < subpath->getNumPoints(); ++j) { + int nPoints; + if (subpath->isClosed()) { + nPoints = subpath->getNumPoints() - 1; + } else { + nPoints = subpath->getNumPoints(); + } + for (int j = 0; j < nPoints; ++j) { double x1 = subpath->getX(j); double y1 = subpath->getY(j); if (i == 0 && j == 0) { - xMin = xMax = x1; - yMin = yMax = y1; + uxMin = uxMax = x1; + uyMin = uyMax = y1; } GBool useMiter = gFalse; if (lineJoin == 0 && // miter join - ((j > 0 && j < subpath->getNumPoints() - 1) || subpath->isClosed())) { + (subpath->isClosed() || (j > 0 && j < subpath->getNumPoints() - 1))) { double x0, y0, x2, y2; - if (j > 0) { + if (j == 0) { + x0 = subpath->getX(nPoints - 1); + y0 = subpath->getY(nPoints - 1); + } else { x0 = subpath->getX(j - 1); y0 = subpath->getY(j - 1); - } else { - x0 = subpath->getLastX(); - y0 = subpath->getLastY(); - } - if (j < subpath->getNumPoints() - 1) { - x2 = subpath->getX(j + 1); - y2 = subpath->getY(j + 1); - } else { - x2 = subpath->getX(0); - y2 = subpath->getY(0); } + x2 = subpath->getX(j + 1); + y2 = subpath->getY(j + 1); if ((fabs(x1 - x0) > 0.0001 || fabs(y1 - y0) > 0.0001) && (fabs(x2 - x1) > 0.0001 || fabs(y2 - y1) > 0.0001)) { double d01 = 1 / sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); @@ -4704,15 +4953,15 @@ void GfxState::clipToStrokePath() { } double mx = ax + m * w * ux; double my = ay + m * w * uy; - if (mx < xMin) { - xMin = mx; - } else if (mx > xMax) { - xMax = mx; + if (mx < uxMin) { + uxMin = mx; + } else if (mx > uxMax) { + uxMax = mx; } - if (my < yMin) { - yMin = my; - } else if (my > yMax) { - yMax = my; + if (my < uyMin) { + uyMin = my; + } else if (my > uyMax) { + uyMax = my; } useMiter = gTrue; } @@ -4720,66 +4969,71 @@ void GfxState::clipToStrokePath() { } } if (!useMiter) { - if (x1 - w < xMin) { - xMin = x1 - w; + if (x1 - w < uxMin) { + uxMin = x1 - w; } - if (x1 + w > xMax) { - xMax = x1 + w; + if (x1 + w > uxMax) { + uxMax = x1 + w; } - if (y1 - w < yMin) { - yMin = y1 - w; + if (y1 - w < uyMin) { + uyMin = y1 - w; } - if (y1 + w > yMax) { - yMax = y1 + w; + if (y1 + w > uyMax) { + uyMax = y1 + w; } } } } - double xx, yy; - transform(xMin, yMin, &xx, &yy); - if (xx < clipXMin) { - clipXMin = xx; - } else if (xx > clipXMax) { - clipXMax = xx; - } - if (yy < clipYMin) { - clipYMin = yy; - } else if (yy > clipYMax) { - clipYMax = yy; - } - transform(xMin, yMax, &xx, &yy); - if (xx < clipXMin) { - clipXMin = xx; - } else if (xx > clipXMax) { - clipXMax = xx; - } - if (yy < clipYMin) { - clipYMin = yy; - } else if (yy > clipYMax) { - clipYMax = yy; - } - transform(xMax, yMin, &xx, &yy); - if (xx < clipXMin) { - clipXMin = xx; - } else if (xx > clipXMax) { - clipXMax = xx; - } - if (yy < clipYMin) { - clipYMin = yy; - } else if (yy > clipYMax) { - clipYMax = yy; - } - transform(xMax, yMax, &xx, &yy); - if (xx < clipXMin) { - clipXMin = xx; - } else if (xx > clipXMax) { - clipXMax = xx; - } - if (yy < clipYMin) { - clipYMin = yy; - } else if (yy > clipYMax) { - clipYMax = yy; + double dxMin, dyMin, dxMax, dyMax, xx, yy; + transform(uxMin, uyMin, &xx, &yy); + dxMin = dxMax = xx; + dyMin = dyMax = yy; + transform(uxMin, uyMax, &xx, &yy); + if (xx < dxMin) { + dxMin = xx; + } else if (xx > dxMax) { + dxMax = xx; + } + if (yy < dyMin) { + dyMin = yy; + } else if (yy > dyMax) { + dyMax = yy; + } + transform(uxMax, uyMin, &xx, &yy); + if (xx < dxMin) { + dxMin = xx; + } else if (xx > dxMax) { + dxMax = xx; + } + if (yy < dyMin) { + dyMin = yy; + } else if (yy > dyMax) { + dyMax = yy; + } + transform(uxMax, uyMax, &xx, &yy); + if (xx < dxMin) { + dxMin = xx; + } else if (xx > dxMax) { + dxMax = xx; + } + if (yy < dyMin) { + dyMin = yy; + } else if (yy > dyMax) { + dyMax = yy; + } + + if (dxMin > clipXMin) { + clipXMin = dxMin; + } + if (dyMin > clipYMin) { + clipYMin = dyMin; + } + if (dxMax < clipXMax) { + clipXMax = dxMax; + } + if (dyMax < clipYMax) { + clipYMax = dyMax; } } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h index 60d48527c29..57b57e06a66 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxState.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "Object.h" #include "Function.h" @@ -663,6 +659,7 @@ public: { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; } double *getMatrix() { return matrix; } Object *getContentStreamRef() { return &contentStreamRef; } + GBool usesBlendMode(XRef *xref); private: @@ -670,6 +667,16 @@ private: double *bboxA, double xStepA, double yStepA, Object *resDictA, double *matrixA, Object *contentStreamA); + GBool scanResourcesForBlendMode(Object *resDict2, + char *scannedObjs, XRef *xref); + GBool scanExtGStateForBlendMode(Object *gsObj, + char *scannedObjs, XRef *xref); + GBool scanSoftMaskForBlendMode(Object *softMaskObj, + char *scannedObjs, XRef *xref); + GBool scanPatternForBlendMode(Object *patternObj, + char *scannedObjs, XRef *xref); + GBool scanXObjectForBlendMode(Object *xObj, + char *scannedObjs, XRef *xref); int paintType; int tilingType; @@ -883,7 +890,7 @@ public: void getTriangle(int i, double *x0, double *y0, double *color0, double *x1, double *y1, double *color1, double *x2, double *y2, double *color2); - void getBBox(double *xMin, double *yMin, double *xMax, double *yMax); + void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA); void getColor(double *in, GfxColor *out); private: @@ -923,7 +930,7 @@ public: int getNComps() { return nComps; } int getNPatches() { return nPatches; } GfxPatch *getPatch(int i) { return &patches[i]; } - void getBBox(double *xMin, double *yMin, double *xMax, double *yMax); + void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA); void getColor(double *in, GfxColor *out); private: diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc index e7cc594b12d..fcacd7f1e71 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <string.h> #include <stdio.h> #include <stdarg.h> @@ -44,10 +40,12 @@ #include "GlobalParams.h" #ifdef _WIN32 +#ifndef __GNUC__ # undef strcasecmp # undef strncasecmp # define strcasecmp _stricmp # define strncasecmp _strnicmp +#endif #else # include <strings.h> #endif @@ -105,14 +103,14 @@ static struct { {NULL} }; -#ifdef _WIN32 static const char *displayFontDirs[] = { +#ifdef BASE14_FONT_DIR + BASE14_FONT_DIR, +#endif +#ifdef _WIN32 "c:/windows/fonts", "c:/winnt/fonts", - NULL -}; -#else -static const char *displayFontDirs[] = { +#else // _WIN32 "/usr/share/ghostscript/fonts", "/usr/local/share/ghostscript/fonts", "/usr/share/fonts/default/Type1", @@ -121,9 +119,9 @@ static const char *displayFontDirs[] = { #if defined(__sun) && defined(__SVR4) "/usr/sfw/share/ghostscript/fonts", #endif +#endif // _WIN32 NULL }; -#endif #ifdef __APPLE__ static const char *macSystemFontPath = "/System/Library/Fonts"; @@ -183,7 +181,7 @@ public: ~SysFontInfo(); GString *mungeName1(GString *in); GString *mungeName2(GString *in); - void mungeName3(GString *name, GBool *bold, GBool *italic); + void mungeName3(GString *nameA, GBool *bold, GBool *italic); int match(GString *nameA); }; @@ -260,24 +258,24 @@ GString *SysFontInfo::mungeName2(GString *in) { // Remove trailing bold/italic/regular/roman tags from the name. // (Note: the names have already been uppercased by mungeName1/2.) -void SysFontInfo::mungeName3(GString *name, GBool *bold, GBool *italic) { +void SysFontInfo::mungeName3(GString *nameA, GBool *bold, GBool *italic) { *bold = gFalse; *italic = gFalse; - int n = name->getLength(); + int n = nameA->getLength(); while (1) { - if (n >= 4 && !strcmp(name->getCString() + n - 4, "BOLD")) { - name->del(n - 4, 4); + if (n >= 4 && !strcmp(nameA->getCString() + n - 4, "BOLD")) { + nameA->del(n - 4, 4); n -= 4; *bold = gTrue; - } else if (n >= 6 && !strcmp(name->getCString() + n - 6, "ITALIC")) { - name->del(n - 6, 6); + } else if (n >= 6 && !strcmp(nameA->getCString() + n - 6, "ITALIC")) { + nameA->del(n - 6, 6); n -= 6; *italic = gTrue; - } else if (n >= 7 && !strcmp(name->getCString() + n - 7, "REGULAR")) { - name->del(n - 7, 7); + } else if (n >= 7 && !strcmp(nameA->getCString() + n - 7, "REGULAR")) { + nameA->del(n - 7, 7); n -= 7; - } else if (n >= 5 && !strcmp(name->getCString() + n - 5, "ROMAN")) { - name->del(n - 5, 5); + } else if (n >= 5 && !strcmp(nameA->getCString() + n - 5, "ROMAN")) { + nameA->del(n - 5, 5); n -= 5; } else { break; @@ -659,7 +657,7 @@ GlobalParams::GlobalParams(const char *cfgFileName) { base14SysFonts = new GHash(gTrue); sysFonts = new SysFontList(); #if HAVE_PAPER_H - char *paperName; + const char *paperName; const struct paper *paperType; paperinit(); if ((paperName = systempapername())) { @@ -715,6 +713,21 @@ GlobalParams::GlobalParams(const char *cfgFileName) { textKeepTinyChars = gTrue; initialZoom = new GString("125"); defaultFitZoom = 0; + zoomScaleFactor = 1; + zoomValues = new GList(); + zoomValues->append(new GString("25")); + zoomValues->append(new GString("50")); + zoomValues->append(new GString("75")); + zoomValues->append(new GString("100")); + zoomValues->append(new GString("110")); + zoomValues->append(new GString("125")); + zoomValues->append(new GString("150")); + zoomValues->append(new GString("175")); + zoomValues->append(new GString("200")); + zoomValues->append(new GString("300")); + zoomValues->append(new GString("400")); + zoomValues->append(new GString("600")); + zoomValues->append(new GString("800")); initialDisplayMode = new GString("continuous"); initialToolbarState = gTrue; initialSidebarState = gTrue; @@ -748,6 +761,7 @@ GlobalParams::GlobalParams(const char *cfgFileName) { fullScreenMatteColor = new GString("#000000"); selectionColor = new GString("#8080ff"); reverseVideoInvertImages = gFalse; + allowLinksToChangeZoom = gTrue; launchCommand = NULL; movieCommand = NULL; defaultPrinter = NULL; @@ -755,10 +769,15 @@ GlobalParams::GlobalParams(const char *cfgFileName) { mapUnknownCharNames = gFalse; mapExtTrueTypeFontsViaUnicode = gTrue; useTrueTypeUnicodeMapping = gFalse; + ignoreWrongSizeToUnicode = gFalse; droppedFonts = new GHash(gTrue); + separateRotatedText = gFalse; createDefaultKeyBindings(); popupMenuCmds = new GList(); - tabStateFile = appendToPath(getHomeDir(), ".xpdf.tab-state"); +#ifndef PDF_PARSER_ONLY + initStateFilePaths(); +#endif + saveSessionOnQuit = gTrue; savePageNumbers = gTrue; printCommands = gFalse; printStatusInfo = gFalse; @@ -1017,6 +1036,27 @@ void GlobalParams::createDefaultKeyBindings() { xpdfKeyContextAny, "zoomFitWidth")); } +#ifndef PDF_PARSER_ONLY +void GlobalParams::initStateFilePaths() { +#ifdef _WIN32 + char path[MAX_PATH]; + if (SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, + SHGFP_TYPE_CURRENT, path) != S_OK) { + return; + } + GString *dir = appendToPath(new GString(path), "xpdf"); + CreateDirectoryA(dir->getCString(), NULL); + pagesFile = appendToPath(dir->copy(), "xpdf.pages"); + tabStateFile = appendToPath(dir->copy(), "xpdf.tab-state"); + sessionFile = appendToPath(dir, "xpdf.session"); +#else + pagesFile = appendToPath(getHomeDir(), ".xpdf.pages"); + tabStateFile = appendToPath(getHomeDir(), ".xpdf.tab-state"); + sessionFile = appendToPath(getHomeDir(), ".xpdf.session"); +#endif +} +#endif + void GlobalParams::parseFile(GString *fileName, FILE *f) { int line; char buf[512]; @@ -1157,6 +1197,10 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parseString("initialZoom", &initialZoom, tokens, fileName, line); } else if (!cmd->cmp("defaultFitZoom")) { parseInteger("defaultFitZoom", &defaultFitZoom, tokens, fileName, line); + } else if (!cmd->cmp("zoomScaleFactor")) { + parseZoomScaleFactor(tokens, fileName, line); + } else if (!cmd->cmp("zoomValues")) { + parseZoomValues(tokens, fileName, line); } else if (!cmd->cmp("initialDisplayMode")) { parseString("initialDisplayMode", &initialDisplayMode, tokens, fileName, line); @@ -1244,6 +1288,9 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { } else if (!cmd->cmp("reverseVideoInvertImages")) { parseYesNo("reverseVideoInvertImages", &reverseVideoInvertImages, tokens, fileName, line); + } else if (!cmd->cmp("allowLinksToChangeZoom")) { + parseYesNo("allowLinksToChangeZoom", &allowLinksToChangeZoom, + tokens, fileName, line); } else if (!cmd->cmp("launchCommand")) { parseString("launchCommand", &launchCommand, tokens, fileName, line); } else if (!cmd->cmp("movieCommand")) { @@ -1261,11 +1308,16 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { &mapExtTrueTypeFontsViaUnicode, tokens, fileName, line); } else if (!cmd->cmp("useTrueTypeUnicodeMapping")) { - parseYesNo("useTrueTypeUnicodeMapping", - &useTrueTypeUnicodeMapping, + parseYesNo("useTrueTypeUnicodeMapping", &useTrueTypeUnicodeMapping, + tokens, fileName, line); + } else if (!cmd->cmp("ignoreWrongSizeToUnicode")) { + parseYesNo("ignoreWrongSizeToUnicode", &ignoreWrongSizeToUnicode, tokens, fileName, line); } else if (!cmd->cmp("dropFont")) { parseDropFont(tokens, fileName, line); + } else if (!cmd->cmp("separateRotatedText")) { + parseYesNo("separateRotatedText", &separateRotatedText, + tokens, fileName, line); } else if (!cmd->cmp("bind")) { parseBind(tokens, fileName, line); } else if (!cmd->cmp("unbind")) { @@ -1274,6 +1326,11 @@ void GlobalParams::parseLine(char *buf, GString *fileName, int line) { parsePopupMenuCmd(tokens, fileName, line); } else if (!cmd->cmp("tabStateFile")) { parseString("tabStateFile", &tabStateFile, tokens, fileName, line); + } else if (!cmd->cmp("sessionFile")) { + parseString("sessionFile", &sessionFile, tokens, fileName, line); + } else if (!cmd->cmp("saveSessionOnQuit")) { + parseYesNo("saveSessionOnQuit", &saveSessionOnQuit, + tokens, fileName, line); } else if (!cmd->cmp("savePageNumbers")) { parseYesNo("savePageNumbers", &savePageNumbers, tokens, fileName, line); } else if (!cmd->cmp("printCommands")) { @@ -1973,6 +2030,59 @@ void GlobalParams::parsePopupMenuCmd(GList *tokens, cmds)); } +void GlobalParams::parseZoomScaleFactor(GList *tokens, + GString *fileName, int line) { + if (tokens->getLength() != 2) { + error(errConfig, -1, "Bad 'zoomScaleFactor' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + GString *tok = (GString *)tokens->get(1); + if (tok->getLength() == 0) { + error(errConfig, -1, "Bad 'zoomScaleFactor' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + if (tok->cmp("actual") == 0) { + zoomScaleFactor = -1; + } else { + for (int i = 0; i < tok->getLength(); ++i) { + if (!((tok->getChar(i) >= '0' && tok->getChar(i) <= '9') || + tok->getChar(i) == '.')) { + error(errConfig, -1, "Bad 'zoomScaleFactor' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + } + zoomScaleFactor = atof(tok->getCString()); + } +} + +void GlobalParams::parseZoomValues(GList *tokens, + GString *fileName, int line) { + if (tokens->getLength() < 2) { + error(errConfig, -1, "Bad 'zoomValues' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + for (int i = 1; i < tokens->getLength(); ++i) { + GString *tok = (GString *)tokens->get(i); + for (int j = 0; j < tok->getLength(); ++j) { + if (tok->getChar(j) < '0' || tok->getChar(j) > '9') { + error(errConfig, -1, "Bad 'zoomValues' config file command ({0:t}:{1:d})", + fileName, line); + return; + } + } + } + deleteGList(zoomValues, GString); + zoomValues = new GList(); + for (int i = 1; i < tokens->getLength(); ++i) { + GString *tok = (GString *)tokens->get(i); + zoomValues->append(tok->copy()); + } +} + void GlobalParams::parseYesNo(const char *cmdName, GBool *flag, GList *tokens, GString *fileName, int line) { GString *tok; @@ -2104,6 +2214,7 @@ GlobalParams::~GlobalParams() { deleteGList(psResidentFontsCC, PSFontParam16); delete textEncoding; delete initialZoom; + deleteGList(zoomValues, GString); delete initialDisplayMode; delete initialSelectMode; if (paperColor) { @@ -2130,7 +2241,9 @@ GlobalParams::~GlobalParams() { delete droppedFonts; deleteGList(keyBindings, KeyBinding); deleteGList(popupMenuCmds, PopupMenuCmd); + delete pagesFile; delete tabStateFile; + delete sessionFile; delete debugLogFile; cMapDirs->startIter(&iter); @@ -2959,6 +3072,19 @@ int GlobalParams::getDefaultFitZoom() { return z; } +double GlobalParams::getZoomScaleFactor() { + double z; + + lockGlobalParams; + z = zoomScaleFactor; + unlockGlobalParams; + return z; +} + +GList *GlobalParams::getZoomValues() { + return zoomValues; +} + GString *GlobalParams::getInitialDisplayMode() { GString *s; @@ -3250,6 +3376,15 @@ GBool GlobalParams::getReverseVideoInvertImages() { return invert; } +GBool GlobalParams::getAllowLinksToChangeZoom() { + GBool allow; + + lockGlobalParams; + allow = allowLinksToChangeZoom; + unlockGlobalParams; + return allow; +} + GString *GlobalParams::getDefaultPrinter() { GString *s; @@ -3295,6 +3430,15 @@ GBool GlobalParams::getUseTrueTypeUnicodeMapping() { return use; } +GBool GlobalParams::getIgnoreWrongSizeToUnicode() { + GBool ignore; + + lockGlobalParams; + ignore = ignoreWrongSizeToUnicode; + unlockGlobalParams; + return ignore; +} + GBool GlobalParams::isDroppedFont(const char *fontName) { GBool isDropped; @@ -3304,6 +3448,15 @@ GBool GlobalParams::isDroppedFont(const char *fontName) { return isDropped; } +GBool GlobalParams::getSeparateRotatedText() { + GBool sep; + + lockGlobalParams; + sep = separateRotatedText; + unlockGlobalParams; + return sep; +} + GList *GlobalParams::getKeyBinding(int code, int mods, int context) { KeyBinding *binding; GList *cmds; @@ -3356,6 +3509,15 @@ PopupMenuCmd *GlobalParams::getPopupMenuCmd(int idx) { return cmd; } +GString *GlobalParams::getPagesFile() { + GString *s; + + lockGlobalParams; + s = pagesFile->copy(); + unlockGlobalParams; + return s; +} + GString *GlobalParams::getTabStateFile() { GString *s; @@ -3365,6 +3527,15 @@ GString *GlobalParams::getTabStateFile() { return s; } +GString *GlobalParams::getSessionFile() { + GString *s; + + lockGlobalParams; + s = sessionFile->copy(); + unlockGlobalParams; + return s; +} + GBool GlobalParams::getSavePageNumbers() { GBool s; @@ -3374,6 +3545,15 @@ GBool GlobalParams::getSavePageNumbers() { return s; } +GBool GlobalParams::getSaveSessionOnQuit() { + GBool s; + + lockGlobalParams; + s = saveSessionOnQuit; + unlockGlobalParams; + return s; +} + GBool GlobalParams::getPrintCommands() { GBool p; @@ -3712,6 +3892,12 @@ void GlobalParams::setInitialZoom(char *s) { unlockGlobalParams; } +void GlobalParams::setDefaultFitZoom(int z) { + lockGlobalParams; + defaultFitZoom = z; + unlockGlobalParams; +} + GBool GlobalParams::setEnableFreeType(char *s) { GBool ok; @@ -3815,6 +4001,13 @@ void GlobalParams::setTabStateFile(char *tabStateFileA) { unlockGlobalParams; } +void GlobalParams::setSessionFile(char *sessionFileA) { + lockGlobalParams; + delete sessionFile; + sessionFile = new GString(sessionFileA); + unlockGlobalParams; +} + void GlobalParams::setPrintCommands(GBool printCommandsA) { lockGlobalParams; printCommands = printCommandsA; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h index d72473f2a46..c9b4c7bdc09 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GlobalParams.h @@ -14,10 +14,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stdio.h> #ifdef _WIN32 # include <windows.h> @@ -303,6 +299,8 @@ public: GBool getTextKeepTinyChars(); GString *getInitialZoom(); int getDefaultFitZoom(); + double getZoomScaleFactor(); + GList *getZoomValues(); GString *getInitialDisplayMode(); GBool getInitialToolbarState(); GBool getInitialSidebarState(); @@ -336,6 +334,7 @@ public: GString *getFullScreenMatteColor(); GString *getSelectionColor(); GBool getReverseVideoInvertImages(); + GBool getAllowLinksToChangeZoom(); GString *getLaunchCommand() { return launchCommand; } GString *getMovieCommand() { return movieCommand; } GString *getDefaultPrinter(); @@ -343,12 +342,17 @@ public: GBool getMapUnknownCharNames(); GBool getMapExtTrueTypeFontsViaUnicode(); GBool getUseTrueTypeUnicodeMapping(); + GBool getIgnoreWrongSizeToUnicode(); GBool isDroppedFont(const char *fontName); + GBool getSeparateRotatedText(); GList *getKeyBinding(int code, int mods, int context); GList *getAllKeyBindings(); int getNumPopupMenuCmds(); PopupMenuCmd *getPopupMenuCmd(int idx); + GString *getPagesFile(); GString *getTabStateFile(); + GString *getSessionFile(); + GBool getSaveSessionOnQuit(); GBool getSavePageNumbers(); GBool getPrintCommands(); GBool getPrintStatusInfo(); @@ -390,6 +394,7 @@ public: void setTextPageBreaks(GBool pageBreaks); void setTextKeepTinyChars(GBool keep); void setInitialZoom(char *s); + void setDefaultFitZoom(int z); GBool setEnableFreeType(char *s); GBool setAntialias(char *s); GBool setVectorAntialias(char *s); @@ -405,6 +410,7 @@ public: void setMapUnknownCharNames(GBool map); void setMapExtTrueTypeFontsViaUnicode(GBool map); void setTabStateFile(char *tabStateFileA); + void setSessionFile(char *sessionFileA); void setPrintCommands(GBool printCommandsA); void setPrintStatusInfo(GBool printStatusInfoA); void setErrQuiet(GBool errQuietA); @@ -420,6 +426,9 @@ private: void setDataDirVar(); void createDefaultKeyBindings(); +#ifndef PDF_PARSER_ONLY + void initStateFilePaths(); +#endif void parseFile(GString *fileName, FILE *f); GList *parseLineTokens(char *buf, GString *fileName, int line); void parseNameToUnicode(GList *tokens, GString *fileName, int line); @@ -450,6 +459,8 @@ private: const char *cmdName, GList *tokens, GString *fileName, int line); void parsePopupMenuCmd(GList *tokens, GString *fileName, int line); + void parseZoomScaleFactor(GList *tokens, GString *fileName, int line); + void parseZoomValues(GList *tokens, GString *fileName, int line); void parseYesNo(const char *cmdName, GBool *flag, GList *tokens, GString *fileName, int line); GBool parseYesNo2(char *token, GBool *flag); @@ -548,7 +559,9 @@ private: GBool textKeepTinyChars; // keep all characters in text output GString *initialZoom; // initial zoom level int defaultFitZoom; // default zoom factor if initialZoom is - // 'page' or 'width'. + // 'page' or 'width' + double zoomScaleFactor; // displayed zoom values are scaled by this + GList *zoomValues; // zoom values for the combo box GString *initialDisplayMode; // initial display mode (single, // continuous, etc.) GBool initialToolbarState; // initial toolbar state - open (true) @@ -586,6 +599,7 @@ private: GString *fullScreenMatteColor; // matte color in full-screen mode GString *selectionColor; // selection color GBool reverseVideoInvertImages; // invert images in reverse video mode + GBool allowLinksToChangeZoom; // allow clicking on a link to change the zoom GString *launchCommand; // command executed for 'launch' links GString *movieCommand; // command executed for movie annotations GString *defaultPrinter; // default printer (for interactive printing @@ -597,10 +611,16 @@ private: GBool useTrueTypeUnicodeMapping; // use the Unicode cmaps in TrueType // fonts, rather than the PDF // ToUnicode mapping + GBool ignoreWrongSizeToUnicode; // ignore ToUnicode CMaps if their size + // (8-bit vs 16-bit) doesn't match the font GHash *droppedFonts; // dropped fonts [int] + GBool separateRotatedText; // separate text at each rotation GList *keyBindings; // key & mouse button bindings [KeyBinding] GList *popupMenuCmds; // popup menu commands [PopupMenuCmd] + GString *pagesFile; // path for the page number save file GString *tabStateFile; // path for the tab state save file + GString *sessionFile; // path for the session save file + GBool saveSessionOnQuit; // save session info when xpdf is quit GBool savePageNumbers; // save page number when file is closed // and restore page number when opened GBool printCommands; // print the drawing commands diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc index a077655ef43..0183d3a14f4 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.cc @@ -21,10 +21,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <png.h> #include "gmem.h" @@ -35,6 +31,7 @@ #include "PDFDoc.h" #include "GfxFont.h" #include "AcroForm.h" +#include "TextString.h" #include "TextOutputDev.h" #include "SplashOutputDev.h" #include "ErrorCodes.h" @@ -42,9 +39,11 @@ #include "HTMLGen.h" #ifdef _WIN32 +#ifndef __GNUC__ # define strcasecmp stricmp # define strncasecmp strnicmp #endif +#endif //------------------------------------------------------------------------ @@ -297,6 +296,7 @@ HTMLGen::HTMLGen(double backgroundResolutionA, GBool tableMode) { convertFormFields = gFalse; embedBackgroundImage = gFalse; embedFonts = gFalse; + includeMetadata = gFalse; // set up the TextOutputDev textOutControl.mode = tableMode ? textOutTableLayout : textOutReadingOrder; @@ -312,6 +312,10 @@ HTMLGen::HTMLGen(double backgroundResolutionA, GBool tableMode) { splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); fontDefns = NULL; + + nVisibleChars = 0; + nInvisibleChars = 0; + nRemovedDupChars = 0; } HTMLGen::~HTMLGen() { @@ -462,11 +466,11 @@ int HTMLGen::convertPage( llyI = bitmap->getHeight() - 1; } if (uryI <= llyI && llxI <= urxI) { - SplashColorPtr p = bitmap->getDataPtr() - + uryI * bitmap->getRowSize() + llxI * 3; - for (int y = uryI; y <= llyI; ++y) { - memset(p, 0xff, (urxI - llxI + 1) * 3); - p += bitmap->getRowSize(); + SplashColorPtr pix = bitmap->getDataPtr() + + uryI * bitmap->getRowSize() + llxI * 3; + for (y = uryI; y <= llyI; ++y) { + memset(pix, 0xff, (urxI - llxI + 1) * 3); + pix += bitmap->getRowSize(); } } @@ -483,6 +487,9 @@ int HTMLGen::convertPage( pr(writeHTML, htmlStream, "<html>\n"); pr(writeHTML, htmlStream, "<head>\n"); pr(writeHTML, htmlStream, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"); + if (includeMetadata) { + genDocMetadata(writeHTML, htmlStream); + } pr(writeHTML, htmlStream, "<style type=\"text/css\">\n"); pr(writeHTML, htmlStream, ".txt { white-space:nowrap; }\n"); if (convertFormFields) { @@ -571,6 +578,9 @@ int HTMLGen::convertPage( // generate the HTML text nextFieldID = 0; cols = text->makeColumns(); + nVisibleChars = text->getNumVisibleChars(); + nInvisibleChars = text->getNumInvisibleChars(); + nRemovedDupChars = text->getNumRemovedDupChars(); for (colIdx = 0; colIdx < cols->getLength(); ++colIdx) { col = (TextColumn *)cols->get(colIdx); pars = col->getParagraphs(); @@ -1118,3 +1128,47 @@ void HTMLGen::getFontDetails(TextFontInfo *font, const char **family, *weight = bold ? "bold" : "normal"; *style = italic ? "italic" : "normal"; } + +void HTMLGen::genDocMetadata(int (*writeHTML)(void *stream, + const char *data, int size), + void *htmlStream) { + Object info; + doc->getDocInfo(&info); + if (info.isDict()) { + genDocMetadataItem(writeHTML, htmlStream, info.getDict(), "Title"); + genDocMetadataItem(writeHTML, htmlStream, info.getDict(), "Subject"); + genDocMetadataItem(writeHTML, htmlStream, info.getDict(), "Keywords"); + genDocMetadataItem(writeHTML, htmlStream, info.getDict(), "Author"); + genDocMetadataItem(writeHTML, htmlStream, info.getDict(), "Creator"); + genDocMetadataItem(writeHTML, htmlStream, info.getDict(), "Producer"); + genDocMetadataItem(writeHTML, htmlStream, info.getDict(), "CreationDate"); + genDocMetadataItem(writeHTML, htmlStream, info.getDict(), "ModDate"); + } + info.free(); +} + +void HTMLGen::genDocMetadataItem(int (*writeHTML)(void *stream, + const char *data, int size), + void *htmlStream, + Dict *infoDict, const char *key) { + Object val; + if (infoDict->lookup(key, &val)->isString()) { + GString *s = GString::format("<meta name=\"{0:s}\" content=\"", key); + TextString *ts = new TextString(val.getString()); + Unicode *u = ts->getUnicode(); + for (int i = 0; i < ts->getLength(); ++i) { + if (u[i] == '"') { + s->append("""); + } else if (u[i] == '&') { + s->append("&"); + } else { + appendUTF8(u[i], s); + } + } + delete ts; + s->append("\">\n"); + writeHTML(htmlStream, s->getCString(), s->getLength()); + delete s; + } + val.free(); +} diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h index 66ee2d27406..47e361f78fa 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/HTMLGen.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - class GString; class PDFDoc; class TextOutputDev; @@ -61,6 +57,9 @@ public: void setEmbedFonts(GBool embedFontsA) { embedFonts = embedFontsA; } + void setIncludeMetadata(GBool includeMetadataA) + { includeMetadata = includeMetadataA; } + void startDoc(PDFDoc *docA); int convertPage(int pg, const char *pngURL, const char *htmlDir, int (*writeHTML)(void *stream, const char *data, int size), @@ -68,6 +67,11 @@ public: int (*writePNG)(void *stream, const char *data, int size), void *pngStream); + // Get the counter values. + int getNumVisibleChars() { return nVisibleChars; } + int getNumInvisibleChars() { return nInvisibleChars; } + int getNumRemovedDupChars() { return nRemovedDupChars; } + private: int findDirSpan(GList *words, int firstWordIdx, int primaryDir, @@ -82,6 +86,13 @@ private: void getFontDetails(TextFontInfo *font, const char **family, const char **weight, const char **style, double *scale); + void genDocMetadata(int (*writeHTML)(void *stream, + const char *data, int size), + void *htmlStream); + void genDocMetadataItem(int (*writeHTML)(void *stream, + const char *data, int size), + void *htmlStream, + Dict *infoDict, const char *key); double backgroundResolution; double zoom; @@ -92,6 +103,7 @@ private: GBool convertFormFields; GBool embedBackgroundImage; GBool embedFonts; + GBool includeMetadata; PDFDoc *doc; TextOutputDev *textOut; @@ -107,6 +119,10 @@ private: GList *formFieldInfo; // [HTMLGenFormFieldInfo] int nextFieldID; + int nVisibleChars; // number of visible chars on the page + int nInvisibleChars; // number of invisible chars on the page + int nRemovedDupChars; // number of duplicate chars removed + GBool ok; }; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/ImageOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/ImageOutputDev.cc index 5a694d7b665..2c2db13fa4d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/ImageOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/ImageOutputDev.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -22,6 +18,7 @@ #include "config.h" #include "Error.h" #include "GfxState.h" +#include "Gfx.h" #include "Object.h" #include "Stream.h" #include "ImageOutputDev.h" @@ -52,7 +49,8 @@ void ImageOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, double *mat, double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) { - // do nothing -- this avoids the potentially slow loop in Gfx.cc + // draw the tile once, just in case it contains image(s) + gfx->drawForm(strRef, resDict, mat, bbox); } void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/ImageOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/ImageOutputDev.h index 5a72925aee9..0abe6f1bb55 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/ImageOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/ImageOutputDev.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stdio.h> #include "gtypes.h" #include "OutputDev.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JArithmeticDecoder.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/JArithmeticDecoder.cc index 3d10cb4acad..f00063e8ec2 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JArithmeticDecoder.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JArithmeticDecoder.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmempp.h" #include "Object.h" #include "Stream.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JArithmeticDecoder.h b/Build/source/libs/xpdf/xpdf-src/xpdf/JArithmeticDecoder.h index c0f773fb107..8714b46a9ef 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JArithmeticDecoder.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JArithmeticDecoder.h @@ -13,10 +13,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" class Stream; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc index 02450b4f816..8d71e17f96c 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <limits.h> #include "gmempp.h" @@ -1798,6 +1794,11 @@ GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, break; } } + if (refAggNum <= 0 || refAggNum > 10000) { + error(errSyntaxError, getPos(), + "Invalid refinement/aggregation instance count in JBIG2 symbol dictionary"); + goto syntaxError; + } #if 0 //~ This special case was added about a year before the final draft //~ of the JBIG2 spec was released. I have encountered some old //~ JBIG2 images that predate it. @@ -2440,6 +2441,18 @@ JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; + if (rdw > INT_MAX - syms[symID]->getWidth() || + rdh > INT_MAX - syms[symID]->getHeight()) { + error(errSyntaxError, getPos(), + "Invalid refinement size in JBIG2 text region"); + continue; + } + // sanity check + if (rdw > 1000 || rdh > 1000) { + error(errSyntaxError, getPos(), + "Invalid refinement size in JBIG2 text region"); + continue; + } symbolBitmap = readGenericRefinementRegion(rdw + syms[symID]->getWidth(), rdh + syms[symID]->getHeight(), @@ -2527,7 +2540,8 @@ void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) { !readULong(&grayMax)) { goto eofError; } - if (patternW == 0 || patternH == 0) { + if (patternW == 0 || patternH == 0 || + grayMax > UINT_MAX / patternW - 1) { error(errSyntaxError, getPos(), "Bad size in JBIG2 pattern dictionary segment"); return; @@ -3948,7 +3962,9 @@ void JBIG2Stream::readPageInfoSeg(Guint length) { !readUByte(&flags) || !readUWord(&striping)) { goto eofError; } - if (pageW == 0 || pageH == 0 || pageW > INT_MAX / pageW) { + if (pageW == 0 || pageH == 0 || + pageW > INT_MAX || pageH > INT_MAX || + pageH > INT_MAX / pageW) { error(errSyntaxError, getPos(), "Bad page size in JBIG2 stream"); return; } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h index bb44ba1ab01..4964255bbf7 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JBIG2Stream.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "Object.h" #include "Stream.h" @@ -45,6 +41,7 @@ public: virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); + virtual GBool hasStrongCompression() { return gTrue; } private: diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc index a1f7395dd57..5ed1890a1d3 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <limits.h> #include "gmem.h" #include "gmempp.h" @@ -1117,6 +1113,7 @@ JPXDecodeResult JPXStream::readCodestream(Guint len) { "JPX COC marker segment before COD segment"); return jpxDecodeFatalError; } + comp = 0; if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || @@ -1269,6 +1266,7 @@ JPXDecodeResult JPXStream::readCodestream(Guint len) { "JPX QCC marker segment before QCD segment"); return jpxDecodeFatalError; } + comp = 0; if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || @@ -1641,6 +1639,7 @@ GBool JPXStream::readTilePart() { error(errSyntaxError, getPos(), "Extraneous JPX COC marker segment"); return gFalse; } + comp = 0; if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || @@ -1774,6 +1773,7 @@ GBool JPXStream::readTilePart() { error(errSyntaxError, getPos(), "Extraneous JPX QCC marker segment"); return gFalse; } + comp = 0; if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || @@ -2619,7 +2619,12 @@ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp, if (cb->arithDecoder) { cover(63); - cb->arithDecoder->restart(cb->dataLen[0]); + if (tileComp->codeBlockStyle & 0x04) { + cb->arithDecoder->setStream(bufStr, cb->dataLen[0]); + cb->arithDecoder->start(); + } else { + cb->arithDecoder->restart(cb->dataLen[0]); + } } else { cover(64); cb->arithDecoder = new JArithmeticDecoder(); @@ -3319,7 +3324,7 @@ void JPXStream::inverseTransform1D(JPXTileComp *tileComp, int *data, // converts fixed point samples back to integers. GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { JPXTileComp *tileComp; - int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal; + int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal, shift, rounding; int *dataPtr; Guint j, comp, x, y; @@ -3404,12 +3409,14 @@ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { maxVal = (1 << tileComp->prec) - 1; zeroVal = 1 << (tileComp->prec - 1); dataPtr = tileComp->data; + shift = fracBits - tileComp->prec; + rounding = 1 << (shift - 1); for (y = 0; y < tileComp->h; ++y) { for (x = 0; x < tileComp->w; ++x) { coeff = *dataPtr; if (tileComp->transform == 0) { cover(112); - coeff >>= fracBits - tileComp->prec; + coeff = (coeff + rounding) >> shift; } coeff += zeroVal; if (coeff < 0) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h index 4b8587b0fb2..ce12427ced9 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "Object.h" #include "Stream.h" @@ -291,6 +287,7 @@ public: virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); + virtual GBool hasStrongCompression() { return gTrue; } virtual void getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMode); void reduceResolution(int reductionA) { reduction = reductionA; } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc index 0c74dbb04ea..d1066d33837 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <stddef.h> #include <string.h> @@ -113,7 +109,7 @@ Object *Lexer::getObj(Object *obj) { char *p; int c, c2; GBool comment, neg, doubleMinus, done, invalid; - int numParen; + int numParen, nErrors; int xi; double xf, scale; GString *s; @@ -434,7 +430,8 @@ Object *Lexer::getObj(Object *obj) { m = n = 0; c2 = 0; s = NULL; - while (1) { + nErrors = 0; + while (nErrors < 100) { c = getChar(); if (c == '>') { break; @@ -443,15 +440,17 @@ Object *Lexer::getObj(Object *obj) { break; } else if (specialChars[c] != 1) { c2 = c2 << 4; - if (c >= '0' && c <= '9') + if (c >= '0' && c <= '9') { c2 += c - '0'; - else if (c >= 'A' && c <= 'F') + } else if (c >= 'A' && c <= 'F') { c2 += c - 'A' + 10; - else if (c >= 'a' && c <= 'f') + } else if (c >= 'a' && c <= 'f') { c2 += c - 'a' + 10; - else + } else { error(errSyntaxError, getPos(), "Illegal character <{0:02x}> in hex string", c); + ++nErrors; + } if (++m == 2) { if (n == tokBufSize) { if (!s) diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.h index d481c2c5a2b..458a5851584 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Lexer.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "Object.h" #include "Stream.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Link.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Link.cc index 900f79ddf85..60f20867338 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Link.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Link.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stddef.h> #include <string.h> #include "gmem.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Link.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Link.h index 480496ad176..d6155447e92 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Link.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Link.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "Object.h" class GString; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/NameToCharCode.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/NameToCharCode.cc index f846d8e940d..0088986d2f0 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/NameToCharCode.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/NameToCharCode.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <string.h> #include "gmem.h" #include "gmempp.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/NameToCharCode.h b/Build/source/libs/xpdf/xpdf-src/xpdf/NameToCharCode.h index 6548133cdcd..cf2170bfd46 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/NameToCharCode.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/NameToCharCode.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "CharTypes.h" struct NameToCharCodeEntry; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Object.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Object.cc index 898fbc99e2b..dbb785868c8 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Object.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Object.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stddef.h> #include "gmempp.h" #include "Object.h" @@ -42,7 +38,7 @@ const char *objTypeNames[numObjTypes] = { "none" }; -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM #if MULTITHREADED GAtomicCounter Object::numAlloc[numObjTypes] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -50,7 +46,7 @@ GAtomicCounter Object::numAlloc[numObjTypes] = long Object::numAlloc[numObjTypes] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; #endif -#endif // DEBUG_MEM +#endif // DEBUG_OBJECT_MEM Object *Object::initArray(XRef *xref) { initObj(objArray); @@ -101,7 +97,7 @@ Object *Object::copy(Object *obj) { default: break; } -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM #if MULTITHREADED gAtomicIncrement(&numAlloc[type]); #else @@ -143,7 +139,7 @@ void Object::free() { default: break; } -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM #if MULTITHREADED gAtomicDecrement(&numAlloc[type]); #else @@ -225,7 +221,7 @@ void Object::print(FILE *f) { } void Object::memCheck(FILE *f) { -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM int i; long t; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Object.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Object.h index cb636510149..17c082041b7 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Object.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Object.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stdio.h> #include <string.h> #include "gtypes.h" @@ -71,7 +67,7 @@ enum ObjType { // Object //------------------------------------------------------------------------ -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM # if MULTITHREADED # define initObj(t) gAtomicIncrement(&numAlloc[type = t]) # else @@ -216,7 +212,7 @@ private: char *cmd; // command }; -#ifdef DEBUG_MEM +#ifdef DEBUG_OBJECT_MEM #if MULTITHREADED static GAtomicCounter // number of each type of object numAlloc[numObjTypes]; // currently allocated diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/OptionalContent.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/OptionalContent.cc index a0fbb1b06c2..501ad2d1220 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/OptionalContent.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/OptionalContent.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmempp.h" #include "GString.h" #include "GList.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/OptionalContent.h b/Build/source/libs/xpdf/xpdf-src/xpdf/OptionalContent.h index f00ef296a0c..f4eb1e95cb7 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/OptionalContent.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/OptionalContent.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "Object.h" #include "CharTypes.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Outline.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Outline.cc index 9593956f8d0..09e3b754bef 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Outline.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Outline.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmem.h" #include "gmempp.h" #include "GString.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Outline.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Outline.h index e9bce83cdad..80943ab8be9 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Outline.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Outline.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "Object.h" #include "CharTypes.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.cc index f2be88edfdc..93dc1bc1273 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stddef.h> #include "gmempp.h" #include "Object.h" @@ -76,6 +72,15 @@ void OutputDev::updateAll(GfxState *state) { updateFont(state); } +void OutputDev::fillStroke(GfxState *state, GBool eo) { + if (eo) { + eoFill(state); + } else { + fill(state); + } + stroke(state); +} + GBool OutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h index 54483cfcc43..0b31d14a50c 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/OutputDev.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "CharTypes.h" @@ -99,6 +95,10 @@ public: // End a page. virtual void endPage() {} + // Start/end a sub-page stream (Form XObject, annotation). + virtual void startStream(Ref streamRef, GfxState *state) {} + virtual void endStream(Ref streamRef) {} + //----- coordinate conversion // Convert between device and user coordinates. @@ -147,13 +147,12 @@ public: virtual void updateHorizScaling(GfxState *state) {} virtual void updateTextPos(GfxState *state) {} virtual void updateTextShift(GfxState *state, double shift) {} - virtual void saveTextPos(GfxState *state) {} - virtual void restoreTextPos(GfxState *state) {} //----- path painting virtual void stroke(GfxState *state) {} virtual void fill(GfxState *state) {} virtual void eoFill(GfxState *state) {} + virtual void fillStroke(GfxState *state, GBool eo); virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, int paintType, int tilingType, Dict *resDict, double *mat, double *bbox, @@ -175,8 +174,17 @@ public: virtual void drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, - CharCode code, int nBytes, Unicode *u, int uLen) {} - virtual void drawString(GfxState *state, GString *s) {} + CharCode code, int nBytes, Unicode *u, int uLen, + GBool fill, GBool stroke, GBool makePath) {} + virtual void drawString(GfxState *state, GString *s, + GBool fill, GBool stroke, GBool makePath) {} + virtual void fillTextPath(GfxState *state) {} + virtual void strokeTextPath(GfxState *state) {} + virtual void clipToTextPath(GfxState *state) {} + virtual void clipToTextStrokePath(GfxState *state) {} + virtual void clearTextPath(GfxState *state) {} + virtual void addTextPathToSavedClipPath(GfxState *state) {} + virtual void clipToSavedClipPath(GfxState *state) {} virtual GBool beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen); @@ -242,6 +250,10 @@ public: //----- links virtual void processLink(Link *link) {} + //----- structure tree + virtual void beginStructureItem(const char *tag, int mcid, Dict *dict) {} + virtual void endStructureItem() {} + private: double defCTM[6]; // default coordinate transform matrix diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDF417Barcode.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PDF417Barcode.cc index 0dd35ee4902..bb273b6161d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDF417Barcode.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDF417Barcode.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <math.h> #include "gtypes.h" #include "GString.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDF417Barcode.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PDF417Barcode.h index 8166865280b..c86f1df4508 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDF417Barcode.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDF417Barcode.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - class GString; // Draw a PDF417 barcode: diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc index b833d5dabf0..baf2353de1c 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <math.h> #include "gmempp.h" #include "GString.h" @@ -47,9 +43,6 @@ PDFCore::PDFCore(SplashColorMode colorMode, int bitmapRowPad, linksPage = 0; links = NULL; - annotsPage = 0; - annots = NULL; - textPage = 0; textDPI = 0; textRotate = 0; @@ -116,6 +109,7 @@ PDFCore::~PDFCore() { delete state; clearPage(); if (doc) { + aboutToDeleteDoc(); delete doc; } for (i = 0; i < pdfHistorySize; ++i) { @@ -201,6 +195,7 @@ int PDFCore::loadFile2(PDFDoc *newDoc) { // NB: do not delete doc until after DisplayState::setDoc() returns state->setDoc(newDoc); if (doc) { + aboutToDeleteDoc(); delete doc; } doc = newDoc; @@ -219,6 +214,7 @@ void PDFCore::clear() { // no document // NB: do not delete doc until after DisplayState::setDoc() returns state->setDoc(NULL); + aboutToDeleteDoc(); delete doc; doc = NULL; clearPage(); @@ -300,6 +296,8 @@ void PDFCore::displayDest(LinkDest *dest) { page = 1; } + GBool changeZoom = globalParams->getAllowLinksToChangeZoom(); + switch (dest->getKind()) { case destXYZ: cvtUserToDev(page, dest->getLeft(), dest->getTop(), &dx, &dy); @@ -317,7 +315,9 @@ void PDFCore::displayDest(LinkDest *dest) { break; case destFit: case destFitB: - state->setZoom(zoomPage); + if (changeZoom) { + state->setZoom(zoomPage); + } scrollX = tileMap->getPageLeftX(page); scrollY = tileMap->getPageTopY(page); startUpdate(); @@ -326,7 +326,9 @@ void PDFCore::displayDest(LinkDest *dest) { break; case destFitH: case destFitBH: - state->setZoom(zoomWidth); + if (changeZoom) { + state->setZoom(zoomWidth); + } scrollX = tileMap->getPageLeftX(page); scrollY = tileMap->getPageTopY(page); if (dest->getChangeTop()) { @@ -339,7 +341,9 @@ void PDFCore::displayDest(LinkDest *dest) { break; case destFitV: case destFitBV: - state->setZoom(zoomHeight); + if (changeZoom) { + state->setZoom(zoomHeight); + } scrollX = tileMap->getPageLeftX(page); scrollY = tileMap->getPageTopY(page); if (dest->getChangeTop()) { @@ -351,8 +355,13 @@ void PDFCore::displayDest(LinkDest *dest) { finishUpdate(gTrue, gTrue); break; case destFitR: - zoomToRect(page, dest->getLeft(), dest->getTop(), - dest->getRight(), dest->getBottom()); + if (changeZoom) { + zoomToRect(page, dest->getLeft(), dest->getTop(), + dest->getRight(), dest->getBottom()); + } else { + scrollToCentered(page, 0.5 * (dest->getLeft() + dest->getRight()), + 0.5 * (dest->getTop(), dest->getBottom())); + } break; } } @@ -426,9 +435,16 @@ void PDFCore::finishUpdate(GBool addToHist, GBool checkForChangedFile) { // tileDone or tick (incremental update) to avoid "flashing" the // screen (drawing a blank background, followed by the actual // content slightly later) - getWindowBitmap(gTrue); - if (bitmapFinished) { + // - this postponement actually causes flickering in certain cases + // (the Qt QML backend) -- don't do it if alwaysInvalidateOnUpdate() + // returns true + if (alwaysInvalidateOnUpdate()) { invalidateWholeWindow(); + } else { + getWindowBitmap(gTrue); + if (bitmapFinished) { + invalidateWholeWindow(); + } } updateScrollbars(); @@ -1637,6 +1653,50 @@ GList *PDFCore::findAll(Unicode *u, int len, GBool caseSensitive, return results; } +GList *AsyncFindAll::run(PDFDoc *doc, Unicode *u, int len, GBool caseSensitive, + GBool wholeWord, int firstPage, int lastPage) { + GList *results = new GList(); + + TextOutputDev *textOut = new TextOutputDev(NULL, &core->textOutCtrl, gFalse); + if (!textOut->isOk()) { + delete textOut; + return results; + } + + for (int pg = firstPage; pg <= lastPage && !canceled; ++pg) { + doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse); + GBool first = gTrue; + while (!canceled) { + double xMin, yMin, xMax, yMax; + if (!textOut->findText(u, len, first, gTrue, !first, gFalse, + caseSensitive, gFalse, wholeWord, + &xMin, &yMin, &xMax, &yMax)) { + break; + } + double uxMin, uyMin, uxMax, uyMax, t; + textOut->cvtDevToUser(xMin, yMin, &uxMin, &uyMin); + textOut->cvtDevToUser(xMax, yMax, &uxMax, &uyMax); + if (uxMin > uxMax) { + t = uxMin; uxMin = uxMax; uxMax = t; + } + if (uyMin > uyMax) { + t = uyMin; uyMin = uyMax; uyMax = t; + } + results->append(new FindResult(pg, uxMin, uyMin, uxMax, uyMax)); + first = gFalse; + } + } + + delete textOut; + + if (canceled) { + deleteGList(results, FindResult); + return NULL; + } + + return results; +} + GBool PDFCore::cvtWindowToUser(int xw, int yw, int *pg, double *xu, double *yu) { @@ -1751,23 +1811,11 @@ LinkAction *PDFCore::findLink(int pg, double x, double y) { } Annot *PDFCore::findAnnot(int pg, double x, double y) { - loadAnnots(pg); - return annots->find(x, y); + return doc->getAnnots()->find(pg, x, y); } int PDFCore::findAnnotIdx(int pg, double x, double y) { - loadAnnots(pg); - return annots->findIdx(x, y); -} - -Annot *PDFCore::getAnnot(int idx) { - if (!annots) { - return NULL; - } - if (idx < 0 || idx >= annots->getNumAnnots()) { - return NULL; - } - return annots->getAnnot(idx); + return doc->getAnnots()->findIdx(pg, x, y); } AcroFormField *PDFCore::findFormField(int pg, double x, double y) { @@ -1816,7 +1864,8 @@ void PDFCore::setWindowSize(int winWidth, int winHeight) { startUpdate(); - wx0 = wy0 = 0; // make gcc happy + page = wx0 = wy0 = 0; // make gcc happy + ux = uy = 0; doScroll = gFalse; if (state->getZoom() < 0 && state->displayModeIsContinuous()) { // save the user coordinates of the appropriate edge of the window @@ -1879,12 +1928,6 @@ void PDFCore::clearPage() { links = NULL; linksPage = 0; - if (annots) { - delete annots; - } - annots = NULL; - annotsPage = 0; - if (text) { delete text; } @@ -1906,22 +1949,6 @@ void PDFCore::loadLinks(int pg) { linksPage = pg; } -// Load the annotations for <pg>. -void PDFCore::loadAnnots(int pg) { - Object annotsObj; - - if (annots && annotsPage == pg) { - return; - } - if (annots) { - delete annots; - } - doc->getCatalog()->getPage(pg)->getAnnots(&annotsObj); - annots = new Annots(doc, &annotsObj); - annotsObj.free(); - annotsPage = pg; -} - // Extract text from <pg>. void PDFCore::loadText(int pg) { TextOutputDev *textOut; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h index accf19d82ef..56ecd958c21 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFCore.h @@ -11,11 +11,10 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stdlib.h> +#ifndef PDF_PARSER_ONLY +#include <atomic> +#endif #include "SplashTypes.h" #include "CharTypes.h" #include "DisplayState.h" @@ -31,7 +30,6 @@ class Links; class LinkDest; class LinkAction; class Annot; -class Annots; class AcroFormField; class TextPage; class HighlightFile; @@ -77,6 +75,34 @@ struct FindResult { }; //------------------------------------------------------------------------ +// AsyncFindAll +//------------------------------------------------------------------------ +#ifndef PDF_PARSER_ONLY +class AsyncFindAll { +public: + + AsyncFindAll(PDFCore *coreA): core(coreA), canceled(gFalse) {} + + void reset() { canceled = false; } + + // Run the search, returning a list of FindResults -- same as + // PDFCore::findAll(). This can be run on a separate thread. If + // cancel() is called while the search is running, this function + // returns null. + GList *run(PDFDoc *doc, Unicode *u, int len, GBool caseSensitive, + GBool wholeWord, int firstPage, int lastPage); + + // Cancel a running search, causing run() to return null. + void cancel() { canceled = true; } + +private: + + PDFCore *core; + std::atomic<bool> canceled; +}; +#endif + +//------------------------------------------------------------------------ // PDFCore //------------------------------------------------------------------------ @@ -256,7 +282,6 @@ public: LinkAction *findLink(int pg, double x, double y); Annot *findAnnot(int pg, double x, double y); int findAnnotIdx(int pg, double x, double y); - Annot *getAnnot(int idx); AcroFormField *findFormField(int pg, double x, double y); int findFormFieldIdx(int pg, double x, double y); AcroFormField *getFormField(int idx); @@ -288,6 +313,11 @@ protected: //--- callbacks to PDFCore subclass + // Subclasses can return true here to force PDFCore::finishUpdate() + // to always invalidate the window. This is necessary to avoid + // flickering on some backends. + virtual GBool alwaysInvalidateOnUpdate() { return gFalse; } + // Invalidate the specified rectangle (in window coordinates). virtual void invalidate(int x, int y, int w, int h) = 0; @@ -304,13 +334,17 @@ protected: // This is called just after a PDF file is loaded. virtual void postLoad() {} + // This is called just before deleting the PDFDoc. The PDFCore + // subclass must shut down any secondary threads that are using the + // PDFDoc pointer. + virtual void aboutToDeleteDoc() {} + //--- internal int loadFile2(PDFDoc *newDoc); void addToHistory(); void clearPage(); void loadLinks(int pg); - void loadAnnots(int pg); void loadText(int pg); void getSelectionBBox(int *wxMin, int *wyMin, int *wxMax, int *wyMax); void getSelectRectListBBox(GList *rects, int *wxMin, int *wyMin, @@ -318,14 +352,13 @@ protected: void checkInvalidate(int x, int y, int w, int h); void invalidateWholeWindow(); + friend class AsyncFindAll; + PDFDoc *doc; int linksPage; // cached links for one page Links *links; - int annotsPage; // cached annotations for one page - Annots *annots; - int textPage; // cached extracted text for one page double textDPI; int textRotate; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc index a6663ea4222..7030904214f 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -26,6 +22,7 @@ #include "GlobalParams.h" #include "Page.h" #include "Catalog.h" +#include "Annot.h" #include "Stream.h" #include "XRef.h" #include "Link.h" @@ -178,6 +175,7 @@ PDFDoc::PDFDoc(char *fileNameA, GString *ownerPassword, int i, j; #endif #endif /* 0 */ + init(coreA); fileName = new GString(fileNameA); @@ -204,7 +202,7 @@ PDFDoc::PDFDoc(char *fileNameA, GString *ownerPassword, file = _wfopen(fileNameU, wfopenReadMode); } else { #endif /* 0 */ - file = fopen(fileName->getCString(), fopenReadMode); + file = fopen(fileName->getCString(), fopenReadMode); #if 0 } #endif /* 0 */ @@ -263,6 +261,7 @@ void PDFDoc::init(PDFCore *coreA) { str = NULL; xref = NULL; catalog = NULL; + annots = NULL; #ifndef DISABLE_OUTLINE outline = NULL; #endif @@ -335,6 +334,9 @@ GBool PDFDoc::setup2(GString *ownerPassword, GString *userPassword, return gFalse; } + // initialize the Annots object + annots = new Annots(this); + return gTrue; } @@ -347,6 +349,9 @@ PDFDoc::~PDFDoc() { delete outline; } #endif + if (annots) { + delete annots; + } if (catalog) { delete catalog; } @@ -485,6 +490,7 @@ void PDFDoc::displayPageSlice(OutputDev *out, int page, abortCheckCbk, abortCheckCbkData); } + Links *PDFDoc::getLinks(int page) { return catalog->getPage(page)->getLinks(); } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h index 2b8eba2cba7..3c1c71c41ed 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PDFDoc.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stdio.h> #include "XRef.h" #include "Catalog.h" @@ -23,6 +19,7 @@ class GString; class BaseStream; class OutputDev; +class Annots; class Links; class LinkAction; class LinkDest; @@ -74,6 +71,9 @@ public: // Get catalog. Catalog *getCatalog() { return catalog; } + // Get annotations. + Annots *getAnnots() { return annots; } + // Get base stream. BaseStream *getBaseStream() { return str; } @@ -121,6 +121,7 @@ public: GBool (*abortCheckCbk)(void *data) = NULL, void *abortCheckCbkData = NULL); + // Find a page, given its object ID. Returns page number, or 0 if // not found. int findPage(int num, int gen) { return catalog->findPage(num, gen); } @@ -195,6 +196,9 @@ public: #endif char *getEmbeddedFileMem(int idx, int *size); + // Return true if the document uses JavaScript. + GBool usesJavaScript() { return catalog->usesJavaScript(); } + private: @@ -216,6 +220,7 @@ private: double pdfVersion; XRef *xref; Catalog *catalog; + Annots *annots; #ifndef DISABLE_OUTLINE Outline *outline; #endif diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc index b9fff4ffaed..4cb4304e172 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stddef.h> #include <stdarg.h> @@ -108,7 +104,8 @@ static const char *prolog[] = { "/pdfOpNames [", " /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke", " /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender", - " /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath", + " /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextPath", + " /pdfTextClipPath", "] def", "~123ngs", "/pdfStartPage {", @@ -145,6 +142,7 @@ static const char *prolog[] = { " /pdfTextRise 0 def", " /pdfWordSpacing 0 def", " /pdfHorizScaling 1 def", + " /pdfTextPath [] def", " /pdfTextClipPath [] def", "} def", "/pdfEndPage { end } def", @@ -475,32 +473,34 @@ static const char *prolog[] = { "/Tj {", " fCol", // because stringwidth has to draw Type 3 chars " 0 pdfTextRise pdfTextMat dtransform rmoveto", - " currentpoint 4 2 roll", - " pdfTextRender 1 and 0 eq {", - " 2 copy xyshow2", - " } if", - " pdfTextRender 3 and dup 1 eq exch 2 eq or {", - " 3 index 3 index moveto", - " 2 copy", - " currentfont /FontType get 3 eq { fCol } { sCol } ifelse", - " xycp currentpoint stroke moveto", - " } if", - " pdfTextRender 4 and 0 ne {", - " 4 2 roll moveto xycp", - " /pdfTextClipPath [ pdfTextClipPath aload pop", - " {/moveto cvx}", - " {/lineto cvx}", - " {/curveto cvx}", - " {/closepath cvx}", - " pathforall ] def", - " currentpoint newpath moveto", - " } {", - " pop pop pop pop", - " } ifelse", + " xyshow2", + " 0 pdfTextRise neg pdfTextMat dtransform rmoveto", + "} def", + "/TjS {", + " fCol", // because stringwidth has to draw Type 3 chars + " 0 pdfTextRise pdfTextMat dtransform rmoveto", + " currentfont /FontType get 3 eq { fCol } { sCol } ifelse", + " xycp currentpoint stroke moveto", + " 0 pdfTextRise neg pdfTextMat dtransform rmoveto", + "} def", + "/TjFS {", + " 2 copy currentpoint 4 2 roll Tj moveto TjS", + "} def", + "/TjSave {", + " fCol", // because stringwidth has to draw Type 3 chars + " 0 pdfTextRise pdfTextMat dtransform rmoveto", + " xycp", + " /pdfTextPath [ pdfTextPath aload pop", + " {/moveto cvx}", + " {/lineto cvx}", + " {/curveto cvx}", + " {/closepath cvx}", + " pathforall ] def", + " currentpoint newpath moveto", " 0 pdfTextRise neg pdfTextMat dtransform rmoveto", "} def", "/Tj3 {", - " pdfTextRender 3 and 3 ne {" + " pdfTextRender 3 and 3 ne {", " fCol", // because stringwidth has to draw Type 3 chars " 0 pdfTextRise pdfTextMat dtransform rmoveto", " xyshow2", @@ -513,8 +513,18 @@ static const char *prolog[] = { " pdfTextMat dtransform rmoveto } def", "/TJmV { 0.001 mul pdfFontSize mul neg 0 exch", " pdfTextMat dtransform rmoveto } def", - "/Tclip { pdfTextClipPath cvx exec clip newpath", - " /pdfTextClipPath [] def } def", + "/Tfill { fCol pdfTextPath cvx exec fill } def", + "/Tstroke { sCol pdfTextPath cvx exec stroke } def", + "/Tclip { pdfTextPath cvx exec clip newpath } def", + "/Tstrokeclip { pdfTextPath cvx exec strokepath clip newpath } def", + "/Tclear { /pdfTextPath [] def } def", + "/Tsave {", + " /pdfTextClipPath [ pdfTextClipPath aload pop pdfTextPath aload pop ] def", + "} def", + "/Tclip2 {", + " pdfTextClipPath cvx exec clip newpath", + " /pdfTextClipPath [] def", + "} def", "~1ns", "% Level 1 image operators", "~1n", @@ -1309,7 +1319,8 @@ PSOutputDev::PSOutputDev(char *fileName, PDFDoc *docA, paperSizes = NULL; embFontList = NULL; customColors = NULL; - haveTextClip = gFalse; + haveSavedTextPath = gFalse; + haveSavedClipPath = gFalse; t3String = NULL; // open file or pipe @@ -1376,7 +1387,8 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, paperSizes = NULL; embFontList = NULL; customColors = NULL; - haveTextClip = gFalse; + haveSavedTextPath = gFalse; + haveSavedClipPath = gFalse; t3String = NULL; init(outputFuncA, outputStreamA, psGeneric, @@ -1748,7 +1760,6 @@ void PSOutputDev::writeXpdfProcset() { void PSOutputDev::writeDocSetup(Catalog *catalog) { Page *page; Dict *resDict; - Annots *annots; AcroForm *form; Object obj1, obj2, obj3; GString *s; @@ -1774,6 +1785,7 @@ void PSOutputDev::writeDocSetup(Catalog *catalog) { } else { writePS("xpdf begin\n"); } + Annots *annots = doc->getAnnots(); needDefaultFont = gFalse; for (pg = firstPage; pg <= lastPage; ++pg) { if (rasterizePage[pg - firstPage]) { @@ -1783,13 +1795,12 @@ void PSOutputDev::writeDocSetup(Catalog *catalog) { if ((resDict = page->getResourceDict())) { setupResources(resDict); } - annots = new Annots(doc, page->getAnnots(&obj1)); - obj1.free(); - if (annots->getNumAnnots()) { + int nAnnots = annots->getNumAnnots(pg); + if (nAnnots > 0) { needDefaultFont = gTrue; } - for (i = 0; i < annots->getNumAnnots(); ++i) { - if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { + for (i = 0; i < nAnnots; ++i) { + if (annots->getAnnot(pg, i)->getAppearance(&obj1)->isStream()) { obj1.streamGetDict()->lookup("Resources", &obj2); if (obj2.isDict()) { setupResources(obj2.getDict()); @@ -1798,7 +1809,6 @@ void PSOutputDev::writeDocSetup(Catalog *catalog) { } obj1.free(); } - delete annots; } if ((form = catalog->getForm())) { if (form->getNumFields() > 0) { @@ -2150,6 +2160,9 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { case fontType1: fi->ff = setupExternalType1Font(font, fontLoc->path); break; + case fontType1COT: + fi->ff = setupExternalOpenTypeT1CFont(font, fontLoc->path); + break; case fontTrueType: case fontTrueTypeOT: fi->ff = setupExternalTrueTypeFont(font, fontLoc->path, @@ -2573,6 +2586,48 @@ PSFontFileInfo *PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, return ff; } +PSFontFileInfo *PSOutputDev::setupExternalOpenTypeT1CFont(GfxFont *font, + GString *fileName) { + GString *psName; + PSFontFileInfo *ff; + FoFiTrueType *ffTT; + + if (font->getName()) { + // check if font is already embedded + if ((ff = (PSFontFileInfo *)fontFileInfo->lookup(font->getName()))) { + return ff; + } + // this assumes that the PS font name matches the PDF font name + psName = font->getName()->copy(); + } else { + // generate name + psName = makePSFontName(font, font->getID()); + } + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 1 font + if ((ffTT = FoFiTrueType::load(fileName->getCString(), 0, gTrue))) { + if (ffTT->isOpenTypeCFF()) { + ffTT->convertToType1(psName->getCString(), NULL, gTrue, + outputFunc, outputStream); + } + delete ffTT; + } + + // ending comment + writePS("%%EndResource\n"); + + ff = new PSFontFileInfo(psName, font->getType(), psFontFileExternal); + ff->extFileName = fileName->copy(); + fontFileInfo->add(ff->psName, ff); + return ff; +} + PSFontFileInfo *PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id) { GString *psName; PSFontFileInfo *ff; @@ -3867,8 +3922,14 @@ void PSOutputDev::setupImage(Ref id, Stream *str, GBool mask, } else { s = str->getPSFilter(level < psLevel3 ? 2 : 3, "", gTrue); if (s) { - useLZW = useRLE = gFalse; - useCompressed = gTrue; + if (globalParams->getPSLZW() && !str->hasStrongCompression()) { + useRLE = gFalse; + useLZW = gTrue; + useCompressed = gFalse; + } else { + useLZW = useRLE = gFalse; + useCompressed = gTrue; + } delete s; } else { if (globalParams->getPSLZW()) { @@ -4541,10 +4602,21 @@ void PSOutputDev::startPage(int pageNum, GfxState *state) { tx -= xScale * x1; ty -= yScale * y1; } - // center + // offset or center if (tx0 >= 0 && ty0 >= 0) { - tx += (rotate == 0 || rotate == 180) ? tx0 : ty0; - ty += (rotate == 0 || rotate == 180) ? ty0 : -tx0; + if (rotate == 0) { + tx += tx0; + ty += ty0; + } else if (rotate == 90) { + tx += ty0; + ty += (imgWidth - yScale * height) - tx0; + } else if (rotate == 180) { + tx += (imgWidth - xScale * width) - tx0; + ty += (imgHeight - yScale * height) - ty0; + } else { // rotate == 270 + tx += (imgHeight - xScale * width) - ty0; + ty += tx0; + } } else if (globalParams->getPSCenter()) { if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { tx += (imgWidth2 - xScale * (clipURX0 - clipLLX0)) / 2; @@ -5103,16 +5175,6 @@ void PSOutputDev::updateTextShift(GfxState *state, double shift) { noStateChanges = gFalse; } -void PSOutputDev::saveTextPos(GfxState *state) { - writePS("currentpoint\n"); - noStateChanges = gFalse; -} - -void PSOutputDev::restoreTextPos(GfxState *state) { - writePS("m\n"); - noStateChanges = gFalse; -} - void PSOutputDev::stroke(GfxState *state) { doPath(state->getPath()); if (inType3Char && t3FillColorOnly) { @@ -5766,23 +5828,10 @@ void PSOutputDev::doPath(GfxPath *path) { } } -void PSOutputDev::drawString(GfxState *state, GString *s) { - GfxFont *font; - int wMode; - int *codeToGID; - GString *s2; - double dx, dy, originX, originY, originX0, originY0, tOriginX0, tOriginY0; - char *p; - PSFontInfo *fi; - UnicodeMap *uMap; - CharCode code; - Unicode u[8]; - char buf[8]; - double *dxdy; - int dxdySize, len, nChars, uLen, n, m, i, j; - +void PSOutputDev::drawString(GfxState *state, GString *s, + GBool fill, GBool stroke, GBool makePath) { // check for invisible text -- this is used by Acrobat Capture - if (state->getRender() == 3) { + if (!fill && !stroke && !makePath) { return; } @@ -5792,13 +5841,14 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { } // get the font - if (!(font = state->getFont())) { + GfxFont *font = state->getFont(); + if (!font) { return; } - wMode = font->getWMode(); + int wMode = font->getWMode(); - fi = NULL; - for (i = 0; i < fontInfo->getLength(); ++i) { + PSFontInfo *fi = NULL; + for (int i = 0; i < fontInfo->getLength(); ++i) { fi = (PSFontInfo *)fontInfo->get(i); if (fi->fontID.num == font->getID()->num && fi->fontID.gen == font->getID()->gen) { @@ -5808,8 +5858,8 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { } // check for a subtitute 16-bit font - uMap = NULL; - codeToGID = NULL; + UnicodeMap *uMap = NULL; + int *codeToGID = NULL; if (font->isCIDFont()) { if (!(fi && fi->ff)) { // font substitution failed, so don't output any text @@ -5827,17 +5877,21 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { } // compute the positioning (dx, dy) for each char in the string - nChars = 0; - p = s->getCString(); - len = s->getLength(); - s2 = new GString(); - dxdySize = font->isCIDFont() ? 8 : s->getLength(); - dxdy = (double *)gmallocn(2 * dxdySize, sizeof(double)); - originX0 = originY0 = 0; // make gcc happy + int nChars = 0; + char *p = s->getCString(); + int len = s->getLength(); + GString *s2 = new GString(); + int dxdySize = font->isCIDFont() ? 8 : s->getLength(); + double *dxdy = (double *)gmallocn(2 * dxdySize, sizeof(double)); + double originX0 = 0, originY0 = 0; while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx, dy, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); //~ this doesn't handle the case where the origin offset changes //~ within a string of characters -- which could be fixed by //~ modifying dx,dy as needed for each character @@ -5867,9 +5921,10 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { } while (nChars + uLen > dxdySize); dxdy = (double *)greallocn(dxdy, 2 * dxdySize, sizeof(double)); } - for (i = 0; i < uLen; ++i) { - m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf)); - for (j = 0; j < m; ++j) { + char buf[8]; + for (int i = 0; i < uLen; ++i) { + int m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf)); + for (int j = 0; j < m; ++j) { s2->append(buf[j]); } //~ this really needs to get the number of chars in the target @@ -5906,25 +5961,45 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { } originX0 *= state->getFontSize(); originY0 *= state->getFontSize(); + double tOriginX0, tOriginY0; state->textTransformDelta(originX0, originY0, &tOriginX0, &tOriginY0); if (nChars > 0) { if (wMode) { writePSFmt("{0:.6g} {1:.6g} rmoveto\n", -tOriginX0, -tOriginY0); } + writePSString(s2); writePS("\n["); - for (i = 0; i < 2 * nChars; ++i) { + for (int i = 0; i < 2 * nChars; ++i) { if (i > 0) { writePS("\n"); } writePSFmt("{0:.6g}", dxdy[i]); } + writePS("] "); + + // the possible operations are: + // - fill + // - stroke + // - fill + stroke + // - makePath + if (font->getType() == fontType3) { - writePS("] Tj3\n"); + writePS("Tj3\n"); } else { - writePS("] Tj\n"); + if (fill && stroke) { + writePS("TjFS\n"); + } else if (fill) { + writePS("Tj\n"); + } else if (stroke) { + writePS("TjS\n"); + } else if (makePath) { + writePS("TjSave\n"); + haveSavedTextPath = gTrue; + } } + if (wMode) { writePSFmt("{0:.6g} {1:.6g} rmoveto\n", tOriginX0, tOriginY0); } @@ -5932,19 +6007,49 @@ void PSOutputDev::drawString(GfxState *state, GString *s) { gfree(dxdy); delete s2; - if ((state->getRender() & 4) && font->getType() != fontType3) { - haveTextClip = gTrue; + noStateChanges = gFalse; +} + +void PSOutputDev::fillTextPath(GfxState *state) { + writePS("Tfill\n"); +} + +void PSOutputDev::strokeTextPath(GfxState *state) { + writePS("Tstroke\n"); +} + +void PSOutputDev::clipToTextPath(GfxState *state) { + writePS("Tclip\n"); +} + +void PSOutputDev::clipToTextStrokePath(GfxState *state) { + writePS("Tstrokeclip\n"); +} + +void PSOutputDev::clearTextPath(GfxState *state) { + if (haveSavedTextPath) { + writePS("Tclear\n"); + haveSavedTextPath = gFalse; } +} - noStateChanges = gFalse; +void PSOutputDev::addTextPathToSavedClipPath(GfxState *state) { + if (haveSavedTextPath) { + writePS("Tsave\n"); + haveSavedTextPath = gFalse; + haveSavedClipPath = gTrue; + } } -void PSOutputDev::endTextObject(GfxState *state) { - if (haveTextClip) { - writePS("Tclip\n"); - haveTextClip = gFalse; - noStateChanges = gFalse; +void PSOutputDev::clipToSavedClipPath(GfxState *state) { + if (!haveSavedClipPath) { + return; } + writePS("Tclip2\n"); + haveSavedClipPath = gFalse; +} + +void PSOutputDev::endTextObject(GfxState *state) { } void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, @@ -6396,6 +6501,11 @@ void PSOutputDev::doImageL2(Object *ref, GfxState *state, } useASCII = !(mode == psModeForm || inType3Char || preload); useCompressed = gFalse; + } else if (globalParams->getPSLZW() && !str->hasStrongCompression()) { + useRLE = gFalse; + useLZW = gTrue; + useASCII = !(mode == psModeForm || inType3Char || preload); + useCompressed = gFalse; } else { useLZW = useRLE = gFalse; useASCII = str->isBinary() && @@ -6869,6 +6979,11 @@ void PSOutputDev::doImageL3(Object *ref, GfxState *state, } maskUseASCII = !(mode == psModeForm || inType3Char || preload); maskUseCompressed = gFalse; + } else if (globalParams->getPSLZW() && !maskStr->hasStrongCompression()) { + maskUseRLE = gFalse; + maskUseLZW = gTrue; + maskUseASCII = !(mode == psModeForm || inType3Char || preload); + maskUseCompressed = gFalse; } else { maskUseLZW = maskUseRLE = gFalse; maskUseASCII = maskStr->isBinary() && @@ -7097,6 +7212,11 @@ void PSOutputDev::doImageL3(Object *ref, GfxState *state, } useASCII = !(mode == psModeForm || inType3Char || preload); useCompressed = gFalse; + } else if (globalParams->getPSLZW() && !str->hasStrongCompression()) { + useRLE = gFalse; + useLZW = gTrue; + useASCII = !(mode == psModeForm || inType3Char || preload); + useCompressed = gFalse; } else { useLZW = useRLE = gFalse; useASCII = str->isBinary() && diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h index b7223c6cdd8..95908dbe675 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PSOutputDev.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stddef.h> #include "config.h" #include "Object.h" @@ -199,8 +195,6 @@ public: virtual void updateHorizScaling(GfxState *state); virtual void updateTextPos(GfxState *state); virtual void updateTextShift(GfxState *state, double shift); - virtual void saveTextPos(GfxState *state); - virtual void restoreTextPos(GfxState *state); //----- path painting virtual void stroke(GfxState *state); @@ -219,7 +213,15 @@ public: virtual void clipToStrokePath(GfxState *state); //----- text drawing - virtual void drawString(GfxState *state, GString *s); + virtual void drawString(GfxState *state, GString *s, + GBool fill, GBool stroke, GBool makePath); + virtual void fillTextPath(GfxState *state); + virtual void strokeTextPath(GfxState *state); + virtual void clipToTextPath(GfxState *state); + virtual void clipToTextStrokePath(GfxState *state); + virtual void clearTextPath(GfxState *state); + virtual void addTextPathToSavedClipPath(GfxState *state); + virtual void clipToSavedClipPath(GfxState *state); virtual void endTextObject(GfxState *state); //----- image drawing @@ -295,6 +297,8 @@ private: PSFontFileInfo *setupExternalType1Font(GfxFont *font, GString *fileName); PSFontFileInfo *setupEmbeddedType1CFont(GfxFont *font, Ref *id); PSFontFileInfo *setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalOpenTypeT1CFont(GfxFont *font, + GString *fileName); PSFontFileInfo *setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id); PSFontFileInfo *setupExternalTrueTypeFont(GfxFont *font, GString *fileName, int fontNum); @@ -489,8 +493,11 @@ private: PSOutCustomColor // used custom colors *customColors; - GBool haveTextClip; // set if text has been drawn with a - // clipping render mode + GBool haveSavedTextPath; // set if text has been drawn with the + // 'makePath' argument + GBool haveSavedClipPath; // set if the text path has been added + // to the saved clipping path (with + // addTextPathToSavedClipPath) GBool inType3Char; // inside a Type 3 CharProc GString *t3String; // Type 3 content string diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PSTokenizer.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PSTokenizer.cc index bbdb0ec44d5..cb525f1be60 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PSTokenizer.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PSTokenizer.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stdlib.h> #include "gmempp.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PSTokenizer.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PSTokenizer.h index 4d5ee97f4dd..3f3c8f4066d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PSTokenizer.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PSTokenizer.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" //------------------------------------------------------------------------ diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc index 368bc68dd8a..322f07063e7 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Page.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stddef.h> #include "gmempp.h" #include "Trace.h" @@ -381,7 +377,6 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, PDFRectangle box; Gfx *gfx; Object obj; - Annots *annotList; AcroForm *form; int i; @@ -426,21 +421,20 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, // draw (non-form) annotations if (globalParams->getDrawAnnotations()) { - annotList = new Annots(doc, getAnnots(&obj)); - obj.free(); - annotList->generateAnnotAppearances(); - if (annotList->getNumAnnots() > 0) { + Annots *annots2 = doc->getAnnots(); + annots2->generateAnnotAppearances(num); + int n = annots2->getNumAnnots(num); + if (n > 0) { if (globalParams->getPrintCommands()) { printf("***** Annotations\n"); } - for (i = 0; i < annotList->getNumAnnots(); ++i) { + for (i = 0; i < n; ++i) { if (abortCheckCbk && (*abortCheckCbk)(abortCheckCbkData)) { break; } - annotList->getAnnot(i)->draw(gfx, printing); + annots2->getAnnot(num, i)->draw(gfx, printing); } } - delete annotList; } // draw form fields @@ -552,3 +546,4 @@ void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI, delete state; #endif } + diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h index fe579e7b3af..0a862265d0f 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Page.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "Object.h" class Dict; @@ -192,6 +188,7 @@ public: void getDefaultCTM(double *ctm, double hDPI, double vDPI, int rotate, GBool useMediaBox, GBool upsideDown); + private: PDFDoc *doc; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc index 4fad6afae13..c594cf9413b 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stddef.h> #include <string.h> #include "gmempp.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.h index bfe5a52bdfc..6e175eb1cea 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Parser.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "Lexer.h" //------------------------------------------------------------------------ diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc index 29f26c00cee..e844e49142f 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <math.h> #include "gmempp.h" #include "GlobalParams.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h index ee21e98b148..703026ba19f 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/PreScanOutputDev.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "GfxState.h" #include "OutputDev.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc index a61a84e8fa2..6f614496859 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmempp.h" #include "GString.h" #include "PDFDoc.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.h b/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.h index 63462339bff..05e58cf64c3 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SecurityHandler.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "Object.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/ShadingImage.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/ShadingImage.cc index d8dc24e0fc6..b40c05d52e1 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/ShadingImage.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/ShadingImage.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <math.h> #include "Trace.h" #include "GfxState.h" @@ -70,6 +66,14 @@ SplashBitmap *ShadingImage::generateBitmap(GfxState *state, } } +static double max4(double x0, double x1, double x2, double x3) { + double t = x0; + t = (x1 > t) ? x1 : t; + t = (x2 > t) ? x2 : t; + t = (x3 > t) ? x3 : t; + return t; +} + SplashBitmap *ShadingImage::generateFunctionBitmap(GfxState *state, GfxFunctionShading *shading, SplashColorMode mode, @@ -204,7 +208,8 @@ SplashBitmap *ShadingImage::generateAxialBitmap(GfxState *state, // compute the inverse CTM double *ctm = state->getCTM(); double det = ctm[0] * ctm[3] - ctm[1] * ctm[2]; - if (fabs(det) < 0.000001) { + if (fabs(det) < 1e-10 * max4(fabs(ctm[0]), fabs(ctm[1]), + fabs(ctm[2]), fabs(ctm[3]))) { return NULL; } det = 1 / det; @@ -468,7 +473,8 @@ SplashBitmap *ShadingImage::generateRadialBitmap(GfxState *state, // compute the inverse CTM double *ctm = state->getCTM(); double det = ctm[0] * ctm[3] - ctm[1] * ctm[2]; - if (fabs(det) < 0.000001) { + if (fabs(det) < 1e-10 * max4(fabs(ctm[0]), fabs(ctm[1]), + fabs(ctm[2]), fabs(ctm[3]))) { return NULL; } det = 1 / det; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/ShadingImage.h b/Build/source/libs/xpdf/xpdf-src/xpdf/ShadingImage.h index 3bbff6922a4..54f193a9c89 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/ShadingImage.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/ShadingImage.h @@ -13,10 +13,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" class GfxState; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc index d758e25b306..581b804f3b0 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <string.h> #include <math.h> #include <limits.h> @@ -598,6 +594,8 @@ struct SplashTransparencyGroup { SplashBitmap *tBitmap; // bitmap for transparency group GfxColorSpace *blendingColorSpace; GBool isolated; + GBool inSoftMask; // true if this, or any containing + // group, is a soft mask //----- modified region in tBitmap int modXMin, modYMin, modXMax, modYMax; @@ -654,7 +652,8 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA, font = NULL; needFontUpdate = gFalse; - textClipPath = NULL; + savedTextPath = NULL; + savedClipPath = NULL; transpGroupStack = NULL; @@ -731,8 +730,11 @@ SplashOutputDev::~SplashOutputDev() { if (bitmap) { delete bitmap; } - if (textClipPath) { - delete textClipPath; + if (savedTextPath) { + delete savedTextPath; + } + if (savedClipPath) { + delete savedClipPath; } } @@ -1074,7 +1076,10 @@ void SplashOutputDev::setOverprintMask(GfxState *state, Guint mask; GfxCMYK cmyk; - if (overprintFlag && globalParams->getOverprintPreview()) { + // Adobe ignores overprint in soft masks. + if (overprintFlag && + !(transpGroupStack && transpGroupStack->inSoftMask) && + globalParams->getOverprintPreview()) { mask = colorSpace->getOverprintMask(); // The OPM (overprintMode) setting is only relevant when the color // space is DeviceCMYK or is "implicitly converted to DeviceCMYK". @@ -2218,27 +2223,24 @@ void SplashOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, CharCode code, int nBytes, - Unicode *u, int uLen) { - SplashPath *path; - int render; - GBool doFill, doStroke, doClip; - SplashStrokeAdjustMode strokeAdjust; - double m[4]; - GBool horiz; - + Unicode *u, int uLen, + GBool fill, GBool stroke, GBool makePath) { if (skipHorizText || skipRotatedText) { + double m[4]; state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]); // this matches the 'diagonal' test in TextPage::updateFont() - horiz = m[0] > 0 && fabs(m[1]) < 0.001 && - fabs(m[2]) < 0.001 && m[3] < 0; + GBool horiz = m[0] > 0 && fabs(m[1]) < 0.001 && + fabs(m[2]) < 0.001 && m[3] < 0; if ((skipHorizText && horiz) || (skipRotatedText && !horiz)) { return; } } + fill = fill && !state->getFillColorSpace()->isNonMarking(); + stroke = stroke && !state->getStrokeColorSpace()->isNonMarking(); + // check for invisible text -- this is used by Acrobat Capture - render = state->getRender(); - if (render == 3) { + if (!fill && !stroke && !makePath) { return; } @@ -2252,13 +2254,8 @@ void SplashOutputDev::drawChar(GfxState *state, double x, double y, x -= originX; y -= originY; - doFill = !(render & 1) && !state->getFillColorSpace()->isNonMarking(); - doStroke = ((render & 3) == 1 || (render & 3) == 2) && - !state->getStrokeColorSpace()->isNonMarking(); - doClip = render & 4; - - path = NULL; - if (doStroke || doClip) { + SplashPath *path = NULL; + if (stroke || makePath) { if ((path = font->getGlyphPath(code))) { path->offset((SplashCoord)x, (SplashCoord)y); } @@ -2267,14 +2264,19 @@ void SplashOutputDev::drawChar(GfxState *state, double x, double y, // don't use stroke adjustment when stroking text -- the results // tend to be ugly (because characters with horizontal upper or // lower edges get misaligned relative to the other characters) - strokeAdjust = splashStrokeAdjustOff; // make gcc happy - if (doStroke) { - strokeAdjust = splash->getStrokeAdjust(); + SplashStrokeAdjustMode savedStrokeAdjust = splashStrokeAdjustOff; + if (stroke) { + savedStrokeAdjust = splash->getStrokeAdjust(); splash->setStrokeAdjust(splashStrokeAdjustOff); } - // fill and stroke - if (doFill && doStroke) { + // the possible operations are: + // - fill + // - stroke + // - fill + stroke + // - makePath + + if (fill && stroke) { if (path) { setOverprintMask(state, state->getFillColorSpace(), state->getFillOverprint(), state->getOverprintMode(), @@ -2286,37 +2288,33 @@ void SplashOutputDev::drawChar(GfxState *state, double x, double y, splash->stroke(path); } - // fill - } else if (doFill) { + } else if (fill) { setOverprintMask(state, state->getFillColorSpace(), state->getFillOverprint(), state->getOverprintMode(), state->getFillColor()); splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font); - // stroke - } else if (doStroke) { + } else if (stroke) { if (path) { setOverprintMask(state, state->getStrokeColorSpace(), state->getStrokeOverprint(), state->getOverprintMode(), state->getStrokeColor()); splash->stroke(path); } - } - // clip - if (doClip) { + } else if (makePath) { if (path) { - if (textClipPath) { - textClipPath->append(path); + if (savedTextPath) { + savedTextPath->append(path); } else { - textClipPath = path; + savedTextPath = path; path = NULL; } } } - if (doStroke) { - splash->setStrokeAdjust(strokeAdjust); + if (stroke) { + splash->setStrokeAdjust(savedStrokeAdjust); } if (path) { @@ -2324,6 +2322,73 @@ void SplashOutputDev::drawChar(GfxState *state, double x, double y, } } +void SplashOutputDev::fillTextPath(GfxState *state) { + if (!savedTextPath) { + return; + } + setOverprintMask(state, state->getFillColorSpace(), + state->getFillOverprint(), state->getOverprintMode(), + state->getFillColor()); + splash->fill(savedTextPath, gFalse); +} + +void SplashOutputDev::strokeTextPath(GfxState *state) { + if (!savedTextPath) { + return; + } + setOverprintMask(state, state->getStrokeColorSpace(), + state->getStrokeOverprint(), state->getOverprintMode(), + state->getStrokeColor()); + splash->stroke(savedTextPath); +} + +void SplashOutputDev::clipToTextPath(GfxState *state) { + if (!savedTextPath) { + return; + } + splash->clipToPath(savedTextPath, gFalse); +} + +void SplashOutputDev::clipToTextStrokePath(GfxState *state) { + if (!savedTextPath) { + return; + } + SplashPath *path = splash->makeStrokePath(savedTextPath, + state->getLineWidth(), + state->getLineCap(), + state->getLineJoin()); + splash->clipToPath(path, gFalse); + delete path; +} + +void SplashOutputDev::clearTextPath(GfxState *state) { + if (savedTextPath) { + delete savedTextPath; + savedTextPath = NULL; + } +} + +void SplashOutputDev::addTextPathToSavedClipPath(GfxState *state) { + if (savedTextPath) { + if (savedClipPath) { + savedClipPath->append(savedTextPath); + delete savedTextPath; + } else { + savedClipPath = savedTextPath; + } + savedTextPath = NULL; + } +} + +void SplashOutputDev::clipToSavedClipPath(GfxState *state) { + if (!savedClipPath) { + return; + } + splash->clipToPath(savedClipPath, gFalse); + delete savedClipPath; + savedClipPath = NULL; +} + GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen) { @@ -2679,11 +2744,6 @@ void SplashOutputDev::drawType3Glyph(GfxState *state, T3FontCache *t3Font, } void SplashOutputDev::endTextObject(GfxState *state) { - if (textClipPath) { - splash->clipToPath(textClipPath, gFalse); - delete textClipPath; - textClipPath = NULL; - } } struct SplashOutImageMaskData { @@ -3855,7 +3915,7 @@ GBool SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, SplashBitmap *backdropBitmap; SplashColor color; double xMin, yMin, xMax, yMax, x, y; - int bw, bh, tx, ty, w, h, i; + int bw, bh, tx, ty, w, h, xx, yy, i; // transform the bbox state->transform(bbox[0], bbox[1], &x, &y); @@ -3928,21 +3988,23 @@ GBool SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, } else if (ty >= bh) { ty = bh - 1; } - w = (int)ceil(xMax) - tx + 1; - // NB bw and tx are both non-negative, so 'bw - tx' can't overflow - if (bw - tx < w) { - w = bw - tx; - } - if (w < 1) { + xx = (int)ceil(xMax); + if (xx < tx) { w = 1; + } else if (xx > bw - 1) { + // NB bw and tx are both non-negative, so 'bw - tx' can't overflow + w = bw - tx; + } else { + w = xx - tx + 1; } - h = (int)ceil(yMax) - ty + 1; - // NB bh and ty are both non-negative, so 'bh - ty' can't overflow - if (bh - ty < h) { - h = bh - ty; - } - if (h < 1) { + yy = (int)ceil(yMax); + if (yy < ty) { h = 1; + } else if (yy > bh - 1) { + // NB bh and ty are both non-negative, so 'bh - ty' can't overflow + h = bh - ty; + } else { + h = yy - ty + 1; } // optimization: a non-isolated group drawn with alpha=1 and @@ -3973,6 +4035,8 @@ GBool SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, transpGroup->ty = ty; transpGroup->blendingColorSpace = blendingColorSpace; transpGroup->isolated = isolated; + transpGroup->inSoftMask = (transpGroupStack && transpGroupStack->inSoftMask) + || forSoftMask; transpGroup->next = transpGroupStack; transpGroupStack = transpGroup; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h index 5ec70e95509..d021d8922b0 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/SplashOutputDev.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "SplashTypes.h" #include "config.h" @@ -129,7 +125,15 @@ public: virtual void drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, - CharCode code, int nBytes, Unicode *u, int uLen); + CharCode code, int nBytes, Unicode *u, int uLen, + GBool fill, GBool stroke, GBool makePath); + virtual void fillTextPath(GfxState *state); + virtual void strokeTextPath(GfxState *state); + virtual void clipToTextPath(GfxState *state); + virtual void clipToTextStrokePath(GfxState *state); + virtual void clearTextPath(GfxState *state); + virtual void addTextPathToSavedClipPath(GfxState *state); + virtual void clipToSavedClipPath(GfxState *state); virtual GBool beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen); @@ -306,7 +310,8 @@ private: SplashFont *font; // current font GBool needFontUpdate; // set when the font needs to be updated - SplashPath *textClipPath; // clipping path built with text object + SplashPath *savedTextPath; // path built for text string + SplashPath *savedClipPath; // clipping path built with text object SplashTransparencyGroup * // transparency group stack transpGroupStack; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc index 383ac5478ff..8387e55d0b0 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -2673,6 +2669,7 @@ DCTStream::DCTStream(Stream *strA, GBool colorXformA): frameBuf[i] = NULL; } rowBuf = NULL; + memset(quantTables, 0, sizeof(quantTables)); memset(dcHuffTables, 0, sizeof(dcHuffTables)); memset(acHuffTables, 0, sizeof(acHuffTables)); @@ -2894,7 +2891,7 @@ void DCTStream::prepare() { bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; if (bufWidth <= 0 || bufHeight <= 0 || - bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) { + bufWidth > INT_MAX / bufHeight / (int)sizeof(int)) { error(errSyntaxError, getPos(), "Invalid image size in DCT stream"); y = height; prepared = gTrue; @@ -2942,7 +2939,13 @@ void DCTStream::prepare() { // allocate a buffer for one row of MCUs bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; - rowBuf = (Guchar *)gmallocn(numComps * mcuHeight, bufWidth); + if (bufWidth <= 0 || bufWidth > INT_MAX / numComps / mcuHeight) { + error(errSyntaxError, getPos(), "Invalid image size in DCT stream"); + y = height; + prepared = gTrue; + return; + } + rowBuf = (Guchar *)gmallocn(bufWidth, numComps * mcuHeight); rowBufPtr = rowBufEnd = rowBuf; // initialize counters @@ -3848,11 +3851,12 @@ int DCTStream::readBit() { } GBool DCTStream::readHeader(GBool frame) { - GBool doScan; + GBool haveSOF, doScan; int n, i; int c = 0; // read headers + haveSOF = gFalse; doScan = gFalse; while (!doScan) { c = readMarker(); @@ -3867,6 +3871,7 @@ GBool DCTStream::readHeader(GBool frame) { if (!readBaselineSOF()) { return gFalse; } + haveSOF = gTrue; break; case 0xc2: // SOF2 (progressive) if (!frame) { @@ -3877,6 +3882,7 @@ GBool DCTStream::readHeader(GBool frame) { if (!readProgressiveSOF()) { return gFalse; } + haveSOF = gTrue; break; case 0xc4: // DHT if (!readHuffmanTables()) { @@ -3893,6 +3899,10 @@ GBool DCTStream::readHeader(GBool frame) { case 0xd9: // EOI return gFalse; case 0xda: // SOS + if (frame && !haveSOF) { + error(errSyntaxError, getPos(), "Missing SOF in DCT stream"); + return gFalse; + } if (!readScanInfo()) { return gFalse; } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h index 9d084c94895..dc850151bc5 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Stream.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stdio.h> #if HAVE_JPEGLIB #include <jpeglib.h> @@ -130,6 +126,10 @@ public: // Does this stream type potentially contain non-printable chars? virtual GBool isBinary(GBool last = gTrue) = 0; + // Does this stream include a "strong" compression filter (anything + // other than RLE)? + virtual GBool hasStrongCompression() { return gFalse; } + // Get the BaseStream of this stream. virtual BaseStream *getBaseStream() = 0; @@ -490,6 +490,7 @@ public: virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); + virtual GBool hasStrongCompression() { return gTrue; } private: @@ -573,6 +574,7 @@ public: virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); + virtual GBool hasStrongCompression() { return gTrue; } private: @@ -672,6 +674,7 @@ public: virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); + virtual GBool hasStrongCompression() { return gTrue; } Stream *getRawStream() { return str; } private: @@ -813,6 +816,7 @@ public: virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); + virtual GBool hasStrongCompression() { return gTrue; } private: diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc index e2da940bb41..86d08414476 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -65,7 +61,11 @@ // A large character has a font size larger than // largeCharThreshold * avgFontSize. -#define largeCharThreshold 1.5 +#define largeCharThreshold 2.0 + +// Max ratio of large-to-total chars to prefer a large char split over +// a line split. +#define largeCharRatio 0.2 // A block will be split vertically only if the resulting chunk widths // are greater than minChunkWidth * avgFontSize. However, Blocks of @@ -83,9 +83,9 @@ #define maxWordGapSize 2.5 #define tableModeMaxWordGapSize 1.1 -// Adjacent lines can overlap by at most lineOverlapThreshold * -// lineHeight. -#define lineOverlapThreshold 0.33 +// Chars whose baseline is within baselineRange * avgFontSize of a +// line's current average baseline are added to the line. +#define baselineRange 0.5 // Subscripts (superscripts) must overlap the next (previous) line by // minSubSuperscriptVertOverlap * fontSize. @@ -214,12 +214,14 @@ public: static int cmpX(const void *p1, const void *p2); static int cmpY(const void *p1, const void *p2); + static int cmpBase(const void *p1, const void *p2); static int cmpCharPos(const void *p1, const void *p2); Unicode c; int charPos; int charLen; double xMin, yMin, xMax, yMax; + double base; TextFontInfo *font; double fontSize; double colorR, @@ -249,38 +251,50 @@ TextChar::TextChar(Unicode cA, int charPosA, int charLenA, yMin = yMinA; xMax = xMaxA; yMax = yMaxA; - // this can happen with vertical writing mode, or with odd values - // for the char/word spacing parameters - if (xMin > xMax) { - t = xMin; xMin = xMax; xMax = t; - } - if (yMin > yMax) { - t = yMin; yMin = yMax; yMax = t; + switch (rotA) { + case 0: + default: base = yMax + fontSizeA * fontA->getDescent(); break; + case 1: base = xMin - fontSizeA * fontA->getDescent(); break; + case 2: base = yMin - fontSizeA * fontA->getDescent(); break; + case 3: base = xMax + fontSizeA * fontA->getDescent(); break; } // TextPage::findGaps uses integer coordinates, so clip the char // bbox to fit in a 32-bit int (this is generally only a problem in // damaged PDF files) if (xMin < -1e8) { xMin = -1e8; + } else if (xMin > 1e8) { + xMin = 1e8; } - if (xMax > 1e8) { + if (xMax < -1e8) { + xMax = -1e8; + } else if (xMax > 1e8) { xMax = 1e8; } if (yMin < -1e8) { yMin = -1e8; + } else if (yMin > 1e8) { + yMin = 1e8; } - if (yMax > 1e8) { + if (yMax < -1e8) { + yMax = -1e8; + } else if (yMax > 1e8) { yMax = 1e8; } - // zero-width characters will cause problems in the splitting code - if (rotA & 1) { - if (yMax - yMin < 1e-6) { - yMax = yMin + 1e-6; - } - } else { - if (xMax - xMin < 1e-6) { - xMax = xMin + 1e-6; - } + // this can happen with vertical writing mode, or with odd values + // for the char/word spacing parameters + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; + } + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; + } + // zero-width/height characters will cause problems in the splitting code + if (xMax - xMin < 1e-6) { + xMax = xMin + 1e-6; + } + if (yMax - yMin < 1e-6) { + yMax = yMin + 1e-6; } rot = (Guchar)rotA; rotated = (char)rotatedA; @@ -321,6 +335,19 @@ int TextChar::cmpY(const void *p1, const void *p2) { } } +int TextChar::cmpBase(const void *p1, const void *p2) { + const TextChar *ch1 = *(const TextChar **)p1; + const TextChar *ch2 = *(const TextChar **)p2; + + if (ch1->base < ch2->base) { + return -1; + } else if (ch1->base > ch2->base) { + return 1; + } else { + return ch1->charPos - ch2->charPos; + } +} + int TextChar::cmpCharPos(const void *p1, const void *p2) { const TextChar *ch1 = *(const TextChar **)p1; const TextChar *ch2 = *(const TextChar **)p2; @@ -985,7 +1012,8 @@ TextLine::TextLine(GList *wordsA, double xMinA, double yMinA, } } //~ need to check for other Unicode chars used as hyphens - hyphenated = text[len - 1] == (Unicode)'-'; + hyphenated = text[len - 1] == (Unicode)'-' || + text[len - 1] == (Unicode)0xad; } TextLine::~TextLine() { @@ -1212,6 +1240,7 @@ TextPage::TextPage(TextOutputControl *controlA) { chars = new GList(); fonts = new GList(); + primaryRot = 0; underlines = new GList(); links = new GList(); @@ -1240,6 +1269,15 @@ void TextPage::startPage(GfxState *state) { if (state) { pageWidth = state->getPageWidth(); pageHeight = state->getPageHeight(); + // When rotating characters, the coordinates are flipped using the + // page size. See the comment in TextChar::TextChar() about + // integer coordinates. + if (pageWidth > 1e8) { + pageWidth = 1e8; + } + if (pageHeight > 1e8) { + pageHeight = 1e8; + } } else { pageWidth = pageHeight = 0; } @@ -1266,6 +1304,9 @@ void TextPage::clear() { underlines = new GList(); deleteGList(links, TextLink); links = new GList(); + nVisibleChars = 0; + nInvisibleChars = 0; + nRemovedDupChars = 0; if (findCols) { deleteGList(findCols, TextColumn); @@ -1560,13 +1601,18 @@ void TextPage::addChar(GfxState *state, double x, double y, } else { j = i; } + GBool invisible = state->getRender() == 3 || alpha < 0.001; chars->append(new TextChar(uBuf[j], charPos, nBytes, xMin, yMin, xMax, yMax, - curRot, rotated, clipped, - state->getRender() == 3 || alpha < 0.001, + curRot, rotated, clipped, invisible, curFont, curFontSize, colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b))); + if (invisible) { + ++nInvisibleChars; + } else { + ++nVisibleChars; + } } } @@ -1730,7 +1776,7 @@ void TextPage::writeReadingOrder(void *outputStream, GList *columns; GBool primaryLR; GString *s; - int colIdx, parIdx, lineIdx, rot, n; + int colIdx, parIdx, lineIdx, n; #if 0 //~debug dumpChars(chars); @@ -1740,7 +1786,7 @@ void TextPage::writeReadingOrder(void *outputStream, } else { overlappingChars = NULL; } - rot = rotateChars(chars); + primaryRot = rotateChars(chars); primaryLR = checkPrimaryLR(chars); tree = splitChars(chars); #if 0 //~debug @@ -1748,14 +1794,14 @@ void TextPage::writeReadingOrder(void *outputStream, #endif if (!tree) { // no text - unrotateChars(chars, rot); + unrotateChars(chars, primaryRot); return; } columns = buildColumns(tree, primaryLR); delete tree; - unrotateChars(chars, rot); + unrotateChars(chars, primaryRot); if (control.html) { - rotateUnderlinesAndLinks(rot); + rotateUnderlinesAndLinks(primaryRot); generateUnderlinesAndLinks(columns); } if (overlappingChars) { @@ -1799,10 +1845,10 @@ GList *TextPage::makeColumns() { GList *overlappingChars; GList *columns; GBool primaryLR; - int rot; if (control.mode == textOutSimple2Layout) { primaryLR = checkPrimaryLR(chars); + primaryRot = 0; rotateCharsToZero(chars); columns = buildSimple2Columns(chars); unrotateCharsFromZero(chars); @@ -1813,7 +1859,7 @@ GList *TextPage::makeColumns() { } else { overlappingChars = NULL; } - rot = rotateChars(chars); + primaryRot = rotateChars(chars); primaryLR = checkPrimaryLR(chars); if ((tree = splitChars(chars))) { columns = buildColumns(tree, primaryLR); @@ -1822,8 +1868,8 @@ GList *TextPage::makeColumns() { // no text columns = new GList(); } - unrotateChars(chars, rot); - unrotateColumns(columns, rot); + unrotateChars(chars, primaryRot); + unrotateColumns(columns, primaryRot); if (control.html) { generateUnderlinesAndLinks(columns); } @@ -1852,7 +1898,7 @@ void TextPage::writePhysLayout(void *outputStream, GList *overlappingChars; GList *columns; GBool primaryLR; - int ph, colIdx, parIdx, lineIdx, rot, y, i; + int ph, colIdx, parIdx, lineIdx, y, i; #if 0 //~debug dumpChars(chars); @@ -1865,7 +1911,7 @@ void TextPage::writePhysLayout(void *outputStream, } else { overlappingChars = NULL; } - rot = rotateChars(chars); + primaryRot = rotateChars(chars); primaryLR = checkPrimaryLR(chars); tree = splitChars(chars); #if 0 //~debug @@ -1873,15 +1919,15 @@ void TextPage::writePhysLayout(void *outputStream, #endif if (!tree) { // no text - unrotateChars(chars, rot); + unrotateChars(chars, primaryRot); return; } //~ this doesn't correctly handle the right-to-left case columns = buildColumns(tree, gTrue); delete tree; - unrotateChars(chars, rot); + unrotateChars(chars, primaryRot); if (control.html) { - rotateUnderlinesAndLinks(rot); + rotateUnderlinesAndLinks(primaryRot); generateUnderlinesAndLinks(columns); } ph = assignPhysLayoutPositions(columns); @@ -1940,7 +1986,7 @@ void TextPage::writePhysLayout(void *outputStream, if (overlappingChars) { if (overlappingChars->getLength() > 0) { - TextColumn *col = buildOverlappingTextColumn(overlappingChars); + col = buildOverlappingTextColumn(overlappingChars); (*outputFunc)(outputStream, eol, eolLen); for (parIdx = 0; parIdx < col->paragraphs->getLength(); ++parIdx) { par = (TextParagraph *)col->paragraphs->get(parIdx); @@ -1973,12 +2019,12 @@ void TextPage::writeSimpleLayout(void *outputStream, GList *superLines; GString *out; GBool primaryLR; - int rot, x, i, j; + int x, i, j; #if 0 //~debug dumpChars(chars); #endif - rot = rotateChars(chars); + primaryRot = rotateChars(chars); primaryLR = checkPrimaryLR(chars); tree = splitChars(chars); #if 0 //~debug @@ -1986,13 +2032,13 @@ void TextPage::writeSimpleLayout(void *outputStream, #endif if (!tree) { // no text - unrotateChars(chars, rot); + unrotateChars(chars, primaryRot); return; } superLines = new GList(); buildSuperLines(tree, superLines); delete tree; - unrotateChars(chars, rot); + unrotateChars(chars, primaryRot); assignSimpleLayoutPositions(superLines, uMap); for (i = 0; i < superLines->getLength(); ++i) { @@ -2036,6 +2082,7 @@ void TextPage::writeSimple2Layout(void *outputStream, int colIdx, parIdx, lineIdx; primaryLR = checkPrimaryLR(chars); + primaryRot = 0; rotateCharsToZero(chars); #if 0 //~debug dumpChars(chars); @@ -2074,9 +2121,9 @@ void TextPage::writeLinePrinter(void *outputStream, double pitch, lineSpacing, delta; double yMin0, yShift, xMin0, xShift; double y, x; - int rot, n, i, j, k; + int n, i, j, k; - rot = rotateChars(chars); + primaryRot = rotateChars(chars); chars->sort(&TextChar::cmpX); // don't call removeDuplicates here, because it expects to be // working on a secondary list that doesn't own the TextChar objects @@ -2186,7 +2233,7 @@ void TextPage::writeLinePrinter(void *outputStream, delete line; } - unrotateChars(chars, rot); + unrotateChars(chars, primaryRot); } void TextPage::writeRaw(void *outputStream, @@ -2451,6 +2498,7 @@ int TextPage::rotateChars(GList *charsA) { ch->xMax = xMax; ch->yMin = yMin; ch->yMax = yMax; + ch->base = pageWidth - ch->base; ch->rot = (ch->rot + 3) & 3; } t = pageWidth; @@ -2468,6 +2516,7 @@ int TextPage::rotateChars(GList *charsA) { ch->xMax = xMax; ch->yMin = yMin; ch->yMax = yMax; + ch->base = pageHeight - ch->base; ch->rot = (ch->rot + 2) & 3; } break; @@ -2515,6 +2564,7 @@ void TextPage::rotateCharsToZero(GList *charsA) { ch->xMax = xMax; ch->yMin = yMin; ch->yMax = yMax; + ch->base = pageWidth - ch->base; break; case 2: xMin = pageWidth - ch->xMax; @@ -2525,6 +2575,7 @@ void TextPage::rotateCharsToZero(GList *charsA) { ch->xMax = xMax; ch->yMin = yMin; ch->yMax = yMax; + ch->base = pageHeight - ch->base; break; case 3: xMin = pageHeight - ch->yMax; @@ -2654,6 +2705,7 @@ void TextPage::unrotateChars(GList *charsA, int rot) { ch->xMax = xMax; ch->yMin = yMin; ch->yMax = yMax; + ch->base = pageWidth - ch->base; ch->rot = (ch->rot + 1) & 3; } break; @@ -2668,6 +2720,7 @@ void TextPage::unrotateChars(GList *charsA, int rot) { ch->xMax = xMax; ch->yMin = yMin; ch->yMax = yMax; + ch->base = pageHeight - ch->base; ch->rot = (ch->rot + 2) & 3; } break; @@ -3220,7 +3273,7 @@ GBool TextPage::checkPrimaryLR(GList *charsA) { // by x for rot=0,2; by y for rot=1,3. void TextPage::removeDuplicates(GList *charsA, int rot) { TextChar *ch, *ch2; - double xDelta, yDelta; + double xDelta, yDelta, xDelta2, yDelta2; int i, j; if (rot & 1) { @@ -3229,6 +3282,10 @@ void TextPage::removeDuplicates(GList *charsA, int rot) { ch = (TextChar *)charsA->get(i); xDelta = dupMaxSecDelta * ch->fontSize; yDelta = dupMaxPriDelta * ch->fontSize; + yDelta2 = 0.5 * (ch->yMax - ch->yMin); + if (yDelta2 < yDelta) { + yDelta = yDelta2; + } j = i + 1; while (j < charsA->getLength()) { ch2 = (TextChar *)charsA->get(j); @@ -3241,6 +3298,7 @@ void TextPage::removeDuplicates(GList *charsA, int rot) { fabs(ch2->yMax - ch->yMax) < yDelta) { if (ch->invisible && !ch2->invisible) { charsA->del(i); + ++nRemovedDupChars; --i; break; } @@ -3248,6 +3306,7 @@ void TextPage::removeDuplicates(GList *charsA, int rot) { ch->spaceAfter = (char)gTrue; } charsA->del(j); + ++nRemovedDupChars; } else { ++j; } @@ -3259,6 +3318,10 @@ void TextPage::removeDuplicates(GList *charsA, int rot) { while (i < charsA->getLength()) { ch = (TextChar *)charsA->get(i); xDelta = dupMaxPriDelta * ch->fontSize; + xDelta2 = 0.5 * (ch->xMax - ch->xMin); + if (xDelta2 < xDelta) { + xDelta = xDelta2; + } yDelta = dupMaxSecDelta * ch->fontSize; j = i + 1; while (j < charsA->getLength()) { @@ -3272,6 +3335,7 @@ void TextPage::removeDuplicates(GList *charsA, int rot) { fabs(ch2->yMax - ch->yMax) < yDelta) { if (ch->invisible && !ch2->invisible) { charsA->del(i); + ++nRemovedDupChars; --i; break; } @@ -3279,6 +3343,7 @@ void TextPage::removeDuplicates(GList *charsA, int rot) { ch->spaceAfter = (char)gTrue; } charsA->del(j); + ++nRemovedDupChars; } else { ++j; } @@ -3559,7 +3624,7 @@ TextBlock *TextPage::splitChars(GList *charsA) { } } if (chars2->getLength() > 0) { - tree[rot] = split(chars2, rot, gFalse); + tree[rot] = split(chars2, rot); } } delete chars2; @@ -3590,9 +3655,11 @@ TextBlock *TextPage::splitChars(GList *charsA) { } // merge non-primary-rotation text into the primary-rotation tree + GBool doReorder = control.mode == textOutReadingOrder && + globalParams->getSeparateRotatedText(); for (rot = 1; rot < 4; ++rot) { if (tree[rot]) { - insertIntoTree(tree[rot], tree[0]); + insertIntoTree(tree[rot], tree[0], doReorder); tree[rot] = NULL; } } @@ -3610,7 +3677,7 @@ TextBlock *TextPage::splitChars(GList *charsA) { } // Generate a tree of TextBlocks, marked as columns, lines, and words. -TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { +TextBlock *TextPage::split(GList *charsA, int rot) { TextBlock *blk; GList *chars2, *chars3; GList *splitLines; @@ -3762,18 +3829,13 @@ TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { doHorizSplit = doVertSplit = doLineSplit = doLargeCharSplit = gFalse; smallSplit = gFalse; if (rot & 1) { - if (vertOnly) { - if (nHorizGaps > 0 && horizGapSize > minGapSize * minFontSize) { - doHorizSplit = gTrue; - smallSplit = horizGapSize < smallSplitThreshold; - } - } else if (control.mode == textOutSimpleLayout) { + if (control.mode == textOutSimpleLayout) { if (nVertGaps > 0) { doVertSplit = gTrue; } else if (nHorizGaps > 0 && horizGapSize > minGapSize * minFontSize) { doHorizSplit = gTrue; smallSplit = horizGapSize < smallSplitThreshold; - } else if (!vertOnly && splitLines->getLength() > 1) { + } else if (splitLines->getLength() > 1) { doLineSplit = gTrue; } } else if (nHorizGaps > 0 && @@ -3786,19 +3848,15 @@ TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { smallSplit = horizGapSize < smallSplitThreshold; } else if (nVertGaps > 0) { doVertSplit = gTrue; - } else if (nLargeChars > 0) { + } else if (nLargeChars > 0 && + ((nLargeChars < largeCharRatio * charsA->getLength()) || + splitLines->getLength() <= 1)) { doLargeCharSplit = gTrue; } else if (splitLines->getLength() > 1) { doLineSplit = gTrue; } } else { - if (vertOnly) { - if (nVertGaps > 0 && - vertGapSize > minGapSize * minFontSize) { - doVertSplit = gTrue; - smallSplit = vertGapSize < smallSplitThreshold; - } - } else if (control.mode == textOutSimpleLayout) { + if (control.mode == textOutSimpleLayout) { if (nHorizGaps > 0) { doHorizSplit = gTrue; } else if (nVertGaps > 0 && vertGapSize > minGapSize * minFontSize) { @@ -3817,7 +3875,9 @@ TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { smallSplit = vertGapSize < smallSplitThreshold; } else if (nHorizGaps > 0) { doHorizSplit = gTrue; - } else if (nLargeChars > 0) { + } else if (nLargeChars > 0 && + ((nLargeChars < largeCharRatio * charsA->getLength()) || + splitLines->getLength() <= 1)) { doLargeCharSplit = gTrue; } else if (splitLines->getLength() > 1) { doLineSplit = gTrue; @@ -3847,13 +3907,13 @@ TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { if (vertGaps->getW(i) > vertGapSize - splitGapSlack * avgFontSize) { x1 = vertGaps->getX(i); chars2 = getChars(charsA, x0, yMin - 1, x1, yMax + 1); - blk->addChild(split(chars2, rot, vertOnly)); + blk->addChild(split(chars2, rot)); delete chars2; x0 = x1; } } chars2 = getChars(charsA, x0, yMin - 1, xMax + 1, yMax + 1); - blk->addChild(split(chars2, rot, vertOnly)); + blk->addChild(split(chars2, rot)); delete chars2; // split horizontally @@ -3874,13 +3934,13 @@ TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { if (horizGaps->getW(i) > horizGapSize - splitGapSlack * avgFontSize) { y1 = horizGaps->getX(i); chars2 = getChars(charsA, xMin - 1, y0, xMax + 1, y1); - blk->addChild(split(chars2, rot, gFalse)); + blk->addChild(split(chars2, rot)); delete chars2; y0 = y1; } } chars2 = getChars(charsA, xMin - 1, y0, xMax + 1, yMax + 1); - blk->addChild(split(chars2, rot, gFalse)); + blk->addChild(split(chars2, rot)); delete chars2; // split into larger and smaller chars @@ -3899,7 +3959,7 @@ TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { chars3->append(ch); } } - blk = split(chars3, rot, gFalse); + blk = split(chars3, rot); chars2->sort((rot & 1) ? &TextChar::cmpY : &TextChar::cmpX); insertLargeChars(chars2, blk); delete chars2; @@ -3925,12 +3985,21 @@ TextBlock *TextPage::split(GList *charsA, int rot, GBool vertOnly) { for (i = 0; i < splitLine->chars->getLength(); ++i) { blk->addChild((TextChar *)splitLine->chars->get(i), gTrue); } +#if 0 //~debug + printf("line-leaf xMin=%g yMin=%g xMax=%g yMax=%g\n", + xMin, pageHeight - yMax, xMax, pageHeight - yMin); + printf(" "); + for (i = 0; i < splitLine->chars->getLength(); ++i) { + printf("%c", ((TextChar *)splitLine->chars->get(i))->c); + } + printf("\n"); +#endif } else { blk = new TextBlock((rot & 1) ? blkVertSplit : blkHorizSplit, rot); blk->smallSplit = gFalse; for (i = 0; i < splitLines->getLength(); ++i) { SplitLine *splitLine = (SplitLine *)splitLines->get(i); - blk->addChild(split(splitLine->chars, rot, singleLine)); + blk->addChild(split(splitLine->chars, rot)); } } @@ -4058,54 +4127,146 @@ void TextPage::findGaps(GList *charsA, int rot, } } - //----- partition into lines and find horizontal gaps + //----- find horizontal gaps if (rot & 1) { charsA->sort(&TextChar::cmpX); - SplitLine *splitLine = NULL; - double xxMin = 0, xxMax = 0; + double xxMax = 0; for (int i = 0; i < charsA->getLength(); ++i) { TextChar *ch = (TextChar *)charsA->get(i); - if (i == 0 || - ch->xMin > xxMax - lineOverlapThreshold * (xxMax - xxMin)) { - if (i > 0 && ch->xMin > xxMax) { - vertGaps->addGap(0.5 * (ch->xMin + xxMax), ch->xMin - xxMax); - } - xxMin = ch->xMin; + if (i == 0) { xxMax = ch->xMax; - splitLine = new SplitLine(i, i, xxMin, xxMax); - splitLines->append(splitLine); - } else { - splitLine->lastCharIdx = i; + } else if (ch->xMin <= xxMax) { if (ch->xMax > xxMax) { xxMax = ch->xMax; - splitLine->yMax = xxMax; } + } else { + vertGaps->addGap(0.5 * (ch->xMin + xxMax), ch->xMin - xxMax); + xxMax = ch->xMax; } } } else { charsA->sort(&TextChar::cmpY); - SplitLine *splitLine = NULL; - double yyMin = 0, yyMax = 0; + double yyMax = 0; for (int i = 0; i < charsA->getLength(); ++i) { TextChar *ch = (TextChar *)charsA->get(i); - if (i == 0 || - ch->yMin > yyMax - lineOverlapThreshold * (yyMax - yyMin)) { - if (i > 0 && ch->yMin > yyMax) { - horizGaps->addGap(0.5 * (ch->yMin + yyMax), ch->yMin - yyMax); - } - yyMin = ch->yMin; + if (i == 0) { yyMax = ch->yMax; - splitLine = new SplitLine(i, i, yyMin, yyMax); - splitLines->append(splitLine); + } else if (ch->yMin <= yyMax) { + if (ch->yMax > yyMax) { + yyMax = ch->yMax; + } } else { - splitLine->lastCharIdx = i; + horizGaps->addGap(0.5 * (ch->yMin + yyMax), ch->yMin - yyMax); + yyMax = ch->yMax; + } + } + } + + //----- split into lines + + double baseDelta = baselineRange * avgFontSize; + + if (rot & 1) { + + // split into non-overlapping chunks + int firstChar = 0; + while (firstChar < charsA->getLength()) { + TextChar *ch = (TextChar *)charsA->get(firstChar); + double xxMax = ch->xMax; + int nextChar = firstChar + 1; + while (nextChar < charsA->getLength()) { + ch = (TextChar *)charsA->get(nextChar); + if (ch->xMin > xxMax) { + break; + } + if (ch->xMax > xxMax) { + xxMax = ch->xMax; + } + ++nextChar; + } + + // split the chunk [firstChar, nextChar) into lines + charsA->sort(firstChar, nextChar - firstChar, &TextChar::cmpBase); + int i0 = firstChar; + while (i0 < nextChar) { + ch = (TextChar *)charsA->get(i0); + double baseTotal = ch->base; + double baseAvg = baseTotal; + double xxMin = ch->xMin; + xxMax = ch->xMax; + int i1 = i0 + 1; + while (i1 < nextChar) { + ch = (TextChar *)charsA->get(i1); + if (ch->base > baseAvg + baseDelta) { + break; + } + baseTotal += ch->base; + if (ch->xMin < xxMin) { + xxMin = ch->xMin; + } + if (ch->xMax > xxMax) { + xxMax = ch->xMax; + } + ++i1; + baseAvg = baseTotal / (i1 - i0); + } + splitLines->append(new SplitLine(i0, i1 - 1, xxMin, xxMax)); + i0 = i1; + } + firstChar = nextChar; + } + + } else { + + // split into non-overlapping chunks + int firstChar = 0; + while (firstChar < charsA->getLength()) { + TextChar *ch = (TextChar *)charsA->get(firstChar); + double yyMax = ch->yMax; + int nextChar = firstChar + 1; + while (nextChar < charsA->getLength()) { + ch = (TextChar *)charsA->get(nextChar); + if (ch->yMin > yyMax) { + break; + } if (ch->yMax > yyMax) { yyMax = ch->yMax; - splitLine->yMax = yyMax; } + ++nextChar; + } + + // split the chunk [firstChar, nextChar) into lines + charsA->sort(firstChar, nextChar - firstChar, &TextChar::cmpBase); + int i0 = firstChar; + while (i0 < nextChar) { + ch = (TextChar *)charsA->get(i0); + double baseTotal = ch->base; + double baseAvg = baseTotal; + double yyMin = ch->yMin; + yyMax = ch->yMax; + int i1 = i0 + 1; + while (i1 < nextChar) { + ch = (TextChar *)charsA->get(i1); + if (ch->base > baseAvg + baseDelta) { + break; + } + baseTotal += ch->base; + if (ch->yMin < yyMin) { + yyMin = ch->yMin; + } + if (ch->yMax > yyMax) { + yyMax = ch->yMax; + } + ++i1; + baseAvg = baseTotal / (i1 - i0); + } + splitLines->append(new SplitLine(i0, i1 - 1, yyMin, yyMax)); + i0 = i1; } + firstChar = nextChar; } + } } @@ -4197,10 +4358,19 @@ void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { // merge sub/superscripts into correct lines if (allSubSuper) { + idxAbove = 0; + idxBelow = 0; for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { TextChar *ch = (TextChar *)splitLine->chars->get(idx); if (maybeSub && ch->xMin < prevLine->yMax) { - prevLine->chars->append(ch); + while (idxAbove < prevLine->chars->getLength()) { + TextChar *ch2 = (TextChar *)prevLine->chars->get(idxAbove); + if (ch2->yMin > ch->yMin && ch2->xMin < ch->xMax && ch2->xMax > ch->xMin) { + break; + } + ++idxAbove; + } + prevLine->chars->insert(idxAbove, ch); if (ch->xMin < prevLine->yMin) { prevLine->yMin = ch->xMin; } @@ -4208,7 +4378,14 @@ void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { prevLine->yMax = ch->xMax; } } else { - nextLine->chars->append(ch); + while (idxBelow < nextLine->chars->getLength()) { + TextChar *ch2 = (TextChar *)nextLine->chars->get(idxBelow); + if (ch2->yMin > ch->yMin && ch2->xMin < ch->xMax && ch2->xMax > ch->xMin) { + break; + } + ++idxBelow; + } + nextLine->chars->insert(idxBelow, ch); if (ch->xMin < nextLine->yMin) { nextLine->yMin = ch->xMin; } @@ -4217,12 +4394,6 @@ void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { } } } - if (maybeSub) { - prevLine->chars->sort(&TextChar::cmpY); - } - if (maybeSuper) { - nextLine->chars->sort(&TextChar::cmpY); - } delete splitLine; splitLines->del(i); } @@ -4252,14 +4423,14 @@ void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { prevLine = (SplitLine *)splitLines->get(i-1); double minOverlap = minSubSuperscriptVertOverlap * (prevLine->yMax - prevLine->yMin); - maybeSub = prevLine->yMax - splitLine->yMin > minOverlap; + maybeSub = prevLine->yMax - splitLine->yMin > minOverlap; } GBool maybeSuper = gFalse; if (i < splitLines->getLength() - 1) { nextLine = (SplitLine *)splitLines->get(i+1); double minOverlap = minSubSuperscriptVertOverlap * (nextLine->yMax - nextLine->yMin); - maybeSuper = splitLine->yMax - nextLine->yMin > minOverlap; + maybeSuper = splitLine->yMax - nextLine->yMin > minOverlap; } if (!maybeSub && !maybeSuper) { continue; @@ -4315,10 +4486,19 @@ void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { // merge sub/superscripts into correct lines if (allSubSuper) { + idxAbove = 0; + idxBelow = 0; for (int idx = 0; idx < splitLine->chars->getLength(); ++idx) { TextChar *ch = (TextChar *)splitLine->chars->get(idx); if (maybeSub && ch->yMin < prevLine->yMax) { - prevLine->chars->append(ch); + while (idxAbove < prevLine->chars->getLength()) { + TextChar *ch2 = (TextChar *)prevLine->chars->get(idxAbove); + if (ch2->xMin > ch->xMin && ch2->yMin < ch->yMax && ch2->yMax > ch->yMin) { + break; + } + ++idxAbove; + } + prevLine->chars->insert(idxAbove, ch); if (ch->yMin < prevLine->yMin) { prevLine->yMin = ch->yMin; } @@ -4326,7 +4506,14 @@ void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { prevLine->yMax = ch->yMax; } } else { - nextLine->chars->append(ch); + while (idxBelow < nextLine->chars->getLength()) { + TextChar *ch2 = (TextChar *)nextLine->chars->get(idxBelow); + if (ch2->xMin > ch->xMin && ch2->yMin < ch->yMax && ch2->yMax > ch->yMin) { + break; + } + ++idxBelow; + } + nextLine->chars->insert(idxBelow, ch); if (ch->yMin < nextLine->yMin) { nextLine->yMin = ch->yMin; } @@ -4335,12 +4522,6 @@ void TextPage::mergeSplitLines(GList *charsA, int rot, GList *splitLines) { } } } - if (maybeSub) { - prevLine->chars->sort(&TextChar::cmpX); - } - if (maybeSuper) { - nextLine->chars->sort(&TextChar::cmpX); - } delete splitLine; splitLines->del(i); } @@ -4517,20 +4698,48 @@ void TextPage::insertLargeCharInLeaf(TextChar *ch, TextBlock *blk) { } // Merge blk (rot != 0) into primaryTree (rot == 0). -void TextPage::insertIntoTree(TextBlock *blk, TextBlock *primaryTree) { - TextBlock *child; +void TextPage::insertIntoTree(TextBlock *blk, TextBlock *primaryTree, + GBool doReorder) { + // if we're separating each rotation (only supported in reading + // order mode), reorder the block's children as appropriate and then + // append the block + if (doReorder) { + reorderBlocks(blk); + primaryTree->children->append(blk); + + // otherwise, insert blocks into the primary tree in the appropriate + // locations + } else { - // we insert a whole column at a time - so call insertIntoTree - // recursively until we get to a column (or line) + // we insert a whole column at a time - so call insertIntoTree + // recursively until we get to a column (or line) + if (blk->tag == blkTagMulticolumn) { + while (blk->children->getLength()) { + TextBlock *child = (TextBlock *)blk->children->del(0); + insertIntoTree(child, primaryTree, doReorder); + } + delete blk; - if (blk->tag == blkTagMulticolumn) { - while (blk->children->getLength()) { - child = (TextBlock *)blk->children->del(0); - insertIntoTree(child, primaryTree); + } else { + insertColumnIntoTree(blk, primaryTree); } - delete blk; - } else { - insertColumnIntoTree(blk, primaryTree); + } +} + +// Reorder non-primary-rotation blocks as appropriate (for reading +// order mode only). +void TextPage::reorderBlocks(TextBlock *blk) { + if (blk->tag != blkTagMulticolumn) { + return; + } + for (int i = 0; i < blk->children->getLength(); ++i) { + reorderBlocks((TextBlock *)blk->children->get(i)); + } + //~ check/test these conditions + if ((blk->rot == 1 && blk->type == blkVertSplit) || + blk->rot == 2 || + (blk->rot == 3 && blk->type == blkHorizSplit)) { + blk->children->reverse(); } } @@ -5095,11 +5304,13 @@ TextLine *TextPage::buildLine(GList *charsA, int rot, TextWord *word; double wordSp, lineFontSize, sp; int dir, dir2; - GBool rotated, spaceAfter, spaceBefore; + GBool rotated2, spaceAfter, spaceBefore; int i, j; wordSp = computeWordSpacingThreshold(charsA, rot); + adjustCombiningChars(charsA, rot); + words = new GList(); lineFontSize = 0; spaceBefore = gFalse; @@ -5113,7 +5324,7 @@ TextLine *TextPage::buildLine(GList *charsA, int rot, : (TextChar *)NULL, (i < charsA->getLength() - 1) ? (TextChar *)charsA->get(i+1) : (TextChar *)NULL); - rotated = ((TextChar *)charsA->get(i))->rotated; + rotated2 = ((TextChar *)charsA->get(i))->rotated; for (j = i+1; j < charsA->getLength(); ++j) { ch = (TextChar *)charsA->get(j-1); ch2 = (TextChar *)charsA->get(j); @@ -5134,7 +5345,7 @@ TextLine *TextPage::buildLine(GList *charsA, int rot, : (TextChar *)NULL); if (ch->font != ch2->font || fabs(ch->fontSize - ch2->fontSize) > 0.01 || - (control.splitRotatedWords && ch2->rotated != rotated) || + (control.splitRotatedWords && ch2->rotated != rotated2) || (dir && dir2 && dir2 != dir) || (control.mode == textOutRawOrder && ch2->charPos != ch->charPos + ch->charLen)) { @@ -5145,7 +5356,7 @@ TextLine *TextPage::buildLine(GList *charsA, int rot, } sp = wordSp - 1; } - word = new TextWord(charsA, i, j - i, rot, rotated, dir, + word = new TextWord(charsA, i, j - i, rot, rotated2, dir, (rot >= 2) ? spaceBefore : spaceAfter); spaceBefore = spaceAfter; i = j; @@ -5277,6 +5488,89 @@ double TextPage::computeWordSpacingThreshold(GList *charsA, int rot) { } } +// Move Unicode combining characters around so that they come +// immediately after the correct base characters. +//~ this currently won't work for RtL scripts +void TextPage::adjustCombiningChars(GList *charsA, int rot) { + int i = 1; + while (i < charsA->getLength()) { + TextChar *ch = (TextChar *)charsA->get(i); + + // look for a zero-width combining char + if (!(unicodeTypeCombiningMark(ch->c) && + fabs((rot & 1) ? ch->yMax - ch->yMin // width ~= zero + : ch->xMax - ch->xMin) < 0.01)) { + ++i; + continue; + } + + // look for a sequence of zero-width combining chars at the same + // position (NB: slight negative char spacing can reorder things + // so that diacritics for different base chars appear next to each + // other) + int j; + for (j = i + 1; j < charsA->getLength(); ++j) { + TextChar *ch2 = (TextChar *)charsA->get(j); + if (!(unicodeTypeCombiningMark(ch2->c) && + fabs((rot & 1) ? ch2->yMin - ch->yMax + : ch2->xMin - ch->xMax) < 0.01 * ch->fontSize && + fabs((rot & 1) ? ch->yMax - ch->yMin // width ~= zero + : ch->xMax - ch->xMin) < 0.01)) { + break; + } + } + + // identify the two previous chars + TextChar *prev1 = (i >= 2) ? (TextChar *)charsA->get(i - 2) : NULL; + TextChar *prev2 = (TextChar *)charsA->get(i - 1); + + //~ this code currently makes things worse for RtL scripts, so + //~ skip any RtL text + if (unicodeTypeR(prev2->c)) { + ++i; + continue; + } + + // if the combining chars are placed in the left 3/4 of prev2, + // assume the base char is prev1, not prev2, and reorder the chars + // accordingly + TextChar *base; + if (prev1 && + ((rot & 1) ? (ch->yMin < 0.25 * prev2->yMin + 0.75 * prev2->yMax) + : (ch->xMin < 0.25 * prev2->xMin + 0.75 * prev2->xMax))) { + for (int k = i; k < j; ++k) { + charsA->put(k - 1, charsA->get(k)); + } + charsA->put(j - 1, prev2); + --i; + --j; + base = prev1; + } else { + base = prev2; + } + + // sort the diacritics into content stream order + // (slight negative char spacing, used for kerning, will push + // zero-width diacritics out of order) + if (j - i > 1) { + charsA->sort(i, j - i, &TextChar::cmpCharPos); + } + + // set the diacritics' positions immediately to the right of the + // base char + for (int k = i; k < j; ++k) { + TextChar *ch2 = (TextChar *)charsA->get(k); + if (rot & 1) { + ch2->yMin = ch2->yMax = base->yMax; + } else { + ch2->xMin = ch2->xMax = base->xMax; + } + } + + i = j; + } +} + // Check the character's direction: returns 1 for L or Num; -1 for R; 0 // for others. int TextPage::getCharDirection(TextChar *ch) { @@ -6624,7 +6918,8 @@ void TextOutputDev::endString(GfxState *state) { void TextOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, - CharCode c, int nBytes, Unicode *u, int uLen) { + CharCode c, int nBytes, Unicode *u, int uLen, + GBool fill, GBool stroke, GBool makePath) { text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen); } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h index 302975cd5f1..fc7bcb616dd 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TextOutputDev.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include <stdio.h> #include "gtypes.h" #include "GfxFont.h" @@ -122,6 +118,9 @@ public: // Get the width of the 'm' character, if available. double getMWidth() { return mWidth; } + double getAscent() { return ascent; } + double getDescent() { return descent; } + Ref getFontID() { return fontID; } private: @@ -474,10 +473,18 @@ public: TextWordList *makeWordListForRect(double xMin, double yMin, double xMax, double yMax); + // Get the primary rotation of text on the page. + int getPrimaryRotation() { return primaryRot; } + // Returns true if the primary character direction is left-to-right, // false if it is right-to-left. GBool primaryDirectionIsLR(); + // Get the counter values. + int getNumVisibleChars() { return nVisibleChars; } + int getNumInvisibleChars() { return nInvisibleChars; } + int getNumRemovedDupChars() { return nRemovedDupChars; } + // Returns true if any of the fonts used on this page are likely to // be problematic when converting text to Unicode. GBool problematicForUnicode() { return problematic; } @@ -557,7 +564,7 @@ private: GList *separateOverlappingText(GList *charsA); TextColumn *buildOverlappingTextColumn(GList *overlappingChars); TextBlock *splitChars(GList *charsA); - TextBlock *split(GList *charsA, int rot, GBool vertOnly); + TextBlock *split(GList *charsA, int rot); GList *getChars(GList *charsA, double xMin, double yMin, double xMax, double yMax); void findGaps(GList *charsA, int rot, @@ -571,7 +578,9 @@ private: void insertLargeChars(GList *largeChars, TextBlock *blk); void insertLargeCharsInFirstLeaf(GList *largeChars, TextBlock *blk); void insertLargeCharInLeaf(TextChar *ch, TextBlock *blk); - void insertIntoTree(TextBlock *subtree, TextBlock *primaryTree); + void insertIntoTree(TextBlock *subtree, TextBlock *primaryTree, + GBool doReorder); + void reorderBlocks(TextBlock *blk); void insertColumnIntoTree(TextBlock *column, TextBlock *tree); void insertClippedChars(GList *clippedChars, TextBlock *tree); TextBlock *findClippedCharLeaf(TextChar *ch, TextBlock *tree); @@ -589,6 +598,7 @@ private: double xMin, double yMin, double xMax, double yMax); void getLineChars(TextBlock *blk, GList *charsA); double computeWordSpacingThreshold(GList *charsA, int rot); + void adjustCombiningChars(GList *charsA, int rot); int getCharDirection(TextChar *ch); int getCharDirection(TextChar *ch, TextChar *left, TextChar *right); int assignPhysLayoutPositions(GList *columns); @@ -640,10 +650,15 @@ private: GList *chars; // [TextChar] GList *fonts; // all font info objects used on this // page [TextFontInfo] + int primaryRot; // primary rotation GList *underlines; // [TextUnderline] GList *links; // [TextLink] + int nVisibleChars; // number of visible chars on the page + int nInvisibleChars; // number of invisible chars on the page + int nRemovedDupChars; // number of duplicate chars removed + GList *findCols; // text used by the findText**/findPoint** // functions [TextColumn] double lastFindXMin, // coordinates of the last "find" result @@ -725,7 +740,8 @@ public: virtual void drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, - CharCode c, int nBytes, Unicode *u, int uLen); + CharCode c, int nBytes, Unicode *u, int uLen, + GBool fill, GBool stroke, GBool makePath); virtual void incCharCount(int nChars); virtual void beginActualText(GfxState *state, Unicode *u, int uLen); virtual void endActualText(GfxState *state); @@ -784,6 +800,11 @@ public: // Turn extra processing for HTML conversion on or off. void enableHTMLExtras(GBool html) { control.html = html; } + // Get the counter values. + int getNumVisibleChars() { return text->nVisibleChars; } + int getNumInvisibleChars() { return text->nInvisibleChars; } + int getNumRemovedDupChars() { return text->nRemovedDupChars; } + private: void generateBOM(); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TextString.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TextString.cc index 8e54a1d5471..5541bc61102 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TextString.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TextString.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <string.h> #include "gmem.h" #include "gmempp.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TextString.h b/Build/source/libs/xpdf/xpdf-src/xpdf/TextString.h index c296d7d6d7a..909d3259097 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TextString.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TextString.h @@ -15,10 +15,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "CharTypes.h" class GString; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCache.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCache.cc index ff002ed46fc..65e60629bd2 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCache.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCache.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmem.h" #include "gmempp.h" #include "GList.h" @@ -237,7 +233,7 @@ GThreadReturn TileCacheThreadPool::threadFunc(void *arg) { } void TileCacheThreadPool::worker() { - CachedTileDesc *ct; + CachedTileDesc *ct = NULL; while (1) { gLockMutex(&mutex); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCache.h b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCache.h index bea58c4c8fc..1c3f83cba47 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCache.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCache.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "SplashTypes.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc index 70128a4a47f..eaea7fa5676 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <string.h> #include <math.h> #include "gmempp.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.h b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.h index aa06c9da7bd..9efec4d0a16 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileCompositor.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "SplashTypes.h" class GList; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc index d5916627082..fa262a28f94 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmem.h" #include "gmempp.h" #include "GList.h" @@ -903,7 +899,7 @@ void TileMap::cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu) { void TileMap::getWindowPageRange(int x, int y, int w, int h, int *firstPage, int *lastPage) { - GList *tiles; + GList *tiles2; PlacedTileDesc *tile; int i; @@ -913,9 +909,9 @@ void TileMap::getWindowPageRange(int x, int y, int w, int h, } *firstPage = state->getDoc()->getNumPages(); *lastPage = 0; - tiles = getTileList(); - for (i = 0; i < tiles->getLength(); ++i) { - tile = (PlacedTileDesc *)tiles->get(i); + tiles2 = getTileList(); + for (i = 0; i < tiles2->getLength(); ++i) { + tile = (PlacedTileDesc *)tiles2->get(i); if (tile->px < x + w && tile->px + tile->tw > x && tile->py < y + h && @@ -1352,7 +1348,7 @@ void TileMap::updatePageParams() { // rotate the page boxes if (page & 1) { otherPage = page + 1; - if (otherPage >= state->getDoc()->getNumPages()) { + if (otherPage > state->getDoc()->getNumPages()) { otherPage = page; } } else { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.h b/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.h index 222877c5050..6a2dcb3e672 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/TileMap.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" class GList; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMap.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMap.cc index 833d6fc2f0c..68e38c3a36e 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMap.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMap.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <string.h> #include "gmem.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMap.h b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMap.h index a15d628b4cc..d932d0e34c9 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMap.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeMap.h @@ -13,10 +13,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "CharTypes.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc index 72dbc0e159c..cfa28a0b79a 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <string.h> #include "gmem.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h index dbf435e7dd1..679c002987f 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeRemapping.h @@ -13,10 +13,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "CharTypes.h" struct UnicodeRemappingString; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc index e6a91af2756..a19bbe0d655 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.cc @@ -25,36 +25,36 @@ static UnicodeMapTableEntry typeTable[256] = { { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN...NNNNN.....##########.NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.N....NNNNLNNNNN..##NLNNN#LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' }, { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLNNNNNNNNNNNNNNLLNNNNNNNNNNNNNNLLLLLNNNNNNNNNLNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLNNLLLLLLLLNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRNRNNRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR###########", 'X' }, - { "######NNR..R.RNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNN##########.##RRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNN#NNNNNNNRRNNNNNNNRR##########RRRRRR", 'X' }, - { "RRRRRRRRRRRRRRRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNRRNNNNRNNNRR", 'X' }, - { "RRRRRRRRRRRRRRRRRRRRRRNNNNRNNNNNNNNNRNNNRNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNN#NNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLLLLNNNNNNNNLLLLNLLLNNNNNNNLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLL..LLLLLLL.LLNN", 'X' }, - { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNLNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLL.LLLLLLLLNNNNNN", 'X' }, - { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNNLLLLLLLLNNNNNNNNNNLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNN.NNNNNN", 'X' }, - { "NLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNNNNNNLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLNNNNNNNNNNNNN", 'X' }, - { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNN.....LLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNLNNNNNLNNLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLNNNNNNLNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLNNNLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNLLNNLLLLLLNLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { NULL, 'L' }, - { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNN", 'X' }, + { "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMLLLLNNLLLLLLLLNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNN.MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMRMRMMRMMRMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR###########", 'X' }, + { "######NNR..R.RNNMMMMMMMMMMMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRMMMMMMMMMMMMMMMMMMMMM##########.##RRRMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRMMMMMMM#NMMMMMMRRMMNMMMMRR##########RRRRRR", 'X' }, + { "RRRRRRRRRRRRRRRRRMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRMMMMMMMMMMMMMMMMMMMMMMMMMMMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRMMMMMMMMMMMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRMMMMMMMMMRRNNNNRMMMRR", 'X' }, + { "RRRRRRRRRRRRRRRRRRRRRRMMMMRMMMMMMMMMRMMMRMMMMMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRMMMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR###MMMMMMMMMMMMMMRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRMMMMMMMMMMMMMMMMMMMMMMMM#MMMMMMMMMMMMMMMMMMMMMMMMMMMMM", 'X' }, + { "MMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLMLLLLMMMMMMMMLLLLMLLLMMMMMMMLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMLLLLMMMMLLLLLLLLMLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLL..LLLLLLL.LLMM", 'X' }, + { "MMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMLLLLMMMMMMMMMMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLMLMMMMMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMLLLLMMMMMMMMLLLLMLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLL.LLLLLLLLMMMMMM", 'X' }, + { "MMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMLLMLMMMMLLLLLLLLMMMMMMMMMMLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLLLLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNN.NMMMMM", 'X' }, + { "MLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMLMMMLLLLMMMMMMMMMMMMMMMMMMLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLNNNNNNNLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLMMMMMMMMMMMM", 'X' }, + { "MMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLMMMMLLLLLLLLMLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMLLLLLLLMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLMMMMMMM.....LLLLLLLMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLMMMMMMMMMLLLLLLLLLLMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLMLMLMNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMLMMMMMLMMLLLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMLLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMLMMMMMMLMMLLMMLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLMMMLLLLLLLLLLLLLLLLMMMMLLLLLLLLLLLLLMLLMMLLLLLLMLLLLLLLLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNN", 'X' }, { "NLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLL.LNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLNNLLLLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLNNLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNNNNNNNLNLLNNNNNNNNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, - { "NNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNNNLNLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNLLLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLNNLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNLLLNLNNNLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLNNNNNNNNNNNNNLNNNNNNNLLLLNLLLLLLNLLLNNLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLMMMMMMMLLLLLLLLMLLMMMMMMMMMMMLLLLLLL.LMLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNMMMNMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMLLLLMMLLLLLLLLLMLLLLLLMMMNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLMMLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLMMMMMMMMMLMLLMMMMMMMMLLLLLLMMMMMMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM", 'X' }, + { "MMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLMMMMMLMLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMLLLLLLLLLLLMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMLLMMLMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLMMLLLMLMMMLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMLMMMMMMMMMMMMMLMMMMMMMLLLLMLLLLLLMLLLMMLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM", 'X' }, { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLLLLLLLLLLNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNNNLLLLLLLLLLLLLNNN", 'X' }, - { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLR......NNNNNNNNNNNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLRNNNNNNNN#L########..NNNL##########..NNNLLLLLLLLLLLLLL...................................NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLR......NNNNNNNNNNNNNNN.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLRNNNNNNNN#L########..NNNL##########..NNNLLLLLLLLLLLLLL....................................MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNNNNNNNNNNNNNNN", 'X' }, { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLL.LLLLLLLLLLLNNLLLLNNNNNLLLLLNNNNLLNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNN..NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, @@ -66,12 +66,12 @@ static UnicodeMapTableEntry typeTable[256] = { { NULL, 'N' }, { NULL, 'N' }, { NULL, 'N' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNLLNNNNNNNNNNNN", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLMMMLLNNNNNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM", 'X' }, { NULL, 'N' }, { NULL, 'N' }, - { "NNNNNLLLNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNNNNLLNLLLLLNNLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "NNNNNLLLNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLMMMMLLNLLLLLNNLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMNNLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN", 'X' }, { NULL, 'L' }, @@ -188,12 +188,12 @@ static UnicodeMapTableEntry typeTable[256] = { { NULL, 'L' }, { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, { NULL, 'L' }, - { "LLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLNNNNNNNN", 'X' }, + { "LLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMNMMMMMMMMMMNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLNNNNNNNN", 'X' }, { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLNLLLNLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLNNLNNNNNLLLLLLLLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLN", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLNNLLNNLLLLLLLLLLLLNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLNNLLLLLNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLNLLLLLLLLL", 'X' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNLLLLNLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLMLLLMLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLMMLNNNNMLLLLLLLLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMMLLLLLLLLLLLLLM", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLMMMMLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMLLMMLLMMLLLLLLLLLLLLMLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLMMMLLMMLLLLLMMLMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMLLLLLLLLMLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMLLMLLLLMLLLLLLLLLLLLLLLLLL", 'X' }, { NULL, 'L' }, { NULL, 'L' }, { NULL, 'L' }, @@ -273,10 +273,10 @@ static UnicodeMapTableEntry typeTable[256] = { { NULL, 'L' }, { NULL, 'L' }, { NULL, 'L' }, - { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRMRRRRRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, { NULL, 'R' }, - { "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, - { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.N.NN.NNNNNNNNN.NN..NNNNN..NRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, + { "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, + { "MMMMMMMMMMMMMMMMNNNNNNNNNNMMMMMMMMMMMMMMMMMMMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.N.NN.NNNNNNNNN.NN..NNNNN..NRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, { "NNN...NNNNN.....##########.NNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.....NNN..NNNNNNNNNNNNNNNNNNNNNNNLL", 'X' } }; @@ -647,9 +647,9 @@ static UnicodeCaseTableVector caseTable1f = {{ 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0x1fbd, 0x03b9, 0x1fbf, 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf, - 0x1fd0, 0x1fd1, 0x1fd2, 0x1fd3, 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, + 0x1fd0, 0x1fd1, 0x1fd2, 0x0390, 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf, - 0x1fe0, 0x1fe1, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fe5, 0x1fe6, 0x1fe7, + 0x1fe0, 0x1fe1, 0x1fe2, 0x03b0, 0x1fe4, 0x1fe5, 0x1fe6, 0x1fe7, 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0x1fed, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff @@ -728,7 +728,7 @@ static UnicodeCaseTableVector caseTable2c = {{ 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47, 0x2c48, 0x2c49, 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4d, 0x2c4e, 0x2c4f, 0x2c50, 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c57, - 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x2c2f, + 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x2c5f, 0x2c30, 0x2c31, 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37, 0x2c38, 0x2c39, 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f, 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47, @@ -815,10 +815,10 @@ static UnicodeCaseTableVector caseTablea7 = {{ 0xa7a9, 0xa7a9, 0x0266, 0x025c, 0x0261, 0x026c, 0x026a, 0xa7af, 0x029e, 0x0287, 0x029d, 0xab53, 0xa7b5, 0xa7b5, 0xa7b7, 0xa7b7, 0xa7b9, 0xa7b9, 0xa7bb, 0xa7bb, 0xa7bd, 0xa7bd, 0xa7bf, 0xa7bf, - 0xa7c0, 0xa7c1, 0xa7c3, 0xa7c3, 0xa794, 0x0282, 0x1d8e, 0xa7c8, + 0xa7c1, 0xa7c1, 0xa7c3, 0xa7c3, 0xa794, 0x0282, 0x1d8e, 0xa7c8, 0xa7c8, 0xa7ca, 0xa7ca, 0xa7cb, 0xa7cc, 0xa7cd, 0xa7ce, 0xa7cf, - 0xa7d0, 0xa7d1, 0xa7d2, 0xa7d3, 0xa7d4, 0xa7d5, 0xa7d6, 0xa7d7, - 0xa7d8, 0xa7d9, 0xa7da, 0xa7db, 0xa7dc, 0xa7dd, 0xa7de, 0xa7df, + 0xa7d1, 0xa7d1, 0xa7d2, 0xa7d3, 0xa7d4, 0xa7d5, 0xa7d7, 0xa7d7, + 0xa7d9, 0xa7d9, 0xa7da, 0xa7db, 0xa7dc, 0xa7dd, 0xa7de, 0xa7df, 0xa7e0, 0xa7e1, 0xa7e2, 0xa7e3, 0xa7e4, 0xa7e5, 0xa7e6, 0xa7e7, 0xa7e8, 0xa7e9, 0xa7ea, 0xa7eb, 0xa7ec, 0xa7ed, 0xa7ee, 0xa7ef, 0xa7f0, 0xa7f1, 0xa7f2, 0xa7f3, 0xa7f4, 0xa7f6, 0xa7f6, 0xa7f7, @@ -858,6 +858,40 @@ static UnicodeCaseTableVector caseTableab = {{ 0xabf0, 0xabf1, 0xabf2, 0xabf3, 0xabf4, 0xabf5, 0xabf6, 0xabf7, 0xabf8, 0xabf9, 0xabfa, 0xabfb, 0xabfc, 0xabfd, 0xabfe, 0xabff }}; +static UnicodeCaseTableVector caseTablefb = {{ + 0xfb00, 0xfb01, 0xfb02, 0xfb03, 0xfb04, 0xfb06, 0xfb06, 0xfb07, + 0xfb08, 0xfb09, 0xfb0a, 0xfb0b, 0xfb0c, 0xfb0d, 0xfb0e, 0xfb0f, + 0xfb10, 0xfb11, 0xfb12, 0xfb13, 0xfb14, 0xfb15, 0xfb16, 0xfb17, + 0xfb18, 0xfb19, 0xfb1a, 0xfb1b, 0xfb1c, 0xfb1d, 0xfb1e, 0xfb1f, + 0xfb20, 0xfb21, 0xfb22, 0xfb23, 0xfb24, 0xfb25, 0xfb26, 0xfb27, + 0xfb28, 0xfb29, 0xfb2a, 0xfb2b, 0xfb2c, 0xfb2d, 0xfb2e, 0xfb2f, + 0xfb30, 0xfb31, 0xfb32, 0xfb33, 0xfb34, 0xfb35, 0xfb36, 0xfb37, + 0xfb38, 0xfb39, 0xfb3a, 0xfb3b, 0xfb3c, 0xfb3d, 0xfb3e, 0xfb3f, + 0xfb40, 0xfb41, 0xfb42, 0xfb43, 0xfb44, 0xfb45, 0xfb46, 0xfb47, + 0xfb48, 0xfb49, 0xfb4a, 0xfb4b, 0xfb4c, 0xfb4d, 0xfb4e, 0xfb4f, + 0xfb50, 0xfb51, 0xfb52, 0xfb53, 0xfb54, 0xfb55, 0xfb56, 0xfb57, + 0xfb58, 0xfb59, 0xfb5a, 0xfb5b, 0xfb5c, 0xfb5d, 0xfb5e, 0xfb5f, + 0xfb60, 0xfb61, 0xfb62, 0xfb63, 0xfb64, 0xfb65, 0xfb66, 0xfb67, + 0xfb68, 0xfb69, 0xfb6a, 0xfb6b, 0xfb6c, 0xfb6d, 0xfb6e, 0xfb6f, + 0xfb70, 0xfb71, 0xfb72, 0xfb73, 0xfb74, 0xfb75, 0xfb76, 0xfb77, + 0xfb78, 0xfb79, 0xfb7a, 0xfb7b, 0xfb7c, 0xfb7d, 0xfb7e, 0xfb7f, + 0xfb80, 0xfb81, 0xfb82, 0xfb83, 0xfb84, 0xfb85, 0xfb86, 0xfb87, + 0xfb88, 0xfb89, 0xfb8a, 0xfb8b, 0xfb8c, 0xfb8d, 0xfb8e, 0xfb8f, + 0xfb90, 0xfb91, 0xfb92, 0xfb93, 0xfb94, 0xfb95, 0xfb96, 0xfb97, + 0xfb98, 0xfb99, 0xfb9a, 0xfb9b, 0xfb9c, 0xfb9d, 0xfb9e, 0xfb9f, + 0xfba0, 0xfba1, 0xfba2, 0xfba3, 0xfba4, 0xfba5, 0xfba6, 0xfba7, + 0xfba8, 0xfba9, 0xfbaa, 0xfbab, 0xfbac, 0xfbad, 0xfbae, 0xfbaf, + 0xfbb0, 0xfbb1, 0xfbb2, 0xfbb3, 0xfbb4, 0xfbb5, 0xfbb6, 0xfbb7, + 0xfbb8, 0xfbb9, 0xfbba, 0xfbbb, 0xfbbc, 0xfbbd, 0xfbbe, 0xfbbf, + 0xfbc0, 0xfbc1, 0xfbc2, 0xfbc3, 0xfbc4, 0xfbc5, 0xfbc6, 0xfbc7, + 0xfbc8, 0xfbc9, 0xfbca, 0xfbcb, 0xfbcc, 0xfbcd, 0xfbce, 0xfbcf, + 0xfbd0, 0xfbd1, 0xfbd2, 0xfbd3, 0xfbd4, 0xfbd5, 0xfbd6, 0xfbd7, + 0xfbd8, 0xfbd9, 0xfbda, 0xfbdb, 0xfbdc, 0xfbdd, 0xfbde, 0xfbdf, + 0xfbe0, 0xfbe1, 0xfbe2, 0xfbe3, 0xfbe4, 0xfbe5, 0xfbe6, 0xfbe7, + 0xfbe8, 0xfbe9, 0xfbea, 0xfbeb, 0xfbec, 0xfbed, 0xfbee, 0xfbef, + 0xfbf0, 0xfbf1, 0xfbf2, 0xfbf3, 0xfbf4, 0xfbf5, 0xfbf6, 0xfbf7, + 0xfbf8, 0xfbf9, 0xfbfa, 0xfbfb, 0xfbfc, 0xfbfd, 0xfbfe, 0xfbff +}}; static UnicodeCaseTableVector caseTableff = {{ 0xff00, 0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, @@ -1144,7 +1178,7 @@ static UnicodeCaseTableVector *caseTable[256] = { NULL, NULL, NULL, - NULL, + &caseTablefb, NULL, NULL, NULL, @@ -1400,8 +1434,8 @@ static Unicode bracketTable2e[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x80002e56, 0x2e55, 0x80002e58, + 0x2e57, 0x80002e5a, 0x2e59, 0x80002e5c, 0x2e5b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1807,6 +1841,10 @@ GBool unicodeTypeR(Unicode c) { return getType(c) == 'R'; } +GBool unicodeTypeCombiningMark(Unicode c) { + return getType(c) == 'M'; +} + GBool unicodeTypeDigit(Unicode c) { return getType(c) == '#'; } @@ -1833,7 +1871,7 @@ GBool unicodeTypeWord(Unicode c) { char t; t = getType(c); - return t == 'L' || t == 'R' || t == '#'; + return t == 'L' || t == 'R' || t == '#' || t == 'M'; } Unicode unicodeToLower(Unicode c) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h index e1149fd6bc2..f04361f9266 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/UnicodeTypeTable.h @@ -15,6 +15,8 @@ extern GBool unicodeTypeL(Unicode c); extern GBool unicodeTypeR(Unicode c); +extern GBool unicodeTypeCombiningMark(Unicode c); + extern GBool unicodeTypeDigit(Unicode c); extern GBool unicodeTypeNumSep(Unicode c); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc index c04b52f937a..24d0896aa84 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "gmem.h" #include "gmempp.h" #include "GHash.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h index 283bdbe914d..c3c8ef1cbdd 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.h @@ -13,10 +13,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "FoFiBase.h" #include "GfxFont.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc index 8002a07a7f6..22b2f0d02e6 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include "GString.h" #include "GHash.h" #include "Object.h" diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.h b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.h index 00ee6f7fcee..22aac009048 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XFAScanner.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - class GHash; class ZxElement; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc index 51af86db5ba..d3f9bcb2906 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <stddef.h> #include <string.h> @@ -133,7 +129,7 @@ public: // Create an object stream, using object number <objStrNum>, // generation 0. - ObjectStream(XRef *xref, int objStrNumA); + ObjectStream(XRef *xref, int objStrNumA, int recursion); GBool isOk() { return ok; } @@ -155,7 +151,7 @@ private: GBool ok; }; -ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { +ObjectStream::ObjectStream(XRef *xref, int objStrNumA, int recursion) { Stream *str; Lexer *lexer; Parser *parser; @@ -169,7 +165,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { objNums = NULL; ok = gFalse; - if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) { + if (!xref->fetch(objStrNum, 0, &objStr, recursion)->isStream()) { goto err1; } @@ -234,11 +230,10 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { lexer->skipToEOF(); delete parser; - // skip to the first object - this shouldn't be necessary because - // the First key is supposed to be equal to offsets[0], but just in - // case... - if (first < offsets[0]) { - objStr.getStream()->discardChars(offsets[0] - first); + // skip to the first object - this generally shouldn't be needed, + // because offsets[0] is normally 0, but just in case... + if (offsets[0] > 0) { + objStr.getStream()->discardChars(offsets[0]); } // parse the objects @@ -880,6 +875,7 @@ GBool XRef::constructXRef() { char *p = buf; char *end = buf; GBool startOfLine = gTrue; + GBool space = gTrue; GBool eof = gFalse; while (1) { if (end - p < 256 && !eof) { @@ -900,6 +896,7 @@ GBool XRef::constructXRef() { constructTrailerDict((GFileOffset)(bufPos + (p + 7 - buf))); p += 7; startOfLine = gFalse; + space = gFalse; } else if (startOfLine && !strncmp(p, "endstream", 9)) { if (streamEndsLen == streamEndsSize) { streamEndsSize += 64; @@ -909,19 +906,23 @@ GBool XRef::constructXRef() { streamEnds[streamEndsLen++] = (GFileOffset)(bufPos + (p - buf)); p += 9; startOfLine = gFalse; - } else if (startOfLine && *p >= '0' && *p <= '9') { + space = gFalse; + } else if (space && *p >= '0' && *p <= '9') { p = constructObjectEntry(p, (GFileOffset)(bufPos + (p - buf)), &lastObjNum); startOfLine = gFalse; + space = gFalse; } else if (p[0] == '>' && p[1] == '>') { p += 2; startOfLine = gFalse; + space = gFalse; // skip any PDF whitespace except for '\0' while (*p == '\t' || *p == '\n' || *p == '\x0c' || *p == '\r' || *p == ' ') { if (*p == '\n' || *p == '\r') { startOfLine = gTrue; } + space = gTrue; ++p; } if (!strncmp(p, "stream", 6)) { @@ -935,12 +936,17 @@ GBool XRef::constructXRef() { } p += 6; startOfLine = gFalse; + space = gFalse; } } else { if (*p == '\n' || *p == '\r') { startOfLine = gTrue; - } else if (!Lexer::isSpace(*p & 0xff)) { + space = gTrue; + } else if (Lexer::isSpace(*p & 0xff)) { + space = gTrue; + } else { startOfLine = gFalse; + space = gFalse; } ++p; } @@ -1263,7 +1269,7 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) { error(errSyntaxError, -1, "Invalid object stream"); goto err; } - if (!getObjectStreamObject((int)e->offset, e->gen, num, obj)) { + if (!getObjectStreamObject((int)e->offset, e->gen, num, obj, recursion)) { goto err; } break; @@ -1297,43 +1303,57 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) { } GBool XRef::getObjectStreamObject(int objStrNum, int objIdx, - int objNum, Object *obj) { - ObjectStream *objStr; - + int objNum, Object *obj, int recursion) { + // check for a cached ObjectStream #if MULTITHREADED gLockMutex(&objStrsMutex); #endif - if (!(objStr = getObjectStream(objStrNum))) { + ObjectStream *objStr = getObjectStreamFromCache(objStrNum); + GBool found = gFalse; + if (objStr) { + objStr->getObject(objIdx, objNum, obj); + cleanObjectStreamCache(); + found = gTrue; + } #if MULTITHREADED - gUnlockMutex(&objStrsMutex); + gUnlockMutex(&objStrsMutex); #endif + if (found) { + return gTrue; + } + + // load a new ObjectStream + objStr = new ObjectStream(this, objStrNum, recursion); + if (!objStr->isOk()) { + delete objStr; return gFalse; } - cleanObjectStreamCache(); objStr->getObject(objIdx, objNum, obj); #if MULTITHREADED + gLockMutex(&objStrsMutex); +#endif + addObjectStreamToCache(objStr); + cleanObjectStreamCache(); +#if MULTITHREADED gUnlockMutex(&objStrsMutex); #endif return gTrue; } // NB: objStrsMutex must be locked when calling this function. -ObjectStream *XRef::getObjectStream(int objStrNum) { - ObjectStream *objStr; - int i, j; - +ObjectStream *XRef::getObjectStreamFromCache(int objStrNum) { // check the MRU entry in the cache if (objStrs[0] && objStrs[0]->getObjStrNum() == objStrNum) { - objStr = objStrs[0]; + ObjectStream *objStr = objStrs[0]; objStrLastUse[0] = objStrTime++; return objStr; } // check the rest of the cache - for (i = 1; i < objStrCacheLength; ++i) { + for (int i = 1; i < objStrCacheLength; ++i) { if (objStrs[i] && objStrs[i]->getObjStrNum() == objStrNum) { - objStr = objStrs[i]; - for (j = i; j > 0; --j) { + ObjectStream *objStr = objStrs[i]; + for (int j = i; j > 0; --j) { objStrs[j] = objStrs[j - 1]; objStrLastUse[j] = objStrLastUse[j - 1]; } @@ -1343,33 +1363,30 @@ ObjectStream *XRef::getObjectStream(int objStrNum) { } } - // load a new ObjectStream - objStr = new ObjectStream(this, objStrNum); - if (!objStr->isOk()) { - delete objStr; - return NULL; - } + return NULL; +} +// NB: objStrsMutex must be locked when calling this function. +void XRef::addObjectStreamToCache(ObjectStream *objStr) { // add to the cache if (objStrCacheLength == objStrCacheSize) { delete objStrs[objStrCacheSize - 1]; --objStrCacheLength; } - for (j = objStrCacheLength; j > 0; --j) { + for (int j = objStrCacheLength; j > 0; --j) { objStrs[j] = objStrs[j - 1]; objStrLastUse[j] = objStrLastUse[j - 1]; } ++objStrCacheLength; objStrs[0] = objStr; objStrLastUse[0] = objStrTime++; - - return objStr; } // If the oldest (least recently used) entry in the object stream // cache is more than objStrCacheTimeout accesses old (hasn't been // used in the last objStrCacheTimeout accesses), eject it from the // cache. +// NB: objStrsMutex must be locked when calling this function. void XRef::cleanObjectStreamCache() { // NB: objStrTime and objStrLastUse[] are unsigned ints, so the // mod-2^32 arithmetic makes the subtraction work out, even if the diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h b/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h index 10e4e6a7501..662b8351c00 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/XRef.h @@ -11,10 +11,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" #include "gfile.h" #include "Object.h" @@ -183,8 +179,9 @@ private: GBool constructXRefEntry(int num, int gen, GFileOffset pos, XRefEntryType type); GBool getObjectStreamObject(int objStrNum, int objIdx, - int objNum, Object *obj); - ObjectStream *getObjectStream(int objStrNum); + int objNum, Object *obj, int recursion); + ObjectStream *getObjectStreamFromCache(int objStrNum); + void addObjectStreamToCache(ObjectStream *objStr); void cleanObjectStreamCache(); GFileOffset strToFileOffset(char *s); }; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Zoox.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Zoox.cc index 9e4fb47900c..2e41d990b59 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Zoox.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Zoox.cc @@ -6,10 +6,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -279,6 +275,8 @@ bool ZxDoc::parse(const char *data, Guint dataLen) { parseEnd = data + dataLen; parseSpace(); + parseBOM(); + parseSpace(); parseXMLDecl(this); parseMisc(this); parseDocTypeDecl(this); @@ -783,6 +781,12 @@ GString *ZxDoc::parseQuotedString() { return s; } +void ZxDoc::parseBOM() { + if (match("\xef\xbb\xbf")) { + parsePtr += 3; + } +} + void ZxDoc::parseSpace() { while (parsePtr < parseEnd && (*parsePtr == '\x20' || *parsePtr == '\x09' || diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Zoox.h b/Build/source/libs/xpdf/xpdf-src/xpdf/Zoox.h index c04ca95064b..c89cd67b065 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Zoox.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Zoox.h @@ -9,10 +9,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - #include "gtypes.h" class GString; @@ -110,6 +106,7 @@ private: void parsePI(ZxNode *par); GString *parseName(); GString *parseQuotedString(); + void parseBOM(); void parseSpace(); bool match(const char *s); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/config.h b/Build/source/libs/xpdf/xpdf-src/xpdf/config.h index b41dd492248..6bd00d500ae 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/config.h +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/config.h @@ -2,7 +2,7 @@ // // config.h // -// Copyright 1996-2022 Glyph & Cog, LLC +// Copyright 1996-2024 Glyph & Cog, LLC // //======================================================================== @@ -14,13 +14,13 @@ //------------------------------------------------------------------------ // xpdf version -#define xpdfVersion "4.04" -#define xpdfVersionNum 4.04 +#define xpdfVersion "4.05" +#define xpdfVersionNum 4.05 #define xpdfMajorVersion 4 -#define xpdfMinorVersion 4 +#define xpdfMinorVersion 5 #define xpdfUpdateVersion 0 #define xpdfMajorVersionStr "4" -#define xpdfMinorVersionStr "4" +#define xpdfMinorVersionStr "5" #define xpdfUpdateVersionStr "0" // supported PDF version @@ -28,11 +28,11 @@ #define supportedPDFVersionNum 2.0 // copyright notice -#define xpdfCopyright "Copyright 1996-2022 Glyph & Cog, LLC" +#define xpdfCopyright "Copyright 1996-2024 Glyph & Cog, LLC" // Windows resource file stuff -#define winxpdfVersion "WinXpdf 4.04" -#define xpdfCopyrightAmp "Copyright 1996-2022 Glyph && Cog, LLC" +#define winxpdfVersion "WinXpdf 4.05" +#define xpdfCopyrightAmp "Copyright 1996-2024 Glyph && Cog, LLC" //------------------------------------------------------------------------ // paper size diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc index 581383fe730..1b80fe474b6 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfdetach.cc @@ -62,6 +62,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + char *fileName; UnicodeMap *uMap; GString *ownerPW, *userPW; @@ -213,4 +217,11 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc index bde57557c3c..ad9e40d7c62 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdffonts.cc @@ -96,6 +96,10 @@ static char *seenObjs; static int numObjects; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + char *fileName; GString *ownerPW, *userPW; GBool ok; @@ -174,22 +178,21 @@ int main(int argc, char *argv[]) { numObjects = doc->getXRef()->getNumObjects(); seenObjs = (char *)gmalloc(numObjects); memset(seenObjs, 0, numObjects); + annots = doc->getAnnots(); for (pg = firstPage; pg <= lastPage; ++pg) { page = doc->getCatalog()->getPage(pg); if ((resDict = page->getResourceDict())) { scanFonts(resDict, doc); } - annots = new Annots(doc, page->getAnnots(&obj1)); - obj1.free(); - for (i = 0; i < annots->getNumAnnots(); ++i) { - if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { + int nAnnots = annots->getNumAnnots(pg); + for (i = 0; i < nAnnots; ++i) { + if (annots->getAnnot(pg, i)->getAppearance(&obj1)->isStream()) { obj1.streamGetDict()->lookupNF("Resources", &obj2); scanFonts(&obj2, doc); obj2.free(); } obj1.free(); } - delete annots; } if ((form = doc->getCatalog()->getForm())) { for (i = 0; i < form->getNumFields(); ++i) { @@ -222,6 +225,13 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } static void scanFonts(Object *obj, PDFDoc *doc) { diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc index 346346bce77..303a046932d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfimages.cc @@ -76,6 +76,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; char *imgRoot; @@ -171,4 +175,11 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc index 88829b993c3..a1fb5c2327d 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdfinfo.cc @@ -41,6 +41,7 @@ static void printInfoString(Object *infoDict, const char *infoKey, const char *xmpKey2, const char *text, GBool parseDate, UnicodeMap *uMap); +static void printCustomInfo(Object *infoDict, UnicodeMap *uMap); static GString *parseInfoDate(GString *s); static GString *parseXMPDate(GString *s); static void printBox(const char *text, PDFRectangle *box); @@ -50,6 +51,7 @@ static int lastPage = 0; static GBool printBoxes = gFalse; static GBool printMetadata = gFalse; static GBool rawDates = gFalse; +static GBool printCustom = gFalse; static char textEncName[128] = ""; static char ownerPassword[33] = "\001"; static char userPassword[33] = "\001"; @@ -68,6 +70,8 @@ static ArgDesc argDesc[] = { "print the document metadata (XML)"}, {"-rawdates", argFlag, &rawDates, 0, "print the undecoded date strings directly from the PDF file"}, + {"-custom", argFlag, &printCustom, 0, + "print the custom info dictionary fields"}, {"-enc", argString, textEncName, sizeof(textEncName), "output text encoding name"}, {"-opw", argString, ownerPassword, sizeof(ownerPassword), @@ -90,6 +94,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; GString *ownerPW, *userPW; @@ -193,6 +201,9 @@ int main(int argc, char *argv[]) { printInfoString(&info, "Producer", xmp, "pdf:Producer", NULL, "Producer: ", gFalse, uMap); printInfoString(&info, "CreationDate", xmp, "xap:CreateDate", "xmp:CreateDate", "CreationDate: ", !rawDates, uMap); printInfoString(&info, "ModDate", xmp, "xap:ModifyDate", "xmp:ModifyDate", "ModDate: ", !rawDates, uMap); + if (printCustom) { + printCustomInfo(&info, uMap); + } info.free(); if (xmp) { delete xmp; @@ -304,6 +315,9 @@ int main(int argc, char *argv[]) { // print linearization info printf("Optimized: %s\n", doc->isLinearized() ? "yes" : "no"); + // print JavaScript info + printf("JavaScript: %s\n", doc->usesJavaScript() ? "yes" : "no"); + // print PDF version printf("PDF version: %.1f\n", doc->getPDFVersion()); @@ -333,6 +347,13 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } static void printInfoString(Object *infoDict, const char *infoKey, @@ -397,7 +418,7 @@ static void printInfoString(Object *infoDict, const char *infoKey, if (!parseDate || !(value = parseXMPDate(((ZxCharData *)node2)->getData()))) { tmp = ((ZxCharData *)node2)->getData(); - int i = 0; + i = 0; value = new GString(); while (getUTF8(tmp, &i, &uu)) { n = uMap->mapUnicode(uu, buf, sizeof(buf)); @@ -414,12 +435,48 @@ static void printInfoString(Object *infoDict, const char *infoKey, if (value) { fputs(text, stdout); - fwrite(value->getCString(), 1, value->getLength(), stdout); + fwrite(value->getCString(), 1, value->getLength(), stdout); fputc('\n', stdout); delete value; } } +static void printCustomInfo(Object *infoDict, UnicodeMap *uMap) { + if (!infoDict->isDict()) { + return; + } + for (int i = 0; i < infoDict->dictGetLength(); ++i) { + char *key = infoDict->dictGetKey(i); + Object obj; + infoDict->dictGetVal(i, &obj); + if (obj.isString() && + strcmp(key, "Title") && + strcmp(key, "Subject") && + strcmp(key, "Keywords") && + strcmp(key, "Author") && + strcmp(key, "Creator") && + strcmp(key, "Producer") && + strcmp(key, "CreationDate") && + strcmp(key, "ModDate")) { + printf("%s: ", key); + int n = 14 - (int)strlen(key); + if (n > 0) { + printf("%*s", n, ""); + } + TextString *s = new TextString(obj.getString()); + Unicode *u = s->getUnicode(); + char buf[8]; + for (int j = 0; j < s->getLength(); ++j) { + n = uMap->mapUnicode(u[j], buf, sizeof(buf)); + fwrite(buf, 1, n, stdout); + } + delete s; + printf("\n"); + } + obj.free(); + } +} + static GString *parseInfoDate(GString *s) { int year, mon, day, hour, min, sec, n; struct tm tmStruct; diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc index 4c98afed50c..92d78b0e5dc 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftohtml.cc @@ -38,7 +38,9 @@ static GBool embedFonts = gFalse; static GBool skipInvisible = gFalse; static GBool allInvisible = gFalse; static GBool formFields = gFalse; +static GBool includeMetadata = gFalse; static GBool tableMode = gFalse; +static GBool overwrite = gFalse; static char ownerPassword[33] = "\001"; static char userPassword[33] = "\001"; static GBool verbose = gFalse; @@ -70,8 +72,12 @@ static ArgDesc argDesc[] = { "treat all text as invisible"}, {"-formfields", argFlag, &formFields, 0, "convert form fields to HTML"}, + {"-meta", argFlag, &includeMetadata, 0, + "include document metadata in the HTML output"}, {"-table", argFlag, &tableMode, 0, "use table mode for text extraction"}, + {"-overwrite", argFlag, &overwrite, 0, + "overwrite files in an existing output directory"}, {"-opw", argString, ownerPassword, sizeof(ownerPassword), "owner password (for encrypted files)"}, {"-upw", argString, userPassword, sizeof(userPassword), @@ -102,6 +108,10 @@ static int writeToFile(void *file, const char *data, int size) { } int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; char *htmlDir; @@ -184,10 +194,19 @@ int main(int argc, char *argv[]) { // create HTML directory if (makeDir(htmlDir, 0755)) { - error(errIO, -1, "Couldn't create HTML output directory '{0:s}'", - htmlDir); - exitCode = 2; - goto err1; + if (pathIsDir(htmlDir)) { + if (!overwrite) { + error(errIO, -1, "HTML output directory '{0:s}' already exists (use '-overwrite' to overwrite it)", + htmlDir); + exitCode = 2; + goto err1; + } + } else { + error(errIO, -1, "Couldn't create HTML output directory '{0:s}'", + htmlDir); + exitCode = 2; + goto err1; + } } // set up the HTMLGen object @@ -204,6 +223,7 @@ int main(int argc, char *argv[]) { htmlGen->setExtractFontFiles(!noFonts); htmlGen->setEmbedFonts(embedFonts); htmlGen->setConvertFormFields(formFields); + htmlGen->setIncludeMetadata(includeMetadata); htmlGen->startDoc(doc); // convert the pages @@ -271,6 +291,13 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } static GBool createIndex(char *htmlDir) { @@ -280,11 +307,12 @@ static GBool createIndex(char *htmlDir) { htmlFileName = GString::format("{0:s}/index.html", htmlDir); html = openFile(htmlFileName->getCString(), "w"); - delete htmlFileName; if (!html) { error(errIO, -1, "Couldn't open HTML file '{0:t}'", htmlFileName); + delete htmlFileName; return gFalse; } + delete htmlFileName; fprintf(html, "<html>\n"); fprintf(html, "<body>\n"); diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc index 7f3b97b9d94..e4107f59899 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftopng.cc @@ -99,6 +99,10 @@ static void writePNGData(png_structp png, SplashBitmap *bitmap); static void finishPNG(png_structp *png, png_infop *pngInfo); int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; char *pngRoot; @@ -296,6 +300,13 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } static void setupPNG(png_structp *png, png_infop *pngInfo, FILE *f, diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc index 28861ef948b..c4dc3494a72 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftoppm.cc @@ -98,6 +98,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; char *ppmRoot; @@ -277,4 +281,11 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc index 77e90fe0165..c6c7c4767ec 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftops.cc @@ -153,6 +153,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; GString *psFileName; @@ -396,4 +400,11 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc index d8bf6df5e67..928de607678 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/pdftotext.cc @@ -132,6 +132,10 @@ static ArgDesc argDesc[] = { }; int main(int argc, char *argv[]) { +#if USE_EXCEPTIONS + try { +#endif + PDFDoc *doc; char *fileName; GString *textFileName; @@ -329,4 +333,11 @@ int main(int argc, char *argv[]) { gMemReport(stderr); return exitCode; + +#if USE_EXCEPTIONS + } catch (GMemException e) { + fprintf(stderr, "Out of memory\n"); + return 98; + } +#endif } |