diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2024-02-10 06:55:23 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2024-02-10 06:55:23 +0000 |
commit | 0357cc55904fda095727bb30f07b68dbf3439f8e (patch) | |
tree | 4dfe670d69c9d538606e6d49fe29b506c05e5975 /Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc | |
parent | 28c5129fe7864e1005edc90cf737372ba1bc78c7 (diff) |
xpdf 4.05
git-svn-id: svn://tug.org/texlive/trunk@69765 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc')
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc | 269 |
1 files changed, 184 insertions, 85 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc index 30e8bd1c79c..c3db4e8651b 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/GfxFont.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -307,26 +303,10 @@ GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) { obj2.initNull(); } + // NB: the PDF spec doesn't say anything about precedence, but Adobe + // uses FontFile3 over FontFile2 if both are present. if (fontDict2->lookup("FontDescriptor", &fontDesc)->isDict()) { - if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) { - *embID = obj3.getRef(); - if (expectedType != fontType1) { - err = gTrue; - } - } - obj3.free(); - if (embID->num == -1 && - fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) { - *embID = obj3.getRef(); - if (isType0) { - expectedType = fontCIDType2; - } else if (expectedType != fontTrueType) { - err = gTrue; - } - } - obj3.free(); - if (embID->num == -1 && - fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) { + if (fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) { *embID = obj3.getRef(); if (obj3.fetch(xref, &obj4)->isStream()) { obj4.streamGetDict()->lookup("Subtype", &subtype); @@ -375,6 +355,26 @@ GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) { obj4.free(); } obj3.free(); + if (embID->num == -1) { + if (fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) { + *embID = obj3.getRef(); + if (isType0) { + expectedType = fontCIDType2; + } else if (expectedType != fontTrueType) { + err = gTrue; + } + } + obj3.free(); + } + if (embID->num == -1) { + if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) { + *embID = obj3.getRef(); + if (expectedType != fontType1) { + err = gTrue; + } + } + obj3.free(); + } } fontDesc.free(); @@ -533,6 +533,33 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { } obj1.free(); + + // scan font name for bold/italic tags and update the flags + if (name) { + i = name->getLength(); + if (i > 2 && !strncmp(name->getCString() + i - 2, "MT", 2)) { + i -= 2; + } + if (i > 6 && !strncmp(name->getCString() + i - 6, "Italic", 6)) { + flags |= fontItalic; + i -= 6; + } else if (i > 2 && !strncmp(name->getCString() + i - 2, "It", 2)) { + flags |= fontItalic; + i -= 2; + } else if (i > 7 && !strncmp(name->getCString() + i - 7, "Oblique", 7)) { + flags |= fontItalic; + i -= 7; + } + char c = name->getChar(i-1); + if (!((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9'))) { + --i; + } + if (i > 4 && !strncmp(name->getCString() + i - 4, "Bold", 4)) { + flags |= fontBold; + } + } } CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, @@ -1436,7 +1463,7 @@ CharCodeToUnicode *Gfx8BitFont::getToUnicode() { int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { int *map; int cmapPlatform, cmapEncoding; - int unicodeCmap, macRomanCmap, msSymbolCmap, cmap; + int unicodeCmap, macRomanCmap, macUnicodeCmap, msSymbolCmap, cmap; GBool nonsymbolic, useMacRoman, useUnicode; char *charName; Unicode u; @@ -1450,15 +1477,16 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { // This is based on the cmap/encoding selection algorithm in the PDF // 2.0 spec, but with some differences to match up with Adobe's // behavior. - unicodeCmap = macRomanCmap = msSymbolCmap = -1; + unicodeCmap = macRomanCmap = macUnicodeCmap = msSymbolCmap = -1; for (i = 0; i < ff->getNumCmaps(); ++i) { cmapPlatform = ff->getCmapPlatform(i); cmapEncoding = ff->getCmapEncoding(i); - if ((cmapPlatform == 3 && cmapEncoding == 1) || - (cmapPlatform == 0 && cmapEncoding <= 4)) { + if (cmapPlatform == 3 && cmapEncoding == 1) { unicodeCmap = i; } else if (cmapPlatform == 1 && cmapEncoding == 0) { macRomanCmap = i; + } else if (cmapPlatform == 0 && cmapEncoding <= 4) { + macUnicodeCmap = i; } else if (cmapPlatform == 3 && cmapEncoding == 0) { msSymbolCmap = i; } @@ -1466,24 +1494,25 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { useMacRoman = gFalse; useUnicode = gFalse; nonsymbolic = !(flags & fontSymbolic); - if (usesMacRomanEnc && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } else if (embFontID.num < 0 && hasEncoding && unicodeCmap >= 0) { + if (embFontID.num < 0 && hasEncoding && unicodeCmap >= 0) { cmap = unicodeCmap; useUnicode = gTrue; - } else if (nonsymbolic && unicodeCmap >= 0) { - cmap = unicodeCmap; - useUnicode = gTrue; - } else if (nonsymbolic && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } else if (msSymbolCmap >= 0) { + } else if (!nonsymbolic && msSymbolCmap >= 0) { cmap = msSymbolCmap; } else if (unicodeCmap >= 0) { cmap = unicodeCmap; + useUnicode = nonsymbolic; + } else if (usesMacRomanEnc && macRomanCmap >= 0) { + // MacRoman cmap has higher precedence than Mac Unicode only if + // the font uses the MacRoman encoding + cmap = macRomanCmap; + useMacRoman = gTrue; + } else if (macUnicodeCmap >= 0) { + cmap = macUnicodeCmap; + useUnicode = nonsymbolic; } else if (macRomanCmap >= 0) { cmap = macRomanCmap; + useMacRoman = nonsymbolic; } else { cmap = 0; } @@ -2229,75 +2258,99 @@ GBool GfxCIDFont::problematicForUnicode() { // GfxFontDict //------------------------------------------------------------------------ -GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) { - GfxFont *font; - char *tag; - Object obj1, obj2; - Ref r; - int i; +class GfxFontDictEntry { +public: + + GfxFontDictEntry(Ref refA, Object *fontObjA); + ~GfxFontDictEntry(); + void load(GfxFont *fontA); + GBool loaded; + Ref ref; + Object fontObj; // valid if unloaded + GfxFont *font; // valid if loaded +}; + +GfxFontDictEntry::GfxFontDictEntry(Ref refA, Object *fontObjA) { + loaded = gFalse; + ref = refA; + fontObjA->copy(&fontObj); + font = NULL; +} + +GfxFontDictEntry::~GfxFontDictEntry() { + // NB: If the font has been loaded, font is non-NULL and is owned by + // GfxFontDict.uniqueFonts. + if (!loaded) { + fontObj.free(); + } +} + +void GfxFontDictEntry::load(GfxFont *fontA) { + loaded = gTrue; + font = fontA; + fontObj.free(); +} + +GfxFontDict::GfxFontDict(XRef *xrefA, Ref *fontDictRef, Dict *fontDict) { + xref = xrefA; fonts = new GHash(gTrue); uniqueFonts = new GList(); - for (i = 0; i < fontDict->getLength(); ++i) { - tag = fontDict->getKey(i); - fontDict->getValNF(i, &obj1); - obj1.fetch(xref, &obj2); - if (!obj2.isDict()) { - error(errSyntaxError, -1, "font resource is not a dictionary"); - } else if (obj1.isRef() && (font = lookupByRef(obj1.getRef()))) { - fonts->add(new GString(tag), font); + + for (int i = 0; i < fontDict->getLength(); ++i) { + char *tag = fontDict->getKey(i); + Object fontObj; + fontDict->getValNF(i, &fontObj); + Ref r; + if (fontObj.isRef()) { + r = fontObj.getRef(); + } else if (fontDictRef) { + // legal generation numbers are five digits, so we use a + // 6-digit number here + r.gen = 100000 + fontDictRef->num; + r.num = i; } else { - if (obj1.isRef()) { - r = obj1.getRef(); - } else if (fontDictRef) { - // legal generation numbers are five digits, so we use a - // 6-digit number here - r.gen = 100000 + fontDictRef->num; - r.num = i; - } else { - // no indirect reference for this font, or for the containing - // font dict, so hash the font and use that - r.gen = 100000; - r.num = hashFontObject(&obj2); - } - if ((font = GfxFont::makeFont(xref, tag, r, obj2.getDict()))) { - if (!font->isOk()) { - delete font; - } else { - uniqueFonts->append(font); - fonts->add(new GString(tag), font); - } - } + // no indirect reference for this font, or for the containing + // font dict, so hash the font and use that + r.gen = 100000; + r.num = hashFontObject(&fontObj); } - obj1.free(); - obj2.free(); + fonts->add(new GString(tag), new GfxFontDictEntry(r, &fontObj)); + fontObj.free(); } } GfxFontDict::~GfxFontDict() { deleteGList(uniqueFonts, GfxFont); - delete fonts; + deleteGHash(fonts, GfxFontDictEntry); } GfxFont *GfxFontDict::lookup(char *tag) { - return (GfxFont *)fonts->lookup(tag); + GfxFontDictEntry *entry = (GfxFontDictEntry *)fonts->lookup(tag); + if (!entry) { + return NULL; + } + load(tag, entry); + return entry->font; } GfxFont *GfxFontDict::lookupByRef(Ref ref) { - GfxFont *font; - int i; - - for (i = 0; i < uniqueFonts->getLength(); ++i) { - font = (GfxFont *)uniqueFonts->get(i); - if (font->getID()->num == ref.num && - font->getID()->gen == ref.gen) { - return font; + GHashIter *iter; + GString *tag; + GfxFontDictEntry *entry; + fonts->startIter(&iter); + while (fonts->getNext(&iter, &tag, (void **)&entry)) { + if (entry->ref.num == ref.num && entry->ref.gen == ref.gen) { + fonts->killIter(&iter); + load(tag->getCString(), entry); + return entry->font; } } return NULL; } int GfxFontDict::getNumFonts() { + loadAll(); return uniqueFonts->getLength(); } @@ -2305,6 +2358,52 @@ GfxFont *GfxFontDict::getFont(int i) { return (GfxFont *)uniqueFonts->get(i); } +void GfxFontDict::loadAll() { + GHashIter *iter; + GString *tag; + GfxFontDictEntry *entry; + fonts->startIter(&iter); + while (fonts->getNext(&iter, &tag, (void **)&entry)) { + load(tag->getCString(), entry); + } +} + +void GfxFontDict::load(char *tag, GfxFontDictEntry *entry) { + if (entry->loaded) { + return; + } + + // check for a duplicate that has already been loaded + // (don't do this for "synthetic" refs) + if (entry->fontObj.isRef()) { + for (int i = 0; i < uniqueFonts->getLength(); ++i) { + GfxFont *font = (GfxFont *)uniqueFonts->get(i); + if (font->getID()->num == entry->ref.num && + font->getID()->gen == entry->ref.gen) { + entry->load(font); + return; + } + } + } + + GfxFont *font = NULL; + Object obj; + entry->fontObj.fetch(xref, &obj); + if (obj.isDict()) { + font = GfxFont::makeFont(xref, tag, entry->ref, obj.getDict()); + if (font->isOk()) { + uniqueFonts->append(font); + } else { + delete font; + font = NULL; + } + } else { + error(errSyntaxError, -1, "font resource is not a dictionary"); + } + obj.free(); + entry->load(font); +} + // FNV-1a hash class FNVHash { public: |