filters

FTFont.cc

00001 //========================================================================
00002 //
00003 // FTFont.cc
00004 //
00005 // Copyright 2001-2002 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #include <aconf.h>
00010 
00011 #if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
00012 
00013 #ifdef USE_GCC_PRAGMAS
00014 #pragma implementation
00015 #endif
00016 
00017 #include <math.h>
00018 #include <string.h>
00019 #include "gmem.h"
00020 #include "freetype/ftoutln.h"
00021 #include "freetype/internal/ftobjs.h"
00022 #if 1 //~ cff cid->gid map
00023 #include "freetype/internal/cfftypes.h"
00024 #include "freetype/internal/tttypes.h"
00025 #endif
00026 #include "GlobalParams.h"
00027 #include "GfxState.h"
00028 #include "FTFont.h"
00029 
00030 //------------------------------------------------------------------------
00031 
00032 FTFontEngine::FTFontEngine(Display *displayA, Visual *visualA, int depthA,
00033                Colormap colormapA, GBool aaA):
00034   SFontEngine(displayA, visualA, depthA, colormapA) {
00035 
00036   ok = gFalse;
00037   if (FT_Init_FreeType(&lib)) {
00038     return;
00039   }
00040   aa = aaA;
00041   ok = gTrue;
00042 }
00043 
00044 FTFontEngine::~FTFontEngine() {
00045   FT_Done_FreeType(lib);
00046 }
00047 
00048 //------------------------------------------------------------------------
00049 
00050 FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName,
00051                char **fontEnc, GBool pdfFontHasEncoding) {
00052   char *name;
00053   int unicodeCmap, macRomanCmap, msSymbolCmap;
00054   int i, j;
00055 
00056   ok = gFalse;
00057   engine = engineA;
00058   codeMap = NULL;
00059   if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
00060     return;
00061   }
00062 
00063   if (!strcmp(face->driver->root.clazz->module_name, "type1") ||
00064       !strcmp(face->driver->root.clazz->module_name, "cff")) {
00065 
00066     mode = ftFontModeCodeMapDirect;
00067     codeMap = (Guint *)gmalloc(256 * sizeof(Guint));
00068     for (i = 0; i < 256; ++i) {
00069       codeMap[i] = 0;
00070       if ((name = fontEnc[i])) {
00071     codeMap[i] = FT_Get_Name_Index(face, name);
00072       }
00073     }
00074 
00075   } else {
00076 
00077     // To match up with the Adobe-defined behaviour, we choose a cmap
00078     // like this:
00079     // 1. If the PDF font has an encoding:
00080     //    1a. If the TrueType font has a Microsoft Unicode cmap, use it,
00081     //        and use the Unicode indexes, not the char codes.
00082     //    1b. If the TrueType font has a Macintosh Roman cmap, use it,
00083     //        and reverse map the char names through MacRomanEncoding to
00084     //        get char codes.
00085     // 2. If the PDF font does not have an encoding:
00086     //    2a. If the TrueType font has a Macintosh Roman cmap, use it,
00087     //        and use char codes directly.
00088     //    2b. If the TrueType font has a Microsoft Symbol cmap, use it,
00089     //        and use (0xf000 + char code).
00090     // 3. If none of these rules apply, use the first cmap and hope for
00091     //    the best (this shouldn't happen).
00092     unicodeCmap = macRomanCmap = msSymbolCmap = 0xffff;
00093     for (i = 0; i < face->num_charmaps; ++i) {
00094       if (face->charmaps[i]->platform_id == 3 &&
00095       face->charmaps[i]->encoding_id == 1) {
00096     unicodeCmap = i;
00097       } else if (face->charmaps[i]->platform_id == 1 &&
00098          face->charmaps[i]->encoding_id == 0) {
00099     macRomanCmap = i;
00100       } else if (face->charmaps[i]->platform_id == 3 &&
00101          face->charmaps[i]->encoding_id == 0) {
00102     msSymbolCmap = i;
00103       }
00104     }
00105     i = 0;
00106     mode = ftFontModeCharCode;
00107     charMapOffset = 0;
00108     if (pdfFontHasEncoding) {
00109       if (unicodeCmap != 0xffff) {
00110     i = unicodeCmap;
00111     mode = ftFontModeUnicode;
00112       } else if (macRomanCmap != 0xffff) {
00113     i = macRomanCmap;
00114     mode = ftFontModeCodeMap;
00115     codeMap = (Guint *)gmalloc(256 * sizeof(Guint));
00116     for (j = 0; j < 256; ++j) {
00117       if (fontEnc[j]) {
00118         codeMap[j] = globalParams->getMacRomanCharCode(fontEnc[j]);
00119       } else {
00120         codeMap[j] = 0;
00121       }
00122     }
00123       }
00124     } else {
00125       if (macRomanCmap != 0xffff) {
00126     i = macRomanCmap;
00127     mode = ftFontModeCharCode;
00128       } else if (msSymbolCmap != 0xffff) {
00129     i = msSymbolCmap;
00130     mode = ftFontModeCharCodeOffset;
00131     charMapOffset = 0xf000;
00132       }
00133     }
00134     if (FT_Set_Charmap(face, face->charmaps[i])) {
00135       return;
00136     }
00137   }
00138 
00139   ok = gTrue;
00140 }
00141 
00142 FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName,
00143                Gushort *cidToGIDA, int cidToGIDLenA) {
00144   ok = gFalse;
00145   engine = engineA;
00146   codeMap = NULL;
00147   if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
00148     return;
00149   }
00150   cidToGID = cidToGIDA;
00151   cidToGIDLen = cidToGIDLenA;
00152   mode = ftFontModeCIDToGIDMap;
00153   ok = gTrue;
00154 }
00155 
00156 FTFontFile::FTFontFile(FTFontEngine *engineA, char *fontFileName) {
00157   ok = gFalse;
00158   engine = engineA;
00159   codeMap = NULL;
00160   if (FT_New_Face(engine->lib, fontFileName, 0, &face)) {
00161     return;
00162   }
00163   cidToGID = NULL;
00164   cidToGIDLen = 0;
00165   mode = ftFontModeCFFCharset;
00166   ok = gTrue;
00167 }
00168 
00169 FTFontFile::~FTFontFile() {
00170   if (face) {
00171     FT_Done_Face(face);
00172   }
00173   if (codeMap) {
00174     gfree(codeMap);
00175   }
00176 }
00177 
00178 //------------------------------------------------------------------------
00179 
00180 FTFont::FTFont(FTFontFile *fontFileA, double *m) {
00181   FTFontEngine *engine;
00182   FT_Face face;
00183   double size, div;
00184   int x, xMin, xMax;
00185   int y, yMin, yMax;
00186   int i;
00187 
00188   ok = gFalse;
00189   fontFile = fontFileA;
00190   engine = fontFile->engine;
00191   face = fontFile->face;
00192   if (FT_New_Size(face, &sizeObj)) {
00193     return;
00194   }
00195   face->size = sizeObj;
00196   size = sqrt(m[2]*m[2] + m[3]*m[3]);
00197   if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
00198     return;
00199   }
00200 
00201   div = face->bbox.xMax > 20000 ? 65536 : 1;
00202 
00203   // transform the four corners of the font bounding box -- the min
00204   // and max values form the bounding box of the transformed font
00205   x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMin) /
00206         (div * face->units_per_EM));
00207   xMin = xMax = x;
00208   y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMin) /
00209         (div * face->units_per_EM));
00210   yMin = yMax = y;
00211   x = (int)((m[0] * face->bbox.xMin + m[2] * face->bbox.yMax) /
00212         (div * face->units_per_EM));
00213   if (x < xMin) {
00214     xMin = x;
00215   } else if (x > xMax) {
00216     xMax = x;
00217   }
00218   y = (int)((m[1] * face->bbox.xMin + m[3] * face->bbox.yMax) /
00219         (div * face->units_per_EM));
00220   if (y < yMin) {
00221     yMin = y;
00222   } else if (y > yMax) {
00223     yMax = y;
00224   }
00225   x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMin) /
00226         (div * face->units_per_EM));
00227   if (x < xMin) {
00228     xMin = x;
00229   } else if (x > xMax) {
00230     xMax = x;
00231   }
00232   y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMin) /
00233         (div * face->units_per_EM));
00234   if (y < yMin) {
00235     yMin = y;
00236   } else if (y > yMax) {
00237     yMax = y;
00238   }
00239   x = (int)((m[0] * face->bbox.xMax + m[2] * face->bbox.yMax) /
00240         (div * face->units_per_EM));
00241   if (x < xMin) {
00242     xMin = x;
00243   } else if (x > xMax) {
00244     xMax = x;
00245   }
00246   y = (int)((m[1] * face->bbox.xMax + m[3] * face->bbox.yMax) /
00247         (div * face->units_per_EM));
00248   if (y < yMin) {
00249     yMin = y;
00250   } else if (y > yMax) {
00251     yMax = y;
00252   }
00253   // This is a kludge: some buggy PDF generators embed fonts with
00254   // zero bounding boxes.
00255   if (xMax == xMin) {
00256     xMin = 0;
00257     xMax = (int)size;
00258   }
00259   if (yMax == yMin) {
00260     yMin = 0;
00261     yMax = (int)(1.2 * size);
00262   }
00263   // this should be (max - min + 1), but we add some padding to
00264   // deal with rounding errors, bogus bboxes, etc.
00265   glyphW = xMax - xMin + 3;
00266   glyphW += glyphW >> 1;
00267   glyphH = yMax - yMin + 3;
00268   glyphH += glyphH >> 1;
00269   if (engine->aa) {
00270     glyphSize = glyphW * glyphH;
00271   } else {
00272     glyphSize = ((glyphW + 7) >> 3) * glyphH;
00273   }
00274 
00275   // set up the glyph pixmap cache
00276   cacheAssoc = 8;
00277   if (glyphSize <= 256) {
00278     cacheSets = 8;
00279   } else if (glyphSize <= 512) {
00280     cacheSets = 4;
00281   } else if (glyphSize <= 1024) {
00282     cacheSets = 2;
00283   } else {
00284     cacheSets = 1;
00285   }
00286   cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
00287   cacheTags = (FTFontCacheTag *)gmalloc(cacheSets * cacheAssoc *
00288                     sizeof(FTFontCacheTag));
00289   for (i = 0; i < cacheSets * cacheAssoc; ++i) {
00290     cacheTags[i].mru = i & (cacheAssoc - 1);
00291   }
00292 
00293   // create the XImage
00294   if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
00295                  ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) {
00296     return;
00297   }
00298   image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
00299 
00300   // compute the transform matrix
00301   matrix.xx = (FT_Fixed)((m[0] / size) * 65536);
00302   matrix.yx = (FT_Fixed)((m[1] / size) * 65536);
00303   matrix.xy = (FT_Fixed)((m[2] / size) * 65536);
00304   matrix.yy = (FT_Fixed)((m[3] / size) * 65536);
00305 
00306   ok = gTrue;
00307 }
00308 
00309 FTFont::~FTFont() {
00310   gfree(cacheTags);
00311   gfree(cache);
00312   gfree(image->data);
00313   image->data = NULL;
00314   XDestroyImage(image);
00315 }
00316 
00317 GBool FTFont::drawChar(Drawable d, int w, int h, GC gc,
00318                int x, int y, int r, int g, int b,
00319                CharCode c, Unicode u) {
00320   FTFontEngine *engine;
00321   XColor xcolor;
00322   int bgR, bgG, bgB;
00323   Gulong colors[5];
00324   Guchar *p;
00325   int pix;
00326   int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;
00327   int xx, yy, xx1;
00328 
00329   engine = fontFile->engine;
00330 
00331   // no Unicode index for this char - don't draw anything
00332   if (fontFile->mode == ftFontModeUnicode && u == 0) {
00333     return gFalse;
00334   }
00335 
00336   // generate the glyph pixmap
00337   if (!(p = getGlyphPixmap(c, u, &xOffset, &yOffset, &gw, &gh))) {
00338     return gFalse;
00339   }
00340 
00341   // compute: (x0,y0) = position in destination drawable
00342   //          (x1,y1) = position in glyph image
00343   //          (w0,h0) = size of image transfer
00344   x0 = x - xOffset;
00345   y0 = y - yOffset;
00346   x1 = 0;
00347   y1 = 0;
00348   w0 = gw;
00349   h0 = gh;
00350   if (x0 < 0) {
00351     x1 = -x0;
00352     w0 += x0;
00353     x0 = 0;
00354   }
00355   if (x0 + w0 > w) {
00356     w0 = w - x0;
00357   }
00358   if (w0 < 0) {
00359     return gTrue;
00360   }
00361   if (y0 < 0) {
00362     y1 = -y0;
00363     h0 += y0;
00364     y0 = 0;
00365   }
00366   if (y0 + h0 > h) {
00367     h0 = h - y0;
00368   }
00369   if (h0 < 0) {
00370     return gTrue;
00371   }
00372 
00373   // read the X image
00374   XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
00375            ZPixmap, image, x1, y1);
00376 
00377   if (engine->aa) {
00378 
00379     // compute the colors
00380     xcolor.pixel = XGetPixel(image, x1 + w0/2, y1 + h0/2);
00381     XQueryColor(engine->display, engine->colormap, &xcolor);
00382     bgR = xcolor.red;
00383     bgG = xcolor.green;
00384     bgB = xcolor.blue;
00385     colors[1] = engine->findColor((r + 3*bgR) / 4,
00386                   (g + 3*bgG) / 4,
00387                   (b + 3*bgB) / 4);
00388     colors[2] = engine->findColor((r + bgR) / 2,
00389                   (g + bgG) / 2,
00390                   (b + bgB) / 2);
00391     colors[3] = engine->findColor((3*r + bgR) / 4,
00392                   (3*g + bgG) / 4,
00393                   (3*b + bgB) / 4);
00394     colors[4] = engine->findColor(r, g, b);
00395 
00396     // stuff the glyph pixmap into the X image
00397     for (yy = 0; yy < gh; ++yy) {
00398       for (xx = 0; xx < gw; ++xx) {
00399     pix = *p++ & 0xff;
00400     // this is a heuristic which seems to produce decent
00401     // results -- the linear mapping would be:
00402     // pix = (pix * 5) / 256;
00403     pix = ((pix + 10) * 5) / 256;
00404     if (pix > 4) {
00405       pix = 4;
00406     }
00407     if (pix > 0) {
00408       XPutPixel(image, xx, yy, colors[pix]);
00409     }
00410       }
00411     }
00412 
00413   } else {
00414 
00415     // one color
00416     colors[1] = engine->findColor(r, g, b);
00417 
00418     // stuff the glyph bitmap into the X image
00419     for (yy = 0; yy < gh; ++yy) {
00420       for (xx = 0; xx < gw; xx += 8) {
00421     pix = *p++;
00422     for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {
00423       if (pix & 0x80) {
00424         XPutPixel(image, xx1, yy, colors[1]);
00425       }
00426       pix <<= 1;
00427     }
00428       }
00429     }
00430 
00431   }
00432 
00433   // draw the X image
00434   XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0);
00435 
00436   return gTrue;
00437 }
00438 
00439 Guchar *FTFont::getGlyphPixmap(CharCode c, Unicode u,
00440                    int *x, int *y, int *w, int *h) {
00441   FT_GlyphSlot slot;
00442   FT_UInt idx;
00443   int rowSize;
00444   int i, j, k;
00445   Guchar *ret, *p, *q;
00446 
00447   // check the cache
00448   i = (c & (cacheSets - 1)) * cacheAssoc;
00449   for (j = 0; j < cacheAssoc; ++j) {
00450     if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
00451       *x = cacheTags[i+j].x;
00452       *y = cacheTags[i+j].y;
00453       *w = cacheTags[i+j].w;
00454       *h = cacheTags[i+j].h;
00455       for (k = 0; k < cacheAssoc; ++k) {
00456     if (k != j &&
00457         (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
00458       ++cacheTags[i+k].mru;
00459     }
00460       }
00461       cacheTags[i+j].mru = 0x8000;
00462       return cache + (i+j) * glyphSize;
00463     }
00464   }
00465 
00466   // generate the glyph pixmap or bitmap
00467   fontFile->face->size = sizeObj;
00468   FT_Set_Transform(fontFile->face, &matrix, NULL);
00469   slot = fontFile->face->glyph;
00470   idx = getGlyphIndex(c, u);
00471   // if we have the FT2 bytecode interpreter, autohinting won't be used
00472 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
00473   if (FT_Load_Glyph(fontFile->face, idx, FT_LOAD_DEFAULT)) {
00474     return gFalse;
00475   }
00476 #else
00477   // FT2's autohinting doesn't always work very well (especially with
00478   // font subsets), so turn it off if anti-aliasing is enabled; if
00479   // anti-aliasing is disabled, this seems to be a tossup - some fonts
00480   // look better with hinting, some without, so leave hinting on
00481   if (FT_Load_Glyph(fontFile->face, idx,
00482             fontFile->engine->aa ? FT_LOAD_NO_HINTING
00483                                  : FT_LOAD_DEFAULT)) {
00484     return gFalse;
00485   }
00486 #endif
00487   if (FT_Render_Glyph(slot,
00488               fontFile->engine->aa ? ft_render_mode_normal :
00489                                      ft_render_mode_mono)) {
00490     return gFalse;
00491   }
00492   *x = -slot->bitmap_left;
00493   *y = slot->bitmap_top;
00494   *w = slot->bitmap.width;
00495   *h = slot->bitmap.rows;
00496   if (*w > glyphW || *h > glyphH) {
00497 #if 1 //~ debug
00498     fprintf(stderr, "Weird FreeType glyph size: %d > %d or %d > %d\n",
00499         *w, glyphW, *h, glyphH);
00500 #endif
00501     return NULL;
00502   }
00503 
00504   // store glyph pixmap in cache
00505   ret = NULL;
00506   for (j = 0; j < cacheAssoc; ++j) {
00507     if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
00508       cacheTags[i+j].mru = 0x8000;
00509       cacheTags[i+j].code = c;
00510       cacheTags[i+j].x = *x;
00511       cacheTags[i+j].y = *y;
00512       cacheTags[i+j].w = *w;
00513       cacheTags[i+j].h = *h;
00514       if (fontFile->engine->aa) {
00515     rowSize = *w;
00516       } else {
00517     rowSize = (*w + 7) >> 3;
00518       }
00519       ret = cache + (i+j) * glyphSize;
00520       for (k = 0, p = ret, q = slot->bitmap.buffer;
00521        k < slot->bitmap.rows;
00522        ++k, p += rowSize, q += slot->bitmap.pitch) {
00523     memcpy(p, q, rowSize);
00524       }
00525     } else {
00526       ++cacheTags[i+j].mru;
00527     }
00528   }
00529   return ret;
00530 }
00531 
00532 GBool FTFont::getCharPath(CharCode c, Unicode u, GfxState *state) {
00533   static FT_Outline_Funcs outlineFuncs = {
00534     &charPathMoveTo,
00535     &charPathLineTo,
00536     &charPathConicTo,
00537     &charPathCubicTo,
00538     0, 0
00539   };
00540   FT_GlyphSlot slot;
00541   FT_UInt idx;
00542   FT_Glyph glyph;
00543 
00544   fontFile->face->size = sizeObj;
00545   FT_Set_Transform(fontFile->face, &matrix, NULL);
00546   slot = fontFile->face->glyph;
00547   idx = getGlyphIndex(c, u);
00548 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
00549   if (FT_Load_Glyph(fontFile->face, idx, FT_LOAD_DEFAULT)) {
00550     return gFalse;
00551   }
00552 #else
00553   // FT2's autohinting doesn't always work very well (especially with
00554   // font subsets), so turn it off if anti-aliasing is enabled; if
00555   // anti-aliasing is disabled, this seems to be a tossup - some fonts
00556   // look better with hinting, some without, so leave hinting on
00557   if (FT_Load_Glyph(fontFile->face, idx,
00558             fontFile->engine->aa ? FT_LOAD_NO_HINTING
00559                                  : FT_LOAD_DEFAULT)) {
00560     return gFalse;
00561   }
00562 #endif
00563   if (FT_Get_Glyph(slot, &glyph)) {
00564     return gFalse;
00565   }
00566   FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
00567                &outlineFuncs, state);
00568   return gTrue;
00569 }
00570 
00571 int FTFont::charPathMoveTo(FT_Vector *pt, void *state) {
00572   ((GfxState *)state)->moveTo(pt->x / 64.0, -pt->y / 64.0);
00573   return 0;
00574 }
00575 
00576 int FTFont::charPathLineTo(FT_Vector *pt, void *state) {
00577   ((GfxState *)state)->lineTo(pt->x / 64.0, -pt->y / 64.0);
00578   return 0;
00579 }
00580 
00581 int FTFont::charPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *state) {
00582   double x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
00583 
00584   x0 = ((GfxState *)state)->getCurX();
00585   y0 = ((GfxState *)state)->getCurY();
00586   xc = ctrl->x / 64.0;
00587   yc = -ctrl->y / 64.0;
00588   x3 = pt->x / 64.0;
00589   y3 = -pt->y / 64.0;
00590 
00591   // A second-order Bezier curve is defined by two endpoints, p0 and
00592   // p3, and one control point, pc:
00593   //
00594   //     p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3
00595   //
00596   // A third-order Bezier curve is defined by the same two endpoints,
00597   // p0 and p3, and two control points, p1 and p2:
00598   //
00599   //     p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3
00600   //
00601   // Applying some algebra, we can convert a second-order curve to a
00602   // third-order curve:
00603   //
00604   //     p1 = (1/3) * (p0 + 2pc)
00605   //     p2 = (1/3) * (2pc + p3)
00606 
00607   x1 = (1.0 / 3.0) * (x0 + 2 * xc);
00608   y1 = (1.0 / 3.0) * (y0 + 2 * yc);
00609   x2 = (1.0 / 3.0) * (2 * xc + x3);
00610   y2 = (1.0 / 3.0) * (2 * yc + y3);
00611 
00612   ((GfxState *)state)->curveTo(x1, y1, x2, y2, x3, y3);
00613   return 0;
00614 }
00615 
00616 int FTFont::charPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
00617                 FT_Vector *pt, void *state) {
00618   ((GfxState *)state)->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
00619                    ctrl2->x / 64.0, -ctrl2->y / 64.0,
00620                    pt->x / 64.0, -pt->y / 64.0);
00621   return 0;
00622 }
00623 
00624 FT_UInt FTFont::getGlyphIndex(CharCode c, Unicode u) {
00625   FT_UInt idx;
00626   int j;
00627 
00628   idx = 0; // make gcc happy
00629   switch (fontFile->mode) {
00630   case ftFontModeUnicode:
00631     idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)u);
00632     break;
00633   case ftFontModeCharCode:
00634     idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)c);
00635     break;
00636   case ftFontModeCharCodeOffset:
00637     idx = FT_Get_Char_Index(fontFile->face,
00638                 (FT_ULong)(c + fontFile->charMapOffset));
00639     break;
00640   case ftFontModeCodeMap:
00641     if (c <= 0xff) {
00642       idx = FT_Get_Char_Index(fontFile->face, (FT_ULong)fontFile->codeMap[c]);
00643     } else {
00644       idx = 0;
00645     }
00646     break;
00647   case ftFontModeCodeMapDirect:
00648     if (c <= 0xff) {
00649       idx = (FT_UInt)fontFile->codeMap[c];
00650     } else {
00651       idx = 0;
00652     }
00653     break;
00654   case ftFontModeCIDToGIDMap:
00655     if (fontFile->cidToGIDLen) {
00656       if ((int)c < fontFile->cidToGIDLen) {
00657     idx = (FT_UInt)fontFile->cidToGID[c];
00658       } else {
00659     idx = (FT_UInt)0;
00660       }
00661     } else {
00662       idx = (FT_UInt)c;
00663     }
00664     break;
00665   case ftFontModeCFFCharset:
00666 #if 1 //~ cff cid->gid map
00667 #if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0
00668     CFF_Font *cff = (CFF_Font *)((TT_Face)fontFile->face)->extra.data;
00669 #else
00670     CFF_Font cff = (CFF_Font)((TT_Face)fontFile->face)->extra.data;
00671 #endif
00672     idx = 0;
00673     for (j = 0; j < (int)cff->num_glyphs; ++j) {
00674       if (cff->charset.sids[j] == c) {
00675     idx = j;
00676     break;
00677       }
00678     }
00679 #endif
00680     break;
00681   }
00682   return idx;
00683 }
00684 
00685 #endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
KDE Home | KDE Accessibility Home | Description of Access Keys