summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2016-07-04 22:07:54 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2016-07-04 22:07:54 +0000
commitab399d16f49b986d1de514b2fb8434872decf91d (patch)
tree6d3d0faca673d7aa1c0f48ca679ce7841a82e3df /Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
parentdd2749b37f7b6a9976869e29a028eeab80d686df (diff)
dvisvgm 1.16
git-svn-id: svn://tug.org/texlive/trunk@41628 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp254
1 files changed, 35 insertions, 219 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
index 4d41b003ee7..2e4ac726ded 100644
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
+++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SVGTree.cpp
@@ -26,6 +26,7 @@
#include "DVIToSVG.h"
#include "Font.h"
#include "FontManager.h"
+#include "SVGCharHandlerFactory.h"
#include "SVGTree.h"
#include "XMLDocument.h"
#include "XMLNode.h"
@@ -35,7 +36,7 @@ using namespace std;
// static class variables
-bool SVGTree::CREATE_STYLE=true;
+bool SVGTree::CREATE_CSS=true;
bool SVGTree::USE_FONTS=true;
bool SVGTree::CREATE_USE_ELEMENTS=false;
bool SVGTree::RELATIVE_PATH_CMDS=false;
@@ -44,13 +45,17 @@ bool SVGTree::ADD_COMMENTS=false;
double SVGTree::ZOOM_FACTOR=1.0;
-SVGTree::SVGTree () : _vertical(false), _font(0), _color(Color::BLACK), _matrix(1) {
- _xchanged = _ychanged = false;
- _fontnum = 0;
+SVGTree::SVGTree () {
+ _charHandler = SVGCharHandlerFactory::createHandler();
reset();
}
+SVGTree::~SVGTree () {
+ delete _charHandler;
+}
+
+
/** Clears the SVG tree and initializes the root element. */
void SVGTree::reset () {
_doc.clear();
@@ -59,7 +64,7 @@ void SVGTree::reset () {
_root->addAttribute("xmlns", "http://www.w3.org/2000/svg");
_root->addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
_doc.setRootNode(_root);
- _page = _text = _span = _defs = 0;
+ _page = _defs = 0;
}
@@ -75,17 +80,17 @@ void SVGTree::setBBox (const BoundingBox &bbox) {
void SVGTree::setColor (const Color &c) {
- if (!_font.get() || _font.get()->color() == Color::BLACK)
- _color.set(c);
+ const Font *font = _charHandler->getFont();
+ if (!font || font->color() == Color::BLACK)
+ _charHandler->setColor(c);
}
void SVGTree::setFont (int num, const Font &font) {
- _font.set(&font);
- _fontnum = num;
+ _charHandler->setFont(font, num);
// set default color assigned to the font
- if (font.color() != Color::BLACK && _color.get() != font.color())
- _color.set(font.color());
+ if (font.color() != Color::BLACK && getColor() != font.color())
+ setColor(font.color());
}
@@ -96,9 +101,9 @@ void SVGTree::newPage (int pageno) {
if (pageno >= 0)
_page->addAttribute("id", string("page")+XMLString(pageno));
_root->append(_page);
- _text = _span = 0;
- while (!_pageContainerStack.empty())
- _pageContainerStack.pop();
+ _charHandler->setInitialContextNode(_page);
+ while (!_contextElementStack.empty())
+ _contextElementStack.pop();
}
@@ -112,210 +117,23 @@ void SVGTree::appendToDefs (XMLNode *node) {
void SVGTree::appendToPage (XMLNode *node) {
- if (_pageContainerStack.empty())
- _page->append(node);
- else
- _pageContainerStack.top()->append(node);
- if (node != _text) // if the appended node differs from the text element currently in use,
- _text = 0; // then force creating a new text element for the following characters
+ XMLElementNode *parent = _contextElementStack.empty() ? _page : _contextElementStack.top();
+ parent->append(node);
+ _charHandler->setInitialContextNode(parent);
}
void SVGTree::prependToPage (XMLNode *node) {
- if (_pageContainerStack.empty())
+ if (_contextElementStack.empty())
_page->prepend(node);
else
- _pageContainerStack.top()->prepend(node);
+ _contextElementStack.top()->prepend(node);
}
-/** Appends a single character or its path represenatation to the current context node.
- * If necessary, and depending on the selected output mode and further output states,
- * new XML elements (text, tspan, g, use, ...) are created.
- * @param[in] c character to be added
- * @param[in] x x coordinate
- * @param[in] y y coordinate
- * @param[in] font font to be used */
-void SVGTree::appendChar (int c, double x, double y, const Font &font) {
- if (USE_FONTS)
- appendCharAsText(c, x, y, font);
- else
- appendCharAsPath(c, x, y, font);
-}
-
-
-/** Appends a single text character to the current context node.
- * @param[in] c character to be added
- * @param[in] x x coordinate
- * @param[in] y y coordinate
- * @param[in] font font to be used */
-void SVGTree::appendCharAsText (int c, double x, double y, const Font &font) {
- XMLElementNode *node=_span;
- // changes of fonts and transformations require a new text element
- if (!MERGE_CHARS || !_text || _font.changed() || _matrix.changed() || _vertical.changed()) {
- newTextNode(x, y);
- node = _text;
- _color.changed(true);
- }
- if (MERGE_CHARS && (_xchanged || _ychanged || (_color.changed() && _color.get() != Color::BLACK))) {
- // if drawing position was explicitly changed, create a new tspan element
- _span = new XMLElementNode("tspan");
- if (_xchanged) {
- if (_vertical) {
- // align glyphs designed for horizontal layout properly
- if (const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(_font.get()))
- if (!pf->getMetrics()->verticalLayout())
- x += pf->scaledAscent()/2.5; // move vertical baseline to the right by strikethrough offset
- }
- _span->addAttribute("x", x);
- _xchanged = false;
- }
- if (_ychanged) {
- _span->addAttribute("y", y);
- _ychanged = false;
- }
- if (_color.get() != font.color()) {
- _span->addAttribute("fill", _color.get().svgColorString());
- _color.changed(false);
- }
- _text->append(_span);
- node = _span;
- }
- if (!node) {
- if (!_text)
- newTextNode(x, y);
- node = _text;
- }
- node->append(XMLString(font.unicode(c), false));
- if (!MERGE_CHARS && _color.get() != font.color()) {
- node->addAttribute("fill", _color.get().svgColorString());
- _color.changed(false);
- }
-}
-
-
-/** Appends a reference to the path representation of a single character to
- * the current context node.
- * @param[in] c character to be added
- * @param[in] x x coordinate
- * @param[in] y y coordinate
- * @param[in] font font to be used */
-void SVGTree::appendCharAsPath (int c, double x, double y, const Font &font) {
- XMLElementNode *node=_span;
- if (_color.changed() || _matrix.changed()) {
- bool set_color = (_color.changed() && _color.get() != Color::BLACK);
- bool set_matrix = (_matrix.changed() && !_matrix.get().isIdentity());
- if (set_color || set_matrix) {
- _span = new XMLElementNode("g");
- if (_color.get() != Color::BLACK)
- _span->addAttribute("fill", _color.get().svgColorString());
- if (!_matrix.get().isIdentity())
- _span->addAttribute("transform", _matrix.get().getSVG());
- appendToPage(_span);
- node = _span;
- _color.changed(false);
- _matrix.changed(false);
- }
- else if (_color.get() == Color::BLACK && _matrix.get().isIdentity())
- node = _span = 0;
- }
- if (!node)
- node = _pageContainerStack.empty() ? _page : _pageContainerStack.top();
- if (font.verticalLayout()) {
- // move glyph graphics so that its origin is located at the top center position
- GlyphMetrics metrics;
- font.getGlyphMetrics(c, _vertical, metrics);
- x -= metrics.wl;
- if (const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(&font)) {
- // Center glyph between top and bottom border of the TFM box.
- // This is just an approximation used until I find a way to compute
- // the exact location in vertical mode.
- GlyphMetrics exact_metrics;
- pf->getExactGlyphBox(c, exact_metrics, false);
- y += exact_metrics.h+(metrics.d-exact_metrics.h-exact_metrics.d)/2;
- }
- else
- y += metrics.d;
- }
- Matrix rotation(1);
- if (_vertical && !font.verticalLayout()) {
- // alphabetic text designed for horizontal mode
- // must be rotated by 90 degrees if in vertical mode
- rotation.translate(-x, -y);
- rotation.rotate(90);
- rotation.translate(x, y);
- }
- if (CREATE_USE_ELEMENTS) {
- ostringstream oss;
- oss << "#g" << FontManager::instance().fontID(_font) << '-' << c;
- XMLElementNode *use = new XMLElementNode("use");
- use->addAttribute("x", XMLString(x));
- use->addAttribute("y", XMLString(y));
- use->addAttribute("xlink:href", oss.str());
- if (!rotation.isIdentity())
- use->addAttribute("transform", rotation.getSVG());
- node->append(use);
- }
- else {
- Glyph glyph;
- const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(&font);
- if (pf && pf->getGlyph(c, glyph)) {
- double sx = pf->scaledSize()/pf->unitsPerEm();
- double sy = -sx;
- ostringstream oss;
- glyph.writeSVG(oss, RELATIVE_PATH_CMDS, sx, sy, x, y);
- XMLElementNode *glyph_node = new XMLElementNode("path");
- glyph_node->addAttribute("d", oss.str());
- if (!rotation.isIdentity())
- glyph_node->addAttribute("transform", rotation.getSVG());
- node->append(glyph_node);
- }
- }
-}
-
-
-/** Creates a new text element. This is a helper function used by appendChar().
- * @param[in] x current x coordinate
- * @param[in] y current y coordinate */
-void SVGTree::newTextNode (double x, double y) {
- _text = new XMLElementNode("text");
- _span = 0; // no tspan in text element yet
- if (USE_FONTS) {
- const Font *font = _font.get();
- if (CREATE_STYLE || !font)
- _text->addAttribute("class", string("f")+XMLString(_fontnum));
- else {
- _text->addAttribute("font-family", font->name());
- _text->addAttribute("font-size", XMLString(font->scaledSize()));
- if (font->color() != Color::BLACK)
- _text->addAttribute("fill", font->color().svgColorString());
- }
- if (_vertical) {
- _text->addAttribute("writing-mode", "tb");
- // align glyphs designed for horizontal layout properly
- if (const PhysicalFont *pf = dynamic_cast<const PhysicalFont*>(_font.get()))
- if (!pf->getMetrics()->verticalLayout()) { // alphabetic text designed for horizontal layout?
- x += pf->scaledAscent()/2.5; // move vertical baseline to the right by strikethrough offset
- _text->addAttribute("glyph-orientation-vertical", 90); // ensure rotation
- }
- }
- }
- _text->addAttribute("x", x);
- _text->addAttribute("y", y);
- if (!_matrix.get().isIdentity())
- _text->addAttribute("transform", _matrix.get().getSVG());
- appendToPage(_text);
- _vertical.changed(false);
- _font.changed(false);
- _matrix.changed(false);
- _xchanged = false;
- _ychanged = false;
-}
-
-
-void SVGTree::transformPage (const Matrix *usermatrix) {
- if (usermatrix && !usermatrix->isIdentity())
- _page->addAttribute("transform", usermatrix->getSVG());
+void SVGTree::transformPage (const Matrix &usermatrix) {
+ if (!usermatrix.isIdentity())
+ _page->addAttribute("transform", usermatrix.getSVG());
}
@@ -375,7 +193,7 @@ static string font_info (const Font &font) {
void SVGTree::appendFontStyles (const set<const Font*> &fonts) {
- if (CREATE_STYLE && USE_FONTS && !fonts.empty() && _defs) {
+ if (CREATE_CSS && USE_FONTS && !fonts.empty() && _defs) {
XMLElementNode *styleNode = new XMLElementNode("style");
styleNode->addAttribute("type", "text/css");
_root->insertAfter(styleNode, _defs);
@@ -468,21 +286,20 @@ 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 (XMLElementNode *node) {
- if (_pageContainerStack.empty())
+ if (_contextElementStack.empty())
_page->append(node);
else
- _pageContainerStack.top()->append(node);
- _pageContainerStack.push(node);
- _text = _span = 0; // ensure the creation of a new text element for the following characters added
+ _contextElementStack.top()->append(node);
+ _contextElementStack.push(node);
+ _charHandler->setInitialContextNode(node);
}
/** Pops the current context element and restored the previous one. */
void SVGTree::popContextElement () {
- if (!_pageContainerStack.empty()) {
- _pageContainerStack.pop();
- _text = _span = 0; // ensure the creation of a new text element for the following characters added
- }
+ if (!_contextElementStack.empty())
+ _contextElementStack.pop();
+ _charHandler->setInitialContextNode(_page);
}
@@ -525,4 +342,3 @@ void SVGTree::removeRedundantElements () {
_defs->remove(node);
}
}
-