diff options
Diffstat (limited to 'dviware/dvisvgm/src/optimizer')
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; } |