diff options
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp')
-rw-r--r-- | Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp | 123 |
1 files changed, 50 insertions, 73 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp index 3c891219e14..57b5fd5a4fa 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp @@ -20,9 +20,9 @@ #include <algorithm> #include <array> +#include <cstring> #include <sstream> #include "BoundingBox.hpp" -#include "DependencyGraph.hpp" #include "DVIToSVG.hpp" #include "FileSystem.hpp" #include "Font.hpp" @@ -36,7 +36,6 @@ using namespace std; - // static class variables bool SVGTree::CREATE_CSS=true; bool SVGTree::USE_FONTS=true; @@ -56,7 +55,7 @@ SVGTree::SVGTree () : _charHandler(SVGCharHandlerFactory::createHandler()) { /** Clears the SVG tree and initializes the root element. */ void SVGTree::reset () { _doc.clear(); - auto rootNode = util::make_unique<XMLElementNode>("svg"); + auto rootNode = util::make_unique<XMLElement>("svg"); rootNode->addAttribute("version", "1.1"); rootNode->addAttribute("xmlns", "http://www.w3.org/2000/svg"); rootNode->addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); @@ -112,45 +111,46 @@ bool SVGTree::setFontFormat (string formatstr) { /** Starts a new page. * @param[in] pageno number of new page */ void SVGTree::newPage (int pageno) { - auto pageNode = util::make_unique<XMLElementNode>("g"); + auto pageNode = util::make_unique<XMLElement>("g"); if (pageno >= 0) pageNode->addAttribute("id", string("page")+XMLString(pageno)); _charHandler->setInitialContextNode(pageNode.get()); _page = pageNode.get(); _root->append(std::move(pageNode)); - while (!_contextElementStack.empty()) - _contextElementStack.pop(); + _defsContextStack = stack<XMLElement*>(); + _pageContextStack = stack<XMLElement*>(); } -void SVGTree::appendToDefs (unique_ptr<XMLNode> &&node) { +void SVGTree::appendToDefs (unique_ptr<XMLNode> node) { if (!_defs) { - auto defsNode = util::make_unique<XMLElementNode>("defs"); + auto defsNode = util::make_unique<XMLElement>("defs"); _defs = defsNode.get(); _root->prepend(std::move(defsNode)); } - _defs->append(std::move(node)); + XMLElement *parent = _defsContextStack.empty() ? _defs : _defsContextStack.top(); + parent->append(std::move(node)); } -void SVGTree::appendToPage (unique_ptr<XMLNode> &&node) { - XMLElementNode *parent = _contextElementStack.empty() ? _page : _contextElementStack.top(); +void SVGTree::appendToPage (unique_ptr<XMLNode> node) { + XMLElement *parent = _pageContextStack.empty() ? _page : _pageContextStack.top(); parent->append(std::move(node)); _charHandler->setInitialContextNode(parent); } -void SVGTree::prependToPage (unique_ptr<XMLNode> &&node) { - if (_contextElementStack.empty()) +void SVGTree::prependToPage (unique_ptr<XMLNode> node) { + if (_pageContextStack.empty()) _page->prepend(std::move(node)); else - _contextElementStack.top()->prepend(std::move(node)); + _pageContextStack.top()->prepend(std::move(node)); } void SVGTree::transformPage (const Matrix &usermatrix) { if (!usermatrix.isIdentity()) - _page->addAttribute("transform", usermatrix.getSVG()); + _page->addAttribute("transform", usermatrix.toSVG()); } @@ -159,17 +159,17 @@ void SVGTree::transformPage (const Matrix &usermatrix) { * @param[in] font font to extract the glyph from * @param[in] cb pointer to callback object for sending feedback to the glyph tracer (may be 0) * @return pointer to element node if glyph exists, 0 otherwise */ -static unique_ptr<XMLElementNode> createGlyphNode (int c, const PhysicalFont &font, GFGlyphTracer::Callback *cb) { +static unique_ptr<XMLElement> createGlyphNode (int c, const PhysicalFont &font, GFGlyphTracer::Callback *cb) { Glyph glyph; if (!font.getGlyph(c, glyph, cb) || (!SVGTree::USE_FONTS && !SVGTree::CREATE_USE_ELEMENTS)) return nullptr; double sx=1.0, sy=1.0; double upem = font.unitsPerEm(); - unique_ptr<XMLElementNode> glyphNode; + unique_ptr<XMLElement> glyphNode; if (SVGTree::USE_FONTS) { double extend = font.style() ? font.style()->extend : 1; - glyphNode = util::make_unique<XMLElementNode>("glyph"); + glyphNode = util::make_unique<XMLElement>("glyph"); glyphNode->addAttribute("unicode", XMLString(font.unicode(c), false)); glyphNode->addAttribute("horiz-adv-x", XMLString(font.hAdvance(c)*extend)); glyphNode->addAttribute("vert-adv-y", XMLString(font.vAdvance(c))); @@ -178,7 +178,7 @@ static unique_ptr<XMLElementNode> createGlyphNode (int c, const PhysicalFont &fo glyphNode->addAttribute("glyph-name", name); } else { - glyphNode = util::make_unique<XMLElementNode>("path"); + glyphNode = util::make_unique<XMLElement>("path"); glyphNode->addAttribute("id", "g"+to_string(FontManager::instance().fontID(&font))+"-"+to_string(c)); sx = font.scaledSize()/upem; sy = -sx; @@ -192,7 +192,7 @@ static unique_ptr<XMLElementNode> createGlyphNode (int c, const PhysicalFont &fo static string font_info (const Font &font) { ostringstream oss; - if (const NativeFont *nf = dynamic_cast<const NativeFont*>(&font)) { + if (auto nf = dynamic_cast<const NativeFont*>(&font)) { oss << nf->familyName() << ' ' << nf->styleName() << "; " << nf->filename(); if (nf->style()) { if (nf->style()->bold != 0) @@ -255,14 +255,14 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr if (ADD_COMMENTS) { string info = font_info(font); if (!info.empty()) - appendToDefs(util::make_unique<XMLCommentNode>(string(" font: ")+info+" ")); + appendToDefs(util::make_unique<XMLComment>(string(" font: ")+info+" ")); } - auto fontNode = util::make_unique<XMLElementNode>("font"); + auto fontNode = util::make_unique<XMLElement>("font"); string fontname = font.name(); fontNode->addAttribute("id", fontname); fontNode->addAttribute("horiz-adv-x", XMLString(font.hAdvance())); - auto faceNode = util::make_unique<XMLElementNode>("font-face"); + auto faceNode = util::make_unique<XMLElement>("font-face"); faceNode->addAttribute("font-family", fontname); faceNode->addAttribute("units-per-em", XMLString(font.unitsPerEm())); if (!font.verticalLayout()) { @@ -281,7 +281,7 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr // reference the already embedded path together with a transformation attribute and let the SVG renderer // scale the glyphs properly. This is only necessary if we don't want to use font but path elements. for (int c : chars) { - auto useNode = util::make_unique<XMLElementNode>("use"); + auto useNode = util::make_unique<XMLElement>("use"); useNode->addAttribute("id", "g"+to_string(FontManager::instance().fontID(&font))+"-"+to_string(c)); useNode->addAttribute("xlink:href", "#g"+to_string(FontManager::instance().fontID(font.uniqueFont()))+"-"+to_string(c)); double scale = font.scaledSize()/font.uniqueFont()->scaledSize(); @@ -297,70 +297,47 @@ void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTr } -/** Pushes a new context element that will take all following nodes added to the page. */ -void SVGTree::pushContextElement (unique_ptr<XMLElementNode> &&node) { - XMLElementNode *nodePtr = node.get(); - if (_contextElementStack.empty()) - _page->append(std::move(node)); +void SVGTree::pushDefsContext (unique_ptr<XMLElement> node) { + XMLElement *nodePtr = node.get(); + if (_defsContextStack.empty()) + appendToDefs(std::move(node)); else - _contextElementStack.top()->append(std::move(node)); - _contextElementStack.push(nodePtr); - _charHandler->setInitialContextNode(nodePtr); + _defsContextStack.top()->append(std::move(node)); + _defsContextStack.push(nodePtr); } -/** Pops the current context element and restored the previous one. */ -void SVGTree::popContextElement () { - if (!_contextElementStack.empty()) - _contextElementStack.pop(); - _charHandler->setInitialContextNode(_page); +void SVGTree::popDefsContext () { + if (!_defsContextStack.empty()) + _defsContextStack.pop(); } -/** Extracts the ID from a local URL reference like url(#abcde) */ -static inline string extract_id_from_url (const string &url) { - return url.substr(5, url.length()-6); +/** Pushes a new context element that will take all following nodes added to the page. */ +void SVGTree::pushPageContext (unique_ptr<XMLElement> node) { + XMLElement *nodePtr = node.get(); + if (_pageContextStack.empty()) + _page->append(std::move(node)); + else + _pageContextStack.top()->append(std::move(node)); + _pageContextStack.push(nodePtr); + _charHandler->setInitialContextNode(nodePtr); } -/** Removes elements present in the SVG tree that are not required. - * For now, only clipPath elements are removed. */ -void SVGTree::removeRedundantElements () { - vector<XMLElementNode*> clipPathElements; - if (!_defs || !_defs->getDescendants("clipPath", nullptr, clipPathElements)) - return; - - // collect dependencies between clipPath elements in the defs section of the SVG tree - DependencyGraph<string> idTree; - for (const XMLElementNode *clip : clipPathElements) { - if (const char *id = clip->getAttributeValue("id")) { - if (const char *url = clip->getAttributeValue("clip-path")) - idTree.insert(extract_id_from_url(url), id); - else - idTree.insert(id); - } - } - // collect elements that reference a clipPath, i.e. have a clip-path attribute - vector<XMLElementNode*> descendants; - _page->getDescendants(nullptr, "clip-path", descendants); - // remove referenced IDs and their dependencies from the dependency graph - for (const XMLElementNode *elem : descendants) { - string idref = extract_id_from_url(elem->getAttributeValue("clip-path")); - idTree.removeDependencyPath(idref); - } - descendants.clear(); - for (const string &str : idTree.getKeys()) { - XMLElementNode *node = _defs->getFirstDescendant("clipPath", "id", str.c_str()); - _defs->remove(node); - } +/** Pops the current context element and restored the previous one. */ +void SVGTree::popPageContext () { + if (!_pageContextStack.empty()) + _pageContextStack.pop(); + _charHandler->setInitialContextNode(_page); } -XMLCDataNode* SVGTree::styleCDataNode () { +XMLCData* SVGTree::styleCDataNode () { if (!_styleCDataNode) { - auto styleNode = util::make_unique<XMLElementNode>("style"); + auto styleNode = util::make_unique<XMLElement>("style"); styleNode->addAttribute("type", "text/css"); - auto cdataNode = util::make_unique<XMLCDataNode>(); + auto cdataNode = util::make_unique<XMLCData>(); _styleCDataNode = cdataNode.get(); styleNode->append(std::move(cdataNode)); _root->insertBefore(std::move(styleNode), _page); |