source: trunk/poppler/mypoppler/poppler/FontInfo.cc @ 461

Last change on this file since 461 was 277, checked in by rbri, 12 years ago

PDF plugin: Poppler library updated to version 0.12.3

File size: 6.6 KB
Line 
1//========================================================================
2//
3// FontInfo.cc
4//
5// Copyright (C) 2005, 2006 Kristian HÞgsberg <krh@redhat.com>
6// Copyright (C) 2005-2008 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//
11// To see a description of the changes please see the Changelog file that
12// came with your tarball or type make ChangeLog if you are building from git
13//
14//========================================================================
15
16//========================================================================
17//
18// Based on code from pdffonts.cc
19//
20// Copyright 2001-2007 Glyph & Cog, LLC
21//
22//========================================================================
23
24#include "config.h"
25#include <stdio.h>
26#include <stdlib.h>
27#include <stddef.h>
28#include <string.h>
29#include <math.h>
30#include "GlobalParams.h"
31#include "Error.h"
32#include "Object.h"
33#include "Dict.h"
34#include "GfxFont.h"
35#include "Annot.h"
36#include "PDFDoc.h"
37#include "FontInfo.h"
38
39FontInfoScanner::FontInfoScanner(PDFDoc *docA, int firstPage) {
40  doc = docA;
41  currentPage = firstPage + 1;
42  fonts = NULL;
43  fontsLen = fontsSize = 0;
44  visitedXObjects = NULL;
45  visitedXObjectsLen = visitedXObjectsSize = 0;
46}
47
48FontInfoScanner::~FontInfoScanner() {
49  gfree(fonts);
50  gfree(visitedXObjects);
51}
52
53GooList *FontInfoScanner::scan(int nPages) {
54  GooList *result;
55  Page *page;
56  Dict *resDict;
57  Annots *annots;
58  Object obj1, obj2;
59  int lastPage;
60
61  if (currentPage > doc->getNumPages()) {
62    return NULL;
63  }
64 
65  result = new GooList();
66
67  lastPage = currentPage + nPages;
68  if (lastPage > doc->getNumPages() + 1) {
69    lastPage = doc->getNumPages() + 1;
70  }
71
72  for (int pg = currentPage; pg < lastPage; ++pg) {
73    page = doc->getCatalog()->getPage(pg);
74    if ((resDict = page->getResourceDict())) {
75      scanFonts(resDict, result);
76    }
77    annots = new Annots(doc->getXRef(), doc->getCatalog(), page->getAnnots(&obj1));
78    obj1.free();
79    for (int i = 0; i < annots->getNumAnnots(); ++i) {
80      if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
81        obj1.streamGetDict()->lookup("Resources", &obj2);
82        if (obj2.isDict()) {
83          scanFonts(obj2.getDict(), result);
84        }
85        obj2.free();
86      }
87      obj1.free();
88    }
89    delete annots;
90  }
91
92  currentPage = lastPage;
93
94  return result;
95}
96
97void FontInfoScanner::scanFonts(Dict *resDict, GooList *fontsList) {
98  Object obj1, obj2, xObjDict, xObj, xObj2, resObj;
99  Ref r;
100  GfxFontDict *gfxFontDict;
101  GfxFont *font;
102  int i;
103
104  // scan the fonts in this resource dictionary
105  gfxFontDict = NULL;
106  resDict->lookupNF("Font", &obj1);
107  if (obj1.isRef()) {
108    obj1.fetch(doc->getXRef(), &obj2);
109    if (obj2.isDict()) {
110      r = obj1.getRef();
111      gfxFontDict = new GfxFontDict(doc->getXRef(), &r, obj2.getDict());
112    }
113    obj2.free();
114  } else if (obj1.isDict()) {
115    gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict());
116  }
117  if (gfxFontDict) {
118    for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
119      int k;
120      if ((font = gfxFontDict->getFont(i))) {
121        Ref fontRef = *font->getID();
122        GBool alreadySeen = gFalse;
123
124        // check for an already-seen font
125        for (k = 0; k < fontsLen; ++k) {
126          if (fontRef.num == fonts[k].num && fontRef.gen == fonts[k].gen) {
127            alreadySeen = gTrue;
128          }
129        }
130
131        // add this font to the list
132        if (!alreadySeen) {
133          fontsList->append(new FontInfo(font, doc));
134          if (fontsLen == fontsSize) {
135            fontsSize += 32;
136            fonts = (Ref *)grealloc(fonts, fontsSize * sizeof(Ref));
137          }
138          fonts[fontsLen++] = *font->getID();
139        }
140      }
141    }
142    delete gfxFontDict;
143  }
144  obj1.free();
145
146  // recursively scan any resource dictionaries in objects in this
147  // resource dictionary
148  resDict->lookup("XObject", &xObjDict);
149  if (xObjDict.isDict()) {
150    for (i = 0; i < xObjDict.dictGetLength(); ++i) {
151      xObjDict.dictGetValNF(i, &xObj);
152      if (xObj.isRef()) {
153        GBool alreadySeen = gFalse;
154        // check for an already-seen XObject
155        for (int k = 0; k < visitedXObjectsLen; ++k) {
156          if (xObj.getRef().num == visitedXObjects[k].num &&
157              xObj.getRef().gen == visitedXObjects[k].gen) {
158            alreadySeen = gTrue;
159          }
160        }
161
162        if (alreadySeen) {
163          xObj.free();
164          continue;
165        }
166
167        if (visitedXObjectsLen == visitedXObjectsSize) {
168          visitedXObjectsSize += 32;
169          visitedXObjects = (Ref *)grealloc(visitedXObjects, visitedXObjectsSize * sizeof(Ref));
170        }
171        visitedXObjects[visitedXObjectsLen++] = xObj.getRef();
172      }
173
174      xObj.fetch(doc->getXRef(), &xObj2);
175
176      if (xObj2.isStream()) {
177        xObj2.streamGetDict()->lookup("Resources", &resObj);
178        if (resObj.isDict() && resObj.getDict() != resDict) {
179          scanFonts(resObj.getDict(), fontsList);
180        }
181        resObj.free();
182      }
183      xObj.free();
184      xObj2.free();
185    }
186  }
187  xObjDict.free();
188}
189
190FontInfo::FontInfo(GfxFont *font, PDFDoc *doc) {
191  GooString *origName;
192  Object fontObj, toUnicodeObj;
193  int i;
194
195  fontRef = *font->getID();
196
197  // font name
198  origName = font->getOrigName();
199  if (origName != NULL) {
200    name = font->getOrigName()->copy();
201  } else {
202    name = NULL;
203  }
204
205  // font type
206  type = (FontInfo::Type)font->getType();
207
208  // check for an embedded font
209  if (font->getType() == fontType3) {
210    emb = gTrue;
211  } else {
212    emb = font->getEmbeddedFontID(&embRef);
213  }
214
215  if (!emb)
216  {
217    DisplayFontParam *dfp = globalParams->getDisplayFont(font);
218    if (dfp)
219    {
220      if (dfp->kind == displayFontT1) file = dfp->t1.fileName->copy();
221      else file = dfp->tt.fileName->copy();
222    }
223    else file = NULL;
224  }
225  else file = NULL;
226
227  // look for a ToUnicode map
228  hasToUnicode = gFalse;
229  if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) {
230    hasToUnicode = fontObj.dictLookup("ToUnicode", &toUnicodeObj)->isStream();
231    toUnicodeObj.free();
232  }
233  fontObj.free();
234
235  // check for a font subset name: capital letters followed by a '+'
236  // sign
237  subset = gFalse;
238  if (name) {
239    for (i = 0; i < name->getLength(); ++i) {
240      if (name->getChar(i) < 'A' || name->getChar(i) > 'Z') {
241        break;
242      }
243    }
244    subset = i > 0 && i < name->getLength() && name->getChar(i) == '+';
245  }
246}
247
248FontInfo::FontInfo(FontInfo& f) {
249  name = f.name ? f.name->copy() : NULL;
250  file = f.file ? f.file->copy() : NULL;
251  type = f.type;
252  emb = f.emb;
253  subset = f.subset;
254  hasToUnicode = f.hasToUnicode;
255  fontRef = f.fontRef;
256  embRef = f.embRef;
257}
258
259FontInfo::~FontInfo() {
260  delete name;
261  delete file;
262}
Note: See TracBrowser for help on using the repository browser.