summaryrefslogtreecommitdiff
path: root/dviware/dvisvgm/src
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/dvisvgm/src')
-rw-r--r--dviware/dvisvgm/src/Font.cpp15
-rw-r--r--dviware/dvisvgm/src/Makefile.am3
-rw-r--r--dviware/dvisvgm/src/Makefile.in13
-rw-r--r--dviware/dvisvgm/src/PSFilter.hpp41
-rw-r--r--dviware/dvisvgm/src/PSInterpreter.cpp23
-rw-r--r--dviware/dvisvgm/src/PSInterpreter.hpp2
-rw-r--r--dviware/dvisvgm/src/PSPreviewHandler.cpp (renamed from dviware/dvisvgm/src/PSPreviewFilter.cpp)85
-rw-r--r--dviware/dvisvgm/src/PSPreviewHandler.hpp (renamed from dviware/dvisvgm/src/PSPreviewFilter.hpp)25
-rw-r--r--dviware/dvisvgm/src/PsSpecialHandler.cpp22
-rw-r--r--dviware/dvisvgm/src/PsSpecialHandler.hpp6
-rw-r--r--dviware/dvisvgm/src/SVGCharPathHandler.cpp4
-rw-r--r--dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp1
-rw-r--r--dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp56
-rw-r--r--dviware/dvisvgm/src/options.xml386
-rw-r--r--dviware/dvisvgm/src/psdefs.cpp253
-rw-r--r--dviware/dvisvgm/src/utility.cpp7
-rw-r--r--dviware/dvisvgm/src/utility.hpp2
17 files changed, 444 insertions, 500 deletions
diff --git a/dviware/dvisvgm/src/Font.cpp b/dviware/dvisvgm/src/Font.cpp
index 4645d33073..218dd30f82 100644
--- a/dviware/dvisvgm/src/Font.cpp
+++ b/dviware/dvisvgm/src/Font.cpp
@@ -454,14 +454,17 @@ bool PhysicalFont::getExactGlyphBox (int c, GlyphMetrics &metrics, bool vertical
BoundingBox charbox;
if (!getExactGlyphBox(c, charbox, cb))
return false;
- if ((metrics.wl = -charbox.minX()) < 0) metrics.wl=0;
- if ((metrics.wr = charbox.maxX()) < 0) metrics.wr=0;
- if ((metrics.h = charbox.maxY()) < 0) metrics.h=0;
- if ((metrics.d = -charbox.minY()) < 0) metrics.d=0;
+ metrics.wl = -charbox.minX();
+ metrics.wr = charbox.maxX();
+ metrics.h = charbox.maxY();
+ metrics.d = -charbox.minY();
if (vertical) { // vertical text orientation
if (verticalLayout()) { // font designed for vertical layout?
- metrics.wl = metrics.wr = (metrics.wl+metrics.wr)/2;
- metrics.d += metrics.h;
+ double wl = max(0.0, metrics.wl);
+ double wr = max(0.0, metrics.wr);
+ double h = max(0.0, metrics.h);
+ metrics.wl = metrics.wr = (wl+wr)/2;
+ metrics.d += h;
metrics.h = 0;
}
else {
diff --git a/dviware/dvisvgm/src/Makefile.am b/dviware/dvisvgm/src/Makefile.am
index 4ccab654f0..852f5c8f01 100644
--- a/dviware/dvisvgm/src/Makefile.am
+++ b/dviware/dvisvgm/src/Makefile.am
@@ -119,10 +119,9 @@ libdvisvgm_la_SOURCES = \
PreScanDVIReader.hpp PreScanDVIReader.cpp \
Process.hpp Process.cpp \
psdefs.cpp \
- PSFilter.hpp \
PSInterpreter.hpp PSInterpreter.cpp \
PSPattern.hpp PSPattern.cpp \
- PSPreviewFilter.hpp PSPreviewFilter.cpp \
+ PSPreviewHandler.hpp PSPreviewHandler.cpp \
PsSpecialHandler.hpp PsSpecialHandler.cpp \
RangeMap.hpp RangeMap.cpp \
ShadingPatch.hpp ShadingPatch.cpp \
diff --git a/dviware/dvisvgm/src/Makefile.in b/dviware/dvisvgm/src/Makefile.in
index a576da9bc4..c537e635e2 100644
--- a/dviware/dvisvgm/src/Makefile.in
+++ b/dviware/dvisvgm/src/Makefile.in
@@ -149,7 +149,7 @@ am_libdvisvgm_la_OBJECTS = BasicDVIReader.lo Bezier.lo \
PapersizeSpecialHandler.lo PathClipper.lo PDFHandler.lo \
PDFParser.lo PdfSpecialHandler.lo PDFToSVG.lo \
PreScanDVIReader.lo Process.lo psdefs.lo PSInterpreter.lo \
- PSPattern.lo PSPreviewFilter.lo PsSpecialHandler.lo \
+ PSPattern.lo PSPreviewHandler.lo PsSpecialHandler.lo \
RangeMap.lo ShadingPatch.lo SignalHandler.lo SourceInput.lo \
SpecialManager.lo StreamReader.lo StreamWriter.lo Subfont.lo \
SVGCharHandler.lo SVGCharHandlerFactory.lo \
@@ -217,7 +217,7 @@ am__depfiles_remade = ./$(DEPDIR)/BasicDVIReader.Plo \
./$(DEPDIR)/Opacity.Plo ./$(DEPDIR)/PDFHandler.Plo \
./$(DEPDIR)/PDFParser.Plo ./$(DEPDIR)/PDFToSVG.Plo \
./$(DEPDIR)/PSInterpreter.Plo ./$(DEPDIR)/PSPattern.Plo \
- ./$(DEPDIR)/PSPreviewFilter.Plo ./$(DEPDIR)/PageRanges.Plo \
+ ./$(DEPDIR)/PSPreviewHandler.Plo ./$(DEPDIR)/PageRanges.Plo \
./$(DEPDIR)/PageSize.Plo \
./$(DEPDIR)/PapersizeSpecialHandler.Plo \
./$(DEPDIR)/PathClipper.Plo ./$(DEPDIR)/PdfSpecialHandler.Plo \
@@ -602,10 +602,9 @@ libdvisvgm_la_SOURCES = \
PreScanDVIReader.hpp PreScanDVIReader.cpp \
Process.hpp Process.cpp \
psdefs.cpp \
- PSFilter.hpp \
PSInterpreter.hpp PSInterpreter.cpp \
PSPattern.hpp PSPattern.cpp \
- PSPreviewFilter.hpp PSPreviewFilter.cpp \
+ PSPreviewHandler.hpp PSPreviewHandler.cpp \
PsSpecialHandler.hpp PsSpecialHandler.cpp \
RangeMap.hpp RangeMap.cpp \
ShadingPatch.hpp ShadingPatch.cpp \
@@ -829,7 +828,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PDFToSVG.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSInterpreter.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSPattern.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSPreviewFilter.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSPreviewHandler.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PageRanges.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PageSize.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PapersizeSpecialHandler.Plo@am__quote@ # am--include-marker
@@ -1166,7 +1165,7 @@ distclean: distclean-recursive
-rm -f ./$(DEPDIR)/PDFToSVG.Plo
-rm -f ./$(DEPDIR)/PSInterpreter.Plo
-rm -f ./$(DEPDIR)/PSPattern.Plo
- -rm -f ./$(DEPDIR)/PSPreviewFilter.Plo
+ -rm -f ./$(DEPDIR)/PSPreviewHandler.Plo
-rm -f ./$(DEPDIR)/PageRanges.Plo
-rm -f ./$(DEPDIR)/PageSize.Plo
-rm -f ./$(DEPDIR)/PapersizeSpecialHandler.Plo
@@ -1310,7 +1309,7 @@ maintainer-clean: maintainer-clean-recursive
-rm -f ./$(DEPDIR)/PDFToSVG.Plo
-rm -f ./$(DEPDIR)/PSInterpreter.Plo
-rm -f ./$(DEPDIR)/PSPattern.Plo
- -rm -f ./$(DEPDIR)/PSPreviewFilter.Plo
+ -rm -f ./$(DEPDIR)/PSPreviewHandler.Plo
-rm -f ./$(DEPDIR)/PageRanges.Plo
-rm -f ./$(DEPDIR)/PageSize.Plo
-rm -f ./$(DEPDIR)/PapersizeSpecialHandler.Plo
diff --git a/dviware/dvisvgm/src/PSFilter.hpp b/dviware/dvisvgm/src/PSFilter.hpp
deleted file mode 100644
index 17dcf0d93e..0000000000
--- a/dviware/dvisvgm/src/PSFilter.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************
-** PSFilter.hpp **
-** **
-** This file is part of dvisvgm -- a fast DVI to SVG converter **
-** Copyright (C) 2005-2023 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 PSFILTER_HPP
-#define PSFILTER_HPP
-
-class PSInterpreter;
-
-class PSFilter
-{
- public:
- explicit PSFilter (PSInterpreter &psi) : _psi(psi) {}
- virtual ~PSFilter () =default;
- virtual void execute (const char *code, size_t len) =0;
- virtual bool active () const =0;
-
- protected:
- PSInterpreter& psInterpreter () {return _psi;}
-
- private:
- PSInterpreter &_psi;
-};
-
-#endif
diff --git a/dviware/dvisvgm/src/PSInterpreter.cpp b/dviware/dvisvgm/src/PSInterpreter.cpp
index 1c20bb6bb4..cd24ec03b9 100644
--- a/dviware/dvisvgm/src/PSInterpreter.cpp
+++ b/dviware/dvisvgm/src/PSInterpreter.cpp
@@ -27,7 +27,6 @@
#include "FileSystem.hpp"
#include "InputReader.hpp"
#include "Message.hpp"
-#include "PSFilter.hpp"
#include "PSInterpreter.hpp"
#include "SignalHandler.hpp"
#include "utility.hpp"
@@ -67,7 +66,8 @@ void PSInterpreter::init () {
// as of GS 9.56.0. Since dvisvgm relies on the old PS-based interpreter for its
// PDF support, we try to disable the new one.
// https://www.ghostscript.com/doc/9.56.0/Use.htm#PDF_switches
- if (gsrev >= 9560)
+ // As of GS 10.02.0, option NEWPDF has been deprecated and has no effect any longer.
+ if (gsrev >= 9560 && gsrev < 10020)
gsargs.emplace_back("-dNEWPDF=false");
}
_gs.init(gsargs.size(), gsargs.data(), this);
@@ -81,16 +81,6 @@ void PSInterpreter::init () {
}
-/** Sets or replaces the filter applied to the PS code.
- * @param[in] filter the new filter being used
- * @return the previous, replaced filter (nullptr if there was none) */
-PSFilter* PSInterpreter::setFilter (PSFilter *filter) {
- PSFilter *prevFilter = _filter;
- _filter = filter;
- return prevFilter;
-}
-
-
PSActions* PSInterpreter::setActions (PSActions *actions) {
PSActions *old_actions = _actions;
_actions = actions;
@@ -136,15 +126,6 @@ bool PSInterpreter::execute (const char *str, size_t len, bool flush) {
complete = true;
}
- if (_filter && _filter->active()) {
- PSFilter *filter = _filter;
- _filter = nullptr; // prevent recursion when filter calls execute()
- filter->execute(str, len);
- if (filter->active()) // filter still active after execution?
- _filter = filter;
- return complete;
- }
-
// feed Ghostscript with code chunks that are not larger than 64KB
// => see documentation of gsapi_run_string_foo()
const char *p=str;
diff --git a/dviware/dvisvgm/src/PSInterpreter.hpp b/dviware/dvisvgm/src/PSInterpreter.hpp
index 6562e3bf98..c71c5af249 100644
--- a/dviware/dvisvgm/src/PSInterpreter.hpp
+++ b/dviware/dvisvgm/src/PSInterpreter.hpp
@@ -108,7 +108,6 @@ class PSInterpreter {
bool executeRaw (const std::string &str, int n);
bool active () const {return _mode != PS_QUIT;}
void limit (size_t max_bytes) {_bytesToRead = max_bytes;}
- PSFilter* setFilter (PSFilter *filter);
PSActions* setActions (PSActions *actions);
int pdfPageCount (const std::string &fname);
BoundingBox pdfPageBox (const std::string &fname, int pageno);
@@ -134,7 +133,6 @@ class PSInterpreter {
Ghostscript _gs;
Mode _mode; ///< current execution mode
PSActions *_actions=nullptr; ///< actions to be performed
- PSFilter *_filter=nullptr; ///< active filter used to process PS code
size_t _bytesToRead=0; ///< if > 0, maximal number of bytes to be processed by following calls of execute()
std::vector<char> _linebuf;
std::string _errorMessage; ///< text of error message
diff --git a/dviware/dvisvgm/src/PSPreviewFilter.cpp b/dviware/dvisvgm/src/PSPreviewHandler.cpp
index 960812a4e0..833890c3eb 100644
--- a/dviware/dvisvgm/src/PSPreviewFilter.cpp
+++ b/dviware/dvisvgm/src/PSPreviewHandler.cpp
@@ -1,5 +1,5 @@
/*************************************************************************
-** PSPreviewFilter.cpp **
+** PSPreviewHandler.cpp **
** **
** This file is part of dvisvgm -- a fast DVI to SVG converter **
** Copyright (C) 2005-2023 Martin Gieseking <martin.gieseking@uos.de> **
@@ -18,66 +18,53 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
-#include <vector>
-#include "InputBuffer.hpp"
-#include "InputReader.hpp"
#include "PSInterpreter.hpp"
-#include "PSPreviewFilter.hpp"
-#include "SpecialActions.hpp"
-
+#include "PSPreviewHandler.hpp"
using namespace std;
+PSPreviewHandler::PSPreviewHandler (PSInterpreter &psi) : _psi(psi) {
+}
+
+
/** Activates this filter so that the PS code will be redirected through it if
* it's hooked into the PSInterpreter. */
-void PSPreviewFilter::activate () {
- if (_tightpage) // reactivate filter?
- _active = true;
- else { // first activation?
- _tightpage = _active = false;
- // try to retrieve version string of preview package set in the PS header section
- if (psInterpreter().executeRaw("SDict begin currentdict/preview@version known{preview@version}{0}ifelse end", 1))
- _version = psInterpreter().rawData()[0];
- // check if tightpage option was set
- if (_version != "0" && psInterpreter().executeRaw("SDict begin preview@tightpage end", 1)) {
- _tightpage = (psInterpreter().rawData()[0] == "true");
- _active = true;
- }
- }
+void PSPreviewHandler::init () {
+ // try to retrieve version string of preview package set in the PS header section
+ if (_psi.executeRaw("SDict begin currentdict/preview@version known{preview@version}{0}ifelse end", 1))
+ _version = _psi.rawData()[0];
+ // check if tightpage option was set
+ if (_version != "0" && _psi.executeRaw("SDict begin preview@tightpage end", 1))
+ _tightpage = (_psi.rawData()[0] == "true");
_boxExtents.clear();
}
-/** Tries to extract the bounding box information from a chunk of PostScript code.
- * @param[in] code pointer to buffer with PS code to filter
- * @param[in] len number of bytes in buffer */
-void PSPreviewFilter::execute (const char *code, size_t len) {
- // If the "tightpage" option was set in the TeX file, 7 integers representing the
- // extent of the bounding box are present at the begin of each page.
+/** Tries to extract the bounding box information from the PS operand stack.
+ @return true on success. */
+bool PSPreviewHandler::readDataFromStack () {
if (!_tightpage)
- psInterpreter().execute(code, len);
- else {
- // Read bounding box information pushed on the operand stack by the preview package.
- // It consists of 7 values in DVI units:
- // adj_left, adj_bottom, adj_right, adj_top, height, depth, width,
- // where the first 4 values are set by \PreviewBorder or \PreviewBbAdjust. They denote
- // the border adjustments to create additional space around the graphics.
- // The baseline of the tight box extends from (0,0) to (tight_width, 0).
- CharInputBuffer ib(code, len);
- BufferInputReader ir(ib);
- ir.skipSpace();
- int val;
- while (ir.parseInt(val) && _boxExtents.size() <= 7) {
- _boxExtents.push_back(val);
- ir.skipSpace();
- }
- }
- _active = false; // no further processing required
+ return false;
+
+ // Read bounding box information pushed on the operand stack by the preview package.
+ // It consists of 7 values in DVI units:
+ // adj_left, adj_bottom, adj_right, adj_top, height, depth, width,
+ // where the first 4 values are set by \PreviewBorder or \PreviewBbAdjust. They denote
+ // the border adjustments to create additional space around the graphics.
+ // The baseline of the tight box extends from (0,0) to (tight_width, 0).
+ const char *getOperands =
+ "count 7 sub neg dup 0 lt{pop 0}if{0}repeat\n" // ensure 7 operands on the stack
+ "7{dup type dup /integertype eq exch /realtype eq or not{pop 0}if cvi 7 1 roll} repeat"; // ensure integer operands
+ _psi.executeRaw(getOperands, 7);
+ _boxExtents.clear();
+ for (const string &str: _psi.rawData())
+ _boxExtents.push_back(stoi(str));
+ return true;
}
/** Returns the bounding box defined by the preview package. */
-bool PSPreviewFilter::getBoundingBox (BoundingBox &bbox) const {
+bool PSPreviewHandler::getBoundingBox (BoundingBox &bbox) const {
if (_boxExtents.size() < 7)
return false;
const double leftX = _boxExtents[0]*_dvi2bp;
@@ -87,18 +74,18 @@ bool PSPreviewFilter::getBoundingBox (BoundingBox &bbox) const {
/** Returns the box height in PS points, or -1 if no data was found or read yet. */
-double PSPreviewFilter::height () const {
+double PSPreviewHandler::height () const {
return _boxExtents.size() > 4 ? (_boxExtents[4]+_boxExtents[3])*_dvi2bp : -1;
}
/** Returns the box depth in PS points, or -1 if no data was found or read yet. */
-double PSPreviewFilter::depth () const {
+double PSPreviewHandler::depth () const {
return _boxExtents.size() > 5 ? (_boxExtents[5]-_boxExtents[1])*_dvi2bp : -1;
}
/** Returns the box width in PS points, or -1 if no data was found or read yet. */
-double PSPreviewFilter::width () const {
+double PSPreviewHandler::width () const {
return _boxExtents.size() > 6 ? (_boxExtents[6]+_boxExtents[2]-_boxExtents[0])*_dvi2bp : -1;
}
diff --git a/dviware/dvisvgm/src/PSPreviewFilter.hpp b/dviware/dvisvgm/src/PSPreviewHandler.hpp
index 24426529bf..4823aca3bc 100644
--- a/dviware/dvisvgm/src/PSPreviewFilter.hpp
+++ b/dviware/dvisvgm/src/PSPreviewHandler.hpp
@@ -1,5 +1,5 @@
/*************************************************************************
-** PSPreviewFilter.hpp **
+** PSPreviewHandler.hpp **
** **
** This file is part of dvisvgm -- a fast DVI to SVG converter **
** Copyright (C) 2005-2023 Martin Gieseking <martin.gieseking@uos.de> **
@@ -18,26 +18,23 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
-#ifndef PSPREVIEWFILTER_HPP
-#define PSPREVIEWFILTER_HPP
+#ifndef PSPREVIEWHANDLER_HPP
+#define PSPREVIEWHANDLER_HPP
#include <string>
#include <vector>
#include "BoundingBox.hpp"
-#include "PSFilter.hpp"
-class SpecialActions;
+class PSInterpreter;
-class PSPreviewFilter : public PSFilter {
+class PSPreviewHandler {
public:
- explicit PSPreviewFilter (PSInterpreter &psi) : PSFilter(psi) {}
- void activate ();
- void execute (const char *code, size_t len) override;
- bool active () const override {return _active;}
- std::string version () const {return _version;}
- bool tightpage () const {return _tightpage;}
+ explicit PSPreviewHandler (PSInterpreter &psi);
+ void init ();
+ std::string version () const {return _version;}
+ bool tightpage () const {return _tightpage;}
+ bool readDataFromStack ();
void setDviScaleFactor (double dvi2bp) {_dvi2bp = dvi2bp;}
- void assignBorders (BoundingBox &bbox) const;
bool getBoundingBox (BoundingBox &bbox) const;
double height () const;
double depth () const;
@@ -45,10 +42,10 @@ class PSPreviewFilter : public PSFilter {
private:
std::string _version; ///< version string of preview package
- bool _active=false; ///< true if filter is active
bool _tightpage=false; ///< true if tightpage option was given
double _dvi2bp=1.0/65536.0; ///< factor to convert dvi units to PS points
std::vector<int> _boxExtents; ///< bounding box data set by the preview package (in DVI units)
+ PSInterpreter &_psi;
};
#endif
diff --git a/dviware/dvisvgm/src/PsSpecialHandler.cpp b/dviware/dvisvgm/src/PsSpecialHandler.cpp
index cb3a8a6bac..a2dc107215 100644
--- a/dviware/dvisvgm/src/PsSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/PsSpecialHandler.cpp
@@ -28,7 +28,7 @@
#include "Message.hpp"
#include "PathClipper.hpp"
#include "PSPattern.hpp"
-#include "PSPreviewFilter.hpp"
+#include "PSPreviewHandler.hpp"
#include "PsSpecialHandler.hpp"
#include "SpecialActions.hpp"
#include "SVGElement.hpp"
@@ -47,7 +47,7 @@ string PsSpecialHandler::BITMAP_FORMAT;
bool PsSpecialHandler::EMBED_BITMAP_DATA = false;
-PsSpecialHandler::PsSpecialHandler () : _psi(this), _previewFilter(_psi)
+PsSpecialHandler::PsSpecialHandler () : _psi(this), _previewHandler(_psi)
{
_psi.setImageDevice(BITMAP_FORMAT);
}
@@ -123,9 +123,8 @@ void PsSpecialHandler::enterBodySection () {
// Check for information generated by preview.sty. If the tightpage options
// was set, don't execute the bop-hook but allow the PS filter to read
// the bbox data present at the beginning of the page.
- _psi.setFilter(&_previewFilter);
- _previewFilter.activate();
- if (!_previewFilter.tightpage())
+ _previewHandler.init();
+ if (!_previewHandler.tightpage())
_psi.execute("userdict/bop-hook known{bop-hook}if\n", false);
}
}
@@ -155,9 +154,7 @@ void PsSpecialHandler::executeAndSync (istream &is, bool updatePos) {
_actions->getColor().getRGB(r, g, b);
ostringstream oss;
oss << '\n' << r << ' ' << g << ' ' << b << " setrgbcolor ";
- PSFilter *filter = _psi.setFilter(nullptr); // don't apply any filters here
_psi.execute(oss.str(), false);
- _psi.setFilter(filter);
}
_psi.execute(is);
if (updatePos) {
@@ -540,14 +537,15 @@ void PsSpecialHandler::dviBeginPage (unsigned int pageno, SpecialActions &action
void PsSpecialHandler::dviEndPage (unsigned, SpecialActions &actions) {
+ _previewHandler.readDataFromStack();
BoundingBox bbox;
- if (_previewFilter.getBoundingBox(bbox)) { // is there any data written by preview package?
+ if (_previewHandler.getBoundingBox(bbox)) { // is there any data written by preview package?
double w=0, h=0, d=0;
if (actions.getBBoxFormatString() == "preview" || actions.getBBoxFormatString() == "min") {
if (actions.getBBoxFormatString() == "preview") {
- w = max(0.0, _previewFilter.width());
- h = max(0.0, _previewFilter.height());
- d = max(0.0, _previewFilter.depth());
+ w = max(0.0, _previewHandler.width());
+ h = max(0.0, _previewHandler.height());
+ d = max(0.0, _previewHandler.depth());
actions.bbox() = bbox;
Message::mstream() << "\napplying bounding box set by";
}
@@ -557,7 +555,7 @@ void PsSpecialHandler::dviEndPage (unsigned, SpecialActions &actions) {
d = max(0.0, actions.bbox().maxY());
Message::mstream() << "\ncomputing extents based on data set by";
}
- Message::mstream() << " preview package (version " << _previewFilter.version() << ")\n";
+ Message::mstream() << " preview package (version " << _previewHandler.version() << ")\n";
// apply page transformations to box extents
Matrix pagetrans = actions.getPageTransformation();
diff --git a/dviware/dvisvgm/src/PsSpecialHandler.hpp b/dviware/dvisvgm/src/PsSpecialHandler.hpp
index fb44e4bfa4..90285a2b0e 100644
--- a/dviware/dvisvgm/src/PsSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/PsSpecialHandler.hpp
@@ -31,7 +31,7 @@
#include "PSInterpreter.hpp"
#include "Opacity.hpp"
#include "PSPattern.hpp"
-#include "PSPreviewFilter.hpp"
+#include "PSPreviewHandler.hpp"
#include "SpecialHandler.hpp"
class PSPattern;
@@ -97,7 +97,7 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
const char* name () const override {return handlerName();}
static const char* handlerName () {return "ps";}
std::vector<const char*> prefixes () const override;
- void setDviScaleFactor (double dvi2bp) override {_previewFilter.setDviScaleFactor(dvi2bp);}
+ void setDviScaleFactor (double dvi2bp) override {_previewHandler.setDviScaleFactor(dvi2bp);}
void enterBodySection ();
PSInterpreter& psInterpreter () {return _psi;}
@@ -180,7 +180,7 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
PSInterpreter _psi;
PDFHandler _pdfHandler;
SpecialActions *_actions=nullptr;
- PSPreviewFilter _previewFilter; ///< filter to extract information generated by the preview package
+ PSPreviewHandler _previewHandler; ///< extracts information generated by the preview package
PsSection _psSection=PS_NONE; ///< current section processed (nothing yet, headers, or body specials)
XMLElement *_xmlnode=nullptr; ///< if != 0, created SVG elements are appended to this node
XMLElement *_savenode=nullptr; ///< pointer to temporaryly store _xmlnode
diff --git a/dviware/dvisvgm/src/SVGCharPathHandler.cpp b/dviware/dvisvgm/src/SVGCharPathHandler.cpp
index 2c753d2e5c..dc0c0724bb 100644
--- a/dviware/dvisvgm/src/SVGCharPathHandler.cpp
+++ b/dviware/dvisvgm/src/SVGCharPathHandler.cpp
@@ -95,7 +95,9 @@ void SVGCharPathHandler::appendChar (uint32_t c, double x, double y) {
// the exact location in vertical mode.
GlyphMetrics exact_metrics;
physicalFont->getExactGlyphBox(c, exact_metrics, false, nullptr);
- y += exact_metrics.h + (metrics.d - exact_metrics.h - exact_metrics.d) / 2;
+ double ed = max(0.0, exact_metrics.d);
+ double eh = max(0.0, exact_metrics.h);
+ y += eh + (metrics.d - eh - ed) / 2;
}
}
}
diff --git a/dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp b/dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp
index 28d9a64346..2cd59558b0 100644
--- a/dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp
+++ b/dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp
@@ -71,6 +71,7 @@ void ClipPathReassigner::execute (XMLElement *defs, XMLElement *context) {
}
// replace clip path references
vector<XMLElement*> descendants;
+ defs->getDescendants(nullptr, "clip-path", descendants);
context->getDescendants(nullptr, "clip-path", descendants);
for (auto &mapEntry : clipPathMap) {
vector<XMLElement*> &identicalClipPathElements = mapEntry.second;
diff --git a/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp b/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
index 889e011571..1554dc9894 100644
--- a/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
+++ b/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
@@ -21,6 +21,7 @@
#include <algorithm>
#include <array>
#include <map>
+#include <set>
#include "SVGOptimizer.hpp"
#include "../SVGTree.hpp"
@@ -30,7 +31,6 @@
#include "RedundantElementRemover.hpp"
#include "TextSimplifier.hpp"
#include "TransformSimplifier.hpp"
-#include "WSNodeRemover.hpp"
using namespace std;
@@ -51,23 +51,41 @@ SVGOptimizer::SVGOptimizer (SVGTree *svg) : _svg(svg) {
void SVGOptimizer::execute () {
if (!_svg || MODULE_SEQUENCE == "none")
return;
- if (MODULE_SEQUENCE.empty())
- MODULE_SEQUENCE = "remove-clippath"; // default behaviour of previous dvisvgm releases
+
+ vector<string> names = util::split(MODULE_SEQUENCE, ",", true);
+ set<string> removedNames;
+ if (names.empty())
+ names.emplace_back("remove-clippaths"); // default behaviour of previous dvisvgm releases
else {
- if (MODULE_SEQUENCE == "all") {
- for (const auto &entry: _moduleEntries)
- entry.module->execute(_svg->defsNode(), _svg->pageNode());
+ auto it = names.begin();
+ if (*it == "all" || (!it->empty() && it->at(0) == '-')) {
+ if (*it == "all")
+ it = names.erase(it);
+ // add names of all optimizer modules
+ for (const auto &moduleEntry : _moduleEntries) {
+ it = names.insert(it, moduleEntry.modname);
+ ++it;
+ }
+ }
+ }
+ // create sequence of module names to be considered
+ for (auto it=names.begin(); it != names.end();) {
+ if ((*it)[0] == '-') {
+ removedNames.insert(it->substr(1));
+ it = names.erase(it);
}
else {
- vector<string> names = util::split(MODULE_SEQUENCE, ",");
- auto it = find_if(names.begin(), names.end(), [](const string &name) {
- return name == "simplify-transform";
- });
- GroupCollapser::COMBINE_TRANSFORMS = (it != names.end());
- for (const string &name: names) {
- if (OptimizerModule *module = getModule(name))
- module->execute(_svg->defsNode(), _svg->pageNode());
- }
+ if ((*it)[0] == '+')
+ *it = it->substr(1);
+ ++it;
+ }
+ }
+ GroupCollapser::COMBINE_TRANSFORMS = (find(names.begin(), names.end(), "simplify-transform") != names.end());
+ // execute optimizer modules
+ for (const string &name: names) {
+ if (removedNames.find(name) == removedNames.end()) {
+ if (OptimizerModule *module = getModule(name))
+ module->execute(_svg->defsNode(), _svg->pageNode());
}
}
}
@@ -93,11 +111,13 @@ void SVGOptimizer::listModules (ostream &os) const {
* @return true if all names are known */
bool SVGOptimizer::checkModuleString (string &namestr, vector<string> &unknownNames) const {
unknownNames.clear();
- if (namestr.empty() || namestr == "all" || namestr == "none")
+ if (namestr.empty() || namestr == "none" || namestr == "all" || namestr.substr(0,4) == "all,")
return true;
vector<string> givenNames = util::split(namestr, ",");
- for (const string &name : givenNames) {
- if (!getModule(name))
+ for (string name : givenNames) {
+ if (name[0] == '-' || name[0] == '+')
+ name = name.substr(1);
+ if (!name.empty() && !getModule(name))
unknownNames.emplace_back(name);
}
return unknownNames.empty();
diff --git a/dviware/dvisvgm/src/options.xml b/dviware/dvisvgm/src/options.xml
index bd7867970f..70fafe4c37 100644
--- a/dviware/dvisvgm/src/options.xml
+++ b/dviware/dvisvgm/src/options.xml
@@ -21,197 +21,197 @@
<!DOCTYPE cmdline SYSTEM "options.dtd">
<cmdline class="CommandLine">
- <program>
- <usage>[options] dvifile</usage>
- <usage>--eps [options] epsfile</usage>
- <usage>--pdf [options] pdffile</usage>
- <description>This program converts DVI files, as created by TeX/LaTeX, as well as\nEPS and PDF files to the XML-based scalable vector graphics format SVG.</description>
- <copyright>Copyright (C) 2005-2023 Martin Gieseking &lt;martin.gieseking@uos.de></copyright>
- </program>
- <options>
- <section title="Input options">
- <option long="page" short="p">
- <arg type="string" name="ranges" default="1"/>
- <description>choose page(s) to convert</description>
- </option>
- <option long="fontmap" short="m">
- <arg type="string" name="filenames"/>
- <description>evaluate (additional) font map files</description>
- </option>
- <option long="eps" short="E" if="!defined(DISABLE_GS)">
- <description>convert EPS file to SVG</description>
- </option>
- <option long="pdf" short="P" if="!defined(DISABLE_GS)">
- <description>convert PDF file to SVG</description>
- </option>
- <option long="stdin">
- <description>read input file from stdin</description>
- </option>
- </section>
- <section title="SVG output options">
- <option long="bbox" short="b">
- <arg type="string" name="size" default="min"/>
- <description>set size of bounding box</description>
- </option>
- <option long="bitmap-format" short="B" if="!defined(DISABLE_GS)">
- <arg type="string" name="fmt" default="jpeg"/>
- <description>set format used to embed PS/EPS bitmaps</description>
- </option>
- <option long="clipjoin" short="j" if="!defined(DISABLE_GS)">
- <description>compute intersection of clipping paths</description>
- </option>
- <option long="colornames">
- <description>prefer color names to RGB values if possible</description>
- </option>
- <option long="comments">
- <description>add comments with additional information</description>
- </option>
- <option long="currentcolor">
- <arg type="string" name="color" default="#000" optional="yes"/>
- <description>replace given color with 'currentColor'</description>
- </option>
- <option long="embed-bitmaps">
- <description>prevent references to external bitmap files</description>
- </option>
- <option long="font-format" short="f" if="!defined(DISABLE_WOFF)">
- <arg type="string" name="format" default="svg"/>
- <description>set file format of embedded fonts</description>
- </option>
- <option long="grad-overlap" if="!defined(DISABLE_GS)">
- <description>create overlapping color gradient segments</description>
- </option>
- <option long="grad-segments" if="!defined(DISABLE_GS)">
- <arg type="int" name="number" default="20"/>
- <description>number of color gradient segments per row</description>
- </option>
- <option long="grad-simplify" if="!defined(DISABLE_GS)">
- <arg type="double" name="delta" default="0.05"/>
- <description>reduce level of detail for small segments</description>
- </option>
- <option long="linkmark" short="L">
- <arg type="string" name="style" default="box"/>
- <description>select how to mark hyperlinked areas</description>
- </option>
- <option long="optimize" short="O">
- <arg name="modules" type="string" default="all" optional="yes"/>
- <description>perform several SVG optimizations</description>
- </option>
- <option long="output" short="o">
- <arg type="string" name="pattern"/>
- <description>set name pattern of output files</description>
- </option>
- <option long="precision" short="d">
- <arg type="int" name="number" default="0"/>
- <description>set number of decimal points (0-6)</description>
- </option>
- <option long="relative" short="R">
- <description>create relative path commands</description>
- </option>
- <option long="stdout" short="s">
- <description>write SVG output to stdout</description>
- </option>
- <option long="tmpdir">
- <arg type="string" name="path" optional="yes"/>
- <description>set/print the directory for temporary files</description>
- </option>
- <option long="no-fonts" short="n">
- <arg type="int" name="variant" default="0" optional="yes"/>
- <description>draw glyphs by using path elements</description>
- </option>
- <option long="no-merge">
- <description>don't merge adjacent text elements</description>
- </option>
- <option long="no-styles">
- <description>don't use CSS styles to reference fonts</description>
- </option>
- <option long="zip" short="z">
- <arg type="int" name="level" default="9" optional="yes"/>
- <description>create compressed .svgz file</description>
- </option>
- </section>
- <section title="SVG transformations">
- <option long="rotate" short="r">
- <arg type="double" name="angle"/>
- <description>rotate page content clockwise</description>
- </option>
- <option long="scale" short="c">
- <arg type="string" name="sx[,sy]"/>
- <description>scale page content</description>
- </option>
- <option long="translate" short="t">
- <arg type="string" name="tx[,ty]"/>
- <description>shift page content</description>
- </option>
- <option long="transform" short="T">
- <arg type="string" name="commands"/>
- <description>transform page content</description>
- </option>
- <option long="zoom" short="Z">
- <arg type="double" name="factor" default="1.0"/>
- <description>zoom page content</description>
- </option>
- </section>
- <section title="Processing options">
- <option long="cache" short="C">
- <arg type="string" name="dir" optional="yes"/>
- <description>set/print path of cache directory</description>
- </option>
- <option long="debug-glyphs" if="defined(TTFDEBUG)">
- <description>create PS files for all glyphs converted to TTF</description>
- </option>
- <option long="exact-bbox" short="e">
- <description>compute exact glyph bounding boxes</description>
- </option>
- <option long="keep">
- <description>keep temporary files</description>
- </option>
- <option long="libgs" if="!defined(HAVE_LIBGS) &amp;&amp; !defined(DISABLE_GS)">
- <arg name="filename" type="string"/>
- <description>set name of Ghostscript shared library</description>
- </option>
- <option long="mag" short="M">
- <arg type="double" name="factor" default="4"/>
- <description>magnification of Metafont output</description>
- </option>
- <option long="no-mktexmf">
- <description>don't try to create missing fonts</description>
- </option>
- <option long="no-specials" short="S">
- <arg type="string" name="prefixes" optional="yes"/>
- <description>don't process [selected] specials</description>
- </option>
- <option long="page-hashes" short="H">
- <arg type="string" name="params" optional="yes" default="xxh64"/>
- <description>activate usage of page hashes</description>
- </option>
- <option long="trace-all" short="a">
- <arg name="retrace" type="bool" optional="yes" default="false"/>
- <description>trace all glyphs of bitmap fonts</description>
- </option>
- </section>
- <section title="Message options">
- <option long="color">
- <description>colorize messages</description>
- </option>
- <option long="help" short="h">
- <arg name="mode" type="int" optional="yes" default="0"/>
- <description>print this summary of options and exit</description>
- </option>
- <option long="list-specials" short="l">
- <description>print supported special sets and exit</description>
- </option>
- <option long="progress">
- <arg name="delay" type="double" optional="yes" default="0.5"/>
- <description>enable progress indicator</description>
- </option>
- <option long="verbosity" short="v">
- <arg type="unsigned" name="level" default="7"/>
- <description>set verbosity level (0-7)</description>
- </option>
- <option long="version" short="V">
- <arg type="bool" name="extended" optional="yes" default="false"/>
- <description>print version and exit</description>
- </option>
- </section>
- </options>
+ <program>
+ <usage>[options] dvifile</usage>
+ <usage>--eps [options] epsfile</usage>
+ <usage>--pdf [options] pdffile</usage>
+ <description>This program converts DVI files, as created by TeX/LaTeX, as well as\nEPS and PDF files to the XML-based scalable vector graphics format SVG.</description>
+ <copyright>Copyright (C) 2005-2023 Martin Gieseking &lt;martin.gieseking@uos.de></copyright>
+ </program>
+ <options>
+ <section title="Input options">
+ <option long="page" short="p">
+ <arg type="string" name="ranges" default="1"/>
+ <description>choose page(s) to convert</description>
+ </option>
+ <option long="fontmap" short="m">
+ <arg type="string" name="filenames"/>
+ <description>evaluate (additional) font map files</description>
+ </option>
+ <option long="eps" short="E" if="!defined(DISABLE_GS)">
+ <description>convert EPS file to SVG</description>
+ </option>
+ <option long="pdf" short="P" if="!defined(DISABLE_GS)">
+ <description>convert PDF file to SVG</description>
+ </option>
+ <option long="stdin">
+ <description>read input file from stdin</description>
+ </option>
+ </section>
+ <section title="SVG output options">
+ <option long="bbox" short="b">
+ <arg type="string" name="size" default="min"/>
+ <description>set size of bounding box</description>
+ </option>
+ <option long="bitmap-format" short="B" if="!defined(DISABLE_GS)">
+ <arg type="string" name="fmt" default="jpeg"/>
+ <description>set format used to embed PS/EPS bitmaps</description>
+ </option>
+ <option long="clipjoin" short="j" if="!defined(DISABLE_GS)">
+ <description>compute intersection of clipping paths</description>
+ </option>
+ <option long="colornames">
+ <description>prefer color names to RGB values if possible</description>
+ </option>
+ <option long="comments">
+ <description>add comments with additional information</description>
+ </option>
+ <option long="currentcolor">
+ <arg type="string" name="color" default="#000" optional="yes"/>
+ <description>replace given color with 'currentColor'</description>
+ </option>
+ <option long="embed-bitmaps">
+ <description>prevent references to external bitmap files</description>
+ </option>
+ <option long="font-format" short="f" if="!defined(DISABLE_WOFF)">
+ <arg type="string" name="format" default="svg"/>
+ <description>set file format of embedded fonts</description>
+ </option>
+ <option long="grad-overlap" if="!defined(DISABLE_GS)">
+ <description>create overlapping color gradient segments</description>
+ </option>
+ <option long="grad-segments" if="!defined(DISABLE_GS)">
+ <arg type="int" name="number" default="20"/>
+ <description>number of color gradient segments per row</description>
+ </option>
+ <option long="grad-simplify" if="!defined(DISABLE_GS)">
+ <arg type="double" name="delta" default="0.05"/>
+ <description>reduce level of detail for small segments</description>
+ </option>
+ <option long="linkmark" short="L">
+ <arg type="string" name="style" default="box"/>
+ <description>select how to mark hyperlinked areas</description>
+ </option>
+ <option long="optimize" short="O">
+ <arg name="modules" type="string" default="all" optional="yes"/>
+ <description>perform several SVG optimizations</description>
+ </option>
+ <option long="output" short="o">
+ <arg type="string" name="pattern"/>
+ <description>set name pattern of output files</description>
+ </option>
+ <option long="precision" short="d">
+ <arg type="int" name="number" default="0"/>
+ <description>set number of decimal points (0-6)</description>
+ </option>
+ <option long="relative" short="R">
+ <description>create relative path commands</description>
+ </option>
+ <option long="stdout" short="s">
+ <description>write SVG output to stdout</description>
+ </option>
+ <option long="tmpdir">
+ <arg type="string" name="path" optional="yes"/>
+ <description>set/print the directory for temporary files</description>
+ </option>
+ <option long="no-fonts" short="n">
+ <arg type="int" name="variant" default="0" optional="yes"/>
+ <description>draw glyphs by using path elements</description>
+ </option>
+ <option long="no-merge">
+ <description>don't merge adjacent text elements</description>
+ </option>
+ <option long="no-styles">
+ <description>don't use CSS styles to reference fonts</description>
+ </option>
+ <option long="zip" short="z">
+ <arg type="int" name="level" default="9" optional="yes"/>
+ <description>create compressed .svgz file</description>
+ </option>
+ </section>
+ <section title="SVG transformations">
+ <option long="rotate" short="r">
+ <arg type="double" name="angle"/>
+ <description>rotate page content clockwise</description>
+ </option>
+ <option long="scale" short="c">
+ <arg type="string" name="sx[,sy]"/>
+ <description>scale page content</description>
+ </option>
+ <option long="translate" short="t">
+ <arg type="string" name="tx[,ty]"/>
+ <description>shift page content</description>
+ </option>
+ <option long="transform" short="T">
+ <arg type="string" name="commands"/>
+ <description>transform page content</description>
+ </option>
+ <option long="zoom" short="Z">
+ <arg type="double" name="factor" default="1.0"/>
+ <description>zoom page content</description>
+ </option>
+ </section>
+ <section title="Processing options">
+ <option long="cache" short="C">
+ <arg type="string" name="dir" optional="yes"/>
+ <description>set/print path of cache directory</description>
+ </option>
+ <option long="debug-glyphs" if="defined(TTFDEBUG)">
+ <description>create PS files for all glyphs converted to TTF</description>
+ </option>
+ <option long="exact-bbox" short="e">
+ <description>compute exact glyph bounding boxes</description>
+ </option>
+ <option long="keep">
+ <description>keep temporary files</description>
+ </option>
+ <option long="libgs" if="!defined(HAVE_LIBGS) &amp;&amp; !defined(DISABLE_GS)">
+ <arg name="filename" type="string"/>
+ <description>set name of Ghostscript shared library</description>
+ </option>
+ <option long="mag" short="M">
+ <arg type="double" name="factor" default="4"/>
+ <description>magnification of Metafont output</description>
+ </option>
+ <option long="no-mktexmf">
+ <description>don't try to create missing fonts</description>
+ </option>
+ <option long="no-specials" short="S">
+ <arg type="string" name="prefixes" optional="yes"/>
+ <description>don't process [selected] specials</description>
+ </option>
+ <option long="page-hashes" short="H">
+ <arg type="string" name="params" optional="yes" default="xxh64"/>
+ <description>activate usage of page hashes</description>
+ </option>
+ <option long="trace-all" short="a">
+ <arg name="retrace" type="bool" optional="yes" default="false"/>
+ <description>trace all glyphs of bitmap fonts</description>
+ </option>
+ </section>
+ <section title="Message options">
+ <option long="color">
+ <description>colorize messages</description>
+ </option>
+ <option long="help" short="h">
+ <arg name="mode" type="int" optional="yes" default="0"/>
+ <description>print this summary of options and exit</description>
+ </option>
+ <option long="list-specials" short="l">
+ <description>print supported special sets and exit</description>
+ </option>
+ <option long="progress">
+ <arg name="delay" type="double" optional="yes" default="0.5"/>
+ <description>enable progress indicator</description>
+ </option>
+ <option long="verbosity" short="v">
+ <arg type="unsigned" name="level" default="7"/>
+ <description>set verbosity level (0-7)</description>
+ </option>
+ <option long="version" short="V">
+ <arg type="bool" name="extended" optional="yes" default="false"/>
+ <description>print version and exit</description>
+ </option>
+ </section>
+ </options>
</cmdline>
diff --git a/dviware/dvisvgm/src/psdefs.cpp b/dviware/dvisvgm/src/psdefs.cpp
index e3a8372671..fdbdabba41 100644
--- a/dviware/dvisvgm/src/psdefs.cpp
+++ b/dviware/dvisvgm/src/psdefs.cpp
@@ -35,131 +35,130 @@ const char *PSInterpreter::PSDEFS =
"tshapealpha known not{@SD/.setshapealpha{pop}put}if @SD/.setblendmode known no"
"t{@SD/.setblendmode{pop}put}if @SD/prseq{-1 1{-1 roll =only( )print}for(\\n)pr"
"int}put @SD/prcmd{( )exch(\\ndvi.)3{print}repeat prseq}put @SD/cvxall{{cvx}for"
-"all}put @SD/defpr{[exch[/copy @SD]cvxall 5 -1 roll dup 6 1 roll[/get/exec]cvxa"
-"ll 6 -1 roll dup 7 1 roll 4 -1 roll dup 5 1 roll dup length string cvs/prcmd c"
-"vx]cvx def}put @SD/querypos{{currentpoint}stopped{$error/newerror false put}{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 dtrans"
-"form dup mul exch dup dup mul 3 -1 roll add dup 0 eq{pop}{sqrt div}ifelse 3(ap"
-"plyscalevals)prcmd}put @SD/prpath{{2(moveto)prcmd}{2(lineto)prcmd}{6(curveto)p"
-"rcmd}{0(closepath)prcmd}pathforall}put @SD/nulldevice{@GD/@nulldev true put :n"
-"ulldevice 1 1(setnulldevice)prcmd}put @SD/charpath{/@dodraw false store :charp"
-"ath/@dodraw true store}put @SD/stringwidth{/@dodraw false store :stringwidth/@"
-"dodraw true store}put @SD/show{@dodraw @GD/@nulldev get not and{dup :gsave cur"
-"rentpoint 2{50 mul exch}repeat :newpath moveto 50 50/scale sysexec true charpa"
-"th fill :grestore/@dodraw false store :show/@dodraw true store}{:show}ifelse}p"
-"ut @SD/varxyshow{dup 0 ge{<</chr 3 -1 roll string/prc 5 -1 roll/arr 7 -1 roll/"
-"str 9 -1 roll/idx 0>>begin 0 chr length str length 1 sub{str exch chr length g"
-"etinterval/chr exch store :gsave chr show :grestore currentpoint prc moveto/id"
-"x idx 1 add store}for end}{pop pop show}ifelse}put @SD/xyshow{dup dup type/arr"
-"aytype eq exch length 0 gt and{dup length 2 idiv 2 index length exch idiv}{-1}"
-"ifelse{exch arr idx 2 mul get add exch arr idx 2 mul 1 add get add}exch varxys"
-"how}put @SD/xshow{dup dup type/arraytype eq exch length 0 gt and{dup length 2 "
-"index length exch idiv}{-1}ifelse{exch arr idx get add exch}exch varxyshow}put"
-" @SD/yshow{dup dup type/arraytype eq exch length 0 gt and{dup length 2 index l"
-"ength exch idiv}{-1}ifelse{arr idx get add}exch varxyshow}put @SD/awidthshow{{"
-"1 string dup 0 5 index put :gsave show :grestore pop 0 rmoveto 3 index eq{4 in"
-"dex 4 index rmoveto}if 1 index 1 index rmoveto}exch cshow 5{pop}repeat}put @SD"
-"/widthshow{0 0 3 -1 roll awidthshow}put @SD/ashow{0 0 0 6 3 roll awidthshow}pu"
-"t @SD/newpath{:newpath 1 1(newpath)prcmd}put @SD/stroke{@dodraw @GD/@nulldev g"
-"et not and{prcolor 0 1(newpath)prcmd prpath 0(stroke)prcmd :newpath}{:stroke}i"
-"felse}put @SD/fill{@dodraw @GD/@nulldev get not and{prcolor 0 1(newpath)prcmd "
-"prpath 0(fill)prcmd :newpath}{:fill}ifelse}put @SD/eofill{@dodraw @GD/@nulldev"
-" get not and{prcolor 0 1(newpath)prcmd prpath 0(eofill)prcmd :newpath}{:eofill"
-"}ifelse}put/.fillstroke{:gsave fill :grestore .swapcolors stroke .swapcolors}b"
-"ind def/.eofillstroke{:gsave eofill :grestore .swapcolors stroke .swapcolors}b"
-"ind def @SD/clip{:clip @GD/@nulldev get not{0 1(newpath)prcmd prpath 0(clip)pr"
-"cmd}if}put @SD/eoclip{:eoclip @GD/@nulldev get not{0 1(newpath)prcmd prpath 0("
-"eoclip)prcmd}if}put @SD/shfill{begin currentdict/ShadingType known currentdict"
-"/ColorSpace known and currentdict/DataSource known and currentdict/Function kn"
-"own not and ShadingType 4 ge{DataSource type/arraytype eq{<</DeviceGray 1/Devi"
-"ceRGB 3/DeviceCMYK 4/bgknown currentdict/Background known/bbknown currentdict/"
-"BBox known>>begin currentdict ColorSpace known{ShadingType ColorSpace load bgk"
-"nown{1 Background aload pop}{0}ifelse bbknown{1 BBox aload pop}{0}ifelse Shadi"
-"ngType 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"
-"}if end}put @SD/image{dup type/dicttype eq{dup}{<</Width 6 index/Height 7 inde"
-"x/colorimg false>>}ifelse @execimg}put @SD/colorimage{<<2 index{/Width 2 index"
-" 8 add index/Height 4 index 9 add index}{/Width 8 index/Height 9 index}ifelse/"
-"colorimg true>>@execimg}put/@imgbase(./)def/@imgdevice(jpeg)def/@execimg{@GD/@"
-"imgcnt 2 copy .knownget{1 add}{1}ifelse put begin<</imgdev null/imgid @GD/@img"
-"cnt get/ispng @imgdevice 0 3 getinterval(png)eq dup/suffix exch{(.png)}{(.jpg)"
-"}ifelse/colorimg currentdict/colorimg .knownget dup{pop}if/colordev 1 index cu"
-"rrentcolorspace dup length 1 ne exch 0 get/DeviceGray ne or or>>begin @imgdevi"
-"ce(png)ne @imgdevice(jpeg)ne and{@imgdevice cvn}{colordev{ispng{/png16m}{/jpeg"
-"}ifelse}{ispng{/pnggray}{/jpeggray}ifelse}ifelse}ifelse dup devicedict exch kn"
-"own{:gsave/imgdev exch finddevice def mark/OutputFile @imgbase imgid 20 string"
-" cvs strconcat suffix strconcat/PageSize[Width Height]/UseFastColor true ispng"
-"{@imgdevice(pngmonod)eq{/MinFeatureSize where{pop/MinFeatureSize MinFeatureSiz"
-"e}if}if}{/JPEGQ where{pop/JPEGQ JPEGQ}if}ifelse imgdev putdeviceprops setdevic"
-"e[Width 0 0 Height neg 0 Height]/setmatrix sysexec colorimg{:colorimage}{:imag"
-"e}ifelse/copypage sysexec mark/OutputFile()imgdev putdeviceprops pop :grestore"
-" imgid Width Height 3(image)prcmd}{pop colorimg{:colorimage}{:image}ifelse}ife"
-"lse end end}def/@rect{4 -2 roll moveto exch dup 0 rlineto exch 0 exch rlineto "
-"neg 0 rlineto closepath}bind def/@rectcc{4 -2 roll moveto 2 copy 0 lt exch 0 l"
-"t xor{dup 0 exch rlineto exch 0 rlineto neg 0 exch rlineto}{exch dup 0 rlineto"
-" exch 0 exch rlineto neg 0 rlineto}ifelse closepath}bind def @SD/rectclip{:new"
-"path dup type/arraytype eq{aload length 4 idiv{@rectcc}repeat}{@rectcc}ifelse "
-"clip :newpath}put @SD/rectfill{:gsave :newpath dup type/arraytype eq{aload len"
-"gth 4 idiv{@rectcc}repeat}{@rectcc}ifelse fill :grestore}put @SD/rectstroke{gs"
-"ave :newpath dup type/arraytype eq{aload length 4 idiv{@rect}repeat}{@rect}ife"
-"lse stroke grestore}put false setglobal @SD readonly pop/initclip 0 defpr/clip"
-"path 0 defpr/sysexec{@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 sy"
-"sexec 1(setlinewidth)prcmd}def/setlinecap 1 defpr/setlinejoin 1 defpr/setmiter"
-"limit 1 defpr/setdash{mark 3 1 roll 2 copy/setdash sysexec exch aload length 1"
-" add -1 roll counttomark(setdash)prcmd pop}def/@setpagedevice{pop<<>>/setpaged"
-"evice sysexec matrix setmatrix newpath 0(setpagedevice)prcmd}def/@checknulldev"
-"{@GD/@nulldev get{currentpagedevice maxlength 0 ne{@GD/@nulldev false put 0 1("
-"setnulldevice)prcmd}if}if}def/prcolor{currentcolorspace @setcolorspace current"
-"rgbcolor 3(setrgbcolor)prcmd}def/printgstate{@dodraw @GD/@nulldev get not and{"
-"matrix currentmatrix aload pop 6(setmatrix)prcmd applyscalevals currentlinewid"
-"th 1(setlinewidth)prcmd currentlinecap 1(setlinecap)prcmd currentlinejoin 1(se"
-"tlinejoin)prcmd currentmiterlimit 1(setmiterlimit)prcmd revision dup 952 lt{po"
-"p}{.currentblendmode .setblendmode 952 eq{.currentopacityalpha .setopacityalph"
-"a .currentshapealpha .setshapealpha}{.currentalphaisshape{1}{0}ifelse 1(setalp"
-"haisshape)prcmd .currentstrokeconstantalpha 1(setstrokeconstantalpha)prcmd .cu"
-"rrentfillconstantalpha 1(setfillconstantalpha)prcmd}ifelse}ifelse prcolor curr"
-"entdash mark 3 1 roll exch aload length 1 add -1 roll counttomark(setdash)prcm"
-"d pop}if}def/strconcat{exch dup length 2 index length add string dup dup 4 2 r"
-"oll copy length 4 -1 roll putinterval}def/setgstate{/setgstate sysexec printgs"
-"tate}def/save{@UD begin/@saveID vmstatus pop pop def end :save @saveID 1(save)"
-"prcmd}def/restore{:restore @checknulldev printgstate @UD/@saveID known{@UD beg"
-"in @saveID end}{0}ifelse 1(restore)prcmd}def/gsave 0 defpr/grestore{:grestore "
-"@checknulldev printgstate 0(grestore)prcmd}def/grestoreall{:grestoreall @check"
-"nulldev setstate 0(grestoreall)prcmd}def/rotate{dup type/arraytype ne @dodraw "
-"and{dup 1(rotate)prcmd}if/rotate sysexec applyscalevals}def/scale{dup type/arr"
-"aytype ne @dodraw and{2 copy 2(scale)prcmd}if/scale sysexec applyscalevals}def"
-"/translate{dup type/arraytype ne @dodraw and{2 copy 2(translate)prcmd}if/trans"
-"late sysexec}def/setmatrix{dup/setmatrix sysexec @dodraw{aload pop 6(setmatrix"
-")prcmd applyscalevals}{pop}ifelse}def/initmatrix{matrix setmatrix}def/concat{m"
-"atrix currentmatrix matrix concatmatrix setmatrix}def/makepattern{gsave<</mx 3"
-" -1 roll>>begin<</XUID[1000000 @patcnt]>>copy mx/makepattern sysexec dup begin"
-" PatternType 2 lt{PatternType @patcnt BBox aload pop XStep YStep PaintType mx "
-"aload pop 15(makepattern)prcmd :newpath matrix setmatrix dup PaintProc 0 1(mak"
-"epattern)prcmd @GD/@patcnt @patcnt 1 add put}if end end grestore}def/setpatter"
-"n{dup begin PatternType end 1 eq{begin PaintType 1 eq{XUID aload pop exch pop "
-"1}{:gsave[currentcolorspace aload length -1 roll pop]/setcolorspace sysexec/se"
-"tcolor sysexec XUID aload pop exch pop currentrgbcolor :grestore 4}ifelse(setp"
-"attern)prcmd currentcolorspace 0 get/Pattern ne{[/Pattern currentcolorspace]/s"
-"etcolorspace sysexec}if currentcolorspace @setcolorspace end}{/setpattern syse"
-"xec}ifelse}def/setcolor{dup type/dicttype eq{setpattern}{/setcolor sysexec/cur"
-"rentrgbcolor sysexec setrgbcolor}ifelse}def/setcolorspace{dup/setcolorspace sy"
-"sexec @setcolorspace}def/@setcolorspace{dup type/arraytype eq{0 get}if/Pattern"
-" eq{1}{0}ifelse 1(setcolorspace)prcmd}def/setgray 1 defpr/setcmykcolor 4 defpr"
-"/sethsbcolor 3 defpr/setrgbcolor 3 defpr/.setalphaisshape{@SD/.setalphaisshape"
-" known{dup/.setalphaisshape sysexec}if{1}{0}ifelse 1(setalphaisshape)prcmd}bin"
-"d def/.setfillconstantalpha{@SD/.setfillconstantalpha known{dup/.setfillconsta"
-"ntalpha sysexec}if 1(setfillconstantalpha)prcmd}bind def/.setstrokeconstantalp"
-"ha{@SD/.setstrokeconstantalpha known{dup/.setstrokeconstantalpha sysexec}if 1("
-"setstrokeconstantalpha)prcmd}bind def/.setopacityalpha{false .setalphaisshape "
-"dup .setfillconstantalpha .setstrokeconstantalpha}bind def/.setshapealpha{true"
-" .setalphaisshape dup .setfillconstantalpha .setstrokeconstantalpha}bind def/."
-"setblendmode{dup/.setblendmode sysexec<</Normal 0/Compatible 0/Multiply 1/Scre"
-"en 2/Overlay 3/SoftLight 4/HardLight 5/ColorDodge 6/ColorBurn 7/Darken 8/Light"
-"en 9/Difference 10/Exclusion 11/Hue 12/Saturation 13/Color 14/Luminosity 15/Co"
-"mpatibleOverprint 16>>exch get 1(setblendmode)prcmd}def/@pdfpagecount{(r)file "
-"runpdfbegin pdfpagecount runpdfend}def/@pdfpagebox{(r)file runpdfbegin dup dup"
-" 1 lt exch pdfpagecount gt or{pop}{pdfgetpage/MediaBox pget pop aload pop}ifel"
-"se runpdfend}def DELAYBIND{.bindnow}if ";
+"all}put @SD/defpr{[exch/copy cvx @SD 4 index[/get/exec]cvxall 5 index 3 index "
+"dup length string cvs/prcmd cvx]cvx bind def}put @SD/querypos{{currentpoint}st"
+"opped{$error/newerror false put}{2(querypos)prcmd}ifelse}put @SD/applyscaleval"
+"s{1 0 dtransform exch dup mul exch dup mul add sqrt 0 1 dtransform exch dup mu"
+"l exch dup mul add sqrt 1 0 dtransform 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(curveto)prcmd}{0(closepath)prcmd}pathforall}put @SD/n"
+"ulldevice{@GD/@nulldev true put :nulldevice 1 1(setnulldevice)prcmd}put @SD/ch"
+"arpath{/@dodraw false store :charpath/@dodraw true store}put @SD/stringwidth{/"
+"@dodraw false store :stringwidth/@dodraw true store}put @SD/show{@dodraw @GD/@"
+"nulldev get not and{dup :gsave currentpoint 2{50 mul exch}repeat :newpath move"
+"to 50 50/scale sysexec true charpath fill :grestore/@dodraw false store :show/"
+"@dodraw true store}{:show}ifelse}put @SD/varxyshow{dup 0 ge{<</chr 3 -1 roll s"
+"tring/prc 5 -1 roll/arr 7 -1 roll/str 9 -1 roll/idx 0>>begin 0 chr length str "
+"length 1 sub{str exch chr length getinterval/chr exch store :gsave chr show :g"
+"restore currentpoint prc moveto/idx idx 1 add store}for end}{pop pop show}ifel"
+"se}put @SD/xyshow{dup dup type/arraytype eq exch length 0 gt and{dup length 2 "
+"idiv 2 index length exch idiv}{-1}ifelse{exch arr idx 2 mul get add exch arr i"
+"dx 2 mul 1 add get add}exch varxyshow}put @SD/xshow{dup dup type/arraytype eq "
+"exch length 0 gt and{dup length 2 index length exch idiv}{-1}ifelse{exch arr i"
+"dx get add exch}exch varxyshow}put @SD/yshow{dup dup type/arraytype eq exch le"
+"ngth 0 gt and{dup length 2 index length exch idiv}{-1}ifelse{arr idx get add}e"
+"xch varxyshow}put @SD/awidthshow{{1 string dup 0 5 index put :gsave show :gres"
+"tore pop 0 rmoveto 3 index eq{4 index 4 index rmoveto}if 1 index 1 index rmove"
+"to}exch cshow 5{pop}repeat}put @SD/widthshow{0 0 3 -1 roll awidthshow}put @SD/"
+"ashow{0 0 0 6 3 roll awidthshow}put @SD/newpath{:newpath 1 1(newpath)prcmd}put"
+" @SD/stroke{@dodraw @GD/@nulldev get not and{prcolor 0 1(newpath)prcmd prpath "
+"0(stroke)prcmd :newpath}{:stroke}ifelse}put @SD/fill{@dodraw @GD/@nulldev get "
+"not and{prcolor 0 1(newpath)prcmd prpath 0(fill)prcmd :newpath}{:fill}ifelse}p"
+"ut @SD/eofill{@dodraw @GD/@nulldev get not and{prcolor 0 1(newpath)prcmd prpat"
+"h 0(eofill)prcmd :newpath}{:eofill}ifelse}put/.fillstroke{:gsave fill :grestor"
+"e .swapcolors stroke .swapcolors}bind def/.eofillstroke{:gsave eofill :grestor"
+"e .swapcolors stroke .swapcolors}bind def @SD/clip{:clip @GD/@nulldev get not{"
+"0 1(newpath)prcmd prpath 0(clip)prcmd}if}put @SD/eoclip{:eoclip @GD/@nulldev g"
+"et not{0 1(newpath)prcmd prpath 0(eoclip)prcmd}if}put @SD/shfill{begin current"
+"dict/ShadingType known currentdict/ColorSpace known and currentdict/DataSource"
+" known and currentdict/Function known not and ShadingType 4 ge{DataSource type"
+"/arraytype eq{<</DeviceGray 1/DeviceRGB 3/DeviceCMYK 4/bgknown currentdict/Bac"
+"kground known/bbknown currentdict/BBox known>>begin currentdict ColorSpace kno"
+"wn{ShadingType ColorSpace load bgknown{1 Background aload pop}{0}ifelse bbknow"
+"n{1 BBox aload pop}{0}ifelse ShadingType 5 eq{VerticesPerRow}if DataSource alo"
+"ad length 4 add bgknown{ColorSpace load add}if bbknown{4 add}if ShadingType 5 "
+"eq{1 add}if(shfill)prcmd}if end}if}if end}put @SD/image{dup type/dicttype eq{d"
+"up}{<</Width 6 index/Height 7 index/colorimg false>>}ifelse @execimg}put @SD/c"
+"olorimage{<<2 index{/Width 2 index 8 add index/Height 4 index 9 add index}{/Wi"
+"dth 8 index/Height 9 index}ifelse/colorimg true>>@execimg}put/@imgbase(./)def/"
+"@imgdevice(jpeg)def/@execimg{@GD/@imgcnt 2 copy .knownget{1 add}{1}ifelse put "
+"begin<</imgdev null/imgid @GD/@imgcnt get/ispng @imgdevice 0 3 getinterval(png"
+")eq dup/suffix exch{(.png)}{(.jpg)}ifelse/colorimg currentdict/colorimg .known"
+"get dup{pop}if/colordev 1 index currentcolorspace dup length 1 ne exch 0 get/D"
+"eviceGray ne or or>>begin @imgdevice(png)ne @imgdevice(jpeg)ne and{@imgdevice "
+"cvn}{colordev{ispng{/png16m}{/jpeg}ifelse}{ispng{/pnggray}{/jpeggray}ifelse}if"
+"else}ifelse dup devicedict exch known{:gsave/imgdev exch finddevice def mark/O"
+"utputFile @imgbase imgid 20 string cvs strconcat suffix strconcat/PageSize[Wid"
+"th Height]/UseFastColor true ispng{@imgdevice(pngmonod)eq{/MinFeatureSize wher"
+"e{pop/MinFeatureSize MinFeatureSize}if}if}{/JPEGQ where{pop/JPEGQ JPEGQ}if}ife"
+"lse imgdev putdeviceprops setdevice[Width 0 0 Height neg 0 Height]/setmatrix s"
+"ysexec colorimg{:colorimage}{:image}ifelse/copypage sysexec mark/OutputFile()i"
+"mgdev putdeviceprops pop :grestore imgid Width Height 3(image)prcmd}{pop color"
+"img{:colorimage}{:image}ifelse}ifelse end end}def/@rect{4 -2 roll moveto exch "
+"dup 0 rlineto exch 0 exch rlineto neg 0 rlineto closepath}bind def/@rectcc{4 -"
+"2 roll moveto 2 copy 0 lt exch 0 lt xor{dup 0 exch rlineto exch 0 rlineto neg "
+"0 exch rlineto}{exch dup 0 rlineto exch 0 exch rlineto neg 0 rlineto}ifelse cl"
+"osepath}bind def @SD/rectclip{:newpath dup type/arraytype eq{aload length 4 id"
+"iv{@rectcc}repeat}{@rectcc}ifelse clip :newpath}put @SD/rectfill{:gsave :newpa"
+"th dup type/arraytype eq{aload length 4 idiv{@rectcc}repeat}{@rectcc}ifelse fi"
+"ll :grestore}put @SD/rectstroke{gsave :newpath dup type/arraytype eq{aload len"
+"gth 4 idiv{@rect}repeat}{@rect}ifelse stroke grestore}put false setglobal @SD "
+"readonly pop/initclip 0 defpr/clippath 0 defpr/sysexec{@SD exch get exec}def/a"
+"dddot{dup length 1 add string dup 0 46 put dup 3 -1 roll 1 exch putinterval}de"
+"f/setlinewidth{dup/setlinewidth sysexec 1(setlinewidth)prcmd}def/setlinecap 1 "
+"defpr/setlinejoin 1 defpr/setmiterlimit 1 defpr/setdash{mark 3 1 roll 2 copy/s"
+"etdash sysexec exch aload length 1 add -1 roll counttomark(setdash)prcmd pop}d"
+"ef/@setpagedevice{pop<<>>/setpagedevice sysexec matrix setmatrix newpath 0(set"
+"pagedevice)prcmd}def/@checknulldev{@GD/@nulldev get{currentpagedevice maxlengt"
+"h 0 ne{@GD/@nulldev false put 0 1(setnulldevice)prcmd}if}if}def/prcolor{curren"
+"tcolorspace @setcolorspace currentrgbcolor 3(setrgbcolor)prcmd}def/printgstate"
+"{@dodraw @GD/@nulldev get not and{matrix currentmatrix aload pop 6(setmatrix)p"
+"rcmd applyscalevals currentlinewidth 1(setlinewidth)prcmd currentlinecap 1(set"
+"linecap)prcmd currentlinejoin 1(setlinejoin)prcmd currentmiterlimit 1(setmiter"
+"limit)prcmd revision dup 952 lt{pop}{.currentblendmode .setblendmode 952 eq{.c"
+"urrentopacityalpha .setopacityalpha .currentshapealpha .setshapealpha}{.curren"
+"talphaisshape{1}{0}ifelse 1(setalphaisshape)prcmd .currentstrokeconstantalpha "
+"1(setstrokeconstantalpha)prcmd .currentfillconstantalpha 1(setfillconstantalph"
+"a)prcmd}ifelse}ifelse prcolor currentdash mark 3 1 roll exch aload length 1 ad"
+"d -1 roll counttomark(setdash)prcmd pop}if}def/strconcat{exch dup length 2 ind"
+"ex length add string dup dup 4 2 roll copy length 4 -1 roll putinterval}def/se"
+"tgstate{/setgstate sysexec printgstate}def/save{@UD begin/@saveID vmstatus pop"
+" pop def end :save @saveID 1(save)prcmd}def/restore{:restore @checknulldev pri"
+"ntgstate @UD/@saveID known{@UD begin @saveID end}{0}ifelse 1(restore)prcmd}def"
+"/gsave 0 defpr/grestore{:grestore @checknulldev printgstate 0(grestore)prcmd}d"
+"ef/grestoreall{:grestoreall @checknulldev setstate 0(grestoreall)prcmd}def/rot"
+"ate{dup type/arraytype ne @dodraw and{dup 1(rotate)prcmd}if/rotate sysexec app"
+"lyscalevals}def/scale{dup type/arraytype ne @dodraw and{2 copy 2(scale)prcmd}i"
+"f/scale sysexec applyscalevals}def/translate{dup type/arraytype ne @dodraw and"
+"{2 copy 2(translate)prcmd}if/translate sysexec}def/setmatrix{dup/setmatrix sys"
+"exec @dodraw{aload pop 6(setmatrix)prcmd applyscalevals}{pop}ifelse}def/initma"
+"trix{matrix setmatrix}def/concat{matrix currentmatrix matrix concatmatrix setm"
+"atrix}def/makepattern{gsave<</mx 3 -1 roll>>begin<</XUID[1000000 @patcnt]>>cop"
+"y mx/makepattern sysexec dup begin PatternType 2 lt{PatternType @patcnt BBox a"
+"load pop XStep YStep PaintType mx aload pop 15(makepattern)prcmd :newpath matr"
+"ix setmatrix dup PaintProc 0 1(makepattern)prcmd @GD/@patcnt @patcnt 1 add put"
+"}if end end grestore}def/setpattern{dup begin PatternType end 1 eq{begin Paint"
+"Type 1 eq{XUID aload pop exch pop 1}{:gsave[currentcolorspace aload length -1 "
+"roll pop]/setcolorspace sysexec/setcolor sysexec XUID aload pop exch pop curre"
+"ntrgbcolor :grestore 4}ifelse(setpattern)prcmd currentcolorspace 0 get/Pattern"
+" ne{[/Pattern currentcolorspace]/setcolorspace sysexec}if currentcolorspace @s"
+"etcolorspace end}{/setpattern sysexec}ifelse}def/setcolor{dup type/dicttype eq"
+"{setpattern}{/setcolor sysexec/currentrgbcolor sysexec setrgbcolor}ifelse}def/"
+"setcolorspace{dup/setcolorspace sysexec @setcolorspace}def/@setcolorspace{dup "
+"type/arraytype eq{0 get}if/Pattern eq{1}{0}ifelse 1(setcolorspace)prcmd}def/se"
+"tgray 1 defpr/setcmykcolor 4 defpr/sethsbcolor 3 defpr/setrgbcolor 3 defpr/.se"
+"talphaisshape{@SD/.setalphaisshape known{dup/.setalphaisshape sysexec}if{1}{0}"
+"ifelse 1(setalphaisshape)prcmd}bind def/.setfillconstantalpha{@SD/.setfillcons"
+"tantalpha known{dup/.setfillconstantalpha sysexec}if 1(setfillconstantalpha)pr"
+"cmd}bind def/.setstrokeconstantalpha{@SD/.setstrokeconstantalpha known{dup/.se"
+"tstrokeconstantalpha sysexec}if 1(setstrokeconstantalpha)prcmd}bind def/.setop"
+"acityalpha{false .setalphaisshape dup .setfillconstantalpha .setstrokeconstant"
+"alpha}bind def/.setshapealpha{true .setalphaisshape dup .setfillconstantalpha "
+".setstrokeconstantalpha}bind def/.setblendmode{dup/.setblendmode sysexec<</Nor"
+"mal 0/Compatible 0/Multiply 1/Screen 2/Overlay 3/SoftLight 4/HardLight 5/Color"
+"Dodge 6/ColorBurn 7/Darken 8/Lighten 9/Difference 10/Exclusion 11/Hue 12/Satur"
+"ation 13/Color 14/Luminosity 15/CompatibleOverprint 16>>exch get 1(setblendmod"
+"e)prcmd}def/@pdfpagecount{(r)file runpdfbegin pdfpagecount runpdfend}def/@pdfp"
+"agebox{(r)file runpdfbegin dup dup 1 lt exch pdfpagecount gt or{pop}{pdfgetpag"
+"e/MediaBox pget pop aload pop}ifelse runpdfend}def DELAYBIND{.bindnow}if ";
diff --git a/dviware/dvisvgm/src/utility.cpp b/dviware/dvisvgm/src/utility.cpp
index 8492cbdeed..3ffa376435 100644
--- a/dviware/dvisvgm/src/utility.cpp
+++ b/dviware/dvisvgm/src/utility.cpp
@@ -150,12 +150,13 @@ string util::replace (string str, const string &find, const string &repl) {
* returns the substrings.
* @param[in] str string to split
* @param[in] sep separator to look for
+ * @param[in] allowEmptyResult if true, the result vector is empty if str is empty; otherwise an empty string is inserted
* @return the substrings between the separators */
-vector<string> util::split (const string &str, const string &sep) {
+vector<string> util::split (const string &str, const string &sep, bool allowEmptyResult) {
vector<string> parts;
- if (str.empty() || sep.empty())
+ if ((str.empty() && !allowEmptyResult) || sep.empty())
parts.push_back(str);
- else {
+ else if (!str.empty()) {
string::size_type left=0;
while (left <= str.length()) {
auto right = str.find(sep, left);
diff --git a/dviware/dvisvgm/src/utility.hpp b/dviware/dvisvgm/src/utility.hpp
index ee272e22ec..9058baaa58 100644
--- a/dviware/dvisvgm/src/utility.hpp
+++ b/dviware/dvisvgm/src/utility.hpp
@@ -69,7 +69,7 @@ std::string replace (std::string str, const std::string &find, const std::string
std::string to_string (double val);
std::string mimetype (const std::string &fname);
-std::vector<std::string> split (const std::string &str, const std::string &sep);
+std::vector<std::string> split (const std::string &str, const std::string &sep, bool allowEmptyResult=false);
int ilog10 (int n);
bool read_double (std::istream &is, double &value);