1 //========================================================================
5 // Copyright (C) 2005, 2006 Kristian Høgsberg <krh@redhat.com>
6 // Copyright (C) 2005-2008, 2010 Albert Astals Cid <aacid@kde.org>
7 // Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
8 // Copyright (C) 2006 Kouhei Sutou <kou@cozmixng.org>
9 // Copyright (C) 2009 Pino Toscano <pino@kde.org>
10 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
11 // Copyright (C) 2010, 2012 Adrian Johnson <ajohnson@redneon.com>
12 // Copyright (C) 2010, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
13 // Copyright (C) 2011 Carlos Garcia Campos <carlosgc@gnome.org>
14 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
16 // To see a description of the changes please see the Changelog file that
17 // came with your tarball or type make ChangeLog if you are building from git
19 //========================================================================
21 //========================================================================
23 // Based on code from pdffonts.cc
25 // Copyright 2001-2007 Glyph & Cog, LLC
27 //========================================================================
35 #include "GlobalParams.h"
44 FontInfoScanner::FontInfoScanner(PDFDoc
*docA
, int firstPage
) {
46 currentPage
= firstPage
+ 1;
49 FontInfoScanner::~FontInfoScanner() {
52 GooList
*FontInfoScanner::scan(int nPages
) {
60 if (currentPage
> doc
->getNumPages()) {
64 result
= new GooList();
66 lastPage
= currentPage
+ nPages
;
67 if (lastPage
> doc
->getNumPages() + 1) {
68 lastPage
= doc
->getNumPages() + 1;
71 XRef
*xrefA
= doc
->getXRef()->copy();
72 for (int pg
= currentPage
; pg
< lastPage
; ++pg
) {
73 page
= doc
->getPage(pg
);
76 if ((resDict
= page
->getResourceDictCopy(xrefA
))) {
77 scanFonts(xrefA
, resDict
, result
);
80 annots
= page
->getAnnots();
81 for (int i
= 0; i
< annots
->getNumAnnots(); ++i
) {
82 if (annots
->getAnnot(i
)->getAppearanceResDict(&obj1
)->isDict()) {
83 scanFonts(xrefA
, obj1
.getDict(), result
);
89 currentPage
= lastPage
;
95 void FontInfoScanner::scanFonts(XRef
*xrefA
, Dict
*resDict
, GooList
*fontsList
) {
96 Object obj1
, obj2
, objDict
, resObj
;
98 GfxFontDict
*gfxFontDict
;
102 // scan the fonts in this resource dictionary
104 resDict
->lookupNF("Font", &obj1
);
106 obj1
.fetch(xrefA
, &obj2
);
109 gfxFontDict
= new GfxFontDict(xrefA
, &r
, obj2
.getDict());
112 } else if (obj1
.isDict()) {
113 gfxFontDict
= new GfxFontDict(xrefA
, NULL
, obj1
.getDict());
116 for (i
= 0; i
< gfxFontDict
->getNumFonts(); ++i
) {
117 if ((font
= gfxFontDict
->getFont(i
))) {
118 Ref fontRef
= *font
->getID();
120 // add this font to the list if not already found
121 if (fonts
.find(fontRef
.num
) == fonts
.end()) {
122 fontsList
->append(new FontInfo(font
, xrefA
));
123 fonts
.insert(fontRef
.num
);
131 // recursively scan any resource dictionaries in objects in this
132 // resource dictionary
133 const char *resTypes
[] = { "XObject", "Pattern" };
134 for (Guint resType
= 0; resType
< sizeof(resTypes
) / sizeof(resTypes
[0]); ++resType
) {
135 resDict
->lookup(resTypes
[resType
], &objDict
);
136 if (objDict
.isDict()) {
137 for (i
= 0; i
< objDict
.dictGetLength(); ++i
) {
138 objDict
.dictGetValNF(i
, &obj1
);
140 // check for an already-seen object
141 const Ref r
= obj1
.getRef();
142 if (visitedObjects
.find(r
.num
) != visitedObjects
.end()) {
147 visitedObjects
.insert(r
.num
);
150 obj1
.fetch(xrefA
, &obj2
);
152 if (obj2
.isStream()) {
153 obj2
.streamGetDict()->lookup("Resources", &resObj
);
154 if (resObj
.isDict() && resObj
.getDict() != resDict
) {
155 scanFonts(xrefA
, resObj
.getDict(), fontsList
);
167 FontInfo::FontInfo(GfxFont
*font
, XRef
*xref
) {
169 Object fontObj
, toUnicodeObj
;
172 fontRef
= *font
->getID();
175 origName
= font
->getName();
176 if (origName
!= NULL
) {
177 name
= font
->getName()->copy();
183 type
= (FontInfo::Type
)font
->getType();
185 // check for an embedded font
186 if (font
->getType() == fontType3
) {
189 emb
= font
->getEmbeddedFontID(&embRef
);
193 substituteName
= NULL
;
198 GooString substituteNameAux
;
199 file
= globalParams
->findSystemFontFile(font
, &dummy
, &dummy2
, &substituteNameAux
);
200 if (substituteNameAux
.getLength() > 0)
201 substituteName
= substituteNameAux
.copy();
203 encoding
= font
->getEncodingName()->copy();
205 // look for a ToUnicode map
206 hasToUnicode
= gFalse
;
207 if (xref
->fetch(fontRef
.num
, fontRef
.gen
, &fontObj
)->isDict()) {
208 hasToUnicode
= fontObj
.dictLookup("ToUnicode", &toUnicodeObj
)->isStream();
213 // check for a font subset name: capital letters followed by a '+'
217 for (i
= 0; i
< name
->getLength(); ++i
) {
218 if (name
->getChar(i
) < 'A' || name
->getChar(i
) > 'Z') {
222 subset
= i
> 0 && i
< name
->getLength() && name
->getChar(i
) == '+';
226 FontInfo::FontInfo(FontInfo
& f
) {
227 name
= f
.name
? f
.name
->copy() : NULL
;
228 file
= f
.file
? f
.file
->copy() : NULL
;
229 encoding
= f
.encoding
? f
.encoding
->copy() : NULL
;
230 substituteName
= f
.substituteName
? f
.substituteName
->copy() : NULL
;
234 hasToUnicode
= f
.hasToUnicode
;
239 FontInfo::~FontInfo() {
244 delete substituteName
;