summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-src/src
diff options
context:
space:
mode:
authorNorbert Preining <preining@logic.at>2019-11-22 02:37:37 +0000
committerNorbert Preining <preining@logic.at>2019-11-22 02:37:37 +0000
commited122ac9332b07846c8f32309a90ee20351b89c3 (patch)
tree1278ed5b65e4815140098fa574e662cd405e25ab /Build/source/texk/dvisvgm/dvisvgm-src/src
parent4d251c1585708a66ebdec74139a6bf13049aa49c (diff)
dvisvgm update to 2.8.1 (from Martin Gieseking)
git-svn-id: svn://tug.org/texlive/trunk@52883 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp12
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp1
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp23
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp18
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp14
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp29
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp35
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.cpp112
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp5
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp16
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp15
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp18
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp41
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp11
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp46
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp28
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp325
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp41
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp13
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/EllipticalArc.cpp260
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/EllipticalArc.hpp59
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp21
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp7
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp5
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp13
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp60
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp17
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp24
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp22
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp130
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp15
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp31
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp75
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp7
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp11
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp7
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp769
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.cpp20
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.cpp24
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.cpp24
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.hpp11
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp43
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp77
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp12
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp12
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/MD5HashFunction.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am313
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in522
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp9
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp29
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp200
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp30
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp32
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.cpp14
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.hpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PDFToSVG.hpp1
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp18
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp5
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp30
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp24
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp35
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp21
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp6
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp230
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp14
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp24
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp14
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp32
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp20
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp12
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp65
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp12
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp123
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp32
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SourceInput.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp26
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp62
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp20
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp27
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp11
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp2
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp26
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp23
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp61
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp16
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp14
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.cpp14
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.hpp4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp20
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp20
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp19
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp10
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp12
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp333
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp169
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp15
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp11
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/XXHashFunction.hpp46
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp16
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp62
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/AttributeExtractor.cpp176
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/AttributeExtractor.hpp61
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/DependencyGraph.hpp (renamed from Build/source/texk/dvisvgm/dvisvgm-src/src/DependencyGraph.hpp)4
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp165
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.hpp36
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/Makefile.am14
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/Makefile.in694
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/OptimizerModule.hpp30
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/RedundantElementRemover.cpp68
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/RedundantElementRemover.hpp29
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/SVGOptimizer.cpp107
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/SVGOptimizer.hpp59
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TextSimplifier.cpp118
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TextSimplifier.hpp30
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TransformSimplifier.cpp182
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TransformSimplifier.hpp (renamed from Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.hpp)36
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/WSNodeRemover.cpp45
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/WSNodeRemover.hpp30
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml8
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp190
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp65
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp27
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp2
186 files changed, 5604 insertions, 2387 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp
index 350e130166a..272c88c3ad1 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.cpp
@@ -19,7 +19,6 @@
*************************************************************************/
#include <algorithm>
-#include <sstream>
#include "BasicDVIReader.hpp"
using namespace std;
@@ -100,11 +99,8 @@ int BasicDVIReader::evalCommand (CommandHandler &handler, int &param) {
handler = &BasicDVIReader::cmdDir;
num_param_bytes = 1;
}
- else if (opcode > OP_POSTPOST) {
- ostringstream oss;
- oss << "undefined DVI command (opcode " << opcode << ')';
- throw DVIException(oss.str());
- }
+ else if (opcode > OP_POSTPOST)
+ throw DVIException("undefined DVI command (opcode " + to_string(opcode) + ")");
else {
const int offset = opcode < OP_FNTNUM0 ? OP_SET1 : (OP_FNTNUM63+1)-(OP_FNTNUM0-OP_SET1);
handler = commands[opcode-offset].handler;
@@ -194,9 +190,7 @@ void BasicDVIReader::setDVIVersion (DVIVersion version) {
case DVI_XDV7:
break;
default:
- ostringstream oss;
- oss << "DVI version " << _dviVersion << " not supported";
- throw DVIException(oss.str());
+ throw DVIException("DVI version " + to_string(_dviVersion) + " not supported");
}
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp
index ce3c0ac4061..14a1fb9858a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BasicDVIReader.hpp
@@ -51,7 +51,6 @@ class BasicDVIReader : public StreamReader {
public:
explicit BasicDVIReader (std::istream &is);
- virtual ~BasicDVIReader () =default;
virtual void executeAllPages ();
virtual double getXPos () const {return 0;}
virtual double getYPos () const {return 0;}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp
index c98f6331930..d2077bcfebe 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.cpp
@@ -21,11 +21,12 @@
#include <algorithm>
#include <utility>
#include "Bezier.hpp"
+#include "Matrix.hpp"
using namespace std;
Bezier::Bezier () {
- _points[0] = _points[1] = _points[2] = _points[3] = 0;
+ _points[0] = _points[1] = _points[2] = _points[3] = DPair(0);
}
@@ -51,13 +52,13 @@ Bezier::Bezier (const Bezier &source, double t0, double t1) {
if (t0 > t1)
swap(t0, t1);
if (t0 == 0)
- source.subdivide(t1, this, 0);
+ source.subdivide(t1, this, nullptr);
else if (t1 == 1)
- source.subdivide(t0, 0, this);
+ source.subdivide(t0, nullptr, this);
else {
Bezier subcurve;
- source.subdivide(t0, 0, &subcurve);
- subcurve.subdivide((t1-t0)/(1-t0), this, 0);
+ source.subdivide(t0, nullptr, &subcurve);
+ subcurve.subdivide((t1-t0)/(1-t0), this, nullptr);
}
}
}
@@ -230,8 +231,8 @@ static bool solve_quadratic_equation (double a, double b, double c, double &x1,
/** Returns a tight bounding box parallel to the x- and y-axis. */
-void Bezier::getBBox (BoundingBox &bbox) const {
- bbox.invalidate();
+BoundingBox Bezier::getBBox () const {
+ BoundingBox bbox;
// coefficients of the derivative
DPair pa = _points[3] - _points[2]*3.0 + _points[1]*3.0 - _points[0];
DPair pb = (_points[2]-_points[1]*2.0+_points[0])*2.0;
@@ -253,4 +254,12 @@ void Bezier::getBBox (BoundingBox &bbox) const {
}
bbox.embed(_points[0]);
bbox.embed(_points[3]);
+ return bbox;
+}
+
+
+Bezier& Bezier::transform (const Matrix &matrix) {
+ for (int i=0; i < 4; i++)
+ _points[i] = matrix*_points[i];
+ return *this;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp
index 7ba44418ea4..525ef23435b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bezier.hpp
@@ -25,8 +25,9 @@
#include "BoundingBox.hpp"
#include "Pair.hpp"
-class Bezier
-{
+class Matrix;
+
+class Bezier {
public:
Bezier ();
Bezier (const DPair &p0, const DPair &p1, const DPair &p2);
@@ -37,10 +38,11 @@ class Bezier
DPair valueAt (double t) const;
DPair blossomValue (double u, double v, double w) const;
void subdivide (double t, Bezier *bezier1, Bezier *bezier2) const;
- int approximate (double delta, std::vector<DPair> &p, std::vector<double> *t=0) const;
+ Bezier& transform (const Matrix &matrix);
+ int approximate (double delta, std::vector<DPair> &p, std::vector<double> *t=nullptr) const;
const DPair& point (int i) const {return _points[i];}
int reduceDegree (double delta, std::vector<DPair> &p) const;
- void getBBox (BoundingBox &bbox) const;
+ BoundingBox getBBox () const;
protected:
int approximate (double delta, double t0, double t1, std::vector<DPair> &p, std::vector<double> *t) const;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp
index 1512e3fbe7c..10c05fca051 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BgColorSpecialHandler.cpp
@@ -54,7 +54,7 @@ void BgColorSpecialHandler::dviBeginPage (unsigned pageno, SpecialActions &actio
if (_pageColors.empty())
return;
// find number of page with bg color change not lower than the current one
- vector<PageColor>::iterator it = lower_bound(_pageColors.begin(), _pageColors.end(), PageColor(pageno, Color::BLACK));
+ auto it = lower_bound(_pageColors.begin(), _pageColors.end(), PageColor(pageno, Color::BLACK));
if (it != _pageColors.end() && it->first == pageno)
actions.setBgColor(it->second);
else if (it != _pageColors.begin())
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp
index e39ad79c476..3fa554eed42 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.cpp
@@ -25,10 +25,6 @@
using namespace std;
-Bitmap::Bitmap () : _rows(0), _cols(0), _xshift(0), _yshift(0), _bpr(0), _bytes(0)
-{
-}
-
/** Constructs a Bitmap */
Bitmap::Bitmap (int minx, int maxx, int miny , int maxy) {
@@ -48,8 +44,7 @@ void Bitmap::resize (int minx, int maxx, int miny , int maxy) {
_yshift = miny;
_bpr = _cols/8 + (_cols % 8 ? 1 : 0); // bytes per row
_bytes.resize(_rows*_bpr);
- for (uint8_t &byte : _bytes)
- byte = 0;
+ std::fill(_bytes.begin(), _bytes.end(), 0);
}
@@ -69,7 +64,7 @@ void Bitmap::setBits (int row, int col, int n) {
int m = min(n, b+1); // number of bits to be set in current byte
int bitseq = (1 << m)-1; // sequence of n set bits (bits 0..n-1 are set)
bitseq <<= b-m+1; // move bit sequence so that bit b is the leftmost set bit
- *byte |= uint8_t(bitseq); // apply bit sequence to current byte
+ *byte |= uint8_t(bitseq); // apply bit sequence to current byte
byte++;
n -= m;
col += m;
@@ -90,10 +85,8 @@ void Bitmap::forAllPixels (Callback &data) const {
}
-class BBoxCallback : public Bitmap::Callback
-{
+class BBoxCallback : public Bitmap::Callback {
public:
- BBoxCallback () : _changed(false), _minx(numeric_limits<int>::max()), _miny(_minx), _maxx(0), _maxy(0) {}
int minx () const {return _minx;}
int miny () const {return _miny;}
int maxx () const {return _maxx;}
@@ -116,8 +109,9 @@ class BBoxCallback : public Bitmap::Callback
}
private:
- bool _changed;
- int _minx, _miny, _maxx, _maxy;
+ bool _changed = false;
+ int _minx = numeric_limits<int>::max(), _miny=_minx;
+ int _maxx = 0, _maxy = 0;
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp
index fe9f31f0536..026edae9a21 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Bitmap.hpp
@@ -25,8 +25,7 @@
#include <vector>
-class Bitmap
-{
+class Bitmap {
public:
struct Callback {
virtual ~Callback() =default;
@@ -36,7 +35,7 @@ class Bitmap
};
public:
- Bitmap ();
+ Bitmap () =default;
Bitmap (int minx, int maxx, int miny , int maxy);
void resize (int minx, int maxx, int miny , int maxy);
void setBits(int row, int col, int n);
@@ -60,9 +59,9 @@ class Bitmap
// std::ostream& write (std::ostream &os) const;
private:
- int _rows, _cols; ///< number of rows, columns
- int _xshift, _yshift; ///< horizontal/vertical shift
- int _bpr; ///< number of bytes per row
+ int _rows=0, _cols=0; ///< number of rows, columns
+ int _xshift=0, _yshift=0; ///< horizontal/vertical shift
+ int _bpr=0; ///< number of bytes per row
std::vector<uint8_t> _bytes;
};
@@ -81,7 +80,7 @@ int Bitmap::copy (std::vector<T> &target, bool vflip) const {
int targetrow = vflip ? _rows-r-1 : r;
for (int b=0; b < _bpr; b++) {
T &t = target[targetrow*tpr + b/s];
- T chunk = (T)_bytes[r*_bpr+b] << (8*(s-1-b%s));
+ T chunk = static_cast<T>(_bytes[r*_bpr+b]) << (8*(s-1-b%s));
if (b % s == 0)
t = chunk;
else
@@ -107,5 +106,4 @@ void Bitmap::write (std::ostream &os, const std::vector<T> &v) const {
}
}*/
-
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp
index 968a1517526..a076b523639 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.cpp
@@ -74,7 +74,7 @@ vector<Length> BoundingBox::extractLengths (string boxstr) {
boxstr = util::replace(boxstr, ",", " ");
boxstr = util::normalize_space(boxstr);
vector<string> lengthStrings = util::split(boxstr, " ");
- for (string lenstr : lengthStrings) {
+ for (const string &lenstr : lengthStrings) {
if (!lenstr.empty())
lengths.emplace_back(Length(lenstr));
}
@@ -263,8 +263,8 @@ ostream& BoundingBox::write (ostream &os) const {
}
-unique_ptr<XMLElementNode> BoundingBox::createSVGRect () const {
- auto rect = util::make_unique<XMLElementNode>("rect");
+unique_ptr<XMLElement> BoundingBox::createSVGRect () const {
+ auto rect = util::make_unique<XMLElement>("rect");
rect->addAttribute("x", minX());
rect->addAttribute("y", minY());
rect->addAttribute("width", width());
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp
index 3ff775d02bf..8848f60f288 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/BoundingBox.hpp
@@ -31,11 +31,11 @@
class Matrix;
-class XMLElementNode;
+class XMLElement;
struct BoundingBoxException : MessageException {
- BoundingBoxException (const std::string &msg) : MessageException(msg) {}
+ explicit BoundingBoxException (const std::string &msg) : MessageException(msg) {}
};
@@ -45,7 +45,7 @@ class BoundingBox {
BoundingBox (double ulxx, double ulyy, double lrxx, double lryy);
BoundingBox (const DPair &p1, const DPair &p2);
BoundingBox (const Length &ulxx, const Length &ulyy, const Length &lrxx, const Length &lryy);
- BoundingBox (const std::string &boxstr);
+ explicit BoundingBox (const std::string &boxstr);
void set (const std::string &boxstr);
void set (const std::vector<Length> &lengths);
void embed (double x, double y);
@@ -78,7 +78,7 @@ class BoundingBox {
void transform (const Matrix &tm);
std::string toSVGViewBox () const;
std::ostream& write (std::ostream &os) const;
- std::unique_ptr<XMLElementNode> createSVGRect () const;
+ std::unique_ptr<XMLElement> createSVGRect () const;
private:
double _ulx, _uly; ///< coordinates of upper left vertex (in PS point units)
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp
index 9b399a2b021..2b0c1b5359e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.cpp
@@ -39,7 +39,7 @@ void CommandLine::parse (int argc, char **argv) {
for (int i=1; i < argc; i++) {
istringstream iss(argv[i]);
if (filesOnly || iss.peek() != '-')
- _files.push_back(argv[i]);
+ _files.emplace_back(argv[i]);
else {
iss.get(); // skip dash
if (iss.peek() < 0)
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp
index e012b21a4c9..a80d9b87d75 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CLCommandLine.hpp
@@ -37,7 +37,7 @@ class CommandLine {
virtual ~CommandLine () =default;
void parse (int argc, char **argv);
void help (std::ostream &os, int mode=0) const;
- void addFilename (std::string fname) {_files.emplace_back(fname);}
+ void addFilename (const std::string &fname) {_files.emplace_back(fname);}
bool singleDashGiven () const {return _singleDashParsed;}
const std::vector<std::string>& filenames () const {return _files;}
@@ -60,7 +60,7 @@ class CommandLine {
struct CommandLineException : public MessageException {
- CommandLineException (const std::string &msg) : MessageException(msg) {}
+ explicit CommandLineException (const std::string &msg) : MessageException(msg) {}
};
} // namespace CL
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp
index 22b16dced0a..0f0259e8538 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMap.hpp
@@ -28,9 +28,7 @@
#include "RangeMap.hpp"
-struct CMap : public NamedFontEncoding
-{
- virtual ~CMap () =default;
+struct CMap : public NamedFontEncoding {
virtual bool vertical () const =0;
virtual bool mapsToCID () const =0;
virtual uint32_t cid (uint32_t c) const =0;
@@ -48,8 +46,7 @@ struct CMap : public NamedFontEncoding
};
-struct IdentityCMap : public CMap
-{
+struct IdentityCMap : public CMap {
uint32_t cid (uint32_t c) const override {return c;}
uint32_t bfcode (uint32_t cid) const override {return 0;}
std::string getROString () const override {return "Adobe-Identity";}
@@ -57,38 +54,34 @@ struct IdentityCMap : public CMap
};
-struct IdentityHCMap : public IdentityCMap
-{
+struct IdentityHCMap : public IdentityCMap {
bool vertical () const override {return false;}
const char* name () const override {return "Identity-H";}
};
-struct IdentityVCMap : public IdentityCMap
-{
+struct IdentityVCMap : public IdentityCMap {
bool vertical () const override {return true;}
const char* name () const override {return "Identity-V";}
};
-struct UnicodeCMap : public CMap
-{
+struct UnicodeCMap : public CMap {
bool vertical () const override {return false;}
const char* name () const override {return "unicode";}
bool mapsToCID () const override {return false;}
- const char* path () const override {return 0;}
+ const char* path () const override {return nullptr;}
uint32_t cid (uint32_t c) const override {return c;}
uint32_t bfcode (uint32_t cid) const override {return cid;}
std::string getROString () const override {return "";}
};
-class SegmentedCMap : public CMap
-{
+class SegmentedCMap : public CMap {
friend class CMapReader;
public:
- SegmentedCMap (const std::string &fname) : _filename(fname), _basemap(0), _vertical(false), _mapsToCID(true) {}
+ explicit SegmentedCMap (std::string fname) : _filename(std::move(fname)) {}
const char* name () const override {return _filename.c_str();}
uint32_t cid (uint32_t c) const override;
uint32_t bfcode (uint32_t cid) const override;
@@ -105,9 +98,9 @@ class SegmentedCMap : public CMap
std::string _filename;
std::string _registry;
std::string _ordering;
- CMap *_basemap;
- bool _vertical;
- bool _mapsToCID; // true: chrcode->CID, false: CID->charcode
+ CMap *_basemap = nullptr;
+ bool _vertical = false;
+ bool _mapsToCID = true; // true: chrcode->CID, false: CID->charcode
RangeMap _cidranges;
RangeMap _bfranges;
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp
index f033da7efc0..779c6ee3a83 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapManager.cpp
@@ -44,9 +44,7 @@ CMap* CMapManager::lookup (const string &name) {
if (_includedCMaps.find(name) != _includedCMaps.end()) {
_level = 0;
- ostringstream oss;
- oss << "circular reference of CMap " << name;
- throw CMapReaderException(oss.str());
+ throw CMapReaderException("circular reference of CMap " + name);
}
unique_ptr<CMap> cmap_ptr;
@@ -124,8 +122,8 @@ const CMap* CMapManager::findCompatibleBaseFontMap (const PhysicalFont *font, co
const bool is_unicode_map = bool(dynamic_cast<const UnicodeCMap*>(cmap));
const string ro = cmap->getROString();
for (const CharMapIDToEncName &enc : encodings) {
- for (size_t i=0; i < charmapIDs.size(); i++) {
- if (enc.id == charmapIDs[i]) {
+ for (const CharMapID &id : charmapIDs) {
+ if (enc.id == id) {
string cmapname = ro+"-"+enc.encname;
if (is_unicode_map || FileFinder::instance().lookup(cmapname, "cmap", false)) {
charmapID = enc.id;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp
index 35f31d78d64..6661afbbb10 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.cpp
@@ -32,10 +32,6 @@
using namespace std;
-CMapReader::CMapReader () : _inCMap(false) {
-}
-
-
/** Reads a cmap file and returns the corresponding CMap object.
* @param fname[in] name/path of cmap file
* @return CMap object representing the read data, or 0 if file could not be read */
@@ -74,7 +70,7 @@ unique_ptr<CMap> CMapReader::read (std::istream& is, const string &name) {
}
}
catch (CMapReaderException &e) {
- _cmap.release();
+ _cmap.reset();
throw;
}
return std::move(_cmap);
@@ -89,9 +85,10 @@ void CMapReader::executeOperator (const string &opname, InputReader &ir) {
const char *name;
void (CMapReader::*handler)(InputReader&);
};
- constexpr array<Operator, 6> operators {{
+ constexpr array<Operator, 7> operators {{
{"beginbfchar", &CMapReader::op_beginbfchar},
{"beginbfrange", &CMapReader::op_beginbfrange},
+ {"begincidchar", &CMapReader::op_begincidchar},
{"begincidrange", &CMapReader::op_begincidrange},
{"def", &CMapReader::op_def},
{"endcmap", &CMapReader::op_endcmap},
@@ -135,7 +132,7 @@ void CMapReader::op_usecmap (InputReader &) {
throw CMapReaderException("stack underflow while processing usecmap");
else {
const string name = popToken().strvalue();
- if ((_cmap->_basemap = CMapManager::instance().lookup(name)) == 0)
+ if ((_cmap->_basemap = CMapManager::instance().lookup(name)) == nullptr)
throw CMapReaderException("CMap file '"+name+"' not found");
}
}
@@ -154,17 +151,19 @@ static uint32_t parse_hexentry (InputReader &ir) {
}
-void CMapReader::op_begincidrange (InputReader &ir) {
+void CMapReader::parseCIDChars (InputReader &ir, bool isRange) {
if (!_tokens.empty() && _tokens.back().type() == Token::Type::NUMBER) {
ir.skipSpace();
int num_entries = static_cast<int>(popToken().numvalue());
while (num_entries > 0 && ir.peek() == '<') {
uint32_t first = parse_hexentry(ir);
- uint32_t last = parse_hexentry(ir);
- uint32_t cid;
+ uint32_t last = first;
+ if (isRange)
+ last = parse_hexentry(ir);
ir.skipSpace();
+ uint32_t cid;
if (!ir.parseUInt(cid))
- throw CMapReaderException("invalid range entry (decimal value expected)");
+ throw CMapReaderException("invalid char entry (decimal value expected)");
_cmap->addCIDRange(first, last, cid);
ir.skipSpace();
}
@@ -172,6 +171,16 @@ void CMapReader::op_begincidrange (InputReader &ir) {
}
+void CMapReader::op_begincidchar (InputReader &ir) {
+ parseCIDChars(ir, false);
+}
+
+
+void CMapReader::op_begincidrange (InputReader &ir) {
+ parseCIDChars(ir, true);
+}
+
+
void CMapReader::op_beginbfrange (InputReader &ir) {
if (!_tokens.empty() && _tokens.back().type() == Token::Type::NUMBER) {
ir.skipSpace();
@@ -249,9 +258,7 @@ void CMapReader::Token::scan (InputReader &ir) {
else if (isdigit(ir.peek())) { // number?
double val;
if (ir.parseDouble(val)) {
- ostringstream oss;
- oss << val;
- _value = oss.str();
+ _value = util::to_string(val);
_type = Type::NUMBER;
}
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp
index 4b04156d53d..3e5b841e0cf 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CMapReader.hpp
@@ -38,7 +38,7 @@ class CMapReader {
enum class Type {UNKNOWN, END, DELIM, NUMBER, STRING, NAME, OPERATOR};
public:
- Token (InputReader &ir);
+ explicit Token (InputReader &ir);
void scan (InputReader &ir);
Type type () const {return _type;}
const std::string& strvalue () const {return _value;}
@@ -50,15 +50,16 @@ class CMapReader {
};
public:
- CMapReader ();
std::unique_ptr<CMap> read (const std::string &fname);
std::unique_ptr<CMap> read (std::istream &is, const std::string &name);
protected:
Token popToken () {Token t=_tokens.back(); _tokens.pop_back(); return t;}
void executeOperator (const std::string &op, InputReader &ir);
+ void parseCIDChars (InputReader &ir, bool isRange);
void op_beginbfchar (InputReader &ir);
void op_beginbfrange (InputReader &ir);
+ void op_begincidchar (InputReader &ir);
void op_begincidrange (InputReader &ir);
void op_def (InputReader &ir);
void op_endcmap (InputReader &ir);
@@ -67,13 +68,12 @@ class CMapReader {
private:
std::unique_ptr<SegmentedCMap> _cmap; ///< pointer to CMap being read
std::vector<Token> _tokens; ///< stack of tokens to be processed
- bool _inCMap; ///< operator begincmap has been executed
+ bool _inCMap=false; ///< true if operator begincmap has been executed
};
-
struct CMapReaderException : public MessageException {
- CMapReaderException (const std::string &msg) : MessageException(msg) {}
+ explicit CMapReaderException (const std::string &msg) : MessageException(msg) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.cpp
deleted file mode 100644
index 583b019324e..00000000000
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*************************************************************************
-** CRC32.cpp **
-** **
-** This file is part of dvisvgm -- a fast DVI to SVG converter **
-** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
-** **
-** This program is free software; you can redistribute it and/or **
-** modify it under the terms of the GNU General Public License as **
-** published by the Free Software Foundation; either version 3 of **
-** the License, or (at your option) any later version. **
-** **
-** This program is distributed in the hope that it will be useful, but **
-** WITHOUT ANY WARRANTY; without even the implied warranty of **
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
-** GNU General Public License for more details. **
-** **
-** You should have received a copy of the GNU General Public License **
-** along with this program; if not, see <http://www.gnu.org/licenses/>. **
-*************************************************************************/
-
-#include <cstring>
-#include "CRC32.hpp"
-
-using namespace std;
-
-
-CRC32::CRC32 () : _crc32(0xFFFFFFFF)
-{
- const uint32_t poly = 0xEDB88320;
- for (int i = 0; i < 256; i++) {
- uint32_t crc=i;
- for (int j=8; j > 0; j--) {
- if (crc & 1)
- crc = (crc >> 1) ^ poly;
- else
- crc >>= 1;
- }
- _tab[i] = crc;
- }
-}
-
-
-/** Resets CRC32 sum to 0. */
-void CRC32::reset () {
- _crc32 = 0xFFFFFFFF;
-}
-
-
-/** Appends string bytes to the previous data and computes the resulting checksum.
- * @param[in] data string to update the checksum with */
-void CRC32::update (const char *data) {
- update((const uint8_t*)data, strlen(data));
-}
-
-
-/** Appends a single value to the previous data and computes the resulting checksum.
- * @param[in] n value to update the checksum with
- * @param[in] bytes number of bytes to consider (0-4) */
-void CRC32::update (uint32_t n, int bytes) {
- for (int i=bytes-1; i >= 0; --i) {
- uint8_t byte = uint8_t((n >> (8*i)) & 0xff);
- update(&byte, 1);
- }
-}
-
-
-/** Appends a sequence of bytes to the previous data and computes the resulting checksum.
- * @param[in] bytes pointer to array of bytes
- * @param[in] len number of bytes in array */
-void CRC32::update (const uint8_t *bytes, size_t len) {
- for (size_t i=0; i < len; ++i)
- _crc32 = ((_crc32 >> 8) & 0x00FFFFFF) ^ _tab[(_crc32 ^ *bytes++) & 0xFF];
-}
-
-
-void CRC32::update (istream &is) {
- char buf [4096];
- while (is) {
- is.read(buf, 4096);
- update((uint8_t*)buf, is.gcount());
- }
-}
-
-
-/** Returns the checksum computed from values added with the update functions. */
-uint32_t CRC32::get () const {
- return _crc32 ^ 0xFFFFFFFF;
-}
-
-
-/** Computes the CRC32 checksum of a sequence of bytes.
- * @param[in] bytes pointer to array of bytes
- * @param[in] len number of bytes in array
- * @return CRC32 checksum */
-uint32_t CRC32::compute (const uint8_t *bytes, size_t len) {
- CRC32 crc32;
- crc32.update(bytes, len);
- return crc32.get();
-}
-
-
-/** Computes the CRC32 checksum of a string. */
-uint32_t CRC32::compute (const char *str) {
- return compute((const uint8_t*)str, strlen(str));
-}
-
-
-uint32_t CRC32::compute (istream &is) {
- CRC32 crc32;
- crc32.update(is);
- return crc32.get();
-}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp
index 876e5e07834..f498365e544 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Calculator.hpp
@@ -28,7 +28,7 @@
struct CalculatorException : public MessageException {
- CalculatorException (const std::string &msg) : MessageException(msg) {}
+ explicit CalculatorException (const std::string &msg) : MessageException(msg) {}
};
class Calculator {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp
index befd5ee2eac..e79c64b24fc 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CharMapID.hpp
@@ -25,8 +25,8 @@
/** Represents a character map of a font. */
struct CharMapID {
- CharMapID () : platform_id(0), encoding_id(0) {}
- CharMapID (uint8_t plf_id, uint8_t enc_id) : platform_id(plf_id), encoding_id(enc_id) {}
+ CharMapID () noexcept : platform_id(0), encoding_id(0) {}
+ CharMapID (uint8_t plf_id, uint8_t enc_id) noexcept : platform_id(plf_id), encoding_id(enc_id) {}
bool operator == (const CharMapID &ids) const {
return platform_id == ids.platform_id && encoding_id == ids.encoding_id;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp
index 338a0fb4982..e232401fb80 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Character.hpp
@@ -22,11 +22,10 @@
#define CHARACTER_HPP
-class Character
-{
+class Character {
public:
enum Type {CHRCODE, INDEX, NAME};
- Character (const char *name) : _type(NAME), _name(name) {}
+ explicit Character (const char *name) : _type(NAME), _name(name) {}
Character (Type type, uint32_t val) : _type(type), _number(val) {}
Character (Type type, const Character &c) : _type(type), _number(c.type() != NAME ? c._number : 0) {}
Type type () const {return _type;}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp
index aa6b90b4063..de7e9074abf 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.cpp
@@ -40,7 +40,7 @@ const Color Color::TRANSPARENT(uint32_t(0xff000000));
static inline uint8_t double_to_byte (double v) {
v = max(0.0, min(1.0, v));
- return uint8_t(floor(255*v+0.5));
+ return uint8_t(round(255.0*v));
}
@@ -61,7 +61,7 @@ void Color::setRGB (double r, double g, double b) {
* @return true if color name could be applied properly */
bool Color::setPSName (string name, bool case_sensitive) {
if (name[0] == '#') {
- char *p=0;
+ char *p=nullptr;
_rgb = uint32_t(strtol(name.c_str()+1, &p, 16));
while (isspace(*p))
p++;
@@ -213,7 +213,7 @@ Color Color::operator *= (double c) {
else if (abs(c-trunc(c)) < 0.999) {
uint32_t rgb=0;
for (int i=0; i < 3; i++) {
- rgb |= uint32_t((_rgb & 0xff)*c+0.5) << (8*i);
+ rgb |= lround((_rgb & 0xff)*c) << (8*i);
_rgb >>= 8;
}
_rgb = rgb;
@@ -394,7 +394,7 @@ string Color::svgColorString (bool rgbonly) const {
{0xfffff0, "ivory"},
{0xffffff, "white"}
}};
- ColorName cmppair = {_rgb, 0};
+ ColorName cmppair = {_rgb, nullptr};
auto it = lower_bound(colornames.begin(), colornames.end(), cmppair, [](const ColorName &c1, const ColorName &c2) {
return c1.rgb < c2.rgb;
});
@@ -632,14 +632,14 @@ double Color::deltaE (const Color &c) const {
c.getLab(l2, a2, b2);
const double deltaL = l2-l1;
const double lBar = (l1+l2)/2;
- const double c1 = sqrt(a1*a1 + b1*b1);
- const double c2 = sqrt(a2*a2 + b2*b2);
+ const double c1 = hypot(a1, b1);
+ const double c2 = hypot(a2, b2);
const double cBar = (c1+c2)/2.0;
const double g = (1.0-sqrt(pow(cBar, 7.0)/(pow(cBar, 7.0)+6103515625.0)))/2.0;
const double aa1 = a1*(1.0+g);
const double aa2 = a2*(1.0+g);
- const double cc1 = sqrt(aa1*aa1 + b1*b1);
- const double cc2 = sqrt(aa2*aa2 + b2*b2);
+ const double cc1 = hypot(aa1, b1);
+ const double cc2 = hypot(aa2, b2);
const double ccBar = (cc1+cc2)/2.0;
const double deltaCC = cc2-cc1;
double hh1 = atan2(b1, aa1);
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp
index 27efa3a5988..f522bded55e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Color.hpp
@@ -30,8 +30,7 @@
#undef TRANSPARENT
#endif
-class Color
-{
+class Color {
public:
static bool SUPPRESS_COLOR_NAMES;
static const Color BLACK;
@@ -41,12 +40,12 @@ class Color
enum class ColorSpace {GRAY, RGB, CMYK, LAB};
public:
- Color () : _rgb(0) {}
- Color (uint32_t rgb) : _rgb(rgb) {}
- Color (uint8_t r, uint8_t g, uint8_t b) {setRGB(r,g,b);}
- Color (double r, double g, double b) {setRGB(r,g,b);}
- Color (const std::valarray<double> &rgb) {setRGB(rgb);}
- Color (const std::string &name);
+ Color () noexcept : _rgb(0) {}
+ explicit Color (uint32_t rgb) noexcept : _rgb(rgb) {}
+ Color (uint8_t r, uint8_t g, uint8_t b) noexcept {setRGB(r,g,b);}
+ Color (double r, double g, double b) noexcept {setRGB(r,g,b);}
+ explicit Color (const std::valarray<double> &rgb) noexcept {setRGB(rgb);}
+ explicit Color (const std::string &name);
explicit operator uint32_t () const {return _rgb;}
bool operator == (const Color &c) const {return _rgb == c._rgb;}
bool operator != (const Color &c) const {return _rgb != c._rgb;}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp
index c6a756be17e..4bfd4940039 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ColorSpecialHandler.cpp
@@ -40,10 +40,10 @@ static double read_double (istream &is) {
/** Reads multiple double values from a given stream. The number of
* values read is determined by the size of the result vector.
* @param[in] is stream to be read from
- * @param[out] v the resulting values */
-static void read_doubles (istream &is, vector<double> &v) {
- for (size_t i=0; i < v.size(); i++)
- v[i] = read_double(is);
+ * @param[out] vec the resulting values */
+static void read_doubles (istream &is, vector<double> &vec) {
+ for (double &val : vec)
+ val = read_double(is);
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp
index d60ad44511f..b1f2636040f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/CommandLine.hpp
@@ -35,7 +35,7 @@ class CommandLine : public CL::CommandLine {
Option colornamesOpt {"colornames", '\0', "prefer color names to RGB values if possible"};
Option commentsOpt {"comments", '\0', "add comments with additional information"};
Option epsOpt {"eps", 'E', "convert EPS file to SVG"};
- Option exactOpt {"exact", 'e', "compute exact glyph boxes"};
+ Option exactBboxOpt {"exact-bbox", 'e', "compute exact glyph bounding boxes"};
TypedOption<std::string, Option::ArgMode::REQUIRED> fontFormatOpt {"font-format", 'f', "format", "svg", "select file format of embedded fonts"};
TypedOption<std::string, Option::ArgMode::REQUIRED> fontmapOpt {"fontmap", 'm', "filenames", "evaluate (additional) font map files"};
Option gradOverlapOpt {"grad-overlap", '\0', "create overlapping color gradient segments"};
@@ -52,6 +52,7 @@ class CommandLine : public CL::CommandLine {
Option noMktexmfOpt {"no-mktexmf", '\0', "don't try to create missing fonts"};
TypedOption<std::string, Option::ArgMode::OPTIONAL> noSpecialsOpt {"no-specials", 'S', "prefixes", "don't process [selected] specials"};
Option noStylesOpt {"no-styles", '\0', "don't use CSS styles to reference fonts"};
+ TypedOption<std::string, Option::ArgMode::OPTIONAL> optimizeOpt {"optimize", 'O', "modules", "all", "perform several SVG optimizations"};
TypedOption<std::string, Option::ArgMode::REQUIRED> outputOpt {"output", 'o', "pattern", "set name pattern of output files"};
TypedOption<std::string, Option::ArgMode::REQUIRED> pageOpt {"page", 'p', "ranges", "1", "choose page(s) to convert"};
TypedOption<std::string, Option::ArgMode::OPTIONAL> pageHashesOpt {"page-hashes", 'H', "params", "xxh64", "activate usage of page hashes"};
@@ -114,6 +115,7 @@ class CommandLine : public CL::CommandLine {
{&gradSimplifyOpt, 1},
#endif
{&linkmarkOpt, 1},
+ {&optimizeOpt, 1},
{&outputOpt, 1},
{&precisionOpt, 1},
{&relativeOpt, 1},
@@ -129,7 +131,7 @@ class CommandLine : public CL::CommandLine {
{&transformOpt, 2},
{&zoomOpt, 2},
{&cacheOpt, 3},
- {&exactOpt, 3},
+ {&exactBboxOpt, 3},
{&keepOpt, 3},
#if !defined(HAVE_LIBGS) && !defined(DISABLE_GS)
{&libgsOpt, 3},
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp
index 47839216010..6bfff573e27 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DLLoader.hpp
@@ -33,7 +33,7 @@
class DLLoader {
public:
DLLoader () =delete;
- DLLoader (const std::string &dlname);
+ explicit DLLoader (const std::string &dlname);
DLLoader (DLLoader &&loader) =default;
virtual ~DLLoader () {closeLibrary();}
bool loaded () const {return _handle != nullptr;}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp
index ac57eb25edc..c42f446d9ee 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIActions.hpp
@@ -40,7 +40,7 @@ struct DVIActions {
virtual void beginPage (unsigned pageno, const std::vector<int32_t> &c) {}
virtual void endPage (unsigned pageno) {}
virtual BoundingBox& bbox () =0;
- virtual void progress (size_t current, size_t total, const char *id=0) {}
+ virtual void progress (size_t current, size_t total, const char *id=nullptr) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp
index 415b97dc438..b0bbabee947 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp
@@ -277,7 +277,7 @@ void DVIReader::cmdPop (int) {
* @param[in] font current font (corresponding to _currFontNum)
* @param[in] c character to typeset */
void DVIReader::putVFChar (Font *font, uint32_t c) {
- if (VirtualFont *vf = dynamic_cast<VirtualFont*>(font)) { // is current font a virtual font?
+ if (auto vf = dynamic_cast<VirtualFont*>(font)) { // is current font a virtual font?
if (const vector<uint8_t> *dvi = vf->getDVI(c)) { // try to get DVI snippet that represents character c
FontManager &fm = FontManager::instance();
DVIState savedState = _dviState; // save current cursor position
@@ -457,11 +457,8 @@ void DVIReader::cmdDir (int) {
uint8_t wmode = readUnsigned(1);
if (wmode == 4) // yoko mode (4) equals default LR mode (0)
wmode = 0;
- if (wmode == 2 || wmode > 3) {
- ostringstream oss;
- oss << "invalid writing mode value " << wmode << " (0, 1, 3, or 4 expected)";
- throw DVIException(oss.str());
- }
+ if (wmode == 2 || wmode > 3)
+ throw DVIException("invalid writing mode value " + std::to_string(wmode) + " (0, 1, 3, or 4 expected)");
_dviState.d = (WritingMode)wmode;
dviDir(_dviState.d);
}
@@ -485,11 +482,8 @@ void DVIReader::setFont (int fontnum, SetFontMode mode) {
_currFontNum = fontnum;
dviFontNum(uint32_t(fontnum), mode, font);
}
- else {
- ostringstream oss;
- oss << "undefined font number " << fontnum;
- throw DVIException(oss.str());
- }
+ else
+ throw DVIException("undefined font number " + std::to_string(fontnum));
}
@@ -522,7 +516,7 @@ const Font* DVIReader::defineFont (uint32_t fontnum, const string &name, uint32_
if (!font) {
int id = fm.registerFont(fontnum, name, cs, ds, ss);
font = fm.getFontById(id);
- if (VirtualFont *vf = dynamic_cast<VirtualFont*>(font)) {
+ if (auto vf = dynamic_cast<VirtualFont*>(font)) {
// read vf file, register its font and character definitions
fm.enterVF(vf);
ifstream ifs(vf->path(), ios::binary);
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp
index 82eeb8a7c9f..4801bd80a01 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.cpp
@@ -38,6 +38,7 @@
#include "PageSize.hpp"
#include "PreScanDVIReader.hpp"
#include "SignalHandler.hpp"
+#include "optimizer/SVGOptimizer.hpp"
#include "SVGOutput.hpp"
#include "utility.hpp"
#include "version.hpp"
@@ -110,18 +111,19 @@ void DVIToSVG::convert (unsigned first, unsigned last, HashFunction *hashFunc) {
combinedHash = hashFunc->digestString();
}
const SVGOutput::HashTriple hashTriple(dviHash, shortenedOptHash, combinedHash);
- string fname = _out.filename(i, numberOfPages(), hashTriple);
- if (!dviHash.empty() && !PAGE_HASH_SETTINGS.isSet(HashSettings::P_REPLACE) && FileSystem::exists(fname)) {
+ FilePath path = _out.filepath(i, numberOfPages(), hashTriple);
+ if (!dviHash.empty() && !PAGE_HASH_SETTINGS.isSet(HashSettings::P_REPLACE) && path.exists()) {
Message::mstream(false, Message::MC_PAGE_NUMBER) << "skipping page " << i;
Message::mstream().indent(1);
- Message::mstream(false, Message::MC_PAGE_WRITTEN) << "\nfile " << fname << " exists\n";
+ Message::mstream(false, Message::MC_PAGE_WRITTEN) << "\nfile " << path.shorterAbsoluteOrRelative() << " exists\n";
Message::mstream().indent(0);
}
else {
executePage(i);
- _svg.removeRedundantElements();
+ SVGOptimizer(_svg).execute();
embedFonts(_svg.rootNode());
bool success = _svg.write(_out.getPageStream(currentPageNumber(), numberOfPages(), hashTriple));
+ string fname = path.shorterAbsoluteOrRelative();
if (fname.empty())
fname = "<stdout>";
if (success)
@@ -161,7 +163,7 @@ void DVIToSVG::convert (const string &rangestr, pair<int,int> *pageinfo) {
throw MessageException("invalid page range format");
Message::mstream(false, Message::MC_PAGE_NUMBER) << "pre-processing DVI file (format version " << getDVIVersion() << ")\n";
- if (DVIToSVGActions *actions = dynamic_cast<DVIToSVGActions*>(_actions.get())) {
+ if (auto actions = dynamic_cast<DVIToSVGActions*>(_actions.get())) {
PreScanDVIReader prescan(getInputStream(), actions);
actions->setDVIReader(prescan);
prescan.executeAllPages();
@@ -243,7 +245,7 @@ void DVIToSVG::enterBeginPage (unsigned pageno, const vector<int32_t> &c) {
if (pageno != (unsigned)c[0]) // Does page number shown on page differ from physical page number?
Message::mstream(false) << " [" << c[0] << ']';
Message::mstream().indent(1);
- _svg.appendToDoc(util::make_unique<XMLCommentNode>(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " "));
+ _svg.appendToDoc(util::make_unique<XMLComment>(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " "));
}
}
@@ -322,7 +324,7 @@ Matrix DVIToSVG::getPageTransformation () const {
calc.setVariable("h", bbox.height()*bp2pt);
}
// add constants for length units to calculator
- for (auto unit : Length::getUnits())
+ for (const auto &unit : Length::getUnits())
calc.setVariable(unit.first, Length(1, unit.second).pt());
matrix.set(_transCmds, calc);
}
@@ -331,18 +333,22 @@ Matrix DVIToSVG::getPageTransformation () const {
static void collect_chars (unordered_map<const Font*, set<int>> &fontmap) {
+ unordered_map<const Font*, set<int>> insertedChars;
for (const auto &entry : fontmap) {
- if (entry.first->uniqueFont() != entry.first) {
+ const Font *unique_font = entry.first->uniqueFont();
+ if (unique_font != entry.first) {
for (int c : entry.second)
- fontmap[entry.first->uniqueFont()].insert(c);
+ insertedChars[unique_font].insert(c);
}
}
+ for (const auto &entry : insertedChars)
+ fontmap[entry.first].insert(entry.second.begin(), entry.second.end());
}
/** Adds the font information to the SVG tree.
* @param[in] svgElement the font nodes are added to this node */
-void DVIToSVG::embedFonts (XMLElementNode *svgElement) {
+void DVIToSVG::embedFonts (XMLElement *svgElement) {
if (!svgElement || !_actions) // no dvi actions => no chars written => no fonts to embed
return;
@@ -355,7 +361,7 @@ void DVIToSVG::embedFonts (XMLElementNode *svgElement) {
unordered_set<const Font*> tracedFonts; // collect unique fonts already traced
for (const auto &fontchar : usedCharsMap) {
const Font *font = fontchar.first;
- if (const PhysicalFont *ph_font = dynamic_cast<const PhysicalFont*>(font)) {
+ if (auto ph_font = dynamic_cast<const PhysicalFont*>(font)) {
// Check if glyphs should be traced. Only trace the glyphs of unique fonts, i.e.
// avoid retracing the same glyphs again if they are referenced in various sizes.
if (TRACE_MODE != 0 && tracedFonts.find(ph_font->uniqueFont()) == tracedFonts.end()) {
@@ -420,8 +426,8 @@ void DVIToSVG::setProcessSpecials (const char *ignorelist, bool pswarning) {
}
-string DVIToSVG::getSVGFilename (unsigned pageno) const {
- return _out.filename(pageno, numberOfPages());
+FilePath DVIToSVG::getSVGFilePath (unsigned pageno) const {
+ return _out.filepath(pageno, numberOfPages());
}
@@ -567,6 +573,15 @@ void DVIToSVG::HashSettings::setParameters (const string &paramstr) {
_params.insert(it->second);
else if (_algo.empty() && HashFunction::isSupportedAlgorithm(name))
_algo = name;
+ else if (!name.empty()) {
+ string msg = "invalid hash parameter '"+name+"' (supported algorithms: ";
+ for (string str : HashFunction::supportedAlgorithms())
+ msg += str + ", ";
+ msg.pop_back();
+ msg.pop_back();
+ msg += ')';
+ throw MessageException(msg);
+ }
}
// set default hash algorithm if none is given
if (_algo.empty())
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp
index b738239408e..40dbdc884ff 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVG.hpp
@@ -25,6 +25,7 @@
#include <string>
#include <utility>
#include "DVIReader.hpp"
+#include "FilePath.hpp"
#include "SVGTree.hpp"
struct DVIActions;
@@ -50,7 +51,8 @@ class DVIToSVG : public DVIReader {
public:
explicit DVIToSVG (std::istream &is, SVGOutputBase &out);
- void convert (const std::string &range, std::pair<int,int> *pageinfo=0);
+ DVIToSVG (const DVIToSVG&) =delete;
+ void convert (const std::string &range, std::pair<int,int> *pageinfo=nullptr);
void setPageSize (const std::string &format) {_bboxFormatString = format;}
void setPageTransformation (const std::string &cmds) {_transCmds = cmds;}
Matrix getPageTransformation () const override;
@@ -61,9 +63,9 @@ class DVIToSVG : public DVIReader {
void finishLine () override {_prevYPos = std::numeric_limits<double>::min();}
void listHashes (const std::string &rangestr, std::ostream &os);
- std::string getSVGFilename (unsigned pageno) const;
+ FilePath getSVGFilePath (unsigned pageno) const;
std::string getUserBBoxString () const {return _bboxFormatString;}
- static void setProcessSpecials (const char *ignorelist=0, bool pswarning=false);
+ static void setProcessSpecials (const char *ignorelist=nullptr, bool pswarning=false);
public:
static bool COMPUTE_PROGRESS; ///< if true, an action to handle the progress ratio of a page is triggered
@@ -71,12 +73,11 @@ class DVIToSVG : public DVIReader {
static HashSettings PAGE_HASH_SETTINGS;
protected:
- DVIToSVG (const DVIToSVG&) =delete;
void convert (unsigned firstPage, unsigned lastPage, HashFunction *hashFunc);
int executeCommand () override;
void enterBeginPage (unsigned pageno, const std::vector<int32_t> &c);
void leaveEndPage (unsigned pageno);
- void embedFonts (XMLElementNode *svgElement);
+ void embedFonts (XMLElement *svgElement);
void moveRight (double dx, MoveMode mode) override;
void moveDown (double dy, MoveMode mode) override;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp
index 226d434bae5..bb8e4d6f845 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.cpp
@@ -32,14 +32,6 @@
using namespace std;
-DVIToSVGActions::DVIToSVGActions (DVIToSVG &dvisvg, SVGTree &svg)
- : _svg(svg), _dvireader(&dvisvg), _bgcolor(Color::TRANSPARENT)
-{
- _currentFontNum = -1;
- _pageCount = 0;
-}
-
-
void DVIToSVGActions::reset() {
_usedChars.clear();
_usedFonts.clear();
@@ -69,17 +61,19 @@ void DVIToSVGActions::moveToY (double y, bool forceSVGMove) {
}
-string DVIToSVGActions::getSVGFilename (unsigned pageno) const {
- if (DVIToSVG *dvi2svg = dynamic_cast<DVIToSVG*>(_dvireader))
- return dvi2svg->getSVGFilename(pageno);
- return "";
+FilePath DVIToSVGActions::getSVGFilePath (unsigned pageno) const {
+ FilePath path;
+ if (auto dvi2svg = dynamic_cast<DVIToSVG*>(_dvireader))
+ path = dvi2svg->getSVGFilePath(pageno);
+ return path;
}
string DVIToSVGActions::getBBoxFormatString () const {
- if (DVIToSVG *dvi2svg = dynamic_cast<DVIToSVG*>(_dvireader))
- return dvi2svg->getUserBBoxString();
- return "";
+ string boxstr;
+ if (auto dvi2svg = dynamic_cast<DVIToSVG*>(_dvireader))
+ boxstr = dvi2svg->getUserBBoxString();
+ return boxstr;
}
@@ -91,6 +85,9 @@ string DVIToSVGActions::getBBoxFormatString () const {
* @param[in] vertical true if we're in vertical mode
* @param[in] font font to be used */
void DVIToSVGActions::setChar (double x, double y, unsigned c, bool vertical, const Font &font) {
+ if (_outputLocked)
+ return;
+
// If we use SVG fonts there is no need to record all font name/char/size combinations
// because the SVG font mechanism handles this automatically. It's sufficient to
// record font names and chars. The various font sizes can be ignored here.
@@ -108,7 +105,7 @@ void DVIToSVGActions::setChar (double x, double y, unsigned c, bool vertical, co
GlyphMetrics metrics;
font.getGlyphMetrics(c, vertical, metrics);
- const PhysicalFont* pf = dynamic_cast<const PhysicalFont*>(&font);
+ auto pf = dynamic_cast<const PhysicalFont*>(&font);
if (PhysicalFont::EXACT_BBOX && pf) {
GlyphMetrics exact_metrics;
pf->getExactGlyphBox(c, exact_metrics, vertical, &callback);
@@ -125,7 +122,7 @@ void DVIToSVGActions::setChar (double x, double y, unsigned c, bool vertical, co
bbox.transform(getMatrix());
embed(bbox);
#if 0
- XMLElementNode *rect = new XMLElementNode("rect");
+ XMLElement *rect = new XMLElement("rect");
rect->addAttribute("x", x-metrics.wl);
rect->addAttribute("y", y-metrics.h);
rect->addAttribute("width", metrics.wl+metrics.wr);
@@ -135,7 +132,7 @@ void DVIToSVGActions::setChar (double x, double y, unsigned c, bool vertical, co
rect->addAttribute("stroke-width", "0.5");
_svg.appendToPage(rect);
if (metrics.d > 0) {
- XMLElementNode *line = new XMLElementNode("line");
+ XMLElement *line = new XMLElement("line");
line->addAttribute("x1", x-metrics.wl);
line->addAttribute("y1", y);
line->addAttribute("x2", x+metrics.wr);
@@ -145,7 +142,7 @@ void DVIToSVGActions::setChar (double x, double y, unsigned c, bool vertical, co
_svg.appendToPage(line);
}
if (metrics.wl > 0) {
- XMLElementNode *line = new XMLElementNode("line");
+ XMLElement *line = new XMLElement("line");
line->addAttribute("x1", x);
line->addAttribute("y1", y-metrics.h);
line->addAttribute("x2", x);
@@ -165,14 +162,17 @@ void DVIToSVGActions::setChar (double x, double y, unsigned c, bool vertical, co
* @param[in] height length of the vertical edges
* @param[in] width length of the horizontal edges */
void DVIToSVGActions::setRule (double x, double y, double height, double width) {
+ if (_outputLocked)
+ return;
+
// (x,y) is the lower left corner of the rectangle
- auto rect = util::make_unique<XMLElementNode>("rect");
+ auto rect = util::make_unique<XMLElement>("rect");
rect->addAttribute("x", x);
rect->addAttribute("y", y-height);
rect->addAttribute("height", height);
rect->addAttribute("width", width);
if (!getMatrix().isIdentity())
- rect->addAttribute("transform", getMatrix().getSVG());
+ rect->addAttribute("transform", getMatrix().toSVG());
if (getColor() != Color::BLACK)
rect->addAttribute("fill", _svg.getColor().svgColorString());
_svg.appendToPage(std::move(rect));
@@ -232,7 +232,7 @@ void DVIToSVGActions::endPage (unsigned pageno) {
_svg.transformPage(matrix);
if (_bgcolor != Color::TRANSPARENT) {
// create a rectangle filled with the background color
- auto rect = util::make_unique<XMLElementNode>("rect");
+ auto rect = util::make_unique<XMLElement>("rect");
rect->addAttribute("x", _bbox.minX());
rect->addAttribute("y", _bbox.minY());
rect->addAttribute("width", _bbox.width());
@@ -306,7 +306,7 @@ static int digits (int n) {
void DVIToSVGActions::progress (size_t current, size_t total, const char *id) {
static double time=0;
static bool draw=false; // show progress indicator?
- static const char *prev_id=0;
+ static const char *prev_id=nullptr;
if (current == 0 && total > 0) {
time = System::time();
draw = false;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp
index 04a345865b9..e9adc63e38b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIToSVGActions.hpp
@@ -42,7 +42,7 @@ class DVIToSVGActions : public DVIActions, public SpecialActions {
using BoxMap = std::unordered_map<std::string,BoundingBox>;
public:
- DVIToSVGActions (DVIToSVG &dvisvg, SVGTree &svg);
+ DVIToSVGActions (DVIToSVG &dvisvg, SVGTree &svg) : _svg(svg), _dvireader(&dvisvg) {}
void reset () override;
void setChar (double x, double y, unsigned c, bool vertical, const Font &f) override;
void setRule (double x, double y, double height, double width) override;
@@ -52,32 +52,31 @@ class DVIToSVGActions : public DVIActions, public SpecialActions {
const Matrix& getMatrix () const override {return _svg.getMatrix();}
Matrix getPageTransformation () const override {return _dvireader->getPageTransformation();}
Color getColor () const override {return _svg.getColor();}
- int getDVIStackDepth() const override {return _dvireader->stackDepth();}
- unsigned getCurrentPageNumber() const override {return _dvireader->currentPageNumber();}
- void appendToPage(std::unique_ptr<XMLNode> &&node) override {_svg.appendToPage(std::move(node));}
- void appendToDefs(std::unique_ptr<XMLNode> &&node) override {_svg.appendToDefs(std::move(node));}
- void prependToPage(std::unique_ptr<XMLNode> &&node) override {_svg.prependToPage(std::move(node));}
- void pushContextElement (std::unique_ptr<XMLElementNode> &&node) override {_svg.pushContextElement(std::move(node));}
- void popContextElement () override {_svg.popContextElement();}
- void setTextOrientation(bool vertical) override {_svg.setVertical(vertical);}
+ int getDVIStackDepth () const override {return _dvireader->stackDepth();}
+ unsigned getCurrentPageNumber () const override {return _dvireader->currentPageNumber();}
+ void setTextOrientation (bool vertical) override {_svg.setVertical(vertical);}
void moveToX (double x, bool forceSVGMove) override;
void moveToY (double y, bool forceSVGMove) override;
void setFont (int num, const Font &font) override;
void special (const std::string &spc, double dvi2bp, bool preprocessing=false) override;
void beginPage (unsigned pageno, const std::vector<int32_t> &c) override;
void endPage (unsigned pageno) override;
- void progress (size_t current, size_t total, const char *id=0) override;
+ void progress (size_t current, size_t total, const char *id=nullptr) override;
void progress (const char *id) override;
double getX() const override {return _dvireader->getXPos();}
double getY() const override {return _dvireader->getYPos();}
void setX (double x) override {_dvireader->translateToX(x); _svg.setX(x);}
void setY (double y) override {_dvireader->translateToY(y); _svg.setY(y);}
void finishLine () override {_dvireader->finishLine();}
+ void lockOutput () override {_outputLocked = true;}
+ void unlockOutput () override {_outputLocked = false;}
+ bool outputLocked () const override {return _outputLocked;}
+ const SVGTree& svgTree () const override {return _svg;}
BoundingBox& bbox () override {return _bbox;}
BoundingBox& bbox (const std::string &name, bool reset=false) override;
void embed (const BoundingBox &bbox) override;
void embed (const DPair &p, double r=0) override;
- std::string getSVGFilename (unsigned pageno) const override;
+ FilePath getSVGFilePath (unsigned pageno) const override;
std::string getBBoxFormatString () const override;
CharMap& getUsedChars () const {return _usedChars;}
const FontSet& getUsedFonts () const {return _usedFonts;}
@@ -87,12 +86,13 @@ class DVIToSVGActions : public DVIActions, public SpecialActions {
SVGTree &_svg;
BasicDVIReader *_dvireader;
BoundingBox _bbox;
- int _pageCount;
- int _currentFontNum;
+ int _pageCount=0;
+ int _currentFontNum=-1;
mutable CharMap _usedChars;
FontSet _usedFonts;
- Color _bgcolor;
+ Color _bgcolor=Color::TRANSPARENT;
BoxMap _boxes;
+ bool _outputLocked=false;
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp
index beb6f887da6..ccc05a2e92c 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.cpp
@@ -25,7 +25,7 @@ using namespace std;
#ifdef _WIN32
#include "windows.hpp"
#else
- #include <errno.h>
+ #include <cerrno>
#include <sys/stat.h>
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp
index ade36daf80d..a703c18977c 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Directory.hpp
@@ -34,7 +34,7 @@ class Directory {
public:
Directory ();
- Directory (const std::string &path);
+ explicit Directory (const std::string &path);
~Directory ();
bool open (std::string path);
void close ();
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp
index 23e9b7107c7..dadf196f779 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.cpp
@@ -26,6 +26,7 @@
#include "InputReader.hpp"
#include "Length.hpp"
#include "SpecialActions.hpp"
+#include "SVGTree.hpp"
#include "utility.hpp"
#include "XMLNode.hpp"
#include "XMLString.hpp"
@@ -33,8 +34,10 @@
using namespace std;
-DvisvgmSpecialHandler::DvisvgmSpecialHandler ()
- : _currentMacro(_macros.end()), _nestingLevel(0)
+DvisvgmSpecialHandler::DvisvgmSpecialHandler () :
+ _currentMacro(_macros.end()),
+ _defsParser(&SVGTree::appendToDefs, &SVGTree::pushDefsContext, &SVGTree::popDefsContext),
+ _pageParser(&SVGTree::appendToPage, &SVGTree::pushPageContext, &SVGTree::popPageContext)
{
}
@@ -54,12 +57,12 @@ void DvisvgmSpecialHandler::preprocess (const string&, istream &is, SpecialActio
StreamInputReader ir(is);
const string cmdstr = ir.getWord();
- for (const Command &command : commands) {
- if (command.name == cmdstr) {
- ir.skipSpace();
- (this->*command.handler)(ir);
- return;
- }
+ auto it = find_if(commands.begin(), commands.end(), [&](const Command &cmd) {
+ return cmd.name == cmdstr;
+ });
+ if (it != commands.end()) {
+ ir.skipSpace();
+ (this->*it->handler)(ir);
}
}
@@ -133,12 +136,12 @@ bool DvisvgmSpecialHandler::process (const string &prefix, istream &is, SpecialA
}};
StreamInputReader ir(is);
const string cmdstr = ir.getWord();
- for (const Command &command : commands) {
- if (command.name == cmdstr) {
- ir.skipSpace();
- (this->*command.handler)(ir, actions);
- return true;
- }
+ auto it = find_if(commands.begin(), commands.end(), [&](const Command &cmd) {
+ return cmd.name == cmdstr;
+ });
+ if (it != commands.end()) {
+ ir.skipSpace();
+ (this->*it->handler)(ir, actions);
}
return true;
}
@@ -169,10 +172,11 @@ static void expand_constants (string &str, SpecialActions &actions) {
const char *name;
string val;
};
- const array<Constant, 4> constants {{
- {"x", XMLString(actions.getX())},
- {"y", XMLString(actions.getY())},
- {"color", actions.getColor().svgColorString()},
+ const array<Constant, 5> constants {{
+ {"x", XMLString(actions.getX())},
+ {"y", XMLString(actions.getY())},
+ {"color", actions.getColor().svgColorString()},
+ {"matrix", actions.getMatrix().toSVG()},
{"nl", "\n"},
}};
for (const Constant &constant : constants) {
@@ -186,12 +190,17 @@ static void expand_constants (string &str, SpecialActions &actions) {
}
+/** Processes raw SVG fragments from the input stream. The SVG data must represent
+ * a single or multiple syntactically complete XML parts, like opening/closing tags,
+ * comments, or CDATA blocks. These must not be split and distributed over several
+ * 'raw' statements. Elements can be split but element tags can't.
+ * Example: "<g transform=" is invalid, "<g transform='scale(2,3)'>" is ok. */
void DvisvgmSpecialHandler::processRaw (InputReader &ir, SpecialActions &actions) {
if (_nestingLevel == 0) {
- string str = ir.getLine();
- if (!str.empty()) {
- expand_constants(str, actions);
- actions.appendToPage(util::make_unique<XMLTextNode>(str));
+ string xml = ir.getLine();
+ if (!xml.empty()) {
+ expand_constants(xml, actions);
+ _pageParser.parse(xml, actions);
}
}
}
@@ -199,10 +208,10 @@ void DvisvgmSpecialHandler::processRaw (InputReader &ir, SpecialActions &actions
void DvisvgmSpecialHandler::processRawDef (InputReader &ir, SpecialActions &actions) {
if (_nestingLevel == 0) {
- string str = ir.getLine();
- if (!str.empty()) {
- expand_constants(str, actions);
- actions.appendToDefs(util::make_unique<XMLTextNode>(str));
+ string xml = ir.getLine();
+ if (!xml.empty()) {
+ expand_constants(xml, actions);
+ _defsParser.parse(xml, actions);
}
}
}
@@ -234,9 +243,9 @@ void DvisvgmSpecialHandler::processRawPut (InputReader &ir, SpecialActions &acti
if ((type == 'P' || type == 'D') && !def.empty()) {
expand_constants(def, actions);
if (type == 'P')
- actions.appendToPage(util::make_unique<XMLTextNode>(def));
+ _pageParser.parse(def, actions);
else { // type == 'D'
- actions.appendToDefs(util::make_unique<XMLTextNode>(def));
+ _defsParser.parse(def, actions);
type = 'L'; // locked
}
}
@@ -249,70 +258,92 @@ void DvisvgmSpecialHandler::processRawPut (InputReader &ir, SpecialActions &acti
* @param[in] w width of the rectangle in PS point units
* @param[in] h height of the rectangle in PS point units
* @param[in] d depth of the rectangle in PS point units
+ * @param[in] transform if true, apply the current transformation matrix to the rectangle
* @param[in] actions object providing the actions that can be performed by the SpecialHandler */
-static void update_bbox (Length w, Length h, Length d, SpecialActions &actions) {
+static void update_bbox (Length w, Length h, Length d, bool transform, SpecialActions &actions) {
double x = actions.getX();
double y = actions.getY();
- actions.embed(BoundingBox(x, y, x+w.bp(), y-h.bp()));
- actions.embed(BoundingBox(x, y, x+w.bp(), y+d.bp()));
+ BoundingBox bbox1(x, y, x+w.bp(), y-h.bp());
+ BoundingBox bbox2(x, y, x+w.bp(), y+d.bp());
+ if (transform) {
+ bbox1.transform(actions.getMatrix());
+ bbox2.transform(actions.getMatrix());
+ }
+ actions.embed(bbox1);
+ actions.embed(bbox2);
}
/** Reads a length value including a trailing unit specifier and returns it. */
static Length read_length (InputReader &ir) {
+ Length length;
ir.skipSpace();
- double val = ir.getDouble();
- string unit = isalpha(ir.peek()) ? ir.getString(2) : "pt";
- return Length(val, unit);
+ if (!isalpha(ir.peek())) {
+ double val = ir.getDouble();
+ string unit = isalpha(ir.peek()) ? ir.getString(2) : "pt";
+ length = Length(val, unit);
+ }
+ return length;
}
/** Evaluates the special dvisvgm:bbox.
- * variant 1: dvisvgm:bbox [r[el]] <width> <height> [<depth>]
- * variant 2: dvisvgm:bbox a[bs] <x1> <y1> <x2> <y2>
- * variant 3: dvisvgm:bbox f[ix] <x1> <y1> <x2> <y2>
- * variant 4: dvisvgm:bbox n[ew] <name> */
+ * variant 1: dvisvgm:bbox [r[el]] <width> <height> [<depth>] [transform]
+ * variant 2: dvisvgm:bbox a[bs] <x1> <y1> <x2> <y2> [transform]
+ * variant 3: dvisvgm:bbox f[ix] <x1> <y1> <x2> <y2> [transform]
+ * variant 4: dvisvgm:bbox n[ew] <name>
+ * variant 5: dvisvgm:bbox lock | unlock */
void DvisvgmSpecialHandler::processBBox (InputReader &ir, SpecialActions &actions) {
ir.skipSpace();
- int c = ir.peek();
- try {
- if (!isalpha(c))
- c = 'r'; // no mode specifier => relative box parameters
- else {
- while (!isspace(ir.peek())) // skip trailing characters
- ir.get();
- if (c == 'n') { // "new": create new local bounding box
- ir.skipSpace();
- string name;
- while (isalnum(ir.peek()))
- name += char(ir.get());
- ir.skipSpace();
- if (!name.empty() && ir.eof())
- actions.bbox(name, true); // create new user box
- }
- else if (c == 'a' || c == 'f') { // "abs" or "fix"
- Length lengths[4];
- for (int i=0; i < 4; i++)
- lengths[i] = read_length(ir);
- BoundingBox b(lengths[0], lengths[1], lengths[2], lengths[3]);
- if (c == 'a')
- actions.embed(b);
- else {
- actions.bbox() = b;
- actions.bbox().lock();
+ if (ir.check("lock"))
+ actions.bbox().lock();
+ else if (ir.check("unlock"))
+ actions.bbox().unlock();
+ else {
+ int c = ir.peek();
+ try {
+ if (!isalpha(c))
+ c = 'r'; // no mode specifier => relative box parameters
+ else {
+ while (!isspace(ir.peek())) // skip trailing characters
+ ir.get();
+ if (c == 'n') { // "new": create new local bounding box
+ ir.skipSpace();
+ string name;
+ while (isalnum(ir.peek()))
+ name += char(ir.get());
+ ir.skipSpace();
+ if (!name.empty() && ir.eof())
+ actions.bbox(name, true); // create new user box
}
+ else if (c == 'a' || c == 'f') { // "abs" or "fix"
+ Length lengths[4];
+ for (Length &len : lengths)
+ len = read_length(ir);
+ BoundingBox b(lengths[0], lengths[1], lengths[2], lengths[3]);
+ ir.skipSpace();
+ if (ir.check("transform"))
+ b.transform(actions.getMatrix());
+ if (c == 'a')
+ actions.embed(b);
+ else {
+ actions.bbox() = b;
+ actions.bbox().lock();
+ }
+ }
+ }
+ if (c == 'r') {
+ Length w = read_length(ir);
+ Length h = read_length(ir);
+ Length d = read_length(ir);
+ ir.skipSpace();
+ update_bbox(w, h, d, ir.check("transform"), actions);
}
}
- if (c == 'r') {
- Length w = read_length(ir);
- Length h = read_length(ir);
- Length d = read_length(ir);
- update_bbox(w, h, d, actions);
+ catch (const UnitException &e) {
+ throw SpecialException(string("dvisvgm:bbox: ") + e.what());
}
}
- catch (const UnitException &e) {
- throw SpecialException(string("dvisvgm:bbox: ") + e.what());
- }
}
@@ -321,16 +352,16 @@ void DvisvgmSpecialHandler::processImg (InputReader &ir, SpecialActions &actions
Length w = read_length(ir);
Length h = read_length(ir);
string f = ir.getString();
- update_bbox(w, h, 0, actions);
- auto img = util::make_unique<XMLElementNode>("image");
+ update_bbox(w, h, Length(0), false, actions);
+ auto img = util::make_unique<XMLElement>("image");
img->addAttribute("x", actions.getX());
img->addAttribute("y", actions.getY());
img->addAttribute("width", w.bp());
img->addAttribute("height", h.bp());
img->addAttribute("xlink:href", f);
if (!actions.getMatrix().isIdentity())
- img->addAttribute("transform", actions.getMatrix().getSVG());
- actions.appendToPage(std::move(img));
+ img->addAttribute("transform", actions.getMatrix().toSVG());
+ actions.svgTree().appendToPage(std::move(img));
}
catch (const UnitException &e) {
throw SpecialException(string("dvisvgm:img: ") + e.what());
@@ -350,7 +381,10 @@ void DvisvgmSpecialHandler::dviPreprocessingFinished () {
}
-void DvisvgmSpecialHandler::dviEndPage (unsigned, SpecialActions&) {
+void DvisvgmSpecialHandler::dviEndPage (unsigned, SpecialActions &actions) {
+ _defsParser.flush(actions);
+ _pageParser.flush(actions);
+ actions.bbox().unlock();
for (auto &strvecpair : _macros) {
StringVector &vec = strvecpair.second;
for (string &str : vec) {
@@ -366,3 +400,140 @@ vector<const char*> DvisvgmSpecialHandler::prefixes() const {
vector<const char*> pfx {"dvisvgm:"};
return pfx;
}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/** Parses a fragment of XML code, creates corresponding XML nodes and adds them
+ * to the SVG tree. The code may be split and processed by several calls of this
+ * function. Incomplete chunks that can't be processed yet are stored and picked
+ * up again together with the next incoming XML fragment. If no further code should
+ * be appended, parameter 'finish' must be set.
+ * @param[in] xml XML fragment to parse
+ * @param[in] actions object providing the SVG tree functions
+ * @param[in] finish if true, no more XML is expected and parsing is finished */
+void DvisvgmSpecialHandler::XMLParser::parse (const string &xml, SpecialActions &actions, bool finish) {
+ // collect/extract an XML fragment that only contains complete tags
+ // incomplete tags are held back
+ _xmlbuf += xml;
+ size_t left=0, right;
+ while (left != string::npos) {
+ right = _xmlbuf.find('<', left);
+ if (left < right && left < _xmlbuf.length()) // plain text found?
+ (actions.svgTree().*_append)(util::make_unique<XMLText>(_xmlbuf.substr(left, right-left)));
+ if (right != string::npos) {
+ left = right;
+ if (_xmlbuf.compare(left, 9, "<![CDATA[") == 0) {
+ right = _xmlbuf.find("]]>", left+9);
+ if (right == string::npos) {
+ if (finish) throw SpecialException("expected ']]>' at end of CDATA block");
+ break;
+ }
+ (actions.svgTree().*_append)(util::make_unique<XMLCData>(_xmlbuf.substr(left+9, right-left-9)));
+ right += 2;
+ }
+ else if (_xmlbuf.compare(left, 4, "<!--") == 0) {
+ right = _xmlbuf.find("-->", left+4);
+ if (right == string::npos) {
+ if (finish) throw SpecialException("expected '-->' at end of comment");
+ break;
+ }
+ (actions.svgTree().*_append)(util::make_unique<XMLComment>(_xmlbuf.substr(left+4, right-left-4)));
+ right += 2;
+ }
+ else if (_xmlbuf.compare(left, 2, "<?") == 0) {
+ right = _xmlbuf.find("?>", left+2);
+ if (right == string::npos) {
+ if (finish) throw SpecialException("expected '?>' at end of processing instruction");
+ break;
+ }
+ (actions.svgTree().*_append)(util::make_unique<XMLText>(_xmlbuf.substr(left, right-left+2)));
+ right++;
+ }
+ else if (_xmlbuf.compare(left, 2, "</") == 0) {
+ right = _xmlbuf.find('>', left+2);
+ if (right == string::npos) {
+ if (finish) throw SpecialException("missing '>' at end of closing XML tag");
+ break;
+ }
+ closeElement(_xmlbuf.substr(left+2, right-left-2), actions);
+ }
+ else {
+ right = _xmlbuf.find('>', left+1);
+ if (right == string::npos) {
+ if (finish) throw SpecialException("missing '>' or '/>' at end of opening XML tag");
+ break;
+ }
+ openElement(_xmlbuf.substr(left+1, right-left-1), actions);
+ }
+ }
+ left = right;
+ if (right != string::npos)
+ left++;
+ }
+ if (left == string::npos)
+ _xmlbuf.clear();
+ else
+ _xmlbuf.erase(0, left);
+}
+
+
+/** Processes an opening element tag.
+ * @param[in] tag tag without leading and trailing angle brackets */
+void DvisvgmSpecialHandler::XMLParser::openElement (const string &tag, SpecialActions &actions) {
+ StringInputBuffer ib(tag);
+ BufferInputReader ir(ib);
+ string name = ir.getString("/ \t\n\r");
+ ir.skipSpace();
+ auto elemNode = util::make_unique<XMLElement>(name);
+ map<string, string> attribs;
+ if (ir.parseAttributes(attribs, true, "\"'")) {
+ for (const auto &attrpair : attribs)
+ elemNode->addAttribute(attrpair.first, attrpair.second);
+ }
+ ir.skipSpace();
+ if (ir.peek() == '/') // end of empty element tag
+ (actions.svgTree().*_append)(std::move(elemNode));
+ else if (ir.peek() < 0) { // end of opening tag
+ _nameStack.push_back(name);
+ (actions.svgTree().*_pushContext)(std::move(elemNode));
+ }
+ else
+ throw SpecialException("'>' or '/>' expected at end of opening tag <"+name);
+}
+
+
+/** Processes a closing element tag.
+ * @param[in] tag tag without leading and trailing angle brackets */
+void DvisvgmSpecialHandler::XMLParser::closeElement (const string &tag, SpecialActions &actions) {
+ StringInputBuffer ib(tag);
+ BufferInputReader ir(ib);
+ string name = ir.getString(" \t\n\r");
+ ir.skipSpace();
+ if (ir.peek() >= 0)
+ throw SpecialException("'>' expected at end of closing tag </"+name);
+ if (_nameStack.empty())
+ throw SpecialException("spurious closing tag </" + name + ">");
+ if (_nameStack.back() != name)
+ throw SpecialException("expected </" + name + "> but found </" + _nameStack.back() + ">");
+ (actions.svgTree().*_popContext)();
+ _nameStack.pop_back();
+}
+
+
+/** Processes any remaining XML fragments, checks for missing closing tags,
+ * and resets the parser state. */
+void DvisvgmSpecialHandler::XMLParser::flush (SpecialActions &actions) {
+ if (!_xmlbuf.empty()) {
+ parse("", actions, true);
+ _xmlbuf.clear();
+ }
+ string tags;
+ while (!_nameStack.empty()) {
+ tags += "</"+_nameStack.back()+">, ";
+ _nameStack.pop_back();
+ }
+ if (!tags.empty()) {
+ tags.resize(tags.length()-2);
+ throw SpecialException("missing closing tags: "+tags);
+ }
+} \ No newline at end of file
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp
index 3a72b04f931..a8bde952e6f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DvisvgmSpecialHandler.hpp
@@ -21,6 +21,7 @@
#ifndef DVISVGMSPECIALHANDLER_HPP
#define DVISVGMSPECIALHANDLER_HPP
+#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
@@ -28,8 +29,44 @@
class InputReader;
class SpecialActions;
+class SVGTree;
+class XMLElement;
+class XMLNode;
+
+#ifdef _MSC_VER
+// MSVC: Prevent aggressive optimization of pointers to member functions.
+// Instatiating class DvisvgmSpecialHandler without the following pragma
+// leads to memory corruption.
+// https://docs.microsoft.com/en-us/cpp/preprocessor/pointers-to-members
+#pragma pointers_to_members(full_generality, single_inheritance)
+#endif
class DvisvgmSpecialHandler : public SpecialHandler {
+ class XMLParser {
+ using AppendFunc = void (SVGTree::*)(std::unique_ptr<XMLNode>);
+ using PushFunc = void (SVGTree::*)(std::unique_ptr<XMLElement>);
+ using PopFunc = void (SVGTree::*)();
+ using NameStack = std::vector<std::string>;
+
+ public:
+ XMLParser (AppendFunc append, PushFunc push, PopFunc pop)
+ : _append(append), _pushContext(push), _popContext(pop) {}
+
+ void parse (const std::string &xml, SpecialActions &actions, bool finish=false);
+ void flush (SpecialActions &actions);
+
+ protected:
+ void openElement (const std::string &tag, SpecialActions &actions);
+ void closeElement (const std::string &tag, SpecialActions &actions);
+
+ private:
+ AppendFunc _append;
+ PushFunc _pushContext;
+ PopFunc _popContext;
+ std::string _xmlbuf;
+ NameStack _nameStack; ///< names of nested elements still missing a closing tag
+ };
+
using StringVector = std::vector<std::string>;
using MacroMap = std::unordered_map<std::string, StringVector>;
@@ -60,7 +97,9 @@ class DvisvgmSpecialHandler : public SpecialHandler {
private:
MacroMap _macros;
MacroMap::iterator _currentMacro;
- int _nestingLevel;
+ int _nestingLevel=0; ///< nesting depth of rawset specials
+ XMLParser _defsParser; ///< parses XML added by 'rawdef' specials
+ XMLParser _pageParser; ///< parses XML added by 'raw' specials
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp
index 21b1967fc6f..5a5fccc08f4 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.cpp
@@ -18,6 +18,7 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
+#include <array>
#include <cstring>
#include <istream>
#include <limits>
@@ -66,8 +67,8 @@ EPSFile::EPSFile (const string &fname) : _ifs(fname, ios::binary) {
_ifs.seekg(_offset); // continue reading at the beginning of the PS section
}
string str;
- str += _ifs.get();
- str += _ifs.get();
+ str += char(_ifs.get());
+ str += char(_ifs.get());
_headerValid = (str == "%!");
_ifs.seekg(0);
}
@@ -98,12 +99,12 @@ BoundingBox EPSFile::bbox () const {
ir.skip(14);
ir.skipSpace();
if (!ir.check("(atend)", true)) {
- int val[4];
- for (int i=0; i < 4; i++) {
+ array<int, 4> values;
+ for (int &v : values) {
ir.skipSpace();
- ir.parseInt(val[i]);
+ ir.parseInt(v);
}
- box = BoundingBox(val[0], val[1], val[2], val[3]);
+ box = BoundingBox(values[0], values[1], values[2], values[3]);
break;
}
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp
index 713aecb2395..4fdd03ee1b3 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EPSFile.hpp
@@ -28,7 +28,7 @@
class EPSFile {
public:
- EPSFile (const std::string &fname);
+ explicit EPSFile (const std::string &fname);
std::istream& istream () const;
bool hasValidHeader () const {return _headerValid;}
BoundingBox bbox () const;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EllipticalArc.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EllipticalArc.cpp
new file mode 100644
index 00000000000..b820af00523
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EllipticalArc.cpp
@@ -0,0 +1,260 @@
+/*************************************************************************
+** EllipticalArc.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** This program is free software; you can redistribute it and/or **
+** modify it under the terms of the GNU General Public License as **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include <cmath>
+#include "EllipticalArc.hpp"
+#include "utility.hpp"
+
+using namespace std;
+
+
+/** Constructs an elliptical arc from end point parameterization.
+ * @param[in] start start point of arc
+ * @param[in] rx length of semi-major axis
+ * @param[in] ry length of semi-minor axis
+ * @param[in] angle rotation of ellipse around its center (in radians)
+ * @param[in] laf if true, choose the larger arc between start and end point
+ * @param[in] sweep if true, arc is drawn in the direction of increasing angles
+ * @param[in] end end point of the arc */
+EllipticalArc::EllipticalArc (const DPair &start, double rx, double ry, double angle, bool laf, bool sweep, const DPair &end)
+ : _rx(abs(rx)), _ry(abs(ry)), _rotationAngle(math::normalize_angle(angle, math::PI)),
+ _largeArc(laf), _sweepPositive(sweep), _startPoint(start), _endPoint(end)
+{
+ if (!isStraightLine()) {
+ // fix out-of-range radii according to section F.6.6.3 in
+ // https://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii
+ double c = cos(_rotationAngle);
+ double s = sin(_rotationAngle);
+ DPair p = (_startPoint-_endPoint)/2.0;
+ p = DPair(c*p.x()+s*p.y(), c*p.y()-s*p.x());
+ double lambda = (p.x()*p.x())/(_rx*_rx) + (p.y()*p.y())/(_ry*_ry);
+ if (lambda > 1) {
+ lambda = sqrt(lambda);
+ _rx *= lambda;
+ _ry *= lambda;
+ }
+ }
+}
+
+
+/** Constructs an elliptical arc from center parameterization
+ * @param[in] center absolute coordinates of the center of the ellipse
+ * @param[in] rx length of semi-major axis
+ * @param[in] ry length of semi-minor axis
+ * @param[in] rot rotation of ellipse around its center (in radians)
+ * @param[in] startAngle angle between major axis and vector from center to start point
+ * @param[in] deltaAngle angle between the vectors from center to start and end point, respectively */
+EllipticalArc::EllipticalArc (const DPair &center, double rx, double ry, double rot, double startAngle, double deltaAngle)
+ : _rx(rx), _ry(ry), _rotationAngle(math::normalize_angle(rot, math::TWO_PI)),
+ _largeArc(abs(deltaAngle) > math::PI), _sweepPositive(deltaAngle > 0)
+{
+ // https://www.w3.org/TR/SVG/implnote.html#ArcConversionCenterToEndpoint
+ double c = cos(_rotationAngle);
+ double s = sin(_rotationAngle);
+ double c1 = cos(startAngle);
+ double s1 = sin(startAngle);
+ double c2 = cos(startAngle+deltaAngle);
+ double s2 = sin(startAngle+deltaAngle);
+ _startPoint = DPair(c*rx*c1*c - s*ry*s1, s*rx*c1 + c*ry*s1) + center;
+ _endPoint = DPair(c*rx*c2*c - s*ry*s2, s*rx*c2 + c*ry*s2) + center;
+}
+
+
+/** Returns the angle between (1, 0) and a given vector.
+ * The angle is normalized to the range [0, 2pi). */
+static inline double angle (const DPair &p) {
+ return math::normalize_0_2pi(atan2(p.y(), p.x()));
+}
+
+
+/** Computes the center parameterization of the arc. */
+EllipticalArc::CenterParams EllipticalArc::getCenterParams () const {
+ EllipticalArc::CenterParams params;
+ if (isStraightLine()) {
+ params.center = (_endPoint-_startPoint)/2.0;
+ params.startAngle = params.deltaAngle = 0;
+ }
+ else {
+ // https://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
+ double c = cos(_rotationAngle);
+ double s = sin(_rotationAngle);
+ DPair p = (_startPoint-_endPoint)/2.0;
+ p = DPair(c*p.x()+s*p.y(), c*p.y()-s*p.x());
+ double rx2 = _rx*_rx, ry2 = _ry*_ry;
+ double px2 = p.x()*p.x(), py2 = p.y()*p.y();
+ double radicand = rx2*ry2 - rx2*py2 - ry2*px2;
+ if (radicand < 0) // should not happen if out-of-range radii were fixed correctly
+ radicand = 0;
+ else
+ radicand /= rx2*py2 + ry2*px2;
+ double root = sqrt(radicand) * (_largeArc == _sweepPositive ? -1 : 1);
+ DPair cp(root*p.y()*_rx/_ry, -root*p.x()*_ry/_rx);
+ DPair mid = (_startPoint+_endPoint)/2.0;
+ params.center = DPair(c*cp.x() - s*cp.y() + mid.x(), s*cp.x() + c*cp.y() + mid.y());
+ DPair q1((p.x() - cp.x())/_rx, (p.y() - cp.y())/_ry);
+ DPair q2(-(p.x() + cp.x())/_rx, -(p.y() + cp.y())/_ry);
+ params.startAngle = angle(q1);
+ params.deltaAngle = angle(q2) - params.startAngle;
+ if (_sweepPositive && params.deltaAngle < 0)
+ params.deltaAngle += math::TWO_PI;
+ else if (!_sweepPositive && params.deltaAngle > 0)
+ params.deltaAngle -= math::TWO_PI;
+ }
+ return params;
+}
+
+
+/** Applies the affine transformation described by a given matrix to the arc. */
+void EllipticalArc::transform (const Matrix &matrix) {
+ double c = cos(_rotationAngle);
+ double s = sin(_rotationAngle);
+ Matrix ellipse({_rx*c, -_ry*s, 0, _rx*s, _ry*c}); // E := rotate(xrot)*scale(rx, ry)
+ ellipse.lmultiply(matrix); // E':= M*E
+ // Compute the singular value decomposition of the transformed ellipse shape:
+ // E' = rotate(phi)*scale(sx, sy)*rotate(theta)
+ // The initial, right-hand rotation can be ignored because it rotates the unit circle
+ // around the origin, i.e. rotate(theta) maps the circle to itself.
+ // The signs of sx and sy don't matter either. They just flip the yet unrotated
+ // ellipse on the x- and/or y-axis. Thus, |sx| and |sy| are the new radii,
+ // and phi the new rotation angle.
+ auto vec = math::svd({{ellipse.get(0,0), ellipse.get(0,1)}, {ellipse.get(1,0), ellipse.get(1,1)}});
+ if (std::abs(vec[1]-vec[2]) < 1e-7) { // circle?
+ _rx = _ry = vec[1]; // always >= 0
+ _rotationAngle = 0;
+ }
+ else {
+ _rx = vec[1]; // always >= 0
+ _ry = abs(vec[2]); // ensure >= 0
+ _rotationAngle = math::normalize_angle(vec[0], math::HALF_PI);
+ }
+ // change drawing direction (clockwise vs. counter-clockwise) if 'matrix'
+ // flipped the ellipse horizontally or vertically but not both
+ if ((matrix.get(0, 0) < 0) != (matrix.get(1, 1) < 0))
+ _sweepPositive = !_sweepPositive;
+ _startPoint = matrix * _startPoint;
+ _endPoint = matrix * _endPoint;
+}
+
+
+/** Approximates an arc of the unit circle by a single cubic Bézier curve.
+ * @param[in] phi start angle of the arc in radians
+ * @param[in] delta length of the arc */
+static Bezier approx_unit_arc (double phi, double delta) {
+ double c = 0.551915024494; // see http://spencermortensen.com/articles/bezier-circle
+ if (abs(delta + math::HALF_PI) < 1e-7)
+ c = -c;
+ else
+ c = 4.0/3*tan(delta/4);
+ DPair p1(cos(phi), sin(phi));
+ DPair p4(cos(phi+delta), sin(phi+delta));
+ DPair p2(p1.x()-c*p1.y(), p1.y()+c*p1.x());
+ DPair p3(p4.x()+c*p4.y(), p4.y()-c*p4.x());
+ return Bezier(p1, p2, p3, p4);
+}
+
+
+/** Approximates the arc by a sequence of cubic Bézier curves. */
+vector<Bezier> EllipticalArc::approximate () const {
+ vector<Bezier> beziers;
+ if (_startPoint != _endPoint) {
+ if (isStraightLine()) {
+ DPair dir = (_endPoint - _startPoint);
+ dir /= dir.length()/3.0;
+ beziers.emplace_back(Bezier(_startPoint, _startPoint+dir, _endPoint-dir, _endPoint));
+ }
+ else {
+ CenterParams cparams = getCenterParams();
+ int numCurves = ceil(cparams.deltaAngle/math::HALF_PI);
+ double remainder = abs(fmod(cparams.deltaAngle, math::HALF_PI));
+ if (remainder < 1e-7)
+ numCurves--;
+ else if (math::HALF_PI-remainder < 1e-7)
+ numCurves++;
+ if (numCurves > 0) {
+ double c = cos(_rotationAngle);
+ double s = sin(_rotationAngle);
+ Matrix ellipse = {_rx*c, -_ry*s, cparams.center.x(), _rx*s, _ry*c, cparams.center.y()};
+ double angle = cparams.startAngle;
+ double diff = cparams.deltaAngle/numCurves;
+ while (numCurves-- > 0) {
+ beziers.emplace_back(approx_unit_arc(angle, diff).transform(ellipse));
+ angle += diff;
+ }
+ }
+ }
+ }
+ return beziers;
+}
+
+
+static inline bool is_angle_between (double t, double angle1, double angle2) {
+ if (angle1 < angle2)
+ return angle1 < t && t < angle2;
+ return angle2 > t || t > angle1;
+}
+
+
+/** Returns the tight bounding box of the arc. */
+BoundingBox EllipticalArc::getBBox () const {
+ BoundingBox bbox;
+ bbox.embed(_startPoint);
+ bbox.embed(_endPoint);
+ if (!isStraightLine()) {
+ // compute extremes of ellipse centered at the origin
+ double c = cos(_rotationAngle);
+ double s = sin(_rotationAngle);
+ double tx1 = math::normalize_0_2pi(-atan2(_ry*s, _rx*c)); // position of vertical tangent, d/dt E(tx1)=(0, y)
+ double tx2 = math::normalize_0_2pi(math::PI+tx1); // position of second vertical tangent
+ double ct = cos(tx1);
+ double st = sin(tx1);
+ DPair pv1(_rx*c*ct - _ry*s*st, _rx*s*ct + _ry*c*st); // E(tx1), 1st point on ellipse with vertical tangent
+ DPair pv2 = -pv1; // E(tx2), 2nd point on ellipse with vertical tangent
+
+ double ty1 = math::normalize_0_2pi(atan2(_ry*c, _rx*s)); // position of horizontal tangent, d/dt E(ty1)=(x, 0)
+ double ty2 = math::normalize_0_2pi(math::PI+ty1); // position of second horizontal tangent
+ ct = cos(ty1);
+ st = sin(ty1);
+ DPair ph1(_rx*c*ct - _ry*s*st, _rx*s*ct + _ry*c*st); // E(ty1), 1st point on ellipse with horizontal tangent
+ DPair ph2 = -ph1; // E(ty2), 2nd point on ellipse with horizontal tangent
+
+ // translate extreme points to actual coordinates
+ CenterParams cparams = getCenterParams();
+ pv1 += cparams.center;
+ pv2 += cparams.center;
+ ph1 += cparams.center;
+ ph2 += cparams.center;
+
+ double angle1 = cparams.startAngle;
+ double angle2 = math::normalize_0_2pi(angle1+cparams.deltaAngle);
+ if (!_sweepPositive)
+ swap(angle1, angle2);
+
+ // only consider extreme points located on the arc
+ if (is_angle_between(tx1, angle1, angle2))
+ bbox.embed(pv1);
+ if (is_angle_between(tx2, angle1, angle2))
+ bbox.embed(pv2);
+ if (is_angle_between(ty1, angle1, angle2))
+ bbox.embed(ph1);
+ if (is_angle_between(ty2, angle1, angle2))
+ bbox.embed(ph2);
+ }
+ return bbox;
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EllipticalArc.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EllipticalArc.hpp
new file mode 100644
index 00000000000..5d205581967
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EllipticalArc.hpp
@@ -0,0 +1,59 @@
+/*************************************************************************
+** EllipticalArc.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 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/>. **
+*************************************************************************/
+
+#pragma once
+
+#include "Bezier.hpp"
+#include "BoundingBox.hpp"
+#include "Matrix.hpp"
+#include "Pair.hpp"
+
+class EllipticalArc {
+ public:
+ struct CenterParams {
+ DPair center; ///< absolute coordinates of the center point
+ double startAngle; ///< angle of start point relative to semi-major axis (in radians)
+ double deltaAngle; ///< difference between angles of the start and end point (>0 if sweep flag is set)
+ };
+
+ public:
+ EllipticalArc (const DPair &start, double rx, double ry, double angle, bool laf, bool sweep, const DPair &end);
+ EllipticalArc (const DPair &center, double rx, double ry, double rot, double startAngle, double deltaAngle);
+ CenterParams getCenterParams () const;
+ double rx () const {return _rx;}
+ double ry () const {return _ry;}
+ bool largeArc () const {return _largeArc;}
+ bool sweepPositive () const {return _sweepPositive;}
+ double rotationAngle () const {return _rotationAngle;}
+ DPair startPoint () const {return _startPoint;}
+ DPair endPoint () const {return _endPoint;}
+ bool isStraightLine () const {return _rx < 1e-7 || _ry < 1e-7;}
+ BoundingBox getBBox () const;
+ void transform (const Matrix &matrix);
+ std::vector<Bezier> approximate () const;
+
+ private:
+ double _rx, _ry; ///< length of semi-major and semi-minor axes
+ double _rotationAngle; ///< rotation angle around center (in radians)
+ bool _largeArc; ///< if true, the longer arc from start to end point is chosen, else the shorter one
+ bool _sweepPositive; ///< if true, arc is drawn in direction of positive angles, else the opposite direction
+ DPair _startPoint, _endPoint; ///< absolute coordinates of start and end point
+};
+
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp
index f2725ad1fa2..c93a798fd74 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.cpp
@@ -24,16 +24,13 @@
#include "InputReader.hpp"
#include "Length.hpp"
#include "SpecialActions.hpp"
+#include "SVGTree.hpp"
#include "XMLNode.hpp"
#include "XMLString.hpp"
using namespace std;
-EmSpecialHandler::EmSpecialHandler () : _linewidth(0.4*72/72.27) {
-}
-
-
/** Computes the "cut vector" that is used to compute the line shape.
* Because each line has a width > 0 the actual shape of the line is a tetragon.
* The 4 vertices can be influenced by the cut parameter c that specifies
@@ -78,11 +75,13 @@ static DPair cut_vector (char cuttype, const DPair &linedir, double linewidth) {
* @param[in] lw line width in PS point units
* @param[in] actions object providing the actions that can be performed by the SpecialHandler */
static void create_line (const DPair &p1, const DPair &p2, char c1, char c2, double lw, SpecialActions &actions) {
- unique_ptr<XMLElementNode> node;
+ if (actions.outputLocked())
+ return;
+ unique_ptr<XMLElement> node;
DPair dir = p2-p1;
if (dir.x() == 0 || dir.y() == 0 || (c1 == 'p' && c2 == 'p')) {
// draw regular line
- node = util::make_unique<XMLElementNode>("line");
+ node = util::make_unique<XMLElement>("line");
node->addAttribute("x1", p1.x());
node->addAttribute("y1", p1.y());
node->addAttribute("x2", p2.x());
@@ -107,7 +106,7 @@ static void create_line (const DPair &p1, const DPair &p2, char c1, char c2, dou
<< XMLString(q12.x()) << ',' << XMLString(q12.y()) << ' '
<< XMLString(q22.x()) << ',' << XMLString(q22.y()) << ' '
<< XMLString(q21.x()) << ',' << XMLString(q21.y());
- node = util::make_unique<XMLElementNode>("polygon");
+ node = util::make_unique<XMLElement>("polygon");
node->addAttribute("points", oss.str());
if (actions.getColor() != Color::BLACK)
node->addAttribute("fill", actions.getColor().svgColorString());
@@ -117,7 +116,7 @@ static void create_line (const DPair &p1, const DPair &p2, char c1, char c2, dou
actions.embed(q21);
actions.embed(q22);
}
- actions.appendToPage(std::move(node));
+ actions.svgTree().appendToPage(std::move(node));
}
@@ -126,8 +125,8 @@ static void create_line (const DPair &p1, const DPair &p2, char c1, char c2, dou
static double read_length (InputReader &in) {
double val = in.getDouble();
string unitstr;
- if (isalpha(in.peek())) unitstr += in.get();
- if (isalpha(in.peek())) unitstr += in.get();
+ if (isalpha(in.peek())) unitstr += char(in.get());
+ if (isalpha(in.peek())) unitstr += char(in.get());
Length::Unit unit = Length::Unit::PT;
try {
unit = Length::stringToUnit(unitstr);
@@ -163,7 +162,7 @@ bool EmSpecialHandler::process (const string &prefix, istream &is, SpecialAction
{"moveto", &EmSpecialHandler::moveto},
{"lineto", &EmSpecialHandler::lineto},
{"linewidth", &EmSpecialHandler::linewidth},
- {0, 0}
+ {nullptr, nullptr}
};
StreamInputReader ir(is);
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp
index 546702c97ca..242ef248ef7 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EmSpecialHandler.hpp
@@ -38,7 +38,6 @@ class EmSpecialHandler : public SpecialHandler {
};
public:
- EmSpecialHandler ();
const char* name () const override {return "em";}
const char* info () const override {return "line drawing statements of the emTeX special set";}
std::vector<const char*> prefixes() const override;
@@ -54,9 +53,9 @@ class EmSpecialHandler : public SpecialHandler {
private:
std::unordered_map<int, DPair> _points; ///< points defined by special em:point
- std::vector<Line> _lines; ///< list of lines with undefined end points
- double _linewidth; ///< global line width
- DPair _pos; ///< current position of "graphic cursor"
+ std::vector<Line> _lines; ///< list of lines with undefined end points
+ double _linewidth=0.4*72/72.27; ///< global line width
+ DPair _pos; ///< current position of "graphic cursor"
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp
index 292ad722d7f..dba0a2544ab 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.cpp
@@ -32,7 +32,7 @@ static string read_entry (InputReader &in);
static bool valid_name_char (int c);
-EncFile::EncFile (const string &encname) : _encname(encname)
+EncFile::EncFile (string encname) : _encname(std::move(encname))
{
read();
}
@@ -101,7 +101,7 @@ static string read_entry (InputReader &in) {
while (!in.eof() && ((in.peek() == '/' && accept_slashes) || valid_name_char(in.peek()))) {
if (in.peek() != '/')
accept_slashes = false;
- entry += in.get();
+ entry += char(in.get());
}
if (entry.length() > 1) {
// strip leading slashes
@@ -127,6 +127,6 @@ static bool valid_name_char (int c) {
* @return character name assigned to character code c*/
const char* EncFile::charName (uint32_t c) const {
if (c < _table.size())
- return !_table[c].empty() ? _table[c].c_str() : 0;
- return 0;
+ return !_table[c].empty() ? _table[c].c_str() : nullptr;
+ return nullptr;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp
index 2eab020b655..fac26fd201f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/EncFile.hpp
@@ -28,10 +28,9 @@
#include "FontEncoding.hpp"
-class EncFile : public NamedFontEncoding
-{
+class EncFile : public NamedFontEncoding {
public:
- EncFile (const std::string &name);
+ explicit EncFile (std::string encname);
void read ();
void read (std::istream &is);
int size () const {return _table.size();}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp
index a5b4ed2ef2e..dfd60412cb8 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.cpp
@@ -69,7 +69,7 @@ FileFinder::FileFinder () {
void FileFinder::init (const std::string &argv0, const std::string &progname, bool enable_mktexmf) {
_argv0 = argv0;
- _progname = progname.c_str();
+ _progname = progname;
_enableMktex = enable_mktexmf;
}
@@ -174,6 +174,11 @@ const char* FileFinder::findFile (const std::string &fname, const char *ftype) c
{"pro", kpse_tex_ps_header_format},
{"sfd", kpse_sfd_format},
{"eps", kpse_pict_format},
+ {"png", kpse_pict_format},
+ {"jpg", kpse_pict_format},
+ {"jpeg", kpse_pict_format},
+ {"svg", kpse_pict_format},
+ {"pdf", kpse_tex_format},
};
auto it = types.find(ext);
if (it == types.end())
@@ -205,10 +210,10 @@ const char* FileFinder::findMappedFile (std::string fname) const {
if (const FontMap::Entry *entry = FontMap::instance().lookup(base)) {
const char *path=nullptr;
if (entry->fontname.find('.') != std::string::npos) // does the mapped filename has an extension?
- path = findFile(entry->fontname, 0); // look for that file
+ path = findFile(entry->fontname, nullptr); // look for that file
else { // otherwise, use extension of unmapped file
fname = entry->fontname + "." + ext;
- (path = findFile(fname, 0)) || (path = mktex(fname));
+ (path = findFile(fname, nullptr)) || (path = mktex(fname));
}
return path;
}
@@ -233,7 +238,7 @@ const char* FileFinder::mktex (const std::string &fname) const {
// maketfm and makemf are located in miktex/bin which is in the search PATH
std::string toolname = (ext == "tfm" ? "miktex-maketfm" : "miktex-makemf");
system((toolname+".exe "+fname).c_str());
- path = findFile(fname, 0);
+ path = findFile(fname, nullptr);
#else
kpse_file_format_type type = (ext == "tfm" ? kpse_tfm_format : kpse_mf_format);
path = kpse_make_tex(type, fname.c_str());
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp
index f7f8f783d87..b01c26b10c0 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileFinder.hpp
@@ -34,7 +34,7 @@ class FileFinder {
std::string version () const;
void addLookupDir (const std::string &path);
const char* lookup (const std::string &fname, const char *ftype, bool extended=true) const;
- const char* lookup (const std::string &fname, bool extended=true) const {return lookup(fname, 0, extended);}
+ const char* lookup (const std::string &fname, bool extended=true) const {return lookup(fname, nullptr, extended);}
protected:
FileFinder ();
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp
index d8834499d38..c859d30469d 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.cpp
@@ -87,10 +87,28 @@ FilePath::FilePath (const string &path, bool isfile, const string &current_dir)
}
-/** Assigns a new path. Relative paths are relative to the current working directory.
+/** Assigns a new path of a file or directory that already exists.
+ * Relative paths are relative to the current working directory.
* @param[in] path absolute or relative path to a file or directory */
-void FilePath::set(const string &path) {
- init(path, !FileSystem::isDirectory(path), FileSystem::getcwd());
+void FilePath::set (const string &path) {
+ set(path, !FileSystem::isDirectory(path));
+}
+
+
+/** Assigns a new path. Relative paths are relative to the current working directory.
+ * @param[in] path absolute or relative path to a file or directory
+ * @param[in] isfile true if 'path' references a file, false if a directory is referenced */
+void FilePath::set (const string &path, bool isfile) {
+ init(path, isfile, FileSystem::getcwd());
+}
+
+
+/** Assigns a new path. Relative paths are relative to the current working directory.
+ * @param[in] path absolute or relative path to a file or directory
+ * @param[in] isfile true if 'path' references a file, false if a directory is referenced
+ * @param[in] current_dir if 'path' is a relative path expression it will be related to 'current_dir' */
+void FilePath::set (const string &path, bool isfile, const string &current_dir) {
+ init(path, isfile, current_dir);
}
@@ -152,7 +170,7 @@ void FilePath::add (const string &dir) {
if (dir == ".." && !_dirs.empty())
_dirs.pop_back();
else if (dir.length() > 0 && dir != ".")
- _dirs.push_back(dir);
+ _dirs.emplace_back(dir);
}
@@ -257,3 +275,37 @@ string FilePath::relative (string reldir, bool with_filename) const {
path = ".";
return single_slashes(path);
}
+
+
+string FilePath::relative (const FilePath &filepath, bool with_filename) const {
+ return relative(filepath.absolute(false), with_filename);
+}
+
+
+/** Return the absolute or relative path whichever is shorter.
+* @param[in] reldir absolute path to a directory
+* @param[in] with_filename if false, the filename is omitted */
+string FilePath::shorterAbsoluteOrRelative (string reldir, bool with_filename) const {
+ string abs = absolute(with_filename);
+ string rel = relative(reldir, with_filename);
+ return abs.length() < rel.length() ? abs : rel;
+}
+
+
+bool FilePath::exists () const {
+ return empty() ? false : FileSystem::exists(absolute());
+}
+
+
+/** Checks if a given path is absolute or relative.
+ * @param[in] path path string to check
+ * @return true if path is absolute */
+bool FilePath::isAbsolute (string path) {
+ path = util::trim(path);
+#ifdef _WIN32
+ path = FileSystem::adaptPathSeperators(path);
+ if (path.length() >= 2 && path[1] == ':' && isalpha(path[0]))
+ path.erase(0, 2); // remove drive letter and colon
+#endif
+ return !path.empty() && path[0] == '/';
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp
index f3efed020b0..32a9be68149 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FilePath.hpp
@@ -28,8 +28,8 @@
class FilePath {
class Directory {
public:
- Directory (const std::string &dir) : _dirstr(dir) {}
- Directory (std::string &&dir) : _dirstr(std::move(dir)) {}
+ explicit Directory (std::string dir) : _dirstr(std::move(dir)) {}
+ explicit Directory (std::string &&dir) : _dirstr(std::move(dir)) {}
bool operator == (const Directory &dir) const;
bool operator != (const Directory &dir) const {return !(*this == dir);}
explicit operator std::string () const {return _dirstr;}
@@ -39,12 +39,17 @@ class FilePath {
};
public:
- FilePath (const std::string &path) {set(path);}
+ FilePath () =default;
+ explicit FilePath (const std::string &path) {set(path);}
FilePath (const std::string &path, bool isfile) : FilePath(path, isfile, "") {}
FilePath (const std::string &path, bool isfile, const std::string &current_dir);
void set (const std::string &path);
+ void set (const std::string &path, bool isfile);
+ void set (const std::string &path, bool isfile, const std::string &current_dir);
std::string absolute (bool with_filename=true) const;
std::string relative (std::string reldir="", bool with_filename=true) const;
+ std::string relative (const FilePath &filepath, bool with_filename=true) const;
+ std::string shorterAbsoluteOrRelative (std::string reldir="", bool with_filename=true) const;
std::string basename () const;
std::string suffix () const;
void suffix (const std::string &s);
@@ -53,16 +58,18 @@ class FilePath {
bool empty () const {return _dirs.empty() && _fname.empty();}
const std::string& filename () const {return _fname;}
void filename (const std::string &fname) {_fname = fname;}
+ bool exists () const;
+ static bool isAbsolute (std::string path);
protected:
void init (std::string path, bool isfile, std::string current_dir);
void add (const std::string &elem);
private:
- std::vector<std::string> _dirs;
+ std::vector<Directory> _dirs;
std::string _fname;
#ifdef _WIN32
- char _drive;
+ char _drive=0;
#endif
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp
index 9540a5e9c7d..35621465a53 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FileSystem.cpp
@@ -175,7 +175,7 @@ const char* FileSystem::userdir () {
if (!ret.empty())
return ret.c_str();
}
- return 0;
+ return nullptr;
#else
const char *dir=getenv("HOME");
if (!dir) {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp
index b83bb849a85..97520c59534 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.cpp
@@ -99,8 +99,8 @@ const char* Font::filename () const {
///////////////////////////////////////////////////////////////////////////////////////
-TFMFont::TFMFont (const string &name, uint32_t cs, double ds, double ss)
- : _fontname(name), _checksum(cs), _dsize(ds), _ssize(ss)
+TFMFont::TFMFont (string name, uint32_t cs, double ds, double ss)
+ : _fontname(std::move(name)), _checksum(cs), _dsize(ds), _ssize(ss)
{
}
@@ -159,7 +159,7 @@ bool TFMFont::verifyChecksums () const {
// static class variables
bool PhysicalFont::EXACT_BBOX = false;
bool PhysicalFont::KEEP_TEMP_FILES = false;
-const char *PhysicalFont::CACHE_PATH = 0;
+string PhysicalFont::CACHE_PATH;
double PhysicalFont::METAFONT_MAG = 4;
FontCache PhysicalFont::_cache;
@@ -175,14 +175,14 @@ unique_ptr<Font> PhysicalFont::create (const string &name, int fontindex, uint32
const char* PhysicalFont::path () const {
- const char *ext=0;
+ const char *ext=nullptr;
switch (type()) {
case Type::OTF: ext = "otf"; break;
case Type::PFB: ext = "pfb"; break;
case Type::TTC: ext = "ttc"; break;
case Type::TTF: ext = "ttf"; break;
case Type::MF : ext = "mf"; break;
- default : ext = 0;
+ default : ext = nullptr;
}
if (ext)
return FileFinder::instance().lookup(name()+"."+ext);
@@ -323,8 +323,8 @@ std::string PhysicalFont::styleName () const {
* @return true if outline could be computed */
bool PhysicalFont::getGlyph (int c, GraphicsPath<int32_t> &glyph, GFGlyphTracer::Callback *callback) const {
if (type() == Type::MF) {
- const Glyph *cached_glyph=0;
- if (CACHE_PATH) {
+ const Glyph *cached_glyph=nullptr;
+ if (!CACHE_PATH.empty()) {
_cache.write(CACHE_PATH);
_cache.read(name(), CACHE_PATH);
cached_glyph = _cache.getGlyph(c);
@@ -342,7 +342,7 @@ bool PhysicalFont::getGlyph (int c, GraphicsPath<int32_t> &glyph, GFGlyphTracer:
tracer.setGlyph(glyph);
tracer.executeChar(c);
glyph.closeOpenSubPaths();
- if (CACHE_PATH)
+ if (!CACHE_PATH.empty())
_cache.setGlyph(c, glyph);
return true;
}
@@ -392,7 +392,7 @@ bool PhysicalFont::createGF (string &gfname) const {
* @return number of glyphs traced */
int PhysicalFont::traceAllGlyphs (bool includeCached, GFGlyphTracer::Callback *cb) const {
int count = 0;
- if (type() == Type::MF && CACHE_PATH) {
+ if (type() == Type::MF && !CACHE_PATH.empty()) {
if (const FontMetrics *metrics = getMetrics()) {
int fchar = metrics->firstChar();
int lchar = metrics->lastChar();
@@ -479,7 +479,7 @@ PhysicalFontImpl::PhysicalFontImpl (const string &name, int fontindex, uint32_t
PhysicalFontImpl::~PhysicalFontImpl () {
- if (CACHE_PATH)
+ if (!CACHE_PATH.empty())
_cache.write(CACHE_PATH);
if (!KEEP_TEMP_FILES)
tidy();
@@ -548,7 +548,7 @@ uint32_t PhysicalFontImpl::unicode (uint32_t c) const {
const FontStyle* PhysicalFontImpl::style () const {
- if (auto *entry = fontMapEntry())
+ if (auto entry = fontMapEntry())
return &entry->style;
return nullptr;
}
@@ -671,6 +671,6 @@ void VirtualFontImpl::assignChar (uint32_t c, DVIVector &&dvi) {
* @return pointer to vector of DVI commands, or 0 if character doesn't exist */
const vector<uint8_t>* VirtualFontImpl::getDVI (int c) const {
auto it = _charDefs.find(c);
- return (it == _charDefs.end() ? 0 : &it->second);
+ return (it == _charDefs.end() ? nullptr : &it->second);
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp
index 294ad4738ee..3273a0c14b8 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Font.hpp
@@ -69,7 +69,7 @@ class Font {
virtual const char* path () const =0;
virtual const char* filename () const;
virtual const FontEncoding* encoding () const;
- virtual bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *callback=0) const =0;
+ virtual bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *callback=nullptr) const =0;
virtual void getGlyphMetrics (int c, bool vertical, GlyphMetrics &metrics) const;
virtual uint32_t unicode (uint32_t c) const;
virtual void tidy () const {}
@@ -88,7 +88,7 @@ class Font {
* The metric values returned by the member functions are based on cmr10. */
class EmptyFont : public Font {
public:
- EmptyFont (const std::string &name) : _fontname(name) {}
+ explicit EmptyFont (std::string name) : _fontname(std::move(name)) {}
std::unique_ptr<Font> clone (double ds, double sc) const override {return util::make_unique<EmptyFont>(*this);}
const Font* uniqueFont () const override {return this;}
std::string name () const override {return _fontname;}
@@ -100,7 +100,7 @@ class EmptyFont : public Font {
double italicCorr (int c) const override {return 0;}
const FontMetrics* getMetrics () const override {return nullptr;}
const char* path () const override {return nullptr;}
- bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=0) const override {return false;}
+ bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=nullptr) const override {return false;}
private:
std::string _fontname;
@@ -115,7 +115,7 @@ class PhysicalFont : public virtual Font {
static std::unique_ptr<Font> create (const std::string &name, uint32_t checksum, double dsize, double ssize, PhysicalFont::Type type);
static std::unique_ptr<Font> create (const std::string &name, int fontindex, uint32_t checksum, double dsize, double ssize);
virtual Type type () const =0;
- virtual bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=nullptr) const override;
+ bool getGlyph (int c, Glyph &glyph, GFGlyphTracer::Callback *cb=nullptr) const override;
virtual bool getExactGlyphBox (int c, BoundingBox &bbox, GFGlyphTracer::Callback *cb=nullptr) const;
virtual bool getExactGlyphBox (int c, GlyphMetrics &metrics, bool vertical, GFGlyphTracer::Callback *cb=nullptr) const;
virtual bool isCIDFont () const;
@@ -142,7 +142,7 @@ class PhysicalFont : public virtual Font {
public:
static bool EXACT_BBOX;
static bool KEEP_TEMP_FILES;
- static const char *CACHE_PATH; ///< path to cache directory (0 if caching is disabled)
+ static std::string CACHE_PATH; ///< path to cache directory ("" if caching is disabled)
static double METAFONT_MAG; ///< magnification factor for Metafont calls
protected:
@@ -168,7 +168,7 @@ class VirtualFont : public virtual Font {
class TFMFont : public virtual Font {
public:
- TFMFont (const std::string &name, uint32_t checksum, double dsize, double ssize);
+ TFMFont (std::string name, uint32_t cs, double ds, double ss);
const FontMetrics* getMetrics () const override;
std::string name () const override {return _fontname;}
double designSize () const override {return _dsize;}
@@ -227,7 +227,7 @@ class PhysicalFontProxy : public PhysicalFont {
class PhysicalFontImpl : public PhysicalFont, public TFMFont {
friend class PhysicalFont;
public:
- ~PhysicalFontImpl();
+ ~PhysicalFontImpl () override;
std::unique_ptr<Font> clone (double ds, double ss) const override {
return std::unique_ptr<PhysicalFontProxy>(new PhysicalFontProxy(this, ds, ss));
@@ -258,7 +258,7 @@ class PhysicalFontImpl : public PhysicalFont, public TFMFont {
class NativeFont : public PhysicalFont {
public:
virtual std::unique_ptr<NativeFont> clone (double ptsize, const FontStyle &style, Color color) const =0;
- virtual std::unique_ptr<Font> clone (double ds, double sc) const override =0;
+ std::unique_ptr<Font> clone (double ds, double sc) const override =0;
std::string name () const override;
Type type () const override;
double designSize () const override {return _ptsize;}
@@ -312,8 +312,8 @@ class NativeFontProxy : public NativeFont {
class NativeFontImpl : public NativeFont {
public:
- NativeFontImpl (const std::string &fname, int fontIndex, double ptsize, const FontStyle &style, Color color)
- : NativeFont(ptsize, style, color), _path(fname), _fontIndex(fontIndex) {}
+ NativeFontImpl (std::string fname, int fontIndex, double ptsize, const FontStyle &style, Color color)
+ : NativeFont(ptsize, style, color), _path(std::move(fname)), _fontIndex(fontIndex) {}
std::unique_ptr<NativeFont> clone (double ptsize, const FontStyle &style, Color color) const override {
return std::unique_ptr<NativeFontProxy>(new NativeFontProxy(this, ptsize, style, color));
@@ -391,7 +391,7 @@ class VirtualFontImpl : public VirtualFont, public TFMFont {
struct FontException : public MessageException {
- FontException (const std::string &msg) : MessageException(msg) {}
+ explicit FontException (const std::string &msg) : MessageException(msg) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp
index 1e2f19a780b..34478542dfb 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.cpp
@@ -23,13 +23,12 @@
#include <fstream>
#include <iomanip>
#include <sstream>
-#include "CRC32.hpp"
#include "FileSystem.hpp"
#include "FontCache.hpp"
-#include "Glyph.hpp"
#include "Pair.hpp"
#include "StreamReader.hpp"
#include "StreamWriter.hpp"
+#include "XXHashFunction.hpp"
using namespace std;
@@ -64,7 +63,7 @@ void FontCache::setGlyph (int c, const Glyph &glyph) {
* @return font glyph data (0 if no matching data was found) */
const Glyph* FontCache::getGlyph (int c) const {
auto it = _glyphs.find(c);
- return (it != _glyphs.end()) ? &it->second : 0;
+ return (it != _glyphs.end()) ? &it->second : nullptr;
}
@@ -78,10 +77,9 @@ bool FontCache::write (const string &fontname, const string &dir) const {
return true;
if (!fontname.empty()) {
- string dirstr = dir.empty() ? FileSystem::getcwd() : dir;
- ostringstream oss;
- oss << dirstr << '/' << fontname << ".fgd";
- ofstream ofs(oss.str(), ios::binary);
+ string pathstr = dir.empty() ? FileSystem::getcwd() : dir;
+ pathstr += "/" + fontname + ".fgd";
+ ofstream ofs(pathstr, ios::binary);
return write(fontname, ofs);
}
return false;
@@ -94,7 +92,7 @@ bool FontCache::write (const string &dir) const {
/** Returns the minimal number of bytes needed to store the given value. */
-static int max_int_size (int32_t value) {
+static int max_number_of_bytes (int32_t value) {
int32_t limit = 0x7f;
for (int i=1; i <= 4; i++) {
if ((value < 0 && -value <= limit+1) || (value >= 0 && value <= limit))
@@ -104,19 +102,49 @@ static int max_int_size (int32_t value) {
return 4;
}
+static int max_int_size () {
+ return 0;
+}
-/** Returns the minimal number of bytes needed to store the biggest
- * pair component of the given vector. */
-static int max_int_size (const Pair<int32_t> *pairs, size_t n) {
- int ret=0;
- for (size_t i=0; i < n; i++) {
- ret = max(ret, max_int_size(pairs[i].x()));
- ret = max(ret, max_int_size(pairs[i].y()));
- }
- return ret;
+template <typename ...Args>
+static int max_int_size (const Glyph::Point &p1, const Args& ...args) {
+ int max1 = max(max_number_of_bytes(p1.x()), max_number_of_bytes(p1.y()));
+ return max(max1, max_int_size(args...));
}
+struct WriteActions : Glyph::IterationActions {
+ WriteActions (StreamWriter &sw, HashFunction &hashfunc) : _sw(sw), _hashfunc(hashfunc) {}
+
+ using Point = Glyph::Point;
+ void moveto (const Point &p) override {write('M', p);}
+ void lineto (const Point &p) override {write('L', p);}
+ void quadto (const Point &p1, const Point &p2) override {write('Q', p1, p2);}
+ void cubicto (const Point &p1, const Point &p2, const Point &p3) override {write('C', p1, p2, p3); }
+ void closepath () override {write('Z');}
+
+ template <typename ...Args>
+ void write (char cmd, Args ...args) {
+ int bytesPerValue = max_int_size(args...);
+ int cmdchar = (bytesPerValue << 5) | (cmd - 'A');
+ _sw.writeUnsigned(cmdchar, 1, _hashfunc);
+ writeParams(bytesPerValue, args...);
+ }
+
+ static void writeParams (int bytesPerValue) {}
+
+ template <typename ...Args>
+ void writeParams (int bytesPerValue, const Point &p, const Args& ...args) {
+ _sw.writeSigned(p.x(), bytesPerValue, _hashfunc);
+ _sw.writeSigned(p.y(), bytesPerValue, _hashfunc);
+ writeParams(bytesPerValue, args...);
+ }
+
+ StreamWriter &_sw;
+ HashFunction &_hashfunc;
+};
+
+
/** Writes the current cache data to a stream (only if anything changed after
* the last call of read()).
* @param[in] fontname name of current font
@@ -129,36 +157,22 @@ bool FontCache::write (const string &fontname, ostream &os) const {
return false;
StreamWriter sw(os);
- CRC32 crc32;
-
- struct WriteActions : Glyph::Actions {
- WriteActions (StreamWriter &sw, CRC32 &crc32) : _sw(sw), _crc32(crc32) {}
-
- void draw (char cmd, const Glyph::Point *points, int n) override {
- int bytes = max_int_size(points, n);
- int cmdchar = (bytes << 5) | (cmd - 'A');
- _sw.writeUnsigned(cmdchar, 1, _crc32);
- for (int i=0; i < n; i++) {
- _sw.writeSigned(points[i].x(), bytes, _crc32);
- _sw.writeSigned(points[i].y(), bytes, _crc32);
- }
- }
- StreamWriter &_sw;
- CRC32 &_crc32;
- } actions(sw, crc32);
-
- sw.writeUnsigned(FORMAT_VERSION, 1, crc32);
- sw.writeUnsigned(0, 4); // space for checksum
- sw.writeString(fontname, crc32, true);
- sw.writeUnsigned(_glyphs.size(), 4, crc32);
+ XXH32HashFunction hashfunc;
+
+ sw.writeUnsigned(FORMAT_VERSION, 1, hashfunc);
+ sw.writeBytes(hashfunc.digestValue()); // space for checksum
+ sw.writeString(fontname, hashfunc, true);
+ sw.writeUnsigned(_glyphs.size(), 4, hashfunc);
+ WriteActions actions(sw, hashfunc);
for (const auto &charglyphpair : _glyphs) {
const Glyph &glyph = charglyphpair.second;
- sw.writeUnsigned(charglyphpair.first, 4, crc32);
- sw.writeUnsigned(glyph.size(), 2, crc32);
+ sw.writeUnsigned(charglyphpair.first, 4, hashfunc);
+ sw.writeUnsigned(glyph.size(), 2, hashfunc);
glyph.iterate(actions, false);
}
os.seekp(1);
- sw.writeUnsigned(crc32.get(), 4); // insert CRC32 checksum
+ auto digest = hashfunc.digestValue();
+ sw.writeBytes(digest); // insert checksum
os.seekp(0, ios::end);
return true;
}
@@ -195,17 +209,17 @@ bool FontCache::read (const string &fontname, istream &is) {
return false;
StreamReader sr(is);
- CRC32 crc32;
- if (sr.readUnsigned(1, crc32) != FORMAT_VERSION)
+ XXH32HashFunction hashfunc;
+ if (sr.readUnsigned(1, hashfunc) != FORMAT_VERSION)
return false;
- uint32_t crc32_cmp = sr.readUnsigned(4);
- crc32.update(is);
- if (crc32.get() != crc32_cmp)
+ auto hashcmp = sr.readBytes(hashfunc.digestSize());
+ hashfunc.update(is);
+ if (hashfunc.digestValue() != hashcmp)
return false;
is.clear();
- is.seekg(5); // continue reading after checksum
+ is.seekg(hashfunc.digestSize()+1); // continue reading after checksum
string fname = sr.readString();
if (fname != fontname)
@@ -237,7 +251,7 @@ bool FontCache::read (const string &fontname, istream &is) {
case 'Q': {
Pair32 p1 = read_pair(bytes, sr);
Pair32 p2 = read_pair(bytes, sr);
- glyph.conicto(p1, p2);
+ glyph.quadto(p1, p2);
break;
}
case 'Z':
@@ -289,17 +303,17 @@ bool FontCache::fontinfo (std::istream &is, FontInfo &info) {
is.seekg(0);
try {
StreamReader sr(is);
- CRC32 crc32;
- if ((info.version = sr.readUnsigned(1, crc32)) != FORMAT_VERSION)
+ XXH32HashFunction hashfunc;
+ if ((info.version = sr.readUnsigned(1, hashfunc)) != FORMAT_VERSION)
return false;
- info.checksum = sr.readUnsigned(4);
- crc32.update(is);
- if (crc32.get() != info.checksum)
+ info.checksum = sr.readBytes(hashfunc.digestSize());
+ hashfunc.update(is);
+ if (hashfunc.digestValue() != info.checksum)
return false;
is.clear();
- is.seekg(5); // continue reading after checksum
+ is.seekg(hashfunc.digestSize()+1); // continue reading after checksum
info.name = sr.readString();
info.numchars = sr.readUnsigned(4);
@@ -361,8 +375,10 @@ void FontCache::fontinfo (const string &dirname, ostream &os, bool purge) {
<< setw(5) << right << strinfopair.second->numchars << " glyph" << (strinfopair.second->numchars == 1 ? ' ':'s')
<< setw(10) << right << strinfopair.second->numcmds << " cmd" << (strinfopair.second->numcmds == 1 ? ' ':'s')
<< setw(12) << right << strinfopair.second->numbytes << " byte" << (strinfopair.second->numbytes == 1 ? ' ':'s')
- << setw(6) << "crc:" << setw(8) << hex << right << setfill('0') << strinfopair.second->checksum
- << endl;
+ << " hash:" << hex;
+ for (int byte : strinfopair.second->checksum)
+ os << setw(2) << setfill('0') << byte;
+ os << '\n';
}
}
if (purge) {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp
index 24c977818e7..0068b6c78bf 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontCache.hpp
@@ -30,16 +30,15 @@
class FontCache {
public:
struct FontInfo {
- std::string name; // fontname
- uint16_t version; // file format version
- uint32_t checksum; // CRC32 checksum of file data
- uint32_t numchars; // number of characters
- uint32_t numbytes; // number of bytes
- uint32_t numcmds; // number of path commands
+ std::string name; // fontname
+ uint16_t version; // file format version
+ std::vector<uint8_t> checksum; // checksum of file data
+ uint32_t numchars; // number of characters
+ uint32_t numbytes; // number of bytes
+ uint32_t numcmds; // number of path commands
};
public:
- FontCache () : _changed(false) {}
~FontCache () {clear();}
bool read (const std::string &fontname, const std::string &dir);
bool read (const std::string &fontname, std::istream &is);
@@ -59,7 +58,7 @@ class FontCache {
static const uint8_t FORMAT_VERSION;
std::string _fontname;
std::map<int, Glyph> _glyphs;
- bool _changed;
+ bool _changed=false;
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp
index add5cfc5ff6..3b038b63c6f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.cpp
@@ -32,7 +32,7 @@ using namespace std;
* @return pointer to encoding object, or 0 if there is no encoding defined */
FontEncoding* FontEncoding::encoding (const string &encname) {
if (encname.empty())
- return 0;
+ return nullptr;
using EncodingMap = unordered_map<string, unique_ptr<EncFile>>;
static EncodingMap encmap;
@@ -77,7 +77,7 @@ const FontEncoding* FontEncodingPair::findCompatibleBaseFontMap (const PhysicalF
return _enc2->findCompatibleBaseFontMap(font, charmapID);
if (_enc1)
return _enc1->findCompatibleBaseFontMap(font, charmapID);
- return 0;
+ return nullptr;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp
index de8ece6bb80..fffccd4224a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEncoding.hpp
@@ -32,7 +32,7 @@ struct FontEncoding {
virtual ~FontEncoding () =default;
virtual Character decode (uint32_t c) const =0;
virtual bool mapsToCharIndex () const =0;
- virtual const FontEncoding* findCompatibleBaseFontMap (const PhysicalFont *font, CharMapID &charmapID) const {return 0;}
+ virtual const FontEncoding* findCompatibleBaseFontMap (const PhysicalFont *font, CharMapID &charmapID) const {return nullptr;}
static FontEncoding* encoding (const std::string &encname);
};
@@ -45,7 +45,7 @@ struct NamedFontEncoding : public FontEncoding {
class FontEncodingPair : public FontEncoding {
public:
- FontEncodingPair (const FontEncoding *enc1) : _enc1(enc1), _enc2(0) {}
+ explicit FontEncodingPair (const FontEncoding *enc1) : _enc1(enc1), _enc2(nullptr) {}
FontEncodingPair (const FontEncoding *enc1, const FontEncoding *enc2) : _enc1(enc1), _enc2(enc2) {}
Character decode (uint32_t c) const override;
bool mapsToCharIndex () const override;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp
index 1bdcbcdbedb..61efd68916f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.cpp
@@ -18,6 +18,7 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
+#include <cmath>
#include <sstream>
#include <ft2build.h>
#include FT_ADVANCES_H
@@ -36,7 +37,7 @@ using namespace std;
/** Converts a floating point value to a 16.16 fixed point value. */
static inline FT_Fixed to_16dot16 (double val) {
- return static_cast<FT_Fixed>(val*65536.0 + 0.5);
+ return static_cast<FT_Fixed>(lround(val*65536.0));
}
@@ -49,9 +50,7 @@ static inline FT_Fixed to_16dot16 (int val) {
///////////////////////////////////////////////////////////////////////////
-FontEngine::FontEngine () : _currentFace(0), _currentFont(0)
-{
- _currentChar = _currentGlyphIndex = 0;
+FontEngine::FontEngine () {
if (FT_Init_FreeType(&_library))
Message::estream(true) << "failed to initialize FreeType library\n";
}
@@ -104,7 +103,7 @@ bool FontEngine::setFont (const Font &font) {
return true;
if (const char *path=font.path()) {
- const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(&font);
+ auto pf = dynamic_cast<const PhysicalFont*>(&font);
if (setFont(path, font.fontIndex(), pf ? pf->getCharMapID() : CharMapID())) {
_currentFont = &font;
return true;
@@ -212,7 +211,7 @@ int FontEngine::getAdvance (int c) const {
int FontEngine::getHAdvance () const {
if (_currentFace) {
- TT_OS2 *table = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(_currentFace, ft_sfnt_os2));
+ auto table = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(_currentFace, ft_sfnt_os2));
return table ? table->xAvgCharWidth : 0;
}
return 0;
@@ -294,7 +293,7 @@ string FontEngine::getGlyphName (const Character &c) const {
vector<int> FontEngine::getPanose () const {
vector<int> panose(10);
if (_currentFace) {
- TT_OS2 *table = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(_currentFace, ft_sfnt_os2));
+ auto table = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(_currentFace, ft_sfnt_os2));
if (table)
for (int i=0; i < 10; i++)
panose[i] = table->panose[i];
@@ -339,35 +338,35 @@ CharMapID FontEngine::setCustomCharMap () {
// Callback functions used by trace_outline/FT_Outline_Decompose
static int moveto (FTVectorPtr to, void *user) {
- Glyph *glyph = static_cast<Glyph*>(user);
+ auto glyph = static_cast<Glyph*>(user);
glyph->moveto(to->x, to->y);
return 0;
}
static int lineto (FTVectorPtr to, void *user) {
- Glyph *glyph = static_cast<Glyph*>(user);
+ auto glyph = static_cast<Glyph*>(user);
glyph->lineto(to->x, to->y);
return 0;
}
-static int conicto (FTVectorPtr control, FTVectorPtr to, void *user) {
- Glyph *glyph = static_cast<Glyph*>(user);
- glyph->conicto(control->x, control->y, to->x, to->y);
+static int quadto (FTVectorPtr control, FTVectorPtr to, void *user) {
+ auto glyph = static_cast<Glyph*>(user);
+ glyph->quadto(control->x, control->y, to->x, to->y);
return 0;
}
static int cubicto (FTVectorPtr control1, FTVectorPtr control2, FTVectorPtr to, void *user) {
- Glyph *glyph = static_cast<Glyph*>(user);
+ auto glyph = static_cast<Glyph*>(user);
glyph->cubicto(control1->x, control1->y, control2->x, control2->y, to->x, to->y);
return 0;
}
/** Traces the outline of a glyph by calling the corresponding "drawing" functions.
- * Each glyph is composed of straight lines, quadratic (conic) or cubic B�zier curves.
+ * Each glyph is composed of straight lines, quadratic or cubic Bézier curves.
* This function creates a Glyph object representing these graphics segments.
* @param[in] face FreeType object representing the font to scan
* @param[in] font corresponding Font object providing additional data
@@ -393,7 +392,7 @@ static bool trace_outline (FT_Face face, const Font *font, int index, Glyph &gly
if (style->bold != 0)
FT_Outline_Embolden(&outline, style->bold/font->scaledSize()*face->units_per_EM);
}
- const FT_Outline_Funcs funcs = {moveto, lineto, conicto, cubicto, 0, 0};
+ const FT_Outline_Funcs funcs = {moveto, lineto, quadto, cubicto, 0, 0};
FT_Outline_Decompose(&outline, &funcs, &glyph);
return true;
}
@@ -403,7 +402,7 @@ static bool trace_outline (FT_Face face, const Font *font, int index, Glyph &gly
/** Traces the outline of a glyph by calling the corresponding "drawing" functions.
- * Each glyph is composed of straight lines, quadratic (conic) or cubic B�zier curves.
+ * Each glyph is composed of straight lines, quadratic or cubic Bézier curves.
* This function creates a Glyph object representing these graphics segments.
* @param[in] c the glyph of this character will be traced
* @param[out] glyph resulting Glyph object containing the graphics segments
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp
index 071f7fcf4b5..33c9b96da2a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontEngine.hpp
@@ -73,10 +73,10 @@ class FontEngine {
int charIndex (const Character &c) const;
private:
- mutable unsigned int _currentChar, _currentGlyphIndex;
- FT_Face _currentFace;
+ mutable unsigned int _currentChar=0, _currentGlyphIndex=0;
+ FT_Face _currentFace = nullptr;
FT_Library _library;
- const Font *_currentFont;
+ const Font *_currentFont = nullptr;
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp
index 7805cc1d53e..4f236b38664 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.cpp
@@ -187,11 +187,11 @@ int FontManager::registerFont (uint32_t fontnum, const string &name, uint32_t ch
fontindex = map_entry->fontindex;
}
// try to find font file with the exact given name
- if (filename.rfind(".") != string::npos)
+ if (filename.rfind('.') != string::npos)
newfont = create_font(filename, name, fontindex, checksum, dsize, ssize);
else {
// try various font file formats if the given file has no extension
- const char *exts[] = {"pfb", "otf", "ttc", "ttf", "vf", "mf", 0};
+ const char *exts[] = {"pfb", "otf", "ttc", "ttf", "vf", "mf", nullptr};
for (const char **p = exts; *p && !newfont; ++p)
newfont = create_font(filename+"."+*p, name, fontindex, checksum, dsize, ssize);
}
@@ -204,7 +204,7 @@ int FontManager::registerFont (uint32_t fontnum, const string &name, uint32_t ch
else {
// create dummy font as a placeholder if the proper font is not available
newfont = util::make_unique<EmptyFont>(name);
- if (filename.rfind(".") == string::npos)
+ if (filename.rfind('.') == string::npos)
filename += ".mf";
// print warning message about missing font file (only once for each filename)
static set<string> missing_fonts;
@@ -263,7 +263,7 @@ int FontManager::registerFont (uint32_t fontnum, string filename, int fontIndex,
const int newid = _fonts.size(); // the new font gets this ID
auto it = _name2id.find(fontname);
if (it != _name2id.end()) { // font with same name already registered?
- if (NativeFont *font = dynamic_cast<NativeFont*>(_fonts[it->second].get()))
+ if (auto font = dynamic_cast<NativeFont*>(_fonts[it->second].get()))
newfont = font->clone(ptsize, style, color);
}
else {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp
index 2228c0c46ae..4405f67ecde 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontManager.hpp
@@ -66,7 +66,7 @@ class FontManager
void enterVF (VirtualFont *vf);
void leaveVF ();
void assignVFChar (int c, std::vector<uint8_t> &&dvi);
- std::ostream& write (std::ostream &os, Font *font=0, int level=0);
+ std::ostream& write (std::ostream &os, Font *font=nullptr, int level=0);
protected:
FontManager () =default;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp
index ee64c335f71..cd109c1809b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMap.hpp
@@ -34,7 +34,7 @@ class Subfont;
class FontMap {
public:
struct Entry {
- Entry (const MapLine &mapline, Subfont *subfont=nullptr);
+ explicit Entry (const MapLine &mapline, Subfont *subfont=nullptr);
Entry (const Entry &entry) =delete;
Entry (Entry &&entry) =default;
Entry& operator = (Entry &&entry) =default;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp
index 3f5296877b0..ccba26b727c 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontMetrics.hpp
@@ -67,7 +67,7 @@ struct NullFontMetric : public FontMetrics {
struct FontMetricException : public MessageException {
- FontMetricException (const std::string &msg) : MessageException(msg) {}
+ explicit FontMetricException (const std::string &msg) : MessageException(msg) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp
index 3c5173e5a85..d93402baf54 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.cpp
@@ -39,21 +39,19 @@ const array<FontWriter::FontFormatInfo, 4> FontWriter::_formatInfos {{
/** Returns the corresponding FontFormat for a given format name (e.g. "svg", "woff" etc.). */
FontWriter::FontFormat FontWriter::toFontFormat (string formatstr) {
formatstr = util::tolower(formatstr);
- for (const FontFormatInfo &info : _formatInfos) {
- if (formatstr == info.formatstr_short)
- return info.format;
- }
- return FontFormat::UNKNOWN;
+ auto it = find_if(_formatInfos.begin(), _formatInfos.end(), [&](const FontFormatInfo &info) {
+ return info.formatstr_short == formatstr;
+ });
+ return it != _formatInfos.end() ? it->format : FontFormat::UNKNOWN;
}
/** Returns the corresponding FontFormatInfo for a given FontFormat. */
const FontWriter::FontFormatInfo* FontWriter::fontFormatInfo (FontFormat format) {
- for (const FontFormatInfo &info : _formatInfos) {
- if (format == info.format)
- return &info;
- }
- return nullptr;
+ auto it = find_if(_formatInfos.begin(), _formatInfos.end(), [&](const FontFormatInfo &info) {
+ return info.format == format;
+ });
+ return it != _formatInfos.end() ? &(*it) : nullptr;
}
@@ -97,33 +95,38 @@ FontWriter::FontWriter (const PhysicalFont &font) : _font(font) {
}
-struct SFDActions : Glyph::Actions {
- SFDActions (ostream &os) : _os(os) {}
- void draw (char cmd, const Glyph::Point *points, int n) override {
- if (cmd == 'Q') {
- // convert quadratic Bézier curve to cubic one
- DPair p0(_currentPoint.x(), _currentPoint.y());
- DPair p1(points[0].x(), points[0].y());
- DPair p2(points[1].x(), points[1].y());
- Bezier bezier(p0, p1, p2);
- for (int i=1; i < 4; i++)
- _os << lround(bezier.point(i).x()) << ' ' << lround(bezier.point(i).y()) << ' ';
- _os << 'c';
- }
- else {
- for (int i=0; i < n; i++)
- _os << points[i].x() << ' ' << points[i].y() << ' ';
- switch (cmd) {
- case 'M': _os << 'm'; _startPoint = points[0]; break;
- case 'L': _os << 'l'; break;
- case 'C': _os << 'c'; break;
- case 'Z': _os << _startPoint.x() << ' ' << _startPoint.y() << " l"; _currentPoint = _startPoint; break;
- }
- }
- if (n > 0)
- _currentPoint = points[n-1];
- _os << " 0\n";
+struct SFDActions : Glyph::IterationActions {
+ explicit SFDActions (ostream &os) : _os(os) {}
+
+ using Point = Glyph::Point;
+ void moveto (const Point &p) override {write('m', p);}
+ void lineto (const Point &p) override {write('l', p);}
+ void cubicto (const Point &p1, const Point &p2, const Point &p3) override {write('c', p1, p2, p3); }
+ void closepath () override {write('m', startPoint());}
+
+ void quadto (const Point &p1, const Point &p2) override {
+ // convert quadratic Bézier curve to cubic one
+ DPair pt0(currentPoint().x(), currentPoint().y());
+ DPair pt1(p1.x(), p1.y());
+ DPair pt2(p2.x(), p2.y());
+ Bezier b(pt0, pt1, pt2);
+ write('c', round(b.point(0)), round(b.point(1)), round(b.point(2)), round(b.point(3)));
}
+
+ template <typename ...Args>
+ void write (char cmd, const Args& ...args) {
+ writeParams(args...);
+ _os << cmd << " 0\n";
+ }
+
+ static void writeParams () {}
+
+ template <typename Pt, typename ...Args>
+ void writeParams (const Pt &p, const Args& ...args) const {
+ _os << p.x() << ' ' << p.y() << ' ';
+ writeParams(args...);
+ }
+
ostream &_os;
Glyph::Point _startPoint, _currentPoint;
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp
index 3becdf2618d..458952cad9b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/FontWriter.hpp
@@ -36,9 +36,9 @@ class FontWriter {
static bool AUTOHINT_FONTS;
public:
- FontWriter (const PhysicalFont &font);
- std::string createFontFile (FontFormat format, const std::set<int> &charcodes, GFGlyphTracer::Callback *cb=0) const;
- bool writeCSSFontFace (FontFormat format, const std::set<int> &charcodes, std::ostream &os, GFGlyphTracer::Callback *cb=0) const;
+ explicit FontWriter (const PhysicalFont &font);
+ std::string createFontFile (FontFormat format, const std::set<int> &charcodes, GFGlyphTracer::Callback *cb=nullptr) const;
+ bool writeCSSFontFace (FontFormat format, const std::set<int> &charcodes, std::ostream &os, GFGlyphTracer::Callback *cb=nullptr) const;
static FontFormat toFontFormat (std::string formatstr);
static std::vector<std::string> supportedFormats ();
@@ -59,7 +59,7 @@ class FontWriter {
struct FontWriterException : MessageException {
- FontWriterException (const std::string &msg) : MessageException(msg) {}
+ explicit FontWriterException (const std::string &msg) : MessageException(msg) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp
index 0a3b653540d..85f7c2cab56 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.cpp
@@ -22,7 +22,7 @@
using namespace std;
-GFGlyphTracer::GFGlyphTracer () : GFTracer(_ifs, 0), _glyph(0), _callback(0)
+GFGlyphTracer::GFGlyphTracer () : GFTracer(_ifs, 0)
{
}
@@ -30,7 +30,7 @@ GFGlyphTracer::GFGlyphTracer () : GFTracer(_ifs, 0), _glyph(0), _callback(0)
* @param[in] is GF input stream
* @param[in] upp target units per PS point */
GFGlyphTracer::GFGlyphTracer (string &fname, double upp, Callback *cb)
- : GFTracer(_ifs, upp), _glyph(0), _callback(cb)
+ : GFTracer(_ifs, upp), _callback(cb)
{
if (_callback)
_callback->setFont(fname);
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp
index c6304c090b3..49f69b69ec7 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFGlyphTracer.hpp
@@ -39,7 +39,7 @@ class GFGlyphTracer : public GFTracer
public:
GFGlyphTracer ();
- GFGlyphTracer (std::string &fname, double upp, Callback *cb=0);
+ GFGlyphTracer (std::string &fname, double upp, Callback *cb=nullptr);
void reset (std::string &fname, double upp);
void setCallback (Callback *cb) {_callback = cb;}
bool executeChar (uint8_t c) override;
@@ -53,8 +53,8 @@ class GFGlyphTracer : public GFTracer
private:
std::ifstream _ifs;
- Glyph *_glyph;
- Callback *_callback;
+ Glyph *_glyph = nullptr;
+ Callback *_callback = nullptr;
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp
index 3cba8e50691..32ba354443f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.cpp
@@ -106,11 +106,8 @@ int GFReader::executeCommand () {
cmdPaint0(opcode);
else if (opcode >= 74 && opcode <= 238)
cmdNewRow(opcode-74);
- else if (opcode >= 250) {
- ostringstream oss;
- oss << "undefined GF command (opcode " << opcode << ")";
- throw GFException(oss.str());
- }
+ else if (opcode >= 250)
+ throw GFException("undefined GF command (opcode " + std::to_string(opcode) + ")");
else {
int offset = opcode <= 73 ? 64 : 239-(73-64+1);
const GFCommand &cmd = commands[opcode-offset];
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp
index 87a9a75f5f2..3dfceb98cd6 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFReader.hpp
@@ -31,16 +31,13 @@
class CharInfo;
-struct GFException : public MessageException
-{
- GFException (const std::string &msg) : MessageException(msg) {}
+struct GFException : public MessageException {
+ explicit GFException (const std::string &msg) : MessageException(msg) {}
};
-class GFReader
-{
- struct CharInfo
- {
+class GFReader {
+ struct CharInfo {
CharInfo () : dx(0), dy(0), width(0), location(0) {}
CharInfo (int32_t dxx, int32_t dyy, int32_t w, uint32_t p) : dx(dxx), dy(dyy), width(w), location(p) {}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp
index 6e7875eba39..8fe746cc05d 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GFTracer.hpp
@@ -24,12 +24,10 @@
#include <istream>
#include "GFReader.hpp"
-class GFTracer : public GFReader
-{
+class GFTracer : public GFReader {
public:
- GFTracer (std::istream &is);
+ explicit GFTracer (std::istream &is);
GFTracer (std::istream &is, double upp);
- virtual ~GFTracer () =default;
virtual void moveTo (double x, double y) =0;
virtual void lineTo (double x, double y) =0;
virtual void curveTo (double c1x, double c1y, double c2x, double c2y, double x, double y) =0;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp
index ff57d213b1d..c097ace667a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.cpp
@@ -66,7 +66,7 @@ static string get_path_from_registry () {
if (major_version >= 7) {
char dll_path[512]; // path to Ghostscript DLL stored in the registry
DWORD length = 512;
- if (RegGetValueA(hkey, subkey, "GS_DLL", RRF_RT_REG_SZ, 0, dll_path, &length) == ERROR_SUCCESS) {
+ if (RegGetValueA(hkey, subkey, "GS_DLL", RRF_RT_REG_SZ, nullptr, dll_path, &length) == ERROR_SUCCESS) {
RegCloseKey(hkey);
return dll_path;
}
@@ -160,7 +160,6 @@ Ghostscript::Ghostscript ()
: DLLoader(get_libgs(LIBGS_NAME))
#endif
{
- _inst = 0;
}
@@ -173,7 +172,6 @@ Ghostscript::Ghostscript (int argc, const char **argv, void *caller)
: DLLoader(get_libgs(LIBGS_NAME))
#endif
{
- _inst = 0;
init(argc, argv, caller);
}
@@ -191,12 +189,12 @@ bool Ghostscript::init (int argc, const char **argv, void *caller) {
if (!_inst) {
int status = new_instance(&_inst, caller);
if (status < 0)
- _inst = 0;
+ _inst = nullptr;
else {
init_with_args(argc, const_cast<char**>(argv));
}
}
- return _inst != 0;
+ return _inst != nullptr;
}
@@ -257,7 +255,7 @@ int Ghostscript::new_instance (void **psinst, void *caller) {
#else
if (auto fn = LOAD_SYMBOL(gsapi_new_instance))
return fn(psinst, caller);
- *psinst = 0;
+ *psinst = nullptr;
return 0;
#endif
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp
index 676da3909d8..4ea62f775f5 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Ghostscript.hpp
@@ -73,10 +73,10 @@ class Ghostscript
public:
Ghostscript ();
- Ghostscript (int argc, const char **argv, void *caller=0);
+ Ghostscript (int argc, const char **argv, void *caller=nullptr);
Ghostscript (const Ghostscript &gs) =delete;
~Ghostscript ();
- bool init (int argc, const char **argv, void *caller=0);
+ bool init (int argc, const char **argv, void *caller=nullptr);
bool available ();
bool revision (gsapi_revision_t *r);
int revision ();
@@ -96,7 +96,7 @@ class Ghostscript
void delete_instance ();
private:
- void *_inst; ///< Ghostscript handle needed to call the gsapi_foo functions
+ void *_inst = nullptr; ///< Ghostscript handle needed to call the gsapi_foo functions
};
#endif // DISABLE_GS
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp
index 579d6720b94..8a41b811d99 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GlyphTracerMessages.hpp
@@ -25,12 +25,11 @@
#include "GFGlyphTracer.hpp"
#include "Message.hpp"
-class GlyphTracerMessages : public GFGlyphTracer::Callback
-{
+class GlyphTracerMessages : public GFGlyphTracer::Callback {
public:
- GlyphTracerMessages (bool sfmsg=true, bool autonl=true) : _sfmsg(sfmsg), _autonl(autonl), _traced(false) {}
+ explicit GlyphTracerMessages (bool sfmsg=true, bool autonl=true) : _sfmsg(sfmsg), _autonl(autonl), _traced(false) {}
- ~GlyphTracerMessages () {
+ ~GlyphTracerMessages () override {
if (_autonl)
Message::mstream() << '\n';
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp
index 31e8e3521d1..78b29d46307 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/GraphicsPath.hpp
@@ -18,17 +18,148 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
-#ifndef GRAPHICSPATH_HPP
-#define GRAPHICSPATH_HPP
+#pragma once
+#include <array>
#include <cctype>
#include <deque>
#include <ostream>
+#include <type_traits>
+#include <mpark/variant.hpp>
#include "BoundingBox.hpp"
+#include "EllipticalArc.hpp"
#include "Matrix.hpp"
#include "Pair.hpp"
+#include "utility.hpp"
#include "XMLString.hpp"
+template <typename T>
+class GraphicsPath;
+
+namespace gp {
+
+/// Base class for all path data commands, like moveto, lineto, curveto, etc.
+struct CommandBase {};
+
+/** Base class for all path data commands with NUM_POINTS point parameters
+ * @tparam NUM_POINTS number of parameter pairs representing points, e.g. 1 for moveto and lineto */
+template <typename T, int NUM_POINTS>
+class Command : public CommandBase {
+ friend class GraphicsPath<T>;
+ public:
+ int numPoints () const {return NUM_POINTS;}
+ Pair<T>& point (int n) {return points[n];}
+ const Pair<T>& point (int n) const {return points[n];}
+
+ /** Transforms the command by a given transformation matrix.
+ * @params[in] matrix describes the affine transformation to apply
+ * @params[in] currentPoint the untransformed end point of the preceding command */
+ void transform (const Matrix &matrix, const Pair<T> &currentPoint) {
+ for (Pair<T> &p : points)
+ p = matrix * p;
+ }
+
+ /** Returns true if all points are identical to those of another command. */
+ bool pointsEqual (const Command &cmd) const {
+ for (int i=0; i < NUM_POINTS; i++)
+ if (points[i] != cmd.points[i])
+ return false;
+ return true;
+ }
+
+ protected:
+ explicit Command () =default;
+ explicit Command (std::array<Pair<T>, NUM_POINTS> &&pts) : points(std::move(pts)) {}
+
+ protected:
+ std::array<Pair<T>, NUM_POINTS> points;
+};
+
+template <typename T>
+struct MoveTo : public Command<T, 1> {
+ explicit MoveTo (const Pair<T> &p) : Command<T, 1>({p}) {}
+};
+
+template <typename T>
+struct LineTo : public Command<T, 1> {
+ explicit LineTo (const Pair<T> &p) : Command<T, 1>({p}) {}
+};
+
+template <typename T>
+struct CubicTo : public Command<T, 3> {
+ explicit CubicTo (const Pair<T> &p1, const Pair<T> &p2, const Pair<T> &p3) : Command<T, 3>({p1, p2, p3}) {}
+};
+
+template <typename T>
+struct QuadTo : public Command<T, 2> {
+ explicit QuadTo (const Pair<T> &p1, const Pair<T> &p2) : Command<T, 2>({p1, p2}) {}
+};
+
+template <typename T>
+struct ClosePath : public Command<T, 0> {
+ ClosePath () : Command<T, 0>() {}
+};
+
+template <typename T>
+struct ArcTo : Command<T, 1> {
+ ArcTo (T rxx, T ryy, double xrot, bool laf, bool sf, const Pair<T> &pp)
+ : Command<T, 1>({pp}), rx(rxx < 0 ? -rxx : rxx), ry(ryy < 0 ? -ryy : ryy),
+ xrotation(xrot), largeArcFlag(laf), sweepFlag(sf) {}
+
+ bool operator == (const ArcTo &arc) const {
+ return rx == arc.rx
+ && ry == arc.ry
+ && xrotation == arc.xrotation
+ && largeArcFlag == arc.largeArcFlag
+ && sweepFlag == arc.sweepFlag
+ && this->points[0] == arc.points[0];
+ }
+
+ void transform (const Matrix &matrix, const Pair<T> &currentPoint);
+
+ bool operator != (const ArcTo &arc) const {return !(*this == arc);}
+
+ T rx, ry; ///< length of the semi-major and semi-minor axes
+ double xrotation; ///< rotation of the semi-major axis in degrees
+ bool largeArcFlag; ///< if true, the longer arc from start to end point is chosen, else the shorter one
+ bool sweepFlag; ///< if true, arc is drawn in direction of positive angles, else the opposite direction
+};
+
+/** Applies an affine transformation described by a given matrix to the arc segment.
+ * @params[in] matrix describes the affine transformation to apply
+ * @params[in] currentPoint the untransformed end point of the preceding command */
+template <typename T>
+void ArcTo<T>::transform (const Matrix &matrix, const Pair<T> &currentPoint) {
+ EllipticalArc arc(currentPoint, rx, ry, math::deg2rad(xrotation), largeArcFlag, sweepFlag, this->points[0]);
+ arc.transform(matrix);
+ rx = arc.rx();
+ ry = arc.ry();
+ xrotation = math::rad2deg(arc.rotationAngle());
+ largeArcFlag = arc.largeArc();
+ sweepFlag = arc.sweepPositive();
+ this->points[0] = Pair<T>(arc.endPoint());
+}
+
+/** Returns true if two path command objects are identical (same command and same parameters). */
+template <typename Cmd1, typename Cmd2>
+inline typename std::enable_if<std::is_base_of<CommandBase, Cmd1>::value, bool>::type
+operator == (const Cmd1 &cmd1, const Cmd2 &cmd2) {
+ if (std::is_convertible<Cmd1, Cmd2>::value && std::is_convertible<Cmd2, Cmd1>::value)
+ return cmd1.pointsEqual(cmd2);
+ return false;
+}
+
+/** Returns true if two path command objects differ (different commands or different parameters). */
+template <typename Cmd1, typename Cmd2>
+inline typename std::enable_if<std::is_base_of<CommandBase, Cmd1>::value, bool>::type
+operator != (const Cmd1 &cmd1, const Cmd2 &cmd2) {
+ if (std::is_convertible<Cmd1, Cmd2>::value && std::is_convertible<Cmd2, Cmd1>::value)
+ return !cmd1.pointsEqual(cmd2);
+ return true;
+}
+
+} // namespace gp
+
template <typename T>
class GraphicsPath {
@@ -37,78 +168,272 @@ class GraphicsPath {
enum class WindingRule {EVEN_ODD, NON_ZERO};
using Point = Pair<T>;
- struct Command {
- enum class Type {MOVETO, LINETO, CONICTO, CUBICTO, CLOSEPATH};
+ protected:
- Command (Type t) : type(t) {}
+ static XMLString to_param_str (double v, double s, double d, bool leadingSpace) {
+ XMLString str(v*s + d);
+ if (leadingSpace && (str[0] != '-'))
+ str.insert(0, " ");
+ return str;
+ }
- Command (Type t, const Point &p) : type(t) {
- params[0] = p;
- }
+ static XMLString to_param_str (double val, double prev, double s, double d, bool leadingSpace) {
+ XMLString str((val-prev)*s + d);
+ if (leadingSpace && (str[0] != '-'))
+ str.insert(0, " ");
+ return str;
+ }
- Command (Type t, const Point &p1, const Point &p2) : type(t) {
- params[0] = p1;
- params[1] = p2;
- }
+ static std::string to_param_str (const Point &p, double sx, double sy, double dx, double dy, bool leadingSpace) {
+ return to_param_str(p.x(), sx, dx, leadingSpace) + to_param_str(p.y(), sy, dy, true);
+ }
- Command (Type t, const Point &p1, const Point &p2, const Point &p3) : type(t) {
- params[0] = p1;
- params[1] = p2;
- params[2] = p3;
- }
+ static std::string to_param_str (const Point &p, const Point &prev, double sx, double sy, double dx, double dy, bool leadingSpace) {
+ return to_param_str(p.x()-prev.x(), sx, dx, leadingSpace) + to_param_str(p.y()-prev.y(), sy, dy, true);
+ }
+
+ using MoveTo = gp::MoveTo<T>;
+ using LineTo = gp::LineTo<T>;
+ using CubicTo = gp::CubicTo<T>;
+ using QuadTo = gp::QuadTo<T>;
+ using ArcTo = gp::ArcTo<T>;
+ using ClosePath = gp::ClosePath<T>;
+
+ /// Variant representing a single path command
+ using CommandVariant = mpark::variant<MoveTo, LineTo, CubicTo, QuadTo, ArcTo, ClosePath>;
+
+ class IterationVisitor;
+
+ public:
+ /** Base class providing several template methods being called when executing
+ * GraphicsPath::iterate(). */
+ class IterationActions {
+ friend class IterationVisitor;
+ public:
+ virtual ~IterationActions () =default;
+ virtual void moveto (const Point &p) {}
+ virtual void lineto (const Point &p) {}
+ virtual void hlineto (const T &x) {}
+ virtual void vlineto (const T &y) {}
+ virtual void quadto (const Point &p) {}
+ virtual void quadto (const Point &p1, const Point &p2) {}
+ virtual void cubicto (const Point &p1, const Point &p2) {}
+ virtual void cubicto (const Point &p1, const Point &p2, const Point &p3) {}
+ virtual void arcto (T rx, T ry, double angle, bool largeArcFlag, bool sweepFlag, const Point &p) {}
+ virtual void closepath () {}
+ virtual bool quit () {return false;}
+ virtual void finished () {}
+ const Point& startPoint () const {return _startPoint;}
+ const Point& currentPoint () const {return _currentPoint;}
+
+ private:
+ Point _startPoint; ///< first point of the current sub-path
+ Point _currentPoint; ///< point reached by preceding path command, or (0,0) otherwise
+ };
+
+ protected:
+ class ModificationActions : public IterationActions {
+ friend class GraphicsPath;
+ public:
+ explicit ModificationActions (GraphicsPath &path) : _path(path) {}
- int numParams () const {
- switch (type) {
- case Type::CLOSEPATH : return 0;
- case Type::MOVETO :
- case Type::LINETO : return 1;
- case Type::CONICTO : return 2;
- case Type::CUBICTO : return 3;
+ protected:
+ GraphicsPath& path () {return _path;}
+ int commandPos () const {return _commandPos;}
+
+ private:
+ GraphicsPath &_path;
+ int _commandPos=0; ///< number of command in path being processed
+ };
+
+ class WriteActions : public IterationActions {
+ public:
+ WriteActions (std::ostream &os, bool rel, double sx, double sy, double dx, double dy)
+ : _os(os), _relative(rel), _sx(sx), _sy(sy), _dx(dx), _dy(dy) {}
+
+ void moveto (const Point &p) override {write('M', {p});}
+ void lineto (const Point &p) override {write('L', {p});}
+ void hlineto (const T &x) override {write('H', x, this->currentPoint().x(), _sx, _dx);}
+ void vlineto (const T &y) override {write('V', y, this->currentPoint().y(), _sy, _dy);}
+ void quadto (const Point &p) override {write('T', {p});}
+ void quadto (const Point &p1, const Point &p2) override {write('Q', {p1, p2});}
+ void cubicto (const Point &p1, const Point &p2) override {write('S', {p1, p2});}
+ void cubicto (const Point &p1, const Point &p2, const Point &p3) override {write('C', {p1, p2, p3});}
+ void closepath () override {_os << (_relative ? 'z' : 'Z');}
+
+ void arcto (T rx, T ry, double angle, bool largeArcFlag, bool sweepFlag, const Point &p) override {
+ Point diff = p-this->currentPoint();
+ if (std::abs(diff.x()) < 1e-7 && std::abs(diff.y()) < 1e-7)
+ return;
+ if (std::abs(rx) < 1e-7 && std::abs(ry) < 1e-7)
+ lineto(p);
+ else {
+ if (std::abs(std::abs(_sx) - std::abs(_sy)) < 1e-7) { // symmetric scaling?
+ angle *= math::sgn(_sx) * math::sgn(_sy);
+ rx *= std::abs(_sx);
+ ry *= std::abs(_sx);
+ }
+ else { // asymmetric scaling => compute new shape parameters
+ EllipticalArc arc(this->currentPoint(), double(rx), double(ry), math::deg2rad(angle), largeArcFlag, sweepFlag, p);
+ arc.transform(ScalingMatrix(_sx, _sy));
+ angle = math::rad2deg(arc.rotationAngle());
+ rx = arc.rx();
+ ry = arc.ry();
+ }
+ _os << (_relative ? 'a' : 'A')
+ << to_param_str(rx, 1.0, 0, false)
+ << to_param_str(ry, 1.0, 0, true)
+ << to_param_str(angle, 1.0, 0, true)
+ << ' ' << (largeArcFlag ? 1 : 0)
+ << ' ' << (sweepFlag ? 1 : 0);
+ if (_relative)
+ _os << to_param_str(p, this->currentPoint(), _sx, _sy, _dx, _dy, true);
+ else
+ _os << to_param_str(p, _sx, _sy, _dx, _dy, true);
+ }
}
- return 0;
- }
- void transform (const Matrix &matrix) {
- for (int i=0; i < numParams(); i++)
- params[i] = matrix * params[i];
- }
+ protected:
+ void write (char cmdchar, std::initializer_list<Point> points) const {
+ int count=0;
+ if (_relative) {
+ _os << char(tolower(cmdchar));
+ for (const Point &p : points)
+ _os << to_param_str(p, this->currentPoint(), _sx, _sy, _dx, _dy, count++ > 0);
+ }
+ else {
+ _os << cmdchar;
+ for (const Point &p : points)
+ _os << to_param_str(p, _sx, _sy, _dx, _dy, count++ > 0);
+ }
+ }
- bool operator == (const Command &cmd) const {
- bool ret = (type == cmd.type);
- for (int i=0; ret && i < numParams(); i++)
- ret &= (params[i] == cmd.params[i]);
- return ret;
- }
+ void write (char cmdchar, T val, T relval, double s, double d) const {
+ if (_relative)
+ _os << char(tolower(cmdchar)) << to_param_str(val, relval, s, d, false);
+ else
+ _os << cmdchar << to_param_str(val, s, d, false);
+ }
- bool operator != (const Command &cmd) const {
- bool ret = (type != cmd.type);
- for (int i=0; !ret && i < numParams(); i++)
- ret |= (params[i] != cmd.params[i]);
- return ret;
- }
+ private:
+ std::ostream &_os; ///< write output to this stream
+ bool _relative; ///< if true, use relative coordinates in path commands
+ double _sx, _sy; ///< horizontal and vertical scaling factors
+ double _dx, _dy; ///< horizontal and vertical translation values
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ /** Calls the corresponding template method of an Action object for the current path command.
+ * If parameter 'useShortCmds' is true, the visitor operators check whether a command
+ * can be shortened due to special cases, e.g. horizontal or vertical lines, smooth
+ * curve connections etc. Otherwise, the full command templates are triggered. */
+ class IterationVisitor {
+ public:
+ IterationVisitor (IterationActions &actions, bool useShortCmds, double eps=1e-7)
+ : _actions(actions), _shortCommandsActive(useShortCmds), _eps(eps) {}
+
+ void setPrevCommand (const CommandVariant &prevCommand) {
+ _prevCommand = &prevCommand;
+ }
+
+ void operator () (const MoveTo &cmd) {
+ _actions.moveto(cmd.points[0]);
+ _actions._startPoint = _actions._currentPoint = cmd.points[0];
+ }
+
+ void operator () (const LineTo &cmd) {
+ Point diff = abs(_actions._currentPoint-cmd.points[0]);
+ if (diff.x() >= _eps || diff.y() >= _eps) {
+ if (!_shortCommandsActive)
+ _actions.lineto(cmd.points[0]);
+ else {
+ if (diff.x() < _eps)
+ _actions.vlineto(cmd.points[0].y());
+ else if (diff.y() < _eps)
+ _actions.hlineto(cmd.points[0].x());
+ else
+ _actions.lineto(cmd.points[0]);
+ }
+ }
+ _actions._currentPoint = cmd.points[0];
+ }
+
+ void operator () (const CubicTo &cmd) {
+ bool smooth=false;
+ if (_shortCommandsActive) {
+ if (auto *prevCubic = mpark::get_if<CubicTo>(_prevCommand)) {
+ Point diff = abs(cmd.points[0] - prevCubic->points[2]*T(2) + prevCubic->points[1]);
+ if ((smooth = (diff.x() < _eps && diff.y() < _eps)))
+ _actions.cubicto(cmd.points[1], cmd.points[2]);
+ }
+ }
+ if (!smooth)
+ _actions.cubicto(cmd.points[0], cmd.points[1], cmd.points[2]);
+ _actions._currentPoint = cmd.points[2];
+ }
+
+ void operator () (const QuadTo &cmd) {
+ bool smooth=false;
+ if (_shortCommandsActive) {
+ if (auto *prevQuad = mpark::get_if<QuadTo>(_prevCommand)) {
+ Point diff = abs(cmd.points[0] - prevQuad->points[1] * T(2) + prevQuad->points[0]);
+ if ((smooth = (diff.x() < _eps && diff.y() < _eps))) // is reflection?
+ _actions.quadto(cmd.points[1]);
+ }
+ }
+ if (!smooth)
+ _actions.quadto(cmd.points[0], cmd.points[1]);
+ _actions._currentPoint = cmd.points[1];
+ }
+
+ void operator () (const ClosePath &cmd) {
+ _actions.closepath();
+ _actions._currentPoint = _actions._startPoint;
+ }
+
+ void operator () (const ArcTo &cmd) {
+ _actions.arcto(cmd.rx, cmd.ry, cmd.xrotation, cmd.largeArcFlag, cmd.sweepFlag, cmd.points[0]);
+ _actions._currentPoint = cmd.points[0];
+ }
- Type type;
- Point params[3];
+ private:
+ IterationActions &_actions;
+ bool _shortCommandsActive=false;
+ double _eps=1e-7;
+ const CommandVariant *_prevCommand=nullptr;
};
- struct Actions {
- virtual ~Actions () =default;
- virtual void moveto (const Point &p) {}
- virtual void lineto (const Point &p) {}
- virtual void hlineto (const T &y) {}
- virtual void vlineto (const T &x) {}
- virtual void conicto (const Point &p) {}
- virtual void conicto (const Point &p1, const Point &p2) {}
- virtual void cubicto (const Point &p1, const Point &p2) {}
- virtual void cubicto (const Point &p1, const Point &p2, const Point &p3) {}
- virtual void closepath () {}
- virtual void draw (char cmd, const Point *points, int n) {}
- virtual bool quit () {return false;}
- virtual void finished () {}
+ ///////////////////////////////////////////////////////////////////////////////
+
+ /** Transforms all Point parameters of a path command. */
+ class TransformVisior {
+ public:
+ explicit TransformVisior (const Matrix &m) : matrix(m) {}
+
+ template <typename Cmd> void operator () (Cmd &cmd) {
+ Point cp = cmd.point(cmd.numPoints()-1);
+ cmd.transform(matrix, _currentPoint);
+ _currentPoint = cp;
+ }
+
+ void operator () (MoveTo &cmd) {
+ Point cp = cmd.point(0);
+ cmd.transform(matrix, _currentPoint);
+ _startPoint = _currentPoint = cp;
+ }
+
+ void operator () (ClosePath &cmd) {
+ _currentPoint = _startPoint;
+ }
+
+ private:
+ const Matrix &matrix;
+ Point _startPoint, _currentPoint; ///< untransformed start end current point
};
public:
- GraphicsPath (WindingRule wr=WindingRule::NON_ZERO) : _windingRule(wr) {}
+ explicit GraphicsPath (WindingRule wr=WindingRule::NON_ZERO) : _windingRule(wr) {}
void setWindingRule (WindingRule wr) {_windingRule = wr;}
WindingRule windingRule () const {return _windingRule;}
@@ -127,6 +452,9 @@ class GraphicsPath {
return _commands.size();
}
+ const Point& startPoint () const {return _startPoint;}
+ const Point& finalPoint () const {return _finalPoint;}
+
/// Insert another path at the beginning of this one.
void prepend (const GraphicsPath &path) {
_commands.insert(_commands.begin(), path._commands.begin(), path._commands.end());
@@ -138,10 +466,11 @@ class GraphicsPath {
void moveto (const Point &p) {
// avoid sequences of several MOVETOs; always use latest
- if (_commands.empty() || _commands.back().type != Command::Type::MOVETO)
- _commands.emplace_back(Command(Command::Type::MOVETO, p));
+ if (_commands.empty() || !mpark::get_if<MoveTo>(&_commands.back()))
+ _commands.emplace_back(MoveTo{p});
else
- _commands.back().params[0] = p;
+ mpark::get<MoveTo>(_commands.back()).points[0] = p;
+ _startPoint = _finalPoint = p;
}
void lineto (const T &x, const T &y) {
@@ -149,57 +478,94 @@ class GraphicsPath {
}
void lineto (const Point &p) {
- _commands.emplace_back(Command(Command::Type::LINETO, p));
+ _commands.emplace_back(LineTo{p});
+ _finalPoint = p;
}
- void conicto (const T &x1, const T &y1, const T &x2, const T &y2) {
- conicto(Point(x1, y1), Point(x2, y2));
+ void quadto (const T &x1, const T &y1, const T &x2, const T &y2) {
+ quadto(Point(x1, y1), Point(x2, y2));
}
- void conicto (const Point &p1, const Point &p2) {
- _commands.emplace_back(Command(Command::Type::CONICTO, p1, p2));
+ /** Creates a quadratic Bézier segment. */
+ void quadto (const Point &p1, const Point &p2) {
+ _commands.emplace_back(QuadTo{p1, p2});
+ _finalPoint = p2;
+ }
+
+ /** Creates a quadratic Bézier segment smoothly extending a preceding one, i.e. the gradients
+ * of the two curves are identical at the connection point. The control point of the second
+ * curve is computed as the reflection of the preceding curve's control point at the connection
+ * point. */
+ void quadto (const Point &p2) {
+ Point p1;
+ if (!_commands.empty()) {
+ if (auto qto = mpark::get_if<QuadTo>(&_commands.back()))
+ p1 = _finalPoint*T(2) - qto->point(0); // reflect previous control point at current point
+ else // previous command isn't a quadto?
+ p1 = _finalPoint; // => use current point as control point
+ }
+ quadto(p1, p2);
}
void cubicto (const T &x1, const T &y1, const T &x2, const T &y2, const T &x3, const T &y3) {
cubicto(Point(x1, y1), Point(x2, y2), Point(x3, y3));
}
+ /** Creates a cubic Bézier segment. */
void cubicto (const Point &p1, const Point &p2, const Point &p3) {
- _commands.emplace_back(Command(Command::Type::CUBICTO, p1, p2, p3));
+ _commands.emplace_back(CubicTo{p1, p2, p3});
+ _finalPoint = p3;
}
- void closepath () {
- _commands.emplace_back(Command(Command::Type::CLOSEPATH));
+ /** Creates a cubic Bézier segment smoothly extending a preceding one, i.e. the gradients
+ * of the two curves are identical at the connection point. The first control point of
+ * the second curve is computed as the reflection of the preceding curve's second control
+ * point at the connection point. */
+ void cubicto (const Point &p2, const Point &p3) {
+ Point p1;
+ if (!_commands.empty()) {
+ if (auto cto = mpark::get_if<CubicTo>(&_commands.back()))
+ p1 = _finalPoint*T(2) - cto->point(1); // reflect previous control point at current point
+ else // previous command isn't a cubicto?
+ p1 = _finalPoint; // => use current point as control point
+ }
+ cubicto(p1, p2, p3);
}
- const std::vector<Command>& commands () const {
- return _commands;
+ void closepath () {
+ if (!_commands.empty() && !mpark::get_if<ClosePath>(&_commands.back())) {
+ _commands.emplace_back(ClosePath{});
+ _finalPoint = _startPoint;
+ }
}
+ void arcto (double rx, double ry, double angle, bool laf, bool sweep, const Point &p) {
+ _commands.emplace_back(ArcTo{rx, ry, angle, laf, sweep, p});
+ _finalPoint = p;
+ }
/** Detects all open subpaths and closes them by adding a closePath command.
* Most font formats only support closed outline paths so there are no explicit closePath statements
* in the glyph's outline description. All open paths are automatically closed by the renderer.
* This method detects all open paths and adds the missing closePath statement. */
void closeOpenSubPaths () {
- Command *prevCommand=0;
+ CommandVariant *prevCmd = nullptr;
for (auto it=_commands.begin(); it != _commands.end(); ++it) {
- if (it->type == Command::Type::MOVETO && prevCommand && prevCommand->type != Command::Type::CLOSEPATH) {
- prevCommand = &(*it);
- it = _commands.insert(it, Command(Command::Type::CLOSEPATH))+1;
+ if (mpark::get_if<MoveTo>(&*it) && prevCmd && !mpark::get_if<ClosePath>(prevCmd)) {
+ prevCmd = &*it;
+ it = _commands.insert(it, ClosePath{})+1;
}
else
- prevCommand = &(*it);
+ prevCmd = &*it;
}
- if (!_commands.empty() && _commands.back().type != Command::Type::CLOSEPATH)
+ if (!_commands.empty() && !mpark::get_if<ClosePath>(&_commands.back()))
closepath();
}
-
- /** Removes redundant path commands commands. Currently, it only removes movetos. */
+ /** Removes redundant path commands commands. Currently, only removes movetos. */
void removeRedundantCommands () {
// remove trailing moveto commands
- while (!_commands.empty() && _commands.back().type == Command::Type::MOVETO)
+ while (!_commands.empty() && mpark::get_if<MoveTo>(&_commands.back()))
_commands.pop_back();
// resolve intermediate sequences of moveto commands
auto it=_commands.begin();
@@ -207,7 +573,7 @@ class GraphicsPath {
return;
auto prev = it++;
while (it != _commands.end()) {
- if (prev->type != Command::Type::MOVETO || it->type != Command::Type::MOVETO)
+ if (!mpark::get_if<MoveTo>(&*prev) || !mpark::get_if<MoveTo>(&*it))
prev = it++;
else {
prev = _commands.erase(prev); // remove leading MOVETO and advance 'prev' to 'it'
@@ -216,7 +582,6 @@ class GraphicsPath {
}
}
-
/** Writes the path data as SVG path drawing command to a given output stream.
* @param[in] os output stream used to write the SVG commands to
* @param[in] relative if true, create relative rather than absolute coordinate values
@@ -225,94 +590,38 @@ class GraphicsPath {
* @param[in] dx horizontal translation in PS point units
* @param[in] dy vertical translation in PS point units */
void writeSVG (std::ostream &os, bool relative, double sx=1.0, double sy=1.0, double dx=0.0, double dy=0.0) const {
- struct WriteActions : Actions {
- WriteActions (std::ostream &os, bool relative, double sx, double sy, double dx, double dy)
- : _os(os), _relative(relative), _sx(sx), _sy(sy), _dx(dx), _dy(dy) {}
-
- void draw (char cmd, const Point *points, int n) override {
- if (_relative)
- cmd = tolower(cmd);
- _os << cmd;
- switch (cmd) {
- case 'h': _os << XMLString(_sx*(points->x()-_currentPoint.x())+_dx); break;
- case 'v': _os << XMLString(_sy*(points->y()-_currentPoint.y())+_dy); break;
- case 'z': _currentPoint = _startPoint; break;
- case 'H': _os << XMLString(_sx*points->x()+_dx); break;
- case 'V': _os << XMLString(_sy*points->y()+_dy); break;
- default :
- for (int i=0; i < n; i++) {
- if (i > 0)
- _os << ' ';
- Point p = points[i];
- if (_relative)
- p -= _currentPoint;
- _os << XMLString(_sx*p.x()+_dx) << ' ' << XMLString(_sy*p.y()+_dy);
- }
- }
- if (cmd == 'm')
- _startPoint = points[0];
- if (islower(cmd) && n > 0)
- _currentPoint = points[n-1];
- }
- std::ostream &_os;
- bool _relative;
- double _sx, _sy, _dx, _dy;
- Point _startPoint, _currentPoint;
- } actions(os, relative, sx, sy, dx, dy);
+ WriteActions actions(os, relative, sx, sy, dx, dy);
iterate(actions, true);
}
-#if 0
- void writePS (std::ostream &os, double sx=1.0, double sy=1.0, double dx=0.0, double dy=0.0) const {
- struct WriteActions : Actions {
- WriteActions (std::ostream &os, double sx, double sy, double dx, double dy)
- : _os(os), _sx(sx), _sy(sy), _dx(dx), _dy(dy) {}
- void draw (char cmd, const Point *points, int n) {
- for (int i=0; i < n; i++)
- _os << _sx*points[i].x()+_dx << ' ' << _sy*points[i].y()+_dy << ' ';
- switch (cmd) {
- case 'M': _os << "moveto"; break;
- case 'L': _os << "lineto"; break;
- case 'C': _os << "curveto"; break;
- case 'Z': _os << "closepath"; break;
- default: ;
- }
- _os << '\n';
- }
- std::ostream &_os;
- bool _relative;
- double _sx, _sy, _dx, _dy;
- } actions(os, sx, sy, dx, dy);
- iterate(actions, false);
- }
-#endif
-
-
/** Computes the bounding box of the current path.
* @param[out] bbox the computed bounding box */
void computeBBox (BoundingBox &bbox) const {
- struct BBoxActions : Actions {
- BBoxActions (BoundingBox &bb) : bbox(bb) {}
+ struct BBoxActions : IterationActions {
+ explicit BBoxActions (BoundingBox &bb) : bbox(bb) {}
void moveto (const Point &p) override {bbox.embed(p);}
void lineto (const Point &p) override {bbox.embed(p);}
- void conicto (const Point &p1, const Point &p2) override {bbox.embed(p1); bbox.embed(p2);}
+ void quadto (const Point &p1, const Point &p2) override {bbox.embed(p1); bbox.embed(p2);}
void cubicto (const Point &p1, const Point &p2, const Point &p3) override {bbox.embed(p1); bbox.embed(p2); bbox.embed(p3);}
+ void arcto (T rx, T ry, double angle, bool laf, bool sweep, const Point &p) override {
+ bbox.embed(EllipticalArc(this->currentPoint(), double(rx), double(ry), angle, laf, sweep, p).getBBox());
+ }
BoundingBox &bbox;
} actions(bbox);
iterate(actions, false);
}
-
/** Checks whether the current path describes a dot/point only (with no extent).
* @param[out] p coordinates of the point if path describes a dot
* @return true if path is a dot/point */
bool isDot (Point &p) const {
- struct DotActions : Actions {
+ struct DotActions : IterationActions {
DotActions () : differs(false) {}
void moveto (const Point &p) override {point = p;}
void lineto (const Point &p) override {differs = (p != point);}
- void conicto (const Point &p1, const Point &p2) override {differs = (point != p1 || point != p2);}
+ void quadto (const Point &p1, const Point &p2) override { differs = (point != p1 || point != p2);}
void cubicto (const Point &p1, const Point &p2, const Point &p3) override {differs = (point != p1 || point != p2 || point != p3);}
+ void arcto (T rx, T ry, double angle, bool largeArcFlag, bool sweepFlag, const Point &p) override { differs = (point != p);}
bool quit () override {return differs;}
Point point;
bool differs;
@@ -322,125 +631,105 @@ class GraphicsPath {
return !actions.differs;
}
+ /** Replaces all elliptic arcs with cubic Bézier curves. */
+ void approximateArcs () {
+ struct ArcActions : ModificationActions {
+ explicit ArcActions (GraphicsPath &path) : ModificationActions(path) {}
+ void arcto (T rx, T ry, double angle, bool largeArcFlag, bool sweepFlag, const Point &p) override {
+ EllipticalArc arc(this->currentPoint(), rx, ry, angle, largeArcFlag, sweepFlag, p);
+ std::vector<CommandVariant> cmds;
+ for (const Bezier &bezier : arc.approximate())
+ cmds.emplace_back(CubicTo{bezier.point(1), bezier.point(2), bezier.point(3)});
+ this->path().replace(this->commandPos(), cmds);
+ }
+ } actions(*this);
+ iterate(actions);
+ }
/** Transforms the path according to a given Matrix.
* @param[in] matrix Matrix describing the affine transformation */
void transform (const Matrix &matrix) {
- for (Command &command : _commands)
- command.transform(matrix);
+ TransformVisior visior(matrix);
+ for (CommandVariant &command : _commands)
+ mpark::visit(visior, command);
}
-
+ /** Returns true if this path equals another one, i.e. it consists the same sequence
+ * of commands and coordinates. */
bool operator == (const GraphicsPath &path) const {
if (size() != path.size())
return false;
auto it = _commands.begin();
- for (const Command &cmd : path._commands) {
+ for (const auto &cmd : path._commands) {
if (*it++ != cmd)
return false;
}
return true;
}
-
+ /** Returns true if this path differs from another one (command-wise). */
bool operator != (const GraphicsPath &path) const {
if (size() != path.size())
return true;
auto it = _commands.begin();
- for (const Command &cmd : path._commands) {
+ for (const auto &cmd : path._commands) {
if (*it++ != cmd)
return true;
}
return false;
}
+ /** Iterates over all commands defining this path and calls the corresponding template methods.
+ * In the case of successive bezier curve sequences, control points or tangent slopes are often
+ * identical so that the path description contains redundant information. SVG provides shorthand
+ * curve commands that require less parameters. If 'optimize' is true, this method detects such
+ * command sequences.
+ * @param[in] actions template methods called by each iteration step
+ * @param[in] optimize if true, shorthand drawing commands (hlineto, vlineto,...) are considered */
+ void iterate (IterationActions &actions, bool optimize) const {
+ double eps = XMLString::DECIMAL_PLACES > 0 ? pow(10, -XMLString::DECIMAL_PLACES) : 1e-7;
+ IterationVisitor visitor(actions, optimize, eps);
+ for (const CommandVariant &cmd : _commands) {
+ if (actions.quit())
+ break;
+ mpark::visit(visitor, cmd);
+ visitor.setPrevCommand(cmd);
+ }
+ actions.finished();
+ }
- void iterate (Actions &actions, bool optimize) const;
+ protected:
+ /** Replaces a command by a sequence of other ones.
+ * @param[in] pos position of command to replace (0-based)
+ * @param[in] cmds commands to insert */
+ void replace (int pos, const std::vector<CommandVariant> &cmds) {
+ auto it = _commands.end();
+ if (!_commands.empty()) {
+ it = _commands.begin()+pos;
+ it = _commands.erase(it);
+ }
+ _commands.insert(it, cmds.begin(), cmds.end());
+ }
+
+ /** Iterates over all commands of the path and calls the corresponding template methods.
+ * In contrast to the public iterate() method, this one allows to modify the command sequence.
+ * @param[in] actions template methods called by each iteration step */
+ void iterate (ModificationActions &actions) {
+ IterationVisitor visitor(actions, false);
+ // no iterators here since they may be invalidated during path modifications
+ for (size_t i=0; i < _commands.size(); i++) {
+ if (actions.quit())
+ break;
+ actions._commandPos = i;
+ mpark::visit(visitor, _commands[i]);
+ visitor.setPrevCommand(_commands[i]);
+ }
+ actions.finished();
+ }
private:
- std::deque<Command> _commands;
+ std::deque<CommandVariant> _commands; ///< sequence of path commands
WindingRule _windingRule;
+ Point _startPoint; ///< start point of final sub-path
+ Point _finalPoint; ///< final point reached by last command in path
};
-
-
-/** Iterates over all commands defining this path and calls the corresponding template methods.
- * In the case of successive bezier curve sequences, control points or tangent slopes are often
- * identical so that the path description contains redundant information. SVG provides shorthand
- * curve commands that require less parameters. If 'optimize' is true, this method detects such
- * command sequences.
- * @param[in] actions template methods called by each iteration step
- * @param[in] optimize if true, shorthand drawing commands (hlineto, vlineto,...) are considered */
-template <typename T>
-void GraphicsPath<T>::iterate (Actions &actions, bool optimize) const {
- auto prev = _commands.end(); // pointer to preceding command
- Point fp; // first point of current path
- Point cp; // current point
- Point pstore[2];
- for (auto it=_commands.begin(); it != _commands.end() && !actions.quit(); ++it) {
- const Point *params = it->params;
- switch (it->type) {
- case Command::Type::MOVETO:
- actions.moveto(params[0]);
- actions.draw('M', params, 1);
- fp = params[0];
- break;
- case Command::Type::LINETO:
- if (optimize) {
- if (cp.x() == params[0].x()) {
- actions.vlineto(params[0].y());
- actions.draw('V', params, 1);
- }
- else if (cp.y() == params[0].y()) {
- actions.hlineto(params[0].x());
- actions.draw('H', params, 1);
- }
- else {
- actions.lineto(params[0]);
- actions.draw('L', params, 1);
- }
- }
- else {
- actions.lineto(params[0]);
- actions.draw('L', params, 1);
- }
- break;
- case Command::Type::CONICTO:
- if (optimize && prev != _commands.end() && prev->type == Command::Type::CONICTO && params[0] == pstore[1]*T(2)-pstore[0]) {
- actions.conicto(params[1]);
- actions.draw('T', params+1, 1);
- }
- else {
- actions.conicto(params[0], params[1]);
- actions.draw('Q', params, 2);
- }
- pstore[0] = params[0]; // store control point and
- pstore[1] = params[1]; // curve endpoint
- break;
- case Command::Type::CUBICTO:
- // is first control point reflection of preceding second control point?
- if (optimize && prev != _commands.end() && prev->type == Command::Type::CUBICTO && params[0] == pstore[1]*T(2)-pstore[0]) {
- actions.cubicto(params[1], params[2]);
- actions.draw('S', params+1, 2);
- }
- else {
- actions.cubicto(params[0], params[1], params[2]);
- actions.draw('C', params, 3);
- }
- pstore[0] = params[1]; // store second control point and
- pstore[1] = params[2]; // curve endpoint
- break;
- case Command::Type::CLOSEPATH:
- actions.closepath();
- actions.draw('Z', params, 0);
- cp = fp;
- }
- // update current point
- const int np = it->numParams();
- if (np > 0)
- cp = it->params[np-1];
- prev = it;
- }
- actions.finished();
-}
-
-#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.cpp
index 7479fca604f..517cc8f3ccb 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.cpp
@@ -31,7 +31,12 @@ using namespace std;
/** Returns a vector containing the names of the currently supported hash algorithms. */
vector<string> HashFunction::supportedAlgorithms () {
- return vector<string> {"md5", "xxh32", "xxh64"};
+ return vector<string> {
+ "md5", "xxh32", "xxh64",
+#ifdef ENABLE_XXH128
+ "xxh128"
+#endif
+ };
}
@@ -52,6 +57,10 @@ unique_ptr<HashFunction> HashFunction::create (const string &name) {
return util::make_unique<XXH32HashFunction>();
if (lowerName == "xxh64")
return util::make_unique<XXH64HashFunction>();
+#ifdef ENABLE_XXH128
+ if (lowerName == "xxh128")
+ return util::make_unique<XXH128HashFunction>();
+#endif
return nullptr;
}
@@ -74,6 +83,15 @@ std::unique_ptr<HashFunction> HashFunction::create (const string &name, const ve
}
+void HashFunction::update (istream &is) {
+ char buf[4096];
+ while (is) {
+ is.read(buf, 4096);
+ update(buf, is.gcount());
+ }
+}
+
+
/** Returns the current digest as hexadecimal value. */
string HashFunction::digestString () const {
ostringstream oss;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.hpp
index 1b1259393fa..bba61918ed9 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/HashFunction.hpp
@@ -21,6 +21,7 @@
#ifndef HASHFUNCTION_HPP
#define HASHFUNCTION_HPP
+#include <istream>
#include <memory>
#include <string>
#include <vector>
@@ -35,6 +36,7 @@ class HashFunction {
virtual void update (const std::string &data) =0;
virtual void update (const std::vector<uint8_t> &data) =0;
virtual std::vector<uint8_t> digestValue () const =0;
+ void update (std::istream &is);
std::string digestString () const;
static std::vector<std::string> supportedAlgorithms ();
static bool isSupportedAlgorithm (const std::string &algo);
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp
index b7f4e9664f6..43d3dbc2244 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/HtmlSpecialHandler.cpp
@@ -31,7 +31,7 @@ void HtmlSpecialHandler::preprocess (const string&, istream &is, SpecialActions
ir.skipSpace();
// collect page number and ID of named anchors
map<string,string> attribs;
- if (ir.check("<a ") && ir.parseAttributes(attribs, "\"") > 0) {
+ if (ir.check("<a ") && ir.parseAttributes(attribs, true, "\"") > 0) {
map<string,string>::iterator it;
if ((it = attribs.find("name")) != attribs.end())
HyperlinkManager::instance().addNameAchor(it->second, actions.getCurrentPageNumber());
@@ -47,7 +47,7 @@ bool HtmlSpecialHandler::process (const string&, istream &is, SpecialActions &ac
ir.skipSpace();
map<string,string> attribs;
map<string,string>::iterator it;
- if (ir.check("<a ") && ir.parseAttributes(attribs, "\"") > 0) {
+ if (ir.check("<a ") && ir.parseAttributes(attribs, true, "\"") > 0) {
if ((it = attribs.find("href")) != attribs.end()) // <a href="URI">
HyperlinkManager::instance().createLink(it->second, actions);
else if ((it = attribs.find("name")) != attribs.end()) // <a name="ID">
@@ -59,7 +59,7 @@ bool HtmlSpecialHandler::process (const string&, istream &is, SpecialActions &ac
HyperlinkManager::instance().closeAnchor(actions);
else if (ir.check("<img src=")) {
}
- else if (ir.check("<base ") && ir.parseAttributes(attribs, "\"") > 0 && (it = attribs.find("href")) != attribs.end())
+ else if (ir.check("<base ") && ir.parseAttributes(attribs, true, "\"") > 0 && (it = attribs.find("href")) != attribs.end())
HyperlinkManager::instance().setBaseUrl(it->second);
return true;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.cpp
index 9d610426808..de412afcdc0 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/HyperlinkManager.cpp
@@ -88,7 +88,7 @@ void HyperlinkManager::createLink (string uri, SpecialActions &actions) {
string name;
if (uri[0] == '#') { // reference to named anchor?
name = uri.substr(1);
- NamedAnchors::iterator it = _namedAnchors.find(name);
+ auto it = _namedAnchors.find(name);
if (it == _namedAnchors.end() || it->second.id < 0)
Message::wstream(true) << "reference to undefined anchor '" << name << "'\n";
else {
@@ -96,7 +96,7 @@ void HyperlinkManager::createLink (string uri, SpecialActions &actions) {
uri = "#loc"+XMLString(id);
if (actions.getCurrentPageNumber() != it->second.pageno) {
ostringstream oss;
- oss << actions.getSVGFilename(it->second.pageno) << uri;
+ oss << actions.getSVGFilePath(it->second.pageno).relative() << uri;
uri = oss.str();
}
}
@@ -106,10 +106,10 @@ void HyperlinkManager::createLink (string uri, SpecialActions &actions) {
uri = "/" + uri;
uri = _base + uri;
}
- auto anchorNode = util::make_unique<XMLElementNode>("a");
+ auto anchorNode = util::make_unique<XMLElement>("a");
anchorNode->addAttribute("xlink:href", uri);
anchorNode->addAttribute("xlink:title", XMLString(name.empty() ? uri : name, false));
- actions.pushContextElement(std::move(anchorNode));
+ actions.svgTree().pushPageContext(std::move(anchorNode));
actions.bbox("{anchor}", true); // start computing the bounding box of the linked area
_depthThreshold = actions.getDVIStackDepth();
_anchorType = AnchorType::HREF;
@@ -119,7 +119,7 @@ void HyperlinkManager::createLink (string uri, SpecialActions &actions) {
void HyperlinkManager::closeAnchor (SpecialActions &actions) {
if (_anchorType == AnchorType::HREF) {
markLinkedBox(actions);
- actions.popContextElement();
+ actions.svgTree().popPageContext();
_depthThreshold = 0;
}
_anchorType = AnchorType::NONE;
@@ -148,7 +148,7 @@ void HyperlinkManager::markLinkedBox (SpecialActions &actions) {
if (bbox.width() > 0 && bbox.height() > 0) { // does the bounding box extend in both dimensions?
if (MARKER_TYPE != MarkerType::NONE) {
const double linewidth = _linewidth >= 0 ? _linewidth : min(0.5, bbox.height()/15);
- auto rect = util::make_unique<XMLElementNode>("rect");
+ auto rect = util::make_unique<XMLElement>("rect");
double x = bbox.minX();
double y = bbox.maxY()+linewidth;
double w = bbox.width();
@@ -179,7 +179,7 @@ void HyperlinkManager::markLinkedBox (SpecialActions &actions) {
rect->addAttribute("y", y);
rect->addAttribute("width", w);
rect->addAttribute("height", h);
- actions.prependToPage(std::move(rect));
+ actions.svgTree().prependToPage(std::move(rect));
if (MARKER_TYPE == MarkerType::BOX || MARKER_TYPE == MarkerType::BGCOLOR) {
// slightly enlarge the boxed area
x -= linewidth/2;
@@ -192,14 +192,14 @@ void HyperlinkManager::markLinkedBox (SpecialActions &actions) {
// Create an invisible rectangle around the linked area so that it's easier to access.
// This is only necessary when using paths rather than real text elements together with fonts.
if (!SVGTree::USE_FONTS) {
- auto rect = util::make_unique<XMLElementNode>("rect");
+ auto rect = util::make_unique<XMLElement>("rect");
rect->addAttribute("x", bbox.minX());
rect->addAttribute("y", bbox.minY());
rect->addAttribute("width", bbox.width());
rect->addAttribute("height", bbox.height());
rect->addAttribute("fill", "white");
rect->addAttribute("fill-opacity", 0);
- actions.appendToPage(std::move(rect));
+ actions.svgTree().appendToPage(std::move(rect));
}
}
}
@@ -213,10 +213,10 @@ void HyperlinkManager::createViews (unsigned pageno, SpecialActions &actions) {
ostringstream oss;
oss << pagebox.minX() << ' ' << stranchorpair.second.pos << ' '
<< pagebox.width() << ' ' << pagebox.height();
- auto view = util::make_unique<XMLElementNode>("view");
+ auto view = util::make_unique<XMLElement>("view");
view->addAttribute("id", "loc"+XMLString(stranchorpair.second.id));
view->addAttribute("viewBox", oss.str());
- actions.appendToDefs(std::move(view));
+ actions.svgTree().appendToDefs(std::move(view));
}
}
closeAnchor(actions);
@@ -229,7 +229,7 @@ void HyperlinkManager::createViews (unsigned pageno, SpecialActions &actions) {
bool HyperlinkManager::setLinkMarker (const string &marker) {
string type; // "none", "box", "line", or a background color specifier
string color; // optional line color specifier
- size_t seppos = marker.find(":");
+ size_t seppos = marker.find(':');
if (seppos == string::npos)
type = marker;
else {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.cpp
index 294b6adf951..26edb3c753c 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.cpp
@@ -27,6 +27,7 @@
#include "MessageException.hpp"
#include "PageRanges.hpp"
#include "PsSpecialHandler.hpp"
+#include "optimizer/SVGOptimizer.hpp"
#include "SVGOutput.hpp"
#include "System.hpp"
#include "utility.hpp"
@@ -72,19 +73,19 @@ void ImageToSVG::convert (int pageno) {
_psHandler.process(psSpecialCmd(), ss, *this);
}
catch (...) {
- progress(0); // remove progress message
+ progress(nullptr); // remove progress message
throw;
}
- progress(0);
+ progress(nullptr);
Matrix matrix = getUserMatrix(_bbox);
// output SVG file
- _svg.removeRedundantElements();
+ SVGOptimizer(_svg).execute();
_svg.transformPage(matrix);
_bbox.transform(matrix);
_svg.setBBox(_bbox);
- _svg.appendToDoc(util::make_unique<XMLCommentNode>(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " "));
+ _svg.appendToDoc(util::make_unique<XMLComment>(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " "));
bool success = _svg.write(_out.getPageStream(pageno, totalPageCount()));
- string svgfname = _out.filename(pageno, totalPageCount());
+ string svgfname = _out.filepath(pageno, totalPageCount()).shorterAbsoluteOrRelative();
if (svgfname.empty())
svgfname = "<stdout>";
if (!success)
@@ -144,10 +145,11 @@ void ImageToSVG::convert (const std::string &rangestr, pair<int,int> *pageinfo)
}
-string ImageToSVG::getSVGFilename (unsigned pageno) const {
+FilePath ImageToSVG::getSVGFilePath (unsigned pageno) const {
+ FilePath path;
if (pageno == 1)
- return _out.filename(1, 1);
- return "";
+ path = _out.filepath(1, 1);
+ return path;
}
@@ -162,13 +164,13 @@ void ImageToSVG::progress (const char *id) {
Terminal::cursor(false);
Message::mstream(false) << "\n";
}
- if (draw && ((System::time() - time > 0.05) || id == 0)) {
+ if (draw && ((System::time() - time > 0.05) || id == nullptr)) {
const size_t DIGITS=6;
Message::mstream(false, Message::MC_PROGRESS)
<< string(DIGITS-min(DIGITS, static_cast<size_t>(log10(count))), ' ')
<< count << " PostScript instructions processed\r";
// overprint indicator when finished
- if (id == 0) {
+ if (id == nullptr) {
Message::estream().clearline();
Terminal::cursor(true);
}
@@ -190,7 +192,7 @@ Matrix ImageToSVG::getUserMatrix (const BoundingBox &bbox) const {
calc.setVariable("w", bbox.width()*bp2pt);
calc.setVariable("h", bbox.height()*bp2pt);
// add constants for length units to calculator
- for (auto unit : Length::getUnits())
+ for (const auto &unit : Length::getUnits())
calc.setVariable(unit.first, Length(1, unit.second).pt());
matrix.set(_transCmds, calc);
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.hpp
index dcbce9b3242..a4e4de223f6 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ImageToSVG.hpp
@@ -32,8 +32,7 @@ struct SVGOutputBase;
class ImageToSVG : protected SpecialActions {
public:
- ImageToSVG (const std::string &fname, SVGOutputBase &out) : _fname(fname), _out(out) {}
- virtual ~ImageToSVG () =default;
+ ImageToSVG (std::string fname, SVGOutputBase &out) : _fname(std::move(fname)), _out(out) {}
void convert (int pageno);
void convert (int firstPage, int lastPage, std::pair<int,int> *pageinfo);
void convert (const std::string &rangestr, std::pair<int,int> *pageinfo);
@@ -61,19 +60,15 @@ class ImageToSVG : protected SpecialActions {
Color getColor () const override {return _svg.getColor();}
void setMatrix (const Matrix &m) override {_svg.setMatrix(m);}
const Matrix& getMatrix () const override {return _svg.getMatrix();}
+ const SVGTree& svgTree () const override {return _svg;}
void setBgColor (const Color &color) override {}
- void appendToPage(std::unique_ptr<XMLNode> &&node) override {_svg.appendToPage(std::move(node));}
- void appendToDefs(std::unique_ptr<XMLNode> &&node) override {_svg.appendToDefs(std::move(node));}
- void prependToPage(std::unique_ptr<XMLNode> &&node) override {_svg.prependToPage(std::move(node));}
- void pushContextElement (std::unique_ptr<XMLElementNode> &&node) override {_svg.pushContextElement(std::move(node));}
- void popContextElement () override {_svg.popContextElement();}
void embed (const BoundingBox &bbox) override {_bbox.embed(bbox);}
void embed (const DPair &p, double r=0) override {if (r==0) _bbox.embed(p); else _bbox.embed(p, r);}
void progress (const char *id) override;
unsigned getCurrentPageNumber() const override {return 0;}
BoundingBox& bbox () override {return _bbox;}
BoundingBox& bbox (const std::string &name, bool reset=false) override {return _bbox;}
- std::string getSVGFilename (unsigned pageno) const override;
+ FilePath getSVGFilePath (unsigned pageno) const override;
std::string getBBoxFormatString () const override {return "";}
private:
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp
index b144d34336d..8a62b6b0118 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputBuffer.hpp
@@ -27,8 +27,7 @@
#include <string>
#include <ostream>
-struct InputBuffer
-{
+struct InputBuffer {
virtual ~InputBuffer () =default;
virtual int get () =0;
virtual int peek () const =0;
@@ -38,11 +37,10 @@ struct InputBuffer
};
-class StreamInputBuffer : public InputBuffer
-{
+class StreamInputBuffer : public InputBuffer {
public:
- StreamInputBuffer (std::istream &is, size_t bufsize=1024);
- ~StreamInputBuffer ();
+ explicit StreamInputBuffer (std::istream &is, size_t bufsize=1024);
+ ~StreamInputBuffer () override;
int get () override;
int peek () const override;
int peek (size_t n) const override;
@@ -64,24 +62,23 @@ class StreamInputBuffer : public InputBuffer
};
-class StringInputBuffer : public InputBuffer
-{
+class StringInputBuffer : public InputBuffer {
public:
- StringInputBuffer (const std::string &str) : _str(str), _pos(0) {}
- int get () override {return _pos < _str.length() ? _str[_pos++] : -1;}
- int peek () const override {return _pos < _str.length() ? _str[_pos] : -1;}
- int peek (size_t n) const override {return _pos+n < _str.length() ? _str[_pos+n] : -1;}
- bool eof () const override {return _pos >= _str.length();}
- void invalidate () override {_pos = _str.length();}
+ explicit StringInputBuffer (const std::string &str) : _str(&str) {}
+ void assign (const std::string &str) {_str = &str; _pos=0;}
+ int get () override {return _pos < _str->length() ? _str->at(_pos++) : -1;}
+ int peek () const override {return _pos < _str->length() ? _str->at(_pos) : -1;}
+ int peek (size_t n) const override {return _pos+n < _str->length() ? _str->at(_pos+n) : -1;}
+ bool eof () const override {return _pos >= _str->length();}
+ void invalidate () override {_pos = _str->length();}
private:
- const std::string &_str;
- size_t _pos;
+ const std::string *_str;
+ size_t _pos=0;
};
-class CharInputBuffer : public InputBuffer
-{
+class CharInputBuffer : public InputBuffer {
public:
CharInputBuffer (const char *buf, size_t size) : _pos(buf), _size(buf ? size : 0) {}
@@ -112,8 +109,7 @@ class CharInputBuffer : public InputBuffer
};
-class SplittedCharInputBuffer : public InputBuffer
-{
+class SplittedCharInputBuffer : public InputBuffer {
public:
SplittedCharInputBuffer (const char *buf1, size_t s1, const char *buf2, size_t s2);
int get () override;
@@ -129,16 +125,15 @@ class SplittedCharInputBuffer : public InputBuffer
};
-class TextStreamInputBuffer : public StreamInputBuffer
-{
+class TextStreamInputBuffer : public StreamInputBuffer {
public:
- TextStreamInputBuffer (std::istream &is) : StreamInputBuffer(is), _line(1), _col(1) {}
+ explicit TextStreamInputBuffer (std::istream &is) : StreamInputBuffer(is) {}
int get () override;
int line () const {return _line;}
int col () const {return _col;}
private:
- int _line, _col;
+ int _line=1, _col=1;
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp
index 9a317b4bf96..5c9b9f5c621 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.cpp
@@ -19,6 +19,7 @@
*************************************************************************/
#include <cmath>
+#include <cstring>
#include <functional>
#include "InputReader.hpp"
@@ -41,11 +42,15 @@ void StringMatcher::setPattern (const string &pattern) {
}
+/** Reads characters from an input stream until the pattern string or EOF is reached.
+ * The matching string is read too if found. An empty pattern matches any character, i.e.
+ * reading stops after the first character.
+ * @return true if the pattern was found */
bool StringMatcher::match (InputReader &ir) {
- _charsRead = 0;
int c;
int i=0;
const int len = static_cast<int>(_pattern.length());
+ _charsRead = 0;
while ((c = ir.get()) >= 0) {
_charsRead++;
while (i >= 0 && c != _pattern[i])
@@ -56,6 +61,25 @@ bool StringMatcher::match (InputReader &ir) {
return false;
}
+
+/** Reads characters from an input stream until the pattern string or EOF is reached
+ * and returns them as a string. The matching string is also appended to the returned string. */
+string StringMatcher::read (InputReader &ir) {
+ string ret;
+ int c;
+ int i=0;
+ const int len = static_cast<int>(_pattern.length());
+ while ((c = ir.get()) >= 0) {
+ ret += char(c);
+ while (i >= 0 && c != _pattern[i])
+ i = _borders[i];
+ if (++i == len)
+ break;
+ }
+ _charsRead = ret.length();
+ return ret;
+}
+
///////////////////////////////////////////////////////////////////////////
/** Skips n characters. */
@@ -73,15 +97,26 @@ void InputReader::skipSpace () {
}
-/** Tries to find a given string and skips all characters preceding that string.
+/** Tries to find a given string and skips all characters preceding that string. If
+ * the string can't be found, all characters until EOF are skipped.
* @param[in] str string to look for (must not be longer than the maximal buffer size)
- * @return true if s was found */
+ * @return true if str was found */
bool InputReader::skipUntil (const char *str) {
StringMatcher matcher(str);
return matcher.match(*this);
}
+/** Tries to find a given string and returns all characters including that string. If
+ * the string can't be found, all characters until EOF are read.
+ * @param[in] str string to look for (must not be longer than the maximal buffer size)
+ * @return the read characters */
+string InputReader::readUntil (const char *str) {
+ StringMatcher matcher(str);
+ return matcher.read(*this);
+}
+
+
/** Looks for the first occurrence of a given character.
* @param[in] c character to lookup
* @return position of character relative to current location, -1 if character was not found */
@@ -246,7 +281,7 @@ string InputReader::getWord () {
string ret;
skipSpace();
while (isalpha(peek()))
- ret += get();
+ ret += char(get());
return ret;
}
@@ -261,7 +296,7 @@ char InputReader::getPunct () {
}
-/** Reads a string optionally delimited by a given quotation character.
+/** Reads a string optionally enclosed by a given quotation character.
* Before reading the string, all leading whitespace is skipped. Then, the function checks
* for one of the the given quotation characters. If it is found, all characters until the
* second appearance of the same quotation char are appended to the result. Otherwise, an
@@ -278,7 +313,7 @@ string InputReader::getQuotedString (const char *quotechars) {
if (const char *quotechar = strchr(quotechars, peek())) {
get();
while (!eof() && peek() != *quotechar)
- ret += get();
+ ret += char(get());
get();
}
return ret;
@@ -294,7 +329,7 @@ string InputReader::getString () {
string ret;
skipSpace();
while (!eof() && !isspace(peek()) && isprint(peek()))
- ret += get();
+ ret += char(get());
return ret;
}
@@ -305,7 +340,7 @@ string InputReader::getString () {
string InputReader::getString (size_t n) {
string ret;
while (n-- > 0)
- ret += get();
+ ret += char(get());
return ret;
}
@@ -319,7 +354,7 @@ string InputReader::getString (const char *delim) {
string ret;
skipSpace();
while (!eof() && peek() > 0 && !strchr(delim, peek()))
- ret += get();
+ ret += char(get());
return ret;
}
@@ -328,33 +363,37 @@ string InputReader::getLine () {
string ret;
skipSpace();
while (!eof() && peek() > 0 && peek() != '\n')
- ret += get();
+ ret += char(get());
// trim trailing whitespace
ret.erase(std::find_if(ret.rbegin(), ret.rend(), not1(ptr_fun<int, int>(isspace))).base(), ret.end());
return ret;
}
-/** Parses a sequence of key-value pairs of the form KEY=VALUE or KEY="VALUE"
+/** Parses a sequence of key-value pairs of the form KEY=VALUE or KEY="VALUE".
+ * If parameter 'requireValues' is false, attributes may also consist of a key only.
* @param[out] attr the scanned atributes
+ * @param[in] requireValues true if all attributes require a value
* @param[in] quotechars recognized quote characters used to enclose the attribute values
* @return number of attributes scanned */
-int InputReader::parseAttributes (map<string,string> &attr, const char *quotechars) {
- bool ready=false;
- while (!eof() && !ready) {
+int InputReader::parseAttributes (map<string,string> &attr, bool requireValues, const char *quotechars) {
+ while (!eof()) {
string key;
skipSpace();
- while (isalnum(peek()))
- key += get();
+ if (!isalpha(peek())) // first character of attribute name must be a letter
+ break;
+ key += char(get());
+ while (isalnum(peek()) || strchr("-:._", peek()))
+ key += char(get());
skipSpace();
if (peek() == '=') {
get();
skipSpace();
string val = getQuotedString(quotechars);
- attr[key] = val;
+ attr.emplace(std::move(key), std::move(val));
}
- else
- ready = true;
+ else if (!requireValues)
+ attr.emplace(std::move(key), "");
}
return attr.size();
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp
index 5523499f073..0ca4f107722 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/InputReader.hpp
@@ -37,7 +37,8 @@ class InputReader {
virtual bool check (char c) const {return peek() == c;}
virtual bool check (const char *s, bool consume=true);
virtual void skip (size_t n);
- virtual bool skipUntil (const char *s);
+ virtual bool skipUntil (const char *str);
+ virtual std::string readUntil (const char *str);
virtual int find (char c) const;
virtual void skipSpace ();
virtual int getInt ();
@@ -53,14 +54,14 @@ class InputReader {
virtual std::string getString (size_t n);
virtual std::string getString (const char *delim);
virtual std::string getLine ();
- virtual int parseAttributes (std::map<std::string,std::string> &attr, const char *quotechars=nullptr);
+ virtual int parseAttributes (std::map<std::string,std::string> &attr, bool requireValues, const char *quotechars=nullptr);
virtual operator bool () const {return !eof();}
};
class StreamInputReader : public InputReader {
public:
- StreamInputReader (std::istream &is) : _is(is) {}
+ explicit StreamInputReader (std::istream &is) : _is(is) {}
int get () override {return _is.get();}
int peek () const override {return _is.peek();}
int peek (size_t n) const override;
@@ -74,7 +75,7 @@ class StreamInputReader : public InputReader {
class BufferInputReader : public InputReader {
public:
- BufferInputReader (InputBuffer &ib) : _ib(&ib) {}
+ explicit BufferInputReader (InputBuffer &ib) : _ib(&ib) {}
void assign (InputBuffer &ib) {_ib = &ib;}
int get () override {return _ib->get();}
int peek () const override {return _ib->peek();}
@@ -91,9 +92,10 @@ class BufferInputReader : public InputReader {
class StringMatcher {
public:
StringMatcher () : _charsRead(0) {}
- StringMatcher (const std::string &pattern) : _charsRead(0) {setPattern(pattern);}
+ explicit StringMatcher (const std::string &pattern) : _charsRead(0) {setPattern(pattern);}
void setPattern (const std::string &pattern);
bool match (InputReader &ir);
+ std::string read (InputReader &ir);
size_t charsRead () const {return _charsRead;}
private:
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp
index a1835f6732c..a79fdf0c03b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.cpp
@@ -32,11 +32,9 @@ JFM::JFM (istream &is) {
is.seekg(0);
StreamReader reader(is);
uint16_t id = uint16_t(reader.readUnsigned(2)); // JFM ID (9 or 11)
- if (id != 9 && id != 11) {
- ostringstream oss;
- oss << "invalid JFM identifier " << id << " (9 or 11 expected)";
- throw FontMetricException(oss.str());
- }
+ if (id != 9 && id != 11)
+ throw FontMetricException("invalid JFM identifier " + std::to_string(id) + " (9 or 11 expected)");
+
_vertical = (id == 9);
uint16_t nt = uint16_t(reader.readUnsigned(2)); // length of character type table
uint16_t lf = uint16_t(reader.readUnsigned(2)); // length of entire file in 4 byte words
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp
index 5b5901ee61f..c51f371a5ec 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/JFM.hpp
@@ -27,7 +27,7 @@
class JFM : public TFM {
public:
- JFM (std::istream &is);
+ explicit JFM (std::istream &is);
bool verticalLayout () const override {return _vertical;}
uint32_t minChar () const {return _minchar;}
uint32_t maxChar () const {return static_cast<uint32_t>(_minchar+_charTypeTable.size()-1);}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp
index ba7dd2a2252..cbee103d49b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.cpp
@@ -60,9 +60,7 @@ void Length::set (double val, Unit unit) {
case Unit::SP: _pt = val/pt2sp; break;
default:
// this isn't supposed to happen
- ostringstream oss;
- oss << "invalid length unit: (" << static_cast<int>(unit) << ")";
- throw UnitException(oss.str());
+ throw UnitException("invalid length unit: (" + std::to_string(static_cast<int>(unit)) + ")");
}
}
@@ -80,9 +78,7 @@ double Length::get (Unit unit) const {
case Unit::SP: return sp();
}
// this isn't supposed to happen
- ostringstream oss;
- oss << "invalid length unit: (" << static_cast<int>(unit) << ")";
- throw UnitException(oss.str());
+ throw UnitException("invalid length unit: (" + std::to_string(static_cast<int>(unit)) + ")");
}
@@ -111,7 +107,7 @@ Length::Unit Length::stringToUnit (const std::string &unitstr) {
case unit_id('s','p'): return Unit::SP;
}
}
- throw UnitException(string("invalid length unit: ")+unitstr);
+ throw UnitException(string("invalid length unit: ") + unitstr);
}
@@ -136,7 +132,7 @@ void Length::set (double val, string unitstr) {
if (unitstr.empty())
unitstr = "pt";
else if (unitstr.length() != 2)
- throw UnitException(string("invalid length unit: ")+unitstr);
+ throw UnitException(string("invalid length unit: ") + unitstr);
set(val, stringToUnit(unitstr));
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp
index 0c9aa6526bf..4454eec168e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Length.hpp
@@ -30,7 +30,7 @@
#endif
struct UnitException : MessageException {
- UnitException (const std::string &msg) : MessageException(msg) {}
+ explicit UnitException (const std::string &msg) : MessageException(msg) {}
};
@@ -40,10 +40,10 @@ class Length {
public:
constexpr Length () : _pt(0) {}
- constexpr Length (long double pt) : _pt(static_cast<double>(pt)) {}
+ explicit constexpr Length (long double pt) : _pt(static_cast<double>(pt)) {}
Length (double val, Unit unit) {set(val, unit);}
Length (double val, const std::string &unitstr) {set(val, unitstr);}
- Length (const std::string &lenstr) {set(lenstr);}
+ explicit Length (const std::string &lenstr) {set(lenstr);}
void set (double val, Unit unit);
void set (double val, std::string unit);
void set (const std::string &lenstr);
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MD5HashFunction.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MD5HashFunction.hpp
index 3ccbdfe12c1..e233673d36d 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MD5HashFunction.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MD5HashFunction.hpp
@@ -34,8 +34,8 @@ class MD5HashFunction : public HashFunction {
public:
MD5HashFunction () {MD5_Init(&_context);}
MD5HashFunction (const char *data, size_t length) : MD5HashFunction() {update(data, length);}
- MD5HashFunction (const std::string &data) : MD5HashFunction() {update(data);}
- MD5HashFunction (const std::vector<uint8_t> &data) : MD5HashFunction() {update(data);}
+ explicit MD5HashFunction (const std::string &data) : MD5HashFunction() {update(data);}
+ explicit MD5HashFunction (const std::vector<uint8_t> &data) : MD5HashFunction() {update(data);}
int digestSize () const override {return 16;}
void reset () override {MD5_Init(&_context);}
void update (const char *data, size_t length) override {MD5_Update(&_context, data, length);}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am b/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am
index 421ccd840e1..8c7786e9dd1 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.am
@@ -5,6 +5,7 @@
bin_PROGRAMS = dvisvgm
noinst_LIBRARIES = libdvisvgm.a
+SUBDIRS = optimizer
dvisvgm_SOURCES = \
CommandLine.hpp \
@@ -14,6 +15,7 @@ include ../libs/defs.am
dvisvgm_LDADD = \
$(noinst_LIBRARIES) \
+ optimizer/liboptimizer.a \
../libs/clipper/libclipper.a \
$(POTRACE_LIBS) \
$(XXHASH_LIBS)
@@ -43,217 +45,123 @@ dvisvgm_DEPENDENCIES += $(KPATHSEA_DEPEND) $(ZLIB_DEPEND) $(FREETYPE2_DEPEND)
libdvisvgm_a_SOURCES = \
AGLTable.hpp \
- BasicDVIReader.cpp \
- BasicDVIReader.hpp \
- Bezier.cpp \
- Bezier.hpp \
- BgColorSpecialHandler.cpp \
- BgColorSpecialHandler.hpp \
- Bitmap.cpp \
- Bitmap.hpp \
- BoundingBox.cpp \
- BoundingBox.hpp \
- Calculator.cpp \
- Calculator.hpp \
+ BasicDVIReader.hpp BasicDVIReader.cpp \
+ Bezier.hpp Bezier.cpp \
+ BgColorSpecialHandler.hpp BgColorSpecialHandler.cpp \
+ Bitmap.hpp Bitmap.cpp \
+ BoundingBox.hpp BoundingBox.cpp \
+ Calculator.hpp Calculator.cpp \
Character.hpp \
- CharMapID.cpp \
- CharMapID.hpp \
- CLCommandLine.cpp \
- CLCommandLine.hpp \
+ CharMapID.hpp CharMapID.cpp \
+ CLCommandLine.hpp CLCommandLine.cpp \
+ CMap.hpp CMap.cpp \
+ CMapManager.hpp CMapManager.cpp \
+ CMapReader.hpp CMapReader.cpp \
CLOption.hpp \
- CMap.cpp \
- CMap.hpp \
- CMapManager.cpp \
- CMapManager.hpp \
- CMapReader.cpp \
- CMapReader.hpp \
- Color.cpp \
- Color.hpp \
- ColorSpecialHandler.cpp \
- ColorSpecialHandler.hpp \
- CRC32.cpp \
- CRC32.hpp \
- DependencyGraph.hpp \
- Directory.cpp \
- Directory.hpp \
- DLLoader.cpp \
- DLLoader.hpp \
+ Color.hpp Color.cpp \
+ ColorSpecialHandler.hpp ColorSpecialHandler.cpp \
+ CommandLine.hpp \
+ Directory.hpp Directory.cpp \
DVIActions.hpp \
- DVIReader.cpp \
- DVIReader.hpp \
- DvisvgmSpecialHandler.cpp \
- DvisvgmSpecialHandler.hpp \
- DVIToSVG.cpp \
- DVIToSVG.hpp \
- DVIToSVGActions.cpp \
- DVIToSVGActions.hpp \
- EmSpecialHandler.cpp \
- EmSpecialHandler.hpp \
- EncFile.cpp \
- EncFile.hpp \
- EPSFile.cpp \
- EPSFile.hpp \
+ DLLoader.hpp DLLoader.cpp \
+ DVIReader.hpp DVIReader.cpp \
+ DvisvgmSpecialHandler.hpp DvisvgmSpecialHandler.cpp \
+ DVIToSVG.hpp DVIToSVG.cpp \
+ DVIToSVGActions.hpp DVIToSVGActions.cpp \
+ EllipticalArc.hpp EllipticalArc.cpp \
+ EmSpecialHandler.hpp EmSpecialHandler.cpp \
+ EncFile.hpp EncFile.cpp \
+ EPSFile.hpp EPSFile.cpp \
EPSToSVG.hpp \
- FileFinder.cpp \
- FileFinder.hpp \
- FilePath.cpp \
- FilePath.hpp \
- FileSystem.cpp \
- FileSystem.hpp \
+ FileFinder.hpp FileFinder.cpp \
+ FilePath.hpp FilePath.cpp \
+ FileSystem.hpp FileSystem.cpp \
FixWord.hpp \
- Font.cpp \
- Font.hpp \
- FontCache.cpp \
- FontCache.hpp \
- FontEncoding.cpp \
- FontEncoding.hpp \
- FontEngine.cpp \
- FontEngine.hpp \
- FontManager.cpp \
- FontManager.hpp \
- FontMap.cpp \
- FontMap.hpp \
- FontMetrics.cpp \
- FontMetrics.hpp \
+ Font.hpp Font.cpp \
+ FontCache.hpp FontCache.cpp \
+ FontEncoding.hpp FontEncoding.cpp \
+ FontEngine.hpp FontEngine.cpp \
+ FontManager.hpp FontManager.cpp \
+ FontMap.hpp FontMap.cpp \
+ FontMetrics.hpp FontMetrics.cpp \
FontStyle.hpp \
- FontWriter.cpp \
- FontWriter.hpp \
- GFGlyphTracer.cpp \
- GFGlyphTracer.hpp \
- GFReader.cpp \
- GFReader.hpp \
- GFTracer.cpp \
- GFTracer.hpp \
- Ghostscript.cpp \
- Ghostscript.hpp \
+ FontWriter.hpp FontWriter.cpp \
+ GFGlyphTracer.hpp GFGlyphTracer.cpp \
+ GFReader.hpp GFReader.cpp \
+ GFTracer.hpp GFTracer.cpp \
+ Ghostscript.hpp Ghostscript.cpp \
Glyph.hpp \
GlyphTracerMessages.hpp \
GraphicsPath.hpp \
- HashFunction.cpp \
- HashFunction.hpp \
- HtmlSpecialHandler.cpp \
- HtmlSpecialHandler.hpp \
- HyperlinkManager.cpp \
- HyperlinkManager.hpp \
- ImageToSVG.cpp \
- ImageToSVG.hpp \
- InputBuffer.cpp \
- InputBuffer.hpp \
- InputReader.cpp \
- InputReader.hpp \
- JFM.cpp \
- JFM.hpp \
- Length.cpp \
- Length.hpp \
+ HashFunction.hpp HashFunction.cpp \
+ HtmlSpecialHandler.hpp HtmlSpecialHandler.cpp \
+ HyperlinkManager.hpp HyperlinkManager.cpp \
+ ImageToSVG.hpp ImageToSVG.cpp \
+ InputBuffer.hpp InputBuffer.cpp \
+ InputReader.hpp InputReader.cpp \
+ JFM.hpp JFM.cpp \
+ Length.hpp Length.cpp \
macros.hpp \
- MapLine.cpp \
- MapLine.hpp \
- Matrix.cpp \
- Matrix.hpp \
+ MapLine.hpp MapLine.cpp \
+ Matrix.hpp Matrix.cpp \
MD5HashFunction.hpp \
- Message.cpp \
- Message.hpp \
+ Message.hpp Message.cpp \
MessageException.hpp \
- MetafontWrapper.cpp \
- MetafontWrapper.hpp \
- NoPsSpecialHandler.cpp \
- NoPsSpecialHandler.hpp \
+ MetafontWrapper.hpp MetafontWrapper.cpp \
+ NoPsSpecialHandler.hpp NoPsSpecialHandler.cpp \
NumericRanges.hpp \
- PageRanges.cpp \
- PageRanges.hpp \
- PageSize.cpp \
- PageSize.hpp \
+ PageRanges.hpp PageRanges.cpp \
+ PageSize.hpp PageSize.cpp \
Pair.hpp \
- PapersizeSpecialHandler.cpp \
- PapersizeSpecialHandler.hpp \
- PathClipper.cpp \
- PathClipper.hpp \
- PDFParser.cpp \
- PDFParser.hpp \
+ PapersizeSpecialHandler.hpp PapersizeSpecialHandler.cpp \
+ PathClipper.hpp PathClipper.cpp \
+ PDFParser.hpp PDFParser.cpp \
+ PdfSpecialHandler.hpp PdfSpecialHandler.cpp \
PDFToSVG.hpp \
- PdfSpecialHandler.cpp \
- PdfSpecialHandler.hpp \
- PreScanDVIReader.cpp \
- PreScanDVIReader.hpp \
- Process.cpp \
- Process.hpp \
+ PreScanDVIReader.hpp PreScanDVIReader.cpp \
+ Process.hpp Process.cpp \
psdefs.cpp \
PSFilter.hpp \
- PSInterpreter.cpp \
- PSInterpreter.hpp \
- PSPattern.cpp \
- PSPattern.hpp \
- PSPreviewFilter.cpp \
- PSPreviewFilter.hpp \
- PsSpecialHandler.cpp \
- PsSpecialHandler.hpp \
- RangeMap.cpp \
- RangeMap.hpp \
- ShadingPatch.cpp \
- ShadingPatch.hpp \
- SignalHandler.cpp \
- SignalHandler.hpp \
- SourceInput.cpp \
- SourceInput.hpp \
+ PSInterpreter.hpp PSInterpreter.cpp \
+ PSPattern.hpp PSPattern.cpp \
+ PSPreviewFilter.hpp PSPreviewFilter.cpp \
+ PsSpecialHandler.hpp PsSpecialHandler.cpp \
+ RangeMap.hpp RangeMap.cpp \
+ ShadingPatch.hpp ShadingPatch.cpp \
+ SignalHandler.hpp SignalHandler.cpp \
+ SourceInput.hpp SourceInput.cpp \
SpecialActions.hpp \
SpecialHandler.hpp \
- SpecialManager.cpp \
- SpecialManager.hpp \
- StreamReader.cpp \
- StreamReader.hpp \
- StreamWriter.cpp \
- StreamWriter.hpp \
- Subfont.cpp \
- Subfont.hpp \
- SVGCharHandler.cpp \
- SVGCharHandler.hpp \
- SVGCharHandlerFactory.cpp \
- SVGCharHandlerFactory.hpp \
- SVGCharPathHandler.cpp \
- SVGCharPathHandler.hpp \
- SVGCharTspanTextHandler.cpp \
- SVGCharTspanTextHandler.hpp \
- SVGOutput.cpp \
- SVGOutput.hpp \
- SVGSingleCharTextHandler.cpp \
- SVGSingleCharTextHandler.hpp \
- SVGTree.cpp \
- SVGTree.hpp \
- System.cpp \
- System.hpp \
- TensorProductPatch.cpp \
- TensorProductPatch.hpp \
- Terminal.cpp \
- Terminal.hpp \
- TFM.cpp \
- TFM.hpp \
- ToUnicodeMap.cpp \
- ToUnicodeMap.hpp \
- TpicSpecialHandler.cpp \
- TpicSpecialHandler.hpp \
- TriangularPatch.cpp \
- TriangularPatch.hpp \
- TrueTypeFont.cpp \
- TrueTypeFont.hpp \
- TTFAutohint.cpp \
- TTFAutohint.hpp \
- Unicode.cpp \
- Unicode.hpp \
- utility.hpp \
- utility.cpp \
+ SpecialManager.hpp SpecialManager.cpp \
+ StreamReader.hpp StreamReader.cpp \
+ StreamWriter.hpp StreamWriter.cpp \
+ Subfont.hpp Subfont.cpp \
+ SVGCharHandler.hpp SVGCharHandler.cpp \
+ SVGCharHandlerFactory.hpp SVGCharHandlerFactory.cpp \
+ SVGCharPathHandler.hpp SVGCharPathHandler.cpp \
+ SVGCharTspanTextHandler.hpp SVGCharTspanTextHandler.cpp \
+ SVGOutput.hpp SVGOutput.cpp \
+ SVGSingleCharTextHandler.hpp SVGSingleCharTextHandler.cpp \
+ SVGTree.hpp SVGTree.cpp \
+ System.hpp System.cpp \
+ TensorProductPatch.hpp TensorProductPatch.cpp \
+ Terminal.hpp Terminal.cpp \
+ TFM.hpp TFM.cpp \
+ ToUnicodeMap.hpp ToUnicodeMap.cpp \
+ TpicSpecialHandler.hpp TpicSpecialHandler.cpp \
+ TriangularPatch.hpp TriangularPatch.cpp \
+ TrueTypeFont.hpp TrueTypeFont.cpp \
+ TTFAutohint.hpp TTFAutohint.cpp \
+ Unicode.hpp Unicode.cpp \
+ utility.hpp utility.cpp \
VectorIterator.hpp \
VectorStream.hpp \
- version.hpp \
VFActions.hpp \
- VFReader.cpp \
- VFReader.hpp \
+ VFReader.hpp VFReader.cpp \
windows.hpp \
- XMLDocument.cpp \
- XMLDocument.hpp \
- XMLNode.cpp \
- XMLNode.hpp \
- XMLString.cpp \
- XMLString.hpp \
+ XMLDocument.hpp XMLDocument.cpp \
+ XMLNode.hpp XMLNode.cpp \
+ XMLString.hpp XMLString.cpp \
XXHashFunction.hpp \
ZLibOutputStream.hpp
@@ -273,7 +181,16 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS) -Wnon-virtual-dtor \
AM_CXXFLAGS += \
$(POTRACE_CFLAGS) \
- $(XXHASH_CFLAGS)
+ $(XXHASH_CFLAGS) \
+ $(KPATHSEA_INCLUDES) \
+ $(POTRACE_INCLUDES) \
+ $(FREETYPE2_INCLUDES) \
+ $(LIBGS_INCLUDES) \
+ $(CODE_COVERAGE_CFLAGS)
+
+if WIN32
+AM_CXXFLAGS += -DTEXLIVEWIN32
+endif WIN32
AM_LDFLAGS = \
$(KPSE_LIBS) \
@@ -284,8 +201,6 @@ AM_CFLAGS += \
-I$(dvisvgm_srcdir)/libs/ff-woff/fontforge \
-I$(dvisvgm_srcdir)/libs/ff-woff/inc
-AM_CXXFLAGS += $(TTFAUTOHINT_CFLAGS)
-
AM_CXXFLAGS += \
$(BROTLI_CFLAGS) \
$(WOFF2_CFLAGS)
@@ -296,23 +211,11 @@ else
AM_CXXFLAGS += $(LIBCRYPTO_CFLAGS)
endif
-AM_LDFLAGS += $(TTFAUTOHINT_LIBS)
endif
-AM_CXXFLAGS += \
- $(KPATHSEA_INCLUDES) \
- $(POTRACE_INCLUDES) \
- $(FREETYPE2_INCLUDES) \
- $(ZLIB_INCLUDES) \
- $(LIBGS_INCLUDES) \
- $(CODE_COVERAGE_CFLAGS)
-
-if WIN32
-AM_CXXFLAGS += -DTEXLIVEWIN32
-endif WIN32
-
-if ! TEXLIVE_BUILD
# TL: do not try to rebuild these source files.
+if ! TEXLIVE_BUILD
+
# the command-line parser class is generated from options.xml by opt2cpp
$(srcdir)/CommandLine.hpp: options.xml
rm -f $@
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in b/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in
index 7da31007555..47584fce862 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Makefile.in
@@ -102,16 +102,17 @@ bin_PROGRAMS = dvisvgm$(EXEEXT)
@USE_BUNDLED_MD5_TRUE@am__append_6 = ../libs/md5/libmd5.a
@USE_BUNDLED_MD5_FALSE@am__append_7 = $(LIBCRYPTO_LIBS)
@ENABLE_WOFF_TRUE@am__append_8 = ffwrapper.c ffwrapper.h
-@ENABLE_WOFF_TRUE@am__append_9 = \
+@WIN32_TRUE@am__append_9 = -DTEXLIVEWIN32
+@ENABLE_WOFF_TRUE@am__append_10 = \
@ENABLE_WOFF_TRUE@ -I$(dvisvgm_srcdir)/libs/ff-woff/fontforge \
@ENABLE_WOFF_TRUE@ -I$(dvisvgm_srcdir)/libs/ff-woff/inc
-@ENABLE_WOFF_TRUE@am__append_10 = $(TTFAUTOHINT_CFLAGS) \
-@ENABLE_WOFF_TRUE@ $(BROTLI_CFLAGS) $(WOFF2_CFLAGS)
-@ENABLE_WOFF_TRUE@@USE_BUNDLED_MD5_TRUE@am__append_11 = -I$(dvisvgm_srcdir)/libs/md5
-@ENABLE_WOFF_TRUE@@USE_BUNDLED_MD5_FALSE@am__append_12 = $(LIBCRYPTO_CFLAGS)
-@ENABLE_WOFF_TRUE@am__append_13 = $(TTFAUTOHINT_LIBS)
-@WIN32_TRUE@am__append_14 = -DTEXLIVEWIN32
+@ENABLE_WOFF_TRUE@am__append_11 = \
+@ENABLE_WOFF_TRUE@ $(BROTLI_CFLAGS) \
+@ENABLE_WOFF_TRUE@ $(WOFF2_CFLAGS)
+
+@ENABLE_WOFF_TRUE@@USE_BUNDLED_MD5_TRUE@am__append_12 = -I$(dvisvgm_srcdir)/libs/md5
+@ENABLE_WOFF_TRUE@@USE_BUNDLED_MD5_FALSE@am__append_13 = $(LIBCRYPTO_CFLAGS)
subdir = dvisvgm-src/src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../../m4/ax_cxx_compile_stdcxx.m4 \
@@ -145,83 +146,82 @@ am__v_AR_0 = @echo " AR " $@;
am__v_AR_1 =
libdvisvgm_a_AR = $(AR) $(ARFLAGS)
libdvisvgm_a_LIBADD =
-am__libdvisvgm_a_SOURCES_DIST = AGLTable.hpp BasicDVIReader.cpp \
- BasicDVIReader.hpp Bezier.cpp Bezier.hpp \
- BgColorSpecialHandler.cpp BgColorSpecialHandler.hpp Bitmap.cpp \
- Bitmap.hpp BoundingBox.cpp BoundingBox.hpp Calculator.cpp \
- Calculator.hpp Character.hpp CharMapID.cpp CharMapID.hpp \
- CLCommandLine.cpp CLCommandLine.hpp CLOption.hpp CMap.cpp \
- CMap.hpp CMapManager.cpp CMapManager.hpp CMapReader.cpp \
- CMapReader.hpp Color.cpp Color.hpp ColorSpecialHandler.cpp \
- ColorSpecialHandler.hpp CRC32.cpp CRC32.hpp \
- DependencyGraph.hpp Directory.cpp Directory.hpp DLLoader.cpp \
- DLLoader.hpp DVIActions.hpp DVIReader.cpp DVIReader.hpp \
- DvisvgmSpecialHandler.cpp DvisvgmSpecialHandler.hpp \
- DVIToSVG.cpp DVIToSVG.hpp DVIToSVGActions.cpp \
- DVIToSVGActions.hpp EmSpecialHandler.cpp EmSpecialHandler.hpp \
- EncFile.cpp EncFile.hpp EPSFile.cpp EPSFile.hpp EPSToSVG.hpp \
- FileFinder.cpp FileFinder.hpp FilePath.cpp FilePath.hpp \
- FileSystem.cpp FileSystem.hpp FixWord.hpp Font.cpp Font.hpp \
- FontCache.cpp FontCache.hpp FontEncoding.cpp FontEncoding.hpp \
- FontEngine.cpp FontEngine.hpp FontManager.cpp FontManager.hpp \
- FontMap.cpp FontMap.hpp FontMetrics.cpp FontMetrics.hpp \
- FontStyle.hpp FontWriter.cpp FontWriter.hpp GFGlyphTracer.cpp \
- GFGlyphTracer.hpp GFReader.cpp GFReader.hpp GFTracer.cpp \
- GFTracer.hpp Ghostscript.cpp Ghostscript.hpp Glyph.hpp \
- GlyphTracerMessages.hpp GraphicsPath.hpp HashFunction.cpp \
- HashFunction.hpp HtmlSpecialHandler.cpp HtmlSpecialHandler.hpp \
- HyperlinkManager.cpp HyperlinkManager.hpp ImageToSVG.cpp \
- ImageToSVG.hpp InputBuffer.cpp InputBuffer.hpp InputReader.cpp \
- InputReader.hpp JFM.cpp JFM.hpp Length.cpp Length.hpp \
- macros.hpp MapLine.cpp MapLine.hpp Matrix.cpp Matrix.hpp \
- MD5HashFunction.hpp Message.cpp Message.hpp \
- MessageException.hpp MetafontWrapper.cpp MetafontWrapper.hpp \
- NoPsSpecialHandler.cpp NoPsSpecialHandler.hpp \
- NumericRanges.hpp PageRanges.cpp PageRanges.hpp PageSize.cpp \
- PageSize.hpp Pair.hpp PapersizeSpecialHandler.cpp \
- PapersizeSpecialHandler.hpp PathClipper.cpp PathClipper.hpp \
- PDFParser.cpp PDFParser.hpp PDFToSVG.hpp PdfSpecialHandler.cpp \
- PdfSpecialHandler.hpp PreScanDVIReader.cpp \
- PreScanDVIReader.hpp Process.cpp Process.hpp psdefs.cpp \
- PSFilter.hpp PSInterpreter.cpp PSInterpreter.hpp PSPattern.cpp \
- PSPattern.hpp PSPreviewFilter.cpp PSPreviewFilter.hpp \
- PsSpecialHandler.cpp PsSpecialHandler.hpp RangeMap.cpp \
- RangeMap.hpp ShadingPatch.cpp ShadingPatch.hpp \
- SignalHandler.cpp SignalHandler.hpp SourceInput.cpp \
- SourceInput.hpp SpecialActions.hpp SpecialHandler.hpp \
- SpecialManager.cpp SpecialManager.hpp StreamReader.cpp \
- StreamReader.hpp StreamWriter.cpp StreamWriter.hpp Subfont.cpp \
- Subfont.hpp SVGCharHandler.cpp SVGCharHandler.hpp \
- SVGCharHandlerFactory.cpp SVGCharHandlerFactory.hpp \
- SVGCharPathHandler.cpp SVGCharPathHandler.hpp \
- SVGCharTspanTextHandler.cpp SVGCharTspanTextHandler.hpp \
- SVGOutput.cpp SVGOutput.hpp SVGSingleCharTextHandler.cpp \
- SVGSingleCharTextHandler.hpp SVGTree.cpp SVGTree.hpp \
- System.cpp System.hpp TensorProductPatch.cpp \
- TensorProductPatch.hpp Terminal.cpp Terminal.hpp TFM.cpp \
- TFM.hpp ToUnicodeMap.cpp ToUnicodeMap.hpp \
- TpicSpecialHandler.cpp TpicSpecialHandler.hpp \
- TriangularPatch.cpp TriangularPatch.hpp TrueTypeFont.cpp \
- TrueTypeFont.hpp TTFAutohint.cpp TTFAutohint.hpp Unicode.cpp \
- Unicode.hpp utility.hpp utility.cpp VectorIterator.hpp \
- VectorStream.hpp version.hpp VFActions.hpp VFReader.cpp \
- VFReader.hpp windows.hpp XMLDocument.cpp XMLDocument.hpp \
- XMLNode.cpp XMLNode.hpp XMLString.cpp XMLString.hpp \
- XXHashFunction.hpp ZLibOutputStream.hpp ffwrapper.c \
- ffwrapper.h
+am__libdvisvgm_a_SOURCES_DIST = AGLTable.hpp BasicDVIReader.hpp \
+ BasicDVIReader.cpp Bezier.hpp Bezier.cpp \
+ BgColorSpecialHandler.hpp BgColorSpecialHandler.cpp Bitmap.hpp \
+ Bitmap.cpp BoundingBox.hpp BoundingBox.cpp Calculator.hpp \
+ Calculator.cpp Character.hpp CharMapID.hpp CharMapID.cpp \
+ CLCommandLine.hpp CLCommandLine.cpp CMap.hpp CMap.cpp \
+ CMapManager.hpp CMapManager.cpp CMapReader.hpp CMapReader.cpp \
+ CLOption.hpp Color.hpp Color.cpp ColorSpecialHandler.hpp \
+ ColorSpecialHandler.cpp CommandLine.hpp Directory.hpp \
+ Directory.cpp DVIActions.hpp DLLoader.hpp DLLoader.cpp \
+ DVIReader.hpp DVIReader.cpp DvisvgmSpecialHandler.hpp \
+ DvisvgmSpecialHandler.cpp DVIToSVG.hpp DVIToSVG.cpp \
+ DVIToSVGActions.hpp DVIToSVGActions.cpp EllipticalArc.hpp \
+ EllipticalArc.cpp EmSpecialHandler.hpp EmSpecialHandler.cpp \
+ EncFile.hpp EncFile.cpp EPSFile.hpp EPSFile.cpp EPSToSVG.hpp \
+ FileFinder.hpp FileFinder.cpp FilePath.hpp FilePath.cpp \
+ FileSystem.hpp FileSystem.cpp FixWord.hpp Font.hpp Font.cpp \
+ FontCache.hpp FontCache.cpp FontEncoding.hpp FontEncoding.cpp \
+ FontEngine.hpp FontEngine.cpp FontManager.hpp FontManager.cpp \
+ FontMap.hpp FontMap.cpp FontMetrics.hpp FontMetrics.cpp \
+ FontStyle.hpp FontWriter.hpp FontWriter.cpp GFGlyphTracer.hpp \
+ GFGlyphTracer.cpp GFReader.hpp GFReader.cpp GFTracer.hpp \
+ GFTracer.cpp Ghostscript.hpp Ghostscript.cpp Glyph.hpp \
+ GlyphTracerMessages.hpp GraphicsPath.hpp HashFunction.hpp \
+ HashFunction.cpp HtmlSpecialHandler.hpp HtmlSpecialHandler.cpp \
+ HyperlinkManager.hpp HyperlinkManager.cpp ImageToSVG.hpp \
+ ImageToSVG.cpp InputBuffer.hpp InputBuffer.cpp InputReader.hpp \
+ InputReader.cpp JFM.hpp JFM.cpp Length.hpp Length.cpp \
+ macros.hpp MapLine.hpp MapLine.cpp Matrix.hpp Matrix.cpp \
+ MD5HashFunction.hpp Message.hpp Message.cpp \
+ MessageException.hpp MetafontWrapper.hpp MetafontWrapper.cpp \
+ NoPsSpecialHandler.hpp NoPsSpecialHandler.cpp \
+ NumericRanges.hpp PageRanges.hpp PageRanges.cpp PageSize.hpp \
+ PageSize.cpp Pair.hpp PapersizeSpecialHandler.hpp \
+ PapersizeSpecialHandler.cpp PathClipper.hpp PathClipper.cpp \
+ PDFParser.hpp PDFParser.cpp PdfSpecialHandler.hpp \
+ PdfSpecialHandler.cpp PDFToSVG.hpp PreScanDVIReader.hpp \
+ PreScanDVIReader.cpp Process.hpp Process.cpp psdefs.cpp \
+ PSFilter.hpp PSInterpreter.hpp PSInterpreter.cpp PSPattern.hpp \
+ PSPattern.cpp PSPreviewFilter.hpp PSPreviewFilter.cpp \
+ PsSpecialHandler.hpp PsSpecialHandler.cpp RangeMap.hpp \
+ RangeMap.cpp ShadingPatch.hpp ShadingPatch.cpp \
+ SignalHandler.hpp SignalHandler.cpp SourceInput.hpp \
+ SourceInput.cpp SpecialActions.hpp SpecialHandler.hpp \
+ SpecialManager.hpp SpecialManager.cpp StreamReader.hpp \
+ StreamReader.cpp StreamWriter.hpp StreamWriter.cpp Subfont.hpp \
+ Subfont.cpp SVGCharHandler.hpp SVGCharHandler.cpp \
+ SVGCharHandlerFactory.hpp SVGCharHandlerFactory.cpp \
+ SVGCharPathHandler.hpp SVGCharPathHandler.cpp \
+ SVGCharTspanTextHandler.hpp SVGCharTspanTextHandler.cpp \
+ SVGOutput.hpp SVGOutput.cpp SVGSingleCharTextHandler.hpp \
+ SVGSingleCharTextHandler.cpp SVGTree.hpp SVGTree.cpp \
+ System.hpp System.cpp TensorProductPatch.hpp \
+ TensorProductPatch.cpp Terminal.hpp Terminal.cpp TFM.hpp \
+ TFM.cpp ToUnicodeMap.hpp ToUnicodeMap.cpp \
+ TpicSpecialHandler.hpp TpicSpecialHandler.cpp \
+ TriangularPatch.hpp TriangularPatch.cpp TrueTypeFont.hpp \
+ TrueTypeFont.cpp TTFAutohint.hpp TTFAutohint.cpp Unicode.hpp \
+ Unicode.cpp utility.hpp utility.cpp VectorIterator.hpp \
+ VectorStream.hpp VFActions.hpp VFReader.hpp VFReader.cpp \
+ windows.hpp XMLDocument.hpp XMLDocument.cpp XMLNode.hpp \
+ XMLNode.cpp XMLString.hpp XMLString.cpp XXHashFunction.hpp \
+ ZLibOutputStream.hpp ffwrapper.c ffwrapper.h
@ENABLE_WOFF_TRUE@am__objects_1 = ffwrapper.$(OBJEXT)
am_libdvisvgm_a_OBJECTS = BasicDVIReader.$(OBJEXT) Bezier.$(OBJEXT) \
BgColorSpecialHandler.$(OBJEXT) Bitmap.$(OBJEXT) \
BoundingBox.$(OBJEXT) Calculator.$(OBJEXT) CharMapID.$(OBJEXT) \
CLCommandLine.$(OBJEXT) CMap.$(OBJEXT) CMapManager.$(OBJEXT) \
CMapReader.$(OBJEXT) Color.$(OBJEXT) \
- ColorSpecialHandler.$(OBJEXT) CRC32.$(OBJEXT) \
- Directory.$(OBJEXT) DLLoader.$(OBJEXT) DVIReader.$(OBJEXT) \
+ ColorSpecialHandler.$(OBJEXT) Directory.$(OBJEXT) \
+ DLLoader.$(OBJEXT) DVIReader.$(OBJEXT) \
DvisvgmSpecialHandler.$(OBJEXT) DVIToSVG.$(OBJEXT) \
- DVIToSVGActions.$(OBJEXT) EmSpecialHandler.$(OBJEXT) \
- EncFile.$(OBJEXT) EPSFile.$(OBJEXT) FileFinder.$(OBJEXT) \
- FilePath.$(OBJEXT) FileSystem.$(OBJEXT) Font.$(OBJEXT) \
- FontCache.$(OBJEXT) FontEncoding.$(OBJEXT) \
+ DVIToSVGActions.$(OBJEXT) EllipticalArc.$(OBJEXT) \
+ EmSpecialHandler.$(OBJEXT) EncFile.$(OBJEXT) EPSFile.$(OBJEXT) \
+ FileFinder.$(OBJEXT) FilePath.$(OBJEXT) FileSystem.$(OBJEXT) \
+ Font.$(OBJEXT) FontCache.$(OBJEXT) FontEncoding.$(OBJEXT) \
FontEngine.$(OBJEXT) FontManager.$(OBJEXT) FontMap.$(OBJEXT) \
FontMetrics.$(OBJEXT) FontWriter.$(OBJEXT) \
GFGlyphTracer.$(OBJEXT) GFReader.$(OBJEXT) GFTracer.$(OBJEXT) \
@@ -283,12 +283,12 @@ am__depfiles_remade = ./$(DEPDIR)/BasicDVIReader.Po \
./$(DEPDIR)/Bitmap.Po ./$(DEPDIR)/BoundingBox.Po \
./$(DEPDIR)/CLCommandLine.Po ./$(DEPDIR)/CMap.Po \
./$(DEPDIR)/CMapManager.Po ./$(DEPDIR)/CMapReader.Po \
- ./$(DEPDIR)/CRC32.Po ./$(DEPDIR)/Calculator.Po \
- ./$(DEPDIR)/CharMapID.Po ./$(DEPDIR)/Color.Po \
- ./$(DEPDIR)/ColorSpecialHandler.Po ./$(DEPDIR)/DLLoader.Po \
- ./$(DEPDIR)/DVIReader.Po ./$(DEPDIR)/DVIToSVG.Po \
- ./$(DEPDIR)/DVIToSVGActions.Po ./$(DEPDIR)/Directory.Po \
- ./$(DEPDIR)/DvisvgmSpecialHandler.Po ./$(DEPDIR)/EPSFile.Po \
+ ./$(DEPDIR)/Calculator.Po ./$(DEPDIR)/CharMapID.Po \
+ ./$(DEPDIR)/Color.Po ./$(DEPDIR)/ColorSpecialHandler.Po \
+ ./$(DEPDIR)/DLLoader.Po ./$(DEPDIR)/DVIReader.Po \
+ ./$(DEPDIR)/DVIToSVG.Po ./$(DEPDIR)/DVIToSVGActions.Po \
+ ./$(DEPDIR)/Directory.Po ./$(DEPDIR)/DvisvgmSpecialHandler.Po \
+ ./$(DEPDIR)/EPSFile.Po ./$(DEPDIR)/EllipticalArc.Po \
./$(DEPDIR)/EmSpecialHandler.Po ./$(DEPDIR)/EncFile.Po \
./$(DEPDIR)/FileFinder.Po ./$(DEPDIR)/FilePath.Po \
./$(DEPDIR)/FileSystem.Po ./$(DEPDIR)/Font.Po \
@@ -368,11 +368,27 @@ am__v_CXXLD_0 = @echo " CXXLD " $@;
am__v_CXXLD_1 =
SOURCES = $(libdvisvgm_a_SOURCES) $(dvisvgm_SOURCES)
DIST_SOURCES = $(am__libdvisvgm_a_SOURCES_DIST) $(dvisvgm_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
@@ -392,14 +408,43 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/../libs/defs.am $(srcdir)/Makefile.in \
$(srcdir)/version.hpp.in $(top_srcdir)/../../build-aux/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_CPPFLAGS = @AM_CPPFLAGS@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AM_LDFLAGS = $(KPSE_LIBS) $(CODE_COVERAGE_LDFLAGS) $(am__append_13)
+AM_LDFLAGS = \
+ $(KPSE_LIBS) \
+ $(CODE_COVERAGE_LDFLAGS)
+
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
@@ -545,6 +590,7 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_LIBRARIES = libdvisvgm.a
+SUBDIRS = optimizer
dvisvgm_SOURCES = \
CommandLine.hpp \
dvisvgm.cpp
@@ -553,87 +599,88 @@ dvisvgm_SOURCES = \
@HAVE_POTRACE_FALSE@POTRACE_LIBS = ../libs/potrace/libpotrace.a
@HAVE_XXHASH_FALSE@XXHASH_CFLAGS = -I$(dvisvgm_srcdir)/libs/xxHash
@HAVE_XXHASH_FALSE@XXHASH_LIBS = ../libs/xxHash/libxxhash.a
-dvisvgm_LDADD = $(noinst_LIBRARIES) ../libs/clipper/libclipper.a \
- $(POTRACE_LIBS) $(XXHASH_LIBS) $(am__append_5) $(am__append_6) \
- $(am__append_7) $(KPATHSEA_LIBS) $(FREETYPE2_LIBS) \
- $(FONTFORGE_LIBS) $(ZLIB_LIBS) $(LIBGS_LIBS)
+dvisvgm_LDADD = $(noinst_LIBRARIES) optimizer/liboptimizer.a \
+ ../libs/clipper/libclipper.a $(POTRACE_LIBS) $(XXHASH_LIBS) \
+ $(am__append_5) $(am__append_6) $(am__append_7) \
+ $(KPATHSEA_LIBS) $(FREETYPE2_LIBS) $(FONTFORGE_LIBS) \
+ $(ZLIB_LIBS) $(LIBGS_LIBS)
dvisvgm_DEPENDENCIES = $(noinst_LIBRARIES) $(KPATHSEA_DEPEND) \
$(ZLIB_DEPEND) $(FREETYPE2_DEPEND)
-libdvisvgm_a_SOURCES = AGLTable.hpp BasicDVIReader.cpp \
- BasicDVIReader.hpp Bezier.cpp Bezier.hpp \
- BgColorSpecialHandler.cpp BgColorSpecialHandler.hpp Bitmap.cpp \
- Bitmap.hpp BoundingBox.cpp BoundingBox.hpp Calculator.cpp \
- Calculator.hpp Character.hpp CharMapID.cpp CharMapID.hpp \
- CLCommandLine.cpp CLCommandLine.hpp CLOption.hpp CMap.cpp \
- CMap.hpp CMapManager.cpp CMapManager.hpp CMapReader.cpp \
- CMapReader.hpp Color.cpp Color.hpp ColorSpecialHandler.cpp \
- ColorSpecialHandler.hpp CRC32.cpp CRC32.hpp \
- DependencyGraph.hpp Directory.cpp Directory.hpp DLLoader.cpp \
- DLLoader.hpp DVIActions.hpp DVIReader.cpp DVIReader.hpp \
- DvisvgmSpecialHandler.cpp DvisvgmSpecialHandler.hpp \
- DVIToSVG.cpp DVIToSVG.hpp DVIToSVGActions.cpp \
- DVIToSVGActions.hpp EmSpecialHandler.cpp EmSpecialHandler.hpp \
- EncFile.cpp EncFile.hpp EPSFile.cpp EPSFile.hpp EPSToSVG.hpp \
- FileFinder.cpp FileFinder.hpp FilePath.cpp FilePath.hpp \
- FileSystem.cpp FileSystem.hpp FixWord.hpp Font.cpp Font.hpp \
- FontCache.cpp FontCache.hpp FontEncoding.cpp FontEncoding.hpp \
- FontEngine.cpp FontEngine.hpp FontManager.cpp FontManager.hpp \
- FontMap.cpp FontMap.hpp FontMetrics.cpp FontMetrics.hpp \
- FontStyle.hpp FontWriter.cpp FontWriter.hpp GFGlyphTracer.cpp \
- GFGlyphTracer.hpp GFReader.cpp GFReader.hpp GFTracer.cpp \
- GFTracer.hpp Ghostscript.cpp Ghostscript.hpp Glyph.hpp \
- GlyphTracerMessages.hpp GraphicsPath.hpp HashFunction.cpp \
- HashFunction.hpp HtmlSpecialHandler.cpp HtmlSpecialHandler.hpp \
- HyperlinkManager.cpp HyperlinkManager.hpp ImageToSVG.cpp \
- ImageToSVG.hpp InputBuffer.cpp InputBuffer.hpp InputReader.cpp \
- InputReader.hpp JFM.cpp JFM.hpp Length.cpp Length.hpp \
- macros.hpp MapLine.cpp MapLine.hpp Matrix.cpp Matrix.hpp \
- MD5HashFunction.hpp Message.cpp Message.hpp \
- MessageException.hpp MetafontWrapper.cpp MetafontWrapper.hpp \
- NoPsSpecialHandler.cpp NoPsSpecialHandler.hpp \
- NumericRanges.hpp PageRanges.cpp PageRanges.hpp PageSize.cpp \
- PageSize.hpp Pair.hpp PapersizeSpecialHandler.cpp \
- PapersizeSpecialHandler.hpp PathClipper.cpp PathClipper.hpp \
- PDFParser.cpp PDFParser.hpp PDFToSVG.hpp PdfSpecialHandler.cpp \
- PdfSpecialHandler.hpp PreScanDVIReader.cpp \
- PreScanDVIReader.hpp Process.cpp Process.hpp psdefs.cpp \
- PSFilter.hpp PSInterpreter.cpp PSInterpreter.hpp PSPattern.cpp \
- PSPattern.hpp PSPreviewFilter.cpp PSPreviewFilter.hpp \
- PsSpecialHandler.cpp PsSpecialHandler.hpp RangeMap.cpp \
- RangeMap.hpp ShadingPatch.cpp ShadingPatch.hpp \
- SignalHandler.cpp SignalHandler.hpp SourceInput.cpp \
- SourceInput.hpp SpecialActions.hpp SpecialHandler.hpp \
- SpecialManager.cpp SpecialManager.hpp StreamReader.cpp \
- StreamReader.hpp StreamWriter.cpp StreamWriter.hpp Subfont.cpp \
- Subfont.hpp SVGCharHandler.cpp SVGCharHandler.hpp \
- SVGCharHandlerFactory.cpp SVGCharHandlerFactory.hpp \
- SVGCharPathHandler.cpp SVGCharPathHandler.hpp \
- SVGCharTspanTextHandler.cpp SVGCharTspanTextHandler.hpp \
- SVGOutput.cpp SVGOutput.hpp SVGSingleCharTextHandler.cpp \
- SVGSingleCharTextHandler.hpp SVGTree.cpp SVGTree.hpp \
- System.cpp System.hpp TensorProductPatch.cpp \
- TensorProductPatch.hpp Terminal.cpp Terminal.hpp TFM.cpp \
- TFM.hpp ToUnicodeMap.cpp ToUnicodeMap.hpp \
- TpicSpecialHandler.cpp TpicSpecialHandler.hpp \
- TriangularPatch.cpp TriangularPatch.hpp TrueTypeFont.cpp \
- TrueTypeFont.hpp TTFAutohint.cpp TTFAutohint.hpp Unicode.cpp \
- Unicode.hpp utility.hpp utility.cpp VectorIterator.hpp \
- VectorStream.hpp version.hpp VFActions.hpp VFReader.cpp \
- VFReader.hpp windows.hpp XMLDocument.cpp XMLDocument.hpp \
- XMLNode.cpp XMLNode.hpp XMLString.cpp XMLString.hpp \
- XXHashFunction.hpp ZLibOutputStream.hpp $(am__append_8)
+libdvisvgm_a_SOURCES = AGLTable.hpp BasicDVIReader.hpp \
+ BasicDVIReader.cpp Bezier.hpp Bezier.cpp \
+ BgColorSpecialHandler.hpp BgColorSpecialHandler.cpp Bitmap.hpp \
+ Bitmap.cpp BoundingBox.hpp BoundingBox.cpp Calculator.hpp \
+ Calculator.cpp Character.hpp CharMapID.hpp CharMapID.cpp \
+ CLCommandLine.hpp CLCommandLine.cpp CMap.hpp CMap.cpp \
+ CMapManager.hpp CMapManager.cpp CMapReader.hpp CMapReader.cpp \
+ CLOption.hpp Color.hpp Color.cpp ColorSpecialHandler.hpp \
+ ColorSpecialHandler.cpp CommandLine.hpp Directory.hpp \
+ Directory.cpp DVIActions.hpp DLLoader.hpp DLLoader.cpp \
+ DVIReader.hpp DVIReader.cpp DvisvgmSpecialHandler.hpp \
+ DvisvgmSpecialHandler.cpp DVIToSVG.hpp DVIToSVG.cpp \
+ DVIToSVGActions.hpp DVIToSVGActions.cpp EllipticalArc.hpp \
+ EllipticalArc.cpp EmSpecialHandler.hpp EmSpecialHandler.cpp \
+ EncFile.hpp EncFile.cpp EPSFile.hpp EPSFile.cpp EPSToSVG.hpp \
+ FileFinder.hpp FileFinder.cpp FilePath.hpp FilePath.cpp \
+ FileSystem.hpp FileSystem.cpp FixWord.hpp Font.hpp Font.cpp \
+ FontCache.hpp FontCache.cpp FontEncoding.hpp FontEncoding.cpp \
+ FontEngine.hpp FontEngine.cpp FontManager.hpp FontManager.cpp \
+ FontMap.hpp FontMap.cpp FontMetrics.hpp FontMetrics.cpp \
+ FontStyle.hpp FontWriter.hpp FontWriter.cpp GFGlyphTracer.hpp \
+ GFGlyphTracer.cpp GFReader.hpp GFReader.cpp GFTracer.hpp \
+ GFTracer.cpp Ghostscript.hpp Ghostscript.cpp Glyph.hpp \
+ GlyphTracerMessages.hpp GraphicsPath.hpp HashFunction.hpp \
+ HashFunction.cpp HtmlSpecialHandler.hpp HtmlSpecialHandler.cpp \
+ HyperlinkManager.hpp HyperlinkManager.cpp ImageToSVG.hpp \
+ ImageToSVG.cpp InputBuffer.hpp InputBuffer.cpp InputReader.hpp \
+ InputReader.cpp JFM.hpp JFM.cpp Length.hpp Length.cpp \
+ macros.hpp MapLine.hpp MapLine.cpp Matrix.hpp Matrix.cpp \
+ MD5HashFunction.hpp Message.hpp Message.cpp \
+ MessageException.hpp MetafontWrapper.hpp MetafontWrapper.cpp \
+ NoPsSpecialHandler.hpp NoPsSpecialHandler.cpp \
+ NumericRanges.hpp PageRanges.hpp PageRanges.cpp PageSize.hpp \
+ PageSize.cpp Pair.hpp PapersizeSpecialHandler.hpp \
+ PapersizeSpecialHandler.cpp PathClipper.hpp PathClipper.cpp \
+ PDFParser.hpp PDFParser.cpp PdfSpecialHandler.hpp \
+ PdfSpecialHandler.cpp PDFToSVG.hpp PreScanDVIReader.hpp \
+ PreScanDVIReader.cpp Process.hpp Process.cpp psdefs.cpp \
+ PSFilter.hpp PSInterpreter.hpp PSInterpreter.cpp PSPattern.hpp \
+ PSPattern.cpp PSPreviewFilter.hpp PSPreviewFilter.cpp \
+ PsSpecialHandler.hpp PsSpecialHandler.cpp RangeMap.hpp \
+ RangeMap.cpp ShadingPatch.hpp ShadingPatch.cpp \
+ SignalHandler.hpp SignalHandler.cpp SourceInput.hpp \
+ SourceInput.cpp SpecialActions.hpp SpecialHandler.hpp \
+ SpecialManager.hpp SpecialManager.cpp StreamReader.hpp \
+ StreamReader.cpp StreamWriter.hpp StreamWriter.cpp Subfont.hpp \
+ Subfont.cpp SVGCharHandler.hpp SVGCharHandler.cpp \
+ SVGCharHandlerFactory.hpp SVGCharHandlerFactory.cpp \
+ SVGCharPathHandler.hpp SVGCharPathHandler.cpp \
+ SVGCharTspanTextHandler.hpp SVGCharTspanTextHandler.cpp \
+ SVGOutput.hpp SVGOutput.cpp SVGSingleCharTextHandler.hpp \
+ SVGSingleCharTextHandler.cpp SVGTree.hpp SVGTree.cpp \
+ System.hpp System.cpp TensorProductPatch.hpp \
+ TensorProductPatch.cpp Terminal.hpp Terminal.cpp TFM.hpp \
+ TFM.cpp ToUnicodeMap.hpp ToUnicodeMap.cpp \
+ TpicSpecialHandler.hpp TpicSpecialHandler.cpp \
+ TriangularPatch.hpp TriangularPatch.cpp TrueTypeFont.hpp \
+ TrueTypeFont.cpp TTFAutohint.hpp TTFAutohint.cpp Unicode.hpp \
+ Unicode.cpp utility.hpp utility.cpp VectorIterator.hpp \
+ VectorStream.hpp VFActions.hpp VFReader.hpp VFReader.cpp \
+ windows.hpp XMLDocument.hpp XMLDocument.cpp XMLNode.hpp \
+ XMLNode.cpp XMLString.hpp XMLString.cpp XXHashFunction.hpp \
+ ZLibOutputStream.hpp $(am__append_8)
EXTRA_DIST = options.xml options.dtd iapi.h ierrors.h MiKTeXCom.hpp MiKTeXCom.cpp
AM_CFLAGS = $(WARNING_CFLAGS) $(ZLIB_INCLUDES) $(CODE_COVERAGE_CFLAGS) \
- $(am__append_9)
+ $(am__append_10)
AM_CXXFLAGS = $(WARNING_CXXFLAGS) -Wnon-virtual-dtor \
-I$(dvisvgm_srcdir)/libs/clipper \
-I$(dvisvgm_srcdir)/libs/variant/include $(POTRACE_CFLAGS) \
- $(XXHASH_CFLAGS) $(am__append_10) $(am__append_11) \
- $(am__append_12) $(KPATHSEA_INCLUDES) $(POTRACE_INCLUDES) \
- $(FREETYPE2_INCLUDES) $(ZLIB_INCLUDES) $(LIBGS_INCLUDES) \
- $(CODE_COVERAGE_CFLAGS) $(am__append_14)
+ $(XXHASH_CFLAGS) $(KPATHSEA_INCLUDES) $(POTRACE_INCLUDES) \
+ $(FREETYPE2_INCLUDES) $(LIBGS_INCLUDES) \
+ $(CODE_COVERAGE_CFLAGS) $(am__append_9) $(am__append_11) \
+ $(am__append_12) $(am__append_13)
CLEANFILES = *.gcda *.gcno
-all: all-am
+all: all-recursive
.SUFFIXES:
.SUFFIXES: .c .cpp .lo .o .obj
@@ -746,7 +793,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CMap.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CMapManager.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CMapReader.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CRC32.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Calculator.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CharMapID.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Color.Po@am__quote@ # am--include-marker
@@ -758,6 +804,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Directory.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DvisvgmSpecialHandler.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EPSFile.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EllipticalArc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EmSpecialHandler.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EncFile.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileFinder.Po@am__quote@ # am--include-marker
@@ -894,14 +941,61 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
+tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
@@ -914,7 +1008,7 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$$unique; \
fi; \
fi
-ctags: ctags-am
+ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
@@ -927,7 +1021,7 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
+cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
@@ -979,22 +1073,48 @@ distdir-am: $(DISTFILES)
|| exit 1; \
fi; \
done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
check-am: all-am
-check: check-am
+check: check-recursive
all-am: Makefile $(PROGRAMS) $(LIBRARIES)
-installdirs:
+installdirs: installdirs-recursive
+installdirs-am:
for dir in "$(DESTDIR)$(bindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-installcheck: installcheck-am
+installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
@@ -1017,12 +1137,12 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
+clean: clean-recursive
clean-am: clean-binPROGRAMS clean-generic clean-libtool \
clean-noinstLIBRARIES mostlyclean-am
-distclean: distclean-am
+distclean: distclean-recursive
-rm -f ./$(DEPDIR)/BasicDVIReader.Po
-rm -f ./$(DEPDIR)/Bezier.Po
-rm -f ./$(DEPDIR)/BgColorSpecialHandler.Po
@@ -1032,7 +1152,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/CMap.Po
-rm -f ./$(DEPDIR)/CMapManager.Po
-rm -f ./$(DEPDIR)/CMapReader.Po
- -rm -f ./$(DEPDIR)/CRC32.Po
-rm -f ./$(DEPDIR)/Calculator.Po
-rm -f ./$(DEPDIR)/CharMapID.Po
-rm -f ./$(DEPDIR)/Color.Po
@@ -1044,6 +1163,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/Directory.Po
-rm -f ./$(DEPDIR)/DvisvgmSpecialHandler.Po
-rm -f ./$(DEPDIR)/EPSFile.Po
+ -rm -f ./$(DEPDIR)/EllipticalArc.Po
-rm -f ./$(DEPDIR)/EmSpecialHandler.Po
-rm -f ./$(DEPDIR)/EncFile.Po
-rm -f ./$(DEPDIR)/FileFinder.Po
@@ -1123,47 +1243,47 @@ distclean: distclean-am
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
-dvi: dvi-am
+dvi: dvi-recursive
dvi-am:
-html: html-am
+html: html-recursive
html-am:
-info: info-am
+info: info-recursive
info-am:
install-data-am:
-install-dvi: install-dvi-am
+install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am: install-binPROGRAMS
-install-html: install-html-am
+install-html: install-html-recursive
install-html-am:
-install-info: install-info-am
+install-info: install-info-recursive
install-info-am:
install-man:
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
install-pdf-am:
-install-ps: install-ps-am
+install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
-maintainer-clean: maintainer-clean-am
+maintainer-clean: maintainer-clean-recursive
-rm -f ./$(DEPDIR)/BasicDVIReader.Po
-rm -f ./$(DEPDIR)/Bezier.Po
-rm -f ./$(DEPDIR)/BgColorSpecialHandler.Po
@@ -1173,7 +1293,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/CMap.Po
-rm -f ./$(DEPDIR)/CMapManager.Po
-rm -f ./$(DEPDIR)/CMapReader.Po
- -rm -f ./$(DEPDIR)/CRC32.Po
-rm -f ./$(DEPDIR)/Calculator.Po
-rm -f ./$(DEPDIR)/CharMapID.Po
-rm -f ./$(DEPDIR)/Color.Po
@@ -1185,6 +1304,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/Directory.Po
-rm -f ./$(DEPDIR)/DvisvgmSpecialHandler.Po
-rm -f ./$(DEPDIR)/EPSFile.Po
+ -rm -f ./$(DEPDIR)/EllipticalArc.Po
-rm -f ./$(DEPDIR)/EmSpecialHandler.Po
-rm -f ./$(DEPDIR)/EncFile.Po
-rm -f ./$(DEPDIR)/FileFinder.Po
@@ -1263,42 +1383,44 @@ maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
-pdf: pdf-am
+pdf: pdf-recursive
pdf-am:
-ps: ps-am
+ps: ps-recursive
ps-am:
uninstall-am: uninstall-binPROGRAMS
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
- clean-binPROGRAMS clean-generic clean-libtool \
- clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-binPROGRAMS install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-pdf install-pdf-am \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags tags-am uninstall uninstall-am uninstall-binPROGRAMS
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+ am--depfiles check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool clean-noinstLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-binPROGRAMS
.PRECIOUS: Makefile
# TL: do not try to rebuild these source files.
+
# the command-line parser class is generated from options.xml by opt2cpp
@TEXLIVE_BUILD_FALSE@$(srcdir)/CommandLine.hpp: options.xml
@TEXLIVE_BUILD_FALSE@ rm -f $@
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp
index eb82372ce58..57aa116f028 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.cpp
@@ -28,11 +28,6 @@
using namespace std;
-MapLine::MapLine () : _sfd(0), _fontindex(0), _slant(0), _bold(0), _extend(1)
-{
-}
-
-
/** Constructs a MapLine object by parsing a single map line from the given stream. */
MapLine::MapLine (istream &is) : MapLine() {
char buf[256];
@@ -226,9 +221,7 @@ void MapLine::parseDVIPDFMLine (InputReader &ir) {
throw_number_expected('w', true);
break;
default:
- ostringstream oss;
- oss << "invalid option: -" << option;
- throw MapLineException(oss.str());
+ throw MapLineException("invalid option: -" + string(1, option));
}
ir.skipSpace();
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp
index 1620becd5e7..ea41fae0d02 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MapLine.hpp
@@ -31,17 +31,15 @@ class InputReader;
class SubfontDefinition;
-struct MapLineException : MessageException
-{
- MapLineException (const std::string &msg) : MessageException(msg) {}
+struct MapLineException : MessageException {
+ explicit MapLineException (const std::string &msg) : MessageException(msg) {}
};
-class MapLine
-{
+class MapLine {
public:
- MapLine (std::istream &is);
- MapLine (std::string str);
+ explicit MapLine (std::istream &is);
+ explicit MapLine (std::string str);
const std::string& texname () const {return _texname;}
const std::string& psname () const {return _psname;}
const std::string& fontfname () const {return _fontfname;}
@@ -53,8 +51,7 @@ class MapLine
SubfontDefinition* sfd () const {return _sfd;}
protected:
- MapLine ();
- void init ();
+ MapLine () =default;
bool isDVIPSFormat (const char *line) const;
void parse (const char *line);
void parseDVIPSLine (InputReader &ir);
@@ -62,13 +59,13 @@ class MapLine
void parseFilenameOptions (std::string opt);
private:
- std::string _texname; ///< TeX font name
- std::string _psname; ///< PS font name
- std::string _fontfname; ///< name of fontfile
- std::string _encname; ///< name of encoding (without file suffix ".enc")
- SubfontDefinition *_sfd; ///< subfont definition to be used
- int _fontindex; ///< font index of file with multiple fonts (e.g. ttc files)
- double _slant, _bold, _extend;
+ std::string _texname; ///< TeX font name
+ std::string _psname; ///< PS font name
+ std::string _fontfname; ///< name of fontfile
+ std::string _encname; ///< name of encoding (without file suffix ".enc")
+ SubfontDefinition *_sfd=nullptr; ///< subfont definition to be used
+ int _fontindex=0; ///< font index of file with multiple fonts (e.g. ttc files)
+ double _slant=0, _bold=0, _extend=1;
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp
index 1f9ff9ac0fa..f94e84809c1 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.cpp
@@ -70,7 +70,7 @@ Matrix::Matrix (double d) {
* remaining matrix components will be set to those of the identity matrix.
* @param[in] v array containing the matrix components
* @param[in] size size of array v */
-Matrix::Matrix (double v[], unsigned size) {
+Matrix::Matrix (const double *v, unsigned size) {
set(v, size);
}
@@ -86,7 +86,7 @@ Matrix::Matrix (const std::vector<double> &v, int start) {
Matrix::Matrix (const string &cmds, Calculator &calc) {
- parse(cmds, calc);
+ *this = parse(cmds, calc);
}
@@ -109,7 +109,7 @@ Matrix& Matrix::set (double d) {
}
-Matrix& Matrix::set (double v[], unsigned size) {
+Matrix& Matrix::set (const double *v, unsigned size) {
size = min(size, 9u);
for (unsigned i=0; i < size; i++)
_values[i/3][i%3] = v[i];
@@ -134,8 +134,8 @@ Matrix& Matrix::set (const vector<double> &v, int start) {
}
-Matrix& Matrix::set(const string &cmds, Calculator &calc) {
- parse(cmds, calc);
+Matrix& Matrix::set (const string &cmds, Calculator &calc) {
+ *this = parse(cmds, calc);
return *this;
}
@@ -143,7 +143,7 @@ Matrix& Matrix::set(const string &cmds, Calculator &calc) {
Matrix& Matrix::translate (double tx, double ty) {
if (tx != 0 || ty != 0) {
TranslationMatrix t(tx, ty);
- rmultiply(t);
+ lmultiply(t);
}
return *this;
}
@@ -152,7 +152,7 @@ Matrix& Matrix::translate (double tx, double ty) {
Matrix& Matrix::scale (double sx, double sy) {
if (sx != 1 || sy != 1) {
ScalingMatrix s(sx, sy);
- rmultiply(s);
+ lmultiply(s);
}
return *this;
}
@@ -163,7 +163,7 @@ Matrix& Matrix::scale (double sx, double sy) {
* @param[in] deg rotation angle in degrees */
Matrix& Matrix::rotate (double deg) {
RotationMatrix r(deg);
- rmultiply(r);
+ lmultiply(r);
return *this;
}
@@ -179,7 +179,7 @@ Matrix& Matrix::xskewByRatio (double xyratio) {
if (xyratio != 0) {
double v[] = {1, xyratio};
Matrix t(v, 2);
- rmultiply(t);
+ lmultiply(t);
}
return *this;
}
@@ -196,7 +196,7 @@ Matrix& Matrix::yskewByRatio (double xyratio) {
if (xyratio != 0) {
double v[] = {1, 0, 0, xyratio};
Matrix t(v, 4);
- rmultiply(t);
+ lmultiply(t);
}
return *this;
}
@@ -208,7 +208,7 @@ Matrix& Matrix::flip (bool haxis, double a) {
s = -1;
double v[] = {-s, 0, (haxis ? 0 : 2*a), 0, s, (haxis ? 2*a : 0), 0, 0, 1};
Matrix t(v);
- rmultiply(t);
+ lmultiply(t);
return *this;
}
@@ -222,8 +222,8 @@ Matrix& Matrix::transpose () {
}
-/** Multiplies this matrix M with matrix tm (tm is the factor on the left side): M := tm * M */
-Matrix& Matrix::lmultiply (const Matrix &tm) {
+/** Multiplies this matrix M with matrix tm (tm is the factor on the right side): M := M * tm */
+Matrix& Matrix::rmultiply (const Matrix &tm) {
Matrix ret;
for (int i=0; i < 3; i++)
for (int j=0; j < 3; j++)
@@ -233,8 +233,8 @@ Matrix& Matrix::lmultiply (const Matrix &tm) {
}
-/** Multiplies this matrix M with matrix tm (tm is the factor on the right side): M := M * tm */
-Matrix& Matrix::rmultiply (const Matrix &tm) {
+/** Multiplies this matrix M with matrix tm (tm is the factor on the left side): M := tm * M */
+Matrix& Matrix::lmultiply (const Matrix &tm) {
Matrix ret;
for (int i=0; i < 3; i++)
for (int j=0; j < 3; j++)
@@ -356,8 +356,8 @@ static double getArgument (istream &is, Calculator &calc, double def, bool optio
}
-Matrix& Matrix::parse (istream &is, Calculator &calc) {
- *this = Matrix(1);
+Matrix Matrix::parse (istream &is, Calculator &calc) {
+ Matrix ret(1);
while (is) {
is >> ws;
int cmd = is.get();
@@ -365,22 +365,22 @@ Matrix& Matrix::parse (istream &is, Calculator &calc) {
case 'T': {
double tx = getArgument(is, calc, 0, false, false);
double ty = getArgument(is, calc, 0, true, true);
- translate(tx, ty);
+ ret.translate(tx, ty);
break;
}
case 'S': {
double sx = getArgument(is, calc, 1, false, false);
double sy = getArgument(is, calc, sx, true, true );
- scale(sx, sy);
+ ret.scale(sx, sy);
break;
}
case 'R': {
double a = getArgument(is, calc, 0, false, false);
double x = getArgument(is, calc, calc.getVariable("ux")+calc.getVariable("w")/2, true, true);
double y = getArgument(is, calc, calc.getVariable("uy")+calc.getVariable("h")/2, true, true);
- translate(-x, -y);
- rotate(a);
- translate(x, y);
+ ret.translate(-x, -y);
+ ret.rotate(a);
+ ret.translate(x, y);
break;
}
case 'F': {
@@ -388,7 +388,7 @@ Matrix& Matrix::parse (istream &is, Calculator &calc) {
if (c != 'H' && c != 'V')
throw ParserException("'H' or 'V' expected");
double a = getArgument(is, calc, 0, false, false);
- flip(c == 'H', a);
+ ret.flip(c == 'H', a);
break;
}
case 'K': {
@@ -396,15 +396,12 @@ Matrix& Matrix::parse (istream &is, Calculator &calc) {
if (c != 'X' && c != 'Y')
throw ParserException("transformation command 'K' must be followed by 'X' or 'Y'");
double a = getArgument(is, calc, 0, false, false);
- if (std::abs(cos(deg2rad(a))) < numeric_limits<double>::epsilon()) {
- ostringstream oss;
- oss << "illegal skewing angle: " << a << " degrees";
- throw ParserException(oss.str());
- }
+ if (std::abs(cos(deg2rad(a))) < numeric_limits<double>::epsilon())
+ throw ParserException("illegal skewing angle: " + util::to_string(a) + " degrees");
if (c == 'X')
- xskewByAngle(a);
+ ret.xskewByAngle(a);
else
- yskewByAngle(a);
+ ret.yskewByAngle(a);
break;
}
case 'M': {
@@ -415,20 +412,18 @@ Matrix& Matrix::parse (istream &is, Calculator &calc) {
v[6] = v[7] = 0;
v[8] = 1;
Matrix tm(v);
- rmultiply(tm);
+ ret.lmultiply(tm);
break;
}
default:
- ostringstream oss;
- oss << "transformation command expected (found '" << char(cmd) << "' instead)";
- throw ParserException(oss.str());
+ throw ParserException("transformation command expected (found '" + string(1, cmd) + "' instead)");
}
}
- return *this;
+ return ret;
}
-Matrix& Matrix::parse (const string &cmds, Calculator &calc) {
+Matrix Matrix::parse (const string &cmds, Calculator &calc) {
istringstream iss;
iss.str(cmds);
return parse(iss, calc);
@@ -437,17 +432,14 @@ Matrix& Matrix::parse (const string &cmds, Calculator &calc) {
/** Returns an SVG matrix expression that can be used in transform attributes.
* ((a,b,c),(d,e,f),(0,0,1)) => matrix(a d b e c f) */
-string Matrix::getSVG () const {
+string Matrix::toSVG () const {
ostringstream oss;
oss << "matrix(";
for (int i=0; i < 3; i++) {
- for (int j=0; j < 2; j++) {
- if (i > 0 || j > 0)
- oss << ' ';
- oss << XMLString(_values[j][i]);
- }
+ for (int j=0; j < 2; j++)
+ oss << XMLString(_values[j][i]) << ' ';
}
- oss << ')';
+ oss.seekp(-1, ios::cur) << ')'; // overwrite trailing space character
return oss.str();
}
@@ -467,9 +459,118 @@ ostream& Matrix::write (ostream &os) const {
}
-//////////////////////////////////////////////////////////////////
+static const char* ord_suffix (int n) {
+ static const char *suffixes[] = {"th", "st", "nd", "rd"};
+ if (abs(n) < 4)
+ return suffixes[n];
+ return suffixes[0];
+}
+
+
+static void skip_comma_wsp (istream &is) {
+ is >> ws;
+ if (is.peek() == ',') is.ignore(1);
+ is >> ws;
+}
+
+
+static size_t parse_transform_cmd (istream &is, string cmd, size_t minparams, size_t maxparams, vector<double> &params) {
+ for (int i=0; i < int(cmd.length()); i++) {
+ if (is.get() != cmd[i]) {
+ is.seekg(-i-1, ios::cur);
+ return 0;
+ }
+ }
+ params.clear();
+ is >> ws;
+ if (is.get() != '(')
+ throw ParserException("missing '(' after command '"+cmd+"'");
+ for (size_t i=1; i <= maxparams; i++) {
+ is >> ws;
+ double val;
+ if (is.fail())
+ throw ParserException(to_string(i)+ord_suffix(i)+" parameter of '"+cmd+"' must be a number");
+ is >> val;
+ params.push_back(val);
+ is >> ws;
+ if (i == minparams && is.peek() == ')') {
+ is.ignore(1);
+ return i;
+ }
+ if (i == maxparams) {
+ if (is.peek() != ')')
+ throw ParserException("missing ')' at end of command '"+cmd+"'");
+ is.ignore(1);
+ }
+ skip_comma_wsp(is);
+ }
+ return maxparams;
+}
+static bool ne (double x, double y) {return abs(x-y) >= 1e-6;}
+static bool ne_angle (double x, double y) {return abs(x-y) >= 1e-3;}
+
+
+Matrix Matrix::parseSVGTransform (const string &transform) {
+ istringstream iss(transform);
+ Matrix matrix(1);
+ iss >> ws;
+ while (iss) {
+ vector<double> params;
+ if (parse_transform_cmd(iss, "matrix", 6, 6, params)) {
+ if (ne(params[0], 1) || ne(params[1], 0) || ne(params[2], 0) || ne(params[3], 1) || ne(params[4], 0) || ne(params[5], 0))
+ matrix.rmultiply({params[0], params[2], params[4], params[1], params[3], params[5]});
+ }
+ else if (parse_transform_cmd(iss, "rotate", 1, 3, params)) {
+ if (params.size() == 1) {
+ params.push_back(0);
+ params.push_back(0);
+ }
+ if (ne_angle(fmod(params[0], 360), 0)) {
+ bool translate = ne(params[1], 0) || ne(params[2], 0);
+ if (translate)
+ matrix.rmultiply(TranslationMatrix(params[1], params[2]));
+ matrix.rmultiply(RotationMatrix(params[0]));
+ if (translate)
+ matrix.rmultiply(TranslationMatrix(-params[1], -params[2]));
+ }
+ }
+ else if (parse_transform_cmd(iss, "scale", 1, 2, params)) {
+ if (params.size() == 1)
+ params.push_back(1);
+ if (ne(params[0], 1) || ne(params[1], 1))
+ matrix.rmultiply(ScalingMatrix(params[0], params[1]));
+ }
+ else if (parse_transform_cmd(iss, "skewX", 1, 1, params)) {
+ if (ne_angle(fmod(abs(params[0])-90, 180), 0))
+ matrix.rmultiply(XSkewingMatrix(params[0]));
+ }
+ else if (parse_transform_cmd(iss, "skewY", 1, 1, params)) {
+ if (ne_angle(fmod(abs(params[0])-90, 180), 0))
+ matrix.rmultiply(YSkewingMatrix(params[0]));
+ }
+ else if (parse_transform_cmd(iss, "translate", 1, 2, params)) {
+ if (params.size() == 1)
+ params.push_back(0);
+ if (ne(params[0], 0) || ne(params[1], 0))
+ matrix.rmultiply(TranslationMatrix(params[0], params[1]));
+ }
+ else { // invalid command
+ string cmd;
+ while (isalpha(iss.peek()))
+ cmd += char(iss.get());
+ if (cmd.empty())
+ throw ParserException("unexpected character in transform attribute: "+to_string(char(iss.get())));
+ throw ParserException("invalid command in transform attribute: "+cmd);
+ }
+ skip_comma_wsp(iss);
+ }
+ return matrix;
+}
+
+//////////////////////////////////////////////////////////////////
+
TranslationMatrix::TranslationMatrix (double tx, double ty) {
double v[] = {1, 0, tx, 0, 1, ty};
set(v, 6);
@@ -490,3 +591,14 @@ RotationMatrix::RotationMatrix (double deg) {
set(v, 5);
}
+
+XSkewingMatrix::XSkewingMatrix (double deg) {
+ double xyratio = tan(deg2rad(deg));
+ lmultiply(Matrix({1, xyratio}));
+}
+
+
+YSkewingMatrix::YSkewingMatrix (double deg) {
+ double xyratio = tan(deg2rad(deg));
+ lmultiply(Matrix({1, 0, 0, xyratio}));
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp
index 73b443a619c..733ff71fad8 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Matrix.hpp
@@ -30,7 +30,7 @@
struct ParserException : public MessageException {
- ParserException (const std::string &msg) : MessageException(msg) {}
+ explicit ParserException (const std::string &msg) : MessageException(msg) {}
};
class Calculator;
@@ -42,20 +42,18 @@ class Matrix {
public:
Matrix (const std::string &cmds, Calculator &calc);
Matrix (double d=0);
- Matrix (double v[], unsigned size=9);
- Matrix (const std::vector<double> &v, int start=0);
+ explicit Matrix (const double *v, unsigned size=9);
+ explicit Matrix (const std::vector<double> &v, int start=0);
Matrix (std::initializer_list<double> initlist);
Matrix& set (double d);
- Matrix& set (double v[], unsigned size);
+ Matrix& set (const double *v, unsigned size);
Matrix& set (const std::vector<double> &v, int start=0);
Matrix& set (const std::string &cmds, Calculator &calc);
double get (int row, int col) const {return _values[row][col];}
Matrix& transpose ();
Matrix& invert ();
- Matrix& parse (std::istream &is, Calculator &c);
- Matrix& parse (const std::string &cmds, Calculator &c);
- Matrix& lmultiply (const Matrix &tm);
Matrix& rmultiply (const Matrix &tm);
+ Matrix& lmultiply (const Matrix &tm);
Matrix& translate (double tx, double ty);
Matrix& translate (const DPair &p) {return translate(p.x(), p.y());}
Matrix& scale (double sx, double sy);
@@ -72,9 +70,13 @@ class Matrix {
bool operator != (const Matrix &m) const;
bool isIdentity() const;
bool isTranslation (double &tx, double &ty) const;
- std::string getSVG () const;
+ std::string toSVG () const;
std::ostream& write (std::ostream &os) const;
+ static Matrix parse (std::istream &is, Calculator &c);
+ static Matrix parse (const std::string &cmds, Calculator &c);
+ static Matrix parseSVGTransform (const std::string &transform);
+
private:
double _values[3][3]; // row x col
};
@@ -91,7 +93,17 @@ struct ScalingMatrix : public Matrix {
struct RotationMatrix : public Matrix {
- RotationMatrix (double deg);
+ explicit RotationMatrix (double deg);
+};
+
+
+struct XSkewingMatrix : public Matrix {
+ explicit XSkewingMatrix (double deg);
+};
+
+
+struct YSkewingMatrix : public Matrix {
+ explicit YSkewingMatrix (double deg);
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp
index 4ab9fc89a7d..85ed204cb43 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.cpp
@@ -28,12 +28,8 @@
using namespace std;
-MessageStream::MessageStream () : _os(0), _nl(false), _col(1), _indent(0) {
-}
-
-
-MessageStream::MessageStream (std::ostream &os)
- : _os(&os), _nl(true), _col(1), _indent(0)
+MessageStream::MessageStream (std::ostream &os) noexcept
+ : _os(&os), _nl(true)
{
Terminal::init(os);
}
@@ -45,7 +41,7 @@ MessageStream::~MessageStream () {
}
-void MessageStream::putChar (const char c, ostream &os) {
+void MessageStream::putChar (char c, ostream &os) {
switch (c) {
case '\r':
os << '\r';
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp
index 95a96555637..a7e60340218 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Message.hpp
@@ -31,13 +31,12 @@
class Message;
-class MessageStream
-{
+class MessageStream {
friend class Message;
public:
- MessageStream ();
- MessageStream (std::ostream &os);
+ MessageStream () =default;
+ explicit MessageStream (std::ostream &os) noexcept;
~MessageStream ();
template <typename T>
@@ -58,26 +57,25 @@ class MessageStream
void clearline ();
protected:
- void putChar (const char c, std::ostream &os);
+ void putChar (char c, std::ostream &os);
std::ostream* os () {return _os;}
private:
- std::ostream *_os;
- bool _nl; ///< true if previous character was a newline
- int _col; ///< current terminal column
- int _indent; ///< indentation width (number of columns/characters)
+ std::ostream *_os=nullptr;
+ bool _nl=false; ///< true if previous character was a newline
+ int _col=1; ///< current terminal column
+ int _indent=0; ///< indentation width (number of columns/characters)
};
-class Message
-{
+class Message {
struct Color {
- Color () : foreground(-1), background(-1) {}
- Color (int8_t fgcolor) : foreground(fgcolor), background(-1) {}
- Color (int8_t fgcolor, bool light) : foreground(fgcolor + (light ? 8 : 0)), background(-1) {}
- Color (int8_t fgcolor, int8_t bgcolor) : foreground(fgcolor), background(bgcolor) {}
- int8_t foreground;
- int8_t background;
+ Color () =default;
+ explicit Color (int8_t fgcolor) noexcept : foreground(fgcolor) {}
+ Color (int8_t fgcolor, bool light) noexcept: foreground(fgcolor + (light ? 8 : 0)) {}
+ Color (int8_t fgcolor, int8_t bgcolor) noexcept : foreground(fgcolor), background(bgcolor) {}
+ int8_t foreground = -1;
+ int8_t background = -1;
};
public:
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp
index ccd6567d3d2..c7aa342860e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MessageException.hpp
@@ -25,12 +25,10 @@
#include <string>
-class MessageException : public std::exception
-{
+class MessageException : public std::exception {
public:
- MessageException (const std::string &msg) : _message(msg) {}
- virtual ~MessageException () throw() =default;
- const char* what () const throw() override {return _message.c_str();}
+ explicit MessageException (std::string msg) : _message(std::move(msg)) {}
+ const char* what () const noexcept override {return _message.c_str();}
private:
std::string _message;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp
index a5f8538c319..5807d7254ef 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.cpp
@@ -18,7 +18,6 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
-#include <cstdlib>
#include <cctype>
#include <fstream>
#include <sstream>
@@ -32,12 +31,13 @@
using namespace std;
-MetafontWrapper::MetafontWrapper (const string &fname, const string &dir) : _fontname(fname), _dir(dir)
+MetafontWrapper::MetafontWrapper (string fname, string dir)
+ : _fontname(std::move(fname)), _dir(std::move(dir))
{
// ensure that folder paths ends with slash
if (_dir.empty())
_dir = "./";
- else if (_dir != "/" && dir[dir.length()-1] != '/')
+ else if (_dir != "/" && _dir.back() != '/')
_dir += '/';
}
@@ -87,7 +87,7 @@ bool MetafontWrapper::call (const string &mode, double mag) {
iss.getline(buf, sizeof(buf));
string line = buf;
if (line.substr(0, 3) == ">> ") {
- resolution = atoi(line.substr(3).c_str());
+ resolution = stoi(line.substr(3));
break;
}
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp
index e1107afe9ba..031eb01ebd1 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MetafontWrapper.hpp
@@ -29,7 +29,7 @@ class FileFinder;
class MetafontWrapper
{
public:
- MetafontWrapper (const std::string &fontname, const std::string &dir);
+ MetafontWrapper (std::string fname, std::string dir);
bool call (const std::string &mode, double mag);
bool make (const std::string &mode, double mag);
bool success () const;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp
index c87d0e3d862..5bf19811674 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/MiKTeXCom.hpp
@@ -25,10 +25,10 @@
#include "windows.hpp"
#ifdef _MSC_VER
-#import <MiKTeX209-session.tlb>
+#import <miktex-session.tlb>
using namespace MiKTeXSession2_9;
#else
-#include "miktex209-session.h"
+#include "miktex-session.h"
#endif
class MiKTeXCom {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp
index 5f97cfdb27a..f4f04218856 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/NoPsSpecialHandler.hpp
@@ -27,8 +27,8 @@ class NoPsSpecialHandler : public SpecialHandler {
public:
NoPsSpecialHandler () : _count(0) {}
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
- const char* name () const override {return 0;}
- const char* info () const override {return 0;}
+ const char* name () const override {return nullptr;}
+ const char* info () const override {return nullptr;}
std::vector<const char*> prefixes() const override;
protected:
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.cpp
index 10dd9b1577c..1ecd40cba82 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.cpp
@@ -119,7 +119,7 @@ static pair<bool,int> parse_escape_seq (InputReader &ir) {
string str;
for (int i=0; i < 3 && isoctaldigit(ir.peek()); i++)
str += static_cast<char>(ir.get());
- return pair<bool,int>{true, stoi(str, 0, 8)};
+ return pair<bool,int>{true, stoi(str, nullptr, 8)};
}
char c = static_cast<char>(ir.get());
switch (c) {
@@ -168,10 +168,8 @@ static string parse_literal_string (InputReader &ir) {
static char get_hex_digit (InputReader &ir) {
int c = ir.get();
if (isxdigit(c))
- return static_cast<char>(c);
- ostringstream oss;
- oss << "invalid hexadecimal digit '" << static_cast<char>(c) << "'";
- throw PDFException(oss.str());
+ return char(c);
+ throw PDFException("invalid hexadecimal digit '" + string(1, char(c)) + "'");
}
@@ -190,7 +188,7 @@ static string parse_hex_string (InputReader &ir) {
else if (ir.peek() == '>')
hexpair += '0';
ir.skipSpace();
- str += static_cast<char>(stoi(hexpair, 0, 16));
+ str += static_cast<char>(stoi(hexpair, nullptr, 16));
}
if (ir.peek() != '>')
throw PDFException("missing '>' at end of hexadecimal string");
@@ -316,7 +314,7 @@ static string& subst_numeric_chars (string &str) {
if (pos > str.length()-3)
throw PDFException("sign character # must be followed by two hexadecimal digits");
if (isxdigit(str[pos+1]) && isxdigit(str[pos+2])) {
- int c = stoi(str.substr(pos+1, 2), 0, 16);
+ int c = stoi(str.substr(pos+1, 2), nullptr, 16);
if (c == 0)
throw PDFException("null character not permitted in name");
str.replace(pos, 3, 1, static_cast<char>(c));
@@ -458,7 +456,7 @@ static ostream& operator << (ostream &os, const unique_ptr<Dictionary<string,PDF
struct WriteVisitor {
- WriteVisitor (ostream &os) : _os(os) {}
+ explicit WriteVisitor (ostream &os) : _os(os) {}
template <typename T> void operator () (const T &val) {_os << val;}
ostream &_os;
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.hpp
index f4595ce4de0..64716683077 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFParser.hpp
@@ -79,12 +79,12 @@ struct PDFObjectRef {
};
struct PDFOperator {
- PDFOperator (const std::string &name) : opname(name) {}
+ explicit PDFOperator (std::string name) : opname(std::move(name)) {}
std::string opname;
};
struct PDFName {
- PDFName (const std::string &val) : str(val) {}
+ explicit PDFName (std::string val) : str(std::move(val)) {}
bool operator == (const PDFName &name) const {return str == name.str;}
std::string str;
};
@@ -134,14 +134,14 @@ class PDFObject {
template<> inline const PDFArray* PDFObject::get() const {
- if (auto *p = mpark::get_if<std::unique_ptr<PDFArray>>(&_value))
+ if (auto p = mpark::get_if<std::unique_ptr<PDFArray>>(&_value))
return &(**p);
return nullptr;
}
template<> inline const PDFDict* PDFObject::get() const {
- if (auto *p = mpark::get_if<std::unique_ptr<PDFDict>>(&_value))
+ if (auto p = mpark::get_if<std::unique_ptr<PDFDict>>(&_value))
return &(**p);
return nullptr;
}
@@ -179,7 +179,7 @@ class PDFParser {
/** If errors occur while parsing a sequence of PDF objects, an instance of this exception is thrown. */
struct PDFException : public MessageException {
- PDFException (const std::string &msg) : MessageException(msg) {}
+ explicit PDFException (const std::string &msg) : MessageException(msg) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFToSVG.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFToSVG.hpp
index f999de88e8d..d1871d0bb1e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFToSVG.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PDFToSVG.hpp
@@ -60,4 +60,3 @@ class PDFToSVG : public ImageToSVG {
};
#endif
-
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp
index c27dcfea4bb..aa9cab21077 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.cpp
@@ -51,8 +51,15 @@ void PSInterpreter::init () {
"-dWRITESYSTEMDICT", // leave systemdict writable as some operators must be replaced
"-dNOPROMPT"
};
- if (int gsrev = _gs.revision())
+ if (int gsrev = _gs.revision()) {
gsargs.emplace_back(gsrev == 922 ? "-dREALLYDELAYBIND" : "-dDELAYBIND");
+ // As of GS 9.50, -dSAFER is active by default which leads to warnings
+ // in conjunction with -dDELAYBIND and -dWRITESYSTEMDICT.
+ // Thus, -dDELAYSAFER (or -dNOSAFER) must be added.
+ // https://www.ghostscript.com/doc/9.50/Use.htm#Safer
+ if (gsrev >= 950)
+ gsargs.emplace_back("-dDELAYSAFER");
+ }
_gs.init(gsargs.size(), gsargs.data(), this);
_gs.set_stdio(input, output, error);
_initialized = true;
@@ -111,7 +118,7 @@ bool PSInterpreter::execute (const char *str, size_t len, bool flush) {
if (_filter && _filter->active()) {
PSFilter *filter = _filter;
- _filter = 0; // prevent recursion when filter calls execute()
+ _filter = nullptr; // prevent recursion when filter calls execute()
filter->execute(str, len);
if (filter->active()) // filter still active after execution?
_filter = filter;
@@ -189,7 +196,7 @@ int GSDLLCALL PSInterpreter::input (void *inst, char *buf, int len) {
* @param[in] len number of characters in buf
* @return number of processed characters (equals 'len') */
int GSDLLCALL PSInterpreter::output (void *inst, const char *buf, int len) {
- PSInterpreter *self = static_cast<PSInterpreter*>(inst);
+ auto self = static_cast<PSInterpreter*>(inst);
if (self && self->_actions) {
const size_t MAXLEN = 512; // maximal line length (longer lines are of no interest)
const char *end = buf+len-1; // last position of buf
@@ -204,7 +211,7 @@ int GSDLLCALL PSInterpreter::output (void *inst, const char *buf, int len) {
vector<char> &linebuf = self->_linebuf; // just a shorter name...
if ((*last == '\n' || !self->active()) || self->_inError) {
if (linelength + linebuf.size() > 1) { // prefix "dvi." plus final newline
- SplittedCharInputBuffer ib(linebuf.empty() ? 0 : &linebuf[0], linebuf.size(), first, linelength);
+ SplittedCharInputBuffer ib(linebuf.empty() ? nullptr : &linebuf[0], linebuf.size(), first, linelength);
BufferInputReader in(ib);
if (self->_inError)
self->_errorMessage += string(first, linelength);
@@ -213,7 +220,7 @@ int GSDLLCALL PSInterpreter::output (void *inst, const char *buf, int len) {
if (in.check("Unrecoverable error: ")) {
self->_errorMessage.clear();
while (!in.eof())
- self->_errorMessage += in.get();
+ self->_errorMessage += char(in.get());
self->_inError = true;
}
else if (in.check("dvi."))
@@ -279,6 +286,7 @@ void PSInterpreter::callActions (InputReader &in) {
{"setlinewidth", { 1, &PSActions::setlinewidth}},
{"setmatrix", { 6, &PSActions::setmatrix}},
{"setmiterlimit", { 1, &PSActions::setmiterlimit}},
+ {"setnulldevice", { 1, &PSActions::setnulldevice}},
{"setopacityalpha",{ 1, &PSActions::setopacityalpha}},
{"setshapealpha", { 1, &PSActions::setshapealpha}},
{"setpagedevice", { 0, &PSActions::setpagedevice}},
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp
index 6a64351889b..8e75e3c5f1a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSInterpreter.hpp
@@ -32,7 +32,7 @@
struct PSException : public MessageException {
- PSException (const std::string &msg) : MessageException(msg) {}
+ explicit PSException (const std::string &msg) : MessageException(msg) {}
};
@@ -71,6 +71,7 @@ struct PSActions {
virtual void setlinewidth (std::vector<double> &p) =0;
virtual void setmatrix (std::vector<double> &p) =0;
virtual void setmiterlimit (std::vector<double> &p) =0;
+ virtual void setnulldevice (std::vector<double> &p) =0;
virtual void setopacityalpha (std::vector<double> &p) =0;
virtual void setshapealpha (std::vector<double> &p) =0;
virtual void setpagedevice (std::vector<double> &p) =0;
@@ -90,7 +91,7 @@ class PSInterpreter {
enum Mode {PS_NONE, PS_RUNNING, PS_QUIT};
public:
- explicit PSInterpreter (PSActions *actions=0);
+ explicit PSInterpreter (PSActions *actions=nullptr);
PSInterpreter (const PSInterpreter &psi) =delete;
bool execute (const char *str, size_t len, bool flush=true);
bool execute (const char *str, bool flush=true) {return execute(str, std::strlen(str), flush);}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp
index 43b45c56596..90ff6a56852 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.cpp
@@ -39,7 +39,7 @@ string PSPattern::svgID () const {
/** Appends the definition of this pattern to the "def" section of the SVG tree. */
void PSPattern::apply (SpecialActions &actions) {
if (auto pattern = createPatternNode())
- actions.appendToDefs(std::move(pattern));
+ actions.svgTree().appendToDefs(std::move(pattern));
}
@@ -54,18 +54,18 @@ PSTilingPattern::PSTilingPattern (int id, BoundingBox &bbox, Matrix &matrix, dou
/** Assigns a new group element. */
-void PSTilingPattern::setGroupNode (unique_ptr<XMLElementNode> &&node) {
+void PSTilingPattern::setGroupNode (unique_ptr<XMLElement> node) {
_groupNode = std::move(node);
_groupNodePtr = _groupNode.get();
}
/** Creates a new pattern element representing the pattern defined in the PS code. */
-unique_ptr<XMLElementNode> PSTilingPattern::createPatternNode () const {
+unique_ptr<XMLElement> PSTilingPattern::createPatternNode () const {
if (!_groupNode)
return nullptr;
BoundingBox box(_bbox.minX(), _bbox.minY(), _bbox.minX()+_xstep, _bbox.minY()+_ystep);
- auto pattern = util::make_unique<XMLElementNode>("pattern");
+ auto pattern = util::make_unique<XMLElement>("pattern");
pattern->addAttribute("id", svgID());
pattern->addAttribute("x", box.minX());
pattern->addAttribute("y", box.minY());
@@ -74,7 +74,7 @@ unique_ptr<XMLElementNode> PSTilingPattern::createPatternNode () const {
pattern->addAttribute("viewBox", box.toSVGViewBox());
pattern->addAttribute("patternUnits", "userSpaceOnUse");
if (!_matrix.isIdentity())
- pattern->addAttribute("patternTransform", _matrix.getSVG());
+ pattern->addAttribute("patternTransform", _matrix.toSVG());
if (_xstep < _bbox.width() || _ystep < _bbox.height()) { // overlapping tiles?
// disable clipping at the tile borders => tiles become "transparent"
pattern->addAttribute("overflow", "visible");
@@ -89,10 +89,10 @@ unique_ptr<XMLElementNode> PSTilingPattern::createPatternNode () const {
/** Creates a new clip element restricting the drawing area to the
* dimensions given in the definition of the pattern. */
-unique_ptr<XMLElementNode> PSTilingPattern::createClipNode() const {
- auto clip = util::make_unique<XMLElementNode>("clipPath");
+unique_ptr<XMLElement> PSTilingPattern::createClipNode() const {
+ auto clip = util::make_unique<XMLElement>("clipPath");
clip->addAttribute("id", "pc"+XMLString(psID()));
- auto rect = util::make_unique<XMLElementNode>("rect");
+ auto rect = util::make_unique<XMLElement>("rect");
rect->addAttribute("x", _bbox.minX());
rect->addAttribute("y", _bbox.minY());
rect->addAttribute("width", _bbox.width());
@@ -104,9 +104,9 @@ unique_ptr<XMLElementNode> PSTilingPattern::createClipNode() const {
/** Creates a new group element that contains all "drawing" elements that
* define the pattern graphic. */
-unique_ptr<XMLElementNode> PSTilingPattern::createGroupNode () const {
+unique_ptr<XMLElement> PSTilingPattern::createGroupNode () const {
// add all succeeding path elements to this group
- auto group = util::make_unique<XMLElementNode>("g");
+ auto group = util::make_unique<XMLElement>("g");
group->addAttribute("clip-path", XMLString("url(#pc")+XMLString(psID())+")");
return group;
}
@@ -145,16 +145,16 @@ string PSUncoloredTilingPattern::svgID () const {
/** Appends the definition of this pattern with the current color applied
* to the "def" section of the SVG tree. */
void PSUncoloredTilingPattern::apply (SpecialActions &actions) {
- set<Color>::iterator it=_colors.find(_currentColor);
+ auto it=_colors.find(_currentColor);
if (it == _colors.end()) {
if (_applied)
- setGroupNode(util::static_unique_ptr_cast<XMLElementNode>(getGroupNode()->clone()));
+ setGroupNode(util::static_unique_ptr_cast<XMLElement>(getGroupNode()->clone()));
// assign current color to the pattern graphic
- vector<XMLElementNode*> colored_elems;
+ vector<XMLElement*> colored_elems;
const array<const char*, 2> attribs = {{"fill", "stroke"}};
for (const char *attrib : attribs) {
getGroupNode()->getDescendants(nullptr, attrib, colored_elems);
- for (XMLElementNode *elem : colored_elems) {
+ for (XMLElement *elem : colored_elems) {
if (string(elem->getAttributeValue(attrib)) != "none")
elem->addAttribute(attrib, _currentColor.svgColorString());
}
@@ -167,7 +167,7 @@ void PSUncoloredTilingPattern::apply (SpecialActions &actions) {
}
-unique_ptr<XMLElementNode> PSUncoloredTilingPattern::createClipNode() const {
+unique_ptr<XMLElement> PSUncoloredTilingPattern::createClipNode() const {
// only the first instance of this patterns get a clip element
if (_colors.empty())
return PSTilingPattern::createClipNode();
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp
index 818e08fc87b..7dde27827d6 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPattern.hpp
@@ -32,7 +32,7 @@
class SpecialActions;
class SVGTree;
-class XMLElementNode;
+class XMLElement;
class PSPattern {
public:
@@ -42,8 +42,8 @@ class PSPattern {
virtual void apply (SpecialActions &actions);
protected:
- PSPattern (int id) : _id(id) {}
- virtual std::unique_ptr<XMLElementNode> createPatternNode () const =0;
+ explicit PSPattern (int id) : _id(id) {}
+ virtual std::unique_ptr<XMLElement> createPatternNode () const =0;
private:
int _id; ///< PostSCript ID of this pattern
@@ -52,23 +52,23 @@ class PSPattern {
class PSTilingPattern : public PSPattern {
public:
- virtual XMLElementNode* getContainerNode () {return _groupNode.get();}
+ virtual XMLElement* getContainerNode () {return _groupNode.get();}
void apply (SpecialActions &actions) override;
protected:
PSTilingPattern (int id, BoundingBox &bbox, Matrix &matrix, double xstep, double ystep);
- std::unique_ptr<XMLElementNode> createPatternNode () const override;
- virtual std::unique_ptr<XMLElementNode> createClipNode () const;
- virtual std::unique_ptr<XMLElementNode> createGroupNode () const;
- virtual XMLElementNode* getGroupNode () const {return _groupNodePtr;}
- virtual void setGroupNode (std::unique_ptr<XMLElementNode> &&node);
+ std::unique_ptr<XMLElement> createPatternNode () const override;
+ virtual std::unique_ptr<XMLElement> createClipNode () const;
+ virtual std::unique_ptr<XMLElement> createGroupNode () const;
+ virtual XMLElement* getGroupNode () const {return _groupNodePtr;}
+ virtual void setGroupNode (std::unique_ptr<XMLElement> node);
private:
BoundingBox _bbox; ///< bounding box of the tile graphics
Matrix _matrix; ///< tile transformation
double _xstep, _ystep; ///< horizontal and vertical distance between neighboured tiles
- mutable std::unique_ptr<XMLElementNode> _groupNode; ///< group containing the drawing elements
- XMLElementNode *_groupNodePtr; ///< keeps a pointer to the group node even after moving _groupNode to the SVGTree
+ mutable std::unique_ptr<XMLElement> _groupNode; ///< group containing the drawing elements
+ XMLElement *_groupNodePtr; ///< keeps a pointer to the group node even after moving _groupNode to the SVGTree
};
@@ -86,7 +86,7 @@ class PSUncoloredTilingPattern final : public PSTilingPattern {
void apply (SpecialActions &actions) override;
protected:
- std::unique_ptr<XMLElementNode> createClipNode () const override;
+ std::unique_ptr<XMLElement> createClipNode () const override;
private:
std::set<Color> _colors; ///< colors this pattern has already been drawn with
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp
index 5f58d931d56..7de5a2e2a8b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PSPreviewFilter.hpp
@@ -30,7 +30,7 @@ class SpecialActions;
class PSPreviewFilter : public PSFilter {
public:
- PSPreviewFilter (PSInterpreter &psi);
+ explicit PSPreviewFilter (PSInterpreter &psi);
void activate ();
void execute (const char *code, size_t len) override;
bool active () const override {return _active;}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp
index dc82151fff9..e6c1a8287bd 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageRanges.cpp
@@ -78,7 +78,7 @@ bool PageRanges::parse (const string &str, int max_page) {
/** Returns the number of pages. */
size_t PageRanges::numberOfPages () const {
size_t sum=0;
- for (NumericRanges<int>::ConstIterator it=begin(); it != end(); ++it)
- sum += it->second - it->first + 1;
+ for (const auto &entry : *this)
+ sum += entry.second - entry.first + 1;
return sum;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp
index 3831f5d49bc..2f0a48aeb94 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.cpp
@@ -96,7 +96,7 @@ void PageSize::resize (string name) {
name = util::tolower(name);
// extract optional suffix
- size_t pos = name.rfind("-");
+ size_t pos = name.rfind('-');
bool landscape = false;
if (pos != string::npos) {
string suffix = name.substr(pos);
@@ -117,14 +117,14 @@ void PageSize::resize (string name) {
}
else if (name == "legal") {
_width = 216_mm;
- _height = 356_mm;;
+ _height = 356_mm;
}
else if (name == "letter") {
_width = 216_mm;
_height = 279_mm;
}
else if (name == "ledger") {
- _width = 279_mm;;
+ _width = 279_mm;
_height = 432_mm;
}
else if (isdigit(name[1]) && name.length() < 5) { // limit length of number to prevent arithmetic errors
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp
index b5a0836162d..c785a89564e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PageSize.hpp
@@ -25,14 +25,14 @@
#include "MessageException.hpp"
struct PageSizeException : public MessageException {
- PageSizeException (const std::string &msg) : MessageException(msg) {}
+ explicit PageSizeException (const std::string &msg) : MessageException(msg) {}
};
class PageSize {
public:
PageSize () =default;
PageSize (Length w, Length h) : _width(w), _height(h) {}
- PageSize (const std::string &name);
+ explicit PageSize (const std::string &name);
void resize (std:: string name);
void resize (Length w, Length h);
Length width () const {return _width;}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp
index 2ca2a9466d7..5dd7c68a932 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Pair.hpp
@@ -26,17 +26,21 @@
#include "macros.hpp"
template <typename T>
-class Pair
-{
+class Pair {
public:
- Pair (T x=0, T y=0) : _x(x), _y(y) {}
+ explicit Pair (T x=0, T y=0) : _x(x), _y(y) {}
+ template <typename U> Pair (const Pair<U> &p) : _x(U(p.x())), _y(U(p.y())) {}
+ Pair (const Pair &p) =default;
+ Pair (Pair &&p) =default;
+ Pair& operator = (const Pair &p) =default;
+ Pair& operator = (Pair &&p) =default;
Pair operator += (const Pair &p) {_x += p._x; _y += p._y; return *this;}
Pair operator -= (const Pair &p) {_x -= p._x; _y -= p._y; return *this;}
Pair operator *= (T c) {_x *= c; _y *= c; return *this;}
Pair operator /= (T c) {_x /= c; _y /= c; return *this;}
Pair operator - () const {return Pair(-_x, -_y);}
Pair ortho () const {return Pair(-_y, _x);}
- double length () const {return std::sqrt(_x*_x + _y*_y);}
+ double length () const {return std::hypot(_x, _y);}
bool operator == (const Pair &p) const {return _x == p._x && _y == p._y;}
bool operator != (const Pair &p) const {return _x != p._x || _y != p._y;}
T x () const {return _x;}
@@ -54,15 +58,30 @@ inline Pair<T> abs (const Pair<T> &p) {
return Pair<T>(std::abs(p.x()), std::abs(p.y()));
}
-struct Pair32 : public Pair<int32_t>
-{
- Pair32 (int32_t x=0, int32_t y=0) : Pair<int32_t>(x, y) {}
- explicit Pair32 (double x, double y) : Pair<int32_t>(int32_t(x+0.5), int32_t(y+0.5)) {}
+/** Returns the dot product of two 2D vectors. */
+template <typename T>
+inline T dot (const Pair<T> &p1, const Pair<T> &p2) {
+ return p1.x()*p1.y() + p1.y()*p2.y();
+}
+
+/** Returns the determinant of two 2D vectors. */
+template <typename T>
+inline T det (const Pair<T> &p1, const Pair<T> &p2) {
+ return p1.x()*p2.y() - p1.y()*p2.x();
+}
+
+struct Pair32 : public Pair<int32_t> {
+ explicit Pair32 (int32_t x=0, int32_t y=0) : Pair<int32_t>(x, y) {}
+ explicit Pair32 (double x, double y) : Pair<int32_t>(lround(x), lround(y)) {}
Pair32 (const Pair<int32_t> &p) : Pair<int32_t>(p) {}
};
typedef Pair<double> DPair;
+inline DPair round (const DPair &p) {
+ return DPair(std::lround(p.x()), std::lround(p.y()));
+}
+
template <typename T>
IMPLEMENT_ARITHMETIC_OPERATOR(Pair<T>, +)
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp
index a08b74a1aad..f646289d25e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PathClipper.cpp
@@ -18,6 +18,7 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
+#include <cmath>
#include "Bezier.hpp"
#include "PathClipper.hpp"
@@ -31,9 +32,7 @@ using CurvedPath = PathClipper::CurvedPath;
const int SCALE_FACTOR = 1000;
inline cInt to_cInt (double x) {
- if (x < 0)
- return static_cast<cInt>(x*SCALE_FACTOR - 0.5);
- return static_cast<cInt>(x*SCALE_FACTOR + 0.5);
+ return static_cast<cInt>(lround(x*SCALE_FACTOR));
}
@@ -50,7 +49,7 @@ inline DPair to_DPair (const IntPoint &p) {
/** In order to flatten a curved path, all path segements are processed sequentially.
* Depending on the type of the segment, one of the methods provided by this class
* is called. */
-class FlattenActions : public CurvedPath::Actions {
+class FlattenActions : public CurvedPath::IterationActions {
public:
FlattenActions (vector<Bezier> &curves, Polygons &polygons, int &numLines)
: _polygons(polygons), _curves(curves), _numLines(numLines) {}
@@ -74,7 +73,7 @@ class FlattenActions : public CurvedPath::Actions {
_currentPoint = p;
}
- void conicto (const CurvedPath::Point &p1, const CurvedPath::Point &p2) override {
+ void quadto (const CurvedPath::Point &p1, const CurvedPath::Point &p2) override {
Bezier bezier(_currentPoint, p1, p2);
addCurvePoints(bezier);
}
@@ -130,9 +129,9 @@ class FlattenActions : public CurvedPath::Actions {
/** Removes adjacent polygon vertices that equal their predecessor. */
static void remove_redundant_vertices (Polygon &polygon) {
- Polygon::iterator it1=polygon.begin();
+ auto it1=polygon.begin();
while (it1 != polygon.end()) {
- Polygon::iterator it2 = it1+1;
+ auto it2 = it1+1;
if (it2 == polygon.end())
it2 = polygon.begin();
if (it1 == it2)
@@ -159,8 +158,8 @@ static void remove_redundant_vertices (Polygon &polygon) {
void PathClipper::flatten (const CurvedPath &curvedPath, Polygons &polygons) {
FlattenActions flattenActions(_curves, polygons, _numLines);
curvedPath.iterate(flattenActions, false);
- for (size_t i=0; i < polygons.size(); i++)
- remove_redundant_vertices(polygons[i]);
+ for (Polygon &poly : polygons)
+ remove_redundant_vertices(poly);
}
@@ -207,7 +206,7 @@ static double division_ratio (const IntPoint &p1, const IntPoint &p2, const IntP
/** Returns the label of point q that lies on the line between points p1 and p2. */
inline ZLabel division_label (const IntPoint &p1, const IntPoint &p2, const IntPoint &q) {
- double t1, t2;
+ double t1=0, t2=0;
double s=0;
int32_t id = segment_id(p1, p2, t1, t2);
if (id > 0)
@@ -237,7 +236,7 @@ void PathClipper::callback (IntPoint &e1bot, IntPoint &e1top, IntPoint &e2bot, I
* @param[out] label if not 0, retrieves the label of the endpoint
* @param[in] startLabel if true, the found endpoint is treated as start point and
* parameter 'label' gets the corresponding value */
-static size_t find_segment_endpoint (const Polygon &polygon, size_t start, ZLabel *label=0, bool startLabel=false) {
+static size_t find_segment_endpoint (const Polygon &polygon, size_t start, ZLabel *label=nullptr, bool startLabel=false) {
if (polygon.empty())
return 0;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp
index 43edd96569e..70174b0fe10 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp
@@ -95,7 +95,7 @@ static char prepare_mode (InputReader &ir) {
void PdfSpecialHandler::preprocessPagesize (StreamInputReader &ir, SpecialActions &actions) {
// add page sizes to collection of paper sizes in order to handle them equally
SpecialHandler *handler = SpecialManager::instance().findHandlerByName("papersize");
- if (auto *papersizeHandler = dynamic_cast<PapersizeSpecialHandler*>(handler)) {
+ if (auto papersizeHandler = dynamic_cast<PapersizeSpecialHandler*>(handler)) {
try {
Length width, height;
// parse parameter sequence of the form (name length)+
@@ -152,8 +152,8 @@ void PdfSpecialHandler::preprocessDest (StreamInputReader &ir, SpecialActions &a
});
if (objects.size() < 2)
return;
- auto *name = objects[0].get<string>();
- auto *dest = objects[1].get<PDFArray>();
+ auto name = objects[0].get<string>();
+ auto dest = objects[1].get<PDFArray>();
// get target info from array [pageno /XYZ xpos ypos zpos]
if (name && dest && dest->size() >= 4 && dest->at(0).get<int>()) {
int pageno = *dest->at(0).get<int>();
@@ -210,7 +210,7 @@ static Color to_color (const PDFObject &obj) {
Color color;
if (obj.get<int>() || obj.get<double>())
color.setGray(double(obj));
- else if (auto *colorArray = obj.get<PDFArray>()) {
+ else if (auto colorArray = obj.get<PDFArray>()) {
size_t size = min(size_t(4), colorArray->size());
valarray<double> colorComps(size);
for (size_t i=0; i < size; i++)
@@ -262,7 +262,7 @@ void PdfSpecialHandler::processDest (StreamInputReader &ir, SpecialActions &acti
PDFParser parser;
vector<PDFObject> objects = parser.parse(ir);
if (!objects.empty()) {
- if (auto *name = objects[0].get<string>())
+ if (auto name = objects[0].get<string>())
HyperlinkManager::instance().setActiveNameAnchor(*name, actions);
}
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp
index f8ede292a2a..ff73cb53366 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp
@@ -21,9 +21,9 @@
#ifdef _WIN32
#include "windows.hpp"
#else
+ #include <csignal>
#include <fcntl.h>
#include <sys/wait.h>
- #include <signal.h>
#include <unistd.h>
#endif
@@ -61,8 +61,8 @@ class Subprocess {
};
-Process::Process (const string &cmd, const string &paramstr)
- : _cmd(cmd), _paramstr(paramstr)
+Process::Process (string cmd, string paramstr)
+ : _cmd(std::move(cmd)), _paramstr(std::move(paramstr))
{
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp
index 3333e24df1d..70eeafb9d8b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.hpp
@@ -25,11 +25,11 @@
class Process {
public:
- Process (const std::string &cmd, const std::string &paramstr);
+ Process (std::string cmd, std::string paramstr);
Process (const Process &orig) =delete;
Process (Process &&orig) =delete;
- bool run (std::string *out=0);
- bool run (const std::string &dir, std::string *out=0);
+ bool run (std::string *out=nullptr);
+ bool run (const std::string &dir, std::string *out=nullptr);
private:
std::string _cmd;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp
index 4b503d34bee..405da48434b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp
@@ -25,6 +25,7 @@
#include <sstream>
#include "EPSFile.hpp"
#include "FileFinder.hpp"
+#include "FilePath.hpp"
#include "FileSystem.hpp"
#include "Message.hpp"
#include "PathClipper.hpp"
@@ -183,6 +184,15 @@ void PsSpecialHandler::preprocess (const string &prefix, istream &is, SpecialAct
}
+static string filename_suffix (const string &fname) {
+ string ret;
+ size_t pos = fname.rfind('.');
+ if (pos != string::npos)
+ ret = util::tolower(fname.substr(pos+1));
+ return ret;
+}
+
+
bool PsSpecialHandler::process (const string &prefix, istream &is, SpecialActions &actions) {
// process PS headers only once (in prescan)
if (prefix == "!" || prefix == "header=")
@@ -203,10 +213,24 @@ bool PsSpecialHandler::process (const string &prefix, istream &is, SpecialAction
else if (prefix == "psfile=" || prefix == "PSfile=" || prefix == "pdffile=") {
if (_actions) {
StreamInputReader in(is);
- const string fname = in.getQuotedString(in.peek() == '"' ? "\"" : nullptr);
+ string fname = in.getQuotedString(in.peek() == '"' ? "\"" : nullptr);
+ fname = FileSystem::adaptPathSeperators(fname);
+ FileType fileType = FileType::EPS;
+ if (prefix == "pdffile")
+ fileType = FileType::PDF;
+ else {
+ // accept selected non-PS files in psfile special
+ string ext = filename_suffix(fname);
+ if (ext == "pdf")
+ fileType = FileType::PDF;
+ else if (ext == "svg")
+ fileType = FileType::SVG;
+ else if (ext == "jpg" || ext == "jpeg" || ext == "png")
+ fileType = FileType::BITMAP;
+ }
map<string,string> attr;
- in.parseAttributes(attr);
- imgfile(prefix == "pdffile=" ? FileType::PDF : FileType::EPS, fname, attr);
+ in.parseAttributes(attr, false);
+ imgfile(fileType, fname, attr);
}
}
else if (prefix == "ps::") {
@@ -216,9 +240,9 @@ bool PsSpecialHandler::process (const string &prefix, istream &is, SpecialAction
// collect characters inside the brackets
string code;
for (int i=0; i < 9 && is.peek() != ']' && !is.eof(); ++i)
- code += is.get();
+ code += char(is.get());
if (is.peek() == ']')
- code += is.get();
+ code += char(is.get());
if (code == "[begin]" || code == "[nobreak]") {
moveToDVIPos();
@@ -272,15 +296,6 @@ void PsSpecialHandler::imgfile (FileType filetype, const string &fname, const ma
if (fname == "/dev/null")
return;
- string filepath;
- if (const char *path = FileFinder::instance().lookup(fname, false))
- filepath = FileSystem::adaptPathSeperators(path);
- if ((filepath.empty() || !FileSystem::exists(filepath)) && FileSystem::exists(fname))
- filepath = fname;
- if (filepath.empty()) {
- Message::wstream(true) << "file '" << fname << "' not found\n";
- return;
- }
map<string,string>::const_iterator it;
// bounding box of EPS figure in PS point units (lower left and upper right corner)
@@ -290,7 +305,9 @@ void PsSpecialHandler::imgfile (FileType filetype, const string &fname, const ma
double ury = (it = attr.find("ury")) != attr.end() ? stod(it->second) : 0;
int pageno = (it = attr.find("page")) != attr.end() ? stoi(it->second, nullptr, 10) : 1;
- if (filetype == FileType::PDF && llx == 0 && lly == 0 && urx == 0 && ury == 0) {
+ if (filetype == FileType::BITMAP || filetype == FileType::SVG)
+ swap(lly, ury);
+ else if (filetype == FileType::PDF && llx == 0 && lly == 0 && urx == 0 && ury == 0) {
BoundingBox pagebox = _psi.pdfPageBox(fname, pageno);
if (pagebox.valid()) {
llx = pagebox.minX();
@@ -316,6 +333,8 @@ void PsSpecialHandler::imgfile (FileType filetype, const string &fname, const ma
double vscale = (it = attr.find("vscale")) != attr.end() ? stod(it->second) : 100;
double angle = (it = attr.find("angle")) != attr.end() ? stod(it->second) : 0;
+ bool clipToBbox = (attr.find("clip") != attr.end());
+
// compute factors to scale the bounding box to width rwi and height rhi
double sx = rwi/abs(llx-urx);
double sy = rhi/abs(lly-ury);
@@ -335,36 +354,26 @@ void PsSpecialHandler::imgfile (FileType filetype, const string &fname, const ma
_actions->setY(0);
moveToDVIPos();
- auto groupNode = util::make_unique<XMLElementNode>("g"); // put SVG nodes created from the EPS/PDF file in this group
- _xmlnode = groupNode.get();
- _psi.execute(
- "\n@beginspecial @setspecial" // enter special environment
- "/setpagedevice{@setpagedevice}def " // activate processing of operator "setpagedevice"
- "matrix setmatrix" // don't apply outer PS transformations
- "/FirstPage "+to_string(pageno)+" def" // set number of fisrt page to convert (PDF only)
- "/LastPage "+to_string(pageno)+" def" // set number of last page to convert (PDF only)
- "("+ filepath + ")run " // execute file content
- "@endspecial " // leave special environment
- );
- if (!groupNode->empty()) { // has anything been drawn?
+ auto imgNode = createImageNode(filetype, fname, pageno, BoundingBox(llx, lly, urx, ury), clipToBbox);
+ if (imgNode) { // has anything been drawn?
Matrix matrix(1);
- matrix.scale(sx, -sy).rotate(-angle).scale(hscale/100, vscale/100); // apply transformation attributes
+ if (filetype == FileType::EPS || filetype == FileType::PDF)
+ sy = -sy; // adapt orientation of y-coordinates
+ matrix.scale(sx, sy).rotate(-angle).scale(hscale/100, vscale/100); // apply transformation attributes
matrix.translate(x+hoffset, y-voffset); // move image to current DVI position
- matrix.rmultiply(_actions->getMatrix());
+ matrix.lmultiply(_actions->getMatrix());
// update bounding box
BoundingBox bbox(0, 0, urx-llx, ury-lly);
bbox.transform(matrix);
_actions->embed(bbox);
- // insert group containing SVG nodes created from image
- matrix.lmultiply(TranslationMatrix(-llx, -lly)); // move lower left corner of image to origin
+ // insert element containing the image data
+ matrix.rmultiply(TranslationMatrix(-llx, -lly)); // move lower left corner of image to origin
if (!matrix.isIdentity())
- groupNode->addAttribute("transform", matrix.getSVG());
- _actions->appendToPage(std::move(groupNode));
+ imgNode->addAttribute("transform", matrix.toSVG());
+ _actions->svgTree().appendToPage(std::move(imgNode));
}
- _xmlnode = nullptr; // append following elements to page group again
-
// restore DVI position
_actions->setX(x);
_actions->setY(y);
@@ -372,6 +381,63 @@ void PsSpecialHandler::imgfile (FileType filetype, const string &fname, const ma
}
+/** Creates an XML element containing the image data depending on the file type.
+ * @param[in] type file type of the image
+ * @param[in] fname file name/path of image file
+ * @param[in] pageno number of page to process (PDF only)
+ * @param[in] bbox bounding box of the image
+ * @param[in] clip if true, the image is clipped to its bounding box
+ * @return pointer to the element or nullptr if there's no image data */
+unique_ptr<XMLElement> PsSpecialHandler::createImageNode (FileType type, const string &fname, int pageno, BoundingBox bbox, bool clip) {
+ unique_ptr<XMLElement> node;
+ string pathstr;
+ if (const char *path = FileFinder::instance().lookup(fname, false))
+ pathstr = FileSystem::adaptPathSeperators(path);
+ if ((pathstr.empty() || !FileSystem::exists(pathstr)) && FileSystem::exists(fname))
+ pathstr = fname;
+ if (pathstr.empty())
+ Message::wstream(true) << "file '" << fname << "' not found\n";
+ else if (type == FileType::BITMAP || type == FileType::SVG) {
+ node = util::make_unique<XMLElement>("image");
+ node->addAttribute("x", 0);
+ node->addAttribute("y", 0);
+ node->addAttribute("width", bbox.width());
+ node->addAttribute("height", bbox.height());
+
+ // Only reference the image with an absolute path if either an absolute path was given by the user
+ // or a given plain filename is not present in the current working directory but was found through
+ // the FileFinder, i.e. it's usually located somewhere in the texmf tree.
+ string href = pathstr;
+ if (!FilePath::isAbsolute(fname) && (fname.find('/') != string::npos || FilePath(fname).exists()))
+ href = FilePath(pathstr).relative(FilePath(_actions->getSVGFilePath(pageno)));
+ node->addAttribute("xlink:href", href);
+ }
+ else { // PostScript or PDF
+ // clip image to its bounding box if flag 'clip' is given
+ string rectclip;
+ if (clip)
+ rectclip = to_string(bbox.minX())+" "+to_string(bbox.minY())+" "+to_string(bbox.width())+" "+to_string(bbox.height())+" rectclip";
+
+ node = util::make_unique<XMLElement>("g"); // put SVG nodes created from the EPS/PDF file in this group
+ _xmlnode = node.get();
+ _psi.execute(
+ "\n@beginspecial @setspecial" // enter special environment
+ "/setpagedevice{@setpagedevice}def " // activate processing of operator "setpagedevice"
+ "matrix setmatrix" // don't apply outer PS transformations
+ "/FirstPage "+to_string(pageno)+" def" // set number of first page to convert (PDF only)
+ "/LastPage "+to_string(pageno)+" def " // set number of last page to convert (PDF only)
+ +rectclip+ // clip to bounding box (if requexted by attribute 'clip')
+ "(" + pathstr + ")run " // execute file content
+ "@endspecial " // leave special environment
+ );
+ if (node->empty())
+ node.reset(nullptr);
+ _xmlnode = nullptr; // append following elements to page group again
+ }
+ return node;
+}
+
+
/** Apply transformation to width, height, and depth set by preview package.
* @param[in] matrix transformation matrix to apply
* @param[out] w width
@@ -386,15 +452,17 @@ static bool transform_box_extents (const Matrix &matrix, double &w, double &h, d
return false; // => non-horizontal baseline, can't compute meaningful extents
if (ex.y() == 0) // horizontal scaling or skewing?
- w *= fabs(ex.x());
+ w *= abs(ex.x());
if (ey.x()==0 || ex.y()==0) { // vertical scaling?
- if (ey.y() < 0) swap(h, d);
- if (double sy = fabs(ey.y())/ey.length()) {
- h *= fabs(ey.y()/sy);
- d *= fabs(ey.y()/sy);
- }
- else
+ if (ey.y() < 0)
+ swap(h, d);
+ double sy = abs(ey.y())/ey.length();
+ if (sy < 1e-8)
h = d = 0;
+ else {
+ h *= abs(ey.y()/sy);
+ d *= abs(ey.y()/sy);
+ }
}
return true;
}
@@ -435,7 +503,7 @@ void PsSpecialHandler::dviEndPage (unsigned, SpecialActions &actions) {
"depth=" << XMLString(d*bp2pt) << "pt\n";
}
#if 0
- auto rect = util::make_unique<XMLElementNode>("rect");
+ auto rect = util::make_unique<XMLElement>("rect");
rect->addAttribute("x", actions.bbox().minX());
rect->addAttribute("y", actions.bbox().minY());
rect->addAttribute("width", w);
@@ -445,7 +513,7 @@ void PsSpecialHandler::dviEndPage (unsigned, SpecialActions &actions) {
rect->addAttribute("stroke-width", "0.1");
actions.appendToPage(std::move(rect));
if (d > 0) {
- auto line = util::make_unique<XMLElementNode>("line");
+ auto line = util::make_unique<XMLElement>("line");
line->addAttribute("x1", actions.bbox().minX());
line->addAttribute("y1", actions.bbox().minY()+h);
line->addAttribute("x2", actions.bbox().maxX());
@@ -553,14 +621,14 @@ void PsSpecialHandler::stroke (vector<double> &p) {
}
if (_clipStack.prependedPath())
_path.prepend(*_clipStack.prependedPath());
- unique_ptr<XMLElementNode> path;
+ unique_ptr<XMLElement> path;
Pair<double> point;
if (_path.isDot(point)) { // zero-length path?
if (_linecap == 1) { // round line ends? => draw dot
double x = point.x();
double y = point.y();
double r = _linewidth/2.0;
- path = util::make_unique<XMLElementNode>("circle");
+ path = util::make_unique<XMLElement>("circle");
path->addAttribute("cx", x);
path->addAttribute("cy", y);
path->addAttribute("r", r);
@@ -575,7 +643,7 @@ void PsSpecialHandler::stroke (vector<double> &p) {
ostringstream oss;
_path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS);
- path = util::make_unique<XMLElementNode>("path");
+ path = util::make_unique<XMLElement>("path");
path->addAttribute("d", oss.str());
path->addAttribute("stroke", _actions->getColor().svgColorString());
path->addAttribute("fill", "none");
@@ -592,13 +660,11 @@ void PsSpecialHandler::stroke (vector<double> &p) {
if (_blendmode > 0 && _blendmode < 16)
path->addAttribute("style", "mix-blend-mode:"+css_blendmode_name(_blendmode));
if (!_dashpattern.empty()) {
- ostringstream oss;
- for (size_t i=0; i < _dashpattern.size(); i++) {
- if (i > 0)
- oss << ',';
- oss << XMLString(_dashpattern[i]);
- }
- path->addAttribute("stroke-dasharray", oss.str());
+ string patternStr;
+ for (double dashValue : _dashpattern)
+ patternStr += XMLString(dashValue)+",";
+ patternStr.pop_back();
+ path->addAttribute("stroke-dasharray", patternStr);
if (_dashoffset != 0)
path->addAttribute("stroke-dashoffset", _dashoffset);
}
@@ -614,7 +680,7 @@ void PsSpecialHandler::stroke (vector<double> &p) {
if (_xmlnode)
_xmlnode->append(std::move(path));
else {
- _actions->appendToPage(std::move(path));
+ _actions->svgTree().appendToPage(std::move(path));
_actions->embed(bbox);
}
_path.clear();
@@ -642,7 +708,7 @@ void PsSpecialHandler::fill (vector<double> &p, bool evenodd) {
ostringstream oss;
_path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS);
- unique_ptr<XMLElementNode> path = util::make_unique<XMLElementNode>("path");
+ unique_ptr<XMLElement> path = util::make_unique<XMLElement>("path");
path->addAttribute("d", oss.str());
if (_pattern)
path->addAttribute("fill", XMLString("url(#")+_pattern->svgID()+")");
@@ -665,7 +731,7 @@ void PsSpecialHandler::fill (vector<double> &p, bool evenodd) {
if (_xmlnode)
_xmlnode->append(std::move(path));
else {
- _actions->appendToPage(std::move(path));
+ _actions->svgTree().appendToPage(std::move(path));
_actions->embed(bbox);
}
_path.clear();
@@ -682,7 +748,7 @@ static void create_matrix (vector<double> &v, int startindex, Matrix &matrix) {
// using corresponding values of the identity matrix.
if (v.size()-startindex < 6) {
v.resize(6+startindex);
- for (int i=v.size()-startindex; i < 6; ++i)
+ for (size_t i=v.size()-startindex; i < 6; ++i)
v[i+startindex] = (i%3 ? 0 : 1);
}
// PS matrix [a b c d e f] equals ((a,b,0),(c,d,0),(e,f,1)).
@@ -724,7 +790,7 @@ void PsSpecialHandler::makepattern (vector<double> &p) {
Matrix matrix; // transformation matrix given together with pattern definition
create_matrix(p, 9, matrix);
- matrix.rmultiply(_actions->getMatrix());
+ matrix.lmultiply(_actions->getMatrix());
unique_ptr<PSTilingPattern> pattern;
if (paint_type == 1)
@@ -756,10 +822,10 @@ void PsSpecialHandler::setpattern (vector<double> &p) {
if (it == _patterns.end())
_pattern = nullptr;
else {
- if (auto *pattern = dynamic_cast<PSUncoloredTilingPattern*>(it->second.get()))
+ if (auto pattern = dynamic_cast<PSUncoloredTilingPattern*>(it->second.get()))
pattern->setColor(color);
it->second->apply(*_actions);
- if (auto *pattern = dynamic_cast<PSTilingPattern*>(it->second.get()))
+ if (auto pattern = dynamic_cast<PSTilingPattern*>(it->second.get()))
_pattern = pattern;
else
_pattern = nullptr;
@@ -828,19 +894,19 @@ void PsSpecialHandler::clip (Path path, bool evenodd) {
intersectedPath.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS);
}
if (pathReplaced) {
- auto pathElem = util::make_unique<XMLElementNode>("path");
+ auto pathElem = util::make_unique<XMLElement>("path");
pathElem->addAttribute("d", oss.str());
if (evenodd)
pathElem->addAttribute("clip-rule", "evenodd");
int newID = _clipStack.topID();
- auto clipElem = util::make_unique<XMLElementNode>("clipPath");
+ auto clipElem = util::make_unique<XMLElement>("clipPath");
clipElem->addAttribute("id", XMLString("clip")+XMLString(newID));
if (!COMPUTE_CLIPPATHS_INTERSECTIONS && oldID)
clipElem->addAttribute("clip-path", XMLString("url(#clip")+XMLString(oldID)+")");
clipElem->append(std::move(pathElem));
- _actions->appendToDefs(std::move(clipElem));
+ _actions->svgTree().appendToDefs(std::move(clipElem));
}
}
@@ -864,7 +930,7 @@ void PsSpecialHandler::shfill (vector<double> &params) {
case 3: colorSpace = Color::ColorSpace::RGB; break;
case 4: colorSpace = Color::ColorSpace::CMYK; break;
}
- VectorIterator<double> it = params;
+ VectorIterator<double> it(params);
it += 2; // skip shading type and color space
// Get color to fill the whole mesh area before drawing the gradient colors on top of that background.
// This is an optional parameter to shfill.
@@ -951,15 +1017,15 @@ static void read_patch_data (ShadingPatch &patch, int edgeflag,
class ShadingCallback : public ShadingPatch::Callback {
public:
- ShadingCallback (SpecialActions &actions, XMLElementNode *parent, int clippathID)
+ ShadingCallback (SpecialActions &actions, XMLElement *parent, int clippathID)
: _actions(actions)
{
- auto group = util::make_unique<XMLElementNode>("g");
+ auto group = util::make_unique<XMLElement>("g");
_group = group.get();
if (parent)
parent->append(std::move(group));
else
- actions.appendToPage(std::move(group));
+ actions.svgTree().appendToPage(std::move(group));
if (clippathID > 0)
_group->addAttribute("clip-path", XMLString("url(#clip")+XMLString(clippathID)+")");
}
@@ -971,7 +1037,7 @@ class ShadingCallback : public ShadingPatch::Callback {
// draw a single patch segment
ostringstream oss;
path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS);
- auto pathElem = util::make_unique<XMLElementNode>("path");
+ auto pathElem = util::make_unique<XMLElement>("path");
pathElem->addAttribute("d", oss.str());
pathElem->addAttribute("fill", color.svgColorString());
_group->append(std::move(pathElem));
@@ -979,7 +1045,7 @@ class ShadingCallback : public ShadingPatch::Callback {
private:
SpecialActions &_actions;
- XMLElementNode *_group;
+ XMLElement *_group;
};
@@ -999,16 +1065,14 @@ void PsSpecialHandler::processSequentialPatchMesh (int shadingTypeID, ColorSpace
#if 0
if (bgcolorGiven) {
// fill whole patch area with given background color
- GraphicsPath<double> outline;
- patch->getBoundaryPath(outline);
+ GraphicsPath<double> outline = patch->getBoundaryPath();
callback.patchSegment(outline, bgcolor);
}
#endif
patch->approximate(SHADING_SEGMENT_SIZE, SHADING_SEGMENT_OVERLAP, SHADING_SIMPLIFY_DELTA, callback);
if (!_xmlnode) {
// update bounding box
- BoundingBox bbox;
- patch->getBBox(bbox);
+ BoundingBox bbox = patch->getBBox();
bbox.transform(_actions->getMatrix());
_actions->embed(bbox);
}
@@ -1093,7 +1157,7 @@ void PsSpecialHandler::scale (vector<double> &p) {
if (_actions) {
Matrix m = _actions->getMatrix();
ScalingMatrix s(p[0], p[1]);
- m.lmultiply(s);
+ m.rmultiply(s);
_actions->setMatrix(m);
}
}
@@ -1103,7 +1167,7 @@ void PsSpecialHandler::translate (vector<double> &p) {
if (_actions) {
Matrix m = _actions->getMatrix();
TranslationMatrix t(p[0], p[1]);
- m.lmultiply(t);
+ m.rmultiply(t);
_actions->setMatrix(m);
}
}
@@ -1113,7 +1177,7 @@ void PsSpecialHandler::rotate (vector<double> &p) {
if (_actions) {
Matrix m = _actions->getMatrix();
RotationMatrix r(p[0]);
- m.lmultiply(r);
+ m.rmultiply(r);
_actions->setMatrix(m);
}
}
@@ -1167,6 +1231,18 @@ void PsSpecialHandler::executed () {
_actions->progress("ps");
}
+
+/** This method is called by PSInterpreter if the status of the output devices has changed.
+ * @param[in] p 1 if output device is the nulldevice, 1 otherwise */
+void PsSpecialHandler::setnulldevice (vector<double> &p) {
+ if (_actions) {
+ if (p[0] != 0)
+ _actions->lockOutput(); // prevent further SVG output
+ else
+ _actions->unlockOutput(); // enable SVG output again
+ }
+}
+
////////////////////////////////////////////
void PsSpecialHandler::ClippingStack::pushEmptyPath () {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp
index 188c4527189..c7a8a978150 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.hpp
@@ -34,7 +34,7 @@
class PSPattern;
-class XMLElementNode;
+class XMLElement;
class PsSpecialHandler : public SpecialHandler, protected PSActions {
using Path = GraphicsPath<double>;
@@ -68,7 +68,7 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
int saveID; ///< if >=0, path was pushed by 'save', and saveID holds the ID of the PS memory object
Entry () : Entry(-1) {}
Entry (const Path &p, int pid, int sid) : path(std::make_shared<Path>(p)), pathID(pid), saveID(sid) {}
- Entry (int sid) : path(nullptr), pathID(0), saveID(sid) {}
+ explicit Entry (int sid) : path(nullptr), pathID(0), saveID(sid) {}
Entry (const Entry &entry) =default;
Entry (Entry &&entry) =default;
};
@@ -77,11 +77,11 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
};
enum PsSection {PS_NONE, PS_HEADERS, PS_BODY};
- enum class FileType {EPS, PDF};
+ enum class FileType {EPS, PDF, SVG, BITMAP};
public:
PsSpecialHandler ();
- ~PsSpecialHandler ();
+ ~PsSpecialHandler () override;
const char* name () const override {return "ps";}
const char* info () const override {return "dvips PostScript specials";}
std::vector<const char*> prefixes() const override;
@@ -104,6 +104,7 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
void executeAndSync (std::istream &is, bool updatePos);
void processHeaderFile (const char *fname);
void imgfile (FileType type, const std::string &fname, const std::map<std::string,std::string> &attr);
+ std::unique_ptr<XMLElement> createImageNode (FileType type, const std::string &fname, int pageno, BoundingBox bbox, bool clip);
void dviEndPage (unsigned pageno, SpecialActions &actions) override;
void clip (Path path, bool evenodd);
void processSequentialPatchMesh (int shadingTypeID, ColorSpace cspace, VectorIterator<double> &it);
@@ -145,6 +146,7 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
void setlinewidth (std::vector<double> &p) override {_linewidth = scale(p[0] ? p[0] : 0.5);}
void setmatrix (std::vector<double> &p) override;
void setmiterlimit (std::vector<double> &p) override {_miterlimit = p[0];}
+ void setnulldevice (std::vector<double> &p) override;
void setopacityalpha (std::vector<double> &p) override {_opacityalpha = p[0];}
void setshapealpha (std::vector<double> &p) override {_shapealpha = p[0];}
void setpagedevice (std::vector<double> &p) override;
@@ -160,8 +162,8 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
SpecialActions *_actions;
PSPreviewFilter _previewFilter; ///< filter to extract information generated by the preview package
PsSection _psSection=PS_NONE; ///< current section processed (nothing yet, headers, or body specials)
- XMLElementNode *_xmlnode; ///< if != 0, created SVG elements are appended to this node
- XMLElementNode *_savenode; ///< pointer to temporaryly store _xmlnode
+ XMLElement *_xmlnode; ///< if != 0, created SVG elements are appended to this node
+ XMLElement *_savenode; ///< pointer to temporaryly store _xmlnode
std::string _headerCode; ///< collected literal PS header code
Path _path;
DPair _currentpoint; ///< current PS position in bp units
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp
index dd9eb88462c..5fa2bb10ab1 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/RangeMap.cpp
@@ -18,6 +18,7 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
+#include <numeric>
#include "RangeMap.hpp"
using namespace std;
@@ -96,7 +97,7 @@ void RangeMap::addRange (uint32_t cmin, uint32_t cmax, uint32_t vmin) {
}
else {
// ranges overlap and/or must be inserted somewhere inside the vector
- Ranges::iterator it = lower_bound(_ranges.begin(), _ranges.end(), range);
+ auto it = lower_bound(_ranges.begin(), _ranges.end(), range);
const bool at_end = (it == _ranges.end());
if (at_end)
--it;
@@ -125,16 +126,16 @@ void RangeMap::addRange (uint32_t cmin, uint32_t cmax, uint32_t vmin) {
void RangeMap::adaptNeighbors (Ranges::iterator it) {
if (it != _ranges.end()) {
// adapt left neighbor
- Ranges::iterator lit = it-1; // points to left neighbor
- if (it != _ranges.begin() && it->min() <= lit->max()) {
+ if (it != _ranges.begin() && it->min() <= (it-1)->max()) {
+ auto lit = it-1; // points to left neighbor
bool left_neighbor_valid = (it->min() > 0 && it->min()-1 >= lit->min());
- if (left_neighbor_valid) // is adapted left neighbor valid?
- lit->max(it->min()-1); // => assign new max value
+ if (left_neighbor_valid) // is adapted left neighbor valid?
+ lit->max(it->min()-1); // => assign new max value
if (!left_neighbor_valid || it->join(*lit))
it = _ranges.erase(lit);
}
// remove right neighbors completely overlapped by *it
- Ranges::iterator rit = it+1; // points to right neighbor
+ auto rit = it+1; // points to right neighbor
while (rit != _ranges.end() && it->max() >= rit->max()) { // complete overlap?
_ranges.erase(rit);
rit = it+1;
@@ -178,10 +179,9 @@ uint32_t RangeMap::valueAt (uint32_t c) const {
/** Returns the number of values mapped. */
size_t RangeMap::numValues () const {
- size_t count=0;
- for (const Range &range : _ranges)
- count += range.max()-range.min()+1;
- return count;
+ return std::accumulate(_ranges.begin(), _ranges.end(), 0, [](size_t sum, const Range &range) {
+ return sum+range.max()-range.min()+1;
+ });
}
@@ -191,7 +191,7 @@ ostream& RangeMap::Range::write (ostream& os) const {
ostream& RangeMap::write (ostream& os) const {
- for (size_t i=0; i < _ranges.size(); i++)
- _ranges[i].write(os) << '\n';
+ for (const Range &range : _ranges)
+ range.write(os) << '\n';
return os;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp
index 70fc6836e9c..3733053e4d0 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.cpp
@@ -25,7 +25,7 @@
using namespace std;
-void SVGCharHandler::setInitialContextNode (XMLElementNode *node) {
+void SVGCharHandler::setInitialContextNode (XMLElement *node) {
resetContextNode();
_initialContextNode = node;
}
@@ -34,9 +34,9 @@ void SVGCharHandler::setInitialContextNode (XMLElementNode *node) {
/** Changes the context element. All following nodes will be appended to this node.
* @param[in] node the new context node
* @return bare pointer to the new context node or 0 if context hasn't changed */
-XMLElementNode* SVGCharHandler::pushContextNode (unique_ptr<XMLElementNode> &&node) {
+XMLElement* SVGCharHandler::pushContextNode (unique_ptr<XMLElement> node) {
if (node && (_contextNodeStack.empty() || node.get() != _contextNodeStack.top())) {
- XMLElementNode *nodeptr = node.get();
+ XMLElement *nodeptr = node.get();
contextNode()->append(std::move(node));
_contextNodeStack.push(nodeptr);
return nodeptr;
@@ -61,11 +61,11 @@ void SVGCharHandler::resetContextNode () {
/** Creates and returns a new SVG text element.
* @param[in] x current x coordinate
* @param[in] y current y coordinate */
-unique_ptr<XMLElementNode> SVGCharTextHandler::createTextNode (double x, double y) const {
+unique_ptr<XMLElement> SVGCharTextHandler::createTextNode (double x, double y) const {
const Font *font = _font.get();
if (!font)
return nullptr;
- auto textNode = util::make_unique<XMLElementNode>("text");
+ auto textNode = util::make_unique<XMLElement>("text");
if (_selectFontByClass)
textNode->addAttribute("class", string("f")+XMLString(_fontnum));
else {
@@ -77,7 +77,7 @@ unique_ptr<XMLElementNode> SVGCharTextHandler::createTextNode (double x, double
if (_vertical) {
textNode->addAttribute("writing-mode", "tb");
// align glyphs designed for horizontal layout properly
- if (const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(font)) {
+ if (auto pf = dynamic_cast<const PhysicalFont*>(font)) {
if (!pf->getMetrics()->verticalLayout()) { // alphabetic text designed for horizontal layout?
x += pf->scaledAscent()/2.5; // move vertical baseline to the right by strikethrough offset
textNode->addAttribute("glyph-orientation-vertical", 90); // ensure rotation
@@ -87,6 +87,6 @@ unique_ptr<XMLElementNode> SVGCharTextHandler::createTextNode (double x, double
textNode->addAttribute("x", x);
textNode->addAttribute("y", y);
if (!_matrix.get().isIdentity())
- textNode->addAttribute("transform", _matrix.get().getSVG());
+ textNode->addAttribute("transform", _matrix.get().toSVG());
return textNode;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp
index c527ee26655..48d24496fab 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharHandler.hpp
@@ -31,7 +31,7 @@
template <typename T>
class CharProperty {
public:
- CharProperty (const T &v) : _value(v), _changed(false) {}
+ CharProperty (const T &v) : _value(v) {}
void set (const T &v) {
if (v != _value) {
@@ -47,20 +47,20 @@ class CharProperty {
private:
T _value;
- bool _changed;
+ bool _changed=false;
};
-class XMLElementNode;
+class XMLElement;
/** Base class for all character handlers. These handlers create SVG representations
* for the added characters and append them to the SVG tree. */
class SVGCharHandler {
public:
- SVGCharHandler () : _color(Color::BLACK), _font(0), _fontnum(0), _matrix(1), _vertical(false), _initialContextNode(0) {}
+ SVGCharHandler () : _matrix(1) {}
virtual ~SVGCharHandler() =default;
- virtual void setInitialContextNode (XMLElementNode *node);
+ virtual void setInitialContextNode (XMLElement *node);
virtual void appendChar (uint32_t c, double x, double y) =0;
virtual void notifyXAdjusted () {}
virtual void notifyYAdjusted () {}
@@ -74,32 +74,32 @@ class SVGCharHandler {
protected:
virtual void resetContextNode ();
- XMLElementNode* pushContextNode (std::unique_ptr<XMLElementNode> &&node);
+ XMLElement* pushContextNode (std::unique_ptr<XMLElement> node);
void popContextNode ();
- XMLElementNode* contextNode () const {
+ XMLElement* contextNode () const {
return _contextNodeStack.empty() ? _initialContextNode : _contextNodeStack.top();
}
- CharProperty<Color> _color; ///< current color
- CharProperty<const Font*> _font; ///< current font
- int _fontnum; ///< current font ID
- CharProperty<Matrix> _matrix; ///< current transformation
- CharProperty<bool> _vertical; ///< current writing mode
+ CharProperty<Color> _color=Color::BLACK; ///< current color
+ CharProperty<const Font*> _font=0; ///< current font
+ int _fontnum=0; ///< current font ID
+ CharProperty<Matrix> _matrix; ///< current transformation
+ CharProperty<bool> _vertical=false; ///< current writing mode
private:
- XMLElementNode *_initialContextNode; ///< SVG element the generated character nodes are attached to
- std::stack<XMLElementNode*> _contextNodeStack;
+ XMLElement *_initialContextNode= nullptr; ///< SVG element the generated character nodes are attached to
+ std::stack<XMLElement*> _contextNodeStack;
};
/** Base class for all character handlers that create SVG <text> elements. */
class SVGCharTextHandler : public SVGCharHandler {
public:
- SVGCharTextHandler (bool selectFontByClass) : _selectFontByClass(selectFontByClass) {}
+ explicit SVGCharTextHandler (bool selectFontByClass) : _selectFontByClass(selectFontByClass) {}
protected:
- std::unique_ptr<XMLElementNode> createTextNode (double x, double y) const;
+ std::unique_ptr<XMLElement> createTextNode (double x, double y) const;
private:
bool _selectFontByClass;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp
index 1b2316926d0..3962168ae2f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.cpp
@@ -31,7 +31,7 @@ using namespace std;
* @param[in] createUseElements determines whether to create "use" elements to reference previous paths or not
* @param[in] relativePathCommands determines whether to create relative or absolute SVG path commands */
SVGCharPathHandler::SVGCharPathHandler (bool createUseElements, bool relativePathCommands)
- : _relativePathCommands(relativePathCommands), _groupNode(0), _fontColor(Color::BLACK)
+ : _relativePathCommands(relativePathCommands)
{
if (createUseElements)
_appendChar = &SVGCharPathHandler::appendUseElement;
@@ -42,7 +42,7 @@ SVGCharPathHandler::SVGCharPathHandler (bool createUseElements, bool relativePat
void SVGCharPathHandler::resetContextNode () {
SVGCharHandler::resetContextNode();
- _groupNode = 0;
+ _groupNode = nullptr;
}
@@ -69,11 +69,11 @@ void SVGCharPathHandler::appendChar (uint32_t c, double x, double y) {
if (color.changed() || _matrix.changed()) {
resetContextNode();
if (applyColor || applyMatrix) {
- _groupNode = pushContextNode(util::make_unique<XMLElementNode>("g"));
+ _groupNode = pushContextNode(util::make_unique<XMLElement>("g"));
if (applyColor)
contextNode()->addAttribute("fill", color.get().svgColorString());
if (applyMatrix)
- contextNode()->addAttribute("transform", _matrix.get().getSVG());
+ contextNode()->addAttribute("transform", _matrix.get().toSVG());
}
color.changed(false);
_matrix.changed(false);
@@ -84,7 +84,7 @@ void SVGCharPathHandler::appendChar (uint32_t c, double x, double y) {
GlyphMetrics metrics;
font->getGlyphMetrics(c, _vertical, metrics);
x -= metrics.wl;
- if (const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(font)) {
+ if (auto pf = dynamic_cast<const PhysicalFont*>(font)) {
// Center glyph between top and bottom border of the TFM box.
// This is just an approximation used until I find a way to compute
// the exact location in vertical mode.
@@ -109,28 +109,28 @@ void SVGCharPathHandler::appendChar (uint32_t c, double x, double y) {
void SVGCharPathHandler::appendUseElement (uint32_t c, double x, double y, const Matrix &matrix) {
string id = "#g" + to_string(FontManager::instance().fontID(_font)) + "-" + to_string(c);
- auto useNode = util::make_unique<XMLElementNode>("use");
+ auto useNode = util::make_unique<XMLElement>("use");
useNode->addAttribute("x", XMLString(x));
useNode->addAttribute("y", XMLString(y));
useNode->addAttribute("xlink:href", id);
if (!matrix.isIdentity())
- useNode->addAttribute("transform", matrix.getSVG());
+ useNode->addAttribute("transform", matrix.toSVG());
contextNode()->append(std::move(useNode));
}
void SVGCharPathHandler::appendPathElement (uint32_t c, double x, double y, const Matrix &matrix) {
Glyph glyph;
- const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(_font.get());
+ auto pf = dynamic_cast<const PhysicalFont*>(_font.get());
if (pf && pf->getGlyph(c, glyph)) {
double sx = pf->scaledSize()/pf->unitsPerEm();
double sy = -sx;
ostringstream oss;
glyph.writeSVG(oss, _relativePathCommands, sx, sy, x, y);
- auto glyphNode = util::make_unique<XMLElementNode>("path");
+ auto glyphNode = util::make_unique<XMLElement>("path");
glyphNode->addAttribute("d", oss.str());
if (!matrix.isIdentity())
- glyphNode->addAttribute("transform", matrix.getSVG());
+ glyphNode->addAttribute("transform", matrix.toSVG());
contextNode()->append(std::move(glyphNode));
}
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp
index 944e554a9e6..ba172de340d 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharPathHandler.hpp
@@ -37,10 +37,10 @@ class SVGCharPathHandler : public SVGCharHandler {
void resetContextNode () override;
private:
- AppendMethod _appendChar; ///< method called to append a single character
- bool _relativePathCommands; ///< if true, create relative rather than absolute SVG path commands
- XMLElementNode *_groupNode; ///< current group node taking the path elements
- CharProperty<Color> _fontColor; ///< color of current font
+ AppendMethod _appendChar; ///< method called to append a single character
+ bool _relativePathCommands; ///< if true, create relative rather than absolute SVG path commands
+ XMLElement *_groupNode=nullptr; ///< current group node taking the path elements
+ CharProperty<Color> _fontColor=Color::BLACK; ///< color of current font
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp
index eb47f493085..a48f5f9a931 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.cpp
@@ -41,20 +41,20 @@ void SVGCharTspanTextHandler::appendChar (uint32_t c, double x, double y) {
if (_tspanNode && (_xchanged || _ychanged || _color.changed())) {
// if drawing position or color was explicitly changed, finish current tspan element
popContextNode();
- _tspanNode = 0;
+ _tspanNode = nullptr;
}
// Apply text color changes only if the color of the entire font is black.
// Glyphs of non-black fonts (e.g. defined in a XeTeX document) can't change their color.
bool applyColor = _color.get() != Color::BLACK && _font.get()->color() == Color::BLACK;
if (_xchanged || _ychanged || (_color.changed() && applyColor)) {
- _tspanNode = pushContextNode(util::make_unique<XMLElementNode>("tspan"));
+ _tspanNode = pushContextNode(util::make_unique<XMLElement>("tspan"));
if (applyColor)
_tspanNode->addAttribute("fill", _color.get().svgColorString());
_color.changed(false);
if (_xchanged) {
if (_vertical) {
// align glyphs designed for horizontal layout properly
- if (const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(_font.get()))
+ if (auto pf = dynamic_cast<const PhysicalFont*>(_font.get()))
if (!pf->getMetrics()->verticalLayout())
x += pf->scaledAscent()/2.5; // move vertical baseline to the right by strikethrough offset
}
@@ -70,16 +70,16 @@ void SVGCharTspanTextHandler::appendChar (uint32_t c, double x, double y) {
}
-void SVGCharTspanTextHandler::setInitialContextNode (XMLElementNode *node) {
+void SVGCharTspanTextHandler::setInitialContextNode (XMLElement *node) {
SVGCharHandler::setInitialContextNode(node);
- _textNode = _tspanNode = 0;
+ _textNode = _tspanNode = nullptr;
_xchanged = _ychanged = false;
}
void SVGCharTspanTextHandler::resetContextNode () {
SVGCharHandler::resetContextNode();
- _textNode = _tspanNode = 0;
+ _textNode = _tspanNode = nullptr;
_xchanged = _ychanged = false;
_font.changed(false);
_matrix.changed(false);
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp
index c88e97bfe52..01567997b63 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGCharTspanTextHandler.hpp
@@ -25,19 +25,19 @@
class SVGCharTspanTextHandler : public SVGCharTextHandler {
public:
- SVGCharTspanTextHandler (bool selectFontByClass);
+ explicit SVGCharTspanTextHandler (bool selectFontByClass);
void notifyXAdjusted () override {_xchanged = true;}
void notifyYAdjusted() override {_ychanged = true;}
void appendChar (uint32_t c, double x, double y) override;
- void setInitialContextNode (XMLElementNode *node) override;
+ void setInitialContextNode (XMLElement *node) override;
protected:
void resetContextNode () override;
private:
bool _xchanged, _ychanged;
- XMLElementNode *_textNode;
- XMLElementNode *_tspanNode;
+ XMLElement *_textNode;
+ XMLElement *_tspanNode;
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp
index 6256acdeba1..7c4108c8769 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.cpp
@@ -34,8 +34,8 @@
using namespace std;
-SVGOutput::SVGOutput (const string &base, const string &pattern, int zipLevel)
- : _path(base), _pattern(pattern), _stdout(base.empty()), _zipLevel(zipLevel), _page(-1)
+SVGOutput::SVGOutput (const string &base, string pattern, int zipLevel)
+ : _path(base), _pattern(std::move(pattern)), _stdout(base.empty()), _zipLevel(zipLevel), _page(-1)
{
}
@@ -46,8 +46,8 @@ SVGOutput::SVGOutput (const string &base, const string &pattern, int zipLevel)
* @param[in] hash hash value of the current page
* @return output stream for the given page */
ostream& SVGOutput::getPageStream (int page, int numPages, const HashTriple &hashes) const {
- string fname = filename(page, numPages, hashes);
- if (fname.empty()) {
+ FilePath path = filepath(page, numPages, hashes);
+ if (path.empty()) {
if (_zipLevel == 0) {
_osptr.reset();
return cout;
@@ -63,52 +63,35 @@ ostream& SVGOutput::getPageStream (int page, int numPages, const HashTriple &has
_page = page;
if (_zipLevel > 0)
- _osptr = util::make_unique<ZLibOutputFileStream>(fname, ZLIB_GZIP, _zipLevel);
+ _osptr = util::make_unique<ZLibOutputFileStream>(path.absolute(), ZLIB_GZIP, _zipLevel);
else
- _osptr = util::make_unique<ofstream>(fname);
+ _osptr = util::make_unique<ofstream>(path.absolute());
if (!_osptr)
- throw MessageException("can't open file "+fname+" for writing");
+ throw MessageException("can't open file "+path.shorterAbsoluteOrRelative()+" for writing");
return *_osptr;
}
-/** Returns the name of the SVG file containing the given page.
+/** Returns the path of the SVG file containing the given page number.
* @param[in] page number of current page
* @param[in] numPages total number of pages
* @param[in] hash hash value of current page */
-string SVGOutput::filename (int page, int numPages, const HashTriple &hashes) const {
- if (_stdout)
- return "";
-
- string expanded_pattern = util::trim(expandFormatString(_pattern, page, numPages, hashes));
- // set and expand default pattern if necessary
- if (expanded_pattern.empty()) {
- string pattern = hashes.empty() ? (numPages > 1 ? "%f-%p" : "%f") : "%f-%hd";
- expanded_pattern = expandFormatString(pattern, page, numPages, hashes);
+FilePath SVGOutput::filepath (int page, int numPages, const HashTriple &hashes) const {
+ FilePath outpath;
+ if (!_stdout) {
+ string expanded_pattern = util::trim(expandFormatString(_pattern, page, numPages, hashes));
+ // set and expand default pattern if necessary
+ if (expanded_pattern.empty()) {
+ string pattern = hashes.empty() ? (numPages > 1 ? "%f-%p" : "%f") : "%f-%hd";
+ expanded_pattern = expandFormatString(pattern, page, numPages, hashes);
+ }
+ // append suffix if necessary
+ outpath.set(expanded_pattern, true);
+ if (outpath.suffix().empty())
+ outpath.suffix(_zipLevel > 0 ? "svgz" : "svg");
}
- // append suffix if necessary
- FilePath outpath(expanded_pattern, true);
- if (outpath.suffix().empty())
- outpath.suffix(_zipLevel > 0 ? "svgz" : "svg");
- string abspath = outpath.absolute();
- string relpath = outpath.relative();
- return abspath.length() < relpath.length() ? abspath : relpath;
-}
-
-
-#if 0
-string SVGOutput::outpath (int page, int numPages) const {
- string path = filename(page, numPages);
- if (path.empty())
- return "";
- size_t pos = path.rfind('/');
- if (pos == string::npos)
- return ".";
- if (pos == 0)
- return "/";
- return path.substr(0, pos);
+ return outpath;
}
-#endif
/** Replaces expressions in a given string by the corresponding values and returns the result.
@@ -174,9 +157,7 @@ string SVGOutput::expandFormatString (string str, int page, int numPages, const
result += oss.str();
}
catch (CalculatorException &e) {
- oss.str("");
- oss << "error in filename pattern (" << e.what() << ")";
- throw MessageException(oss.str());
+ throw MessageException("error in filename pattern (" + string(e.what()) + ")");
}
pos = endpos;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp
index 6fb4ee6abf1..3c382f0b7fe 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGOutput.hpp
@@ -31,8 +31,8 @@ struct SVGOutputBase {
class HashTriple {
public:
HashTriple () =default;
- HashTriple (const std::string &dviHash, const std::string &optHash, const std::string &cmbHash)
- : _dviHash(dviHash), _optHash(optHash), _cmbHash(cmbHash) {}
+ HashTriple (std::string dviHash, std::string optHash, std::string cmbHash)
+ : _dviHash(std::move(dviHash)), _optHash(std::move(optHash)), _cmbHash(std::move(cmbHash)) {}
std::string dviHash () const {return _dviHash;}
std::string optHash () const {return _optHash;}
std::string cmbHash () const {return _cmbHash;}
@@ -46,7 +46,7 @@ struct SVGOutputBase {
virtual ~SVGOutputBase () =default;
virtual std::ostream& getPageStream (int page, int numPages, const HashTriple &hashes=HashTriple()) const =0;
- virtual std::string filename (int page, int numPages, const HashTriple &hashes=HashTriple()) const =0;
+ virtual FilePath filepath (int page, int numPages, const HashTriple &hashes= HashTriple()) const =0;
virtual bool ignoresHashes () const {return true;}
};
@@ -54,11 +54,11 @@ struct SVGOutputBase {
class SVGOutput : public SVGOutputBase {
public:
SVGOutput () : SVGOutput("", "", 0) {}
- SVGOutput (const std::string &base) : SVGOutput(base, "", 0) {}
+ explicit SVGOutput (const std::string &base) : SVGOutput(base, "", 0) {}
SVGOutput (const std::string &base, const std::string &pattern) : SVGOutput(base, pattern, 0) {}
- SVGOutput (const std::string &base, const std::string &pattern, int zipLevel);
+ SVGOutput (const std::string &base, std::string pattern, int zipLevel);
std::ostream& getPageStream (int page, int numPages, const HashTriple &hash=HashTriple()) const override;
- std::string filename (int page, int numPages, const HashTriple &hash=HashTriple()) const override;
+ FilePath filepath (int page, int numPages, const HashTriple &hash=HashTriple()) const override;
bool ignoresHashes () const override;
protected:
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp
index 9729bafabac..7fd2174f127 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGSingleCharTextHandler.hpp
@@ -26,7 +26,7 @@
class SVGSingleCharTextHandler : public SVGCharTextHandler {
public:
- SVGSingleCharTextHandler (bool createStyleElements) : SVGCharTextHandler(createStyleElements) {}
+ explicit SVGSingleCharTextHandler (bool createStyleElements) : SVGCharTextHandler(createStyleElements) {}
void appendChar (uint32_t c, double x, double y) override;
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
index 3c891219e14..57b5fd5a4fa 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
@@ -20,9 +20,9 @@
#include <algorithm>
#include <array>
+#include <cstring>
#include <sstream>
#include "BoundingBox.hpp"
-#include "DependencyGraph.hpp"
#include "DVIToSVG.hpp"
#include "FileSystem.hpp"
#include "Font.hpp"
@@ -36,7 +36,6 @@
using namespace std;
-
// static class variables
bool SVGTree::CREATE_CSS=true;
bool SVGTree::USE_FONTS=true;
@@ -56,7 +55,7 @@ SVGTree::SVGTree () : _charHandler(SVGCharHandlerFactory::createHandler()) {
/** Clears the SVG tree and initializes the root element. */
void SVGTree::reset () {
_doc.clear();
- auto rootNode = util::make_unique<XMLElementNode>("svg");
+ auto rootNode = util::make_unique<XMLElement>("svg");
rootNode->addAttribute("version", "1.1");
rootNode->addAttribute("xmlns", "http://www.w3.org/2000/svg");
rootNode->addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
@@ -112,45 +111,46 @@ bool SVGTree::setFontFormat (string formatstr) {
/** Starts a new page.
* @param[in] pageno number of new page */
void SVGTree::newPage (int pageno) {
- auto pageNode = util::make_unique<XMLElementNode>("g");
+ auto pageNode = util::make_unique<XMLElement>("g");
if (pageno >= 0)
pageNode->addAttribute("id", string("page")+XMLString(pageno));
_charHandler->setInitialContextNode(pageNode.get());
_page = pageNode.get();
_root->append(std::move(pageNode));
- while (!_contextElementStack.empty())
- _contextElementStack.pop();
+ _defsContextStack = stack<XMLElement*>();
+ _pageContextStack = stack<XMLElement*>();
}
-void SVGTree::appendToDefs (unique_ptr<XMLNode> &&node) {
+void SVGTree::appendToDefs (unique_ptr<XMLNode> node) {
if (!_defs) {
- auto defsNode = util::make_unique<XMLElementNode>("defs");
+ auto defsNode = util::make_unique<XMLElement>("defs");
_defs = defsNode.get();
_root->prepend(std::move(defsNode));
}
- _defs->append(std::move(node));
+ XMLElement *parent = _defsContextStack.empty() ? _defs : _defsContextStack.top();
+ parent->append(std::move(node));
}
-void SVGTree::appendToPage (unique_ptr<XMLNode> &&node) {
- XMLElementNode *parent = _contextElementStack.empty() ? _page : _contextElementStack.top();
+void SVGTree::appendToPage (unique_ptr<XMLNode> node) {
+ XMLElement *parent = _pageContextStack.empty() ? _page : _pageContextStack.top();
parent->append(std::move(node));
_charHandler->setInitialContextNode(parent);
}
-void SVGTree::prependToPage (unique_ptr<XMLNode> &&node) {
- if (_contextElementStack.empty())
+void SVGTree::prependToPage (unique_ptr<XMLNode> node) {
+ if (_pageContextStack.empty())
_page->prepend(std::move(node));
else
- _contextElementStack.top()->prepend(std::move(node));
+ _pageContextStack.top()->prepend(std::move(node));
}
void SVGTree::transformPage (const Matrix &usermatrix) {
if (!usermatrix.isIdentity())
- _page->addAttribute("transform", usermatrix.getSVG());
+ _page->addAttribute("transform", usermatrix.toSVG());
}
@@ -159,17 +159,17 @@ void SVGTree::transformPage (const Matrix &usermatrix) {
* @param[in] font font to extract the glyph from
* @param[in] cb pointer to callback object for sending feedback to the glyph tracer (may be 0)
* @return pointer to element node if glyph exists, 0 otherwise */
-static unique_ptr<XMLElementNode> createGlyphNode (int c, const PhysicalFont &font, GFGlyphTracer::Callback *cb) {
+static unique_ptr<XMLElement> createGlyphNode (int c, const PhysicalFont &font, GFGlyphTracer::Callback *cb) {
Glyph glyph;
if (!font.getGlyph(c, glyph, cb) || (!SVGTree::USE_FONTS && !SVGTree::CREATE_USE_ELEMENTS))
return nullptr;
double sx=1.0, sy=1.0;
double upem = font.unitsPerEm();
- unique_ptr<XMLElementNode> glyphNode;
+ unique_ptr<XMLElement> glyphNode;
if (SVGTree::USE_FONTS) {
double extend = font.style() ? font.style()->extend : 1;
- glyphNode = util::make_unique<XMLElementNode>("glyph");
+ glyphNode = util::make_unique<XMLElement>("glyph");
glyphNode->addAttribute("unicode", XMLString(font.unicode(c), false));
glyphNode->addAttribute("horiz-adv-x", XMLString(font.hAdvance(c)*extend));
glyphNode->addAttribute("vert-adv-y", XMLString(font.vAdvance(c)));
@@ -178,7 +178,7 @@ static unique_ptr<XMLElementNode> createGlyphNode (int c, const PhysicalFont &fo
glyphNode->addAttribute("glyph-name", name);
}
else {
- glyphNode = util::make_unique<XMLElementNode>("path");
+ glyphNode = util::make_unique<XMLElement>("path");
glyphNode->addAttribute("id", "g"+to_string(FontManager::instance().fontID(&font))+"-"+to_string(c));
sx = font.scaledSize()/upem;
sy = -sx;
@@ -192,7 +192,7 @@ static unique_ptr<XMLElementNode> createGlyphNode (int c, const PhysicalFont &fo
static string font_info (const Font &font) {
ostringstream oss;
- if (const NativeFont *nf = dynamic_cast<const NativeFont*>(&font)) {
+ if (auto nf = dynamic_cast<const NativeFont*>(&font)) {
oss << nf->familyName() << ' ' << nf->styleName() << "; " << nf->filename();
if (nf->style()) {
if (nf->style()->bold != 0)
@@ -255,14 +255,14 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr
if (ADD_COMMENTS) {
string info = font_info(font);
if (!info.empty())
- appendToDefs(util::make_unique<XMLCommentNode>(string(" font: ")+info+" "));
+ appendToDefs(util::make_unique<XMLComment>(string(" font: ")+info+" "));
}
- auto fontNode = util::make_unique<XMLElementNode>("font");
+ auto fontNode = util::make_unique<XMLElement>("font");
string fontname = font.name();
fontNode->addAttribute("id", fontname);
fontNode->addAttribute("horiz-adv-x", XMLString(font.hAdvance()));
- auto faceNode = util::make_unique<XMLElementNode>("font-face");
+ auto faceNode = util::make_unique<XMLElement>("font-face");
faceNode->addAttribute("font-family", fontname);
faceNode->addAttribute("units-per-em", XMLString(font.unitsPerEm()));
if (!font.verticalLayout()) {
@@ -281,7 +281,7 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr
// reference the already embedded path together with a transformation attribute and let the SVG renderer
// scale the glyphs properly. This is only necessary if we don't want to use font but path elements.
for (int c : chars) {
- auto useNode = util::make_unique<XMLElementNode>("use");
+ auto useNode = util::make_unique<XMLElement>("use");
useNode->addAttribute("id", "g"+to_string(FontManager::instance().fontID(&font))+"-"+to_string(c));
useNode->addAttribute("xlink:href", "#g"+to_string(FontManager::instance().fontID(font.uniqueFont()))+"-"+to_string(c));
double scale = font.scaledSize()/font.uniqueFont()->scaledSize();
@@ -297,70 +297,47 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr
}
-/** Pushes a new context element that will take all following nodes added to the page. */
-void SVGTree::pushContextElement (unique_ptr<XMLElementNode> &&node) {
- XMLElementNode *nodePtr = node.get();
- if (_contextElementStack.empty())
- _page->append(std::move(node));
+void SVGTree::pushDefsContext (unique_ptr<XMLElement> node) {
+ XMLElement *nodePtr = node.get();
+ if (_defsContextStack.empty())
+ appendToDefs(std::move(node));
else
- _contextElementStack.top()->append(std::move(node));
- _contextElementStack.push(nodePtr);
- _charHandler->setInitialContextNode(nodePtr);
+ _defsContextStack.top()->append(std::move(node));
+ _defsContextStack.push(nodePtr);
}
-/** Pops the current context element and restored the previous one. */
-void SVGTree::popContextElement () {
- if (!_contextElementStack.empty())
- _contextElementStack.pop();
- _charHandler->setInitialContextNode(_page);
+void SVGTree::popDefsContext () {
+ if (!_defsContextStack.empty())
+ _defsContextStack.pop();
}
-/** Extracts the ID from a local URL reference like url(#abcde) */
-static inline string extract_id_from_url (const string &url) {
- return url.substr(5, url.length()-6);
+/** Pushes a new context element that will take all following nodes added to the page. */
+void SVGTree::pushPageContext (unique_ptr<XMLElement> node) {
+ XMLElement *nodePtr = node.get();
+ if (_pageContextStack.empty())
+ _page->append(std::move(node));
+ else
+ _pageContextStack.top()->append(std::move(node));
+ _pageContextStack.push(nodePtr);
+ _charHandler->setInitialContextNode(nodePtr);
}
-/** Removes elements present in the SVG tree that are not required.
- * For now, only clipPath elements are removed. */
-void SVGTree::removeRedundantElements () {
- vector<XMLElementNode*> clipPathElements;
- if (!_defs || !_defs->getDescendants("clipPath", nullptr, clipPathElements))
- return;
-
- // collect dependencies between clipPath elements in the defs section of the SVG tree
- DependencyGraph<string> idTree;
- for (const XMLElementNode *clip : clipPathElements) {
- if (const char *id = clip->getAttributeValue("id")) {
- if (const char *url = clip->getAttributeValue("clip-path"))
- idTree.insert(extract_id_from_url(url), id);
- else
- idTree.insert(id);
- }
- }
- // collect elements that reference a clipPath, i.e. have a clip-path attribute
- vector<XMLElementNode*> descendants;
- _page->getDescendants(nullptr, "clip-path", descendants);
- // remove referenced IDs and their dependencies from the dependency graph
- for (const XMLElementNode *elem : descendants) {
- string idref = extract_id_from_url(elem->getAttributeValue("clip-path"));
- idTree.removeDependencyPath(idref);
- }
- descendants.clear();
- for (const string &str : idTree.getKeys()) {
- XMLElementNode *node = _defs->getFirstDescendant("clipPath", "id", str.c_str());
- _defs->remove(node);
- }
+/** Pops the current context element and restored the previous one. */
+void SVGTree::popPageContext () {
+ if (!_pageContextStack.empty())
+ _pageContextStack.pop();
+ _charHandler->setInitialContextNode(_page);
}
-XMLCDataNode* SVGTree::styleCDataNode () {
+XMLCData* SVGTree::styleCDataNode () {
if (!_styleCDataNode) {
- auto styleNode = util::make_unique<XMLElementNode>("style");
+ auto styleNode = util::make_unique<XMLElement>("style");
styleNode->addAttribute("type", "text/css");
- auto cdataNode = util::make_unique<XMLCDataNode>();
+ auto cdataNode = util::make_unique<XMLCData>();
_styleCDataNode = cdataNode.get();
styleNode->append(std::move(cdataNode));
_root->insertBefore(std::move(styleNode), _page);
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp
index 62891e76fa3..d351ec97991 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.hpp
@@ -46,17 +46,18 @@ class SVGTree {
void reset ();
bool write (std::ostream &os) const {return bool(_doc.write(os));}
void newPage (int pageno);
- void appendToDefs (std::unique_ptr<XMLNode> &&node);
- void appendToPage (std::unique_ptr<XMLNode> &&node);
- void prependToPage (std::unique_ptr<XMLNode> &&node);
- void appendToDoc (std::unique_ptr<XMLNode> &&node) {_doc.append(std::move(node));}
- void appendToRoot (std::unique_ptr<XMLNode> &&node) {_root->append(std::move(node));}
+ void appendToDefs (std::unique_ptr<XMLNode> node);
+ void appendToPage (std::unique_ptr<XMLNode> node);
+ void prependToPage (std::unique_ptr<XMLNode> node);
+ void appendToDoc (std::unique_ptr<XMLNode> node) {_doc.append(std::move(node));}
+ void appendToRoot (std::unique_ptr<XMLNode> node) {_root->append(std::move(node));}
void appendChar (int c, double x, double y) {_charHandler->appendChar(c, x, y);}
void appendFontStyles (const std::unordered_set<const Font*> &fonts);
- void append (const PhysicalFont &font, const std::set<int> &chars, GFGlyphTracer::Callback *callback=0);
- void pushContextElement (std::unique_ptr<XMLElementNode> &&node);
- void popContextElement ();
- void removeRedundantElements ();
+ void append (const PhysicalFont &font, const std::set<int> &chars, GFGlyphTracer::Callback *callback=nullptr);
+ void pushDefsContext (std::unique_ptr<XMLElement> node);
+ void popDefsContext ();
+ void pushPageContext (std::unique_ptr<XMLElement> node);
+ void popPageContext ();
void setBBox (const BoundingBox &bbox);
void setFont (int id, const Font &font);
static bool setFontFormat (std::string formatstr);
@@ -68,10 +69,12 @@ class SVGTree {
void transformPage (const Matrix &m);
Color getColor () const {return _charHandler->getColor();}
const Matrix& getMatrix () const {return _charHandler->getMatrix();}
- XMLElementNode* rootNode () const {return _root;}
+ XMLElement* rootNode () const {return _root;}
+ XMLElement* defsNode () const {return _defs;}
+ XMLElement* pageNode () const {return _page;}
protected:
- XMLCDataNode* styleCDataNode ();
+ XMLCData* styleCDataNode ();
public:
static bool USE_FONTS; ///< if true, create font references and don't draw paths directly
@@ -85,10 +88,11 @@ class SVGTree {
private:
XMLDocument _doc;
- XMLElementNode *_root, *_page, *_defs;
- XMLCDataNode *_styleCDataNode;
+ XMLElement *_root, *_page, *_defs;
+ XMLCData *_styleCDataNode;
std::unique_ptr<SVGCharHandler> _charHandler;
- std::stack<XMLElementNode*> _contextElementStack;
+ std::stack<XMLElement*> _defsContextStack;
+ std::stack<XMLElement*> _pageContextStack;
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp
index 2c430ac58bf..4346301e7bf 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ShadingPatch.hpp
@@ -38,12 +38,12 @@ class ShadingPatch {
using ColorVec = std::vector<Color>;
public:
- ShadingPatch (Color::ColorSpace colorSpace) : _colorspace(colorSpace) {}
+ explicit ShadingPatch (Color::ColorSpace colorSpace) : _colorspace(colorSpace) {}
virtual ~ShadingPatch () =default;
virtual int psShadingType () const =0;
virtual void approximate (int gridsize, bool overlap, double delta, Callback &callback) const =0;
- virtual void getBBox (BoundingBox &bbox) const =0;
- virtual void getBoundaryPath (GraphicsPath<double> &path) const =0;
+ virtual BoundingBox getBBox () const =0;
+ virtual GraphicsPath<double> getBoundaryPath () const =0;
virtual void setPoints (const PointVec &points, int edgeflag, ShadingPatch *patch) =0;
virtual void setColors (const ColorVec &colors, int edgeflag, ShadingPatch *patch) =0;
virtual int numPoints (int edgeflag) const =0;
@@ -63,7 +63,7 @@ class ShadingPatch {
struct ShadingException : public MessageException {
- ShadingException (const std::string &msg) : MessageException(msg) {}
+ explicit ShadingException (const std::string &msg) : MessageException(msg) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp
index aa2a5dde55e..886c9281bbc 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp
@@ -129,7 +129,7 @@ bool SignalHandler::Impl::setSigintHandler (HandlerFunc handler) {
bool SignalHandler::Impl::restoreSigintHandler () {
if (_origSigaction.sa_handler == nullptr)
return false;
- return (sigaction(SIGINT, &_origSigaction, 0) == 0);
+ return (sigaction(SIGINT, &_origSigaction, nullptr) == 0);
}
#else // !HAVE_SIGACTION
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SourceInput.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SourceInput.hpp
index 05df49ee84a..3b0f7b3c62c 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SourceInput.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SourceInput.hpp
@@ -43,7 +43,7 @@ class TemporaryFile {
class SourceInput {
public:
- SourceInput (const std::string &fname) : _fname(fname) {}
+ explicit SourceInput (const std::string &fname) : _fname(fname) {}
std::istream& getInputStream (bool showMessages=false);
std::string getFileName () const;
std::string getMessageFileName () const;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp
index 5e32f84413b..7e53303792b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.hpp
@@ -25,10 +25,12 @@
#include <memory>
#include "BoundingBox.hpp"
#include "Color.hpp"
+#include "FilePath.hpp"
#include "Matrix.hpp"
+#include "SVGTree.hpp"
+class XMLElement;
class XMLNode;
-class XMLElementNode;
class SpecialActions {
public:
@@ -44,20 +46,20 @@ class SpecialActions {
virtual const Matrix& getMatrix () const =0;
virtual Matrix getPageTransformation () const {return Matrix(1);}
virtual void setBgColor (const Color &color) =0;
- virtual void appendToPage(std::unique_ptr<XMLNode> &&node) =0;
- virtual void appendToDefs(std::unique_ptr<XMLNode> &&node) =0;
- virtual void prependToPage(std::unique_ptr<XMLNode> &&node) =0;
- virtual void pushContextElement (std::unique_ptr<XMLElementNode> &&node) =0;
- virtual void popContextElement () =0;
+ virtual const SVGTree& svgTree () const =0;
+ SVGTree& svgTree () {return const_cast<SVGTree&>(const_cast<const SpecialActions*>(this)->svgTree());}
virtual BoundingBox& bbox () =0;
virtual BoundingBox& bbox (const std::string &name, bool reset=false) =0;
virtual void embed (const BoundingBox &bbox) =0;
virtual void embed (const DPair &p, double r=0) =0;
virtual unsigned getCurrentPageNumber () const =0;
- virtual std::string getSVGFilename (unsigned pageno) const =0;
+ virtual FilePath getSVGFilePath (unsigned pageno) const =0;
virtual std::string getBBoxFormatString () const =0;
virtual void progress (const char *id) {}
virtual int getDVIStackDepth () const {return 0;}
+ virtual void lockOutput () {}
+ virtual void unlockOutput () {}
+ virtual bool outputLocked () const {return false;}
static double PROGRESSBAR_DELAY; ///< progress bar doesn't appear before this time has elapsed (in sec)
};
@@ -65,6 +67,7 @@ class SpecialActions {
class EmptySpecialActions : public SpecialActions {
public:
+ EmptySpecialActions () : _matrix(1) {_svg.newPage(1);}
double getX () const override {return 0;}
double getY () const override {return 0;}
void setX (double x) override {}
@@ -75,22 +78,19 @@ class EmptySpecialActions : public SpecialActions {
Color getColor () const override {return Color::BLACK;}
void setMatrix (const Matrix &m) override {}
const Matrix& getMatrix () const override {return _matrix;}
- void appendToPage(std::unique_ptr<XMLNode> &&node) override {}
- void appendToDefs(std::unique_ptr<XMLNode> &&node) override {}
- void prependToPage(std::unique_ptr<XMLNode> &&node) override {}
- void pushContextElement (std::unique_ptr<XMLElementNode> &&node) override {}
- void popContextElement () override {}
+ const SVGTree& svgTree () const override {return _svg;}
BoundingBox& bbox () override {return _bbox;}
BoundingBox& bbox (const std::string &name, bool reset=false) override {return _bbox;}
void embed (const BoundingBox &bbox) override {}
void embed (const DPair &p, double r=0) override {}
unsigned getCurrentPageNumber() const override {return 0;}
- std::string getSVGFilename (unsigned pageno) const override {return "";}
+ FilePath getSVGFilePath (unsigned pageno) const override {return FilePath();}
std::string getBBoxFormatString () const override {return "";}
private:
BoundingBox _bbox;
Matrix _matrix;
+ SVGTree _svg;
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp
index 35b4caf44a0..4a3439bb246 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialHandler.hpp
@@ -32,7 +32,7 @@ class SpecialManager;
struct SpecialException : public MessageException {
- SpecialException (const std::string &msg) : MessageException(msg) {}
+ explicit SpecialException (const std::string &msg) : MessageException(msg) {}
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp
index 5b8646879f0..4838cbdf47b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.cpp
@@ -46,7 +46,7 @@ void SpecialManager::unregisterHandlers () {
/** Registers a single special handler. This method doesn't check if a
* handler of the same class is already registered.
* @param[in] handler pointer to handler to be registered */
-void SpecialManager::registerHandler (unique_ptr<SpecialHandler> &&handler) {
+void SpecialManager::registerHandler (unique_ptr<SpecialHandler> handler) {
if (handler) {
// get array of prefixes this handler is responsible for
for (const char *prefix : handler->prefixes())
@@ -104,11 +104,11 @@ static string extract_prefix (istream &is) {
int c;
string prefix;
while (isalnum(c=is.get()))
- prefix += c;
+ prefix += char(c);
if (ispunct(c)) // also add separation character to identifying prefix
- prefix += c;
+ prefix += char(c);
if (prefix == "ps:" && is.peek() == ':')
- prefix += is.get();
+ prefix += char(is.get());
return prefix;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp
index 671078baa6b..fe88eaf58eb 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialManager.hpp
@@ -36,8 +36,9 @@ class SpecialManager {
using HandlerMap = std::unordered_map<std::string,SpecialHandler*>;
public:
+ SpecialManager (const SpecialManager &) =delete;
static SpecialManager& instance ();
- void registerHandler (std::unique_ptr<SpecialHandler> &&handler);
+ void registerHandler (std::unique_ptr<SpecialHandler> handler);
void registerHandlers (std::vector<std::unique_ptr<SpecialHandler>> &handlers, const char *ignorelist);
void unregisterHandlers ();
void preprocess (const std::string &special, SpecialActions &actions) const;
@@ -51,7 +52,6 @@ class SpecialManager {
protected:
SpecialManager () =default;
- SpecialManager (const SpecialManager &) =delete;
SpecialHandler* findHandlerByPrefix (const std::string &prefix) const;
private:
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp
index 08067566075..ccfb176abee 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.cpp
@@ -20,8 +20,9 @@
#include <algorithm>
#include <vector>
-#include "CRC32.hpp"
+#include "HashFunction.hpp"
#include "StreamReader.hpp"
+#include "utility.hpp"
using namespace std;
@@ -46,13 +47,13 @@ uint32_t StreamReader::readUnsigned (int bytes) {
}
-/** Reads an unsigned integer from assigned input stream and updates the CRC32 checksum.
- * @param[in] bytes number of bytes to read (max. 4)
- * @param[in,out] crc32 checksum to be updated
+/** Reads an unsigned integer from assigned input stream and updates the hash value.
+ * @param[in] n number of bytes to read (max. 4)
+ * @param[in,out] hashfunc hash to update
* @return read integer */
-uint32_t StreamReader::readUnsigned (int bytes, CRC32 &crc32) {
- uint32_t ret = readUnsigned(bytes);
- crc32.update(ret, bytes);
+uint32_t StreamReader::readUnsigned (int n, HashFunction &hashfunc) {
+ uint32_t ret = readUnsigned(n);
+ hashfunc.update(util::bytes(ret, n));
return ret;
}
@@ -70,13 +71,13 @@ int32_t StreamReader::readSigned (int bytes) {
}
-/** Reads an signed integer from assigned input stream and updates the CRC32 checksum.
+/** Reads an signed integer from assigned input stream and updates the hash value.
* @param[in] bytes number of bytes to read (max. 4)
- * @param[in,out] crc32 checksum to be updated
+ * @param[in,out] hashfunc hash to update
* @return read integer */
-int32_t StreamReader::readSigned (int bytes, CRC32 &crc32) {
- int32_t ret = readSigned(bytes);
- crc32.update(uint32_t(ret), bytes);
+int32_t StreamReader::readSigned (int n, HashFunction &hashfunc) {
+ int32_t ret = readSigned(n);
+ hashfunc.update(util::bytes(ret, n));
return ret;
}
@@ -87,21 +88,21 @@ string StreamReader::readString () {
throw StreamReaderException("no stream assigned");
string ret;
while (!_is->eof() && _is->peek() > 0)
- ret += _is->get();
+ ret += char(_is->get());
_is->get(); // skip 0-byte
return ret;
}
-/** Reads a string terminated by a 0-byte and updates the CRC32 checksum.
- * @param[in,out] crc32 checksum to be updated
+/** Reads a string terminated by a 0-byte and updates the hash value.
+ * @param[in,out] hashfunc hash to update
* @param[in] finalZero consider final 0-byte in checksum
* @return the string read */
-string StreamReader::readString (CRC32 &crc32, bool finalZero) {
+string StreamReader::readString (HashFunction &hashfunc, bool finalZero) {
string ret = readString();
- crc32.update(reinterpret_cast<const uint8_t*>(ret.data()), ret.length());
+ hashfunc.update(ret.data(), ret.length());
if (finalZero)
- crc32.update(0, 1);
+ hashfunc.update(0, 1);
return ret;
}
@@ -119,36 +120,37 @@ string StreamReader::readString (int length) {
}
-/** Reads a string of a given length and updates the CRC32 checksum.
+/** Reads a string of a given length and updates the hash value.
* @param[in] length number of characters to read
- * @param[in,out] crc32 checksum to be updated
+ * @param[in,out] hashfunc hash to update
* @return the string read */
-string StreamReader::readString (int length, CRC32 &crc32) {
+string StreamReader::readString (int length, HashFunction &hashfunc) {
string ret = readString(length);
- crc32.update(reinterpret_cast<const uint8_t*>(ret.data()), length);
+ hashfunc.update(ret.data(), length);
return ret;
}
-vector<uint8_t>& StreamReader::readBytes (int n, vector<uint8_t> &bytes) {
+vector<uint8_t> StreamReader::readBytes (int n) {
+ vector<uint8_t> bytes(n);
if (n > 0)
- _is->read((char*)&bytes[0], n);
+ _is->read(reinterpret_cast<char*>(bytes.data()), n);
return bytes;
}
-vector<uint8_t>& StreamReader::readBytes (int n, vector<uint8_t> &bytes, CRC32 &crc32) {
- readBytes(n, bytes);
- crc32.update(&bytes[0], bytes.size());
+vector<uint8_t> StreamReader::readBytes (int n, HashFunction &hashfunc) {
+ vector<uint8_t> bytes = readBytes(n);
+ hashfunc.update(bytes);
return bytes;
}
-int StreamReader::readByte (CRC32 &crc32) {
+int StreamReader::readByte (HashFunction &hashfunc) {
int ret = readByte();
if (ret >= 0) {
- const uint8_t c = uint8_t(ret & 0xff);
- crc32.update(&c, 1);
+ char c = ret & 0xff;
+ hashfunc.update(&c, 1);
}
return ret;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp
index bf38b2cbf76..05c4e1e701b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamReader.hpp
@@ -26,28 +26,28 @@
#include <vector>
#include "MessageException.hpp"
-class CRC32;
+class HashFunction;
class StreamReader {
public:
- StreamReader (std::istream &is) : _is(&is) {}
+ explicit StreamReader (std::istream &is) : _is(&is) {}
virtual ~StreamReader () =default;
bool isStreamValid () const {return _is;}
bool eof () const {return _is->eof();}
void clearStream () {_is->clear();}
std::istream& replaceStream (std::istream &s);
uint32_t readUnsigned (int n);
- uint32_t readUnsigned (int n, CRC32 &crc32);
+ uint32_t readUnsigned (int n, HashFunction &hashfunc);
int32_t readSigned (int n);
- int32_t readSigned (int n, CRC32 &crc32);
+ int32_t readSigned (int n, HashFunction &hashfunc);
std::string readString ();
- std::string readString (CRC32 &crc32, bool finalZero=false);
+ std::string readString (HashFunction &hashfunc, bool finalZero=false);
std::string readString (int length);
- std::string readString (int length, CRC32 &crc32);
- std::vector<uint8_t>& readBytes (int n, std::vector<uint8_t> &bytes);
- std::vector<uint8_t>& readBytes (int n, std::vector<uint8_t> &bytes, CRC32 &crc32);
+ std::string readString (int length, HashFunction &hashfunc);
+ std::vector<uint8_t> readBytes (int n);
+ std::vector<uint8_t> readBytes (int n, HashFunction &hash);
int readByte () {return _is->get();}
- int readByte (CRC32 &crc32);
+ int readByte (HashFunction &hashfunc);
void seek (std::streampos pos, std::ios::seekdir dir) {_is->seekg(pos, dir);}
void seek (std::streampos pos) {_is->seekg(pos);}
std::streampos tell () const {return _is->tellg();}
@@ -62,7 +62,7 @@ class StreamReader {
struct StreamReaderException : public MessageException {
- StreamReaderException (const std::string &msg) : MessageException(msg) {}
+ explicit StreamReaderException (const std::string &msg) : MessageException(msg) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp
index c5630f56ba2..62164686952 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.cpp
@@ -18,8 +18,9 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
-#include "CRC32.hpp"
+#include "HashFunction.hpp"
#include "StreamWriter.hpp"
+#include "utility.hpp"
using namespace std;
@@ -37,7 +38,7 @@ void StreamWriter::writeUnsigned (uint32_t val, int n) {
* @param[in] val the value to write
* @param[in] n number of bytes to be considered */
void StreamWriter::writeSigned (int32_t val, int n) {
- writeUnsigned((uint32_t)val, n);
+ writeUnsigned(uint32_t(val), n);
}
@@ -71,27 +72,27 @@ void StreamWriter::writeString (const string &str, bool finalZero) {
/** Writes an unsigned integer to the output stream.
* @param[in] val the value to write
* @param[in] n number of bytes to be considered
- * @param[in,out] crc32 checksum to be updated */
-void StreamWriter::writeUnsigned (uint32_t val, int n, CRC32 &crc32) {
+ * @param[in,out] hashfunc hash to update */
+void StreamWriter::writeUnsigned (uint32_t val, int n, HashFunction &hashfunc) {
writeUnsigned(val, n);
- crc32.update(val, n);
+ hashfunc.update(util::bytes(val, n));
}
-/** Writes a signed integer to the output stream and updates the CRC32 checksum.
+/** Writes a signed integer to the output stream and updates the hash value.
* @param[in] val the value to write
* @param[in] n number of bytes to be considered
- * @param[in,out] crc32 checksum to be updated */
-void StreamWriter::writeSigned (int32_t val, int n, CRC32 &crc32) {
- writeUnsigned((uint32_t)val, n, crc32);
+ * @param[in,out] hashfunc hash to update */
+void StreamWriter::writeSigned (int32_t val, int n, HashFunction &hashfunc) {
+ writeUnsigned(uint32_t(val), n, hashfunc);
}
-/** Writes a string to the output stream and updates the CRC32 checksum.
+/** Writes a string to the output stream and updates the hash value.
* @param[in] str the string to write
- * @param[in,out] crc32 checksum to be updated
+ * @param[in,out] hashfunc hash to update
* @param[in] finalZero if true, a final 0-byte is appended */
-void StreamWriter::writeString (const std::string &str, CRC32 &crc32, bool finalZero) {
+void StreamWriter::writeString (const std::string &str, HashFunction &hashfunc, bool finalZero) {
writeString(str, finalZero);
- crc32.update((const uint8_t*)str.c_str(), str.length() + (finalZero ? 1 : 0));
+ hashfunc.update(str.data(), str.length() + (finalZero ? 1 : 0));
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp
index b60e61811e9..441a9a7e7ff 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/StreamWriter.hpp
@@ -24,21 +24,20 @@
#include <ostream>
#include <vector>
-class CRC32;
+class HashFunction;
class StreamWriter {
public:
- StreamWriter (std::ostream &os) : _os(os) {}
- virtual ~StreamWriter () =default;
+ explicit StreamWriter (std::ostream &os) : _os(os) {}
void writeUnsigned (uint32_t val, int n);
void writeSigned (int32_t val, int n);
void writeBytes (const std::vector<uint8_t> &bytes);
void writeBytes (const uint8_t *buf, size_t bufsize);
void writeBytes (int byte, size_t count);
void writeString (const std::string &str, bool finalZero=false);
- void writeUnsigned (uint32_t val, int n, CRC32 &crc32);
- void writeSigned (int32_t val, int n, CRC32 &crc32);
- void writeString (const std::string &str, CRC32 &crc32, bool finalZero=false);
+ void writeUnsigned (uint32_t val, int n, HashFunction &hashfunc);
+ void writeSigned (int32_t val, int n, HashFunction &hashfunc);
+ void writeString (const std::string &str, HashFunction &hashfunc, bool finalZero=false);
private:
std::ostream &_os;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp
index 3f246c0dd8d..e0b2570d8c7 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.cpp
@@ -34,13 +34,13 @@ using namespace std;
// helper functions
static int skip_mapping_data (istream &is);
-static bool scan_line (const char *line, int lineno, vector<uint16_t> &mapping, const string &fname, long &pos);
+static bool scan_line (const char *line, int lineno, vector<uint16_t> &mapping, const string &fname, long &offset);
/** Constructs a new SubfontDefinition object.
* @param[in] name name of subfont definition
* @param[in] fpath path to corresponding .sfd file*/
-SubfontDefinition::SubfontDefinition (const string &name, const char *fpath) : _sfname(name) {
+SubfontDefinition::SubfontDefinition (string name, const char *fpath) : _sfname(std::move(name)) {
// read all subfont IDs from the .sfd file but skip the mapping data
ifstream is(fpath);
while (is) {
@@ -51,7 +51,7 @@ SubfontDefinition::SubfontDefinition (const string &name, const char *fpath) : _
else {
string id;
while (is && !isspace(is.peek()))
- id += is.get();
+ id += char(is.get());
if (!id.empty()) {
auto state = _subfonts.emplace(pair<string,unique_ptr<Subfont>>(id, unique_ptr<Subfont>()));
if (state.second) // id was not present in map already
@@ -136,7 +136,7 @@ bool Subfont::read () {
else {
string id;
while (is && !isspace(is.peek()))
- id += is.get();
+ id += char(is.get());
if (id != _id)
lineno += skip_mapping_data(is);
else {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp
index c452aaeaccf..ca88520ea2f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Subfont.hpp
@@ -37,6 +37,7 @@ class Subfont;
class SubfontDefinition {
using Subfonts = std::map<std::string, std::unique_ptr<Subfont>>;
public:
+ SubfontDefinition (const SubfontDefinition &sfd) =delete;
static SubfontDefinition* lookup (const std::string &name);
// int getIDs (std::vector<std::string> &ids) const;
const std::string& name() const {return _sfname;}
@@ -46,8 +47,7 @@ class SubfontDefinition {
const char* path () const;
protected:
- SubfontDefinition (const std::string &name, const char *fpath);
- SubfontDefinition (const SubfontDefinition &sfd) =delete;
+ SubfontDefinition (std::string name, const char *fpath);
private:
std::string _sfname; ///< name of subfont
@@ -59,12 +59,12 @@ class SubfontDefinition {
class Subfont {
friend class SubfontDefinition;
public:
+ Subfont (const Subfont &sf) =delete;
const std::string& id () const {return _id;}
uint16_t decode (unsigned char c);
protected:
Subfont (SubfontDefinition &sfd, const std::string &id) : _sfd(sfd), _id(id), _mapping(0) {}
- Subfont (const Subfont &sf) =delete;
bool read ();
private:
@@ -76,8 +76,8 @@ class Subfont {
class SubfontException : public MessageException {
public:
- SubfontException (const std::string &msg, const std::string &fname, int lineno=0)
- : MessageException(msg), _fname(fname), _lineno(lineno) {}
+ SubfontException (const std::string &msg, std::string fname, int lineno=0)
+ : MessageException(msg), _fname(std::move(fname)), _lineno(lineno) {}
const char* filename () const {return _fname.c_str();}
int lineno () const {return _lineno;}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp
index c63e5e02dcd..b2724bdcab2 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/System.cpp
@@ -36,7 +36,7 @@ using namespace std;
double System::time () {
#if defined (HAVE_SYS_TIME_H)
struct timeval tv;
- gettimeofday(&tv, NULL);
+ gettimeofday(&tv, nullptr);
return tv.tv_sec + tv.tv_usec/1000000.0;
#elif defined (HAVE_SYS_TIMEB_H)
struct timeb tb;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp
index 36cb462b6f3..668ff390833 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TFM.hpp
@@ -33,7 +33,7 @@ class StreamReader;
class TFM : public FontMetrics
{
public:
- TFM (std::istream &is);
+ explicit TFM (std::istream &is);
double getCharWidth (int c) const override;
double getCharHeight (int c) const override;
double getCharDepth (int c) const override;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp
index e9e0ef4b192..52acd63179a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.cpp
@@ -63,7 +63,7 @@ void TensorProductPatch::setFirstMatrixColumn (DPair source[4][4], int col, bool
* @param[in] edgeflag defines how to connect this patch with another one
* @param[in] patch reference patch required if edgeflag > 0 */
void TensorProductPatch::setPoints (const PointVec &points, int edgeflag, ShadingPatch *patch) {
- TensorProductPatch *tpPatch = dynamic_cast<TensorProductPatch*>(patch);
+ auto tpPatch = dynamic_cast<TensorProductPatch*>(patch);
if (edgeflag > 0 && !tpPatch)
throw ShadingException("missing preceding data in definition of tensor-product patch");
if ((edgeflag == 0 && points.size() != 16) || (edgeflag > 0 && points.size() != 12))
@@ -107,7 +107,7 @@ void TensorProductPatch::setPoints (const PointVec &points, int edgeflag, Shadin
* @param[in] edgeflag defines how to connect this patch with another one
* @param[in] patch reference patch required if edgeflag > 0 */
void TensorProductPatch::setColors(const ColorVec &colors, int edgeflag, ShadingPatch* patch) {
- TensorProductPatch *tpPatch = dynamic_cast<TensorProductPatch*>(patch);
+ auto tpPatch = dynamic_cast<TensorProductPatch*>(patch);
if (edgeflag > 0 && !tpPatch)
throw ShadingException("missing preceding data in definition of tensor-product patch");
if ((edgeflag == 0 && colors.size() != 4) || (edgeflag > 0 && colors.size() != 2))
@@ -201,16 +201,18 @@ Color TensorProductPatch::averageColor (const Color &c1, const Color &c2, const
}
-void TensorProductPatch::getBoundaryPath (GraphicsPath<double> &path) const {
+GraphicsPath<double> TensorProductPatch::getBoundaryPath () const {
// Simple approach: Use the outer curves as boundary path. This doesn't always lead
// to correct results since, depending on the control points, P(u,v) might exceed
// the simple boundary.
+ GraphicsPath<double> path;
path.moveto(_points[0][0]);
path.cubicto(_points[0][1], _points[0][2], _points[0][3]);
path.cubicto(_points[1][3], _points[2][3], _points[3][3]);
path.cubicto(_points[3][2], _points[3][1], _points[3][0]);
path.cubicto(_points[2][0], _points[1][0], _points[0][0]);
path.closepath();
+ return path;
}
@@ -354,8 +356,7 @@ void TensorProductPatch::approximateRow (double v1, double inc, bool overlap, do
void TensorProductPatch::approximate (int gridsize, bool overlap, double delta, Callback &callback) const {
if (_colors[0] == _colors[1] && _colors[1] == _colors[2] && _colors[2] == _colors[3]) {
// simple case: monochromatic patch
- GraphicsPath<double> path;
- getBoundaryPath(path);
+ GraphicsPath<double> path = getBoundaryPath();
callback.patchSegment(path, _colors[0]);
}
else {
@@ -377,17 +378,16 @@ void TensorProductPatch::approximate (int gridsize, bool overlap, double delta,
}
-void TensorProductPatch::getBBox (BoundingBox &bbox) const {
+BoundingBox TensorProductPatch::getBBox () const {
+ BoundingBox bbox;
Bezier bezier;
- BoundingBox bezierBox;
for (int i=0; i <= 1; i++) {
horizontalCurve(i, bezier);
- bezier.getBBox(bezierBox);
- bbox.embed(bezierBox);
+ bbox.embed(bezier.getBBox());
verticalCurve(i, bezier);
- bezier.getBBox(bezierBox);
- bbox.embed(bezierBox);
+ bbox.embed(bezier.getBBox());
}
+ return bbox;
}
@@ -492,7 +492,7 @@ DPair CoonsPatch::valueAt (double u, double v) const {
* @param[in] edgeflag defines how to connect this patch to another one
* @param[in] patch reference patch required if edgeflag > 0 */
void CoonsPatch::setPoints (const PointVec &points, int edgeflag, ShadingPatch *patch) {
- CoonsPatch *coonsPatch = dynamic_cast<CoonsPatch*>(patch);
+ auto coonsPatch = dynamic_cast<CoonsPatch*>(patch);
if (edgeflag > 0 && !coonsPatch)
throw ShadingException("missing preceding data in definition of relative Coons patch");
if ((edgeflag == 0 && points.size() != 12) || (edgeflag > 0 && points.size() != 8))
@@ -529,7 +529,7 @@ void CoonsPatch::setPoints (const PointVec &points, int edgeflag, ShadingPatch *
void CoonsPatch::setColors (const ColorVec &colors, int edgeflag, ShadingPatch *patch) {
- CoonsPatch *coonsPatch = dynamic_cast<CoonsPatch*>(patch);
+ auto coonsPatch = dynamic_cast<CoonsPatch*>(patch);
if (edgeflag > 0 && !coonsPatch)
throw ShadingException("missing preceding data in definition of relative Coons patch");
if ((edgeflag == 0 && colors.size() != 4) || (edgeflag > 0 && colors.size() != 2))
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp
index ca5071d2eb4..711feefc2d8 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TensorProductPatch.hpp
@@ -36,13 +36,11 @@
* \f[P(u,v):=\sum_{i=0}^3\sum_{j=0}^3 p_{ij} B_i(u) B_j(v)\f]
* where \f$B_k(t)={3\choose k}(1-t)^k t^k\f$ and \f$u,v \in [0,1]\f$. The four colors assigned
* to the vertices are interpolated bilinearily over the unit square. */
-class TensorProductPatch : public ShadingPatch
-{
+class TensorProductPatch : public ShadingPatch {
friend class CoonsPatch;
-
public:
TensorProductPatch () : ShadingPatch(Color::ColorSpace::RGB) {}
- TensorProductPatch (Color::ColorSpace cspace) : ShadingPatch(cspace) {}
+ explicit TensorProductPatch (Color::ColorSpace cspace) : ShadingPatch(cspace) {}
TensorProductPatch (const PointVec &points, const ColorVec &colors, Color::ColorSpace cspace, int edgeflag, TensorProductPatch *patch);
int psShadingType() const override {return 7;}
void setPoints (const DPair points[4][4], int edgeflag, TensorProductPatch *patch);
@@ -53,12 +51,12 @@ class TensorProductPatch : public ShadingPatch
Color averageColor () const override;
void horizontalCurve (double v, Bezier &bezier) const;
void verticalCurve (double u, Bezier &bezier) const;
- void getBoundaryPath (GraphicsPath<double> &path) const override;
+ GraphicsPath<double> getBoundaryPath () const override;
void subpatch (double u1, double u2, double v1, double v2, TensorProductPatch &patch) const;
DPair blossomValue (double u1, double u2, double u3, double v1, double v2, double v3) const;
DPair blossomValue (double u[3], double v[3]) const {return blossomValue(u[0], u[1], u[2], v[0], v[1], v[2]);}
void approximate (int gridsize, bool overlap, double delta, Callback &callback) const override;
- void getBBox (BoundingBox &bbox) const override;
+ BoundingBox getBBox () const override;
int numPoints (int edgeflag) const override {return edgeflag == 0 ? 16 : 12;}
int numColors (int edgeflag) const override {return edgeflag == 0 ? 4 : 2;}
@@ -78,16 +76,15 @@ class TensorProductPatch : public ShadingPatch
* depend on the outer ones, i.e. they are computed automatically and can't be set by the user.
* Thus, a Coons patch is defined by 12 control points, 4 vertex colors and a corresponding
* color space. */
-class CoonsPatch : public TensorProductPatch
-{
+class CoonsPatch : public TensorProductPatch {
public:
- CoonsPatch () {}
- CoonsPatch (Color::ColorSpace cspace) : TensorProductPatch(cspace) {}
+ CoonsPatch () =default;
+ explicit CoonsPatch (Color::ColorSpace cspace) : TensorProductPatch(cspace) {}
CoonsPatch (const PointVec &points, const ColorVec &colors, Color::ColorSpace cspace, int edgeflag, CoonsPatch *patch);
int psShadingType() const override {return 6;}
- virtual void setPoints (const PointVec &points, int edgeflag, ShadingPatch *patch) override;
- virtual void setColors (const ColorVec &colors, int edgeflag, ShadingPatch *patch) override;
- virtual DPair valueAt (double u, double v) const override;
+ void setPoints (const PointVec &points, int edgeflag, ShadingPatch *patch) override;
+ void setColors (const ColorVec &colors, int edgeflag, ShadingPatch *patch) override;
+ DPair valueAt (double u, double v) const override;
int numPoints (int edgeflag) const override {return edgeflag == 0 ? 12 : 8;}
int numColors (int edgeflag) const override {return edgeflag == 0 ? 4 : 2;}
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp
index ae940d2d8ea..b97fa439afe 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TpicSpecialHandler.cpp
@@ -23,6 +23,7 @@
#include <sstream>
#include <string>
#include "Color.hpp"
+#include "EllipticalArc.hpp"
#include "InputBuffer.hpp"
#include "InputReader.hpp"
#include "GraphicsPath.hpp"
@@ -69,7 +70,7 @@ Color TpicSpecialHandler::fillColor (bool grayOnly) const {
* @param[in] penwidth pen with used to compute the stroke parameters
* @param[in] pencolor the drawing color
* @param[in] ddist dash/dot distance of line in PS point units (0:solid line, >0:dashed line, <0:dotted line) */
-static void add_stroke_attribs (XMLElementNode *elem, double penwidth, Color pencolor, double ddist) {
+static void add_stroke_attribs (XMLElement *elem, double penwidth, Color pencolor, double ddist) {
if (penwidth > 0) { // attributes actually required?
elem->addAttribute("stroke", pencolor.svgColorString());
elem->addAttribute("stroke-width", XMLString(penwidth));
@@ -81,9 +82,9 @@ static void add_stroke_attribs (XMLElementNode *elem, double penwidth, Color pen
}
-static unique_ptr<XMLElementNode> create_ellipse_element (double cx, double cy, double rx, double ry) {
+static unique_ptr<XMLElement> create_ellipse_element (double cx, double cy, double rx, double ry) {
bool is_circle = (rx == ry);
- auto elem = util::make_unique<XMLElementNode>(is_circle ? "circle" : "ellipse");
+ auto elem = util::make_unique<XMLElement>(is_circle ? "circle" : "ellipse");
elem->addAttribute("cx", XMLString(cx));
elem->addAttribute("cy", XMLString(cy));
if (is_circle)
@@ -100,8 +101,8 @@ static unique_ptr<XMLElementNode> create_ellipse_element (double cx, double cy,
* @param[in] ddist dash/dot distance of line in PS point units (0:solid line, >0:dashed line, <0:dotted line)
* @param[in] actions object providing the actions that can be performed by the SpecialHandler */
void TpicSpecialHandler::drawLines (double ddist, SpecialActions &actions) {
- if (!_points.empty() && (_penwidth > 0 || _grayLevel >= 0)) {
- unique_ptr<XMLElementNode> elem;
+ if (!_points.empty() && (_penwidth > 0 || _grayLevel >= 0) && !actions.outputLocked()) {
+ unique_ptr<XMLElement> elem;
if (_points.size() == 1) {
const DPair &p = _points.back();
elem = create_ellipse_element(p.x()+actions.getX(), p.y()+actions.getY(), _penwidth/2.0, _penwidth/2.0);
@@ -109,14 +110,14 @@ void TpicSpecialHandler::drawLines (double ddist, SpecialActions &actions) {
}
else {
if (_points.size() == 2 || (_grayLevel < 0 && _points.front() != _points.back())) {
- elem = util::make_unique<XMLElementNode>("polyline");
+ elem = util::make_unique<XMLElement>("polyline");
elem->addAttribute("fill", "none");
elem->addAttribute("stroke-linecap", "round");
}
else {
while (_points.front() == _points.back())
_points.pop_back();
- elem = util::make_unique<XMLElementNode>("polygon");
+ elem = util::make_unique<XMLElement>("polygon");
elem->addAttribute("fill", _grayLevel < 0 ? "none" : fillColor(false).svgColorString());
}
ostringstream oss;
@@ -131,7 +132,7 @@ void TpicSpecialHandler::drawLines (double ddist, SpecialActions &actions) {
elem->addAttribute("points", oss.str());
add_stroke_attribs(elem.get(), _penwidth, Color::BLACK, ddist);
}
- actions.appendToPage(std::move(elem));
+ actions.svgTree().appendToPage(std::move(elem));
}
reset();
}
@@ -146,7 +147,7 @@ void TpicSpecialHandler::drawLines (double ddist, SpecialActions &actions) {
* @param[in] ddist length of dashes and gaps
* @param[in] actions object providing the actions that can be performed by the SpecialHandler */
void TpicSpecialHandler::drawSplines (double ddist, SpecialActions &actions) {
- if (!_points.empty() && _penwidth > 0) {
+ if (!_points.empty() && _penwidth > 0 && !actions.outputLocked()) {
const size_t numPoints = _points.size();
if (numPoints < 3) {
_grayLevel = -1;
@@ -164,7 +165,7 @@ void TpicSpecialHandler::drawSplines (double ddist, SpecialActions &actions) {
const DPair p1 = p+_points[i];
const DPair p2 = p+_points[i+1];
mid = p1+(p2-p1)/2.0;
- path.conicto(p1, mid);
+ path.quadto(p1, mid);
actions.embed(mid);
actions.embed((p0+p1*6.0+p2)/8.0, _penwidth);
}
@@ -174,27 +175,19 @@ void TpicSpecialHandler::drawSplines (double ddist, SpecialActions &actions) {
path.lineto(p+_points[numPoints-1]);
actions.embed(p+_points[numPoints-1]);
}
- auto pathElem = util::make_unique<XMLElementNode>("path");
+ auto pathElem = util::make_unique<XMLElement>("path");
pathElem->addAttribute("fill", "none");
ostringstream oss;
path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS);
pathElem->addAttribute("d", oss.str());
add_stroke_attribs(pathElem.get(), _penwidth, _dviColor, ddist);
- actions.appendToPage(std::move(pathElem));
+ actions.svgTree().appendToPage(std::move(pathElem));
}
}
reset();
}
-static double normalized_angle (double rad) {
- rad = fmod(rad, math::TWO_PI);
- if (rad < 0)
- rad += math::TWO_PI;
- return rad;
-}
-
-
/** Draws an elliptical arc.
* @param[in] cx x-coordinate of arc center relative to current DVI position
* @param[in] cy y-coordinate of arc center relative to current DVI position
@@ -204,31 +197,25 @@ static double normalized_angle (double rad) {
* @param[in] angle2 ending angle (clockwise) relative to x-axis
* @param[in] actions object providing the actions that can be performed by the SpecialHandler */
void TpicSpecialHandler::drawArc (double cx, double cy, double rx, double ry, double angle1, double angle2, SpecialActions &actions) {
- if (_penwidth > 0 || _grayLevel >= 0) {
- angle1 = -angle1;
- angle2 = -angle2;
+ if ((_penwidth > 0 || _grayLevel >= 0) && !actions.outputLocked()) {
cx += actions.getX();
cy += actions.getY();
- unique_ptr<XMLElementNode> elem;
+ unique_ptr<XMLElement> elem;
bool closed=true;
if (abs(angle2-angle1) >= math::TWO_PI) // closed ellipse?
elem = create_ellipse_element(cx, cy, rx, ry);
else {
- angle1 = normalized_angle(angle1);
- angle2 = normalized_angle(angle2);
- double delta = normalized_angle(angle2-angle1);
- int large_arg = (delta < math::PI) ? 1 : 0;
- ostringstream oss;
- oss << 'M' << XMLString(cx+rx*cos(angle1)) << ' ' << XMLString(cy+ry*sin(-angle1))
- << 'A' << XMLString(rx) << ' ' << XMLString(ry)
- << " 0 " // no rotation of x-axis
- << large_arg << " 1 " // always draw arc clockwise (sweep flag == 1)
- << XMLString(cx+rx*cos(angle2)) << ' ' << XMLString(cy-ry*sin(angle2));
+ EllipticalArc arc(DPair(cx, cy), rx, ry, 0, -angle1, math::normalize_0_2pi(angle2-angle1));
+ GraphicsPath<double> path;
+ path.moveto(arc.startPoint());
+ path.arcto(rx, ry, 0, arc.largeArc(), arc.sweepPositive(), arc.endPoint());
if (_grayLevel >= 0)
- oss << 'Z';
+ path.closepath();
else
closed = false;
- elem = util::make_unique<XMLElementNode>("path");
+ elem = util::make_unique<XMLElement>("path");
+ ostringstream oss;
+ path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS);
elem->addAttribute("d", oss.str());
}
if (_penwidth > 0) {
@@ -238,7 +225,7 @@ void TpicSpecialHandler::drawArc (double cx, double cy, double rx, double ry, do
elem->addAttribute("stroke-linecap", "round");
}
elem->addAttribute("fill", _grayLevel < 0 ? "none" : fillColor(true).svgColorString());
- actions.appendToPage(std::move(elem));
+ actions.svgTree().appendToPage(std::move(elem));
double pw = _penwidth/2.0;
actions.embed(BoundingBox(cx-rx-pw, cy-ry-pw, cx+rx+pw, cy+ry+pw));
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp
index 4f9a4a1f58e..01efe2e8f0d 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.cpp
@@ -31,7 +31,7 @@ TriangularPatch::TriangularPatch (const PointVec &points, const ColorVec &colors
void TriangularPatch::setPoints (const PointVec &points, int edgeflag, ShadingPatch *patch) {
- TriangularPatch *triangularPatch = dynamic_cast<TriangularPatch*>(patch);
+ auto triangularPatch = dynamic_cast<TriangularPatch*>(patch);
if (edgeflag > 0 && !triangularPatch)
throw ShadingException("missing preceding data in definition of triangular patch");
if ((edgeflag == 0 && points.size() != 3) || (edgeflag > 0 && points.size() != 1))
@@ -62,7 +62,7 @@ void TriangularPatch::setPoints (const DPair &p1, const DPair &p2, const DPair &
void TriangularPatch::setColors (const ColorVec &colors, int edgeflag, ShadingPatch *patch) {
- TriangularPatch *triangularPatch = dynamic_cast<TriangularPatch*>(patch);
+ auto triangularPatch = dynamic_cast<TriangularPatch*>(patch);
if (edgeflag > 0 && !triangularPatch)
throw ShadingException("missing preceding data in definition of triangular patch");
if ((edgeflag == 0 && colors.size() != 3) || (edgeflag > 0 && colors.size() != 1))
@@ -161,8 +161,7 @@ static inline double snap (double x) {
* @param[in] callback object notified */
void TriangularPatch::approximate (int gridsize, bool overlap, double delta, Callback &callback) const {
if (_colors[0] == _colors[1] && _colors[1] == _colors[2]) {
- GraphicsPath<double> path;
- getBoundaryPath(path);
+ GraphicsPath<double> path = getBoundaryPath();
callback.patchSegment(path, _colors[0]);
}
else {
@@ -197,18 +196,21 @@ void TriangularPatch::approximate (int gridsize, bool overlap, double delta, Cal
}
-void TriangularPatch::getBoundaryPath(GraphicsPath<double> &path) const {
+GraphicsPath<double> TriangularPatch::getBoundaryPath () const {
+ GraphicsPath<double> path;
path.clear();
path.moveto(_points[0]);
path.lineto(_points[1]);
path.lineto(_points[2]);
path.closepath();
+ return path;
}
-void TriangularPatch::getBBox (BoundingBox &bbox) const {
- bbox.invalidate();
+BoundingBox TriangularPatch::getBBox () const {
+ BoundingBox bbox;
bbox.embed(_points[0]);
bbox.embed(_points[1]);
bbox.embed(_points[2]);
+ return bbox;
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp
index 3ad189aff88..d329e43fa1a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TriangularPatch.hpp
@@ -25,11 +25,10 @@
#include "Pair.hpp"
#include "ShadingPatch.hpp"
-class TriangularPatch : public ShadingPatch
-{
+class TriangularPatch : public ShadingPatch {
public:
TriangularPatch ();
- TriangularPatch (Color::ColorSpace cspace) : ShadingPatch(cspace) {}
+ explicit TriangularPatch (Color::ColorSpace cspace) : ShadingPatch(cspace) {}
TriangularPatch (const PointVec &points, const ColorVec &colors, Color::ColorSpace cspace, int edgeflag, TriangularPatch *patch);
int psShadingType() const override {return 4;}
DPair valueAt (double u, double v) const;
@@ -40,8 +39,8 @@ class TriangularPatch : public ShadingPatch
void setColors (const ColorVec &colors, int edgeflag, ShadingPatch *patch) override;
void setColors (const Color &c1, const Color &c2, const Color &c3);
void approximate (int gridsize, bool overlap, double delta, Callback &listener) const override;
- void getBBox (BoundingBox &bbox) const override;
- void getBoundaryPath(GraphicsPath<double> &path) const override;
+ BoundingBox getBBox () const override;
+ GraphicsPath<double> getBoundaryPath () const override;
int numPoints (int edgeflag) const override {return edgeflag == 0 ? 3 : 1;}
int numColors (int edgeflag) const override {return edgeflag == 0 ? 3 : 1;}
@@ -54,10 +53,9 @@ class TriangularPatch : public ShadingPatch
};
-class LatticeTriangularPatch : public TriangularPatch
-{
+class LatticeTriangularPatch : public TriangularPatch {
public:
- LatticeTriangularPatch (Color::ColorSpace cspace) : TriangularPatch(cspace) {}
+ explicit LatticeTriangularPatch (Color::ColorSpace cspace) : TriangularPatch(cspace) {}
int psShadingType() const override {return 5;}
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.cpp
index 2cbb77bac51..408a00eede2 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.cpp
@@ -127,7 +127,7 @@ void TrueTypeFont::writeWOFF (ostream &os) const {
void TrueTypeFont::writeWOFF (const string &fname) const {
- ofstream ofs(fname.c_str(), ios::binary);
+ ofstream ofs(fname, ios::binary);
writeWOFF(ofs);
}
@@ -136,10 +136,10 @@ void TrueTypeFont::writeWOFF (const string &fname) const {
* @param[out] os stream to write the WOFF2 data to
* @return true on success */
bool TrueTypeFont::writeWOFF2 (ostream &os) const {
- const uint8_t* input_data = reinterpret_cast<const uint8_t*>(_buffer.data());
+ auto input_data = reinterpret_cast<const uint8_t*>(_buffer.data());
size_t output_size = woff2::MaxWOFF2CompressedSize(input_data, _buffer.size());
string output(output_size, 0);
- uint8_t* output_data = reinterpret_cast<uint8_t*>(&output[0]);
+ auto output_data = reinterpret_cast<uint8_t*>(&output[0]);
woff2::WOFF2Params params;
if (woff2::ConvertTTFToWOFF2(input_data, _buffer.size(), output_data, &output_size, params)) {
output.resize(output_size);
@@ -151,7 +151,7 @@ bool TrueTypeFont::writeWOFF2 (ostream &os) const {
bool TrueTypeFont::writeWOFF2 (const string &fname) const {
- ofstream ofs(fname.c_str(), ios::binary);
+ ofstream ofs(fname, ios::binary);
return writeWOFF2(ofs);
}
@@ -167,9 +167,9 @@ string TrueTypeFont::TTFTableRecord::name () const {
uint32_t TrueTypeFont::TTFTableRecord::computeChecksum () const {
uint32_t sum=0;
- const uint32_t *startptr = reinterpret_cast<const uint32_t*>(data);
- const uint32_t *endptr = startptr + paddedSize()/sizeof(uint32_t);
+ auto startptr = reinterpret_cast<const uint32_t*>(data);
+ auto endptr = startptr + paddedSize()/sizeof(uint32_t);
while (startptr < endptr)
sum += *startptr++;
return sum;
-} \ No newline at end of file
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.hpp
index 67a90be3ffb..d2e5b6e98d4 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/TrueTypeFont.hpp
@@ -53,7 +53,7 @@ class TrueTypeFont {
public:
TrueTypeFont () : _version(0) {}
- TrueTypeFont (const std::string &fname) {read(fname);}
+ explicit TrueTypeFont (const std::string &fname) {read(fname);}
bool read (const std::string &fname);
void writeWOFF (std::ostream &os) const;
void writeWOFF (const std::string &fname) const;
@@ -68,7 +68,7 @@ class TrueTypeFont {
struct TrueTypeFontException : public MessageException {
- TrueTypeFontException (const std::string &msg) : MessageException(msg) {}
+ explicit TrueTypeFontException (const std::string &msg) : MessageException(msg) {}
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp
index ab17d48fa90..d4a18a7bb96 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/Unicode.cpp
@@ -92,21 +92,21 @@ string Unicode::utf8 (int32_t cp) {
string utf8;
if (cp >= 0) {
if (cp < 0x80)
- utf8 += cp;
+ utf8 += char(cp);
else if (cp < 0x800) {
- utf8 += 0xC0 + (cp >> 6);
- utf8 += 0x80 + (cp & 0x3F);
+ utf8 += char(0xC0 + (cp >> 6));
+ utf8 += char(0x80 + (cp & 0x3F));
}
else if (cp < 0x10000) {
- utf8 += 0xE0 + (cp >> 12);
- utf8 += 0x80 + ((cp >> 6) & 0x3F);
- utf8 += 0x80 + (cp & 0x3F);
+ utf8 += char(0xE0 + (cp >> 12));
+ utf8 += char(0x80 + ((cp >> 6) & 0x3F));
+ utf8 += char(0x80 + (cp & 0x3F));
}
else if (cp < 0x110000) {
- utf8 += 0xF0 + (cp >> 18);
- utf8 += 0x80 + ((cp >> 12) & 0x3F);
- utf8 += 0x80 + ((cp >> 6) & 0x3F);
- utf8 += 0x80 + (cp & 0x3F);
+ utf8 += char(0xF0 + (cp >> 18));
+ utf8 += char(0x80 + ((cp >> 12) & 0x3F));
+ utf8 += char(0x80 + ((cp >> 6) & 0x3F));
+ utf8 += char(0x80 + (cp & 0x3F));
}
// UTF-8 does not support codepoints >= 0x110000
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp
index df150d0a511..cff67c919c1 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.cpp
@@ -28,12 +28,8 @@
using namespace std;
-VFReader::VFReader (istream &is)
- : StreamReader(is), _actions(0), _designSize(0) {
-}
-
-
-VFReader::~VFReader () {
+VFReader::VFReader (istream &is) : StreamReader(is)
+{
}
@@ -57,7 +53,7 @@ int VFReader::executeCommand (ApproveAction approve) {
bool approved = !approve || approve(opcode);
VFActions *actions = _actions;
if (!approved)
- replaceActions(0); // disable actions
+ replaceActions(nullptr); // disable actions
if (opcode <= 241) // short character definition?
cmdShortChar(opcode);
@@ -70,9 +66,7 @@ int VFReader::executeCommand (ApproveAction approve) {
case 248: cmdPost(); break; // postamble
default : { // invalid opcode
replaceActions(actions); // reenable actions
- ostringstream oss;
- oss << "undefined VF command (opcode " << opcode << ')';
- throw VFException(oss.str());
+ throw VFException("undefined VF command (opcode " + std::to_string(opcode) + ")");
}
}
}
@@ -143,8 +137,7 @@ void VFReader::cmdLongChar () {
else {
uint32_t cc = readUnsigned(4); // character code
readUnsigned(4); // equals character width from corresponding TFM file
- vector<uint8_t> dvi(pl); // DVI subroutine
- readBytes(pl, dvi);
+ auto dvi = readBytes(pl); // DVI subroutine
_actions->defineVFChar(cc, std::move(dvi)); // call template method for user actions
}
}
@@ -158,8 +151,7 @@ void VFReader::cmdShortChar (int pl) {
else {
uint32_t cc = readUnsigned(1); // character code
readUnsigned(3); // character width from corresponding TFM file
- vector<uint8_t> dvi(pl); // DVI subroutine
- readBytes(pl, dvi);
+ auto dvi = readBytes(pl); // DVI subroutine
_actions->defineVFChar(cc, std::move(dvi)); // call template method for user actions
}
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp
index 00da32bbfdc..8ddba805e8f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VFReader.hpp
@@ -25,28 +25,23 @@
#include "StreamReader.hpp"
-struct VFException : public MessageException
-{
- VFException (const std::string &msg) : MessageException(msg) {}
+struct VFException : public MessageException {
+ explicit VFException (const std::string &msg) : MessageException(msg) {}
};
-
struct VFActions;
-
-class VFReader : public StreamReader
-{
+class VFReader : public StreamReader{
using ApproveAction = bool (*)(int);
public:
- VFReader (std::istream &is);
- virtual ~VFReader ();
+ explicit VFReader (std::istream &is);
VFActions* replaceActions (VFActions *a);
bool executeAll ();
bool executePreambleAndFontDefs ();
bool executeCharDefs ();
protected:
- int executeCommand (ApproveAction approve=0);
+ int executeCommand (ApproveAction approve=nullptr);
// the following methods represent the VF commands
// they are called by executeCommand and should not be used directly
@@ -57,8 +52,8 @@ class VFReader : public StreamReader
void cmdFontDef (int len);
private:
- VFActions *_actions; ///< actions to execute when reading a VF command
- double _designSize; ///< design size of currently read VF in PS points
+ VFActions *_actions=nullptr; ///< actions to execute when reading a VF command
+ double _designSize=0; ///< design size of currently read VF in PS points
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp
index d5615eafb35..17707fbc965 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorIterator.hpp
@@ -25,17 +25,15 @@
#include "MessageException.hpp"
-struct IteratorException : public MessageException
-{
- IteratorException (const std::string &msg) : MessageException(msg) {}
+struct IteratorException : public MessageException {
+ explicit IteratorException (const std::string &msg) : MessageException(msg) {}
};
template <typename T>
-class VectorIterator
-{
+class VectorIterator {
public:
- VectorIterator (std::vector<T> &vec) : _vector(vec), _pos(0) {}
+ explicit VectorIterator (std::vector<T> &vec) : _vector(vec), _pos(0) {}
VectorIterator operator ++ () {
_pos++;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp
index ddf9aa5985a..c74388e076b 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/VectorStream.hpp
@@ -25,10 +25,9 @@
#include <vector>
template <typename T>
-class VectorStreamBuffer : public std::streambuf
-{
+class VectorStreamBuffer : public std::streambuf {
public:
- VectorStreamBuffer (const std::vector<T> &v) {
+ explicit VectorStreamBuffer (const std::vector<T> &v) {
if (v.empty())
_begin = _end = _curr = nullptr;
else {
@@ -76,10 +75,9 @@ class VectorStreamBuffer : public std::streambuf
template <typename T>
-class VectorInputStream : public std::istream
-{
+class VectorInputStream : public std::istream {
public:
- VectorInputStream (const std::vector<T> &source) : std::istream(&_buf), _buf(source) {}
+ explicit VectorInputStream (const std::vector<T> &source) : std::istream(&_buf), _buf(source) {}
private:
VectorStreamBuffer<T> _buf;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp
index 66ef7e612c9..be14eaf6786 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.cpp
@@ -22,7 +22,7 @@
using namespace std;
-XMLDocument::XMLDocument (unique_ptr<XMLElementNode> &&root)
+XMLDocument::XMLDocument (unique_ptr<XMLElement> root)
: _rootElement(std::move(root))
{
}
@@ -34,17 +34,17 @@ void XMLDocument::clear () {
}
-void XMLDocument::append (unique_ptr<XMLNode> &&node) {
+void XMLDocument::append (unique_ptr<XMLNode> node) {
if (node) {
- if (dynamic_cast<XMLElementNode*>(node.get()))
- _rootElement = util::static_unique_ptr_cast<XMLElementNode>(std::move(node));
+ if (node->toElement())
+ _rootElement = util::static_unique_ptr_cast<XMLElement>(std::move(node));
else
_nodes.emplace_back(std::move(node));
}
}
-void XMLDocument::setRootNode (unique_ptr<XMLElementNode> &&root) {
+void XMLDocument::setRootNode (unique_ptr<XMLElement> root) {
_rootElement = std::move(root);
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp
index 0e5dc6a6ee3..e9132c44d8f 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLDocument.hpp
@@ -28,17 +28,17 @@
class XMLDocument {
public:
XMLDocument () =default;
- XMLDocument (std::unique_ptr<XMLElementNode> &&root);
+ explicit XMLDocument(std::unique_ptr<XMLElement> root);
void clear ();
- void append (std::unique_ptr<XMLElementNode> &&node);
- void append (std::unique_ptr<XMLNode> &&node);
- void setRootNode (std::unique_ptr<XMLElementNode> &&root);
- const XMLElementNode* getRootElement () const {return _rootElement.get();}
+ void append (std::unique_ptr<XMLElement> node);
+ void append (std::unique_ptr<XMLNode> node);
+ void setRootNode (std::unique_ptr<XMLElement> root);
+ const XMLElement* getRootElement () const {return _rootElement.get();}
std::ostream& write (std::ostream &os) const;
private:
std::vector<std::unique_ptr<XMLNode>> _nodes;
- std::unique_ptr<XMLElementNode> _rootElement;
+ std::unique_ptr<XMLElement> _rootElement;
};
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp
index e0598c4956a..128be5b9e51 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.cpp
@@ -28,32 +28,71 @@
using namespace std;
+bool XMLElement::WRITE_NEWLINES=true;
-XMLElementNode::XMLElementNode (const string &n) : _name(n) {
+
+/** Inserts a sibling node after this one.
+ * @param[in] node node to insert
+ * @return raw pointer to inserted node */
+XMLNode* XMLNode::insertNext (unique_ptr<XMLNode> node) {
+ if (_next) {
+ _next->_prev = node.get();
+ node->_next = std::move(_next);
+ }
+ node->_prev = this;
+ node->_parent = _parent;
+ _next = std::move(node);
+ return _next.get();
}
-XMLElementNode::XMLElementNode (const XMLElementNode &node)
- : _name(node._name), _attributes(node._attributes)
+/** Removes the following sibling node of this one.
+ * @return pointer to the removed node */
+unique_ptr<XMLNode> XMLNode::removeNext () {
+ unique_ptr<XMLNode> oldnext = std::move(_next);
+ if (oldnext) {
+ oldnext->_parent = oldnext->_prev = nullptr;
+ if ((_next = std::move(oldnext->_next))) {
+ _next->_prev = this;
+ oldnext->_next.reset();
+ }
+ }
+ return oldnext;
+}
+
+/////////////////////////////////////////////////////////////////////
+
+XMLElement::XMLElement (string name) : _name(std::move(name)) {
+}
+
+
+XMLElement::XMLElement (const XMLElement &node)
+ : XMLNode(node), _name(node._name), _attributes(node._attributes)
{
- for (const auto &child : node._children)
- _children.emplace_back(unique_ptr<XMLNode>(child->clone()));
+ for (XMLNode *child=_firstChild.get(); child; child = child->next())
+ insertLast(child->clone());
}
-XMLElementNode::XMLElementNode (XMLElementNode &&node)
- : _name(std::move(node._name)), _attributes(std::move(node._attributes)), _children(std::move(node._children))
+XMLElement::XMLElement (XMLElement &&node) noexcept
+ : XMLNode(std::move(node)),
+ _name(std::move(node._name)),
+ _attributes(std::move(node._attributes)),
+ _firstChild(std::move(node._firstChild)),
+ _lastChild(node._lastChild)
{
}
-void XMLElementNode::clear () {
+/** Removes all attributes and children. */
+void XMLElement::clear () {
_attributes.clear();
- _children.clear();
+ _firstChild.reset();
+ _lastChild = nullptr;
}
-void XMLElementNode::addAttribute (const string &name, const string &value) {
+void XMLElement::addAttribute (const string &name, const string &value) {
if (Attribute *attr = getAttribute(name))
attr->value = value;
else
@@ -61,27 +100,66 @@ void XMLElementNode::addAttribute (const string &name, const string &value) {
}
-void XMLElementNode::addAttribute (const string &name, double value) {
+void XMLElement::addAttribute (const string &name, double value) {
addAttribute(name, XMLString(value));
}
+void XMLElement::removeAttribute (const std::string &name) {
+ _attributes.erase(find_if(_attributes.begin(), _attributes.end(), [&](const Attribute &attr) {
+ return attr.name == name;
+ }));
+}
+
+
+/** Inserts a new last child node and returns a raw pointer to it. */
+XMLNode* XMLElement::insertLast (unique_ptr<XMLNode> child) {
+ if (!child)
+ return nullptr;
+ child->parent(this);
+ if (!empty())
+ _lastChild = _lastChild->insertNext(std::move(child));
+ else {
+ _firstChild = std::move(child);
+ _lastChild = _firstChild.get();
+ }
+ return _lastChild;
+}
+
+
+/** Inserts a new first child node and returns a raw pointer to it. */
+XMLNode* XMLElement::insertFirst (unique_ptr<XMLNode> child) {
+ if (!child)
+ return nullptr;
+ child->parent(this);
+ if (empty()) {
+ _firstChild = std::move(child);
+ _lastChild = _firstChild.get();
+ }
+ else {
+ child->insertNext(std::move(_firstChild));
+ _firstChild = std::move(child);
+ }
+ return _firstChild.get();
+}
+
+
/** Appends a child node to this element. The element also takes the ownership of the child.
* @param[in] child node to be appended
* @return raw pointer to the appended child node */
-XMLNode* XMLElementNode::append (unique_ptr<XMLNode> &&child) {
+XMLNode* XMLElement::append (unique_ptr<XMLNode> child) {
if (!child)
return nullptr;
- XMLTextNode *textNode1 = dynamic_cast<XMLTextNode*>(child.get());
- if (!textNode1 || _children.empty())
- _children.emplace_back(std::move(child));
+ XMLText *textNode1 = child->toText();
+ if (!textNode1 || empty())
+ insertLast(std::move(child));
else {
- if (XMLTextNode *textNode2 = dynamic_cast<XMLTextNode*>(_children.back().get()))
- textNode2->append(util::static_unique_ptr_cast<XMLTextNode>(std::move(child))); // merge two consecutive text nodes
+ if (XMLText *textNode2 = _lastChild->toText())
+ textNode2->append(util::static_unique_ptr_cast<XMLText>(std::move(child))); // merge two consecutive text nodes
else
- _children.emplace_back(std::move(child));
+ insertLast(std::move(child));
}
- return _children.back().get();
+ return _lastChild;
}
@@ -89,30 +167,31 @@ XMLNode* XMLElementNode::append (unique_ptr<XMLNode> &&child) {
* appended there, otherwise a new text node is created.
* @param[in] str string to be appended
* @return raw pointer to the text node the string was appended to */
-XMLNode* XMLElementNode::append (const string &str) {
- if (_children.empty() || !dynamic_cast<XMLTextNode*>(_children.back().get()))
- _children.emplace_back(util::make_unique<XMLTextNode>(str));
+XMLNode* XMLElement::append (const string &str) {
+ XMLText *last;
+ if (!empty() && (last = _lastChild->toText()))
+ last->append(str);
else
- static_cast<XMLTextNode*>(_children.back().get())->append(str);
- return _children.back().get();
+ insertLast(util::make_unique<XMLText>(str));
+ return _lastChild;
}
/** Prepends a child node to this element. The element also takes the ownership of the child.
* @param[in] child node to be prepended
* @return raw pointer to the prepended child node */
-XMLNode* XMLElementNode::prepend (unique_ptr<XMLNode> &&child) {
+XMLNode* XMLElement::prepend (unique_ptr<XMLNode> child) {
if (!child)
return nullptr;
- XMLTextNode *textNode1 = dynamic_cast<XMLTextNode*>(child.get());
- if (textNode1 && !_children.empty()) {
- if (XMLTextNode *textNode2 = dynamic_cast<XMLTextNode*>(_children.front().get())) {
- textNode2->prepend(util::static_unique_ptr_cast<XMLTextNode>(std::move(child))); // merge two consecutive text nodes
+ XMLText *textNode1 = child->toText();
+ if (textNode1 && !empty()) {
+ if (XMLText *textNode2 = _firstChild->toText()) {
+ textNode2->prepend(util::static_unique_ptr_cast<XMLText>(std::move(child))); // merge two consecutive text nodes
return textNode2;
}
}
- _children.emplace_front(std::move(child));
- return _children.front().get();
+ insertFirst(std::move(child));
+ return _firstChild.get();
}
@@ -121,15 +200,15 @@ XMLNode* XMLElementNode::prepend (unique_ptr<XMLNode> &&child) {
* node present, nothing is inserted.
* @param[in] child node to be inserted
* @param[in] sibling following sibling of 'child'
- * @return true on success */
-bool XMLElementNode::insertBefore (unique_ptr<XMLNode> &&child, XMLNode *sibling) {
- auto it = _children.begin();
- while (it != _children.end() && it->get() != sibling)
- ++it;
- if (it == _children.end())
- return false;
- _children.emplace(it, std::move(child));
- return true;
+ * @return raw pointer to inserted node */
+XMLNode* XMLElement::insertBefore (unique_ptr<XMLNode> child, XMLNode *sibling) {
+ if (!child || (sibling && sibling->parent() != this))
+ return nullptr;
+ if (!sibling)
+ return insertLast(std::move(child));
+ if (sibling == _firstChild.get())
+ return insertFirst(std::move(child));
+ return sibling->prev()->insertNext(std::move(child));
}
@@ -138,25 +217,93 @@ bool XMLElementNode::insertBefore (unique_ptr<XMLNode> &&child, XMLNode *sibling
* node present, nothing is inserted.
* @param[in] child node to be inserted
* @param[in] sibling preceding sibling of 'child'
- * @return true on success */
-bool XMLElementNode::insertAfter (unique_ptr<XMLNode> &&child, XMLNode *sibling) {
- auto it = _children.begin();
- while (it != _children.end() && it->get() != sibling)
- ++it;
- if (it == _children.end())
- return false;
- _children.emplace(++it, std::move(child));
- return true;
-}
-
-
-/** Removes a given child from the element. */
-void XMLElementNode::remove (const XMLNode *child) {
- auto it = find_if(_children.begin(), _children.end(), [=](const unique_ptr<XMLNode> &ptr) {
- return ptr.get() == child;
- });
- if (it != _children.end())
- _children.erase(it);
+ * @return raw pointer to inserted node */
+XMLNode* XMLElement::insertAfter (unique_ptr<XMLNode> child, XMLNode *sibling) {
+ if (!child || (sibling && sibling->parent() != this))
+ return nullptr;
+ if (!sibling)
+ return insertFirst(std::move(child));
+ if (sibling == _lastChild)
+ return insertLast(std::move(child));
+ return sibling->insertNext(std::move(child));
+}
+
+
+/** Moves a sequence of child nodes to a new element of a given name and inserts
+ * this (wrapper) element at the former position of the first node of the sequence.
+ * Example: wrap 3 child nodes of element a with b:
+ * <a>text1<c/>text2<d/></a> => <a>text1<b><c/>text2<d/></b></a>
+ * @param[in] first first node to wrap
+ * @param[in] last last node to wrap (or nullptr if all following siblings of 'first' are to be wrapped)
+ * @param[in] name name of the wrapper element to be created
+ * @return raw pointer to the new wrapper element */
+XMLElement* XMLElement::wrap (XMLNode *first, XMLNode *last, const string &name) {
+ if (!first || !first->parent() || (last && first->parent() != last->parent()))
+ return nullptr;
+ XMLElement *parent = first->parent()->toElement();
+ XMLNode *prev = first->prev();
+ auto wrapper = util::make_unique<XMLElement>(name);
+ if (last)
+ last = last->next();
+ XMLNode *child = first;
+ while (child && child != last) {
+ XMLNode *next = child->next();
+ wrapper->insertLast(remove(child));
+ child = next;
+ }
+ XMLElement *ret = wrapper.get();
+ if (prev)
+ parent->insertAfter(std::move(wrapper), prev);
+ else
+ parent->insertFirst(std::move(wrapper));
+ return ret;
+}
+
+
+/** Moves all child nodes C1,...,Cn of a given element E to its parent and
+ * removes E afterwards, so that C1 is located at the former position of E
+ * followed by C2,...,Cn.
+ * Example: unwrap a child element b of a:
+ * <a>text1<b><c/>text2<d/></b></a> => <a>text1<c/>text2<d/></a>
+ * @param[in] child child element to unwrap
+ * @return raw pointer to the first node C1 of the unwrapped sequence */
+XMLNode* XMLElement::unwrap (XMLElement *child) {
+ if (!child || !child->parent())
+ return nullptr;
+ XMLElement *parent = child->parent()->toElement();
+ auto removedChild = remove(child);
+ if (child->empty())
+ return child->next();
+ XMLNode *firstGrandchild = child->firstChild();
+ XMLNode *prev = child->prev();
+ unique_ptr<XMLNode> grandchild = std::move(child->_firstChild);
+ while (grandchild) {
+ prev = parent->insertAfter(std::move(grandchild), prev);
+ grandchild = std::move(prev->_next);
+ }
+ return firstGrandchild;
+}
+
+
+/** Removes a child node from the element.
+ * @param[in] child pointer to child to remove
+ * @return pointer to removed child or nullptr if given child doesn't belong to this element */
+unique_ptr<XMLNode> XMLElement::remove (XMLNode *child) {
+ unique_ptr<XMLNode> node;
+ if (child && child->parent()) {
+ XMLElement *parent = child->parent()->toElement();
+ if (child == parent->_lastChild)
+ parent->_lastChild = child->prev();
+ if (child != parent->firstChild())
+ node = child->prev()->removeNext();
+ else {
+ node = std::move(parent->_firstChild);
+ if ((parent->_firstChild = std::move(node->_next)))
+ parent->_firstChild->prev(nullptr);
+ }
+ child->parent(nullptr);
+ }
+ return node;
}
@@ -165,10 +312,10 @@ void XMLElementNode::remove (const XMLNode *child) {
* @param[in] attrName name of attribute to find
* @param[out] descendants all elements found
* @return true if at least one element was found */
-bool XMLElementNode::getDescendants (const char *name, const char *attrName, vector<XMLElementNode*> &descendants) const {
- for (auto &child : _children) {
- if (XMLElementNode *elem = dynamic_cast<XMLElementNode*>(child.get())) {
- if ((!name || elem->getName() == name) && (!attrName || elem->hasAttribute(attrName)))
+bool XMLElement::getDescendants (const char *name, const char *attrName, vector<XMLElement*> &descendants) const {
+ for (XMLNode *child = _firstChild.get(); child; child = child->next()) {
+ if (XMLElement *elem = child->toElement()) {
+ if ((!name || elem->name() == name) && (!attrName || elem->hasAttribute(attrName)))
descendants.push_back(elem);
elem->getDescendants(name, attrName, descendants);
}
@@ -182,15 +329,15 @@ bool XMLElementNode::getDescendants (const char *name, const char *attrName, vec
* @param[in] attrName if not 0, only elements with an attribute of this name are considered
* @param[in] attrValue if not 0, only elements with attribute attrName="attrValue" are considered
* @return pointer to the found element or 0 */
-XMLElementNode* XMLElementNode::getFirstDescendant (const char *name, const char *attrName, const char *attrValue) const {
- for (auto &child : _children) {
- if (XMLElementNode *elem = dynamic_cast<XMLElementNode*>(child.get())) {
- if (!name || elem->getName() == name) {
+XMLElement* XMLElement::getFirstDescendant (const char *name, const char *attrName, const char *attrValue) const {
+ for (XMLNode *child = _firstChild.get(); child; child = child->next()) {
+ if (XMLElement *elem = child->toElement()) {
+ if (!name || elem->name() == name) {
const char *value;
- if (!attrName || (((value = elem->getAttributeValue(attrName)) != 0) && (!attrValue || string(value) == attrValue)))
+ if (!attrName || (((value = elem->getAttributeValue(attrName)) != nullptr) && (!attrValue || string(value) == attrValue)))
return elem;
}
- if (XMLElementNode *descendant = elem->getFirstDescendant(name, attrName, attrValue))
+ if (XMLElement *descendant = elem->getFirstDescendant(name, attrName, attrValue))
return descendant;
}
}
@@ -198,23 +345,22 @@ XMLElementNode* XMLElementNode::getFirstDescendant (const char *name, const char
}
-ostream& XMLElementNode::write (ostream &os) const {
+ostream& XMLElement::write (ostream &os) const {
os << '<' << _name;
for (const auto &attrib : _attributes)
os << ' ' << attrib.name << "='" << attrib.value << '\'';
- if (_children.empty())
+ if (empty())
os << "/>";
else {
os << '>';
// Insert newlines around children except text nodes. According to the
// SVG specification, pure whitespace nodes are ignored by the SVG renderer.
- if (!dynamic_cast<XMLTextNode*>(_children.front().get()))
+ if (WRITE_NEWLINES && !_firstChild->toText())
os << '\n';
- for (auto it=_children.begin(); it != _children.end(); ++it) {
- (*it)->write(os);
- if (!dynamic_cast<XMLTextNode*>(it->get())) {
- auto next=it;
- if (++next == _children.end() || !dynamic_cast<XMLTextNode*>(next->get()))
+ for (XMLNode *child = _firstChild.get(); child; child = child->next()) {
+ child->write(os);
+ if (!child->toText()) {
+ if (WRITE_NEWLINES && (!child->next() || !child->next()->toText()))
os << '\n';
}
}
@@ -225,7 +371,7 @@ ostream& XMLElementNode::write (ostream &os) const {
/** Returns true if this element has an attribute of given name. */
-bool XMLElementNode::hasAttribute (const string &name) const {
+bool XMLElement::hasAttribute (const string &name) const {
return getAttribute(name) != nullptr;
}
@@ -233,14 +379,14 @@ bool XMLElementNode::hasAttribute (const string &name) const {
/** Returns the value of an attribute.
* @param[in] name name of attribute
* @return attribute value or 0 if attribute doesn't exist */
-const char* XMLElementNode::getAttributeValue (const std::string& name) const {
+const char* XMLElement::getAttributeValue (const std::string& name) const {
if (const Attribute *attr = getAttribute(name))
return attr->value.c_str();
return nullptr;
}
-XMLElementNode::Attribute* XMLElementNode::getAttribute (const string &name) {
+XMLElement::Attribute* XMLElement::getAttribute (const string &name) {
auto it = find_if(_attributes.begin(), _attributes.end(), [&](const Attribute &attr) {
return attr.name == name;
});
@@ -248,7 +394,7 @@ XMLElementNode::Attribute* XMLElementNode::getAttribute (const string &name) {
}
-const XMLElementNode::Attribute* XMLElementNode::getAttribute (const string &name) const {
+const XMLElement::Attribute* XMLElement::getAttribute (const string &name) const {
auto it = find_if(_attributes.begin(), _attributes.end(), [&](const Attribute &attr) {
return attr.name == name;
});
@@ -258,11 +404,11 @@ const XMLElementNode::Attribute* XMLElementNode::getAttribute (const string &nam
//////////////////////
-void XMLTextNode::append (unique_ptr<XMLNode> &&node) {
+void XMLText::append (unique_ptr<XMLNode> node) {
if (!node)
return;
- if (dynamic_cast<XMLTextNode*>(node.get()))
- append(util::static_unique_ptr_cast<XMLTextNode>(std::move(node)));
+ if (node->toText())
+ append(util::static_unique_ptr_cast<XMLText>(std::move(node)));
else {
// append text representation of the node
ostringstream oss;
@@ -272,32 +418,37 @@ void XMLTextNode::append (unique_ptr<XMLNode> &&node) {
}
-void XMLTextNode::append (unique_ptr<XMLTextNode> &&node) {
+void XMLText::append (unique_ptr<XMLText> node) {
if (node)
_text += node->_text;
}
-void XMLTextNode::append (const string &str) {
+void XMLText::append (const string &str) {
_text += str;
}
-void XMLTextNode::prepend (unique_ptr<XMLNode> &&node) {
- if (XMLTextNode *textNode = dynamic_cast<XMLTextNode*>(node.get()))
+void XMLText::prepend (unique_ptr<XMLNode> node) {
+ if (XMLText *textNode = node->toText())
_text = textNode->_text + _text;
}
+
+const XMLText* XMLText::toWSNode () const {
+ return _text.find_first_not_of(" \t\n\r") == string::npos ? this : nullptr;
+}
+
/////////////////////////////////////////////////////////////////////
-ostream& XMLCDataNode::write (ostream &os) const {
+ostream& XMLCData::write (ostream &os) const {
if (!_data.empty())
- os << "<![CDATA[\n" << _data << "]]>";
+ os << "<![CDATA[" << _data << "]]>";
return os;
}
-void XMLCDataNode::append (string &&str) {
+void XMLCData::append (string &&str) {
if (_data.empty())
_data = move(str);
else
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp
index b9a75fa0588..b4e5ed6f2b4 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLNode.hpp
@@ -29,107 +29,198 @@
#include <vector>
#include "utility.hpp"
+class XMLCData;
+class XMLComment;
+class XMLElement;
+class XMLText;
class XMLNode {
+ friend class XMLElement;
+
+ template <typename T>
+ T* cast (const T* (XMLNode::*func)() const) {
+ return const_cast<T*>((const_cast<const XMLNode*>(this)->*func)());
+ }
+
public:
+ XMLNode () =default;
+ XMLNode (const XMLNode &node) : _next(nullptr) {}
+ XMLNode (XMLNode &&node) noexcept : _parent(node._parent), _prev(node._prev), _next(std::move(node._next)) {}
virtual ~XMLNode () =default;
virtual std::unique_ptr<XMLNode> clone () const =0;
virtual void clear () =0;
virtual std::ostream& write (std::ostream &os) const =0;
+ virtual const XMLElement* toElement () const {return nullptr;}
+ virtual const XMLText* toText () const {return nullptr;}
+ virtual const XMLText* toWSNode () const {return nullptr;}
+ virtual const XMLComment* toComment () const {return nullptr;}
+ virtual const XMLCData* toCData () const {return nullptr;}
+ XMLElement* toElement () {return cast<XMLElement>(&XMLNode::toElement);}
+ XMLText* toText () {return cast<XMLText>(&XMLNode::toText);}
+ XMLComment* toComment () {return cast<XMLComment>(&XMLNode::toComment);}
+ XMLCData* toCData () {return cast<XMLCData>(&XMLNode::toCData);}
+ XMLNode* parent () const {return _parent;}
+ XMLNode* prev () const {return _prev;}
+ XMLNode* next () const {return _next.get();}
+
+ protected:
+ XMLNode* insertNext (std::unique_ptr<XMLNode> node);
+ std::unique_ptr<XMLNode> removeNext ();
+ void parent (XMLNode *p) {_parent = p;}
+ void prev (XMLNode *p) {_prev = p;}
+
+ private:
+ XMLNode *_parent=nullptr; ///< pointer to parent node
+ XMLNode *_prev=nullptr; ///< pointer to preceding sibling
+ std::unique_ptr<XMLNode> _next; ///< pointer to next sibling (incl. ownership)
+};
+
+
+class XMLNodeIterator {
+ public:
+ XMLNodeIterator () =default;
+ explicit XMLNodeIterator (XMLNode *curr) : _curr(curr) {}
+ XMLNodeIterator& operator ++ () {_curr = _curr->next(); return *this;}
+ XMLNodeIterator& operator -- () {_curr = _curr->prev(); return *this;}
+ XMLNodeIterator operator ++ (int) {auto p=_curr; _curr = _curr->next(); return XMLNodeIterator(p);}
+ XMLNodeIterator operator -- (int) {auto p=_curr; _curr = _curr->prev(); return XMLNodeIterator(p);}
+ XMLNode* operator * () {return _curr;}
+ XMLNode& operator -> () {return *_curr;}
+ bool operator == (const XMLNodeIterator &it) const {return _curr == it._curr;}
+ bool operator != (const XMLNodeIterator &it) const {return _curr != it._curr;}
+
+ private:
+ XMLNode *_curr=nullptr;
};
-class XMLElementNode : public XMLNode {
+class ConstXMLNodeIterator {
+ public:
+ ConstXMLNodeIterator () =default;
+ explicit ConstXMLNodeIterator (const XMLNode *curr) : _curr(curr) {}
+ ConstXMLNodeIterator& operator ++ () {_curr = _curr->next(); return *this;}
+ ConstXMLNodeIterator& operator -- () {_curr = _curr->prev(); return *this;}
+ ConstXMLNodeIterator operator ++ (int) {auto p=_curr; _curr = _curr->next(); return ConstXMLNodeIterator(p);}
+ ConstXMLNodeIterator operator -- (int) {auto p=_curr; _curr = _curr->prev(); return ConstXMLNodeIterator(p);}
+ const XMLNode* operator * () {return _curr;}
+ const XMLNode& operator -> () {return *_curr;}
+ bool operator == (const ConstXMLNodeIterator &it) const {return _curr == it._curr;}
+ bool operator != (const ConstXMLNodeIterator &it) const {return _curr != it._curr;}
+
+ private:
+ const XMLNode *_curr=nullptr;
+};
+
+
+class XMLElement : public XMLNode {
public:
struct Attribute {
- Attribute (const std::string &nam, const std::string &val) : name(nam), value(val) {}
+ Attribute (std::string nam, std::string val) : name(std::move(nam)), value(std::move(val)) {}
std::string name;
std::string value;
};
- using ChildList = std::deque<std::unique_ptr<XMLNode>>;
+ using Attributes = std::vector<Attribute>;
+ static bool WRITE_NEWLINES; ///< insert line breaks after element tags?
public:
- XMLElementNode (const std::string &name);
- XMLElementNode (const XMLElementNode &node);
- XMLElementNode (XMLElementNode &&node);
- std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLElementNode>(*this);}
+ explicit XMLElement (std::string name);
+ XMLElement (const XMLElement &node);
+ XMLElement (XMLElement &&node) noexcept;
+ std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLElement>(*this);}
void clear () override;
void addAttribute (const std::string &name, const std::string &value);
void addAttribute (const std::string &name, double value);
- XMLNode* append (std::unique_ptr<XMLNode> &&child);
+ void removeAttribute (const std::string &name);
+ XMLNode* append (std::unique_ptr<XMLNode> child);
XMLNode* append (const std::string &str);
- XMLNode* prepend (std::unique_ptr<XMLNode> &&child);
- void remove (const XMLNode *child);
- bool insertAfter (std::unique_ptr<XMLNode> &&child, XMLNode *sibling);
- bool insertBefore (std::unique_ptr<XMLNode> &&child, XMLNode *sibling);
+ XMLNode* prepend (std::unique_ptr<XMLNode> child);
+ XMLNode* insertAfter (std::unique_ptr<XMLNode> child, XMLNode *sibling);
+ XMLNode* insertBefore (std::unique_ptr<XMLNode> child, XMLNode *sibling);
bool hasAttribute (const std::string &name) const;
const char* getAttributeValue (const std::string &name) const;
- bool getDescendants (const char *name, const char *attrName, std::vector<XMLElementNode*> &descendants) const;
- XMLElementNode* getFirstDescendant (const char *name, const char *attrName, const char *attrValue) const;
+ bool getDescendants (const char *name, const char *attrName, std::vector<XMLElement*> &descendants) const;
+ XMLElement* getFirstDescendant (const char *name, const char *attrName, const char *attrValue) const;
+ XMLNode* firstChild () const {return _firstChild.get();}
+ XMLNode* lastChild () const {return _lastChild;}
std::ostream& write (std::ostream &os) const override;
- bool empty () const {return _children.empty();}
- const ChildList& children () const {return _children;}
- const std::string& getName () const {return _name;}
+ bool empty () const {return !_firstChild;}
+ Attributes& attributes () {return _attributes;}
+ const Attributes& attributes () const {return _attributes;}
+ XMLNodeIterator begin () {return XMLNodeIterator(_firstChild.get());}
+ XMLNodeIterator end () {return XMLNodeIterator(nullptr);}
+ ConstXMLNodeIterator begin () const {return ConstXMLNodeIterator(_firstChild.get());}
+ ConstXMLNodeIterator end () const {return ConstXMLNodeIterator(nullptr);}
+ const std::string& name () const {return _name;}
+ const XMLElement* toElement () const override {return this;}
+ const Attribute* getAttribute (const std::string &name) const;
+
+ static std::unique_ptr<XMLNode> remove (XMLNode *child);
+ static XMLElement* wrap (XMLNode *first, XMLNode *last, const std::string &name);
+ static XMLNode* unwrap (XMLElement *child);
+
protected:
Attribute* getAttribute (const std::string &name);
- const Attribute* getAttribute (const std::string &name) const;
+ XMLNode* insertFirst (std::unique_ptr<XMLNode> child);
+ XMLNode* insertLast (std::unique_ptr<XMLNode> child);
private:
std::string _name; // element name (<name a1="v1" .. an="vn">...</name>)
std::vector<Attribute> _attributes;
- ChildList _children; // child nodes
+ std::unique_ptr<XMLNode> _firstChild; ///< pointer to first child node (incl. ownership)
+ XMLNode *_lastChild=nullptr; ///< pointer to last child node
};
-class XMLTextNode : public XMLNode {
+class XMLText : public XMLNode {
public:
- XMLTextNode (const std::string &str) : _text(str) {}
- XMLTextNode (std::string &&str) : _text(std::move(str)) {}
- std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLTextNode>(*this);}
+ explicit XMLText (std::string str) : _text(std::move(str)) {}
+ std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLText>(*this);}
void clear () override {_text.clear();}
- void append (std::unique_ptr<XMLNode> &&node);
- void append (std::unique_ptr<XMLTextNode> &&node);
+ void append (std::unique_ptr<XMLNode> node);
+ void append (std::unique_ptr<XMLText> node);
void append (const std::string &str);
- void prepend (std::unique_ptr<XMLNode> &&node);
+ void prepend (std::unique_ptr<XMLNode> node);
std::ostream& write (std::ostream &os) const override {return os << _text;}
const std::string& getText () const {return _text;}
+ const XMLText* toText () const override {return this;}
+ const XMLText* toWSNode () const override;
private:
std::string _text;
};
-class XMLCommentNode : public XMLNode {
+class XMLComment : public XMLNode {
public:
- XMLCommentNode (const std::string &str) : _text(str) {}
- XMLCommentNode (std::string &&str) : _text(std::move(str)) {}
- std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLCommentNode>(*this);}
+ explicit XMLComment (std::string str) : _text(std::move(str)) {}
+ std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLComment>(*this);}
void clear () override {_text.clear();}
std::ostream& write (std::ostream &os) const override {return os << "<!--" << _text << "-->";}
+ const XMLComment* toComment () const override {return this;}
private:
std::string _text;
};
-class XMLCDataNode : public XMLNode {
+class XMLCData : public XMLNode {
public:
- XMLCDataNode () =default;
- XMLCDataNode (const std::string &d) : _data(d) {}
- XMLCDataNode (std::string &&d) : _data(std::move(d)) {}
- std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLCDataNode>(*this);}
+ XMLCData () =default;
+ explicit XMLCData (std::string data) : _data(std::move(data)) {}
+ std::unique_ptr<XMLNode> clone () const override {return util::make_unique<XMLCData>(*this);}
void clear () override {_data.clear();}
void append (std::string &&str);
std::ostream& write (std::ostream &os) const override;
+ const XMLCData* toCData () const override {return this;}
private:
std::string _data;
};
-inline std::ostream& operator << (std::ostream &os, const XMLElementNode &node) {return node.write(os);}
-inline std::ostream& operator << (std::ostream &os, const XMLTextNode &node) {return node.write(os);}
-inline std::ostream& operator << (std::ostream &os, const XMLCommentNode &node) {return node.write(os);}
-inline std::ostream& operator << (std::ostream &os, const XMLCDataNode &node) {return node.write(os);}
+inline std::ostream& operator << (std::ostream &os, const XMLElement &node) {return node.write(os);}
+inline std::ostream& operator << (std::ostream &os, const XMLText &node) {return node.write(os);}
+inline std::ostream& operator << (std::ostream &os, const XMLComment &node) {return node.write(os);}
+inline std::ostream& operator << (std::ostream &os, const XMLCData &node) {return node.write(os);}
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp
index 734cc7ff8cd..fcafb8d1ee0 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.cpp
@@ -21,6 +21,7 @@
#include <cmath>
#include <cstdlib>
#include "Unicode.hpp"
+#include "utility.hpp"
#include "XMLString.hpp"
using namespace std;
@@ -89,14 +90,8 @@ XMLString::XMLString (double x) {
}
if (std::abs(x) < 1e-6)
x = 0;
- assign(to_string(x));
- size_t pos = find('.');
- if (pos != string::npos) {
- pos = find_last_not_of('0');
- if (pos != string::npos) {
- erase(pos+1); // remove trailing zeros
- if (at(length()-1) == '.')
- pop_back(); // remove trailing dot
- }
- }
+ assign(util::to_string(x));
+ size_t pos = find("0.");
+ if (pos != string::npos && (pos == 0 || at(pos-1) == '-'))
+ erase(pos, 1);
}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp
index efc88d1a25a..fa9cf15f9ea 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XMLString.hpp
@@ -24,14 +24,13 @@
#include <string>
-class XMLString : public std::string
-{
+class XMLString : public std::string {
public:
XMLString () : std::string() {}
- XMLString (const char *str, bool plain=false);
- XMLString (const std::string &str, bool plain=false);
- XMLString (int n, bool cast=true);
- XMLString (double x);
+ explicit XMLString (const char *str, bool plain=false);
+ explicit XMLString (const std::string &str, bool plain=false);
+ explicit XMLString (int n, bool cast=true);
+ explicit XMLString (double x);
static int DECIMAL_PLACES; ///< number of decimal places applied to floating point values (0-6)
};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/XXHashFunction.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/XXHashFunction.hpp
index 62f10db3792..f81deddbd46 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/XXHashFunction.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/XXHashFunction.hpp
@@ -23,7 +23,11 @@
#include <xxhash.h>
#include "HashFunction.hpp"
+#include "utility.hpp"
+#if (XXH_VERSION_NUMBER >= 701) && defined(XXH3_SECRET_SIZE_MIN)
+#define ENABLE_XXH128
+#endif
template <int HASH_SIZE>
struct XXHInterface {
@@ -49,6 +53,17 @@ struct XXHInterface<8> {
static constexpr auto digest = &XXH64_digest;
};
+#ifdef ENABLE_XXH128
+template<>
+struct XXHInterface<16> {
+ using State = XXH3_state_t;
+ static constexpr auto createState = &XXH3_createState;
+ static constexpr auto freeState = &XXH3_freeState;
+ static constexpr auto reset = &XXH3_128bits_reset_withSeed;
+ static constexpr auto update = &XXH3_128bits_update;
+ static constexpr auto digest = &XXH3_128bits_digest;
+};
+#endif
/** Implements the HashFunction class for the xxHash algorithms. */
template <int HASH_BYTES>
@@ -57,23 +72,19 @@ class XXHashFunction : public HashFunction {
public:
XXHashFunction () : _state(Interface::createState()) {Interface::reset(_state, 0);}
XXHashFunction(const char *data, size_t length) : XXHashFunction() {update(data, length);}
- XXHashFunction(const std::string &data) : XXHashFunction() {update(data);}
- XXHashFunction(const std::vector<uint8_t> &data) : XXHashFunction() {update(data);}
- ~XXHashFunction () {Interface::freeState(_state);}
+ explicit XXHashFunction(const std::string &data) : XXHashFunction() {update(data);}
+ explicit XXHashFunction(const std::vector<uint8_t> &data) : XXHashFunction() {update(data);}
+ ~XXHashFunction () override {Interface::freeState(_state);}
int digestSize () const override {return HASH_BYTES;}
void reset () override {Interface::reset(_state, 0);}
void update (const char *data, size_t length) override {Interface::update(_state, data, length);}
void update (const std::string &data) override {update(data.data(), data.length());}
void update (const std::vector<uint8_t> &data) override {update(reinterpret_cast<const char*>(data.data()), data.size());}
+ using HashFunction::update; // unhide update(istream &is) defined in base class
+
std::vector<uint8_t> digestValue () const override {
- std::vector<uint8_t> hash(HASH_BYTES);
- auto digest = Interface::digest(_state);
- for (int i=HASH_BYTES-1; i >= 0; i--) {
- hash[i] = digest & 0xff;
- digest >>= 8;
- }
- return hash;
+ return util::bytes(Interface::digest(_state), HASH_BYTES);
}
static unsigned version () {return XXH_versionNumber();}
@@ -85,4 +96,19 @@ class XXHashFunction : public HashFunction {
using XXH32HashFunction = XXHashFunction<4>;
using XXH64HashFunction = XXHashFunction<8>;
+#ifdef ENABLE_XXH128
+using XXH128HashFunction = XXHashFunction<16>;
+
+template<>
+inline std::vector<uint8_t> XXHashFunction<16>::digestValue () const {
+ std::vector<uint8_t> hash;
+ auto digest = Interface::digest(_state);
+ for (auto chunk : {digest.high64, digest.low64}) {
+ auto bytes = util::bytes(chunk);
+ hash.insert(hash.end(), bytes.begin(), bytes.end());
+ }
+ return hash;
+}
+#endif
+
#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp
index 4e882813550..8331cb9eed3 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/ZLibOutputStream.hpp
@@ -33,20 +33,20 @@
#endif
struct ZLibException : public MessageException {
- ZLibException (const std::string &msg) : MessageException(msg) {}
+ explicit ZLibException (const std::string &msg) : MessageException(msg) {}
};
enum ZLibCompressionFormat {ZLIB_DEFLATE=0, ZLIB_GZIP=16};
class ZLibOutputBuffer : public std::streambuf {
public:
- ZLibOutputBuffer () {}
+ ZLibOutputBuffer () =default;
ZLibOutputBuffer (std::streambuf *sbuf, ZLibCompressionFormat format, int zipLevel) {
open(sbuf, format, zipLevel);
}
- ~ZLibOutputBuffer () {
+ ~ZLibOutputBuffer () override {
close();
}
@@ -84,7 +84,7 @@ class ZLibOutputBuffer : public std::streambuf {
else {
if (_inbuf.size() == _inbuf.capacity())
flush(Z_NO_FLUSH);
- _inbuf.push_back(c);
+ _inbuf.push_back(static_cast<unsigned char>(c));
}
return c;
}
@@ -101,10 +101,10 @@ class ZLibOutputBuffer : public std::streambuf {
* @throws ZLibException if compression failed */
void flush (int flushmode) {
if (_opened) {
- _zstream.avail_in = _inbuf.size();
+ _zstream.avail_in = static_cast<uInt>(_inbuf.size());
_zstream.next_in = _inbuf.data();
do {
- _zstream.avail_out = _zbuf.size();
+ _zstream.avail_out = static_cast<uInt>(_zbuf.size());
_zstream.next_out = _zbuf.data();
int ret = deflate(&_zstream, flushmode);
if (ret == Z_STREAM_ERROR) {
@@ -146,7 +146,7 @@ class ZLibOutputStream : private ZLibOutputBuffer, public std::ostream {
ZLibOutputStream (std::ostream &os, ZLibCompressionFormat format, int zipLevel)
: ZLibOutputBuffer(os.rdbuf(), format, zipLevel), std::ostream(this) {}
- ~ZLibOutputStream () {close();}
+ ~ZLibOutputStream () override {close();}
bool open (std::ostream &os, ZLibCompressionFormat format, int zipLevel) {
ZLibOutputBuffer::close();
@@ -172,7 +172,7 @@ class ZLibOutputFileStream : public ZLibOutputStream {
}
}
- ~ZLibOutputFileStream () {close();}
+ ~ZLibOutputFileStream () override {close();}
private:
std::ofstream _ofs;
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp
index b82709f1f55..37584d5ddbd 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/dvisvgm.cpp
@@ -45,6 +45,7 @@
#include "PsSpecialHandler.hpp"
#include "SignalHandler.hpp"
#include "SourceInput.hpp"
+#include "optimizer/SVGOptimizer.hpp"
#include "SVGOutput.hpp"
#include "System.hpp"
#include "XXHashFunction.hpp"
@@ -108,27 +109,36 @@ static void set_libgs (CommandLine &args) {
static bool set_cache_dir (const CommandLine &args) {
if (args.cacheOpt.given() && !args.cacheOpt.value().empty()) {
if (args.cacheOpt.value() == "none")
- PhysicalFont::CACHE_PATH = 0;
+ PhysicalFont::CACHE_PATH.clear();
else if (FileSystem::exists(args.cacheOpt.value()))
- PhysicalFont::CACHE_PATH = args.cacheOpt.value().c_str();
+ PhysicalFont::CACHE_PATH = args.cacheOpt.value();
else
Message::wstream(true) << "cache directory '" << args.cacheOpt.value() << "' does not exist (caching disabled)\n";
}
- else if (const char *userdir = FileSystem::userdir()) {
+ else {
+ string &cachepath = PhysicalFont::CACHE_PATH;
+ const char *cachehome = getenv("XDG_CACHE_HOME");
+ if (!cachehome || util::trim(cachehome).empty()) {
#ifdef _WIN32
- string cachedir = "\\.dvisvgm\\cache";
+ cachehome = "~\\.cache";
#else
- string cachedir = "/.dvisvgm/cache";
+ cachehome = "~/.cache";
#endif
- static string cachepath = userdir + cachedir;
+ }
+ cachepath = util::trim(cachehome) + FileSystem::PATHSEP + "dvisvgm";
+ if (cachepath[0] == '~' && cachepath[1] == FileSystem::PATHSEP) {
+ if (FileSystem::userdir())
+ cachepath.replace(0, 1, FileSystem::userdir());
+ else
+ cachepath.erase(0, 2); // strip leading "~/"
+ }
if (!FileSystem::exists(cachepath))
FileSystem::mkdir(cachepath);
- PhysicalFont::CACHE_PATH = cachepath.c_str();
}
if (args.cacheOpt.given() && args.cacheOpt.value().empty()) {
- cout << "cache directory: " << (PhysicalFont::CACHE_PATH ? PhysicalFont::CACHE_PATH : "(none)") << '\n';
+ cout << "cache directory: " << (PhysicalFont::CACHE_PATH.empty() ? "(none)" : PhysicalFont::CACHE_PATH) << '\n';
try {
- if (PhysicalFont::CACHE_PATH)
+ if (!PhysicalFont::CACHE_PATH.empty())
FontCache::fontinfo(PhysicalFont::CACHE_PATH, cout, true);
}
catch (StreamReaderException &e) {
@@ -143,7 +153,7 @@ static bool set_cache_dir (const CommandLine &args) {
static bool set_temp_dir (const CommandLine &args) {
if (args.tmpdirOpt.given()) {
if (!args.tmpdirOpt.value().empty())
- FileSystem::TMPDIR = args.tmpdirOpt.value().c_str();
+ FileSystem::TMPDIR = args.tmpdirOpt.value();
else {
cout << "temporary folder: " << FileSystem::tmpdir() << '\n';
return false;
@@ -299,14 +309,14 @@ static string svg_options_hash (const CommandLine &cmdline) {
// options affecting the SVG output
vector<const CL::Option*> svg_options = {
&cmdline.bboxOpt, &cmdline.clipjoinOpt, &cmdline.colornamesOpt, &cmdline.commentsOpt,
- &cmdline.exactOpt, &cmdline.fontFormatOpt, &cmdline.fontmapOpt, &cmdline.gradOverlapOpt,
+ &cmdline.exactBboxOpt, &cmdline.fontFormatOpt, &cmdline.fontmapOpt, &cmdline.gradOverlapOpt,
&cmdline.gradSegmentsOpt, &cmdline.gradSimplifyOpt, &cmdline.linkmarkOpt, &cmdline.magOpt,
- &cmdline.noFontsOpt, &cmdline.noMergeOpt, &cmdline.noSpecialsOpt, &cmdline.noStylesOpt,
- &cmdline.precisionOpt, &cmdline.relativeOpt, &cmdline.zoomOpt
+ &cmdline.noFontsOpt, &cmdline.noMergeOpt, &cmdline.noSpecialsOpt, &cmdline.noStylesOpt,
+ &cmdline.optimizeOpt, &cmdline.precisionOpt, &cmdline.relativeOpt, &cmdline.zoomOpt
};
string idString = get_transformation_string(cmdline);
for (const CL::Option *opt : svg_options) {
- idString += opt->given();
+ idString += char(opt->given());
idString += opt->valueString();
}
return XXH64HashFunction(idString).digestString();
@@ -337,10 +347,9 @@ static void set_variables (const CommandLine &cmdline) {
SVGTree::USE_FONTS = !cmdline.noFontsOpt.given();
if (!SVGTree::setFontFormat(cmdline.fontFormatOpt.value())) {
string msg = "unknown font format '"+cmdline.fontFormatOpt.value()+"' (supported formats: ";
- ostringstream oss;
for (const string &format : FontWriter::supportedFormats())
- oss << ", " << format;
- msg += oss.str().substr(2) + ')';
+ msg += format + ", ";
+ msg.erase(msg.end()-2);
throw CL::CommandLineException(msg);
}
SVGTree::CREATE_USE_ELEMENTS = cmdline.noFontsOpt.value() < 1;
@@ -350,7 +359,7 @@ static void set_variables (const CommandLine &cmdline) {
SVGTree::ADD_COMMENTS = cmdline.commentsOpt.given();
DVIToSVG::TRACE_MODE = cmdline.traceAllOpt.given() ? (cmdline.traceAllOpt.value() ? 'a' : 'm') : 0;
Message::LEVEL = cmdline.verbosityOpt.value();
- PhysicalFont::EXACT_BBOX = cmdline.exactOpt.given();
+ PhysicalFont::EXACT_BBOX = cmdline.exactBboxOpt.given();
PhysicalFont::KEEP_TEMP_FILES = cmdline.keepOpt.given();
PhysicalFont::METAFONT_MAG = max(1.0, cmdline.magOpt.value());
XMLString::DECIMAL_PLACES = max(0, min(6, cmdline.precisionOpt.value()));
@@ -358,6 +367,19 @@ static void set_variables (const CommandLine &cmdline) {
PsSpecialHandler::SHADING_SEGMENT_OVERLAP = cmdline.gradOverlapOpt.given();
PsSpecialHandler::SHADING_SEGMENT_SIZE = max(1, cmdline.gradSegmentsOpt.value());
PsSpecialHandler::SHADING_SIMPLIFY_DELTA = cmdline.gradSimplifyOpt.value();
+ if (cmdline.optimizeOpt.given()) {
+ SVGOptimizer::MODULE_SEQUENCE = cmdline.optimizeOpt.value();
+ vector<string> modnames;
+ if (!SVGOptimizer().checkModuleString(SVGOptimizer::MODULE_SEQUENCE, modnames)) {
+ string msg = "invalid optimizer module";
+ if (modnames.size() > 1) msg += 's';
+ msg += ": ";
+ for (const string &modname : modnames)
+ msg += modname + ", ";
+ msg.erase(msg.end()-2);
+ throw CL::CommandLineException(msg);
+ }
+ }
}
@@ -393,6 +415,10 @@ int main (int argc, char *argv[]) {
SpecialManager::instance().writeHandlerInfo(cout);
return 0;
}
+ if (cmdline.optimizeOpt.value() == "list") {
+ SVGOptimizer().listModules(cout);
+ return 0;
+ }
if (!set_cache_dir(cmdline) || !set_temp_dir(cmdline))
return 0;
check_bbox(cmdline.bboxOpt.value());
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/AttributeExtractor.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/AttributeExtractor.cpp
new file mode 100644
index 00000000000..e26018253d6
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/AttributeExtractor.cpp
@@ -0,0 +1,176 @@
+/*************************************************************************
+** AttributeExtractor.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** This program is free software; you can redistribute it and/or **
+** modify it under the terms of the GNU General Public License as **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include <algorithm>
+#include <array>
+#include "AttributeExtractor.hpp"
+
+using namespace std;
+
+/** Constructs a new run object for an attribute and a sequence of sibling nodes.
+ * @param[in] attr attribute to look for
+ * @param[in] first first element of node sequence to scan */
+AttributeExtractor::AttributeRun::AttributeRun (const Attribute &attr, XMLElement *first) {
+ _length = 1;
+ _first = first;
+ for (_last=_first->next(); _last; _last=_last->next()) {
+ if (_last->toText() || _last->toCData()) // don't include text/CDATA nodes
+ break;
+ if (XMLElement *childElem = _last->toElement()) {
+ if (!groupable(*childElem))
+ break;
+ const char *val = childElem->getAttributeValue(attr.name);
+ if (val && val == attr.value)
+ ++_length;
+ else
+ break;
+ }
+ }
+ if (_first != _last && _last)
+ _last = _last->prev();
+}
+
+
+const char* AttributeExtractor::info () const {
+ return "move common attributes from a sequence of elements to enclosing groups";
+}
+
+
+/** Performs the attribute extraction on a given context node. Each extracted
+ * attribute gets its own group, i.e. the extraction of multiple attributes
+ * of the same elements leads to nested groups.
+ * @param[in] context attributes of all children in this element are extracted
+ * @param[in] recurse if true, the algorithm is recursively performed on all descendant elements */
+void AttributeExtractor::execute (XMLElement *context, bool recurse) {
+ if (!context || context->empty())
+ return;
+ if (recurse) {
+ for (auto node : *context) {
+ if (XMLElement *elem = node->toElement())
+ execute(elem, true);
+ }
+ }
+ for (XMLNode *child=context->firstChild(); child; child=child->next()) {
+ if (XMLElement *elem = child->toElement())
+ child = extractAttribute(elem);
+ }
+}
+
+
+/** Looks for the first attribute not yet processed and tries to group it. If
+ * there is a sequence of adjacent sibling nodes N1,...,Nn with an identical inheritable
+ * attribute, the function creates a group element with this attribute and moves the
+ * nodes N1,...,Nn into that group. The group is inserted at the former position of N1.
+ * @param[in] elem first element of a node sequence with potentially identical attributes
+ * @return the new group element if attributes could be grouped, 'elem' otherwise */
+XMLNode* AttributeExtractor::extractAttribute (XMLElement *elem) {
+ for (const auto &currentAttribute : elem->attributes()) {
+ if (!inheritable(currentAttribute) || extracted(currentAttribute))
+ continue;
+ AttributeRun run(currentAttribute, elem);
+ if (run.length() >= MIN_RUN_LENGTH) {
+ XMLElement::Attribute attrib = currentAttribute;
+ XMLElement *group = XMLElement::wrap(run.first(), run.last(), "g");
+ group->addAttribute(attrib.name, attrib.value);
+ // remove attribute from the grouped elements but keep it on elements with 'id' attribute
+ // since they can be referenced, and keep 'fill' attribute on animation elements
+ for (XMLNode *node : *group) {
+ XMLElement *elem = node->toElement();
+ if (elem && extractable(attrib, *elem))
+ elem->removeAttribute(attrib.name);
+ }
+ // continue with children of the new group but ignore the just extracted attribute
+ _extractedAttributes.insert(attrib.name);
+ execute(group, false);
+ _extractedAttributes.erase(attrib.name);
+ return group;
+ }
+ }
+ return elem;
+}
+
+
+/** Checks whether an element type is allowed to be put in a group element (<g>...</g>).
+ * For now we only consider a subset of the actually allowed set of elements.
+ * @param[in] elem name of element to check
+ * @return true if the element is groupable */
+bool AttributeExtractor::groupable (const XMLElement &elem) {
+ // https://www.w3.org/TR/SVG/struct.html#GElement
+ static const char *names[] = {
+ "a", "altGlyphDef", "animate", "animateColor", "animateMotion", "animateTransform",
+ "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "ellipse", "filter",
+ "font", "font-face", "foreignObject", "g", "image", "line", "linearGradient", "marker",
+ "mask", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "set",
+ "style", "switch", "symbol", "text", "title", "use", "view"
+ };
+ return binary_search(begin(names), end(names), elem.name(), [](const string &name1, const string &name2) {
+ return name1 < name2;
+ });
+}
+
+
+/** Checks whether an SVG attribute A of an element E implicitly propagates its properties
+ * to all child elements of E that don't specify A. For now we only consider a subset of
+ * the inheritable properties.
+ * @param[in] attrib name of attribute to check
+ * @return true if the attribute is inheritable */
+bool AttributeExtractor::inheritable (const Attribute &attrib) {
+ // subset of inheritable properties listed on https://www.w3.org/TR/SVG11/propidx.html
+ // clip-path is not inheritable but can be moved to the parent element as long as
+ // no child gets an different clip-path attribute
+ // https://www.w3.org/TR/SVG11/styling.html#Inheritance
+ static const char *names[] = {
+ "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile",
+ "color-rendering", "direction", "fill", "fill-opacity", "fill-rule", "font", "font-family", "font-size",
+ "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "glyph-orientation-horizontal",
+ "glyph-orientation-vertical", "letter-spacing", "paint-order", "stroke", "stroke-dasharray", "stroke-dashoffset",
+ "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "transform",
+ "visibility", "word-spacing", "writing-mode"
+ };
+ return binary_search(begin(names), end(names), attrib.name, [](const string &name1, const string &name2) {
+ return name1 < name2;
+ });
+}
+
+
+/** Checks whether an attribute is allowed to be removed from a given element. */
+bool AttributeExtractor::extractable (const Attribute &attrib, XMLElement &element) {
+ if (element.hasAttribute("id"))
+ return false;
+ if (attrib.name != "fill")
+ return true;
+ // the 'fill' attribute of animation elements has different semantics than
+ // that of graphics elements => don't extract it from animation nodes
+ // https://www.w3.org/TR/SVG11/animate.html#TimingAttributes
+ static const char *names[] = {
+ "animate", "animateColor", "animateMotion", "animateTransform", "set"
+ };
+ auto it = find_if(begin(names), end(names), [&](const string &name) {
+ return element.name() == name;
+ });
+ return it == end(names);
+}
+
+
+/** Returns true if a given attribute was already extracted from the
+ * current run of elements. */
+bool AttributeExtractor::extracted (const Attribute &attr) const {
+ return _extractedAttributes.find(attr.name) != _extractedAttributes.end();
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/AttributeExtractor.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/AttributeExtractor.hpp
new file mode 100644
index 00000000000..c882e8b4c8f
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/AttributeExtractor.hpp
@@ -0,0 +1,61 @@
+/*************************************************************************
+** AttributeExtractor.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 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/>. **
+*************************************************************************/
+
+#pragma once
+
+#include <set>
+#include <string>
+#include "OptimizerModule.hpp"
+#include "../XMLNode.hpp"
+
+/** Moves common attributes of adjacent elements to enclosing groups. */
+class AttributeExtractor : public OptimizerModule {
+ using Attribute = XMLElement::Attribute;
+
+ /** Represents a range of adjacent nodes where all elements have a common attribute. */
+ struct AttributeRun {
+ public:
+ AttributeRun (const Attribute &attr, XMLElement *first);
+ XMLNode* first () {return _first;}
+ XMLNode* last () {return _last;}
+ int length () const {return _length;}
+
+ private:
+ int _length; ///< run length excluding non-element nodes
+ XMLNode *_first, *_last; ///< first and last node in run
+ };
+
+ public:
+ void execute (XMLElement*, XMLElement *context) override {execute(context, true);};
+ const char* info () const override;
+ static bool groupable (const XMLElement &elem);
+ static bool inheritable (const Attribute &attrib);
+ static bool extractable (const Attribute &attr, XMLElement &element);
+
+ protected:
+ void execute (XMLElement *context, bool recurse);
+ XMLNode* extractAttribute (XMLElement *elem);
+ bool extracted (const Attribute &attr) const;
+
+ private:
+ std::set<std::string> _extractedAttributes;
+ static constexpr int MIN_RUN_LENGTH = 3;
+};
+
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DependencyGraph.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/DependencyGraph.hpp
index c9738d3f030..c9111b43d56 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DependencyGraph.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/DependencyGraph.hpp
@@ -25,12 +25,12 @@
#include <memory>
#include <set>
#include <vector>
-#include "utility.hpp"
+#include "../utility.hpp"
template <typename T>
class DependencyGraph {
struct GraphNode {
- GraphNode (const T &k) : key(k), dependent() {}
+ explicit GraphNode (const T &k) : key(k), dependent() {}
void addDependee (GraphNode *node) {
if (node) {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp
new file mode 100644
index 00000000000..36bf3a8cd5a
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp
@@ -0,0 +1,165 @@
+/*************************************************************************
+** GroupCollapser.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** This program is free software; you can redistribute it and/or **
+** modify it under the terms of the GNU General Public License as **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include <algorithm>
+#include <array>
+#include <string>
+#include <vector>
+#include "AttributeExtractor.hpp"
+#include "GroupCollapser.hpp"
+#include "../XMLNode.hpp"
+
+using namespace std;
+
+
+const char* GroupCollapser::info () const {
+ return "join nested group elements";
+}
+
+
+/** Checks if there's only a single child element and optional whitespace
+ * siblings in a given element.
+ * @param[in] elem element to check
+ * @return pointer to the only child element or nullptr */
+static XMLElement* only_child_element (XMLElement *elem) {
+ XMLElement *firstChildElement=nullptr;
+ for (XMLNode *child : *elem) {
+ if (XMLElement *childElement = child->toElement()) {
+ if (firstChildElement)
+ return nullptr;
+ firstChildElement = childElement;
+ }
+ else if (!child->toWSNode())
+ return nullptr;
+ }
+ return firstChildElement;
+}
+
+
+/** Removes all whitespace child nodes from a given element. */
+static void remove_ws_nodes (XMLElement *elem) {
+ XMLNode *node = elem->firstChild();
+ while (node) {
+ if (!node->toWSNode())
+ node = node->next();
+ else {
+ XMLNode *next = node->next();
+ XMLElement::remove(node);
+ node = next;
+ }
+ }
+}
+
+
+/** Recursively removes all redundant group elements from the given context element
+ * and moves their attributes to the corresponding parent element.
+ * @param[in] context root of the subtree to process */
+void GroupCollapser::execute (XMLElement *context) {
+ if (!context)
+ return;
+ XMLNode *node=context->firstChild();
+ while (node) {
+ XMLNode *next = node->next(); // keep safe pointer to next node
+ if (XMLElement *elem = node->toElement())
+ execute(elem);
+ node = next;
+ }
+ if (context->name() == "g" && context->attributes().empty()) {
+ // unwrap group without attributes
+ remove_ws_nodes(context);
+ XMLElement::unwrap(context);
+ }
+ else {
+ XMLElement *child = only_child_element(context);
+ if (child && collapsible(*context)) {
+ if (child->name() == "g" && unwrappable(*child, *context) && moveAttributes(*child, *context)) {
+ remove_ws_nodes(context);
+ XMLElement::unwrap(child);
+ }
+ }
+ }
+}
+
+
+/** Moves all attributes from an element to another one. Attributes already
+ * present in the destination element are overwritten or combined.
+ * @param[in] source element the attributes are taken from
+ * @param[in] dest element that receives the attributes
+ * @return true if all attributes have been moved */
+bool GroupCollapser::moveAttributes (XMLElement &source, XMLElement &dest) {
+ vector<string> movedAttributes;
+ for (const XMLElement::Attribute &attr : source.attributes()) {
+ if (attr.name == "transform") {
+ string transform;
+ if (const char *destvalue = dest.getAttributeValue("transform"))
+ transform = destvalue+attr.value;
+ else
+ transform = attr.value;
+ dest.addAttribute("transform", transform);
+ movedAttributes.emplace_back("transform");
+ }
+ else if (AttributeExtractor::inheritable(attr)) {
+ dest.addAttribute(attr.name, attr.value);
+ movedAttributes.emplace_back(attr.name);
+ }
+ }
+ for (const string &attrname : movedAttributes)
+ source.removeAttribute(attrname);
+ return source.attributes().empty();
+}
+
+
+/** Returns true if a given element is allowed to take the inheritable attributes
+ * and children of a child group without changing the semantics.
+ * @param[in] element group element to check */
+bool GroupCollapser::collapsible (const XMLElement &element) {
+ // the 'fill' attribute of animation elements has different semantics than
+ // that of graphics elements => don't collapse them
+ static const char *names[] = {
+ "animate", "animateColor", "animateMotion", "animateTransform", "set"
+ };
+ auto it = find_if(begin(names), end(names), [&](const string &name) {
+ return element.name() == name;
+ });
+ return it == end(names);
+}
+
+
+/** Returns true if a given group element is allowed to be unwrapped, i.e. its
+ * attributes and children can be moved to the parent without changing the semantics.
+ * @param[in] source element whose children and attributes should be moved
+ * @param[in] dest element that should receive the children and attributes */
+bool GroupCollapser::unwrappable (const XMLElement &source, const XMLElement &dest) {
+ // check for colliding clip-path attributes
+ if (const char *cp1 = source.getAttributeValue("clip-path")) {
+ if (const char *cp2 = dest.getAttributeValue("clip-path")) {
+ if (string(cp1) != cp2)
+ return false;
+ }
+ }
+ // these attributes prevent a group from being unwrapped
+ static const char *attribs[] = {
+ "class", "id", "filter", "mask", "style"
+ };
+ auto it = find_if(begin(attribs), end(attribs), [&](const string &name) {
+ return source.hasAttribute(name) || dest.hasAttribute(name);
+ });
+ return it == end(attribs);
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.hpp
new file mode 100644
index 00000000000..9b5eb018293
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.hpp
@@ -0,0 +1,36 @@
+/*************************************************************************
+** GroupCollapser.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 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/>. **
+*************************************************************************/
+
+#pragma once
+
+#include "OptimizerModule.hpp"
+
+/** Joins the attributes of nested groups and removes groups without attributes. */
+class GroupCollapser : public OptimizerModule {
+ public:
+ void execute (XMLElement*, XMLElement *context) override {execute(context);};
+ void execute (XMLElement *context);
+ const char* info () const override;
+
+ protected:
+ static bool moveAttributes (XMLElement &source, XMLElement &dest);
+ static bool collapsible (const XMLElement &elem);
+ static bool unwrappable (const XMLElement &source, const XMLElement &dest);
+};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/Makefile.am b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/Makefile.am
new file mode 100644
index 00000000000..10232c273d3
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/Makefile.am
@@ -0,0 +1,14 @@
+noinst_LIBRARIES = liboptimizer.a
+
+liboptimizer_a_SOURCES = \
+ AttributeExtractor.hpp AttributeExtractor.cpp \
+ DependencyGraph.hpp \
+ GroupCollapser.hpp GroupCollapser.cpp \
+ OptimizerModule.hpp \
+ RedundantElementRemover.hpp RedundantElementRemover.cpp \
+ SVGOptimizer.hpp SVGOptimizer.cpp \
+ TextSimplifier.hpp TextSimplifier.cpp \
+ TransformSimplifier.hpp TransformSimplifier.cpp \
+ WSNodeRemover.hpp WSNodeRemover.cpp
+
+AM_CXXFLAGS = -I$(dvisvgm_srcdir)/libs/variant/include
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/Makefile.in b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/Makefile.in
new file mode 100644
index 00000000000..103e6bc0e36
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/Makefile.in
@@ -0,0 +1,694 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = dvisvgm-src/src/optimizer
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../../m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/../../m4/kpse-common.m4 \
+ $(top_srcdir)/../../m4/kpse-cxx-hack.m4 \
+ $(top_srcdir)/../../m4/kpse-freetype2-flags.m4 \
+ $(top_srcdir)/../../m4/kpse-kpathsea-flags.m4 \
+ $(top_srcdir)/../../m4/kpse-warnings.m4 \
+ $(top_srcdir)/../../m4/kpse-win32.m4 \
+ $(top_srcdir)/../../m4/kpse-zlib-flags.m4 \
+ $(top_srcdir)/../../m4/libtool.m4 \
+ $(top_srcdir)/../../m4/ltoptions.m4 \
+ $(top_srcdir)/../../m4/ltsugar.m4 \
+ $(top_srcdir)/../../m4/ltversion.m4 \
+ $(top_srcdir)/../../m4/lt~obsolete.m4 $(top_srcdir)/version.ac \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+liboptimizer_a_AR = $(AR) $(ARFLAGS)
+liboptimizer_a_LIBADD =
+am_liboptimizer_a_OBJECTS = AttributeExtractor.$(OBJEXT) \
+ GroupCollapser.$(OBJEXT) RedundantElementRemover.$(OBJEXT) \
+ SVGOptimizer.$(OBJEXT) TextSimplifier.$(OBJEXT) \
+ TransformSimplifier.$(OBJEXT) WSNodeRemover.$(OBJEXT)
+liboptimizer_a_OBJECTS = $(am_liboptimizer_a_OBJECTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/../../build-aux/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/AttributeExtractor.Po \
+ ./$(DEPDIR)/GroupCollapser.Po \
+ ./$(DEPDIR)/RedundantElementRemover.Po \
+ ./$(DEPDIR)/SVGOptimizer.Po ./$(DEPDIR)/TextSimplifier.Po \
+ ./$(DEPDIR)/TransformSimplifier.Po \
+ ./$(DEPDIR)/WSNodeRemover.Po
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(liboptimizer_a_SOURCES)
+DIST_SOURCES = $(liboptimizer_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/../../build-aux/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BROTLI_CFLAGS = @BROTLI_CFLAGS@
+BROTLI_LIBS = @BROTLI_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CODE_COVERAGE_RULES = @CODE_COVERAGE_RULES@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CXXLD = @CXXLD@
+CYGPATH_W = @CYGPATH_W@
+DATE = @DATE@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DVISVGM_TREE = @DVISVGM_TREE@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FREETYPE2_DEPEND = @FREETYPE2_DEPEND@
+FREETYPE2_INCLUDES = @FREETYPE2_INCLUDES@
+FREETYPE2_LIBS = @FREETYPE2_LIBS@
+FT2_CONFIG = @FT2_CONFIG@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KPATHSEA_DEPEND = @KPATHSEA_DEPEND@
+KPATHSEA_INCLUDES = @KPATHSEA_INCLUDES@
+KPATHSEA_LIBS = @KPATHSEA_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBGS_INCLUDES = @LIBGS_INCLUDES@
+LIBGS_LIBS = @LIBGS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WOFF2_CFLAGS = @WOFF2_CFLAGS@
+WOFF2_LIBS = @WOFF2_LIBS@
+ZLIB_DEPEND = @ZLIB_DEPEND@
+ZLIB_INCLUDES = @ZLIB_INCLUDES@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+dvisvgm_srcdir = @dvisvgm_srcdir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = liboptimizer.a
+liboptimizer_a_SOURCES = \
+ AttributeExtractor.hpp AttributeExtractor.cpp \
+ DependencyGraph.hpp \
+ GroupCollapser.hpp GroupCollapser.cpp \
+ OptimizerModule.hpp \
+ RedundantElementRemover.hpp RedundantElementRemover.cpp \
+ SVGOptimizer.hpp SVGOptimizer.cpp \
+ TextSimplifier.hpp TextSimplifier.cpp \
+ TransformSimplifier.hpp TransformSimplifier.cpp \
+ WSNodeRemover.hpp WSNodeRemover.cpp
+
+AM_CXXFLAGS = -I$(dvisvgm_srcdir)/libs/variant/include
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign dvisvgm-src/src/optimizer/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign dvisvgm-src/src/optimizer/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+liboptimizer.a: $(liboptimizer_a_OBJECTS) $(liboptimizer_a_DEPENDENCIES) $(EXTRA_liboptimizer_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f liboptimizer.a
+ $(AM_V_AR)$(liboptimizer_a_AR) liboptimizer.a $(liboptimizer_a_OBJECTS) $(liboptimizer_a_LIBADD)
+ $(AM_V_at)$(RANLIB) liboptimizer.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AttributeExtractor.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GroupCollapser.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RedundantElementRemover.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SVGOptimizer.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TextSimplifier.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TransformSimplifier.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WSNodeRemover.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/AttributeExtractor.Po
+ -rm -f ./$(DEPDIR)/GroupCollapser.Po
+ -rm -f ./$(DEPDIR)/RedundantElementRemover.Po
+ -rm -f ./$(DEPDIR)/SVGOptimizer.Po
+ -rm -f ./$(DEPDIR)/TextSimplifier.Po
+ -rm -f ./$(DEPDIR)/TransformSimplifier.Po
+ -rm -f ./$(DEPDIR)/WSNodeRemover.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/AttributeExtractor.Po
+ -rm -f ./$(DEPDIR)/GroupCollapser.Po
+ -rm -f ./$(DEPDIR)/RedundantElementRemover.Po
+ -rm -f ./$(DEPDIR)/SVGOptimizer.Po
+ -rm -f ./$(DEPDIR)/TextSimplifier.Po
+ -rm -f ./$(DEPDIR)/TransformSimplifier.Po
+ -rm -f ./$(DEPDIR)/WSNodeRemover.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/OptimizerModule.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/OptimizerModule.hpp
new file mode 100644
index 00000000000..ff4fec1b4dc
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/OptimizerModule.hpp
@@ -0,0 +1,30 @@
+/*************************************************************************
+** OptimizerModule.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 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/>. **
+*************************************************************************/
+
+#pragma once
+
+class XMLElement;
+
+class OptimizerModule {
+ public:
+ virtual ~OptimizerModule () =default;
+ virtual void execute (XMLElement *defs, XMLElement *context) =0;
+ virtual const char* info () const =0;
+};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/RedundantElementRemover.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/RedundantElementRemover.cpp
new file mode 100644
index 00000000000..85d8e5b1fa8
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/RedundantElementRemover.cpp
@@ -0,0 +1,68 @@
+/*************************************************************************
+** RedundantElementRemover.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** This program is free software; you can redistribute it and/or **
+** modify it under the terms of the GNU General Public License as **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include "DependencyGraph.hpp"
+#include "RedundantElementRemover.hpp"
+#include "../XMLNode.hpp"
+
+using namespace std;
+
+const char* RedundantElementRemover::info () const {
+ return "remove redundant 'clipPath' elements";
+}
+
+
+/** Extracts the ID from a local URL reference like url(#abcde) */
+static inline string extract_id_from_url (const string &url) {
+ return url.substr(5, url.length()-6);
+}
+
+
+/** Removes elements present in the SVG tree that are not required.
+ * For now, only clipPath elements are removed. */
+void RedundantElementRemover::execute (XMLElement *defs, XMLElement *context) {
+ vector<XMLElement*> clipPathElements;
+ if (!defs || !context || !defs->getDescendants("clipPath", nullptr, clipPathElements))
+ return;
+
+ // collect dependencies between clipPath elements in the defs section of the SVG tree
+ DependencyGraph<string> idTree;
+ for (const XMLElement *clip : clipPathElements) {
+ if (const char *id = clip->getAttributeValue("id")) {
+ if (const char *url = clip->getAttributeValue("clip-path"))
+ idTree.insert(extract_id_from_url(url), id);
+ else
+ idTree.insert(id);
+ }
+ }
+ // collect elements that reference a clipPath, i.e. have a clip-path attribute
+ vector<XMLElement*> descendants;
+ context->getDescendants(nullptr, "clip-path", descendants);
+ // remove referenced IDs and their dependencies from the dependency graph
+ for (const XMLElement *elem : descendants) {
+ string idref = extract_id_from_url(elem->getAttributeValue("clip-path"));
+ idTree.removeDependencyPath(idref);
+ }
+ descendants.clear();
+ for (const string &str : idTree.getKeys()) {
+ XMLElement *node = defs->getFirstDescendant("clipPath", "id", str.c_str());
+ XMLElement::remove(node);
+ }
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/RedundantElementRemover.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/RedundantElementRemover.hpp
new file mode 100644
index 00000000000..dd46cfeba5d
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/RedundantElementRemover.hpp
@@ -0,0 +1,29 @@
+/*************************************************************************
+** RedundantElementRemover.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 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/>. **
+*************************************************************************/
+
+#pragma once
+
+#include "OptimizerModule.hpp"
+
+class RedundantElementRemover : public OptimizerModule {
+ public:
+ void execute (XMLElement *defs, XMLElement *context) override;
+ const char* info () const override;
+};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/SVGOptimizer.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/SVGOptimizer.cpp
new file mode 100644
index 00000000000..0320f8b565e
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/SVGOptimizer.cpp
@@ -0,0 +1,107 @@
+/*************************************************************************
+** SVGOptimizer.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** This program is free software; you can redistribute it and/or **
+** modify it under the terms of the GNU General Public License as **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include <algorithm>
+#include <array>
+#include <map>
+#include "SVGOptimizer.hpp"
+#include "../SVGTree.hpp"
+
+#include "AttributeExtractor.hpp"
+#include "GroupCollapser.hpp"
+#include "RedundantElementRemover.hpp"
+#include "TextSimplifier.hpp"
+#include "TransformSimplifier.hpp"
+#include "WSNodeRemover.hpp"
+
+using namespace std;
+
+string SVGOptimizer::MODULE_SEQUENCE;
+
+SVGOptimizer::SVGOptimizer (SVGTree *svg) : _svg(svg) {
+ // optimizer modules available to the user; must be listed in default order
+// _moduleEntries.emplace_back(ModuleEntry("remove-ws", util::make_unique<WSNodeRemover>()));
+ _moduleEntries.emplace_back(ModuleEntry("simplify-text", util::make_unique<TextSimplifier>()));
+ _moduleEntries.emplace_back(ModuleEntry("group-attributes", util::make_unique<AttributeExtractor>()));
+ _moduleEntries.emplace_back(ModuleEntry("collapse-groups", util::make_unique<GroupCollapser>()));
+ _moduleEntries.emplace_back(ModuleEntry("simplify-transform", util::make_unique<TransformSimplifier>()));
+ _moduleEntries.emplace_back(ModuleEntry("remove-clippath", util::make_unique<RedundantElementRemover>()));
+}
+
+
+void SVGOptimizer::execute () {
+ if (!_svg || MODULE_SEQUENCE == "none")
+ return;
+ if (MODULE_SEQUENCE.empty())
+ MODULE_SEQUENCE = "remove-clippath"; // default behaviour of previous dvisvgm releases
+ if (MODULE_SEQUENCE == "all") {
+ for (const auto &entry : _moduleEntries)
+ entry.module->execute(_svg->defsNode(), _svg->pageNode());
+ }
+ else {
+ vector<string> names = util::split(MODULE_SEQUENCE, ",");
+ for (const string &name : names) {
+ if (OptimizerModule *module = getModule(name))
+ module->execute(_svg->defsNode(), _svg->pageNode());
+ }
+ }
+}
+
+
+void SVGOptimizer::listModules (ostream &os) const {
+ size_t maxlen=0;
+ map<string, const char*> infos;
+ for (const auto &entry : _moduleEntries) {
+ maxlen = max(maxlen, entry.modname.length());
+ infos.emplace(entry.modname, entry.module->info());
+ }
+ for (const auto &infopair : infos) {
+ os << setw(maxlen) << left << infopair.first;
+ os << " | " << infopair.second << '\n';
+ }
+}
+
+
+/** Checks if all module names given in a comma-separated list are known.
+ * @param[in] namestr comma-separated list of module names
+ * @param[out] unknownNames names not recognized
+ * @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")
+ return true;
+ vector<string> givenNames = util::split(namestr, ",");
+ for (const string &name : givenNames) {
+ if (!getModule(name))
+ unknownNames.emplace_back(name);
+ }
+ return unknownNames.empty();
+}
+
+
+OptimizerModule* SVGOptimizer::getModule (const string &name) const {
+ auto it = find_if(_moduleEntries.begin(), _moduleEntries.end(), [&](const ModuleEntry &entry) {
+ return entry.modname == name;
+ });
+ if (it != _moduleEntries.end())
+ return (*it).module.get();
+ return nullptr;
+}
+
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/SVGOptimizer.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/SVGOptimizer.hpp
new file mode 100644
index 00000000000..809f1f497c2
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/SVGOptimizer.hpp
@@ -0,0 +1,59 @@
+/*************************************************************************
+** SVGOptimizer.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 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/>. **
+*************************************************************************/
+
+#pragma once
+
+#include <memory>
+#include <ostream>
+#include <set>
+#include <vector>
+#include "OptimizerModule.hpp"
+#include "../XMLNode.hpp"
+
+class SVGTree;
+
+class SVGOptimizer {
+ struct ModuleEntry {
+ ModuleEntry (std::string name, std::unique_ptr<OptimizerModule> mod)
+ : modname(std::move(name)), module(std::move(mod)) {}
+
+ std::string modname;
+ std::unique_ptr<OptimizerModule> module;
+ };
+ public:
+ explicit SVGOptimizer (SVGTree *svg=nullptr);
+ explicit SVGOptimizer (SVGTree &svg) : SVGOptimizer(&svg) {}
+ void execute ();
+ void listModules (std::ostream &os) const;
+ bool checkModuleString (std::string &namestr, std::vector<std::string> &unknownNames) const;
+
+ static std::string MODULE_SEQUENCE;
+
+ protected:
+ OptimizerModule* getModule (const std::string &name) const;
+
+ private:
+ SVGTree *_svg;
+ std::vector<ModuleEntry> _moduleEntries;
+};
+
+
+
+
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TextSimplifier.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TextSimplifier.cpp
new file mode 100644
index 00000000000..23e0e386dfe
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TextSimplifier.cpp
@@ -0,0 +1,118 @@
+/*************************************************************************
+** TextSimplifier.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** This program is free software; you can redistribute it and/or **
+** modify it under the terms of the GNU General Public License as **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include <vector>
+#include "AttributeExtractor.hpp"
+#include "TextSimplifier.hpp"
+#include "../XMLNode.hpp"
+
+using namespace std;
+
+
+const char* TextSimplifier::info () const {
+ return "merge data of tspans into enclosing text elements";
+}
+
+
+/** Returns all common inheritable attributes of multiple elements. */
+static XMLElement::Attributes common_inheritable_attributes (const vector<XMLElement*> &elements) {
+ bool intersected=false;
+ XMLElement::Attributes commonAttribs;
+ for (const XMLElement *elem : elements) {
+ if (commonAttribs.empty()) {
+ if (intersected)
+ break;
+ for (const auto attrib : elem->attributes()) {
+ if (AttributeExtractor::inheritable(attrib))
+ commonAttribs.push_back(attrib);
+ }
+ }
+ else {
+ for (auto it = commonAttribs.begin(); it != commonAttribs.end();) {
+ auto *attrib = elem->getAttribute(it->name);
+ if (!attrib || attrib->value != it->value)
+ it = commonAttribs.erase(it);
+ else
+ ++it;
+ }
+ }
+ intersected = true;
+ }
+ return commonAttribs;
+}
+
+
+/** Returns all tspan elements of a text element if the latter doesn't contain
+ * any non-whitespace text nodes. Otherwise, the returned vector is empty.
+ * @param[in] textElement text element to check
+ * @return the tspan children of the text element */
+static vector<XMLElement*> get_tspans (XMLElement *textElement) {
+ vector<XMLElement*> tspans;
+ bool failed=false;
+ for (XMLNode *child : *textElement) {
+ if (child->toWSNode() || child->toComment())
+ continue;
+ if (child->toText())
+ failed = true;
+ else if (XMLElement *childElement = child->toElement()) {
+ if (childElement->name() != "tspan")
+ failed = true;
+ else
+ tspans.push_back(childElement);
+ }
+ if (failed) {
+ tspans.clear();
+ break;
+ }
+ }
+ return tspans;
+}
+
+
+void TextSimplifier::execute (XMLElement *context) {
+ if (!context)
+ return;
+ if (context->name() == "text") {
+ vector<XMLElement*> tspans = get_tspans(context);
+ vector<XMLElement::Attribute> attribs = common_inheritable_attributes(tspans);
+ if (!tspans.empty() && !attribs.empty()) {
+ // move all common tspan attributes to the parent text element
+ for (const XMLElement::Attribute &attr : attribs)
+ context->addAttribute(attr.name, attr.value);
+ // remove all common attributes from the tspan elements
+ for (XMLElement *tspan : tspans) {
+ for (const XMLElement::Attribute &attr : attribs)
+ tspan->removeAttribute(attr.name);
+ // unwrap the tspan if there are no remaining attributes
+ if (tspan->attributes().empty())
+ XMLElement::unwrap(tspan);
+ }
+ }
+ }
+ else {
+ XMLNode *node = context->firstChild();
+ while (node) {
+ XMLNode *next = node->next(); // keep safe pointer to next node
+ if (XMLElement *elem = node->toElement())
+ execute(elem);
+ node = next;
+ }
+ }
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TextSimplifier.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TextSimplifier.hpp
new file mode 100644
index 00000000000..86f44e50518
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TextSimplifier.hpp
@@ -0,0 +1,30 @@
+/*************************************************************************
+** TextSimplifier.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 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/>. **
+*************************************************************************/
+
+#pragma once
+
+#include "OptimizerModule.hpp"
+
+class TextSimplifier : public OptimizerModule {
+ public:
+ void execute (XMLElement *defs, XMLElement *context) override {execute(context);}
+ static void execute (XMLElement *context);
+ const char *info () const override;
+};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TransformSimplifier.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TransformSimplifier.cpp
new file mode 100644
index 00000000000..b9d4c3db596
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TransformSimplifier.cpp
@@ -0,0 +1,182 @@
+/*************************************************************************
+** TransformSimplifier.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** This program is free software; you can redistribute it and/or **
+** modify it under the terms of the GNU General Public License as **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include <cmath>
+#include <cstdlib>
+#include "TransformSimplifier.hpp"
+#include "../Matrix.hpp"
+#include "../utility.hpp"
+#include "../XMLNode.hpp"
+#include "../XMLString.hpp"
+
+using namespace std;
+
+const char* TransformSimplifier::info () const {
+ return "try to simplify and shorten the values of 'transform' attributes";
+}
+
+
+/** Tries to simplify the transform attributes of the context node and all its descendants. */
+void TransformSimplifier::execute (XMLElement *context) {
+ if (!context)
+ return;
+ if (const char *transform = context->getAttributeValue("transform")) {
+ Matrix matrix = Matrix::parseSVGTransform(transform);
+ if (!incorporateTransform(context, matrix)) {
+ string decomp = decompose(matrix);
+ if (decomp.length() > matrix.toSVG().length())
+ context->addAttribute("transform", matrix.toSVG());
+ else {
+ if (decomp.empty())
+ context->removeAttribute("transform");
+ else
+ context->addAttribute("transform", decomp);
+ }
+ }
+ }
+ // continue with child elements
+ for (XMLNode *child : *context) {
+ if (XMLElement *elem = child->toElement())
+ execute(elem);
+ }
+}
+
+
+/** Tries to incorporate the translation and scaling components of the 'transform' attribute
+ * of a given element into the positional and/or size attributes of that element. If successful,
+ * the 'transform' attribute is removed.
+ * Currently, only 'image' and 'rect' elements are considered.
+ * @param[in] elem element to check
+ * @param[in] matrix matrix representing the 'transform' attribute of the element
+ * @return true on success */
+bool TransformSimplifier::incorporateTransform (XMLElement *elem, const Matrix &matrix) {
+ if ((elem->name() == "image" || elem->name() == "rect") && matrix.get(0, 1) == 0 && matrix.get(1, 0) == 0) {
+ double tx = matrix.get(0, 2);
+ double ty = matrix.get(1, 2);
+ double sx = matrix.get(0, 0);
+ double sy = matrix.get(1, 1);
+ if (const char *xstr = elem->getAttributeValue("x"))
+ tx += sx*strtod(xstr, nullptr);
+ if (const char *ystr = elem->getAttributeValue("y"))
+ ty += sy*strtod(ystr, nullptr);
+ if (const char *wstr = elem->getAttributeValue("width"))
+ elem->addAttribute("width", sx*strtod(wstr, nullptr));
+ if (const char *hstr = elem->getAttributeValue("height"))
+ elem->addAttribute("height", sy*strtod(hstr, nullptr));
+ elem->addAttribute("x", tx); // update x attribute
+ elem->addAttribute("y", ty); // update x attribute
+ elem->removeAttribute("transform");
+ return true;
+ }
+ return false;
+}
+
+
+static string translate_cmd (double dx, double dy) {
+ string ret;
+ XMLString dxstr(dx), dystr(dy);
+ if (dxstr != "0" || dystr != "0") {
+ ret = "translate("+dxstr;
+ if (dystr != "0")
+ ret += " "+dystr;
+ ret += ')';
+ }
+ return ret;
+}
+
+
+static string scale_cmd (double sx, double sy) {
+ string ret;
+ XMLString sxstr(sx), systr(sy);
+ if (sxstr != "1" || systr != "1") {
+ ret = "scale("+sxstr;
+ if (systr != "1")
+ ret += " "+systr;
+ ret += ')';
+ }
+ return ret;
+}
+
+
+static string rotate_cmd (double rad) {
+ string ret;
+ XMLString degstr(math::rad2deg(fmod(rad, math::TWO_PI)));
+ if (degstr != "0")
+ ret = "rotate("+degstr+")";
+ return ret;
+}
+
+
+static string skewx_cmd (double rad) {
+ string ret;
+ XMLString degstr(math::rad2deg(fmod(rad, math::PI)));
+ if (degstr != "0")
+ ret = "skewX("+degstr+")";
+ return ret;
+}
+
+
+static string skewy_cmd (double rad) {
+ string ret;
+ XMLString degstr(math::rad2deg(fmod(rad, math::PI)));
+ if (degstr != "0")
+ ret = "skewY("+degstr+")";
+ return ret;
+}
+
+
+static bool not_equal (double x, double y) {
+ return abs(x-y) >= 1e-6;
+}
+
+
+/** Decomposes a transformation matrix into a sequence of basic SVG transformations, i.e.
+ * translation, rotation, scaling, and skewing. The algorithm (QR-based decomposition)
+ * is taken from http://frederic-wang.fr/decomposition-of-2d-transform-matrices.html.
+ * @param[in] matrix matrix to decompose
+ * @return string containing the SVG transformation commands */
+string TransformSimplifier::decompose (const Matrix &matrix) {
+ // transformation matrix [a b c d e f] according to
+ // https://www.w3.org/TR/SVG11/coords.html#EstablishingANewUserSpace
+ double a = matrix.get(0, 0);
+ double b = matrix.get(1, 0);
+ double c = matrix.get(0, 1);
+ double d = matrix.get(1, 1);
+ double e = matrix.get(0, 2);
+ double f = matrix.get(1, 2);
+ string ret = translate_cmd(e, f);
+ double delta = a*d - b*c;
+ if (not_equal(a, 0) || not_equal(b, 0)) {
+ double r = sqrt(a*a + b*b);
+ ret += rotate_cmd(b > 0 ? acos(a/r) : -acos(a/r));
+ ret += scale_cmd(r, delta/r);
+ ret += skewx_cmd(atan((a*c + b*d)/(r*r)));
+ }
+ else if (not_equal(c, 0) || not_equal(d, 0)) {
+ double s = sqrt(c*c + d*d);
+ ret += rotate_cmd(math::HALF_PI - (d > 0 ? acos(-c/s) : -acos(c/s)));
+ ret += scale_cmd(delta/s, s);
+ ret += skewy_cmd(atan((a*c + b*d)/(s*s)));
+ }
+ else
+ ret += scale_cmd(0, 0);
+ return ret;
+}
+
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TransformSimplifier.hpp
index 880f8b737ef..c4b6d9ee16e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/CRC32.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/TransformSimplifier.hpp
@@ -1,5 +1,5 @@
/*************************************************************************
-** CRC32.hpp **
+** TransformSimplifier.hpp **
** **
** This file is part of dvisvgm -- a fast DVI to SVG converter **
** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
@@ -18,30 +18,20 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
-#ifndef CRC32_HPP
-#define CRC32_HPP
+#pragma once
-#include <cstdlib>
-#include <istream>
+#include <string>
+#include "OptimizerModule.hpp"
-class CRC32 {
+class Matrix;
+
+class TransformSimplifier : public OptimizerModule {
public:
- CRC32 ();
- CRC32 (const CRC32 &crc32) =delete;
- void update (const uint8_t *bytes, size_t len);
- void update (uint32_t n, int bytes=4);
- void update (const char *str);
- void update (std::istream &is);
- uint32_t get () const;
- void reset ();
- static uint32_t compute (const uint8_t *bytes, size_t len);
- static uint32_t compute (const char *str);
- static uint32_t compute (std::istream &is);
+ void execute (XMLElement*, XMLElement *context) override {execute(context);}
+ void execute (XMLElement *context);
+ const char* info () const override;
- private:
- uint32_t _crc32;
- uint32_t _tab[256];
+ protected:
+ bool incorporateTransform (XMLElement *elem, const Matrix &matrix);
+ std::string decompose (const Matrix &matrix);
};
-
-
-#endif
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/WSNodeRemover.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/WSNodeRemover.cpp
new file mode 100644
index 00000000000..2135e285bb6
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/WSNodeRemover.cpp
@@ -0,0 +1,45 @@
+/*************************************************************************
+** WSNodeRemover.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** This program is free software; you can redistribute it and/or **
+** modify it under the terms of the GNU General Public License as **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include "WSNodeRemover.hpp"
+#include "../XMLNode.hpp"
+
+const char* WSNodeRemover::info () const {
+ return "remove redundant whitespace nodes";
+}
+
+
+void WSNodeRemover::execute (XMLElement *context) {
+ if (!context)
+ return;
+ bool removeWS = context->name() != "text" && context->name() != "tspan";
+ XMLNode *child = context->firstChild();
+ while (child) {
+ if (removeWS && child->toWSNode()) {
+ XMLNode *next = child->next();
+ XMLElement::remove(child);
+ child = next;
+ continue;
+ }
+ if (XMLElement *elem = child->toElement())
+ execute(elem);
+ child = child->next();
+ }
+}
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/WSNodeRemover.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/WSNodeRemover.hpp
new file mode 100644
index 00000000000..c4fe7f989e1
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/WSNodeRemover.hpp
@@ -0,0 +1,30 @@
+/*************************************************************************
+** WSNodeRemover.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2019 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/>. **
+*************************************************************************/
+
+#pragma once
+
+#include "OptimizerModule.hpp"
+
+class WSNodeRemover : public OptimizerModule {
+ public:
+ void execute (XMLElement*, XMLElement *context) override {execute(context);};
+ void execute (XMLElement *context);
+ const char* info () const override;
+};
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml b/Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml
index 0764db3e5b8..27975f15910 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/options.xml
@@ -81,6 +81,10 @@
<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>
@@ -141,8 +145,8 @@
<arg type="string" name="dir" optional="yes"/>
<description>set/print path of cache directory</description>
</option>
- <option long="exact" short="e">
- <description>compute exact glyph boxes</description>
+ <option long="exact-bbox" short="e">
+ <description>compute exact glyph bounding boxes</description>
</option>
<option long="keep">
<description>keep temporary files</description>
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp
index 5baf1a0bc0a..d38e2354e0a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/psdefs.cpp
@@ -22,93 +22,103 @@
const char *PSInterpreter::PSDEFS =
"<</Install{matrix setmatrix}/HWResolution[72 72]/PageSize[10000 10000]/Imaging"
-"BBox null>>setpagedevice/@dodraw true store/@patcnt 0 store/@SD systemdict def"
-"/@UD userdict def true setglobal @SD/:save @SD/save get put @SD/:restore @SD/r"
-"estore get put @SD/:gsave @SD/gsave get put @SD/:grestore @SD/grestore get put"
-" @SD/:grestoreall @SD/grestoreall get put @SD/:newpath @SD/newpath get put @SD"
-"/:stroke @SD/stroke get put @SD/:fill @SD/fill get put @SD/:eofill @SD/eofill "
-"get put @SD/:clip @SD/clip get put @SD/:eoclip @SD/eoclip get put @SD/:charpat"
-"h @SD/charpath get put @SD/:show @SD/show get put @SD/:stringwidth @SD/stringw"
-"idth get put @SD/.setopacityalpha known not{@SD/.setopacityalpha{pop}put}if @S"
-"D/.setshapealpha known not{@SD/.setshapealpha{pop}put}if @SD/.setblendmode kno"
-"wn not{@SD/.setblendmode{pop}put}if @SD/prseq{-1 1{-1 roll =only( )print}for(\\"
-"n)print}put @SD/prcmd{( )exch(\\ndvi.)3{print}repeat prseq}put @SD/cvxall{{cvx"
-"}forall}put @SD/defpr{[exch[/copy @SD]cvxall 5 -1 roll dup 6 1 roll[/get/exec]"
-"cvxall 6 -1 roll dup 7 1 roll 4 -1 roll dup 5 1 roll dup length string cvs/prc"
-"md cvx]cvx def}put @SD/querypos{{currentpoint}stopped{$error/newerror false pu"
-"t}{2(querypos)prcmd}ifelse}put @SD/applyscalevals{1 0 dtransform exch dup mul "
-"exch dup mul add sqrt 0 1 dtransform exch dup mul exch dup mul add sqrt 1 0 dt"
-"ransform dup mul exch dup dup mul 3 -1 roll add dup 0 eq{pop}{sqrt div}ifelse "
-"3(applyscalevals)prcmd}put @SD/prpath{{2(moveto)prcmd}{2(lineto)prcmd}{6(curve"
-"to)prcmd}{0(closepath)prcmd}pathforall}put @SD/charpath{/@dodraw false store :"
-"charpath/@dodraw true store}put @SD/stringwidth{/@dodraw false store :stringwi"
-"dth/@dodraw true store}put @SD/show{@dodraw{dup :gsave currentpoint 2{50 mul e"
-"xch}repeat :newpath moveto 50 50/scale sysexec true charpath fill :grestore/@d"
-"odraw false store :show/@dodraw true store}{:show}ifelse}put @SD/awidthshow{{1"
-" string dup 0 5 index put :gsave show :grestore pop 0 rmoveto 3 index eq{4 ind"
-"ex 4 index rmoveto}if 1 index 1 index rmoveto}exch cshow 5{pop}repeat}put @SD/"
-"widthshow{0 0 3 -1 roll pstack awidthshow}put @SD/ashow{0 0 0 6 3 roll awidths"
-"how}put @SD/newpath{:newpath 1 1(newpath)prcmd}put @SD/stroke{@dodraw{prcolor "
-"0 1(newpath)prcmd prpath 0(stroke)prcmd :newpath}{:stroke}ifelse}put @SD/fill{"
-"@dodraw{prcolor 0 1(newpath)prcmd prpath 0(fill)prcmd :newpath}{:fill}ifelse}p"
-"ut @SD/eofill{@dodraw{prcolor 0 1(newpath)prcmd prpath 0(eofill)prcmd :newpath"
-"}{:eofill}ifelse}put @SD/clip{:clip 0 1(newpath)prcmd prpath 0(clip)prcmd}put "
-"@SD/eoclip{:eoclip 0 1(newpath)prcmd prpath 0(eoclip)prcmd}put @SD/shfill{begi"
-"n currentdict/ShadingType known currentdict/ColorSpace known and currentdict/D"
-"ataSource known and currentdict/Function known not and ShadingType 4 ge and Da"
-"taSource type/arraytype eq and{<</DeviceGray 1/DeviceRGB 3/DeviceCMYK 4/bgknow"
-"n currentdict/Background known/bbknown currentdict/BBox known>>begin currentdi"
-"ct ColorSpace known{ShadingType ColorSpace load bgknown{1 Background aload pop"
-"}{0}ifelse bbknown{1 BBox aload pop}{0}ifelse ShadingType 5 eq{VerticesPerRow}"
-"if DataSource aload length 4 add bgknown{ColorSpace load add}if bbknown{4 add}"
-"if ShadingType 5 eq{1 add}if(shfill)prcmd}if end}if end}put/@rect{4 -2 roll mo"
-"veto 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 rl"
-"ineto neg 0 exch rlineto}{exch dup 0 rlineto exch 0 exch rlineto neg 0 rlineto"
-"}ifelse closepath}bind def @SD/rectclip{:newpath dup type/arraytype eq{aload l"
-"ength 4 idiv{@rectcc}repeat}{@rectcc}ifelse clip :newpath}put @SD/rectfill{gsa"
-"ve :newpath dup type/arraytype eq{aload length 4 idiv{@rectcc}repeat}{@rectcc}"
-"ifelse fill grestore}put @SD/rectstroke{gsave :newpath dup type/arraytype eq{a"
-"load length 4 idiv{@rect}repeat}{@rect}ifelse stroke grestore}put false setglo"
-"bal @SD readonly pop/initclip 0 defpr/clippath 0 defpr/sysexec{@SD exch get ex"
-"ec}def/adddot{dup length 1 add string dup 0 46 put dup 3 -1 roll 1 exch putint"
-"erval}def/setlinewidth{dup/setlinewidth sysexec 1(setlinewidth)prcmd}def/setli"
-"necap 1 defpr/setlinejoin 1 defpr/setmiterlimit 1 defpr/setdash{mark 3 1 roll "
-"2 copy/setdash sysexec exch aload length 1 add -1 roll counttomark(setdash)prc"
-"md pop}def/@setpagedevice{pop<<>>/setpagedevice sysexec matrix setmatrix newpa"
-"th 0(setpagedevice)prcmd}def/prcolor{currentrgbcolor 3(setrgbcolor)prcmd}def/p"
-"rintgstate{@dodraw{matrix currentmatrix aload pop 6(setmatrix)prcmd applyscale"
-"vals currentlinewidth 1(setlinewidth)prcmd currentlinecap 1(setlinecap)prcmd c"
-"urrentlinejoin 1(setlinejoin)prcmd currentmiterlimit 1(setmiterlimit)prcmd cur"
-"rentrgbcolor 3(setrgbcolor)prcmd currentdash mark 3 1 roll exch aload length 1"
-" add -1 roll counttomark(setdash)prcmd pop}if}def/setgstate{/setgstate sysexec"
-" printgstate}def/save{@UD begin/@saveID vmstatus pop pop def end :save @saveID"
-" 1(save)prcmd}def/restore{:restore printgstate @UD/@saveID known{@UD begin @sa"
-"veID end}{0}ifelse 1(restore)prcmd}def/gsave 0 defpr/grestore{:grestore printg"
-"state 0(grestore)prcmd}def/grestoreall{:grestoreall setstate 0(grestoreall)prc"
-"md}def/rotate{dup type/arraytype ne @dodraw and{dup 1(rotate)prcmd}if/rotate s"
-"ysexec applyscalevals}def/scale{dup type/arraytype ne @dodraw and{2 copy 2(sca"
-"le)prcmd}if/scale sysexec applyscalevals}def/translate{dup type/arraytype ne @"
-"dodraw and{2 copy 2(translate)prcmd}if/translate sysexec}def/setmatrix{dup/set"
-"matrix sysexec @dodraw{aload pop 6(setmatrix)prcmd applyscalevals}if}def/initm"
-"atrix{matrix setmatrix}def/concat{matrix currentmatrix matrix concatmatrix set"
-"matrix}def/makepattern{gsave<</mx 3 -1 roll>>begin dup/XUID[1000000 @patcnt]pu"
-"t mx/makepattern sysexec dup dup begin PatternType @patcnt BBox aload pop XSte"
-"p YStep PaintType mx aload pop 15(makepattern)prcmd :newpath matrix setmatrix "
-"PaintProc 0 1(makepattern)prcmd end/@patcnt @patcnt 1 add store end grestore}d"
-"ef/setpattern{begin PatternType 1 eq{PaintType 1 eq{XUID aload pop exch pop 1}"
-"{:gsave[currentcolorspace aload length -1 roll pop]setcolorspace/setcolor syse"
-"xec XUID aload pop exch pop currentrgbcolor :grestore 4}ifelse(setpattern)prcm"
-"d}{/setpattern sysexec}ifelse end}def/setcolor{dup type/dicttype eq{setpattern"
-"}{/setcolor sysexec/currentrgbcolor sysexec setrgbcolor}ifelse}def/setgray 1 d"
-"efpr/setcmykcolor 4 defpr/sethsbcolor 3 defpr/setrgbcolor 3 defpr/.setopacitya"
-"lpha{dup/.setopacityalpha sysexec 1(setopacityalpha)prcmd}def/.setshapealpha{d"
-"up/.setshapealpha sysexec 1(setshapealpha)prcmd}def/.setblendmode{dup/.setblen"
-"dmode sysexec<</Normal 0/Compatible 0/Multiply 1/Screen 2/Overlay 3/SoftLight "
-"4/HardLight 5/ColorDodge 6/ColorBurn 7/Darken 8/Lighten 9/Difference 10/Exclus"
-"ion 11/Hue 12/Saturation 13/Color 14/Luminosity 15/CompatibleOverprint 16>>exc"
-"h get 1(setblendmode)prcmd}def/@pdfpagecount{GS_PDF_ProcSet begin pdfdict begi"
-"n(r)file pdfopen begin pdfpagecount currentdict pdfclose end end end}def/@pdfp"
-"agebox{GS_PDF_ProcSet begin pdfdict begin(r)file pdfopen begin dup dup 1 lt ex"
-"ch pdfpagecount gt or{pop}{pdfgetpage/MediaBox pget pop aload pop}ifelse curre"
-"ntdict pdfclose end end end}def DELAYBIND{.bindnow}if ";
+"BBox null>>setpagedevice/@dodraw true store/@nulldev false store/@patcnt 0 sto"
+"re/@SD systemdict def/@UD userdict def true setglobal @SD/:save @SD/save get p"
+"ut @SD/:restore @SD/restore get put @SD/:gsave @SD/gsave get put @SD/:grestore"
+" @SD/grestore get put @SD/:grestoreall @SD/grestoreall get put @SD/:newpath @S"
+"D/newpath get put @SD/:stroke @SD/stroke get put @SD/:fill @SD/fill get put @S"
+"D/:eofill @SD/eofill get put @SD/:clip @SD/clip get put @SD/:eoclip @SD/eoclip"
+" get put @SD/:charpath @SD/charpath get put @SD/:show @SD/show get put @SD/:st"
+"ringwidth @SD/stringwidth get put @SD/:nulldevice @SD/nulldevice get put @SD/."
+"setopacityalpha known not{@SD/.setopacityalpha{pop}put}if @SD/.setshapealpha k"
+"nown not{@SD/.setshapealpha{pop}put}if @SD/.setblendmode known not{@SD/.setble"
+"ndmode{pop}put}if @SD/prseq{-1 1{-1 roll =only( )print}for(\\n)print}put @SD/p"
+"rcmd{( )exch(\\ndvi.)3{print}repeat prseq}put @SD/cvxall{{cvx}forall}put @SD/d"
+"efpr{[exch[/copy @SD]cvxall 5 -1 roll dup 6 1 roll[/get/exec]cvxall 6 -1 roll "
+"dup 7 1 roll 4 -1 roll dup 5 1 roll dup length string cvs/prcmd cvx]cvx def}pu"
+"t @SD/querypos{{currentpoint}stopped{$error/newerror false put}{2(querypos)prc"
+"md}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 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(close"
+"path)prcmd}pathforall}put @SD/nulldevice{/@nulldev true store :nulldevice 1 1("
+"setnulldevice)prcmd}put @SD/charpath{/@dodraw false store :charpath/@dodraw tr"
+"ue store}put @SD/stringwidth{/@dodraw false store :stringwidth/@dodraw true st"
+"ore}put @SD/show{@dodraw @nulldev not and{dup :gsave currentpoint 2{50 mul exc"
+"h}repeat :newpath moveto 50 50/scale sysexec true charpath fill :grestore/@dod"
+"raw false store :show/@dodraw true store}{:show}ifelse}put @SD/varxyshow{exch "
+"dup type/arraytype eq{<</arr 3 -1 roll/prc 5 -1 roll/chr 1 string/idx 0>>begin"
+"{chr 0 3 -1 roll put :gsave chr show :grestore currentpoint prc moveto/idx idx"
+" 1 add store}forall end}{pop show}ifelse}put @SD/xyshow{{exch arr idx 2 mul ge"
+"t add exch arr idx 2 mul 1 add get add}varxyshow}put @SD/xshow{{exch arr idx g"
+"et add exch}varxyshow}put @SD/yshow{{arr idx get add}varxyshow}put @SD/awidths"
+"how{{1 string dup 0 5 index put :gsave show :grestore pop 0 rmoveto 3 index eq"
+"{4 index 4 index rmoveto}if 1 index 1 index rmoveto}exch cshow 5{pop}repeat}pu"
+"t @SD/widthshow{0 0 3 -1 roll pstack awidthshow}put @SD/ashow{0 0 0 6 3 roll a"
+"widthshow}put @SD/newpath{:newpath 1 1(newpath)prcmd}put @SD/stroke{@dodraw @n"
+"ulldev not and{prcolor 0 1(newpath)prcmd prpath 0(stroke)prcmd :newpath}{:stro"
+"ke}ifelse}put @SD/fill{@dodraw @nulldev not and{prcolor 0 1(newpath)prcmd prpa"
+"th 0(fill)prcmd :newpath}{:fill}ifelse}put @SD/eofill{@dodraw @nulldev not and"
+"{prcolor 0 1(newpath)prcmd prpath 0(eofill)prcmd :newpath}{:eofill}ifelse}put "
+"@SD/clip{:clip @nulldev not{0 1(newpath)prcmd prpath 0(clip)prcmd}if}put @SD/e"
+"oclip{:eoclip @nulldev not{0 1(newpath)prcmd prpath 0(eoclip)prcmd}}put @SD/sh"
+"fill{begin currentdict/ShadingType known currentdict/ColorSpace known and curr"
+"entdict/DataSource known and currentdict/Function known not and ShadingType 4 "
+"ge and DataSource type/arraytype eq and{<</DeviceGray 1/DeviceRGB 3/DeviceCMYK"
+" 4/bgknown currentdict/Background known/bbknown currentdict/BBox known>>begin "
+"currentdict ColorSpace known{ShadingType ColorSpace load bgknown{1 Background "
+"aload pop}{0}ifelse bbknown{1 BBox aload pop}{0}ifelse ShadingType 5 eq{Vertic"
+"esPerRow}if DataSource aload length 4 add bgknown{ColorSpace load add}if bbkno"
+"wn{4 add}if ShadingType 5 eq{1 add}if(shfill)prcmd}if end}if end}put/@rect{4 -"
+"2 roll moveto exch dup 0 rlineto exch 0 exch rlineto neg 0 rlineto closepath}b"
+"ind 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 closepath}bind def @SD/rectclip{:newpath dup type/arraytype e"
+"q{aload length 4 idiv{@rectcc}repeat}{@rectcc}ifelse clip :newpath}put @SD/rec"
+"tfill{gsave :newpath dup type/arraytype eq{aload length 4 idiv{@rectcc}repeat}"
+"{@rectcc}ifelse fill grestore}put @SD/rectstroke{gsave :newpath dup type/array"
+"type eq{aload length 4 idiv{@rect}repeat}{@rect}ifelse stroke grestore}put fal"
+"se setglobal @SD readonly pop/initclip 0 defpr/clippath 0 defpr/sysexec{@SD ex"
+"ch get exec}def/adddot{dup length 1 add string dup 0 46 put dup 3 -1 roll 1 ex"
+"ch putinterval}def/setlinewidth{dup/setlinewidth sysexec 1(setlinewidth)prcmd}"
+"def/setlinecap 1 defpr/setlinejoin 1 defpr/setmiterlimit 1 defpr/setdash{mark "
+"3 1 roll 2 copy/setdash sysexec exch aload length 1 add -1 roll counttomark(se"
+"tdash)prcmd pop}def/@setpagedevice{pop<<>>/setpagedevice sysexec matrix setmat"
+"rix newpath 0(setpagedevice)prcmd}def/@checknulldev{@nulldev{currentpagedevice"
+" maxlength 0 ne{/@nulldev false store 0 1(setnulldevice)prcmd}if}if}def/prcolo"
+"r{currentrgbcolor 3(setrgbcolor)prcmd}def/printgstate{@dodraw @nulldev not and"
+"{matrix currentmatrix aload pop 6(setmatrix)prcmd applyscalevals currentlinewi"
+"dth 1(setlinewidth)prcmd currentlinecap 1(setlinecap)prcmd currentlinejoin 1(s"
+"etlinejoin)prcmd currentmiterlimit 1(setmiterlimit)prcmd currentrgbcolor 3(set"
+"rgbcolor)prcmd currentdash mark 3 1 roll exch aload length 1 add -1 roll count"
+"tomark(setdash)prcmd pop}if}def/setgstate{/setgstate sysexec printgstate}def/s"
+"ave{@UD begin/@saveID vmstatus pop pop def end :save @saveID 1(save)prcmd}def/"
+"restore{:restore @checknulldev printgstate @UD/@saveID known{@UD begin @saveID"
+" end}{0}ifelse 1(restore)prcmd}def/gsave 0 defpr/grestore{:grestore @checknull"
+"dev printgstate 0(grestore)prcmd}def/grestoreall{:grestoreall @checknulldev se"
+"tstate 0(grestoreall)prcmd}def/rotate{dup type/arraytype ne @dodraw and{dup 1("
+"rotate)prcmd}if/rotate sysexec applyscalevals}def/scale{dup type/arraytype 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/translate sysex"
+"ec}def/setmatrix{dup/setmatrix sysexec @dodraw{aload pop 6(setmatrix)prcmd app"
+"lyscalevals}{pop}ifelse}def/initmatrix{matrix setmatrix}def/concat{matrix curr"
+"entmatrix matrix concatmatrix setmatrix}def/makepattern{gsave<</mx 3 -1 roll>>"
+"begin dup/XUID[1000000 @patcnt]put mx/makepattern sysexec dup dup begin Patter"
+"nType @patcnt BBox aload pop XStep YStep PaintType mx aload pop 15(makepattern"
+")prcmd :newpath matrix setmatrix PaintProc 0 1(makepattern)prcmd end/@patcnt @"
+"patcnt 1 add store end grestore}def/setpattern{begin PatternType 1 eq{PaintTyp"
+"e 1 eq{XUID aload pop exch pop 1}{:gsave[currentcolorspace aload length -1 rol"
+"l pop]setcolorspace/setcolor sysexec XUID aload pop exch pop currentrgbcolor :"
+"grestore 4}ifelse(setpattern)prcmd}{/setpattern sysexec}ifelse end}def/setcolo"
+"r{dup type/dicttype eq{setpattern}{/setcolor sysexec/currentrgbcolor sysexec s"
+"etrgbcolor}ifelse}def/setgray 1 defpr/setcmykcolor 4 defpr/sethsbcolor 3 defpr"
+"/setrgbcolor 3 defpr/.setopacityalpha{dup/.setopacityalpha sysexec 1(setopacit"
+"yalpha)prcmd}def/.setshapealpha{dup/.setshapealpha sysexec 1(setshapealpha)prc"
+"md}def/.setblendmode{dup/.setblendmode sysexec<</Normal 0/Compatible 0/Multipl"
+"y 1/Screen 2/Overlay 3/SoftLight 4/HardLight 5/ColorDodge 6/ColorBurn 7/Darken"
+" 8/Lighten 9/Difference 10/Exclusion 11/Hue 12/Saturation 13/Color 14/Luminosi"
+"ty 15/CompatibleOverprint 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}ifelse runpdfend}def DELAYBIND{.bindnow}if ";
+
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp
index 99e8e194a02..f1ae59ec08e 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.cpp
@@ -20,6 +20,7 @@
#include <algorithm>
#include <cctype>
+#include <cmath>
#include <fstream>
#include <functional>
#include <iterator>
@@ -27,6 +28,56 @@
using namespace std;
+/** Computes the singular value decomposition of a given 2x2 matrix M
+ * so that M = rotate(phi)*scale(sx,sy)*rotate(theta), where
+ * rotate(t):={{cos t, -sin t}, {sin t, cos t}} and scale(sx, sy):={{sx, 0}, {0, sy}}.
+ * The corresponding math can be found in Jim Blinn: "Consider the Lowly 2x2 Matrix"
+ * https://ieeexplore.ieee.org/document/486688
+ * Also published in "Jim Blinn's Corner: Notation, Notation, Notation", pp. 69--95.
+ * @param[in] m matrix {{m00, m01}, {m10, m11}} where the inner pairs denote the rows
+ * @return vector {phi, sx, sy, theta} */
+vector<double> math::svd (const double (&m)[2][2]) {
+ double phi=0, theta=0, sx=0, sy=0;
+ if (m[0][0] != 0 || m[0][1] != 0 || m[1][0] != 0 || m[1][1] != 0) {
+ double e = (m[0][0] + m[1][1])/2; // = cos(phi+theta)*(sx+sy)/2
+ double f = (m[0][0] - m[1][1])/2; // = cos(phi-theta)*(sx-sy)/2
+ double g = (m[1][0] + m[0][1])/2; // = sin(phi-theta)*(sx-sy)/2
+ double h = (m[1][0] - m[0][1])/2; // = sin(phi+theta)*(sx+sy)/2
+ double hyp1 = hypot(e, h); // = (sx+sy)/2
+ double hyp2 = hypot(f, g); // = (sx-sy)/2
+ sx = hyp1+hyp2;
+ sy = hyp1-hyp2;
+ if (hyp2 == 0) // uniformly scaled rotation?
+ theta = atan2(h, e);
+ else if (hyp1 == 0) // uniformly scaled reflection?
+ theta = -atan2(g, f);
+ else {
+ double a1 = atan2(g, f); // = phi-theta (g/f = tan(phi-theta))
+ double a2 = atan2(h, e); // = phi+theta (h/e = tan(phi+theta))
+ phi = (a2+a1)/2;
+ theta = (a2-a1)/2;
+ }
+ }
+ return vector<double>{phi, sx, sy, theta};
+}
+
+
+/** Normalizes an angle to the interval [-mod, mod). */
+double math::normalize_angle (double angle, double mod) {
+ angle = fmod(angle+mod, 2.0*mod);
+ if (angle < 0)
+ angle += 2.0*mod;
+ return angle-mod;
+}
+
+
+double math::normalize_0_2pi (double rad) {
+ rad = fmod(rad, TWO_PI);
+ if (rad < 0)
+ rad += TWO_PI;
+ return rad;
+}
+
/** Returns a given string with leading and trailing whitespace removed.
* @param[in] str the string to process
@@ -109,6 +160,20 @@ string util::tolower (const string &str) {
}
+/** Converts a double to a string and strips redundant trailing digits/dots. */
+string util::to_string (double val) {
+ string str = std::to_string(val);
+ if (str.find('.') != string::npos) { // double value and not an integer?
+ size_t pos = str.find_last_not_of('0');
+ if (pos != string::npos) // trailing zeros
+ str.erase(pos+1, string::npos);
+ if (str.back() == '.') // trailing dot?
+ str.pop_back();
+ }
+ return str;
+}
+
+
/** Returns the integer part of log10 of a given integer \f$n>0\f$.
* If \f$n<0\f$, the result is 0. */
int util::ilog10 (int n) {
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp
index 905e4150dd5..7127280284a 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/utility.hpp
@@ -35,6 +35,14 @@ constexpr const double TWO_PI = 6.283185307179586476925286766559005768;
constexpr const double SQRT2 = 1.414213562373095048801688724209698079;
inline double deg2rad (double deg) {return PI*deg/180.0;}
+inline double rad2deg (double rad) {return 180.0*rad/PI;}
+double normalize_angle (double angle, double mod);
+double normalize_0_2pi (double rad);
+std::vector<double> svd (const double (&m)[2][2]);
+
+/** Signum function (returns x/abs(x) if x != 0, and 0 otherwise). */
+template <typename T>
+inline int sgn (T x) {return (x > T(0)) - (x < T(0));}
} // namespace math
@@ -51,12 +59,31 @@ std::string trim (const std::string &str, const char *ws=" \t\n\r\f");
std::string normalize_space (std::string str, const char *ws=" \t\n\r\f");
std::string tolower (const std::string &str);
std::string replace (std::string str, const std::string &find, const std::string &repl);
+std::string to_string (double val);
std::vector<std::string> split (const std::string &str, const std::string &sep);
int ilog10 (int n);
std::string read_file_contents (const std::string &fname);
void write_file_contents (const std::string &fname, std::string::iterator start, std::string::iterator end);
+
+/** Returns a sequence of bytes of a given integral value.
+ * @param[in] val get bytes of this value
+ * @param[in] n number of bytes to extract (from LSB to MSB), all if n == 0
+ * @return vector of bytes in big-endian order */
+template <typename T>
+std::vector<uint8_t> bytes (T val, int n=0) {
+ if (n <= 0)
+ n = sizeof(T);
+ std::vector<uint8_t> ret(n);
+ for (int i=0; i < n; i++) {
+ ret[n-i-1] = val & 0xff;
+ val >>= 8;
+ }
+ return ret;
+}
+
+
/** Encodes the bytes in the half-open range [first,last) to Base64 and writes
* the result to the range starting at 'dest'.
* @param[in] first initial position of the range to be encoded
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp
index 22305f75f2b..59320fa6d2d 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/version.hpp
@@ -22,7 +22,7 @@
#define VERSION_HPP
constexpr const char *PROGRAM_NAME = "dvisvgm";
-constexpr const char *PROGRAM_VERSION = "2.6.3";
+constexpr const char *PROGRAM_VERSION = "2.8.1";
#endif