summaryrefslogtreecommitdiff
path: root/dviware/dvisvgm/src/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/dvisvgm/src/optimizer')
-rw-r--r--dviware/dvisvgm/src/optimizer/GroupCollapser.cpp53
-rw-r--r--dviware/dvisvgm/src/optimizer/RedundantElementRemover.cpp2
-rw-r--r--dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp2
-rw-r--r--dviware/dvisvgm/src/optimizer/TransformSimplifier.cpp7
-rw-r--r--dviware/dvisvgm/src/optimizer/WSNodeRemover.cpp2
5 files changed, 36 insertions, 30 deletions
diff --git a/dviware/dvisvgm/src/optimizer/GroupCollapser.cpp b/dviware/dvisvgm/src/optimizer/GroupCollapser.cpp
index b8a32786c1..c3060be788 100644
--- a/dviware/dvisvgm/src/optimizer/GroupCollapser.cpp
+++ b/dviware/dvisvgm/src/optimizer/GroupCollapser.cpp
@@ -61,7 +61,7 @@ static void remove_ws_nodes (XMLElement *elem) {
node = node->next();
else {
XMLNode *next = node->next();
- XMLElement::remove(node);
+ XMLElement::detach(node);
node = next;
}
}
@@ -69,29 +69,31 @@ static void remove_ws_nodes (XMLElement *elem) {
/** Recursively removes all redundant group elements from the given context element
- * and moves their attributes to the corresponding parent 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 *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);
+
+ 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;
}
- else {
- XMLElement *child = only_child_element(context);
- if (child && collapsible(*context)) {
- if (child->name() == "g" && unwrappable(*child, *context) && moveAttributes(*child, *context)) {
+ 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(child);
+ XMLElement::unwrap(childElement);
}
}
}
@@ -147,12 +149,15 @@ bool GroupCollapser::collapsible (const XMLElement &element) {
* @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;
- }
+ 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[] = {
diff --git a/dviware/dvisvgm/src/optimizer/RedundantElementRemover.cpp b/dviware/dvisvgm/src/optimizer/RedundantElementRemover.cpp
index 906ccc2d14..a8aca1a993 100644
--- a/dviware/dvisvgm/src/optimizer/RedundantElementRemover.cpp
+++ b/dviware/dvisvgm/src/optimizer/RedundantElementRemover.cpp
@@ -64,6 +64,6 @@ void RedundantElementRemover::execute (XMLElement *defs, XMLElement *context) {
descendants.clear();
for (const string &str : idTree.getKeys()) {
XMLElement *node = defs->getFirstDescendant("clipPath", "id", str.c_str());
- XMLElement::remove(node);
+ XMLElement::detach(node);
}
}
diff --git a/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp b/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
index b2d45176e7..ac4a78fe20 100644
--- a/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
+++ b/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
@@ -39,9 +39,9 @@ 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("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("simplify-transform", util::make_unique<TransformSimplifier>()));
_moduleEntries.emplace_back(ModuleEntry("remove-clippath", util::make_unique<RedundantElementRemover>()));
}
diff --git a/dviware/dvisvgm/src/optimizer/TransformSimplifier.cpp b/dviware/dvisvgm/src/optimizer/TransformSimplifier.cpp
index 461698b62a..2541631b0e 100644
--- a/dviware/dvisvgm/src/optimizer/TransformSimplifier.cpp
+++ b/dviware/dvisvgm/src/optimizer/TransformSimplifier.cpp
@@ -79,8 +79,9 @@ bool TransformSimplifier::incorporateTransform (XMLElement *elem, const Matrix &
if (const char *ystr = elem->getAttributeValue("y"))
y = strtod(ystr, nullptr);
// width and height attributes must not become negative. Hence, only apply the scaling
- // values if they are non-negative. Otherwise, keep a scaling matrix
- if (sx < 0 || sy < 0) {
+ // values if they are non-negative. Otherwise, keep a scaling matrix. Also retain scaling
+ // transformations in image elements to avoid the need of attribute 'preseveAspectRatio'.
+ if (sx < 0 || sy < 0 || elem->name() == "image") {
x += (sx == 0 ? 0 : tx/sx);
y += (sy == 0 ? 0 : ty/sy);
elem->addAttribute("transform", "scale("+XMLString(sx)+","+XMLString(sy)+")");
@@ -120,7 +121,7 @@ static string scale_cmd (double sx, double sy) {
XMLString sxstr(sx), systr(sy);
if (sxstr != "1" || systr != "1") {
ret = "scale("+sxstr;
- if (systr != "1")
+ if (systr != sxstr)
ret += " "+systr;
ret += ')';
}
diff --git a/dviware/dvisvgm/src/optimizer/WSNodeRemover.cpp b/dviware/dvisvgm/src/optimizer/WSNodeRemover.cpp
index be58bf70fd..3f83011f5a 100644
--- a/dviware/dvisvgm/src/optimizer/WSNodeRemover.cpp
+++ b/dviware/dvisvgm/src/optimizer/WSNodeRemover.cpp
@@ -34,7 +34,7 @@ void WSNodeRemover::execute (XMLElement *context) {
while (child) {
if (removeWS && child->toWSNode()) {
XMLNode *next = child->next();
- XMLElement::remove(child);
+ XMLElement::detach(child);
child = next;
continue;
}