00001
00002
00003
00004
00005
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
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
00104 globalParams = new GlobalParams(cfgFileName);
00105
00106
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
00130 if (firstPage < 1) {
00131 firstPage = 1;
00132 }
00133 if (lastPage < 1 || lastPage > doc->getNumPages()) {
00134 lastPage = doc->getNumPages();
00135 }
00136
00137
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
00165 gfree(fonts);
00166 err1:
00167 delete doc;
00168 delete globalParams;
00169 err0:
00170
00171
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
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
00197
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
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
00232
00233
00234
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
00248
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
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
00276 if (fontsLen == fontsSize) {
00277 fontsSize += 32;
00278 fonts = (Ref *)grealloc(fonts, fontsSize * sizeof(Ref));
00279 }
00280 fonts[fontsLen++] = *font->getID();
00281 }