summaryrefslogtreecommitdiff
path: root/dviware/dvisvgm/src
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/dvisvgm/src')
-rw-r--r--dviware/dvisvgm/src/BasicDVIReader.cpp72
-rw-r--r--dviware/dvisvgm/src/BasicDVIReader.hpp5
-rw-r--r--dviware/dvisvgm/src/CMap.cpp28
-rw-r--r--dviware/dvisvgm/src/CMap.hpp7
-rw-r--r--dviware/dvisvgm/src/CMapReader.cpp2
-rw-r--r--dviware/dvisvgm/src/DVIReader.cpp115
-rw-r--r--dviware/dvisvgm/src/DVIReader.hpp19
-rw-r--r--dviware/dvisvgm/src/DVIToSVG.cpp1
-rw-r--r--dviware/dvisvgm/src/Font.cpp2
-rw-r--r--dviware/dvisvgm/src/FontEncoding.cpp9
-rw-r--r--dviware/dvisvgm/src/FontEncoding.hpp2
-rw-r--r--dviware/dvisvgm/src/FontManager.cpp14
-rw-r--r--dviware/dvisvgm/src/FontManager.hpp16
-rw-r--r--dviware/dvisvgm/src/FontMap.cpp6
-rw-r--r--dviware/dvisvgm/src/Ghostscript.cpp16
-rw-r--r--dviware/dvisvgm/src/Makefile.in4
-rw-r--r--dviware/dvisvgm/src/PSInterpreter.cpp87
-rw-r--r--dviware/dvisvgm/src/PSInterpreter.hpp5
-rw-r--r--dviware/dvisvgm/src/PdfSpecialHandler.cpp10
-rw-r--r--dviware/dvisvgm/src/PdfSpecialHandler.hpp4
-rw-r--r--dviware/dvisvgm/src/PsSpecialHandler.cpp18
-rw-r--r--dviware/dvisvgm/src/PsSpecialHandler.hpp44
-rw-r--r--dviware/dvisvgm/src/Subfont.cpp7
-rw-r--r--dviware/dvisvgm/src/Subfont.hpp2
-rw-r--r--dviware/dvisvgm/src/Unicode.cpp35
-rw-r--r--dviware/dvisvgm/src/Unicode.hpp6
-rw-r--r--dviware/dvisvgm/src/XMLNode.cpp8
-rw-r--r--dviware/dvisvgm/src/optimizer/Makefile.in4
-rw-r--r--dviware/dvisvgm/src/psdefs.cpp24
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 &param);
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 ";