📄 ftfont.cc
字号:
//========================================================================//// FTFont.cc//// Copyright 2001-2002 Glyph & Cog, LLC////========================================================================#include <aconf.h>#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)#ifdef USE_GCC_PRAGMAS#pragma implementation#endif#include <math.h>#include <string.h>#include "gmem.h"#include "freetype/ftoutln.h"#include "freetype/internal/ftobjs.h"#if 1 //~ cff cid->gid map#include "freetype/internal/cfftypes.h"#include "freetype/internal/tttypes.h"#endif#include "GlobalParams.h"#include "GfxState.h"#include "FTFont.h"//------------------------------------------------------------------------FTFontEngine::FTFontEngine(Display *displayA, Visual *visualA, int depthA, Colormap colormapA, GBool aaA): SFontEngine(displayA, visualA, depthA, colormapA) { ok = gFalse; if (FT_Init_FreeType(&lib)) { return; } aa = aaA; ok = gTrue;}FTFontEngine::~FTFontEngine() { FT_Done_FreeType(lib);}//------------------------------------------------------------------------FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName, char **fontEnc, GBool pdfFontHasEncoding) { char *name; int unicodeCmap, macRomanCmap, msSymbolCmap; int i, j; ok = gFalse; engine = engineA; codeMap = NULL; cidToGID = NULL; cidToGIDLen = 0; if (FT_New_Face(engine->lib, fontFileName, 0, &face)) { return; } if (!strcmp(face->driver->root.clazz->module_name, "type1") || !strcmp(face->driver->root.clazz->module_name, "cff")) { mode = ftFontModeCodeMapDirect; codeMap = (Guint *)gmalloc(256 * sizeof(Guint)); for (i = 0; i < 256; ++i) { codeMap[i] = 0; if ((name = fontEnc[i])) { codeMap[i] = FT_Get_Name_Index(face, name); } } } else { // To match up with the Adobe-defined behaviour, we choose a cmap // like this: // 1. If the PDF font has an encoding: // 1a. If the TrueType font has a Microsoft Unicode cmap, use it, // and use the Unicode indexes, not the char codes. // 1b. If the TrueType font has a Macintosh Roman cmap, use it, // and reverse map the char names through MacRomanEncoding to // get char codes. // 2. If the PDF font does not have an encoding: // 2a. If the TrueType font has a Macintosh Roman cmap, use it, // and use char codes directly. // 2b. If the TrueType font has a Microsoft Symbol cmap, use it, // and use (0xf000 + char code). // 3. If none of these rules apply, use the first cmap and hope for // the best (this shouldn't happen). unicodeCmap = macRomanCmap = msSymbolCmap = 0xffff; for (i = 0; i < face->num_charmaps; ++i) { if (face->charmaps[i]->platform_id == 3 && face->charmaps[i]->encoding_id == 1) { unicodeCmap = i; } else if (face->charmaps[i]->platform_id == 1 && face->charmaps[i]->encoding_id == 0) { macRomanCmap = i; } else if (face->charmaps[i]->platform_id == 3 && face->charmaps[i]->encoding_id == 0) { msSymbolCmap = i; } } i = 0; mode = ftFontModeCharCode; charMapOffset = 0; if (pdfFontHasEncoding) { if (unicodeCmap != 0xffff) { i = unicodeCmap; mode = ftFontModeUnicode; } else if (macRomanCmap != 0xffff) { i = macRomanCmap; mode = ftFontModeCodeMap; codeMap = (Guint *)gmalloc(256 * sizeof(Guint)); for (j = 0; j < 256; ++j) { if (fontEnc[j]) { codeMap[j] = globalParams->getMacRomanCharCode(fontEnc[j]); } else { codeMap[j] = 0; } } } } else { if (macRomanCmap != 0xffff) { i = macRomanCmap; mode = ftFontModeCharCode; } else if (msSymbolCmap != 0xffff) { i = msSymbolCmap; mode = ftFontModeCharCodeOffset; charMapOffset = 0xf000; } } if (FT_Set_Charmap(face, face->charmaps[i])) { return; } } ok = gTrue;}FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName, Gushort *cidToGIDA, int cidToGIDLenA) { ok = gFalse; engine = engineA; codeMap = NULL; cidToGID = NULL; cidToGIDLen = 0; if (FT_New_Face(engine->lib, fontFileName, 0, &face)) { return; } cidToGIDLen = cidToGIDLenA; cidToGID = (Gushort *)gmalloc(cidToGIDLen * sizeof(Gushort)); memcpy(cidToGID, cidToGIDA, cidToGIDLen * sizeof(Gushort)); mode = ftFontModeCIDToGIDMap; ok = gTrue;}FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName) { ok = gFalse; engine = engineA; codeMap = NULL; cidToGID = NULL; cidToGIDLen = 0; if (FT_New_Face(engine->lib, fontFileName, 0, &face)) { return; } if (!strcmp(face->driver->root.clazz->module_name, "t1cid")) { mode = ftFontModeCID; } else { mode = ftFontModeCFFCharset; } ok = gTrue;}FTFontFile::~FTFontFile() { if (face) { FT_Done_Face(face); } if (codeMap) { gfree(codeMap); } if (cidToGID) { gfree(cidToGID); }}//------------------------------------------------------------------------FTFont::FTFont(FTFontFile *fontFileA, double *m) { FTFontEngine *engine; FT_Face face; double size, div; int x, xMin, xMax; int y, yMin, yMax; int i; ok = gFalse; fontFile = fontFileA; engine = fontFile->engine; face = fontFile->face; if (FT_New_Size(face, &sizeObj)) { return; } face->size = sizeObj; size = sqrt(m[2]*m[2] + m[3]*m[3]); if (FT_Set_Pixel_Sizes(face, 0, (int)size)) { return; } div = face->bbox.xMax > 20000 ? 65536 : 1; // transform the four corners of the font bounding box -- the min // and max values form the bounding box of the transformed font x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMin) / (div * face->units_per_EM)); xMin = xMax = x; y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMin) / (div * face->units_per_EM)); yMin = yMax = y; x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMax) / (div * face->units_per_EM)); if (x < xMin) { xMin = x; } else if (x > xMax) { xMax = x; } y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMax) / (div * face->units_per_EM)); if (y < yMin) { yMin = y; } else if (y > yMax) { yMax = y; } x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMin) / (div * face->units_per_EM)); if (x < xMin) { xMin = x; } else if (x > xMax) { xMax = x; } y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMin) / (div * face->units_per_EM)); if (y < yMin) { yMin = y; } else if (y > yMax) { yMax = y; } x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMax) / (div * face->units_per_EM)); if (x < xMin) { xMin = x; } else if (x > xMax) { xMax = x; } y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMax) / (div * face->units_per_EM)); if (y < yMin) { yMin = y; } else if (y > yMax) { yMax = y; } // This is a kludge: some buggy PDF generators embed fonts with // zero bounding boxes. if (xMax == xMin) { xMin = 0; xMax = (int)size; } if (yMax == yMin) { yMin = 0; yMax = (int)(1.2 * size); } // this should be (max - min + 1), but we add some padding to // deal with rounding errors, bogus bboxes, etc. glyphW = xMax - xMin + 3; glyphW += glyphW >> 1; glyphH = yMax - yMin + 3; glyphH += glyphH >> 1; if (engine->aa) { glyphSize = glyphW * glyphH; } else { glyphSize = ((glyphW + 7) >> 3) * glyphH; } // set up the glyph pixmap cache cacheAssoc = 8; if (glyphSize <= 256) { cacheSets = 8; } else if (glyphSize <= 512) { cacheSets = 4; } else if (glyphSize <= 1024) { cacheSets = 2; } else { cacheSets = 1; } cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize); cacheTags = (FTFontCacheTag *)gmalloc(cacheSets * cacheAssoc * sizeof(FTFontCacheTag)); for (i = 0; i < cacheSets * cacheAssoc; ++i) { cacheTags[i].mru = i & (cacheAssoc - 1); } // create the XImage if (!(image = XCreateImage(engine->display, engine->visual, engine->depth, ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) { return; } image->data = (char *)gmalloc(glyphH * image->bytes_per_line); // compute the transform matrix matrix.xx = (FT_Fixed)((m[0] / size) * 65536); matrix.yx = (FT_Fixed)((m[1] / size) * 65536); matrix.xy = (FT_Fixed)((m[2] / size) * 65536); matrix.yy = (FT_Fixed)((m[3] / size) * 65536); ok = gTrue;}FTFont::~FTFont() { gfree(cacheTags); gfree(cache); gfree(image->data); image->data = NULL; XDestroyImage(image);}GBool FTFont::drawChar(Drawable d, int w, int h, GC gc, int x, int y, int r, int g, int b, CharCode c, Unicode u) { FTFontEngine *engine; XColor xcolor; int bgR, bgG, bgB; Gulong colors[5]; Guchar *p; int pix; int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0; int xx, yy, xx1; engine = fontFile->engine; // no Unicode index for this char - don't draw anything if (fontFile->mode == ftFontModeUnicode && u == 0) { return gFalse; } // generate the glyph pixmap if (!(p = getGlyphPixmap(c, u, &xOffset, &yOffset, &gw, &gh))) { return gFalse;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -