diff options
Diffstat (limited to 'xpdf/pdffonts.cc')
-rw-r--r-- | xpdf/pdffonts.cc | 158 |
1 files changed, 143 insertions, 15 deletions
diff --git a/xpdf/pdffonts.cc b/xpdf/pdffonts.cc index 80403a1..e1a0b43 100644 --- a/xpdf/pdffonts.cc +++ b/xpdf/pdffonts.cc @@ -22,6 +22,7 @@ #include "Dict.h" #include "GfxFont.h" #include "Annot.h" +#include "Form.h" #include "PDFDoc.h" #include "config.h" @@ -41,11 +42,14 @@ static const char *fontTypeNames[] = { "CID TrueType (OT)" }; +static void scanFonts(Object *obj, PDFDoc *doc); static void scanFonts(Dict *resDict, PDFDoc *doc); static void scanFont(GfxFont *font, PDFDoc *doc); static int firstPage = 1; static int lastPage = 0; +static GBool showFontLoc = gFalse; +static GBool showFontLocPS = gFalse; static char ownerPassword[33] = "\001"; static char userPassword[33] = "\001"; static char cfgFileName[256] = ""; @@ -57,6 +61,10 @@ static ArgDesc argDesc[] = { "first page to examine"}, {"-l", argInt, &lastPage, 0, "last page to examine"}, + {"-loc", argFlag, &showFontLoc, 0, + "print extended info on font location"}, + {"-locPS", argFlag, &showFontLocPS, 0, + "print extended info on font location for PostScript conversion"}, {"-opw", argString, ownerPassword, sizeof(ownerPassword), "owner password (for encrypted files)"}, {"-upw", argString, userPassword, sizeof(userPassword), @@ -80,6 +88,10 @@ static Ref *fonts; static int fontsLen; static int fontsSize; +static Ref *seenObjs; +static int seenObjsLen; +static int seenObjsSize; + int main(int argc, char *argv[]) { PDFDoc *doc; GString *fileName; @@ -88,8 +100,9 @@ int main(int argc, char *argv[]) { Page *page; Dict *resDict; Annots *annots; + Form *form; Object obj1, obj2; - int pg, i; + int pg, i, j; int exitCode; exitCode = 99; @@ -108,6 +121,7 @@ int main(int argc, char *argv[]) { // read config file globalParams = new GlobalParams(cfgFileName); + globalParams->setupBaseFonts(NULL); // open PDF file if (ownerPassword[0] != '\001') { @@ -141,10 +155,17 @@ int main(int argc, char *argv[]) { } // scan the fonts - printf("name type emb sub uni object ID\n"); - printf("------------------------------------ ----------------- --- --- --- ---------\n"); + if (showFontLoc || showFontLocPS) { + printf("name type emb sub uni object ID location\n"); + printf("------------------------------------ ----------------- --- --- --- --------- --------\n"); + } else { + printf("name type emb sub uni object ID\n"); + printf("------------------------------------ ----------------- --- --- --- ---------\n"); + } fonts = NULL; fontsLen = fontsSize = 0; + seenObjs = NULL; + seenObjsLen = seenObjsSize = 0; for (pg = firstPage; pg <= lastPage; ++pg) { page = doc->getCatalog()->getPage(pg); if ((resDict = page->getResourceDict())) { @@ -154,21 +175,35 @@ int main(int argc, char *argv[]) { obj1.free(); for (i = 0; i < annots->getNumAnnots(); ++i) { if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { - obj1.streamGetDict()->lookup("Resources", &obj2); - if (obj2.isDict()) { - scanFonts(obj2.getDict(), doc); - } + 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) { + form->getField(i)->getResources(&obj1); + if (obj1.isArray()) { + for (j = 0; j < obj1.arrayGetLength(); ++j) { + obj1.arrayGetNF(j, &obj2); + scanFonts(&obj2, doc); + obj2.free(); + } + } else if (obj1.isDict()) { + scanFonts(obj1.getDict(), doc); + } + obj1.free(); + } + } exitCode = 0; // clean up gfree(fonts); + gfree(seenObjs); err1: delete doc; delete globalParams; @@ -181,8 +216,37 @@ int main(int argc, char *argv[]) { return exitCode; } +static void scanFonts(Object *obj, PDFDoc *doc) { + Object obj2; + int i; + + if (obj->isRef()) { + for (i = 0; i < seenObjsLen; ++i) { + if (obj->getRefNum() == seenObjs[i].num && + obj->getRefGen() == seenObjs[i].gen) { + return; + } + } + if (seenObjsLen == seenObjsSize) { + if (seenObjsSize <= INT_MAX - 32) { + seenObjsSize += 32; + } else { + // let greallocn throw an exception + seenObjsSize = -1; + } + seenObjs = (Ref *)greallocn(seenObjs, seenObjsSize, sizeof(Ref)); + } + seenObjs[seenObjsLen++] = obj->getRef(); + } + if (obj->fetch(doc->getXRef(), &obj2)->isDict()) { + scanFonts(obj2.getDict(), doc); + } + obj2.free(); +} + static void scanFonts(Dict *resDict, PDFDoc *doc) { - Object obj1, obj2, xObjDict, xObj, resObj; + Object obj1, obj2, xObjDict, xObj; + Object patternDict, pattern, gsDict, gs, smask, smaskGroup, resObj; Ref r; GfxFontDict *gfxFontDict; GfxFont *font; @@ -211,23 +275,58 @@ static void scanFonts(Dict *resDict, PDFDoc *doc) { } obj1.free(); - // recursively scan any resource dictionaries in objects in this + // recursively scan any resource dictionaries in XObjects in this // resource dictionary resDict->lookup("XObject", &xObjDict); if (xObjDict.isDict()) { for (i = 0; i < xObjDict.dictGetLength(); ++i) { xObjDict.dictGetVal(i, &xObj); if (xObj.isStream()) { - xObj.streamGetDict()->lookup("Resources", &resObj); - if (resObj.isDict()) { - scanFonts(resObj.getDict(), doc); - } + xObj.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); resObj.free(); } xObj.free(); } } xObjDict.free(); + + // recursively scan any resource dictionaries in Patterns in this + // resource dictionary + resDict->lookup("Pattern", &patternDict); + if (patternDict.isDict()) { + for (i = 0; i < patternDict.dictGetLength(); ++i) { + patternDict.dictGetVal(i, &pattern); + if (pattern.isStream()) { + pattern.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); + resObj.free(); + } + pattern.free(); + } + } + patternDict.free(); + + // recursively scan any resource dictionaries in ExtGStates in this + // resource dictionary + resDict->lookup("ExtGState", &gsDict); + if (gsDict.isDict()) { + for (i = 0; i < gsDict.dictGetLength(); ++i) { + if (gsDict.dictGetVal(i, &gs)->isDict()) { + if (gs.dictLookup("SMask", &smask)->isDict()) { + if (smask.dictLookup("G", &smaskGroup)->isStream()) { + smaskGroup.streamGetDict()->lookupNF("Resources", &resObj); + scanFonts(&resObj, doc); + resObj.free(); + } + smaskGroup.free(); + } + smask.free(); + } + gs.free(); + } + } + gsDict.free(); } static void scanFont(GfxFont *font, PDFDoc *doc) { @@ -235,6 +334,7 @@ static void scanFont(GfxFont *font, PDFDoc *doc) { Object fontObj, toUnicodeObj; GString *name; GBool emb, subset, hasToUnicode; + GfxFontLoc *loc; int i; fontRef = *font->getID(); @@ -284,10 +384,38 @@ static void scanFont(GfxFont *font, PDFDoc *doc) { subset ? "yes" : "no", hasToUnicode ? "yes" : "no"); if (fontRef.gen >= 100000) { - printf(" [none]\n"); + printf(" [none]"); } else { - printf(" %6d %2d\n", fontRef.num, fontRef.gen); + printf(" %6d %2d", fontRef.num, fontRef.gen); + } + if (showFontLoc || showFontLocPS) { + if (font->getType() == fontType3) { + printf(" embedded"); + } else { + loc = font->locateFont(doc->getXRef(), showFontLocPS); + if (loc) { + if (loc->locType == gfxFontLocEmbedded) { + printf(" embedded"); + } else if (loc->locType == gfxFontLocExternal) { + if (loc->path) { + printf(" external: %s", loc->path->getCString()); + } else { + printf(" unavailable"); + } + } else if (loc->locType == gfxFontLocResident) { + if (loc->path) { + printf(" resident: %s", loc->path->getCString()); + } else { + printf(" unavailable"); + } + } + } else { + printf(" unknown"); + } + delete loc; + } } + printf("\n"); // add this font to the list if (fontsLen == fontsSize) { |