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

Last change on this file since 290 was 290, checked in by rbri, 11 years ago

PDF plugin: Poppler library updated to version 0.12.4

File size: 19.9 KB
Line 
1//========================================================================
2//
3// CairoFontEngine.cc
4//
5// Copyright 2003 Glyph & Cog, LLC
6// Copyright 2004 Red Hat, Inc
7//
8//========================================================================
9
10//========================================================================
11//
12// Modified under the Poppler project - http://poppler.freedesktop.org
13//
14// All changes made under the Poppler project to this file are licensed
15// under GPL version 2 or later
16//
17// Copyright (C) 2005-2007 Jeff Muizelaar <jeff@infidigm.net>
18// Copyright (C) 2005, 2006 Kristian HÞgsberg <krh@redhat.com>
19// Copyright (C) 2005 Martin Kretzschmar <martink@gnome.org>
20// Copyright (C) 2005, 2009 Albert Astals Cid <aacid@kde.org>
21// Copyright (C) 2006, 2007 Carlos Garcia Campos <carlosgc@gnome.org>
22// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
23// Copyright (C) 2008, 2009 Chris Wilson <chris@chris-wilson.co.uk>
24// Copyright (C) 2008 Adrian Johnson <ajohnson@redneon.com>
25// Copyright (C) 2009 Darren Kenny <darren.kenny@sun.com>
26//
27// To see a description of the changes please see the Changelog file that
28// came with your tarball or type make ChangeLog if you are building from git
29//
30//========================================================================
31
32#include <config.h>
33
34#include "config.h"
35#include <string.h>
36#include "CairoFontEngine.h"
37#include "CairoOutputDev.h"
38#include "CharCodeToUnicode.h"
39#include "GlobalParams.h"
40#include <fofi/FoFiTrueType.h>
41#include <fofi/FoFiType1C.h>
42#include "goo/gfile.h"
43#include "Error.h"
44#include "XRef.h"
45#include "Gfx.h"
46#include "Page.h"
47
48#if HAVE_FCNTL_H && HAVE_SYS_MMAN_H && HAVE_SYS_STAT_H
49#include <fcntl.h>
50#include <sys/stat.h>
51#include <sys/mman.h>
52#define CAN_CHECK_OPEN_FACES 1
53#endif
54
55#ifdef USE_GCC_PRAGMAS
56#pragma implementation
57#endif
58
59
60//------------------------------------------------------------------------
61// CairoFont
62//------------------------------------------------------------------------
63
64CairoFont::CairoFont(Ref ref,
65                     cairo_font_face_t *cairo_font_face,
66                     Gushort *codeToGID,
67                     int codeToGIDLen,
68                     GBool substitute,
69                     GBool printing) : ref(ref),
70                                       cairo_font_face(cairo_font_face),
71                                       codeToGID(codeToGID),
72                                       codeToGIDLen(codeToGIDLen),
73                                       substitute(substitute),
74                                       printing(printing)      { }
75
76CairoFont::~CairoFont() {
77  cairo_font_face_destroy (cairo_font_face);
78  gfree(codeToGID);
79}
80
81GBool
82CairoFont::matches(Ref &other, GBool printingA) {
83  return (other.num == ref.num && other.gen == ref.gen);
84}
85
86cairo_font_face_t *
87CairoFont::getFontFace(void) {
88  return cairo_font_face;
89}
90
91unsigned long
92CairoFont::getGlyph(CharCode code,
93                    Unicode *u, int uLen) {
94  FT_UInt gid;
95
96  if (codeToGID && code < codeToGIDLen) {
97    gid = (FT_UInt)codeToGID[code];
98  } else {
99    gid = (FT_UInt)code;
100  }
101  return gid;
102}
103
104double
105CairoFont::getSubstitutionCorrection(GfxFont *gfxFont)
106{
107  double w1, w2,w3;
108  CharCode code;
109  char *name;
110
111  // for substituted fonts: adjust the font matrix -- compare the
112  // width of 'm' in the original font and the substituted font
113  if (isSubstitute() && !gfxFont->isCIDFont()) {
114    for (code = 0; code < 256; ++code) {
115      if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
116          name[0] == 'm' && name[1] == '\0') {
117        break;
118      }
119    }
120    if (code < 256) {
121      w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
122      {
123        cairo_matrix_t m;
124        cairo_matrix_init_identity(&m);
125        cairo_font_options_t *options = cairo_font_options_create();
126        cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
127        cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_OFF);
128        cairo_scaled_font_t *scaled_font = cairo_scaled_font_create(cairo_font_face, &m, &m, options);
129
130        cairo_text_extents_t extents;
131        cairo_scaled_font_text_extents(scaled_font, "m", &extents);
132
133        cairo_scaled_font_destroy(scaled_font);
134        cairo_font_options_destroy(options);
135        w3 = extents.width;
136        w2 = extents.x_advance;
137      }
138      if (!gfxFont->isSymbolic()) {
139        // if real font is substantially narrower than substituted
140        // font, reduce the font size accordingly
141        if (w1 > 0.01 && w1 < 0.9 * w2) {
142          w1 /= w2;
143          return w1;
144        }
145      }
146    }
147  }
148  return 1.0;
149}
150
151//------------------------------------------------------------------------
152// CairoFreeTypeFont
153//------------------------------------------------------------------------
154
155static cairo_user_data_key_t _ft_cairo_key;
156
157static void
158_ft_done_face_uncached (void *closure)
159{
160    FT_Face face = (FT_Face) closure;
161    FT_Done_Face (face);
162}
163
164static GBool
165_ft_new_face_uncached (FT_Library lib,
166                       const char *filename,
167                       FT_Face *face_out,
168                       cairo_font_face_t **font_face_out)
169{
170  FT_Face face;
171  cairo_font_face_t *font_face;
172
173  if (FT_New_Face (lib, filename, 0, &face))
174    return gFalse;
175
176  font_face = cairo_ft_font_face_create_for_ft_face (face,
177                                                          FT_LOAD_NO_HINTING |
178                                                          FT_LOAD_NO_BITMAP);
179  if (cairo_font_face_set_user_data (font_face,
180                                     &_ft_cairo_key,
181                                     face,
182                                     _ft_done_face_uncached))
183  {
184    _ft_done_face_uncached (face);
185    cairo_font_face_destroy (font_face);
186    return gFalse;
187  }
188
189  *face_out = face;
190  *font_face_out = font_face;
191  return gTrue;
192}
193
194#if CAN_CHECK_OPEN_FACES
195static struct _ft_face_data {
196  struct _ft_face_data *prev, *next, **head;
197
198  int fd;
199  unsigned long hash;
200  size_t size;
201  unsigned char *bytes;
202
203  FT_Library lib;
204  FT_Face face;
205  cairo_font_face_t *font_face;
206} *_ft_open_faces;
207
208static unsigned long
209_djb_hash (const unsigned char *bytes, size_t len)
210{
211  unsigned long hash = 5381;
212  while (len--) {
213    unsigned char c = *bytes++;
214    hash *= 33;
215    hash ^= c;
216  }
217  return hash;
218}
219
220static GBool
221_ft_face_data_equal (struct _ft_face_data *a, struct _ft_face_data *b)
222{
223  if (a->lib != b->lib)
224    return gFalse;
225  if (a->size != b->size)
226    return gFalse;
227  if (a->hash != b->hash)
228    return gFalse;
229
230  return memcmp (a->bytes, b->bytes, a->size) == 0;
231}
232
233static void
234_ft_done_face (void *closure)
235{
236  struct _ft_face_data *data = (struct _ft_face_data *) closure;
237
238  if (data->next)
239    data->next->prev = data->prev;
240  if (data->prev)
241    data->prev->next = data->next;
242  else
243    _ft_open_faces = data->next;
244
245#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
246  munmap ((char*)data->bytes, data->size);
247#else
248  munmap (data->bytes, data->size);
249#endif
250  close (data->fd);
251
252  FT_Done_Face (data->face);
253  gfree (data);
254}
255
256static GBool
257_ft_new_face (FT_Library lib,
258              const char *filename,
259              FT_Face *face_out,
260              cairo_font_face_t **font_face_out)
261{
262  struct _ft_face_data *l;
263  struct stat st;
264  struct _ft_face_data tmpl;
265
266  /* if we fail to mmap the file, just pass it to FreeType instead */
267  tmpl.fd = open (filename, O_RDONLY);
268  if (tmpl.fd == -1)
269    return _ft_new_face_uncached (lib, filename, face_out, font_face_out);
270
271  if (fstat (tmpl.fd, &st) == -1) {
272    close (tmpl.fd);
273    return _ft_new_face_uncached (lib, filename, face_out, font_face_out);
274  }
275
276  tmpl.bytes = (unsigned char *) mmap (NULL, st.st_size,
277                                       PROT_READ, MAP_PRIVATE,
278                                       tmpl.fd, 0);
279  if (tmpl.bytes == MAP_FAILED) {
280    close (tmpl.fd);
281    return _ft_new_face_uncached (lib, filename, face_out, font_face_out);
282  }
283
284  /* check to see if this is a duplicate of any of the currently open fonts */
285  tmpl.lib = lib;
286  tmpl.size = st.st_size;
287  tmpl.hash = _djb_hash (tmpl.bytes, tmpl.size);
288
289  for (l = _ft_open_faces; l; l = l->next) {
290    if (_ft_face_data_equal (l, &tmpl)) {
291#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
292      munmap ((char*)tmpl.bytes, tmpl.size);
293#else
294      munmap (tmpl.bytes, tmpl.size);
295#endif
296      close (tmpl.fd);
297      *face_out = l->face;
298      *font_face_out = cairo_font_face_reference (l->font_face);
299      return gTrue;
300    }
301  }
302
303  /* not a dup, open and insert into list */
304  if (FT_New_Memory_Face (lib,
305                          (FT_Byte *) tmpl.bytes, tmpl.size,
306                          0, &tmpl.face))
307  {
308#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
309    munmap ((char*)tmpl.bytes, tmpl.size);
310#else
311    munmap (tmpl.bytes, tmpl.size);
312#endif
313
314    close (tmpl.fd);
315    return gFalse;
316  }
317
318  l = (struct _ft_face_data *) gmallocn (1, sizeof (struct _ft_face_data));
319  *l = tmpl;
320  l->prev = NULL;
321  l->next = _ft_open_faces;
322  if (_ft_open_faces)
323    _ft_open_faces->prev = l;
324  _ft_open_faces = l;
325
326  l->font_face = cairo_ft_font_face_create_for_ft_face (tmpl.face,
327                                                          FT_LOAD_NO_HINTING |
328                                                          FT_LOAD_NO_BITMAP);
329  if (cairo_font_face_set_user_data (l->font_face,
330                                     &_ft_cairo_key,
331                                     l,
332                                     _ft_done_face))
333  {
334    cairo_font_face_destroy (l->font_face);
335    _ft_done_face (l);
336    return gFalse;
337  }
338
339  *face_out = l->face;
340  *font_face_out = l->font_face;
341  return gTrue;
342}
343#else
344#define _ft_new_face _ft_new_face_uncached
345#endif
346
347CairoFreeTypeFont::CairoFreeTypeFont(Ref ref,
348                                     cairo_font_face_t *cairo_font_face,
349                                     FT_Face face,
350                                     Gushort *codeToGID,
351                                     int codeToGIDLen,
352                                     GBool substitute) : CairoFont(ref,
353                                                                   cairo_font_face,
354                                                                   codeToGID,
355                                                                   codeToGIDLen,
356                                                                   substitute,
357                                                                   gTrue),
358                                                         face(face) { }
359
360CairoFreeTypeFont::~CairoFreeTypeFont() { }
361
362CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
363                                             FT_Library lib, GBool useCIDs) {
364  Ref embRef;
365  Object refObj, strObj;
366  GooString *tmpFileName, *fileName;
367  DisplayFontParam *dfp;
368  FILE *tmpFile;
369  int c, i, n;
370  GfxFontType fontType;
371  char **enc;
372  char *name;
373  FoFiTrueType *ff;
374  FoFiType1C *ff1c;
375  Ref ref;
376  FT_Face face;
377  cairo_font_face_t *font_face;
378
379  Gushort *codeToGID;
380  int codeToGIDLen;
381 
382  dfp = NULL;
383  codeToGID = NULL;
384  codeToGIDLen = 0;
385
386  GBool substitute = gFalse;
387 
388  ref = *gfxFont->getID();
389  fontType = gfxFont->getType();
390
391  tmpFileName = NULL;
392
393  if (gfxFont->getEmbeddedFontID(&embRef)) {
394    if (!openTempFile(&tmpFileName, &tmpFile, "wb")) {
395      error(-1, "Couldn't create temporary font file");
396      goto err2;
397    }
398   
399    refObj.initRef(embRef.num, embRef.gen);
400    refObj.fetch(xref, &strObj);
401    refObj.free();
402    if (!strObj.isStream()) {
403      error(-1, "Embedded font object is wrong type");
404      strObj.free();
405      fclose(tmpFile);
406      goto err2;
407    }
408    strObj.streamReset();
409    while ((c = strObj.streamGetChar()) != EOF) {
410      fputc(c, tmpFile);
411    }
412    strObj.streamClose();
413    strObj.free();
414    fclose(tmpFile);
415    fileName = tmpFileName;
416   
417  } else if (!(fileName = gfxFont->getExtFontFile())) {
418    // look for a display font mapping or a substitute font
419    dfp = NULL;
420    if (gfxFont->getName()) {
421      dfp = globalParams->getDisplayFont(gfxFont);
422    }
423    if (!dfp) {
424      error(-1, "Couldn't find a font for '%s'",
425            gfxFont->getName() ? gfxFont->getName()->getCString()
426            : "(unnamed)");
427      goto err2;
428    }
429    switch (dfp->kind) {
430    case displayFontT1:
431      fileName = dfp->t1.fileName;
432      fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1;
433      break;
434    case displayFontTT:
435      fileName = dfp->tt.fileName;
436      fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
437      break;
438    }
439    substitute = gTrue;
440  }
441
442  switch (fontType) {
443  case fontType1:
444  case fontType1C:
445  case fontType1COT:
446    if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) {
447      error(-1, "could not create type1 face");
448      goto err2;
449    }
450   
451    enc = ((Gfx8BitFont *)gfxFont)->getEncoding();
452   
453    codeToGID = (Gushort *)gmallocn(256, sizeof(int));
454    codeToGIDLen = 256;
455    for (i = 0; i < 256; ++i) {
456      codeToGID[i] = 0;
457      if ((name = enc[i])) {
458        codeToGID[i] = (Gushort)FT_Get_Name_Index(face, name);
459      }
460    }
461    break;
462   
463  case fontCIDType2:
464    codeToGID = NULL;
465    n = 0;
466    if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
467      n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
468      if (n) {
469        codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
470        memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
471                n * sizeof(Gushort));
472      }
473    } else {
474      ff = FoFiTrueType::load(fileName->getCString());
475      if (! ff)
476        goto err2;
477      codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
478      delete ff;
479    }
480    codeToGIDLen = n;
481    /* Fall through */
482  case fontTrueType:
483    if (!(ff = FoFiTrueType::load(fileName->getCString()))) {
484      error(-1, "failed to load truetype font\n");
485      goto err2;
486    }
487    /* This might be set already for the CIDType2 case */
488    if (fontType == fontTrueType) {
489      codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
490      codeToGIDLen = 256;
491    }
492    delete ff;
493    if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) {
494      error(-1, "could not create truetype face\n");
495      goto err2;
496    }
497    break;
498   
499  case fontCIDType0:
500  case fontCIDType0C:
501
502    codeToGID = NULL;
503    codeToGIDLen = 0;
504
505    if (!useCIDs)
506    {
507      if ((ff1c = FoFiType1C::load(fileName->getCString()))) {
508        codeToGID = ff1c->getCIDToGIDMap(&codeToGIDLen);
509        delete ff1c;
510      }
511    }
512
513    if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) {
514      gfree(codeToGID);
515      codeToGID = NULL;
516      error(-1, "could not create cid face\n");
517      goto err2;
518    }
519    break;
520   
521  default:
522    printf ("font type %d not handled\n", (int)fontType);
523    goto err2;
524    break;
525  }
526
527  // delete the (temporary) font file -- with Unix hard link
528  // semantics, this will remove the last link; otherwise it will
529  // return an error, leaving the file to be deleted later
530  if (fileName == tmpFileName) {
531    unlink (fileName->getCString());
532    delete tmpFileName;
533  }
534
535  return new CairoFreeTypeFont(ref,
536                       font_face, face,
537                       codeToGID, codeToGIDLen,
538                       substitute);
539
540 err2:
541  /* hmm? */
542  printf ("some font thing failed\n");
543  return NULL;
544}
545
546//------------------------------------------------------------------------
547// CairoType3Font
548//------------------------------------------------------------------------
549
550static const cairo_user_data_key_t type3_font_key = {0};
551
552typedef struct _type3_font_info {
553  GfxFont *font;
554  XRef *xref;
555  Catalog *catalog;
556  CairoFontEngine *fontEngine;
557  GBool printing;
558} type3_font_info_t;
559
560static void
561_free_type3_font_info(void *closure)
562{
563  type3_font_info_t *info = (type3_font_info_t *) closure;
564
565  info->font->decRefCnt();
566  free (info);
567}
568
569static cairo_status_t
570_render_type3_glyph (cairo_scaled_font_t  *scaled_font,
571                     unsigned long         glyph,
572                     cairo_t              *cr,
573                     cairo_text_extents_t *metrics)
574{
575  Dict *charProcs;
576  Object charProc;
577  CairoOutputDev *output_dev;
578  cairo_matrix_t matrix, invert_y_axis;
579  double *mat;
580  double wx, wy;
581  PDFRectangle box;
582  type3_font_info_t *info;
583  GfxFont *font;
584  Dict *resDict;
585  Gfx *gfx;
586
587  info = (type3_font_info_t *)
588    cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
589                                   &type3_font_key);
590
591  font = info->font;
592  resDict = ((Gfx8BitFont *)font)->getResources();
593  charProcs = ((Gfx8BitFont *)(info->font))->getCharProcs();
594  if (!charProcs)
595    return CAIRO_STATUS_USER_FONT_ERROR;
596
597  if ((int)glyph >= charProcs->getLength())
598    return CAIRO_STATUS_USER_FONT_ERROR;
599
600  mat = font->getFontMatrix();
601  matrix.xx = mat[0];
602  matrix.yx = mat[1];
603  matrix.xy = mat[2];
604  matrix.yy = mat[3];
605  matrix.x0 = mat[4];
606  matrix.y0 = mat[5];
607  cairo_matrix_init_scale (&invert_y_axis, 1, -1);
608  cairo_matrix_multiply (&matrix, &matrix, &invert_y_axis);
609  cairo_transform (cr, &matrix);
610
611  output_dev = new CairoOutputDev();
612  output_dev->setCairo(cr);
613  output_dev->setPrinting(info->printing);
614
615  mat = font->getFontBBox();
616  box.x1 = mat[0];
617  box.y1 = mat[1];
618  box.x2 = mat[2];
619  box.y2 = mat[3];
620  gfx = new Gfx(info->xref, output_dev, resDict, info->catalog, &box, NULL);
621  output_dev->startDoc(info->xref, info->catalog, info->fontEngine);
622  output_dev->startPage (1, gfx->getState());
623  output_dev->setInType3Char(gTrue);
624  gfx->display(charProcs->getVal(glyph, &charProc));
625
626  output_dev->getType3GlyphWidth (&wx, &wy);
627  cairo_matrix_transform_distance (&matrix, &wx, &wy);
628  metrics->x_advance = wx;
629  metrics->y_advance = wy;
630  if (output_dev->hasType3GlyphBBox()) {
631    double *bbox = output_dev->getType3GlyphBBox();
632
633    cairo_matrix_transform_point (&matrix, &bbox[0], &bbox[1]);
634    cairo_matrix_transform_point (&matrix, &bbox[2], &bbox[3]);
635    metrics->x_bearing = bbox[0];
636    metrics->y_bearing = bbox[1];
637    metrics->width = bbox[2] - bbox[0];
638    metrics->height = bbox[3] - bbox[1];
639  }
640
641  delete gfx;
642  delete output_dev;
643  charProc.free();
644
645  return CAIRO_STATUS_SUCCESS;
646}
647
648
649CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, XRef *xref,
650                                       Catalog *catalog, CairoFontEngine *fontEngine,
651                                       GBool printing) {
652  Object refObj, strObj;
653  type3_font_info_t *info;
654  cairo_font_face_t *font_face;
655  Ref ref;
656  Gushort *codeToGID;
657  int codeToGIDLen;
658  int i, j;
659  char **enc;
660  Dict *charProcs;
661  char *name;
662
663  charProcs = ((Gfx8BitFont *)gfxFont)->getCharProcs();
664  info = (type3_font_info_t *) malloc(sizeof(*info));
665  ref = *gfxFont->getID();
666  font_face = cairo_user_font_face_create();
667  cairo_user_font_face_set_render_glyph_func (font_face, _render_type3_glyph);
668  gfxFont->incRefCnt();
669  info->font = gfxFont;
670  info->xref = xref;
671  info->catalog = catalog;
672  info->fontEngine = fontEngine;
673  info->printing = printing;
674
675  cairo_font_face_set_user_data (font_face, &type3_font_key, (void *) info, _free_type3_font_info);
676
677  enc = ((Gfx8BitFont *)gfxFont)->getEncoding();
678  codeToGID = (Gushort *)gmallocn(256, sizeof(int));
679  codeToGIDLen = 256;
680  for (i = 0; i < 256; ++i) {
681    codeToGID[i] = 0;
682    if ((name = enc[i])) {
683      for (j = 0; j < charProcs->getLength(); j++) {
684        if (strcmp(name, charProcs->getKey(j)) == 0) {
685          codeToGID[i] = (Gushort) j;
686        }
687      }
688    }
689  }
690
691  return new CairoType3Font(ref, xref, catalog, font_face, codeToGID, codeToGIDLen, printing);
692}
693
694CairoType3Font::CairoType3Font(Ref ref,
695                               XRef *xref,
696                               Catalog *cat,
697                               cairo_font_face_t *cairo_font_face,
698                               Gushort *codeToGID,
699                               int codeToGIDLen,
700                               GBool printing) : CairoFont(ref,
701                                                           cairo_font_face,
702                                                           codeToGID,
703                                                           codeToGIDLen,
704                                                           gFalse,
705                                                           printing),
706                                                 xref(xref),
707                                                 catalog(catalog) { }
708
709CairoType3Font::~CairoType3Font() { }
710
711GBool
712CairoType3Font::matches(Ref &other, GBool printingA) {
713  return (other.num == ref.num && other.gen == ref.gen && printing == printingA);
714}
715
716
717//------------------------------------------------------------------------
718// CairoFontEngine
719//------------------------------------------------------------------------
720
721CairoFontEngine::CairoFontEngine(FT_Library libA) {
722  int i;
723
724  lib = libA;
725  for (i = 0; i < cairoFontCacheSize; ++i) {
726    fontCache[i] = NULL;
727  }
728 
729  FT_Int major, minor, patch;
730  // as of FT 2.1.8, CID fonts are indexed by CID instead of GID
731  FT_Library_Version(lib, &major, &minor, &patch);
732  useCIDs = major > 2 ||
733            (major == 2 && (minor > 1 || (minor == 1 && patch > 7)));
734}
735
736CairoFontEngine::~CairoFontEngine() {
737  int i;
738 
739  for (i = 0; i < cairoFontCacheSize; ++i) {
740    if (fontCache[i])
741      delete fontCache[i];
742  }
743}
744
745CairoFont *
746CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref, Catalog *catalog, GBool printing) {
747  int i, j;
748  Ref ref;
749  CairoFont *font;
750  GfxFontType fontType;
751 
752  ref = *gfxFont->getID();
753
754  for (i = 0; i < cairoFontCacheSize; ++i) {
755    font = fontCache[i];
756    if (font && font->matches(ref, printing)) {
757      for (j = i; j > 0; --j) {
758        fontCache[j] = fontCache[j-1];
759      }
760      fontCache[0] = font;
761      return font;
762    }
763  }
764 
765  fontType = gfxFont->getType();
766  if (fontType == fontType3)
767    font = CairoType3Font::create (gfxFont, xref, catalog, this, printing);
768  else
769    font = CairoFreeTypeFont::create (gfxFont, xref, lib, useCIDs);
770
771  //XXX: if font is null should we still insert it into the cache?
772  if (fontCache[cairoFontCacheSize - 1]) {
773    delete fontCache[cairoFontCacheSize - 1];
774  }
775  for (j = cairoFontCacheSize - 1; j > 0; --j) {
776    fontCache[j] = fontCache[j-1];
777  }
778  fontCache[0] = font;
779  return font;
780}
Note: See TracBrowser for help on using the repository browser.