diff options
author | Norbert Preining <norbert@preining.info> | 2020-12-01 03:01:08 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2020-12-01 03:01:08 +0000 |
commit | 13dc4c947f3b419fc1b2ed24f10d69c841b0a37b (patch) | |
tree | b70e11ae7d2e2d77221ef406a555d4f7e52fbaf7 /dviware/dvisvgm/src | |
parent | cb68d38823870fa7adb5f0c2b68cf59205dd4bec (diff) |
CTAN sync 202012010301
Diffstat (limited to 'dviware/dvisvgm/src')
29 files changed, 344 insertions, 228 deletions
diff --git a/dviware/dvisvgm/src/BasicDVIReader.cpp b/dviware/dvisvgm/src/BasicDVIReader.cpp index bb30154e7b..29ca84999f 100644 --- a/dviware/dvisvgm/src/BasicDVIReader.cpp +++ b/dviware/dvisvgm/src/BasicDVIReader.cpp @@ -154,6 +154,47 @@ int BasicDVIReader::executeCommand () { } +void BasicDVIReader::executePreamble () { + clearStream(); + if (isStreamValid()) { + seek(0); + if (readByte() == OP_PRE) { + cmdPre(0); + return; + } + } + throw DVIException("invalid DVI file"); +} + + +/** Moves stream pointer to begin of postamble */ +void BasicDVIReader::goToPostamble () { + clearStream(); + if (!isStreamValid()) + throw DVIException("invalid DVI file"); + + seek(-1, ios::end); // stream pointer to last byte + int count=0; + while (peek() == DVI_FILL) { // skip fill bytes + seek(-1, ios::cur); + count++; + } + if (count < 4) // the standard requires at least 4 trailing fill bytes + throw DVIException("missing fill bytes at end of file"); + + seek(-4, ios::cur); // now at first byte of q (pointer to begin of postamble) + uint32_t q = readUnsigned(4); // pointer to begin of postamble + seek(q); // now at begin of postamble +} + + +/** Reads and executes the commands of the postamble. */ +void BasicDVIReader::executePostamble () { + goToPostamble(); + while (executeCommand() != OP_POSTPOST); // executes all commands until post_post (= 249) is reached +} + + void BasicDVIReader::executePostPost () { clearStream(); // reset all status bits if (!isStreamValid()) @@ -172,6 +213,37 @@ void BasicDVIReader::executePostPost () { } +void BasicDVIReader::executeFontDefs () { + goToPostamble(); + seek(1+28, ios::cur); // now on first fontdef or postpost + if (peek() != OP_POSTPOST) + while (executeCommand() != OP_POSTPOST); +} + + +/** Collects and records the file offsets of all bop commands. */ +vector<uint32_t> BasicDVIReader::collectBopOffsets () { + std::vector<uint32_t> bopOffsets; + goToPostamble(); + bopOffsets.push_back(tell()); // also add offset of postamble + readByte(); // skip post command + uint32_t offset = readUnsigned(4); // offset of final bop + while (int32_t(offset) != -1) { // not yet on first bop? + bopOffsets.push_back(offset); // record offset + seek(offset); // now on previous bop + if (readByte() != OP_BOP) + throw DVIException("bop offset at "+to_string(offset)+" doesn't point to bop command" ); + seek(40, ios::cur); // skip the 10 \count values => now on offset of previous bop + uint32_t prevOffset = readUnsigned(4); + if ((prevOffset >= offset && int32_t(prevOffset) != -1)) + throw DVIException("invalid bop offset at "+to_string(tell()-static_cast<streamoff>(4))); + offset = prevOffset; + } + reverse(bopOffsets.begin(), bopOffsets.end()); + return bopOffsets; +} + + void BasicDVIReader::executeAllPages () { if (_dviVersion == DVI_NONE) executePostPost(); // get version ID from post_post diff --git a/dviware/dvisvgm/src/BasicDVIReader.hpp b/dviware/dvisvgm/src/BasicDVIReader.hpp index 7ce1f989e2..a5b18b0420 100644 --- a/dviware/dvisvgm/src/BasicDVIReader.hpp +++ b/dviware/dvisvgm/src/BasicDVIReader.hpp @@ -52,6 +52,7 @@ class BasicDVIReader : public StreamReader { public: explicit BasicDVIReader (std::istream &is); virtual void executeAllPages (); + virtual void executeFontDefs (); virtual double getXPos () const {return 0;} virtual double getYPos () const {return 0;} virtual void finishLine () {} @@ -66,7 +67,11 @@ class BasicDVIReader : public StreamReader { DVIVersion getDVIVersion () const {return _dviVersion;} virtual int evalCommand (CommandHandler &handler, int ¶m); virtual int executeCommand (); + void executePreamble (); + void executePostamble (); void executePostPost (); + void goToPostamble (); + std::vector<uint32_t> collectBopOffsets (); bool evalXDVOpcode (int op, CommandHandler &handler) const; // The following template methods represent the single DVI commands. They diff --git a/dviware/dvisvgm/src/CMap.cpp b/dviware/dvisvgm/src/CMap.cpp index 747fb5ad50..193def52fd 100644 --- a/dviware/dvisvgm/src/CMap.cpp +++ b/dviware/dvisvgm/src/CMap.cpp @@ -23,6 +23,7 @@ #include "CMap.hpp" #include "CMapManager.hpp" #include "FileFinder.hpp" +#include "Unicode.hpp" using namespace std; @@ -38,6 +39,22 @@ const FontEncoding* CMap::findCompatibleBaseFontMap (const PhysicalFont *font, C ////////////////////////////////////////////////////////////////////// +void SegmentedCMap::addCIDRange (uint32_t first, uint32_t last, uint32_t cid) { + if (uint32_t cp = Unicode::fromSurrogate(first)) // is 'first' a surrogate? + first = cp; + if (uint32_t cp = Unicode::fromSurrogate(last)) // is 'last' a surrogate? + last = cp; + _cidranges.addRange(first, last, cid); +} + + +void SegmentedCMap::addBFRange (uint32_t first, uint32_t last, uint32_t chrcode) { + if (uint32_t cp = Unicode::fromSurrogate(chrcode)) // is 'chrcode' a surrogate? + chrcode = cp; + _bfranges.addRange(first, last, chrcode); +} + + /** Returns the RO (Registry-Ordering) string of the CMap. */ string SegmentedCMap::getROString() const { if (_registry.empty() || _ordering.empty()) @@ -46,6 +63,17 @@ string SegmentedCMap::getROString() const { } +bool SegmentedCMap::mapsToUnicode () const { + vector<string> encstrings = {"UTF8", "UTF16", "UCS2", "UCS4", "UCS32"}; + for (const string &encstr : encstrings) { + size_t pos = _filename.find(encstr); + if (pos != string::npos && (pos == 0 || _filename[pos-1] == '-')) + return true; + } + return false; +} + + /** Returns the CID for a given character code. */ uint32_t SegmentedCMap::cid (uint32_t c) const { if (_cidranges.valueExists(c)) diff --git a/dviware/dvisvgm/src/CMap.hpp b/dviware/dvisvgm/src/CMap.hpp index 63761ff2ff..37a54ba0f8 100644 --- a/dviware/dvisvgm/src/CMap.hpp +++ b/dviware/dvisvgm/src/CMap.hpp @@ -74,6 +74,7 @@ struct UnicodeCMap : public CMap { uint32_t cid (uint32_t c) const override {return c;} uint32_t bfcode (uint32_t cid) const override {return cid;} std::string getROString () const override {return "";} + bool mapsToUnicode () const override {return true;} }; @@ -85,19 +86,21 @@ class SegmentedCMap : public CMap { const char* name () const override {return _filename.c_str();} uint32_t cid (uint32_t c) const override; uint32_t bfcode (uint32_t cid) const override; - void addCIDRange (uint32_t first, uint32_t last, uint32_t cid) {_cidranges.addRange(first, last, cid);} - void addBFRange (uint32_t first, uint32_t last, uint32_t chrcode) {_bfranges.addRange(first, last, chrcode);} + void addCIDRange (uint32_t first, uint32_t last, uint32_t cid); + void addBFRange (uint32_t first, uint32_t last, uint32_t chrcode); void write (std::ostream &os) const; bool vertical () const override {return _vertical;} bool mapsToCID () const override {return _mapsToCID;} size_t numCIDRanges () const {return _cidranges.numRanges();} size_t numBFRanges () const {return _bfranges.numRanges();} std::string getROString () const override; + bool mapsToUnicode () const override; private: std::string _filename; std::string _registry; std::string _ordering; + std::string _cmaptype; CMap *_basemap = nullptr; bool _vertical = false; bool _mapsToCID = true; // true: chrcode->CID, false: CID->charcode diff --git a/dviware/dvisvgm/src/CMapReader.cpp b/dviware/dvisvgm/src/CMapReader.cpp index 51ba52b95d..8ab22c22e3 100644 --- a/dviware/dvisvgm/src/CMapReader.cpp +++ b/dviware/dvisvgm/src/CMapReader.cpp @@ -114,6 +114,8 @@ void CMapReader::op_def (InputReader&) { else throw CMapReaderException("invalid WMode (0 or 1 expected)"); } + else if (name == "CMapType") + _cmap->_cmaptype = val; else if (name == "Registry") _cmap->_registry = val; else if (name == "Ordering") diff --git a/dviware/dvisvgm/src/DVIReader.cpp b/dviware/dvisvgm/src/DVIReader.cpp index 0581ad25c3..893e6a818b 100644 --- a/dviware/dvisvgm/src/DVIReader.cpp +++ b/dviware/dvisvgm/src/DVIReader.cpp @@ -26,6 +26,7 @@ #include "Font.hpp" #include "FontManager.hpp" #include "HashFunction.hpp" +#include "JFM.hpp" #include "utility.hpp" #include "VectorStream.hpp" @@ -33,21 +34,12 @@ using namespace std; DVIReader::DVIReader (istream &is) : BasicDVIReader(is) { - _inPage = false; - _dvi2bp = 0.0; - _inPostamble = false; - _currFontNum = 0; - _currPageNum = 0; - _mag = 1; executePreamble(); - collectBopOffsets(); - executePostamble(); -} - - -int DVIReader::executeCommand () { - int opcode = BasicDVIReader::executeCommand(); - return opcode; + _bopOffsets = collectBopOffsets(); + // read data from postamble but don't process font definitions + goToPostamble(); + executeCommand(); + executePostPost(); } @@ -78,75 +70,12 @@ bool DVIReader::executePage (unsigned n) { return false; seek(_bopOffsets[n-1]); // goto bop of n-th page - _inPostamble = false; // not in postamble _currPageNum = n; while (executeCommand() != OP_EOP); return true; } -void DVIReader::executePreamble () { - clearStream(); - if (isStreamValid()) { - seek(0); - if (readByte() == OP_PRE) { - cmdPre(0); - return; - } - } - throw DVIException("invalid DVI file"); -} - - -/** Moves stream pointer to begin of postamble */ -void DVIReader::goToPostamble () { - clearStream(); - if (!isStreamValid()) - throw DVIException("invalid DVI file"); - - seek(-1, ios::end); // stream pointer to last byte - int count=0; - while (peek() == DVI_FILL) { // skip fill bytes - seek(-1, ios::cur); - count++; - } - if (count < 4) // the standard requires at least 4 trailing fill bytes - throw DVIException("missing fill bytes at end of file"); - - seek(-4, ios::cur); // now at first byte of q (pointer to begin of postamble) - uint32_t q = readUnsigned(4); // pointer to begin of postamble - seek(q); // now at begin of postamble -} - - -/** Reads and executes the commands of the postamble. */ -void DVIReader::executePostamble () { - goToPostamble(); - while (executeCommand() != OP_POSTPOST); // executes all commands until post_post (= 249) is reached -} - - -/** Collects and records the file offsets of all bop commands. */ -void DVIReader::collectBopOffsets () { - goToPostamble(); - _bopOffsets.push_back(tell()); // also add offset of postamble - readByte(); // skip post command - uint32_t offset = readUnsigned(4); // offset of final bop - while (int32_t(offset) != -1) { // not yet on first bop? - _bopOffsets.push_back(offset); // record offset - seek(offset); // now on previous bop - if (readByte() != OP_BOP) - throw DVIException("bop offset at "+to_string(offset)+" doesn't point to bop command" ); - seek(40, ios::cur); // skip the 10 \count values => now on offset of previous bop - uint32_t prevOffset = readUnsigned(4); - if ((prevOffset >= offset && int32_t(prevOffset) != -1)) - throw DVIException("invalid bop offset at "+to_string(tell()-static_cast<streamoff>(4))); - offset = prevOffset; - } - reverse(_bopOffsets.begin(), _bopOffsets.end()); -} - - /** Computes a hash value for a given page. The hash algorithm is selected by * a HashFunction object which will also contain the resulting hash value if * this function returns true. @@ -212,7 +141,6 @@ void DVIReader::cmdPost (int) { // 1 dviunit * num/den == multiples of 0.0000001m // 1 dviunit * _dvi2bp: length of 1 dviunit in PS points * _mag/1000 _dvi2bp = numer/254000.0*72.0/denom*_mag/1000.0; - _inPostamble = true; dviPost(stackDepth, numPages, pageWidth*_dvi2bp, pageHeight*_dvi2bp, _mag, numer, denom, prevBopOffset); } @@ -220,7 +148,6 @@ void DVIReader::cmdPost (int) { /** Reads and executes DVI post_post command. * Format: post_post q[4] i[1] 223[>=4] */ void DVIReader::cmdPostPost (int) { - _inPostamble = false; uint32_t postOffset = readUnsigned(4); // pointer to begin of postamble uint8_t id = readUnsigned(1); setDVIVersion(DVIVersion(id)); // identification byte @@ -277,16 +204,22 @@ void DVIReader::cmdPop (int) { * @param[in] c character to typeset */ void DVIReader::putVFChar (Font *font, uint32_t c) { if (auto vf = dynamic_cast<VirtualFont*>(font)) { // is current font a virtual font? - if (const vector<uint8_t> *dvi = vf->getDVI(c)) { // try to get DVI snippet that represents character c - FontManager &fm = FontManager::instance(); - DVIState savedState = _dviState; // save current cursor position - _dviState.x = _dviState.y = _dviState.w = _dviState.z = 0; - int savedFontNum = _currFontNum; // save current font number - fm.enterVF(vf); // enter VF font number context - setFont(fm.vfFirstFontNum(vf), SetFontMode::VF_ENTER); - double savedScale = _dvi2bp; + FontManager &fm = FontManager::instance(); + const vector<uint8_t> *dvi = vf->getDVI(c); // try to get DVI snippet that represents character c + Font *firstFont = fm.vfFirstFont(vf); + if (!dvi && (!firstFont || !dynamic_cast<const JFM*>(firstFont->getMetrics()))) + return; + fm.enterVF(vf); // enter VF font number context + int savedFontNum = _currFontNum; // save current font number + setFont(fm.vfFirstFontNum(vf), SetFontMode::VF_ENTER); + if (!dvi) // no definition present for current (Japanese) char? + dviPutChar(c, firstFont); // fallback for JFM-based virtual fonts + else { // DVI units in virtual fonts are multiples of 1^(-20) times the scaled size of the VF + double savedScale = _dvi2bp; _dvi2bp = vf->scaledSize()/(1 << 20); + DVIState savedState = _dviState; // save current cursor position + _dviState.x = _dviState.y = _dviState.w = _dviState.z = 0; VectorInputStream<uint8_t> vis(*dvi); istream &is = replaceStream(vis); try { @@ -295,12 +228,12 @@ void DVIReader::putVFChar (Font *font, uint32_t c) { catch (const DVIException &e) { // Message::estream(true) << "invalid dvi in vf: " << e.getMessage() << endl; // @@ } - replaceStream(is); // restore previous input stream - _dvi2bp = savedScale; // restore previous scale factor - fm.leaveVF(); // restore previous font number context - setFont(savedFontNum, SetFontMode::VF_LEAVE); // restore previous font number + replaceStream(is); // restore previous input stream _dviState = savedState; // restore previous cursor position + _dvi2bp = savedScale; // restore previous scale factor } + fm.leaveVF(); // restore previous font number context + setFont(savedFontNum, SetFontMode::VF_LEAVE); // restore previous font number } } diff --git a/dviware/dvisvgm/src/DVIReader.hpp b/dviware/dvisvgm/src/DVIReader.hpp index 61c4866714..0e227ba8f6 100644 --- a/dviware/dvisvgm/src/DVIReader.hpp +++ b/dviware/dvisvgm/src/DVIReader.hpp @@ -53,10 +53,7 @@ class DVIReader : public BasicDVIReader, public VFActions { explicit DVIReader (std::istream &is); bool executeDocument (); void executeAll (); - void executePreamble (); - void executePostamble (); bool executePage (unsigned n); - bool inPostamble () const {return _inPostamble;} double getXPos () const override {return _dviState.h;} double getYPos () const override {return _dviState.v;} int stackDepth () const override {return _stateStack.size();} @@ -65,11 +62,8 @@ class DVIReader : public BasicDVIReader, public VFActions { unsigned numberOfPages () const {return _bopOffsets.empty() ? 0 : _bopOffsets.size()-1;} protected: - int executeCommand () override; - void collectBopOffsets (); size_t numberOfPageBytes (int n) const {return _bopOffsets.size() > 1 ? _bopOffsets[n+1]-_bopOffsets[n] : 0;} bool computePageHash (size_t pageno, HashFunction &hashFunc); - void goToPostamble (); virtual void moveRight (double dx, MoveMode mode); virtual void moveDown (double dy, MoveMode mode); void putVFChar (Font *font, uint32_t c); @@ -160,13 +154,12 @@ class DVIReader : public BasicDVIReader, public VFActions { void cmdXTextAndGlyphs (int len) override; private: - bool _inPage; ///< true if stream pointer is between bop and eop - unsigned _currPageNum; ///< current page number (1 is first page) - int _currFontNum; ///< current font number - double _dvi2bp; ///< factor to convert dvi units to PS points - uint32_t _mag; ///< magnification factor * 1000 - bool _inPostamble; ///< true if stream pointer is inside the postamble - DVIState _dviState; ///< current state of the DVI registers + bool _inPage=false; ///< true if stream pointer is between bop and eop + unsigned _currPageNum=0; ///< current page number (1 is first page) + int _currFontNum=0; ///< current font number + double _dvi2bp=0.0; ///< factor to convert dvi units to PS points + uint32_t _mag=1; ///< magnification factor * 1000 + DVIState _dviState; ///< current state of the DVI registers std::stack<DVIState> _stateStack; std::vector<uint32_t> _bopOffsets; }; diff --git a/dviware/dvisvgm/src/DVIToSVG.cpp b/dviware/dvisvgm/src/DVIToSVG.cpp index 7280495e83..df3d3e39e6 100644 --- a/dviware/dvisvgm/src/DVIToSVG.cpp +++ b/dviware/dvisvgm/src/DVIToSVG.cpp @@ -169,6 +169,7 @@ void DVIToSVG::convert (const string &rangestr, pair<int,int> *pageinfo) { prescan.executeAllPages(); actions->setDVIReader(*this); SpecialManager::instance().notifyPreprocessingFinished(); + executeFontDefs(); } unique_ptr<HashFunction> hashFunc; diff --git a/dviware/dvisvgm/src/Font.cpp b/dviware/dvisvgm/src/Font.cpp index 8cbcb1db47..5aee699422 100644 --- a/dviware/dvisvgm/src/Font.cpp +++ b/dviware/dvisvgm/src/Font.cpp @@ -495,7 +495,7 @@ const FontEncoding* PhysicalFontImpl::encoding () const { bool PhysicalFontImpl::findAndAssignBaseFontMap () { const FontEncoding *enc = encoding(); - if (enc && enc->mapsToCharIndex()) { + if (enc && !enc->mapsToUnicode() && enc->mapsToCharIndex()) { // try to find a base font map that maps from character indexes to a suitable // target encoding supported by the font file if (const FontEncoding *bfmap = enc->findCompatibleBaseFontMap(this, _charmapID)) diff --git a/dviware/dvisvgm/src/FontEncoding.cpp b/dviware/dvisvgm/src/FontEncoding.cpp index 8f2673f123..f1e1e38383 100644 --- a/dviware/dvisvgm/src/FontEncoding.cpp +++ b/dviware/dvisvgm/src/FontEncoding.cpp @@ -72,6 +72,15 @@ bool FontEncodingPair::mapsToCharIndex () const { } +bool FontEncodingPair::mapsToUnicode () const { + if (_enc2) + return _enc2->mapsToUnicode(); + if (_enc1) + return _enc1->mapsToUnicode(); + return false; +} + + const FontEncoding* FontEncodingPair::findCompatibleBaseFontMap (const PhysicalFont *font, CharMapID &charmapID) const { if (_enc2) return _enc2->findCompatibleBaseFontMap(font, charmapID); diff --git a/dviware/dvisvgm/src/FontEncoding.hpp b/dviware/dvisvgm/src/FontEncoding.hpp index 1c4a979aa9..a50d97eabf 100644 --- a/dviware/dvisvgm/src/FontEncoding.hpp +++ b/dviware/dvisvgm/src/FontEncoding.hpp @@ -32,6 +32,7 @@ struct FontEncoding { virtual ~FontEncoding () =default; virtual Character decode (uint32_t c) const =0; virtual bool mapsToCharIndex () const =0; + virtual bool mapsToUnicode () const {return false;} virtual const FontEncoding* findCompatibleBaseFontMap (const PhysicalFont *font, CharMapID &charmapID) const {return nullptr;} static FontEncoding* encoding (const std::string &encname); }; @@ -49,6 +50,7 @@ class FontEncodingPair : public FontEncoding { FontEncodingPair (const FontEncoding *enc1, const FontEncoding *enc2) : _enc1(enc1), _enc2(enc2) {} Character decode (uint32_t c) const override; bool mapsToCharIndex () const override; + bool mapsToUnicode () const override; const FontEncoding* findCompatibleBaseFontMap (const PhysicalFont *font, CharMapID &charmapID) const override; const FontEncoding* enc1 () const {return _enc1;} const FontEncoding* enc2 () const {return _enc2;} diff --git a/dviware/dvisvgm/src/FontManager.cpp b/dviware/dvisvgm/src/FontManager.cpp index eabb4a3d30..929e9f823b 100644 --- a/dviware/dvisvgm/src/FontManager.cpp +++ b/dviware/dvisvgm/src/FontManager.cpp @@ -101,8 +101,14 @@ int FontManager::fontnum (int id) const { int FontManager::vfFirstFontNum (const VirtualFont *vf) const { + auto it = _vfFirstFontNumMap.find(vf); + return (it == _vfFirstFontNumMap.end()) ? -1 : (int) it->second; +} + + +Font* FontManager::vfFirstFont (const VirtualFont *vf) const { auto it = _vfFirstFontMap.find(vf); - return (it == _vfFirstFontMap.end()) ? -1 : (int) it->second; + return (it == _vfFirstFontMap.end()) ? nullptr : it->second; } @@ -221,8 +227,10 @@ int FontManager::registerFont (uint32_t fontnum, const string &name, uint32_t ch else { // register font referenced in vf file const VirtualFont *vf = _vfStack.top(); _vfnum2id[vf][fontnum] = newid; - if (_vfFirstFontMap.find(vf) == _vfFirstFontMap.end()) // first fontdef of VF? - _vfFirstFontMap[vf] = fontnum; + if (_vfFirstFontNumMap.find(vf) == _vfFirstFontNumMap.end()) { // first fontdef of VF? + _vfFirstFontNumMap.emplace(vf, fontnum); + _vfFirstFontMap.emplace(vf, _fonts.back().get()); + } } return newid; } diff --git a/dviware/dvisvgm/src/FontManager.hpp b/dviware/dvisvgm/src/FontManager.hpp index 2fe88bee38..321e167b11 100644 --- a/dviware/dvisvgm/src/FontManager.hpp +++ b/dviware/dvisvgm/src/FontManager.hpp @@ -41,12 +41,12 @@ class VirtualFont; * we need a single list with unique IDs of all physical fonts. Characters of * virtual fonts are completely replaced by their DVI description so they don't * appear anywhere in the output. */ -class FontManager -{ - using Num2IdMap = std::unordered_map<uint32_t,int>; - using Name2IdMap = std::unordered_map<std::string,int>; - using VfNum2IdMap = std::unordered_map<const VirtualFont*,Num2IdMap>; - using VfFirstFontMap = std::unordered_map<const VirtualFont*,uint32_t>; +class FontManager { + using Num2IdMap = std::unordered_map<uint32_t, int>; + using Name2IdMap = std::unordered_map<std::string, int>; + using VfNum2IdMap = std::unordered_map<const VirtualFont*, Num2IdMap>; + using VfFirstFontNumMap = std::unordered_map<const VirtualFont*, uint32_t>; + using VfFirstFontMap = std::unordered_map<const VirtualFont*, Font*>; using VfStack = std::stack<VirtualFont*>; public: @@ -63,6 +63,7 @@ class FontManager int fontID (const std::string &name) const; int fontnum (int id) const; int vfFirstFontNum (const VirtualFont *vf) const; + Font* vfFirstFont (const VirtualFont *vf) const; void enterVF (VirtualFont *vf); void leaveVF (); void assignVFChar (int c, std::vector<uint8_t> &&dvi); @@ -77,7 +78,8 @@ class FontManager Name2IdMap _name2id; ///< fontname -> fontID VfNum2IdMap _vfnum2id; VfStack _vfStack; ///< stack of currently processed virtual fonts - VfFirstFontMap _vfFirstFontMap; ///< VF -> local font number of first font defined in VF + VfFirstFontNumMap _vfFirstFontNumMap; ///< VF -> local font number of first font defined in VF + VfFirstFontMap _vfFirstFontMap; ///< VF -> first font defined }; #endif diff --git a/dviware/dvisvgm/src/FontMap.cpp b/dviware/dvisvgm/src/FontMap.cpp index 727fdd83ba..6be5fe6690 100644 --- a/dviware/dvisvgm/src/FontMap.cpp +++ b/dviware/dvisvgm/src/FontMap.cpp @@ -162,7 +162,7 @@ bool FontMap::append (const MapLine &mapline) { if (!mapline.fontfname().empty() || !mapline.encname().empty()) { vector<Subfont*> subfonts; if (mapline.sfd()) - mapline.sfd()->subfonts(subfonts); + subfonts = mapline.sfd()->subfonts(); else subfonts.push_back(nullptr); for (Subfont *subfont : subfonts) { @@ -191,7 +191,7 @@ bool FontMap::replace (const MapLine &mapline) { vector<Subfont*> subfonts; if (mapline.sfd()) - mapline.sfd()->subfonts(subfonts); + subfonts = mapline.sfd()->subfonts(); else subfonts.push_back(nullptr); for (Subfont *subfont : subfonts) { @@ -215,7 +215,7 @@ bool FontMap::remove (const MapLine &mapline) { if (!mapline.texname().empty()) { vector<Subfont*> subfonts; if (mapline.sfd()) - mapline.sfd()->subfonts(subfonts); + subfonts = mapline.sfd()->subfonts(); else subfonts.push_back(nullptr); for (const Subfont *subfont : subfonts) { diff --git a/dviware/dvisvgm/src/Ghostscript.cpp b/dviware/dvisvgm/src/Ghostscript.cpp index 1ff82314ec..11ea79fc1a 100644 --- a/dviware/dvisvgm/src/Ghostscript.cpp +++ b/dviware/dvisvgm/src/Ghostscript.cpp @@ -239,10 +239,18 @@ int Ghostscript::revision () { string Ghostscript::revisionstr () { string revstr; if (int rev = revision()) { - revstr = to_string(rev/100) + "."; - if (rev % 100 < 10) - revstr += "0"; - revstr += to_string(rev%100); + if (rev < 1000) { // until GS 9.52 + revstr = to_string(rev/100) + "."; + if (rev % 100 < 10) + revstr += "0"; + revstr += to_string(rev%100); + } + else { // as of GS 9.52.1, see ghostpdl/base/gsmisc.c + int major = rev / 1000; + int minor = (rev - major*1000)/10; + int patch = rev % 10; + revstr = to_string(major) + "." + to_string(minor) + "." + to_string(patch); + } } return revstr; } diff --git a/dviware/dvisvgm/src/Makefile.in b/dviware/dvisvgm/src/Makefile.in index 7c6cf1ae15..b327bda7ac 100644 --- a/dviware/dvisvgm/src/Makefile.in +++ b/dviware/dvisvgm/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/dviware/dvisvgm/src/PSInterpreter.cpp b/dviware/dvisvgm/src/PSInterpreter.cpp index 038e1326f2..5e09642ef6 100644 --- a/dviware/dvisvgm/src/PSInterpreter.cpp +++ b/dviware/dvisvgm/src/PSInterpreter.cpp @@ -256,49 +256,50 @@ void PSInterpreter::callActions (InputReader &in) { void (PSActions::*handler)(vector<double> &p); // operation handler }; static const unordered_map<string, Operator> operators { - {"applyscalevals", { 3, &PSActions::applyscalevals}}, - {"clip", { 0, &PSActions::clip}}, - {"clippath", { 0, &PSActions::clippath}}, - {"closepath", { 0, &PSActions::closepath}}, - {"curveto", { 6, &PSActions::curveto}}, - {"eoclip", { 0, &PSActions::eoclip}}, - {"eofill", { 0, &PSActions::eofill}}, - {"fill", { 0, &PSActions::fill}}, - {"grestore", { 0, &PSActions::grestore}}, - {"grestoreall", { 0, &PSActions::grestoreall}}, - {"gsave", { 0, &PSActions::gsave}}, - {"image", { 3, &PSActions::image}}, - {"initclip", { 0, &PSActions::initclip}}, - {"lineto", { 2, &PSActions::lineto}}, - {"makepattern", {-1, &PSActions::makepattern}}, - {"moveto", { 2, &PSActions::moveto}}, - {"newpath", { 1, &PSActions::newpath}}, - {"querypos", { 2, &PSActions::querypos}}, - {"raw", {-1, nullptr}}, - {"restore", { 1, &PSActions::restore}}, - {"rotate", { 1, &PSActions::rotate}}, - {"save", { 1, &PSActions::save}}, - {"scale", { 2, &PSActions::scale}}, - {"setblendmode", { 1, &PSActions::setblendmode}}, - {"setcolorspace", { 1, &PSActions::setcolorspace}}, - {"setcmykcolor", { 4, &PSActions::setcmykcolor}}, - {"setdash", {-1, &PSActions::setdash}}, - {"setgray", { 1, &PSActions::setgray}}, - {"sethsbcolor", { 3, &PSActions::sethsbcolor}}, - {"setlinecap", { 1, &PSActions::setlinecap}}, - {"setlinejoin", { 1, &PSActions::setlinejoin}}, - {"setlinewidth", { 1, &PSActions::setlinewidth}}, - {"setmatrix", { 6, &PSActions::setmatrix}}, - {"setmiterlimit", { 1, &PSActions::setmiterlimit}}, - {"setnulldevice", { 1, &PSActions::setnulldevice}}, - {"setopacityalpha",{ 1, &PSActions::setopacityalpha}}, - {"setshapealpha", { 1, &PSActions::setshapealpha}}, - {"setpagedevice", { 0, &PSActions::setpagedevice}}, - {"setpattern", {-1, &PSActions::setpattern}}, - {"setrgbcolor", { 3, &PSActions::setrgbcolor}}, - {"shfill", {-1, &PSActions::shfill}}, - {"stroke", { 0, &PSActions::stroke}}, - {"translate", { 2, &PSActions::translate}}, + {"applyscalevals", { 3, &PSActions::applyscalevals}}, + {"clip", { 0, &PSActions::clip}}, + {"clippath", { 0, &PSActions::clippath}}, + {"closepath", { 0, &PSActions::closepath}}, + {"curveto", { 6, &PSActions::curveto}}, + {"eoclip", { 0, &PSActions::eoclip}}, + {"eofill", { 0, &PSActions::eofill}}, + {"fill", { 0, &PSActions::fill}}, + {"grestore", { 0, &PSActions::grestore}}, + {"grestoreall", { 0, &PSActions::grestoreall}}, + {"gsave", { 0, &PSActions::gsave}}, + {"image", { 3, &PSActions::image}}, + {"initclip", { 0, &PSActions::initclip}}, + {"lineto", { 2, &PSActions::lineto}}, + {"makepattern", {-1, &PSActions::makepattern}}, + {"moveto", { 2, &PSActions::moveto}}, + {"newpath", { 1, &PSActions::newpath}}, + {"querypos", { 2, &PSActions::querypos}}, + {"raw", {-1, nullptr}}, + {"restore", { 1, &PSActions::restore}}, + {"rotate", { 1, &PSActions::rotate}}, + {"save", { 1, &PSActions::save}}, + {"scale", { 2, &PSActions::scale}}, + {"setblendmode", { 1, &PSActions::setblendmode}}, + {"setcolorspace", { 1, &PSActions::setcolorspace}}, + {"setcmykcolor", { 4, &PSActions::setcmykcolor}}, + {"setdash", {-1, &PSActions::setdash}}, + {"setfillconstantalpha", { 1, &PSActions::setfillconstantalpha}}, + {"setgray", { 1, &PSActions::setgray}}, + {"sethsbcolor", { 3, &PSActions::sethsbcolor}}, + {"setisshapealpha", { 1, &PSActions::setisshapealpha}}, + {"setlinecap", { 1, &PSActions::setlinecap}}, + {"setlinejoin", { 1, &PSActions::setlinejoin}}, + {"setlinewidth", { 1, &PSActions::setlinewidth}}, + {"setmatrix", { 6, &PSActions::setmatrix}}, + {"setmiterlimit", { 1, &PSActions::setmiterlimit}}, + {"setnulldevice", { 1, &PSActions::setnulldevice}}, + {"setpagedevice", { 0, &PSActions::setpagedevice}}, + {"setpattern", {-1, &PSActions::setpattern}}, + {"setrgbcolor", { 3, &PSActions::setrgbcolor}}, + {"setstrokeconstantalpha", { 1, &PSActions::setstrokeconstantalpha}}, + {"shfill", {-1, &PSActions::shfill}}, + {"stroke", { 0, &PSActions::stroke}}, + {"translate", { 2, &PSActions::translate}}, }; if (_actions) { in.skipSpace(); diff --git a/dviware/dvisvgm/src/PSInterpreter.hpp b/dviware/dvisvgm/src/PSInterpreter.hpp index 138242abb7..638e42dd8d 100644 --- a/dviware/dvisvgm/src/PSInterpreter.hpp +++ b/dviware/dvisvgm/src/PSInterpreter.hpp @@ -66,19 +66,20 @@ struct PSActions { virtual void setcolorspace (std::vector<double> &p) =0; virtual void setcmykcolor (std::vector<double> &cmyk) =0; virtual void setdash (std::vector<double> &p) =0; + virtual void setfillconstantalpha (std::vector<double> &p) =0; virtual void setgray (std::vector<double> &p) =0; virtual void sethsbcolor (std::vector<double> &hsb) =0; + virtual void setisshapealpha (std::vector<double> &p) =0; virtual void setlinecap (std::vector<double> &p) =0; virtual void setlinejoin (std::vector<double> &p) =0; virtual void setlinewidth (std::vector<double> &p) =0; virtual void setmatrix (std::vector<double> &p) =0; virtual void setmiterlimit (std::vector<double> &p) =0; virtual void setnulldevice (std::vector<double> &p) =0; - virtual void setopacityalpha (std::vector<double> &p) =0; - virtual void setshapealpha (std::vector<double> &p) =0; virtual void setpagedevice (std::vector<double> &p) =0; virtual void setpattern (std::vector<double> &p) =0; virtual void setrgbcolor (std::vector<double> &rgb) =0; + virtual void setstrokeconstantalpha (std::vector<double> &p) =0; virtual void shfill (std::vector<double> &p) =0; virtual void stroke (std::vector<double> &p) =0; virtual void translate (std::vector<double> &p) =0; diff --git a/dviware/dvisvgm/src/PdfSpecialHandler.cpp b/dviware/dvisvgm/src/PdfSpecialHandler.cpp index 3466e44f8e..0d1b7177bd 100644 --- a/dviware/dvisvgm/src/PdfSpecialHandler.cpp +++ b/dviware/dvisvgm/src/PdfSpecialHandler.cpp @@ -48,7 +48,9 @@ void PdfSpecialHandler::preprocess (const string&, istream &is, SpecialActions & {"bannot", &PdfSpecialHandler::preprocessBeginAnn}, {"beginann", &PdfSpecialHandler::preprocessBeginAnn}, {"dest", &PdfSpecialHandler::preprocessDest}, - {"pagesize", &PdfSpecialHandler::preprocessPagesize} + {"pagesize", &PdfSpecialHandler::preprocessPagesize}, + {"mapfile", &PdfSpecialHandler::preprocessMapfile}, + {"mapline", &PdfSpecialHandler::preprocessMapline} }; auto it = commands.find(cmdstr); if (it != commands.end()) @@ -71,8 +73,6 @@ bool PdfSpecialHandler::process (const string&, istream &is, SpecialActions &act {"eannot", &PdfSpecialHandler::processEndAnn}, {"endann", &PdfSpecialHandler::processEndAnn}, {"dest", &PdfSpecialHandler::processDest}, - {"mapfile", &PdfSpecialHandler::processMapfile}, - {"mapline", &PdfSpecialHandler::processMapline} }; auto it = commands.find(cmdstr); if (it != commands.end()) @@ -116,7 +116,7 @@ void PdfSpecialHandler::preprocessPagesize (StreamInputReader &ir, SpecialAction } -void PdfSpecialHandler::processMapfile (StreamInputReader &ir, SpecialActions&) { +void PdfSpecialHandler::preprocessMapfile (StreamInputReader &ir, SpecialActions&) { char modechar = prepare_mode(ir); string fname = ir.getString(); if (!FontMap::instance().read(fname, modechar)) @@ -124,7 +124,7 @@ void PdfSpecialHandler::processMapfile (StreamInputReader &ir, SpecialActions&) } -void PdfSpecialHandler::processMapline (StreamInputReader &ir, SpecialActions&) { +void PdfSpecialHandler::preprocessMapline (StreamInputReader &ir, SpecialActions&) { char modechar = prepare_mode(ir); try { MapLine mapline(ir.getStream()); diff --git a/dviware/dvisvgm/src/PdfSpecialHandler.hpp b/dviware/dvisvgm/src/PdfSpecialHandler.hpp index 67512dd403..0e7d3382ad 100644 --- a/dviware/dvisvgm/src/PdfSpecialHandler.hpp +++ b/dviware/dvisvgm/src/PdfSpecialHandler.hpp @@ -38,11 +38,11 @@ class PdfSpecialHandler : public SpecialHandler { void preprocessBeginAnn (StreamInputReader &ir, SpecialActions &actions); void preprocessDest (StreamInputReader &ir, SpecialActions &actions); void preprocessPagesize (StreamInputReader &ir, SpecialActions &actions); + void preprocessMapfile (StreamInputReader &ir, SpecialActions &actions); + void preprocessMapline (StreamInputReader &ir, SpecialActions &actions); void processBeginAnn (StreamInputReader &ir, SpecialActions &actions); void processEndAnn (StreamInputReader &ir, SpecialActions &actions); void processDest (StreamInputReader &ir, SpecialActions &actions); - void processMapfile (StreamInputReader &ir, SpecialActions &actions); - void processMapline (StreamInputReader &ir, SpecialActions &actions); void dviMovedTo (double x, double y, SpecialActions &actions) override; void dviEndPage (unsigned pageno, SpecialActions &actions) override; diff --git a/dviware/dvisvgm/src/PsSpecialHandler.cpp b/dviware/dvisvgm/src/PsSpecialHandler.cpp index 9641556dd5..f7b5508b65 100644 --- a/dviware/dvisvgm/src/PsSpecialHandler.cpp +++ b/dviware/dvisvgm/src/PsSpecialHandler.cpp @@ -81,8 +81,9 @@ void PsSpecialHandler::initgraphics () { _linecap = _linejoin = 0; // butt end caps and miter joins _miterlimit = 4; _xmlnode = _savenode = nullptr; - _opacityalpha = _shapealpha = 1; // fully opaque - _blendmode = 0; // "normal" mode (no blending) + _isshapealpha = false; // opacity operators change constant component by default + _fillalpha = _strokealpha = {1, 1}; // set constant and shape opacity to non-transparent + _blendmode = 0; // "normal" mode (no blending) _sx = _sy = _cos = 1.0; _pattern = nullptr; _patternEnabled = false; @@ -555,8 +556,9 @@ void PsSpecialHandler::setpagedevice (std::vector<double> &p) { _linewidth = 1; _linecap = _linejoin = 0; // butt end caps and miter joins _miterlimit = 4; - _opacityalpha = _shapealpha = 1; // fully opaque - _blendmode = 0; // "normal" mode (no blending) + _isshapealpha = false; // opacity operators change constant component by default + _fillalpha = _strokealpha = {1, 1}; // set constant and shape opacity to non-transparent + _blendmode = 0; // "normal" mode (no blending) _sx = _sy = _cos = 1.0; _pattern = nullptr; _currentcolor = Color::BLACK; @@ -671,8 +673,8 @@ void PsSpecialHandler::stroke (vector<double> &p) { path->addAttribute("stroke-linecap", _linecap == 1 ? "round" : "square"); if (_linejoin > 0) // default value is "miter", no need to set it explicitly path->addAttribute("stroke-linejoin", _linecap == 1 ? "round" : "bevel"); - if (_opacityalpha < 1 || _shapealpha < 1) - path->addAttribute("stroke-opacity", _opacityalpha*_shapealpha); + if (_strokealpha[0] < 1 || _strokealpha[1] < 1) + path->addAttribute("stroke-opacity", _strokealpha[0] * _strokealpha[1]); if (_blendmode > 0 && _blendmode < 16) path->addAttribute("style", "mix-blend-mode:"+css_blendmode_name(_blendmode)); if (!_dashpattern.empty()) { @@ -735,8 +737,8 @@ void PsSpecialHandler::fill (vector<double> &p, bool evenodd) { } if (evenodd) // SVG default fill rule is "nonzero" algorithm path->addAttribute("fill-rule", "evenodd"); - if (_opacityalpha < 1 || _shapealpha < 1) - path->addAttribute("fill-opacity", _opacityalpha*_shapealpha); + if (_fillalpha[0] < 1 || _fillalpha[1] < 1) + path->addAttribute("fill-opacity", _fillalpha[0] * _fillalpha[1]); if (_blendmode > 0 && _blendmode < 16) path->addAttribute("style", "mix-blend-mode:"+css_blendmode_name(_blendmode)); if (_xmlnode) diff --git a/dviware/dvisvgm/src/PsSpecialHandler.hpp b/dviware/dvisvgm/src/PsSpecialHandler.hpp index 9dcbc2d4ce..8b66499041 100644 --- a/dviware/dvisvgm/src/PsSpecialHandler.hpp +++ b/dviware/dvisvgm/src/PsSpecialHandler.hpp @@ -142,19 +142,20 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions { void setcolorspace (std::vector<double> &p) override {_patternEnabled = bool(p[0]);} void setcmykcolor (std::vector<double> &cmyk) override; void setdash (std::vector<double> &p) override; + void setfillconstantalpha (std::vector<double> &p) override {_fillalpha[_isshapealpha ? 1 : 0] = p[0];} void setgray (std::vector<double> &p) override; void sethsbcolor (std::vector<double> &hsb) override; + void setisshapealpha (std::vector<double> &p) override {_isshapealpha = bool(p[0]);} void setlinecap (std::vector<double> &p) override {_linecap = uint8_t(p[0]);} void setlinejoin (std::vector<double> &p) override {_linejoin = uint8_t(p[0]);} void setlinewidth (std::vector<double> &p) override {_linewidth = scale(p[0] ? p[0] : 0.5);} void setmatrix (std::vector<double> &p) override; void setmiterlimit (std::vector<double> &p) override {_miterlimit = p[0];} void setnulldevice (std::vector<double> &p) override; - void setopacityalpha (std::vector<double> &p) override {_opacityalpha = p[0];} - void setshapealpha (std::vector<double> &p) override {_shapealpha = p[0];} void setpagedevice (std::vector<double> &p) override; void setpattern (std::vector<double> &p) override; void setrgbcolor (std::vector<double> &rgb) override; + void setstrokeconstantalpha (std::vector<double> &p) override {_strokealpha[_isshapealpha ? 1 : 0] = p[0];} void shfill (std::vector<double> &p) override; void stroke (std::vector<double> &p) override; void translate (std::vector<double> &p) override; @@ -163,29 +164,30 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions { private: PSInterpreter _psi; SpecialActions *_actions=nullptr; - PSPreviewFilter _previewFilter; ///< filter to extract information generated by the preview package - PsSection _psSection=PS_NONE; ///< current section processed (nothing yet, headers, or body specials) - XMLElement *_xmlnode=nullptr; ///< if != 0, created SVG elements are appended to this node - XMLElement *_savenode=nullptr; ///< pointer to temporaryly store _xmlnode - std::string _headerCode; ///< collected literal PS header code + PSPreviewFilter _previewFilter; ///< filter to extract information generated by the preview package + PsSection _psSection=PS_NONE; ///< current section processed (nothing yet, headers, or body specials) + XMLElement *_xmlnode=nullptr; ///< if != 0, created SVG elements are appended to this node + XMLElement *_savenode=nullptr; ///< pointer to temporaryly store _xmlnode + std::string _headerCode; ///< collected literal PS header code Path _path; - DPair _currentpoint; ///< current PS position in bp units - Color _currentcolor; ///< current stroke/fill color - double _sx, _sy; ///< horizontal and vertical scale factors retrieved by operator "applyscalevals" - double _cos; ///< cosine of angle between (1,0) and transform(1,0) - double _linewidth; ///< current line width in bp units - double _miterlimit; ///< current miter limit in bp units - double _opacityalpha; ///< opacity level (0=fully transparent, ..., 1=opaque) - double _shapealpha; ///< shape opacity level (0=fully transparent, ..., 1=opaque) - int _blendmode; ///< blend mode used when overlaying colored areas - uint8_t _linecap : 2; ///< current line cap (0=butt, 1=round, 2=projecting square) - uint8_t _linejoin : 2; ///< current line join (0=miter, 1=round, 2=bevel) - double _dashoffset; ///< current dash offset + DPair _currentpoint; ///< current PS position in bp units + Color _currentcolor; ///< current stroke/fill color + double _sx, _sy; ///< horizontal and vertical scale factors retrieved by operator "applyscalevals" + double _cos; ///< cosine of angle between (1,0) and transform(1,0) + double _linewidth; ///< current line width in bp units + double _miterlimit; ///< current miter limit in bp units + bool _isshapealpha; ///< if true, opacity operators act on index 1 (shape component), otherwise on index 0 (constant component) + std::array<double,2> _fillalpha; ///< constant and shape opacity used for fill operations (0=fully transparent, ..., 1=opaque) + std::array<double,2> _strokealpha; ///< constant and shape opacity used for stroke operations (0=fully transparent, ..., 1=opaque) + int _blendmode; ///< blend mode used when overlaying colored areas + uint8_t _linecap : 2; ///< current line cap (0=butt, 1=round, 2=projecting square) + uint8_t _linejoin : 2; ///< current line join (0=miter, 1=round, 2=bevel) + double _dashoffset; ///< current dash offset std::vector<double> _dashpattern; ClippingStack _clipStack; std::map<int, std::unique_ptr<PSPattern>> _patterns; - PSTilingPattern *_pattern; ///< current pattern - bool _patternEnabled; ///< true if active color space is a pattern + PSTilingPattern *_pattern; ///< current pattern + bool _patternEnabled; ///< true if active color space is a pattern }; #endif diff --git a/dviware/dvisvgm/src/Subfont.cpp b/dviware/dvisvgm/src/Subfont.cpp index eb7f244cdb..540270f8a8 100644 --- a/dviware/dvisvgm/src/Subfont.cpp +++ b/dviware/dvisvgm/src/Subfont.cpp @@ -97,10 +97,11 @@ Subfont* SubfontDefinition::subfont (const string &id) const { /** Returns all subfonts defined in this SFD. */ -int SubfontDefinition::subfonts (vector<Subfont*> &sfs) const { +vector<Subfont*> SubfontDefinition::subfonts () const { + vector<Subfont*> subfonts; for (const auto &strsfpair : _subfonts) - sfs.push_back(strsfpair.second.get()); - return int(sfs.size()); + subfonts.push_back(strsfpair.second.get()); + return subfonts; } ////////////////////////////////////////////////////////////////////// diff --git a/dviware/dvisvgm/src/Subfont.hpp b/dviware/dvisvgm/src/Subfont.hpp index 5125194e9d..5b921bdddb 100644 --- a/dviware/dvisvgm/src/Subfont.hpp +++ b/dviware/dvisvgm/src/Subfont.hpp @@ -43,7 +43,7 @@ class SubfontDefinition { const std::string& name() const {return _sfname;} std::string filename() const {return _sfname+".sfd";} Subfont* subfont (const std::string &id) const; - int subfonts (std::vector<Subfont*> &sfs) const; + std::vector<Subfont*> subfonts () const; const char* path () const; protected: diff --git a/dviware/dvisvgm/src/Unicode.cpp b/dviware/dvisvgm/src/Unicode.cpp index 950209bda0..0fea9c3daf 100644 --- a/dviware/dvisvgm/src/Unicode.cpp +++ b/dviware/dvisvgm/src/Unicode.cpp @@ -113,6 +113,41 @@ string Unicode::utf8 (int32_t cp) { return utf8; } + +/** Converts a surrogate pair to its code point. + * @param[in] high high-surrogate value (upper 16 bits) + * @param[in] low low-surrogate value (lower 16 bits) + * @return corresponding code point or 0 if the surrogate is invalid */ +uint32_t Unicode::fromSurrogate (uint32_t high, uint32_t low) { + if (high < 0xD800 || high > 0xDBff || low < 0xDC00 || low > 0xDFFF) + return 0; + // http://www.unicode.org/versions/Unicode3.0.0/ch03.pdf, p. 45 + return (high-0xD800)*0x400 + low-0xDC00 + 0x10000; +} + + +/** Converts a surrogate value to its code point. + * @param[in] surrogate combined high and low surrogate value + * @return corresponding code point or 0 if the surrogate is invalid */ +uint32_t Unicode::fromSurrogate (uint32_t surrogate) { + return fromSurrogate(surrogate >> 16, surrogate & 0xFFFF); +} + + +/** Converts a code point of the surrogate range (0x10000--0x10FFFF) + * to its surrogate value. + * @param[in] cp code point to convert + * @return 32-bit surrogate (combined high and low values) */ +uint32_t Unicode::toSurrogate (uint32_t cp) { + if (cp < 0x10000 || cp > 0x10FFFF) + return 0; + // http://www.unicode.org/versions/Unicode3.0.0/ch03.pdf, p. 45 + uint32_t high = (cp-0x10000)/0x400 + 0xD800; + uint32_t low = (cp-0x10000)%0x400 + 0xDC00; + return (high << 16) | low; +} + + #include "AGLTable.hpp" /** Tries to extract the codepoint from AGL character names like "uni1234" or "u1234". diff --git a/dviware/dvisvgm/src/Unicode.hpp b/dviware/dvisvgm/src/Unicode.hpp index bc9db7e731..e085bac54d 100644 --- a/dviware/dvisvgm/src/Unicode.hpp +++ b/dviware/dvisvgm/src/Unicode.hpp @@ -23,11 +23,13 @@ #include <string> -struct Unicode -{ +struct Unicode { static bool isValidCodepoint (uint32_t code); static uint32_t charToCodepoint (uint32_t c); static std::string utf8 (int32_t c); + static uint32_t fromSurrogate (uint32_t high, uint32_t low); + static uint32_t fromSurrogate (uint32_t cp); + static uint32_t toSurrogate (uint32_t cp); static int32_t aglNameToCodepoint (const std::string &name); }; diff --git a/dviware/dvisvgm/src/XMLNode.cpp b/dviware/dvisvgm/src/XMLNode.cpp index 363115fbca..eb49b9c9db 100644 --- a/dviware/dvisvgm/src/XMLNode.cpp +++ b/dviware/dvisvgm/src/XMLNode.cpp @@ -283,11 +283,11 @@ XMLNode* XMLElement::unwrap (XMLElement *element) { return nullptr; XMLElement *parent = element->parent()->toElement(); XMLNode *prev = element->prev(); - auto unlinkedElement = util::static_unique_ptr_cast<XMLElement>(detach(element)); - if (unlinkedElement->empty()) + auto detachedElement = util::static_unique_ptr_cast<XMLElement>(detach(element)); + if (detachedElement->empty()) return nullptr; - XMLNode *firstChild = unlinkedElement->firstChild(); - while (auto child = detach(unlinkedElement->firstChild())) + XMLNode *firstChild = detachedElement->firstChild(); + while (auto child = detach(detachedElement->firstChild())) prev = parent->insertAfter(std::move(child), prev); return firstChild; } diff --git a/dviware/dvisvgm/src/optimizer/Makefile.in b/dviware/dvisvgm/src/optimizer/Makefile.in index d31d32c12a..0913c8462f 100644 --- a/dviware/dvisvgm/src/optimizer/Makefile.in +++ b/dviware/dvisvgm/src/optimizer/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/dviware/dvisvgm/src/psdefs.cpp b/dviware/dvisvgm/src/psdefs.cpp index 9c8380816d..8cc5a10cb9 100644 --- a/dviware/dvisvgm/src/psdefs.cpp +++ b/dviware/dvisvgm/src/psdefs.cpp @@ -143,13 +143,19 @@ const char *PSInterpreter::PSDEFS = "rgbcolor}ifelse}def/setcolorspace{dup/setcolorspace sysexec @setcolorspace}def" "/@setcolorspace{dup type/arraytype eq{0 get}if/Pattern eq{1}{0}ifelse 1(setcol" "orspace)prcmd}def/setgray 1 defpr/setcmykcolor 4 defpr/sethsbcolor 3 defpr/set" -"rgbcolor 3 defpr/.setopacityalpha{dup/.setopacityalpha sysexec 1(setopacityalp" -"ha)prcmd}def/.setshapealpha{dup/.setshapealpha sysexec 1(setshapealpha)prcmd}d" -"ef/.setblendmode{dup/.setblendmode sysexec<</Normal 0/Compatible 0/Multiply 1/" -"Screen 2/Overlay 3/SoftLight 4/HardLight 5/ColorDodge 6/ColorBurn 7/Darken 8/L" -"ighten 9/Difference 10/Exclusion 11/Hue 12/Saturation 13/Color 14/Luminosity 1" -"5/CompatibleOverprint 16>>exch get 1(setblendmode)prcmd}def/@pdfpagecount{(r)f" -"ile runpdfbegin pdfpagecount runpdfend}def/@pdfpagebox{(r)file runpdfbegin dup" -" dup 1 lt exch pdfpagecount gt or{pop}{pdfgetpage/MediaBox pget pop aload pop}" -"ifelse runpdfend}def DELAYBIND{.bindnow}if "; +"rgbcolor 3 defpr/.setalphaisshape{@SD/.setalphaisshape known{dup/.setalphaissh" +"ape sysexec}if{1}{0}ifelse 1(setisshapealpha)prcmd}bind def/.setfillconstantal" +"pha{@SD/.setfillconstantalpha known{dup/.setfillconstantalpha sysexec}if 1(set" +"fillconstantalpha)prcmd}bind def/.setstrokeconstantalpha{@SD/.setstrokeconstan" +"talpha known{dup/.setstrokeconstantalpha sysexec}if 1(setstrokeconstantalpha)p" +"rcmd}bind def/.setopacityalpha{false .setalphaisshape dup .setfillconstantalph" +"a .setstrokeconstantalpha}bind def/.setshapealpha{true .setalphaisshape dup .s" +"etfillconstantalpha .setstrokeconstantalpha}bind def/.setblendmode{dup/.setble" +"ndmode sysexec<</Normal 0/Compatible 0/Multiply 1/Screen 2/Overlay 3/SoftLight" +" 4/HardLight 5/ColorDodge 6/ColorBurn 7/Darken 8/Lighten 9/Difference 10/Exclu" +"sion 11/Hue 12/Saturation 13/Color 14/Luminosity 15/CompatibleOverprint 16>>ex" +"ch get 1(setblendmode)prcmd}def/@pdfpagecount{(r)file runpdfbegin pdfpagecount" +" runpdfend}def/@pdfpagebox{(r)file runpdfbegin dup dup 1 lt exch pdfpagecount " +"gt or{pop}{pdfgetpage/MediaBox pget pop aload pop}ifelse runpdfend}def DELAYBI" +"ND{.bindnow}if "; |