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, 2022 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[] = { { .arg: "-f" , .kind: argInt, .val: &firstPage, .size: 0, .usage: "first page to examine" }, |
58 | { .arg: "-l" , .kind: argInt, .val: &lastPage, .size: 0, .usage: "last page to examine" }, |
59 | { .arg: "-subst" , .kind: argFlag, .val: &showSubst, .size: 0, .usage: "show font substitutions" }, |
60 | { .arg: "-opw" , .kind: argString, .val: ownerPassword, .size: sizeof(ownerPassword), .usage: "owner password (for encrypted files)" }, |
61 | { .arg: "-upw" , .kind: argString, .val: userPassword, .size: sizeof(userPassword), .usage: "user password (for encrypted files)" }, |
62 | { .arg: "-v" , .kind: argFlag, .val: &printVersion, .size: 0, .usage: "print copyright and version info" }, |
63 | { .arg: "-h" , .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" }, |
64 | { .arg: "-help" , .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" }, |
65 | { .arg: "--help" , .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" }, |
66 | { .arg: "-?" , .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" }, |
67 | {} }; |
68 | |
69 | int main(int argc, char *argv[]) |
70 | { |
71 | std::optional<GooString> ownerPW, userPW; |
72 | bool ok; |
73 | |
74 | Win32Console win32Console(&argc, &argv); |
75 | |
76 | // parse args |
77 | ok = parseArgs(args: argDesc, argc: &argc, argv); |
78 | if (!ok || argc != 2 || printVersion || printHelp) { |
79 | fprintf(stderr, format: "pdffonts version %s\n" , PACKAGE_VERSION); |
80 | fprintf(stderr, format: "%s\n" , popplerCopyright); |
81 | fprintf(stderr, format: "%s\n" , xpdfCopyright); |
82 | if (!printVersion) { |
83 | printUsage(program: "pdffonts" , otherArgs: "<PDF-file>" , args: argDesc); |
84 | } |
85 | if (printVersion || printHelp) { |
86 | return 0; |
87 | } |
88 | return 99; |
89 | } |
90 | |
91 | std::string fileName(argv[1]); |
92 | if (fileName == "-" ) { |
93 | fileName = "fd://0" ; |
94 | } |
95 | |
96 | // read config file |
97 | globalParams = std::make_unique<GlobalParams>(); |
98 | |
99 | // open PDF file |
100 | if (ownerPassword[0] != '\001') { |
101 | ownerPW = GooString(ownerPassword); |
102 | } |
103 | if (userPassword[0] != '\001') { |
104 | userPW = GooString(userPassword); |
105 | } |
106 | |
107 | auto doc = std::unique_ptr<PDFDoc>(PDFDocFactory().createPDFDoc(uri: GooString(fileName), ownerPassword: ownerPW, userPassword: userPW)); |
108 | |
109 | if (!doc->isOk()) { |
110 | return 1; |
111 | } |
112 | |
113 | // get page range |
114 | if (firstPage < 1) { |
115 | firstPage = 1; |
116 | } |
117 | if (lastPage < 1 || lastPage > doc->getNumPages()) { |
118 | lastPage = doc->getNumPages(); |
119 | } |
120 | if (lastPage < firstPage) { |
121 | fprintf(stderr, format: "Wrong page range given: the first page (%d) can not be after the last page (%d).\n" , firstPage, lastPage); |
122 | return 99; |
123 | } |
124 | |
125 | // get the fonts |
126 | { |
127 | FontInfoScanner scanner(doc.get(), firstPage - 1); |
128 | const std::vector<FontInfo *> fonts = scanner.scan(nPages: lastPage - firstPage + 1); |
129 | |
130 | if (showSubst) { |
131 | // print the font substitutions |
132 | printf(format: "name object ID substitute font substitute font file\n" ); |
133 | printf(format: "------------------------------------ --------- ------------------------------------ ------------------------------------\n" ); |
134 | for (const FontInfo *font : fonts) { |
135 | if (font->getFile()) { |
136 | printf(format: "%-36s" , font->getName() ? font->getName()->c_str() : "[none]" ); |
137 | const Ref fontRef = font->getRef(); |
138 | if (fontRef.gen >= 100000) { |
139 | printf(format: " [none]" ); |
140 | } else { |
141 | printf(format: " %6d %2d" , fontRef.num, fontRef.gen); |
142 | } |
143 | printf(format: " %-36s %s\n" , font->getSubstituteName() ? font->getSubstituteName()->c_str() : "[none]" , font->getFile()->c_str()); |
144 | } |
145 | delete font; |
146 | } |
147 | } else { |
148 | // print the font info |
149 | printf(format: "name type encoding emb sub uni object ID\n" ); |
150 | printf(format: "------------------------------------ ----------------- ---------------- --- --- --- ---------\n" ); |
151 | for (const FontInfo *font : fonts) { |
152 | printf(format: "%-36s %-17s %-16s %-3s %-3s %-3s" , font->getName() ? font->getName()->c_str() : "[none]" , fontTypeNames[font->getType()], font->getEncoding().c_str(), font->getEmbedded() ? "yes" : "no" , |
153 | font->getSubset() ? "yes" : "no" , font->getToUnicode() ? "yes" : "no" ); |
154 | const Ref fontRef = font->getRef(); |
155 | if (fontRef.gen >= 100000) { |
156 | printf(format: " [none]\n" ); |
157 | } else { |
158 | printf(format: " %6d %2d\n" , fontRef.num, fontRef.gen); |
159 | } |
160 | delete font; |
161 | } |
162 | } |
163 | } |
164 | |
165 | return 0; |
166 | } |
167 | |