1 //========================================================================
2 //
3 // pdffonts.cc
4 //
5 // Copyright 2001-2007 Glyph & Cog, LLC
6 //
7 //========================================================================
8 
9 //========================================================================
10 //
11 // Modified under the Poppler project - http://poppler.freedesktop.org
12 //
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
15 //
16 // Copyright (C) 2006 Dominic Lachowicz <cinamod@hotmail.com>
17 // Copyright (C) 2007-2008, 2010, 2018 Albert Astals Cid <aacid@kde.org>
18 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
19 // Copyright (C) 2012, 2017 Adrian Johnson <ajohnson@redneon.com>
20 // Copyright (C) 2013 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
21 // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
22 // Copyright (C) 2019, 2021 Oliver Sander <oliver.sander@tu-dresden.de>
23 //
24 // To see a description of the changes please see the Changelog file that
25 // came with your tarball or type make ChangeLog if you are building from git
26 //
27 //========================================================================
28 
29 #include "config.h"
30 #include <poppler-config.h>
31 #include <cstdio>
32 #include <cstdlib>
33 #include <cstddef>
34 #include <cmath>
35 #include <memory>
36 #include <string>
37 #include "parseargs.h"
38 #include "goo/GooString.h"
39 #include "goo/gmem.h"
40 #include "GlobalParams.h"
41 #include "Object.h"
42 #include "PDFDoc.h"
43 #include "PDFDocFactory.h"
44 #include "FontInfo.h"
45 #include "Win32Console.h"
46 
47 static const char *fontTypeNames[] = { "unknown", "Type 1", "Type 1C", "Type 1C (OT)", "Type 3", "TrueType", "TrueType (OT)", "CID Type 0", "CID Type 0C", "CID Type 0C (OT)", "CID TrueType", "CID TrueType (OT)" };
48 
49 static int firstPage = 1;
50 static int lastPage = 0;
51 static bool showSubst = false;
52 static char ownerPassword[33] = "\001";
53 static char userPassword[33] = "\001";
54 static bool printVersion = false;
55 static bool printHelp = false;
56 
57 static const ArgDesc argDesc[] = { { "-f", argInt, &firstPage, 0, "first page to examine" },
58                                    { "-l", argInt, &lastPage, 0, "last page to examine" },
59                                    { "-subst", argFlag, &showSubst, 0, "show font substitutions" },
60                                    { "-opw", argString, ownerPassword, sizeof(ownerPassword), "owner password (for encrypted files)" },
61                                    { "-upw", argString, userPassword, sizeof(userPassword), "user password (for encrypted files)" },
62                                    { "-v", argFlag, &printVersion, 0, "print copyright and version info" },
63                                    { "-h", argFlag, &printHelp, 0, "print usage information" },
64                                    { "-help", argFlag, &printHelp, 0, "print usage information" },
65                                    { "--help", argFlag, &printHelp, 0, "print usage information" },
66                                    { "-?", argFlag, &printHelp, 0, "print usage information" },
67                                    {} };
68 
main(int argc,char * argv[])69 int main(int argc, char *argv[])
70 {
71     std::unique_ptr<GooString> ownerPW, userPW;
72     bool ok;
73 
74     Win32Console win32Console(&argc, &argv);
75 
76     // parse args
77     ok = parseArgs(argDesc, &argc, argv);
78     if (!ok || argc != 2 || printVersion || printHelp) {
79         fprintf(stderr, "pdffonts version %s\n", PACKAGE_VERSION);
80         fprintf(stderr, "%s\n", popplerCopyright);
81         fprintf(stderr, "%s\n", xpdfCopyright);
82         if (!printVersion) {
83             printUsage("pdffonts", "<PDF-file>", argDesc);
84         }
85         if (printVersion || printHelp)
86             return 0;
87         return 99;
88     }
89 
90     std::string fileName(argv[1]);
91     if (fileName == "-") {
92         fileName = "fd://0";
93     }
94 
95     // read config file
96     globalParams = std::make_unique<GlobalParams>();
97 
98     // open PDF file
99     if (ownerPassword[0] != '\001') {
100         ownerPW = std::make_unique<GooString>(ownerPassword);
101     }
102     if (userPassword[0] != '\001') {
103         userPW = std::make_unique<GooString>(userPassword);
104     }
105 
106     auto doc = std::unique_ptr<PDFDoc>(PDFDocFactory().createPDFDoc(GooString(fileName), ownerPW.get(), userPW.get()));
107 
108     if (!doc->isOk()) {
109         return 1;
110     }
111 
112     // get page range
113     if (firstPage < 1) {
114         firstPage = 1;
115     }
116     if (lastPage < 1 || lastPage > doc->getNumPages()) {
117         lastPage = doc->getNumPages();
118     }
119     if (lastPage < firstPage) {
120         fprintf(stderr, "Wrong page range given: the first page (%d) can not be after the last page (%d).\n", firstPage, lastPage);
121         return 99;
122     }
123 
124     // get the fonts
125     {
126         FontInfoScanner scanner(doc.get(), firstPage - 1);
127         const std::vector<FontInfo *> fonts = scanner.scan(lastPage - firstPage + 1);
128 
129         if (showSubst) {
130             // print the font substitutions
131             printf("name                                 object ID substitute font                      substitute font file\n");
132             printf("------------------------------------ --------- ------------------------------------ ------------------------------------\n");
133             for (const FontInfo *font : fonts) {
134                 if (font->getFile()) {
135                     printf("%-36s", font->getName() ? font->getName()->c_str() : "[none]");
136                     const Ref fontRef = font->getRef();
137                     if (fontRef.gen >= 100000) {
138                         printf(" [none]");
139                     } else {
140                         printf(" %6d %2d", fontRef.num, fontRef.gen);
141                     }
142                     printf(" %-36s %s\n", font->getSubstituteName() ? font->getSubstituteName()->c_str() : "[none]", font->getFile()->c_str());
143                 }
144                 delete font;
145             }
146         } else {
147             // print the font info
148             printf("name                                 type              encoding         emb sub uni object ID\n");
149             printf("------------------------------------ ----------------- ---------------- --- --- --- ---------\n");
150             for (const FontInfo *font : fonts) {
151                 printf("%-36s %-17s %-16s %-3s %-3s %-3s", font->getName() ? font->getName()->c_str() : "[none]", fontTypeNames[font->getType()], font->getEncoding().c_str(), font->getEmbedded() ? "yes" : "no",
152                        font->getSubset() ? "yes" : "no", font->getToUnicode() ? "yes" : "no");
153                 const Ref fontRef = font->getRef();
154                 if (fontRef.gen >= 100000) {
155                     printf(" [none]\n");
156                 } else {
157                     printf(" %6d %2d\n", fontRef.num, fontRef.gen);
158                 }
159                 delete font;
160             }
161         }
162     }
163 
164     return 0;
165 }
166