1 //========================================================================
5 // Copyright 2001-2003 Glyph & Cog, LLC
7 //========================================================================
15 #include "parseargs.h"
18 #include "GlobalParams.h"
27 static char *fontTypeNames[] = {
38 static void scanFonts(Dict *resDict, PDFDoc *doc);
39 static void scanFont(GfxFont *font, PDFDoc *doc);
41 static int firstPage = 1;
42 static int lastPage = 0;
43 static char ownerPassword[33] = "\001";
44 static char userPassword[33] = "\001";
45 static char cfgFileName[256] = "";
46 static GBool printVersion = gFalse;
47 static GBool printHelp = gFalse;
49 static ArgDesc argDesc[] = {
50 {"-f", argInt, &firstPage, 0,
51 "first page to examine"},
52 {"-l", argInt, &lastPage, 0,
53 "last page to examine"},
54 {"-opw", argString, ownerPassword, sizeof(ownerPassword),
55 "owner password (for encrypted files)"},
56 {"-upw", argString, userPassword, sizeof(userPassword),
57 "user password (for encrypted files)"},
58 {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
59 "configuration file to use in place of .xpdfrc"},
60 {"-v", argFlag, &printVersion, 0,
61 "print copyright and version info"},
62 {"-h", argFlag, &printHelp, 0,
63 "print usage information"},
64 {"-help", argFlag, &printHelp, 0,
65 "print usage information"},
66 {"--help", argFlag, &printHelp, 0,
67 "print usage information"},
68 {"-?", argFlag, &printHelp, 0,
69 "print usage information"},
77 int main(int argc, char *argv[]) {
80 GString *ownerPW, *userPW;
92 ok = parseArgs(argDesc, &argc, argv);
93 if (!ok || argc != 2 || printVersion || printHelp) {
94 fprintf(stderr, "pdffonts version %s\n", xpdfVersion);
95 fprintf(stderr, "%s\n", xpdfCopyright);
97 printUsage("pdffonts", "<PDF-file>", argDesc);
101 fileName = new GString(argv[1]);
104 globalParams = new GlobalParams(cfgFileName);
107 if (ownerPassword[0] != '\001') {
108 ownerPW = new GString(ownerPassword);
112 if (userPassword[0] != '\001') {
113 userPW = new GString(userPassword);
117 doc = new PDFDoc(fileName, ownerPW, userPW);
133 if (lastPage < 1 || lastPage > doc->getNumPages()) {
134 lastPage = doc->getNumPages();
138 printf("name type emb sub uni object ID\n");
139 printf("------------------------------------ ------------ --- --- --- ---------\n");
141 fontsLen = fontsSize = 0;
142 for (pg = firstPage; pg <= lastPage; ++pg) {
143 page = doc->getCatalog()->getPage(pg);
144 if ((resDict = page->getResourceDict())) {
145 scanFonts(resDict, doc);
147 annots = new Annots(doc->getXRef(), page->getAnnots(&obj1));
149 for (i = 0; i < annots->getNumAnnots(); ++i) {
150 if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
151 obj1.streamGetDict()->lookup("Resources", &obj2);
153 scanFonts(obj2.getDict(), doc);
171 // check for memory leaks
172 Object::memCheck(stderr);
178 static void scanFonts(Dict *resDict, PDFDoc *doc) {
179 Object obj1, obj2, xObjDict, xObj, resObj;
181 GfxFontDict *gfxFontDict;
185 // scan the fonts in this resource dictionary
187 resDict->lookupNF("Font", &obj1);
189 obj1.fetch(doc->getXRef(), &obj2);
192 gfxFontDict = new GfxFontDict(doc->getXRef(), &r, obj2.getDict());
195 } else if (obj1.isDict()) {
196 gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict());
199 for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
200 if ((font = gfxFontDict->getFont(i))) {
208 // recursively scan any resource dictionaries in objects in this
209 // resource dictionary
210 resDict->lookup("XObject", &xObjDict);
211 if (xObjDict.isDict()) {
212 for (i = 0; i < xObjDict.dictGetLength(); ++i) {
213 xObjDict.dictGetVal(i, &xObj);
214 if (xObj.isStream()) {
215 xObj.streamGetDict()->lookup("Resources", &resObj);
216 if (resObj.isDict()) {
217 scanFonts(resObj.getDict(), doc);
227 static void scanFont(GfxFont *font, PDFDoc *doc) {
229 Object fontObj, toUnicodeObj;
231 GBool emb, subset, hasToUnicode;
234 fontRef = *font->getID();
236 // check for an already-seen font
237 for (i = 0; i < fontsLen; ++i) {
238 if (fontRef.num == fonts[i].num && fontRef.gen == fonts[i].gen) {
244 name = font->getOrigName();
246 // check for an embedded font
247 if (font->getType() == fontType3) {
250 emb = font->getEmbeddedFontID(&embRef);
253 // look for a ToUnicode map
254 hasToUnicode = gFalse;
255 if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
256 hasToUnicode = fontObj.dictLookup("ToUnicode", &toUnicodeObj)->isStream();
261 // check for a font subset name: capital letters followed by a '+'
265 for (i = 0; i < name->getLength(); ++i) {
266 if (name->getChar(i) < 'A' || name->getChar(i) > 'Z') {
270 subset = i > 0 && i < name->getLength() && name->getChar(i) == '+';
273 // print the font info
274 printf("%-36s %-12s %-3s %-3s %-3s",
275 name ? name->getCString() : "[none]",
276 fontTypeNames[font->getType()],
278 subset ? "yes" : "no",
279 hasToUnicode ? "yes" : "no");
280 if (fontRef.gen >= 100000) {
283 printf(" %6d %2d\n", fontRef.num, fontRef.gen);
286 // add this font to the list
287 if (fontsLen == fontsSize) {
289 fonts = (Ref *)grealloc(fonts, fontsSize * sizeof(Ref));
291 fonts[fontsLen++] = *font->getID();