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

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

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