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

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

PDF plugin: Poppler library updated to version 0.12.3

File size: 19.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//========================================================================
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    if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) {
493      error(-1, "could not create truetype face\n");
494      goto err2;
495    }
496    break;
497   
498  case fontCIDType0:
499  case fontCIDType0C:
500
501    codeToGID = NULL;
502    codeToGIDLen = 0;
503
504    if (!useCIDs)
505    {
506      if ((ff1c = FoFiType1C::load(fileName->getCString()))) {
507        codeToGID = ff1c->getCIDToGIDMap(&codeToGIDLen);
508        delete ff1c;
509      }
510    }
511
512    if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) {
513      gfree(codeToGID);
514      codeToGID = NULL;
515      error(-1, "could not create cid face\n");
516      goto err2;
517    }
518    break;
519   
520  default:
521    printf ("font type %d not handled\n", (int)fontType);
522    goto err2;
523    break;
524  }
525
526  // delete the (temporary) font file -- with Unix hard link
527  // semantics, this will remove the last link; otherwise it will
528  // return an error, leaving the file to be deleted later
529  if (fileName == tmpFileName) {
530    unlink (fileName->getCString());
531    delete tmpFileName;
532  }
533
534  return new CairoFreeTypeFont(ref,
535                       font_face, face,
536                       codeToGID, codeToGIDLen,
537                       substitute);
538
539 err2:
540  /* hmm? */
541  printf ("some font thing failed\n");
542  return NULL;
543}
544
545//------------------------------------------------------------------------
546// CairoType3Font
547//------------------------------------------------------------------------
548
549static const cairo_user_data_key_t type3_font_key = {0};
550
551typedef struct _type3_font_info {
552  GfxFont *font;
553  XRef *xref;
554  Catalog *catalog;
555  CairoFontEngine *fontEngine;
556  GBool printing;
557} type3_font_info_t;
558
559static void
560_free_type3_font_info(void *closure)
561{
562  type3_font_info_t *info = (type3_font_info_t *) closure;
563
564  info->font->decRefCnt();
565  free (info);
566}
567
568static cairo_status_t
569_render_type3_glyph (cairo_scaled_font_t  *scaled_font,
570                     unsigned long         glyph,
571                     cairo_t              *cr,
572                     cairo_text_extents_t *metrics)
573{
574  Dict *charProcs;
575  Object charProc;
576  CairoOutputDev *output_dev;
577  cairo_matrix_t matrix, invert_y_axis;
578  double *mat;
579  double wx, wy;
580  PDFRectangle box;
581  type3_font_info_t *info;
582  GfxFont *font;
583  Dict *resDict;
584  Gfx *gfx;
585
586  info = (type3_font_info_t *)
587    cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
588                                   &type3_font_key);
589
590  font = info->font;
591  resDict = ((Gfx8BitFont *)font)->getResources();
592  charProcs = ((Gfx8BitFont *)(info->font))->getCharProcs();
593  if (!charProcs)
594    return CAIRO_STATUS_USER_FONT_ERROR;
595
596  if ((int)glyph >= charProcs->getLength())
597    return CAIRO_STATUS_USER_FONT_ERROR;
598
599  mat = font->getFontMatrix();
600  matrix.xx = mat[0];
601  matrix.yx = mat[1];
602  matrix.xy = mat[2];
603  matrix.yy = mat[3];
604  matrix.x0 = mat[4];
605  matrix.y0 = mat[5];
606  cairo_matrix_init_scale (&invert_y_axis, 1, -1);
607  cairo_matrix_multiply (&matrix, &matrix, &invert_y_axis);
608  cairo_transform (cr, &matrix);
609
610  output_dev = new CairoOutputDev();
611  output_dev->setCairo(cr);
612  output_dev->setPrinting(info->printing);
613
614  mat = font->getFontBBox();
615  box.x1 = mat[0];
616  box.y1 = mat[1];
617  box.x2 = mat[2];
618  box.y2 = mat[3];
619  gfx = new Gfx(info->xref, output_dev, resDict, info->catalog, &box, NULL);
620  output_dev->startDoc(info->xref, info->catalog, info->fontEngine);
621  output_dev->startPage (1, gfx->getState());
622  output_dev->setInType3Char(gTrue);
623  gfx->display(charProcs->getVal(glyph, &charProc));
624
625  output_dev->getType3GlyphWidth (&wx, &wy);
626  cairo_matrix_transform_distance (&matrix, &wx, &wy);
627  metrics->x_advance = wx;
628  metrics->y_advance = wy;
629  if (output_dev->hasType3GlyphBBox()) {
630    double *bbox = output_dev->getType3GlyphBBox();
631
632    cairo_matrix_transform_point (&matrix, &bbox[0], &bbox[1]);
633    cairo_matrix_transform_point (&matrix, &bbox[2], &bbox[3]);
634    metrics->x_bearing = bbox[0];
635    metrics->y_bearing = bbox[1];
636    metrics->width = bbox[2] - bbox[0];
637    metrics->height = bbox[3] - bbox[1];
638  }
639
640  delete gfx;
641  delete output_dev;
642  charProc.free();
643
644  return CAIRO_STATUS_SUCCESS;
645}
646
647
648CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, XRef *xref,
649                                       Catalog *catalog, CairoFontEngine *fontEngine,
650                                       GBool printing) {
651  Object refObj, strObj;
652  type3_font_info_t *info;
653  cairo_font_face_t *font_face;
654  Ref ref;
655  Gushort *codeToGID;
656  int codeToGIDLen;
657  int i, j;
658  char **enc;
659  Dict *charProcs;
660  char *name;
661
662  charProcs = ((Gfx8BitFont *)gfxFont)->getCharProcs();
663  info = (type3_font_info_t *) malloc(sizeof(*info));
664  ref = *gfxFont->getID();
665  font_face = cairo_user_font_face_create();
666  cairo_user_font_face_set_render_glyph_func (font_face, _render_type3_glyph);
667  gfxFont->incRefCnt();
668  info->font = gfxFont;
669  info->xref = xref;
670  info->catalog = catalog;
671  info->fontEngine = fontEngine;
672  info->printing = printing;
673
674  cairo_font_face_set_user_data (font_face, &type3_font_key, (void *) info, _free_type3_font_info);
675
676  enc = ((Gfx8BitFont *)gfxFont)->getEncoding();
677  codeToGID = (Gushort *)gmallocn(256, sizeof(int));
678  codeToGIDLen = 256;
679  for (i = 0; i < 256; ++i) {
680    codeToGID[i] = 0;
681    if ((name = enc[i])) {
682      for (j = 0; j < charProcs->getLength(); j++) {
683        if (strcmp(name, charProcs->getKey(j)) == 0) {
684          codeToGID[i] = (Gushort) j;
685        }
686      }
687    }
688  }
689
690  return new CairoType3Font(ref, xref, catalog, font_face, codeToGID, codeToGIDLen, printing);
691}
692
693CairoType3Font::CairoType3Font(Ref ref,
694                               XRef *xref,
695                               Catalog *cat,
696                               cairo_font_face_t *cairo_font_face,
697                               Gushort *codeToGID,
698                               int codeToGIDLen,
699                               GBool printing) : CairoFont(ref,
700                                                           cairo_font_face,
701                                                           codeToGID,
702                                                           codeToGIDLen,
703                                                           gFalse,
704                                                           printing),
705                                                 xref(xref),
706                                                 catalog(catalog) { }
707
708CairoType3Font::~CairoType3Font() { }
709
710GBool
711CairoType3Font::matches(Ref &other, GBool printingA) {
712  return (other.num == ref.num && other.gen == ref.gen && printing == printingA);
713}
714
715
716//------------------------------------------------------------------------
717// CairoFontEngine
718//------------------------------------------------------------------------
719
720CairoFontEngine::CairoFontEngine(FT_Library libA) {
721  int i;
722
723  lib = libA;
724  for (i = 0; i < cairoFontCacheSize; ++i) {
725    fontCache[i] = NULL;
726  }
727 
728  FT_Int major, minor, patch;
729  // as of FT 2.1.8, CID fonts are indexed by CID instead of GID
730  FT_Library_Version(lib, &major, &minor, &patch);
731  useCIDs = major > 2 ||
732            (major == 2 && (minor > 1 || (minor == 1 && patch > 7)));
733}
734
735CairoFontEngine::~CairoFontEngine() {
736  int i;
737 
738  for (i = 0; i < cairoFontCacheSize; ++i) {
739    if (fontCache[i])
740      delete fontCache[i];
741  }
742}
743
744CairoFont *
745CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref, Catalog *catalog, GBool printing) {
746  int i, j;
747  Ref ref;
748  CairoFont *font;
749  GfxFontType fontType;
750 
751  ref = *gfxFont->getID();
752
753  for (i = 0; i < cairoFontCacheSize; ++i) {
754    font = fontCache[i];
755    if (font && font->matches(ref, printing)) {
756      for (j = i; j > 0; --j) {
757        fontCache[j] = fontCache[j-1];
758      }
759      fontCache[0] = font;
760      return font;
761    }
762  }
763 
764  fontType = gfxFont->getType();
765  if (fontType == fontType3)
766    font = CairoType3Font::create (gfxFont, xref, catalog, this, printing);
767  else
768    font = CairoFreeTypeFont::create (gfxFont, xref, lib, useCIDs);
769
770  //XXX: if font is null should we still insert it into the cache?
771  if (fontCache[cairoFontCacheSize - 1]) {
772    delete fontCache[cairoFontCacheSize - 1];
773  }
774  for (j = cairoFontCacheSize - 1; j > 0; --j) {
775    fontCache[j] = fontCache[j-1];
776  }
777  fontCache[0] = font;
778  return font;
779}
Note: See TracBrowser for help on using the repository browser.