summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp123
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);