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.cpp346
1 files changed, 0 insertions, 346 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
deleted file mode 100644
index 372dd28bf22..00000000000
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
+++ /dev/null
@@ -1,346 +0,0 @@
-/*************************************************************************
-** SVGTree.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 <cstring>
-#include <sstream>
-#include "BoundingBox.hpp"
-#include "DVIToSVG.hpp"
-#include "FileSystem.hpp"
-#include "Font.hpp"
-#include "FontManager.hpp"
-#include "FontWriter.hpp"
-#include "SVGCharHandlerFactory.hpp"
-#include "SVGTree.hpp"
-#include "XMLDocument.hpp"
-#include "XMLNode.hpp"
-#include "XMLString.hpp"
-
-using namespace std;
-
-// static class variables
-bool SVGTree::CREATE_CSS=true;
-bool SVGTree::USE_FONTS=true;
-FontWriter::FontFormat SVGTree::FONT_FORMAT = FontWriter::FontFormat::SVG;
-bool SVGTree::CREATE_USE_ELEMENTS=false;
-bool SVGTree::RELATIVE_PATH_CMDS=false;
-bool SVGTree::MERGE_CHARS=true;
-bool SVGTree::ADD_COMMENTS=false;
-double SVGTree::ZOOM_FACTOR=1.0;
-
-
-SVGTree::SVGTree () : _charHandler(SVGCharHandlerFactory::createHandler()) {
- reset();
-}
-
-
-/** Clears the SVG tree and initializes the root element. */
-void SVGTree::reset () {
- _doc.clear();
- 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");
- _root = rootNode.get();
- _doc.setRootNode(std::move(rootNode));
- _page = _defs = nullptr;
- _styleCDataNode = nullptr;
-}
-
-
-/** Sets the bounding box of the document.
- * @param[in] bbox bounding box in PS point units */
-void SVGTree::setBBox (const BoundingBox &bbox) {
- if (ZOOM_FACTOR >= 0) {
- _root->addAttribute("width", XMLString(bbox.width()*ZOOM_FACTOR)+"pt");
- _root->addAttribute("height", XMLString(bbox.height()*ZOOM_FACTOR)+"pt");
- }
- _root->addAttribute("viewBox", bbox.toSVGViewBox());
-}
-
-
-void SVGTree::setColor (const Color &c) {
- const Font *font = _charHandler->getFont();
- if (!font || font->color() == Color::BLACK)
- _charHandler->setColor(c);
-}
-
-
-void SVGTree::setFont (int num, const Font &font) {
- _charHandler->setFont(font, num);
- // set default color assigned to the font
- if (font.color() != Color::BLACK && getColor() != font.color())
- setColor(font.color());
-}
-
-
-bool SVGTree::setFontFormat (string formatstr) {
- size_t pos = formatstr.find(',');
- string opt;
- if (pos != string::npos) {
- opt = formatstr.substr(pos+1);
- formatstr = formatstr.substr(0, pos);
- }
- FontWriter::FontFormat format = FontWriter::toFontFormat(formatstr);
- if (format == FontWriter::FontFormat::UNKNOWN)
- return false;
- FONT_FORMAT = format;
- FontWriter::AUTOHINT_FONTS = (opt == "autohint" || opt == "ah");
- return true;
-}
-
-
-/** Starts a new page.
- * @param[in] pageno number of new page */
-void SVGTree::newPage (int pageno) {
- 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));
- _defsContextStack = stack<XMLElement*>();
- _pageContextStack = stack<XMLElement*>();
-}
-
-
-void SVGTree::appendToDefs (unique_ptr<XMLNode> node) {
- if (!_defs) {
- auto defsNode = util::make_unique<XMLElement>("defs");
- _defs = defsNode.get();
- _root->prepend(std::move(defsNode));
- }
- XMLElement *parent = _defsContextStack.empty() ? _defs : _defsContextStack.top();
- parent->append(std::move(node));
-}
-
-
-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 (_pageContextStack.empty())
- _page->prepend(std::move(node));
- else
- _pageContextStack.top()->prepend(std::move(node));
-}
-
-
-void SVGTree::transformPage (const Matrix &usermatrix) {
- if (!usermatrix.isIdentity())
- _page->addAttribute("transform", usermatrix.toSVG());
-}
-
-
-/** Creates an SVG element for a single glyph.
- * @param[in] c character number
- * @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<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<XMLElement> glyphNode;
- if (SVGTree::USE_FONTS) {
- double extend = font.style() ? font.style()->extend : 1;
- 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)));
- string name = font.glyphName(c);
- if (!name.empty())
- glyphNode->addAttribute("glyph-name", name);
- }
- else {
- 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;
- }
- ostringstream oss;
- glyph.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS, sx, sy);
- glyphNode->addAttribute("d", oss.str());
- return glyphNode;
-}
-
-
-static string font_info (const Font &font) {
- ostringstream oss;
- if (auto nf = dynamic_cast<const NativeFont*>(&font)) {
- oss << nf->familyName() << ' ' << nf->styleName() << "; " << nf->filename();
- if (nf->style()) {
- if (nf->style()->bold != 0)
- oss << ", bold:" << XMLString(nf->style()->bold) << "pt";
- if (nf->style()->extend != 1)
- oss << ", extent:" << XMLString(nf->style()->extend);
- if (nf->style()->slant != 0)
- oss << ", slant:" << XMLString(nf->style()->slant);
- }
- }
- return oss.str();
-}
-
-
-void SVGTree::appendFontStyles (const unordered_set<const Font*> &fonts) {
- if (CREATE_CSS && USE_FONTS && !fonts.empty() && _page) {
- map<int, const Font*> sortmap;
- for (const Font *font : fonts)
- if (!dynamic_cast<const VirtualFont*>(font)) // skip virtual fonts
- sortmap[FontManager::instance().fontID(font)] = font;
- ostringstream style;
- // add font style definitions in ascending order
- for (auto &idfontpair : sortmap) {
- if (CREATE_CSS) {
- style << "text.f" << idfontpair.first << ' '
- << "{font-family:" << idfontpair.second->name()
- << ";font-size:" << XMLString(idfontpair.second->scaledSize()) << "px";
- if (idfontpair.second->color() != Color::BLACK)
- style << ";fill:" << idfontpair.second->color().svgColorString();
- style << '}';
- if (ADD_COMMENTS) {
- string info = font_info(*idfontpair.second);
- if (!info.empty())
- style << " /* " << info << " */";
- }
- style << '\n';
- }
- }
- styleCDataNode()->append(style.str());
- }
-}
-
-
-/** Appends glyph definitions of a given font to the defs section of the SVG tree.
- * @param[in] font font to be appended
- * @param[in] chars codes of the characters whose glyph outlines should be appended
- * @param[in] callback pointer to callback object for sending feedback to the glyph tracer (may be 0) */
-void SVGTree::append (const PhysicalFont &font, const set<int> &chars, GFGlyphTracer::Callback *callback) {
- if (chars.empty())
- return;
-
- if (USE_FONTS) {
- if (FONT_FORMAT != FontWriter::FontFormat::SVG) {
- ostringstream style;
- FontWriter fontWriter(font);
- if (fontWriter.writeCSSFontFace(FONT_FORMAT, chars, style, callback))
- styleCDataNode()->append(style.str());
- }
- else {
- if (ADD_COMMENTS) {
- string info = font_info(font);
- if (!info.empty())
- appendToDefs(util::make_unique<XMLComment>(string(" font: ")+info+" "));
- }
- 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<XMLElement>("font-face");
- faceNode->addAttribute("font-family", fontname);
- faceNode->addAttribute("units-per-em", XMLString(font.unitsPerEm()));
- if (!font.verticalLayout()) {
- faceNode->addAttribute("ascent", XMLString(font.ascent()));
- faceNode->addAttribute("descent", XMLString(font.descent()));
- }
- fontNode->append(std::move(faceNode));
- for (int c : chars)
- fontNode->append(createGlyphNode(c, font, callback));
- appendToDefs(std::move(fontNode));
- }
- }
- else if (CREATE_USE_ELEMENTS && &font != font.uniqueFont()) {
- // If the same character is used in various sizes, we don't want to embed the complete (lengthy) path
- // descriptions multiple times. Because they would only differ by a scale factor, it's better to
- // 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<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();
- if (scale != 1.0)
- useNode->addAttribute("transform", "scale("+XMLString(scale)+")");
- appendToDefs(std::move(useNode));
- }
- }
- else {
- for (int c : chars)
- appendToDefs(createGlyphNode(c, font, callback));
- }
-}
-
-
-void SVGTree::pushDefsContext (unique_ptr<XMLElement> node) {
- XMLElement *nodePtr = node.get();
- if (_defsContextStack.empty())
- appendToDefs(std::move(node));
- else
- _defsContextStack.top()->append(std::move(node));
- _defsContextStack.push(nodePtr);
-}
-
-
-void SVGTree::popDefsContext () {
- if (!_defsContextStack.empty())
- _defsContextStack.pop();
-}
-
-
-/** 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);
-}
-
-
-/** Pops the current context element and restored the previous one. */
-void SVGTree::popPageContext () {
- if (!_pageContextStack.empty())
- _pageContextStack.pop();
- _charHandler->setInitialContextNode(_page);
-}
-
-
-XMLCData* SVGTree::styleCDataNode () {
- if (!_styleCDataNode) {
- auto styleNode = util::make_unique<XMLElement>("style");
- styleNode->addAttribute("type", "text/css");
- auto cdataNode = util::make_unique<XMLCData>();
- _styleCDataNode = cdataNode.get();
- styleNode->append(std::move(cdataNode));
- _root->insertBefore(std::move(styleNode), _page);
- }
- return _styleCDataNode;
-}