]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/pdffonts.cc
Imported Xpdf 2.03 and fixed build.
[evince.git] / pdf / xpdf / pdffonts.cc
1 //========================================================================
2 //
3 // pdffonts.cc
4 //
5 // Copyright 2001-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stddef.h>
13 #include <string.h>
14 #include <math.h>
15 #include "parseargs.h"
16 #include "GString.h"
17 #include "gmem.h"
18 #include "GlobalParams.h"
19 #include "Error.h"
20 #include "Object.h"
21 #include "Dict.h"
22 #include "GfxFont.h"
23 #include "Annot.h"
24 #include "PDFDoc.h"
25 #include "config.h"
26
27 static char *fontTypeNames[] = {
28   "unknown",
29   "Type 1",
30   "Type 1C",
31   "Type 3",
32   "TrueType",
33   "CID Type 0",
34   "CID Type 0C",
35   "CID TrueType"
36 };
37
38 static void scanFonts(Dict *resDict, PDFDoc *doc);
39 static void scanFont(GfxFont *font, PDFDoc *doc);
40
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;
48
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"},
70   {NULL}
71 };
72
73 static Ref *fonts;
74 static int fontsLen;
75 static int fontsSize;
76
77 int main(int argc, char *argv[]) {
78   PDFDoc *doc;
79   GString *fileName;
80   GString *ownerPW, *userPW;
81   GBool ok;
82   Page *page;
83   Dict *resDict;
84   Annots *annots;
85   Object obj1, obj2;
86   int pg, i;
87   int exitCode;
88
89   exitCode = 99;
90
91   // parse args
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);
96     if (!printVersion) {
97       printUsage("pdffonts", "<PDF-file>", argDesc);
98     }
99     goto err0;
100   }
101   fileName = new GString(argv[1]);
102
103   // read config file
104   globalParams = new GlobalParams(cfgFileName);
105
106   // open PDF file
107   if (ownerPassword[0] != '\001') {
108     ownerPW = new GString(ownerPassword);
109   } else {
110     ownerPW = NULL;
111   }
112   if (userPassword[0] != '\001') {
113     userPW = new GString(userPassword);
114   } else {
115     userPW = NULL;
116   }
117   doc = new PDFDoc(fileName, ownerPW, userPW);
118   if (userPW) {
119     delete userPW;
120   }
121   if (ownerPW) {
122     delete ownerPW;
123   }
124   if (!doc->isOk()) {
125     exitCode = 1;
126     goto err1;
127   }
128
129   // get page range
130   if (firstPage < 1) {
131     firstPage = 1;
132   }
133   if (lastPage < 1 || lastPage > doc->getNumPages()) {
134     lastPage = doc->getNumPages();
135   }
136
137   // scan the fonts
138   printf("name                                 type         emb sub uni object ID\n");
139   printf("------------------------------------ ------------ --- --- --- ---------\n");
140   fonts = NULL;
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);
146     }
147     annots = new Annots(doc->getXRef(), page->getAnnots(&obj1));
148     obj1.free();
149     for (i = 0; i < annots->getNumAnnots(); ++i) {
150       if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
151         obj1.streamGetDict()->lookup("Resources", &obj2);
152         if (obj2.isDict()) {
153           scanFonts(obj2.getDict(), doc);
154         }
155         obj2.free();
156       }
157       obj1.free();
158     }
159     delete annots;
160   }
161
162   exitCode = 0;
163
164   // clean up
165   gfree(fonts);
166  err1:
167   delete doc;
168   delete globalParams;
169  err0:
170
171   // check for memory leaks
172   Object::memCheck(stderr);
173   gMemReport(stderr);
174
175   return exitCode;
176 }
177
178 static void scanFonts(Dict *resDict, PDFDoc *doc) {
179   Object obj1, obj2, xObjDict, xObj, resObj;
180   Ref r;
181   GfxFontDict *gfxFontDict;
182   GfxFont *font;
183   int i;
184
185   // scan the fonts in this resource dictionary
186   gfxFontDict = NULL;
187   resDict->lookupNF("Font", &obj1);
188   if (obj1.isRef()) {
189     obj1.fetch(doc->getXRef(), &obj2);
190     if (obj2.isDict()) {
191       r = obj1.getRef();
192       gfxFontDict = new GfxFontDict(doc->getXRef(), &r, obj2.getDict());
193     }
194     obj2.free();
195   } else if (obj1.isDict()) {
196     gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict());
197   }
198   if (gfxFontDict) {
199     for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
200       font = gfxFontDict->getFont(i);
201       scanFont(font, doc);
202     }
203     delete gfxFontDict;
204   }
205   obj1.free();
206
207   // recursively scan any resource dictionaries in objects in this
208   // resource dictionary
209   resDict->lookup("XObject", &xObjDict);
210   if (xObjDict.isDict()) {
211     for (i = 0; i < xObjDict.dictGetLength(); ++i) {
212       xObjDict.dictGetVal(i, &xObj);
213       if (xObj.isStream()) {
214         xObj.streamGetDict()->lookup("Resources", &resObj);
215         if (resObj.isDict()) {
216           scanFonts(resObj.getDict(), doc);
217         }
218         resObj.free();
219       }
220       xObj.free();
221     }
222   }
223   xObjDict.free();
224 }
225
226 static void scanFont(GfxFont *font, PDFDoc *doc) {
227   Ref fontRef, embRef;
228   Object fontObj, nameObj, toUnicodeObj;
229   GString *name;
230   GBool subset, hasToUnicode;
231   int i;
232
233   fontRef = *font->getID();
234
235   // check for an already-seen font
236   for (i = 0; i < fontsLen; ++i) {
237     if (fontRef.num == fonts[i].num && fontRef.gen == fonts[i].gen) {
238       return;
239     }
240   }
241
242   // font name
243   name = font->getOrigName();
244
245   // look for a ToUnicode map
246   hasToUnicode = gFalse;
247   if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
248     hasToUnicode = fontObj.dictLookup("ToUnicode", &toUnicodeObj)->isStream();
249     toUnicodeObj.free();
250   }
251   fontObj.free();
252
253   // check for a font subset name: capital letters followed by a '+'
254   // sign
255   subset = gFalse;
256   if (name) {
257     for (i = 0; i < name->getLength(); ++i) {
258       if (name->getChar(i) < 'A' || name->getChar(i) > 'Z') {
259         break;
260       }
261     }
262     subset = i > 0 && i < name->getLength() && name->getChar(i) == '+';
263   }
264
265   // print the font info
266   printf("%-36s %-12s %-3s %-3s %-3s",
267          name ? name->getCString() : "[none]",
268          fontTypeNames[font->getType()],
269          font->getEmbeddedFontID(&embRef) ? "yes" : "no",
270          subset ? "yes" : "no",
271          hasToUnicode ? "yes" : "no");
272   if (fontRef.gen >= 100000) {
273     printf(" [none]\n");
274   } else {
275     printf(" %6d %2d\n", fontRef.num, fontRef.gen);
276   }
277
278   // add this font to the list
279   if (fontsLen == fontsSize) {
280     fontsSize += 32;
281     fonts = (Ref *)grealloc(fonts, fontsSize * sizeof(Ref));
282   }
283   fonts[fontsLen++] = *font->getID();
284 }