summaryrefslogtreecommitdiff
path: root/dviware/dvisvgm/src
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-02-28 03:02:40 +0000
committerNorbert Preining <norbert@preining.info>2022-02-28 03:02:40 +0000
commit7a8d1925127ad121a8f591db931524f9b8eacb93 (patch)
treedf5084184ea4d6732d6a9fae1d263b6915dbb36d /dviware/dvisvgm/src
parenta911d39178540078c8ff5bc880418478d7433c40 (diff)
CTAN sync 202202280302
Diffstat (limited to 'dviware/dvisvgm/src')
-rw-r--r--dviware/dvisvgm/src/BoundingBox.cpp16
-rw-r--r--dviware/dvisvgm/src/BoundingBox.hpp1
-rw-r--r--dviware/dvisvgm/src/PsSpecialHandler.cpp23
-rw-r--r--dviware/dvisvgm/src/PsSpecialHandler.hpp1
-rw-r--r--dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp94
-rw-r--r--dviware/dvisvgm/src/optimizer/ClipPathReassigner.hpp43
-rw-r--r--dviware/dvisvgm/src/optimizer/Makefile.am6
-rw-r--r--dviware/dvisvgm/src/optimizer/Makefile.in32
-rw-r--r--dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp4
9 files changed, 198 insertions, 22 deletions
diff --git a/dviware/dvisvgm/src/BoundingBox.cpp b/dviware/dvisvgm/src/BoundingBox.cpp
index d79848f8f9..64b24fd233 100644
--- a/dviware/dvisvgm/src/BoundingBox.cpp
+++ b/dviware/dvisvgm/src/BoundingBox.cpp
@@ -23,6 +23,7 @@
#include "BoundingBox.hpp"
#include "Matrix.hpp"
#include "utility.hpp"
+#include "SVGTree.hpp"
#include "XMLNode.hpp"
#include "XMLString.hpp"
@@ -272,3 +273,18 @@ unique_ptr<XMLElement> BoundingBox::createSVGRect () const {
rect->addAttribute("fill", "none");
return rect;
}
+
+
+unique_ptr<XMLElement> BoundingBox::createSVGPath () const {
+ GraphicsPath<double> path;
+ path.moveto(minX(), minY());
+ path.lineto(maxX(), minY());
+ path.lineto(maxX(), maxY());
+ path.lineto(minX(), maxY());
+ path.closepath();
+ ostringstream oss;
+ path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS);
+ auto pathElem = util::make_unique<XMLElement>("path");
+ pathElem->addAttribute("d", oss.str());
+ return pathElem;
+} \ No newline at end of file
diff --git a/dviware/dvisvgm/src/BoundingBox.hpp b/dviware/dvisvgm/src/BoundingBox.hpp
index e9ffe2c946..51da4d04fb 100644
--- a/dviware/dvisvgm/src/BoundingBox.hpp
+++ b/dviware/dvisvgm/src/BoundingBox.hpp
@@ -79,6 +79,7 @@ class BoundingBox {
std::string svgViewBoxString () const;
std::ostream& write (std::ostream &os) const;
std::unique_ptr<XMLElement> createSVGRect () const;
+ std::unique_ptr<XMLElement> createSVGPath () const;
private:
double _ulx, _uly; ///< coordinates of upper left vertex (in PS point units)
diff --git a/dviware/dvisvgm/src/PsSpecialHandler.cpp b/dviware/dvisvgm/src/PsSpecialHandler.cpp
index ff853c72ee..45328fbd18 100644
--- a/dviware/dvisvgm/src/PsSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/PsSpecialHandler.cpp
@@ -422,18 +422,8 @@ unique_ptr<SVGElement> PsSpecialHandler::createImageNode (FileType type, const s
node->addAttribute("xlink:href", href);
}
else { // PostScript or PDF
- if (!clip)
- node = util::make_unique<SVGElement>("g");
- else {
- // clip image to its bounding box if flag 'clip' is given
- node = util::make_unique<SVGElement>("svg");
- node->addAttribute("overflow", "hidden");
- node->addAttribute("x", bbox.minX());
- node->addAttribute("y", bbox.minY());
- node->addAttribute("width", bbox.width());
- node->addAttribute("height", bbox.height());
- node->addAttribute("viewBox", bbox.svgViewBoxString());
- }
+ node = util::make_unique<SVGElement>("g"); // put SVG nodes created from the EPS/PDF file in this group
+
_xmlnode = node.get();
_psi.execute(
"\n@beginspecial @setspecial" // enter special environment
@@ -447,6 +437,14 @@ unique_ptr<SVGElement> PsSpecialHandler::createImageNode (FileType type, const s
);
if (node->empty())
node.reset(nullptr);
+ else if (clip) {
+ // clip image to its bounding box if flag 'clip' is given
+ auto clippath = util::make_unique<SVGElement>("clipPath");
+ clippath->addAttribute("id", "imgclip"+ to_string(_imgClipCount));
+ clippath->append(bbox.createSVGPath());
+ node->setClipPathUrl("imgclip"+ to_string(_imgClipCount++));
+ _actions->svgTree().appendToDefs(std::move(clippath));
+ }
_xmlnode = nullptr; // append following elements to page group again
}
return node;
@@ -485,6 +483,7 @@ static bool transform_box_extents (const Matrix &matrix, double &w, double &h, d
void PsSpecialHandler::dviBeginPage (unsigned int pageno, SpecialActions &actions) {
_psi.execute("/@imgbase("+image_base_path(actions)+")store\n"); // path and basename of image files
+ _imgClipCount = 0;
}
diff --git a/dviware/dvisvgm/src/PsSpecialHandler.hpp b/dviware/dvisvgm/src/PsSpecialHandler.hpp
index f4a9b333f4..6a35052b27 100644
--- a/dviware/dvisvgm/src/PsSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/PsSpecialHandler.hpp
@@ -184,6 +184,7 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
double _dashoffset; ///< current dash offset
std::vector<double> _dashpattern;
ClippingStack _clipStack;
+ int _imgClipCount=0; ///< current number of clip paths assigned to images
bool _makingPattern=false; ///< true if executing makepattern operator
std::map<int, std::unique_ptr<PSPattern>> _patterns;
PSTilingPattern *_pattern; ///< current pattern
diff --git a/dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp b/dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp
new file mode 100644
index 0000000000..0f684cd7eb
--- /dev/null
+++ b/dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************
+** ClipPathReassigner.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2022 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 <set>
+#include <sstream>
+#include "ClipPathReassigner.hpp"
+#include "../XMLNode.hpp"
+#include "../XXHashFunction.hpp"
+
+using namespace std;
+
+const char* ClipPathReassigner::info () const {
+ return "remove duplicate clip paths and update the references";
+}
+
+
+/** Returns a hash value for an XML element where the id attribute is not taken into account.
+ * Two elements that differ only by their id attribute get the same hash value. */
+static uint64_t hash_value (XMLElement *elem) {
+ const char *id = elem->getAttributeValue("id");
+ elem->removeAttribute("id");
+ ostringstream oss;
+ elem->write(oss);
+ uint64_t value = XXH64HashFunction(oss.str().data(), oss.str().length()).digestValue();
+ if (id)
+ elem->addAttribute("id", id);
+ return value;
+}
+
+
+/** Extracts the ID from a local URL reference like url(#abcde) */
+static inline string extract_id_from_url (const string &url) {
+ if (url.length() >= 7) {
+ size_t first = url.find('#');
+ size_t last = url.rfind(')');
+ if (first != string::npos && last != string::npos && first < last)
+ return url.substr(first+1, last-first-1);
+ }
+ return "";
+}
+
+
+void ClipPathReassigner::execute (XMLElement *defs, XMLElement *context) {
+ vector<XMLElement*> clipPathElements;
+ if (!defs || !context || !defs->getDescendants("clipPath", nullptr, clipPathElements))
+ return;
+ map<uint64_t, vector<XMLElement*>> clipPathMap;
+ for (XMLElement *clipPathElement: clipPathElements) {
+ uint64_t hash = hash_value(clipPathElement);
+ clipPathMap[hash].push_back(clipPathElement); // put identical clipPath elements into a common vector
+ }
+ // replace clip path references
+ vector<XMLElement*> descendants;
+ context->getDescendants(nullptr, "clip-path", descendants);
+ for (auto &mapEntry : clipPathMap) {
+ vector<XMLElement*> &identicalClipPathElements = mapEntry.second;
+ set<string> ids;
+ for (auto elem : identicalClipPathElements)
+ ids.insert(elem->getAttributeValue("id"));
+ for (auto it = descendants.begin(); it != descendants.end();) {
+ string id = extract_id_from_url((*it)->getAttributeValue("clip-path"));
+ if (ids.find(id) == ids.end())
+ ++it;
+ else {
+ (*it)->addAttribute("clip-path", string("url(#") + (*ids.begin()) + ")");
+ it = descendants.erase(it); // no need to process this element again
+ }
+ }
+ }
+ // remove redundant clipPath elements
+ for (auto mapEntry : clipPathMap) {
+ auto it = mapEntry.second.begin();
+ for (++it; it != mapEntry.second.end(); ++it)
+ XMLElement::detach(*it);
+ }
+}
diff --git a/dviware/dvisvgm/src/optimizer/ClipPathReassigner.hpp b/dviware/dvisvgm/src/optimizer/ClipPathReassigner.hpp
new file mode 100644
index 0000000000..6abe6d1e00
--- /dev/null
+++ b/dviware/dvisvgm/src/optimizer/ClipPathReassigner.hpp
@@ -0,0 +1,43 @@
+/*************************************************************************
+** ClipPathReassigner.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2022 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 <string>
+#include <vector>
+#include "OptimizerModule.hpp"
+
+class ClipPathReassigner : public OptimizerModule {
+ struct NamedPathString {
+ NamedPathString () =default;
+ NamedPathString (const std::string &svgPathName, const char *svgPathString) : name(svgPathName), pathString(svgPathString) {}
+ std::string name;
+ const char *pathString = nullptr;
+ };
+
+ public:
+ void execute (XMLElement*, XMLElement *context) override;
+ const char* info () const override;
+
+ private:
+ std::vector<NamedPathString> _namedPathStrings;
+
+};
+
diff --git a/dviware/dvisvgm/src/optimizer/Makefile.am b/dviware/dvisvgm/src/optimizer/Makefile.am
index 1039627843..af23fd22a7 100644
--- a/dviware/dvisvgm/src/optimizer/Makefile.am
+++ b/dviware/dvisvgm/src/optimizer/Makefile.am
@@ -2,6 +2,7 @@ noinst_LTLIBRARIES = liboptimizer.la
liboptimizer_la_SOURCES = \
AttributeExtractor.hpp AttributeExtractor.cpp \
+ ClipPathReassigner.hpp ClipPathReassigner.cpp \
DependencyGraph.hpp \
GroupCollapser.hpp GroupCollapser.cpp \
OptimizerModule.hpp \
@@ -11,4 +12,7 @@ liboptimizer_la_SOURCES = \
TransformSimplifier.hpp TransformSimplifier.cpp \
WSNodeRemover.hpp WSNodeRemover.cpp
-AM_CXXFLAGS = -I$(dvisvgm_srcdir)/libs/variant/include
+include ../../libs/defs.am
+
+AM_CXXFLAGS = -I$(dvisvgm_srcdir)/libs/variant/include $(XXHASH_CFLAGS)
+
diff --git a/dviware/dvisvgm/src/optimizer/Makefile.in b/dviware/dvisvgm/src/optimizer/Makefile.in
index 26731769a2..3d7cf25df6 100644
--- a/dviware/dvisvgm/src/optimizer/Makefile.in
+++ b/dviware/dvisvgm/src/optimizer/Makefile.in
@@ -89,6 +89,10 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
+@HAVE_BROTLI_FALSE@am__append_1 = -I$(dvisvgm_srcdir)/libs/brotli/include
+@HAVE_BROTLI_FALSE@am__append_2 = ../libs/brotli/libbrotli.a
+@HAVE_WOFF2_FALSE@am__append_3 = -I$(dvisvgm_srcdir)/libs/woff2/include
+@HAVE_WOFF2_FALSE@am__append_4 = ../libs/woff2/libwoff2.a
subdir = src/optimizer
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
@@ -106,7 +110,8 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
liboptimizer_la_LIBADD =
-am_liboptimizer_la_OBJECTS = AttributeExtractor.lo GroupCollapser.lo \
+am_liboptimizer_la_OBJECTS = AttributeExtractor.lo \
+ ClipPathReassigner.lo GroupCollapser.lo \
RedundantElementRemover.lo SVGOptimizer.lo TextSimplifier.lo \
TransformSimplifier.lo WSNodeRemover.lo
liboptimizer_la_OBJECTS = $(am_liboptimizer_la_OBJECTS)
@@ -130,6 +135,7 @@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/AttributeExtractor.Plo \
+ ./$(DEPDIR)/ClipPathReassigner.Plo \
./$(DEPDIR)/GroupCollapser.Plo \
./$(DEPDIR)/RedundantElementRemover.Plo \
./$(DEPDIR)/SVGOptimizer.Plo ./$(DEPDIR)/TextSimplifier.Plo \
@@ -198,7 +204,8 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
-am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+am__DIST_COMMON = $(srcdir)/../../libs/defs.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@@ -211,8 +218,8 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
-BROTLI_CFLAGS = @BROTLI_CFLAGS@
-BROTLI_LIBS = @BROTLI_LIBS@
+BROTLI_CFLAGS = @BROTLI_CFLAGS@ $(am__append_1)
+BROTLI_LIBS = @BROTLI_LIBS@ $(am__append_2)
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
@@ -294,8 +301,8 @@ STRIP = @STRIP@
TTFAUTOHINT_CFLAGS = @TTFAUTOHINT_CFLAGS@
TTFAUTOHINT_LIBS = @TTFAUTOHINT_LIBS@
VERSION = @VERSION@
-WOFF2_CFLAGS = @WOFF2_CFLAGS@
-WOFF2_LIBS = @WOFF2_LIBS@
+WOFF2_CFLAGS = @WOFF2_CFLAGS@ $(am__append_3)
+WOFF2_LIBS = @WOFF2_LIBS@ $(am__append_4)
XMLTO = @XMLTO@
XSLTPROC = @XSLTPROC@
ZLIB_CFLAGS = @ZLIB_CFLAGS@
@@ -362,6 +369,7 @@ top_srcdir = @top_srcdir@
noinst_LTLIBRARIES = liboptimizer.la
liboptimizer_la_SOURCES = \
AttributeExtractor.hpp AttributeExtractor.cpp \
+ ClipPathReassigner.hpp ClipPathReassigner.cpp \
DependencyGraph.hpp \
GroupCollapser.hpp GroupCollapser.cpp \
OptimizerModule.hpp \
@@ -371,12 +379,16 @@ liboptimizer_la_SOURCES = \
TransformSimplifier.hpp TransformSimplifier.cpp \
WSNodeRemover.hpp WSNodeRemover.cpp
-AM_CXXFLAGS = -I$(dvisvgm_srcdir)/libs/variant/include
+@HAVE_POTRACE_FALSE@POTRACE_CFLAGS = -I$(dvisvgm_srcdir)/libs/potrace
+@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
+AM_CXXFLAGS = -I$(dvisvgm_srcdir)/libs/variant/include $(XXHASH_CFLAGS)
all: all-am
.SUFFIXES:
.SUFFIXES: .cpp .lo .o .obj
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../libs/defs.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@@ -396,6 +408,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
+$(srcdir)/../../libs/defs.am $(am__empty):
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
@@ -427,6 +440,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AttributeExtractor.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClipPathReassigner.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GroupCollapser.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RedundantElementRemover.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SVGOptimizer.Plo@am__quote@ # am--include-marker
@@ -596,6 +610,7 @@ clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
distclean: distclean-am
-rm -f ./$(DEPDIR)/AttributeExtractor.Plo
+ -rm -f ./$(DEPDIR)/ClipPathReassigner.Plo
-rm -f ./$(DEPDIR)/GroupCollapser.Plo
-rm -f ./$(DEPDIR)/RedundantElementRemover.Plo
-rm -f ./$(DEPDIR)/SVGOptimizer.Plo
@@ -648,6 +663,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/AttributeExtractor.Plo
+ -rm -f ./$(DEPDIR)/ClipPathReassigner.Plo
-rm -f ./$(DEPDIR)/GroupCollapser.Plo
-rm -f ./$(DEPDIR)/RedundantElementRemover.Plo
-rm -f ./$(DEPDIR)/SVGOptimizer.Plo
diff --git a/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp b/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
index 9ff1b8163f..4809439c8e 100644
--- a/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
+++ b/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
@@ -25,6 +25,7 @@
#include "../SVGTree.hpp"
#include "AttributeExtractor.hpp"
+#include "ClipPathReassigner.hpp"
#include "GroupCollapser.hpp"
#include "RedundantElementRemover.hpp"
#include "TextSimplifier.hpp"
@@ -42,7 +43,8 @@ SVGOptimizer::SVGOptimizer (SVGTree *svg) : _svg(svg) {
_moduleEntries.emplace_back(ModuleEntry("simplify-transform", util::make_unique<TransformSimplifier>()));
_moduleEntries.emplace_back(ModuleEntry("group-attributes", util::make_unique<AttributeExtractor>()));
_moduleEntries.emplace_back(ModuleEntry("collapse-groups", util::make_unique<GroupCollapser>()));
- _moduleEntries.emplace_back(ModuleEntry("remove-clippath", util::make_unique<RedundantElementRemover>()));
+ _moduleEntries.emplace_back(ModuleEntry("remove-clippaths", util::make_unique<RedundantElementRemover>()));
+ _moduleEntries.emplace_back(ModuleEntry("reassign-clippaths", util::make_unique<ClipPathReassigner>()));
}