summaryrefslogtreecommitdiff
path: root/xpdf/pdffonts.cc
diff options
context:
space:
mode:
Diffstat (limited to 'xpdf/pdffonts.cc')
-rw-r--r--xpdf/pdffonts.cc158
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) {