diff options
Diffstat (limited to 'dviware/dvisvgm/src')
-rw-r--r-- | dviware/dvisvgm/src/Font.cpp | 15 | ||||
-rw-r--r-- | dviware/dvisvgm/src/Makefile.am | 3 | ||||
-rw-r--r-- | dviware/dvisvgm/src/Makefile.in | 13 | ||||
-rw-r--r-- | dviware/dvisvgm/src/PSFilter.hpp | 41 | ||||
-rw-r--r-- | dviware/dvisvgm/src/PSInterpreter.cpp | 23 | ||||
-rw-r--r-- | dviware/dvisvgm/src/PSInterpreter.hpp | 2 | ||||
-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.cpp | 22 | ||||
-rw-r--r-- | dviware/dvisvgm/src/PsSpecialHandler.hpp | 6 | ||||
-rw-r--r-- | dviware/dvisvgm/src/SVGCharPathHandler.cpp | 4 | ||||
-rw-r--r-- | dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp | 1 | ||||
-rw-r--r-- | dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp | 56 | ||||
-rw-r--r-- | dviware/dvisvgm/src/options.xml | 386 | ||||
-rw-r--r-- | dviware/dvisvgm/src/psdefs.cpp | 253 | ||||
-rw-r--r-- | dviware/dvisvgm/src/utility.cpp | 7 | ||||
-rw-r--r-- | dviware/dvisvgm/src/utility.hpp | 2 |
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 <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) && !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 <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) && !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); |