1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/*************************************************************************
** SVGFontEmitter.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 <sstream>
#include "macros.h"
#include "CharmapTranslator.h"
#include "Font.h"
#include "FontEncoding.h"
#include "FontEngine.h"
#include "FontManager.h"
#include "FontGlyph.h"
#include "SVGFontEmitter.h"
#include "SVGTree.h"
#include "XMLNode.h"
#include "XMLString.h"
using namespace std;
SVGFontEmitter::SVGFontEmitter (const Font *font, const FontManager &fm, const CharmapTranslator &cmt, SVGTree &svg, bool uf)
: _fontManager(fm), _charmapTranslator(cmt), _svg(svg), _useFonts(uf)
{
_font = font;
_fontEngine.setFont(font->path());
}
int SVGFontEmitter::emitFont (const char *id) {
return emitFont(0, id);
}
int SVGFontEmitter::emitFont (const set<int> &usedChars, const char *id) {
return emitFont(&usedChars, id);
}
int SVGFontEmitter::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);
fontNode->addAttribute("horiz-adv", XMLString(_fontEngine.getHAdvance()));
_svg.appendToDefs(fontNode);
XMLElementNode *faceNode = new XMLElementNode("font-face");
faceNode->addAttribute("font-family", (id && strlen(id) > 0) ? id : _fontEngine.getFamilyName());
faceNode->addAttribute("units-per-em", XMLString(_fontEngine.getUnitsPerEM()));
faceNode->addAttribute("ascent", XMLString(_fontEngine.getAscender()));
faceNode->addAttribute("descent", XMLString(_fontEngine.getDescender()));
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);
}
}
return usedChars->size();
}
bool SVGFontEmitter::emitGlyph (int c) {
double sx=1.0, sy=1.0;
FontEncoding *encoding = _fontManager.encoding(_font);
if (_useFonts) {
_glyphNode = new XMLElementNode("glyph");
_glyphNode->addAttribute("unicode", XMLString(_charmapTranslator.unicode(c), false));
int advance;
string name;
if (encoding && encoding->getEntry(c)) {
advance = _fontEngine.getHAdvance(encoding->getEntry(c));
name = encoding->getEntry(c);
}
else {
advance = _fontEngine.getHAdvance(c);
name = _fontEngine.getGlyphName(c);
}
_glyphNode->addAttribute("horiz-adv-x", XMLString(advance));
_glyphNode->addAttribute("glyph-name", name);
}
else {
ostringstream oss;
oss << 'g' << _fontManager.fontID(_font) << c;
_glyphNode = new XMLElementNode("path");
_glyphNode->addAttribute("id" , oss.str());
sx = double(_font->scaledSize())/_fontEngine.getUnitsPerEM();
sy = -sx;
}
ostringstream path;
Glyph glyph;
glyph.read(c, encoding, _fontEngine);
glyph.closeOpenPaths();
glyph.optimizeCommands();
glyph.writeSVGCommands(path, sx, sy);
_glyphNode->addAttribute("d", path.str());
return true;
}
|