📄 gfxfont.cc
字号:
//========================================================================//// GfxFont.cc//// Copyright 1996-2003 Glyph & Cog, LLC////========================================================================#include <aconf.h>#ifdef USE_GCC_PRAGMAS#pragma implementation#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "gmem.h"#include "Error.h"#include "Object.h"#include "Dict.h"#include "GlobalParams.h"#include "CMap.h"#include "CharCodeToUnicode.h"#include "FontEncodingTables.h"#include "BuiltinFontTables.h"#include "FoFiType1.h"#include "FoFiType1C.h"#include "FoFiTrueType.h"#include "GfxFont.h"//------------------------------------------------------------------------struct StdFontMapEntry { char *altName; char *properName;};// Acrobat 4.0 and earlier substituted Base14-compatible fonts without// providing Widths and a FontDescriptor, so we munge the names into// the proper Base14 names. This table is from implementation note 44// in the PDF 1.4 spec, with some additions based on empirical// evidence.static StdFontMapEntry stdFontMap[] = { { "Arial", "Helvetica" }, { "Arial,Bold", "Helvetica-Bold" }, { "Arial,BoldItalic", "Helvetica-BoldOblique" }, { "Arial,Italic", "Helvetica-Oblique" }, { "Arial-Bold", "Helvetica-Bold" }, { "Arial-BoldItalic", "Helvetica-BoldOblique" }, { "Arial-BoldItalicMT", "Helvetica-BoldOblique" }, { "Arial-BoldMT", "Helvetica-Bold" }, { "Arial-Italic", "Helvetica-Oblique" }, { "Arial-ItalicMT", "Helvetica-Oblique" }, { "ArialMT", "Helvetica" }, { "Courier,Bold", "Courier-Bold" }, { "Courier,BoldItalic", "Courier-BoldOblique" }, { "Courier,Italic", "Courier-Oblique" }, { "CourierNew", "Courier" }, { "CourierNew,Bold", "Courier-Bold" }, { "CourierNew,BoldItalic", "Courier-BoldOblique" }, { "CourierNew,Italic", "Courier-Oblique" }, { "CourierNew-Bold", "Courier-Bold" }, { "CourierNew-BoldItalic", "Courier-BoldOblique" }, { "CourierNew-Italic", "Courier-Oblique" }, { "CourierNewPS-BoldItalicMT", "Courier-BoldOblique" }, { "CourierNewPS-BoldMT", "Courier-Bold" }, { "CourierNewPS-ItalicMT", "Courier-Oblique" }, { "CourierNewPSMT", "Courier" }, { "Helvetica,Bold", "Helvetica-Bold" }, { "Helvetica,BoldItalic", "Helvetica-BoldOblique" }, { "Helvetica,Italic", "Helvetica-Oblique" }, { "Helvetica-BoldItalic", "Helvetica-BoldOblique" }, { "Helvetica-Italic", "Helvetica-Oblique" }, { "Symbol,Bold", "Symbol" }, { "Symbol,BoldItalic", "Symbol" }, { "Symbol,Italic", "Symbol" }, { "TimesNewRoman", "Times-Roman" }, { "TimesNewRoman,Bold", "Times-Bold" }, { "TimesNewRoman,BoldItalic", "Times-BoldItalic" }, { "TimesNewRoman,Italic", "Times-Italic" }, { "TimesNewRoman-Bold", "Times-Bold" }, { "TimesNewRoman-BoldItalic", "Times-BoldItalic" }, { "TimesNewRoman-Italic", "Times-Italic" }, { "TimesNewRomanPS", "Times-Roman" }, { "TimesNewRomanPS-Bold", "Times-Bold" }, { "TimesNewRomanPS-BoldItalic", "Times-BoldItalic" }, { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" }, { "TimesNewRomanPS-BoldMT", "Times-Bold" }, { "TimesNewRomanPS-Italic", "Times-Italic" }, { "TimesNewRomanPS-ItalicMT", "Times-Italic" }, { "TimesNewRomanPSMT", "Times-Roman" }, { "TimesNewRomanPSMT,Bold", "Times-Bold" }, { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" }, { "TimesNewRomanPSMT,Italic", "Times-Italic" }};//------------------------------------------------------------------------// GfxFont//------------------------------------------------------------------------GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) { GString *nameA; GfxFont *font; Object obj1; // get base font name nameA = NULL; fontDict->lookup("BaseFont", &obj1); if (obj1.isName()) { nameA = new GString(obj1.getName()); } obj1.free(); // get font type font = NULL; fontDict->lookup("Subtype", &obj1); if (obj1.isName("Type1") || obj1.isName("MMType1")) { font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict); } else if (obj1.isName("Type1C")) { font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict); } else if (obj1.isName("Type3")) { font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict); } else if (obj1.isName("TrueType")) { font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict); } else if (obj1.isName("Type0")) { font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict); } else { error(-1, "Unknown font type: '%s'", obj1.isName() ? obj1.getName() : "???"); font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict); } obj1.free(); return font;}GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) { ok = gFalse; tag = new GString(tagA); id = idA; name = nameA; origName = nameA; embFontName = NULL; extFontFile = NULL;}GfxFont::~GfxFont() { delete tag; if (origName && origName != name) { delete origName; } if (name) { delete name; } if (embFontName) { delete embFontName; } if (extFontFile) { delete extFontFile; }}void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { Object obj1, obj2, obj3, obj4; double t; int i; // assume Times-Roman by default (for substitution purposes) flags = fontSerif; embFontID.num = -1; embFontID.gen = -1; missingWidth = 0; if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) { // get flags if (obj1.dictLookup("Flags", &obj2)->isInt()) { flags = obj2.getInt(); } obj2.free(); // get name obj1.dictLookup("FontName", &obj2); if (obj2.isName()) { embFontName = new GString(obj2.getName()); } obj2.free(); // look for embedded font file if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) { embFontID = obj2.getRef(); if (type != fontType1) { error(-1, "Mismatch between font type and embedded font file"); type = fontType1; } } obj2.free(); if (embFontID.num == -1 && obj1.dictLookupNF("FontFile2", &obj2)->isRef()) { embFontID = obj2.getRef(); if (type != fontTrueType && type != fontCIDType2) { error(-1, "Mismatch between font type and embedded font file"); type = type == fontCIDType0 ? fontCIDType2 : fontTrueType; } } obj2.free(); if (embFontID.num == -1 && obj1.dictLookupNF("FontFile3", &obj2)->isRef()) { if (obj2.fetch(xref, &obj3)->isStream()) { obj3.streamGetDict()->lookup("Subtype", &obj4); if (obj4.isName("Type1")) { embFontID = obj2.getRef(); if (type != fontType1) { error(-1, "Mismatch between font type and embedded font file"); type = fontType1; } } else if (obj4.isName("Type1C")) { embFontID = obj2.getRef(); if (type != fontType1 && type != fontType1C) { error(-1, "Mismatch between font type and embedded font file"); } type = fontType1C; } else if (obj4.isName("TrueType")) { embFontID = obj2.getRef(); if (type != fontTrueType) { error(-1, "Mismatch between font type and embedded font file"); type = fontTrueType; } } else if (obj4.isName("CIDFontType0C")) { embFontID = obj2.getRef(); if (type != fontCIDType0) { error(-1, "Mismatch between font type and embedded font file"); } type = fontCIDType0C; } else if (obj4.isName("OpenType")) { embFontID = obj2.getRef(); if (type == fontTrueType) { type = fontTrueTypeOT; } else if (type == fontType1) { type = fontType1COT; } else if (type == fontCIDType0) { type = fontCIDType0COT; } else if (type == fontCIDType2) { type = fontCIDType2OT; } else { error(-1, "Mismatch between font type and embedded font file"); } } else { error(-1, "Unknown embedded font type '%s'", obj4.isName() ? obj4.getName() : "???"); } obj4.free(); } obj3.free(); } obj2.free(); // look for MissingWidth obj1.dictLookup("MissingWidth", &obj2); if (obj2.isNum()) { missingWidth = obj2.getNum(); } obj2.free(); // get Ascent and Descent obj1.dictLookup("Ascent", &obj2); if (obj2.isNum()) { t = 0.001 * obj2.getNum(); // some broken font descriptors set ascent and descent to 0 if (t != 0) { ascent = t; } } obj2.free(); obj1.dictLookup("Descent", &obj2); if (obj2.isNum()) { t = 0.001 * obj2.getNum(); // some broken font descriptors set ascent and descent to 0 if (t != 0) { descent = t; } // some broken font descriptors specify a positive descent if (descent > 0) { descent = -descent; } } obj2.free(); // font FontBBox if (obj1.dictLookup("FontBBox", &obj2)->isArray()) { for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) { if (obj2.arrayGet(i, &obj3)->isNum()) { fontBBox[i] = 0.001 * obj3.getNum(); } obj3.free(); } } obj2.free(); } obj1.free();}CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, CharCodeToUnicode *ctu) { GString *buf; Object obj1; int c; if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) { obj1.free(); return NULL; } buf = new GString(); obj1.streamReset(); while ((c = obj1.streamGetChar()) != EOF) { buf->append(c); } obj1.streamClose(); obj1.free(); if (ctu) { ctu->mergeCMap(buf, nBits); } else { ctu = CharCodeToUnicode::parseCMap(buf, nBits); } delete buf; return ctu;}void GfxFont::findExtFontFile() { static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL }; static char *ttExts[] = { ".ttf", NULL }; if (name) { if (type == fontType1) { extFontFile = globalParams->findFontFile(name, type1Exts); } else if (type == fontTrueType) { extFontFile = globalParams->findFontFile(name, ttExts); } }}char *GfxFont::readExtFontFile(int *len) { FILE *f; char *buf; if (!(f = fopen(extFontFile->getCString(), "rb"))) { error(-1, "External font file '%s' vanished", extFontFile->getCString()); return NULL; } fseek(f, 0, SEEK_END); *len = (int)ftell(f); fseek(f, 0, SEEK_SET); buf = (char *)gmalloc(*len); if ((int)fread(buf, 1, *len, f) != *len) { error(-1, "Error reading external font file '%s'", extFontFile->getCString()); } fclose(f); return buf;}char *GfxFont::readEmbFontFile(XRef *xref, int *len) { char *buf; Object obj1, obj2; Stream *str; int c; int size, i; obj1.initRef(embFontID.num, embFontID.gen); obj1.fetch(xref, &obj2); if (!obj2.isStream()) { error(-1, "Embedded font file is not a stream"); obj2.free(); obj1.free(); embFontID.num = -1; return NULL; } str = obj2.getStream(); buf = NULL; i = size = 0; str->reset(); while ((c = str->getChar()) != EOF) { if (i == size) { size += 4096; buf = (char *)grealloc(buf, size); } buf[i++] = c; } *len = i; str->close(); obj2.free(); obj1.free(); return buf;}//------------------------------------------------------------------------// Gfx8BitFont//------------------------------------------------------------------------Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, GfxFontType typeA, Dict *fontDict): GfxFont(tagA, idA, nameA){ GString *name2; BuiltinFont *builtinFont; char **baseEnc; GBool baseEncFromFontFile; char *buf; int len; FoFiType1 *ffT1; FoFiType1C *ffT1C; int code, code2; char *charName; GBool missing, hex; Unicode toUnicode[256]; CharCodeToUnicode *utu, *ctu2; Unicode uBuf[8]; double mul; int firstChar, lastChar; Gushort w; Object obj1, obj2, obj3; int n, i, a, b, m; type = typeA; ctu = NULL; // do font name substitution for various aliases of the Base 14 font // names if (name) { name2 = name->copy(); i = 0; while (i < name2->getLength()) { if (name2->getChar(i) == ' ') { name2->del(i); } else { ++i; } } a = 0; b = sizeof(stdFontMap) / sizeof(StdFontMapEntry); // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName while (b - a > 1) { m = (a + b) / 2; if (name2->cmp(stdFontMap[m].altName) >= 0) { a = m; } else { b = m; } } if (!name2->cmp(stdFontMap[a].altName)) { name = new GString(stdFontMap[a].properName); } delete name2; } // is it a built-in font? builtinFont = NULL; if (name) { for (i = 0; i < nBuiltinFonts; ++i) { if (!name->cmp(builtinFonts[i].name)) { builtinFont = &builtinFonts[i]; break; } } } // default ascent/descent values if (builtinFont) { ascent = 0.001 * builtinFont->ascent; descent = 0.001 * builtinFont->descent; fontBBox[0] = 0.001 * builtinFont->bbox[0]; fontBBox[1] = 0.001 * builtinFont->bbox[1]; fontBBox[2] = 0.001 * builtinFont->bbox[2]; fontBBox[3] = 0.001 * builtinFont->bbox[3]; } else { ascent = 0.95; descent = -0.35; fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; } // get info from font descriptor readFontDescriptor(xref, fontDict); // for non-embedded fonts, don't trust the ascent/descent/bbox // values from the font descriptor if (builtinFont && embFontID.num < 0) { ascent = 0.001 * builtinFont->ascent; descent = 0.001 * builtinFont->descent; fontBBox[0] = 0.001 * builtinFont->bbox[0]; fontBBox[1] = 0.001 * builtinFont->bbox[1]; fontBBox[2] = 0.001 * builtinFont->bbox[2]; fontBBox[3] = 0.001 * builtinFont->bbox[3]; } // look for an external font file findExtFontFile(); // get font matrix fontMat[0] = fontMat[3] = 1; fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0; if (fontDict->lookup("FontMatrix", &obj1)->isArray()) { for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) { if (obj1.arrayGet(i, &obj2)->isNum()) { fontMat[i] = obj2.getNum(); } obj2.free(); } } obj1.free(); // get Type 3 bounding box, font definition, and resources if (type == fontType3) { if (fontDict->lookup("FontBBox", &obj1)->isArray()) { for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) { if (obj1.arrayGet(i, &obj2)->isNum()) { fontBBox[i] = obj2.getNum(); } obj2.free(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -