summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc384
1 files changed, 384 insertions, 0 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc
new file mode 100644
index 00000000000..95f0e983a31
--- /dev/null
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/WebFont.cc
@@ -0,0 +1,384 @@
+//========================================================================
+//
+// WebFont.cc
+//
+// Copyright 2019 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "gmempp.h"
+#include "GHash.h"
+#include "FoFiTrueType.h"
+#include "FoFiType1C.h"
+#include "CharCodeToUnicode.h"
+#include "WebFont.h"
+
+WebFont::WebFont(GfxFont *gfxFontA, XRef *xref) {
+ GfxFontType type;
+
+ gfxFont = gfxFontA;
+ fontBuf = NULL;
+ ffTrueType = NULL;
+ ffType1C = NULL;
+ isOpenType = gFalse;
+
+ type = gfxFont->getType();
+ if (type == fontTrueType ||
+ type == fontTrueTypeOT ||
+ type == fontCIDType2 ||
+ type == fontCIDType2OT) {
+ if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) {
+ ffTrueType = FoFiTrueType::make(fontBuf, fontLength, 0);
+ }
+ } else if (type == fontType1C ||
+ type == fontCIDType0C) {
+ if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) {
+ ffType1C = FoFiType1C::make(fontBuf, fontLength);
+ }
+ } else if (type == fontType1COT ||
+ type == fontCIDType0COT) {
+ if ((fontBuf = gfxFont->readEmbFontFile(xref, &fontLength))) {
+ isOpenType = gTrue;
+ }
+ }
+}
+
+WebFont::~WebFont() {
+ delete ffTrueType;
+ delete ffType1C;
+ gfree(fontBuf);
+}
+
+GBool WebFont::canWriteTTF() {
+ return ffTrueType != NULL;
+}
+
+GBool WebFont::canWriteOTF() {
+ return ffType1C || isOpenType;
+}
+
+static void writeToFile(void *stream, const char *data, int len) {
+ fwrite(data, 1, len, (FILE *)stream);
+}
+
+GBool WebFont::writeTTF(const char *fontFilePath) {
+ FILE *out;
+ int *codeToGID;
+ Guchar *cmapTable;
+ GBool freeCodeToGID;
+ int nCodes, cmapTableLength;
+
+ if (!ffTrueType) {
+ return gFalse;
+ }
+ if (gfxFont->isCIDFont()) {
+ codeToGID = ((GfxCIDFont *)gfxFont)->getCIDToGID();
+ nCodes = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
+ if (!codeToGID) {
+ nCodes = ffTrueType->getNumGlyphs();
+ }
+ freeCodeToGID = gFalse;
+ } else {
+ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffTrueType);
+ nCodes = 256;
+ freeCodeToGID = gTrue;
+ }
+ cmapTable = makeUnicodeCmapTable(codeToGID, nCodes, &cmapTableLength);
+ if (freeCodeToGID) {
+ gfree(codeToGID);
+ }
+ if (!cmapTable) {
+ return gFalse;
+ }
+ if (!(out = fopen(fontFilePath, "wb"))) {
+ gfree(cmapTable);
+ return gFalse;
+ }
+ ffTrueType->writeTTF(writeToFile, out, NULL, NULL,
+ cmapTable, cmapTableLength);
+ fclose(out);
+ gfree(cmapTable);
+ return gTrue;
+}
+
+GBool WebFont::writeOTF(const char *fontFilePath) {
+ int *codeToGID;
+ Gushort *widths;
+ Guchar *cmapTable;
+ FILE *out;
+ int nCodes, nWidths, cmapTableLength;
+
+ if (ffType1C) {
+ if (gfxFont->getType() == fontType1C) {
+ codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ffType1C);
+ if (!(cmapTable = makeUnicodeCmapTable(codeToGID, 256,
+ &cmapTableLength))) {
+ gfree(codeToGID);
+ return gFalse;
+ }
+ widths = makeType1CWidths(codeToGID, 256, &nWidths);
+ gfree(codeToGID);
+ } else { // fontCIDType0C
+ codeToGID = ffType1C->getCIDToGIDMap(&nCodes);
+ if (!(cmapTable = makeUnicodeCmapTable(codeToGID, nCodes,
+ &cmapTableLength))) {
+ gfree(codeToGID);
+ return gFalse;
+ }
+ widths = makeCIDType0CWidths(codeToGID, nCodes, &nWidths);
+ gfree(codeToGID);
+ }
+ if (!(out = fopen(fontFilePath, "wb"))) {
+ gfree(cmapTable);
+ gfree(widths);
+ return gFalse;
+ }
+ ffType1C->convertToOpenType(writeToFile, out,
+ nWidths, widths,
+ cmapTable, cmapTableLength);
+ fclose(out);
+ gfree(cmapTable);
+ gfree(widths);
+
+ } else if (isOpenType) {
+ if (!(out = fopen(fontFilePath, "wb"))) {
+ return gFalse;
+ }
+ if (fwrite(fontBuf, 1, fontLength, out) != (Guint)fontLength) {
+ fclose(out);
+ return gFalse;
+ }
+ fclose(out);
+
+ } else {
+ return gFalse;
+ }
+
+ return gTrue;
+}
+
+Gushort *WebFont::makeType1CWidths(int *codeToGID, int nCodes,
+ int *nWidths) {
+ Gushort *widths;
+ Gushort width;
+ int widthsLen, gid, i;
+
+ widthsLen = ffType1C->getNumGlyphs();
+ widths = (Gushort *)gmallocn(widthsLen, sizeof(Gushort));
+ for (i = 0; i < widthsLen; ++i) {
+ widths[i] = 0;
+ }
+ for (i = 0; i < nCodes; ++i) {
+ gid = codeToGID[i];
+ if (gid < 0 || gid >= widthsLen) {
+ continue;
+ }
+ width = (Gushort)(((Gfx8BitFont *)gfxFont)->getWidth((Guchar)i)
+ * 1000 + 0.5);
+ if (width == 0) {
+ continue;
+ }
+ widths[gid] = width;
+ }
+ *nWidths = widthsLen;
+ return widths;
+}
+
+Gushort *WebFont::makeCIDType0CWidths(int *codeToGID, int nCodes,
+ int *nWidths) {
+ Gushort *widths;
+ Gushort width;
+ int widthsLen, gid, i;
+
+ widthsLen = ffType1C->getNumGlyphs();
+ widths = (Gushort *)gmallocn(widthsLen, sizeof(Gushort));
+ for (i = 0 ; i < widthsLen; ++i) {
+ widths[i] = 0;
+ }
+ for (i = 0; i < nCodes; ++i) {
+ gid = codeToGID[i];
+ if (gid < 0 || gid >= widthsLen) {
+ continue;
+ }
+ width = (Gushort)(((GfxCIDFont *)gfxFont)->getWidth((CID)i)
+ * 1000 + 0.5);
+ if (width == 0) {
+ continue;
+ }
+ widths[gid] = width;
+ }
+ *nWidths = widthsLen;
+ return widths;
+}
+
+Guchar *WebFont::makeUnicodeCmapTable(int *codeToGID, int nCodes,
+ int *unicodeCmapLength) {
+ int *unicodeToGID;
+ Guchar *cmapTable;
+ int unicodeToGIDLength, nMappings, len;
+ int nSegs, searchRange, entrySelector, rangeShift;
+ int glyphIdOffset, idRangeOffset;
+ int start, end, c, i;
+
+ if (!(unicodeToGID = makeUnicodeToGID(codeToGID, nCodes,
+ &unicodeToGIDLength))) {
+ return NULL;
+ }
+
+ // count the valid code-to-glyph mappings, and the sequences of
+ // consecutive valid mappings
+ // (note: char code 65535 is used to mark the end of table)
+ nMappings = 0;
+ nSegs = 1; // count the last segment, mapping 65535
+ for (c = 0; c < unicodeToGIDLength && c <= 65534; ++c) {
+ if (unicodeToGID[c]) {
+ ++nMappings;
+ if (c == 0 || !unicodeToGID[c-1]) {
+ ++nSegs;
+ }
+ }
+ }
+
+ i = 1;
+ entrySelector = 0;
+ while (2 * i <= nSegs) {
+ i *= 2;
+ ++entrySelector;
+ }
+ searchRange = 1 << (entrySelector + 1);
+ rangeShift = 2 * nSegs - searchRange;
+
+ len = 28 + nSegs * 8 + nMappings * 2;
+ cmapTable = (Guchar *)gmalloc(len);
+
+ // header
+ cmapTable[ 0] = 0x00; // table version
+ cmapTable[ 1] = 0x00;
+ cmapTable[ 2] = 0x00; // number of cmaps
+ cmapTable[ 3] = 0x01;
+ cmapTable[ 4] = 0x00; // platform[0]
+ cmapTable[ 5] = 0x03;
+ cmapTable[ 6] = 0x00; // encoding[0]
+ cmapTable[ 7] = 0x01;
+ cmapTable[ 8] = 0x00; // offset[0]
+ cmapTable[ 9] = 0x00;
+ cmapTable[10] = 0x00;
+ cmapTable[11] = 0x0c;
+
+ // table info
+ cmapTable[12] = 0x00; // cmap format
+ cmapTable[13] = 0x04;
+ cmapTable[14] = (Guchar)((len - 12) >> 8); // cmap length
+ cmapTable[15] = (Guchar)(len - 12);
+ cmapTable[16] = 0x00; // cmap version
+ cmapTable[17] = 0x00;
+ cmapTable[18] = (Guchar)(nSegs >> 7); // segCountX2
+ cmapTable[19] = (Guchar)(nSegs << 1);
+ cmapTable[20] = (Guchar)(searchRange >> 8); // searchRange
+ cmapTable[21] = (Guchar)searchRange;
+ cmapTable[22] = (Guchar)(entrySelector >> 8); // entrySelector
+ cmapTable[23] = (Guchar)entrySelector;
+ cmapTable[24] = (Guchar)(rangeShift >> 8); // rangeShift
+ cmapTable[25] = (Guchar)rangeShift;
+ cmapTable[26 + nSegs*2 ] = 0; // reservedPad
+ cmapTable[26 + nSegs*2 + 1] = 0;
+
+ i = 0;
+ glyphIdOffset = 28 + nSegs*8;
+ for (c = 0; c < unicodeToGIDLength && c <= 65534; ++c) {
+ if (unicodeToGID[c]) {
+ if (c == 0 || !unicodeToGID[c-1]) {
+ start = c;
+ cmapTable[28 + nSegs*2 + i*2 ] = (Guchar)(start >> 8);
+ cmapTable[28 + nSegs*2 + i*2 + 1] = (Guchar)start;
+ cmapTable[28 + nSegs*4 + i*2 ] = (Guchar)0; // idDelta
+ cmapTable[28 + nSegs*4 + i*2 + 1] = (Guchar)0;
+ idRangeOffset = glyphIdOffset - (28 + nSegs*6 + i*2);
+ cmapTable[28 + nSegs*6 + i*2 ] = (Guchar)(idRangeOffset >> 8);
+ cmapTable[28 + nSegs*6 + i*2 + 1] = (Guchar)idRangeOffset;
+ }
+ if (c == 65534 || !unicodeToGID[c+1]) {
+ end = c;
+ cmapTable[26 + i*2 ] = (Guchar)(end >> 8);
+ cmapTable[26 + i*2 + 1] = (Guchar)end;
+ ++i;
+ }
+ cmapTable[glyphIdOffset++] = (Guchar)(unicodeToGID[c] >> 8);
+ cmapTable[glyphIdOffset++] = (Guchar)unicodeToGID[c];
+ }
+ }
+
+ // last segment maps code 65535 to GID 0
+ cmapTable[26 + i*2 ] = (Guchar)0xff; // end
+ cmapTable[26 + i*2 + 1] = (Guchar)0xff;
+ cmapTable[28 + nSegs*2 + i*2 ] = (Guchar)0xff; // start
+ cmapTable[28 + nSegs*2 + i*2 + 1] = (Guchar)0xff;
+ cmapTable[28 + nSegs*4 + i*2 ] = (Guchar)0; // idDelta
+ cmapTable[28 + nSegs*4 + i*2 + 1] = (Guchar)1;
+ cmapTable[28 + nSegs*6 + i*2 ] = (Guchar)0; // idRangeOffset
+ cmapTable[28 + nSegs*6 + i*2 + 1] = (Guchar)0;
+
+ gfree(unicodeToGID);
+
+ *unicodeCmapLength = len;
+ return cmapTable;
+}
+
+int *WebFont::makeUnicodeToGID(int *codeToGID, int nCodes,
+ int *unicodeToGIDLength) {
+ int *unicodeToGID;
+ CharCodeToUnicode *ctu;
+ Unicode u[2];
+ int len, size, newSize, uLen, c, gid;
+
+ if (gfxFont->isCIDFont()) {
+ if (!(ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) {
+ return NULL;
+ }
+ } else {
+ ctu = ((Gfx8BitFont *)gfxFont)->getToUnicode();
+ }
+
+ len = 0;
+ size = 256;
+ unicodeToGID = (int *)gmallocn(size, sizeof(int));
+ memset(unicodeToGID, 0, size * sizeof(int));
+ for (c = 0; c < nCodes; ++c) {
+ gid = codeToGID ? codeToGID[c] : c;
+ if (gid < 0 || gid >= 65536) {
+ continue;
+ }
+ uLen = ctu->mapToUnicode(c, u, 2);
+ if (uLen != 1) {
+ continue;
+ }
+ if (u[0] >= 65536) { // sanity check
+ continue;
+ }
+ if ((int)u[0] >= size) {
+ newSize = 2 * size;
+ while ((int)u[0] >= newSize) {
+ newSize *= 2;
+ }
+ unicodeToGID = (int *)greallocn(unicodeToGID, newSize, sizeof(int));
+ memset(unicodeToGID + size, 0, (newSize - size) * sizeof(int));
+ size = newSize;
+ }
+ unicodeToGID[u[0]] = gid;
+ if ((int)u[0] >= len) {
+ len = u[0] + 1;
+ }
+ }
+
+ ctu->decRefCnt();
+
+ *unicodeToGIDLength = len;
+ return unicodeToGID;
+}