diff options
Diffstat (limited to 'filters/kword/pdf/xpdf/xpdf/TTFont.cpp')
-rw-r--r-- | filters/kword/pdf/xpdf/xpdf/TTFont.cpp | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/filters/kword/pdf/xpdf/xpdf/TTFont.cpp b/filters/kword/pdf/xpdf/xpdf/TTFont.cpp new file mode 100644 index 000000000..51761fbf1 --- /dev/null +++ b/filters/kword/pdf/xpdf/xpdf/TTFont.cpp @@ -0,0 +1,480 @@ +//======================================================================== +// +// TTFont.cpp +// +// 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 <string.h> +#include "gmem.h" +#include "GlobalParams.h" +#include "TTFont.h" + +//------------------------------------------------------------------------ + +TTFontEngine::TTFontEngine(Display *displayA, Visual *visualA, int depthA, + Colormap colormapA, GBool aaA): + SFontEngine(displayA, visualA, depthA, colormapA) { + static TT_Byte ttPalette[5] = {0, 1, 2, 3, 4}; + + ok = gFalse; + if (TT_Init_FreeType(&engine)) { + return; + } + aa = aaA; + if (aa) { + if (TT_Set_Raster_Gray_Palette(engine, ttPalette)) { + return; + } + } + ok = gTrue; +} + +TTFontEngine::~TTFontEngine() { + TT_Done_FreeType(engine); +} + +//------------------------------------------------------------------------ + +TTFontFile::TTFontFile(TTFontEngine *engineA, char *fontFileName, + char **fontEnc, GBool pdfFontHasEncoding) { + TT_Face_Properties props; + TT_UShort unicodeCmap, macRomanCmap, msSymbolCmap; + TT_UShort platform, encoding, i; + int j; + + ok = gFalse; + engine = engineA; + codeMap = NULL; + if (TT_Open_Face(engine->engine, fontFileName, &face)) { + return; + } + if (TT_Get_Face_Properties(face, &props)) { + return; + } + + // 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 < props.num_CharMaps; ++i) { + if (!TT_Get_CharMap_ID(face, i, &platform, &encoding)) { + if (platform == 3 && encoding == 1) { + unicodeCmap = i; + } else if (platform == 1 && encoding == 0) { + macRomanCmap = i; + } else if (platform == 3 && encoding == 0) { + msSymbolCmap = i; + } + } + } + i = 0; + mode = ttFontModeCharCode; + charMapOffset = 0; + if (pdfFontHasEncoding) { + if (unicodeCmap != 0xffff) { + i = unicodeCmap; + mode = ttFontModeUnicode; + } else if (macRomanCmap != 0xffff) { + i = macRomanCmap; + mode = ttFontModeCodeMap; + codeMap = (Guchar *)gmalloc(256 * sizeof(Guchar)); + for (j = 0; j < 256; ++j) { + if (fontEnc[j]) { + codeMap[j] = (Guchar)globalParams->getMacRomanCharCode(fontEnc[j]); + } else { + codeMap[j] = 0; + } + } + } + } else { + if (macRomanCmap != 0xffff) { + i = macRomanCmap; + mode = ttFontModeCharCode; + } else if (msSymbolCmap != 0xffff) { + i = msSymbolCmap; + mode = ttFontModeCharCodeOffset; + charMapOffset = 0xf000; + } + } + TT_Get_CharMap(face, i, &charMap); + + ok = gTrue; +} + +TTFontFile::TTFontFile(TTFontEngine *engineA, char *fontFileName, + Gushort *cidToGIDA, int cidToGIDLenA) { + ok = gFalse; + engine = engineA; + codeMap = NULL; + cidToGID = cidToGIDA; + cidToGIDLen = cidToGIDLenA; + if (TT_Open_Face(engine->engine, fontFileName, &face)) { + return; + } + mode = ttFontModeCIDToGIDMap; + ok = gTrue; +} + +TTFontFile::~TTFontFile() { + TT_Close_Face(face); + if (codeMap) { + gfree(codeMap); + } +} + +//------------------------------------------------------------------------ + +TTFont::TTFont(TTFontFile *fontFileA, double *m) { + TTFontEngine *engine; + TT_Face_Properties props; + TT_Instance_Metrics metrics; + int x, xMin, xMax; + int y, yMin, yMax; + int i; + + ok = gFalse; + fontFile = fontFileA; + engine = fontFile->engine; + if (TT_New_Instance(fontFile->face, &instance) || + TT_Set_Instance_Resolutions(instance, 72, 72) || + TT_Set_Instance_CharSize(instance, 1000 * 64) || + TT_New_Glyph(fontFile->face, &glyph) || + TT_Get_Face_Properties(fontFile->face, &props) || + TT_Get_Instance_Metrics(instance, &metrics)) { + return; + } + + // 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] * props.header->xMin + m[2] * props.header->yMin) * + 0.001 * metrics.x_ppem / props.header->Units_Per_EM); + xMin = xMax = x; + y = (int)((m[1] * props.header->xMin + m[3] * props.header->yMin) * + 0.001 * metrics.x_ppem / props.header->Units_Per_EM); + yMin = yMax = y; + x = (int)((m[0] * props.header->xMin + m[2] * props.header->yMax) * + 0.001 * metrics.x_ppem / props.header->Units_Per_EM); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)((m[1] * props.header->xMin + m[3] * props.header->yMax) * + 0.001 * metrics.x_ppem / props.header->Units_Per_EM); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + x = (int)((m[0] * props.header->xMax + m[2] * props.header->yMin) * + 0.001 * metrics.x_ppem / props.header->Units_Per_EM); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)((m[1] * props.header->xMax + m[3] * props.header->yMin) * + 0.001 * metrics.x_ppem / props.header->Units_Per_EM); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + x = (int)((m[0] * props.header->xMax + m[2] * props.header->yMax) * + 0.001 * metrics.x_ppem / props.header->Units_Per_EM); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)((m[1] * props.header->xMax + m[3] * props.header->yMax) * + 0.001 * metrics.x_ppem / props.header->Units_Per_EM); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + xOffset = -xMin; + yOffset = -yMin; + ras.width = xMax - xMin + 1; + ras.rows = yMax - yMin + 1; + + // set up the Raster_Map structure + if (engine->aa) { + ras.width = (ras.width + 3) & ~3; + ras.cols = ras.width; + } else { + ras.width = (ras.width + 7) & ~7; + ras.cols = ras.width >> 3; + } + ras.flow = TT_Flow_Down; + ras.size = ras.rows * ras.cols; + ras.bitmap = gmalloc(ras.size); + + // set up the glyph pixmap cache + cacheAssoc = 8; + if (ras.size <= 256) { + cacheSets = 8; + } else if (ras.size <= 512) { + cacheSets = 4; + } else if (ras.size <= 1024) { + cacheSets = 2; + } else { + cacheSets = 1; + } + cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * ras.size); + cacheTags = (TTFontCacheTag *)gmalloc(cacheSets * cacheAssoc * + sizeof(TTFontCacheTag)); + 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, ras.width, ras.rows, 8, 0))) { + return; + } + image->data = (char *)gmalloc(ras.rows * image->bytes_per_line); + + // compute the transform matrix + matrix.xx = (TT_Fixed)(m[0] * 65.536); + matrix.yx = (TT_Fixed)(m[1] * 65.536); + matrix.xy = (TT_Fixed)(m[2] * 65.536); + matrix.yy = (TT_Fixed)(m[3] * 65.536); + + ok = gTrue; +} + +TTFont::~TTFont() { + gfree(cacheTags); + gfree(cache); + gfree(image->data); + image->data = NULL; + XDestroyImage(image); + gfree(ras.bitmap); + TT_Done_Glyph(glyph); + TT_Done_Instance(instance); +} + +GBool TTFont::drawChar(Drawable d, int w, int h, GC gc, + int x, int y, int r, int g, int b, + CharCode c, Unicode u) { + TTFontEngine *engine; + XColor xcolor; + int bgR, bgG, bgB; + Gulong colors[5]; + TT_Byte *p; + TT_Byte pix; + int xx, yy, xx1; + int x0, y0, x1, y1, w0, h0; + + engine = fontFile->engine; + + // compute: (x0,y0) = position in destination drawable + // (x1,y1) = position in glyph image + // (w0,h0) = size of image transfer + x0 = x - xOffset; + y0 = y - (ras.rows - yOffset); + x1 = 0; + y1 = 0; + w0 = ras.width; + h0 = ras.rows; + if (x0 < 0) { + x1 = -x0; + w0 += x0; + x0 = 0; + } + if (x0 + w0 > w) { + w0 = w - x0; + } + if (w0 < 0) { + return gTrue; + } + if (y0 < 0) { + y1 = -y0; + h0 += y0; + y0 = 0; + } + if (y0 + h0 > h) { + h0 = h - y0; + } + if (h0 < 0) { + return gTrue; + } + + // read the X image + XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1, + ZPixmap, image, x1, y1); + + // generate the glyph pixmap + if (!getGlyphPixmap(c, u)) { + return gFalse; + } + + if (engine->aa) { + + // compute the colors + xcolor.pixel = XGetPixel(image, x1 + w0/2, y1 + h0/2); + XQueryColor(engine->display, engine->colormap, &xcolor); + bgR = xcolor.red; + bgG = xcolor.green; + bgB = xcolor.blue; + colors[1] = engine->findColor((r + 3*bgR) / 4, + (g + 3*bgG) / 4, + (b + 3*bgB) / 4); + colors[2] = engine->findColor((r + bgR) / 2, + (g + bgG) / 2, + (b + bgB) / 2); + colors[3] = engine->findColor((3*r + bgR) / 4, + (3*g + bgG) / 4, + (3*b + bgB) / 4); + colors[4] = engine->findColor(r, g, b); + + // stuff the glyph pixmap into the X image + p = (TT_Byte *)ras.bitmap; + for (yy = 0; yy < ras.rows; ++yy) { + for (xx = 0; xx < ras.width; ++xx) { + pix = *p++; + if (pix > 0) { + if (pix > 4) { + pix = 4; + } + XPutPixel(image, xx, yy, colors[pix]); + } + } + } + + } else { + + // one color + colors[1] = engine->findColor(r, g, b); + + // stuff the glyph bitmap into the X image + p = (TT_Byte *)ras.bitmap; + for (yy = 0; yy < ras.rows; ++yy) { + for (xx = 0; xx < ras.width; xx += 8) { + pix = *p++; + for (xx1 = xx; xx1 < xx + 8 && xx1 < ras.width; ++xx1) { + if (pix & 0x80) { + XPutPixel(image, xx1, yy, colors[1]); + } + pix <<= 1; + } + } + } + + } + + // draw the X image + XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0); + + return gTrue; +} + +GBool TTFont::getGlyphPixmap(CharCode c, Unicode u) { + TT_UShort idx; + TT_Outline outline; + int i, j, k; + + // check the cache + i = (c & (cacheSets - 1)) * cacheAssoc; + for (j = 0; j < cacheAssoc; ++j) { + if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) { + memcpy(ras.bitmap, cache + (i+j) * ras.size, ras.size); + for (k = 0; k < cacheAssoc; ++k) { + if (k != j && + (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) { + ++cacheTags[i+k].mru; + } + } + cacheTags[i+j].mru = 0x8000; + return gTrue; + } + } + + // generate the glyph pixmap or bitmap + idx = 0; // make gcc happy + switch (fontFile->mode) { + case ttFontModeUnicode: + idx = TT_Char_Index(fontFile->charMap, (TT_UShort)u); + break; + case ttFontModeCharCode: + idx = TT_Char_Index(fontFile->charMap, (TT_UShort)c); + break; + case ttFontModeCharCodeOffset: + idx = TT_Char_Index(fontFile->charMap, + (TT_UShort)(c + fontFile->charMapOffset)); + break; + case ttFontModeCodeMap: + if (c <= 0xff) { + idx = TT_Char_Index(fontFile->charMap, + (TT_UShort)(fontFile->codeMap[c] & 0xff)); + } else { + idx = 0; + } + break; + case ttFontModeCIDToGIDMap: + if (fontFile->cidToGIDLen) { + if ((int)c < fontFile->cidToGIDLen) { + idx = (TT_UShort)fontFile->cidToGID[c]; + } else { + idx = (TT_UShort)0; + } + } else { + idx = (TT_UShort)c; + } + break; + } + if (TT_Load_Glyph(instance, glyph, idx, TTLOAD_DEFAULT) || + TT_Get_Glyph_Outline(glyph, &outline)) { + return gFalse; + } + TT_Transform_Outline(&outline, &matrix); + memset(ras.bitmap, 0, ras.size); + if (fontFile->engine->aa) { + if (TT_Get_Glyph_Pixmap(glyph, &ras, xOffset * 64, yOffset * 64)) { + return gFalse; + } + } else { + if (TT_Get_Glyph_Bitmap(glyph, &ras, xOffset * 64, yOffset * 64)) { + return gFalse; + } + } + + // store glyph pixmap in cache + for (j = 0; j < cacheAssoc; ++j) { + if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) { + cacheTags[i+j].mru = 0x8000; + cacheTags[i+j].code = c; + memcpy(cache + (i+j) * ras.size, ras.bitmap, ras.size); + } else { + ++cacheTags[i+j].mru; + } + } + + return gTrue; +} + +#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H) |