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