11#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
20#include "freetype/ftoutln.h"
21#include "freetype/internal/ftobjs.h"
23#include "freetype/internal/cfftypes.h"
24#include "freetype/internal/tttypes.h"
26#include "GlobalParams.h"
32FTFontEngine::FTFontEngine(Display *displayA, Visual *visualA,
int depthA,
33 Colormap colormapA, GBool aaA):
34 SFontEngine(displayA, visualA, depthA, colormapA) {
37 if (FT_Init_FreeType(&lib)) {
44FTFontEngine::~FTFontEngine() {
45 FT_Done_FreeType(lib);
50FTFontFile::FTFontFile(FTFontEngine *engineA,
char *fontFileName,
51 char **fontEnc, GBool pdfFontHasEncoding) {
53 int unicodeCmap, macRomanCmap, msSymbolCmap;
59 if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
63 if (!strcmp(face->driver->root.clazz->module_name,
"type1") ||
64 !strcmp(face->driver->root.clazz->module_name,
"cff")) {
66 mode = ftFontModeCodeMapDirect;
67 codeMap = (Guint *)gmalloc(256 *
sizeof(Guint));
68 for (i = 0; i < 256; ++i) {
70 if ((name = fontEnc[i])) {
71 codeMap[i] = FT_Get_Name_Index(face, name);
92 unicodeCmap = macRomanCmap = msSymbolCmap = 0xffff;
93 for (i = 0; i < face->num_charmaps; ++i) {
94 if (face->charmaps[i]->platform_id == 3 &&
95 face->charmaps[i]->encoding_id == 1) {
97 }
else if (face->charmaps[i]->platform_id == 1 &&
98 face->charmaps[i]->encoding_id == 0) {
100 }
else if (face->charmaps[i]->platform_id == 3 &&
101 face->charmaps[i]->encoding_id == 0) {
106 mode = ftFontModeCharCode;
108 if (pdfFontHasEncoding) {
109 if (unicodeCmap != 0xffff) {
111 mode = ftFontModeUnicode;
112 }
else if (macRomanCmap != 0xffff) {
114 mode = ftFontModeCodeMap;
115 codeMap = (Guint *)gmalloc(256 *
sizeof(Guint));
116 for (j = 0; j < 256; ++j) {
118 codeMap[j] = globalParams->getMacRomanCharCode(fontEnc[j]);
125 if (macRomanCmap != 0xffff) {
127 mode = ftFontModeCharCode;
128 }
else if (msSymbolCmap != 0xffff) {
130 mode = ftFontModeCharCodeOffset;
131 charMapOffset = 0xf000;
134 if (FT_Set_Charmap(face, face->charmaps[i])) {
142FTFontFile::FTFontFile(FTFontEngine *engineA,
char *fontFileName,
143 Gushort *cidToGIDA,
int cidToGIDLenA) {
147 if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
150 cidToGID = cidToGIDA;
151 cidToGIDLen = cidToGIDLenA;
152 mode = ftFontModeCIDToGIDMap;
156FTFontFile::FTFontFile(FTFontEngine *engineA,
char *fontFileName) {
160 if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
165 mode = ftFontModeCFFCharset;
169FTFontFile::~FTFontFile() {
180FTFont::FTFont(FTFontFile *fontFileA,
double *m) {
181 FTFontEngine *engine;
189 fontFile = fontFileA;
190 engine = fontFile->engine;
191 face = fontFile->face;
192 if (FT_New_Size(face, &sizeObj)) {
195 face->size = sizeObj;
196 size = sqrt(m[2]*m[2] + m[3]*m[3]);
197 if (FT_Set_Pixel_Sizes(face, 0, (
int)size)) {
201 div = face->bbox.xMax > 20000 ? 65536 : 1;
205 x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMin) /
206 (div * face->units_per_EM));
208 y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMin) /
209 (div * face->units_per_EM));
211 x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMax) /
212 (div * face->units_per_EM));
215 }
else if (x > xMax) {
218 y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMax) /
219 (div * face->units_per_EM));
222 }
else if (y > yMax) {
225 x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMin) /
226 (div * face->units_per_EM));
229 }
else if (x > xMax) {
232 y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMin) /
233 (div * face->units_per_EM));
236 }
else if (y > yMax) {
239 x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMax) /
240 (div * face->units_per_EM));
243 }
else if (x > xMax) {
246 y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMax) /
247 (div * face->units_per_EM));
250 }
else if (y > yMax) {
261 yMax = (int)(1.2 * size);
265 glyphW = xMax - xMin + 3;
266 glyphW += glyphW >> 1;
267 glyphH = yMax - yMin + 3;
268 glyphH += glyphH >> 1;
270 glyphSize = glyphW * glyphH;
272 glyphSize = ((glyphW + 7) >> 3) * glyphH;
277 if (glyphSize <= 256) {
279 }
else if (glyphSize <= 512) {
281 }
else if (glyphSize <= 1024) {
286 cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
287 cacheTags = (FTFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
288 sizeof(FTFontCacheTag));
289 for (i = 0; i < cacheSets * cacheAssoc; ++i) {
290 cacheTags[i].mru = i & (cacheAssoc - 1);
294 if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
295 ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) {
298 image->data = (
char *)gmalloc(glyphH * image->bytes_per_line);
301 matrix.xx = (FT_Fixed)((m[0] / size) * 65536);
302 matrix.yx = (FT_Fixed)((m[1] / size) * 65536);
303 matrix.xy = (FT_Fixed)((m[2] / size) * 65536);
304 matrix.yy = (FT_Fixed)((m[3] / size) * 65536);
314 XDestroyImage(image);
317GBool FTFont::drawChar(Drawable d,
int w,
int h, GC gc,
318 int x,
int y,
int r,
int g,
int b,
319 CharCode c, Unicode u) {
320 FTFontEngine *engine;
326 int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;
329 engine = fontFile->engine;
332 if (fontFile->mode == ftFontModeUnicode && u == 0) {
337 if (!(p = getGlyphPixmap(c, u, &xOffset, &yOffset, &gw, &gh))) {
374 XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
375 ZPixmap, image, x1, y1);
380 xcolor.pixel = XGetPixel(image, x1 + w0/2, y1 + h0/2);
381 XQueryColor(engine->display, engine->colormap, &xcolor);
385 colors[1] = engine->findColor((r + 3*bgR) / 4,
388 colors[2] = engine->findColor((r + bgR) / 2,
391 colors[3] = engine->findColor((3*r + bgR) / 4,
394 colors[4] = engine->findColor(r, g, b);
397 for (yy = 0; yy < gh; ++yy) {
398 for (xx = 0; xx < gw; ++xx) {
403 pix = ((pix + 10) * 5) / 256;
408 XPutPixel(image, xx, yy, colors[pix]);
416 colors[1] = engine->findColor(r, g, b);
419 for (yy = 0; yy < gh; ++yy) {
420 for (xx = 0; xx < gw; xx += 8) {
422 for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {
424 XPutPixel(image, xx1, yy, colors[1]);
434 XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0);
439Guchar *FTFont::getGlyphPixmap(CharCode c, Unicode u,
440 int *x,
int *y,
int *w,
int *h) {
448 i = (c & (cacheSets - 1)) * cacheAssoc;
449 for (j = 0; j < cacheAssoc; ++j) {
450 if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
451 *x = cacheTags[i+j].x;
452 *y = cacheTags[i+j].y;
453 *w = cacheTags[i+j].w;
454 *h = cacheTags[i+j].h;
455 for (k = 0; k < cacheAssoc; ++k) {
457 (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
458 ++cacheTags[i+k].mru;
461 cacheTags[i+j].mru = 0x8000;
462 return cache + (i+j) * glyphSize;
467 fontFile->face->size = sizeObj;
468 FT_Set_Transform(fontFile->face, &matrix, NULL);
469 slot = fontFile->face->glyph;
470 idx = getGlyphIndex(c, u);
472#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
473 if (FT_Load_Glyph(fontFile->face, idx, FT_LOAD_DEFAULT)) {
481 if (FT_Load_Glyph(fontFile->face, idx,
482 fontFile->engine->aa ? FT_LOAD_NO_HINTING
483 : FT_LOAD_DEFAULT)) {
487 if (FT_Render_Glyph(slot,
488 fontFile->engine->aa ? ft_render_mode_normal :
489 ft_render_mode_mono)) {
492 *x = -slot->bitmap_left;
493 *y = slot->bitmap_top;
494 *w = slot->bitmap.width;
495 *h = slot->bitmap.rows;
496 if (*w > glyphW || *h > glyphH) {
498 fprintf(stderr,
"Weird FreeType glyph size: %d > %d or %d > %d\n",
499 *w, glyphW, *h, glyphH);
506 for (j = 0; j < cacheAssoc; ++j) {
507 if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
508 cacheTags[i+j].mru = 0x8000;
509 cacheTags[i+j].code = c;
510 cacheTags[i+j].x = *x;
511 cacheTags[i+j].y = *y;
512 cacheTags[i+j].w = *w;
513 cacheTags[i+j].h = *h;
514 if (fontFile->engine->aa) {
517 rowSize = (*w + 7) >> 3;
519 ret = cache + (i+j) * glyphSize;
520 for (k = 0, p = ret, q = slot->bitmap.buffer;
521 k < slot->bitmap.rows;
522 ++k, p += rowSize, q += slot->bitmap.pitch) {
523 memcpy(p, q, rowSize);
526 ++cacheTags[i+j].mru;
532GBool FTFont::getCharPath(CharCode c, Unicode u, GfxState *state) {
533 static FT_Outline_Funcs outlineFuncs = {
544 fontFile->face->size = sizeObj;
545 FT_Set_Transform(fontFile->face, &matrix, NULL);
546 slot = fontFile->face->glyph;
547 idx = getGlyphIndex(c, u);
548#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
549 if (FT_Load_Glyph(fontFile->face, idx, FT_LOAD_DEFAULT)) {
557 if (FT_Load_Glyph(fontFile->face, idx,
558 fontFile->engine->aa ? FT_LOAD_NO_HINTING
559 : FT_LOAD_DEFAULT)) {
563 if (FT_Get_Glyph(slot, &glyph)) {
566 FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
567 &outlineFuncs, state);
571int FTFont::charPathMoveTo(FT_Vector *pt,
void *state) {
572 ((GfxState *)state)->moveTo(pt->x / 64.0, -pt->y / 64.0);
576int FTFont::charPathLineTo(FT_Vector *pt,
void *state) {
577 ((GfxState *)state)->lineTo(pt->x / 64.0, -pt->y / 64.0);
581int FTFont::charPathConicTo(FT_Vector *ctrl, FT_Vector *pt,
void *state) {
582 double x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
584 x0 = ((GfxState *)state)->getCurX();
585 y0 = ((GfxState *)state)->getCurY();
587 yc = -ctrl->y / 64.0;
607 x1 = (1.0 / 3.0) * (x0 + 2 * xc);
608 y1 = (1.0 / 3.0) * (y0 + 2 * yc);
609 x2 = (1.0 / 3.0) * (2 * xc + x3);
610 y2 = (1.0 / 3.0) * (2 * yc + y3);
612 ((GfxState *)state)->curveTo(x1, y1, x2, y2, x3, y3);
616int FTFont::charPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
617 FT_Vector *pt,
void *state) {
618 ((GfxState *)state)->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
619 ctrl2->x / 64.0, -ctrl2->y / 64.0,
620 pt->x / 64.0, -pt->y / 64.0);
624FT_UInt FTFont::getGlyphIndex(CharCode c, Unicode u) {
629 switch (fontFile->mode) {
630 case ftFontModeUnicode:
631 idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)u);
633 case ftFontModeCharCode:
634 idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)c);
636 case ftFontModeCharCodeOffset:
637 idx = FT_Get_Char_Index(fontFile->face,
638 (FT_ULong)(c + fontFile->charMapOffset));
640 case ftFontModeCodeMap:
642 idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)fontFile->codeMap[c]);
647 case ftFontModeCodeMapDirect:
649 idx = (FT_UInt)fontFile->codeMap[c];
654 case ftFontModeCIDToGIDMap:
655 if (fontFile->cidToGIDLen) {
656 if ((
int)c < fontFile->cidToGIDLen) {
657 idx = (FT_UInt)fontFile->cidToGID[c];
665 case ftFontModeCFFCharset:
667#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0
668 CFF_Font *cff = (CFF_Font *)((TT_Face)fontFile->face)->extra.data;
670 CFF_Font cff = (CFF_Font)((TT_Face)fontFile->face)->extra.data;
673 for (j = 0; j < (int)cff->num_glyphs; ++j) {
674 if (cff->charset.sids[j] == c) {