📄 gfxfont.cc
字号:
return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;}Object *Gfx8BitFont::getCharProc(int code, Object *proc) { if (enc[code] && charProcs.isDict()) { charProcs.dictLookup(enc[code], proc); } else { proc->initNull(); } return proc;}Dict *Gfx8BitFont::getResources() { return resources.isDict() ? resources.getDict() : (Dict *)NULL;}//------------------------------------------------------------------------// GfxCIDFont//------------------------------------------------------------------------static int CDECL cmpWidthExcep(const void *w1, const void *w2) { return ((GfxFontCIDWidthExcep *)w1)->first - ((GfxFontCIDWidthExcep *)w2)->first;}static int CDECL cmpWidthExcepV(const void *w1, const void *w2) { return ((GfxFontCIDWidthExcepV *)w1)->first - ((GfxFontCIDWidthExcepV *)w2)->first;}GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, Dict *fontDict): GfxFont(tagA, idA, nameA){ Dict *desFontDict; GString *collection, *cMapName; Object desFontDictObj; Object obj1, obj2, obj3, obj4, obj5, obj6; CharCodeToUnicode *utu; CharCode c; Unicode uBuf[8]; int c1, c2; int excepsSize, i, j, k, n; ascent = 0.95; descent = -0.35; fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; cMap = NULL; ctu = NULL; widths.defWidth = 1.0; widths.defHeight = -1.0; widths.defVY = 0.880; widths.exceps = NULL; widths.nExceps = 0; widths.excepsV = NULL; widths.nExcepsV = 0; cidToGID = NULL; cidToGIDLen = 0; // get the descendant font if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) { error(-1, "Missing DescendantFonts entry in Type 0 font"); obj1.free(); goto err1; } if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) { error(-1, "Bad descendant font in Type 0 font"); goto err3; } obj1.free(); desFontDict = desFontDictObj.getDict(); // font type if (!desFontDict->lookup("Subtype", &obj1)) { error(-1, "Missing Subtype entry in Type 0 descendant font"); goto err3; } if (obj1.isName("CIDFontType0")) { type = fontCIDType0; } else if (obj1.isName("CIDFontType2")) { type = fontCIDType2; } else { error(-1, "Unknown Type 0 descendant font type '%s'", obj1.isName() ? obj1.getName() : "???"); goto err3; } obj1.free(); // get info from font descriptor readFontDescriptor(xref, desFontDict); // look for an external font file findExtFontFile(); //----- encoding info ----- // char collection if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) { error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font"); goto err3; } obj1.dictLookup("Registry", &obj2); obj1.dictLookup("Ordering", &obj3); if (!obj2.isString() || !obj3.isString()) { error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font"); goto err4; } collection = obj2.getString()->copy()->append('-')->append(obj3.getString()); obj3.free(); obj2.free(); obj1.free(); // look for a ToUnicode CMap if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) { // the "Adobe-Identity" and "Adobe-UCS" collections don't have // cidToUnicode files if (collection->cmp("Adobe-Identity") && collection->cmp("Adobe-UCS")) { // look for a user-supplied .cidToUnicode file if (!(ctu = globalParams->getCIDToUnicode(collection))) { error(-1, "Unknown character collection '%s'", collection->getCString()); // fall-through, assuming the Identity mapping -- this appears // to match Adobe's behavior } } } // look for a Unicode-to-Unicode mapping if (name && (utu = globalParams->getUnicodeToUnicode(name))) { if (ctu) { for (c = 0; c < ctu->getLength(); ++c) { n = ctu->mapToUnicode(c, uBuf, 8); if (n >= 1) { n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8); if (n >= 1) { ctu->setMapping(c, uBuf, n); } } } utu->decRefCnt(); } else { ctu = utu; } } // encoding (i.e., CMap) //~ need to handle a CMap stream here //~ also need to deal with the UseCMap entry in the stream dict if (!fontDict->lookup("Encoding", &obj1)->isName()) { error(-1, "Missing or invalid Encoding entry in Type 0 font"); delete collection; goto err3; } cMapName = new GString(obj1.getName()); obj1.free(); if (!(cMap = globalParams->getCMap(collection, cMapName))) { error(-1, "Unknown CMap '%s' for character collection '%s'", cMapName->getCString(), collection->getCString()); delete collection; delete cMapName; goto err2; } delete collection; delete cMapName; // CIDToGIDMap (for embedded TrueType fonts) if (type == fontCIDType2) { desFontDict->lookup("CIDToGIDMap", &obj1); if (obj1.isStream()) { cidToGIDLen = 0; i = 64; cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort)); obj1.streamReset(); while ((c1 = obj1.streamGetChar()) != EOF && (c2 = obj1.streamGetChar()) != EOF) { if (cidToGIDLen == i) { i *= 2; cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort)); } cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2); } } else if (!obj1.isName("Identity") && !obj1.isNull()) { error(-1, "Invalid CIDToGIDMap entry in CID font"); } obj1.free(); } //----- character metrics ----- // default char width if (desFontDict->lookup("DW", &obj1)->isInt()) { widths.defWidth = obj1.getInt() * 0.001; } obj1.free(); // char width exceptions if (desFontDict->lookup("W", &obj1)->isArray()) { excepsSize = 0; i = 0; while (i + 1 < obj1.arrayGetLength()) { obj1.arrayGet(i, &obj2); obj1.arrayGet(i + 1, &obj3); if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) { if (obj1.arrayGet(i + 2, &obj4)->isNum()) { if (widths.nExceps == excepsSize) { excepsSize += 16; widths.exceps = (GfxFontCIDWidthExcep *) greallocn(widths.exceps, excepsSize, sizeof(GfxFontCIDWidthExcep)); } widths.exceps[widths.nExceps].first = obj2.getInt(); widths.exceps[widths.nExceps].last = obj3.getInt(); widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; ++widths.nExceps; } else { error(-1, "Bad widths array in Type 0 font"); } obj4.free(); i += 3; } else if (obj2.isInt() && obj3.isArray()) { if (widths.nExceps + obj3.arrayGetLength() > excepsSize) { excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15; widths.exceps = (GfxFontCIDWidthExcep *) greallocn(widths.exceps, excepsSize, sizeof(GfxFontCIDWidthExcep)); } j = obj2.getInt(); for (k = 0; k < obj3.arrayGetLength(); ++k) { if (obj3.arrayGet(k, &obj4)->isNum()) { widths.exceps[widths.nExceps].first = j; widths.exceps[widths.nExceps].last = j; widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; ++j; ++widths.nExceps; } else { error(-1, "Bad widths array in Type 0 font"); } obj4.free(); } i += 2; } else { error(-1, "Bad widths array in Type 0 font"); ++i; } obj3.free(); obj2.free(); } qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep), &cmpWidthExcep); } obj1.free(); // default metrics for vertical font if (desFontDict->lookup("DW2", &obj1)->isArray() && obj1.arrayGetLength() == 2) { if (obj1.arrayGet(0, &obj2)->isNum()) { widths.defVY = obj2.getNum() * 0.001; } obj2.free(); if (obj1.arrayGet(1, &obj2)->isNum()) { widths.defHeight = obj2.getNum() * 0.001; } obj2.free(); } obj1.free(); // char metric exceptions for vertical font if (desFontDict->lookup("W2", &obj1)->isArray()) { excepsSize = 0; i = 0; while (i + 1 < obj1.arrayGetLength()) { obj1.arrayGet(i, &obj2); obj1.arrayGet(i+ 1, &obj3); if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) { if (obj1.arrayGet(i + 2, &obj4)->isNum() && obj1.arrayGet(i + 3, &obj5)->isNum() && obj1.arrayGet(i + 4, &obj6)->isNum()) { if (widths.nExcepsV == excepsSize) { excepsSize += 16; widths.excepsV = (GfxFontCIDWidthExcepV *) greallocn(widths.excepsV, excepsSize, sizeof(GfxFontCIDWidthExcepV)); } widths.excepsV[widths.nExcepsV].first = obj2.getInt(); widths.excepsV[widths.nExcepsV].last = obj3.getInt(); widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001; widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001; widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001; ++widths.nExcepsV; } else { error(-1, "Bad widths (W2) array in Type 0 font"); } obj6.free(); obj5.free(); obj4.free(); i += 5; } else if (obj2.isInt() && obj3.isArray()) { if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) { excepsSize = (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15; widths.excepsV = (GfxFontCIDWidthExcepV *) greallocn(widths.excepsV, excepsSize, sizeof(GfxFontCIDWidthExcepV)); } j = obj2.getInt(); for (k = 0; k < obj3.arrayGetLength(); k += 3) { if (obj3.arrayGet(k, &obj4)->isNum() && obj3.arrayGet(k+1, &obj5)->isNum() && obj3.arrayGet(k+2, &obj6)->isNum()) { widths.excepsV[widths.nExceps].first = j; widths.excepsV[widths.nExceps].last = j; widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001; widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001; widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001; ++j; ++widths.nExcepsV; } else { error(-1, "Bad widths (W2) array in Type 0 font"); } obj6.free(); obj5.free(); obj4.free(); } i += 2; } else { error(-1, "Bad widths (W2) array in Type 0 font"); ++i; } obj3.free(); obj2.free(); } qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV), &cmpWidthExcepV); } obj1.free(); desFontDictObj.free(); ok = gTrue; return; err4: obj3.free(); obj2.free(); err3: obj1.free(); err2: desFontDictObj.free(); err1:;}GfxCIDFont::~GfxCIDFont() { if (cMap) { cMap->decRefCnt(); } if (ctu) { ctu->decRefCnt(); } gfree(widths.exceps); gfree(widths.excepsV); if (cidToGID) { gfree(cidToGID); }}int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, Unicode *u, int uSize, int *uLen, double *dx, double *dy, double *ox, double *oy) { CID cid; double w, h, vx, vy; int n, a, b, m; if (!cMap) { *code = 0; *uLen = 0; *dx = *dy = 0; return 1; } *code = (CharCode)(cid = cMap->getCID(s, len, &n)); if (ctu) { *uLen = ctu->mapToUnicode(cid, u, uSize); } else { *uLen = 0; } // horizontal if (cMap->getWMode() == 0) { w = widths.defWidth; h = vx = vy = 0; if (widths.nExceps > 0 && cid >= widths.exceps[0].first) { a = 0; b = widths.nExceps; // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first while (b - a > 1) { m = (a + b) / 2; if (widths.exceps[m].first <= cid) { a = m; } else { b = m; } } if (cid <= widths.exceps[a].last) { w = widths.exceps[a].width; } } // vertical } else { w = 0; h = widths.defHeight; vx = widths.defWidth / 2; vy = widths.defVY; if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) { a = 0; b = widths.nExcepsV; // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first while (b - a > 1) { m = (a + b) / 2; if (widths.excepsV[m].last <= cid) { a = m; } else { b = m; } } if (cid <= widths.excepsV[a].last) { h = widths.excepsV[a].height; vx = widths.excepsV[a].vx; vy = widths.excepsV[a].vy; } } } *dx = w; *dy = h; *ox = vx; *oy = vy; return n;}int GfxCIDFont::getWMode() { return cMap ? cMap->getWMode() : 0;}CharCodeToUnicode *GfxCIDFont::getToUnicode() { if (ctu) { ctu->incRefCnt(); } return ctu;}GString *GfxCIDFont::getCollection() { return cMap ? cMap->getCollection() : (GString *)NULL;}//------------------------------------------------------------------------// GfxFontDict//------------------------------------------------------------------------GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) { int i; Object obj1, obj2; Ref r; numFonts = fontDict->getLength(); fonts = (GfxFont **)gmallocn(numFonts, sizeof(GfxFont *)); for (i = 0; i < numFonts; ++i) { fontDict->getValNF(i, &obj1); obj1.fetch(xref, &obj2); if (obj2.isDict()) { if (obj1.isRef()) { r = obj1.getRef(); } else { // no indirect reference for this font, so invent a unique one // (legal generation numbers are five digits, so any 6-digit // number would be safe) r.num = i; if (fontDictRef) { r.gen = 100000 + fontDictRef->num; } else { r.gen = 999999; } } fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i), r, obj2.getDict()); if (fonts[i] && !fonts[i]->isOk()) { delete fonts[i]; fonts[i] = NULL; } } else { error(-1, "font resource is not a dictionary"); fonts[i] = NULL; } obj1.free(); obj2.free(); }}GfxFontDict::~GfxFontDict() { int i; for (i = 0; i < numFonts; ++i) { if (fonts[i]) { delete fonts[i]; } } gfree(fonts);}GfxFont *GfxFontDict::lookup(char *tag) { int i; for (i = 0; i < numFonts; ++i) { if (fonts[i] && fonts[i]->matches(tag)) { return fonts[i]; } } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -