diff options
Diffstat (limited to 'dviware/dvisvgm/src/optimizer')
-rw-r--r-- | dviware/dvisvgm/src/optimizer/ClipPathReassigner.cpp | 94 | ||||
-rw-r--r-- | dviware/dvisvgm/src/optimizer/ClipPathReassigner.hpp | 43 | ||||
-rw-r--r-- | dviware/dvisvgm/src/optimizer/Makefile.am | 6 | ||||
-rw-r--r-- | dviware/dvisvgm/src/optimizer/Makefile.in | 32 | ||||
-rw-r--r-- | dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp | 4 |
5 files changed, 169 insertions, 10 deletions
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>())); } |