summaryrefslogtreecommitdiffstats
path: root/filters/kword/pdf/xpdf/xpdf/TTFont.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'filters/kword/pdf/xpdf/xpdf/TTFont.cpp')
-rw-r--r--filters/kword/pdf/xpdf/xpdf/TTFont.cpp480
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)