1 //========================================================================
5 // Copyright 2001-2003 Glyph & Cog, LLC
7 //========================================================================
11 #if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
13 #ifdef USE_GCC_PRAGMAS
14 #pragma implementation
19 #include "GlobalParams.h"
22 //------------------------------------------------------------------------
24 TTFontEngine::TTFontEngine(Display *displayA, Visual *visualA, int depthA,
25 Colormap colormapA, GBool aaA):
26 SFontEngine(displayA, visualA, depthA, colormapA) {
27 static TT_Byte ttPalette[5] = {0, 1, 2, 3, 4};
30 if (TT_Init_FreeType(&engine)) {
35 if (TT_Set_Raster_Gray_Palette(engine, ttPalette)) {
42 TTFontEngine::~TTFontEngine() {
43 TT_Done_FreeType(engine);
46 //------------------------------------------------------------------------
48 TTFontFile::TTFontFile(TTFontEngine *engineA, char *fontFileName,
49 char **fontEnc, GBool pdfFontHasEncoding) {
50 TT_Face_Properties props;
51 TT_UShort unicodeCmap, macRomanCmap, msSymbolCmap;
52 TT_UShort platform, encoding, i;
58 if (TT_Open_Face(engine->engine, fontFileName, &face)) {
61 if (TT_Get_Face_Properties(face, &props)) {
65 // To match up with the Adobe-defined behaviour, we choose a cmap
67 // 1. If the PDF font has an encoding:
68 // 1a. If the PDF font specified MacRomanEncoding and the
69 // TrueType font has a Macintosh Roman cmap, use it, and
70 // reverse map the char names through MacRomanEncoding to
72 // 1b. If the TrueType font has a Microsoft Unicode cmap or a
73 // non-Microsoft Unicode cmap, use it, and use the Unicode
74 // indexes, not the char codes.
75 // 1c. If the PDF font is symbolic and the TrueType font has a
76 // Microsoft Symbol cmap, use it, and use char codes
77 // directly (possibly with an offset of 0xf000).
78 // 1d. If the TrueType font has a Macintosh Roman cmap, use it,
80 // 2. If the PDF font does not have an encoding:
81 // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
82 // and use char codes directly (possibly with an offset of
84 // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
85 // and use char codes directly (possible with an offset of
87 // 3. If none of these rules apply, use the first cmap and hope for
88 // the best (this shouldn't happen).
89 unicodeCmap = macRomanCmap = msSymbolCmap = 0xffff;
90 for (i = 0; i < props.num_CharMaps; ++i) {
91 if (!TT_Get_CharMap_ID(face, i, &platform, &encoding)) {
92 if ((platform == 3 && encoding == 1) || platform == 0) {
94 } else if (platform == 1 && encoding == 0) {
96 } else if (platform == 3 && encoding == 0) {
102 mode = ttFontModeCharCode;
103 if (pdfFontHasEncoding) {
104 if (unicodeCmap != 0xffff) {
106 mode = ttFontModeUnicode;
107 } else if (macRomanCmap != 0xffff) {
109 mode = ttFontModeCodeMap;
110 codeMap = (Guchar *)gmalloc(256 * sizeof(Guchar));
111 for (j = 0; j < 256; ++j) {
113 codeMap[j] = (Guchar)globalParams->getMacRomanCharCode(fontEnc[j]);
120 if (macRomanCmap != 0xffff) {
122 mode = ttFontModeCharCode;
123 } else if (msSymbolCmap != 0xffff) {
125 mode = ttFontModeCharCode;
128 TT_Get_CharMap(face, i, &charMap);
133 TTFontFile::TTFontFile(TTFontEngine *engineA, char *fontFileName,
134 Gushort *cidToGIDA, int cidToGIDLenA) {
138 cidToGID = cidToGIDA;
139 cidToGIDLen = cidToGIDLenA;
140 if (TT_Open_Face(engine->engine, fontFileName, &face)) {
143 mode = ttFontModeCIDToGIDMap;
147 TTFontFile::~TTFontFile() {
154 //------------------------------------------------------------------------
156 TTFont::TTFont(TTFontFile *fontFileA, double *m) {
157 TTFontEngine *engine;
158 TT_Face_Properties props;
159 TT_Instance_Metrics metrics;
165 fontFile = fontFileA;
166 engine = fontFile->engine;
167 if (TT_New_Instance(fontFile->face, &instance) ||
168 TT_Set_Instance_Resolutions(instance, 72, 72) ||
169 TT_Set_Instance_CharSize(instance, 1000 * 64) ||
170 TT_New_Glyph(fontFile->face, &glyph) ||
171 TT_Get_Face_Properties(fontFile->face, &props) ||
172 TT_Get_Instance_Metrics(instance, &metrics)) {
176 // transform the four corners of the font bounding box -- the min
177 // and max values form the bounding box of the transformed font
178 x = (int)((m[0] * props.header->xMin + m[2] * props.header->yMin) *
179 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
181 y = (int)((m[1] * props.header->xMin + m[3] * props.header->yMin) *
182 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
184 x = (int)((m[0] * props.header->xMin + m[2] * props.header->yMax) *
185 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
188 } else if (x > xMax) {
191 y = (int)((m[1] * props.header->xMin + m[3] * props.header->yMax) *
192 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
195 } else if (y > yMax) {
198 x = (int)((m[0] * props.header->xMax + m[2] * props.header->yMin) *
199 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
202 } else if (x > xMax) {
205 y = (int)((m[1] * props.header->xMax + m[3] * props.header->yMin) *
206 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
209 } else if (y > yMax) {
212 x = (int)((m[0] * props.header->xMax + m[2] * props.header->yMax) *
213 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
216 } else if (x > xMax) {
219 y = (int)((m[1] * props.header->xMax + m[3] * props.header->yMax) *
220 0.001 * metrics.x_ppem / props.header->Units_Per_EM);
223 } else if (y > yMax) {
228 ras.width = xMax - xMin + 1;
229 ras.rows = yMax - yMin + 1;
231 // set up the Raster_Map structure
233 ras.width = (ras.width + 3) & ~3;
234 ras.cols = ras.width;
236 ras.width = (ras.width + 7) & ~7;
237 ras.cols = ras.width >> 3;
239 ras.flow = TT_Flow_Down;
240 ras.size = ras.rows * ras.cols;
241 ras.bitmap = gmalloc(ras.size);
243 // set up the glyph pixmap cache
245 if (ras.size <= 256) {
247 } else if (ras.size <= 512) {
249 } else if (ras.size <= 1024) {
254 cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * ras.size);
255 cacheTags = (TTFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
256 sizeof(TTFontCacheTag));
257 for (i = 0; i < cacheSets * cacheAssoc; ++i) {
258 cacheTags[i].mru = i & (cacheAssoc - 1);
262 if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
263 ZPixmap, 0, NULL, ras.width, ras.rows, 8, 0))) {
266 image->data = (char *)gmalloc(ras.rows * image->bytes_per_line);
268 // compute the transform matrix
269 matrix.xx = (TT_Fixed)(m[0] * 65.536);
270 matrix.yx = (TT_Fixed)(m[1] * 65.536);
271 matrix.xy = (TT_Fixed)(m[2] * 65.536);
272 matrix.yy = (TT_Fixed)(m[3] * 65.536);
282 XDestroyImage(image);
284 TT_Done_Glyph(glyph);
285 TT_Done_Instance(instance);
288 GBool TTFont::drawChar(Drawable d, int w, int h, GC gc,
289 int x, int y, int r, int g, int b,
290 CharCode c, Unicode u) {
291 TTFontEngine *engine;
298 int x0, y0, x1, y1, w0, h0;
300 engine = fontFile->engine;
302 // compute: (x0,y0) = position in destination drawable
303 // (x1,y1) = position in glyph image
304 // (w0,h0) = size of image transfer
306 y0 = y - (ras.rows - yOffset);
335 XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
336 ZPixmap, image, x1, y1);
338 // generate the glyph pixmap
339 if (!getGlyphPixmap(c, u)) {
345 // compute the colors
346 xcolor.pixel = XGetPixel(image, x1 + w0/2, y1 + h0/2);
347 XQueryColor(engine->display, engine->colormap, &xcolor);
351 colors[1] = engine->findColor((r + 3*bgR) / 4,
354 colors[2] = engine->findColor((r + bgR) / 2,
357 colors[3] = engine->findColor((3*r + bgR) / 4,
360 colors[4] = engine->findColor(r, g, b);
362 // stuff the glyph pixmap into the X image
363 p = (TT_Byte *)ras.bitmap;
364 for (yy = 0; yy < ras.rows; ++yy) {
365 for (xx = 0; xx < ras.width; ++xx) {
371 XPutPixel(image, xx, yy, colors[pix]);
379 colors[1] = engine->findColor(r, g, b);
381 // stuff the glyph bitmap into the X image
382 p = (TT_Byte *)ras.bitmap;
383 for (yy = 0; yy < ras.rows; ++yy) {
384 for (xx = 0; xx < ras.width; xx += 8) {
386 for (xx1 = xx; xx1 < xx + 8 && xx1 < ras.width; ++xx1) {
388 XPutPixel(image, xx1, yy, colors[1]);
398 XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0);
403 GBool TTFont::getGlyphPixmap(CharCode c, Unicode u) {
409 i = (c & (cacheSets - 1)) * cacheAssoc;
410 for (j = 0; j < cacheAssoc; ++j) {
411 if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
412 memcpy(ras.bitmap, cache + (i+j) * ras.size, ras.size);
413 for (k = 0; k < cacheAssoc; ++k) {
415 (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
416 ++cacheTags[i+k].mru;
419 cacheTags[i+j].mru = 0x8000;
424 // generate the glyph pixmap or bitmap
425 idx = 0; // make gcc happy
426 switch (fontFile->mode) {
427 case ttFontModeUnicode:
428 idx = TT_Char_Index(fontFile->charMap, (TT_UShort)u);
430 case ttFontModeCharCode:
431 if ((idx = TT_Char_Index(fontFile->charMap, (TT_UShort)c)) == 0) {
432 idx = TT_Char_Index(fontFile->charMap, (TT_UShort)(0xf000 + c));
435 case ttFontModeCodeMap:
437 idx = TT_Char_Index(fontFile->charMap,
438 (TT_UShort)(fontFile->codeMap[c] & 0xff));
443 case ttFontModeCIDToGIDMap:
444 if (fontFile->cidToGIDLen) {
445 if ((int)c < fontFile->cidToGIDLen) {
446 idx = (TT_UShort)fontFile->cidToGID[c];
455 if (TT_Load_Glyph(instance, glyph, idx, TTLOAD_DEFAULT) ||
456 TT_Get_Glyph_Outline(glyph, &outline)) {
459 TT_Transform_Outline(&outline, &matrix);
460 memset(ras.bitmap, 0, ras.size);
461 if (fontFile->engine->aa) {
462 if (TT_Get_Glyph_Pixmap(glyph, &ras, xOffset * 64, yOffset * 64)) {
466 if (TT_Get_Glyph_Bitmap(glyph, &ras, xOffset * 64, yOffset * 64)) {
471 // store glyph pixmap in cache
472 for (j = 0; j < cacheAssoc; ++j) {
473 if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
474 cacheTags[i+j].mru = 0x8000;
475 cacheTags[i+j].code = c;
476 memcpy(cache + (i+j) * ras.size, ras.bitmap, ras.size);
478 ++cacheTags[i+j].mru;
485 #endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)