summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-0.8.7/src/SVGFontTraceEmitter.cpp
diff options
context:
space:
mode:
authorPeter Breitenlohner <peb@mppmu.mpg.de>2009-11-13 14:43:15 +0000
committerPeter Breitenlohner <peb@mppmu.mpg.de>2009-11-13 14:43:15 +0000
commit4b03955aab00a38ad11244687daec832f83a350a (patch)
tree0d638f8a003f7c17642ca0b11779ba01779870ae /Build/source/texk/dvisvgm/dvisvgm-0.8.7/src/SVGFontTraceEmitter.cpp
parent56cd2a40f239fb8a84ff7fcfa393f449bec2d41d (diff)
Import dvisvgm-0.8.7
git-svn-id: svn://tug.org/texlive/trunk@16003 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-0.8.7/src/SVGFontTraceEmitter.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-0.8.7/src/SVGFontTraceEmitter.cpp213
1 files changed, 213 insertions, 0 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-0.8.7/src/SVGFontTraceEmitter.cpp b/Build/source/texk/dvisvgm/dvisvgm-0.8.7/src/SVGFontTraceEmitter.cpp
new file mode 100644
index 00000000000..e7da9986581
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-0.8.7/src/SVGFontTraceEmitter.cpp
@@ -0,0 +1,213 @@
+/*************************************************************************
+** SVGFontTraceEmitter.cpp **
+** **
+** This file is part of dvisvgm -- the DVI to SVG converter **
+** Copyright (C) 2005-2009 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 <cstring>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include "Font.h"
+#include "FontCache.h"
+#include "FontManager.h"
+#include "GFGlyphTracer.h"
+#include "macros.h"
+#include "Message.h"
+#include "MetafontWrapper.h"
+#include "SVGFontTraceEmitter.h"
+#include "SVGTree.h"
+#include "TFM.h"
+#include "XMLNode.h"
+#include "XMLString.h"
+
+using namespace std;
+
+const char *SVGFontTraceEmitter::CACHE_PATH = 0;
+bool SVGFontTraceEmitter::TRACE_ALL = false;
+double SVGFontTraceEmitter::METAFONT_MAG = 4;
+
+
+SVGFontTraceEmitter::SVGFontTraceEmitter (const Font *f, const FontManager &fm, const CharmapTranslator &cmt, SVGTree &svg, bool uf)
+ : _gfTracer(0), _in(0), _font(f), _fontManager(fm), _cache(0),
+ _charmapTranslator(cmt), _svg(svg), _glyphNode(0), _useFonts(uf)
+{
+ if (CACHE_PATH && _font) {
+ _cache = new FontCache;
+ if (TRACE_ALL && prepareTracer()) {
+ traceAllGlyphs();
+ _cache->write(_font->name().c_str(), CACHE_PATH);
+ }
+ else
+ _cache->read(_font->name().c_str(), CACHE_PATH);
+ }
+}
+
+
+SVGFontTraceEmitter::~SVGFontTraceEmitter () {
+ delete _gfTracer;
+ delete _in;
+ if (_cache && _font)
+ _cache->write(_font->name().c_str(), CACHE_PATH);
+ delete _cache;
+ MetafontWrapper::removeOutputFiles(_font->name());
+}
+
+
+/** Creates the tracer object and calls Metafont to generate a GF file of the current font.
+ * @return true if GF file tracer were successfully created */
+bool SVGFontTraceEmitter::prepareTracer () {
+ if (!_gfTracer) {
+ MetafontWrapper mf(_font->name());
+ mf.make("ljfour", METAFONT_MAG); // call Metafont if necessary
+ if (mf.success() && _font->getTFM()) {
+ _in = new ifstream((_font->name()+".gf").c_str(), ios_base::binary);
+ _gfTracer = new GFGlyphTracer(*_in, 1000.0/_font->getTFM()->getDesignSize()); // 1000 units per em
+ Message::mstream() << "tracing glyphs of " << _font->name() << endl;
+ }
+ else {
+ Message::wstream(true) << "unable to find " << _font->name() << ".mf, can't embed font\n";
+ return false; // Metafont failed
+ }
+ }
+ return true;
+}
+
+
+int SVGFontTraceEmitter::emitFont (const char *id) {
+ // @@ not needed at the moment
+ return 0;
+}
+
+
+/** Appends a new font element of the current font to the SVG document.
+ * @param[in] usedChars characters to be embedded
+ * @param[in] id unique font identifier (usually the font name)
+ * @return number of embedded glyphs */
+int SVGFontTraceEmitter::emitFont (const set<int> &usedChars, const char *id) {
+ return emitFont(&usedChars, id);
+}
+
+
+/** Appends a new font element of the current font to the SVG document.
+ * @param[in] usedChars characters to be embedded
+ * @param[in] id unique font identifier (usually the font name)
+ * @return number of embedded glyphs */
+int SVGFontTraceEmitter::emitFont (const set<int> *usedChars, const char *id) {
+ if (!usedChars || usedChars->empty())
+ return 0;
+
+ XMLElementNode *fontNode=0;
+ if (_useFonts) {
+ fontNode = new XMLElementNode("font");
+ if (id && strlen(id) > 0)
+ fontNode->addAttribute("id", id);
+ _svg.appendToDefs(fontNode);
+
+ XMLElementNode *faceNode = new XMLElementNode("font-face");
+ faceNode->addAttribute("font-family", id);
+ faceNode->addAttribute("units-per-em", XMLString(1000));
+ fontNode->append(faceNode);
+ FORALL(*usedChars, set<int>::const_iterator, i) {
+ emitGlyph(*i); // create new glyphNode
+ fontNode->append(_glyphNode);
+ }
+ }
+ else {
+ FORALL(*usedChars, set<int>::const_iterator, i) {
+ emitGlyph(*i); // create new glyphNode
+ _svg.appendToDefs(_glyphNode);
+ }
+ }
+
+ if (_gfTracer)
+ Message::mstream() << endl;
+ return usedChars->size();
+}
+
+
+static inline void write_char_info (int c, ostream &os) {
+ os << '[';
+ if (isprint(c))
+ os << char(c);
+ else
+ os << '#' << c;
+}
+
+
+/** Creates the SVG definition of a single glyph.
+ * @param[in] c character code of the glyph
+ * @param[in] duplicate true if the glyph is already included in different size */
+bool SVGFontTraceEmitter::emitGlyph (int c) {
+ const TFM *tfm = _font->getTFM();
+ if (!tfm)
+ return false;
+
+ bool write_info=false;
+ const Glyph *glyph = _cache ? _cache->getGlyph(c) : 0;
+ if (!glyph && prepareTracer()) {
+ write_char_info(c, Message::wstream());
+ _gfTracer->executeChar(c);
+ glyph = &_gfTracer->getGlyph();
+ if (_cache)
+ _cache->setGlyph(c, _gfTracer->transferGlyph());
+ write_info = true;
+ }
+
+ ostringstream path;
+ double sx=1.0, sy=1.0;
+ if (_useFonts) {
+ _glyphNode = new XMLElementNode("glyph");
+ _glyphNode->addAttribute("unicode", XMLString(_charmapTranslator.unicode(c), false));
+ _glyphNode->addAttribute("horiz-adv-x", XMLString(1000.0*tfm->getCharWidth(c)/tfm->getDesignSize()));
+ }
+ else {
+ ostringstream oss;
+ oss << 'g' << _fontManager.fontID(_font) << c;
+ _glyphNode = new XMLElementNode("path");
+ _glyphNode->addAttribute("id", oss.str());
+ sx = _font->scaledSize()/1000.0; // 1000 units per em
+ sy = -sx;
+ }
+ glyph->writeSVGCommands(path, sx, sy);
+ _glyphNode->addAttribute("d", path.str());
+ if (write_info)
+ Message::mstream() << ']';
+ return true;
+}
+
+
+/** Traces all glyphs of the current font and stores them in the cache.
+ * If caching is disabled nothing happens. */
+void SVGFontTraceEmitter::traceAllGlyphs () {
+ const TFM *tfm = _font->getTFM();
+ if (tfm && _cache && prepareTracer()) {
+ int fchar = tfm->firstChar();
+ int lchar = tfm->lastChar();
+ for (int i=fchar; i <= lchar; i++) {
+ if (!_cache->getGlyph(i)) {
+ write_char_info(i, Message::wstream());
+ if (_gfTracer->executeChar(i)) // does char i exist in font?
+ _cache->setGlyph(i, _gfTracer->transferGlyph());
+ else
+ Message::wstream() << "(empty)";
+ Message::wstream() << ']';
+ }
+ }
+ }
+}