⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t1font.cc

📁 source code: Covert TXT to PDF
💻 CC
字号:
//========================================================================//// T1Font.cc//// Copyright 2001-2002 Glyph & Cog, LLC////========================================================================#include <aconf.h>#if HAVE_T1LIB_H#ifdef USE_GCC_PRAGMAS#pragma implementation#endif#include <math.h>#include <string.h>#include <X11/Xlib.h>#include "gmem.h"#include "GfxState.h"#include "T1Font.h"//------------------------------------------------------------------------int T1FontEngine::t1libInitCount = 0;//------------------------------------------------------------------------T1FontEngine::T1FontEngine(Display *displayA, Visual *visualA, int depthA,			   Colormap colormapA, GBool aaA, GBool aaHighA):  SFontEngine(displayA, visualA, depthA, colormapA){  static unsigned long grayVals[17] = {    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16  };  ok = gFalse;  aa = aaA;  aaHigh = aaHighA;  //~ for multithreading: need a mutex here  if (t1libInitCount == 0) {    T1_SetBitmapPad(8);    if (!T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE |		    T1_NO_AFM)) {      return;    }    if (aa) {      T1_AASetBitsPerPixel(8);      if (aaHigh) {	T1_AASetLevel(T1_AA_HIGH);	T1_AAHSetGrayValues(grayVals);      } else {	T1_AASetLevel(T1_AA_LOW);	T1_AASetGrayValues(0, 1, 2, 3, 4);      }    } else {      T1_AANSetGrayValues(0, 1);    }  }  ++t1libInitCount;  ok = gTrue;}T1FontEngine::~T1FontEngine() {  //~ for multithreading: need a mutex here  if (--t1libInitCount == 0) {    T1_CloseLib();  }}//------------------------------------------------------------------------T1FontFile::T1FontFile(T1FontEngine *engineA, char *fontFileName,		       char **fontEnc, double *bboxA) {  int encStrSize;  char *encPtr;  int i;  ok = gFalse;  engine = engineA;  enc = NULL;  encStr = NULL;  for (i = 0; i < 4; ++i) {    bbox[i] = bboxA[i];  }  // load the font file  if ((id = T1_AddFont(fontFileName)) < 0) {    return;  }  T1_LoadFont(id);  // reencode it  encStrSize = 0;  for (i = 0; i < 256; ++i) {    if (fontEnc[i]) {      encStrSize += strlen(fontEnc[i]) + 1;    }  }  enc = (char **)gmalloc(257 * sizeof(char *));  encStr = (char *)gmalloc(encStrSize * sizeof(char));  encPtr = encStr;  for (i = 0; i < 256; ++i) {    if (fontEnc[i]) {      strcpy(encPtr, fontEnc[i]);      enc[i] = encPtr;      encPtr += strlen(encPtr) + 1;    } else {      enc[i] = ".notdef";    }  }  enc[256] = "custom";  T1_ReencodeFont(id, enc);  ok = gTrue;}T1FontFile::~T1FontFile() {  gfree(enc);  gfree(encStr);  if (id >= 0) {    T1_DeleteFont(id);  }}//------------------------------------------------------------------------T1Font::T1Font(T1FontFile *fontFileA, double *m) {  T1FontEngine *engine;  T1_TMATRIX matrix;  BBox bbox;  double bbx0, bby0, bbx1, bby1;  int x, y, xMin, xMax, yMin, yMax;  int i;  ok = gFalse;  fontFile = fontFileA;  engine = fontFile->engine;  id = T1_CopyFont(fontFile->id);  // compute font size  size = (float)sqrt(m[2]*m[2] + m[3]*m[3]);  // transform the four corners of the font bounding box -- the min  // and max values form the bounding box of the transformed font  bbx0 = fontFile->bbox[0];  bby0 = fontFile->bbox[1];  bbx1 = fontFile->bbox[2];  bby1 = fontFile->bbox[3];  // some fonts in PDF files have bboxes which are just plain wrong,  // so we check the font file's bbox too  bbox = T1_GetFontBBox(id);  if (0.001 * bbox.llx < bbx0) {    bbx0 = 0.001 * bbox.llx;  }  if (0.001 * bbox.lly < bby0) {    bby0 = 0.001 * bbox.lly;  }  if (0.001 * bbox.urx > bbx1) {    bbx1 = 0.001 * bbox.urx;  }  if (0.001 * bbox.ury > bby1) {    bby1 = 0.001 * bbox.ury;  }  // some fonts are completely broken, so we fake it (with values  // large enough that most glyphs should fit)  if (bbx0 == 0 && bby0 == 0 && bbx1 == 0 && bby1 == 0) {    bbx0 = bby0 = -0.5;    bbx1 = bby1 = 1.5;  }  x = (int)(m[0] * bbx0 + m[2] * bby0);  xMin = xMax = x;  y = (int)(m[1] * bbx0 + m[3] * bby0);  yMin = yMax = y;  x = (int)(m[0] * bbx0 + m[2] * bby1);  if (x < xMin) {    xMin = x;  } else if (x > xMax) {    xMax = x;  }  y = (int)(m[1] * bbx0 + m[3] * bby1);  if (y < yMin) {    yMin = y;  } else if (y > yMax) {    yMax = y;  }  x = (int)(m[0] * bbx1 + m[2] * bby0);  if (x < xMin) {    xMin = x;  } else if (x > xMax) {    xMax = x;  }  y = (int)(m[1] * bbx1 + m[3] * bby0);  if (y < yMin) {    yMin = y;  } else if (y > yMax) {    yMax = y;  }  x = (int)(m[0] * bbx1 + m[2] * bby1);  if (x < xMin) {    xMin = x;  } else if (x > xMax) {    xMax = x;  }  y = (int)(m[1] * bbx1 + m[3] * bby1);  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);  }  // Another kludge: an unusually large xMin or yMin coordinate is  // probably wrong.  if (xMin > 0) {    xMin = 0;  }  if (yMin > 0) {    yMin = 0;  }  // Another kludge: t1lib doesn't correctly handle fonts with  // real (non-integer) bounding box coordinates.  if (xMax - xMin > 5000) {    xMin = 0;    xMax = (int)size;  }  if (yMax - yMin > 5000) {    yMin = 0;    yMax = (int)(1.2 * size);  }  // this should be (max - min + 1), but we add some padding to  // deal with rounding errors  glyphW = xMax - xMin + 3;  glyphH = yMax - yMin + 3;  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 = (T1FontCacheTag *)gmalloc(cacheSets * cacheAssoc *					sizeof(T1FontCacheTag));  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);  // transform the font  matrix.cxx = m[0] / size;  matrix.cxy = m[1] / size;  matrix.cyx = m[2] / size;  matrix.cyy = m[3] / size;  T1_TransformFont(id, &matrix);  ok = gTrue;}T1Font::~T1Font() {  gfree(cacheTags);  gfree(cache);  if (image) {    gfree(image->data);    image->data = NULL;    XDestroyImage(image);  }  T1_DeleteFont(id);}GBool T1Font::drawChar(Drawable d, int w, int h, GC gc,		       int x, int y, int r, int g, int b,		       CharCode c, Unicode u) {  T1FontEngine *engine;  XColor xcolor;  int bgR, bgG, bgB;  Gulong colors[17];  Guchar *p;  int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;  int xx, yy, xx1;  Guchar pix, mPix;  int i;  engine = fontFile->engine;  // generate the glyph pixmap  if (!(p = getGlyphPixmap(c, &xOffset, &yOffset, &gw, &gh))) {    return gFalse;  }  // compute: (x0,y0) = position in destination drawable  //          (x1,y1) = position in glyph image  //          (w0,h0) = size of image transfer  x0 = x - xOffset;  y0 = y - yOffset;  x1 = 0;  y1 = 0;  w0 = gw;  h0 = gh;  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);  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;    if (engine->aaHigh) {      mPix = 16;      for (i = 1; i <= 16; ++i) {	colors[i] = engine->findColor((i * r + (16 - i) * bgR) / 16,				      (i * g + (16 - i) * bgG) / 16,				      (i * b + (16 - i) * bgB) / 16);      }    } else {      mPix = 4;      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    for (yy = 0; yy < gh; ++yy) {      for (xx = 0; xx < gw; ++xx) {	pix = *p++;	if (pix > 0) {	  if (pix > mPix) {	    pix = mPix;	  }	  XPutPixel(image, xx, yy, colors[pix]);	}      }    }  } else {    // one color    colors[1] = engine->findColor(r, g, b);    // stuff the glyph bitmap into the X image    for (yy = 0; yy < gh; ++yy) {      for (xx = 0; xx < gw; xx += 8) {	pix = *p++;	for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {	  if (pix & 0x01) {	    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;}Guchar *T1Font::getGlyphPixmap(CharCode c, int *x, int *y, int *w, int *h) {  T1FontEngine *engine;  GLYPH *glyph;  int gSize;  int i, j, k;  Guchar *ret;  engine = fontFile->engine;  // 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) {      *x = cacheTags[i+j].x;      *y = cacheTags[i+j].y;      *w = cacheTags[i+j].w;      *h = cacheTags[i+j].h;      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 cache + (i+j) * glyphSize;    }  }  // generate the glyph pixmap  if (engine->aa) {    glyph = T1_AASetChar(id, c, size, NULL);  } else {    glyph = T1_SetChar(id, c, size, NULL);  }  if (!glyph) {    return NULL;  }  *x = -glyph->metrics.leftSideBearing;  *y = glyph->metrics.ascent;  *w = glyph->metrics.rightSideBearing - glyph->metrics.leftSideBearing;  *h = glyph->metrics.ascent - glyph->metrics.descent;  if (*w > glyphW || *h > glyphH) {#if 1 //~ debug    fprintf(stderr, "Weird t1lib glyph size: %d > %d or %d > %d\n",	    *w, glyphW, *h, glyphH);#endif    return NULL;  }  // store glyph pixmap in cache  ret = NULL;  for (j = 0; j < cacheAssoc; ++j) {    if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {      cacheTags[i+j].mru = 0x8000;      cacheTags[i+j].code = c;      cacheTags[i+j].x = *x;      cacheTags[i+j].y = *y;      cacheTags[i+j].w = *w;      cacheTags[i+j].h = *h;      if (engine->aa) {	gSize = *w * *h;      } else {	gSize = ((*w + 7) >> 3) * *h;      }      ret = cache + (i+j) * glyphSize;      if (glyph->bits) {	memcpy(ret, glyph->bits, gSize);      } else {	memset(ret, 0, gSize);      }    } else {      ++cacheTags[i+j].mru;    }  }  return ret;}GBool T1Font::getCharPath(CharCode c, Unicode u, GfxState *state) {  T1_OUTLINE *outline;  T1_PATHSEGMENT *seg;  T1_BEZIERSEGMENT *bez;  double x, y, x1, y1;  outline = T1_GetCharOutline(id, c, size, NULL);  x = 0;  y = 0;  for (seg = outline; seg; seg = seg->link) {    switch (seg->type) {    case T1_PATHTYPE_MOVE:      x += seg->dest.x / 65536.0;      y += seg->dest.y / 65536.0;      state->moveTo(x, y);      break;    case T1_PATHTYPE_LINE:      x += seg->dest.x / 65536.0;      y += seg->dest.y / 65536.0;      state->lineTo(x, y);      break;    case T1_PATHTYPE_BEZIER:      bez = (T1_BEZIERSEGMENT *)seg;      x1 = x + bez->dest.x / 65536.0;      y1 = y + bez->dest.y / 65536.0;      state->curveTo(x + bez->B.x / 65536.0, y + bez->B.y / 65536.0,		     x + bez->C.x / 65536.0, y + bez->C.y / 65536.0,		     x1, y1);      x = x1;      y = y1;      break;    }  }  T1_FreeOutline(outline);  return gTrue;}#endif // HAVE_T1LIB_H

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -