a patch for ttc fonts with bad index
[luatex.git] / source / libs / poppler / poppler-0.36.0 / poppler / CairoFontEngine.cc
blob1d611b59d3c89b85e9b1a3ccfd1189607de5212f
1 //========================================================================
2 //
3 // CairoFontEngine.cc
4 //
5 // Copyright 2003 Glyph & Cog, LLC
6 // Copyright 2004 Red Hat, Inc
7 //
8 //========================================================================
10 //========================================================================
12 // Modified under the Poppler project - http://poppler.freedesktop.org
14 // All changes made under the Poppler project to this file are licensed
15 // under GPL version 2 or later
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, 2012, 2013, 2015 Albert Astals Cid <aacid@kde.org>
21 // Copyright (C) 2006, 2007, 2010, 2011 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, 2012, 2014 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 // Copyright (C) 2012 Hib Eris <hib@hiberis.nl>
29 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
30 // Copyright (C) 2015 Jason Crain <jason@aquaticape.us>
32 // To see a description of the changes please see the Changelog file that
33 // came with your tarball or type make ChangeLog if you are building from git
35 //========================================================================
37 #include <config.h>
39 #include "config.h"
40 #include <string.h>
41 #include "CairoFontEngine.h"
42 #include "CairoOutputDev.h"
43 #include "GlobalParams.h"
44 #include <fofi/FoFiTrueType.h>
45 #include <fofi/FoFiType1C.h>
46 #include "goo/gfile.h"
47 #include "Error.h"
48 #include "XRef.h"
49 #include "Gfx.h"
50 #include "Page.h"
52 #if HAVE_FCNTL_H && HAVE_SYS_MMAN_H && HAVE_SYS_STAT_H
53 #include <fcntl.h>
54 #include <sys/stat.h>
55 #include <sys/mman.h>
56 #define CAN_CHECK_OPEN_FACES 1
57 #endif
59 #ifdef USE_GCC_PRAGMAS
60 #pragma implementation
61 #endif
63 #if MULTITHREADED
64 # define fontEngineLocker() MutexLocker locker(&mutex)
65 #else
66 # define fontEngineLocker()
67 #endif
69 //------------------------------------------------------------------------
70 // CairoFont
71 //------------------------------------------------------------------------
73 CairoFont::CairoFont(Ref ref,
74 cairo_font_face_t *cairo_font_face,
75 int *codeToGID,
76 Guint codeToGIDLen,
77 GBool substitute,
78 GBool printing) : ref(ref),
79 cairo_font_face(cairo_font_face),
80 codeToGID(codeToGID),
81 codeToGIDLen(codeToGIDLen),
82 substitute(substitute),
83 printing(printing) { }
85 CairoFont::~CairoFont() {
86 cairo_font_face_destroy (cairo_font_face);
87 gfree(codeToGID);
90 GBool
91 CairoFont::matches(Ref &other, GBool printingA) {
92 return (other.num == ref.num && other.gen == ref.gen);
95 cairo_font_face_t *
96 CairoFont::getFontFace(void) {
97 return cairo_font_face;
100 unsigned long
101 CairoFont::getGlyph(CharCode code,
102 Unicode *u, int uLen) {
103 FT_UInt gid;
105 if (codeToGID && code < codeToGIDLen) {
106 gid = (FT_UInt)codeToGID[code];
107 } else {
108 gid = (FT_UInt)code;
110 return gid;
113 double
114 CairoFont::getSubstitutionCorrection(GfxFont *gfxFont)
116 double w1, w2;
117 CharCode code;
118 char *name;
120 // for substituted fonts: adjust the font matrix -- compare the
121 // width of 'm' in the original font and the substituted font
122 if (isSubstitute() && !gfxFont->isCIDFont()) {
123 for (code = 0; code < 256; ++code) {
124 if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
125 name[0] == 'm' && name[1] == '\0') {
126 break;
129 if (code < 256) {
130 w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
132 cairo_matrix_t m;
133 cairo_matrix_init_identity(&m);
134 cairo_font_options_t *options = cairo_font_options_create();
135 cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
136 cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_OFF);
137 cairo_scaled_font_t *scaled_font = cairo_scaled_font_create(cairo_font_face, &m, &m, options);
139 cairo_text_extents_t extents;
140 cairo_scaled_font_text_extents(scaled_font, "m", &extents);
142 cairo_scaled_font_destroy(scaled_font);
143 cairo_font_options_destroy(options);
144 w2 = extents.x_advance;
146 if (!gfxFont->isSymbolic()) {
147 // if real font is substantially narrower than substituted
148 // font, reduce the font size accordingly
149 if (w1 > 0.01 && w1 < 0.9 * w2) {
150 w1 /= w2;
151 return w1;
156 return 1.0;
159 //------------------------------------------------------------------------
160 // CairoFreeTypeFont
161 //------------------------------------------------------------------------
163 static cairo_user_data_key_t _ft_cairo_key;
165 static void
166 _ft_done_face_uncached (void *closure)
168 FT_Face face = (FT_Face) closure;
169 FT_Done_Face (face);
172 static GBool
173 _ft_new_face_uncached (FT_Library lib,
174 const char *filename,
175 char *font_data,
176 int font_data_len,
177 FT_Face *face_out,
178 cairo_font_face_t **font_face_out)
180 FT_Face face;
181 cairo_font_face_t *font_face;
183 if (font_data == NULL) {
184 if (FT_New_Face (lib, filename, 0, &face))
185 return gFalse;
186 } else {
187 if (FT_New_Memory_Face (lib, (unsigned char *)font_data, font_data_len, 0, &face))
188 return gFalse;
191 font_face = cairo_ft_font_face_create_for_ft_face (face,
192 FT_LOAD_NO_HINTING |
193 FT_LOAD_NO_BITMAP);
194 if (cairo_font_face_set_user_data (font_face,
195 &_ft_cairo_key,
196 face,
197 _ft_done_face_uncached))
199 _ft_done_face_uncached (face);
200 cairo_font_face_destroy (font_face);
201 return gFalse;
204 *face_out = face;
205 *font_face_out = font_face;
206 return gTrue;
209 #if CAN_CHECK_OPEN_FACES
210 static struct _ft_face_data {
211 struct _ft_face_data *prev, *next, **head;
213 int fd;
214 unsigned long hash;
215 size_t size;
216 unsigned char *bytes;
218 FT_Library lib;
219 FT_Face face;
220 cairo_font_face_t *font_face;
221 } *_ft_open_faces;
223 static unsigned long
224 _djb_hash (const unsigned char *bytes, size_t len)
226 unsigned long hash = 5381;
227 while (len--) {
228 unsigned char c = *bytes++;
229 hash *= 33;
230 hash ^= c;
232 return hash;
235 static GBool
236 _ft_face_data_equal (struct _ft_face_data *a, struct _ft_face_data *b)
238 if (a->lib != b->lib)
239 return gFalse;
240 if (a->size != b->size)
241 return gFalse;
242 if (a->hash != b->hash)
243 return gFalse;
245 return memcmp (a->bytes, b->bytes, a->size) == 0;
248 static void
249 _ft_done_face (void *closure)
251 struct _ft_face_data *data = (struct _ft_face_data *) closure;
253 if (data->next)
254 data->next->prev = data->prev;
255 if (data->prev)
256 data->prev->next = data->next;
257 else
258 _ft_open_faces = data->next;
260 if (data->fd != -1) {
261 #if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
262 munmap ((char*)data->bytes, data->size);
263 #else
264 munmap (data->bytes, data->size);
265 #endif
266 close (data->fd);
267 } else {
268 gfree (data->bytes);
271 FT_Done_Face (data->face);
272 gfree (data);
275 static GBool
276 _ft_new_face (FT_Library lib,
277 const char *filename,
278 char *font_data,
279 int font_data_len,
280 FT_Face *face_out,
281 cairo_font_face_t **font_face_out)
283 struct _ft_face_data *l;
284 struct stat st;
285 struct _ft_face_data tmpl;
287 tmpl.fd = -1;
289 if (font_data == NULL) {
290 /* if we fail to mmap the file, just pass it to FreeType instead */
291 tmpl.fd = open (filename, O_RDONLY);
292 if (tmpl.fd == -1)
293 return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out);
295 if (fstat (tmpl.fd, &st) == -1) {
296 close (tmpl.fd);
297 return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out);
300 tmpl.bytes = (unsigned char *) mmap (NULL, st.st_size,
301 PROT_READ, MAP_PRIVATE,
302 tmpl.fd, 0);
303 if (tmpl.bytes == MAP_FAILED) {
304 close (tmpl.fd);
305 return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out);
307 tmpl.size = st.st_size;
308 } else {
309 tmpl.bytes = (unsigned char*) font_data;
310 tmpl.size = font_data_len;
313 /* check to see if this is a duplicate of any of the currently open fonts */
314 tmpl.lib = lib;
315 tmpl.hash = _djb_hash (tmpl.bytes, tmpl.size);
317 for (l = _ft_open_faces; l; l = l->next) {
318 if (_ft_face_data_equal (l, &tmpl)) {
319 if (tmpl.fd != -1) {
320 #if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
321 munmap ((char*)tmpl.bytes, tmpl.size);
322 #else
323 munmap (tmpl.bytes, tmpl.size);
324 #endif
325 close (tmpl.fd);
326 } else {
327 gfree (tmpl.bytes);
329 *face_out = l->face;
330 *font_face_out = cairo_font_face_reference (l->font_face);
331 return gTrue;
335 /* not a dup, open and insert into list */
336 if (FT_New_Memory_Face (lib,
337 (FT_Byte *) tmpl.bytes, tmpl.size,
338 0, &tmpl.face))
340 if (tmpl.fd != -1) {
341 #if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
342 munmap ((char*)tmpl.bytes, tmpl.size);
343 #else
344 munmap (tmpl.bytes, tmpl.size);
345 #endif
347 close (tmpl.fd);
349 return gFalse;
352 l = (struct _ft_face_data *) gmallocn (1, sizeof (struct _ft_face_data));
353 *l = tmpl;
354 l->prev = NULL;
355 l->next = _ft_open_faces;
356 if (_ft_open_faces)
357 _ft_open_faces->prev = l;
358 _ft_open_faces = l;
360 l->font_face = cairo_ft_font_face_create_for_ft_face (tmpl.face,
361 FT_LOAD_NO_HINTING |
362 FT_LOAD_NO_BITMAP);
363 if (cairo_font_face_set_user_data (l->font_face,
364 &_ft_cairo_key,
366 _ft_done_face))
368 cairo_font_face_destroy (l->font_face);
369 _ft_done_face (l);
370 return gFalse;
373 *face_out = l->face;
374 *font_face_out = l->font_face;
375 return gTrue;
377 #else
378 #define _ft_new_face _ft_new_face_uncached
379 #endif
381 CairoFreeTypeFont::CairoFreeTypeFont(Ref ref,
382 cairo_font_face_t *cairo_font_face,
383 int *codeToGID,
384 Guint codeToGIDLen,
385 GBool substitute) : CairoFont(ref,
386 cairo_font_face,
387 codeToGID,
388 codeToGIDLen,
389 substitute,
390 gTrue) { }
392 CairoFreeTypeFont::~CairoFreeTypeFont() { }
394 CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
395 FT_Library lib, GBool useCIDs) {
396 Object refObj, strObj;
397 GooString *fileName;
398 char *fileNameC;
399 char *font_data;
400 int font_data_len;
401 int i, n;
402 GfxFontType fontType;
403 GfxFontLoc *fontLoc;
404 char **enc;
405 const char *name;
406 FoFiTrueType *ff;
407 FoFiType1C *ff1c;
408 Ref ref;
409 FT_Face face;
410 cairo_font_face_t *font_face;
412 int *codeToGID;
413 Guint codeToGIDLen;
415 codeToGID = NULL;
416 codeToGIDLen = 0;
417 font_data = NULL;
418 font_data_len = 0;
419 fileName = NULL;
420 fileNameC = NULL;
422 GBool substitute = gFalse;
424 ref = *gfxFont->getID();
425 fontType = gfxFont->getType();
427 if (!(fontLoc = gfxFont->locateFont(xref, NULL))) {
428 error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
429 gfxFont->getName() ? gfxFont->getName()->getCString()
430 : "(unnamed)");
431 goto err2;
434 // embedded font
435 if (fontLoc->locType == gfxFontLocEmbedded) {
436 font_data = gfxFont->readEmbFontFile(xref, &font_data_len);
437 if (NULL == font_data)
438 goto err2;
440 // external font
441 } else { // gfxFontLocExternal
442 fileName = fontLoc->path;
443 fontType = fontLoc->fontType;
444 substitute = gTrue;
447 if (fileName != NULL) {
448 fileNameC = fileName->getCString();
451 switch (fontType) {
452 case fontType1:
453 case fontType1C:
454 case fontType1COT:
455 if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) {
456 error(errSyntaxError, -1, "could not create type1 face");
457 goto err2;
460 enc = ((Gfx8BitFont *)gfxFont)->getEncoding();
462 codeToGID = (int *)gmallocn(256, sizeof(int));
463 codeToGIDLen = 256;
464 for (i = 0; i < 256; ++i) {
465 codeToGID[i] = 0;
466 if ((name = enc[i])) {
467 codeToGID[i] = FT_Get_Name_Index(face, (char*)name);
468 if (codeToGID[i] == 0) {
469 name = GfxFont::getAlternateName(name);
470 if (name) {
471 codeToGID[i] = FT_Get_Name_Index(face, (char*)name);
476 break;
477 case fontCIDType2:
478 case fontCIDType2OT:
479 codeToGID = NULL;
480 n = 0;
481 if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
482 n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
483 if (n) {
484 codeToGID = (int *)gmallocn(n, sizeof(int));
485 memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
486 n * sizeof(int));
488 } else {
489 if (font_data != NULL) {
490 ff = FoFiTrueType::make(font_data, font_data_len);
491 } else {
492 ff = FoFiTrueType::load(fileNameC);
494 if (! ff)
495 goto err2;
496 codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
497 delete ff;
499 codeToGIDLen = n;
500 /* Fall through */
501 case fontTrueType:
502 if (font_data != NULL) {
503 ff = FoFiTrueType::make(font_data, font_data_len);
504 } else {
505 ff = FoFiTrueType::load(fileNameC);
507 if (! ff) {
508 error(errSyntaxError, -1, "failed to load truetype font\n");
509 goto err2;
511 /* This might be set already for the CIDType2 case */
512 if (fontType == fontTrueType) {
513 codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
514 codeToGIDLen = 256;
516 delete ff;
517 if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) {
518 error(errSyntaxError, -1, "could not create truetype face\n");
519 goto err2;
521 break;
523 case fontCIDType0:
524 case fontCIDType0C:
526 codeToGID = NULL;
527 codeToGIDLen = 0;
529 if (!useCIDs)
531 if (font_data != NULL) {
532 ff1c = FoFiType1C::make(font_data, font_data_len);
533 } else {
534 ff1c = FoFiType1C::load(fileNameC);
536 if (ff1c) {
537 codeToGID = ff1c->getCIDToGIDMap((int *)&codeToGIDLen);
538 delete ff1c;
542 if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) {
543 error(errSyntaxError, -1, "could not create cid face\n");
544 goto err2;
546 break;
548 default:
549 fprintf (stderr, "font type %d not handled\n", (int)fontType);
550 goto err2;
551 break;
554 delete fontLoc;
555 return new CairoFreeTypeFont(ref,
556 font_face,
557 codeToGID, codeToGIDLen,
558 substitute);
560 err2:
561 /* hmm? */
562 delete fontLoc;
563 gfree (codeToGID);
564 gfree (font_data);
565 fprintf (stderr, "some font thing failed\n");
566 return NULL;
569 //------------------------------------------------------------------------
570 // CairoType3Font
571 //------------------------------------------------------------------------
573 static const cairo_user_data_key_t type3_font_key = {0};
575 typedef struct _type3_font_info {
576 GfxFont *font;
577 PDFDoc *doc;
578 CairoFontEngine *fontEngine;
579 GBool printing;
580 XRef *xref;
581 } type3_font_info_t;
583 static void
584 _free_type3_font_info(void *closure)
586 type3_font_info_t *info = (type3_font_info_t *) closure;
588 info->font->decRefCnt();
589 free (info);
592 static cairo_status_t
593 _init_type3_glyph (cairo_scaled_font_t *scaled_font,
594 cairo_t *cr,
595 cairo_font_extents_t *extents)
597 type3_font_info_t *info;
598 GfxFont *font;
599 double *mat;
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 font = info->font;
605 mat = font->getFontBBox();
606 extents->ascent = mat[3]; /* y2 */
607 extents->descent = -mat[3]; /* -y1 */
608 extents->height = extents->ascent + extents->descent;
609 extents->max_x_advance = mat[2] - mat[1]; /* x2 - x1 */
610 extents->max_y_advance = 0;
612 return CAIRO_STATUS_SUCCESS;
615 static cairo_status_t
616 _render_type3_glyph (cairo_scaled_font_t *scaled_font,
617 unsigned long glyph,
618 cairo_t *cr,
619 cairo_text_extents_t *metrics)
621 Dict *charProcs;
622 Object charProc;
623 CairoOutputDev *output_dev;
624 cairo_matrix_t matrix, invert_y_axis;
625 double *mat;
626 double wx, wy;
627 PDFRectangle box;
628 type3_font_info_t *info;
629 GfxFont *font;
630 Dict *resDict;
631 Gfx *gfx;
633 info = (type3_font_info_t *)
634 cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
635 &type3_font_key);
637 font = info->font;
638 resDict = ((Gfx8BitFont *)font)->getResources();
639 charProcs = ((Gfx8BitFont *)(info->font))->getCharProcs();
640 if (!charProcs)
641 return CAIRO_STATUS_USER_FONT_ERROR;
643 if ((int)glyph >= charProcs->getLength())
644 return CAIRO_STATUS_USER_FONT_ERROR;
646 mat = font->getFontMatrix();
647 matrix.xx = mat[0];
648 matrix.yx = mat[1];
649 matrix.xy = mat[2];
650 matrix.yy = mat[3];
651 matrix.x0 = mat[4];
652 matrix.y0 = mat[5];
653 cairo_matrix_init_scale (&invert_y_axis, 1, -1);
654 cairo_matrix_multiply (&matrix, &matrix, &invert_y_axis);
655 cairo_transform (cr, &matrix);
657 output_dev = new CairoOutputDev();
658 output_dev->setCairo(cr);
659 output_dev->setPrinting(info->printing);
661 mat = font->getFontBBox();
662 box.x1 = mat[0];
663 box.y1 = mat[1];
664 box.x2 = mat[2];
665 box.y2 = mat[3];
666 gfx = new Gfx(info->doc, output_dev, resDict, &box, NULL);
667 output_dev->startDoc(info->doc, info->fontEngine);
668 output_dev->startPage (1, gfx->getState(), gfx->getXRef());
669 output_dev->setInType3Char(gTrue);
670 gfx->display(charProcs->getVal(glyph, &charProc));
672 output_dev->getType3GlyphWidth (&wx, &wy);
673 cairo_matrix_transform_distance (&matrix, &wx, &wy);
674 metrics->x_advance = wx;
675 metrics->y_advance = wy;
676 if (output_dev->hasType3GlyphBBox()) {
677 double *bbox = output_dev->getType3GlyphBBox();
679 cairo_matrix_transform_point (&matrix, &bbox[0], &bbox[1]);
680 cairo_matrix_transform_point (&matrix, &bbox[2], &bbox[3]);
681 metrics->x_bearing = bbox[0];
682 metrics->y_bearing = bbox[1];
683 metrics->width = bbox[2] - bbox[0];
684 metrics->height = bbox[3] - bbox[1];
687 delete gfx;
688 delete output_dev;
689 charProc.free();
691 return CAIRO_STATUS_SUCCESS;
695 CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, PDFDoc *doc,
696 CairoFontEngine *fontEngine,
697 GBool printing, XRef *xref) {
698 Object refObj, strObj;
699 type3_font_info_t *info;
700 cairo_font_face_t *font_face;
701 Ref ref;
702 int *codeToGID;
703 Guint codeToGIDLen;
704 int i, j;
705 char **enc;
706 Dict *charProcs;
707 char *name;
709 charProcs = ((Gfx8BitFont *)gfxFont)->getCharProcs();
710 info = (type3_font_info_t *) malloc(sizeof(*info));
711 ref = *gfxFont->getID();
712 font_face = cairo_user_font_face_create();
713 cairo_user_font_face_set_init_func (font_face, _init_type3_glyph);
714 cairo_user_font_face_set_render_glyph_func (font_face, _render_type3_glyph);
715 gfxFont->incRefCnt();
716 info->font = gfxFont;
717 info->doc = doc;
718 info->fontEngine = fontEngine;
719 info->printing = printing;
720 info->xref = xref;
722 cairo_font_face_set_user_data (font_face, &type3_font_key, (void *) info, _free_type3_font_info);
724 enc = ((Gfx8BitFont *)gfxFont)->getEncoding();
725 codeToGID = (int *)gmallocn(256, sizeof(int));
726 codeToGIDLen = 256;
727 for (i = 0; i < 256; ++i) {
728 codeToGID[i] = 0;
729 if (charProcs && (name = enc[i])) {
730 for (j = 0; j < charProcs->getLength(); j++) {
731 if (strcmp(name, charProcs->getKey(j)) == 0) {
732 codeToGID[i] = j;
738 return new CairoType3Font(ref, doc, font_face, codeToGID, codeToGIDLen, printing, xref);
741 CairoType3Font::CairoType3Font(Ref ref,
742 PDFDoc *doc,
743 cairo_font_face_t *cairo_font_face,
744 int *codeToGID,
745 Guint codeToGIDLen,
746 GBool printing, XRef *xref) : CairoFont(ref,
747 cairo_font_face,
748 codeToGID,
749 codeToGIDLen,
750 gFalse,
751 printing),
752 doc(doc) { }
754 CairoType3Font::~CairoType3Font() { }
756 GBool
757 CairoType3Font::matches(Ref &other, GBool printingA) {
758 return (other.num == ref.num && other.gen == ref.gen && printing == printingA);
762 //------------------------------------------------------------------------
763 // CairoFontEngine
764 //------------------------------------------------------------------------
766 CairoFontEngine::CairoFontEngine(FT_Library libA) {
767 int i;
769 lib = libA;
770 for (i = 0; i < cairoFontCacheSize; ++i) {
771 fontCache[i] = NULL;
774 FT_Int major, minor, patch;
775 // as of FT 2.1.8, CID fonts are indexed by CID instead of GID
776 FT_Library_Version(lib, &major, &minor, &patch);
777 useCIDs = major > 2 ||
778 (major == 2 && (minor > 1 || (minor == 1 && patch > 7)));
779 #if MULTITHREADED
780 gInitMutex(&mutex);
781 #endif
784 CairoFontEngine::~CairoFontEngine() {
785 int i;
787 for (i = 0; i < cairoFontCacheSize; ++i) {
788 if (fontCache[i])
789 delete fontCache[i];
791 #if MULTITHREADED
792 gDestroyMutex(&mutex);
793 #endif
796 CairoFont *
797 CairoFontEngine::getFont(GfxFont *gfxFont, PDFDoc *doc, GBool printing, XRef *xref) {
798 int i, j;
799 Ref ref;
800 CairoFont *font;
801 GfxFontType fontType;
803 fontEngineLocker();
804 ref = *gfxFont->getID();
806 for (i = 0; i < cairoFontCacheSize; ++i) {
807 font = fontCache[i];
808 if (font && font->matches(ref, printing)) {
809 for (j = i; j > 0; --j) {
810 fontCache[j] = fontCache[j-1];
812 fontCache[0] = font;
813 return font;
817 fontType = gfxFont->getType();
818 if (fontType == fontType3)
819 font = CairoType3Font::create (gfxFont, doc, this, printing, xref);
820 else
821 font = CairoFreeTypeFont::create (gfxFont, xref, lib, useCIDs);
823 //XXX: if font is null should we still insert it into the cache?
824 if (fontCache[cairoFontCacheSize - 1]) {
825 delete fontCache[cairoFontCacheSize - 1];
827 for (j = cairoFontCacheSize - 1; j > 0; --j) {
828 fontCache[j] = fontCache[j-1];
830 fontCache[0] = font;
831 return font;