source: trunk/poppler/mypoppler/poppler/CairoFontEngine.cc @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 8.8 KB
Line 
1//========================================================================
2//
3// CairoFontEngine.cc
4//
5// Copyright 2003 Glyph & Cog, LLC
6// Copyright 2004 Red Hat, Inc
7//
8//========================================================================
9
10#include <config.h>
11
12#include "config.h"
13#include <string.h>
14#include "CairoFontEngine.h"
15#include "CharCodeToUnicode.h"
16#include "GlobalParams.h"
17#include <fofi/FoFiTrueType.h>
18#include <fofi/FoFiType1C.h>
19#include "goo/gfile.h"
20#include "Error.h"
21
22#ifdef USE_GCC_PRAGMAS
23#pragma implementation
24#endif
25
26static void fileWrite(void *stream, char *data, int len) {
27  fwrite(data, 1, len, (FILE *)stream);
28}
29
30//------------------------------------------------------------------------
31// CairoFont
32//------------------------------------------------------------------------
33
34static void cairo_font_face_destroy (void *data)
35{
36  CairoFont *font = (CairoFont *) data;
37
38  delete font;
39}
40
41CairoFont::CairoFont(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs) {
42  Ref embRef;
43  Object refObj, strObj;
44  GooString *tmpFileName, *fileName, *substName,*tmpFileName2;
45  DisplayFontParam *dfp;
46  FILE *tmpFile;
47  int c, i, n, code, cmap;
48  GfxFontType fontType;
49  char **enc;
50  char *name;
51  FoFiTrueType *ff;
52  FoFiType1C *ff1c;
53  CharCodeToUnicode *ctu;
54  Unicode uBuf[8];
55  static cairo_user_data_key_t cairo_font_face_key;
56 
57  dfp = NULL;
58  codeToGID = NULL;
59  codeToGIDLen = 0;
60  cairo_font_face = NULL;
61 
62  ref = *gfxFont->getID();
63  fontType = gfxFont->getType();
64
65  tmpFileName = NULL;
66
67  if (gfxFont->getEmbeddedFontID(&embRef)) {
68    if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
69      error(-1, "Couldn't create temporary font file");
70      goto err2;
71    }
72   
73    refObj.initRef(embRef.num, embRef.gen);
74    refObj.fetch(xref, &strObj);
75    refObj.free();
76    strObj.streamReset();
77    while ((c = strObj.streamGetChar()) != EOF) {
78      fputc(c, tmpFile);
79    }
80    strObj.streamClose();
81    strObj.free();
82    fclose(tmpFile);
83    fileName = tmpFileName;
84   
85  } else if (!(fileName = gfxFont->getExtFontFile())) {
86    // look for a display font mapping or a substitute font
87    dfp = NULL;
88    if (gfxFont->getName()) {
89      dfp = globalParams->getDisplayFont(gfxFont);
90    }
91    if (!dfp) {
92      error(-1, "Couldn't find a font for '%s'",
93            gfxFont->getName() ? gfxFont->getName()->getCString()
94            : "(unnamed)");
95      goto err2;
96    }
97    switch (dfp->kind) {
98    case displayFontT1:
99      fileName = dfp->t1.fileName;
100      fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1;
101      break;
102    case displayFontTT:
103      fileName = dfp->tt.fileName;
104      fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
105      break;
106    }
107  }
108
109  switch (fontType) {
110  case fontType1:
111  case fontType1C:
112    if (FT_New_Face(lib, fileName->getCString(), 0, &face)) {
113      error(-1, "could not create type1 face");
114      goto err2;
115    }
116   
117    enc = ((Gfx8BitFont *)gfxFont)->getEncoding();
118   
119    codeToGID = (Gushort *)gmallocn(256, sizeof(int));
120    codeToGIDLen = 256;
121    for (i = 0; i < 256; ++i) {
122      codeToGID[i] = 0;
123      if ((name = enc[i])) {
124        codeToGID[i] = (Gushort)FT_Get_Name_Index(face, name);
125      }
126    }
127    break;
128   
129  case fontCIDType2:
130    codeToGID = NULL;
131    n = 0;
132    if (dfp) {
133      // create a CID-to-GID mapping, via Unicode
134      if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) {
135        if ((ff = FoFiTrueType::load(fileName->getCString()))) {
136          // look for a Unicode cmap
137          for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) {
138            if ((ff->getCmapPlatform(cmap) == 3 &&
139                 ff->getCmapEncoding(cmap) == 1) ||
140                 ff->getCmapPlatform(cmap) == 0) {
141              break;
142            }
143          }
144          if (cmap < ff->getNumCmaps()) {
145            // map CID -> Unicode -> GID
146            n = ctu->getLength();
147            codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
148            for (code = 0; code < n; ++code) {
149              if (ctu->mapToUnicode(code, uBuf, 8) > 0) {
150                  codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]);
151              } else {
152                codeToGID[code] = 0;
153              }
154            }
155          }
156          delete ff;
157        }
158        ctu->decRefCnt();
159      } else {
160        error(-1, "Couldn't find a mapping to Unicode for font '%s'",
161              gfxFont->getName() ? gfxFont->getName()->getCString()
162                        : "(unnamed)");
163      }
164    } else {
165      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
166        n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
167        codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
168        memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
169               n * sizeof(Gushort));
170      }
171    }
172    codeToGIDLen = n;
173    /* Fall through */
174  case fontTrueType:
175    if (!(ff = FoFiTrueType::load(fileName->getCString()))) {
176      error(-1, "failed to load truetype font\n");
177      goto err2;
178    }
179    /* This might be set already for the CIDType2 case */
180    if (fontType == fontTrueType) {
181      codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
182      codeToGIDLen = 256;
183    }
184    if (!openTempFile(&tmpFileName2, &tmpFile, "wb", NULL)) {
185      delete ff;
186      error(-1, "failed to open truetype tempfile\n");
187      goto err2;
188    }
189    ff->writeTTF(&fileWrite, tmpFile);
190    fclose(tmpFile);
191    delete ff;
192
193    if (FT_New_Face(lib, tmpFileName2->getCString(), 0, &face)) {
194      error(-1, "could not create truetype face\n");
195      goto err2;
196    }
197    unlink (tmpFileName2->getCString());
198    delete tmpFileName2;
199    break;
200   
201  case fontCIDType0:
202  case fontCIDType0C:
203
204    codeToGID = NULL;
205    codeToGIDLen = 0;
206
207    if (!useCIDs)
208    {
209      if ((ff1c = FoFiType1C::load(fileName->getCString()))) {
210        codeToGID = ff1c->getCIDToGIDMap(&codeToGIDLen);
211        delete ff1c;
212      }
213    }
214
215    if (FT_New_Face(lib, fileName->getCString(), 0, &face)) {
216      gfree(codeToGID);
217      codeToGID = NULL;
218      error(-1, "could not create cid face\n");
219      goto err2;
220    }
221    break;
222   
223  default:
224    printf ("font type not handled\n");
225    goto err2;
226    break;
227  }
228
229  // delete the (temporary) font file -- with Unix hard link
230  // semantics, this will remove the last link; otherwise it will
231  // return an error, leaving the file to be deleted later
232  if (fileName == tmpFileName) {
233    unlink (fileName->getCString());
234    delete tmpFileName;
235  }
236
237  cairo_font_face = cairo_ft_font_face_create_for_ft_face (face,
238                                                           FT_LOAD_NO_HINTING |
239                                                           FT_LOAD_NO_BITMAP);
240  if (cairo_font_face == NULL) {
241    error(-1, "could not create cairo font\n");
242    goto err2; /* this doesn't do anything, but it looks like we're
243                * handling the error */
244  }
245
246  cairo_font_face_set_user_data (cairo_font_face, 
247                                 &cairo_font_face_key,
248                                 this,
249                                 cairo_font_face_destroy);
250
251  return;
252 err2:
253  /* hmm? */
254  printf ("some font thing failed\n");
255}
256
257CairoFont::~CairoFont() {
258  FT_Done_Face (face);
259  gfree(codeToGID);
260}
261
262GBool
263CairoFont::matches(Ref &other) {
264  return (other.num == ref.num && other.gen == ref.gen);
265}
266
267cairo_font_face_t *
268CairoFont::getFontFace(void) {
269  return cairo_font_face;
270}
271
272unsigned long
273CairoFont::getGlyph(CharCode code,
274                    Unicode *u, int uLen) {
275  FT_UInt gid;
276
277  if (codeToGID && code < codeToGIDLen) {
278    gid = (FT_UInt)codeToGID[code];
279  } else {
280    gid = (FT_UInt)code;
281  }
282  return gid;
283}
284
285//------------------------------------------------------------------------
286// CairoFontEngine
287//------------------------------------------------------------------------
288
289CairoFontEngine::CairoFontEngine(FT_Library libA) {
290  int i;
291
292  lib = libA;
293  for (i = 0; i < cairoFontCacheSize; ++i) {
294    fontCache[i] = NULL;
295  }
296 
297  FT_Int major, minor, patch;
298  // as of FT 2.1.8, CID fonts are indexed by CID instead of GID
299  FT_Library_Version(lib, &major, &minor, &patch);
300  useCIDs = major > 2 ||
301            (major == 2 && (minor > 1 || (minor == 1 && patch > 7)));
302}
303
304CairoFontEngine::~CairoFontEngine() {
305  int i;
306 
307  for (i = 0; i < cairoFontCacheSize; ++i) {
308    if (fontCache[i])
309      delete fontCache[i];
310  }
311}
312
313CairoFont *
314CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref) {
315  int i, j;
316  Ref ref;
317  CairoFont *font;
318  GfxFontType fontType;
319 
320  fontType = gfxFont->getType();
321  if (fontType == fontType3) {
322    /* Need to figure this out later */
323    //    return NULL;
324  }
325
326  ref = *gfxFont->getID();
327
328  for (i = 0; i < cairoFontCacheSize; ++i) {
329    font = fontCache[i];
330    if (font && font->matches(ref)) {
331      for (j = i; j > 0; --j) {
332        fontCache[j] = fontCache[j-1];
333      }
334      fontCache[0] = font;
335      return font;
336    }
337  }
338 
339  font = new CairoFont (gfxFont, xref, lib, useCIDs);
340  if (fontCache[cairoFontCacheSize - 1]) {
341    delete fontCache[cairoFontCacheSize - 1];
342  }
343  for (j = cairoFontCacheSize - 1; j > 0; --j) {
344    fontCache[j] = fontCache[j-1];
345  }
346  fontCache[0] = font;
347  return font;
348}
349
Note: See TracBrowser for help on using the repository browser.