📄 fontfile.cc
字号:
//========================================================================//// FontFile.cc//// Copyright 1999-2002 Glyph & Cog, LLC////========================================================================#include <aconf.h>#ifdef USE_GCC_PRAGMAS#pragma implementation#endif#include <math.h>#include <stdlib.h>#include <stddef.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include "gmem.h"#include "Error.h"#include "GlobalParams.h"#include "CharCodeToUnicode.h"#include "FontEncodingTables.h"#include "FontFile.h"#include "CompactFontTables.h"//------------------------------------------------------------------------static inline char *nextLine(char *line, char *end) { while (line < end && *line != '\n' && *line != '\r') ++line; while (line < end && *line == '\n' || *line == '\r') ++line; return line;}static char hexChars[17] = "0123456789ABCDEF";//------------------------------------------------------------------------// FontFile//------------------------------------------------------------------------FontFile::FontFile() {}FontFile::~FontFile() {}//------------------------------------------------------------------------// Type1FontFile//------------------------------------------------------------------------Type1FontFile::Type1FontFile(char *file, int len) { char *line, *line1, *p, *p2; GBool haveEncoding; char buf[256]; char c; int n, code, i, j; name = NULL; encoding = (char **)gmalloc(256 * sizeof(char *)); for (i = 0; i < 256; ++i) { encoding[i] = NULL; } haveEncoding = gFalse; for (i = 1, line = file; i <= 100 && line < file + len && !haveEncoding; ++i) { // get font name if (!strncmp(line, "/FontName", 9)) { strncpy(buf, line, 255); buf[255] = '\0'; if ((p = strchr(buf+9, '/')) && (p = strtok(p+1, " \t\n\r"))) { name = copyString(p); } line = nextLine(line, file + len); // get encoding } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) { for (j = 0; j < 256; ++j) { if (standardEncoding[j]) { encoding[j] = copyString(standardEncoding[j]); } } haveEncoding = gTrue; } else if (!strncmp(line, "/Encoding 256 array", 19)) { for (j = 0; j < 300; ++j) { line1 = nextLine(line, file + len); if ((n = line1 - line) > 255) { n = 255; } strncpy(buf, line, n); buf[n] = '\0'; for (p = buf; *p == ' ' || *p == '\t'; ++p) ; if (!strncmp(p, "dup", 3)) { for (p += 3; *p == ' ' || *p == '\t'; ++p) ; for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ; if (*p2) { c = *p2; *p2 = '\0'; if ((code = atoi(p)) < 256) { *p2 = c; for (p = p2; *p == ' ' || *p == '\t'; ++p) ; if (*p == '/') { ++p; for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ; *p2 = '\0'; encoding[code] = copyString(p); } } } } else { if (strtok(buf, " \t") && (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) { break; } } line = line1; } //~ check for getinterval/putinterval junk haveEncoding = gTrue; } else { line = nextLine(line, file + len); } }}Type1FontFile::~Type1FontFile() { int i; if (name) { gfree(name); } for (i = 0; i < 256; ++i) { gfree(encoding[i]); } gfree(encoding);}//------------------------------------------------------------------------// Type1CFontFile//------------------------------------------------------------------------struct Type1CTopDict { int version; int notice; int copyright; int fullName; int familyName; int weight; int isFixedPitch; double italicAngle; double underlinePosition; double underlineThickness; int paintType; int charstringType; double fontMatrix[6]; int uniqueID; double fontBBox[4]; double strokeWidth; int charset; int encoding; int charStrings; int privateSize; int privateOffset; //----- CIDFont entries int registry; int ordering; int supplement; int fdArrayOffset; int fdSelectOffset;};struct Type1CPrivateDict { GString *dictData; int subrsOffset; double defaultWidthX; GBool defaultWidthXFP; double nominalWidthX; GBool nominalWidthXFP;};Type1CFontFile::Type1CFontFile(char *fileA, int lenA) { Guchar *nameIdxPtr, *idxPtr0, *idxPtr1; file = fileA; len = lenA; name = NULL; encoding = NULL; // some tools embed Type 1C fonts with an extra whitespace char at // the beginning if (file[0] != '\x01') { ++file; } // read header topOffSize = file[3] & 0xff; // read name index (first font only) nameIdxPtr = (Guchar *)file + (file[2] & 0xff); idxPtr0 = getIndexValPtr(nameIdxPtr, 0); idxPtr1 = getIndexValPtr(nameIdxPtr, 1); name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0); topDictIdxPtr = getIndexEnd(nameIdxPtr); stringIdxPtr = getIndexEnd(topDictIdxPtr); gsubrIdxPtr = getIndexEnd(stringIdxPtr);}Type1CFontFile::~Type1CFontFile() { int i; delete name; if (encoding) { for (i = 0; i < 256; ++i) { gfree(encoding[i]); } gfree(encoding); }}char *Type1CFontFile::getName() { return name->getCString();}char **Type1CFontFile::getEncoding() { if (!encoding) { readNameAndEncoding(); } return encoding;}void Type1CFontFile::readNameAndEncoding() { char buf[256]; Guchar *idxPtr0, *idxPtr1, *ptr; int nGlyphs; int nCodes, nRanges, nLeft, nSups; Gushort *glyphNames; int charset, enc, charstrings; int encFormat; int c, sid; double x; GBool isFP; int key; int i, j; encoding = (char **)gmalloc(256 * sizeof(char *)); for (i = 0; i < 256; ++i) { encoding[i] = NULL; } // read top dict (first font only) idxPtr0 = getIndexValPtr(topDictIdxPtr, 0); idxPtr1 = getIndexValPtr(topDictIdxPtr, 1); charset = enc = charstrings = 0; i = 0; ptr = idxPtr0; while (ptr < idxPtr1) { if (*ptr <= 27 || *ptr == 31) { key = *ptr++; if (key == 0x0c) { key = (key << 8) | *ptr++; } if (key == 0x0f) { // charset charset = (int)op[0]; } else if (key == 0x10) { // encoding enc = (int)op[0]; } else if (key == 0x11) { // charstrings charstrings = (int)op[0]; } i = 0; } else { x = getNum(&ptr, &isFP); if (i < 48) { op[i++] = x; } } } // get number of glyphs from charstrings index nGlyphs = getIndexLen((Guchar *)file + charstrings); // read charset (GID -> name mapping) glyphNames = readCharset(charset, nGlyphs); // read encoding (GID -> code mapping) if (enc == 0) { for (i = 0; i < 256; ++i) { if (standardEncoding[i]) { encoding[i] = copyString(standardEncoding[i]); } } } else if (enc == 1) { for (i = 0; i < 256; ++i) { if (expertEncoding[i]) { encoding[i] = copyString(expertEncoding[i]); } } } else { ptr = (Guchar *)file + enc; encFormat = *ptr++; if ((encFormat & 0x7f) == 0) { nCodes = 1 + *ptr++; if (nCodes > nGlyphs) { nCodes = nGlyphs; } for (i = 1; i < nCodes; ++i) { c = *ptr++; encoding[c] = copyString(getString(glyphNames[i], buf)); } } else if ((encFormat & 0x7f) == 1) { nRanges = *ptr++; nCodes = 1; for (i = 0; i < nRanges; ++i) { c = *ptr++; nLeft = *ptr++; for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) { encoding[c] = copyString(getString(glyphNames[nCodes], buf)); ++nCodes; ++c; } } } if (encFormat & 0x80) { nSups = *ptr++; for (i = 0; i < nSups; ++i) { c = *ptr++; sid = getWord(ptr, 2); ptr += 2; encoding[c] = copyString(getString(sid, buf)); } } } if (charset > 2) { gfree(glyphNames); }}void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA, void *outputStreamA) { Type1CTopDict dict; Type1CPrivateDict privateDict; char buf[512], eBuf[256]; Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr; int nGlyphs, nCodes, nRanges, nLeft, nSups; Gushort *glyphNames; int encFormat, nSubrs, nCharStrings; int c, sid; int i, j, n; outputFunc = outputFuncA; outputStream = outputStreamA; // read top dict (first font only) readTopDict(&dict); // get global subrs //~ ... global subrs are unimplemented // write header and font dictionary, up to encoding (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17); (*outputFunc)(outputStream, name->getCString(), name->getLength()); if (dict.version != 0) { getString(dict.version, buf); (*outputFunc)(outputStream, buf, strlen(buf)); } (*outputFunc)(outputStream, "\n", 1); (*outputFunc)(outputStream, "11 dict begin\n", 14); (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28); if (dict.version != 0) { (*outputFunc)(outputStream, "/version (", 10); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, ") readonly def\n", 15); } if (dict.notice != 0) { getString(dict.notice, buf); (*outputFunc)(outputStream, "/Notice (", 9); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, ") readonly def\n", 15); } if (dict.copyright != 0) { getString(dict.copyright, buf); (*outputFunc)(outputStream, "/Copyright (", 12); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, ") readonly def\n", 15); } if (dict.fullName != 0) { getString(dict.fullName, buf); (*outputFunc)(outputStream, "/FullName (", 11); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, ") readonly def\n", 15); } if (dict.familyName != 0) { getString(dict.familyName, buf); (*outputFunc)(outputStream, "/FamilyName (", 13); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, ") readonly def\n", 15); } if (dict.weight != 0) { getString(dict.weight, buf); (*outputFunc)(outputStream, "/Weight (", 9); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, ") readonly def\n", 15); } if (dict.isFixedPitch) { (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23); } else { (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24); } sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle); (*outputFunc)(outputStream, buf, strlen(buf)); sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition); (*outputFunc)(outputStream, buf, strlen(buf)); sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, "end readonly def\n", 17); (*outputFunc)(outputStream, "/FontName /", 11); (*outputFunc)(outputStream, name->getCString(), name->getLength()); (*outputFunc)(outputStream, " def\n", 5); sprintf(buf, "/PaintType %d def\n", dict.paintType); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, "/FontType 1 def\n", 16); sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n", dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2], dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]); (*outputFunc)(outputStream, buf, strlen(buf)); sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n", dict.fontBBox[0], dict.fontBBox[1], dict.fontBBox[2], dict.fontBBox[3]); (*outputFunc)(outputStream, buf, strlen(buf)); sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth); (*outputFunc)(outputStream, buf, strlen(buf)); if (dict.uniqueID != 0) { sprintf(buf, "/UniqueID %d def\n", dict.uniqueID); (*outputFunc)(outputStream, buf, strlen(buf)); } // get number of glyphs from charstrings index nGlyphs = getIndexLen((Guchar *)file + dict.charStrings); // read charset glyphNames = readCharset(dict.charset, nGlyphs); // read encoding (glyph -> code mapping), write Type 1 encoding (*outputFunc)(outputStream, "/Encoding ", 10); if (dict.encoding == 0) { (*outputFunc)(outputStream, "StandardEncoding def\n", 21); } else { (*outputFunc)(outputStream, "256 array\n", 10); (*outputFunc)(outputStream, "0 1 255 {1 index exch /.notdef put} for\n", 40); if (dict.encoding == 1) { for (i = 0; i < 256; ++i) { if (expertEncoding[i]) { sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]); (*outputFunc)(outputStream, buf, strlen(buf)); } } } else { ptr = (Guchar *)file + dict.encoding; encFormat = *ptr++; if ((encFormat & 0x7f) == 0) { nCodes = 1 + *ptr++; if (nCodes > nGlyphs) { nCodes = nGlyphs; } for (i = 1; i < nCodes; ++i) { c = *ptr++; sprintf(buf, "dup %d /", c); (*outputFunc)(outputStream, buf, strlen(buf)); getString(glyphNames[i], buf); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, " put\n", 5); } } else if ((encFormat & 0x7f) == 1) { nRanges = *ptr++; nCodes = 1; for (i = 0; i < nRanges; ++i) { c = *ptr++; nLeft = *ptr++; for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) { sprintf(buf, "dup %d /", c); (*outputFunc)(outputStream, buf, strlen(buf)); getString(glyphNames[nCodes], buf); (*outputFunc)(outputStream, buf, strlen(buf)); (*outputFunc)(outputStream, " put\n", 5); ++nCodes; ++c; } } } if (encFormat & 0x80) { nSups = *ptr++; for (i = 0; i < nSups; ++i) { c = *ptr++; sid = getWord(ptr, 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -