filters

pdffonts.cc

00001 //========================================================================
00002 //
00003 // pdffonts.cc
00004 //
00005 // Copyright 2001-2002 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #include <aconf.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <stddef.h>
00013 #include <string.h>
00014 #include <math.h>
00015 #include "parseargs.h"
00016 #include "GString.h"
00017 #include "gmem.h"
00018 #include "GlobalParams.h"
00019 #include "Error.h"
00020 #include "Object.h"
00021 #include "Dict.h"
00022 #include "GfxFont.h"
00023 #include "Annot.h"
00024 #include "PDFDoc.h"
00025 #include "config.h"
00026 
00027 static char *fontTypeNames[] = {
00028   "unknown",
00029   "Type 1",
00030   "Type 1C",
00031   "Type 3",
00032   "TrueType",
00033   "CID Type 0",
00034   "CID Type 0C",
00035   "CID TrueType"
00036 };
00037 
00038 static void scanFonts(Dict *resDict, PDFDoc *doc);
00039 static void scanFont(GfxFont *font, PDFDoc *doc);
00040 
00041 static int firstPage = 1;
00042 static int lastPage = 0;
00043 static char ownerPassword[33] = "";
00044 static char userPassword[33] = "";
00045 static char cfgFileName[256] = "";
00046 static GBool printVersion = gFalse;
00047 static GBool printHelp = gFalse;
00048 
00049 static ArgDesc argDesc[] = {
00050   {"-f",      argInt,      &firstPage,     0,
00051    "first page to examine"},
00052   {"-l",      argInt,      &lastPage,      0,
00053    "last page to examine"},
00054   {"-opw",    argString,   ownerPassword,  sizeof(ownerPassword),
00055    "owner password (for encrypted files)"},
00056   {"-upw",    argString,   userPassword,   sizeof(userPassword),
00057    "user password (for encrypted files)"},
00058   {"-cfg",        argString,      cfgFileName,    sizeof(cfgFileName),
00059    "configuration file to use in place of .xpdfrc"},
00060   {"-v",      argFlag,     &printVersion,  0,
00061    "print copyright and version info"},
00062   {"-h",      argFlag,     &printHelp,     0,
00063    "print usage information"},
00064   {"-help",   argFlag,     &printHelp,     0,
00065    "print usage information"},
00066   {"--help",  argFlag,     &printHelp,     0,
00067    "print usage information"},
00068   {"-?",      argFlag,     &printHelp,     0,
00069    "print usage information"},
00070   {NULL}
00071 };
00072 
00073 static Ref *fonts;
00074 static int fontsLen;
00075 static int fontsSize;
00076 
00077 int main(int argc, char *argv[]) {
00078   PDFDoc *doc;
00079   GString *fileName;
00080   GString *ownerPW, *userPW;
00081   GBool ok;
00082   Page *page;
00083   Dict *resDict;
00084   Annots *annots;
00085   Object obj1, obj2;
00086   int pg, i;
00087   int exitCode;
00088 
00089   exitCode = 99;
00090 
00091   // parse args
00092   ok = parseArgs(argDesc, &argc, argv);
00093   if (!ok || argc != 2 || printVersion || printHelp) {
00094     fprintf(stderr, "pdfinfo version %s\n", xpdfVersion);
00095     fprintf(stderr, "%s\n", xpdfCopyright);
00096     if (!printVersion) {
00097       printUsage("pdfinfo", "<PDF-file>", argDesc);
00098     }
00099     goto err0;
00100   }
00101   fileName = new GString(argv[1]);
00102 
00103   // read config file
00104   globalParams = new GlobalParams(cfgFileName);
00105 
00106   // open PDF file
00107   if (ownerPassword[0]) {
00108     ownerPW = new GString(ownerPassword);
00109   } else {
00110     ownerPW = NULL;
00111   }
00112   if (userPassword[0]) {
00113     userPW = new GString(userPassword);
00114   } else {
00115     userPW = NULL;
00116   }
00117   doc = new PDFDoc(fileName, ownerPW, userPW);
00118   if (userPW) {
00119     delete userPW;
00120   }
00121   if (ownerPW) {
00122     delete ownerPW;
00123   }
00124   if (!doc->isOk()) {
00125     exitCode = 1;
00126     goto err1;
00127   }
00128 
00129   // get page range
00130   if (firstPage < 1) {
00131     firstPage = 1;
00132   }
00133   if (lastPage < 1 || lastPage > doc->getNumPages()) {
00134     lastPage = doc->getNumPages();
00135   }
00136 
00137   // scan the fonts
00138   printf("name                                 type         emb sub uni object ID\n");
00139   printf("------------------------------------ ------------ --- --- --- ---------\n");
00140   fonts = NULL;
00141   fontsLen = fontsSize = 0;
00142   for (pg = firstPage; pg <= lastPage; ++pg) {
00143     page = doc->getCatalog()->getPage(pg);
00144     if ((resDict = page->getResourceDict())) {
00145       scanFonts(resDict, doc);
00146     }
00147     annots = new Annots(doc->getXRef(), page->getAnnots(&obj1));
00148     obj1.free();
00149     for (i = 0; i < annots->getNumAnnots(); ++i) {
00150       if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
00151     obj1.streamGetDict()->lookup("Resources", &obj2);
00152     if (obj2.isDict()) {
00153       scanFonts(obj2.getDict(), doc);
00154     }
00155     obj2.free();
00156       }
00157       obj1.free();
00158     }
00159     delete annots;
00160   }
00161 
00162   exitCode = 0;
00163 
00164   // clean up
00165   gfree(fonts);
00166  err1:
00167   delete doc;
00168   delete globalParams;
00169  err0:
00170 
00171   // check for memory leaks
00172   Object::memCheck(stderr);
00173   gMemReport(stderr);
00174 
00175   return exitCode;
00176 }
00177 
00178 static void scanFonts(Dict *resDict, PDFDoc *doc) {
00179   GfxFontDict *gfxFontDict;
00180   GfxFont *font;
00181   Object fontDict, xObjDict, xObj, resObj;
00182   int i;
00183 
00184   // scan the fonts in this resource dictionary
00185   resDict->lookup("Font", &fontDict);
00186   if (fontDict.isDict()) {
00187     gfxFontDict = new GfxFontDict(doc->getXRef(), fontDict.getDict());
00188     for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
00189       font = gfxFontDict->getFont(i);
00190       scanFont(font, doc);
00191     }
00192     delete gfxFontDict;
00193   }
00194   fontDict.free();
00195 
00196   // recursively scan any resource dictionaries in objects in this
00197   // resource dictionary
00198   resDict->lookup("XObject", &xObjDict);
00199   if (xObjDict.isDict()) {
00200     for (i = 0; i < xObjDict.dictGetLength(); ++i) {
00201       xObjDict.dictGetVal(i, &xObj);
00202       if (xObj.isStream()) {
00203     xObj.streamGetDict()->lookup("Resources", &resObj);
00204     if (resObj.isDict()) {
00205       scanFonts(resObj.getDict(), doc);
00206     }
00207     resObj.free();
00208       }
00209       xObj.free();
00210     }
00211   }
00212   xObjDict.free();
00213 }
00214 
00215 static void scanFont(GfxFont *font, PDFDoc *doc) {
00216   Ref fontRef, embRef;
00217   Object fontObj, nameObj, toUnicodeObj;
00218   GString *name;
00219   GBool subset, hasToUnicode;
00220   int i;
00221 
00222   fontRef = *font->getID();
00223 
00224   // check for an already-seen font
00225   for (i = 0; i < fontsLen; ++i) {
00226     if (fontRef.num == fonts[i].num && fontRef.gen == fonts[i].gen) {
00227       return;
00228     }
00229   }
00230 
00231   // get the original font name -- the GfxFont class munges substitute
00232   // Base-14 font names into proper form, so this code grabs the
00233   // original name from the font dictionary; also look for a ToUnicode
00234   // map
00235   name = NULL;
00236   hasToUnicode = gFalse;
00237   if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
00238     if (fontObj.dictLookup("BaseFont", &nameObj)->isName()) {
00239       name = new GString(nameObj.getName());
00240     }
00241     nameObj.free();
00242     hasToUnicode = fontObj.dictLookup("ToUnicode", &toUnicodeObj)->isStream();
00243     toUnicodeObj.free();
00244   }
00245   fontObj.free();
00246 
00247   // check for a font subset name: capital letters followed by a '+'
00248   // sign
00249   subset = gFalse;
00250   if (name) {
00251     for (i = 0; i < name->getLength(); ++i) {
00252       if (name->getChar(i) < 'A' || name->getChar(i) > 'Z') {
00253     break;
00254       }
00255     }
00256     subset = i > 0 && i < name->getLength() && name->getChar(i) == '+';
00257   }
00258 
00259   // print the font info
00260   printf("%-36s %-12s %-3s %-3s %-3s",
00261      name ? name->getCString() : "[none]",
00262      fontTypeNames[font->getType()],
00263      font->getEmbeddedFontID(&embRef) ? "yes" : "no",
00264      subset ? "yes" : "no",
00265      hasToUnicode ? "yes" : "no");
00266   if (fontRef.gen == 999999) {
00267     printf(" [none]\n");
00268   } else {
00269     printf(" %6d %2d\n", fontRef.num, fontRef.gen);
00270   }
00271   if (name) {
00272     delete name;
00273   }
00274 
00275   // add this font to the list
00276   if (fontsLen == fontsSize) {
00277     fontsSize += 32;
00278     fonts = (Ref *)grealloc(fonts, fontsSize * sizeof(Ref));
00279   }
00280   fonts[fontsLen++] = *font->getID();
00281 }
KDE Home | KDE Accessibility Home | Description of Access Keys