diff options
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp')
-rw-r--r-- | Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp | 170 |
1 files changed, 0 insertions, 170 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp deleted file mode 100644 index 47c0ac44ee5..00000000000 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/optimizer/GroupCollapser.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/************************************************************************* -** GroupCollapser.cpp ** -** ** -** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2021 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::detach(node); - node = next; - } - } -} - - -/** Recursively removes all redundant group elements from the given context element - * and moves their attributes to the corresponding parent elements. - * @param[in] context root of the subtree to process */ -void GroupCollapser::execute (XMLElement *context) { - if (!context) - return; - - XMLNode *child=context->firstChild(); - while (child) { - XMLNode *next=child->next(); - if (XMLElement *childElement = child->toElement()) { - execute(childElement); - // check for groups without attributes and remove them - if (childElement->name() == "g" && childElement->attributes().empty()) { - remove_ws_nodes(childElement); - if (XMLNode *firstUnwrappedNode = XMLElement::unwrap(childElement)) - next = firstUnwrappedNode; - } - } - child = next; - } - if (XMLElement *childElement = only_child_element(context)) { - if (collapsible(*context)) { - if (childElement->name() == "g" && unwrappable(*childElement, *context) && moveAttributes(*childElement, *context)) { - remove_ws_nodes(context); - XMLElement::unwrap(childElement); - } - } - } -} - - -/** 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) { - const char *cp1 = source.getAttributeValue("clip-path"); - const char *cp2 = dest.getAttributeValue("clip-path"); - if (cp2) { - // check for colliding clip-path attributes - if (cp1 && string(cp1) != string(cp2)) - return false; - // don't apply inner transformations to outer clipping paths - if (source.hasAttribute("transform")) - 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); -} |