From 8b78a8791bc539bcffe7159f9d9714d577cb3d7d Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 23 May 2021 20:48:35 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro --- filters/kword/pdf/xpdf/xpdf/T1Font.cpp | 535 +++++++++++++++++++++++++++++++++ 1 file changed, 535 insertions(+) create mode 100644 filters/kword/pdf/xpdf/xpdf/T1Font.cpp (limited to 'filters/kword/pdf/xpdf/xpdf/T1Font.cpp') diff --git a/filters/kword/pdf/xpdf/xpdf/T1Font.cpp b/filters/kword/pdf/xpdf/xpdf/T1Font.cpp new file mode 100644 index 000000000..350f7bd66 --- /dev/null +++ b/filters/kword/pdf/xpdf/xpdf/T1Font.cpp @@ -0,0 +1,535 @@ +//======================================================================== +// +// T1Font.cpp +// +// Copyright 2001-2002 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#if HAVE_T1LIB_H + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#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 -- cgit v1.2.3