diff options
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src')
217 files changed, 4495 insertions, 2610 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/AGLTable.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/AGLTable.hpp index fe4e6466ac2..8b8514626b3 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/AGLTable.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/AGLTable.hpp @@ -2,7 +2,7 @@ ** AGLTable.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ - /* The following table provides a compact mapping from PostScript character names * to Unicode points. Instead of using the character names directly it maps the * hash values (xxhash32) of the names to the corresponding code points. @@ -33,7 +32,7 @@ struct HashCodepointPair { uint32_t codepoint; }; -std::array<HashCodepointPair, 4048> hash2unicode = {{ +std::array<HashCodepointPair, 4048> hash2unicode {{ {0x001cf4a9, 0x0118}, // Eogonek {0x003b11fb, 0x055f}, // abbreviationmarkarmenian {0x0050a316, 0x0444}, // afii10086 diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp index 88eeefdb69e..7bd3e73b90b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp @@ -2,7 +2,7 @@ ** BasicDVIReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <sstream> #include "BasicDVIReader.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp index cf2d8194e04..f3fc8c7d37c 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp @@ -2,7 +2,7 @@ ** BasicDVIReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -47,7 +47,7 @@ class Matrix; class BasicDVIReader : public StreamReader { protected: - typedef void (BasicDVIReader::*CommandHandler)(int); + using CommandHandler = void (BasicDVIReader::*)(int); enum DVIVersion {DVI_NONE=0, DVI_STANDARD=2, DVI_PTEX=3, DVI_XDV5=5, DVI_XDV6=6, DVI_XDV7=7}; const uint8_t OP_SETCHAR0=0, OP_SETCHAR127=127, OP_SET1=128, OP_EOP=140, OP_FNTNUM0=171, OP_FNTNUM63=234, OP_PRE=247, OP_POST=248, OP_POSTPOST=249, OP_DIR=255, DVI_FILL=223; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp index 5a342fbb111..f056409aa75 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp @@ -2,7 +2,7 @@ ** Bezier.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp index a4f227c014f..82275212e22 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp @@ -2,7 +2,7 @@ ** Bezier.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp index d8a7efb39ee..e2873311574 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp @@ -2,7 +2,7 @@ ** BgColorSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include "BgColorSpecialHandler.hpp" #include "ColorSpecialHandler.hpp" @@ -47,12 +46,6 @@ bool BgColorSpecialHandler::process (const char*, istream &, SpecialActions&) { } -static bool operator < (const pair<unsigned,Color> &pc1, const pair<unsigned,Color> &pc2) { - // order PageColor objects by page number - return pc1.first < pc2.first; -} - - void BgColorSpecialHandler::dviBeginPage (unsigned pageno, SpecialActions &actions) { // Ensure that the background color of the preceeding page is set as the // default background color of the current page because this special affects @@ -69,7 +62,7 @@ void BgColorSpecialHandler::dviBeginPage (unsigned pageno, SpecialActions &actio } -const char** BgColorSpecialHandler::prefixes () const { - static const char *pfx[] = {"background", 0}; +const vector<const char*> BgColorSpecialHandler::prefixes () const { + const vector<const char*> pfx {"background"}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.hpp index d83fb1c7ddc..06572ab1a7e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.hpp @@ -2,7 +2,7 @@ ** BgColorSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -33,13 +33,13 @@ class BgColorSpecialHandler : public SpecialHandler, public DVIBeginPageListener bool process (const char *prefix, std::istream &is, SpecialActions &actions) override; const char* info () const override {return "background color special";} const char* name () const override {return "bgcolor";} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; protected: void dviBeginPage (unsigned pageno, SpecialActions &actions) override; private: - typedef std::pair<unsigned,Color> PageColor; // page number and color + using PageColor = std::pair<unsigned,Color>; // page number and color std::vector<PageColor> _pageColors; }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp index 40f5c1b5f8b..25fa2c66125 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp @@ -2,7 +2,7 @@ ** Bitmap.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <cstdlib> #include <limits> diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp index 30c29cf5f16..c82e2cdba99 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp @@ -2,7 +2,7 @@ ** Bitmap.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp index ba5d62c9835..1b1f234a604 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp @@ -2,7 +2,7 @@ ** BoundingBox.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <sstream> #include "BoundingBox.hpp" @@ -70,25 +69,16 @@ BoundingBox::BoundingBox (const string &boxstr) /** Extracts a sequence of length values from a string like "5cm, 2.4in, 0pt". * @param[in] boxstr whitespace and/or comma separated string of lengths. * @param[out] the extracted lengths */ -void BoundingBox::extractLengths (string boxstr, vector<Length> &lengths) { - boxstr = util::trim(boxstr); - const size_t len = boxstr.length(); - size_t left=0; - string lenstr; - do { - while (left < len && isspace(boxstr[left])) - left++; - size_t right=left; - while (right < len && !isspace(boxstr[right]) && boxstr[right] != ',') - right++; - lenstr = boxstr.substr(left, right-left); - if (!lenstr.empty()) { +vector<Length> BoundingBox::extractLengths (string boxstr) { + vector<Length> lengths; + boxstr = util::replace(boxstr, ",", " "); + boxstr = util::normalize_space(boxstr); + vector<string> lengthStrings = util::split(boxstr, " "); + for (string lenstr : lengthStrings) { + if (!lenstr.empty()) lengths.emplace_back(Length(lenstr)); - if (boxstr[right] == ',') - right++; - left = right; - } - } while (!lenstr.empty() && lengths.size() < 4); + } + return lengths; } @@ -98,8 +88,7 @@ void BoundingBox::extractLengths (string boxstr, vector<Length> &lengths) { * left and (l,l) to the lower right corner. * @param[in] boxstr whitespace and/or comma separated string of lengths. */ void BoundingBox::set (const string &boxstr) { - vector<Length> coord; - extractLengths(boxstr, coord); + vector<Length> coord = extractLengths(boxstr); set(coord); } @@ -272,8 +261,8 @@ ostream& BoundingBox::write (ostream &os) const { } -XMLElementNode* BoundingBox::createSVGRect () const { - XMLElementNode *rect = new XMLElementNode("rect"); +unique_ptr<XMLElementNode> BoundingBox::createSVGRect () const { + auto rect = util::make_unique<XMLElementNode>("rect"); rect->addAttribute("x", minX()); rect->addAttribute("y", minY()); rect->addAttribute("width", width()); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp index 963484ad9d0..2d50dab803a 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp @@ -2,7 +2,7 @@ ** BoundingBox.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,6 +21,7 @@ #ifndef BOUNDINGBOX_HPP #define BOUNDINGBOX_HPP +#include <memory> #include <ostream> #include <string> #include <vector> @@ -33,14 +34,12 @@ class Matrix; class XMLElementNode; -struct BoundingBoxException : MessageException -{ +struct BoundingBoxException : MessageException { BoundingBoxException (const std::string &msg) : MessageException(msg) {} }; -class BoundingBox -{ +class BoundingBox { public: BoundingBox (); BoundingBox (double ulxx, double ulyy, double lrxx, double lryy); @@ -54,7 +53,7 @@ class BoundingBox void embed (const DPair &p) {embed(p.x(), p.y());} void embed (const DPair &c, double r); - static void extractLengths (std::string boxstr, std::vector<Length> &lengths); + static std::vector<Length> extractLengths (std::string boxstr); template <typename T> void embed (const Pair<T> &p) {embed(p.x(), p.y());} @@ -79,7 +78,7 @@ class BoundingBox void transform (const Matrix &tm); std::string toSVGViewBox () const; std::ostream& write (std::ostream &os) const; - XMLElementNode* createSVGRect () const; + std::unique_ptr<XMLElementNode> createSVGRect () const; private: double _ulx, _uly; ///< coordinates of upper left vertex (in PS point units) diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp index 45a9a4d4b17..1127fa0531b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp @@ -2,7 +2,7 @@ ** CLCommandLine.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -20,7 +20,7 @@ #include <algorithm> #include <cstring> -#include <map> +#include <unordered_map> #include "CLCommandLine.hpp" #include "version.hpp" @@ -192,7 +192,7 @@ void CommandLine::help (ostream &os, int mode) const { os << '\n'; // compute width of first column of help output - map<Option*, pair<string,string>> linecols; + unordered_map<Option*, pair<string,string>> linecols; size_t col1width=0; for (const OptSectPair &ospair : options()) { string line = ospair.first->helpline(); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp index 549bfa80c32..e4e6788aef6 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp @@ -2,7 +2,7 @@ ** CLCommandLine.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -40,7 +40,7 @@ class CommandLine { const std::vector<std::string>& filenames () const {return _files;} protected: - typedef std::pair<Option*,int> OptSectPair; + using OptSectPair = std::pair<Option*,int>; void parseShortOption (std::istringstream &is, int argc, char **argv, int &argn); void parseLongOption (std::istream &is); virtual std::vector<OptSectPair>& options () const =0; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLOption.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLOption.hpp index 3e1efe84043..96bc9a3d13e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLOption.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLOption.hpp @@ -2,7 +2,7 @@ ** CLOption.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.cpp index 857d6b0947f..10be33338c0 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.cpp @@ -2,7 +2,7 @@ ** CMap.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <sstream> #include "CMap.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp index 31adbaac038..86a76e9bfea 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp @@ -2,7 +2,7 @@ ** CMap.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp index 5881a8f8af6..9fcaa484b4e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp @@ -2,7 +2,7 @@ ** CMapManager.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,7 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> +#include <array> #include <sstream> #include "CMap.hpp" #include "CMapManager.hpp" @@ -38,7 +38,7 @@ CMapManager& CMapManager::instance () { /** Loads a cmap and returns the corresponding object. */ CMap* CMapManager::lookup (const string &name) { - CMaps::iterator it = _cmaps.find(name); + auto it = _cmaps.find(name); if (it != _cmaps.end()) return it->second.get(); @@ -49,16 +49,17 @@ CMap* CMapManager::lookup (const string &name) { throw CMapReaderException(oss.str()); } - CMap *cmap=0; + unique_ptr<CMap> cmap_ptr; if (name == "Identity-H") - cmap = new IdentityHCMap; + cmap_ptr = util::make_unique<IdentityHCMap>(); else if (name == "Identity-V") - cmap = new IdentityVCMap; + cmap_ptr = util::make_unique<IdentityVCMap>(); else if (name == "unicode") - cmap = new UnicodeCMap; - if (cmap) { - _cmaps[name].reset(cmap); - return cmap; + cmap_ptr = util::make_unique<UnicodeCMap>(); + if (cmap_ptr) { + CMap *ret = cmap_ptr.get(); + _cmaps[name] = std::move(cmap_ptr); + return ret; } // Load cmap data of file <name> and also process all cmaps referenced by operator "usecmap". // This can lead to a sequence of further calls of lookup(). In order to prevent infinite loops @@ -66,20 +67,22 @@ CMap* CMapManager::lookup (const string &name) { // a sequence of inclusions. _includedCMaps.insert(name); // save name of current cmap being processed _level++; // increase nesting level + CMap *ret=nullptr; try { CMapReader reader; - if (!(cmap = reader.read(name))) { + if (!(cmap_ptr = reader.read(name))) { _level = 1; Message::wstream(true) << "CMap file '" << name << "' not found\n"; } - _cmaps[name].reset(cmap); + ret = cmap_ptr.get(); + _cmaps[name] = std::move(cmap_ptr); } catch (const CMapReaderException &e) { Message::estream(true) << "CMap file " << name << ": " << e.what() << "\n"; } if (--_level == 0) // back again at initial nesting level? _includedCMaps.clear(); // => names of included cmaps are no longer needed - return cmap; + return ret; } @@ -93,12 +96,13 @@ CMap* CMapManager::lookup (const string &name) { * @return base font CMap that maps from CIDs to character codes */ const CMap* CMapManager::findCompatibleBaseFontMap (const PhysicalFont *font, const CMap *cmap, CharMapID &charmapID) { if (!font || !cmap) - return 0; + return nullptr; - static const struct CharMapIDToEncName { + struct CharMapIDToEncName { CharMapID id; const char *encname; - } encodings[] = { + }; + const array<CharMapIDToEncName, 10> encodings {{ {CharMapID::WIN_UCS4, "UCS4"}, {CharMapID::WIN_UCS2, "UCS2"}, {CharMapID::WIN_SHIFTJIS, "90ms-RKSJ"}, @@ -109,28 +113,27 @@ const CMap* CMapManager::findCompatibleBaseFontMap (const PhysicalFont *font, co {CharMapID::MAC_TRADCHINESE, "B5pc"}, {CharMapID::MAC_SIMPLCHINESE, "GBpc-EUC"}, {CharMapID::MAC_KOREAN, "KSCpc-EUC"} - }; + }}; // get IDs of all available charmaps in font vector<CharMapID> charmapIDs; font->collectCharMapIDs(charmapIDs); - const bool is_unicode_map = bool(dynamic_cast<const UnicodeCMap*>(cmap)); - const size_t num_encodings = is_unicode_map ? 2 : sizeof(encodings)/sizeof(CharMapIDToEncName); // try to find a compatible encoding CMap + const bool is_unicode_map = bool(dynamic_cast<const UnicodeCMap*>(cmap)); const string ro = cmap->getROString(); - for (const CharMapIDToEncName *enc=encodings; enc < enc+num_encodings; enc++) { + for (const CharMapIDToEncName &enc : encodings) { for (size_t i=0; i < charmapIDs.size(); i++) { - if (enc->id == charmapIDs[i]) { - string cmapname = ro+"-"+enc->encname; + if (enc.id == charmapIDs[i]) { + string cmapname = ro+"-"+enc.encname; if (is_unicode_map || FileFinder::instance().lookup(cmapname, "cmap", false)) { - charmapID = enc->id; + charmapID = enc.id; return is_unicode_map ? cmap : lookup(cmapname); } } } } - return 0; + return nullptr; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.hpp index 994d5dc2155..1c6f0b7332f 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.hpp @@ -2,7 +2,7 @@ ** CMapManager.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,10 +21,10 @@ #ifndef CMAPMANAGER_HPP #define CMAPMANAGER_HPP -#include <map> #include <memory> -#include <set> #include <string> +#include <unordered_map> +#include <unordered_set> #include "CharMapID.hpp" struct CMap; @@ -34,7 +34,6 @@ class PhysicalFont; class CMapManager { - typedef std::map<std::string, std::unique_ptr<CMap>> CMaps; public: CMap* lookup (const std::string &name); const CMap* findCompatibleBaseFontMap (const PhysicalFont *font, const CMap *cmap, CharMapID &charmapID); @@ -44,9 +43,9 @@ class CMapManager CMapManager () : _level(0) {} private: - CMaps _cmaps; ///< loaded cmaps + std::unordered_map<std::string, std::unique_ptr<CMap>> _cmaps; ///< loaded cmaps + std::unordered_set<std::string> _includedCMaps; ///< names of cmaps loaded by "usecmap" int _level; ///< current inclusion depth; >0 if a cmap loaded by "usecmap" is being processed - std::set<std::string> _includedCMaps; ///< names of cmaps loaded by "usecmap" }; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp index 642e0e3a595..e736e1fdd98 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp @@ -2,7 +2,7 @@ ** CMapReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <array> #include <fstream> @@ -28,26 +27,26 @@ #include "CMapReader.hpp" #include "FileFinder.hpp" #include "InputReader.hpp" +#include "utility.hpp" using namespace std; -CMapReader::CMapReader () : _cmap(0), _inCMap(false) -{ +CMapReader::CMapReader () : _inCMap(false) { } /** Reads a cmap file and returns the corresponding CMap object. * @param fname[in] name/path of cmap file * @return CMap object representing the read data, or 0 if file could not be read */ -CMap* CMapReader::read (const string &fname) { - if (const char *path = FileFinder::instance().lookup(fname.c_str(), "cmap", false)) { +unique_ptr<CMap> CMapReader::read (const string &fname) { + if (const char *path = FileFinder::instance().lookup(fname, "cmap", false)) { ifstream ifs(path); if (ifs) return read(ifs, fname); } _tokens.clear(); - return 0; + return unique_ptr<CMap>(); } @@ -55,9 +54,9 @@ CMap* CMapReader::read (const string &fname) { * @param is[in] cmap data input stream * @param is[in] name name of CMap to be read * @return CMap object representing the read data, or 0 if file could not be read */ -CMap* CMapReader::read (std::istream& is, const string &name) { +unique_ptr<CMap> CMapReader::read (std::istream& is, const string &name) { _tokens.clear(); - _cmap = new SegmentedCMap(name); + _cmap = util::make_unique<SegmentedCMap>(name); StreamInputReader ir(is); try { while (ir) { @@ -75,11 +74,10 @@ CMap* CMapReader::read (std::istream& is, const string &name) { } } catch (CMapReaderException &e) { - delete _cmap; - _cmap = 0; + _cmap.release(); throw; } - return _cmap; + return std::move(_cmap); } @@ -91,7 +89,7 @@ void CMapReader::executeOperator (const string &opname, InputReader &ir) { const char *name; void (CMapReader::*handler)(InputReader&); }; - array<Operator, 6> operators = {{ + constexpr array<Operator, 6> operators {{ {"beginbfchar", &CMapReader::op_beginbfchar}, {"beginbfrange", &CMapReader::op_beginbfrange}, {"begincidrange", &CMapReader::op_begincidrange}, diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp index 7c6662d2b17..3d199f6bbf0 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp @@ -2,7 +2,7 @@ ** CMapReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,6 +23,7 @@ #include <cstdlib> #include <istream> +#include <memory> #include <string> #include <vector> #include "MessageException.hpp" @@ -31,10 +32,8 @@ struct CMap; class InputReader; -class CMapReader -{ - class Token - { +class CMapReader { + class Token { public: enum class Type {UNKNOWN, END, DELIM, NUMBER, STRING, NAME, OPERATOR}; @@ -52,8 +51,8 @@ class CMapReader public: CMapReader (); - CMap* read (const std::string &fname); - CMap* read (std::istream &is, const std::string &name); + std::unique_ptr<CMap> read (const std::string &fname); + std::unique_ptr<CMap> read (std::istream &is, const std::string &name); protected: Token popToken () {Token t=_tokens.back(); _tokens.pop_back(); return t;} @@ -66,15 +65,14 @@ class CMapReader void op_usecmap (InputReader &ir); private: - SegmentedCMap *_cmap; ///< CMap being read - std::vector<Token> _tokens; ///< stack of tokens to be processed - bool _inCMap; ///< operator begincmap has been executed + std::unique_ptr<SegmentedCMap> _cmap; ///< pointer to CMap being read + std::vector<Token> _tokens; ///< stack of tokens to be processed + bool _inCMap; ///< operator begincmap has been executed }; -struct CMapReaderException : public MessageException -{ +struct CMapReaderException : public MessageException { CMapReaderException (const std::string &msg) : MessageException(msg) {} }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.cpp index 1a4b56eb740..f530cedda03 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.cpp @@ -2,7 +2,7 @@ ** CRC32.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cstring> #include "CRC32.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.hpp index f91de71a41b..8ecfe5bb226 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.hpp @@ -2,7 +2,7 @@ ** CRC32.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -24,10 +24,10 @@ #include <cstdlib> #include <istream> -class CRC32 -{ +class CRC32 { public: CRC32 (); + CRC32 (const CRC32 &crc32) =delete; void update (const uint8_t *bytes, size_t len); void update (uint32_t n, int bytes=4); void update (const char *str); @@ -38,9 +38,6 @@ class CRC32 static uint32_t compute (const char *str); static uint32_t compute (std::istream &is); - protected: - CRC32 (const CRC32 &crc32) {} - private: uint32_t _crc32; uint32_t _tab[256]; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.cpp index 493751df0a4..b4e90eacec2 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.cpp @@ -2,7 +2,7 @@ ** Calculator.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cmath> #include <sstream> #include <stdexcept> @@ -178,7 +177,7 @@ char Calculator::lex (istream &is) { * @param[in] name name of variable * @return assigned value */ double Calculator::getVariable (const string &name) const { - map<string,double>::const_iterator it = _variables.find(name); + auto it = _variables.find(name); if (it == _variables.end()) throw CalculatorException("undefined variable '" + name + "'"); return it->second; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp index 2c117bb0456..5c0df985b20 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp @@ -2,7 +2,7 @@ ** Calculator.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,8 +22,8 @@ #define CALCULATOR_HPP #include <istream> -#include <map> #include <string> +#include <unordered_map> #include "MessageException.hpp" @@ -49,7 +49,7 @@ class Calculator char lookAhead (std::istream &is); private: - std::map<std::string,double> _variables; + std::unordered_map<std::string,double> _variables; double _numValue; std::string _strValue; }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.cpp index 5084081d0c9..25a973fb15d 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.cpp @@ -2,7 +2,7 @@ ** CharMapID.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp index ca1d47be9b7..1e3fc2142a9 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp @@ -2,7 +2,7 @@ ** CharMapID.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp index ebb4c3476cb..c7dcbbcb1db 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp @@ -2,7 +2,7 @@ ** Character.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp index 948aa8adfb4..b0a3dcd8608 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp @@ -2,7 +2,7 @@ ** Color.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -73,7 +73,7 @@ bool Color::setPSName (string name, bool case_sensitive) { const uint32_t rgb; }; // converted color constants from color.pro - static const array<ColorConstant, 68> constants = {{ + static const array<ColorConstant, 68> constants {{ {"Apricot", 0xFFAD7A}, {"Aquamarine", 0x2DFFB2}, {"Bittersweet", 0xC10200}, @@ -156,11 +156,9 @@ bool Color::setPSName (string name, bool case_sensitive) { } } else { - util::tolower(name); + name = util::tolower(name); auto it = find_if(constants.begin(), constants.end(), [&](const ColorConstant &cc) { - string cmpname = cc.name; - util::tolower(cmpname); - return name == cmpname; + return name == util::tolower(cc.name); }); if (it != constants.end()) { _rgb = it->rgb; @@ -210,12 +208,16 @@ void Color::set (ColorSpace colorSpace, VectorIterator<double> &it) { Color Color::operator *= (double c) { - uint32_t rgb=0; - for (int i=0; i < 3; i++) { - rgb |= uint32_t(floor((_rgb & 0xff)*c+0.5)) << (8*i); - _rgb >>= 8; + if (abs(c) < 0.001) + _rgb &= 0xff000000; + else if (abs(c-trunc(c)) < 0.999) { + uint32_t rgb=0; + for (int i=0; i < 3; i++) { + rgb |= uint32_t((_rgb & 0xff)*c+0.5) << (8*i); + _rgb >>= 8; + } + _rgb = rgb; } - _rgb = rgb; return *this; } @@ -241,7 +243,7 @@ string Color::svgColorString (bool rgbonly) const { uint32_t rgb; const char *name; }; - static const array<ColorName, 138> colornames = {{ + static const array<ColorName, 138> colornames {{ {0x000000, "black"}, {0x000080, "navy"}, {0x00008b, "darkblue"}, @@ -552,7 +554,7 @@ void Color::getLab (std::valarray<double> &lab) const { } -static inline double sqr (double x) {return x*x;} +// static inline double sqr (double x) {return x*x;} static inline double cube (double x) {return x*x*x;} void Color::Lab2XYZ (const valarray<double> &lab, valarray<double> &xyz) { diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp index 035c36e6b6b..95187e0dc53 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp @@ -2,7 +2,7 @@ ** Color.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -47,9 +47,12 @@ class Color Color (double r, double g, double b) {setRGB(r,g,b);} Color (const std::valarray<double> &rgb) {setRGB(rgb);} Color (const std::string &name); - operator uint32_t () const {return _rgb;} + explicit operator uint32_t () const {return _rgb;} bool operator == (const Color &c) const {return _rgb == c._rgb;} bool operator != (const Color &c) const {return _rgb != c._rgb;} + bool operator < (const Color &c) const {return _rgb < c._rgb;} + Color operator *= (double c); + Color operator * (double c) const {return Color(*this) *= c;} void setRGB (uint8_t r, uint8_t g, uint8_t b) {_rgb = (r << 16) | (g << 8) | b;} void setRGB (double r, double g, double b); void setRGB (const std::valarray<double> &rgb) {setRGB(rgb[0], rgb[1], rgb[2]);} @@ -74,7 +77,6 @@ class Color void getXYZ (double &x, double &y, double &z) const; void getLab (double &l, double &a, double &b) const; void getLab (std::valarray<double> &lab) const; - Color operator *= (double c); double deltaE (const Color &c) const; std::string rgbString () const; std::string svgColorString (bool rgbonly) const; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp index 1bc7067c23a..ffca4aa780d 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp @@ -2,7 +2,7 @@ ** ColorSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cstring> #include <sstream> #include <vector> @@ -114,8 +113,8 @@ bool ColorSpecialHandler::process (const char *, istream &is, SpecialActions &ac } -const char** ColorSpecialHandler::prefixes () const { - static const char *pfx[] = {"color", 0}; +const vector<const char*> ColorSpecialHandler::prefixes () const { + const vector<const char*> pfx {"color"}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.hpp index 079618f73ca..e36901564b2 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.hpp @@ -2,7 +2,7 @@ ** ColorSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -36,7 +36,7 @@ class ColorSpecialHandler : public SpecialHandler static Color readColor (const std::string &model, std::istream &is); const char* name () const override {return "color";} const char* info () const override {return "complete support of color specials";} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; private: std::stack<Color> _colorStack; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp index f412aa2927d..d742d6a877d 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp @@ -2,7 +2,7 @@ // It is part of the dvisvgm package and published under the terms // of the GNU General Public License version 3, or (at your option) any later version. // See file COPYING for further details. -// Copyright (C) 2016-2017 Martin Gieseking <martin.gieseking@uos.de> +// Copyright (C) 2016-2018 Martin Gieseking <martin.gieseking@uos.de> #ifndef COMMANDLINE_HPP #define COMMANDLINE_HPP @@ -21,7 +21,7 @@ class CommandLine : public CL::CommandLine CommandLine () : CL::CommandLine( "This program converts DVI files, as created by TeX/LaTeX, to\nthe XML-based scalable vector graphics format SVG.", "[options] dvifile\n-E [options] epsfile", - "Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de>" + "Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de>" ) {} CommandLine (int argc, char **argv) : CommandLine() { @@ -75,7 +75,7 @@ class CommandLine : public CL::CommandLine const char* section (size_t n) const override {return n < _sections.size() ? _sections[n] : nullptr;} private: - std::array<const char*, 5> _sections = {{ + std::array<const char*, 5> _sections {{ "Input options", "SVG output options", "SVG transformations", diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.cpp index b0bd0bd1f49..e00d0894034 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.cpp @@ -2,7 +2,7 @@ ** DLLoader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,43 +18,42 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include "DLLoader.hpp" +using namespace std; -DLLoader::DLLoader (const char *dlname) : _handle(0) -{ - if (dlname && *dlname) { -#ifdef _WIN32 - _handle = LoadLibrary(dlname); -#else - _handle = dlopen(dlname, RTLD_LAZY); -#endif - } + +/** Creates a new DLLoader object and tries to load the given dynamic/shared library. + * @param[in] dlname name of library to load */ +DLLoader::DLLoader (const string &dlname) : _handle(nullptr) { + loadLibrary(dlname); } -DLLoader::~DLLoader () { - if (_handle) { +/** Releases the currently assigned dynamic/shared library and loads another one. + * @param[in] dlname name of library to load */ +bool DLLoader::loadLibrary (const string &dlname) { + closeLibrary(); + if (!dlname.empty()) { #ifdef _WIN32 - FreeLibrary(_handle); + _handle = LoadLibrary(dlname.c_str()); #else - dlclose(_handle); + _handle = dlopen(dlname.c_str(), RTLD_LAZY); #endif } + return _handle != nullptr; } -/** Loads a function or variable from the dynamic/shared library. - * @param[in] name name of function/variable to load - * @return pointer to loaded symbol, or 0 if the symbol could not be loaded */ -void* DLLoader::loadSymbol (const char *name) { +/** Releases the library currently assigned to the DLLoader object. */ +void DLLoader::closeLibrary () { if (_handle) { #ifdef _WIN32 - return (void*)GetProcAddress(_handle, name); + FreeLibrary(_handle); #else - return dlsym(_handle, name); + dlclose(_handle); #endif + _handle = nullptr; } - return 0; } + diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp index 6cedd193abc..1dc71393809 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp @@ -2,7 +2,7 @@ ** DLLoader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,23 +21,27 @@ #ifndef DLLOADER_HPP #define DLLOADER_HPP +#include <string> + #ifdef _WIN32 - #include <windows.h> + #include "windows.hpp" #else #include <dlfcn.h> #endif -class DLLoader -{ +class DLLoader { public: - DLLoader (const char *dlname); - virtual ~DLLoader (); - bool loaded () const {return _handle != 0;} + DLLoader () =delete; + DLLoader (const std::string &dlname); + DLLoader (DLLoader &&loader) =default; + virtual ~DLLoader () {closeLibrary();} + bool loaded () const {return _handle != nullptr;} + bool loadLibrary (const std::string &dlname); protected: - DLLoader () : _handle(0) {} - void* loadSymbol (const char *name); + template <typename T> T loadSymbol (const char *name) const; + void closeLibrary (); private: #ifdef _WIN32 @@ -47,4 +51,22 @@ class DLLoader #endif }; + +/** Loads a function or variable from the dynamic/shared library. + * @param[in] name name of function/variable to load + * @return pointer to loaded symbol, or 0 if the symbol could not be loaded */ +template <typename T> +T DLLoader::loadSymbol (const char *name) const { + if (_handle) { +#ifdef _WIN32 + return reinterpret_cast<T>(GetProcAddress(_handle, name)); +#else + return reinterpret_cast<T>(dlsym(_handle, name)); +#endif + } + return nullptr; +} + +#define LOAD_SYMBOL(sym) loadSymbol<decltype(&sym)>(#sym) + #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp index fa3228d1473..8361e7dccce 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp @@ -2,7 +2,7 @@ ** DVIActions.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -27,10 +27,9 @@ class BoundingBox; class Font; - -struct DVIActions -{ +struct DVIActions{ virtual ~DVIActions () =default; + virtual void reset () {} virtual void setChar (double x, double y, unsigned c, bool vertical, const Font &f) {} virtual void setRule (double x, double y, double height, double width) {} virtual void setTextOrientation (bool vertical) {} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp index 4c94d3edf7a..ff0237109f0 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp @@ -2,7 +2,7 @@ ** DVIReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <cstdarg> #include <fstream> diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.hpp index cd66c0e5681..e46748e664c 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.hpp @@ -2,7 +2,7 @@ ** DVIReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -34,14 +34,12 @@ class FontStyle; class NativeFont; class VirtualFont; -class DVIReader : public BasicDVIReader, public VFActions -{ +class DVIReader : public BasicDVIReader, public VFActions { protected: enum class WritingMode {LR=0, TB=1, BT=3}; enum class SetFontMode {SF_SHORT, SF_LONG, VF_ENTER, VF_LEAVE}; - struct DVIState - { + struct DVIState { double h, v; ///< horizontal and vertical cursor position double x, w, y, z; ///< additional registers to store horizontal (x, w) and vertical (y, z) positions WritingMode d; ///< direction: 0: horizontal, 1: vertical(top->bottom), 3: vertical (bottom->top) diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp index 64a0e183b4a..d527ab2553d 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp @@ -2,7 +2,7 @@ ** DVIToSVG.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -37,6 +37,7 @@ #include "PreScanDVIReader.hpp" #include "SignalHandler.hpp" #include "SVGOutput.hpp" +#include "utility.hpp" #include "version.hpp" /////////////////////////////////// @@ -49,13 +50,13 @@ #include "HtmlSpecialHandler.hpp" #include "PapersizeSpecialHandler.hpp" #include "PdfSpecialHandler.hpp" +#include "TpicSpecialHandler.hpp" #ifndef HAVE_LIBGS #include "NoPsSpecialHandler.hpp" #endif #ifndef DISABLE_GS #include "PsSpecialHandler.hpp" #endif -#include "TpicSpecialHandler.hpp" /////////////////////////////////// @@ -75,12 +76,7 @@ DVIToSVG::DVIToSVG (istream &is, SVGOutputBase &out) : DVIReader(is), _out(out) _pageByte = 0; _prevXPos = _prevYPos = numeric_limits<double>::min(); _prevWritingMode = WritingMode::LR; - _actions = new DVIToSVGActions(*this, _svg); -} - - -DVIToSVG::~DVIToSVG () { - delete _actions; + _actions = util::make_unique<DVIToSVGActions>(*this, _svg); } @@ -112,7 +108,7 @@ void DVIToSVG::convert (unsigned first, unsigned last, pair<int,int> *pageinfo) else Message::wstream(true) << "failed to write output to " << fname << '\n'; _svg.reset(); - static_cast<DVIToSVGActions*>(_actions)->reset(); + _actions->reset(); } if (pageinfo) { pageinfo->first = last-first+1; @@ -130,7 +126,7 @@ void DVIToSVG::convert (const string &rangestr, pair<int,int> *pageinfo) { throw MessageException("invalid page range format"); Message::mstream(false, Message::MC_PAGE_NUMBER) << "pre-processing DVI file (format version " << getDVIVersion() << ")\n"; - if (DVIToSVGActions *actions = dynamic_cast<DVIToSVGActions*>(_actions)) { + if (DVIToSVGActions *actions = dynamic_cast<DVIToSVGActions*>(_actions.get())) { PreScanDVIReader prescan(getInputStream(), actions); actions->setDVIReader(prescan); prescan.executeAllPages(); @@ -171,13 +167,13 @@ int DVIToSVG::executeCommand () { * @param[in] pageno physical page number (1 = first page) * @param[in] c contains information about the page (page number etc.) */ void DVIToSVG::enterBeginPage (unsigned pageno, const vector<int32_t> &c) { - if (dynamic_cast<DVIToSVGActions*>(_actions)) { + if (dynamic_cast<DVIToSVGActions*>(_actions.get())) { Message::mstream().indent(0); Message::mstream(false, Message::MC_PAGE_NUMBER) << "processing page " << pageno; if (pageno != (unsigned)c[0]) // Does page number shown on page differ from physical page number? Message::mstream(false) << " [" << c[0] << ']'; Message::mstream().indent(1); - _svg.appendToDoc(new XMLCommentNode(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " ")); + _svg.appendToDoc(util::make_unique<XMLCommentNode>(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " ")); } } @@ -185,7 +181,7 @@ void DVIToSVG::enterBeginPage (unsigned pageno, const vector<int32_t> &c) { /** This template method is called by DVIReader::cmdEop() after * executing the EOP actions. */ void DVIToSVG::leaveEndPage (unsigned) { - if (!dynamic_cast<DVIToSVGActions*>(_actions)) + if (!dynamic_cast<DVIToSVGActions*>(_actions.get())) return; // set bounding box and apply page transformations @@ -212,13 +208,12 @@ void DVIToSVG::leaveEndPage (unsigned) { // convention: DVI position (0,0) equals (1in, 1in) relative // to the upper left vertex of the page (see DVI specification) const double border = -72; - bbox = BoundingBox(border, border, size.widthInBP()+border, size.heightInBP()+border); + bbox = BoundingBox(border, border, size.width().bp()+border, size.height().bp()+border); } } else { // set/modify bounding box by explicitly given values try { - vector<Length> lengths; - BoundingBox::extractLengths(_bboxFormatString, lengths); + vector<Length> lengths = BoundingBox::extractLengths(_bboxFormatString); if (lengths.size() == 1 || lengths.size() == 2) { // relative box size? // apply the page transformation and adjust the bbox afterwards Matrix matrix; @@ -269,7 +264,7 @@ void DVIToSVG::getPageTransformation(Matrix &matrix) const { } -static void collect_chars (map<const Font*, set<int>> &fontmap) { +static void collect_chars (unordered_map<const Font*, set<int>> &fontmap) { for (const auto &entry : fontmap) { if (entry.first->uniqueFont() != entry.first) { for (int c : entry.second) @@ -282,18 +277,16 @@ static void collect_chars (map<const Font*, set<int>> &fontmap) { /** Adds the font information to the SVG tree. * @param[in] svgElement the font nodes are added to this node */ void DVIToSVG::embedFonts (XMLElementNode *svgElement) { - if (!svgElement) - return; - if (!_actions) // no dvi actions => no chars written => no fonts to embed + if (!svgElement || !_actions) // no dvi actions => no chars written => no fonts to embed return; - const DVIToSVGActions *svgActions = static_cast<DVIToSVGActions*>(_actions); - map<const Font*,set<int>> &usedCharsMap = svgActions->getUsedChars(); + const DVIToSVGActions *svgActions = static_cast<DVIToSVGActions*>(_actions.get()); + auto &usedCharsMap = svgActions->getUsedChars(); collect_chars(usedCharsMap); GlyphTracerMessages messages; - set<const Font*> tracedFonts; // collect unique fonts already traced + unordered_set<const Font*> tracedFonts; // collect unique fonts already traced for (const auto &fontchar : usedCharsMap) { const Font *font = fontchar.first; if (const PhysicalFont *ph_font = dynamic_cast<const PhysicalFont*>(font)) { @@ -324,32 +317,28 @@ void DVIToSVG::embedFonts (XMLElementNode *svgElement) { * @param[in] pswarning if true, shows warning about disabled PS support * @return the SpecialManager that handles special statements */ void DVIToSVG::setProcessSpecials (const char *ignorelist, bool pswarning) { - if (ignorelist && strcmp(ignorelist, "*") == 0) { // ignore all specials? + if (ignorelist && strcmp(ignorelist, "*") == 0) // ignore all specials? SpecialManager::instance().unregisterHandlers(); - } else { // add special handlers - SpecialHandler *handlers[] = { - 0, // placeholder for PsSpecialHandler - new BgColorSpecialHandler, // handles background color special - new ColorSpecialHandler, // handles color specials - new DvisvgmSpecialHandler, // handles raw SVG embeddings - new EmSpecialHandler, // handles emTeX specials - new HtmlSpecialHandler, // handles hyperref specials - new PapersizeSpecialHandler, // handles papersize special - new PdfSpecialHandler, // handles pdf specials - new TpicSpecialHandler, // handles tpic specials - 0 - }; - SpecialHandler **p = handlers; + vector<unique_ptr<SpecialHandler>> handlers; + handlers.emplace_back(util::make_unique<BgColorSpecialHandler>()); // handles background color special + handlers.emplace_back(util::make_unique<ColorSpecialHandler>()); // handles color specials + handlers.emplace_back(util::make_unique<DvisvgmSpecialHandler>()); // handles raw SVG embeddings + handlers.emplace_back(util::make_unique<EmSpecialHandler>()); // handles emTeX specials + handlers.emplace_back(util::make_unique<HtmlSpecialHandler>()); // handles hyperref specials + handlers.emplace_back(util::make_unique<PapersizeSpecialHandler>()); // handles papersize special + handlers.emplace_back(util::make_unique<PdfSpecialHandler>()); // handles pdf specials + handlers.emplace_back(util::make_unique<TpicSpecialHandler>()); // handles tpic specials #ifndef DISABLE_GS if (Ghostscript().available()) - *p = new PsSpecialHandler; + handlers.emplace_back(util::make_unique<PsSpecialHandler>()); // handles PostScript specials else #endif { #ifndef HAVE_LIBGS - *p = new NoPsSpecialHandler; // dummy PS special handler that only prints warning messages + // dummy PS special handler that only prints warning messages + handlers.emplace_back(util::make_unique<NoPsSpecialHandler>()); if (pswarning) { #ifdef DISABLE_GS Message::wstream() << "processing of PostScript specials has been disabled permanently\n"; @@ -360,7 +349,7 @@ void DVIToSVG::setProcessSpecials (const char *ignorelist, bool pswarning) { #endif } SpecialManager::instance().unregisterHandlers(); - SpecialManager::instance().registerHandlers(p, ignorelist); + SpecialManager::instance().registerHandlers(handlers, ignorelist); } } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp index 6e1aafd699e..5385188f370 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp @@ -2,7 +2,7 @@ ** DVIToSVG.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -30,11 +30,9 @@ struct DVIActions; class Matrix; struct SVGOutputBase; -class DVIToSVG : public DVIReader -{ +class DVIToSVG : public DVIReader { public: explicit DVIToSVG (std::istream &is, SVGOutputBase &out); - ~DVIToSVG (); void convert (const std::string &range, std::pair<int,int> *pageinfo=0); void setPageSize (const std::string &format) {_bboxFormatString = format;} void setPageTransformation (const std::string &cmds) {_transCmds = cmds;} @@ -54,7 +52,7 @@ class DVIToSVG : public DVIReader static char TRACE_MODE; protected: - DVIToSVG (const DVIToSVG&); + DVIToSVG (const DVIToSVG&) =delete; void convert (unsigned firstPage, unsigned lastPage, std::pair<int,int> *pageinfo=0); int executeCommand () override; void enterBeginPage (unsigned pageno, const std::vector<int32_t> &c); @@ -82,7 +80,7 @@ class DVIToSVG : public DVIReader private: SVGTree _svg; SVGOutputBase &_out; - DVIActions *_actions; + std::unique_ptr<DVIActions> _actions; std::string _bboxFormatString; ///< bounding box size/format set by the user std::string _transCmds; ///< page transformation commands set by the user double _pageHeight, _pageWidth; ///< global page height and width stored in the postamble diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp index c1f35ef0115..ef377e7266b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp @@ -2,7 +2,7 @@ ** DVIToSVGActions.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -158,7 +158,7 @@ void DVIToSVGActions::setChar (double x, double y, unsigned c, bool vertical, co * @param[in] width length of the horizontal edges */ void DVIToSVGActions::setRule (double x, double y, double height, double width) { // (x,y) is the lower left corner of the rectangle - XMLElementNode *rect = new XMLElementNode("rect"); + auto rect = util::make_unique<XMLElementNode>("rect"); rect->addAttribute("x", x); rect->addAttribute("y", y-height); rect->addAttribute("height", height); @@ -167,7 +167,7 @@ void DVIToSVGActions::setRule (double x, double y, double height, double width) rect->addAttribute("transform", getMatrix().getSVG()); if (getColor() != Color::BLACK) rect->addAttribute("fill", _svg.getColor().svgColorString()); - _svg.appendToPage(rect); + _svg.appendToPage(std::move(rect)); // update bounding box BoundingBox bb(x, y-height, x+width, y); @@ -225,13 +225,13 @@ void DVIToSVGActions::endPage (unsigned pageno) { _svg.transformPage(matrix); if (_bgcolor != Color::TRANSPARENT) { // create a rectangle filled with the background color - XMLElementNode *r = new XMLElementNode("rect"); - r->addAttribute("x", _bbox.minX()); - r->addAttribute("y", _bbox.minY()); - r->addAttribute("width", _bbox.width()); - r->addAttribute("height", _bbox.height()); - r->addAttribute("fill", _bgcolor.svgColorString()); - _svg.prependToPage(r); + auto rect = util::make_unique<XMLElementNode>("rect"); + rect->addAttribute("x", _bbox.minX()); + rect->addAttribute("y", _bbox.minY()); + rect->addAttribute("width", _bbox.width()); + rect->addAttribute("height", _bbox.height()); + rect->addAttribute("fill", _bgcolor.svgColorString()); + _svg.prependToPage(std::move(rect)); } } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp index 613315346e1..0712f6cd1e0 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp @@ -2,7 +2,7 @@ ** DVIToSVGActions.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,8 +21,8 @@ #ifndef DVITOSVGACTIONS_HPP #define DVITOSVGACTIONS_HPP -#include <map> -#include <set> +#include <unordered_map> +#include <unordered_set> #include "BoundingBox.hpp" #include "DVIActions.hpp" #include "Matrix.hpp" @@ -36,15 +36,14 @@ class FileFinder; class Font; class XMLNode; -class DVIToSVGActions : public DVIActions, public SpecialActions -{ - typedef std::map<const Font*, std::set<int>> CharMap; - typedef std::set<const Font*> FontSet; - typedef std::map<std::string,BoundingBox> BoxMap; +class DVIToSVGActions : public DVIActions, public SpecialActions { + using CharMap = std::unordered_map<const Font*, std::set<int>>; + using FontSet = std::unordered_set<const Font*>; + using BoxMap = std::unordered_map<std::string,BoundingBox>; public: DVIToSVGActions (DVIToSVG &dvisvg, SVGTree &svg); - void reset (); + void reset () override; void setChar (double x, double y, unsigned c, bool vertical, const Font &f) override; void setRule (double x, double y, double height, double width) override; void setBgColor (const Color &color) override; @@ -55,10 +54,10 @@ class DVIToSVGActions : public DVIActions, public SpecialActions Color getColor () const override {return _svg.getColor();} int getDVIStackDepth() const override {return _dvireader->stackDepth();} unsigned getCurrentPageNumber() const override {return _dvireader->currentPageNumber();} - void appendToPage (XMLNode *node) override {_svg.appendToPage(node);} - void appendToDefs (XMLNode *node) override {_svg.appendToDefs(node);} - void prependToPage (XMLNode *node) override {_svg.prependToPage(node);} - void pushContextElement (XMLElementNode *node) override {_svg.pushContextElement(node);} + void appendToPage(std::unique_ptr<XMLNode> &&node) override {_svg.appendToPage(std::move(node));} + void appendToDefs(std::unique_ptr<XMLNode> &&node) override {_svg.appendToDefs(std::move(node));} + void prependToPage(std::unique_ptr<XMLNode> &&node) override {_svg.prependToPage(std::move(node));} + void pushContextElement (std::unique_ptr<XMLElementNode> &&node) override {_svg.pushContextElement(std::move(node));} void popContextElement () override {_svg.popContextElement();} void setTextOrientation(bool vertical) override {_svg.setVertical(vertical);} void moveToX (double x) override; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DependencyGraph.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DependencyGraph.hpp index 52dd46ac17b..ba8fccd932d 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DependencyGraph.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DependencyGraph.hpp @@ -2,7 +2,7 @@ ** DependencyGraph.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,73 +22,86 @@ #define DEPENDENCYGRAPH_HPP #include <map> +#include <memory> +#include <set> #include <vector> +#include "utility.hpp" template <typename T> -class DependencyGraph -{ +class DependencyGraph { struct GraphNode { - typedef typename std::vector<GraphNode*> Dependees; - - GraphNode (const T &k) : key(k), dependent(0) {} + GraphNode (const T &k) : key(k), dependent() {} void addDependee (GraphNode *node) { if (node) { node->dependent = this; - dependees.push_back(node); + dependees.insert(node); } } - void deleteDependentsAndSelf () { - if (dependent) - dependent->deleteDependentsAndSelf(); - for (typename Dependees::iterator it = dependees.begin(); it != dependees.end(); ++it) - (*it)->dependent = 0; - delete this; + void unlinkDependees () { + for (GraphNode *dependee : dependees) + dependee->dependent = nullptr; + dependees.clear(); + } + + void unlinkDependee (GraphNode *dependee) { + auto it = dependees.find(dependee); + if (it != dependees.end()) { + (*it)->dependent = nullptr; + dependees.erase(it); + } } T key; GraphNode *dependent; - Dependees dependees; + std::set<GraphNode*> dependees; }; - typedef std::map<T, GraphNode*> NodeMap; + using NodeMap = std::map<T, std::unique_ptr<GraphNode>>; public: - ~DependencyGraph() { - for (typename NodeMap::iterator it=_nodeMap.begin(); it != _nodeMap.end(); ++it) - delete it->second; - } - + /** Inserts a new isolated node into the dependency graph. */ void insert (const T &key) { if (!contains(key)) - _nodeMap[key] = new GraphNode(key); + _nodeMap.emplace(key, util::make_unique<GraphNode>(key)); } - void insert (const T &depKey, const T &key) { - if (contains(key)) - return; - typename NodeMap::iterator it = _nodeMap.find(depKey); - if (it != _nodeMap.end()) { - GraphNode *node = new GraphNode(key); - it->second->addDependee(node); - _nodeMap[key] = node; + /** Inserts a new node to the graph and adds a dependency on an existing one to it. + * @param[in] key ID of new node to insert + * @param[in] dependantKey ID of node the new node should depend on */ + void insert (const T &dependentKey, const T &key) { + if (!contains(key)) { + auto dependentIter = _nodeMap.find(dependentKey); + if (dependentIter != _nodeMap.end()) { + auto node = util::make_unique<GraphNode>(key); + dependentIter->second->addDependee(node.get()); + _nodeMap.emplace(key, std::move(node)); + } } } + /** Removes a node and all its dependents from the graph. */ void removeDependencyPath (const T &key) { - typename NodeMap::iterator it = _nodeMap.find(key); + auto it = _nodeMap.find(key); if (it != _nodeMap.end()) { - GraphNode *startNode = it->second; - for (GraphNode *node=startNode; node; node=node->dependent) + for (GraphNode *node = it->second.get(); node;) { + GraphNode *dependent = node->dependent; + node->unlinkDependees(); + if (dependent) + dependent->unlinkDependee(node); _nodeMap.erase(node->key); - startNode->deleteDependentsAndSelf(); + node = dependent; + } } } - void getKeys (std::vector<T> &keys) const { - for (typename NodeMap::const_iterator it=_nodeMap.begin(); it != _nodeMap.end(); ++it) - keys.push_back(it->first); + /** Returns the IDs of all nodes present in the graph. */ + std::vector<T> getKeys () const { + std::vector<T> keys; + for (auto &entry : _nodeMap) + keys.emplace_back(entry.first); + return keys; } bool contains (const T &value) const { @@ -102,7 +115,7 @@ class DependencyGraph #if 0 void writeDOT (std::ostream &os) const { os << "digraph {\n"; - for (typename NodeMap::const_iterator it=_nodeMap.begin(); it != _nodeMap.end(); ++it) { + for (auto it=_nodeMap.begin(); it != _nodeMap.end(); ++it) { GraphNode *node = it->second; if (node->dependent) os << (node->key) << " -> " << (node->dependent->key) << ";\n"; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp index 3849200d7bc..15bcfd83f92 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp @@ -2,7 +2,7 @@ ** Directory.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,13 +18,12 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include "Directory.hpp" using namespace std; #ifdef _WIN32 - #include <windows.h> + #include "windows.hpp" #else #include <errno.h> #include <sys/stat.h> @@ -111,7 +110,7 @@ const char* Directory::read (EntryType type) { #else if (_dir) { while ((_dirent = readdir(_dir))) { - string path = string(_dirname) + "/" + _dirent->d_name; + string path = _dirname + "/" + _dirent->d_name; struct stat stats; if (stat(path.c_str(), &stats) == 0) { if (S_ISDIR(stats.st_mode)) { diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp index fa0e2543abb..4ff46e734f2 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp @@ -2,7 +2,7 @@ ** Directory.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,13 +23,12 @@ #include <string> #ifdef _WIN32 - #include <windows.h> + #include "windows.hpp" #else #include <dirent.h> #endif -class Directory -{ +class Directory { public: enum EntryType {ET_FILE, ET_DIR, ET_FILE_OR_DIR}; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp index ad09f800d7e..720da8ddeca 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp @@ -2,7 +2,7 @@ ** DvisvgmSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,7 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> +#include <array> #include <cstring> #include <utility> #include "DvisvgmSpecialHandler.hpp" @@ -26,6 +26,7 @@ #include "InputReader.hpp" #include "Length.hpp" #include "SpecialActions.hpp" +#include "utility.hpp" #include "XMLNode.hpp" #include "XMLString.hpp" @@ -42,20 +43,21 @@ void DvisvgmSpecialHandler::preprocess (const char*, istream &is, SpecialActions struct Command { const char *name; void (DvisvgmSpecialHandler::*handler)(InputReader&); - } commands[] = { + }; + constexpr array<Command, 5> commands {{ {"raw", &DvisvgmSpecialHandler::preprocessRaw}, {"rawdef", &DvisvgmSpecialHandler::preprocessRawDef}, {"rawset", &DvisvgmSpecialHandler::preprocessRawSet}, {"endrawset", &DvisvgmSpecialHandler::preprocessEndRawSet}, - {"rawput", &DvisvgmSpecialHandler::preprocessRawPut}, - }; + {"rawput", &DvisvgmSpecialHandler::preprocessRawPut} + }}; StreamInputReader ir(is); - string cmd = ir.getWord(); - for (size_t i=0; i < sizeof(commands)/sizeof(Command); i++) { - if (commands[i].name == cmd) { + string cmdstr = ir.getWord(); + for (const Command &command : commands) { + if (command.name == cmdstr) { ir.skipSpace(); - (this->*commands[i].handler)(ir); + (this->*command.handler)(ir); return; } } @@ -92,7 +94,7 @@ void DvisvgmSpecialHandler::preprocessRaw (InputReader &ir) { return; string str = ir.getLine(); if (!str.empty()) - _currentMacro->second.emplace_back(string("P")+str); + _currentMacro->second.emplace_back("P"+str); } @@ -101,7 +103,7 @@ void DvisvgmSpecialHandler::preprocessRawDef (InputReader &ir) { return; string str = ir.getLine(); if (!str.empty()) - _currentMacro->second.emplace_back(string("D")+str); + _currentMacro->second.emplace_back("D"+str); } @@ -119,21 +121,22 @@ bool DvisvgmSpecialHandler::process (const char *prefix, istream &is, SpecialAct struct Command { const char *name; void (DvisvgmSpecialHandler::*handler)(InputReader&, SpecialActions&); - } commands[] = { + }; + constexpr array<Command, 7> commands {{ {"raw", &DvisvgmSpecialHandler::processRaw}, {"rawdef", &DvisvgmSpecialHandler::processRawDef}, {"rawset", &DvisvgmSpecialHandler::processRawSet}, {"endrawset", &DvisvgmSpecialHandler::processEndRawSet}, {"rawput", &DvisvgmSpecialHandler::processRawPut}, {"bbox", &DvisvgmSpecialHandler::processBBox}, - {"img", &DvisvgmSpecialHandler::processImg}, - }; + {"img", &DvisvgmSpecialHandler::processImg} + }}; StreamInputReader ir(is); - string cmd = ir.getWord(); - for (size_t i=0; i < sizeof(commands)/sizeof(Command); i++) { - if (commands[i].name == cmd) { + string cmdstr = ir.getWord(); + for (const Command &command : commands) { + if (command.name == cmdstr) { ir.skipSpace(); - (this->*commands[i].handler)(ir, actions); + (this->*command.handler)(ir, actions); return true; } } @@ -145,20 +148,9 @@ bool DvisvgmSpecialHandler::process (const char *prefix, istream &is, SpecialAct * @param[in,out] str text to expand * @param[in] actions interfcae to the world outside the special handler */ static void expand_constants (string &str, SpecialActions &actions) { - struct Constant { - const char *name; - string val; - } - constants[] = { - {"x", XMLString(actions.getX())}, - {"y", XMLString(actions.getY())}, - {"color", actions.getColor().svgColorString()}, - {"nl", "\n"}, - {0, ""} - }; bool repl_bbox = true; while (repl_bbox) { - size_t pos = str.find(string("{?bbox ")); + size_t pos = str.find("{?bbox "); if (pos == string::npos) repl_bbox = false; else { @@ -173,12 +165,22 @@ static void expand_constants (string &str, SpecialActions &actions) { repl_bbox = false; } } - for (const Constant *p=constants; p->name; p++) { - const string pattern = string("{?")+p->name+"}"; + struct Constant { + const char *name; + string val; + }; + const array<Constant, 4> constants {{ + {"x", XMLString(actions.getX())}, + {"y", XMLString(actions.getY())}, + {"color", actions.getColor().svgColorString()}, + {"nl", "\n"}, + }}; + for (const Constant &constant : constants) { + const string pattern = string("{?")+constant.name+"}"; size_t pos = str.find(pattern); while (pos != string::npos) { - str.replace(pos, strlen(p->name)+3, p->val); - pos = str.find(pattern, pos+p->val.length()); // look for further matches + str.replace(pos, strlen(constant.name)+3, constant.val); + pos = str.find(pattern, pos+constant.val.length()); // look for further matches } } } @@ -189,7 +191,7 @@ void DvisvgmSpecialHandler::processRaw (InputReader &ir, SpecialActions &actions string str = ir.getLine(); if (!str.empty()) { expand_constants(str, actions); - actions.appendToPage(new XMLTextNode(str)); + actions.appendToPage(util::make_unique<XMLTextNode>(str)); } } } @@ -200,7 +202,7 @@ void DvisvgmSpecialHandler::processRawDef (InputReader &ir, SpecialActions &acti string str = ir.getLine(); if (!str.empty()) { expand_constants(str, actions); - actions.appendToDefs(new XMLTextNode(str)); + actions.appendToDefs(util::make_unique<XMLTextNode>(str)); } } } @@ -221,7 +223,7 @@ void DvisvgmSpecialHandler::processRawPut (InputReader &ir, SpecialActions &acti if (_nestingLevel > 0) return; string id = ir.getString(); - MacroMap::iterator it = _macros.find(id); + auto it = _macros.find(id); if (it == _macros.end()) throw SpecialException("undefined SVG fragment '" + id + "' referenced"); @@ -232,9 +234,9 @@ void DvisvgmSpecialHandler::processRawPut (InputReader &ir, SpecialActions &acti if ((type == 'P' || type == 'D') && !def.empty()) { expand_constants(def, actions); if (type == 'P') - actions.appendToPage(new XMLTextNode(def)); + actions.appendToPage(util::make_unique<XMLTextNode>(def)); else { // type == 'D' - actions.appendToDefs(new XMLTextNode(def)); + actions.appendToDefs(util::make_unique<XMLTextNode>(def)); type = 'L'; // locked } } @@ -248,11 +250,20 @@ void DvisvgmSpecialHandler::processRawPut (InputReader &ir, SpecialActions &acti * @param[in] h height of the rectangle in PS point units * @param[in] d depth of the rectangle in PS point units * @param[in] actions object providing the actions that can be performed by the SpecialHandler */ -static void update_bbox (double w, double h, double d, SpecialActions &actions) { +static void update_bbox (Length w, Length h, Length d, SpecialActions &actions) { double x = actions.getX(); double y = actions.getY(); - actions.embed(BoundingBox(x, y, x+w, y-h)); - actions.embed(BoundingBox(x, y, x+w, y+d)); + actions.embed(BoundingBox(x, y, x+w.bp(), y-h.bp())); + actions.embed(BoundingBox(x, y, x+w.bp(), y+d.bp())); +} + + +/** Reads a length value including a trailing unit specifier and returns it. */ +static Length read_length (InputReader &ir) { + ir.skipSpace(); + double val = ir.getDouble(); + string unit = isalpha(ir.peek()) ? ir.getString(2) : "pt"; + return Length(val, unit); } @@ -264,57 +275,66 @@ static void update_bbox (double w, double h, double d, SpecialActions &actions) void DvisvgmSpecialHandler::processBBox (InputReader &ir, SpecialActions &actions) { ir.skipSpace(); int c = ir.peek(); - if (isalpha(c)) { - while (!isspace(ir.peek())) // skip trailing characters - ir.get(); - if (c == 'n') { - ir.skipSpace(); - string name; - while (isalnum(ir.peek())) - name += char(ir.get()); - ir.skipSpace(); - if (!name.empty() && ir.eof()) - actions.bbox(name, true); // create new user box - } - else if (c == 'a' || c == 'f') { - double p[4]; - for (int i=0; i < 4; i++) - p[i] = ir.getDouble()*Length::pt2bp; - BoundingBox b(p[0], p[1], p[2], p[3]); - if (c == 'a') - actions.embed(b); - else { - actions.bbox() = b; - actions.bbox().lock(); + try { + if (!isalpha(c)) + c = 'r'; // no mode specifier => relative box parameters + else { + while (!isspace(ir.peek())) // skip trailing characters + ir.get(); + if (c == 'n') { // "new": create new local bounding box + ir.skipSpace(); + string name; + while (isalnum(ir.peek())) + name += char(ir.get()); + ir.skipSpace(); + if (!name.empty() && ir.eof()) + actions.bbox(name, true); // create new user box + } + else if (c == 'a' || c == 'f') { // "abs" or "fix" + Length lengths[4]; + for (int i=0; i < 4; i++) + lengths[i] = read_length(ir); + BoundingBox b(lengths[0], lengths[1], lengths[2], lengths[3]); + if (c == 'a') + actions.embed(b); + else { + actions.bbox() = b; + actions.bbox().lock(); + } } } + if (c == 'r') { + Length w = read_length(ir); + Length h = read_length(ir); + Length d = read_length(ir); + update_bbox(w, h, d, actions); + } } - else - c = 'r'; // no mode specifier => relative box parameters - - if (c == 'r') { - double w = ir.getDouble()*Length::pt2bp; - double h = ir.getDouble()*Length::pt2bp; - double d = ir.getDouble()*Length::pt2bp; - update_bbox(w, h, d, actions); + catch (const UnitException &e) { + throw SpecialException(string("dvisvgm:bbox: ") + e.what()); } } void DvisvgmSpecialHandler::processImg (InputReader &ir, SpecialActions &actions) { - double w = ir.getDouble()*Length::pt2bp; - double h = ir.getDouble()*Length::pt2bp; - string f = ir.getString(); - update_bbox(w, h, 0, actions); - XMLElementNode *img = new XMLElementNode("image"); - img->addAttribute("x", actions.getX()); - img->addAttribute("y", actions.getY()); - img->addAttribute("width", w); - img->addAttribute("height", h); - img->addAttribute("xlink:href", f); - if (!actions.getMatrix().isIdentity()) - img->addAttribute("transform", actions.getMatrix().getSVG()); - actions.appendToPage(img); + try { + Length w = read_length(ir); + Length h = read_length(ir); + string f = ir.getString(); + update_bbox(w, h, 0, actions); + auto img = util::make_unique<XMLElementNode>("image"); + img->addAttribute("x", actions.getX()); + img->addAttribute("y", actions.getY()); + img->addAttribute("width", w.bp()); + img->addAttribute("height", h.bp()); + img->addAttribute("xlink:href", f); + if (!actions.getMatrix().isIdentity()) + img->addAttribute("transform", actions.getMatrix().getSVG()); + actions.appendToPage(std::move(img)); + } + catch (const UnitException &e) { + throw SpecialException(string("dvisvgm:img: ") + e.what()); + } } @@ -342,7 +362,7 @@ void DvisvgmSpecialHandler::dviEndPage (unsigned, SpecialActions&) { } -const char** DvisvgmSpecialHandler::prefixes () const { - static const char *pfx[] = {"dvisvgm:", 0}; +const vector<const char*> DvisvgmSpecialHandler::prefixes () const { + const vector<const char*> pfx {"dvisvgm:"}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp index 5282f546bc1..242aa6a4aa4 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp @@ -2,7 +2,7 @@ ** DvisvgmSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,8 +21,8 @@ #ifndef DVISVGMSPECIALHANDLER_HPP #define DVISVGMSPECIALHANDLER_HPP -#include <map> #include <string> +#include <unordered_map> #include <vector> #include "SpecialHandler.hpp" @@ -31,14 +31,14 @@ class SpecialActions; class DvisvgmSpecialHandler : public SpecialHandler, public DVIPreprocessingListener, public DVIEndPageListener { - typedef std::vector<std::string> StringVector; - typedef std::map<std::string, StringVector> MacroMap; + using StringVector = std::vector<std::string>; + using MacroMap = std::unordered_map<std::string, StringVector>; public: DvisvgmSpecialHandler (); const char* name () const override {return "dvisvgm";} const char* info () const override {return "special set for embedding raw SVG snippets";} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; void preprocess (const char *prefix, std::istream &is, SpecialActions &actions) override; bool process (const char *prefix, std::istream &is, SpecialActions &actions) override; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp index 516590e84aa..ef1096ef6b9 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp @@ -2,7 +2,7 @@ ** EPSFile.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cstring> #include <istream> #include <limits> diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp index b4139090d13..28d2aa8264c 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp @@ -2,7 +2,7 @@ ** EPSFile.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSToSVG.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSToSVG.cpp index ec50c21c487..06958c1b963 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSToSVG.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSToSVG.cpp @@ -2,7 +2,7 @@ ** EPSToSVG.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,6 +18,7 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ +#include <config.h> #include <fstream> #include <sstream> #include "EPSFile.hpp" @@ -27,6 +28,7 @@ #include "PsSpecialHandler.hpp" #include "SVGOutput.hpp" #include "System.hpp" +#include "utility.hpp" #include "version.hpp" using namespace std; @@ -65,8 +67,9 @@ void EPSToSVG::convert () { } progress(0); // output SVG file + _svg.removeRedundantElements(); _svg.setBBox(_bbox); - _svg.appendToDoc(new XMLCommentNode(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " ")); + _svg.appendToDoc(util::make_unique<XMLCommentNode>(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " ")); bool success = _svg.write(_out.getPageStream(1, 1)); string svgfname = _out.filename(1, 1); if (svgfname.empty()) diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSToSVG.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSToSVG.hpp index 5d3172d2911..6965a65a9e9 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSToSVG.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSToSVG.hpp @@ -2,7 +2,7 @@ ** EPSToSVG.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,14 +21,14 @@ #ifndef EPSTOSVG_HPP #define EPSTOSVG_HPP +#include <memory> #include <string> #include "SpecialActions.hpp" #include "SVGTree.hpp" struct SVGOutputBase; -class EPSToSVG : protected SpecialActions -{ +class EPSToSVG : protected SpecialActions { public: EPSToSVG (const std::string &fname, SVGOutputBase &out) : _fname(fname), _out(out), _x(0), _y(0) {} void convert (); @@ -48,10 +48,10 @@ class EPSToSVG : protected SpecialActions const Matrix& getMatrix () const override {return _svg.getMatrix();} void getPageTransform (Matrix &matrix) const override {} void setBgColor (const Color &color) override {} - void appendToPage (XMLNode *node) override {_svg.appendToPage(node);} - void appendToDefs (XMLNode *node) override {_svg.appendToDefs(node);} - void prependToPage (XMLNode *node) override {_svg.prependToPage(node);} - void pushContextElement (XMLElementNode *node) override {_svg.pushContextElement(node);} + void appendToPage(std::unique_ptr<XMLNode> &&node) override {_svg.appendToPage(std::move(node));} + void appendToDefs(std::unique_ptr<XMLNode> &&node) override {_svg.appendToDefs(std::move(node));} + void prependToPage(std::unique_ptr<XMLNode> &&node) override {_svg.prependToPage(std::move(node));} + void pushContextElement (std::unique_ptr<XMLElementNode> &&node) override {_svg.pushContextElement(std::move(node));} void popContextElement () override {_svg.popContextElement();} void embed (const BoundingBox &bbox) override {_bbox.embed(bbox);} void embed (const DPair &p, double r=0) override {if (r==0) _bbox.embed(p); else _bbox.embed(p, r);} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp index d7fc27bce98..83f167e428e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp @@ -2,7 +2,7 @@ ** EmSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <sstream> #include "EmSpecialHandler.hpp" #include "InputBuffer.hpp" @@ -79,11 +78,11 @@ static DPair cut_vector (char cuttype, const DPair &linedir, double linewidth) { * @param[in] lw line width in PS point units * @param[in] actions object providing the actions that can be performed by the SpecialHandler */ static void create_line (const DPair &p1, const DPair &p2, char c1, char c2, double lw, SpecialActions &actions) { - XMLElementNode *node=0; + unique_ptr<XMLElementNode> node; DPair dir = p2-p1; if (dir.x() == 0 || dir.y() == 0 || (c1 == 'p' && c2 == 'p')) { // draw regular line - node = new XMLElementNode("line"); + node = util::make_unique<XMLElementNode>("line"); node->addAttribute("x1", p1.x()); node->addAttribute("y1", p1.y()); node->addAttribute("x2", p2.x()); @@ -108,7 +107,7 @@ static void create_line (const DPair &p1, const DPair &p2, char c1, char c2, dou << XMLString(q12.x()) << ',' << XMLString(q12.y()) << ' ' << XMLString(q22.x()) << ',' << XMLString(q22.y()) << ' ' << XMLString(q21.x()) << ',' << XMLString(q21.y()); - node = new XMLElementNode("polygon"); + node = util::make_unique<XMLElementNode>("polygon"); node->addAttribute("points", oss.str()); if (actions.getColor() != Color::BLACK) node->addAttribute("fill", actions.getColor().svgColorString()); @@ -118,7 +117,7 @@ static void create_line (const DPair &p1, const DPair &p2, char c1, char c2, dou actions.embed(q21); actions.embed(q22); } - actions.appendToPage(node); + actions.appendToPage(std::move(node)); } @@ -230,8 +229,8 @@ void EmSpecialHandler::line (InputReader &ir, SpecialActions& actions) { double linewidth = _linewidth; if (ir.getPunct() == ',') linewidth = read_length(ir); - map<int,DPair>::iterator it1=_points.find(pointnum1); - map<int,DPair>::iterator it2=_points.find(pointnum2); + auto it1=_points.find(pointnum1); + auto it2=_points.find(pointnum2); if (it1 != _points.end() && it2 != _points.end()) create_line(it1->second, it2->second, char(cut1), char(cut2), linewidth, actions); else { @@ -259,7 +258,7 @@ void EmSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) { } -const char** EmSpecialHandler::prefixes () const { - static const char *pfx[] = {"em:", 0}; +const vector<const char*> EmSpecialHandler::prefixes () const { + const vector<const char*> pfx {"em:"}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp index c9febab3425..5a86b1322ce 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp @@ -2,7 +2,7 @@ ** EmSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,7 +22,7 @@ #define EMSPECIALHANDLER_HPP #include <list> -#include <map> +#include <unordered_map> #include "Pair.hpp" #include "SpecialHandler.hpp" @@ -42,7 +42,7 @@ class EmSpecialHandler : public SpecialHandler, public DVIEndPageListener EmSpecialHandler (); const char* name () const override {return "em";} const char* info () const override {return "line drawing statements of the emTeX special set";} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; bool process (const char *prefix, std::istream &in, SpecialActions &actions) override; protected: @@ -54,10 +54,10 @@ class EmSpecialHandler : public SpecialHandler, public DVIEndPageListener void point (InputReader &ir, SpecialActions &actions); private: - std::map<int, DPair> _points; ///< points defined by special em:point - std::list<Line> _lines; ///< list of lines with undefined end points - double _linewidth; ///< global line width - DPair _pos; ///< current position of "graphic cursor" + std::unordered_map<int, DPair> _points; ///< points defined by special em:point + std::list<Line> _lines; ///< list of lines with undefined end points + double _linewidth; ///< global line width + DPair _pos; ///< current position of "graphic cursor" }; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp index 2dc2ab8e7d2..1b99d17e280 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp @@ -2,7 +2,7 @@ ** EncFile.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <fstream> #include "Font.hpp" #include "EncFile.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp index 6296104e0b1..4cb4945856a 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp @@ -2,7 +2,7 @@ ** EncFile.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp index 591da5e6fe9..40a7aa01c22 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp @@ -2,7 +2,7 @@ ** FileFinder.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -19,9 +19,9 @@ *************************************************************************/ #include <config.h> - #ifdef MIKTEX #include "MiKTeXCom.hpp" + #include "utility.hpp" #else #ifdef KPSE_CXX_UNSAFE extern "C" { @@ -37,13 +37,14 @@ #include <map> #include <set> #include "FileFinder.hpp" +#include "FilePath.hpp" #include "FileSystem.hpp" #include "FontMap.hpp" #include "Message.hpp" #include "MessageException.hpp" #include "Process.hpp" -const char *FileFinder::_argv0 = nullptr; +std::string FileFinder::_argv0; std::string FileFinder::_progname; bool FileFinder::_enableMktex = false; @@ -55,11 +56,9 @@ bool FileFinder::_enableMktex = false; FileFinder::FileFinder () { addLookupDir("."); // always lookup files in the current working directory #ifdef MIKTEX - _miktex.reset(new MiKTeXCom); + _miktex = util::make_unique<MiKTeXCom>(); #else - if (_argv0 == nullptr) - _argv0 = ""; - kpse_set_program_name(_argv0, _progname.c_str()); + kpse_set_program_name(_argv0.c_str(), _progname.c_str()); // enable tfm and mf generation (actually invoked by calls of kpse_make_tex) kpse_set_program_enabled(kpse_tfm_format, 1, kpse_src_env); kpse_set_program_enabled(kpse_mf_format, 1, kpse_src_env); @@ -71,9 +70,9 @@ FileFinder::FileFinder () { } -void FileFinder::init (const char *argv0, const char *progname, bool enable_mktexmf) { +void FileFinder::init (const std::string &argv0, const std::string &progname, bool enable_mktexmf) { _argv0 = argv0; - _progname = progname; + _progname = progname.c_str(); _enableMktex = enable_mktexmf; } @@ -99,7 +98,8 @@ std::string FileFinder::version () const { void FileFinder::addLookupDir (const std::string &path) { - _additionalDirs.insert(path); + FilePath filepath(path); + _additionalDirs.insert(filepath.absolute()); } @@ -110,27 +110,22 @@ void FileFinder::addLookupDir (const std::string &path) { * @return file path on success, 0 otherwise */ const char* FileFinder::findFile (const std::string &fname, const char *ftype) const { if (fname.empty()) - return 0; + return nullptr; static std::string buf; // try to lookup the file in the additionally specified directories for (const std::string &dir : _additionalDirs) { - if (dir[0] == '/') - buf.clear(); - else - buf = FileSystem::getcwd()+"/"; - buf += dir + "/" + fname; + buf = dir + "/" + fname; if (FileSystem::exists(buf)) return buf.c_str(); } - std::string ext; if (ftype) ext = ftype; else { size_t pos = fname.rfind('.'); if (pos == std::string::npos) - return 0; // no extension and no file type => no search + return nullptr; // no extension and no file type => no search ext = fname.substr(pos+1); } @@ -145,15 +140,15 @@ const char* FileFinder::findFile (const std::string &fname, const char *ftype) c // The MiKTeX SDK doesn't support the lookup of files without suffix (yet), thus // it's not possible to find cmap files which usually don't have a suffix. In order // to work around this, we try to lookup the files by calling kpsewhich. - Process process("kpsewhich", std::string("-format=cmap ")+fname); + Process process("kpsewhich", "-format=cmap "+fname); process.run(&buf); - return buf.empty() ? 0 : buf.c_str(); + return buf.empty() ? nullptr : buf.c_str(); } try { return _miktex->findFile(fname.c_str()); } catch (const MessageException &e) { - return 0; + return nullptr; } #else #ifdef TEXLIVEWIN32 @@ -161,9 +156,9 @@ const char* FileFinder::findFile (const std::string &fname, const char *ftype) c // lookup exe files in directory where dvisvgm is located if (const char *path = kpse_var_value("SELFAUTOLOC")) { buf = std::string(path) + "/" + fname; - return FileSystem::exists(buf) ? buf.c_str() : 0; + return FileSystem::exists(buf) ? buf.c_str() : nullptr; } - return 0; + return nullptr; } #endif static std::map<std::string, kpse_file_format_type> types = { @@ -180,10 +175,11 @@ const char* FileFinder::findFile (const std::string &fname, const char *ftype) c {"enc", kpse_enc_format}, {"pro", kpse_tex_ps_header_format}, {"sfd", kpse_sfd_format}, + {"eps", kpse_pict_format}, }; - auto it = types.find(ext.c_str()); + auto it = types.find(ext); if (it == types.end()) - return 0; + return nullptr; if (char *path = kpse_find_file(fname.c_str(), it->second, 0)) { // In the current version of libkpathsea, each call of kpse_find_file produces @@ -193,7 +189,7 @@ const char* FileFinder::findFile (const std::string &fname, const char *ftype) c std::free(path); return buf.c_str(); } - return 0; + return nullptr; #endif } @@ -205,11 +201,11 @@ const char* FileFinder::findFile (const std::string &fname, const char *ftype) c const char* FileFinder::findMappedFile (std::string fname) const { size_t pos = fname.rfind('.'); if (pos == std::string::npos) - return 0; + return nullptr; const std::string ext = fname.substr(pos+1); // file extension const std::string base = fname.substr(0, pos); if (const FontMap::Entry *entry = FontMap::instance().lookup(base)) { - const char *path=0; + const char *path=nullptr; if (entry->fontname.find('.') != std::string::npos) // does the mapped filename has an extension? path = findFile(entry->fontname, 0); // look for that file else { // otherwise, use extension of unmapped file @@ -218,7 +214,7 @@ const char* FileFinder::findMappedFile (std::string fname) const { } return path; } - return 0; + return nullptr; } @@ -228,13 +224,13 @@ const char* FileFinder::findMappedFile (std::string fname) const { const char* FileFinder::mktex (const std::string &fname) const { size_t pos = fname.rfind('.'); if (!_enableMktex || pos == std::string::npos) - return 0; + return nullptr; std::string ext = fname.substr(pos+1); // file extension if (ext != "tfm" && ext != "mf") - return 0; + return nullptr; - const char *path = 0; + const char *path = nullptr; #ifdef MIKTEX // maketfm and makemf are located in miktex/bin which is in the search PATH std::string toolname = (ext == "tfm" ? "miktex-maketfm" : "miktex-makemf"); @@ -263,5 +259,5 @@ const char* FileFinder::lookup (const std::string &fname, const char *ftype, boo const char *path; if ((path = findFile(fname, ftype)) || (extended && ((path = findMappedFile(fname)) || (path = mktex(fname))))) return path; - return 0; + return nullptr; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp index cc88e52d57f..0ccc84f2755 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp @@ -2,7 +2,7 @@ ** FileFinder.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -27,10 +27,9 @@ class MiKTeXCom; -class FileFinder -{ +class FileFinder { public: - static void init (const char *argv0, const char *progname, bool enable_mktexmf); + static void init (const std::string &argv0, const std::string &progname, bool enable_mktexmf); static FileFinder& instance (); std::string version () const; void addLookupDir (const std::string &path); @@ -44,7 +43,7 @@ class FileFinder const char* mktex (const std::string &fname) const; private: - static const char *_argv0; + static std::string _argv0; static std::string _progname; static bool _enableMktex; std::set<std::string> _additionalDirs; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp index 9f9b295ad62..f7fe431cf16 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp @@ -2,7 +2,7 @@ ** FilePath.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cctype> #include "FilePath.hpp" #include "FileSystem.hpp" @@ -70,14 +69,12 @@ static char adapt_current_path (string &path, char target_drive) { bool FilePath::Directory::operator == (const Directory &dir) const { - string dirstr1 = _dirstr; - string dirstr2 = dir._dirstr; #ifdef _WIN32 // letter case is not significant on Windows systems - util::tolower(dirstr1); - util::tolower(dirstr2); + return util::tolower(_dirstr) == util::tolower(dir._dirstr); +#else + return _dirstr == dir._dirstr; #endif - return dirstr1 == dirstr2; } @@ -85,7 +82,7 @@ bool FilePath::Directory::operator == (const Directory &dir) const { * relative to the current working directory. * @param[in] path absolute or relative path to a file or directory */ FilePath::FilePath (const string &path) { - init(path, !FileSystem::isDirectory(path.c_str()), FileSystem::getcwd()); + init(path, !FileSystem::isDirectory(path), FileSystem::getcwd()); } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp index 4f73324a27a..385e1d2fb4b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp @@ -2,7 +2,7 @@ ** FilePath.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -25,8 +25,7 @@ #include <utility> #include <vector> -class FilePath -{ +class FilePath { class Directory { public: Directory (const std::string &dir) : _dirstr(dir) {} @@ -39,7 +38,6 @@ class FilePath std::string _dirstr; }; - typedef std::vector<Directory> Directories; public: FilePath (const std::string &path); FilePath (const std::string &path, bool isfile) : FilePath(path, isfile, "") {} @@ -60,7 +58,7 @@ class FilePath void add (const std::string &elem); private: - Directories _dirs; + std::vector<std::string> _dirs; std::string _fname; #ifdef _WIN32 char _drive; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp index 8c5386ac8d5..769ff0a7c23 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp @@ -2,7 +2,7 @@ ** FileSystem.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -36,7 +36,7 @@ using namespace std; #ifdef _WIN32 #include <direct.h> - #include <windows.h> + #include "windows.hpp" const char *FileSystem::DEVNULL = "nul"; const char FileSystem::PATHSEP = '\\'; #define unlink _unlink @@ -272,7 +272,7 @@ bool FileSystem::rmdir (const string &dirname) { struct dirent *ent; while ((ent = readdir(dir)) && ok) { const char *fname = ent->d_name; - string path = string(fname) + "/" + fname; + string path = dirname + "/" + fname; if (isDirectory(path)) { if (strcmp(fname, ".") != 0 && strcmp(fname, "..") != 0) ok = rmdir(path) && s_rmdir(path); @@ -335,16 +335,16 @@ bool FileSystem::isFile (const string &fname) { } -int FileSystem::collect (const char *dirname, vector<string> &entries) { +int FileSystem::collect (const std::string &dirname, vector<string> &entries) { entries.clear(); #ifdef _WIN32 - string pattern = string(dirname) + "/*"; + string pattern = dirname + "/*"; WIN32_FIND_DATA data; HANDLE h = FindFirstFile(pattern.c_str(), &data); bool ready = (h == INVALID_HANDLE_VALUE); while (!ready) { string fname = data.cFileName; - string path = string(dirname)+"/"+fname; + string path = dirname+"/"+fname; string typechar = isFile(path) ? "f" : isDirectory(path) ? "d" : "?"; if (fname != "." && fname != "..") entries.emplace_back(typechar+fname); @@ -352,11 +352,11 @@ int FileSystem::collect (const char *dirname, vector<string> &entries) { } FindClose(h); #else - if (DIR *dir = opendir(dirname)) { + if (DIR *dir = opendir(dirname.c_str())) { struct dirent *ent; while ((ent = readdir(dir))) { string fname = ent->d_name; - string path = string(dirname)+"/"+fname; + string path = dirname+"/"+fname; string typechar = isFile(path) ? "f" : isDirectory(path) ? "d" : "?"; if (fname != "." && fname != "..") entries.emplace_back(typechar+fname); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.hpp index 798ca982e74..955062d956f 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.hpp @@ -2,7 +2,7 @@ ** FileSystem.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -39,7 +39,7 @@ class FileSystem static bool exists (const std::string &fname); static bool mkdir (const std::string &dirname); static bool rmdir (const std::string &dirname); - static int collect (const char *dirname, std::vector<std::string> &entries); + static int collect (const std::string &dirname, std::vector<std::string> &entries); static bool isDirectory (const std::string &fname); static bool isFile (const std::string &fname); static const char* userdir (); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FixWord.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FixWord.hpp index 7f6a5ebd298..a7078ec46e2 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FixWord.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FixWord.hpp @@ -2,7 +2,7 @@ ** FixWord.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp index 01f18f41690..889e070b263 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp @@ -2,7 +2,7 @@ ** Font.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cstdlib> #include <fstream> #include <set> @@ -33,6 +32,7 @@ #include "SignalHandler.hpp" #include "Subfont.hpp" #include "Unicode.hpp" +#include "utility.hpp" using namespace std; @@ -48,7 +48,7 @@ uint32_t Font::unicode (uint32_t c) const { const FontEncoding* Font::encoding () const { if (const FontMap::Entry *entry = fontMapEntry()) return FontEncoding::encoding(entry->encname); - return 0; + return nullptr; } @@ -110,14 +110,14 @@ TFMFont::TFMFont (const string &name, uint32_t cs, double ds, double ss) const FontMetrics* TFMFont::getMetrics () const { if (!_metrics) { try { - _metrics.reset(FontMetrics::read(_fontname.c_str())); + _metrics = FontMetrics::read(_fontname); if (!_metrics) { - _metrics.reset(new NullFontMetric); + _metrics = util::make_unique<NullFontMetric>(); Message::wstream(true) << "can't find "+_fontname+".tfm\n"; } } catch (FontMetricException &e) { - _metrics.reset(new NullFontMetric); + _metrics = util::make_unique<NullFontMetric>(); Message::wstream(true) << e.what() << " in " << _fontname << ".tfm\n"; } } @@ -127,18 +127,18 @@ const FontMetrics* TFMFont::getMetrics () const { double TFMFont::charWidth (int c) const { double w = getMetrics() ? getMetrics()->getCharWidth(c) : 0; - if (style()) { + if (style()) w *= style()->extend; - w += fabs(style()->slant*charHeight(c)); // slant := tan(phi) = dx/height - } return w; } double TFMFont::italicCorr (int c) const { double w = getMetrics() ? getMetrics()->getItalicCorr(c) : 0; - if (style()) + if (style()) { + w += abs(style()->slant*charHeight(c)); // slant := tan(phi) = dx/height w *= style()->extend; + } return w; } @@ -164,13 +164,13 @@ double PhysicalFont::METAFONT_MAG = 4; FontCache PhysicalFont::_cache; -Font* PhysicalFont::create (const string &name, uint32_t checksum, double dsize, double ssize, PhysicalFont::Type type) { - return new PhysicalFontImpl(name, 0, checksum, dsize, ssize, type); +unique_ptr<Font> PhysicalFont::create (const string &name, uint32_t checksum, double dsize, double ssize, PhysicalFont::Type type) { + return unique_ptr<PhysicalFontImpl>(new PhysicalFontImpl(name, 0, checksum, dsize, ssize, type)); } -Font* PhysicalFont::create (const string &name, int fontindex, uint32_t checksum, double dsize, double ssize) { - return new PhysicalFontImpl(name, fontindex, checksum, dsize, ssize, PhysicalFont::Type::TTC); +unique_ptr<Font> PhysicalFont::create (const string &name, int fontindex, uint32_t checksum, double dsize, double ssize) { + return unique_ptr<PhysicalFontImpl>(new PhysicalFontImpl(name, fontindex, checksum, dsize, ssize, PhysicalFont::Type::TTC)); } @@ -326,7 +326,7 @@ bool PhysicalFont::getGlyph (int c, GraphicsPath<int32_t> &glyph, GFGlyphTracer: const Glyph *cached_glyph=0; if (CACHE_PATH) { _cache.write(CACHE_PATH); - _cache.read(name().c_str(), CACHE_PATH); + _cache.read(name(), CACHE_PATH); cached_glyph = _cache.getGlyph(c); } if (cached_glyph) { @@ -399,7 +399,7 @@ int PhysicalFont::traceAllGlyphs (bool includeCached, GFGlyphTracer::Callback *c string gfname; Glyph glyph; if (createGF(gfname)) { - _cache.read(name().c_str(), CACHE_PATH); + _cache.read(name(), CACHE_PATH); double ds = getMetrics() ? getMetrics()->getDesignSize() : 1; GFGlyphTracer tracer(gfname, unitsPerEm()/ds, cb); tracer.setGlyph(glyph); @@ -463,8 +463,8 @@ bool PhysicalFont::getExactGlyphBox (int c, GlyphMetrics &metrics, bool vertical } -Font* VirtualFont::create (const string &name, uint32_t checksum, double dsize, double ssize) { - return new VirtualFontImpl(name, checksum, dsize, ssize); +unique_ptr<Font> VirtualFont::create (const string &name, uint32_t checksum, double dsize, double ssize) { + return unique_ptr<VirtualFontImpl>(new VirtualFontImpl(name, checksum, dsize, ssize)); } @@ -473,7 +473,7 @@ Font* VirtualFont::create (const string &name, uint32_t checksum, double dsize, PhysicalFontImpl::PhysicalFontImpl (const string &name, int fontindex, uint32_t cs, double ds, double ss, PhysicalFont::Type type) : TFMFont(name, cs, ds, ss), - _filetype(type), _fontIndex(fontindex), _fontMapEntry(Font::fontMapEntry()), _encodingPair(Font::encoding()), _localCharMap(0) + _filetype(type), _fontIndex(fontindex), _encodingPair(Font::encoding()) { } @@ -483,13 +483,12 @@ PhysicalFontImpl::~PhysicalFontImpl () { _cache.write(CACHE_PATH); if (!KEEP_TEMP_FILES) tidy(); - delete _localCharMap; } const FontEncoding* PhysicalFontImpl::encoding () const { if (!_encodingPair.enc1()) - return 0; + return nullptr; return &_encodingPair; } @@ -506,7 +505,8 @@ bool PhysicalFontImpl::findAndAssignBaseFontMap () { } else if (type() != Type::MF) { FontEngine::instance().setFont(*this); - if ((_localCharMap = FontEngine::instance().createCustomToUnicodeMap()) != 0) + _localCharMap = FontEngine::instance().createCustomToUnicodeMap(); + if (_localCharMap) _charmapID = FontEngine::instance().setCustomCharMap(); else _charmapID = FontEngine::instance().setUnicodeCharMap(); @@ -547,14 +547,20 @@ uint32_t PhysicalFontImpl::unicode (uint32_t c) const { } +const FontStyle* PhysicalFontImpl::style () const { + if (auto *entry = fontMapEntry()) + return &entry->style; + return nullptr; +} + + /** Delete all temporary font files created by Metafont. */ void PhysicalFontImpl::tidy () const { if (type() == Type::MF) { - const char *ext[] = {"gf", "tfm", "log", 0}; string fname = FileSystem::tmpdir()+name(); - for (const char **p=ext; *p; ++p) { - if (FileSystem::exists(fname+"."+(*p))) - FileSystem::remove(fname+"."+(*p)); + for (const char *ext : {"gf", "tfm", "log"}) { + if (FileSystem::exists(fname+"."+ext)) + FileSystem::remove(fname+"."+ext); } } } @@ -562,10 +568,10 @@ void PhysicalFontImpl::tidy () const { ////////////////////////////////////////////////////////////////////////////// string NativeFont::uniqueName (const string &path, const FontStyle &style) { - static map<string, int> ids; + static unordered_map<string, int> ids; ostringstream oss; oss << path << "b" << style.bold << "e" << style.extend << "s" << style.slant; - map<string, int>::iterator it = ids.find(oss.str()); + auto it = ids.find(oss.str()); int id = ids.size(); if (it == ids.end()) ids[oss.str()] = id; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp index f04368b9a8f..49f69f54725 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp @@ -2,7 +2,7 @@ ** Font.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,9 +21,9 @@ #ifndef FONT_HPP #define FONT_HPP -#include <map> #include <memory> #include <string> +#include <unordered_map> #include <vector> #include "Character.hpp" #include "CharMapID.hpp" @@ -40,13 +40,11 @@ #include "ToUnicodeMap.hpp" #include "VFActions.hpp" #include "VFReader.hpp" - +#include "utility.hpp" struct FontStyle; - -struct GlyphMetrics -{ +struct GlyphMetrics { GlyphMetrics () : wl(0), wr(0), h(0), d(0) {} GlyphMetrics (double wwl, double wwr, double hh, double dd) : wl(wwl), wr(wwr), h(hh), d(dd) {} double wl, wr, h, d; @@ -57,7 +55,7 @@ struct GlyphMetrics class Font { public: virtual ~Font () =default; - virtual Font* clone (double ds, double sc) const =0; + virtual std::unique_ptr<Font> clone (double ds, double sc) const =0; virtual const Font* uniqueFont () const =0; virtual std::string name () const =0; virtual double designSize () const =0; @@ -79,7 +77,7 @@ class Font { virtual bool verticalLayout () const {return getMetrics() ? getMetrics()->verticalLayout() : false;} virtual bool verifyChecksums () const {return true;} virtual int fontIndex () const {return 0;} - virtual const FontStyle* style () const {return 0;} + virtual const FontStyle* style () const {return nullptr;} virtual Color color () const {return Color::BLACK;} virtual const FontMap::Entry* fontMapEntry () const; }; @@ -91,7 +89,7 @@ class Font { class EmptyFont : public Font { public: EmptyFont (const std::string &name) : _fontname(name) {} - Font* clone (double ds, double sc) const override {return new EmptyFont(*this);} + std::unique_ptr<Font> clone (double ds, double sc) const override {return util::make_unique<EmptyFont>(*this);} const Font* uniqueFont () const override {return this;} std::string name () const override {return _fontname;} double designSize () const override {return 10;} // cmr10 design size in pt @@ -100,8 +98,8 @@ class EmptyFont : public Font { double charHeight (int c) const override {return 6.833;} // height of cmr10's 'M' in pt double charDepth (int c) const override {return 0;} double italicCorr (int c) const override {return 0;} - const FontMetrics* getMetrics () const override {return 0;} - const char* path () const override {return 0;} + const FontMetrics* getMetrics () const override {return nullptr;} + const char* path () const override {return nullptr;} bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=0) const override {return false;} private: @@ -114,12 +112,12 @@ class PhysicalFont : public virtual Font { public: enum class Type {MF, OTF, PFB, TTC, TTF, UNKNOWN}; - static Font* create (const std::string &name, uint32_t checksum, double dsize, double ssize, PhysicalFont::Type type); - static Font* create (const std::string &name, int fontindex, uint32_t checksum, double dsize, double ssize); + static std::unique_ptr<Font> create (const std::string &name, uint32_t checksum, double dsize, double ssize, PhysicalFont::Type type); + static std::unique_ptr<Font> create (const std::string &name, int fontindex, uint32_t checksum, double dsize, double ssize); virtual Type type () const =0; - virtual bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=0) const override; - virtual bool getExactGlyphBox (int c, BoundingBox &bbox, GFGlyphTracer::Callback *cb=0) const; - virtual bool getExactGlyphBox (int c, GlyphMetrics &metrics, bool vertical, GFGlyphTracer::Callback *cb=0) const; + virtual bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=nullptr) const override; + virtual bool getExactGlyphBox (int c, BoundingBox &bbox, GFGlyphTracer::Callback *cb=nullptr) const; + virtual bool getExactGlyphBox (int c, GlyphMetrics &metrics, bool vertical, GFGlyphTracer::Callback *cb=nullptr) const; virtual bool isCIDFont () const; virtual int hAdvance () const; virtual std::string familyName () const; @@ -131,7 +129,7 @@ class PhysicalFont : public virtual Font { virtual double scaledAscent () const; virtual int ascent () const; virtual int descent () const; - virtual int traceAllGlyphs (bool includeCached, GFGlyphTracer::Callback *cb=0) const; + virtual int traceAllGlyphs (bool includeCached, GFGlyphTracer::Callback *cb=nullptr) const; virtual int collectCharMapIDs (std::vector<CharMapID> &charmapIDs) const; virtual CharMapID getCharMapID () const =0; virtual void setCharMapID (const CharMapID &id) {} @@ -156,12 +154,12 @@ class PhysicalFont : public virtual Font { class VirtualFont : public virtual Font { friend class FontManager; public: - typedef std::vector<uint8_t> DVIVector; + using DVIVector = std::vector<uint8_t>; public: - static Font* create (const std::string &name, uint32_t checksum, double dsize, double ssize); + static std::unique_ptr<Font> create (const std::string &name, uint32_t checksum, double dsize, double ssize); virtual const DVIVector* getDVI (int c) const =0; - bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=0) const override {return false;} + bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=nullptr) const override {return false;} protected: virtual void assignChar (uint32_t c, DVIVector &&dvi) =0; @@ -193,7 +191,10 @@ class TFMFont : public virtual Font { class PhysicalFontProxy : public PhysicalFont { friend class PhysicalFontImpl; public: - Font* clone (double ds, double sc) const override {return new PhysicalFontProxy(*this, ds, sc);} + std::unique_ptr<Font> clone (double ds, double sc) const override { + return std::unique_ptr<PhysicalFontProxy>(new PhysicalFontProxy(*this, ds, sc)); + } + const Font* uniqueFont () const override {return _pf;} std::string name () const override {return _pf->name();} double designSize () const override {return _dsize;} @@ -227,12 +228,15 @@ class PhysicalFontImpl : public PhysicalFont, public TFMFont { friend class PhysicalFont; public: ~PhysicalFontImpl(); - Font* clone (double ds, double ss) const override {return new PhysicalFontProxy(this, ds, ss);} + + std::unique_ptr<Font> clone (double ds, double ss) const override { + return std::unique_ptr<PhysicalFontProxy>(new PhysicalFontProxy(this, ds, ss)); + } + const Font* uniqueFont () const override {return this;} Type type () const override {return _filetype;} int fontIndex() const override {return _fontIndex;} - const FontStyle* style () const override {return _fontMapEntry ? &_fontMapEntry->style : 0;} - const FontMap::Entry* fontMapEntry () const override {return _fontMapEntry;} + const FontStyle* style () const override; const FontEncoding* encoding () const override; uint32_t unicode (uint32_t c) const override; bool findAndAssignBaseFontMap () override; @@ -245,17 +249,16 @@ class PhysicalFontImpl : public PhysicalFont, public TFMFont { private: Type _filetype; int _fontIndex; - const FontMap::Entry *_fontMapEntry; FontEncodingPair _encodingPair; CharMapID _charmapID; ///< ID of the font's charmap to use - const RangeMap *_localCharMap; + std::unique_ptr<const RangeMap> _localCharMap; }; class NativeFont : public PhysicalFont { public: - virtual NativeFont* clone (double ptsize, const FontStyle &style, Color color) const =0; - virtual Font* clone (double ds, double sc) const override =0; + virtual std::unique_ptr<NativeFont> clone (double ptsize, const FontStyle &style, Color color) const =0; + virtual std::unique_ptr<Font> clone (double ds, double sc) const override =0; std::string name () const override; Type type () const override; double designSize () const override {return _ptsize;} @@ -264,10 +267,10 @@ class NativeFont : public PhysicalFont { double charDepth (int c) const override; double charHeight (int c) const override; double italicCorr (int c) const override {return 0;} - const FontMetrics* getMetrics () const override {return 0;} + const FontMetrics* getMetrics () const override {return nullptr;} const FontStyle* style () const override {return &_style;} Color color () const override {return _color;} - const FontMap::Entry* fontMapEntry () const override {return 0;} + const FontMap::Entry* fontMapEntry () const override {return nullptr;} static std::string uniqueName (const std::string &path, const FontStyle &style); protected: @@ -283,11 +286,14 @@ class NativeFont : public PhysicalFont { class NativeFontProxy : public NativeFont { friend class NativeFontImpl; public: - NativeFont* clone (double ptsize, const FontStyle &style, Color color) const override { - return new NativeFontProxy(this, ptsize, style, color); + std::unique_ptr<NativeFont> clone (double ptsize, const FontStyle &style, Color color) const override { + return std::unique_ptr<NativeFontProxy>(new NativeFontProxy(this, ptsize, style, color)); + } + + std::unique_ptr<Font> clone (double ds, double sc) const override { + return std::unique_ptr<NativeFontProxy>(new NativeFontProxy(this , sc, *style(), color())); } - Font* clone (double ds, double sc) const override {return new NativeFontProxy(this , sc, *style(), color());} const Font* uniqueFont () const override {return _nfont;} const char* path () const override {return _nfont->path();} int fontIndex () const override {return _nfont->fontIndex();} @@ -309,11 +315,14 @@ class NativeFontImpl : public NativeFont { NativeFontImpl (const std::string &fname, int fontIndex, double ptsize, const FontStyle &style, Color color) : NativeFont(ptsize, style, color), _path(fname), _fontIndex(fontIndex) {} - NativeFont* clone (double ptsize, const FontStyle &style, Color color) const override { - return new NativeFontProxy(this, ptsize, style, color); + std::unique_ptr<NativeFont> clone (double ptsize, const FontStyle &style, Color color) const override { + return std::unique_ptr<NativeFontProxy>(new NativeFontProxy(this, ptsize, style, color)); + } + + std::unique_ptr<Font> clone (double ds, double sc) const override { + return std::unique_ptr<NativeFontProxy>(new NativeFontProxy(this , sc, *style(), color())); } - Font* clone (double ds, double sc) const override {return new NativeFontProxy(this , sc, *style(), color());} const Font* uniqueFont () const override {return this;} const char* path () const override {return _path.c_str();} int fontIndex() const override {return _fontIndex;} @@ -333,7 +342,10 @@ class NativeFontImpl : public NativeFont { class VirtualFontProxy : public VirtualFont { friend class VirtualFontImpl; public: - Font* clone (double ds, double ss) const override {return new VirtualFontProxy(*this, ds, ss);} + std::unique_ptr<Font> clone (double ds, double ss) const override { + return std::unique_ptr<VirtualFontProxy>(new VirtualFontProxy(*this, ds, ss)); + } + const Font* uniqueFont () const override {return _vf;} std::string name () const override {return _vf->name();} const DVIVector* getDVI (int c) const override {return _vf->getDVI(c);} @@ -361,7 +373,10 @@ class VirtualFontProxy : public VirtualFont { class VirtualFontImpl : public VirtualFont, public TFMFont { friend class VirtualFont; public: - Font* clone (double ds, double ss) const override {return new VirtualFontProxy(this, ds, ss);} + std::unique_ptr<Font> clone (double ds, double ss) const override { + return std::unique_ptr<VirtualFontProxy>(new VirtualFontProxy(this, ds, ss)); + } + const Font* uniqueFont () const override {return this;} const DVIVector* getDVI (int c) const override; const char* path () const override; @@ -371,12 +386,11 @@ class VirtualFontImpl : public VirtualFont, public TFMFont { void assignChar (uint32_t c, DVIVector &&dvi) override; private: - std::map<uint32_t, DVIVector> _charDefs; ///< dvi subroutines defining the characters + std::unordered_map<uint32_t, DVIVector> _charDefs; ///< dvi subroutines defining the characters }; -struct FontException : public MessageException -{ +struct FontException : public MessageException { FontException (const std::string &msg) : MessageException(msg) {} }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp index cd1b6529092..f14a4ca8bd0 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp @@ -2,7 +2,7 @@ ** FontCache.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,8 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ - -#include <config.h> #include <algorithm> #include <cstring> #include <fstream> @@ -65,7 +63,7 @@ void FontCache::setGlyph (int c, const Glyph &glyph) { * @param[in] c character code * @return font glyph data (0 if no matching data was found) */ const Glyph* FontCache::getGlyph (int c) const { - GlyphMap::const_iterator it = _glyphs.find(c); + auto it = _glyphs.find(c); return (it != _glyphs.end()) ? &it->second : 0; } @@ -75,12 +73,12 @@ const Glyph* FontCache::getGlyph (int c) const { * @param[in] fontname name of current font * @param[in] dir directory where the cache file should go * @return true if writing was successful */ -bool FontCache::write (const char *fontname, const char *dir) const { +bool FontCache::write (const string &fontname, const string &dir) const { if (!_changed) return true; - if (fontname && strlen(fontname) > 0) { - string dirstr = (dir == 0 || strlen(dir) == 0) ? FileSystem::getcwd() : dir; + if (!fontname.empty()) { + string dirstr = dir.empty() ? FileSystem::getcwd() : dir; ostringstream oss; oss << dirstr << '/' << fontname << ".fgd"; ofstream ofs(oss.str().c_str(), ios::binary); @@ -90,8 +88,8 @@ bool FontCache::write (const char *fontname, const char *dir) const { } -bool FontCache::write (const char* dir) const { - return _fontname.empty() ? false : write(_fontname.c_str(), dir); +bool FontCache::write (const string &dir) const { + return _fontname.empty() ? false : write(_fontname, dir); } @@ -124,7 +122,7 @@ static int max_int_size (const Pair<int32_t> *pairs, size_t n) { * @param[in] fontname name of current font * @param[in] os output stream * @return true if writing was successful */ -bool FontCache::write (const char *fontname, ostream &os) const { +bool FontCache::write (const string &fontname, ostream &os) const { if (!_changed) return true; if (!os) @@ -170,13 +168,13 @@ bool FontCache::write (const char *fontname, ostream &os) const { * @param[in] fontname name of font data to read * @param[in] dir directory where the cache files are located * @return true if reading was successful */ -bool FontCache::read (const char *fontname, const char *dir) { - if (!fontname || strlen(fontname) == 0) +bool FontCache::read (const string &fontname, const string &dir) { + if (fontname.empty()) return false; if (_fontname == fontname) return true; clear(); - string dirstr = (dir == 0 || strlen(dir) == 0) ? FileSystem::getcwd() : dir; + string dirstr = dir.empty() ? FileSystem::getcwd() : dir; ostringstream oss; oss << dirstr << '/' << fontname << ".fgd"; ifstream ifs(oss.str().c_str(), ios::binary); @@ -188,7 +186,7 @@ bool FontCache::read (const char *fontname, const char *dir) { * @param[in] fontname name of font data to read * @param[in] is input stream to read the glyph data from * @return true if reading was successful */ -bool FontCache::read (const char *fontname, istream &is) { +bool FontCache::read (const string &fontname, istream &is) { if (_fontname == fontname) return true; clear(); @@ -257,16 +255,16 @@ bool FontCache::read (const char *fontname, istream &is) { * @param[out] infos the collected font information * @param[out] invalid names of outdated/corrupted cache files * @return true on success */ -bool FontCache::fontinfo (const char *dirname, vector<FontInfo> &infos, vector<string> &invalid) { +bool FontCache::fontinfo (const string &dirname, vector<FontInfo> &infos, vector<string> &invalid) { infos.clear(); invalid.clear(); - if (dirname) { + if (!dirname.empty()) { vector<string> fnames; FileSystem::collect(dirname, fnames); for (const string &fname : fnames) { if (fname[0] == 'f' && fname.length() > 5 && fname.substr(fname.length()-4) == ".fgd") { FontInfo info; - string path = string(dirname)+"/"+(fname.substr(1)); + string path = dirname+"/"+(fname.substr(1)); ifstream ifs(path.c_str(), ios::binary); if (fontinfo(ifs, info)) infos.emplace_back(move(info)); @@ -345,8 +343,8 @@ bool FontCache::fontinfo (std::istream &is, FontInfo &info) { * @param[in] dirname path to font cache directory * @param[in] os output is written to this stream * @param[in] purge if true, outdated and corrupted cache files are removed */ -void FontCache::fontinfo (const char *dirname, ostream &os, bool purge) { - if (dirname) { +void FontCache::fontinfo (const string &dirname, ostream &os, bool purge) { + if (!dirname.empty()) { ios::fmtflags osflags(os.flags()); vector<FontInfo> infos; vector<string> invalid_files; @@ -369,7 +367,7 @@ void FontCache::fontinfo (const char *dirname, ostream &os, bool purge) { } if (purge) { for (const string &str : invalid_files) { - string path=string(dirname)+"/"+str; + string path=dirname+"/"+str; if (FileSystem::remove(path)) os << "invalid cache file " << str << " removed\n"; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp index 7cdfe4d16eb..e8d25bd0d0c 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp @@ -2,7 +2,7 @@ ** FontCache.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,18 +21,15 @@ #ifndef FONTCACHE_HPP #define FONTCACHE_HPP -#include <string> #include <map> +#include <string> +#include <vector> #include "Glyph.hpp" -class FontCache -{ - typedef std::map<int, Glyph> GlyphMap; - +class FontCache { public: - struct FontInfo - { + struct FontInfo { std::string name; // fontname uint16_t version; // file format version uint32_t checksum; // CRC32 checksum of file data @@ -44,24 +41,24 @@ class FontCache public: FontCache () : _changed(false) {} ~FontCache () {clear();} - bool read (const char *fontname, const char *dir); - bool read (const char *fontname, std::istream &is); - bool write (const char *dir) const; - bool write (const char *fontname, const char *dir) const; - bool write (const char *fontname, std::ostream &os) const; + bool read (const std::string &fontname, const std::string &dir); + bool read (const std::string &fontname, std::istream &is); + bool write (const std::string &dir) const; + bool write (const std::string &fontname, const std::string &dir) const; + bool write (const std::string &fontname, std::ostream &os) const; const Glyph* getGlyph (int c) const; void setGlyph (int c, const Glyph &glyph); void clear (); const std::string& fontname () const {return _fontname;} - static bool fontinfo (const char *dirname, std::vector<FontInfo> &infos, std::vector<std::string> &invalid); + static bool fontinfo (const std::string &dirname, std::vector<FontInfo> &infos, std::vector<std::string> &invalid); static bool fontinfo (std::istream &is, FontInfo &info); - static void fontinfo (const char *dirname, std::ostream &os, bool purge=false); + static void fontinfo (const std::string &dirname, std::ostream &os, bool purge=false); private: static const uint8_t FORMAT_VERSION; std::string _fontname; - GlyphMap _glyphs; + std::map<int, Glyph> _glyphs; bool _changed; }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp index 886ab0ec6c6..d6f3325d31e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp @@ -2,7 +2,7 @@ ** FontEncoding.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,45 +18,36 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include "CMap.hpp" #include "CMapManager.hpp" #include "EncFile.hpp" #include "FileFinder.hpp" #include "FontEncoding.hpp" +#include "utility.hpp" using namespace std; - -struct EncodingMap : public map<string, EncFile*> -{ - ~EncodingMap () { - for (auto &entry : *this) - delete entry.second; - } -}; - - /** Returns the encoding object for a given encoding name. * @param[in] encname name of the encoding to lookup * @return pointer to encoding object, or 0 if there is no encoding defined */ FontEncoding* FontEncoding::encoding (const string &encname) { if (encname.empty()) return 0; - // initially, try to find an .enc file with the given name + + using EncodingMap = unordered_map<string, unique_ptr<EncFile>>; static EncodingMap encmap; - EncodingMap::const_iterator it = encmap.find(encname); + // initially, try to find an .enc file with the given name + auto it = encmap.find(encname); if (it != encmap.end()) - return it->second; + return it->second.get(); if (FileFinder::instance().lookup(encname + ".enc", false)) { - EncFile *enc = new EncFile(encname); - encmap[encname] = enc; - return enc; + auto state = encmap.emplace(encname, util::make_unique<EncFile>(encname)); + return state.first->second.get(); } // no .enc file found => try to find a CMap if (CMap *cmap = CMapManager::instance().lookup(encname)) return cmap; - return 0; + return nullptr; } ///////////////////////////////////////////////////////////////////////// diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp index ea0f15e4beb..77175adce06 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp @@ -2,7 +2,7 @@ ** FontEncoding.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -28,8 +28,7 @@ struct CharMapID; class PhysicalFont; -struct FontEncoding -{ +struct FontEncoding { virtual ~FontEncoding () =default; virtual Character decode (uint32_t c) const =0; virtual bool mapsToCharIndex () const =0; @@ -38,15 +37,13 @@ struct FontEncoding }; -struct NamedFontEncoding : public FontEncoding -{ +struct NamedFontEncoding : public FontEncoding { virtual const char* name () const =0; virtual const char* path () const =0; }; -class FontEncodingPair : public FontEncoding -{ +class FontEncodingPair : public FontEncoding { public: FontEncodingPair (const FontEncoding *enc1) : _enc1(enc1), _enc2(0) {} FontEncodingPair (const FontEncoding *enc1, const FontEncoding *enc2) : _enc1(enc1), _enc2(enc2) {} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp index 61128964655..59101458caa 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp @@ -2,7 +2,7 @@ ** FontEngine.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <sstream> #include <ft2build.h> #include FT_ADVANCES_H @@ -30,6 +29,7 @@ #include "FontEngine.hpp" #include "FontStyle.hpp" #include "Message.hpp" +#include "utility.hpp" using namespace std; @@ -143,15 +143,15 @@ void FontEngine::buildCharMap (RangeMap &charmap) { /** Creates a charmap that maps from the custom character encoding to unicode. * @return pointer to charmap if it could be created, 0 otherwise */ -const RangeMap* FontEngine::createCustomToUnicodeMap () { +unique_ptr<const RangeMap> FontEngine::createCustomToUnicodeMap () { FT_CharMap ftcharmap = _currentFace->charmap; if (FT_Select_Charmap(_currentFace, FT_ENCODING_ADOBE_CUSTOM) != 0) - return 0; + return nullptr; RangeMap index_to_source_chrcode; buildCharMap(index_to_source_chrcode); if (FT_Select_Charmap(_currentFace, FT_ENCODING_UNICODE) != 0) - return 0; - RangeMap *charmap = new RangeMap; + return nullptr; + auto charmap = util::make_unique<RangeMap>(); FT_UInt glyph_index; uint32_t unicode_point = FT_Get_First_Char(_currentFace, &glyph_index); while (glyph_index) { @@ -160,17 +160,17 @@ const RangeMap* FontEngine::createCustomToUnicodeMap () { unicode_point = FT_Get_Next_Char(_currentFace, unicode_point, &glyph_index); } FT_Set_Charmap(_currentFace, ftcharmap); - return charmap; + return std::move(charmap); } const char* FontEngine::getFamilyName () const { - return _currentFace ? _currentFace->family_name : 0; + return _currentFace ? _currentFace->family_name : nullptr; } const char* FontEngine::getStyleName () const { - return _currentFace ? _currentFace->style_name : 0; + return _currentFace ? _currentFace->style_name : nullptr; } @@ -326,9 +326,9 @@ CharMapID FontEngine::setCustomCharMap () { // handle API change in freetype version 2.2.1 #if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && (FREETYPE_MINOR > 2 || (FREETYPE_MINOR == 2 && FREETYPE_PATCH >= 1))) - typedef const FT_Vector *FTVectorPtr; + using FTVectorPtr = const FT_Vector*; #else - typedef FT_Vector *FTVectorPtr; + using FTVectorPtr = FT_Vector*; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp index a2ec3947c2b..0f831cc971b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp @@ -2,7 +2,7 @@ ** FontEngine.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -25,6 +25,7 @@ #include FT_FREETYPE_H #include FT_CID_H #include <map> +#include <memory> #include <string> #include <vector> #include "Character.hpp" @@ -36,8 +37,7 @@ class Font; /** This class provides methods to handle font files and font data. * It's a wrapper for the Freetype font library. */ -class FontEngine -{ +class FontEngine { public: ~FontEngine (); static FontEngine& instance (); @@ -65,7 +65,7 @@ class FontEngine int getCharByGlyphName (const char *name) const; bool setCharMap (const CharMapID &charMapID); void buildCharMap (RangeMap &charmap); - const RangeMap* createCustomToUnicodeMap (); + std::unique_ptr<const RangeMap> createCustomToUnicodeMap (); protected: FontEngine (); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp index 885a596b7cd..dafd4938004 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp @@ -2,7 +2,7 @@ ** FontManager.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cstring> #include <cstdlib> #include <fstream> @@ -48,7 +47,7 @@ int FontManager::fontID (int n) const { auto it = _num2id.find(n); return (it == _num2id.end()) ? -1 : it->second; } - VfNum2IdMap::const_iterator vit = _vfnum2id.find(_vfStack.top()); + auto vit = _vfnum2id.find(_vfStack.top()); if (vit == _vfnum2id.end()) return -1; const Num2IdMap &num2id = vit->second; @@ -102,7 +101,7 @@ int FontManager::fontnum (int id) const { int FontManager::vfFirstFontNum (const VirtualFont *vf) const { - VfFirstFontMap::const_iterator it = _vfFirstFontMap.find(vf); + auto it = _vfFirstFontMap.find(vf); return (it == _vfFirstFontMap.end()) ? -1 : (int) it->second; } @@ -112,32 +111,32 @@ int FontManager::vfFirstFontNum (const VirtualFont *vf) const { * @return pointer to font if font was found, 0 otherwise */ Font* FontManager::getFont (int n) const { int id = fontID(n); - return (id < 0) ? 0 : _fonts[id].get(); + return (id < 0) ? nullptr : _fonts[id].get(); } Font* FontManager::getFont (const string &name) const { int id = fontID(name); if (id < 0) - return 0; + return nullptr; return _fonts[id].get(); } Font* FontManager::getFontById (int id) const { if (id < 0 || size_t(id) >= _fonts.size()) - return 0; + return nullptr; return _fonts[id].get(); } /** Returns the current active virtual font. */ const VirtualFont* FontManager::getVF () const { - return _vfStack.empty() ? 0 : _vfStack.top(); + return _vfStack.empty() ? nullptr : _vfStack.top(); } -static Font* create_font (const string &filename, const string &fontname, int fontindex, uint32_t checksum, double dsize, double ssize) { +static unique_ptr<Font> create_font (const string &filename, const string &fontname, int fontindex, uint32_t checksum, double dsize, double ssize) { string ext; if (const char *dot = strrchr(filename.c_str(), '.')) ext = dot+1; @@ -155,7 +154,7 @@ static Font* create_font (const string &filename, const string &fontname, int fo if (ext == "mf") return PhysicalFont::create(fontname, checksum, dsize, ssize, PhysicalFont::Type::MF); } - return 0; + return nullptr; } @@ -174,10 +173,10 @@ int FontManager::registerFont (uint32_t fontnum, const string &name, uint32_t ch unique_ptr<Font> newfont; const int newid = _fonts.size(); // the new font gets this ID - Name2IdMap::iterator it = _name2id.find(name); + auto it = _name2id.find(name); if (it != _name2id.end()) { // font with same name already registered? const auto &font = _fonts[it->second]; - newfont.reset(font->clone(dsize, ssize)); + newfont = font->clone(dsize, ssize); } else { string filename = name; @@ -189,12 +188,12 @@ int FontManager::registerFont (uint32_t fontnum, const string &name, uint32_t ch } // try to find font file with the exact given name if (filename.rfind(".") != string::npos) - newfont.reset(create_font(filename, name, fontindex, checksum, dsize, ssize)); + newfont = create_font(filename, name, fontindex, checksum, dsize, ssize); else { // try various font file formats if the given file has no extension const char *exts[] = {"pfb", "otf", "ttc", "ttf", "vf", "mf", 0}; for (const char **p = exts; *p && !newfont; ++p) - newfont.reset(create_font(filename+"."+*p, name, fontindex, checksum, dsize, ssize)); + newfont = create_font(filename+"."+*p, name, fontindex, checksum, dsize, ssize); } if (newfont) { if (!newfont->findAndAssignBaseFontMap()) @@ -204,7 +203,7 @@ int FontManager::registerFont (uint32_t fontnum, const string &name, uint32_t ch } else { // create dummy font as a placeholder if the proper font is not available - newfont.reset(new EmptyFont(name)); + newfont = util::make_unique<EmptyFont>(name); if (filename.rfind(".") == string::npos) filename += ".mf"; // print warning message about missing font file (only once for each filename) @@ -262,10 +261,10 @@ int FontManager::registerFont (uint32_t fontnum, string filename, int fontIndex, const char *path = filename.c_str(); unique_ptr<Font> newfont; const int newid = _fonts.size(); // the new font gets this ID - Name2IdMap::iterator it = _name2id.find(fontname); + auto it = _name2id.find(fontname); if (it != _name2id.end()) { // font with same name already registered? if (NativeFont *font = dynamic_cast<NativeFont*>(_fonts[it->second].get())) - newfont.reset(font->clone(ptsize, style, color)); + newfont = font->clone(ptsize, style, color); } else { if (!FileSystem::exists(path)) @@ -276,7 +275,7 @@ int FontManager::registerFont (uint32_t fontnum, string filename, int fontIndex, } if (!newfont) { // create dummy font as a placeholder if the proper font is not available - newfont.reset(new EmptyFont(filename)); + newfont = util::make_unique<EmptyFont>(filename); // print warning message about missing font file (only once for each filename) static set<string> missing_fonts; if (missing_fonts.find(filename) == missing_fonts.end()) { diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp index ade32bec26c..49aece6fc62 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp @@ -2,7 +2,7 @@ ** FontManager.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,12 +21,12 @@ #ifndef FONTMANAGER_HPP #define FONTMANAGER_HPP -#include <map> #include <memory> #include <ostream> #include <set> #include <string> #include <stack> +#include <unordered_map> #include <vector> #include "Color.hpp" #include "FontStyle.hpp" @@ -43,11 +43,11 @@ class VirtualFont; * appear anywhere in the output. */ class FontManager { - typedef std::map<uint32_t,int> Num2IdMap; - typedef std::map<std::string,int> Name2IdMap; - typedef std::map<const VirtualFont*,Num2IdMap> VfNum2IdMap; - typedef std::map<const VirtualFont*, uint32_t> VfFirstFontMap; - typedef std::stack<VirtualFont*> VfStack; + 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>; + using VfStack = std::stack<VirtualFont*>; public: static FontManager& instance (); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.cpp index e91d9c7eaa6..b8293a14361 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.cpp @@ -2,7 +2,7 @@ ** FontMap.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <cstring> #include <fstream> @@ -32,6 +31,7 @@ #include "MapLine.hpp" #include "Message.hpp" #include "Subfont.hpp" +#include "utility.hpp" using namespace std; @@ -164,12 +164,12 @@ bool FontMap::append (const MapLine &mapline) { if (mapline.sfd()) mapline.sfd()->subfonts(subfonts); else - subfonts.push_back(0); + subfonts.push_back(nullptr); for (Subfont *subfont : subfonts) { string fontname = mapline.texname()+(subfont ? subfont->id() : ""); auto it = _entries.find(fontname); if (it == _entries.end()) { - _entries[fontname].reset(new Entry(mapline, subfont)); + _entries.emplace(fontname, util::make_unique<Entry>(mapline, subfont)); appended = true; } } @@ -193,12 +193,12 @@ bool FontMap::replace (const MapLine &mapline) { if (mapline.sfd()) mapline.sfd()->subfonts(subfonts); else - subfonts.push_back(0); + subfonts.push_back(nullptr); for (Subfont *subfont : subfonts) { string fontname = mapline.texname()+(subfont ? subfont->id() : ""); auto it = _entries.find(fontname); if (it == _entries.end()) - _entries[fontname].reset(new Entry(mapline, subfont)); + _entries.emplace(fontname, util::make_unique<Entry>(mapline, subfont)); else if (!it->second->locked) *it->second = Entry(mapline, subfont); } @@ -217,7 +217,7 @@ bool FontMap::remove (const MapLine &mapline) { if (mapline.sfd()) mapline.sfd()->subfonts(subfonts); else - subfonts.push_back(0); + subfonts.push_back(nullptr); for (const Subfont *subfont : subfonts) { string fontname = mapline.texname()+(subfont ? subfont->id() : ""); auto it = _entries.find(fontname); @@ -245,7 +245,7 @@ void FontMap::readdir (const string &dirname) { while (const char *fname = dir.read(Directory::ET_FILE)) { if (strlen(fname) >= 4 && strcmp(fname+strlen(fname)-4, ".map") == 0) { string path = dirname + "/" + fname; - read(path.c_str()); + read(path); } } } @@ -257,7 +257,7 @@ void FontMap::readdir (const string &dirname) { const FontMap::Entry* FontMap::lookup (const string &fontname) const { auto it = _entries.find(fontname); if (it == _entries.end()) - return 0; + return nullptr; return it->second.get(); } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp index 103bb6aa89a..09344b68fc3 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp @@ -2,7 +2,7 @@ ** FontMap.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,23 +21,20 @@ #ifndef FONTMAP_HPP #define FONTMAP_HPP -#include <map> #include <memory> #include <ostream> #include <string> +#include <unordered_map> #include "FontStyle.hpp" - struct FontEncoding; class MapLine; class Subfont; -class FontMap -{ +class FontMap { public: - struct Entry - { - Entry (const MapLine &mapline, Subfont *subfont=0); + struct Entry { + Entry (const MapLine &mapline, Subfont *subfont=nullptr); Entry (const Entry &entry) =delete; Entry (Entry &&entry) =default; Entry& operator = (Entry &&entry) =default; @@ -71,7 +68,7 @@ class FontMap FontMap () =default; private: - std::map<std::string,std::unique_ptr<Entry>> _entries; + std::unordered_map<std::string,std::unique_ptr<Entry>> _entries; }; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.cpp index 375062f7f0a..87a03599795 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.cpp @@ -2,7 +2,7 @@ ** FontMetrics.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,23 +18,24 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <fstream> +#include <memory> #include "FileFinder.hpp" #include "FontMetrics.hpp" #include "JFM.hpp" +#include "utility.hpp" using namespace std; -FontMetrics* FontMetrics::read (const char *fontname) { - const char *path = FileFinder::instance().lookup(string(fontname) + ".tfm"); +unique_ptr<FontMetrics> FontMetrics::read (const string &fontname) { + const char *path = FileFinder::instance().lookup(fontname + ".tfm"); ifstream ifs(path, ios::binary); if (!ifs) - return 0; + return unique_ptr<FontMetrics>(); uint16_t id = 256*ifs.get(); id += ifs.get(); if (id == 9 || id == 11) // Japanese font metric file? - return new JFM(ifs); - return new TFM(ifs); + return util::make_unique<JFM>(ifs); + return util::make_unique<TFM>(ifs); } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp index cdf462a5a20..c9d8b2d37b7 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp @@ -2,7 +2,7 @@ ** FontMetrics.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,10 +22,11 @@ #define FONTMETRICS_HPP #include <istream> +#include <memory> +#include <string> #include "MessageException.hpp" -struct FontMetrics -{ +struct FontMetrics { virtual ~FontMetrics () =default; virtual double getDesignSize () const =0; virtual double getCharWidth (int c) const =0; @@ -42,12 +43,11 @@ struct FontMetrics virtual uint32_t getChecksum () const =0; virtual uint16_t firstChar () const =0; virtual uint16_t lastChar () const =0; - static FontMetrics* read (const char *fontname); + static std::unique_ptr<FontMetrics> read (const std::string &fontname); }; -struct NullFontMetric : public FontMetrics -{ +struct NullFontMetric : public FontMetrics { double getDesignSize () const override {return 1;} double getCharWidth (int c) const override {return 0;} double getCharHeight (int c) const override {return 0;} @@ -66,8 +66,7 @@ struct NullFontMetric : public FontMetrics }; -struct FontMetricException : public MessageException -{ +struct FontMetricException : public MessageException { FontMetricException (const std::string &msg) : MessageException(msg) {} }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontStyle.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontStyle.hpp index fc2a952142a..8f0d17c8764 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontStyle.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontStyle.hpp @@ -2,7 +2,7 @@ ** FontStyle.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp index 86a822db976..774bfeb40a4 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp @@ -2,7 +2,7 @@ ** FontWriter.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,17 +18,17 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <array> #include "FontWriter.hpp" +#include "Message.hpp" #include "utility.hpp" using namespace std; bool FontWriter::AUTOHINT_FONTS = false; -const array<FontWriter::FontFormatInfo, 4> FontWriter::_formatInfos = {{ +const array<FontWriter::FontFormatInfo, 4> FontWriter::_formatInfos {{ {FontWriter::FontFormat::SVG, "image/svg+xml", "svg", "svg"}, {FontWriter::FontFormat::TTF, "application/x-font-ttf", "ttf", "truetype"}, {FontWriter::FontFormat::WOFF, "application/x-font-woff", "woff", "woff"}, @@ -38,7 +38,7 @@ const array<FontWriter::FontFormatInfo, 4> FontWriter::_formatInfos = {{ /** Returns the corresponding FontFormat for a given format name (e.g. "svg", "woff" etc.). */ FontWriter::FontFormat FontWriter::toFontFormat (string formatstr) { - util::tolower(formatstr); + formatstr = util::tolower(formatstr); for (const FontFormatInfo &info : _formatInfos) { if (formatstr == info.formatstr_short) return info.format; @@ -66,6 +66,8 @@ vector<string> FontWriter::supportedFormats () { } +#include <config.h> + #ifdef DISABLE_WOFF // dummy functions used if WOFF support is disabled FontWriter::FontWriter (const PhysicalFont &font) : _font(font) {} @@ -76,14 +78,14 @@ bool FontWriter::writeCSSFontFace (FontFormat format, const set<int> &charcodes, #include <fstream> #include <iomanip> #include <sstream> -#include <woff2_enc.h> -#include <file.h> +#include <woff2/encode.h> #include "ffwrapper.h" #include "Bezier.hpp" #include "FileSystem.hpp" #include "Font.hpp" #include "Glyph.hpp" -#include "utility.hpp" +#include "TTFAutohint.hpp" +#include "TrueTypeFont.hpp" FontWriter::FontWriter (const PhysicalFont &font) : _font(font) { @@ -183,6 +185,32 @@ static void writeSFD (const string &sfdname, const PhysicalFont &font, const set } +bool FontWriter::createTTFFile (const string &sfdname, const string &ttfname) const { + TTFAutohint autohinter; + if (!autohinter.available()) + return ff_sfd_to_ttf(sfdname.c_str(), ttfname.c_str(), AUTOHINT_FONTS); + + bool ok = ff_sfd_to_ttf(sfdname.c_str(), ttfname.c_str(), false); + if (ok && AUTOHINT_FONTS) { + string tmpname = ttfname+"-ah"; + int errnum = autohinter.autohint(ttfname, tmpname, true); + if (errnum) { + Message::wstream(true) << "failed to autohint font '" << _font.name() << "'"; + string msg = autohinter.lastErrorMessage(); + if (!msg.empty()) + Message::wstream() << " (" << msg << ")"; + // keep the unhinted TTF + FileSystem::remove(tmpname); + } + else { + FileSystem::remove(ttfname); + FileSystem::rename(tmpname, ttfname); + } + } + return ok; +} + + /** Creates a font file containing a given set of glyphs mapped to their Unicode points. * @param[in] format target font format * @param[in] charcodes character codes of the glyphs to be considered @@ -190,37 +218,22 @@ static void writeSFD (const string &sfdname, const PhysicalFont &font, const set * @return name of the created font file */ string FontWriter::createFontFile (FontFormat format, const set<int> &charcodes, GFGlyphTracer::Callback *cb) const { string tmpdir = FileSystem::tmpdir(); - string sfdname = tmpdir+_font.name()+"-tmp.sfd"; + string basename = tmpdir+_font.name()+"-tmp"; + string sfdname = basename+".sfd"; writeSFD(sfdname, _font, charcodes, cb); - bool ok = false; - string targetname = tmpdir+_font.name()+"-tmp."+fontFormatInfo(format)->formatstr_short; - switch (format) { - case FontFormat::TTF: - ok = ff_sfd_to_ttf(sfdname.c_str(), targetname.c_str(), AUTOHINT_FONTS); - break; - case FontFormat::WOFF: - ok = ff_sfd_to_woff(sfdname.c_str(), targetname.c_str(), AUTOHINT_FONTS); - break; - case FontFormat::WOFF2: { - string ttfname = tmpdir+_font.name()+".ttf"; - if (ff_sfd_to_ttf(sfdname.c_str(), ttfname.c_str(), AUTOHINT_FONTS)) { - string input = woff2::GetFileContent(ttfname); - const uint8_t* input_data = reinterpret_cast<const uint8_t*>(input.data()); - size_t output_size = woff2::MaxWOFF2CompressedSize(input_data, input.size()); - string output(output_size, 0); - uint8_t* output_data = reinterpret_cast<uint8_t*>(&output[0]); - woff2::WOFF2Params params; - if (woff2::ConvertTTFToWOFF2(input_data, input.size(), output_data, &output_size, params)) { - output.resize(output_size); - woff2::SetFileContents(targetname, output.begin(), output.end()); - ok = true; - } - if (!PhysicalFont::KEEP_TEMP_FILES) - FileSystem::remove(ttfname); - } - break; + string ttfname = basename+".ttf"; + string targetname = basename+"."+fontFormatInfo(format)->formatstr_short; + bool ok = createTTFFile(sfdname, ttfname); + if (ok) { + if (format == FontFormat::WOFF || format == FontFormat::WOFF2) { + TrueTypeFont ttf(ttfname); + if (format == FontFormat::WOFF) + ttf.writeWOFF(targetname); + else + ok = ttf.writeWOFF2(targetname); + if (!PhysicalFont::KEEP_TEMP_FILES) + FileSystem::remove(ttfname); } - default:; } if (!PhysicalFont::KEEP_TEMP_FILES) FileSystem::remove(sfdname); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp index 05995200383..8b780d02ebc 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp @@ -2,7 +2,7 @@ ** FontWriter.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -49,8 +49,8 @@ class FontWriter { const char *formatstr_short; const char *formatstr_long; }; - static const FontFormatInfo* fontFormatInfo (FontFormat format); + bool createTTFFile (const std::string &sfdname, const std::string &ttfname) const; private: const PhysicalFont &_font; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp index 79b3d085782..425bc6494aa 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp @@ -2,7 +2,7 @@ ** GFGlyphTracer.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include "GFGlyphTracer.hpp" using namespace std; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp index 4ccad3fd19e..bbcebedd557 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp @@ -2,7 +2,7 @@ ** GFGlyphTracer.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp index ae58c1b8bf6..ddb306d612e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp @@ -2,7 +2,7 @@ ** GFReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -28,8 +28,7 @@ using namespace std; -struct GFCommand -{ +struct GFCommand { void (GFReader::*method)(int); int numBytes; }; @@ -340,21 +339,21 @@ void GFReader::cmdNop (int) { /** Reads character locator (part of postamble) */ void GFReader::cmdCharLoc0 (int) { uint8_t c = readUnsigned(1); // character code mod 256 - uint8_t dm = readUnsigned(1); // + uint8_t dm = readUnsigned(1); // = dx/65536 int32_t w = readSigned(4); // (1<<24)*characterWidth/designSize - int32_t p = readSigned(4); // pointer to begin of (last) character data - int32_t dx = 65536*dm; - int32_t dy = 0; - _charInfoMap[c] = CharInfo(dx, dy, w, p); + int32_t p = readSigned(4); // pointer to begin of (last) character data + int32_t dx = 65536*dm; // horizontal escapement + int32_t dy = 0; // vertical escapement + _charInfoMap.emplace(c, CharInfo(dx, dy, w, p)); } /** Reads character locator (part of postamble) */ void GFReader::cmdCharLoc (int) { - uint32_t c = readUnsigned(1); // character code mod 256 + uint8_t c = readUnsigned(1); // character code mod 256 int32_t dx = readSigned(4); // horizontal escapement (scaled pixel units) int32_t dy = readSigned(4); // vertical escapement (scaled pixel units) int32_t w = readSigned(4); // (1<<24)*characterWidth/designSize int32_t p = readSigned(4); // pointer to begin of (last) character data - _charInfoMap[c] = CharInfo(dx, dy, w, p); + _charInfoMap.emplace(c, CharInfo(dx, dy, w, p)); } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp index 6ca0dc3fca1..85ee6ffd8fb 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp @@ -2,7 +2,7 @@ ** GFReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,8 +22,8 @@ #define GFREADER_HPP #include <istream> -#include <map> #include <string> +#include <unordered_map> #include "Bitmap.hpp" #include "MessageException.hpp" @@ -101,7 +101,7 @@ class GFReader double _designSize; ///< designSize in PS points double _hppp, _vppp; ///< horizontal and vertical pixel per point uint32_t _checksum; - std::map<uint8_t,CharInfo> _charInfoMap; + std::unordered_map<uint8_t,CharInfo> _charInfoMap; bool _insideCharDef; ///< true if inside a character definition (between BOC and EOC) bool _penDown; }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.cpp index 66f16f05bff..cff950025d6 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.cpp @@ -2,7 +2,7 @@ ** GFTracer.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <fstream> #include <potracelib.h> #include "GFTracer.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp index 229ef2593fe..61c8fdd6e49 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp @@ -2,7 +2,7 @@ ** GFTracer.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp index 1798f35a1b5..5672a8b4eb0 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp @@ -2,7 +2,7 @@ ** Ghostscript.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -51,13 +51,11 @@ static string get_path_from_registry () { mode |= KEY_WOW64_32KEY; #endif #endif - static const char *gs_companies[] = {"GPL", "GNU", "AFPL", "Aladdin"}; - for (size_t i=0; i < sizeof(gs_companies)/sizeof(char*); i++) { - const string reg_path = string("SOFTWARE\\") + gs_companies[i] + " Ghostscript"; - static HKEY reg_roots[] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE}; - for (size_t j=0; j < sizeof(reg_roots)/sizeof(HKEY); j++) { + for (const char *gs_company : {"GPL", "GNU", "AFPL", "Aladdin"}) { + const string reg_path = string("SOFTWARE\\") + gs_company + " Ghostscript"; + for (HKEY reg_root : {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE}) { HKEY hkey; - if (RegOpenKeyExA(reg_roots[j], reg_path.c_str(), 0, mode, &hkey) == ERROR_SUCCESS) { + if (RegOpenKeyExA(reg_root, reg_path.c_str(), 0, mode, &hkey) == ERROR_SUCCESS) { char subkey[16]; for (int k=0; RegEnumKeyA(hkey, k, subkey, 16) == ERROR_SUCCESS; k++) { istringstream iss(subkey); @@ -112,15 +110,19 @@ static string get_libgs (const string &fname) { // try to find libgs.so.X on the user's system const int abi_min=7, abi_max=9; // supported libgs ABI versions for (int i=abi_max; i >= abi_min; i--) { - ostringstream oss; #if defined(__CYGWIN__) - oss << "cyggs-" << i << ".dll"; + string dlname = "cyggs-" + to_string(i) + ".dll"; #else - oss << "libgs.so." << i; + string dlname = "libgs.so." + to_string(i); #endif - DLLoader loader(oss.str().c_str()); + DLLoader loader(dlname); if (loader.loaded()) - return oss.str(); + return dlname; +#if defined(__APPLE__) + dlname = "libgs." + to_string(i) + ".dylib"; + if (loader.loadLibrary(dlname)) + return dlname; +#endif } #endif // no appropriate library found @@ -133,7 +135,7 @@ static string get_libgs (const string &fname) { * constructor should only be used to call available() and revision(). */ Ghostscript::Ghostscript () #if !defined(HAVE_LIBGS) - : DLLoader(get_libgs(LIBGS_NAME).c_str()) + : DLLoader(get_libgs(LIBGS_NAME)) #endif { _inst = 0; @@ -146,7 +148,7 @@ Ghostscript::Ghostscript () * @param[in] caller this parameter is passed to all callback functions */ Ghostscript::Ghostscript (int argc, const char **argv, void *caller) #if !defined(HAVE_LIBGS) - : DLLoader(get_libgs(LIBGS_NAME).c_str()) + : DLLoader(get_libgs(LIBGS_NAME)) #endif { _inst = 0; @@ -194,7 +196,7 @@ bool Ghostscript::revision (gsapi_revision_t *r) { #if defined(HAVE_LIBGS) return (gsapi_revision(r, sizeof(gsapi_revision_t)) == 0); #else - if (PFN_gsapi_revision fn = (PFN_gsapi_revision)loadSymbol("gsapi_revision")) + if (auto fn = LOAD_SYMBOL(gsapi_revision)) return (fn(r, sizeof(gsapi_revision_t)) == 0); return false; #endif @@ -224,7 +226,7 @@ int Ghostscript::new_instance (void **psinst, void *caller) { #if defined(HAVE_LIBGS) return gsapi_new_instance(psinst, caller); #else - if (PFN_gsapi_new_instance fn = (PFN_gsapi_new_instance)loadSymbol("gsapi_new_instance")) + if (auto fn = LOAD_SYMBOL(gsapi_new_instance)) return fn(psinst, caller); *psinst = 0; return 0; @@ -238,7 +240,7 @@ void Ghostscript::delete_instance () { #if defined(HAVE_LIBGS) gsapi_delete_instance(_inst); #else - if (PFN_gsapi_delete_instance fn = (PFN_gsapi_delete_instance)loadSymbol("gsapi_delete_instance")) + if (auto fn = LOAD_SYMBOL(gsapi_delete_instance)) fn(_inst); #endif } @@ -249,7 +251,7 @@ int Ghostscript::exit () { #if defined(HAVE_LIBGS) return gsapi_exit(_inst); #else - if (PFN_gsapi_exit fn = (PFN_gsapi_exit)loadSymbol("gsapi_exit")) + if (auto fn = LOAD_SYMBOL(gsapi_exit)) return fn(_inst); return 0; #endif @@ -264,7 +266,7 @@ int Ghostscript::set_stdio (Stdin in, Stdout out, Stderr err) { #if defined(HAVE_LIBGS) return gsapi_set_stdio(_inst, in, out, err); #else - if (PFN_gsapi_set_stdio fn = (PFN_gsapi_set_stdio)loadSymbol("gsapi_set_stdio")) + if (auto fn = LOAD_SYMBOL(gsapi_set_stdio)) return fn(_inst, in, out, err); return 0; #endif @@ -279,7 +281,7 @@ int Ghostscript::init_with_args (int argc, char **argv) { #if defined(HAVE_LIBGS) return gsapi_init_with_args(_inst, argc, argv); #else - if (PFN_gsapi_init_with_args fn = (PFN_gsapi_init_with_args)loadSymbol("gsapi_init_with_args")) + if (auto fn = LOAD_SYMBOL(gsapi_init_with_args)) return fn(_inst, argc, argv); return 0; #endif @@ -291,7 +293,7 @@ int Ghostscript::run_string_begin (int user_errors, int *pexit_code) { #if defined(HAVE_LIBGS) return gsapi_run_string_begin(_inst, user_errors, pexit_code); #else - if (PFN_gsapi_run_string_begin fn = (PFN_gsapi_run_string_begin)loadSymbol("gsapi_run_string_begin")) + if (auto fn = LOAD_SYMBOL(gsapi_run_string_begin)) return fn(_inst, user_errors, pexit_code); *pexit_code = 0; return 0; @@ -310,7 +312,7 @@ int Ghostscript::run_string_continue (const char *str, unsigned length, int user #if defined(HAVE_LIBGS) return gsapi_run_string_continue(_inst, str, length, user_errors, pexit_code); #else - if (PFN_gsapi_run_string_continue fn = (PFN_gsapi_run_string_continue)loadSymbol("gsapi_run_string_continue")) + if (auto fn = LOAD_SYMBOL(gsapi_run_string_continue)) return fn(_inst, str, length, user_errors, pexit_code); *pexit_code = 0; return 0; @@ -323,7 +325,7 @@ int Ghostscript::run_string_end (int user_errors, int *pexit_code) { #if defined(HAVE_LIBGS) return gsapi_run_string_end(_inst, user_errors, pexit_code); #else - if (PFN_gsapi_run_string_end fn = (PFN_gsapi_run_string_end)loadSymbol("gsapi_run_string_end")) + if (auto fn = LOAD_SYMBOL(gsapi_run_string_end)) return fn(_inst, user_errors, pexit_code); *pexit_code = 0; return 0; @@ -336,7 +338,7 @@ const char* Ghostscript::error_name (int code) { code = -code; const char *error_names[] = { ERROR_NAMES }; if (code == 0 || (size_t)code > sizeof(error_names)/sizeof(error_names[0])) - return 0; + return nullptr; #if defined(HAVE_LIBGS) // use array defined in libgs to avoid linking the error strings into the binary return gs_error_names[code-1]; @@ -344,9 +346,9 @@ const char* Ghostscript::error_name (int code) { // gs_error_names is private in the Ghostscript DLL so we can't access it here return error_names[code-1]; #else - if (const char **error_names = (const char**)loadSymbol("gs_error_names")) + if (auto error_names = loadSymbol<const char**>("gs_error_names")) return error_names[code-1]; - return 0; + return nullptr; #endif } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp index 01f4b3abea2..258055f7672 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp @@ -2,7 +2,7 @@ ** Ghostscript.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -40,9 +40,9 @@ #if defined(DISABLE_GS) struct Ghostscript { - typedef int (GSDLLCALLPTR Stdin) (void *caller, char *buf, int len); - typedef int (GSDLLCALLPTR Stdout) (void *caller, const char *str, int len); - typedef int (GSDLLCALLPTR Stderr) (void *caller, const char *str, int len); + using Stdin = int (GSDLLCALLPTR)(void *caller, char *buf, int len); + using Stdout = int (GSDLLCALLPTR)(void *caller, const char *str, int len); + using Stderr = int (GSDLLCALLPTR)(void *caller, const char *str, int len); Ghostscript () {} Ghostscript (int argc, const char **argv, void *caller=0) {} @@ -67,9 +67,9 @@ class Ghostscript #endif { public: - typedef int (GSDLLCALLPTR Stdin) (void *caller, char *buf, int len); - typedef int (GSDLLCALLPTR Stdout) (void *caller, const char *str, int len); - typedef int (GSDLLCALLPTR Stderr) (void *caller, const char *str, int len); + using Stdin = int (GSDLLCALLPTR)(void *caller, char *buf, int len); + using Stdout = int (GSDLLCALLPTR)(void *caller, const char *str, int len); + using Stderr = int (GSDLLCALLPTR)(void *caller, const char *str, int len); public: Ghostscript (); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Glyph.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Glyph.hpp index cc593a269aa..d2ec97e1c1b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Glyph.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Glyph.hpp @@ -2,7 +2,7 @@ ** Glyph.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,6 +23,6 @@ #include "GraphicsPath.hpp" -typedef GraphicsPath<int32_t> Glyph; +using Glyph = GraphicsPath<int32_t>; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp index b77a582796b..f37e6f06860 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp @@ -2,7 +2,7 @@ ** GlyphTracerMessages.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp index 010302a2257..bcf781256b7 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp @@ -2,7 +2,7 @@ ** GraphicsPath.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,8 +22,8 @@ #define GRAPHICSPATH_HPP #include <cctype> +#include <deque> #include <ostream> -#include <vector> #include "BoundingBox.hpp" #include "Matrix.hpp" #include "Pair.hpp" @@ -36,7 +36,7 @@ class GraphicsPath friend class PathClipper; public: enum class WindingRule {EVEN_ODD, NON_ZERO}; - typedef Pair<T> Point; + using Point = Pair<T>; struct Command { enum class Type {MOVETO, LINETO, CONICTO, CUBICTO, CLOSEPATH}; @@ -320,7 +320,7 @@ class GraphicsPath void iterate (Actions &actions, bool optimize) const; private: - std::vector<Command> _commands; + std::deque<Command> _commands; WindingRule _windingRule; }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp index e8b11bcb434..86f0ef022bf 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp @@ -2,7 +2,7 @@ ** HtmlSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,64 +18,25 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> -#include <cassert> -#include <sstream> #include "HtmlSpecialHandler.hpp" +#include "HyperlinkManager.hpp" #include "InputReader.hpp" -#include "Message.hpp" #include "SpecialActions.hpp" -#include "SVGTree.hpp" using namespace std; -// variable to select the link marker variant (none, underlined, boxed, or colored background) -HtmlSpecialHandler::MarkerType HtmlSpecialHandler::MARKER_TYPE = HtmlSpecialHandler::MarkerType::LINE; -Color HtmlSpecialHandler::LINK_BGCOLOR; -Color HtmlSpecialHandler::LINK_LINECOLOR; -bool HtmlSpecialHandler::USE_LINECOLOR = false; - void HtmlSpecialHandler::preprocess (const char *, istream &is, SpecialActions &actions) { StreamInputReader ir(is); ir.skipSpace(); // collect page number and ID of named anchors - map<string,string> attribs; + unordered_map<string,string> attribs; if (ir.check("<a ") && ir.parseAttributes(attribs, '"') > 0) { - map<string,string>::iterator it; + unordered_map<string,string>::iterator it; if ((it = attribs.find("name")) != attribs.end()) - preprocessNameAnchor(it->second, actions); + HyperlinkManager::instance().addNameAchor(it->second, actions.getCurrentPageNumber()); else if ((it = attribs.find("href")) != attribs.end()) - preprocessHrefAnchor(it->second); - } -} - - -void HtmlSpecialHandler::preprocessNameAnchor (const string &name, SpecialActions &actions) { - NamedAnchors::iterator it = _namedAnchors.find(name); - if (it == _namedAnchors.end()) { // anchor completely undefined? - int id = static_cast<int>(_namedAnchors.size())+1; - _namedAnchors[name] = NamedAnchor(actions.getCurrentPageNumber(), id, 0); - } - else if (it->second.id < 0) { // anchor referenced but not defined yet? - it->second.id *= -1; - it->second.pageno = actions.getCurrentPageNumber(); - } - else - Message::wstream(true) << "named hyperref anchor '" << name << "' redefined\n"; -} - - -void HtmlSpecialHandler::preprocessHrefAnchor (const string &uri) { - if (uri[0] != '#') - return; - string name = uri.substr(1); - NamedAnchors::iterator it = _namedAnchors.find(name); - if (it != _namedAnchors.end()) // anchor already defined? - it->second.referenced = true; - else { - int id = static_cast<int>(_namedAnchors.size())+1; - _namedAnchors[name] = NamedAnchor(0, -id, 0, true); + HyperlinkManager::instance().addHrefAnchor(it->second); } } @@ -84,218 +45,42 @@ bool HtmlSpecialHandler::process (const char *, istream &is, SpecialActions &act _active = true; StreamInputReader ir(is); ir.skipSpace(); - map<string,string> attribs; - map<string,string>::iterator it; + unordered_map<string,string> attribs; + unordered_map<string,string>::iterator it; if (ir.check("<a ") && ir.parseAttributes(attribs, '"') > 0) { if ((it = attribs.find("href")) != attribs.end()) // <a href="URI"> - processHrefAnchor(it->second, actions); + HyperlinkManager::instance().createLink(it->second, actions); else if ((it = attribs.find("name")) != attribs.end()) // <a name="ID"> - processNameAnchor(it->second, actions); + HyperlinkManager::instance().setActiveNameAnchor(it->second, actions); else return false; // none or only invalid attributes } else if (ir.check("</a>")) - closeAnchor(actions); + HyperlinkManager::instance().closeAnchor(actions); else if (ir.check("<img src=")) { } else if (ir.check("<base ") && ir.parseAttributes(attribs, '"') > 0 && (it = attribs.find("href")) != attribs.end()) - _base = it->second; + HyperlinkManager::instance().setBaseUrl(it->second); return true; } -/** Handles anchors with href attribute: <a href="URI">...</a> - * @param uri value of href attribute */ -void HtmlSpecialHandler::processHrefAnchor (string uri, SpecialActions &actions) { - closeAnchor(actions); - string name; - if (uri[0] == '#') { // reference to named anchor? - name = uri.substr(1); - NamedAnchors::iterator it = _namedAnchors.find(name); - if (it == _namedAnchors.end() || it->second.id < 0) - Message::wstream(true) << "reference to undefined anchor '" << name << "'\n"; - else { - int id = it->second.id; - uri = "#loc"+XMLString(id); - if (actions.getCurrentPageNumber() != it->second.pageno) { - ostringstream oss; - oss << actions.getSVGFilename(it->second.pageno) << uri; - uri = oss.str(); - } - } - } - if (!_base.empty() && uri.find("://") != string::npos) { - if (*_base.rbegin() != '/' && uri[0] != '/' && uri[0] != '#') - uri = "/" + uri; - uri = _base + uri; - } - XMLElementNode *anchor = new XMLElementNode("a"); - anchor->addAttribute("xlink:href", uri); - anchor->addAttribute("xlink:title", XMLString(name.empty() ? uri : name, false)); - actions.pushContextElement(anchor); - actions.bbox("{anchor}", true); // start computing the bounding box of the linked area - _depthThreshold = actions.getDVIStackDepth(); - _anchorType = AnchorType::HREF; -} - - -/** Handles anchors with name attribute: <a name="NAME">...</a> - * @param name value of name attribute */ -void HtmlSpecialHandler::processNameAnchor (const string &name, SpecialActions &actions) { - closeAnchor(actions); - NamedAnchors::iterator it = _namedAnchors.find(name); - assert(it != _namedAnchors.end()); - it->second.pos = actions.getY(); - _anchorType = AnchorType::NAME; -} - - -/** Handles the closing tag (</a> of the current anchor element. */ -void HtmlSpecialHandler::closeAnchor (SpecialActions &actions) { - if (_anchorType == AnchorType::HREF) { - markLinkedBox(actions); - actions.popContextElement(); - _depthThreshold = 0; - } - _anchorType = AnchorType::NONE; -} - - -/** Marks a single rectangular area of the linked part of the document with a line or - * a box so that it's noticeable by the user. Additionally, an invisible rectangle is - * placed over this area in order to avoid flickering of the mouse cursor when moving - * it over the hyperlinked area. */ -void HtmlSpecialHandler::markLinkedBox (SpecialActions &actions) { - const BoundingBox &bbox = actions.bbox("{anchor}"); - if (bbox.width() > 0 && bbox.height() > 0) { // does the bounding box extend in both dimensions? - if (MARKER_TYPE != MarkerType::NONE) { - const double linewidth = min(0.5, bbox.height()/15); - XMLElementNode *rect = new XMLElementNode("rect"); - double x = bbox.minX(); - double y = bbox.maxY()+linewidth; - double w = bbox.width(); - double h = linewidth; - const Color &linecolor = USE_LINECOLOR ? LINK_LINECOLOR : actions.getColor(); - if (MARKER_TYPE == MarkerType::LINE) - rect->addAttribute("fill", linecolor.svgColorString()); - else { - x -= linewidth; - y = bbox.minY()-linewidth; - w += 2*linewidth; - h += bbox.height()+linewidth; - if (MARKER_TYPE == MarkerType::BGCOLOR) { - rect->addAttribute("fill", LINK_BGCOLOR.svgColorString()); - if (USE_LINECOLOR) { - rect->addAttribute("stroke", linecolor.svgColorString()); - rect->addAttribute("stroke-width", linewidth); - } - } - else { // LM_BOX - rect->addAttribute("fill", "none"); - rect->addAttribute("stroke", linecolor.svgColorString()); - rect->addAttribute("stroke-width", linewidth); - } - } - rect->addAttribute("x", x); - rect->addAttribute("y", y); - rect->addAttribute("width", w); - rect->addAttribute("height", h); - actions.prependToPage(rect); - if (MARKER_TYPE == MarkerType::BOX || MARKER_TYPE == MarkerType::BGCOLOR) { - // slightly enlarge the boxed area - x -= linewidth; - y -= linewidth; - w += 2*linewidth; - h += 2*linewidth; - } - actions.embed(BoundingBox(x, y, x+w, y+h)); - } - // Create an invisible rectangle around the linked area so that it's easier to access. - // This is only necessary when using paths rather than real text elements together with fonts. - if (!SVGTree::USE_FONTS) { - XMLElementNode *rect = new XMLElementNode("rect"); - rect->addAttribute("x", bbox.minX()); - rect->addAttribute("y", bbox.minY()); - rect->addAttribute("width", bbox.width()); - rect->addAttribute("height", bbox.height()); - rect->addAttribute("fill", "white"); - rect->addAttribute("fill-opacity", 0); - actions.appendToPage(rect); - } - } -} - - /** This method is called every time the DVI position changes. */ void HtmlSpecialHandler::dviMovedTo (double x, double y, SpecialActions &actions) { - if (_active && _anchorType != AnchorType::NONE) { - // Start a new box if the current depth of the DVI stack underruns - // the initial threshold which indicates a line break. - if (actions.getDVIStackDepth() < _depthThreshold) { - markLinkedBox(actions); - _depthThreshold = actions.getDVIStackDepth(); - actions.bbox("{anchor}", true); // start a new box on the new line - } - } + if (_active) + HyperlinkManager::instance().checkNewLine(actions); } void HtmlSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) { if (_active) { - // create views for all collected named anchors defined on the recent page - const BoundingBox &pagebox = actions.bbox(); - for (auto &stranchorpair : _namedAnchors) { - if (stranchorpair.second.pageno == pageno && stranchorpair.second.referenced) { // current anchor referenced? - ostringstream oss; - oss << pagebox.minX() << ' ' << stranchorpair.second.pos << ' ' - << pagebox.width() << ' ' << pagebox.height(); - XMLElementNode *view = new XMLElementNode("view"); - view->addAttribute("id", "loc"+XMLString(stranchorpair.second.id)); - view->addAttribute("viewBox", oss.str()); - actions.appendToDefs(view); - } - } - closeAnchor(actions); + HyperlinkManager::instance().createViews(pageno, actions); _active = false; } } -/** Sets the appearance of the link markers. - * @param[in] marker string specifying the marker (format: type[:linecolor]) - * @return true on success */ -bool HtmlSpecialHandler::setLinkMarker (const string &marker) { - string type; // "none", "box", "line", or a background color specifier - string color; // optional line color specifier - size_t seppos = marker.find(":"); - if (seppos == string::npos) - type = marker; - else { - type = marker.substr(0, seppos); - color = marker.substr(seppos+1); - } - if (type.empty() || type == "none") - MARKER_TYPE = MarkerType::NONE; - else if (type == "line") - MARKER_TYPE = MarkerType::LINE; - else if (type == "box") - MARKER_TYPE = MarkerType::BOX; - else { - if (!LINK_BGCOLOR.setPSName(type, false)) - return false; - MARKER_TYPE = MarkerType::BGCOLOR; - } - USE_LINECOLOR = false; - if (MARKER_TYPE != MarkerType::NONE && !color.empty()) { - if (!LINK_LINECOLOR.setPSName(color, false)) - return false; - USE_LINECOLOR = true; - } - return true; -} - - -const char** HtmlSpecialHandler::prefixes () const { - static const char *pfx[] = {"html:", 0}; +const vector<const char*> HtmlSpecialHandler::prefixes () const { + const vector<const char*> pfx {"html:"}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.hpp index 6d64a93b879..125f69192fd 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.hpp @@ -2,7 +2,7 @@ ** HtmlSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,59 +21,28 @@ #ifndef HTMLSPECIALHANDLER_HPP #define HTMLSPECIALHANDLER_HPP -#include <map> #include <string> +#include <unordered_map> #include "Color.hpp" #include "SpecialHandler.hpp" class SpecialActions; -class HtmlSpecialHandler : public SpecialHandler, public DVIEndPageListener, public DVIPositionListener -{ - struct NamedAnchor { - NamedAnchor () : pageno(0), id(0), pos(0), referenced(false) {} - NamedAnchor (unsigned pn, int i, double p, bool r=false) : pageno(pn), id(i), pos(p), referenced(r) {} - unsigned pageno; ///< page number where the anchor is located - int id; ///< unique numerical ID (< 0 if anchor is undefined yet) - double pos; ///< vertical position of named anchor (in PS point units) - bool referenced; ///< true if a reference to this anchor exists - }; - - enum class AnchorType {NONE, HREF, NAME}; - typedef std::map<std::string, NamedAnchor> NamedAnchors; - +class HtmlSpecialHandler : public SpecialHandler, public DVIEndPageListener, public DVIPositionListener { public: - HtmlSpecialHandler () : _active(false), _anchorType(AnchorType::NONE), _depthThreshold(0) {} + HtmlSpecialHandler () : _active(false) {} void preprocess (const char *prefix, std::istream &is, SpecialActions &actions) override; bool process (const char *prefix, std::istream &is, SpecialActions &actions) override; const char* name () const override {return "html";} const char* info () const override {return "hyperref specials";} - const char** prefixes () const override; - - static bool setLinkMarker (const std::string &marker); + const std::vector<const char*> prefixes () const override; protected: - void preprocessHrefAnchor (const std::string &uri); - void preprocessNameAnchor (const std::string &name, SpecialActions &actions); - void processHrefAnchor (std::string uri, SpecialActions &actions); - void processNameAnchor (const std::string &name, SpecialActions &actions); void dviEndPage (unsigned pageno, SpecialActions &actions) override; void dviMovedTo (double x, double y, SpecialActions &actions) override; - void closeAnchor (SpecialActions &actions); - void markLinkedBox (SpecialActions &actions); - - enum class MarkerType {NONE, LINE, BOX, BGCOLOR}; - static MarkerType MARKER_TYPE; ///< selects how to mark linked areas - static Color LINK_BGCOLOR; ///< background color if linkmark type == LT_BGCOLOR - static Color LINK_LINECOLOR; ///< line color if linkmark type is LM_LINE or LM_BOX - static bool USE_LINECOLOR; ///< if true, LINK_LINECOLOR is applied private: bool _active; - AnchorType _anchorType; ///< type of active anchor - int _depthThreshold; ///< break anchor box if the DVI stack depth underruns this threshold - std::string _base; ///< base URL that is prepended to all relative targets - NamedAnchors _namedAnchors; ///< information about all named anchors processed }; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.cpp new file mode 100644 index 00000000000..1c41c22a5db --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.cpp @@ -0,0 +1,265 @@ +/************************************************************************* +** HyperlinkManager.cpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#include <sstream> +#include "HyperlinkManager.hpp" +#include "Message.hpp" +#include "SpecialActions.hpp" +#include "SVGTree.hpp" +#include "utility.hpp" +#include "XMLNode.hpp" + +using namespace std; + +// variable to select the link marker variant (none, underlined, boxed, or colored background) +HyperlinkManager::MarkerType HyperlinkManager::MARKER_TYPE = MarkerType::LINE; +Color HyperlinkManager::LINK_BGCOLOR; +Color HyperlinkManager::LINK_LINECOLOR; +HyperlinkManager::ColorSource HyperlinkManager::COLORSOURCE = ColorSource::DEFAULT; + + +HyperlinkManager& HyperlinkManager::instance () { + static HyperlinkManager instance; + return instance; +} + + +void HyperlinkManager::addHrefAnchor (const string &uri) { + if (uri.empty() || uri[0] != '#') + return; + string name = uri.substr(1); + auto it = _namedAnchors.find(name); + if (it != _namedAnchors.end()) // anchor already defined? + it->second.referenced = true; + else { + int id = static_cast<int>(_namedAnchors.size())+1; + _namedAnchors.emplace(name, NamedAnchor(0, -id, 0, true)); + } +} + + +void HyperlinkManager::addNameAchor (const string &name, int pageno) { + if (name.empty()) + return; + auto it = _namedAnchors.find(name); + if (it == _namedAnchors.end()) { // anchor completely undefined? + int id = static_cast<int>(_namedAnchors.size())+1; + _namedAnchors.emplace(name, NamedAnchor(pageno, id, 0)); + } + else if (it->second.id >= 0) // anchor already defined? + Message::wstream(true) << "named hyperref anchor '" << name << "' redefined\n"; + else { + // anchor referenced but not defined yet? + it->second.id *= -1; + it->second.pageno = pageno; + } +} + + +void HyperlinkManager::setActiveNameAnchor (const string &name, SpecialActions &actions) { + auto it = _namedAnchors.find(name); + if (it != _namedAnchors.end()) { + closeAnchor(actions); + it->second.pos = actions.getY(); + _anchorType = AnchorType::NAME; + } +} + + +void HyperlinkManager::createLink (string uri, SpecialActions &actions) { + closeAnchor(actions); + string name; + if (uri[0] == '#') { // reference to named anchor? + name = uri.substr(1); + NamedAnchors::iterator it = _namedAnchors.find(name); + if (it == _namedAnchors.end() || it->second.id < 0) + Message::wstream(true) << "reference to undefined anchor '" << name << "'\n"; + else { + int id = it->second.id; + uri = "#loc"+XMLString(id); + if (actions.getCurrentPageNumber() != it->second.pageno) { + ostringstream oss; + oss << actions.getSVGFilename(it->second.pageno) << uri; + uri = oss.str(); + } + } + } + if (!_base.empty() && uri.find("://") != string::npos) { + if (*_base.rbegin() != '/' && uri[0] != '/' && uri[0] != '#') + uri = "/" + uri; + uri = _base + uri; + } + auto anchorNode = util::make_unique<XMLElementNode>("a"); + anchorNode->addAttribute("xlink:href", uri); + anchorNode->addAttribute("xlink:title", XMLString(name.empty() ? uri : name, false)); + actions.pushContextElement(std::move(anchorNode)); + actions.bbox("{anchor}", true); // start computing the bounding box of the linked area + _depthThreshold = actions.getDVIStackDepth(); + _anchorType = AnchorType::HREF; +} + + +void HyperlinkManager::closeAnchor (SpecialActions &actions) { + if (_anchorType == AnchorType::HREF) { + markLinkedBox(actions); + actions.popContextElement(); + _depthThreshold = 0; + } + _anchorType = AnchorType::NONE; +} + + +void HyperlinkManager::checkNewLine (SpecialActions &actions) { + if (_anchorType == AnchorType::NONE) + return; + // Start a new box if the current depth of the DVI stack underruns + // the initial threshold which indicates a line break. + if (actions.getDVIStackDepth() < _depthThreshold) { + markLinkedBox(actions); + _depthThreshold = actions.getDVIStackDepth(); + actions.bbox("{anchor}", true); // start a new box on the new line + } +} + + +/** Marks a single rectangular area of the linked part of the document with a line or + * a box so that it's noticeable by the user. Additionally, an invisible rectangle is + * placed over this area in order to avoid flickering of the mouse cursor when moving + * it over the hyperlinked area. */ +void HyperlinkManager::markLinkedBox (SpecialActions &actions) { + const BoundingBox &bbox = actions.bbox("{anchor}"); + if (bbox.width() > 0 && bbox.height() > 0) { // does the bounding box extend in both dimensions? + if (MARKER_TYPE != MarkerType::NONE) { + const double linewidth = _linewidth >= 0 ? _linewidth : min(0.5, bbox.height()/15); + auto rect = util::make_unique<XMLElementNode>("rect"); + double x = bbox.minX(); + double y = bbox.maxY()+linewidth; + double w = bbox.width(); + double h = linewidth; + const Color linecolor = COLORSOURCE == ColorSource::DEFAULT ? actions.getColor() : LINK_LINECOLOR; + if (MARKER_TYPE == MarkerType::LINE) + rect->addAttribute("fill", linecolor.svgColorString()); + else { + const double offset = _linewidth < 0 ? linewidth : 0 ; + x -= offset; + y = bbox.minY()-offset; + w += 2*offset; + h += bbox.height()+offset; + if (MARKER_TYPE == MarkerType::BGCOLOR) { + rect->addAttribute("fill", LINK_BGCOLOR.svgColorString()); + if (COLORSOURCE != ColorSource::DEFAULT) { + rect->addAttribute("stroke", linecolor.svgColorString()); + rect->addAttribute("stroke-width", linewidth); + } + } + else { // LM_BOX + rect->addAttribute("fill", "none"); + rect->addAttribute("stroke", linecolor.svgColorString()); + rect->addAttribute("stroke-width", linewidth); + } + } + rect->addAttribute("x", x); + rect->addAttribute("y", y); + rect->addAttribute("width", w); + rect->addAttribute("height", h); + actions.prependToPage(std::move(rect)); + if (MARKER_TYPE == MarkerType::BOX || MARKER_TYPE == MarkerType::BGCOLOR) { + // slightly enlarge the boxed area + x -= linewidth; + y -= linewidth; + w += 2*linewidth; + h += 2*linewidth; + } + actions.embed(BoundingBox(x, y, x+w, y+h)); + } + // Create an invisible rectangle around the linked area so that it's easier to access. + // This is only necessary when using paths rather than real text elements together with fonts. + if (!SVGTree::USE_FONTS) { + auto rect = util::make_unique<XMLElementNode>("rect"); + rect->addAttribute("x", bbox.minX()); + rect->addAttribute("y", bbox.minY()); + rect->addAttribute("width", bbox.width()); + rect->addAttribute("height", bbox.height()); + rect->addAttribute("fill", "white"); + rect->addAttribute("fill-opacity", 0); + actions.appendToPage(std::move(rect)); + } + } +} + + +// Creates SVG views for all collected named anchors defined on a given page. +void HyperlinkManager::createViews (unsigned pageno, SpecialActions &actions) { + const BoundingBox &pagebox = actions.bbox(); + for (auto &stranchorpair : _namedAnchors) { + if (stranchorpair.second.pageno == pageno && stranchorpair.second.referenced) { // current anchor referenced? + ostringstream oss; + oss << pagebox.minX() << ' ' << stranchorpair.second.pos << ' ' + << pagebox.width() << ' ' << pagebox.height(); + auto view = util::make_unique<XMLElementNode>("view"); + view->addAttribute("id", "loc"+XMLString(stranchorpair.second.id)); + view->addAttribute("viewBox", oss.str()); + actions.appendToDefs(std::move(view)); + } + } + closeAnchor(actions); +} + + +/** Sets the appearance of the link markers. + * @param[in] marker string specifying the marker (format: type[:linecolor]) + * @return true on success */ +bool HyperlinkManager::setLinkMarker (const string &marker) { + string type; // "none", "box", "line", or a background color specifier + string color; // optional line color specifier + size_t seppos = marker.find(":"); + if (seppos == string::npos) + type = marker; + else { + type = marker.substr(0, seppos); + color = marker.substr(seppos+1); + } + if (type.empty() || type == "none") + MARKER_TYPE = MarkerType::NONE; + else if (type == "line") + MARKER_TYPE = MarkerType::LINE; + else if (type == "box") + MARKER_TYPE = MarkerType::BOX; + else { + if (!LINK_BGCOLOR.setPSName(type, false)) + return false; + MARKER_TYPE = MarkerType::BGCOLOR; + } + COLORSOURCE = ColorSource::DEFAULT; + if (MARKER_TYPE != MarkerType::NONE && !color.empty()) { + if (!LINK_LINECOLOR.setPSName(color, false)) + return false; + COLORSOURCE = ColorSource::LINKMARKER; + } + return true; +} + + +void HyperlinkManager::setDefaultLinkColor (Color color) { + if (COLORSOURCE != ColorSource::LINKMARKER) { + COLORSOURCE = ColorSource::STATIC; + LINK_LINECOLOR = color; + } +}
\ No newline at end of file diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.hpp new file mode 100644 index 00000000000..2b4f9cb1420 --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.hpp @@ -0,0 +1,79 @@ +/************************************************************************* +** HyperlinkManager.hpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#ifndef HYPERLINKMANAGER_HPP +#define HYPERLINKMANAGER_HPP + +#include <string> +#include <unordered_map> +#include "Color.hpp" +#include "SpecialActions.hpp" + +class SpecialActions; + +class HyperlinkManager { + struct NamedAnchor { + NamedAnchor () : pageno(0), id(0), pos(0), referenced(false) {} + NamedAnchor (unsigned pn, int i, double p, bool r=false) : pageno(pn), id(i), pos(p), referenced(r) {} + unsigned pageno; ///< page number where the anchor is located + int id; ///< unique numerical ID (< 0 if anchor is undefined yet) + double pos; ///< vertical position of named anchor (in PS point units) + bool referenced; ///< true if a reference to this anchor exists + }; + + enum class AnchorType {NONE, HREF, NAME}; + enum class ColorSource {DEFAULT, LINKMARKER, STATIC}; + using NamedAnchors = std::unordered_map<std::string, NamedAnchor>; + + public: + HyperlinkManager (const HyperlinkManager&) =delete; + HyperlinkManager (HyperlinkManager&&) =delete; + void addHrefAnchor (const std::string &uri); + void addNameAchor (const std::string &name, int pageno); + void setActiveNameAnchor (const std::string &name, SpecialActions &actions); + void closeAnchor (SpecialActions &actions); + void checkNewLine (SpecialActions &actions); + void createLink (std::string uri, SpecialActions &actions); + void createViews (unsigned pageno, SpecialActions &actions); + void setBaseUrl (std::string &base) {_base = base;} + void setLineWidth (double w) {_linewidth = w;} + static HyperlinkManager& instance (); + static bool setLinkMarker (const std::string &marker); + static void setDefaultLinkColor (Color color); + + protected: + HyperlinkManager () : _anchorType(AnchorType::NONE), _depthThreshold(0), _linewidth(-1) {} + void markLinkedBox (SpecialActions &actions); + + enum class MarkerType {NONE, LINE, BOX, BGCOLOR}; + static MarkerType MARKER_TYPE; ///< selects how to mark linked areas + static Color LINK_BGCOLOR; ///< background color if linkmark type == LT_BGCOLOR + static Color LINK_LINECOLOR; ///< line color if linkmark type is LM_LINE or LM_BOX + static ColorSource COLORSOURCE; ///< if true, LINK_LINECOLOR is applied + + private: + AnchorType _anchorType; ///< type of active anchor + int _depthThreshold; ///< break anchor box if the DVI stack depth underruns this threshold + double _linewidth; ///< line width of link marker (-1 => compute individual value per link) + std::string _base; ///< base URL that is prepended to all relative targets + NamedAnchors _namedAnchors; ///< information about all named anchors processed +}; + +#endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.cpp index 53d7eeee9d0..a89d95462f5 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.cpp @@ -2,7 +2,7 @@ ** InputBuffer.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cmath> #include <cstring> #include "InputBuffer.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp index 2509997d05c..4ee43615517 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp @@ -2,7 +2,7 @@ ** InputBuffer.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp index 6b4cd500343..99f7bfe35f9 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp @@ -2,7 +2,7 @@ ** InputReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,15 +18,46 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cmath> #include <functional> -#include <vector> #include "InputReader.hpp" using namespace std; +void StringMatcher::setPattern (const string &pattern) { + _pattern = pattern; + _charsRead = 0; + _borders.resize(pattern.length()+1); + // preprocessing to set up the border indexes + _borders[0] = -1; + int i=0, j=-1; + const int len = static_cast<int>(pattern.length()); + while (i < len) { + while (j >= 0 && _pattern[i] != _pattern[j]) + j = _borders[j]; + _borders[++i] = ++j; + } +} + + +bool StringMatcher::match (InputReader &ir) { + _charsRead = 0; + int c; + int i=0; + const int len = static_cast<int>(_pattern.length()); + while ((c = ir.get()) >= 0) { + _charsRead++; + while (i >= 0 && c != _pattern[i]) + i = _borders[i]; + if (++i == len) + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////// + /** Skips n characters. */ void InputReader::skip (size_t n) { while (n-- > 0) @@ -43,14 +74,11 @@ void InputReader::skipSpace () { /** Tries to find a given string and skips all characters preceding that string. - * @param[in] s string to look for (must not be longer than the maximal buffer size) - * @param[in] consume if true, the buffer pointer is moved to the first character following string s + * @param[in] str string to look for (must not be longer than the maximal buffer size) * @return true if s was found */ -bool InputReader::skipUntil (const char *s, bool consume) { - bool found = false; - while (!eof() && !(found = check(s, consume))) - get(); - return found; +bool InputReader::skipUntil (const char *str) { + StringMatcher matcher(str); + return matcher.match(*this); } @@ -82,22 +110,6 @@ bool InputReader::check (const char *s, bool consume) { } -int InputReader::compare (const char *s, bool consume) { - size_t count = 0; - for (const char *p=s; *p; p++) { - int c = peek(count++); - if (c != *p) - return c < *p ? -1 : 1; - } - int c = peek(count); - if (c < 0 || !isspace(c)) - return 1; - if (consume) - skip(count); - return 0; -} - - /** Reads an integer from the buffer. All characters that are part of * the read integer constant are skipped. If this function returns false, * the buffer pointer points to the same position as before the function call. @@ -298,6 +310,20 @@ string InputReader::getString (size_t n) { } +/** Reads a string delimited by EOF or a single character from a given set of characters. + * @param[in] delim characters delimiting the string + * @return the read string */ +string InputReader::getString (const char *delim) { + if (!delim || !delim[0]) + return getString(); + string ret; + skipSpace(); + while (!eof() && peek() > 0 && !strchr(delim, peek())) + ret += get(); + return ret; +} + + string InputReader::getLine () { string ret; skipSpace(); @@ -313,7 +339,7 @@ string InputReader::getLine () { * @param[out] attr the scanned atributes * @param[in] quotechar quote character used to enclose the attribute values * @return number of attributes scanned */ -int InputReader::parseAttributes (map<string,string> &attr, char quotechar) { +int InputReader::parseAttributes (unordered_map<string,string> &attr, char quotechar) { bool ready=false; while (!eof() && !ready) { string key; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp index 0780da028dd..037cf8b4365 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp @@ -2,7 +2,7 @@ ** InputReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,13 +22,12 @@ #define INPUTREADER_HPP #include <istream> -#include <map> #include <string> +#include <unordered_map> +#include <vector> #include "InputBuffer.hpp" - -class InputReader -{ +class InputReader { public: virtual ~InputReader() =default; virtual int get () =0; @@ -37,9 +36,8 @@ class InputReader virtual bool eof () const =0; virtual bool check (char c) const {return peek() == c;} virtual bool check (const char *s, bool consume=true); - virtual int compare (const char *s, bool consume=true); virtual void skip (size_t n); - virtual bool skipUntil (const char *s, bool consume=true); + virtual bool skipUntil (const char *s); virtual int find (char c) const; virtual void skipSpace (); virtual int getInt (); @@ -53,28 +51,28 @@ class InputReader virtual std::string getQuotedString (char quotechar); virtual std::string getString (); virtual std::string getString (size_t n); + virtual std::string getString (const char *delim); virtual std::string getLine (); - virtual int parseAttributes (std::map<std::string,std::string> &attr, char quotechar=0); + virtual int parseAttributes (std::unordered_map<std::string,std::string> &attr, char quotechar=0); virtual operator bool () const {return !eof();} }; -class StreamInputReader : public InputReader -{ +class StreamInputReader : public InputReader { public: StreamInputReader (std::istream &is) : _is(is) {} int get () override {return _is.get();} int peek () const override {return _is.peek();} int peek (size_t n) const override; bool eof () const override {return !_is || _is.eof();} + std::istream& getStream () {return _is;} private: std::istream &_is; }; -class BufferInputReader : public InputReader -{ +class BufferInputReader : public InputReader { public: BufferInputReader (InputBuffer &ib) : _ib(&ib) {} void assign (InputBuffer &ib) {_ib = &ib;} @@ -87,4 +85,21 @@ class BufferInputReader : public InputReader InputBuffer *_ib; }; + +/** Implementation of the Knuth-Morris-Pratt search algorithm. + * http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm */ +class StringMatcher { + public: + StringMatcher () : _charsRead(0) {} + StringMatcher (const std::string &pattern) : _charsRead(0) {setPattern(pattern);} + void setPattern (const std::string &pattern); + bool match (InputReader &ir); + size_t charsRead () const {return _charsRead;} + + private: + std::string _pattern; + std::vector<size_t> _borders; + size_t _charsRead; +}; + #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp index 9946e7cc26a..2291ca83ec1 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp @@ -2,7 +2,7 @@ ** JFM.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <cstring> #include <fstream> diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp index e267b29def3..908ad7a1c14 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp @@ -2,7 +2,7 @@ ** JFM.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp index 7b8b84814fd..f4c9d6638d0 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp @@ -2,7 +2,7 @@ ** Length.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp index 8c05ae49834..f606dab4549 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp @@ -2,7 +2,7 @@ ** Length.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -28,20 +28,19 @@ #undef IN #endif -struct UnitException : MessageException -{ +struct UnitException : MessageException { UnitException (const std::string &msg) : MessageException(msg) {} }; -class Length -{ +class Length { public: enum class Unit {PT, BP, CM, MM, IN, PC, DD, CC, SP}; public: - Length () : _pt(0) {} - Length (double val, Unit unit=Unit::PT) {set(val, unit);} + constexpr Length () : _pt(0) {} + constexpr Length (long double pt) : _pt(static_cast<double>(pt)) {} + Length (double val, Unit unit) {set(val, unit);} Length (double val, const std::string &unitstr) {set(val, unitstr);} Length (const std::string &lenstr) {set(lenstr);} void set (double val, Unit unit); @@ -76,4 +75,14 @@ class Length double _pt; // length in TeX point units (72.27pt = 1in) }; + +constexpr Length operator "" _pt (long double pt) {return Length(pt);} +constexpr Length operator "" _bp (long double bp) {return Length(bp/Length::pt2bp);} +constexpr Length operator "" _mm (long double mm) {return Length(mm/Length::pt2mm);} +constexpr Length operator "" _in (long double in) {return Length(in/Length::pt2in);} +constexpr Length operator "" _pt (unsigned long long pt) {return Length(static_cast<double>(pt));} +constexpr Length operator "" _bp (unsigned long long bp) {return Length(static_cast<double>(bp)/Length::pt2bp);} +constexpr Length operator "" _mm (unsigned long long mm) {return Length(static_cast<double>(mm)/Length::pt2mm);} +constexpr Length operator "" _in (unsigned long long in) {return Length(static_cast<double>(in)/Length::pt2in);} + #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am b/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am index 512f66dbb00..9d098904169 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am @@ -1,12 +1,14 @@ ## This file is part of dvisvgm -## Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> +## Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ## ## Process this file with automake. -bin_PROGRAMS = dvisvgm -noinst_LIBRARIES = libdvisvgm.a +bin_PROGRAMS = dvisvgm +noinst_LIBRARIES = libdvisvgm.a -dvisvgm_SOURCES = dvisvgm.cpp +dvisvgm_SOURCES = \ + CommandLine.hpp \ + dvisvgm.cpp dvisvgm_LDADD = \ $(noinst_LIBRARIES) \ @@ -17,7 +19,7 @@ if ENABLE_WOFF dvisvgm_LDADD += \ ../libs/ff-woff/libfontforge.a \ ../libs/woff2/libwoff2.a \ - ../libs/woff2/brotli/libbrotli.a + ../libs/brotli/libbrotli.a endif dvisvgm_LDADD += \ @@ -61,7 +63,6 @@ libdvisvgm_a_SOURCES = \ Color.hpp \ ColorSpecialHandler.cpp \ ColorSpecialHandler.hpp \ - CommandLine.hpp \ CRC32.cpp \ CRC32.hpp \ DependencyGraph.hpp \ @@ -123,6 +124,8 @@ libdvisvgm_a_SOURCES = \ GraphicsPath.hpp \ HtmlSpecialHandler.cpp \ HtmlSpecialHandler.hpp \ + HyperlinkManager.cpp \ + HyperlinkManager.hpp \ InputBuffer.cpp \ InputBuffer.hpp \ InputReader.cpp \ @@ -153,6 +156,8 @@ libdvisvgm_a_SOURCES = \ PapersizeSpecialHandler.hpp \ PathClipper.cpp \ PathClipper.hpp \ + PDFParser.cpp \ + PDFParser.hpp \ PdfSpecialHandler.cpp \ PdfSpecialHandler.hpp \ PreScanDVIReader.cpp \ @@ -213,6 +218,10 @@ libdvisvgm_a_SOURCES = \ TpicSpecialHandler.hpp \ TriangularPatch.cpp \ TriangularPatch.hpp \ + TrueTypeFont.cpp \ + TrueTypeFont.hpp \ + TTFAutohint.cpp \ + TTFAutohint.hpp \ Unicode.cpp \ Unicode.hpp \ utility.hpp \ @@ -223,6 +232,7 @@ libdvisvgm_a_SOURCES = \ VFActions.hpp \ VFReader.cpp \ VFReader.hpp \ + windows.hpp \ XMLDocument.cpp \ XMLDocument.hpp \ XMLNode.cpp \ @@ -245,16 +255,23 @@ AM_CFLAGS = $(WARNING_CFLAGS) \ AM_CXXFLAGS = $(WARNING_CFLAGS) -Wnon-virtual-dtor \ -I$(dvisvgm_srcdir)/libs/clipper \ + -I$(dvisvgm_srcdir)/libs/variant/include \ -I$(dvisvgm_srcdir)/libs/xxHash +AM_LDFLAGS = \ + $(CODE_COVERAGE_LDFLAGS) + if ENABLE_WOFF AM_CFLAGS += \ -I$(dvisvgm_srcdir)/libs/ff-woff/fontforge \ -I$(dvisvgm_srcdir)/libs/ff-woff/inc AM_CXXFLAGS += \ - -I$(dvisvgm_srcdir)/libs/woff2/brotli/enc \ - -I$(dvisvgm_srcdir)/libs/woff2/src + $(TTFAUTOHINT_CFLAGS) \ + -I$(dvisvgm_srcdir)/libs/brotli/include \ + -I$(dvisvgm_srcdir)/libs/woff2/include + +AM_LDFLAGS += $(TTFAUTOHINT_LIBS) endif AM_CXXFLAGS += \ @@ -269,13 +286,11 @@ if WIN32 AM_CXXFLAGS += -DTEXLIVEWIN32 endif WIN32 -AM_LDFLAGS = $(CODE_COVERAGE_LDFLAGS) - if ! TEXLIVE_BUILD # TL: do not try to rebuild these source files. # the command-line parser class is generated from options.xml by opt2cpp $(srcdir)/CommandLine.hpp: options.xml - rm -f $@ $*.hpp + rm -f $@ python $(srcdir)/opt2cpp.py $< >$@ # Create a C string definition containing the PostScript routines psdefs.ps needed by class PSInterpreter diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in b/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in index 5a8296297ff..dfaa9fb0896 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in @@ -93,7 +93,7 @@ bin_PROGRAMS = dvisvgm$(EXEEXT) @ENABLE_WOFF_TRUE@am__append_1 = \ @ENABLE_WOFF_TRUE@ ../libs/ff-woff/libfontforge.a \ @ENABLE_WOFF_TRUE@ ../libs/woff2/libwoff2.a \ -@ENABLE_WOFF_TRUE@ ../libs/woff2/brotli/libbrotli.a +@ENABLE_WOFF_TRUE@ ../libs/brotli/libbrotli.a @ENABLE_WOFF_TRUE@am__append_2 = ffwrapper.c ffwrapper.h @ENABLE_WOFF_TRUE@am__append_3 = \ @@ -101,10 +101,12 @@ bin_PROGRAMS = dvisvgm$(EXEEXT) @ENABLE_WOFF_TRUE@ -I$(dvisvgm_srcdir)/libs/ff-woff/inc @ENABLE_WOFF_TRUE@am__append_4 = \ -@ENABLE_WOFF_TRUE@ -I$(dvisvgm_srcdir)/libs/woff2/brotli/enc \ -@ENABLE_WOFF_TRUE@ -I$(dvisvgm_srcdir)/libs/woff2/src +@ENABLE_WOFF_TRUE@ $(TTFAUTOHINT_CFLAGS) \ +@ENABLE_WOFF_TRUE@ -I$(dvisvgm_srcdir)/libs/brotli/include \ +@ENABLE_WOFF_TRUE@ -I$(dvisvgm_srcdir)/libs/woff2/include -@WIN32_TRUE@am__append_5 = -DTEXLIVEWIN32 +@ENABLE_WOFF_TRUE@am__append_5 = $(TTFAUTOHINT_LIBS) +@WIN32_TRUE@am__append_6 = -DTEXLIVEWIN32 subdir = dvisvgm-src/src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../../m4/ax_cxx_compile_stdcxx.m4 \ @@ -145,7 +147,7 @@ am__libdvisvgm_a_SOURCES_DIST = AGLTable.hpp BasicDVIReader.cpp \ CLCommandLine.cpp CLCommandLine.hpp CLOption.hpp CMap.cpp \ CMap.hpp CMapManager.cpp CMapManager.hpp CMapReader.cpp \ CMapReader.hpp Color.cpp Color.hpp ColorSpecialHandler.cpp \ - ColorSpecialHandler.hpp CommandLine.hpp CRC32.cpp CRC32.hpp \ + ColorSpecialHandler.hpp CRC32.cpp CRC32.hpp \ DependencyGraph.hpp Directory.cpp Directory.hpp DLLoader.cpp \ DLLoader.hpp DVIActions.hpp DVIReader.cpp DVIReader.hpp \ DvisvgmSpecialHandler.cpp DvisvgmSpecialHandler.hpp \ @@ -161,7 +163,8 @@ am__libdvisvgm_a_SOURCES_DIST = AGLTable.hpp BasicDVIReader.cpp \ GFGlyphTracer.cpp GFGlyphTracer.hpp GFReader.cpp GFReader.hpp \ GFTracer.cpp GFTracer.hpp Ghostscript.cpp Ghostscript.hpp \ Glyph.hpp GlyphTracerMessages.hpp GraphicsPath.hpp \ - HtmlSpecialHandler.cpp HtmlSpecialHandler.hpp InputBuffer.cpp \ + HtmlSpecialHandler.cpp HtmlSpecialHandler.hpp \ + HyperlinkManager.cpp HyperlinkManager.hpp InputBuffer.cpp \ InputBuffer.hpp InputReader.cpp InputReader.hpp JFM.cpp \ JFM.hpp Length.cpp Length.hpp macros.hpp MapLine.cpp \ MapLine.hpp Matrix.cpp Matrix.hpp Message.cpp Message.hpp \ @@ -170,32 +173,33 @@ am__libdvisvgm_a_SOURCES_DIST = AGLTable.hpp BasicDVIReader.cpp \ NumericRanges.hpp PageRanges.cpp PageRanges.hpp PageSize.cpp \ PageSize.hpp Pair.hpp PapersizeSpecialHandler.cpp \ PapersizeSpecialHandler.hpp PathClipper.cpp PathClipper.hpp \ - PdfSpecialHandler.cpp PdfSpecialHandler.hpp \ - PreScanDVIReader.cpp PreScanDVIReader.hpp Process.cpp \ - Process.hpp psdefs.cpp PSFilter.hpp PSInterpreter.cpp \ - PSInterpreter.hpp PSPattern.cpp PSPattern.hpp \ - PSPreviewFilter.cpp PSPreviewFilter.hpp PsSpecialHandler.cpp \ - PsSpecialHandler.hpp RangeMap.cpp RangeMap.hpp \ - ShadingPatch.cpp ShadingPatch.hpp SignalHandler.cpp \ - SignalHandler.hpp SpecialActions.hpp SpecialHandler.hpp \ - SpecialManager.cpp SpecialManager.hpp StreamReader.cpp \ - StreamReader.hpp StreamWriter.cpp StreamWriter.hpp Subfont.cpp \ - Subfont.hpp SVGCharHandler.cpp SVGCharHandler.hpp \ - SVGCharHandlerFactory.cpp SVGCharHandlerFactory.hpp \ - SVGCharPathHandler.cpp SVGCharPathHandler.hpp \ - SVGCharTspanTextHandler.cpp SVGCharTspanTextHandler.hpp \ - SVGOutput.cpp SVGOutput.hpp SVGSingleCharTextHandler.cpp \ - SVGSingleCharTextHandler.hpp SVGTree.cpp SVGTree.hpp \ - System.cpp System.hpp TensorProductPatch.cpp \ - TensorProductPatch.hpp Terminal.cpp Terminal.hpp TFM.cpp \ - TFM.hpp ToUnicodeMap.cpp ToUnicodeMap.hpp \ + PDFParser.cpp PDFParser.hpp PdfSpecialHandler.cpp \ + PdfSpecialHandler.hpp PreScanDVIReader.cpp \ + PreScanDVIReader.hpp Process.cpp Process.hpp psdefs.cpp \ + PSFilter.hpp PSInterpreter.cpp PSInterpreter.hpp PSPattern.cpp \ + PSPattern.hpp PSPreviewFilter.cpp PSPreviewFilter.hpp \ + PsSpecialHandler.cpp PsSpecialHandler.hpp RangeMap.cpp \ + RangeMap.hpp ShadingPatch.cpp ShadingPatch.hpp \ + SignalHandler.cpp SignalHandler.hpp SpecialActions.hpp \ + SpecialHandler.hpp SpecialManager.cpp SpecialManager.hpp \ + StreamReader.cpp StreamReader.hpp StreamWriter.cpp \ + StreamWriter.hpp Subfont.cpp Subfont.hpp SVGCharHandler.cpp \ + SVGCharHandler.hpp SVGCharHandlerFactory.cpp \ + SVGCharHandlerFactory.hpp SVGCharPathHandler.cpp \ + SVGCharPathHandler.hpp SVGCharTspanTextHandler.cpp \ + SVGCharTspanTextHandler.hpp SVGOutput.cpp SVGOutput.hpp \ + SVGSingleCharTextHandler.cpp SVGSingleCharTextHandler.hpp \ + SVGTree.cpp SVGTree.hpp System.cpp System.hpp \ + TensorProductPatch.cpp TensorProductPatch.hpp Terminal.cpp \ + Terminal.hpp TFM.cpp TFM.hpp ToUnicodeMap.cpp ToUnicodeMap.hpp \ TpicSpecialHandler.cpp TpicSpecialHandler.hpp \ - TriangularPatch.cpp TriangularPatch.hpp Unicode.cpp \ + TriangularPatch.cpp TriangularPatch.hpp TrueTypeFont.cpp \ + TrueTypeFont.hpp TTFAutohint.cpp TTFAutohint.hpp Unicode.cpp \ Unicode.hpp utility.hpp utility.cpp VectorIterator.hpp \ VectorStream.hpp version.hpp VFActions.hpp VFReader.cpp \ - VFReader.hpp XMLDocument.cpp XMLDocument.hpp XMLNode.cpp \ - XMLNode.hpp XMLString.cpp XMLString.hpp ZLibOutputStream.hpp \ - ffwrapper.c ffwrapper.h + VFReader.hpp windows.hpp XMLDocument.cpp XMLDocument.hpp \ + XMLNode.cpp XMLNode.hpp XMLString.cpp XMLString.hpp \ + ZLibOutputStream.hpp ffwrapper.c ffwrapper.h @ENABLE_WOFF_TRUE@am__objects_1 = ffwrapper.$(OBJEXT) am_libdvisvgm_a_OBJECTS = BasicDVIReader.$(OBJEXT) Bezier.$(OBJEXT) \ BgColorSpecialHandler.$(OBJEXT) Bitmap.$(OBJEXT) \ @@ -213,12 +217,13 @@ am_libdvisvgm_a_OBJECTS = BasicDVIReader.$(OBJEXT) Bezier.$(OBJEXT) \ FontMetrics.$(OBJEXT) FontWriter.$(OBJEXT) \ GFGlyphTracer.$(OBJEXT) GFReader.$(OBJEXT) GFTracer.$(OBJEXT) \ Ghostscript.$(OBJEXT) HtmlSpecialHandler.$(OBJEXT) \ - InputBuffer.$(OBJEXT) InputReader.$(OBJEXT) JFM.$(OBJEXT) \ - Length.$(OBJEXT) MapLine.$(OBJEXT) Matrix.$(OBJEXT) \ - Message.$(OBJEXT) MetafontWrapper.$(OBJEXT) \ - NoPsSpecialHandler.$(OBJEXT) PageRanges.$(OBJEXT) \ - PageSize.$(OBJEXT) PapersizeSpecialHandler.$(OBJEXT) \ - PathClipper.$(OBJEXT) PdfSpecialHandler.$(OBJEXT) \ + HyperlinkManager.$(OBJEXT) InputBuffer.$(OBJEXT) \ + InputReader.$(OBJEXT) JFM.$(OBJEXT) Length.$(OBJEXT) \ + MapLine.$(OBJEXT) Matrix.$(OBJEXT) Message.$(OBJEXT) \ + MetafontWrapper.$(OBJEXT) NoPsSpecialHandler.$(OBJEXT) \ + PageRanges.$(OBJEXT) PageSize.$(OBJEXT) \ + PapersizeSpecialHandler.$(OBJEXT) PathClipper.$(OBJEXT) \ + PDFParser.$(OBJEXT) PdfSpecialHandler.$(OBJEXT) \ PreScanDVIReader.$(OBJEXT) Process.$(OBJEXT) psdefs.$(OBJEXT) \ PSInterpreter.$(OBJEXT) PSPattern.$(OBJEXT) \ PSPreviewFilter.$(OBJEXT) PsSpecialHandler.$(OBJEXT) \ @@ -232,9 +237,9 @@ am_libdvisvgm_a_OBJECTS = BasicDVIReader.$(OBJEXT) Bezier.$(OBJEXT) \ System.$(OBJEXT) TensorProductPatch.$(OBJEXT) \ Terminal.$(OBJEXT) TFM.$(OBJEXT) ToUnicodeMap.$(OBJEXT) \ TpicSpecialHandler.$(OBJEXT) TriangularPatch.$(OBJEXT) \ - Unicode.$(OBJEXT) utility.$(OBJEXT) VFReader.$(OBJEXT) \ - XMLDocument.$(OBJEXT) XMLNode.$(OBJEXT) XMLString.$(OBJEXT) \ - $(am__objects_1) + TrueTypeFont.$(OBJEXT) TTFAutohint.$(OBJEXT) Unicode.$(OBJEXT) \ + utility.$(OBJEXT) VFReader.$(OBJEXT) XMLDocument.$(OBJEXT) \ + XMLNode.$(OBJEXT) XMLString.$(OBJEXT) $(am__objects_1) libdvisvgm_a_OBJECTS = $(am_libdvisvgm_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) @@ -470,7 +475,10 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LIBRARIES = libdvisvgm.a -dvisvgm_SOURCES = dvisvgm.cpp +dvisvgm_SOURCES = \ + CommandLine.hpp \ + dvisvgm.cpp + dvisvgm_LDADD = $(noinst_LIBRARIES) ../libs/clipper/libclipper.a \ ../libs/xxHash/libxxhash.a $(am__append_1) $(KPATHSEA_LIBS) \ $(POTRACE_LIBS) $(FREETYPE2_LIBS) $(FONTFORGE_LIBS) \ @@ -485,7 +493,7 @@ libdvisvgm_a_SOURCES = AGLTable.hpp BasicDVIReader.cpp \ CLCommandLine.cpp CLCommandLine.hpp CLOption.hpp CMap.cpp \ CMap.hpp CMapManager.cpp CMapManager.hpp CMapReader.cpp \ CMapReader.hpp Color.cpp Color.hpp ColorSpecialHandler.cpp \ - ColorSpecialHandler.hpp CommandLine.hpp CRC32.cpp CRC32.hpp \ + ColorSpecialHandler.hpp CRC32.cpp CRC32.hpp \ DependencyGraph.hpp Directory.cpp Directory.hpp DLLoader.cpp \ DLLoader.hpp DVIActions.hpp DVIReader.cpp DVIReader.hpp \ DvisvgmSpecialHandler.cpp DvisvgmSpecialHandler.hpp \ @@ -501,7 +509,8 @@ libdvisvgm_a_SOURCES = AGLTable.hpp BasicDVIReader.cpp \ GFGlyphTracer.cpp GFGlyphTracer.hpp GFReader.cpp GFReader.hpp \ GFTracer.cpp GFTracer.hpp Ghostscript.cpp Ghostscript.hpp \ Glyph.hpp GlyphTracerMessages.hpp GraphicsPath.hpp \ - HtmlSpecialHandler.cpp HtmlSpecialHandler.hpp InputBuffer.cpp \ + HtmlSpecialHandler.cpp HtmlSpecialHandler.hpp \ + HyperlinkManager.cpp HyperlinkManager.hpp InputBuffer.cpp \ InputBuffer.hpp InputReader.cpp InputReader.hpp JFM.cpp \ JFM.hpp Length.cpp Length.hpp macros.hpp MapLine.cpp \ MapLine.hpp Matrix.cpp Matrix.hpp Message.cpp Message.hpp \ @@ -510,43 +519,45 @@ libdvisvgm_a_SOURCES = AGLTable.hpp BasicDVIReader.cpp \ NumericRanges.hpp PageRanges.cpp PageRanges.hpp PageSize.cpp \ PageSize.hpp Pair.hpp PapersizeSpecialHandler.cpp \ PapersizeSpecialHandler.hpp PathClipper.cpp PathClipper.hpp \ - PdfSpecialHandler.cpp PdfSpecialHandler.hpp \ - PreScanDVIReader.cpp PreScanDVIReader.hpp Process.cpp \ - Process.hpp psdefs.cpp PSFilter.hpp PSInterpreter.cpp \ - PSInterpreter.hpp PSPattern.cpp PSPattern.hpp \ - PSPreviewFilter.cpp PSPreviewFilter.hpp PsSpecialHandler.cpp \ - PsSpecialHandler.hpp RangeMap.cpp RangeMap.hpp \ - ShadingPatch.cpp ShadingPatch.hpp SignalHandler.cpp \ - SignalHandler.hpp SpecialActions.hpp SpecialHandler.hpp \ - SpecialManager.cpp SpecialManager.hpp StreamReader.cpp \ - StreamReader.hpp StreamWriter.cpp StreamWriter.hpp Subfont.cpp \ - Subfont.hpp SVGCharHandler.cpp SVGCharHandler.hpp \ - SVGCharHandlerFactory.cpp SVGCharHandlerFactory.hpp \ - SVGCharPathHandler.cpp SVGCharPathHandler.hpp \ - SVGCharTspanTextHandler.cpp SVGCharTspanTextHandler.hpp \ - SVGOutput.cpp SVGOutput.hpp SVGSingleCharTextHandler.cpp \ - SVGSingleCharTextHandler.hpp SVGTree.cpp SVGTree.hpp \ - System.cpp System.hpp TensorProductPatch.cpp \ - TensorProductPatch.hpp Terminal.cpp Terminal.hpp TFM.cpp \ - TFM.hpp ToUnicodeMap.cpp ToUnicodeMap.hpp \ + PDFParser.cpp PDFParser.hpp PdfSpecialHandler.cpp \ + PdfSpecialHandler.hpp PreScanDVIReader.cpp \ + PreScanDVIReader.hpp Process.cpp Process.hpp psdefs.cpp \ + PSFilter.hpp PSInterpreter.cpp PSInterpreter.hpp PSPattern.cpp \ + PSPattern.hpp PSPreviewFilter.cpp PSPreviewFilter.hpp \ + PsSpecialHandler.cpp PsSpecialHandler.hpp RangeMap.cpp \ + RangeMap.hpp ShadingPatch.cpp ShadingPatch.hpp \ + SignalHandler.cpp SignalHandler.hpp SpecialActions.hpp \ + SpecialHandler.hpp SpecialManager.cpp SpecialManager.hpp \ + StreamReader.cpp StreamReader.hpp StreamWriter.cpp \ + StreamWriter.hpp Subfont.cpp Subfont.hpp SVGCharHandler.cpp \ + SVGCharHandler.hpp SVGCharHandlerFactory.cpp \ + SVGCharHandlerFactory.hpp SVGCharPathHandler.cpp \ + SVGCharPathHandler.hpp SVGCharTspanTextHandler.cpp \ + SVGCharTspanTextHandler.hpp SVGOutput.cpp SVGOutput.hpp \ + SVGSingleCharTextHandler.cpp SVGSingleCharTextHandler.hpp \ + SVGTree.cpp SVGTree.hpp System.cpp System.hpp \ + TensorProductPatch.cpp TensorProductPatch.hpp Terminal.cpp \ + Terminal.hpp TFM.cpp TFM.hpp ToUnicodeMap.cpp ToUnicodeMap.hpp \ TpicSpecialHandler.cpp TpicSpecialHandler.hpp \ - TriangularPatch.cpp TriangularPatch.hpp Unicode.cpp \ + TriangularPatch.cpp TriangularPatch.hpp TrueTypeFont.cpp \ + TrueTypeFont.hpp TTFAutohint.cpp TTFAutohint.hpp Unicode.cpp \ Unicode.hpp utility.hpp utility.cpp VectorIterator.hpp \ VectorStream.hpp version.hpp VFActions.hpp VFReader.cpp \ - VFReader.hpp XMLDocument.cpp XMLDocument.hpp XMLNode.cpp \ - XMLNode.hpp XMLString.cpp XMLString.hpp ZLibOutputStream.hpp \ - $(am__append_2) + VFReader.hpp windows.hpp XMLDocument.cpp XMLDocument.hpp \ + XMLNode.cpp XMLNode.hpp XMLString.cpp XMLString.hpp \ + ZLibOutputStream.hpp $(am__append_2) EXTRA_DIST = options.xml options.dtd iapi.h ierrors.h MiKTeXCom.hpp MiKTeXCom.cpp dvisvgm_srcdir = $(top_srcdir)/dvisvgm-src AM_CFLAGS = $(WARNING_CFLAGS) $(ZLIB_INCLUDES) $(CODE_COVERAGE_CFLAGS) \ $(am__append_3) AM_CXXFLAGS = $(WARNING_CFLAGS) -Wnon-virtual-dtor \ -I$(dvisvgm_srcdir)/libs/clipper \ + -I$(dvisvgm_srcdir)/libs/variant/include \ -I$(dvisvgm_srcdir)/libs/xxHash $(am__append_4) \ $(KPATHSEA_INCLUDES) $(POTRACE_INCLUDES) $(FREETYPE2_INCLUDES) \ $(ZLIB_INCLUDES) $(LIBGS_INCLUDES) $(CODE_COVERAGE_CFLAGS) \ - $(am__append_5) -AM_LDFLAGS = $(CODE_COVERAGE_LDFLAGS) + $(am__append_6) +AM_LDFLAGS = $(CODE_COVERAGE_LDFLAGS) $(am__append_5) CLEANFILES = *.gcda *.gcno all: all-am @@ -691,6 +702,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GFTracer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Ghostscript.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HtmlSpecialHandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HyperlinkManager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InputBuffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InputReader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/JFM.Po@am__quote@ @@ -700,6 +712,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Message.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetafontWrapper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NoPsSpecialHandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PDFParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSInterpreter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSPattern.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSPreviewFilter.Po@am__quote@ @@ -727,11 +740,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Subfont.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/System.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TFM.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TTFAutohint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TensorProductPatch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Terminal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ToUnicodeMap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TpicSpecialHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TriangularPatch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrueTypeFont.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Unicode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VFReader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLDocument.Po@am__quote@ @@ -1010,7 +1025,7 @@ uninstall-am: uninstall-binPROGRAMS # TL: do not try to rebuild these source files. # the command-line parser class is generated from options.xml by opt2cpp @TEXLIVE_BUILD_FALSE@$(srcdir)/CommandLine.hpp: options.xml -@TEXLIVE_BUILD_FALSE@ rm -f $@ $*.hpp +@TEXLIVE_BUILD_FALSE@ rm -f $@ @TEXLIVE_BUILD_FALSE@ python $(srcdir)/opt2cpp.py $< >$@ # Create a C string definition containing the PostScript routines psdefs.ps needed by class PSInterpreter diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp index 333bd204cb2..00284bcad86 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp @@ -2,7 +2,7 @@ ** MapLine.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cstring> #include <sstream> #include "InputBuffer.hpp" @@ -124,8 +123,8 @@ void MapLine::parseDVIPSLine (InputReader &ir) { while (ir.peek() == '<' || ir.peek() == '"') { if (ir.peek() == '<') { ir.get(); - if (ir.peek() == '[') - ir.get(); + if (ir.peek() == '[' || ir.peek() == '<') + ir.get(); // skip second char of "<[" and "<<" string name = ir.getString(); if (name.length() > 4 && name.substr(name.length()-4) == ".enc") _encname = name.substr(0, name.length()-4); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp index f5fea478ad7..64d85050648 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp @@ -2,7 +2,7 @@ ** MapLine.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp index 257335c0071..57456ba36b0 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp @@ -2,7 +2,7 @@ ** Matrix.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp index 0d8917f56ae..9ea836b9837 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp @@ -2,7 +2,7 @@ ** Matrix.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -57,7 +57,9 @@ class Matrix Matrix& lmultiply (const Matrix &tm); Matrix& rmultiply (const Matrix &tm); Matrix& translate (double tx, double ty); + Matrix& translate (const DPair &p) {return translate(p.x(), p.y());} Matrix& scale (double sx, double sy); + Matrix& scale (const DPair &p) {return scale(p.x(), p.y());} Matrix& rotate (double deg); Matrix& xskewByAngle (double deg); Matrix& yskewByAngle (double deg); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp index 7e60ad3b9fa..96c826f5a41 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp @@ -2,7 +2,7 @@ ** Message.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,12 +18,11 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cstdarg> #include <cstdlib> #include <cstring> #include <iostream> -#include <map> +#include <unordered_map> #include "Message.hpp" #include "Terminal.hpp" @@ -218,7 +217,7 @@ static bool colorchar2int (char colorchar, int *val) { * - 0-7: dark colors * - 8-F: light colors * - *: default color - * Example: num:01 sets page number messages to red on black background */ + * Example: pn:01 sets page number messages to red on black background */ void Message::init () { if (_initialized || !Message::COLORIZE) return; @@ -234,7 +233,7 @@ void Message::init () { _classColors[MC_PROGRESS] = Color(Terminal::MAGENTA); if (const char *color_str = getenv("DVISVGM_COLORS")) { - map<string, MessageClass> classes = { + unordered_map<string, MessageClass> classes = { {"er", MC_ERROR}, {"wn", MC_WARNING}, {"pn", MC_PAGE_NUMBER}, @@ -263,7 +262,7 @@ void Message::init () { p += 5; // skip trailing characters in a malformed entry - while (!isspace(*p) && *p != ':' && *p != ';') + while (*p && !isspace(*p) && *p != ':' && *p != ';') ++p; // skip separation characters while (isspace(*p) || *p == ':' || *p == ';') diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp index f05eb6aa0ed..acd3454daa3 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp @@ -2,7 +2,7 @@ ** Message.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp index d94a1feab8a..cf217db2688 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp @@ -2,7 +2,7 @@ ** MessageException.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp index dd2a6cf2941..295237d1d91 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp @@ -2,7 +2,7 @@ ** MetafontWrapper.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cstdlib> #include <cctype> #include <fstream> @@ -76,7 +75,7 @@ bool MetafontWrapper::call (const string &mode, double mag) { "batchmode;" // don't halt on errors and don't print informational messages "input " << _fontname << "\""; // load font description Message::mstream(false, Message::MC_STATE) << "\nrunning Metafont for " << _fontname << '\n'; - Process mf_process(cmd, oss.str().c_str()); + Process mf_process(cmd, oss.str()); string mf_messages; mf_process.run(_dir, &mf_messages); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp index 3bda79c5683..03f77b9ef11 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp @@ -2,7 +2,7 @@ ** MetafontWrapper.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.cpp index bdb0cc89073..d22cc45f690 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.cpp @@ -2,7 +2,7 @@ ** MiKTeXCom.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <stdio.h> #include <comdef.h> #include <string> @@ -29,8 +28,8 @@ using namespace std; /** Constructs a COM object representing a MiKTeX session. */ -MiKTeXCom::MiKTeXCom () : _session(0) { - if (FAILED(CoInitialize(0))) +MiKTeXCom::MiKTeXCom () : _session() { + if (FAILED(CoInitialize(nullptr))) throw MessageException("COM library could not be initialized\n"); // try to initialize the MiKTeX session object #ifdef _MSC_VER @@ -54,7 +53,7 @@ MiKTeXCom::~MiKTeXCom () { #else _session->Release(); #endif - _session = 0; // prevent automatic call of Release() after CoUninitialize() + _session = nullptr; // prevent automatic call of Release() after CoUninitialize() } CoUninitialize(); } @@ -105,7 +104,7 @@ const char* MiKTeXCom::findFile (const char *fname) { ret = _bstr_t(path); return ret.c_str(); } - return 0; + return nullptr; } catch (_com_error &e) { throw MessageException((const char*)e.Description()); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp index a87a8488c7c..a68dc4dc674 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp @@ -2,7 +2,7 @@ ** MiKTeXCom.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,6 +22,7 @@ #define MIKTEXCOM_HPP #include <string> +#include "windows.hpp" #ifdef _MSC_VER #import <MiKTeX209-session.tlb> @@ -30,9 +31,7 @@ using namespace MiKTeXSession2_9; #include "miktex209-session.h" #endif - -class MiKTeXCom -{ +class MiKTeXCom { public: MiKTeXCom (); ~MiKTeXCom (); @@ -48,5 +47,4 @@ class MiKTeXCom #endif }; - #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.cpp index a5b2a680ebc..a1df816cb67 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.cpp @@ -2,7 +2,7 @@ ** NoPsSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include "Message.hpp" #include "NoPsSpecialHandler.hpp" @@ -40,7 +39,7 @@ void NoPsSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) { } -const char** NoPsSpecialHandler::prefixes () const { - static const char *pfx[] = {"header=", "psfile=", "PSfile=", "ps:", "ps::", "!", "\"", 0}; +const vector<const char*> NoPsSpecialHandler::prefixes () const { + const vector<const char*> pfx {"header=", "psfile=", "PSfile=", "ps:", "ps::", "!", "\""}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp index bec66478864..33922799b2f 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp @@ -2,7 +2,7 @@ ** NoPsSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -30,7 +30,7 @@ class NoPsSpecialHandler : public SpecialHandler, public DVIEndPageListener bool process (const char *prefix, std::istream &is, SpecialActions &actions) override; const char* name () const override {return 0;} const char* info () const override {return 0;} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; protected: void dviEndPage (unsigned pageno, SpecialActions &actions) override; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/NumericRanges.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/NumericRanges.hpp index c87eddf054f..4ba3f8719cb 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/NumericRanges.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/NumericRanges.hpp @@ -2,7 +2,7 @@ ** NumericRanges.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -29,9 +29,9 @@ template <class T> class NumericRanges { public: - typedef std::pair<T,T> Range; - typedef std::list<Range> Container; - typedef typename Container::const_iterator ConstIterator; + using Range = std::pair<T,T>; + using Container = std::list<Range>; + using ConstIterator = typename Container::const_iterator; public: void addRange (T value) {addRange(value, value);} @@ -98,7 +98,7 @@ void NumericRanges<T>::addRange (T first, T last) { template <class T> bool NumericRanges<T>::valueExists (T value) const { - ConstIterator it = std::lower_bound(_ranges.begin(), _ranges.end(), Range(value, 0), + auto it = std::lower_bound(_ranges.begin(), _ranges.end(), Range(value, 0), [](const Range &r1, const Range &r2) { return r1.first < r2.first; }); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.cpp new file mode 100644 index 00000000000..91020868a3c --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.cpp @@ -0,0 +1,469 @@ +/************************************************************************* +** PDFParser.cpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#include <cctype> +#include <istream> +#include <ostream> +#include <sstream> +#include <stdexcept> +#include "InputReader.hpp" +#include "PDFParser.hpp" +#include "utility.hpp" + +using namespace std; + + +/** Parses PDF from an input stream and returns the corresponding object representation. + * @param[in] is input stream the PDF data is read from + * @param[in] opHandler handler used to treat PDF operators + * @return the parsed objects */ +vector<PDFObject> PDFParser::parse (std::istream &is, const PDFOperatorHandler &opHandler) { + StreamInputReader ir(is); + return parse(ir, opHandler); +} + + +/** Parses PDF from a string and returns the corresponding object representation. + * @param[in] str string that contains the PDF data + * @param[in] opHandler handler used to treat PDF operators + * @return the parsed objects */ +vector<PDFObject> PDFParser::parse (const std::string &str, const PDFOperatorHandler &opHandler) { + istringstream iss(str); + return parse(iss, opHandler); +} + + +/** Parses PDF from an InputReader object and returns the corresponding object representation. + * @param[in] ir InputReader the PDF data is read from + * @param[in] opHandler handler used to treat PDF operators + * @return the parsed objects */ +vector<PDFObject> PDFParser::parse (InputReader &ir, const PDFOperatorHandler &opHandler) { + vector<PDFObject> objects; + while (!ir.eof()) { + ir.skipSpace(); + if (ir.peek() == '%') // comment? + while (ir.get() != '\n' && !ir.eof()); + else if (!ir.eof()) + parse(ir, objects, opHandler); + } + return objects; +} + + +/** Default handler for PDF operators. Just adds the operators to the + * object vector without evaluating them. + * @param[in] opname name of the operator + * @param[in,out] objects vector holding the parsed objects */ +static void append_operator (const string &opname, vector<PDFObject> &objects) { + objects.emplace_back(PDFOperator(opname)); +} + + +/** Parses PDF from an input stream and returns the corresponding object representation. + * @param[in] is input stream the PDF data is read from + * @return the parsed objects */ +vector<PDFObject> PDFParser::parse (std::istream &is) { + return parse(is, append_operator); +} + + +/** Parses PDF from a string and returns the corresponding object representation. + * @param[in] str string that contains the PDF data + * @return the parsed objects */ +vector<PDFObject> PDFParser::parse (const std::string &str) { + return parse(str, append_operator); +} + +/** Parses PDF from an InputReader object and returns the corresponding object representation. + * @param[in] ir InputReader the PDF data is read from + * @return the parsed objects */ +vector<PDFObject> PDFParser::parse (InputReader &ir) { + return parse(ir, append_operator); +} + + +/** Parses PDF from an InputReader object and appends the recognized objects to a vector. + * @param[in] ir InputReader the PDF data is read from + * @param[in,out] objects the parsed PDF objects are appended to this vector + * @return the parsed objects */ +void PDFParser::parse (InputReader &ir, vector<PDFObject> &objects) { + parse(ir, objects, append_operator); +} + + +inline bool isoctaldigit (int c) {return c >= '0' && c <= '7';} + +/** Parses a PDF escape sequence of the form \FOO, where FOO is a single + * character or a sequence of 1-3 octal digits + * @return pair (s,c), s=true if c contains a parsed character */ +static pair<bool,int> parse_escape_seq (InputReader &ir) { + // leading backslash has already been read + if (isoctaldigit(ir.peek())) { + string str; + for (int i=0; i < 3 && isoctaldigit(ir.peek()); i++) + str += static_cast<char>(ir.get()); + return pair<bool,int>{true, stoi(str, 0, 8)}; + } + char c = static_cast<char>(ir.get()); + switch (c) { + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case '\n': + case '\r': + if ((c == '\n' && ir.peek() == '\r') || (c == '\r' && ir.peek() == '\n')) + ir.get(); + return pair<bool,int>{false, 0}; + } + return pair<bool,int>{true, c}; +} + + +/** Parses a literal PDF string of the form (FOO). */ +static string parse_literal_string (InputReader &ir) { + string str; + ir.get(); // skip initial '(' + int open_parens=1; + while (ir.peek() >= 0 && open_parens > 0) { + if (ir.peek() == '\n' || ir.peek() == '\r') + break; + int c = ir.get(); + switch (c) { + case '(': open_parens++; break; + case ')': open_parens--; break; + case '\\': + pair<bool,int> state = parse_escape_seq(ir); + c = state.first ? state.second : -1; + break; + } + if (open_parens > 0 && c >= 0) + str += static_cast<char>(c); + } + if (open_parens > 0) + throw PDFException("missing ')' at end of literal string"); + return str; +} + + +/** Gets a single hex digit from the InputReader. */ +static char get_hex_digit (InputReader &ir) { + int c = ir.get(); + if (isxdigit(c)) + return static_cast<char>(c); + ostringstream oss; + oss << "invalid hexadecimal digit '" << static_cast<char>(c) << "'"; + throw PDFException(oss.str()); +} + + +/** Parses a PDF hex string of the form <FOO>, where FOO is a sequence of + * hex digits optionally separated by whitespace. */ +static string parse_hex_string (InputReader &ir) { + // initial '<' has already been read + string str; + ir.skipSpace(); + while (ir.peek() > 0 && ir.peek() != '>') { + string hexpair; + hexpair += get_hex_digit(ir); + ir.skipSpace(); + if (ir.peek() > 0 && ir.peek() != '>') + hexpair += get_hex_digit(ir); + else if (ir.peek() == '>') + hexpair += '0'; + ir.skipSpace(); + str += static_cast<char>(stoi(hexpair, 0, 16)); + } + if (ir.peek() != '>') + throw PDFException("missing '>' at end of hexadecimal string"); + ir.get(); // skip closing '>' + return str; +} + + +using NumberVariant = mpark::variant<int, double>; + +/** Parses a PDF number from a string. The number is either integer or real. + * @param[in] str string to parse + * @param[out] nv variant holding the numeric value + * @return true if entire string has been parsed succesfully */ +static bool parse_number (const string &str, NumberVariant &nv) { + if (str.empty()) + return false; + try { + size_t dotpos = str.find('.'); + if (dotpos == string::npos) { // not a real number? + size_t count; + nv = NumberVariant(stoi(str, &count, 10)); // then try to convert str to int + return count == str.length(); // successful only if all characters have been processed + } + string postdot = str.substr(dotpos+1); + // ensure signless integer after dot to exclude exponental notation + // which is not allowed in PDF real number constants + if (!postdot.empty() && isdigit(postdot[0])) { + size_t count; + stoi(postdot, &count, 10); + if (count != postdot.length()) + return false; + } + size_t count; + nv = NumberVariant(stod(str, &count)); + return count == str.length(); + } + catch (invalid_argument &e) { + return false; + } +} + + +/** Parses a PDF array from the input stream and returns a corresponding object. */ +PDFArray PDFParser::parseArray (InputReader &ir, const PDFOperatorHandler &opHandler) { + ir.get(); // skip '[' + vector<PDFObject> localObjects; + while (!ir.eof() && ir.peek() != ']') + parse(ir, localObjects, opHandler); + ir.skipSpace(); + if (ir.peek() != ']') + throw PDFException("missing ']' at end of array"); + ir.get(); + PDFArray arr; + std::move(localObjects.begin(), localObjects.end(), back_inserter(arr)); + return arr; +} + + +/** Parses a PDF dictionary from the input stream and returns a corresponding object. + * The function expects that the first opening angle bracket denoting the start of an + * dictionary has already been swallowed from the stream. */ +PDFDict PDFParser::parseDict (InputReader &ir, const PDFOperatorHandler &opHandler) { + ir.get(); // skip second "<" + vector<PDFObject> localObjects; + while (!ir.eof() && ir.peek() != '>') + parse(ir, localObjects, opHandler); + if (ir.getString(2) != ">>") + throw PDFException("missing '>>' at end of dictionary"); + PDFDict dict; + for (auto it=localObjects.begin(); it != localObjects.end(); ++it) { + if (!it->get<PDFName>()) + throw PDFException("name key expected in dictionary"); + const PDFName &key = *it->get<PDFName>(); + if (++it == localObjects.end()) + throw PDFException(string("missing dictionary value for key '")+key.str+"'"); + dict.emplace(key.str, std::move(*it)); + } + return dict; +} + + +static PDFStream parse_stream (InputReader &ir, const char *delim) { + do + ir.skipUntil("endstream"); + while (ir.peek() >= 0 && !strchr(delim, ir.peek())); // ensure delimiter after "endstream" + return PDFStream(); +} + + +static PDFIndirectObject parse_indirect_object (InputReader &ir, const char *delim, vector<PDFObject> &objects) { + do + ir.skipUntil("endobj"); + while (ir.peek() >= 0 && !strchr(delim, ir.peek())); // ensure delimiter after "endobj" + if (objects.size() >= 2) { + const int *genno = objects.back().get<int>(); + objects.pop_back(); + const int *objno = objects.back().get<int>(); + objects.pop_back(); + if (objno && genno) + return PDFIndirectObject(*objno, *genno); + } + throw PDFException("object and generation number expected before 'obj'"); +} + + +static PDFObjectRef parse_object_ref (vector<PDFObject> &objects) { + if (objects.size() >= 2) { + const int *genno = objects.back().get<int>(); + objects.pop_back(); + const int *objno = objects.back().get<int>(); + objects.pop_back(); + if (objno && genno) + return PDFObjectRef(*objno, *genno); + } + throw PDFException("object and generation number expected before 'R'"); +} + + +/** Replaces all occurences of "#XX" (XX are two hex digits) with the corresponding character. */ +static string& subst_numeric_chars (string &str) { + for (size_t pos=str.find('#'); pos != string::npos; pos=str.find('#', pos+1)) { + if (pos > str.length()-3) + throw PDFException("sign character # must be followed by two hexadecimal digits"); + if (isxdigit(str[pos+1]) && isxdigit(str[pos+2])) { + int c = stoi(str.substr(pos+1, 2), 0, 16); + if (c == 0) + throw PDFException("null character not permitted in name"); + str.replace(pos, 3, 1, static_cast<char>(c)); + } + else + throw PDFException("sign character # must be followed by two hexadecimal digits"); + } + return str; +} + + +/** Parses a single PDF object from an InputReader object. + * @param[in,out] ir reader object to read the PDF data from + * @param[out] objects the parsed object is appended to this vector + * @param[in] opHandler handler used to treat PDF operators + * @throws PDFException on failure */ +void PDFParser::parse (InputReader &ir, vector<PDFObject> &objects, const PDFOperatorHandler &opHandler) { + static const char *delim = "()<>[]{}/% \t\n\r\f"; + ir.skipSpace(); + if (ir.peek() < 0) + return; + switch (ir.peek()) { + case '(': + objects.emplace_back(parse_literal_string(ir)); break; + case '[': + objects.emplace_back(util::make_unique<PDFArray>(parseArray(ir, opHandler))); break; + case '<': + ir.get(); + if (ir.peek() != '<') + objects.emplace_back(parse_hex_string(ir)); + else + objects.emplace_back(util::make_unique<PDFDict>(parseDict(ir, opHandler))); + break; + case '/': { + ir.get(); + string name = ir.getString(delim); + objects.emplace_back(PDFName(subst_numeric_chars(name))); + break; + } + default: { + string str = ir.getString(delim); + if (str.empty()) + break; + if (str == "null") + objects.emplace_back(PDFNull()); + else if (str == "true") + objects.emplace_back(true); + else if (str == "false") + objects.emplace_back(false); + else if (str == "stream") + objects.emplace_back(parse_stream(ir, delim)); + else if (str == "obj") + objects.emplace_back(parse_indirect_object(ir, delim, objects)); + else if (str == "R") + objects.emplace_back(parse_object_ref(objects)); + else { + NumberVariant number; + if (!parse_number(str, number)) + opHandler(str, objects); + else { + if (mpark::get_if<int>(&number)) + objects.emplace_back(mpark::get<int>(number)); + else + objects.emplace_back(mpark::get<double>(number)); + } + } + } + } +} + +////////////////////////////////////////////////////////////////////////// + +struct ToDoubleVisitor { + template <typename V> + double operator () (const V &val) {return 0;} +}; + +template<> double ToDoubleVisitor::operator () (const int &val) {return static_cast<double>(val);} +template<> double ToDoubleVisitor::operator () (const double &val) {return val;} +template<> double ToDoubleVisitor::operator () (const string &val) { + try { + return stod(val); + } + catch (exception &e) { + return 0; + } +} + + +PDFObject::operator double () const { + return mpark::visit(ToDoubleVisitor(), _value); +} + + +PDFObject::operator std::string () const { + ostringstream oss; + oss << *this; + return oss.str(); +} + + +static std::ostream& operator << (std::ostream &os, const PDFName &name) {return os << name.str;} +static ostream& operator << (ostream &os, const PDFNull&) {return os << "null";} +static ostream& operator << (ostream &os, const PDFStream&) {return os << "stream";} +static ostream& operator << (ostream &os, const PDFOperator &op) {return os << op.opname;} + +static ostream& operator << (ostream &os, const PDFIndirectObject &obj) { + return os << "obj(" << obj.objnum << ", " << obj.gennum << ')'; +} + + +static ostream& operator << (ostream &os, const PDFObjectRef &ref) { + return os << "obj(" << ref.objnum << ", " << ref.gennum << ')'; +} + + +static ostream& operator << (ostream &os, const unique_ptr<vector<PDFObject>> &val) { + os << '['; + for (auto it=val->begin(); it != val->end(); ++it) { + if (it != val->begin()) + os << ", "; + it->write(os); + } + os << ']'; + return os; +} + + +static ostream& operator << (ostream &os, const unique_ptr<Dictionary<string,PDFObject>> &val) { + os << "<<"; + for (auto it=val->begin(); it != val->end(); ++it) { + if (it != val->begin()) + os << ", "; + os << it->first << ':' << it->second; + } + os << ">>"; + return os; +} + + +struct WriteVisitor { + WriteVisitor (ostream &os) : _os(os) {} + template <typename T> void operator () (const T &val) {_os << val;} + ostream &_os; +}; + + +void PDFObject::write (ostream &os) const { + mpark::visit(WriteVisitor(os), _value); +} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.hpp new file mode 100644 index 00000000000..18e61ee19a6 --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.hpp @@ -0,0 +1,185 @@ +/************************************************************************* +** PDFParser.hpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#ifndef PDFPARSER_HPP +#define PDFPARSER_HPP + +#include <initializer_list> +#include <istream> +#include <functional> +#include <map> +#include <memory> +#include <string> +#include <unordered_map> +#include <utility> +#include <vector> +#include <mpark/variant.hpp> +#include "MessageException.hpp" + +template <typename K, typename V> +class Dictionary { + using Map = std::map<K, V>; + + public: + typename Map::const_iterator begin () const {return _map.begin();} + typename Map::const_iterator end () const {return _map.end();} + typename Map::iterator begin () {return _map.begin();} + typename Map::iterator end () {return _map.end();} + typename Map::const_iterator find (const K &key) const {return _map.find(key);} + bool empty () const {return _map.empty();} + bool exists (const K &key) const {return _map.find(key) != _map.end();} + size_t size () const {return _map.size();} + + const V* get (const K &key) const { + auto it = _map.find(key); + if (it != _map.end()) + return &it->second; + return nullptr; + } + + std::pair<typename Map::iterator,bool> emplace (const K &key, V &&value) { + return _map.emplace(key, std::forward<V>(value)); + } + + private: + Map _map; +}; + +////////////////////////////////////////////////////////////////////////// +// PDF object types + +struct PDFNull {}; +struct PDFStream {}; + +struct PDFIndirectObject { + PDFIndirectObject (int n, int gen) : objnum(n), gennum(gen) {} + int objnum, gennum; +}; + +struct PDFObjectRef { + PDFObjectRef (int n, int gen) : objnum(n), gennum(gen) {} + int objnum, gennum; +}; + +struct PDFOperator { + PDFOperator (const std::string &name) : opname(name) {} + std::string opname; +}; + +struct PDFName { + PDFName (const std::string &val) : str(val) {} + bool operator == (const PDFName &name) const {return str == name.str;} + std::string str; +}; + +class PDFObject; + +using PDFArray = std::vector<PDFObject>; +using PDFDict = Dictionary<std::string, PDFObject>; + +////////////////////////////////////////////////////////////////////////// + +/** This class represents a single variadic PDF object. */ +class PDFObject { + using Value = mpark::variant< + PDFNull, + bool, + int, + double, + PDFName, + PDFStream, + PDFIndirectObject, + PDFObjectRef, + PDFOperator, + std::string, + std::unique_ptr<PDFArray>, + std::unique_ptr<PDFDict> + >; + + public: + PDFObject () : _value(0) {} + + template <typename T> + explicit PDFObject (T &&value) : _value(std::forward<T>(value)) {} + + explicit PDFObject (const char *value) : _value(std::string(value)) {} + explicit operator std::string () const; + explicit operator double () const; + + template <typename T> + const T* get () const {return mpark::get_if<T>(&_value);} + + void write (std::ostream &os) const; + + private: + Value _value; +}; + + +template<> inline const PDFArray* PDFObject::get() const { + if (auto *p = mpark::get_if<std::unique_ptr<PDFArray>>(&_value)) + return &(**p); + return nullptr; +} + + +template<> inline const PDFDict* PDFObject::get() const { + if (auto *p = mpark::get_if<std::unique_ptr<PDFDict>>(&_value)) + return &(**p); + return nullptr; +} + + +inline std::ostream& operator << (std::ostream &os, const PDFObject &obj) { + obj.write(os); + return os; +} + +////////////////////////////////////////////////////////////////////////// + +class InputReader; + +class PDFParser { + public: + using PDFOperatorHandler = std::function<void (const std::string&, std::vector<PDFObject>&)>; + + public: + std::vector<PDFObject> parse (std::istream &is); + std::vector<PDFObject> parse (const std::string &str); + std::vector<PDFObject> parse (InputReader &ir); + void parse (InputReader &ir, std::vector<PDFObject> &objects); + + std::vector<PDFObject> parse (std::istream &is, const PDFOperatorHandler &opHandler); + std::vector<PDFObject> parse (const std::string &str, const PDFOperatorHandler &opHandler); + std::vector<PDFObject> parse (InputReader &ir, const PDFOperatorHandler &opHandler); + void parse (InputReader &ir, std::vector<PDFObject> &objects, const PDFOperatorHandler &opHandler); + + protected: + PDFArray parseArray (InputReader &ir, const PDFOperatorHandler &opHandler); + PDFDict parseDict (InputReader &ir, const PDFOperatorHandler &opHandler); +}; + + +/** If errors occur while parsing a sequence of PDF objects, an instance of this exception is thrown. */ +struct PDFException : public MessageException { + PDFException (const std::string &msg) : MessageException(msg) {} +}; + +#endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSFilter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSFilter.hpp index 61adb5af36e..4e74879d301 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSFilter.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSFilter.hpp @@ -2,7 +2,7 @@ ** PSFilter.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp index 407f0eb32e7..c33bffb8927 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp @@ -2,7 +2,7 @@ ** PSInterpreter.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,10 +18,11 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> +#include <algorithm> #include <cstring> #include <fstream> #include <sstream> +#include <unordered_map> #include "FileFinder.hpp" #include "InputReader.hpp" #include "Message.hpp" @@ -239,108 +240,90 @@ int GSDLLCALL PSInterpreter::output (void *inst, const char *buf, int len) { } -/** Converts a vector of strings to a vector of doubles. - * @param[in] str the strings to be converted - * @param[out] d the resulting doubles */ -static void str2double (const vector<string> &str, vector<double> &d) { - for (size_t i=0; i < str.size(); i++) { - istringstream iss(str[i]); - iss >> d[i]; - } -} - - /** Evaluates a command emitted by Ghostscript and invokes the corresponding * method of interface class PSActions. * @param[in] in reader pointing to the next command */ void PSInterpreter::callActions (InputReader &in) { - // array of currently supported operators (must be ascendingly sorted) - static const struct Operator { - const char *name; // name of operator + struct Operator { int pcount; // number of parameters (< 0 : variable number of parameters) - void (PSActions::*op)(vector<double> &p); // operation handler - } 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}, - {"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, 0}, - {"restore", 1, &PSActions::restore}, - {"rotate", 1, &PSActions::rotate}, - {"save", 1, &PSActions::save}, - {"scale", 2, &PSActions::scale}, - {"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}, - {"setopacityalpha", 1, &PSActions::setopacityalpha}, - {"setpattern", -1, &PSActions::setpattern}, - {"setrgbcolor", 3, &PSActions::setrgbcolor}, - {"shfill", -1, &PSActions::shfill}, - {"stroke", 0, &PSActions::stroke}, - {"translate", 2, &PSActions::translate}, + 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}}, + {"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}}, + {"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}}, + {"setopacityalpha",{ 1, &PSActions::setopacityalpha}}, + {"setpattern", {-1, &PSActions::setpattern}}, + {"setrgbcolor", { 3, &PSActions::setrgbcolor}}, + {"shfill", {-1, &PSActions::shfill}}, + {"stroke", { 0, &PSActions::stroke}}, + {"translate", { 2, &PSActions::translate}}, }; if (_actions) { in.skipSpace(); - // binary search - int first=0, last=sizeof(operators)/sizeof(Operator)-1; - while (first <= last) { - int mid = first+(last-first)/2; - int cmp = in.compare(operators[mid].name); - if (cmp < 0) - last = mid-1; - else if (cmp > 0) - first = mid+1; + auto it = operators.find(in.getWord()); + if (it != operators.end()) { + if (!it->second.handler) { // raw string data received? + _rawData.clear(); + in.skipSpace(); + while (!in.eof()) { + _rawData.emplace_back(in.getString()); + in.skipSpace(); + } + } else { - if (!operators[mid].op) { // raw string data received - _rawData.clear(); + // collect parameters + vector<string> params; + int pcount = it->second.pcount; + if (pcount < 0) { // variable number of parameters? in.skipSpace(); - while (!in.eof()) { - _rawData.emplace_back(in.getString()); + while (!in.eof()) { // read all available parameters + params.emplace_back(in.getString()); in.skipSpace(); } } - else { - // collect parameters and call handler - vector<string> params; - int pcount = operators[mid].pcount; - if (pcount < 0) { // variable number of parameters? + else { // fix number of parameters + for (int i=0; i < pcount; i++) { in.skipSpace(); - while (!in.eof()) { // read all available parameters - params.emplace_back(in.getString()); - in.skipSpace(); - } - } - else { // fix number of parameters - for (int i=0; i < pcount; i++) { - in.skipSpace(); - params.emplace_back(in.getString()); - } + params.emplace_back(in.getString()); } - vector<double> v(params.size()); - str2double(params, v); - (_actions->*operators[mid].op)(v); - _actions->executed(); } - break; + // convert parameter strings to doubles + vector<double> v(params.size()); + transform(params.begin(), params.end(), v.begin(), [](const string &str) { + return stod(str); + }); + // call operator handler + (_actions->*it->second.handler)(v); + _actions->executed(); } } } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp index d3ae0733b54..503c45dac65 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp @@ -2,7 +2,7 @@ ** PSInterpreter.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp index cbcd7f1e10a..419df9cc8eb 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp @@ -2,7 +2,7 @@ ** PSPattern.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,13 +18,14 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> +#include <array> #include <sstream> #include <vector> #include "BoundingBox.hpp" #include "PSPattern.hpp" #include "SpecialActions.hpp" #include "SVGTree.hpp" +#include "utility.hpp" #include "XMLNode.hpp" using namespace std; @@ -37,31 +38,34 @@ string PSPattern::svgID () const { /** Appends the definition of this pattern to the "def" section of the SVG tree. */ void PSPattern::apply (SpecialActions &actions) { - if (XMLElementNode *pattern = createPatternNode()) - actions.appendToDefs(pattern); + if (auto pattern = createPatternNode()) + actions.appendToDefs(std::move(pattern)); } ///////////////////////////////////////////////////////////////////////////// PSTilingPattern::PSTilingPattern (int id, BoundingBox &bbox, Matrix &matrix, double xstep, double ystep) - : PSPattern(id), _bbox(bbox), _matrix(matrix), _xstep(xstep), _ystep(ystep), _groupNode(0) + : PSPattern(id), _bbox(bbox), _matrix(matrix), _xstep(xstep), _ystep(ystep) { _groupNode = PSTilingPattern::createGroupNode(); + _groupNodePtr = _groupNode.get(); } -PSTilingPattern::~PSTilingPattern () { - delete _groupNode; +/** Assigns a new group element. */ +void PSTilingPattern::setGroupNode (unique_ptr<XMLElementNode> &&node) { + _groupNode = std::move(node); + _groupNodePtr = _groupNode.get(); } /** Creates a new pattern element representing the pattern defined in the PS code. */ -XMLElementNode* PSTilingPattern::createPatternNode () const { +unique_ptr<XMLElementNode> PSTilingPattern::createPatternNode () const { if (!_groupNode) - return 0; + return nullptr; BoundingBox box(_bbox.minX(), _bbox.minY(), _bbox.minX()+_xstep, _bbox.minY()+_ystep); - XMLElementNode *pattern = new XMLElementNode("pattern"); + auto pattern = util::make_unique<XMLElementNode>("pattern"); pattern->addAttribute("id", svgID()); pattern->addAttribute("x", box.minX()); pattern->addAttribute("y", box.minY()); @@ -75,33 +79,34 @@ XMLElementNode* PSTilingPattern::createPatternNode () const { // disable clipping at the tile borders => tiles become "transparent" pattern->addAttribute("overflow", "visible"); } - if (XMLElementNode *clip=createClipNode()) - pattern->append(clip); - pattern->append(_groupNode); + if (auto clip = createClipNode()) + pattern->append(std::move(clip)); + pattern->append(std::move(_groupNode)); + _groupNode.reset(); return pattern; } /** Creates a new clip element restricting the drawing area to the * dimensions given in the definition of the pattern. */ -XMLElementNode* PSTilingPattern::createClipNode() const { - XMLElementNode *clip = new XMLElementNode("clipPath"); +unique_ptr<XMLElementNode> PSTilingPattern::createClipNode() const { + auto clip = util::make_unique<XMLElementNode>("clipPath"); clip->addAttribute("id", "pc"+XMLString(psID())); - XMLElementNode *rect = new XMLElementNode("rect"); + auto rect = util::make_unique<XMLElementNode>("rect"); rect->addAttribute("x", _bbox.minX()); rect->addAttribute("y", _bbox.minY()); rect->addAttribute("width", _bbox.width()); rect->addAttribute("height", _bbox.height()); - clip->append(rect); + clip->append(std::move(rect)); return clip; } /** Creates a new group element that contains all "drawing" elements that * define the pattern graphic. */ -XMLElementNode* PSTilingPattern::createGroupNode () const { +unique_ptr<XMLElementNode> PSTilingPattern::createGroupNode () const { // add all succeeding path elements to this group - XMLElementNode *group = new XMLElementNode("g"); + auto group = util::make_unique<XMLElementNode>("g"); group->addAttribute("clip-path", XMLString("url(#pc")+XMLString(psID())+")"); return group; } @@ -109,7 +114,7 @@ XMLElementNode* PSTilingPattern::createGroupNode () const { void PSTilingPattern::apply (SpecialActions &actions) { PSPattern::apply(actions); - _groupNode = 0; + _groupNode.reset(); } @@ -124,21 +129,15 @@ PSColoredTilingPattern::PSColoredTilingPattern (int id, BoundingBox &bbox, Matri ///////////////////////////////////////////////////////////////////////////// PSUncoloredTilingPattern::PSUncoloredTilingPattern (int id, BoundingBox &bbox, Matrix &matrix, double xstep, double ystep) - : PSTilingPattern(id, bbox, matrix, xstep, ystep), _applied(false) + : PSTilingPattern(id, bbox, matrix, xstep, ystep), _applied() { } -PSUncoloredTilingPattern::~PSUncoloredTilingPattern () { - if (_applied) - setGroupNode(0); // prevent deleting the group node in the parent destructor -} - - /** Returns an SVG id value that identifies this pattern with the current color applied. */ string PSUncoloredTilingPattern::svgID () const { ostringstream oss; - oss << PSPattern::svgID() << '-' << hex << _currentColor; + oss << PSPattern::svgID() << '-' << hex << uint32_t(_currentColor); return oss.str(); } @@ -149,15 +148,16 @@ void PSUncoloredTilingPattern::apply (SpecialActions &actions) { set<Color>::iterator it=_colors.find(_currentColor); if (it == _colors.end()) { if (_applied) - setGroupNode(static_cast<XMLElementNode*>(getGroupNode()->clone())); + setGroupNode(util::static_unique_ptr_cast<XMLElementNode>(getGroupNode()->clone())); // assign current color to the pattern graphic vector<XMLElementNode*> colored_elems; - const char *attribs[] = {"fill", "stroke"}; - for (int i=0; i < 2; i++) { - getGroupNode()->getDescendants(0, attribs[i], colored_elems); - for (XMLElementNode *elem : colored_elems) - if (string(elem->getAttributeValue(attribs[i])) != "none") - elem->addAttribute(attribs[i], _currentColor.svgColorString()); + const array<const char*, 2> attribs = {{"fill", "stroke"}}; + for (const char *attrib : attribs) { + getGroupNode()->getDescendants(nullptr, attrib, colored_elems); + for (XMLElementNode *elem : colored_elems) { + if (string(elem->getAttributeValue(attrib)) != "none") + elem->addAttribute(attrib, _currentColor.svgColorString()); + } colored_elems.clear(); } PSPattern::apply(actions); @@ -167,9 +167,9 @@ void PSUncoloredTilingPattern::apply (SpecialActions &actions) { } -XMLElementNode* PSUncoloredTilingPattern::createClipNode() const { +unique_ptr<XMLElementNode> PSUncoloredTilingPattern::createClipNode() const { // only the first instance of this patterns get a clip element if (_colors.empty()) return PSTilingPattern::createClipNode(); - return 0; + return nullptr; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp index 122ae590f82..ec2a6949331 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp @@ -2,7 +2,7 @@ ** PSPattern.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,19 +21,20 @@ #ifndef PSPATTERN_HPP #define PSPATTERN_HPP +#include <memory> #include <set> #include <string> #include "BoundingBox.hpp" #include "Color.hpp" #include "Matrix.hpp" +#include "XMLNode.hpp" class SpecialActions; class SVGTree; class XMLElementNode; -class PSPattern -{ +class PSPattern { public: virtual ~PSPattern () =default; virtual int psID () const {return _id;} @@ -42,54 +43,50 @@ class PSPattern protected: PSPattern (int id) : _id(id) {} - virtual XMLElementNode* createPatternNode () const =0; + virtual std::unique_ptr<XMLElementNode> createPatternNode () const =0; private: int _id; ///< PostSCript ID of this pattern }; -class PSTilingPattern : public PSPattern -{ +class PSTilingPattern : public PSPattern { public: - ~PSTilingPattern (); - virtual XMLElementNode* getContainerNode () {return _groupNode;} + virtual XMLElementNode* getContainerNode () {return _groupNode.get();} void apply (SpecialActions &actions) override; protected: PSTilingPattern (int id, BoundingBox &bbox, Matrix &matrix, double xstep, double ystep); - XMLElementNode* createPatternNode () const override; - virtual XMLElementNode* createClipNode () const; - virtual XMLElementNode* createGroupNode () const; - virtual XMLElementNode* getGroupNode () const {return _groupNode;} - virtual void setGroupNode (XMLElementNode *node) {_groupNode = node;} + std::unique_ptr<XMLElementNode> createPatternNode () const override; + virtual std::unique_ptr<XMLElementNode> createClipNode () const; + virtual std::unique_ptr<XMLElementNode> createGroupNode () const; + virtual XMLElementNode* getGroupNode () const {return _groupNodePtr;} + virtual void setGroupNode (std::unique_ptr<XMLElementNode> &&node); private: BoundingBox _bbox; ///< bounding box of the tile graphics Matrix _matrix; ///< tile transformation double _xstep, _ystep; ///< horizontal and vertical distance between neighboured tiles - XMLElementNode *_groupNode; ///< group containing the drawing elements + mutable std::unique_ptr<XMLElementNode> _groupNode; ///< group containing the drawing elements + XMLElementNode *_groupNodePtr; ///< keeps a pointer to the group node even after moving _groupNode to the SVGTree }; -class PSColoredTilingPattern : public PSTilingPattern -{ +class PSColoredTilingPattern final : public PSTilingPattern { public: PSColoredTilingPattern (int id, BoundingBox &bbox, Matrix &matrix, double xstep, double ystep); }; -class PSUncoloredTilingPattern : public PSTilingPattern -{ +class PSUncoloredTilingPattern final : public PSTilingPattern { public: PSUncoloredTilingPattern (int id, BoundingBox &bbox, Matrix &matrix, double xstep, double ystep); - ~PSUncoloredTilingPattern (); std::string svgID () const override; void setColor (Color color) {_currentColor = color;} void apply (SpecialActions &actions) override; protected: - XMLElementNode* createClipNode () const override; + std::unique_ptr<XMLElementNode> createClipNode () const override; private: std::set<Color> _colors; ///< colors this pattern has already been drawn with diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.cpp index 7ad11c04d6a..efe5835981e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.cpp @@ -2,7 +2,7 @@ ** PSPreviewFilter.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <vector> #include "InputBuffer.hpp" #include "InputReader.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp index 0479120391c..62a40699145 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp @@ -2,7 +2,7 @@ ** PSPreviewFilter.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp index c2f3b4f3ad5..29627b1be2e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp @@ -2,7 +2,7 @@ ** PageRanges.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <sstream> #include "InputBuffer.hpp" #include "InputReader.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.hpp index 61f04f7225a..28fa5a7b914 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.hpp @@ -2,7 +2,7 @@ ** PageRanges.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp index a1a5dd41ce8..4f4cc448ecc 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp @@ -2,7 +2,7 @@ ** PageSize.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <cctype> #include <cmath> @@ -29,40 +28,39 @@ using namespace std; -/** Computes width and height of ISO/DIN An in millimeters. +/** Computes width and height of ISO/DIN An. * @param[in] n the A level (e.g. n=4 => DIN A4) * @param[out] width contains the page width when function returns * @param[out] height contains the page height when function returns */ -static void computeASize (int n, double &width, double &height) { - double sqrt2 = sqrt(2.0); - height = floor(1189.0/pow(sqrt2, n)+0.5); - width = floor(height/sqrt2+0.5); +static void computeASize (int n, Length &width, Length &height) { + height.set(floor(1189.0/pow(math::SQRT2, n)+0.5), Length::Unit::MM); + width.set(floor(height.mm()/math::SQRT2+0.5), Length::Unit::MM); } -/** Computes width and height of ISO/DIN Bn in millimeters. +/** Computes width and height of ISO/DIN Bn. * @param[in] n the B level (e.g. n=4 => DIN B4) * @param[out] width contains the page width when function returns * @param[out] height contains the page height when function returns */ -static void computeBSize (int n, double &width, double &height) { - double w, h; +static void computeBSize (int n, Length &width, Length &height) { + Length w, h; computeASize(n, width, height); computeASize(n-1, w, h); - width = floor(sqrt(width * w)+0.5); - height = floor(sqrt(height * h)+0.5); + width.set(floor(sqrt(width.mm() * w.mm())+0.5), Length::Unit::MM); + height.set(floor(sqrt(height.mm() * h.mm())+0.5), Length::Unit::MM); } -/** Computes width and height of ISO/DIN Cn in millimeters. +/** Computes width and height of ISO/DIN Cn. * @param[in] n the C level (e.g. n=4 => DIN C4) * @param[out] width contains the page width when function returns * @param[out] height contains the page height when function returns */ -static void computeCSize (int n, double &width, double &height) { - double w, h; +static void computeCSize (int n, Length &width, Length &height) { + Length w, h; computeASize(n, width, height); computeBSize(n, w, h); - width = floor(sqrt(width * w)+0.5); - height = floor(sqrt(height * h)+0.5); + width.set(floor(sqrt(width.mm() * w.mm())+0.5), Length::Unit::MM); + height.set(floor(sqrt(height.mm() * h.mm())+0.5), Length::Unit::MM); } @@ -70,12 +68,12 @@ static void computeCSize (int n, double &width, double &height) { * @param[in] n the D level (e.g. n=4 => DIN D4) * @param[out] width contains the page width when function returns * @param[out] height contains the page height when function returns */ -static void computeDSize (int n, double &width, double &height) { - double w, h; +static void computeDSize (int n, Length &width, Length &height) { + Length w, h; computeASize(n, width, height); computeBSize(n+1, w, h); - width = floor(sqrt(width * w)+0.5); - height = floor(sqrt(height * h)+0.5); + width.set(floor(sqrt(width.mm() * w.mm())+0.5), Length::Unit::MM); + height.set(floor(sqrt(height.mm() * h.mm())+0.5), Length::Unit::MM); } @@ -86,16 +84,17 @@ PageSize::PageSize (const string &name) : _width(0), _height(0) { } -void PageSize::resize (double w, double h) { +void PageSize::resize (Length w, Length h) { _width = w; _height = h; } + void PageSize::resize (string name) { if (name.length() < 2) throw PageSizeException("unknown page format: "+name); - util::tolower(name); + name = util::tolower(name); // extract optional suffix size_t pos = name.rfind("-"); bool landscape = false; @@ -109,24 +108,24 @@ void PageSize::resize (string name) { } if (name == "invoice") { - _width = 140; - _height = 216; + _width = 140_mm; + _height = 216_mm; } else if (name == "executive") { - _width = 184; - _height = 267; + _width = 184_mm; + _height = 267_mm; } else if (name == "legal") { - _width = 216; - _height = 356; + _width = 216_mm; + _height = 356_mm;; } else if (name == "letter") { - _width = 216; - _height = 279; + _width = 216_mm; + _height = 279_mm; } else if (name == "ledger") { - _width = 279; - _height = 432; + _width = 279_mm;; + _height = 432_mm; } else if (isdigit(name[1]) && name.length() < 5) { // limit length of number to prevent arithmetic errors istringstream iss(name.substr(1)); @@ -140,13 +139,8 @@ void PageSize::resize (string name) { default : throw PageSizeException("invalid page format: "+name); } } - if (_width == 0 || _height == 0) + if (_width.pt() == 0 || _height.pt() == 0) throw PageSizeException("unknown page format: "+name); if (landscape) swap(_width, _height); - - const double bppmm = 72/25.4; // PS points per millimeter (72pt = 1in = 25.4mm) - _width *= bppmm; - _height *= bppmm; } - diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp index 9c0dced9491..f9db51b4bc1 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp @@ -2,7 +2,7 @@ ** PageSize.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,28 +21,26 @@ #ifndef PAGESIZE_HPP #define PAGESIZE_HPP +#include "Length.hpp" #include "MessageException.hpp" -struct PageSizeException : public MessageException -{ +struct PageSizeException : public MessageException { PageSizeException (const std::string &msg) : MessageException(msg) {} }; -class PageSize -{ +class PageSize { public: - PageSize (double w=0, double h=0) : _width(w), _height(h) {} + PageSize () =default; + PageSize (Length w, Length h) : _width(w), _height(h) {} PageSize (const std::string &name); void resize (std:: string name); - void resize (double w, double h); - double widthInBP () const {return _width;} - double heightInBP () const {return _height;} - double widthInMM () const {return _width*25.4/72;} - double heightInMM () const {return _height*25.4/72;} - bool valid () const {return _width > 0 && _height > 0;} + void resize (Length w, Length h); + Length width () const {return _width;} + Length height () const {return _height;} + bool valid () const {return _width.pt() > 0 && _height.pt() > 0;} private: - double _width, _height; // in PS points + Length _width, _height; }; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp index c9058a3ff69..a3747faeb57 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp @@ -2,7 +2,7 @@ ** Pair.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -34,6 +34,7 @@ class Pair Pair operator -= (const Pair &p) {_x -= p._x; _y -= p._y; return *this;} Pair operator *= (T c) {_x *= c; _y *= c; return *this;} Pair operator /= (T c) {_x /= c; _y /= c; return *this;} + Pair operator - () const {return Pair(-_x, -_y);} Pair ortho () const {return Pair(-_y, _x);} double length () const {return std::sqrt(_x*_x + _y*_y);} bool operator == (const Pair &p) const {return _x == p._x && _y == p._y;} @@ -48,6 +49,10 @@ class Pair T _x, _y; }; +template <typename T> +inline Pair<T> abs (const Pair<T> &p) { + return Pair<T>(std::abs(p.x()), std::abs(p.y())); +} struct Pair32 : public Pair<int32_t> { diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PapersizeSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PapersizeSpecialHandler.cpp index 031d59ffaf0..00cd7428757 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PapersizeSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PapersizeSpecialHandler.cpp @@ -2,7 +2,7 @@ ** PapersizeSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include "Length.hpp" #include "Message.hpp" #include "PapersizeSpecialHandler.hpp" #include "SpecialActions.hpp" @@ -30,21 +29,18 @@ void PapersizeSpecialHandler::preprocess (const char*, std::istream &is, Special is >> params; Length w, h; size_t splitpos = params.find(','); - if (splitpos == string::npos) { - w.set(params); - h.set(params); + try { + if (splitpos == string::npos) { + w.set(params); + h.set(params); + } + else { + w.set(params.substr(0, splitpos)); + h.set(params.substr(splitpos+1)); + } + storePaperSize(actions.getCurrentPageNumber(), w, h); } - else { - w.set(params.substr(0, splitpos)); - h.set(params.substr(splitpos+1)); - } - DoublePair whpair(w.bp(), h.bp()); - if (_pageSizes.empty() || _pageSizes.back().second != whpair) { - unsigned pageno = actions.getCurrentPageNumber(); - if (!_pageSizes.empty() && _pageSizes.back().first == pageno) - _pageSizes.back().second = whpair; - else - _pageSizes.emplace_back(PageSize(pageno, whpair)); + catch (UnitException &e) { // ignore invalid length units for now } } @@ -54,18 +50,28 @@ bool PapersizeSpecialHandler::process (const char*, std::istream&, SpecialAction } -void PapersizeSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) { - if (actions.getBBoxFormatString() != "papersize") - return; +/** Records a paper size for a given page number for later processing. This function doesn't + * assign them to the page. */ +void PapersizeSpecialHandler::storePaperSize (unsigned pageno, Length width, Length height) { + DoublePair whpair(width.bp(), height.bp()); + if (_pageSizes.empty() || _pageSizes.back().second != whpair) { + if (!_pageSizes.empty() && _pageSizes.back().first == pageno) + _pageSizes.back().second = whpair; + else + _pageSizes.emplace_back(PageSize(pageno, whpair)); + } +} + +/** Applies the previously recorded size to a given page. */ +void PapersizeSpecialHandler::applyPaperSize (unsigned pageno, SpecialActions &actions) { // find page n >= pageno that contains a papersize special - typedef vector<PageSize>::iterator Iterator; - Iterator lb_it = lower_bound(_pageSizes.begin(), _pageSizes.end(), PageSize(pageno, DoublePair()), + auto lb_it = lower_bound(_pageSizes.begin(), _pageSizes.end(), PageSize(pageno, DoublePair()), [](const PageSize &ps1, const PageSize &ps2) { // order PageSize objects by page number return ps1.first < ps2.first; }); - Iterator it = _pageSizes.end(); + auto it = _pageSizes.end(); if (lb_it != _pageSizes.end() && lb_it->first == pageno) it = lb_it; // if current page contains a papersize special, use it else if (lb_it != _pageSizes.begin()) // no papersize special on current page? @@ -80,7 +86,13 @@ void PapersizeSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actio } -const char** PapersizeSpecialHandler::prefixes () const { - static const char *pfx[] = {"papersize=", 0}; +void PapersizeSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) { + if (actions.getBBoxFormatString() == "papersize") + applyPaperSize(pageno, actions); +} + + +const vector<const char*> PapersizeSpecialHandler::prefixes () const { + const vector<const char*> pfx {"papersize="}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PapersizeSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PapersizeSpecialHandler.hpp index 211920a9340..c38b58cd649 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PapersizeSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PapersizeSpecialHandler.hpp @@ -2,7 +2,7 @@ ** PapersizeSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,26 +23,28 @@ #include <utility> #include <vector> +#include "Length.hpp" #include "SpecialHandler.hpp" class PapersizeSpecialHandler : public SpecialHandler, public DVIEndPageListener { - typedef std::pair<double,double> DoublePair; - typedef std::pair<unsigned,DoublePair> PageSize; + using DoublePair = std::pair<double,double>; // (width, height) + using PageSize = std::pair<unsigned,DoublePair>; // page number -> (width, height) public: void preprocess (const char *prefix, std::istream &is, SpecialActions &actions) override; bool process (const char *prefix, std::istream &is, SpecialActions &actions) override; const char* info () const override {return "special to set the page size";} const char* name () const override {return "papersize";} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; + void storePaperSize (unsigned pageno, Length width, Length height); void reset () {_pageSizes.clear();} protected: void dviEndPage (unsigned pageno, SpecialActions &actions) override; + void applyPaperSize (unsigned pageno, SpecialActions &actions); private: std::vector<PageSize> _pageSizes; }; #endif - diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp index 7fa21855b23..ceb550ea815 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp @@ -2,7 +2,7 @@ ** PathClipper.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,16 +18,15 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include "Bezier.hpp" #include "PathClipper.hpp" using namespace std; using namespace ClipperLib; -typedef ClipperLib::Path Polygon; -typedef ClipperLib::Paths Polygons; -typedef PathClipper::CurvedPath CurvedPath; +using Polygon = ClipperLib::Path; +using Polygons = ClipperLib::Paths; +using CurvedPath = PathClipper::CurvedPath; const int SCALE_FACTOR = 1000; @@ -192,12 +191,6 @@ static int32_t segment_id (const IntPoint &p1, const IntPoint &p2, double &t1, d } -inline int32_t edge_id (const IntPoint &p1, const IntPoint &p2) { - double t=0; - return segment_id(p1, p2, t, t); -} - - /** This function expects 3 colinear points p1, p2, and q, where q lies between p1 and p2, * i.e. q divides the line \f$ \overline{p_1 p_2} \f$ somewhere. The function returns * the corresponding division ratio. */ diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.hpp index b265c9de0cf..72ce9a47695 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.hpp @@ -2,7 +2,7 @@ ** PathClipper.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -34,7 +34,7 @@ using ClipperLib::IntPoint; class PathClipper { public: - typedef GraphicsPath<double> CurvedPath; + using CurvedPath = GraphicsPath<double>; public: PathClipper () : _numLines(0) {} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp index f5e6026bc99..99d6e370190 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp @@ -2,7 +2,7 @@ ** PdfSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,58 +18,282 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> +#include <array> #include <cstring> +#include <unordered_map> +#include <utility> +#include "Color.hpp" +#include "HyperlinkManager.hpp" #include "InputReader.hpp" #include "MapLine.hpp" #include "PdfSpecialHandler.hpp" #include "FontMap.hpp" #include "Message.hpp" +#include "PapersizeSpecialHandler.hpp" +#include "PDFParser.hpp" +#include "SpecialActions.hpp" +#include "SpecialManager.hpp" using namespace std; -PdfSpecialHandler::PdfSpecialHandler () : _maplineProcessed(false) +using CmdHandler = void (PdfSpecialHandler::*)(StreamInputReader&, SpecialActions&); + + +PdfSpecialHandler::PdfSpecialHandler () : _active(false), _maplineProcessed(false) { } -bool PdfSpecialHandler::process (const char *prefix, istream &is, SpecialActions &actions) { +void PdfSpecialHandler::preprocess (const char*, istream &is, SpecialActions &actions) { + StreamInputReader ir(is); + ir.skipSpace(); + string cmdstr = ir.getWord(); + static unordered_map<string, CmdHandler> commands = { + {"bann", &PdfSpecialHandler::preprocessBeginAnn}, + {"bannot", &PdfSpecialHandler::preprocessBeginAnn}, + {"beginann", &PdfSpecialHandler::preprocessBeginAnn}, + {"dest", &PdfSpecialHandler::preprocessDest}, + {"pagesize", &PdfSpecialHandler::preprocessPagesize} + }; + auto it = commands.find(cmdstr); + if (it != commands.end()) + (this->*it->second)(ir, actions); +} + + +bool PdfSpecialHandler::process (const char*, istream &is, SpecialActions &actions) { + _active = true; StreamInputReader ir(is); ir.skipSpace(); - string cmd = ir.getWord(); + string cmdstr = ir.getWord(); ir.skipSpace(); - if (cmd == "mapline" || cmd == "mapfile") { - // read mode selector ('+', '-', or '=') - char modechar = '+'; // default mode (append if new, do not replace existing mapping) - if (strchr("=+-", ir.peek())) // leading modifier given? - modechar = char(ir.get()); - else if (!_maplineProcessed) { // no modifier given? - // remove default map entries if this is the first mapline/mapfile special called - FontMap::instance().clear(); - } + // dvipdfm(x) specials currently supported + static unordered_map<string, CmdHandler> commands = { + {"bann", &PdfSpecialHandler::processBeginAnn}, + {"bannot", &PdfSpecialHandler::processBeginAnn}, + {"beginann", &PdfSpecialHandler::processBeginAnn}, + {"eann", &PdfSpecialHandler::processEndAnn}, + {"eannot", &PdfSpecialHandler::processEndAnn}, + {"endann", &PdfSpecialHandler::processEndAnn}, + {"dest", &PdfSpecialHandler::processDest}, + {"mapfile", &PdfSpecialHandler::processMapfile}, + {"mapline", &PdfSpecialHandler::processMapline} + }; + auto it = commands.find(cmdstr); + if (it != commands.end()) + (this->*it->second)(ir, actions); + return true; +} + + +static char prepare_mode (InputReader &ir, bool maplineProcessed) { + // read mode selector ('+', '-', or '=') + char modechar = '+'; // default mode (append if new, do not replace existing mapping) + if (strchr("=+-", ir.peek())) // leading modifier given? + modechar = static_cast<char>(ir.get()); + else if (!maplineProcessed) { // no modifier given? + // remove default map entries if this is the first mapline/mapfile special called + FontMap::instance().clear(); + } + return modechar; +} - if (cmd == "mapline") { - try { - MapLine mapline(is); - FontMap::instance().apply(mapline, modechar); + +/** Sets the page size. This command is similar to the papersize special. + * Syntax pdf:pagesize (<dimname> <dimlenhth>)+ */ +void PdfSpecialHandler::preprocessPagesize (StreamInputReader &ir, SpecialActions &actions) { + // add page sizes to collection of paper sizes in order to handle them equally + SpecialHandler *handler = SpecialManager::instance().findHandlerByName("papersize"); + if (auto *papersizeHandler = dynamic_cast<PapersizeSpecialHandler*>(handler)) { + try { + Length width, height; + // parse parameter sequence of the form (name length)+ + while (!ir.eof()) { + string dimname = ir.getWord(); + string lenstr = ir.getString(" \t"); + // only consider width and height settings + if (dimname == "width" && !lenstr.empty()) + width.set(lenstr); + else if (dimname == "height" && !lenstr.empty()) + height.set(lenstr); } - catch (const MapLineException &ex) { - Message::wstream(true) << "pdf:mapline: " << ex.what() << '\n'; + papersizeHandler->storePaperSize(actions.getCurrentPageNumber(), width, height); + } + catch (UnitException &e) { // ignore invalid length units for now + } + } +} + + +void PdfSpecialHandler::processMapfile (StreamInputReader &ir, SpecialActions&) { + char modechar = prepare_mode(ir, _maplineProcessed); + string fname = ir.getString(); + if (!FontMap::instance().read(fname, modechar)) + Message::wstream(true) << "can't open map file " << fname << '\n'; +} + + +void PdfSpecialHandler::processMapline (StreamInputReader &ir, SpecialActions&) { + char modechar = prepare_mode(ir, _maplineProcessed); + try { + MapLine mapline(ir.getStream()); + FontMap::instance().apply(mapline, modechar); + } + catch (const MapLineException &ex) { + Message::wstream(true) << "pdf:mapline: " << ex.what() << '\n'; + } +} + + +/** Defines a named destination, e.g. a link target. + * Syntax: dest PDFString PDFDest */ +void PdfSpecialHandler::preprocessDest (StreamInputReader &ir, SpecialActions &actions) { + PDFParser parser; + vector<PDFObject> objects = parser.parse(ir, [&](const string &opname, vector<PDFObject> &objects) { + if (!opname.empty() && opname[0] == '@') { + if (opname == "@thispage") + objects.emplace_back(static_cast<int>(actions.getCurrentPageNumber())); + else if (opname == "@xpos") + objects.emplace_back(actions.getX()); + else if (opname == "@ypos") + objects.emplace_back(actions.getY()); + } + }); + if (objects.size() < 2) + return; + auto *name = objects[0].get<string>(); + auto *dest = objects[1].get<PDFArray>(); + // get target info from array [pageno /XYZ xpos ypos zpos] + if (name && dest && dest->size() >= 4 && dest->at(0).get<int>()) { + int pageno = *dest->at(0).get<int>(); + HyperlinkManager::instance().addNameAchor(*name, pageno); + } +} + + +/** Extracts the URI from a PDF annotation dictionary. "GoTo" targets (named anchors) + * are prefixed with a '#'. + * @param[in] annotDict annotation dictionary containing the target URI + * @return the URI if one was found, "" otherwise */ +static string get_uri (const PDFDict &annotDict) { + // At the moment, we only support link annotations + const PDFObject *type = annotDict.get("Type"); + if (type && string(*type) == "Annot") { + const PDFObject *subtype = annotDict.get("Subtype"); + if (subtype && string(*subtype) == "Link") { + const PDFObject *dict = annotDict.get("A"); + if (const PDFDict *actionDict = dict->get<PDFDict>()) { + if (const PDFObject *s = actionDict->get("S")) { + if (string(*s) == "GoTo") { + if (const PDFObject *dest = actionDict->get("D")) + return "#" + string(*dest); + } + else if (string(*s) == "URI") { + if (const PDFObject *uri = actionDict->get("URI")) + return string(*uri); + } + } } } - else { // mapfile - string fname = ir.getString(); - if (!FontMap::instance().read(fname, modechar)) - Message::wstream(true) << "can't open map file " << fname << '\n'; + } + return ""; +} + + +void PdfSpecialHandler::preprocessBeginAnn (StreamInputReader &ir, SpecialActions&) { + PDFParser parser; + vector<PDFObject> pdfobjs = parser.parse(ir); + if (pdfobjs.empty() || !pdfobjs[0].get<PDFDict>()) + return; + const PDFDict &annotDict = *pdfobjs[0].get<PDFDict>(); + string uri = get_uri(annotDict); + if (!uri.empty()) + HyperlinkManager::instance().addHrefAnchor(uri); +} + + +/** Converts a PDFObject to a Color, where a single number denotes a gray value. + * Number arrays are treated as gray, RGB, or CMYK colors depending on the + * number of components. */ +static Color to_color (const PDFObject &obj) { + Color color; + if (obj.get<int>() || obj.get<double>()) + color.setGray(double(obj)); + else if (auto *colorArray = obj.get<PDFArray>()) { + size_t size = min(size_t(4), colorArray->size()); + valarray<double> colorComps(size); + for (size_t i=0; i < size; i++) + colorComps[i] = double(colorArray->at(i)); + switch (size) { + case 1: color.setGray(colorComps); break; + case 3: color.setRGB(colorComps); break; + case 4: color.setCMYK(colorComps); break; } - _maplineProcessed = true; } - return true; + return color; +} + + +/** Begins a breakable annotation, e.g. a hyperlink. + * Syntax: beginann PDFDict */ +void PdfSpecialHandler::processBeginAnn (StreamInputReader &ir, SpecialActions &actions) { + PDFParser parser; + vector<PDFObject> pdfobjs = parser.parse(ir); + if (pdfobjs.empty() || !pdfobjs[0].get<PDFDict>()) + return; + const PDFDict &annotDict = *pdfobjs[0].get<PDFDict>(); + string uri = get_uri(annotDict); + if (uri.empty()) + return; + + // check presence of entry /Border [hr vr bw] defining the horizontal/vertical + // corner radius and the border width + auto it = annotDict.find("Border"); + if (it != annotDict.end() && it->second.get<PDFArray>() && it->second.get<PDFArray>()->size() > 2) + HyperlinkManager::instance().setLineWidth(double(it->second.get<PDFArray>()->at(2))); + + // check presence of entry /C defining the border color + it = annotDict.find("C"); + if (it != annotDict.end()) + HyperlinkManager::setDefaultLinkColor(to_color(it->second)); + HyperlinkManager::instance().createLink(uri, actions); +} + + +/** Terminates the preceding breakable annotation. + * Syntax: endann */ +void PdfSpecialHandler::processEndAnn (StreamInputReader&, SpecialActions &actions) { + HyperlinkManager::instance().closeAnchor(actions); +} + + +void PdfSpecialHandler::processDest (StreamInputReader &ir, SpecialActions &actions) { + PDFParser parser; + vector<PDFObject> objects = parser.parse(ir); + if (!objects.empty()) { + if (auto *name = objects[0].get<string>()) + HyperlinkManager::instance().setActiveNameAnchor(*name, actions); + } +} + + +/** This method is called every time the DVI position changes. */ +void PdfSpecialHandler::dviMovedTo (double x, double y, SpecialActions &actions) { + if (_active) + HyperlinkManager::instance().checkNewLine(actions); +} + + +void PdfSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) { + if (_active) { + HyperlinkManager::instance().createViews(pageno, actions); + _active = false; + } } -const char** PdfSpecialHandler::prefixes () const { - static const char *pfx[] = {"pdf:", 0}; +const vector<const char*> PdfSpecialHandler::prefixes () const { + const vector<const char*> pfx {"pdf:"}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.hpp index cca0d07fc83..f2d145c1328 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.hpp @@ -2,7 +2,7 @@ ** PdfSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,16 +23,33 @@ #include "SpecialHandler.hpp" -class PdfSpecialHandler : public SpecialHandler -{ +class StreamInputReader; + +class PdfSpecialHandler : public SpecialHandler, public DVIPositionListener, public DVIEndPageListener { public: PdfSpecialHandler (); - const char* info () const override {return "pdfTeX font map specials";} + const char* info () const override {return "PDF hyperlink, font map, and pagesize specials";} const char* name () const override {return "pdf";} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; + void preprocess (const char *prefix, std::istream &is, SpecialActions &actions) override; bool process (const char *prefix, std::istream &is, SpecialActions &actions) override; + protected: + // handlers for corresponding PDF specials + void preprocessBeginAnn (StreamInputReader &ir, SpecialActions &actions); + void preprocessDest (StreamInputReader &ir, SpecialActions &actions); + void preprocessPagesize (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; + private: + bool _active; bool _maplineProcessed; ///< true if a mapline or mapfile special has already been processed }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PreScanDVIReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PreScanDVIReader.cpp index 0f831439c60..05c4a6e82d2 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PreScanDVIReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PreScanDVIReader.cpp @@ -2,7 +2,7 @@ ** PreScanDVIReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PreScanDVIReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PreScanDVIReader.hpp index b543490c8a4..eb646e9a7a7 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PreScanDVIReader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PreScanDVIReader.hpp @@ -2,7 +2,7 @@ ** PreScanDVIReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp index 16c2d41b3c4..238bacb2373 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp @@ -2,7 +2,7 @@ ** Process.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,15 +18,13 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> - #ifdef _WIN32 - #include <windows.h> + #include "windows.hpp" #else #include <fcntl.h> #include <sys/wait.h> - #include <unistd.h> #include <signal.h> + #include <unistd.h> #endif #include <cstdlib> @@ -36,43 +34,208 @@ using namespace std; + +/** Helper class that encapsulates the system-specific parts of + * running a subprocess and retrieving its terminal output. */ +class Subprocess { + public: + enum class State {RUNNING, FINISHED, FAILED}; + + public: + Subprocess (); + Subprocess (const Subprocess&) =delete; + Subprocess (Subprocess&&) =delete; + ~Subprocess (); + bool run (const string &cmd, string params); + bool readFromPipe (string &out); + State state (); + + private: +#ifdef _WIN32 + HANDLE _pipeReadHandle; ///< handle of read end of pipe + HANDLE _childProcHandle; ///< handle of child process +#else + int _readfd; ///< file descriptor of read end of pipe + pid_t _pid; ///< PID of the subprocess +#endif +}; + + Process::Process (const string &cmd, const string ¶mstr) : _cmd(cmd), _paramstr(paramstr) { } -#ifdef _WIN32 -static void pipe_read (HANDLE handle, string &out) { - char buf[4096]; - out.clear(); +/** Runs the process and waits until it's finished. + * @param[out] out takes the output written to stdout by the executed subprocess + * @return true if process terminated properly + * @throw SignalException if CTRL-C was pressed during execution */ +bool Process::run (string *out) { + Subprocess subprocess; + if (!subprocess.run(_cmd, _paramstr)) + return false; for (;;) { - DWORD num_chars; - bool success = ReadFile(handle, buf, 1024, &num_chars, NULL); - if (!success || num_chars == 0) - break; - out.append(buf, num_chars); + if (out) + subprocess.readFromPipe(*out); + Subprocess::State state = subprocess.state(); + if (state != Subprocess::State::RUNNING) + return state == Subprocess::State::FINISHED; + SignalHandler::instance().check(); } - // remove trailing space - if (!out.empty()) { - int pos = out.size()-1; - while (pos >= 0 && isspace(out[pos])) - pos--; - out.erase(pos+1); +} + + +/** Runs the process in the given working directory and waits until it's finished. + * @param[in] dir working directory + * @param[out] out takes the output written to stdout by the executed process + * @return true if process terminated properly + * @throw SignalException if CTRL-C was pressed during execution */ +bool Process::run (const string &dir, string *out) { + bool ret = false; + string cwd = FileSystem::getcwd(); + if (FileSystem::chdir(dir)) { + ret = run(out); + ret &= FileSystem::chdir(cwd); } + return ret; } +// system-specific stuff -static inline void close_handle (HANDLE handle) { - if (handle != NULL) - CloseHandle(handle); +#ifdef _WIN32 + +static inline void close_and_zero_handle (HANDLE &handle) { + CloseHandle(handle); + handle = NULL; } -#else -/** Extracts whitespace-sparated parameters from a string. +Subprocess::Subprocess() : _pipeReadHandle(NULL), _childProcHandle(NULL) { +} + + +Subprocess::~Subprocess () { + if (_pipeReadHandle != NULL) + CloseHandle(_pipeReadHandle); + if (_childProcHandle != NULL) { + TerminateProcess(_childProcHandle, 1); + CloseHandle(_childProcHandle); + } +} + + +/** Retrieves output generated by child process. + * @param[out] out read output is appended to this string + * @returns false on errors */ +bool Subprocess::readFromPipe (string &out) { + if (!_pipeReadHandle) + return false; + + bool success=false; + DWORD len; + while (PeekNamedPipe(_pipeReadHandle, NULL, 0, NULL, &len, NULL) && len > 0) { // prevent blocking + char buf[4096]; + success = ReadFile(_pipeReadHandle, buf, sizeof(buf), &len, NULL); + if (success && len > 0) + out.append(buf, len); + } + return success; +} + + +/** Starts a child process. + * @param[in] cmd name of command to execute + * @param[in] paramstr parameters required by command + * @returns true if child process started properly */ +bool Subprocess::run (const string &cmd, string paramstr) { + SECURITY_ATTRIBUTES securityAttribs; + ZeroMemory(&securityAttribs, sizeof(SECURITY_ATTRIBUTES)); + securityAttribs.nLength = sizeof(SECURITY_ATTRIBUTES); + securityAttribs.bInheritHandle = true; + + HANDLE pipeWriteHandle; // write end of pipe + if (CreatePipe(&_pipeReadHandle, &pipeWriteHandle, &securityAttribs, 0) == ERROR_INVALID_HANDLE) + return false; + + SetHandleInformation(_pipeReadHandle, HANDLE_FLAG_INHERIT, 0); + HANDLE nullFile = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &securityAttribs, OPEN_EXISTING, 0, NULL); + bool success = false; + if (nullFile != INVALID_HANDLE_VALUE) { + STARTUPINFO startupInfo; + ZeroMemory(&startupInfo, sizeof(STARTUPINFO)); + startupInfo.cb = sizeof(STARTUPINFO); + startupInfo.dwFlags = STARTF_USESTDHANDLES; + startupInfo.hStdInput = nullFile; + startupInfo.hStdOutput = pipeWriteHandle; + startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION processInfo; + ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION)); + + string cmdline = cmd + " " + paramstr; + // put subprocess in separate process group to prevent its termination in case of CTRL-C + success = CreateProcess(NULL, (LPSTR)cmdline.c_str(), NULL, NULL, true, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &startupInfo, &processInfo); + if (success) { + _childProcHandle = processInfo.hProcess; + CloseHandle(processInfo.hThread); + } + CloseHandle(nullFile); + } + CloseHandle(pipeWriteHandle); // must be closed before reading from pipe to prevent blocking + if (!success) + close_and_zero_handle(_pipeReadHandle); + return success; +} + + +/** Returns the current state of the child process. */ +Subprocess::State Subprocess::state () { + DWORD status; + if (!GetExitCodeProcess(_childProcHandle, &status)) + return State::FAILED; + if (status == STILL_ACTIVE) + return State::RUNNING; + close_and_zero_handle(_childProcHandle); + return status == 0 ? State::FINISHED : State::FAILED; +} + +#else // !_WIN32 + +Subprocess::Subprocess () : _readfd(-1), _pid(-1) { +} + + +Subprocess::~Subprocess () { + if (_readfd >= 0) + close(_readfd); + if (_pid > 0) + kill(_pid, SIGKILL); +} + + +/** Retrieves output generated by child process. + * @param[out] out read output is appended to this string + * @returns false on errors */ +bool Subprocess::readFromPipe (string &out) { + if (_readfd < 0 || _pid < 0) + return false; + + char buf[1024]; + ssize_t len; + while ((len = read(_readfd, buf, sizeof(buf))) > 0) + out.append(buf, len); + if (len < 0) { + close(_readfd); + _readfd = -1; + } + return len >= 0; +} + + +/** Extracts whitespace-separated parameters from a string. * @param[in,out] paramstr the parameter string - * @param[out] params vector holding the extracted parameters */ + * @param[out] params vector holding pointers to the extracted parameters */ static void split_paramstr (string ¶mstr, vector<const char*> ¶ms) { size_t left=0, right=0; // index of first and last character of current parameter char quote=0; // current quote character, 0=none @@ -99,119 +262,52 @@ static void split_paramstr (string ¶mstr, vector<const char*> ¶ms) { } } -#endif +/** Starts a child process. + * @param[in] cmd name of command to execute + * @param[in] paramstr parameters required by command + * @returns true if child process started properly */ +bool Subprocess::run (const string &cmd, string paramstr) { + int pipefd[2]; + if (pipe(pipefd) < 0) + return false; -/** Runs the process and waits until it's finished. - * @param[out] out takes the output written to stdout by the executed process - * @return true if process terminated properly - * @throw SignalException if CTRL-C was pressed during execution */ -bool Process::run (string *out) { -#ifdef _WIN32 - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = true; - - STARTUPINFO si; - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES; - HANDLE devnull = NULL; - HANDLE proc_read_handle = NULL; - HANDLE proc_write_handle = NULL; - if (out) { - CreatePipe(&proc_read_handle, &proc_write_handle, &sa, 0); - SetHandleInformation(proc_read_handle, HANDLE_FLAG_INHERIT, 0); - si.hStdOutput = proc_write_handle; - } - else { - devnull = CreateFile("nul", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - si.hStdOutput = devnull; - } - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(pi)); - DWORD exitcode = DWORD(-1); - string cmdline = _cmd+" "+_paramstr; - bool success = CreateProcess(NULL, (LPSTR)cmdline.c_str(), NULL, NULL, true, 0, NULL, NULL, &si, &pi); - if (success) { - WaitForSingleObject(pi.hProcess, INFINITE); - GetExitCodeProcess(pi.hProcess, &exitcode); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + _pid = fork(); + if (_pid < 0) { + close(pipefd[0]); + close(pipefd[1]); + return false; } - close_handle(proc_write_handle); // must be closed before reading from pipe to prevent blocking - if (success && out) - pipe_read(proc_read_handle, *out); - close_handle(proc_read_handle); - close_handle(devnull); - return exitcode == 0; -#else - int pipefd[2]; - pipe(pipefd); - pid_t pid = fork(); - if (pid == 0) { // child process + if (_pid == 0) { // child process dup2(pipefd[1], STDOUT_FILENO); // redirect stdout to the pipe dup2(pipefd[1], STDERR_FILENO); // redirect stderr to the pipe close(pipefd[0]); close(pipefd[1]); vector<const char*> params; - params.push_back(_cmd.c_str()); - string paramstr = _paramstr; // private copy to be changed by split_paramstr() + params.push_back(cmd.c_str()); split_paramstr(paramstr, params); - params.push_back(0); // trailing NULL marks end of parameter list - execvp(_cmd.c_str(), const_cast<char* const*>(¶ms[0])); + params.push_back(nullptr); // trailing null pointer marks end of parameter list + signal(SIGINT, SIG_IGN); // child process is supposed to ignore ctrl-c events + execvp(cmd.c_str(), const_cast<char* const*>(¶ms[0])); exit(1); } - close(pipefd[1]); - bool ok = false; - if (pid > 0) { // parent process - for (;;) { - if (out) { - char buf[512]; - ssize_t len; - while ((len = read(pipefd[0], buf, sizeof(buf)-1)) > 0) { - buf[len] = 0; - *out += string(buf); - } - } - int status; - waitpid(pid, &status, WNOHANG); - if (WIFEXITED(status)) { // child process exited normally - ok = (WEXITSTATUS(status) == 0); - break; - } - try { - SignalHandler::instance().check(); - } - catch (SignalException &e) { // caught ctrl-c - close(pipefd[0]); - kill(pid, SIGKILL); - throw; - } - } - } - close(pipefd[0]); - return ok; -#endif + _readfd = pipefd[0]; + close(pipefd[1]); // close write end of pipe + return true; } -/** Runs the process in the given working directory and waits until it's finished. - * @param[in] dir working directory - * @param[out] out takes the output written to stdout by the executed process - * @return true if process terminated properly - * @throw SignalException if CTRL-C was pressed during execution */ -bool Process::run (const string &dir, string *out) { - bool ret = false; - string cwd = FileSystem::getcwd(); - if (FileSystem::chdir(dir)) { - ret = run(out); - ret &= FileSystem::chdir(cwd); - } - return ret; +/** Returns the current state of the child process. */ +Subprocess::State Subprocess::state () { + int status; + pid_t wpid = waitpid(_pid, &status, WNOHANG); + if (wpid == 0) + return State::RUNNING; // still running + _pid = -1; + if (wpid > 0 && WIFEXITED(status) && WEXITSTATUS(status) == 0) + return State::FINISHED; + return State::FAILED; } + +#endif // !_WIN32 diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp index b45bdfe1fe4..caed7139439 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp @@ -2,7 +2,7 @@ ** Process.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,16 +23,14 @@ #include <string> -class Process -{ +class Process { public: Process (const std::string &cmd, const std::string ¶mstr); + Process (const Process &orig) =delete; + Process (Process &&orig) =delete; bool run (std::string *out=0); bool run (const std::string &dir, std::string *out=0); - protected: - Process (const Process &orig) =default; - private: std::string _cmd; const std::string _paramstr; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp index 9c60546bc0f..c0624cc8c8a 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp @@ -2,7 +2,7 @@ ** PsSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cmath> #include <fstream> #include <memory> @@ -53,15 +52,13 @@ int PsSpecialHandler::SHADING_SEGMENT_SIZE = 20; double PsSpecialHandler::SHADING_SIMPLIFY_DELTA = 0.01; -PsSpecialHandler::PsSpecialHandler () : _psi(this), _actions(0), _previewFilter(_psi), _psSection(PS_NONE), _xmlnode(0) +PsSpecialHandler::PsSpecialHandler () : _psi(this), _actions(), _previewFilter(_psi), _psSection(PS_NONE), _xmlnode(), _savenode() { } PsSpecialHandler::~PsSpecialHandler () { - _psi.setActions(0); // ensure no further PS actions are performed - for (auto &entry : _patterns) - delete entry.second; + _psi.setActions(nullptr); // ensure no further PS actions are performed } @@ -72,9 +69,8 @@ void PsSpecialHandler::initialize () { if (_psSection == PS_NONE) { initgraphics(); // execute dvips prologue/header files - const char *headers[] = {"tex.pro", "texps.pro", "special.pro", /*"color.pro",*/ 0}; - for (const char **p=headers; *p; ++p) - processHeaderFile(*p); + for (const char *fname : {"tex.pro", "texps.pro", "special.pro"}) + processHeaderFile(fname); // disable bop/eop operators to prevent side-effects by // unexpected bops/eops present in PS specials _psi.execute("\nTeXDict begin /bop{pop pop}def /eop{}def end "); @@ -88,10 +84,10 @@ void PsSpecialHandler::initgraphics () { _linewidth = 1; _linecap = _linejoin = 0; // butt end caps and miter joins _miterlimit = 4; - _xmlnode = _savenode = 0; + _xmlnode = _savenode = nullptr; _opacityalpha = 1; // fully opaque _sx = _sy = _cos = 1.0; - _pattern = 0; + _pattern = nullptr; _currentcolor = Color::BLACK; _dashoffset = 0; _dashpattern.clear(); @@ -214,7 +210,7 @@ bool PsSpecialHandler::process (const char *prefix, istream &is, SpecialActions if (_actions) { StreamInputReader in(is); string fname = in.getQuotedString(in.peek() == '"' ? '"' : 0); - map<string,string> attr; + unordered_map<string,string> attr; in.parseAttributes(attr); psfile(fname, attr); } @@ -273,87 +269,96 @@ bool PsSpecialHandler::process (const char *prefix, istream &is, SpecialActions /** Handles psfile special. * @param[in] fname EPS file to be included * @param[in] attr attributes given with \\special psfile */ -void PsSpecialHandler::psfile (const string &fname, const map<string,string> &attr) { - EPSFile epsfile(fname); - istream &is = epsfile.istream(); - if (!is) +void PsSpecialHandler::psfile (const string &fname, const unordered_map<string,string> &attr) { + const char *filepath = FileFinder::instance().lookup(fname, false); + if (!filepath) { Message::wstream(true) << "file '" << fname << "' not found in special 'psfile'\n"; - else { - map<string,string>::const_iterator it; - - // bounding box of EPS figure - double llx = (it = attr.find("llx")) != attr.end() ? str2double(it->second) : 0; - double lly = (it = attr.find("lly")) != attr.end() ? str2double(it->second) : 0; - double urx = (it = attr.find("urx")) != attr.end() ? str2double(it->second) : 0; - double ury = (it = attr.find("ury")) != attr.end() ? str2double(it->second) : 0; - - // desired width/height of resulting figure - double rwi = (it = attr.find("rwi")) != attr.end() ? str2double(it->second)/10.0 : -1; - double rhi = (it = attr.find("rhi")) != attr.end() ? str2double(it->second)/10.0 : -1; - if (rwi == 0 || rhi == 0 || urx-llx == 0 || ury-lly == 0) - return; - - // user transformations (default values chosen according to dvips manual) - double hoffset = (it = attr.find("hoffset")) != attr.end() ? str2double(it->second) : 0; - double voffset = (it = attr.find("voffset")) != attr.end() ? str2double(it->second) : 0; -// double hsize = (it = attr.find("hsize")) != attr.end() ? str2double(it->second) : 612; -// double vsize = (it = attr.find("vsize")) != attr.end() ? str2double(it->second) : 792; - double hscale = (it = attr.find("hscale")) != attr.end() ? str2double(it->second) : 100; - double vscale = (it = attr.find("vscale")) != attr.end() ? str2double(it->second) : 100; - double angle = (it = attr.find("angle")) != attr.end() ? str2double(it->second) : 0; - - Matrix m(1); - m.rotate(angle).scale(hscale/100, vscale/100).translate(hoffset, voffset); - BoundingBox bbox(llx, lly, urx, ury); - bbox.transform(m); - - double sx = rwi/bbox.width(); - double sy = rhi/bbox.height(); - if (sx < 0) sx = sy; - if (sy < 0) sy = sx; - if (sx < 0) sx = sy = 1.0; - - // save current DVI position (in pt units) - const double x = _actions->getX(); - const double y = _actions->getY(); - - // all following drawings are relative to (0,0) - _actions->setX(0); - _actions->setY(0); - moveToDVIPos(); - - _xmlnode = new XMLElementNode("g"); // append following elements to this group - _psi.execute("\n@beginspecial @setspecial "); // enter \special environment - _psi.limit(epsfile.pslength()); // limit the number of bytes to be processed - _psi.execute(is); // process EPS file - _psi.limit(0); // disable limitation - _psi.execute("\n@endspecial "); // leave special environment - if (_xmlnode->empty()) // nothing been drawn? - delete _xmlnode; // => don't need to add empty group node - else { // has anything been drawn? - Matrix matrix(1); - matrix.rotate(angle).scale(hscale/100, vscale/100).translate(hoffset, voffset); - matrix.translate(-llx, lly); - matrix.scale(sx, sy); // resize image to width "rwi" and height "rhi" - matrix.translate(x, y); // move image to current DVI position - if (!matrix.isIdentity()) - _xmlnode->addAttribute("transform", matrix.getSVG()); - _actions->appendToPage(_xmlnode); - } - _xmlnode = 0; // append following elements to page group again + return; + } + unordered_map<string,string>::const_iterator it; + + // bounding box of EPS figure (lower left and upper right corner) + double llx = (it = attr.find("llx")) != attr.end() ? str2double(it->second) : 0; + double lly = (it = attr.find("lly")) != attr.end() ? str2double(it->second) : 0; + double urx = (it = attr.find("urx")) != attr.end() ? str2double(it->second) : 0; + double ury = (it = attr.find("ury")) != attr.end() ? str2double(it->second) : 0; + + // desired width/height of resulting figure + double rwi = (it = attr.find("rwi")) != attr.end() ? str2double(it->second)/10.0 : -1; + double rhi = (it = attr.find("rhi")) != attr.end() ? str2double(it->second)/10.0 : -1; + if (rwi == 0 || rhi == 0 || urx-llx == 0 || ury-lly == 0) + return; - // restore DVI position - _actions->setX(x); - _actions->setY(y); - moveToDVIPos(); + // user transformations (default values chosen according to dvips manual) + double hoffset = (it = attr.find("hoffset")) != attr.end() ? str2double(it->second) : 0; + double voffset = (it = attr.find("voffset")) != attr.end() ? str2double(it->second) : 0; +// double hsize = (it = attr.find("hsize")) != attr.end() ? str2double(it->second) : 612; +// double vsize = (it = attr.find("vsize")) != attr.end() ? str2double(it->second) : 792; + double hscale = (it = attr.find("hscale")) != attr.end() ? str2double(it->second) : 100; + double vscale = (it = attr.find("vscale")) != attr.end() ? str2double(it->second) : 100; + double angle = (it = attr.find("angle")) != attr.end() ? str2double(it->second) : 0; + + Matrix m(1); + m.rotate(angle).scale(hscale/100, vscale/100).translate(hoffset, voffset); + BoundingBox bbox(llx, lly, urx, ury); + bbox.transform(m); + + // compute factors to scale the bounding box to width rwi and height rhi + double sx = rwi/bbox.width(); + double sy = rhi/bbox.height(); + if (sx == 0 || sy == 0) + return; - // update bounding box - m.scale(sx, -sy); - m.translate(x, y); - bbox = BoundingBox(0, 0, fabs(urx-llx), fabs(ury-lly)); - bbox.transform(m); - _actions->embed(bbox); + if (sx < 0) sx = sy; // rwi attribute not set + if (sy < 0) sy = sx; // rhi attribute not set + if (sx < 0) sx = sy = 1.0; // neither rwi nor rhi set + + // save current DVI position + const double x = _actions->getX(); + const double y = _actions->getY(); + + // all following drawings are relative to (0,0) + _actions->setX(0); + _actions->setY(0); + moveToDVIPos(); + + // transform current DVI position and bounding box location + // according to current transformation matrix + DPair llTrans = _actions->getMatrix()*DPair(llx, -lly); + DPair urTrans = _actions->getMatrix()*DPair(urx, -ury); + DPair dviposTrans = _actions->getMatrix()*DPair(x, y); + + auto groupNode = util::make_unique<XMLElementNode>("g"); // append following elements to this group + _xmlnode = groupNode.get(); + _psi.execute("\n@beginspecial @setspecial "); // enter \special environment + EPSFile epsfile(filepath); + _psi.limit(epsfile.pslength()); // limit the number of bytes going to be processed + _psi.execute(epsfile.istream()); // process EPS file + _psi.limit(0); // disable limitation + _psi.execute("\n@endspecial "); // leave special environment + if (!groupNode->empty()) { // has anything been drawn? + Matrix matrix(1); + matrix.rotate(angle).scale(hscale/100, vscale/100).translate(hoffset, voffset); + matrix.translate(-llTrans); + matrix.scale(sx, sy); // resize image to width "rwi" and height "rhi" + matrix.translate(dviposTrans); // move image to current DVI position + if (!matrix.isIdentity()) + groupNode->addAttribute("transform", matrix.getSVG()); + _actions->appendToPage(std::move(groupNode)); } + _xmlnode = nullptr; // append following elements to page group again + + // restore DVI position + _actions->setX(x); + _actions->setY(y); + moveToDVIPos(); + + // update bounding box + m.scale(sx, -sy); + m.translate(dviposTrans); + bbox = BoundingBox(DPair(0, 0), abs(urTrans-llTrans)); + bbox.transform(m); + _actions->embed(bbox); } @@ -525,14 +530,14 @@ void PsSpecialHandler::stroke (vector<double> &p) { } if (_clipStack.clippathLoaded() && _clipStack.top()) _path.prepend(*_clipStack.top()); - XMLElementNode *path=0; + unique_ptr<XMLElementNode> path; Pair<double> point; if (_path.isDot(point)) { // zero-length path? if (_linecap == 1) { // round line ends? => draw dot double x = point.x(); double y = point.y(); double r = _linewidth/2.0; - path = new XMLElementNode("circle"); + path = util::make_unique<XMLElementNode>("circle"); path->addAttribute("cx", x); path->addAttribute("cy", y); path->addAttribute("r", r); @@ -547,7 +552,7 @@ void PsSpecialHandler::stroke (vector<double> &p) { ostringstream oss; _path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); - path = new XMLElementNode("path"); + path = util::make_unique<XMLElementNode>("path"); path->addAttribute("d", oss.str()); path->addAttribute("stroke", _actions->getColor().svgColorString()); path->addAttribute("fill", "none"); @@ -582,9 +587,9 @@ void PsSpecialHandler::stroke (vector<double> &p) { _clipStack.setClippathLoaded(false); } if (_xmlnode) - _xmlnode->append(path); + _xmlnode->append(std::move(path)); else { - _actions->appendToPage(path); + _actions->appendToPage(std::move(path)); _actions->embed(bbox); } _path.clear(); @@ -612,7 +617,7 @@ void PsSpecialHandler::fill (vector<double> &p, bool evenodd) { ostringstream oss; _path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); - XMLElementNode *path = new XMLElementNode("path"); + unique_ptr<XMLElementNode> path = util::make_unique<XMLElementNode>("path"); path->addAttribute("d", oss.str()); if (_pattern) path->addAttribute("fill", XMLString("url(#")+_pattern->svgID()+")"); @@ -631,9 +636,9 @@ void PsSpecialHandler::fill (vector<double> &p, bool evenodd) { if (_opacityalpha < 1) path->addAttribute("fill-opacity", _opacityalpha); if (_xmlnode) - _xmlnode->append(path); + _xmlnode->append(std::move(path)); else { - _actions->appendToPage(path); + _actions->appendToPage(std::move(path)); _actions->embed(bbox); } _path.clear(); @@ -682,7 +687,7 @@ void PsSpecialHandler::makepattern (vector<double> &p) { // pattern definition completed if (_savenode) { _xmlnode = _savenode; - _savenode = 0; + _savenode = nullptr; } break; case 1: { // tiling pattern @@ -694,14 +699,14 @@ void PsSpecialHandler::makepattern (vector<double> &p) { create_matrix(p, 9, matrix); matrix.rmultiply(_actions->getMatrix()); - PSTilingPattern *pattern=0; + unique_ptr<PSTilingPattern> pattern; if (paint_type == 1) - pattern = new PSColoredTilingPattern(id, bbox, matrix, xstep, ystep); + pattern = util::make_unique<PSColoredTilingPattern>(id, bbox, matrix, xstep, ystep); else - pattern = new PSUncoloredTilingPattern(id, bbox, matrix, xstep, ystep); - _patterns[id] = pattern; + pattern = util::make_unique<PSUncoloredTilingPattern>(id, bbox, matrix, xstep, ystep); _savenode = _xmlnode; _xmlnode = pattern->getContainerNode(); // insert the following SVG elements into this node + _patterns[id] = std::move(pattern); break; } case 2: { @@ -716,21 +721,21 @@ void PsSpecialHandler::makepattern (vector<double> &p) { * 1-3: (optional) RGB values for uncolored tiling patterns * further parameters depend on the pattern type */ void PsSpecialHandler::setpattern (vector<double> &p) { - int pattern_id = static_cast<int>(p[0]); + int patternID = static_cast<int>(p[0]); Color color; if (p.size() == 4) color.setRGB(p[1], p[2], p[3]); - map<int,PSPattern*>::iterator it = _patterns.find(pattern_id); + auto it = _patterns.find(patternID); if (it == _patterns.end()) - _pattern = 0; + _pattern = nullptr; else { - if (PSUncoloredTilingPattern *pattern = dynamic_cast<PSUncoloredTilingPattern*>(it->second)) + if (auto *pattern = dynamic_cast<PSUncoloredTilingPattern*>(it->second.get())) pattern->setColor(color); it->second->apply(*_actions); - if (PSTilingPattern *pattern = dynamic_cast<PSTilingPattern*>(it->second)) + if (auto *pattern = dynamic_cast<PSTilingPattern*>(it->second.get())) _pattern = pattern; else - _pattern = 0; + _pattern = nullptr; } } @@ -787,7 +792,7 @@ void PsSpecialHandler::clip (Path &path, bool evenodd) { } else { // compute the intersection of the current clipping path with the current graphics path - Path *oldPath = _clipStack.getPath(oldID); + const Path *oldPath = _clipStack.top(); Path intersectedPath(windingRule); PathClipper clipper; clipper.intersect(*oldPath, path, intersectedPath); @@ -795,19 +800,19 @@ void PsSpecialHandler::clip (Path &path, bool evenodd) { intersectedPath.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); } - XMLElementNode *pathElem = new XMLElementNode("path"); + auto pathElem = util::make_unique<XMLElementNode>("path"); pathElem->addAttribute("d", oss.str()); if (evenodd) pathElem->addAttribute("clip-rule", "evenodd"); int newID = _clipStack.topID(); - XMLElementNode *clipElem = new XMLElementNode("clipPath"); + auto clipElem = util::make_unique<XMLElementNode>("clipPath"); clipElem->addAttribute("id", XMLString("clip")+XMLString(newID)); if (!COMPUTE_CLIPPATHS_INTERSECTIONS && oldID) clipElem->addAttribute("clip-path", XMLString("url(#clip")+XMLString(oldID)+")"); - clipElem->append(pathElem); - _actions->appendToDefs(clipElem); + clipElem->append(std::move(pathElem)); + _actions->appendToDefs(std::move(clipElem)); } @@ -918,12 +923,14 @@ static void read_patch_data (ShadingPatch &patch, int edgeflag, class ShadingCallback : public ShadingPatch::Callback { public: ShadingCallback (SpecialActions &actions, XMLElementNode *parent, int clippathID) - : _actions(actions), _group(new XMLElementNode("g")) + : _actions(actions) { + auto group = util::make_unique<XMLElementNode>("g"); + _group = group.get(); if (parent) - parent->append(_group); + parent->append(std::move(group)); else - actions.appendToPage(_group); + actions.appendToPage(std::move(group)); if (clippathID > 0) _group->addAttribute("clip-path", XMLString("url(#clip")+XMLString(clippathID)+")"); } @@ -935,10 +942,10 @@ class ShadingCallback : public ShadingPatch::Callback { // draw a single patch segment ostringstream oss; path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); - XMLElementNode *pathElem = new XMLElementNode("path"); + auto pathElem = util::make_unique<XMLElementNode>("path"); pathElem->addAttribute("d", oss.str()); pathElem->addAttribute("fill", color.svgColorString()); - _group->append(pathElem); + _group->append(std::move(pathElem)); } private: @@ -955,9 +962,7 @@ void PsSpecialHandler::processSequentialPatchMesh (int shadingTypeID, ColorSpace int edgeflag = static_cast<int>(*it++); vector<DPair> points; vector<Color> colors; - unique_ptr<ShadingPatch> patch; - - patch = unique_ptr<ShadingPatch>(ShadingPatch::create(shadingTypeID, colorSpace)); + unique_ptr<ShadingPatch> patch = ShadingPatch::create(shadingTypeID, colorSpace); read_patch_data(*patch, edgeflag, it, points, colors); patch->setPoints(points, edgeflag, previousPatch.get()); patch->setColors(colors, edgeflag, previousPatch.get()); @@ -1139,22 +1144,20 @@ void PsSpecialHandler::executed () { void PsSpecialHandler::ClippingStack::pushEmptyPath () { if (!_stack.empty()) - _stack.push(Entry(0, -1)); + _stack.emplace(Entry()); } void PsSpecialHandler::ClippingStack::push (const Path &path, int saveID) { if (path.empty()) - _stack.push(Entry(0, saveID)); - else { - _paths.push_back(path); - _stack.push(Entry(_paths.size(), saveID)); - } + _stack.emplace(Entry(saveID)); + else + _stack.emplace(Entry(path, ++_maxID, saveID)); } /** Pops a single or several elements from the clipping stack. - * The method distingushes between the following cases: + * The method distinguishes between the following cases: * 1) saveID < 0 and grestoreall == false: * pop top element if it was pushed by gsave (its saveID is < 0 as well) * 2) saveID < 0 and grestoreall == true @@ -1163,36 +1166,30 @@ void PsSpecialHandler::ClippingStack::push (const Path &path, int saveID) { * 3) saveID >= 0: * pop all elements until the saveID of the top element equals parameter saveID */ void PsSpecialHandler::ClippingStack::pop (int saveID, bool grestoreall) { - if (!_stack.empty()) { - if (saveID < 0) { // grestore? - if (_stack.top().saveID < 0) // pushed by 'gsave'? - _stack.pop(); - // pop all further elements pushed by 'gsave' if grestoreall == true - while (grestoreall && !_stack.empty() && _stack.top().saveID < 0) - _stack.pop(); - } - else { - // pop elements pushed by 'gsave' - while (!_stack.empty() && _stack.top().saveID != saveID) - _stack.pop(); - // pop element pushed by 'save' - if (!_stack.empty()) - _stack.pop(); - } + if (_stack.empty()) + return; + + if (saveID < 0) { // grestore? + if (_stack.top().saveID < 0) // pushed by 'gsave'? + _stack.pop(); + // pop all further elements pushed by 'gsave' if grestoreall == true + while (grestoreall && !_stack.empty() && _stack.top().saveID < 0) + _stack.pop(); + } + else { + // pop elements pushed by 'gsave' + while (!_stack.empty() && _stack.top().saveID != saveID) + _stack.pop(); + // pop element pushed by 'save' + if (!_stack.empty()) + _stack.pop(); } } /** Returns a pointer to the path on top of the stack, or 0 if the stack is empty. */ const PsSpecialHandler::Path* PsSpecialHandler::ClippingStack::top () const { - return (!_stack.empty() && _stack.top().pathID) - ? &_paths[_stack.top().pathID-1] - : 0; -} - - -PsSpecialHandler::Path* PsSpecialHandler::ClippingStack::getPath (size_t id) { - return (id > 0 && id <= _paths.size()) ? &_paths[id-1] : 0; + return _stack.empty() ? nullptr : _stack.top().path.get(); } @@ -1211,7 +1208,6 @@ void PsSpecialHandler::ClippingStack::setClippathLoaded (bool loaded) { /** Pops all elements from the stack. */ void PsSpecialHandler::ClippingStack::clear() { - _paths.clear(); while (!_stack.empty()) _stack.pop(); } @@ -1223,21 +1219,21 @@ void PsSpecialHandler::ClippingStack::replace (const Path &path) { if (_stack.empty()) push(path, -1); else { - _paths.push_back(path); - _stack.top().pathID = _paths.size(); + _stack.top().path = make_shared<Path>(path); + _stack.top().pathID = ++_maxID; } } /** Duplicates the top element, i.e. the top element is pushed again. */ void PsSpecialHandler::ClippingStack::dup (int saveID) { - _stack.push(_stack.empty() ? Entry(0, -1) : _stack.top()); + _stack.emplace(_stack.empty() ? Entry() : _stack.top()); _stack.top().saveID = saveID; } -const char** PsSpecialHandler::prefixes () const { - static const char *pfx[] = { +const vector<const char*> PsSpecialHandler::prefixes () const { + const vector<const char*> pfx { "header=", // read and execute PS header file prior to the following PS statements "psfile=", // read and execute PS file "PSfile=", // dito @@ -1247,6 +1243,6 @@ const char** PsSpecialHandler::prefixes () const { "\"", // execute literal PS code following this prefix "pst:", // dito "PST:", // same as "ps:" - 0}; + }; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp index fe95443215b..310a6b8c34e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp @@ -2,7 +2,7 @@ ** PsSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,6 +21,7 @@ #ifndef PSSPECIALHANDLER_HPP #define PSSPECIALHANDLER_HPP +#include <memory> #include <set> #include <stack> #include <string> @@ -35,15 +36,17 @@ class PSPattern; class XMLElementNode; -class PsSpecialHandler : public SpecialHandler, public DVIEndPageListener, protected PSActions -{ - typedef GraphicsPath<double> Path; - typedef std::vector<double>::const_iterator DoubleVecIt; - typedef Color::ColorSpace ColorSpace; +class PsSpecialHandler : public SpecialHandler, public DVIEndPageListener, protected PSActions { + using Path = GraphicsPath<double>; + using ColorSpace = Color::ColorSpace; - class ClippingStack - { + /** Helper class storing the clipping paths currently present on the graphics context stack. + * Since PS operator 'clippath' only delivers a linearly approximated version of the paths + * that are sometimes too imprecise for direct usage in SVG, we keep the possibly curved + * clipping paths and compute their intersections locally if necessary. */ + class ClippingStack { public: + ClippingStack () : _maxID(0) {} void pushEmptyPath (); void push (const Path &path, int saveID=-1); void replace (const Path &path); @@ -54,18 +57,22 @@ class PsSpecialHandler : public SpecialHandler, public DVIEndPageListener, prote bool clippathLoaded () const; void setClippathLoaded (bool loaded); const Path* top () const; - Path* getPath (size_t id); int topID () const {return _stack.empty() ? 0 : _stack.top().pathID;} private: struct Entry { - int pathID; ///< index referencing a path of the pool - int saveID; ///< if >=0, path was pushed by 'save', and saveID holds the ID of the + std::shared_ptr<Path> path; // pointer to current clipping path + int pathID; ///< ID of current clipping path + int saveID; ///< if >=0, path was pushed by 'save', and saveID holds the ID of the PS memory object bool cpathLoaded; ///< true if clipping path was loaded into current path - Entry (int pid, int sid) : pathID(pid), saveID(sid), cpathLoaded(false) {} + Entry () : Entry(-1) {} + Entry (const Path &p, int pid, int sid) : path(std::make_shared<Path>(p)), pathID(pid), saveID(sid), cpathLoaded(false) {} + Entry (int sid) : path(nullptr), pathID(0), saveID(sid), cpathLoaded(false) {} + Entry (const Entry &entry) =default; + Entry (Entry &&entry) =default; }; - std::vector<Path> _paths; ///< pool of all clipping paths - std::stack<Entry> _stack; + size_t _maxID; + std::stack<Entry> _stack; ///< stack holding the clipping information of the current graphics context }; enum PsSection {PS_NONE, PS_HEADERS, PS_BODY}; @@ -75,7 +82,7 @@ class PsSpecialHandler : public SpecialHandler, public DVIEndPageListener, prote ~PsSpecialHandler (); const char* name () const override {return "ps";} const char* info () const override {return "dvips PostScript specials";} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; void preprocess (const char *prefix, std::istream &is, SpecialActions &actions) override; bool process (const char *prefix, std::istream &is, SpecialActions &actions) override; void setDviScaleFactor (double dvi2bp) override {_previewFilter.setDviScaleFactor(dvi2bp);} @@ -93,14 +100,14 @@ class PsSpecialHandler : public SpecialHandler, public DVIEndPageListener, prote void moveToDVIPos (); void executeAndSync (std::istream &is, bool updatePos); void processHeaderFile (const char *fname); - void psfile (const std::string &fname, const std::map<std::string,std::string> &attr); + void psfile (const std::string &fname, const std::unordered_map<std::string,std::string> &attr); void dviEndPage (unsigned pageno, SpecialActions &actions) override; void clip (Path &path, bool evenodd); void processSequentialPatchMesh (int shadingTypeID, ColorSpace cspace, VectorIterator<double> &it); void processLatticeTriangularPatchMesh (ColorSpace colorSpace, VectorIterator<double> &it); /// scale given value by current PS scale factors - double scale (double v) const {return v*(_sx*_cos*_cos + _sy*(1-_cos*_cos));} + double scale (double v) const {return v*(_sx*(1-_cos*_cos) + _sy*_cos*_cos);} void applyscalevals (std::vector<double> &p) override {_sx = p[0]; _sy = p[1]; _cos = p[2];} void clip (std::vector<double> &p) override {clip(p, false);} @@ -131,9 +138,9 @@ class PsSpecialHandler : public SpecialHandler, public DVIEndPageListener, prote void sethsbcolor (std::vector<double> &hsb) override; 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 = p[0] ? scale(p[0])*1.00375 : 0.5;} + 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]*1.00375;} + void setmiterlimit (std::vector<double> &p) override {_miterlimit = p[0];} void setopacityalpha (std::vector<double> &p) override {_opacityalpha = p[0];} void setpattern (std::vector<double> &p) override; void setrgbcolor (std::vector<double> &rgb) override; @@ -155,15 +162,15 @@ class PsSpecialHandler : public SpecialHandler, public DVIEndPageListener, prote 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 linewidth - double _miterlimit; ///< current miter limit + 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) 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, PSPattern*> _patterns; + std::unordered_map<int, std::unique_ptr<PSPattern>> _patterns; PSTilingPattern *_pattern; ///< current pattern }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp index ac2097624f7..24b76362bd5 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp @@ -2,7 +2,7 @@ ** RangeMap.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.hpp index 6170a2aa5dc..70291696f66 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.hpp @@ -2,7 +2,7 @@ ** RangeMap.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -58,7 +58,7 @@ class RangeMap { uint32_t _minval; }; - typedef std::vector<Range> Ranges; + using Ranges = std::vector<Range>; public: void addRange (uint32_t first, uint32_t last, uint32_t cid); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp index 50215d936dc..140207bb67a 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp @@ -2,7 +2,7 @@ ** SVGCharHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -19,6 +19,7 @@ *************************************************************************/ #include "SVGCharHandler.hpp" +#include "utility.hpp" #include "XMLNode.hpp" using namespace std; @@ -30,12 +31,17 @@ void SVGCharHandler::setInitialContextNode (XMLElementNode *node) { } -/** Changes the context element. All following nodes will be appended to this node. */ -void SVGCharHandler::pushContextNode (XMLElementNode *node) { - if (node && (_contextNodeStack.empty() || node != _contextNodeStack.top())) { - contextNode()->append(node); - _contextNodeStack.push(node); +/** Changes the context element. All following nodes will be appended to this node. + * @param[in] node the new context node + * @return bare pointer to the new context node or 0 if context hasn't changed */ +XMLElementNode* SVGCharHandler::pushContextNode (unique_ptr<XMLElementNode> &&node) { + if (node && (_contextNodeStack.empty() || node.get() != _contextNodeStack.top())) { + XMLElementNode *nodeptr = node.get(); + contextNode()->append(std::move(node)); + _contextNodeStack.push(nodeptr); + return nodeptr; } + return nullptr; } @@ -55,15 +61,14 @@ void SVGCharHandler::resetContextNode () { /** Creates and returns a new SVG text element. * @param[in] x current x coordinate * @param[in] y current y coordinate */ -XMLElementNode* SVGCharTextHandler::createTextNode (double x, double y) const { +unique_ptr<XMLElementNode> SVGCharTextHandler::createTextNode (double x, double y) const { const Font *font = _font.get(); if (!font) - return 0; - XMLElementNode *textNode = new XMLElementNode("text"); + return nullptr; + auto textNode = util::make_unique<XMLElementNode>("text"); if (_selectFontByClass) textNode->addAttribute("class", string("f")+XMLString(_fontnum)); else { - textNode->addAttribute("font-family", font->name()); textNode->addAttribute("font-size", XMLString(font->scaledSize())); if (font->color() != Color::BLACK) @@ -72,15 +77,16 @@ XMLElementNode* SVGCharTextHandler::createTextNode (double x, double y) const { if (_vertical) { textNode->addAttribute("writing-mode", "tb"); // align glyphs designed for horizontal layout properly - if (const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(font)) + if (const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(font)) { if (!pf->getMetrics()->verticalLayout()) { // alphabetic text designed for horizontal layout? x += pf->scaledAscent()/2.5; // move vertical baseline to the right by strikethrough offset textNode->addAttribute("glyph-orientation-vertical", 90); // ensure rotation } + } } textNode->addAttribute("x", x); textNode->addAttribute("y", y); if (!_matrix.get().isIdentity()) textNode->addAttribute("transform", _matrix.get().getSVG()); return textNode; -}
\ No newline at end of file +} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp index 5bcd92a685a..2cc54614f35 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp @@ -2,7 +2,7 @@ ** SVGCharHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,6 +21,7 @@ #ifndef SVGCHARHANDLER_HPP #define SVGCHARHANDLER_HPP +#include <memory> #include <stack> #include "Color.hpp" #include "Font.hpp" @@ -73,7 +74,7 @@ class SVGCharHandler { protected: virtual void resetContextNode (); - void pushContextNode (XMLElementNode *node); + XMLElementNode* pushContextNode (std::unique_ptr<XMLElementNode> &&node); void popContextNode (); XMLElementNode* contextNode () const { @@ -98,7 +99,7 @@ class SVGCharTextHandler : public SVGCharHandler { SVGCharTextHandler (bool selectFontByClass) : _selectFontByClass(selectFontByClass) {} protected: - XMLElementNode* createTextNode (double x, double y) const; + std::unique_ptr<XMLElementNode> createTextNode (double x, double y) const; private: bool _selectFontByClass; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandlerFactory.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandlerFactory.cpp index 820850a161c..ebc4eb4fe69 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandlerFactory.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandlerFactory.cpp @@ -2,7 +2,7 @@ ** SVGCharHandlerFactory.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,14 +23,14 @@ #include "SVGSingleCharTextHandler.hpp" #include "SVGCharTspanTextHandler.hpp" #include "SVGTree.hpp" +#include "utility.hpp" +using namespace std; -SVGCharHandler* SVGCharHandlerFactory::createHandler () { +unique_ptr<SVGCharHandler> SVGCharHandlerFactory::createHandler () { if (!SVGTree::USE_FONTS) - return new SVGCharPathHandler(SVGTree::CREATE_USE_ELEMENTS, SVGTree::RELATIVE_PATH_CMDS); + return util::make_unique<SVGCharPathHandler>(SVGTree::CREATE_USE_ELEMENTS, SVGTree::RELATIVE_PATH_CMDS); if (SVGTree::MERGE_CHARS) - return new SVGCharTspanTextHandler(SVGTree::CREATE_CSS); - else - return new SVGSingleCharTextHandler(SVGTree::CREATE_CSS); - return 0; -}
\ No newline at end of file + return util::make_unique<SVGCharTspanTextHandler>(SVGTree::CREATE_CSS); + return util::make_unique<SVGSingleCharTextHandler>(SVGTree::CREATE_CSS); +} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandlerFactory.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandlerFactory.hpp index 4000bd76634..5bd1d01493a 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandlerFactory.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandlerFactory.hpp @@ -2,7 +2,7 @@ ** SVGCharHandlerFactory.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,12 +21,11 @@ #ifndef SVGCHARHANDLERFACTORY_HPP #define SVGCHARHANDLERFACTORY_HPP +#include <memory> #include "SVGCharHandler.hpp" - -struct SVGCharHandlerFactory -{ - static SVGCharHandler* createHandler (); +struct SVGCharHandlerFactory { + static std::unique_ptr<SVGCharHandler> createHandler (); }; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp index db6c2aba999..c3a4f283e9e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp @@ -2,7 +2,7 @@ ** SVGCharPathHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,6 +22,7 @@ #include "Font.hpp" #include "FontManager.hpp" #include "SVGCharPathHandler.hpp" +#include "utility.hpp" #include "XMLNode.hpp" using namespace std; @@ -68,8 +69,7 @@ void SVGCharPathHandler::appendChar (uint32_t c, double x, double y) { if (color.changed() || _matrix.changed()) { resetContextNode(); if (applyColor || applyMatrix) { - _groupNode = new XMLElementNode("g"); - pushContextNode(_groupNode); + _groupNode = pushContextNode(util::make_unique<XMLElementNode>("g")); if (applyColor) contextNode()->addAttribute("fill", color.get().svgColorString()); if (applyMatrix) @@ -108,15 +108,14 @@ void SVGCharPathHandler::appendChar (uint32_t c, double x, double y) { void SVGCharPathHandler::appendUseElement (uint32_t c, double x, double y, const Matrix &matrix) { - ostringstream oss; - oss << "#g" << FontManager::instance().fontID(_font) << '-' << c; - XMLElementNode *useNode = new XMLElementNode("use"); + string id = "#g" + to_string(FontManager::instance().fontID(_font)) + "-" + to_string(c); + auto useNode = util::make_unique<XMLElementNode>("use"); useNode->addAttribute("x", XMLString(x)); useNode->addAttribute("y", XMLString(y)); - useNode->addAttribute("xlink:href", oss.str()); + useNode->addAttribute("xlink:href", id); if (!matrix.isIdentity()) useNode->addAttribute("transform", matrix.getSVG()); - contextNode()->append(useNode); + contextNode()->append(std::move(useNode)); } @@ -128,10 +127,10 @@ void SVGCharPathHandler::appendPathElement (uint32_t c, double x, double y, cons double sy = -sx; ostringstream oss; glyph.writeSVG(oss, _relativePathCommands, sx, sy, x, y); - XMLElementNode *glyphNode = new XMLElementNode("path"); + auto glyphNode = util::make_unique<XMLElementNode>("path"); glyphNode->addAttribute("d", oss.str()); if (!matrix.isIdentity()) glyphNode->addAttribute("transform", matrix.getSVG()); - contextNode()->append(glyphNode); + contextNode()->append(std::move(glyphNode)); } } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp index 2031c6c472f..6e248cbca89 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp @@ -2,7 +2,7 @@ ** SVGCharPathHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -25,7 +25,7 @@ /** Creates SVG path elements for all characters. */ class SVGCharPathHandler : public SVGCharHandler { - typedef void (SVGCharPathHandler::*AppendMethod)(uint32_t c, double x, double y, const Matrix &matrix); + using AppendMethod = void (SVGCharPathHandler::*)(uint32_t c, double x, double y, const Matrix &matrix); public: SVGCharPathHandler (bool createUseElements, bool relativePathsCommands); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp index d9432971180..cb1e4d23f2d 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp @@ -2,7 +2,7 @@ ** SVGCharTspanTextHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -19,6 +19,7 @@ *************************************************************************/ #include "SVGCharTspanTextHandler.hpp" +#include "utility.hpp" #include "XMLNode.hpp" using namespace std; @@ -34,8 +35,7 @@ void SVGCharTspanTextHandler::appendChar (uint32_t c, double x, double y) { // changes of fonts and transformations require a new text element if (!_textNode || _font.changed() || _matrix.changed() || _vertical.changed()) { resetContextNode(); - _textNode = createTextNode(x, y); - pushContextNode(_textNode); + _textNode = pushContextNode(createTextNode(x, y)); _color.changed(true); // force creating tspan with color attribute if current color differs from font color } if (_tspanNode && (_xchanged || _ychanged || _color.changed())) { @@ -47,8 +47,7 @@ void SVGCharTspanTextHandler::appendChar (uint32_t c, double x, double y) { // Glyphs of non-black fonts (e.g. defined in a XeTeX document) can't change their color. bool applyColor = _color.get() != Color::BLACK && _font.get()->color() == Color::BLACK; if (_xchanged || _ychanged || (_color.changed() && applyColor)) { - _tspanNode = new XMLElementNode("tspan"); - pushContextNode(_tspanNode); + _tspanNode = pushContextNode(util::make_unique<XMLElementNode>("tspan")); if (applyColor) _tspanNode->addAttribute("fill", _color.get().svgColorString()); _color.changed(false); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp index 868a90626e9..ee8a049a691 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp @@ -2,7 +2,7 @@ ** SVGCharTspanTextHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp index 84c66d82ac1..f65d4e85181 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp @@ -2,7 +2,7 @@ ** SVGOutput.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -54,9 +54,9 @@ ostream& SVGOutput::getPageStream (int page, int numPages) const { _page = page; if (_zipLevel > 0) - _osptr.reset(new ZLibOutputStream(fname, _zipLevel)); + _osptr = util::make_unique<ZLibOutputStream>(fname, _zipLevel); else - _osptr.reset(new ofstream(fname.c_str())); + _osptr = util::make_unique<ofstream>(fname.c_str()); if (!_osptr) throw MessageException("can't open file "+fname+" for writing"); return *_osptr; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp index d5edebf7865..a24f09821e6 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp @@ -2,7 +2,7 @@ ** SVGOutput.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.cpp index af99de0dacb..9ef88c708ee 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.cpp @@ -2,7 +2,7 @@ ** SVGSingleCharTextHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -25,7 +25,7 @@ using namespace std; void SVGSingleCharTextHandler::appendChar (uint32_t c, double x, double y) { const Font *font = _font.get(); - XMLElementNode *textNode = createTextNode(x, y); + auto textNode = createTextNode(x, y); textNode->append(XMLString(font->unicode(c), false)); // Apply color changes only if the color differs from black and if the font color itself is black. // Glyphs from non-black fonts (e.g. defined in a XeTeX document) can't change their color. @@ -33,5 +33,5 @@ void SVGSingleCharTextHandler::appendChar (uint32_t c, double x, double y) { textNode->addAttribute("fill", _color.get().svgColorString()); _color.changed(false); } - contextNode()->append(textNode); + contextNode()->append(std::move(textNode)); } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp index f2525dcbce0..c8c0555b024 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp @@ -2,7 +2,7 @@ ** SVGSingleCharTextHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -24,8 +24,7 @@ #include "SVGCharHandler.hpp" -class SVGSingleCharTextHandler : public SVGCharTextHandler -{ +class SVGSingleCharTextHandler : public SVGCharTextHandler { public: SVGSingleCharTextHandler (bool createStyleElements) : SVGCharTextHandler(createStyleElements) {} void appendChar (uint32_t c, double x, double y) override; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp index 5a88650b864..646af3d4e40 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp @@ -2,7 +2,7 @@ ** SVGTree.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <algorithm> #include <array> #include <sstream> @@ -49,8 +48,7 @@ bool SVGTree::ADD_COMMENTS=false; double SVGTree::ZOOM_FACTOR=1.0; -SVGTree::SVGTree () { - _charHandler.reset(SVGCharHandlerFactory::createHandler()); +SVGTree::SVGTree () : _charHandler(SVGCharHandlerFactory::createHandler()) { reset(); } @@ -58,11 +56,12 @@ SVGTree::SVGTree () { /** Clears the SVG tree and initializes the root element. */ void SVGTree::reset () { _doc.clear(); - _root = new XMLElementNode("svg"); - _root->addAttribute("version", "1.1"); - _root->addAttribute("xmlns", "http://www.w3.org/2000/svg"); - _root->addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); - _doc.setRootNode(_root); + auto rootNode = util::make_unique<XMLElementNode>("svg"); + rootNode->addAttribute("version", "1.1"); + rootNode->addAttribute("xmlns", "http://www.w3.org/2000/svg"); + rootNode->addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); + _root = rootNode.get(); + _doc.setRootNode(std::move(rootNode)); _page = _defs = nullptr; _styleCDataNode = nullptr; } @@ -113,37 +112,39 @@ bool SVGTree::setFontFormat (string formatstr) { /** Starts a new page. * @param[in] pageno number of new page */ void SVGTree::newPage (int pageno) { - _page = new XMLElementNode("g"); + auto pageNode = util::make_unique<XMLElementNode>("g"); if (pageno >= 0) - _page->addAttribute("id", string("page")+XMLString(pageno)); - _root->append(_page); - _charHandler->setInitialContextNode(_page); + pageNode->addAttribute("id", string("page")+XMLString(pageno)); + _charHandler->setInitialContextNode(pageNode.get()); + _page = pageNode.get(); + _root->append(std::move(pageNode)); while (!_contextElementStack.empty()) _contextElementStack.pop(); } -void SVGTree::appendToDefs (XMLNode *node) { +void SVGTree::appendToDefs (unique_ptr<XMLNode> &&node) { if (!_defs) { - _defs = new XMLElementNode("defs"); - _root->prepend(_defs); + auto defsNode = util::make_unique<XMLElementNode>("defs"); + _defs = defsNode.get(); + _root->prepend(std::move(defsNode)); } - _defs->append(node); + _defs->append(std::move(node)); } -void SVGTree::appendToPage (XMLNode *node) { +void SVGTree::appendToPage (unique_ptr<XMLNode> &&node) { XMLElementNode *parent = _contextElementStack.empty() ? _page : _contextElementStack.top(); - parent->append(node); + parent->append(std::move(node)); _charHandler->setInitialContextNode(parent); } -void SVGTree::prependToPage (XMLNode *node) { +void SVGTree::prependToPage (unique_ptr<XMLNode> &&node) { if (_contextElementStack.empty()) - _page->prepend(node); + _page->prepend(std::move(node)); else - _contextElementStack.top()->prepend(node); + _contextElementStack.top()->prepend(std::move(node)); } @@ -158,36 +159,34 @@ void SVGTree::transformPage (const Matrix &usermatrix) { * @param[in] font font to extract the glyph from * @param[in] cb pointer to callback object for sending feedback to the glyph tracer (may be 0) * @return pointer to element node if glyph exists, 0 otherwise */ -static XMLElementNode* createGlyphNode (int c, const PhysicalFont &font, GFGlyphTracer::Callback *cb) { +static unique_ptr<XMLElementNode> createGlyphNode (int c, const PhysicalFont &font, GFGlyphTracer::Callback *cb) { Glyph glyph; if (!font.getGlyph(c, glyph, cb) || (!SVGTree::USE_FONTS && !SVGTree::CREATE_USE_ELEMENTS)) - return 0; + return nullptr; double sx=1.0, sy=1.0; double upem = font.unitsPerEm(); - XMLElementNode *glyph_node=0; + unique_ptr<XMLElementNode> glyphNode; if (SVGTree::USE_FONTS) { double extend = font.style() ? font.style()->extend : 1; - glyph_node = new XMLElementNode("glyph"); - glyph_node->addAttribute("unicode", XMLString(font.unicode(c), false)); - glyph_node->addAttribute("horiz-adv-x", XMLString(font.hAdvance(c)*extend)); - glyph_node->addAttribute("vert-adv-y", XMLString(font.vAdvance(c))); + glyphNode = util::make_unique<XMLElementNode>("glyph"); + glyphNode->addAttribute("unicode", XMLString(font.unicode(c), false)); + glyphNode->addAttribute("horiz-adv-x", XMLString(font.hAdvance(c)*extend)); + glyphNode->addAttribute("vert-adv-y", XMLString(font.vAdvance(c))); string name = font.glyphName(c); if (!name.empty()) - glyph_node->addAttribute("glyph-name", name); + glyphNode->addAttribute("glyph-name", name); } else { - ostringstream oss; - oss << 'g' << FontManager::instance().fontID(&font) << '-' << c; - glyph_node = new XMLElementNode("path"); - glyph_node->addAttribute("id", oss.str()); + glyphNode = util::make_unique<XMLElementNode>("path"); + glyphNode->addAttribute("id", "g"+to_string(FontManager::instance().fontID(&font))+"-"+to_string(c)); sx = font.scaledSize()/upem; sy = -sx; } ostringstream oss; glyph.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS, sx, sy); - glyph_node->addAttribute("d", oss.str()); - return glyph_node; + glyphNode->addAttribute("d", oss.str()); + return glyphNode; } @@ -208,7 +207,7 @@ static string font_info (const Font &font) { } -void SVGTree::appendFontStyles (const set<const Font*> &fonts) { +void SVGTree::appendFontStyles (const unordered_set<const Font*> &fonts) { if (CREATE_CSS && USE_FONTS && !fonts.empty() && _page) { map<int, const Font*> sortmap; for (const Font *font : fonts) @@ -256,24 +255,24 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr if (ADD_COMMENTS) { string info = font_info(font); if (!info.empty()) - appendToDefs(new XMLCommentNode(string(" font: ")+info+" ")); + appendToDefs(util::make_unique<XMLCommentNode>(string(" font: ")+info+" ")); } - XMLElementNode *fontNode = new XMLElementNode("font"); + auto fontNode = util::make_unique<XMLElementNode>("font"); string fontname = font.name(); fontNode->addAttribute("id", fontname); fontNode->addAttribute("horiz-adv-x", XMLString(font.hAdvance())); - appendToDefs(fontNode); - XMLElementNode *faceNode = new XMLElementNode("font-face"); + auto faceNode = util::make_unique<XMLElementNode>("font-face"); faceNode->addAttribute("font-family", fontname); faceNode->addAttribute("units-per-em", XMLString(font.unitsPerEm())); if (!font.verticalLayout()) { faceNode->addAttribute("ascent", XMLString(font.ascent())); faceNode->addAttribute("descent", XMLString(font.descent())); } - fontNode->append(faceNode); + fontNode->append(std::move(faceNode)); for (int c : chars) fontNode->append(createGlyphNode(c, font, callback)); + appendToDefs(std::move(fontNode)); } } else if (CREATE_USE_ELEMENTS && &font != font.uniqueFont()) { @@ -282,20 +281,13 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr // reference the already embedded path together with a transformation attribute and let the SVG renderer // scale the glyphs properly. This is only necessary if we don't want to use font but path elements. for (int c : chars) { - ostringstream oss; - XMLElementNode *use = new XMLElementNode("use"); - oss << 'g' << FontManager::instance().fontID(&font) << '-' << c; - use->addAttribute("id", oss.str()); - oss.str(""); - oss << "#g" << FontManager::instance().fontID(font.uniqueFont()) << '-' << c; - use->addAttribute("xlink:href", oss.str()); + auto useNode = util::make_unique<XMLElementNode>("use"); + useNode->addAttribute("id", "g"+to_string(FontManager::instance().fontID(&font))+"-"+to_string(c)); + useNode->addAttribute("xlink:href", "#g"+to_string(FontManager::instance().fontID(font.uniqueFont()))+"-"+to_string(c)); double scale = font.scaledSize()/font.uniqueFont()->scaledSize(); - if (scale != 1.0) { - oss.str(""); - oss << "scale(" << scale << ')'; - use->addAttribute("transform", oss.str()); - } - appendToDefs(use); + if (scale != 1.0) + useNode->addAttribute("transform", "scale("+XMLString(scale)+")"); + appendToDefs(std::move(useNode)); } } else { @@ -306,13 +298,14 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr /** Pushes a new context element that will take all following nodes added to the page. */ -void SVGTree::pushContextElement (XMLElementNode *node) { +void SVGTree::pushContextElement (unique_ptr<XMLElementNode> &&node) { + XMLElementNode *nodePtr = node.get(); if (_contextElementStack.empty()) - _page->append(node); + _page->append(std::move(node)); else - _contextElementStack.top()->append(node); - _contextElementStack.push(node); - _charHandler->setInitialContextNode(node); + _contextElementStack.top()->append(std::move(node)); + _contextElementStack.push(nodePtr); + _charHandler->setInitialContextNode(nodePtr); } @@ -330,16 +323,16 @@ static inline string extract_id_from_url (const string &url) { } -/** Removes elements present in the SVH tree that are not required. +/** Removes elements present in the SVG tree that are not required. * For now, only clipPath elements are removed. */ void SVGTree::removeRedundantElements () { - vector<XMLElementNode*> clipElements; - if (!_defs || !_defs->getDescendants("clipPath", 0, clipElements)) + vector<XMLElementNode*> clipPathElements; + if (!_defs || !_defs->getDescendants("clipPath", nullptr, clipPathElements)) return; // collect dependencies between clipPath elements in the defs section of the SVG tree DependencyGraph<string> idTree; - for (const XMLElementNode *clip : clipElements) { + for (const XMLElementNode *clip : clipPathElements) { if (const char *id = clip->getAttributeValue("id")) { if (const char *url = clip->getAttributeValue("clip-path")) idTree.insert(extract_id_from_url(url), id); @@ -347,18 +340,16 @@ void SVGTree::removeRedundantElements () { idTree.insert(id); } } - // collect elements that reference a clipPath (have a clip-path attribute) + // collect elements that reference a clipPath, i.e. have a clip-path attribute vector<XMLElementNode*> descendants; - _page->getDescendants(0, "clip-path", descendants); + _page->getDescendants(nullptr, "clip-path", descendants); // remove referenced IDs and their dependencies from the dependency graph for (const XMLElementNode *elem : descendants) { string idref = extract_id_from_url(elem->getAttributeValue("clip-path")); idTree.removeDependencyPath(idref); } descendants.clear(); - vector<string> ids; - idTree.getKeys(ids); - for (const string &str : ids) { + for (const string &str : idTree.getKeys()) { XMLElementNode *node = _defs->getFirstDescendant("clipPath", "id", str.c_str()); _defs->remove(node); } @@ -367,11 +358,12 @@ void SVGTree::removeRedundantElements () { XMLCDataNode* SVGTree::styleCDataNode () { if (!_styleCDataNode) { - XMLElementNode *styleNode = new XMLElementNode("style"); + auto styleNode = util::make_unique<XMLElementNode>("style"); styleNode->addAttribute("type", "text/css"); - _root->insertBefore(styleNode, _page); - _styleCDataNode = new XMLCDataNode; - styleNode->append(_styleCDataNode); + auto cdataNode = util::make_unique<XMLCDataNode>(); + _styleCDataNode = cdataNode.get(); + styleNode->append(std::move(cdataNode)); + _root->insertBefore(std::move(styleNode), _page); } return _styleCDataNode; -}
\ No newline at end of file +} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp index 82ccc8332dc..9cac4ff51d9 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp @@ -2,7 +2,7 @@ ** SVGTree.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -25,6 +25,7 @@ #include <memory> #include <set> #include <stack> +#include <unordered_set> #include "Color.hpp" #include "FontWriter.hpp" #include "GFGlyphTracer.hpp" @@ -45,15 +46,15 @@ class SVGTree { void reset (); bool write (std::ostream &os) const {return bool(_doc.write(os));} void newPage (int pageno); - void appendToDefs (XMLNode *node); - void appendToPage (XMLNode *node); - void prependToPage (XMLNode *node); - void appendToDoc (XMLNode *node) {_doc.append(node);} - void appendToRoot (XMLNode *node) {_root->append(node);} + void appendToDefs (std::unique_ptr<XMLNode> &&node); + void appendToPage (std::unique_ptr<XMLNode> &&node); + void prependToPage (std::unique_ptr<XMLNode> &&node); + void appendToDoc (std::unique_ptr<XMLNode> &&node) {_doc.append(std::move(node));} + void appendToRoot (std::unique_ptr<XMLNode> &&node) {_root->append(std::move(node));} void appendChar (int c, double x, double y) {_charHandler->appendChar(c, x, y);} - void appendFontStyles (const std::set<const Font*> &fonts); + void appendFontStyles (const std::unordered_set<const Font*> &fonts); void append (const PhysicalFont &font, const std::set<int> &chars, GFGlyphTracer::Callback *callback=0); - void pushContextElement (XMLElementNode *node); + void pushContextElement (std::unique_ptr<XMLElementNode> &&node); void popContextElement (); void removeRedundantElements (); void setBBox (const BoundingBox &bbox); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.cpp index 97a567fd20d..f3239da84ba 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.cpp @@ -2,7 +2,7 @@ ** ShadingPatch.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,6 +22,7 @@ #include "ShadingPatch.hpp" #include "TensorProductPatch.hpp" #include "TriangularPatch.hpp" +#include "utility.hpp" using namespace std; @@ -48,12 +49,12 @@ void ShadingPatch::colorQueryFuncs (ColorGetter &getter, ColorSetter &setter) co /** Factory method: Creates a shading patch object depending on the given PostScript shading type. */ -ShadingPatch* ShadingPatch::create (int psShadingType, Color::ColorSpace cspace) { +unique_ptr<ShadingPatch> ShadingPatch::create (int psShadingType, Color::ColorSpace cspace) { switch (psShadingType) { - case 4: return new TriangularPatch(cspace); - case 5: return new LatticeTriangularPatch(cspace); - case 6: return new CoonsPatch(cspace); - case 7: return new TensorProductPatch(cspace); + case 4: return util::make_unique<TriangularPatch>(cspace); + case 5: return util::make_unique<LatticeTriangularPatch>(cspace); + case 6: return util::make_unique<CoonsPatch>(cspace); + case 7: return util::make_unique<TensorProductPatch>(cspace); } ostringstream oss; if (psShadingType > 0 && psShadingType < 4) diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp index 25d88d0ac49..c401b959d1a 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp @@ -2,7 +2,7 @@ ** ShadingPatch.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,21 +21,21 @@ #ifndef SHADINGPATCH_HPP #define SHADINGPATCH_HPP +#include <memory> #include "Color.hpp" #include "GraphicsPath.hpp" #include "MessageException.hpp" -class ShadingPatch -{ +class ShadingPatch { public: struct Callback { virtual ~Callback () =default; virtual void patchSegment (GraphicsPath<double> &path, const Color &color) =0; }; - typedef std::vector<DPair> PointVec; - typedef std::vector<Color> ColorVec; + using PointVec = std::vector<DPair>; + using ColorVec = std::vector<Color>; public: ShadingPatch (Color::ColorSpace colorSpace) : _colorspace(colorSpace) {} @@ -50,11 +50,11 @@ class ShadingPatch virtual int numColors (int edgeflag) const =0; virtual Color averageColor() const =0; Color::ColorSpace colorSpace () const {return _colorspace;} - static ShadingPatch* create (int psShadingType, Color::ColorSpace cspace); + static std::unique_ptr<ShadingPatch> create (int psShadingType, Color::ColorSpace cspace); protected: - typedef void (Color::*ColorGetter)(std::valarray<double> &va) const; - typedef void (Color::*ColorSetter)(const std::valarray<double> &va); + using ColorGetter = void (Color::*)(std::valarray<double> &va) const; + using ColorSetter = void (Color::*)(const std::valarray<double> &va); void colorQueryFuncs (ColorGetter &getter, ColorSetter &setter) const; private: @@ -62,8 +62,7 @@ class ShadingPatch }; -struct ShadingException : public MessageException -{ +struct ShadingException : public MessageException { ShadingException (const std::string &msg) : MessageException(msg) {} }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp index 696c99ac18d..988ec8d19a5 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp @@ -2,7 +2,7 @@ ** SignalHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,13 +23,38 @@ #include <csignal> #include <cstdlib> #include "SignalHandler.hpp" +#include "utility.hpp" using namespace std; -bool SignalHandler::_break = false; +volatile bool SignalHandler::_break = false; + +/** Helper class that encapsulates the system-specific parts of + * registering and handling CTRL-C (SIGINT) events. */ +class SignalHandler::Impl { + using HandlerFunc = void (*)(int); + public: + Impl (); + bool setSigintHandler (HandlerFunc handler); + bool restoreSigintHandler (); + + private: +#ifdef HAVE_SIGACTION + struct sigaction _currentSigaction; + struct sigaction _origSigaction; +#else + HandlerFunc _origHandlerFunc; +#endif +}; + + +SignalHandler::SignalHandler () + : _active(false), _impl(util::make_unique<SignalHandler::Impl>()) +{ +} -SignalHandler::~SignalHandler() { +SignalHandler::~SignalHandler () { stop(); } @@ -46,19 +71,17 @@ SignalHandler& SignalHandler::instance() { bool SignalHandler::start () { if (!_active) { _break = false; - if (signal(SIGINT, SignalHandler::callback) != SIG_ERR) { + if (_impl->setSigintHandler(callback)) _active = true; - return true; - } } - return false; + return _active; } /** Stops listening for CTRL-C signals. */ void SignalHandler::stop () { if (_active) { - signal(SIGINT, SIG_DFL); + _impl->restoreSigintHandler(); _active = false; } } @@ -84,3 +107,47 @@ void SignalHandler::callback (int) { _break = true; } + +// Prefer sigaction() to signal() due to its more reliable interface and behavior. +// Use signal() as fallback on systems that don't provide sigaction(). + +#ifdef HAVE_SIGACTION + +SignalHandler::Impl::Impl () { + _origSigaction.sa_handler = nullptr; +} + + +bool SignalHandler::Impl::setSigintHandler (HandlerFunc handler) { + sigemptyset(&_currentSigaction.sa_mask); + _currentSigaction.sa_handler = handler; + _currentSigaction.sa_flags = SA_SIGINFO; + return (sigaction(SIGINT, &_currentSigaction, &_origSigaction) == 0); +} + + +bool SignalHandler::Impl::restoreSigintHandler () { + if (_origSigaction.sa_handler == nullptr) + return false; + return (sigaction(SIGINT, &_origSigaction, 0) == 0); +} + +#else // !HAVE_SIGACTION + +SignalHandler::Impl::Impl () : _origHandlerFunc(SIG_ERR) { +} + + +bool SignalHandler::Impl::setSigintHandler (HandlerFunc handler) { + _origHandlerFunc = signal(SIGINT, handler); + return _origHandlerFunc != SIG_ERR; +} + + +bool SignalHandler::Impl::restoreSigintHandler () { + if (_origHandlerFunc == SIG_ERR) + return false; + return (signal(SIGINT, _origHandlerFunc) != SIG_ERR); +} + +#endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.hpp index c1c48346d43..06dd163f38e 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.hpp @@ -2,7 +2,7 @@ ** SignalHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,14 +22,16 @@ #define SIGNALHANDLER_HPP #include <exception> +#include <memory> struct SignalException : public std::exception { }; -class SignalHandler -{ +class SignalHandler { public: + SignalHandler (const SignalHandler&) =delete; + SignalHandler (SignalHandler&&) =delete; ~SignalHandler (); static SignalHandler& instance (); bool start (); @@ -39,12 +41,14 @@ class SignalHandler bool active () const {return _active;} protected: - SignalHandler () : _active(false) {} + SignalHandler (); static void callback (int signal); private: bool _active; ///< true if listening for signals - static bool _break; ///< true if signal has been caught + static volatile bool _break; ///< true if signal has been caught + class Impl; + std::unique_ptr<Impl> _impl; ///< system-specific data/functions }; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp index 5dfaaa17b08..80dbd595d91 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp @@ -2,7 +2,7 @@ ** SpecialActions.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,6 +22,7 @@ #define SPECIALACTIONS_HPP #include <string> +#include <memory> #include "BoundingBox.hpp" #include "Color.hpp" #include "Matrix.hpp" @@ -29,8 +30,7 @@ class XMLNode; class XMLElementNode; -class SpecialActions -{ +class SpecialActions { public: virtual ~SpecialActions () =default; virtual double getX () const =0; @@ -44,10 +44,10 @@ class SpecialActions virtual const Matrix& getMatrix () const =0; virtual void getPageTransform (Matrix &matrix) const =0; virtual void setBgColor (const Color &color) =0; - virtual void appendToPage (XMLNode *node) =0; - virtual void appendToDefs (XMLNode *node) =0; - virtual void prependToPage (XMLNode *node) =0; - virtual void pushContextElement (XMLElementNode *node) =0; + virtual void appendToPage(std::unique_ptr<XMLNode> &&node) =0; + virtual void appendToDefs(std::unique_ptr<XMLNode> &&node) =0; + virtual void prependToPage(std::unique_ptr<XMLNode> &&node) =0; + virtual void pushContextElement (std::unique_ptr<XMLElementNode> &&node) =0; virtual void popContextElement () =0; virtual BoundingBox& bbox () =0; virtual BoundingBox& bbox (const std::string &name, bool reset=false) =0; @@ -63,8 +63,7 @@ class SpecialActions }; -class EmptySpecialActions : public SpecialActions -{ +class EmptySpecialActions : public SpecialActions { public: double getX () const override {return 0;} double getY () const override {return 0;} @@ -77,10 +76,10 @@ class EmptySpecialActions : public SpecialActions void setMatrix (const Matrix &m) override {} const Matrix& getMatrix () const override {return _matrix;} void getPageTransform (Matrix &matrix) const override {} - void appendToPage (XMLNode *node) override {} - void appendToDefs (XMLNode *node) override {} - void prependToPage (XMLNode *node) override {} - void pushContextElement (XMLElementNode *node) override {} + void appendToPage(std::unique_ptr<XMLNode> &&node) override {} + void appendToDefs(std::unique_ptr<XMLNode> &&node) override {} + void prependToPage(std::unique_ptr<XMLNode> &&node) override {} + void pushContextElement (std::unique_ptr<XMLElementNode> &&node) override {} void popContextElement () override {} BoundingBox& bbox () override {return _bbox;} BoundingBox& bbox (const std::string &name, bool reset=false) override {return _bbox;} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp index 1822181ad4c..e08bcd6092d 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp @@ -2,7 +2,7 @@ ** SpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,6 +23,7 @@ #include <istream> #include <list> +#include <vector> #include "MessageException.hpp" @@ -30,48 +31,42 @@ class SpecialActions; class SpecialManager; -struct SpecialException : public MessageException -{ +struct SpecialException : public MessageException { SpecialException (const std::string &msg) : MessageException(msg) {} }; -struct DVIPreprocessingListener -{ +struct DVIPreprocessingListener { virtual ~DVIPreprocessingListener () =default; virtual void dviPreprocessingFinished () =0; }; -struct DVIBeginPageListener -{ +struct DVIBeginPageListener { virtual ~DVIBeginPageListener () =default; virtual void dviBeginPage (unsigned pageno, SpecialActions &actions) =0; }; -struct DVIEndPageListener -{ +struct DVIEndPageListener { virtual ~DVIEndPageListener () =default; virtual void dviEndPage (unsigned pageno, SpecialActions &actions) =0; }; -struct DVIPositionListener -{ +struct DVIPositionListener { virtual ~DVIPositionListener () =default; virtual void dviMovedTo (double x, double y, SpecialActions &actions) =0; }; -class SpecialHandler -{ +class SpecialHandler { friend class SpecialManager; public: virtual ~SpecialHandler () =default; - virtual const char** prefixes () const=0; virtual const char* info () const=0; virtual const char* name () const=0; + virtual const std::vector<const char*> prefixes () const=0; virtual void setDviScaleFactor (double dvi2bp) {} virtual void preprocess (const char *prefix, std::istream &is, SpecialActions &actions) {} virtual bool process (const char *prefix, std::istream &is, SpecialActions &actions)=0; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp index 9a2027cb8f7..7b0c66c9b5b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp @@ -2,7 +2,7 @@ ** SpecialManager.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,24 +18,18 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <iomanip> +#include <map> #include <sstream> #include "SpecialActions.hpp" #include "SpecialHandler.hpp" #include "SpecialManager.hpp" -#include "PsSpecialHandler.hpp" using namespace std; double SpecialActions::PROGRESSBAR_DELAY=1000; // initial delay in seconds (values >= 1000 disable the progressbar) -SpecialManager::~SpecialManager () { - unregisterHandlers(); -} - - SpecialManager& SpecialManager::instance() { static SpecialManager sm; return sm; @@ -44,11 +38,11 @@ SpecialManager& SpecialManager::instance() { /** Remove all registered handlers. */ void SpecialManager::unregisterHandlers () { - for (SpecialHandler *handler : _pool) - delete handler; - _pool.clear(); - _handlers.clear(); + _handlerPool.clear(); + _handlersByPrefix.clear(); + _beginPageListeners.clear(); _endPageListeners.clear(); + _preprocListeners.clear(); _positionListeners.clear(); } @@ -56,20 +50,21 @@ void SpecialManager::unregisterHandlers () { /** Registers a single special handler. This method doesn't check if a * handler of the same class is already registered. * @param[in] handler pointer to handler to be registered */ -void SpecialManager::registerHandler (SpecialHandler *handler) { +void SpecialManager::registerHandler (unique_ptr<SpecialHandler> &&handler) { if (handler) { // get array of prefixes this handler is responsible for - _pool.push_back(handler); - for (const char **p=handler->prefixes(); *p; ++p) - _handlers[*p] = handler; - if (DVIPreprocessingListener *listener = dynamic_cast<DVIPreprocessingListener*>(handler)) + for (const char *prefix : handler->prefixes()) + _handlersByPrefix[prefix] = handler.get(); + // initialize listener vectors + if (auto listener = dynamic_cast<DVIPreprocessingListener*>(handler.get())) _preprocListeners.push_back(listener); - if (DVIBeginPageListener *listener = dynamic_cast<DVIBeginPageListener*>(handler)) + if (auto listener = dynamic_cast<DVIBeginPageListener*>(handler.get())) _beginPageListeners.push_back(listener); - if (DVIEndPageListener *listener = dynamic_cast<DVIEndPageListener*>(handler)) + if (auto listener = dynamic_cast<DVIEndPageListener*>(handler.get())) _endPageListeners.push_back(listener); - if (DVIPositionListener *listener = dynamic_cast<DVIPositionListener*>(handler)) + if (auto listener = dynamic_cast<DVIPositionListener*>(handler.get())) _positionListeners.push_back(listener); + _handlerPool.emplace_back(std::move(handler)); } } @@ -80,32 +75,41 @@ void SpecialManager::registerHandler (SpecialHandler *handler) { * e.g. "color, ps, em" or "color: ps em" etc. * @param[in] handlers pointer to zero-terminated array of handlers to be registered * @param[in] ignorelist list of special names to be ignored */ -void SpecialManager::registerHandlers (SpecialHandler **handlers, const char *ignorelist) { - if (handlers) { - string ignorestr = ignorelist ? ignorelist : ""; - for (char &c : ignorestr) - if (!isalnum(c)) - c = '%'; - ignorestr = "%"+ignorestr+"%"; - - for (; *handlers; handlers++) { - if (!(*handlers)->name() || ignorestr.find("%"+string((*handlers)->name())+"%") == string::npos) - registerHandler(*handlers); - else - delete *handlers; - } - } +void SpecialManager::registerHandlers (vector<unique_ptr<SpecialHandler>> &handlers, const char *ignorelist) { + if (handlers.empty()) + return; + string ignorestr = ignorelist ? ignorelist : ""; + for (char &c : ignorestr) + if (!isalnum(c)) + c = '%'; + ignorestr = "%"+ignorestr+"%"; + + for (auto &handler : handlers) + if (!handler->name() || ignorestr.find("%"+string(handler->name())+"%") == string::npos) + registerHandler(std::move(handler)); } -/** Looks for an appropriate handler for a given special prefix. +/** Looks for a handler responsible for a given special prefix. * @param[in] prefix the special prefix, e.g. "color" or "em" * @return in case of success: pointer to handler, 0 otherwise */ -SpecialHandler* SpecialManager::findHandler (const string &prefix) const { - auto it = _handlers.find(prefix); - if (it != _handlers.end()) +SpecialHandler* SpecialManager::findHandlerByPrefix (const string &prefix) const { + auto it = _handlersByPrefix.find(prefix); + if (it != _handlersByPrefix.end()) return it->second; - return 0; + return nullptr; +} + + +/** Looks for a handler with a given name. + * @param[in] name name of handler to look for, e.g. "papersize" + * @return in case of success: pointer to handler, 0 otherwise */ +SpecialHandler* SpecialManager::findHandlerByName (const string &name) const { + for (auto &handler : _handlerPool) { + if (handler->name() == name) + return handler.get(); + } + return nullptr; } @@ -114,7 +118,7 @@ static string extract_prefix (istream &is) { string prefix; while (isalnum(c=is.get())) prefix += c; - if (ispunct(c)) // also add seperation character to identifying prefix + if (ispunct(c)) // also add separation character to identifying prefix prefix += c; if (prefix == "ps:" && is.peek() == ':') prefix += is.get(); @@ -125,7 +129,7 @@ static string extract_prefix (istream &is) { void SpecialManager::preprocess (const string &special, SpecialActions &actions) const { istringstream iss(special); string prefix = extract_prefix(iss); - if (SpecialHandler *handler = findHandler(prefix)) + if (SpecialHandler *handler = findHandlerByPrefix(prefix)) handler->preprocess(prefix.c_str(), iss, actions); } @@ -140,7 +144,7 @@ bool SpecialManager::process (const string &special, double dvi2bp, SpecialActio istringstream iss(special); string prefix = extract_prefix(iss); bool success=false; - if (SpecialHandler *handler = findHandler(prefix)) { + if (SpecialHandler *handler = findHandlerByPrefix(prefix)) { handler->setDviScaleFactor(dvi2bp); success = handler->process(prefix.c_str(), iss, actions); } @@ -149,36 +153,36 @@ bool SpecialManager::process (const string &special, double dvi2bp, SpecialActio void SpecialManager::notifyPreprocessingFinished () const { - for (DVIPreprocessingListener *listener : _preprocListeners) + for (auto *listener : _preprocListeners) listener->dviPreprocessingFinished(); } void SpecialManager::notifyBeginPage (unsigned pageno, SpecialActions &actions) const { - for (DVIBeginPageListener *listener : _beginPageListeners) + for (auto *listener : _beginPageListeners) listener->dviBeginPage(pageno, actions); } void SpecialManager::notifyEndPage (unsigned pageno, SpecialActions &actions) const { - for (DVIEndPageListener *listener : _endPageListeners) + for (auto *listener : _endPageListeners) listener->dviEndPage(pageno, actions); } void SpecialManager::notifyPositionChange (double x, double y, SpecialActions &actions) const { - for (DVIPositionListener *listener : _positionListeners) + for (auto *listener : _positionListeners) listener->dviMovedTo(x, y, actions); } void SpecialManager::writeHandlerInfo (ostream &os) const { ios::fmtflags osflags(os.flags()); - HandlerMap sortmap; - for (const auto &strhandlerpair : _handlers) - if (strhandlerpair.second->name()) - sortmap[strhandlerpair.second->name()] = strhandlerpair.second; - for (auto &strhandlerpair : sortmap) { + map<string,SpecialHandler*> sortmap; + for (const auto &handler : _handlerPool) + if (handler->name()) + sortmap[handler->name()] = handler.get(); + for (const auto &strhandlerpair : sortmap) { os << setw(10) << left << strhandlerpair.second->name() << ' '; if (strhandlerpair.second->info()) os << strhandlerpair.second->info(); @@ -186,4 +190,3 @@ void SpecialManager::writeHandlerInfo (ostream &os) const { } os.flags(osflags); // restore format flags } - diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp index 919881811a4..250ebef082b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp @@ -2,7 +2,7 @@ ** SpecialManager.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,25 +21,24 @@ #ifndef SPECIALMANAGER_HPP #define SPECIALMANAGER_HPP -#include <map> +#include <memory> #include <ostream> #include <string> +#include <unordered_map> #include <vector> #include "SpecialHandler.hpp" class SpecialActions; -class SpecialManager -{ +class SpecialManager { private: - typedef std::vector<SpecialHandler*> HandlerPool; - typedef std::map<std::string,SpecialHandler*> HandlerMap; + using HandlerPool = std::vector<std::unique_ptr<SpecialHandler>>; + using HandlerMap = std::unordered_map<std::string,SpecialHandler*>; public: - ~SpecialManager (); static SpecialManager& instance (); - void registerHandler (SpecialHandler *handler); - void registerHandlers (SpecialHandler **handlers, const char *ignorelist); + void registerHandler (std::unique_ptr<SpecialHandler> &&handler); + void registerHandlers (std::vector<std::unique_ptr<SpecialHandler>> &handlers, const char *ignorelist); void unregisterHandlers (); void preprocess (const std::string &special, SpecialActions &actions) const; bool process (const std::string &special, double dvi2bp, SpecialActions &actions) const; @@ -48,15 +47,16 @@ class SpecialManager void notifyEndPage (unsigned pageno, SpecialActions &actions) const; void notifyPositionChange (double x, double y, SpecialActions &actions) const; void writeHandlerInfo (std::ostream &os) const; + SpecialHandler* findHandlerByName (const std::string &name) const; protected: - SpecialManager () {} - SpecialManager (const SpecialManager &) {} - SpecialHandler* findHandler (const std::string &prefix) const; + SpecialManager () =default; + SpecialManager (const SpecialManager &) =delete; + SpecialHandler* findHandlerByPrefix (const std::string &prefix) const; private: - HandlerPool _pool; ///< stores pointers to all handlers - HandlerMap _handlers; ///< pointers to handlers for corresponding prefixes + HandlerPool _handlerPool; ///< stores pointers to all handlers + HandlerMap _handlersByPrefix; ///< pointers to handlers for corresponding prefixes std::vector<DVIPreprocessingListener*> _preprocListeners; std::vector<DVIBeginPageListener*> _beginPageListeners; std::vector<DVIEndPageListener*> _endPageListeners; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp index 60080634ce9..3e4fa2adcc5 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp @@ -2,7 +2,7 @@ ** StreamReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp index 45cafe73423..586bf0b6980 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp @@ -2,7 +2,7 @@ ** StreamReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -28,8 +28,7 @@ class CRC32; -class StreamReader -{ +class StreamReader { public: StreamReader (std::istream &is) : _is(&is) {} virtual ~StreamReader () =default; @@ -62,8 +61,7 @@ class StreamReader }; -struct StreamReaderException : public MessageException -{ +struct StreamReaderException : public MessageException { StreamReaderException (const std::string &msg) : MessageException(msg) {} }; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp index 16bd13c82ce..9291f066ad7 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp @@ -2,7 +2,7 @@ ** StreamWriter.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include "CRC32.hpp" #include "StreamWriter.hpp" @@ -42,12 +41,28 @@ void StreamWriter::writeSigned (int32_t val, int n) { } -/** Writes a signed integer to the output stream. - * @param[in] val the value to write +void StreamWriter::writeBytes (const std::vector<uint8_t> &bytes) { + _os.write(reinterpret_cast<const char*>(bytes.data()), bytes.size()); +} + + +void StreamWriter::writeBytes (const uint8_t *buf, size_t bufsize) { + _os.write(reinterpret_cast<const char*>(buf), bufsize); +} + + +void StreamWriter::writeBytes (int byte, size_t count) { + while (count-- > 0) + _os.put(byte); +} + + +/** Writes a string to the output stream. + * @param[in] str the string to write * @param[in] finalZero if true, a final 0-byte is appended */ void StreamWriter::writeString (const string &str, bool finalZero) { - for (size_t i=0; i < str.length(); i++) - _os.put(str[i]); + for (char c : str) + _os.put(c); if (finalZero) _os.put(0); } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp index bc6e504348a..8228bd04267 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp @@ -2,7 +2,7 @@ ** StreamWriter.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,17 +22,19 @@ #define STREAMWRITER_HPP #include <ostream> - +#include <vector> class CRC32; -class StreamWriter -{ +class StreamWriter { public: StreamWriter (std::ostream &os) : _os(os) {} virtual ~StreamWriter () =default; void writeUnsigned (uint32_t val, int n); void writeSigned (int32_t val, int n); + void writeBytes (const std::vector<uint8_t> &bytes); + void writeBytes (const uint8_t *buf, size_t bufsize); + void writeBytes (int byte, size_t count); void writeString (const std::string &str, bool finalZero=false); void writeUnsigned (uint32_t val, int n, CRC32 &crc32); void writeSigned (int32_t val, int n, CRC32 &crc32); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp index 8eadf5e0e78..dff6337ad1c 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp @@ -2,7 +2,7 @@ ** Subfont.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -26,6 +26,7 @@ #include "FileFinder.hpp" #include "Message.hpp" #include "Subfont.hpp" +#include "utility.hpp" using namespace std; @@ -33,7 +34,7 @@ using namespace std; // helper functions static int skip_mapping_data (istream &is); -static bool scan_line (const char *line, int lineno, uint16_t *mapping, const string &fname, long &pos); +static bool scan_line (const char *line, int lineno, vector<uint16_t> &mapping, const string &fname, long &pos); /** Constructs a new SubfontDefinition object. @@ -52,9 +53,9 @@ SubfontDefinition::SubfontDefinition (const string &name, const char *fpath) : _ while (is && !isspace(is.peek())) id += is.get(); if (!id.empty()) { - auto state = _subfonts.emplace(pair<string,Subfont*>(id, (Subfont*)0)); + auto state = _subfonts.emplace(pair<string,unique_ptr<Subfont>>(id, unique_ptr<Subfont>())); if (state.second) // id was not present in map already - state.first->second = new Subfont(*this, state.first->first); + state.first->second = unique_ptr<Subfont>(new Subfont(*this, state.first->first)); skip_mapping_data(is); } } @@ -62,12 +63,6 @@ SubfontDefinition::SubfontDefinition (const string &name, const char *fpath) : _ } -SubfontDefinition::~SubfontDefinition () { - for (auto &entry : _subfonts) - delete entry.second; -} - - /** Looks for a subfont definition of the given name and returns the corresponding object. * All objects are only created once for a given name and stored in an internal cache. * @param[in] name name of subfont definition to lookup @@ -77,12 +72,12 @@ SubfontDefinition* SubfontDefinition::lookup (const std::string &name) { auto it = sfdMap.find(name); if (it != sfdMap.end()) return it->second.get(); - unique_ptr<SubfontDefinition> sfd; + SubfontDefinition *sfd=nullptr; if (const char *path = FileFinder::instance().lookup(name+".sfd", false)) { - sfd.reset(new SubfontDefinition(name, path)); - sfdMap[name] = std::move(sfd); + sfd = new SubfontDefinition(name, path); + sfdMap[name] = unique_ptr<SubfontDefinition>(sfd); } - return sfd.get(); + return sfd; } @@ -96,24 +91,20 @@ const char* SubfontDefinition::path () const { Subfont* SubfontDefinition::subfont (const string &id) const { auto it = _subfonts.find(id); if (it != _subfonts.end()) - return it->second; - return 0; + return it->second.get(); + return nullptr; } /** Returns all subfonts defined in this SFD. */ int SubfontDefinition::subfonts (vector<Subfont*> &sfs) const { for (const auto &strsfpair : _subfonts) - sfs.push_back(strsfpair.second); + sfs.push_back(strsfpair.second.get()); return int(sfs.size()); } ////////////////////////////////////////////////////////////////////// -Subfont::~Subfont () { - delete [] _mapping; -} - /** Reads the character mappings for a given subfont ID. * Format of subfont definition (sfd) files: @@ -128,13 +119,12 @@ Subfont::~Subfont () { * to c=10, 11 and 12, respectively. * @return true if the data has been read successfully */ bool Subfont::read () { - if (_mapping) // if there's already a mapping assigned, we're finished here + if (!_mapping.empty()) // if there's already a mapping assigned, we're finished here return true; if (const char *p = _sfd.path()) { ifstream is(p); if (!is) return false; - int lineno=1; while (is) { if (is.peek() == '#' || is.peek() == '\n') { @@ -151,14 +141,13 @@ bool Subfont::read () { lineno += skip_mapping_data(is); else { // build mapping array - _mapping = new uint16_t[256]; - memset(_mapping, 0, 256*sizeof(uint16_t)); + _mapping.resize(256, 0); long pos=0; char buf[1024]; bool complete=false; while (!complete) { is.getline(buf, 1024); - complete = scan_line(buf, lineno, _mapping, _sfd.filename() ,pos); + complete = scan_line(buf, lineno, _mapping, _sfd.filename(), pos); } return true; } @@ -174,7 +163,7 @@ bool Subfont::read () { * @param[in] c local character code relative to the subfont * @return character code of the target font */ uint16_t Subfont::decode (unsigned char c) { - if (!_mapping && !read()) + if (_mapping.empty() && !read()) return 0; return _mapping[c]; } @@ -210,7 +199,7 @@ static int skip_mapping_data (istream &is) { * @param[in] fname name of the mapfile being scanned * @param[in,out] offset position/index of next mapping value * @return true if the line is the last one the current mapping sequence, i.e. the line doesn't end with a backslash */ -static bool scan_line (const char *line, int lineno, uint16_t *mapping, const string &fname, long &offset) { +static bool scan_line (const char *line, int lineno, vector<uint16_t> &mapping, const string &fname, long &offset) { const char *p=line; char *q; for (; *p && isspace(*p); p++); @@ -223,11 +212,10 @@ static bool scan_line (const char *line, int lineno, uint16_t *mapping, const st else { long val1 = strtol(p, &q, 0); // first value of range long val2 = -1; // last value of range - ostringstream oss; // output stream for exception messages switch (*q) { case ':': if (val1 < 0 || val1 > 255) - throw SubfontException(oss << "offset value " << val1 << " out of range (0-255)", fname, lineno); + throw SubfontException("offset value "+to_string(val1)+" out of range (0-255)", fname, lineno); offset = val1; val1 = -1; q++; @@ -236,25 +224,25 @@ static bool scan_line (const char *line, int lineno, uint16_t *mapping, const st p = q+1; val2 = strtol(p, &q, 0); if (val1 < 0 || val1 > 0xffffL) - throw SubfontException(oss << "table value " << val1 << " out of range", fname, lineno); + throw SubfontException("table value "+to_string(val1)+" out of range", fname, lineno); if (val2 < 0 || val2 > 0xffffL) - throw SubfontException(oss << "table value " << val2 << " out of range", fname, lineno); + throw SubfontException("table value "+to_string(val2)+" out of range", fname, lineno); if (p == q || (!isspace(*q) && *q != '\\' && *q)) - throw SubfontException(oss << "unexpected character '" << *q << "'", fname, lineno); + throw SubfontException("unexpected character '"+to_string(*q)+"'", fname, lineno); break; default: if (p == q || (!isspace(*q) && *q != '\\' && *q)) - throw SubfontException(oss << "unexpected character '" << *q << "'", fname, lineno); + throw SubfontException("unexpected character '"+to_string(*q)+"'", fname, lineno); if (val1 < 0 || val1 > 0xffffL) throw SubfontException("invalid character code", fname, lineno); val2 = val1; } if (val1 >= 0) { if (val1 > val2 || offset+val2-val1 > 255) - throw SubfontException(oss << "invalid range in mapping table: " << hex << val1 << '_' << val2, fname, lineno); + throw SubfontException("invalid range in mapping table: "+util::tohex(val1)+"_"+util::tohex(val2), fname, lineno); for (long v=val1; v <= val2; v++) { if (mapping[offset]) - throw SubfontException(oss << "mapping of character " << offset << " already defined", fname, lineno); + throw SubfontException("mapping of character "+to_string(offset)+" already defined", fname, lineno); mapping[offset++] = static_cast<uint16_t>(v); } } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp index 46c322a4c08..a1aa52a4d58 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp @@ -2,7 +2,7 @@ ** Subfont.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,22 +23,20 @@ #include <istream> #include <map> +#include <memory> #include <sstream> #include <string> #include <vector> #include "MessageException.hpp" - class Subfont; /** Represents a collection of subfont mappings as defined in a .sfd file, and * encapsulates the evaluation of these files. */ -class SubfontDefinition -{ - typedef std::map<std::string, Subfont*> Subfonts; +class SubfontDefinition { + using Subfonts = std::map<std::string, std::unique_ptr<Subfont>>; public: - ~SubfontDefinition (); static SubfontDefinition* lookup (const std::string &name); // int getIDs (std::vector<std::string> &ids) const; const std::string& name() const {return _sfname;} @@ -49,7 +47,7 @@ class SubfontDefinition protected: SubfontDefinition (const std::string &name, const char *fpath); - SubfontDefinition (const SubfontDefinition &sfd) {} + SubfontDefinition (const SubfontDefinition &sfd) =delete; private: std::string _sfname; ///< name of subfont @@ -58,38 +56,31 @@ class SubfontDefinition /** Represents a single subfont mapping defined in a SubfontDefinition (.sfd file). */ -class Subfont -{ +class Subfont { friend class SubfontDefinition; public: - ~Subfont(); const std::string& id () const {return _id;} uint16_t decode (unsigned char c); protected: Subfont (SubfontDefinition &sfd, const std::string &id) : _sfd(sfd), _id(id), _mapping(0) {} + Subfont (const Subfont &sf) =delete; bool read (); private: - SubfontDefinition &_sfd; ///< SubfontDefinition where this Subfont belongs to - const std::string &_id; ///< id of this subfont as specified in the .sfd file - uint16_t *_mapping; ///< the character mapping table with 256 entries + SubfontDefinition &_sfd; ///< SubfontDefinition where this Subfont belongs to + const std::string &_id; ///< id of this subfont as specified in the .sfd file + std::vector<uint16_t> _mapping; ///< the character mapping table with 256 entries }; -class SubfontException : public MessageException -{ +class SubfontException : public MessageException { public: SubfontException (const std::string &msg, const std::string &fname, int lineno=0) : MessageException(msg), _fname(fname), _lineno(lineno) {} - SubfontException (const std::ostream &oss, const std::string &fname, int lineno=0) - : MessageException(dynamic_cast<const std::ostringstream&>(oss).str()), _fname(fname), _lineno(lineno) {} - - virtual ~SubfontException () throw() =default; - const char* filename () const {return _fname.c_str();} - int lineno () const {return _lineno;} + int lineno () const {return _lineno;} private: std::string _fname; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp index 30af5e0aa00..52d568cd1d9 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp @@ -2,7 +2,7 @@ ** System.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/System.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/System.hpp index 19f89f7074f..7574ccdef0d 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/System.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/System.hpp @@ -2,7 +2,7 @@ ** System.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.cpp index 94901437c7a..0aba9d4811f 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.cpp @@ -2,7 +2,7 @@ ** TFM.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <fstream> #include <vector> #include "FileFinder.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp index 495b051eb89..9fdc432bdf7 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp @@ -2,7 +2,7 @@ ** TFM.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TTFAutohint.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TTFAutohint.cpp new file mode 100644 index 00000000000..e2d7714de42 --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TTFAutohint.cpp @@ -0,0 +1,139 @@ +/************************************************************************* +** TTFAutohint.cpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#include "TTFAutohint.hpp" + +using namespace std; + +#ifndef HAVE_TTFAUTOHINT_H +TTFAutohint::TTFAutohint () {} + +bool TTFAutohint::available () const { + return false; +} + +int TTFAutohint::autohint (const string&, const string&, bool) { + return 0; +} + +string TTFAutohint::lastErrorMessage () const { + return ""; +} + +string TTFAutohint::version () const { + return ""; +} + +#else // HAVE_TTFAUTOHINT_H + +#include <ttfautohint.h> + +#ifndef HAVE_LIBTTFAUTOHINT +static string get_libttfautohint () { +#ifdef _WIN32 + return "ttfautohint.dll"; +#else + string dlname = "libttfautohint.so.1"; +#ifdef __APPLE__ + DLLoader loader(dlname); + if (!loader.loaded()) + dlname = "libttfautohint.1.dylib"; +#endif + return dlname; +#endif // _WIN32 +} +#endif // HAVE_LIBTTFAUTOHINT + + +TTFAutohint::TTFAutohint () : +#ifndef HAVE_LIBTTFAUTOHINT + DLLoader(get_libttfautohint()), +#endif + _lastErrorMessage() +{ +} + + +/** Returns true if the ttfautohint library is present. */ +bool TTFAutohint::available () const { +#ifdef HAVE_LIBTTFAUTOHINT + return true; +#else + return loaded(); +#endif +} + + +/** Runs ttfautohint on a given font file. + * @param[in] source name of TTF input file + * @param[in] target name of TTF output file + * @param[in] rehintIfSymbolFont if true, ttfautohint is run again with option "symbol" in case regular hinting is rejected. + * @return ttfautohint error code (0 = success) */ +int TTFAutohint::autohint (const string &source, const string &target, bool rehintIfSymbolFont) { +#ifdef HAVE_LIBTTFAUTOHINT + auto fn = &TTF_autohint; +#else + auto fn = LOAD_SYMBOL(TTF_autohint); +#endif + int ret=0; + if (fn) { + FILE *ttf_in = fopen(source.c_str(), "rb"); + FILE *ttf_out = fopen(target.c_str(), "wb"); + ret = fn("in-file, out-file, default-script, error-string", ttf_in, ttf_out, "latn", &_lastErrorMessage); + if (ret == TA_Err_Missing_Glyph && rehintIfSymbolFont) { + fseek(ttf_in, 0, SEEK_SET); + fseek(ttf_out, 0, SEEK_SET); + ret = fn("in-file, out-file, symbol, error-string", ttf_in, ttf_out, true, &_lastErrorMessage); + } + fclose(ttf_out); + fclose(ttf_in); + } + return ret; +} + + +/** Returns the error message of the last autohint call. */ +string TTFAutohint::lastErrorMessage () const { + string message; + if (_lastErrorMessage) + message = reinterpret_cast<const char*>(_lastErrorMessage); + return message; +} + + +/** Returns the version number of ttfautohint. */ +string TTFAutohint::version () const { +#ifdef HAVE_LIBTTFAUTOHINT + auto fn = &TTF_autohint_version; +#else + auto fn = LOAD_SYMBOL(TTF_autohint_version); +#endif + string ret; + if (fn) { + int major, minor, revision; + fn(&major, &minor, &revision); + ret = to_string(major)+"."+to_string(minor); + if (revision) + ret += "."+to_string(revision); + } + return ret; +} + +#endif // HAVE_TTFAUTOHINT_H diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TTFAutohint.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TTFAutohint.hpp new file mode 100644 index 00000000000..68d9e89357d --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TTFAutohint.hpp @@ -0,0 +1,51 @@ +/************************************************************************* +** TTFAutohint.hpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#ifndef TTFAUTOHINT_HPP +#define TTFAUTOHINT_HPP + +#include <config.h> +#include <string> + +#if defined(HAVE_TTFAUTOHINT_H) && !defined(HAVE_LIBTTFAUTOHINT) +#include "DLLoader.hpp" +#endif + +class TTFAutohint +#if defined(HAVE_TTFAUTOHINT_H) && !defined(HAVE_LIBTTFAUTOHINT) + : public DLLoader +#endif +{ + public: + TTFAutohint (); + TTFAutohint (const TTFAutohint &ta) =delete; + bool available () const; + int autohint (const std::string &source, const std::string &target, bool rehintIfSymbolFont); + std::string lastErrorMessage () const; + std::string version () const; + +#ifdef HAVE_TTFAUTOHINT_H + private: + const unsigned char *_lastErrorMessage; +#endif +}; + +#endif + diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp index 89ee6174233..4d910e140dc 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp @@ -2,7 +2,7 @@ ** TensorProductPatch.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp index c9d2818fc25..3c8084d03ce 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp @@ -2,7 +2,7 @@ ** TensorProductPatch.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Terminal.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Terminal.cpp index 32ebf3a35f8..f7f185507ba 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Terminal.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Terminal.cpp @@ -2,7 +2,7 @@ ** Terminal.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -30,7 +30,7 @@ #endif #ifdef _WIN32 -#include <windows.h> +#include "windows.hpp" #endif #include <cstdio> diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Terminal.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Terminal.hpp index ea8f67e42d1..c51affcfbdc 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Terminal.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Terminal.hpp @@ -2,7 +2,7 @@ ** Terminal.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ToUnicodeMap.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ToUnicodeMap.cpp index 752b8517fa0..1e405d94a28 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ToUnicodeMap.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ToUnicodeMap.cpp @@ -2,7 +2,7 @@ ** ToUnicodeMap.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ToUnicodeMap.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ToUnicodeMap.hpp index f8ffe3bace9..403651dc0f9 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ToUnicodeMap.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ToUnicodeMap.hpp @@ -2,7 +2,7 @@ ** ToUnicodeMap.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp index ecccf636906..7f007697395 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp @@ -2,7 +2,7 @@ ** TpicSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,9 +18,10 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> +#include <bitset> #include <cstring> #include <sstream> +#include <string> #include "Color.hpp" #include "InputBuffer.hpp" #include "InputReader.hpp" @@ -46,42 +47,77 @@ void TpicSpecialHandler::dviEndPage (unsigned pageno, SpecialActions&) { void TpicSpecialHandler::reset () { _points.clear(); _penwidth = 1.0; - _fill = -1.0; // no fill + _grayLevel = -1.0; // no fill +} + + +/** Returns the current color used to fill closed paths or shapes. + * The TPIC documentation only specifies grayscale colors set by a floating point value + * in the range of 0 (white) and 1 (black). Most DVI drivers extend the color support + * by taking color specials into account: The grayscale colors are only applied if + * the DVI color is set to black. All other colors are directly used as fill color + * without evaluating the TPIC gray level. */ +Color TpicSpecialHandler::fillColor (bool grayOnly) const { + if (_grayLevel >= 0 && (_dviColor == Color::BLACK || grayOnly)) + return Color::WHITE*(1.0-_grayLevel); + return _dviColor; +} + + +/** Adds stroke attributes to a given element depending on the pen width. + * @param[in] elem element node the attributes are added to + * @param[in] penwidth pen with used to compute the stroke parameters + * @param[in] pencolor the drawing color + * @param[in] ddist dash/dot distance of line in PS point units (0:solid line, >0:dashed line, <0:dotted line) */ +static void add_stroke_attribs (XMLElementNode *elem, double penwidth, Color pencolor, double ddist) { + if (penwidth > 0) { // attributes actually required? + elem->addAttribute("stroke", pencolor.svgColorString()); + elem->addAttribute("stroke-width", XMLString(penwidth)); + if (ddist > 0) + elem->addAttribute("stroke-dasharray", XMLString(ddist)); + else if (ddist < 0) + elem->addAttribute("stroke-dasharray", XMLString(penwidth) + ' ' + XMLString(-ddist)); + } +} + + +static unique_ptr<XMLElementNode> create_ellipse_element (double cx, double cy, double rx, double ry) { + bool is_circle = (rx == ry); + auto elem = util::make_unique<XMLElementNode>(is_circle ? "circle" : "ellipse"); + elem->addAttribute("cx", XMLString(cx)); + elem->addAttribute("cy", XMLString(cy)); + if (is_circle) + elem->addAttribute("r", XMLString(rx)); + else { + elem->addAttribute("rx", XMLString(rx)); + elem->addAttribute("ry", XMLString(ry)); + } + return elem; } /** Creates SVG elements that draw lines through the recorded points. - * @param[in] stroke if true, the (out)line is drawn (in black) - * @param[in] fill if true, enclosed area is filled with current color - * @param[in] ddist dash/dot distance of line in PS point units - * (0:solid line, >0:dashed line, <0:dotted line) + * @param[in] ddist dash/dot distance of line in PS point units (0:solid line, >0:dashed line, <0:dotted line) * @param[in] actions object providing the actions that can be performed by the SpecialHandler */ -void TpicSpecialHandler::drawLines (bool stroke, bool fill, double ddist, SpecialActions &actions) { - if (!_points.empty()) { - XMLElementNode *elem=0; +void TpicSpecialHandler::drawLines (double ddist, SpecialActions &actions) { + if (!_points.empty() && (_penwidth > 0 || _grayLevel >= 0)) { + unique_ptr<XMLElementNode> elem; if (_points.size() == 1) { const DPair &p = _points.back(); - elem = new XMLElementNode("circle"); - elem->addAttribute("cx", p.x()+actions.getX()); - elem->addAttribute("cy", p.y()+actions.getY()); - elem->addAttribute("r", _penwidth/2.0); + elem = create_ellipse_element(p.x()+actions.getX(), p.y()+actions.getY(), _penwidth/2.0, _penwidth/2.0); actions.embed(p, _penwidth/2.0); } else { - if (_points.size() == 2 || (!fill && _points.front() != _points.back())) { - elem = new XMLElementNode("polyline"); + if (_points.size() == 2 || (_grayLevel < 0 && _points.front() != _points.back())) { + elem = util::make_unique<XMLElementNode>("polyline"); elem->addAttribute("fill", "none"); elem->addAttribute("stroke-linecap", "round"); } else { - if (_points.front() == _points.back()) + while (_points.front() == _points.back()) _points.pop_back(); - if (_fill < 0) - _fill = 1; - Color color = actions.getColor(); - color *= _fill; - elem = new XMLElementNode("polygon"); - elem->addAttribute("fill", fill ? color.svgColorString() : "none"); + elem = util::make_unique<XMLElementNode>("polygon"); + elem->addAttribute("fill", _grayLevel < 0 ? "none" : fillColor(false).svgColorString()); } ostringstream oss; for (auto it=_points.begin(); it != _points.end(); ++it) { @@ -93,16 +129,9 @@ void TpicSpecialHandler::drawLines (bool stroke, bool fill, double ddist, Specia actions.embed(DPair(x, y)); } elem->addAttribute("points", oss.str()); - if (stroke) { // draw outline? - elem->addAttribute("stroke", "black"); - elem->addAttribute("stroke-width", XMLString(_penwidth)); - } + add_stroke_attribs(elem.get(), _penwidth, Color::BLACK, ddist); } - if (ddist > 0) - elem->addAttribute("stroke-dasharray", XMLString(ddist)); - else if (ddist < 0) - elem->addAttribute("stroke-dasharray", XMLString(_penwidth) + ' ' + XMLString(-ddist)); - actions.appendToPage(elem); + actions.appendToPage(std::move(elem)); } reset(); } @@ -117,177 +146,191 @@ void TpicSpecialHandler::drawLines (bool stroke, bool fill, double ddist, Specia * @param[in] ddist length of dashes and gaps * @param[in] actions object providing the actions that can be performed by the SpecialHandler */ void TpicSpecialHandler::drawSplines (double ddist, SpecialActions &actions) { - if (_points.empty()) - return; - const size_t size = _points.size(); - if (size < 3) - drawLines(true, false, ddist, actions); - else { - DPair p(actions.getX(), actions.getY()); - GraphicsPath<double> path; - path.moveto(p+_points[0]); - DPair mid = p+_points[0]+(_points[1]-_points[0])/2.0; - path.lineto(mid); - actions.embed(p+_points[0]); - for (size_t i=1; i < size-1; i++) { - const DPair p0 = p+_points[i-1]; - const DPair p1 = p+_points[i]; - const DPair p2 = p+_points[i+1]; - mid = p1+(p2-p1)/2.0; - path.conicto(p1, mid); - actions.embed(mid); - actions.embed((p0+p1*6.0+p2)/8.0, _penwidth); + if (!_points.empty() && _penwidth > 0) { + const size_t numPoints = _points.size(); + if (numPoints < 3) { + _grayLevel = -1; + drawLines(ddist, actions); } - if (_points[0] == _points[size-1]) // closed path? - path.closepath(); else { - path.lineto(p+_points[size-1]); - actions.embed(p+_points[size-1]); - } - - Color color = actions.getColor(); - color *= _fill; - XMLElementNode *pathElem = new XMLElementNode("path"); - if (_fill >= 0) { - if (_points[0] != _points[size-1]) + DPair p(actions.getX(), actions.getY()); + GraphicsPath<double> path; + path.moveto(p+_points[0]); + DPair mid = p+_points[0]+(_points[1]-_points[0])/2.0; + path.lineto(mid); + actions.embed(p+_points[0]); + for (size_t i=1; i < numPoints-1; i++) { + const DPair p0 = p+_points[i-1]; + const DPair p1 = p+_points[i]; + const DPair p2 = p+_points[i+1]; + mid = p1+(p2-p1)/2.0; + path.conicto(p1, mid); + actions.embed(mid); + actions.embed((p0+p1*6.0+p2)/8.0, _penwidth); + } + if (_points[0] == _points[numPoints-1]) // closed path? path.closepath(); - pathElem->addAttribute("fill", color.svgColorString()); - } - else + else { + path.lineto(p+_points[numPoints-1]); + actions.embed(p+_points[numPoints-1]); + } + auto pathElem = util::make_unique<XMLElementNode>("path"); pathElem->addAttribute("fill", "none"); - - ostringstream oss; - path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); - pathElem->addAttribute("d", oss.str()); - pathElem->addAttribute("stroke", actions.getColor().svgColorString()); - pathElem->addAttribute("stroke-width", XMLString(_penwidth)); - if (ddist > 0) - pathElem->addAttribute("stroke-dasharray", XMLString(ddist)); - else if (ddist < 0) - pathElem->addAttribute("stroke-dasharray", XMLString(_penwidth) + ' ' + XMLString(-ddist)); - actions.appendToPage(pathElem); + ostringstream oss; + path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); + pathElem->addAttribute("d", oss.str()); + add_stroke_attribs(pathElem.get(), _penwidth, _dviColor, ddist); + actions.appendToPage(std::move(pathElem)); + } } reset(); } +static double normalized_angle (double rad) { + rad = fmod(rad, math::TWO_PI); + if (rad < 0) + rad += math::TWO_PI; + return rad; +} + + /** Draws an elliptical arc. - * @param[in] cx x-coordinate of arc center - * @param[in] cy y-coordinate of arc center - * @param[in] rx length of horizonal semi-axis + * @param[in] cx x-coordinate of arc center relative to current DVI position + * @param[in] cy y-coordinate of arc center relative to current DVI position + * @param[in] rx length of horizontal semi-axis * @param[in] ry length of vertical semi-axis * @param[in] angle1 starting angle (clockwise) relative to x-axis * @param[in] angle2 ending angle (clockwise) relative to x-axis * @param[in] actions object providing the actions that can be performed by the SpecialHandler */ void TpicSpecialHandler::drawArc (double cx, double cy, double rx, double ry, double angle1, double angle2, SpecialActions &actions) { - angle1 *= -1; - angle2 *= -1; - if (fabs(angle1) > math::TWO_PI) { - int n = (int)(angle1/math::TWO_PI); - angle1 = angle1 - n*math::TWO_PI; - angle2 = angle2 - n*math::TWO_PI; - } - - double x = cx + actions.getX(); - double y = cy + actions.getY(); - XMLElementNode *elem=0; - if (fabs(angle1-angle2) >= math::TWO_PI) { // closed ellipse? - elem = new XMLElementNode("ellipse"); - elem->addAttribute("cx", XMLString(x)); - elem->addAttribute("cy", XMLString(y)); - elem->addAttribute("rx", XMLString(rx)); - elem->addAttribute("ry", XMLString(ry)); - } - else { - if (angle1 < 0) - angle1 = math::TWO_PI+angle1; - if (angle2 < 0) - angle2 = math::TWO_PI+angle2; - elem = new XMLElementNode("path"); - int large_arg = fabs(angle1-angle2) > math::PI ? 0 : 1; - int sweep_flag = angle1 > angle2 ? 0 : 1; - if (angle1 > angle2) { - large_arg = 1-large_arg; - sweep_flag = 1-sweep_flag; + if (_penwidth > 0 || _grayLevel >= 0) { + angle1 = -angle1; + angle2 = -angle2; + cx += actions.getX(); + cy += actions.getY(); + unique_ptr<XMLElementNode> elem; + bool closed=true; + if (abs(angle2-angle1) >= math::TWO_PI) // closed ellipse? + elem = create_ellipse_element(cx, cy, rx, ry); + else { + angle1 = normalized_angle(angle1); + angle2 = normalized_angle(angle2); + double delta = normalized_angle(angle2-angle1); + int large_arg = (delta < math::PI) ? 1 : 0; + ostringstream oss; + oss << 'M' << XMLString(cx+rx*cos(angle1)) << ' ' << XMLString(cy+ry*sin(-angle1)) + << 'A' << XMLString(rx) << ' ' << XMLString(ry) + << " 0 " // no rotation of x-axis + << large_arg << " 1 " // always draw arc clockwise (sweep flag == 1) + << XMLString(cx+rx*cos(angle2)) << ' ' << XMLString(cy-ry*sin(angle2)); + if (_grayLevel >= 0) + oss << 'Z'; + else + closed = false; + elem = util::make_unique<XMLElementNode>("path"); + elem->addAttribute("d", oss.str()); } - ostringstream oss; - oss << 'M' << XMLString(x+rx*cos(angle1)) << ',' << XMLString(y+ry*sin(-angle1)) - << 'A' << XMLString(rx) << ',' << XMLString(ry) - << " 0 " - << large_arg << ' ' << sweep_flag << ' ' - << XMLString(x+rx*cos(angle2)) << ',' << XMLString(y-ry*sin(angle2)); - if (_fill >= 0) - oss << 'Z'; - elem->addAttribute("d", oss.str()); - } - elem->addAttribute("stroke-width", _penwidth); - elem->addAttribute("stroke", actions.getColor().svgColorString()); - elem->addAttribute("stroke-linecap", "round"); - elem->addAttribute("fill", "none"); - if (_fill >= 0) { - Color color=actions.getColor(); - color *= _fill; - elem->addAttribute("fill", color.svgColorString()); + if (_penwidth > 0) { + elem->addAttribute("stroke-width", _penwidth); + elem->addAttribute("stroke", actions.getColor().svgColorString()); + if (!closed) + elem->addAttribute("stroke-linecap", "round"); + } + elem->addAttribute("fill", _grayLevel < 0 ? "none" : fillColor(true).svgColorString()); + actions.appendToPage(std::move(elem)); + double pw = _penwidth/2.0; + actions.embed(BoundingBox(cx-rx-pw, cy-ry-pw, cx+rx+pw, cy+ry+pw)); } - else - elem->addAttribute("fill", "none"); - actions.appendToPage(elem); - actions.embed(BoundingBox(cx-rx, cy-ry, cx+rx, cy+ry)); reset(); } -static constexpr int cmd_id (int a, int b) { - return (a << 8) | b; +/** Computes the gray level based on the ratio of set bits to the total + * number of bits of a given hex value. + * @param[in] hexstr a sequence of hexadecimal digits + * @return the computed gray level [0-1] */ +static double bit_sequence_to_gray (const string &hexstr) { + if (hexstr.empty()) + return 1.0; + int setbits=0; // number of bits set + int totalbits=0; // number of bits processed + constexpr int CHUNKBITS = 8*sizeof(unsigned long long); + for (size_t pos=0; pos < hexstr.length(); pos+=CHUNKBITS/4) { + size_t digitcount; // number of hex digits processed + unsigned long long val = stoull(hexstr.substr(pos, CHUNKBITS/4), &digitcount, 16); + setbits += bitset<CHUNKBITS>(val).count(); + totalbits += 4*digitcount; + } + return 1.0-double(setbits)/double(totalbits); +} + + +/** Returns a unique integer for a TPIC command (consisting of two letters). */ +constexpr int cmd_id (const char *cmd) { + return (cmd[0] << 8) | cmd[1]; }; + bool TpicSpecialHandler::process (const char *prefix, istream &is, SpecialActions &actions) { if (!prefix || strlen(prefix) != 2) return false; - + _dviColor = actions.getColor(); const double mi2bp=0.072; // factor for milli-inch to PS points StreamInputBuffer ib(is); BufferInputReader ir(ib); - switch (cmd_id(prefix[0], prefix[1])) { - case cmd_id('p','n'): // set pen width in milli-inches - _penwidth = ir.getDouble()*mi2bp; + switch (cmd_id(prefix)) { + case cmd_id("pn"): // set pen width in milli-inches + _penwidth = max(0.0, ir.getDouble()*mi2bp); break; - case cmd_id('b','k'): // set fill color to black - _fill = 0; + case cmd_id("bk"): // set fill color to black + _grayLevel = 1; break; - case cmd_id('w','h'): // set fill color to white - _fill = 1; + case cmd_id("wh"): // set fill color to white + _grayLevel = 0; break; - case cmd_id('s','h'): // set fill color to given gray level + case cmd_id("sh"): // set fill color to given gray level (0=white, 1=black) ir.skipSpace(); - _fill = ir.eof() ? 0.5 : max(0.0, min(1.0, ir.getDouble())); + _grayLevel = ir.eof() ? 0.5 : max(0.0, min(1.0, ir.getDouble())); break; - case cmd_id('t','x'): // set fill pattern + case cmd_id("tx"): { // set fill color depending on a sequence of bits (given as hex value) + string hexstr; + while (!ir.eof()) { + ir.skipSpace(); + int c = ir.get(); + if (isxdigit(c)) + hexstr += static_cast<char>(tolower(c)); + else + break; + } + _grayLevel = bit_sequence_to_gray(hexstr); break; - case cmd_id('p','a'): { // add point to path + } + case cmd_id("pa"): { // add point to path double x = ir.getDouble()*mi2bp; double y = ir.getDouble()*mi2bp; _points.emplace_back(DPair(x,y)); break; } - case cmd_id('f','p'): // draw solid lines through recorded points; close and fill path if fill color was defined - drawLines(true, _fill >= 0, 0, actions); + case cmd_id("fp"): // draw solid lines through recorded points; close and fill path if fill color was defined + drawLines(0, actions); break; - case cmd_id('i','p'): // don't draw outlines but close the recorded path and fill the resulting polygon - drawLines(false, true, 0, actions); + case cmd_id("ip"): // don't draw outlines but close the recorded path and fill the resulting polygon + _penwidth = 0; + drawLines(0, actions); break; - case cmd_id('d','a'): // as fp but draw dashed lines - drawLines(true, _fill >= 0, ir.getDouble()*72, actions); + case cmd_id("da"): // as fp but draw dashed lines + drawLines(ir.getDouble()*72, actions); break; - case cmd_id('d','t'): // as fp but draw dotted lines - drawLines(true, _fill >= 0, -ir.getDouble()*72, actions); + case cmd_id("dt"): // as fp but draw dotted lines + drawLines(-ir.getDouble()*72, actions); break; - case cmd_id('s','p'): { // draw quadratic splines through recorded points - double ddist = ir.getDouble(); + case cmd_id("sp"): { // draw quadratic splines through recorded points + double ddist = ir.getDouble()*72; drawSplines(ddist, actions); break; } - case cmd_id('a','r'): { // draw elliptical arc + case cmd_id("ar"): { // draw elliptical arc double cx = ir.getDouble()*mi2bp; double cy = ir.getDouble()*mi2bp; double rx = ir.getDouble()*mi2bp; @@ -297,18 +340,15 @@ bool TpicSpecialHandler::process (const char *prefix, istream &is, SpecialAction drawArc(cx, cy, rx, ry, a1, a2, actions); break; } - case cmd_id('i','a'): { // fill elliptical arc + case cmd_id("ia"): { // fill elliptical arc double cx = ir.getDouble()*mi2bp; double cy = ir.getDouble()*mi2bp; double rx = ir.getDouble()*mi2bp; double ry = ir.getDouble()*mi2bp; double a1 = ir.getDouble(); double a2 = ir.getDouble(); - if (_fill < 0) - _fill = 1; + _penwidth = 0; drawArc(cx, cy, rx, ry, a1, a2, actions); - if (_fill < 0) - _fill = -1; break; } default: @@ -318,7 +358,7 @@ bool TpicSpecialHandler::process (const char *prefix, istream &is, SpecialAction } -const char** TpicSpecialHandler::prefixes () const { - static const char *pfx[] = {"ar", "bk", "da", "dt", "fp", "ia", "ip", "pa", "pn", "sh", "sp", "tx", "wh", 0}; +const vector<const char*> TpicSpecialHandler::prefixes () const { + const vector<const char*> pfx {"ar", "bk", "da", "dt", "fp", "ia", "ip", "pa", "pn", "sh", "sp", "tx", "wh"}; return pfx; } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.hpp index ec2ff5d4cde..2bbc8182b12 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.hpp @@ -2,7 +2,7 @@ ** TpicSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -31,20 +31,24 @@ class TpicSpecialHandler : public SpecialHandler, public DVIEndPageListener TpicSpecialHandler (); const char* info () const override {return "TPIC specials";} const char* name () const override {return "tpic";} - const char** prefixes () const override; + const std::vector<const char*> prefixes () const override; bool process (const char *prefix, std::istream &is, SpecialActions &actions) override; + double penwidth () const {return _penwidth;} + double grayLevel () const {return _grayLevel;} + Color fillColor (bool grayOnly) const; protected: void dviEndPage (unsigned pageno, SpecialActions &actions) override; void reset (); - void drawLines (bool stroke, bool fill, double ddist, SpecialActions &actions); + void drawLines (double ddist, SpecialActions &actions); void drawSplines (double ddist, SpecialActions &actions); void drawArc (double cx, double cy, double rx, double ry, double angle1, double angle2, SpecialActions &actions); private: - double _penwidth; ///< pen width in PS point units - double _fill; ///< fill intensity [0,1]; if < 0, we don't fill anything + double _penwidth; ///< pen width in PS point units + double _grayLevel; ///< [0,1]; 0=white, 1=black, if < 0, we don't fill anything std::vector<DPair> _points; + Color _dviColor; ///< current DVI color }; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp index 7d38a5edfc8..65826459ee8 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp @@ -2,7 +2,7 @@ ** TriangularPatch.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp index c37f94d0f11..c2aa6028a76 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp @@ -2,7 +2,7 @@ ** TriangularPatch.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.cpp new file mode 100644 index 00000000000..c7191c53698 --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.cpp @@ -0,0 +1,175 @@ +/************************************************************************* +** TrueTypeFont.cpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#include <iterator> +#include <sstream> +#include <woff2/encode.h> +#include <zlib.h> +#include "StreamReader.hpp" +#include "StreamWriter.hpp" +#include "TrueTypeFont.hpp" +#include "utility.hpp" + +using namespace std; + + +/** Reads the font data from a TTF file. + * OTF specification: https://www.microsoft.com/typography/otspec/otff.htm + * @param[in] fname name/path of file to read + * @return true on success */ +bool TrueTypeFont::read (const string &fname) { + _tableRecords.clear(); + _buffer = util::read_file_contents(fname); + if (_buffer.empty()) + return false; + istringstream iss(_buffer); + StreamReader reader(iss); + _version = reader.readUnsigned(4); + uint16_t numTables = reader.readUnsigned(2); + if (numTables == 0 || _buffer.size() <= 12u+16u*numTables) + return false; + + // read table records + reader.seek(12); // skip searchRange, entrySelector, and rangeShift + for (uint16_t i=0; i < numTables; i++) { + uint32_t tag = reader.readUnsigned(4); + uint32_t checksum = reader.readUnsigned(4); + uint32_t offset = reader.readUnsigned(4); + uint32_t length = reader.readUnsigned(4); + if ((offset | length) > _buffer.size() || offset+length > _buffer.size()) + return false; + TTFTableRecord record = {tag, checksum, length, reinterpret_cast<const uint8_t*>(_buffer.data())+offset}; + _tableRecords.emplace_back(std::move(record)); + } + return true; +} + + +/** Compresses the data of the referenced TTF table and updated the record data accordingly. + * @return true if the data was compressed */ +bool TrueTypeFont::WOFFTableRecord::compressTableData () { + if (ttfRecord.size < 16) + return false; + uLong compressedSize = compressBound(ttfRecord.size); + compressedData.resize(compressedSize); + // Compress with zlib for now. We could also use zopfli for slightly better but much slower compression. + // Only use the compressed data if it actually leads to a size reduction. Otherwise, use the original table data. + if (compress2(compressedData.data(), &compressedSize, ttfRecord.data, ttfRecord.size, Z_BEST_COMPRESSION) != Z_OK + || compressedSize >= ttfRecord.size) { + compressedData.clear(); + return false; + } + size = compressedSize; + data = compressedData.data(); + return true; +} + + +/** Writes font data in WOFF format to a given output stream. + WOFF specifiction: https://www.w3.org/TR/WOFF */ +void TrueTypeFont::writeWOFF (ostream &os) const { + // compute WOFF table records first + vector<WOFFTableRecord> woffRecords; + uint32_t woffSize = static_cast<uint32_t>(44 + 20*_tableRecords.size()); + uint32_t ttfSize = static_cast<uint32_t>(12 + 16*_tableRecords.size()); + for (const TTFTableRecord &ttfRecord : _tableRecords) { + WOFFTableRecord woffRecord(woffSize, ttfRecord); + woffRecord.compressTableData(); + woffSize += woffRecord.paddedSize(); + ttfSize += ttfRecord.paddedSize(); + woffRecords.emplace_back(std::move(woffRecord)); + } + // write WOFF header + StreamWriter writer(os); + writer.writeUnsigned(0x774F4646, 4); // "WOFF" + writer.writeUnsigned(_version, 4); // version of contained TTF font + writer.writeUnsigned(woffSize, 4); // total length of WOFF file + writer.writeUnsigned(_tableRecords.size(), 2); // number of tables + writer.writeBytes(0, 2); // reserved + writer.writeUnsigned(ttfSize, 4); // size of uncompressed TTF data + writer.writeBytes(0, 4); // WOFF version (not required) + writer.writeBytes(0, 12); // offset, compressed and uncompressed size of metadata block + writer.writeBytes(0, 8); // offset and size of private data block + + // write WOFF table directory + for (const WOFFTableRecord &woffRecord : woffRecords) { + writer.writeUnsigned(woffRecord.ttfRecord.tag, 4); + writer.writeUnsigned(woffRecord.offset, 4); + writer.writeUnsigned(woffRecord.size, 4); + writer.writeUnsigned(woffRecord.ttfRecord.size, 4); + writer.writeUnsigned(woffRecord.ttfRecord.checksum, 4); + } + + // write WOFF tables + for (const WOFFTableRecord &woffRecord : woffRecords) { + writer.writeBytes(woffRecord.data, woffRecord.size); + size_t padding = woffRecord.paddedSize()-woffRecord.size; + writer.writeBytes(0, padding); + } +} + + +void TrueTypeFont::writeWOFF (const string &fname) const { + ofstream ofs(fname.c_str(), ios::binary); + writeWOFF(ofs); +} + + +/** Puts the TrueType data in a WOFF2 container and writes the resulting data to a given stream. + * @param[out] os stream to write the WOFF2 data to + * @return true on success */ +bool TrueTypeFont::writeWOFF2 (ostream &os) const { + const uint8_t* input_data = reinterpret_cast<const uint8_t*>(_buffer.data()); + size_t output_size = woff2::MaxWOFF2CompressedSize(input_data, _buffer.size()); + string output(output_size, 0); + uint8_t* output_data = reinterpret_cast<uint8_t*>(&output[0]); + woff2::WOFF2Params params; + if (woff2::ConvertTTFToWOFF2(input_data, _buffer.size(), output_data, &output_size, params)) { + output.resize(output_size); + copy(output.begin(), output.end(), ostream_iterator<uint8_t>(os)); + return true; + } + return false; +} + + +bool TrueTypeFont::writeWOFF2 (const string &fname) const { + ofstream ofs(fname.c_str(), ios::binary); + return writeWOFF2(ofs); +} + + +/** Converts the numeric table tag (which represents a four-character ID) to a string. */ +string TrueTypeFont::TTFTableRecord::name () const { + string ret; + for (int i=24; i >= 0; i-= 8) + ret += static_cast<char>(tag >> i); + return ret; +} + + +uint32_t TrueTypeFont::TTFTableRecord::computeChecksum () const { + uint32_t sum=0; + const uint32_t *startptr = reinterpret_cast<const uint32_t*>(data); + const uint32_t *endptr = startptr + paddedSize()/sizeof(uint32_t); + while (startptr < endptr) + sum += *startptr++; + return sum; +}
\ No newline at end of file diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.hpp new file mode 100644 index 00000000000..5a6f2a180bd --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.hpp @@ -0,0 +1,74 @@ +/************************************************************************* +** TrueTypeFont.hpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#ifndef TRUETYPEFONT_HPP +#define TRUETYPEFONT_HPP + +#include <istream> +#include <fstream> +#include <ostream> +#include <string> +#include <vector> +#include "MessageException.hpp" + + +class TrueTypeFont { + struct TTFTableRecord { + std::string name () const; + uint32_t paddedSize () const {return (size+3) & ~3;} + uint32_t computeChecksum () const; + uint32_t tag; ///< table tag + uint32_t checksum; ///< checksum of the table data + uint32_t size; ///< number of bytes in the table + const uint8_t *data; ///< points to the begin of the table + }; + + struct WOFFTableRecord { + WOFFTableRecord (uint32_t off, const TTFTableRecord &rec) : offset(off), size(rec.size), data(rec.data), ttfRecord(rec) {} + size_t paddedSize () const {return (size+3) & ~3;} + bool compressTableData (); + uint32_t offset; ///< file offset to first byte of the table + uint32_t size; ///< number of bytes in the table + const uint8_t *data; ///< points to the begin of the WOFF table + std::vector<uint8_t> compressedData; ///< compressed table data + const TTFTableRecord &ttfRecord; ///< corresponding TTF table record + }; + + public: + TrueTypeFont () : _version(0) {} + TrueTypeFont (const std::string &fname) {read(fname);} + bool read (const std::string &fname); + void writeWOFF (std::ostream &os) const; + void writeWOFF (const std::string &fname) const; + bool writeWOFF2 (std::ostream &os) const; + bool writeWOFF2 (const std::string &fname) const; + + private: + uint32_t _version; ///< TTF version + std::string _buffer; ///< contents of TTF file + std::vector<TTFTableRecord> _tableRecords; +}; + + +struct TrueTypeFontException : public MessageException { + TrueTypeFontException (const std::string &msg) : MessageException(msg) {} +}; + +#endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp index efb6122e2a7..75256e38ce3 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp @@ -2,7 +2,7 @@ ** Unicode.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.hpp index b44ed6e1a67..eef6788f2cd 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.hpp @@ -2,7 +2,7 @@ ** Unicode.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFActions.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFActions.hpp index d9816a12aa5..c5161954a6a 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFActions.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFActions.hpp @@ -2,7 +2,7 @@ ** VFActions.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp index f8a93932316..a5014768921 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp @@ -2,7 +2,7 @@ ** VFReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,7 +18,6 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <sstream> #include "FixWord.hpp" #include "Font.hpp" diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp index 69664c43474..7dc6238689b 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp @@ -2,7 +2,7 @@ ** VFReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -36,7 +36,7 @@ struct VFActions; class VFReader : public StreamReader { - typedef bool (*ApproveAction)(int); + using ApproveAction = bool (*)(int); public: VFReader (std::istream &is); virtual ~VFReader (); diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp index 34e90e3f864..f0d6fa88ec9 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp @@ -2,7 +2,7 @@ ** VectorIterator.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp index bb5f4ddfdfa..98d4ce50399 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp @@ -2,7 +2,7 @@ ** VectorStream.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp index 2b539924025..13c25b4540f 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp @@ -2,7 +2,7 @@ ** XMLDocument.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,13 +18,12 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include "XMLDocument.hpp" using namespace std; -XMLDocument::XMLDocument (XMLElementNode *root) - : _rootElement(root) +XMLDocument::XMLDocument (unique_ptr<XMLElementNode> &&root) + : _rootElement(std::move(root)) { } @@ -35,18 +34,18 @@ void XMLDocument::clear () { } -void XMLDocument::append (XMLNode *node) { +void XMLDocument::append (unique_ptr<XMLNode> &&node) { if (node) { - if (XMLElementNode *newRoot = dynamic_cast<XMLElementNode*>(node)) - _rootElement.reset(newRoot); + if (dynamic_cast<XMLElementNode*>(node.get())) + _rootElement = util::static_unique_ptr_cast<XMLElementNode>(std::move(node)); else - _nodes.emplace_back(unique_ptr<XMLNode>(node)); + _nodes.emplace_back(std::move(node)); } } -void XMLDocument::setRootNode (XMLElementNode *root) { - _rootElement.reset(root); +void XMLDocument::setRootNode (unique_ptr<XMLElementNode> &&root) { + _rootElement = std::move(root); } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp index d8590b8b35f..90e1cd23cfb 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp @@ -2,7 +2,7 @@ ** XMLDocument.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -24,13 +24,14 @@ #include <memory> #include "XMLNode.hpp" -class XMLDocument -{ +class XMLDocument { public: - XMLDocument (XMLElementNode *root=0); + XMLDocument () =default; + XMLDocument (std::unique_ptr<XMLElementNode> &&root); void clear (); - void append (XMLNode *node); - void setRootNode (XMLElementNode *root); + void append (std::unique_ptr<XMLElementNode> &&node); + void append (std::unique_ptr<XMLNode> &&node); + void setRootNode (std::unique_ptr<XMLElementNode> &&root); const XMLElementNode* getRootElement () const {return _rootElement.get();} std::ostream& write (std::ostream &os) const; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp index 32607250f11..bfdbbe476ea 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp @@ -2,7 +2,7 @@ ** XMLNode.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,10 +18,10 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <map> #include <list> #include <sstream> +#include "utility.hpp" #include "XMLNode.hpp" #include "XMLString.hpp" @@ -40,6 +40,12 @@ XMLElementNode::XMLElementNode (const XMLElementNode &node) } +XMLElementNode::XMLElementNode (XMLElementNode &&node) + : _name(std::move(node._name)), _attributes(std::move(node._attributes)), _children(std::move(node._children)) +{ +} + + void XMLElementNode::clear () { _attributes.clear(); _children.clear(); @@ -47,50 +53,62 @@ void XMLElementNode::clear () { void XMLElementNode::addAttribute (const string &name, const string &value) { - _attributes[name] = value; + _attributes.emplace(name, value); } void XMLElementNode::addAttribute (const string &name, double value) { - _attributes[name] = XMLString(value); + _attributes.emplace(name, XMLString(value)); } -void XMLElementNode::append (XMLNode *child) { +/** Appends a child node to this element. The element also takes the ownership of the child. + * @param[in] child node to be appended + * @return raw pointer to the appended child node */ +XMLNode* XMLElementNode::append (unique_ptr<XMLNode> &&child) { if (!child) - return; - XMLTextNode *textNode1 = dynamic_cast<XMLTextNode*>(child); + return nullptr; + XMLTextNode *textNode1 = dynamic_cast<XMLTextNode*>(child.get()); if (!textNode1 || _children.empty()) - _children.emplace_back(unique_ptr<XMLNode>(child)); + _children.emplace_back(std::move(child)); else { if (XMLTextNode *textNode2 = dynamic_cast<XMLTextNode*>(_children.back().get())) - textNode2->append(textNode1); // merge two consecutive text nodes + textNode2->append(util::static_unique_ptr_cast<XMLTextNode>(std::move(child))); // merge two consecutive text nodes else - _children.emplace_back(unique_ptr<XMLNode>(child)); + _children.emplace_back(std::move(child)); } + return _children.back().get(); } -void XMLElementNode::append (const string &str) { +/** Appends a string to this element. If the last child is a text node, the string is + * appended there, otherwise a new text node is created. + * @param[in] str string to be appended + * @return raw pointer to the text node the string was appended to */ +XMLNode* XMLElementNode::append (const string &str) { if (_children.empty() || !dynamic_cast<XMLTextNode*>(_children.back().get())) - _children.emplace_back(unique_ptr<XMLNode>(new XMLTextNode(str))); + _children.emplace_back(util::make_unique<XMLTextNode>(str)); else static_cast<XMLTextNode*>(_children.back().get())->append(str); + return _children.back().get(); } -void XMLElementNode::prepend (XMLNode *child) { +/** Prepends a child node to this element. The element also takes the ownership of the child. + * @param[in] child node to be prepended + * @return raw pointer to the prepended child node */ +XMLNode* XMLElementNode::prepend (unique_ptr<XMLNode> &&child) { if (!child) - return; - XMLTextNode *textNode1 = dynamic_cast<XMLTextNode*>(child); - unique_ptr<XMLNode> child_uptr(child); + return nullptr; + XMLTextNode *textNode1 = dynamic_cast<XMLTextNode*>(child.get()); if (textNode1 && !_children.empty()) { if (XMLTextNode *textNode2 = dynamic_cast<XMLTextNode*>(_children.front().get())) { - textNode2->prepend(textNode1); // merge two consecutive text nodes - return; + textNode2->prepend(util::static_unique_ptr_cast<XMLTextNode>(std::move(child))); // merge two consecutive text nodes + return textNode2; } } - _children.emplace_front(std::move(child_uptr)); + _children.emplace_front(std::move(child)); + return _children.front().get(); } @@ -100,13 +118,13 @@ void XMLElementNode::prepend (XMLNode *child) { * @param[in] child node to be inserted * @param[in] sibling following sibling of 'child' * @return true on success */ -bool XMLElementNode::insertBefore (XMLNode *child, XMLNode *sibling) { - ChildList::iterator it = _children.begin(); +bool XMLElementNode::insertBefore (unique_ptr<XMLNode> &&child, XMLNode *sibling) { + auto it = _children.begin(); while (it != _children.end() && it->get() != sibling) ++it; if (it == _children.end()) return false; - _children.emplace(it, unique_ptr<XMLNode>(child)); + _children.emplace(it, std::move(child)); return true; } @@ -117,13 +135,13 @@ bool XMLElementNode::insertBefore (XMLNode *child, XMLNode *sibling) { * @param[in] child node to be inserted * @param[in] sibling preceding sibling of 'child' * @return true on success */ -bool XMLElementNode::insertAfter (XMLNode *child, XMLNode *sibling) { - ChildList::iterator it = _children.begin(); +bool XMLElementNode::insertAfter (unique_ptr<XMLNode> &&child, XMLNode *sibling) { + auto it = _children.begin(); while (it != _children.end() && it->get() != sibling) ++it; if (it == _children.end()) return false; - _children.emplace(++it, unique_ptr<XMLNode>(child)); + _children.emplace(++it, std::move(child)); return true; } @@ -170,7 +188,7 @@ XMLElementNode* XMLElementNode::getFirstDescendant (const char *name, const char return descendant; } } - return 0; + return nullptr; } @@ -209,35 +227,33 @@ bool XMLElementNode::hasAttribute (const string &name) const { /** Returns the value of an attribute. * @param[in] name name of attribute * @return attribute value or 0 if attribute doesn't exist */ -const char* XMLElementNode::getAttributeValue(const std::string& name) const { - AttribMap::const_iterator it = _attributes.find(name); +const char* XMLElementNode::getAttributeValue (const std::string& name) const { + auto it = _attributes.find(name); if (it != _attributes.end()) return it->second.c_str(); - return 0; + return nullptr; } ////////////////////// -void XMLTextNode::append (XMLNode *node) { +void XMLTextNode::append (unique_ptr<XMLNode> &&node) { if (!node) return; - if (XMLTextNode *tn = dynamic_cast<XMLTextNode*>(node)) - append(tn); + if (dynamic_cast<XMLTextNode*>(node.get())) + append(util::static_unique_ptr_cast<XMLTextNode>(std::move(node))); else { // append text representation of the node ostringstream oss; node->write(oss); append(XMLString(oss.str())); - delete node; } } -void XMLTextNode::append (XMLTextNode *node) { +void XMLTextNode::append (unique_ptr<XMLTextNode> &&node) { if (node) _text += node->_text; - delete node; } @@ -246,16 +262,12 @@ void XMLTextNode::append (const string &str) { } -void XMLTextNode::prepend (XMLNode *node) { - if (XMLTextNode *tn = dynamic_cast<XMLTextNode*>(node)) - _text = tn->_text + _text; - else - delete node; +void XMLTextNode::prepend (unique_ptr<XMLNode> &&node) { + if (XMLTextNode *textNode = dynamic_cast<XMLTextNode*>(node.get())) + _text = textNode->_text + _text; } - -////////////////////// - +///////////////////////////////////////////////////////////////////// ostream& XMLCDataNode::write (ostream &os) const { if (!_data.empty()) @@ -269,4 +281,4 @@ void XMLCDataNode::append (string &&str) { _data = move(str); else _data += str; -}
\ No newline at end of file +} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp index 698b4b43205..faaab0b5322 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp @@ -2,7 +2,7 @@ ** XMLNode.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -27,37 +27,37 @@ #include <ostream> #include <string> #include <vector> +#include "utility.hpp" -class XMLNode -{ +class XMLNode { public: virtual ~XMLNode () =default; - virtual XMLNode* clone () const =0; + virtual std::unique_ptr<XMLNode> clone () const =0; virtual void clear () =0; virtual std::ostream& write (std::ostream &os) const =0; }; -class XMLElementNode : public XMLNode -{ +class XMLElementNode : public XMLNode { public: - typedef std::map<std::string,std::string> AttribMap; - typedef std::list<std::unique_ptr<XMLNode>> ChildList; + using AttribMap = std::map<std::string,std::string>; + using ChildList = std::list<std::unique_ptr<XMLNode>>; public: XMLElementNode (const std::string &name); XMLElementNode (const XMLElementNode &node); - XMLElementNode* clone () const override {return new XMLElementNode(*this);} + XMLElementNode (XMLElementNode &&node); + std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLElementNode>(*this);} void clear () override; void addAttribute (const std::string &name, const std::string &value); void addAttribute (const std::string &name, double value); - void append (XMLNode *child); - void append (const std::string &str); - void prepend (XMLNode *child); + XMLNode* append (std::unique_ptr<XMLNode> &&child); + XMLNode* append (const std::string &str); + XMLNode* prepend (std::unique_ptr<XMLNode> &&child); void remove (const XMLNode *child); - bool insertAfter (XMLNode *child, XMLNode *sibling); - bool insertBefore (XMLNode *child, XMLNode *sibling); + bool insertAfter (std::unique_ptr<XMLNode> &&child, XMLNode *sibling); + bool insertBefore (std::unique_ptr<XMLNode> &&child, XMLNode *sibling); bool hasAttribute (const std::string &name) const; const char* getAttributeValue (const std::string &name) const; bool getDescendants (const char *name, const char *attrName, std::vector<XMLElementNode*> &descendants) const; @@ -74,17 +74,16 @@ class XMLElementNode : public XMLNode }; -class XMLTextNode : public XMLNode -{ +class XMLTextNode : public XMLNode { public: XMLTextNode (const std::string &str) : _text(str) {} XMLTextNode (std::string &&str) : _text(std::move(str)) {} - XMLTextNode* clone () const override {return new XMLTextNode(*this);} + std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLTextNode>(*this);} void clear () override {_text.clear();} - void append (XMLNode *node); - void append (XMLTextNode *node); + void append (std::unique_ptr<XMLNode> &&node); + void append (std::unique_ptr<XMLTextNode> &&node); void append (const std::string &str); - void prepend (XMLNode *child); + void prepend (std::unique_ptr<XMLNode> &&node); std::ostream& write (std::ostream &os) const override {return os << _text;} const std::string& getText () const {return _text;} @@ -93,12 +92,11 @@ class XMLTextNode : public XMLNode }; -class XMLCommentNode : public XMLNode -{ +class XMLCommentNode : public XMLNode { public: XMLCommentNode (const std::string &str) : _text(str) {} XMLCommentNode (std::string &&str) : _text(std::move(str)) {} - XMLCommentNode* clone () const override {return new XMLCommentNode(*this);} + std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLCommentNode>(*this);} void clear () override {_text.clear();} std::ostream& write (std::ostream &os) const override {return os << "<!--" << _text << "-->";} @@ -107,13 +105,12 @@ class XMLCommentNode : public XMLNode }; -class XMLCDataNode : public XMLNode -{ +class XMLCDataNode : public XMLNode { public: - XMLCDataNode () {} + XMLCDataNode () =default; XMLCDataNode (const std::string &d) : _data(d) {} XMLCDataNode (std::string &&d) : _data(std::move(d)) {} - XMLCDataNode* clone () const override {return new XMLCDataNode(*this);} + std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLCDataNode>(*this);} void clear () override {_data.clear();} void append (std::string &&str); std::ostream& write (std::ostream &os) const override; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp index e23df4b7656..9c52064f1f1 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp @@ -2,7 +2,7 @@ ** XMLString.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,11 +18,8 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ -#include <config.h> #include <cmath> #include <cstdlib> -#include <iomanip> -#include <sstream> #include "Unicode.hpp" #include "XMLString.hpp" @@ -47,7 +44,7 @@ XMLString::XMLString (const string &str, bool plain) { assign(str); else { for (char c : str) - *this += translate(c); + append(translate(c)); } } @@ -58,20 +55,15 @@ XMLString::XMLString (const char *str, bool plain) { assign(str); else { while (*str) - *this += translate(*str++); + append(translate(*str++)); } } } -XMLString::XMLString (int n, bool cast) { - if (cast) { - stringstream ss; - ss << n; - ss >> *this; - } - else - *this += translate(n); +XMLString::XMLString (int n, bool cast) + : string(cast ? to_string(n) : translate(n)) +{ } @@ -90,14 +82,21 @@ static inline double round (double x, int n) { XMLString::XMLString (double x) { - stringstream ss; if (DECIMAL_PLACES > 0) { // don't use fixed and setprecision() manipulators here to avoid // banker's rounding applied in some STL implementations x = round(x, DECIMAL_PLACES); } - if (std::abs(x) < 1e-7) + if (std::abs(x) < 1e-6) x = 0; - ss << x; - ss >> *this; + assign(to_string(x)); + size_t pos = find('.'); + if (pos != string::npos) { + pos = find_last_not_of('0'); + if (pos != string::npos) { + erase(pos+1); // remove trailing zeros + if (at(length()-1) == '.') + pop_back(); // remove trailing dot + } + } } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp index 905d5413952..17323c3f99f 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp @@ -2,7 +2,7 @@ ** XMLString.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp index 3f321625f3e..4a0b2fa52e2 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp @@ -2,7 +2,7 @@ ** ZLibOutputStream.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp index a15f9f27845..2a8e6d60425 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp @@ -2,7 +2,7 @@ ** dvisvgm.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -18,9 +18,11 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. ** *************************************************************************/ +#include <config.h> #include <clipper.hpp> #include <fstream> #include <iostream> +#include <list> #include <potracelib.h> #include <sstream> #include <xxhash.h> @@ -34,7 +36,7 @@ #include "Font.hpp" #include "FontEngine.hpp" #include "Ghostscript.hpp" -#include "HtmlSpecialHandler.hpp" +#include "HyperlinkManager.hpp" #include "Message.hpp" #include "PageSize.hpp" #include "PSInterpreter.hpp" @@ -42,10 +44,14 @@ #include "SignalHandler.hpp" #include "SVGOutput.hpp" #include "System.hpp" +#include "utility.hpp" #include "version.hpp" #ifndef DISABLE_WOFF +#include <brotli/encode.h> +#include <woff2/version.h> #include "ffwrapper.h" +#include "TTFAutohint.hpp" #endif using namespace std; @@ -136,9 +142,8 @@ static bool set_temp_dir (const CommandLine &args) { static bool check_bbox (const string &bboxstr) { - const char *formats[] = {"none", "min", "preview", "papersize", "dvi", 0}; - for (const char **p=formats; *p; ++p) - if (bboxstr == *p) + for (const char *fmt : {"none", "min", "preview", "papersize", "dvi"}) + if (bboxstr == fmt) return true; if (isalpha(bboxstr[0])) { try { @@ -163,51 +168,122 @@ static bool check_bbox (const string &bboxstr) { } +// Helper class to generate a list of version information of the used libraries. +class VersionInfo { + public: + void add (const string &name, const string &version, bool ignoreEmpty=false) { + if (!version.empty() || !ignoreEmpty) + append(name, util::trim(version)); + } + + void add (const string &name, const char *version, bool ignoreEmpty=false) { + if (version && *version) + append(name, util::trim(version)); + else if (!ignoreEmpty) + append(name, ""); + } + + void add (const string &name, const vector<int> &versionComponents) { + string version; + for (auto it=versionComponents.begin(); it != versionComponents.end(); ++it) { + if (it != versionComponents.begin()) + version += '.'; + version += to_string(*it); + } + append(name, version); + } + + /** Adds a version number given as a single unsigned integer, and optionally + * extracts its components, e.g. 0x00010203 => "1.2.3" (3 components separated + * by multiples of 256). + * @param[in] name library name + * @param[in] version version number + * @param[in] compcount number of components the version consists of + * @param[in] factor factor used to separate the components */ + void add (const string &name, uint32_t version, int compcount=1, uint32_t factor=0xffffffff) { + string str; + while (compcount-- > 0) { + if (!str.empty()) + str.insert(0, "."); + str.insert(0, to_string(version % factor)); + version /= factor; + } + append(name, str); + } + + /** Writes the version information to the given output stream. */ + void write (ostream &os) { + using Entry = pair<string,string>; + _versionPairs.sort([](const Entry &e1, const Entry &e2) { + return util::tolower(e1.first) < util::tolower(e2.first); + }); + size_t maxNameLength=0; + for (const Entry &versionPair : _versionPairs) + maxNameLength = max(maxNameLength, versionPair.first.length()); + for (const Entry &versionPair : _versionPairs) { + string name = versionPair.first+":"; + os << left << setw(maxNameLength+2) << name; + os << (versionPair.second.empty() ? "unknown" : versionPair.second) << '\n'; + } + } + + protected: + void append (const string &name, const string &version) { + _versionPairs.emplace_back(pair<string,string>(name, version)); + } + + private: + list<pair<string,string>> _versionPairs; +}; + + static void print_version (bool extended) { - ostringstream oss; - oss << "dvisvgm " << PROGRAM_VERSION; + string versionstr = string(PROGRAM_NAME)+" "+PROGRAM_VERSION; +#ifdef TARGET_SYSTEM + if (extended && strlen(TARGET_SYSTEM) > 0) + versionstr += " (" TARGET_SYSTEM ")"; +#endif + cout << versionstr << '\n'; if (extended) { - if (strlen(TARGET_SYSTEM) > 0) - oss << " (" TARGET_SYSTEM ")"; - int len = oss.str().length(); - oss << "\n" << string(len, '-') << "\n" - "clipper: " << CLIPPER_VERSION "\n"; + cout << string(versionstr.length(), '-') << '\n'; + VersionInfo versionInfo; + versionInfo.add("clipper", CLIPPER_VERSION); + versionInfo.add("freetype", FontEngine::version()); + versionInfo.add("potrace", strchr(potrace_version(), ' ')); + versionInfo.add("xxhash", XXH_versionNumber(), 3, 100); + versionInfo.add("zlib", zlibVersion()); + versionInfo.add("Ghostscript", Ghostscript().revision(true), true); #ifndef DISABLE_WOFF - oss << "fontforge: " << ff_version() << '\n'; + versionInfo.add("brotli", BrotliEncoderVersion(), 3, 0x1000); + versionInfo.add("woff2", woff2::version, 3, 0x100); + versionInfo.add("fontforge", ff_version()); + versionInfo.add("ttfautohint", TTFAutohint().version(), true); #endif - oss << "freetype: " << FontEngine::version() << "\n"; - - Ghostscript gs; - string gsver = gs.revision(true); - if (!gsver.empty()) - oss << "Ghostscript: " << gsver + "\n"; - const unsigned xxh_ver = XXH_versionNumber(); - oss << #ifdef MIKTEX - "MiKTeX: " << FileFinder::instance().version() << "\n" + versionInfo.add("MiKTeX", FileFinder::instance().version()); #else - "kpathsea: " << FileFinder::instance().version() << "\n" + versionInfo.add("kpathsea", FileFinder::instance().version()); #endif - "potrace: " << (strchr(potrace_version(), ' ') ? strchr(potrace_version(), ' ')+1 : "unknown") << "\n" - "xxhash: " << xxh_ver/10000 << '.' << (xxh_ver/100)%100 << '.' << xxh_ver%100 << "\n" - "zlib: " << zlibVersion(); + versionInfo.write(cout); } - cout << oss.str() << endl; } static void init_fontmap (const CommandLine &cmdline) { - const char *mapseq = cmdline.fontmapOpt.given() ? cmdline.fontmapOpt.value().c_str() : 0; - bool additional = mapseq && strchr("+-=", *mapseq); - if (!mapseq || additional) { - const char *mapfiles[] = {"ps2pk.map", "dvipdfm.map", "psfonts.map", 0}; + string mapseq; + if (cmdline.fontmapOpt.given()) + mapseq = cmdline.fontmapOpt.value(); + bool additional = !mapseq.empty() && strchr("+-=", mapseq[0]); + if (mapseq.empty() || additional) { bool found = false; - for (const char **p=mapfiles; *p && !found; p++) - found = FontMap::instance().read(*p); + for (string mapfile : {"ps2pk", "pdftex", "dvipdfm", "psfonts"}) { + if ((found = FontMap::instance().read(mapfile+".map"))) + break; + } if (!found) Message::wstream(true) << "none of the default map files could be found\n"; } - if (mapseq) + if (!mapseq.empty()) FontMap::instance().read(mapseq); } @@ -274,7 +350,7 @@ int main (int argc, char *argv[]) { } if (!check_bbox(cmdline.bboxOpt.value())) return 1; - if (!HtmlSpecialHandler::setLinkMarker(cmdline.linkmarkOpt.value())) + if (!HyperlinkManager::setLinkMarker(cmdline.linkmarkOpt.value())) Message::wstream(true) << "invalid argument '"+cmdline.linkmarkOpt.value()+"' supplied for option --linkmark\n"; if (argc > 1 && cmdline.filenames().size() < 1) { Message::estream(true) << "no input file given\n"; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ffwrapper.c b/Build/source/texk/dvisvgm/dvisvgm-src/src/ffwrapper.c index e74d4d6e8ec..0238c1ea952 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ffwrapper.c +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ffwrapper.c @@ -2,7 +2,7 @@ ** ffwrapper.c ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -82,20 +82,3 @@ int ff_sfd_to_ttf (const char *sfdname, const char *ttfname, int autohint) { } return ret; } - - -/** Creates a WOFF font from a FontForge SFD file. - * @param[in] sfdname name of SFD file - * @param[in] woffname name of WOFF file - * @param[in] autohint run the autohinter if != 0 */ -int ff_sfd_to_woff (const char *sfdname, const char *woffname, int autohint) { - int ret=0; - SplineFont *sf = SFDRead((char*)sfdname); - if (sf) { - if (autohint) - ff_autohint(sf, false); - ret = WriteWOFFFont((char*)woffname, sf, ff_woff, 0, 0, 0, sf->map, ly_fore); - SplineFontFree(sf); - } - return ret; -} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ffwrapper.h b/Build/source/texk/dvisvgm/dvisvgm-src/src/ffwrapper.h index 763d122e56a..083b19faa9f 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ffwrapper.h +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ffwrapper.h @@ -2,7 +2,7 @@ ** ffwrapper.h ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -28,7 +28,6 @@ extern "C" { void ff_init (); int ff_version (); int ff_sfd_to_ttf (const char *sfdname, const char *ttfname, int autohint); -int ff_sfd_to_woff (const char *sfdname, const char *woffname, int autohint); #ifdef __cplusplus } diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/macros.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/macros.hpp index 1966d31e17b..a353e516c04 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/macros.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/macros.hpp @@ -2,7 +2,7 @@ ** macros.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/options.dtd b/Build/source/texk/dvisvgm/dvisvgm-src/src/options.dtd index ff016a33990..1b6737a8f5c 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/options.dtd +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/options.dtd @@ -3,7 +3,7 @@ ** options.dtd ** ** ** ** This file is part of dvisvgm - a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml b/Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml index 20185e10841..39659844307 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml @@ -3,7 +3,7 @@ ** options.xml ** ** ** ** This file is part of dvisvgm - a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -25,7 +25,7 @@ <usage>[options] dvifile</usage> <usage>-E [options] epsfile</usage> <description>This program converts DVI files, as created by TeX/LaTeX, to\nthe XML-based scalable vector graphics format SVG.</description> - <copyright>Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de></copyright> + <copyright>Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de></copyright> </program> <options> <section title="Input options"> diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp index eafc838749e..520d831a1d1 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp @@ -2,7 +2,7 @@ ** psdefs.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -34,66 +34,66 @@ const char *PSInterpreter::PSDEFS = "}forall}put @SD/defpr{[exch[/copy @SD]cvxall 5 -1 roll dup 6 1 roll[/get/exec]" "cvxall 6 -1 roll dup 7 1 roll 4 -1 roll dup 5 1 roll dup length string cvs/prc" "md cvx]cvx def}put @SD/querypos{{currentpoint}stopped{$error/newerror false pu" -"t}{2(querypos)prcmd}ifelse}put @SD/applyscalevals{1 0 transform 0 0 transform " -"3 -1 roll sub dup mul 3 1 roll sub dup mul add sqrt 0 1 transform 0 0 transfor" -"m 3 -1 roll sub dup mul 3 1 roll sub dup mul add sqrt 1 0 transform dup mul ex" -"ch dup dup mul 3 -1 roll add sqrt div 3(applyscalevals)prcmd}put @SD/prpath{{2" -"(moveto)prcmd}{2(lineto)prcmd}{6(curveto)prcmd}{0(closepath)prcmd}pathforall}p" -"ut @SD/charpath{/@dodraw false store :charpath/@dodraw true store}put @SD/show" -"{@dodraw{dup :gsave currentpoint 2{50 mul exch}repeat :newpath moveto 50 50/sc" -"ale sysexec true charpath eofill :grestore/@dodraw false store :show/@dodraw t" -"rue store}{pop}ifelse}put @SD/awidthshow{{1 string dup 0 5 index put :gsave sh" -"ow :grestore pop 0 rmoveto 3 index eq{4 index 4 index rmoveto}if 1 index 1 ind" -"ex rmoveto}exch cshow 5{pop}repeat}put @SD/widthshow{0 0 3 -1 roll pstack awid" -"thshow}put @SD/ashow{0 0 0 6 3 roll awidthshow}put @SD/newpath{:newpath 0 1(ne" -"wpath)prcmd}put @SD/stroke{@dodraw{1 1(newpath)prcmd prpath 0(stroke)prcmd :ne" -"wpath}{:stroke}ifelse}put @SD/fill{@dodraw{1 1(newpath)prcmd prpath 0(fill)prc" -"md :newpath}{:fill}ifelse}put @SD/eofill{@dodraw{1 1(newpath)prcmd prpath 0(eo" -"fill)prcmd :newpath}{:eofill}ifelse}put @SD/clip{:clip 0 1(newpath)prcmd prpat" -"h 0(clip)prcmd}put @SD/eoclip{:eoclip 1 1(newpath)prcmd prpath 0(eoclip)prcmd}" -"put @SD/shfill{begin currentdict/ShadingType known currentdict/ColorSpace know" -"n and currentdict/DataSource known and currentdict/Function known not and Shad" -"ingType 4 ge and DataSource type/arraytype eq and{<</DeviceGray 1/DeviceRGB 3/" -"DeviceCMYK 4/bgknown currentdict/Background known/bbknown currentdict/BBox kno" -"wn>>begin currentdict ColorSpace known{ShadingType ColorSpace load bgknown{1 B" -"ackground aload pop}{0}ifelse bbknown{1 BBox aload pop}{0}ifelse ShadingType 5" -" eq{VerticesPerRow}if DataSource aload length 4 add bgknown{ColorSpace load ad" -"d}if bbknown{4 add}if ShadingType 5 eq{1 add}if(shfill)prcmd}if end}if end}put" -"/@rect{4 -2 roll moveto exch dup 0 rlineto exch 0 exch rlineto neg 0 rlineto c" -"losepath}bind def/@rectcc{4 -2 roll moveto 2 copy 0 lt exch 0 lt xor{dup 0 exc" -"h rlineto exch 0 rlineto neg 0 exch rlineto}{exch dup 0 rlineto exch 0 exch rl" -"ineto neg 0 rlineto}ifelse closepath}bind def @SD/rectclip{:newpath dup type/a" -"rraytype eq{aload length 4 idiv{@rectcc}repeat}{@rectcc}ifelse clip :newpath}p" -"ut @SD/rectfill{gsave :newpath dup type/arraytype eq{aload length 4 idiv{@rect" -"cc}repeat}{@rectcc}ifelse fill grestore}put @SD/rectstroke{gsave :newpath dup " -"type/arraytype eq{aload length 4 idiv{@rect}repeat}{@rect}ifelse stroke gresto" -"re}put false setglobal @SD readonly pop/initclip 0 defpr/clippath 0 defpr/syse" -"xec{@SD exch get exec}def/adddot{dup length 1 add string dup 0 46 put dup 3 -1" -" roll 1 exch putinterval}def/setlinewidth{dup/setlinewidth sysexec applyscalev" -"als 1(setlinewidth)prcmd}def/setlinecap 1 defpr/setlinejoin 1 defpr/setmiterli" -"mit 1 defpr/setdash{mark 3 1 roll 2 copy/setdash sysexec applyscalevals exch a" -"load length 1 add -1 roll counttomark(setdash)prcmd pop}def/setgstate{currentl" -"inewidth 1(setlinewidth)prcmd currentlinecap 1(setlinecap)prcmd currentlinejoi" -"n 1(setlinejoin)prcmd currentmiterlimit 1(setmiterlimit)prcmd currentrgbcolor " -"3(setrgbcolor)prcmd 6 array currentmatrix aload pop 6(setmatrix)prcmd currentd" -"ash mark 3 1 roll exch aload length 1 add -1 roll counttomark(setdash)prcmd po" -"p}def/save{@UD begin/@saveID vmstatus pop pop def end :save @saveID 1(save)prc" -"md}def/restore{:restore setgstate @UD/@saveID known{@UD begin @saveID end}{0}i" -"felse 1(restore)prcmd}def/gsave 0 defpr/grestore{:grestore setgstate 0(grestor" -"e)prcmd}def/grestoreall{:grestoreall setstate 0(grestoreall)prcmd}def/rotate{d" -"up type/arraytype ne{dup 1(rotate)prcmd}if/rotate sysexec}def/scale{dup type/a" -"rraytype ne{2 copy 2(scale)prcmd}if/scale sysexec}def/translate{dup type/array" -"type ne{2 copy 2(translate)prcmd}if/translate sysexec}def/setmatrix{dup/setmat" -"rix sysexec aload pop 6(setmatrix)prcmd}def/initmatrix{matrix setmatrix}def/co" -"ncat{matrix currentmatrix matrix concatmatrix setmatrix}def/makepattern{gsave<" -"</mx 3 -1 roll>>begin dup/XUID[1000000 @patcnt]put mx/makepattern sysexec dup " -"dup begin PatternType @patcnt BBox aload pop XStep YStep PaintType mx aload po" -"p 15(makepattern)prcmd :newpath matrix setmatrix PaintProc 0 1(makepattern)prc" -"md end/@patcnt @patcnt 1 add store end grestore}def/setpattern{begin PatternTy" -"pe 1 eq{PaintType 1 eq{XUID aload pop exch pop 1}{:gsave[currentcolorspace alo" -"ad length -1 roll pop]setcolorspace/setcolor sysexec XUID aload pop exch pop c" -"urrentrgbcolor :grestore 4}ifelse(setpattern)prcmd}{/setpattern sysexec}ifelse" -" end}def/setcolor{dup type/dicttype eq{setpattern}{/setcolor sysexec/currentrg" -"bcolor sysexec setrgbcolor}ifelse}def/setgray 1 defpr/setcmykcolor 4 defpr/set" -"hsbcolor 3 defpr/setrgbcolor 3 defpr/.setopacityalpha{dup/.setopacityalpha sys" -"exec 1(setopacityalpha)prcmd}def "; +"t}{2(querypos)prcmd}ifelse}put @SD/applyscalevals{1 0 dtransform exch dup mul " +"exch dup mul add sqrt 0 1 dtransform exch dup mul exch dup mul add sqrt 1 0 dt" +"ransform dup mul exch dup dup mul 3 -1 roll add dup 0 eq{pop}{sqrt div}ifelse " +"3(applyscalevals)prcmd}put @SD/prpath{{2(moveto)prcmd}{2(lineto)prcmd}{6(curve" +"to)prcmd}{0(closepath)prcmd}pathforall}put @SD/charpath{/@dodraw false store :" +"charpath/@dodraw true store}put @SD/show{@dodraw{dup :gsave currentpoint 2{50 " +"mul exch}repeat :newpath moveto 50 50/scale sysexec true charpath eofill :gres" +"tore/@dodraw false store :show/@dodraw true store}{pop}ifelse}put @SD/awidthsh" +"ow{{1 string dup 0 5 index put :gsave show :grestore pop 0 rmoveto 3 index eq{" +"4 index 4 index rmoveto}if 1 index 1 index rmoveto}exch cshow 5{pop}repeat}put" +" @SD/widthshow{0 0 3 -1 roll pstack awidthshow}put @SD/ashow{0 0 0 6 3 roll aw" +"idthshow}put @SD/newpath{:newpath 0 1(newpath)prcmd}put @SD/stroke{@dodraw{1 1" +"(newpath)prcmd prpath 0(stroke)prcmd :newpath}{:stroke}ifelse}put @SD/fill{@do" +"draw{1 1(newpath)prcmd prpath 0(fill)prcmd :newpath}{:fill}ifelse}put @SD/eofi" +"ll{@dodraw{1 1(newpath)prcmd prpath 0(eofill)prcmd :newpath}{:eofill}ifelse}pu" +"t @SD/clip{:clip 0 1(newpath)prcmd prpath 0(clip)prcmd}put @SD/eoclip{:eoclip " +"1 1(newpath)prcmd prpath 0(eoclip)prcmd}put @SD/shfill{begin currentdict/Shadi" +"ngType known currentdict/ColorSpace known and currentdict/DataSource known and" +" currentdict/Function known not and ShadingType 4 ge and DataSource type/array" +"type eq and{<</DeviceGray 1/DeviceRGB 3/DeviceCMYK 4/bgknown currentdict/Backg" +"round known/bbknown currentdict/BBox known>>begin currentdict ColorSpace known" +"{ShadingType ColorSpace load bgknown{1 Background aload pop}{0}ifelse bbknown{" +"1 BBox aload pop}{0}ifelse ShadingType 5 eq{VerticesPerRow}if DataSource aload" +" length 4 add bgknown{ColorSpace load add}if bbknown{4 add}if ShadingType 5 eq" +"{1 add}if(shfill)prcmd}if end}if end}put/@rect{4 -2 roll moveto exch dup 0 rli" +"neto exch 0 exch rlineto neg 0 rlineto closepath}bind def/@rectcc{4 -2 roll mo" +"veto 2 copy 0 lt exch 0 lt xor{dup 0 exch rlineto exch 0 rlineto neg 0 exch rl" +"ineto}{exch dup 0 rlineto exch 0 exch rlineto neg 0 rlineto}ifelse closepath}b" +"ind def @SD/rectclip{:newpath dup type/arraytype eq{aload length 4 idiv{@rectc" +"c}repeat}{@rectcc}ifelse clip :newpath}put @SD/rectfill{gsave :newpath dup typ" +"e/arraytype eq{aload length 4 idiv{@rectcc}repeat}{@rectcc}ifelse fill grestor" +"e}put @SD/rectstroke{gsave :newpath dup type/arraytype eq{aload length 4 idiv{" +"@rect}repeat}{@rect}ifelse stroke grestore}put false setglobal @SD readonly po" +"p/initclip 0 defpr/clippath 0 defpr/sysexec{@SD exch get exec}def/adddot{dup l" +"ength 1 add string dup 0 46 put dup 3 -1 roll 1 exch putinterval}def/setlinewi" +"dth{dup/setlinewidth sysexec 1(setlinewidth)prcmd}def/setlinecap 1 defpr/setli" +"nejoin 1 defpr/setmiterlimit 1 defpr/setdash{mark 3 1 roll 2 copy/setdash syse" +"xec exch aload length 1 add -1 roll counttomark(setdash)prcmd pop}def/setgstat" +"e{currentlinewidth 1(setlinewidth)prcmd currentlinecap 1(setlinecap)prcmd curr" +"entlinejoin 1(setlinejoin)prcmd currentmiterlimit 1(setmiterlimit)prcmd curren" +"trgbcolor 3(setrgbcolor)prcmd matrix currentmatrix aload pop 6(setmatrix)prcmd" +" applyscalevals currentdash mark 3 1 roll exch aload length 1 add -1 roll coun" +"ttomark(setdash)prcmd pop}def/save{@UD begin/@saveID vmstatus pop pop def end " +":save @saveID 1(save)prcmd}def/restore{:restore setgstate @UD/@saveID known{@U" +"D begin @saveID end}{0}ifelse 1(restore)prcmd}def/gsave 0 defpr/grestore{:gres" +"tore setgstate 0(grestore)prcmd}def/grestoreall{:grestoreall setstate 0(gresto" +"reall)prcmd}def/rotate{dup type/arraytype ne{dup 1(rotate)prcmd}if/rotate syse" +"xec applyscalevals}def/scale{dup type/arraytype ne{2 copy 2(scale)prcmd}if/sca" +"le sysexec applyscalevals}def/translate{dup type/arraytype ne{2 copy 2(transla" +"te)prcmd}if/translate sysexec}def/setmatrix{dup/setmatrix sysexec aload pop 6(" +"setmatrix)prcmd applyscalevals}def/initmatrix{matrix setmatrix}def/concat{matr" +"ix currentmatrix matrix concatmatrix setmatrix}def/makepattern{gsave<</mx 3 -1" +" roll>>begin dup/XUID[1000000 @patcnt]put mx/makepattern sysexec dup dup begin" +" PatternType @patcnt BBox aload pop XStep YStep PaintType mx aload pop 15(make" +"pattern)prcmd :newpath matrix setmatrix PaintProc 0 1(makepattern)prcmd end/@p" +"atcnt @patcnt 1 add store end grestore}def/setpattern{begin PatternType 1 eq{P" +"aintType 1 eq{XUID aload pop exch pop 1}{:gsave[currentcolorspace aload length" +" -1 roll pop]setcolorspace/setcolor sysexec XUID aload pop exch pop currentrgb" +"color :grestore 4}ifelse(setpattern)prcmd}{/setpattern sysexec}ifelse end}def/" +"setcolor{dup type/dicttype eq{setpattern}{/setcolor sysexec/currentrgbcolor sy" +"sexec setrgbcolor}ifelse}def/setgray 1 defpr/setcmykcolor 4 defpr/sethsbcolor " +"3 defpr/setrgbcolor 3 defpr/.setopacityalpha{dup/.setopacityalpha sysexec 1(se" +"topacityalpha)prcmd}def "; diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp index c6b9ea63fe9..9517a6a1013 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp @@ -2,7 +2,7 @@ ** utility.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -20,7 +20,9 @@ #include <algorithm> #include <cctype> +#include <fstream> #include <functional> +#include <iterator> #include "utility.hpp" using namespace std; @@ -56,12 +58,57 @@ string util::normalize_space (string str, const char *ws) { } -string& util::tolower (string &str) { - transform(str.begin(), str.end(), str.begin(), ::tolower); +/** Replaces all occurences of a substring with another string. + * @param[in] str string to search through + * @param[in] find string to look for + * @param[in] repl replacement for "find" + * @return the resulting string */ +string util::replace (string str, const string &find, const string &repl) { + if (!find.empty() && !repl.empty()) { + size_t first = str.find(find); + while (first != string::npos) { + str.replace(first, find.length(), repl); + first = str.find(find, first+repl.length()); + } + } return str; } +/** Splits a string at all occurences of a given separator string and + * returns the substrings. + * @param[in] str string to split + * @param[in] sep separator to look for + * @return the substrings between the separators */ +vector<string> util::split (const string &str, const string &sep) { + vector<string> parts; + if (str.empty() || sep.empty()) + parts.emplace_back(str); + else { + size_t left=0; + while (left <= str.length()) { + size_t right = str.find(sep, left); + if (right == string::npos) { + parts.emplace_back(str.substr(left)); + left = string::npos; + } + else { + parts.emplace_back(str.substr(left, right-left)); + left = right+sep.length(); + } + } + } + return parts; +} + + +string util::tolower (const string &str) { + string ret=str; + transform(str.begin(), str.end(), ret.begin(), ::tolower); + return ret; +} + + /** Returns the integer part of log10 of a given integer \f$n>0\f$. * If \f$n<0\f$, the result is 0. */ int util::ilog10 (int n) { @@ -72,3 +119,21 @@ int util::ilog10 (int n) { } return result; } + + +/** Returns the contents of a file. + * @param[in] fname name/path of the file */ +string util::read_file_contents (const string &fname) { + ifstream ifs(fname.c_str(), ios::binary); + return string(istreambuf_iterator<char>(ifs.rdbuf()), istreambuf_iterator<char>()); +} + + +/** Writes a sequence of bytes given as a string to a file. + * @param[in] name/path of the file to write + * @param[in] start iterator pointing to the begin of the byte sequence + * @param[in] end iterator pointing to the first byte after the byte sequence to write */ +void util::write_file_contents (const string &fname, string::iterator start, string::iterator end) { + ofstream ofs(fname.c_str(), ios::binary); + copy(start, end, ostream_iterator<char>(ofs)); +} diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp index 760dfb634dd..72b4c8d06f6 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp @@ -2,7 +2,7 @@ ** utility.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -21,14 +21,18 @@ #ifndef UTILITY_HPP #define UTILITY_HPP +#include <iomanip> +#include <memory> +#include <sstream> #include <string> +#include <vector> namespace math { constexpr const double PI = 3.141592653589793238462643383279502884; constexpr const double HALF_PI = 1.570796326794896619231321691639751442; constexpr const double TWO_PI = 6.283185307179586476925286766559005768; - +constexpr const double SQRT2 = 1.414213562373095048801688724209698079; inline double deg2rad (double deg) {return PI*deg/180.0;} @@ -36,11 +40,22 @@ inline double deg2rad (double deg) {return PI*deg/180.0;} namespace util { +template <typename T> +std::string tohex (T val) { + std::ostringstream oss; + oss << std::hex << val; + return oss.str(); +} + std::string trim (const std::string &str, const char *ws=" \t\n\r\f"); std::string normalize_space (std::string str, const char *ws=" \t\n\r\f"); -std::string& tolower (std::string &str); +std::string tolower (const std::string &str); +std::string replace (std::string str, const std::string &find, const std::string &repl); +std::vector<std::string> split (const std::string &str, const std::string &sep); int ilog10 (int n); +std::string read_file_contents (const std::string &fname); +void write_file_contents (const std::string &fname, std::string::iterator start, std::string::iterator end); /** Encodes the bytes in the half-open range [first,last) to Base64 and writes * the result to the range starting at 'dest'. @@ -72,6 +87,21 @@ void base64_copy (InputIterator first, InputIterator last, OutputIterator dest) } } + +/** Simple implementation mimicking std::make_unique introduced in C++14. + * Constructs an object of class T on the heap and returns a unique_ptr<T> to it. + * @param[in] args arguments forwarded to an constructor of T */ +template<typename T, typename... Args> +std::unique_ptr<T> make_unique (Args&&... args) { + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + + +template<typename T, typename U> +std::unique_ptr<T> static_unique_ptr_cast (std::unique_ptr<U> &&old){ + return std::unique_ptr<T>{static_cast<T*>(old.release())}; +} + } // namespace util #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp index 41f118cfeb5..5feeeb38f68 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp @@ -2,7 +2,7 @@ ** version.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -22,7 +22,7 @@ #define VERSION_HPP constexpr const char *PROGRAM_NAME = "dvisvgm"; -constexpr const char *PROGRAM_VERSION = "2.1.3"; +constexpr const char *PROGRAM_VERSION = "2.3.1"; #endif diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp.in b/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp.in index 40477d7360f..bea9f02bf72 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp.in +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp.in @@ -2,7 +2,7 @@ ** version.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/windows.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/windows.hpp new file mode 100644 index 00000000000..463b1f7a86c --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/windows.hpp @@ -0,0 +1,32 @@ +/************************************************************************* +** windows.hpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#ifndef WINDOWS_HPP +#define WINDOWS_HPP + +// Prevent defining the macros min and max present in windows.h +#ifndef NOMINMAX + #define NOMINMAX +#endif + +#include <windows.h> + +#endif + |