diff options
author | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
---|---|---|
committer | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
commit | c6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch) | |
tree | 1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc | |
parent | 07ee7222e389b0777456b427a55c22d0e6ffd267 (diff) |
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc')
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc | 1197 |
1 files changed, 0 insertions, 1197 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc deleted file mode 100644 index 6ea8fa89ff4..00000000000 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc +++ /dev/null @@ -1,1197 +0,0 @@ -//======================================================================== -// -// Catalog.cc -// -// Copyright 1996-2013 Glyph & Cog, LLC -// -//======================================================================== - -#include <aconf.h> - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include <string.h> -#include <stddef.h> -#include <limits.h> -#include "gmem.h" -#include "gmempp.h" -#include "gfile.h" -#include "GList.h" -#include "Object.h" -#include "CharTypes.h" -#include "PDFDoc.h" -#include "XRef.h" -#include "Array.h" -#include "Dict.h" -#include "Page.h" -#include "Error.h" -#include "Link.h" -#include "AcroForm.h" -#include "TextString.h" -#include "Catalog.h" - -//------------------------------------------------------------------------ -// PageTreeNode -//------------------------------------------------------------------------ - -class PageTreeNode { -public: - - PageTreeNode(Ref refA, int countA, PageTreeNode *parentA); - ~PageTreeNode(); - - Ref ref; - int count; - PageTreeNode *parent; - GList *kids; // [PageTreeNode] - PageAttrs *attrs; -}; - -PageTreeNode::PageTreeNode(Ref refA, int countA, PageTreeNode *parentA) { - ref = refA; - count = countA; - parent = parentA; - kids = NULL; - attrs = NULL; -} - -PageTreeNode::~PageTreeNode() { - delete attrs; - if (kids) { - deleteGList(kids, PageTreeNode); - } -} - -//------------------------------------------------------------------------ -// EmbeddedFile -//------------------------------------------------------------------------ - -class EmbeddedFile { -public: - - EmbeddedFile(TextString *nameA, Object *streamRefA); - ~EmbeddedFile(); - - TextString *name; - Object streamRef; -}; - -EmbeddedFile::EmbeddedFile(TextString *nameA, Object *streamRefA) { - name = nameA; - streamRefA->copy(&streamRef); -} - -EmbeddedFile::~EmbeddedFile() { - delete name; - streamRef.free(); -} - -//------------------------------------------------------------------------ -// PageLabelNode -//------------------------------------------------------------------------ - -class PageLabelNode { -public: - - PageLabelNode(int firstPageA, Dict *dict); - ~PageLabelNode(); - - int firstPage; // first page number covered by this node - int lastPage; // last page number covered by this node - TextString *prefix; // label prefix (may be empty) - int start; // value of the numeric portion of this - // label for the first page in the range - char style; // page label style -}; - -PageLabelNode::PageLabelNode(int firstPageA, Dict *dict) { - Object prefixObj, styleObj, startObj; - - // convert page index to page number - firstPage = firstPageA + 1; - - // lastPage will be filled in later - lastPage = -1; - - if (dict->lookup("P", &prefixObj)->isString()) { - prefix = new TextString(prefixObj.getString()); - } else { - prefix = new TextString(); - } - prefixObj.free(); - - style = '\0'; - if (dict->lookup("S", &styleObj)->isName()) { - if (strlen(styleObj.getName()) == 1) { - style = styleObj.getName()[0]; - } - } - styleObj.free(); - - start = 1; - if (dict->lookup("St", &startObj)->isInt()) { - start = startObj.getInt(); - } - startObj.free(); -} - -PageLabelNode::~PageLabelNode() { - delete prefix; -} - -//------------------------------------------------------------------------ -// Catalog -//------------------------------------------------------------------------ - -Catalog::Catalog(PDFDoc *docA) { - Object catDict; - Object obj, obj2; - - ok = gTrue; - doc = docA; - xref = doc->getXRef(); - pageTree = NULL; - pages = NULL; - pageRefs = NULL; - numPages = 0; - baseURI = NULL; - form = NULL; - embeddedFiles = NULL; - pageLabels = NULL; -#if MULTITHREADED - gInitMutex(&pageMutex); -#endif - - xref->getCatalog(&catDict); - if (!catDict.isDict()) { - error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", - catDict.getTypeName()); - goto err1; - } - - // read page tree - if (!readPageTree(&catDict)) { - goto err1; - } - - // read named destination dictionary - catDict.dictLookup("Dests", &dests); - - // read root of named destination tree - if (catDict.dictLookup("Names", &obj)->isDict()) - obj.dictLookup("Dests", &nameTree); - else - nameTree.initNull(); - obj.free(); - - // read base URI - if (catDict.dictLookup("URI", &obj)->isDict()) { - if (obj.dictLookup("Base", &obj2)->isString()) { - baseURI = obj2.getString()->copy(); - } - obj2.free(); - } - obj.free(); - if (!baseURI || baseURI->getLength() == 0) { - if (baseURI) { - delete baseURI; - } - if (doc->getFileName()) { - baseURI = makePathAbsolute(grabPath(doc->getFileName()->getCString())); - if (baseURI->getChar(0) == '/') { - baseURI->insert(0, "file://localhost"); - } else { - baseURI->insert(0, "file://localhost/"); - } - } else { - baseURI = new GString("file://localhost/"); - } - } - - // get the metadata stream - catDict.dictLookup("Metadata", &metadata); - - // get the structure tree root - catDict.dictLookup("StructTreeRoot", &structTreeRoot); - - // get the outline dictionary - catDict.dictLookup("Outlines", &outline); - - // get the AcroForm dictionary - catDict.dictLookup("AcroForm", &acroForm); - - // get the NeedsRendering flag - // NB: AcroForm::load() uses this value - needsRendering = catDict.dictLookup("NeedsRendering", &obj)->isBool() && - obj.getBool(); - obj.free(); - - // create the Form - // (if acroForm is a null object, this will still create an AcroForm - // if there are unattached Widget-type annots) - form = AcroForm::load(doc, this, &acroForm); - - // get the OCProperties dictionary - catDict.dictLookup("OCProperties", &ocProperties); - - // get the list of embedded files - readEmbeddedFileList(catDict.getDict()); - - // get the ViewerPreferences object - catDict.dictLookupNF("ViewerPreferences", &viewerPrefs); - - if (catDict.dictLookup("PageLabels", &obj)->isDict()) { - readPageLabelTree(&obj); - } - obj.free(); - - catDict.free(); - return; - - err1: - catDict.free(); - dests.initNull(); - nameTree.initNull(); - ok = gFalse; -} - -Catalog::~Catalog() { - int i; - - if (pageTree) { - delete pageTree; - } - if (pages) { - for (i = 0; i < numPages; ++i) { - if (pages[i]) { - delete pages[i]; - } - } - gfree(pages); - gfree(pageRefs); - } -#if MULTITHREADED - gDestroyMutex(&pageMutex); -#endif - dests.free(); - nameTree.free(); - if (baseURI) { - delete baseURI; - } - metadata.free(); - structTreeRoot.free(); - outline.free(); - acroForm.free(); - if (form) { - delete form; - } - ocProperties.free(); - if (embeddedFiles) { - deleteGList(embeddedFiles, EmbeddedFile); - } - if (pageLabels) { - deleteGList(pageLabels, PageLabelNode); - } - viewerPrefs.free(); -} - -Page *Catalog::getPage(int i) { - Page *page; - -#if MULTITHREADED - gLockMutex(&pageMutex); -#endif - if (!pages[i-1]) { - loadPage(i); - } - page = pages[i-1]; -#if MULTITHREADED - gUnlockMutex(&pageMutex); -#endif - return page; -} - -Ref *Catalog::getPageRef(int i) { - Ref *pageRef; - -#if MULTITHREADED - gLockMutex(&pageMutex); -#endif - if (!pages[i-1]) { - loadPage(i); - } - pageRef = &pageRefs[i-1]; -#if MULTITHREADED - gUnlockMutex(&pageMutex); -#endif - return pageRef; -} - -void Catalog::doneWithPage(int i) { -#if MULTITHREADED - gLockMutex(&pageMutex); -#endif - if (pages[i-1]) { - delete pages[i-1]; - pages[i-1] = NULL; - } -#if MULTITHREADED - gUnlockMutex(&pageMutex); -#endif -} - -GString *Catalog::readMetadata() { - GString *s; - Dict *dict; - Object obj; - char buf[4096]; - int n; - - if (!metadata.isStream()) { - return NULL; - } - dict = metadata.streamGetDict(); - if (!dict->lookup("Subtype", &obj)->isName("XML")) { - error(errSyntaxWarning, -1, "Unknown Metadata type: '{0:s}'", - obj.isName() ? obj.getName() : "???"); - } - obj.free(); - s = new GString(); - metadata.streamReset(); - while ((n = metadata.streamGetBlock(buf, sizeof(buf))) > 0) { - s->append(buf, n); - } - metadata.streamClose(); - return s; -} - -int Catalog::findPage(int num, int gen) { - int i; - -#if MULTITHREADED - gLockMutex(&pageMutex); -#endif - for (i = 0; i < numPages; ++i) { - if (!pages[i]) { - loadPage(i+1); - } - if (pageRefs[i].num == num && pageRefs[i].gen == gen) { -#if MULTITHREADED - gUnlockMutex(&pageMutex); -#endif - return i + 1; - } - } -#if MULTITHREADED - gUnlockMutex(&pageMutex); -#endif - return 0; -} - -LinkDest *Catalog::findDest(GString *name) { - LinkDest *dest; - Object obj1, obj2; - GBool found; - - // try named destination dictionary then name tree - found = gFalse; - if (dests.isDict()) { - if (!dests.dictLookup(name->getCString(), &obj1)->isNull()) { - found = gTrue; - } else { - obj1.free(); - } - } - if (!found && nameTree.isDict()) { - if (!findDestInTree(&nameTree, name, &obj1)->isNull()) { - found = gTrue; - } else { - obj1.free(); - } - } - if (!found) { - return NULL; - } - - // construct LinkDest - dest = NULL; - if (obj1.isArray()) { - dest = new LinkDest(obj1.getArray()); - } else if (obj1.isDict()) { - if (obj1.dictLookup("D", &obj2)->isArray()) { - dest = new LinkDest(obj2.getArray()); - } else { - error(errSyntaxWarning, -1, "Bad named destination value"); - } - obj2.free(); - } else { - error(errSyntaxWarning, -1, "Bad named destination value"); - } - obj1.free(); - if (dest && !dest->isOk()) { - delete dest; - dest = NULL; - } - - return dest; -} - -Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) { - Object names, name1; - Object kids, kid, limits, low, high; - GBool done, found; - int cmp, i; - - // leaf node - if (tree->dictLookup("Names", &names)->isArray()) { - done = found = gFalse; - for (i = 0; !done && i < names.arrayGetLength(); i += 2) { - if (names.arrayGet(i, &name1)->isString()) { - cmp = name->cmp(name1.getString()); - if (cmp == 0) { - names.arrayGet(i+1, obj); - found = gTrue; - done = gTrue; - } else if (cmp < 0) { - done = gTrue; - } - } - name1.free(); - } - names.free(); - if (!found) { - obj->initNull(); - } - return obj; - } - names.free(); - - // root or intermediate node - done = gFalse; - if (tree->dictLookup("Kids", &kids)->isArray()) { - for (i = 0; !done && i < kids.arrayGetLength(); ++i) { - if (kids.arrayGet(i, &kid)->isDict()) { - if (kid.dictLookup("Limits", &limits)->isArray()) { - if (limits.arrayGet(0, &low)->isString() && - name->cmp(low.getString()) >= 0) { - if (limits.arrayGet(1, &high)->isString() && - name->cmp(high.getString()) <= 0) { - findDestInTree(&kid, name, obj); - done = gTrue; - } - high.free(); - } - low.free(); - } - limits.free(); - } - kid.free(); - } - } - kids.free(); - - // name was outside of ranges of all kids - if (!done) { - obj->initNull(); - } - - return obj; -} - -GBool Catalog::readPageTree(Object *catDict) { - Object topPagesRef, topPagesObj, countObj; - int i; - - if (!catDict->dictLookupNF("Pages", &topPagesRef)->isRef()) { - error(errSyntaxError, -1, "Top-level pages reference is wrong type ({0:s})", - topPagesRef.getTypeName()); - topPagesRef.free(); - return gFalse; - } - if (!topPagesRef.fetch(xref, &topPagesObj)->isDict()) { - error(errSyntaxError, -1, "Top-level pages object is wrong type ({0:s})", - topPagesObj.getTypeName()); - topPagesObj.free(); - topPagesRef.free(); - return gFalse; - } - if (topPagesObj.dictLookup("Count", &countObj)->isInt()) { - numPages = countObj.getInt(); - if (numPages == 0 || numPages > 50000) { - // 1. Acrobat apparently scans the page tree if it sees a zero - // count. - // 2. Absurdly large page counts result in very slow loading, - // 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); - } - } else { - // assume we got a Page node instead of a Pages node - numPages = 1; - } - countObj.free(); - if (numPages < 0) { - error(errSyntaxError, -1, "Invalid page count"); - topPagesObj.free(); - topPagesRef.free(); - numPages = 0; - return gFalse; - } - pageTree = new PageTreeNode(topPagesRef.getRef(), numPages, NULL); - topPagesObj.free(); - topPagesRef.free(); - pages = (Page **)greallocn(pages, numPages, sizeof(Page *)); - pageRefs = (Ref *)greallocn(pageRefs, numPages, sizeof(Ref)); - for (i = 0; i < numPages; ++i) { - pages[i] = NULL; - pageRefs[i].num = -1; - pageRefs[i].gen = -1; - } - return gTrue; -} - -int Catalog::countPageTree(Object *pagesObj) { - Object kids, kid; - int n, n2, i; - - if (!pagesObj->isDict()) { - 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(); - } - } else { - n = 1; - } - kids.free(); - return n; -} - -void Catalog::loadPage(int pg) { - loadPage2(pg, pg - 1, pageTree); -} - -void Catalog::loadPage2(int pg, int relPg, PageTreeNode *node) { - Object pageRefObj, pageObj, kidsObj, kidRefObj, kidObj, countObj; - PageTreeNode *kidNode, *p; - PageAttrs *attrs; - int count, i; - - if (relPg >= node->count) { - error(errSyntaxError, -1, "Internal error in page tree"); - pages[pg-1] = new Page(doc, pg); - return; - } - - // if this node has not been filled in yet, it's either a leaf node - // or an unread internal node - if (!node->kids) { - - // check for a loop in the page tree - for (p = node->parent; p; p = p->parent) { - if (node->ref.num == p->ref.num && node->ref.gen == p->ref.gen) { - error(errSyntaxError, -1, "Loop in Pages tree"); - pages[pg-1] = new Page(doc, pg); - return; - } - } - - // fetch the Page/Pages object - pageRefObj.initRef(node->ref.num, node->ref.gen); - if (!pageRefObj.fetch(xref, &pageObj)->isDict()) { - error(errSyntaxError, -1, "Page tree object is wrong type ({0:s})", - pageObj.getTypeName()); - pageObj.free(); - pageRefObj.free(); - pages[pg-1] = new Page(doc, pg); - return; - } - - // merge the PageAttrs - attrs = new PageAttrs(node->parent ? node->parent->attrs - : (PageAttrs *)NULL, - pageObj.getDict()); - - // if "Kids" exists, it's an internal node - if (pageObj.dictLookup("Kids", &kidsObj)->isArray()) { - - // save the PageAttrs - node->attrs = attrs; - - // read the kids - node->kids = new GList(); - for (i = 0; i < kidsObj.arrayGetLength(); ++i) { - if (kidsObj.arrayGetNF(i, &kidRefObj)->isRef()) { - if (kidRefObj.fetch(xref, &kidObj)->isDict()) { - if (kidObj.dictLookup("Count", &countObj)->isInt()) { - count = countObj.getInt(); - } else { - count = 1; - } - countObj.free(); - node->kids->append(new PageTreeNode(kidRefObj.getRef(), count, - node)); - } else { - error(errSyntaxError, -1, "Page tree object is wrong type ({0:s})", - kidObj.getTypeName()); - } - kidObj.free(); - } else { - error(errSyntaxError, -1, - "Page tree reference is wrong type ({0:s})", - kidRefObj.getTypeName()); - } - kidRefObj.free(); - } - - } else { - - // create the Page object - pageRefs[pg-1] = node->ref; - pages[pg-1] = new Page(doc, pg, pageObj.getDict(), attrs); - if (!pages[pg-1]->isOk()) { - delete pages[pg-1]; - pages[pg-1] = new Page(doc, pg); - } - - } - - kidsObj.free(); - pageObj.free(); - pageRefObj.free(); - } - - // recursively descend the tree - if (node->kids) { - for (i = 0; i < node->kids->getLength(); ++i) { - kidNode = (PageTreeNode *)node->kids->get(i); - if (relPg < kidNode->count) { - loadPage2(pg, relPg, kidNode); - break; - } - relPg -= kidNode->count; - } - - // this will only happen if the page tree is invalid - // (i.e., parent count > sum of children counts) - if (i == node->kids->getLength()) { - error(errSyntaxError, -1, "Invalid page count in page tree"); - pages[pg-1] = new Page(doc, pg); - } - } -} - -Object *Catalog::getDestOutputProfile(Object *destOutProf) { - Object catDict, intents, intent, subtype; - int i; - - if (!xref->getCatalog(&catDict)->isDict()) { - goto err1; - } - if (!catDict.dictLookup("OutputIntents", &intents)->isArray()) { - goto err2; - } - for (i = 0; i < intents.arrayGetLength(); ++i) { - intents.arrayGet(i, &intent); - if (!intent.isDict()) { - intent.free(); - continue; - } - if (!intent.dictLookup("S", &subtype)->isName("GTS_PDFX")) { - subtype.free(); - intent.free(); - continue; - } - subtype.free(); - if (!intent.dictLookup("DestOutputProfile", destOutProf)->isStream()) { - destOutProf->free(); - intent.free(); - goto err2; - } - intent.free(); - intents.free(); - catDict.free(); - return destOutProf; - } - - err2: - intents.free(); - err1: - catDict.free(); - return NULL; -} - -void Catalog::readEmbeddedFileList(Dict *catDict) { - Object obj1, obj2; - char *touchedObjs; - - // read the embedded file name tree - if (catDict->lookup("Names", &obj1)->isDict()) { - if (obj1.dictLookup("EmbeddedFiles", &obj2)->isDict()) { - readEmbeddedFileTree(&obj2); - } - 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; - Object namesObj, nameObj, fileSpecObj; - int i; - - if (node->dictLookup("Kids", &kidsObj)->isArray()) { - for (i = 0; i < kidsObj.arrayGetLength(); ++i) { - if (kidsObj.arrayGet(i, &kidObj)->isDict()) { - readEmbeddedFileTree(&kidObj); - } - kidObj.free(); - } - } else { - if (node->dictLookup("Names", &namesObj)->isArray()) { - for (i = 0; i+1 < namesObj.arrayGetLength(); ++i) { - namesObj.arrayGet(i, &nameObj); - namesObj.arrayGet(i+1, &fileSpecObj); - readEmbeddedFile(&fileSpecObj, &nameObj); - nameObj.free(); - fileSpecObj.free(); - } - } - namesObj.free(); - } - kidsObj.free(); -} - -void Catalog::readFileAttachmentAnnots(Object *pageNodeRef, - char *touchedObjs) { - Object pageNode, kids, kid, annots, annot, subtype, fileSpec, contents; - int i; - - // check for an invalid object reference (e.g., in a damaged PDF file) - if (pageNodeRef->getRefNum() < 0 || - pageNodeRef->getRefNum() >= xref->getNumObjects()) { - return; - } - - // check for a page tree loop - if (pageNodeRef->isRef()) { - if (touchedObjs[pageNodeRef->getRefNum()]) { - return; - } - touchedObjs[pageNodeRef->getRefNum()] = 1; - xref->fetch(pageNodeRef->getRefNum(), pageNodeRef->getRefGen(), &pageNode); - } else { - pageNodeRef->copy(&pageNode); - } - - if (pageNode.isDict()) { - if (pageNode.dictLookup("Kids", &kids)->isArray()) { - for (i = 0; i < kids.arrayGetLength(); ++i) { - readFileAttachmentAnnots(kids.arrayGetNF(i, &kid), touchedObjs); - kid.free(); - } - } else { - if (pageNode.dictLookup("Annots", &annots)->isArray()) { - for (i = 0; i < annots.arrayGetLength(); ++i) { - if (annots.arrayGet(i, &annot)->isDict()) { - if (annot.dictLookup("Subtype", &subtype) - ->isName("FileAttachment")) { - if (annot.dictLookup("FS", &fileSpec)) { - readEmbeddedFile(&fileSpec, - annot.dictLookup("Contents", &contents)); - contents.free(); - } - fileSpec.free(); - } - subtype.free(); - } - annot.free(); - } - } - annots.free(); - } - kids.free(); - } - - pageNode.free(); -} - -void Catalog::readEmbeddedFile(Object *fileSpec, Object *name1) { - Object name2, efObj, streamObj; - GString *s; - TextString *name; - - if (fileSpec->isDict()) { - if (fileSpec->dictLookup("UF", &name2)->isString()) { - name = new TextString(name2.getString()); - } else { - name2.free(); - if (fileSpec->dictLookup("F", &name2)->isString()) { - name = new TextString(name2.getString()); - } else if (name1 && name1->isString()) { - name = new TextString(name1->getString()); - } else { - s = new GString("?"); - name = new TextString(s); - delete s; - } - } - name2.free(); - if (fileSpec->dictLookup("EF", &efObj)->isDict()) { - if (efObj.dictLookupNF("F", &streamObj)->isRef()) { - if (!embeddedFiles) { - embeddedFiles = new GList(); - } - embeddedFiles->append(new EmbeddedFile(name, &streamObj)); - } else { - delete name; - } - streamObj.free(); - } else { - delete name; - } - efObj.free(); - } -} - -int Catalog::getNumEmbeddedFiles() { - return embeddedFiles ? embeddedFiles->getLength() : 0; -} - -Unicode *Catalog::getEmbeddedFileName(int idx) { - return ((EmbeddedFile *)embeddedFiles->get(idx))->name->getUnicode(); -} - -int Catalog::getEmbeddedFileNameLength(int idx) { - return ((EmbeddedFile *)embeddedFiles->get(idx))->name->getLength(); -} - -Object *Catalog::getEmbeddedFileStreamRef(int idx) { - return &((EmbeddedFile *)embeddedFiles->get(idx))->streamRef; -} - -Object *Catalog::getEmbeddedFileStreamObj(int idx, Object *strObj) { - ((EmbeddedFile *)embeddedFiles->get(idx))->streamRef.fetch(xref, strObj); - if (!strObj->isStream()) { - strObj->free(); - return NULL; - } - return strObj; -} - -void Catalog::readPageLabelTree(Object *root) { - PageLabelNode *label0, *label1; - int i; - - pageLabels = new GList(); - readPageLabelTree2(root); - - if (pageLabels->getLength() == 0) { - deleteGList(pageLabels, PageLabelNode); - pageLabels = NULL; - return; - } - - // set lastPage in each node - label0 = (PageLabelNode *)pageLabels->get(0); - for (i = 1; i < pageLabels->getLength(); ++i) { - label1 = (PageLabelNode *)pageLabels->get(i); - label0->lastPage = label1->firstPage - 1; - label0 = label1; - } - label0->lastPage = numPages; -} - -void Catalog::readPageLabelTree2(Object *node) { - Object nums, num, labelObj, kids, kid; - int i; - - if (!node->isDict()) { - return; - } - - 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()) { - pageLabels->append(new PageLabelNode(num.getInt(), - labelObj.getDict())); - } - labelObj.free(); - } - num.free(); - } - } - nums.free(); - - if (node->dictLookup("Kids", &kids)->isArray()) { - for (i = 0; i < kids.arrayGetLength(); ++i) { - kids.arrayGet(i, &kid); - readPageLabelTree2(&kid); - kid.free(); - } - } - kids.free(); -} - -TextString *Catalog::getPageLabel(int pageNum) { - PageLabelNode *label; - TextString *ts; - int pageRangeNum; - GString *suffix; - - if (!pageLabels || !(label = findPageLabel(pageNum))) { - return NULL; - } - - ts = new TextString(label->prefix); - - pageRangeNum = label->start + (pageNum - label->firstPage); - - suffix = NULL; - if (label->style == 'D') { - suffix = GString::format("{0:d}", pageRangeNum); - } else if (label->style == 'R') { - suffix = makeRomanNumeral(pageRangeNum, gTrue); - } else if (label->style == 'r') { - suffix = makeRomanNumeral(pageRangeNum, gFalse); - } else if (label->style == 'A') { - suffix = makeLetterLabel(pageRangeNum, gTrue); - } else if (label->style == 'a') { - suffix = makeLetterLabel(pageRangeNum, gFalse); - } - if (suffix) { - ts->append(suffix); - delete suffix; - } - - return ts; -} - -PageLabelNode *Catalog::findPageLabel(int pageNum) { - PageLabelNode *label; - int i; - - //~ this could use a binary search - for (i = 0; i < pageLabels->getLength(); ++i) { - label = (PageLabelNode *)pageLabels->get(i); - if (pageNum >= label->firstPage && pageNum <= label->lastPage) { - return label; - } - } - return NULL; -} - -GString *Catalog::makeRomanNumeral(int num, GBool uppercase) { - GString *s; - - s = new GString(); - while (num >= 1000) { - s->append(uppercase ? 'M' : 'm'); - num -= 1000; - } - if (num >= 900) { - s->append(uppercase ? "CM" : "cm"); - num -= 900; - } else if (num >= 500) { - s->append(uppercase ? 'D' : 'd'); - num -= 500; - } else if (num >= 400) { - s->append(uppercase ? "CD" : "cd"); - num -= 400; - } - while (num >= 100) { - s->append(uppercase ? 'C' : 'c'); - num -= 100; - } - if (num >= 90) { - s->append(uppercase ? "XC" : "xc"); - num -= 90; - } else if (num >= 50) { - s->append(uppercase ? 'L' : 'l'); - num -= 50; - } else if (num >= 40) { - s->append(uppercase ? "XL" : "xl"); - num -= 40; - } - while (num >= 10) { - s->append(uppercase ? 'X' : 'x'); - num -= 10; - } - if (num >= 9) { - s->append(uppercase ? "IX" : "ix"); - num -= 9; - } else if (num >= 5) { - s->append(uppercase ? 'V' : 'v'); - num -= 5; - } else if (num >= 4) { - s->append(uppercase ? "IV" : "iv"); - num -= 4; - } - while (num >= 1) { - s->append(uppercase ? 'I' : 'i'); - num -= 1; - } - return s; -} - -GString *Catalog::makeLetterLabel(int num, GBool uppercase) { - GString *s; - int m, n, i; - - m = (num - 1) / 26 + 1; - n = (num - 1) % 26; - s = new GString(); - for (i = 0; i < m; ++i) { - s->append((char)((uppercase ? 'A' : 'a') + n)); - } - return s; -} - -int Catalog::getPageNumFromPageLabel(TextString *pageLabel) { - PageLabelNode *label; - int pageNum, prefixLength, i, n; - - if (!pageLabels) { - return -1; - } - for (i = 0; i < pageLabels->getLength(); ++i) { - label = (PageLabelNode *)pageLabels->get(i); - prefixLength = label->prefix->getLength(); - if (pageLabel->getLength() < prefixLength || - memcmp(pageLabel->getUnicode(), label->prefix->getUnicode(), - prefixLength * sizeof(Unicode))) { - continue; - } - if (label->style == '\0' && pageLabel->getLength() == prefixLength) { - return label->firstPage; - } - if (!convertPageLabelToInt(pageLabel, prefixLength, label->style, &n)) { - continue; - } - if (n < label->start) { - continue; - } - pageNum = label->firstPage + n - label->start; - if (pageNum <= label->lastPage) { - return pageNum; - } - } - return -1; -} - -// Attempts to convert pageLabel[prefixLength .. end] to an integer, -// following the specified page label style. If successful, sets *n -// and returns true; else returns false. -GBool Catalog::convertPageLabelToInt(TextString *pageLabel, int prefixLength, - char style, int *n) { - Unicode *u; - Unicode delta; - int len, i; - - len = pageLabel->getLength(); - if (len <= prefixLength) { - return gFalse; - } - u = pageLabel->getUnicode(); - if (style == 'D') { - *n = 0; - for (i = prefixLength; i < len; ++i) { - if (u[i] < (Unicode)'0' || u[i] > (Unicode)'9') { - return gFalse; - } - *n = *n * 10 + (u[i] - (Unicode)'0'); - } - return gTrue; - } else if (style == 'R' || style == 'r') { - delta = style - 'R'; - *n = 0; - i = prefixLength; - while (i < len && u[i] == (Unicode)'M' + delta) { - *n += 1000; - ++i; - } - if (i+1 < len && u[i] == (Unicode)'C' + delta && - u[i+1] == (Unicode)'M' + delta) { - *n += 900; - i += 2; - } else if (i < len && u[i] == (Unicode)'D' + delta) { - *n += 500; - ++i; - } else if (i+1 < len && u[i] == (Unicode)'C' + delta && - u[i+1] == (Unicode)'D' + delta) { - *n += 400; - i += 2; - } - while (i < len && u[i] == (Unicode)'C' + delta) { - *n += 100; - ++i; - } - if (i+1 < len && u[i] == (Unicode)'X' + delta && - u[i+1] == (Unicode)'C' + delta) { - *n += 90; - i += 2; - } else if (i < len && u[i] == (Unicode)'L' + delta) { - *n += 50; - ++i; - } else if (i+1 < len && u[i] == (Unicode)'X' + delta && - u[i+1] == (Unicode)'L' + delta) { - *n += 40; - i += 2; - } - while (i < len && u[i] == (Unicode)'X' + delta) { - *n += 10; - ++i; - } - if (i+1 < len && u[i] == (Unicode)'I' + delta && - u[i+1] == (Unicode)'X' + delta) { - *n += 9; - i += 2; - } else if (i < len && u[i] == (Unicode)'V' + delta) { - *n += 5; - ++i; - } else if (i+1 < len && u[i] == (Unicode)'I' + delta && - u[i+1] == (Unicode)'V' + delta) { - *n += 4; - i += 2; - } - while (i < len && u[i] == (Unicode)'I' + delta) { - *n += 1; - ++i; - } - return i == len; - } else if (style == 'A' || style == 'a') { - if (u[prefixLength] < (Unicode)style || - u[prefixLength] > (Unicode)style + 25) { - return gFalse; - } - for (i = prefixLength + 1; i < len; ++i) { - if (u[i] != u[prefixLength]) { - return gFalse; - } - } - *n = (len - prefixLength - 1) * 26 + (u[prefixLength] - (Unicode)style) + 1; - return gTrue; - } - return gFalse; -} |