beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / poppler / FontInfo.cc
blob8fc89e9d8278ee8a0b1e90e0110d6f1663b37c15
1 //========================================================================
2 //
3 // FontInfo.cc
4 //
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 //========================================================================
29 #include "config.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include <string.h>
34 #include <math.h>
35 #include "GlobalParams.h"
36 #include "Error.h"
37 #include "Object.h"
38 #include "Dict.h"
39 #include "GfxFont.h"
40 #include "Annot.h"
41 #include "PDFDoc.h"
42 #include "FontInfo.h"
44 FontInfoScanner::FontInfoScanner(PDFDoc *docA, int firstPage) {
45 doc = docA;
46 currentPage = firstPage + 1;
49 FontInfoScanner::~FontInfoScanner() {
52 GooList *FontInfoScanner::scan(int nPages) {
53 GooList *result;
54 Page *page;
55 Dict *resDict;
56 Annots *annots;
57 Object obj1;
58 int lastPage;
60 if (currentPage > doc->getNumPages()) {
61 return NULL;
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);
74 if (!page) continue;
76 if ((resDict = page->getResourceDictCopy(xrefA))) {
77 scanFonts(xrefA, resDict, result);
78 delete resDict;
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);
85 obj1.free();
89 currentPage = lastPage;
91 delete xrefA;
92 return result;
95 void FontInfoScanner::scanFonts(XRef *xrefA, Dict *resDict, GooList *fontsList) {
96 Object obj1, obj2, objDict, resObj;
97 Ref r;
98 GfxFontDict *gfxFontDict;
99 GfxFont *font;
100 int i;
102 // scan the fonts in this resource dictionary
103 gfxFontDict = NULL;
104 resDict->lookupNF("Font", &obj1);
105 if (obj1.isRef()) {
106 obj1.fetch(xrefA, &obj2);
107 if (obj2.isDict()) {
108 r = obj1.getRef();
109 gfxFontDict = new GfxFontDict(xrefA, &r, obj2.getDict());
111 obj2.free();
112 } else if (obj1.isDict()) {
113 gfxFontDict = new GfxFontDict(xrefA, NULL, obj1.getDict());
115 if (gfxFontDict) {
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);
127 delete gfxFontDict;
129 obj1.free();
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);
139 if (obj1.isRef()) {
140 // check for an already-seen object
141 const Ref r = obj1.getRef();
142 if (visitedObjects.find(r.num) != visitedObjects.end()) {
143 obj1.free();
144 continue;
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);
157 resObj.free();
159 obj1.free();
160 obj2.free();
163 objDict.free();
167 FontInfo::FontInfo(GfxFont *font, XRef *xref) {
168 GooString *origName;
169 Object fontObj, toUnicodeObj;
170 int i;
172 fontRef = *font->getID();
174 // font name
175 origName = font->getName();
176 if (origName != NULL) {
177 name = font->getName()->copy();
178 } else {
179 name = NULL;
182 // font type
183 type = (FontInfo::Type)font->getType();
185 // check for an embedded font
186 if (font->getType() == fontType3) {
187 emb = gTrue;
188 } else {
189 emb = font->getEmbeddedFontID(&embRef);
192 file = NULL;
193 substituteName = NULL;
194 if (!emb)
196 SysFontType dummy;
197 int dummy2;
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();
209 toUnicodeObj.free();
211 fontObj.free();
213 // check for a font subset name: capital letters followed by a '+'
214 // sign
215 subset = gFalse;
216 if (name) {
217 for (i = 0; i < name->getLength(); ++i) {
218 if (name->getChar(i) < 'A' || name->getChar(i) > 'Z') {
219 break;
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;
231 type = f.type;
232 emb = f.emb;
233 subset = f.subset;
234 hasToUnicode = f.hasToUnicode;
235 fontRef = f.fontRef;
236 embRef = f.embRef;
239 FontInfo::~FontInfo() {
240 delete name;
241 delete file;
242 delete encoding;
243 if (substituteName)
244 delete substituteName;