summaryrefslogtreecommitdiff
path: root/dviware/dvisvgm/src
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/dvisvgm/src')
-rw-r--r--dviware/dvisvgm/src/Bezier.cpp4
-rw-r--r--dviware/dvisvgm/src/BgColorSpecialHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/BgColorSpecialHandler.hpp5
-rw-r--r--dviware/dvisvgm/src/Color.cpp29
-rw-r--r--dviware/dvisvgm/src/Color.hpp1
-rw-r--r--dviware/dvisvgm/src/ColorSpecialHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/ColorSpecialHandler.hpp5
-rw-r--r--dviware/dvisvgm/src/CommandLine.hpp2
-rw-r--r--dviware/dvisvgm/src/DVIActions.hpp1
-rw-r--r--dviware/dvisvgm/src/DVIReader.cpp7
-rw-r--r--dviware/dvisvgm/src/DVIToSVG.cpp63
-rw-r--r--dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp77
-rw-r--r--dviware/dvisvgm/src/DvisvgmSpecialHandler.hpp9
-rw-r--r--dviware/dvisvgm/src/EmSpecialHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/EmSpecialHandler.hpp7
-rw-r--r--dviware/dvisvgm/src/FileFinder.cpp1
-rw-r--r--dviware/dvisvgm/src/Font.cpp7
-rw-r--r--dviware/dvisvgm/src/Font.hpp2
-rw-r--r--dviware/dvisvgm/src/FontCache.cpp2
-rw-r--r--dviware/dvisvgm/src/FontManager.cpp7
-rw-r--r--dviware/dvisvgm/src/FontMetrics.cpp39
-rw-r--r--dviware/dvisvgm/src/FontMetrics.hpp13
-rw-r--r--dviware/dvisvgm/src/Ghostscript.cpp5
-rw-r--r--dviware/dvisvgm/src/GraphicsPathParser.hpp19
-rw-r--r--dviware/dvisvgm/src/HtmlSpecialHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/HtmlSpecialHandler.hpp5
-rw-r--r--dviware/dvisvgm/src/JFM.cpp39
-rw-r--r--dviware/dvisvgm/src/JFM.hpp9
-rw-r--r--dviware/dvisvgm/src/Makefile.am1
-rw-r--r--dviware/dvisvgm/src/Makefile.in37
-rw-r--r--dviware/dvisvgm/src/NoPsSpecialHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/NoPsSpecialHandler.hpp5
-rw-r--r--dviware/dvisvgm/src/OFM.cpp270
-rw-r--r--dviware/dvisvgm/src/OFM.hpp135
-rw-r--r--dviware/dvisvgm/src/PDFHandler.cpp31
-rw-r--r--dviware/dvisvgm/src/PDFHandler.hpp1
-rw-r--r--dviware/dvisvgm/src/PDFParser.cpp6
-rw-r--r--dviware/dvisvgm/src/PDFToSVG.cpp7
-rw-r--r--dviware/dvisvgm/src/Pair.hpp1
-rw-r--r--dviware/dvisvgm/src/PapersizeSpecialHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/PapersizeSpecialHandler.hpp5
-rw-r--r--dviware/dvisvgm/src/PathClipper.cpp12
-rw-r--r--dviware/dvisvgm/src/PdfSpecialHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/PdfSpecialHandler.hpp7
-rw-r--r--dviware/dvisvgm/src/Process.cpp11
-rw-r--r--dviware/dvisvgm/src/PsSpecialHandler.cpp6
-rw-r--r--dviware/dvisvgm/src/PsSpecialHandler.hpp7
-rw-r--r--dviware/dvisvgm/src/SVGCharPathHandler.cpp23
-rw-r--r--dviware/dvisvgm/src/SVGCharTspanTextHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/SVGElement.cpp9
-rw-r--r--dviware/dvisvgm/src/SVGElement.hpp3
-rw-r--r--dviware/dvisvgm/src/SVGSingleCharTextHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/SVGTree.hpp4
-rw-r--r--dviware/dvisvgm/src/SpecialHandler.hpp9
-rw-r--r--dviware/dvisvgm/src/SpecialManager.hpp10
-rw-r--r--dviware/dvisvgm/src/StreamReader.cpp28
-rw-r--r--dviware/dvisvgm/src/StreamReader.hpp1
-rw-r--r--dviware/dvisvgm/src/TFM.cpp60
-rw-r--r--dviware/dvisvgm/src/TFM.hpp12
-rw-r--r--dviware/dvisvgm/src/TpicSpecialHandler.cpp2
-rw-r--r--dviware/dvisvgm/src/TpicSpecialHandler.hpp7
-rw-r--r--dviware/dvisvgm/src/XMLNode.cpp2
-rw-r--r--dviware/dvisvgm/src/dvisvgm.cpp15
-rw-r--r--dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp12
-rw-r--r--dviware/dvisvgm/src/options.dtd2
-rw-r--r--dviware/dvisvgm/src/options.xml4
-rw-r--r--dviware/dvisvgm/src/ttf/HmtxTable.cpp2
-rw-r--r--dviware/dvisvgm/src/ttf/TTFWriter.cpp10
-rw-r--r--dviware/dvisvgm/src/ttf/VmtxTable.cpp2
-rw-r--r--dviware/dvisvgm/src/utility.cpp75
-rw-r--r--dviware/dvisvgm/src/utility.hpp1
71 files changed, 931 insertions, 280 deletions
diff --git a/dviware/dvisvgm/src/Bezier.cpp b/dviware/dvisvgm/src/Bezier.cpp
index 2d90122531..568fe19578 100644
--- a/dviware/dvisvgm/src/Bezier.cpp
+++ b/dviware/dvisvgm/src/Bezier.cpp
@@ -270,7 +270,7 @@ vector<QuadBezier> CubicBezier::toQuadBeziers (double precision, vector<double>
QuadBezier CubicBezier::midpointApproximation () const {
DPair p0 = (_points[1]*3.0 - _points[0])/2.0;
DPair p1 = (_points[2]*3.0 - _points[3])/2.0;
- return QuadBezier(_points[0], (p0+p1)/2.0, _points[3]);
+ return {_points[0], (p0+p1)/2.0, _points[3]};
}
@@ -305,7 +305,7 @@ void CubicBezier::toQuadBeziers (double t0, double t1, double precision, vector<
double tmax3 = 18.0/sqrt(3.0)*precision/dist; // the cube of tmax
if (tmax3 >= 1.0) {
// curve is already quadratic, no subdivision necessary, return MPA
- qbeziers.emplace_back(QuadBezier(_points[0], (q1+q2)/2.0, _points[3]));
+ qbeziers.emplace_back(_points[0], (q1+q2)/2.0, _points[3]);
if (startParams)
startParams->push_back(t0);
}
diff --git a/dviware/dvisvgm/src/BgColorSpecialHandler.cpp b/dviware/dvisvgm/src/BgColorSpecialHandler.cpp
index 86e5fb72d7..84cb55eb10 100644
--- a/dviware/dvisvgm/src/BgColorSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/BgColorSpecialHandler.cpp
@@ -62,7 +62,7 @@ void BgColorSpecialHandler::dviBeginPage (unsigned pageno, SpecialActions &actio
}
-vector<const char*> BgColorSpecialHandler::prefixes() const {
+vector<const char*> BgColorSpecialHandler::prefixes () const {
vector<const char*> pfx {"background"};
return pfx;
}
diff --git a/dviware/dvisvgm/src/BgColorSpecialHandler.hpp b/dviware/dvisvgm/src/BgColorSpecialHandler.hpp
index 7a0290b05f..cb6146477e 100644
--- a/dviware/dvisvgm/src/BgColorSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/BgColorSpecialHandler.hpp
@@ -31,8 +31,9 @@ class BgColorSpecialHandler : public SpecialHandler {
void preprocess (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
const char* info () const override {return "background color special";}
- const char* name () const override {return "bgcolor";}
- std::vector<const char*> prefixes() const override;
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "bgcolor";}
+ std::vector<const char*> prefixes () const override;
protected:
void dviBeginPage (unsigned pageno, SpecialActions &actions) override;
diff --git a/dviware/dvisvgm/src/Color.cpp b/dviware/dvisvgm/src/Color.cpp
index d5b6413081..42f786d869 100644
--- a/dviware/dvisvgm/src/Color.cpp
+++ b/dviware/dvisvgm/src/Color.cpp
@@ -55,6 +55,35 @@ void Color::setRGB (double r, double g, double b) {
}
+/** Sets the color value according to a given hex RGB string of the
+ * form "#123456" or "#123" where the latter is expanded to "#112233".
+ * The leading '#' character is optional.
+ * @param[in] hexString the RGB hex string
+ * @return true if the color value was assigned successfully */
+bool Color::setRGBHexString (string hexString) {
+ if (!hexString.empty()) {
+ if (hexString[0] == '#')
+ hexString = hexString.substr(1);
+ if (hexString.length() == 3) {
+ // expand short form "123" to "112233"
+ hexString.resize(6);
+ hexString[5] = hexString[4] = hexString[2];
+ hexString[3] = hexString[2] = hexString[1];
+ hexString[1] = hexString[0];
+ }
+ if (hexString.length() == 6) {
+ try {
+ _rgb = stoi(hexString, nullptr, 16);
+ return true;
+ }
+ catch (...) {
+ }
+ }
+ }
+ return false;
+}
+
+
/** Expects a PostScript color name and sets the color accordingly.
* @param[in] name PS color name
* @param[in] case_sensitive if true, upper/lower case spelling is significant
diff --git a/dviware/dvisvgm/src/Color.hpp b/dviware/dvisvgm/src/Color.hpp
index e133db7436..156aa269e4 100644
--- a/dviware/dvisvgm/src/Color.hpp
+++ b/dviware/dvisvgm/src/Color.hpp
@@ -56,6 +56,7 @@ class Color {
void setRGB (uint8_t r, uint8_t g, uint8_t b) {_rgb = (r << 16) | (g << 8) | b;}
void setRGB (double r, double g, double b);
void setRGB (const std::valarray<double> &rgb) {setRGB(rgb[0], rgb[1], rgb[2]);}
+ bool setRGBHexString (std::string hexString);
bool setPSName (std::string name, bool case_sensitive=true);
void setGray (uint8_t g) {setRGB(g,g,g);}
void setGray (double g) {setRGB(g,g,g);}
diff --git a/dviware/dvisvgm/src/ColorSpecialHandler.cpp b/dviware/dvisvgm/src/ColorSpecialHandler.cpp
index 35bc111ee3..c6a3e2bfd6 100644
--- a/dviware/dvisvgm/src/ColorSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/ColorSpecialHandler.cpp
@@ -113,7 +113,7 @@ bool ColorSpecialHandler::process (const string&, istream &is, SpecialActions &a
}
-vector<const char*> ColorSpecialHandler::prefixes() const {
+vector<const char*> ColorSpecialHandler::prefixes () const {
vector<const char*> pfx {"color"};
return pfx;
}
diff --git a/dviware/dvisvgm/src/ColorSpecialHandler.hpp b/dviware/dvisvgm/src/ColorSpecialHandler.hpp
index ea542e1f06..72809e8e0f 100644
--- a/dviware/dvisvgm/src/ColorSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/ColorSpecialHandler.hpp
@@ -33,9 +33,10 @@ class ColorSpecialHandler : public SpecialHandler {
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
static Color readColor (std::istream &is);
static Color readColor (const std::string &model, std::istream &is);
- const char* name () const override {return "color";}
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "color";}
const char* info () const override {return "complete support of color specials";}
- std::vector<const char*> prefixes() const override;
+ std::vector<const char*> prefixes () const override;
private:
std::stack<Color> _colorStack;
diff --git a/dviware/dvisvgm/src/CommandLine.hpp b/dviware/dvisvgm/src/CommandLine.hpp
index 72edde3ee1..d4f0745219 100644
--- a/dviware/dvisvgm/src/CommandLine.hpp
+++ b/dviware/dvisvgm/src/CommandLine.hpp
@@ -35,6 +35,7 @@ class CommandLine : public CL::CommandLine {
Option colorOpt {"color", '\0', "colorize messages"};
Option colornamesOpt {"colornames", '\0', "prefer color names to RGB values if possible"};
Option commentsOpt {"comments", '\0', "add comments with additional information"};
+ TypedOption<std::string, Option::ArgMode::OPTIONAL> currentcolorOpt {"currentcolor", '\0', "color", "#000", "replace given color with 'currentColor'"};
Option debugGlyphsOpt {"debug-glyphs", '\0', "create PS files for all glyphs converted to TTF"};
Option embedBitmapsOpt {"embed-bitmaps", '\0', "prevent references to external bitmap files"};
Option epsOpt {"eps", 'E', "convert EPS file to SVG"};
@@ -108,6 +109,7 @@ class CommandLine : public CL::CommandLine {
#endif
{&colornamesOpt, 1},
{&commentsOpt, 1},
+ {&currentcolorOpt, 1},
{&embedBitmapsOpt, 1},
#if !defined(DISABLE_WOFF)
{&fontFormatOpt, 1},
diff --git a/dviware/dvisvgm/src/DVIActions.hpp b/dviware/dvisvgm/src/DVIActions.hpp
index 8e2e2a0829..ed3c012f58 100644
--- a/dviware/dvisvgm/src/DVIActions.hpp
+++ b/dviware/dvisvgm/src/DVIActions.hpp
@@ -21,6 +21,7 @@
#ifndef DVIACTIONS_HPP
#define DVIACTIONS_HPP
+#include <cstdint>
#include <string>
#include <vector>
diff --git a/dviware/dvisvgm/src/DVIReader.cpp b/dviware/dvisvgm/src/DVIReader.cpp
index 6dd7bebb69..2c52ba5210 100644
--- a/dviware/dvisvgm/src/DVIReader.cpp
+++ b/dviware/dvisvgm/src/DVIReader.cpp
@@ -206,8 +206,11 @@ void DVIReader::putVFChar (Font *font, uint32_t c) {
FontManager &fm = FontManager::instance();
const vector<uint8_t> *dvi = vf->getDVI(c); // try to get DVI snippet that represents character c
Font *firstFont = fm.vfFirstFont(vf);
- if (!dvi && (!firstFont || !firstFont->getMetrics()->isJFM()))
- return;
+ if (!dvi) {
+ const FontMetrics *ffm = firstFont ? firstFont->getMetrics() : nullptr;
+ if (!ffm || (!ffm->isJFM() && !ffm->isOFM()))
+ return;
+ }
fm.enterVF(vf); // enter VF font number context
int savedFontNum = _currFontNum; // save current font number
setFont(fm.vfFirstFontNum(vf), SetFontMode::VF_ENTER);
diff --git a/dviware/dvisvgm/src/DVIToSVG.cpp b/dviware/dvisvgm/src/DVIToSVG.cpp
index f5501f33f6..ad809ca931 100644
--- a/dviware/dvisvgm/src/DVIToSVG.cpp
+++ b/dviware/dvisvgm/src/DVIToSVG.cpp
@@ -377,48 +377,67 @@ void DVIToSVG::embedFonts (XMLElement *svgElement) {
}
+static vector<string> extract_prefixes (const char *ignorelist) {
+ vector<string> prefixes;
+ if (ignorelist) {
+ const char *left = ignorelist;
+ while (*left) {
+ while (*left && !isalnum(*left))
+ left++;
+ const char *right = left;
+ while (*right && isalnum(*right))
+ right++;
+ if (*left)
+ prefixes.emplace_back(left, right-left);
+ left = right;
+ }
+ }
+ return prefixes;
+}
+
+
/** Enables or disables processing of specials. If ignorelist == 0, all
* supported special handlers are loaded. To disable selected sets of specials,
* the corresponding prefixes can be given separated by non alpha-numeric characters,
* e.g. "color, ps, em" or "color: ps em" etc.
* A single "*" in the ignore list disables all specials.
- * @param[in] ignorelist list of special prefixes to ignore
+ * @param[in] ignorelist list of hanlder names to ignore
* @param[in] pswarning if true, shows warning about disabled PS support
* @return the SpecialManager that handles special statements */
void DVIToSVG::setProcessSpecials (const char *ignorelist, bool pswarning) {
if (ignorelist && strcmp(ignorelist, "*") == 0) // ignore all specials?
SpecialManager::instance().unregisterHandlers();
else {
+ auto ignoredHandlerName = extract_prefixes(ignorelist);
// add special handlers
- vector<unique_ptr<SpecialHandler>> handlers;
- handlers.emplace_back(util::make_unique<BgColorSpecialHandler>()); // handles background color special
- handlers.emplace_back(util::make_unique<ColorSpecialHandler>()); // handles color specials
- handlers.emplace_back(util::make_unique<DvisvgmSpecialHandler>()); // handles raw SVG embeddings
- handlers.emplace_back(util::make_unique<EmSpecialHandler>()); // handles emTeX specials
- handlers.emplace_back(util::make_unique<HtmlSpecialHandler>()); // handles hyperref specials
- handlers.emplace_back(util::make_unique<PapersizeSpecialHandler>()); // handles papersize special
- handlers.emplace_back(util::make_unique<PdfSpecialHandler>()); // handles pdf specials
- handlers.emplace_back(util::make_unique<TpicSpecialHandler>()); // handles tpic specials
+ SpecialManager::registerHandler<BgColorSpecialHandler>(ignoredHandlerName); // handles background color special
+ SpecialManager::registerHandler<ColorSpecialHandler>(ignoredHandlerName); // handles color specials
+ SpecialManager::registerHandler<DvisvgmSpecialHandler>(ignoredHandlerName); // handles raw SVG embeddings
+ SpecialManager::registerHandler<EmSpecialHandler>(ignoredHandlerName); // handles emTeX specials
+ SpecialManager::registerHandler<HtmlSpecialHandler>(ignoredHandlerName); // handles hyperref specials
+ SpecialManager::registerHandler<PapersizeSpecialHandler>(ignoredHandlerName); // handles papersize special
+ SpecialManager::registerHandler<PdfSpecialHandler>(ignoredHandlerName); // handles pdf specials
+ SpecialManager::registerHandler<TpicSpecialHandler>(ignoredHandlerName); // handles tpic specials
+ if (find(ignoredHandlerName.begin(), ignoredHandlerName.end(), PsSpecialHandler::handlerName()) == ignoredHandlerName.end()) {
#ifndef DISABLE_GS
- if (Ghostscript().available())
- handlers.emplace_back(util::make_unique<PsSpecialHandler>()); // handles PostScript specials
- else
+ if (Ghostscript().available())
+ SpecialManager::registerHandler<PsSpecialHandler>(ignoredHandlerName); // handles PostScript specials
+ else
#endif
- {
+ {
#ifndef HAVE_LIBGS
- // dummy PS special handler that only prints warning messages
- handlers.emplace_back(util::make_unique<NoPsSpecialHandler>());
- if (pswarning) {
+ // dummy PS special handler that only prints warning messages
+ SpecialManager::registerHandler<NoPsSpecialHandler>(ignoredHandlerName);
+ if (pswarning) {
#ifdef DISABLE_GS
- Message::wstream() << "processing of PostScript specials has been disabled permanently\n";
+ Message::wstream() << "processing of PostScript specials has been disabled permanently\n";
#else
- Message::wstream() << "processing of PostScript specials is disabled (Ghostscript not found)\n";
+ Message::wstream() << "processing of PostScript specials is disabled (Ghostscript not found)\n";
#endif
- }
+ }
#endif
+ }
}
- SpecialManager::instance().unregisterHandlers();
- SpecialManager::instance().registerHandlers(handlers, ignorelist);
}
}
diff --git a/dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp b/dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp
index abeb52be36..0a84038500 100644
--- a/dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp
@@ -18,7 +18,6 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
-#include <array>
#include <cstring>
#include <utility>
#include "Calculator.hpp"
@@ -27,6 +26,7 @@
#include "InputBuffer.hpp"
#include "InputReader.hpp"
#include "Length.hpp"
+#include "Message.hpp"
#include "SpecialActions.hpp"
#include "SVGTree.hpp"
#include "utility.hpp"
@@ -95,24 +95,23 @@ DvisvgmSpecialHandler::DvisvgmSpecialHandler () : _currentMacro(_macros.end())
void DvisvgmSpecialHandler::preprocess (const string&, istream &is, SpecialActions&) {
- struct Command {
+ constexpr struct Command {
const char *name;
void (DvisvgmSpecialHandler::*handler)(InputReader&);
- };
- constexpr array<Command, 5> commands {{
+ } commands[] = {
{"raw", &DvisvgmSpecialHandler::preprocessRaw},
{"rawdef", &DvisvgmSpecialHandler::preprocessRawDef},
{"rawset", &DvisvgmSpecialHandler::preprocessRawSet},
{"endrawset", &DvisvgmSpecialHandler::preprocessEndRawSet},
{"rawput", &DvisvgmSpecialHandler::preprocessRawPut}
- }};
+ };
StreamInputReader ir(is);
const string cmdstr = ir.getWord();
- auto it = find_if(commands.begin(), commands.end(), [&](const Command &cmd) {
+ auto it = find_if(begin(commands), end(commands), [&](const Command &cmd) {
return cmd.name == cmdstr;
});
- if (it != commands.end()) {
+ if (it != end(commands)) {
ir.skipSpace();
(this->*it->handler)(ir);
}
@@ -172,25 +171,26 @@ void DvisvgmSpecialHandler::preprocessRawPut (InputReader &ir) {
* @param[in] is the special statement is read from this stream
* @param[in] actions object providing the actions that can be performed by the SpecialHandler */
bool DvisvgmSpecialHandler::process (const string &prefix, istream &is, SpecialActions &actions) {
- struct Command {
+ constexpr struct Command {
const char *name;
void (DvisvgmSpecialHandler::*handler)(InputReader&, SpecialActions&);
+ } commands[] = {
+ {"raw", &DvisvgmSpecialHandler::processRaw},
+ {"rawdef", &DvisvgmSpecialHandler::processRawDef},
+ {"rawset", &DvisvgmSpecialHandler::processRawSet},
+ {"endrawset", &DvisvgmSpecialHandler::processEndRawSet},
+ {"rawput", &DvisvgmSpecialHandler::processRawPut},
+ {"bbox", &DvisvgmSpecialHandler::processBBox},
+ {"img", &DvisvgmSpecialHandler::processImg},
+ {"currentcolor", &DvisvgmSpecialHandler::processCurrentColor},
+ {"message", &DvisvgmSpecialHandler::processMessage}
};
- constexpr array<Command, 7> commands {{
- {"raw", &DvisvgmSpecialHandler::processRaw},
- {"rawdef", &DvisvgmSpecialHandler::processRawDef},
- {"rawset", &DvisvgmSpecialHandler::processRawSet},
- {"endrawset", &DvisvgmSpecialHandler::processEndRawSet},
- {"rawput", &DvisvgmSpecialHandler::processRawPut},
- {"bbox", &DvisvgmSpecialHandler::processBBox},
- {"img", &DvisvgmSpecialHandler::processImg}
- }};
StreamInputReader ir(is);
const string cmdstr = ir.getWord();
- auto it = find_if(commands.begin(), commands.end(), [&](const Command &cmd) {
+ auto it = find_if(begin(commands), end(commands), [&](const Command &cmd) {
return cmd.name == cmdstr;
});
- if (it != commands.end()) {
+ if (it != end(commands)) {
ir.skipSpace();
(this->*it->handler)(ir, actions);
}
@@ -219,17 +219,16 @@ static void expand_constants (string &str, SpecialActions &actions) {
}
}
}
- struct Constant {
+ const struct Constant {
const char *name;
string val;
- };
- const array<Constant, 5> constants {{
+ } constants[] = {
{"x", XMLString(actions.getX())},
{"y", XMLString(actions.getY())},
- {"color", actions.getColor().svgColorString()},
+ {"color", SVGElement::USE_CURRENTCOLOR && SVGElement::CURRENTCOLOR == actions.getColor() ? "currentColor" : actions.getColor().svgColorString()},
{"matrix", actions.getMatrix().toSVG()},
{"nl", "\n"},
- }};
+ };
for (const Constant &constant : constants) {
const string pattern = string("{?")+constant.name+"}";
auto pos = str.find(pattern);
@@ -452,6 +451,34 @@ void DvisvgmSpecialHandler::processImg (InputReader &ir, SpecialActions &actions
}
+void DvisvgmSpecialHandler::processCurrentColor (InputReader &ir, SpecialActions &actions) {
+ string param = ir.getString();
+ Color color = actions.getColor();
+ if (param.empty() || param == "on") {
+ SVGElement::CURRENTCOLOR = color;
+ SVGElement::USE_CURRENTCOLOR = true;
+ }
+ else if (param == "off") {
+ if (SVGElement::USE_CURRENTCOLOR) {
+ // force a color change to get the new currentColor setting recognized
+ actions.setColor(Color{uint32_t(color)+1});
+ actions.setColor(color);
+ SVGElement::USE_CURRENTCOLOR = false;
+ }
+ }
+ else
+ throw SpecialException("currentcolor: unknown parameter '"+param+"'");
+}
+
+
+void DvisvgmSpecialHandler::processMessage (InputReader &ir, SpecialActions &actions) {
+ string message = ir.getLine();
+ evaluate_expressions(message, actions);
+ expand_constants(message, actions);
+ Message::mstream() << message << "\n";
+}
+
+
void DvisvgmSpecialHandler::dviPreprocessingFinished () {
string id;
if (_currentMacro != _macros.end())
@@ -486,7 +513,7 @@ void DvisvgmSpecialHandler::dviEndPage (unsigned, SpecialActions &actions) {
}
-vector<const char*> DvisvgmSpecialHandler::prefixes() const {
+vector<const char*> DvisvgmSpecialHandler::prefixes () const {
vector<const char*> pfx {"dvisvgm:"};
return pfx;
}
diff --git a/dviware/dvisvgm/src/DvisvgmSpecialHandler.hpp b/dviware/dvisvgm/src/DvisvgmSpecialHandler.hpp
index 4c9c84b078..7edecb12c8 100644
--- a/dviware/dvisvgm/src/DvisvgmSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/DvisvgmSpecialHandler.hpp
@@ -73,11 +73,12 @@ class DvisvgmSpecialHandler : public SpecialHandler {
public:
DvisvgmSpecialHandler ();
- const char* name () const override {return "dvisvgm";}
- const char* info () const override {return "special set for embedding raw SVG snippets";}
- std::vector<const char*> prefixes() const override;
void preprocess (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
+ const char* info () const override {return "special set for embedding raw SVG snippets";}
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "dvisvgm";}
+ std::vector<const char*> prefixes () const override;
protected:
void preprocessRaw (InputReader &ir);
@@ -92,6 +93,8 @@ class DvisvgmSpecialHandler : public SpecialHandler {
void processRawPut (InputReader &ir, SpecialActions &actions);
void processBBox (InputReader &ir, SpecialActions &actions);
void processImg (InputReader &ir, SpecialActions &actions);
+ void processCurrentColor (InputReader &ir, SpecialActions &actions);
+ void processMessage (InputReader &ir, SpecialActions &actions);
void dviPreprocessingFinished () override;
void dviBeginPage (unsigned pageno, SpecialActions &actions) override;
void dviEndPage (unsigned pageno, SpecialActions &actions) override;
diff --git a/dviware/dvisvgm/src/EmSpecialHandler.cpp b/dviware/dvisvgm/src/EmSpecialHandler.cpp
index e116227ba9..919de50b2c 100644
--- a/dviware/dvisvgm/src/EmSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/EmSpecialHandler.cpp
@@ -258,7 +258,7 @@ void EmSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) {
}
-vector<const char*> EmSpecialHandler::prefixes() const {
+vector<const char*> EmSpecialHandler::prefixes () const {
vector<const char*> pfx {"em:"};
return pfx;
}
diff --git a/dviware/dvisvgm/src/EmSpecialHandler.hpp b/dviware/dvisvgm/src/EmSpecialHandler.hpp
index aee0219c12..5adb90aaca 100644
--- a/dviware/dvisvgm/src/EmSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/EmSpecialHandler.hpp
@@ -38,10 +38,11 @@ class EmSpecialHandler : public SpecialHandler {
};
public:
- const char* name () const override {return "em";}
- const char* info () const override {return "line drawing statements of the emTeX special set";}
- std::vector<const char*> prefixes() const override;
bool process (const std::string &prefix, std::istream &in, SpecialActions &actions) override;
+ const char* info () const override {return "line drawing statements of the emTeX special set";}
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "em";}
+ std::vector<const char*> prefixes () const override;
protected:
void dviEndPage (unsigned pageno, SpecialActions &actions) override;
diff --git a/dviware/dvisvgm/src/FileFinder.cpp b/dviware/dvisvgm/src/FileFinder.cpp
index 369ef33f49..f01b230af2 100644
--- a/dviware/dvisvgm/src/FileFinder.cpp
+++ b/dviware/dvisvgm/src/FileFinder.cpp
@@ -161,6 +161,7 @@ const char* FileFinder::findFile (const std::string &fname, const char *ftype) c
#ifndef MIKTEX
static std::map<std::string, kpse_file_format_type> types = {
{"tfm", kpse_tfm_format},
+ {"ofm", kpse_ofm_format},
{"pfb", kpse_type1_format},
{"vf", kpse_vf_format},
{"mf", kpse_mf_format},
diff --git a/dviware/dvisvgm/src/Font.cpp b/dviware/dvisvgm/src/Font.cpp
index c60b162828..4645d33073 100644
--- a/dviware/dvisvgm/src/Font.cpp
+++ b/dviware/dvisvgm/src/Font.cpp
@@ -112,13 +112,14 @@ const FontMetrics* TFMFont::getMetrics () const {
try {
_metrics = FontMetrics::read(_fontname);
if (!_metrics) {
- _metrics = util::make_unique<NullFontMetric>();
+ _metrics = util::make_unique<NullFontMetrics>();
Message::wstream(true) << "can't find "+_fontname+".tfm\n";
}
}
catch (FontMetricException &e) {
- _metrics = util::make_unique<NullFontMetric>();
- Message::wstream(true) << e.what() << " in " << _fontname << ".tfm\n";
+ const char *ext = (_metrics && _metrics->isOFM()) ? ".ofm" : ".tfm";
+ _metrics = util::make_unique<NullFontMetrics>();
+ Message::wstream(true) << e.what() << " in " << _fontname << ext << "\n";
}
}
return _metrics.get();
diff --git a/dviware/dvisvgm/src/Font.hpp b/dviware/dvisvgm/src/Font.hpp
index 74f1b510cb..587a078500 100644
--- a/dviware/dvisvgm/src/Font.hpp
+++ b/dviware/dvisvgm/src/Font.hpp
@@ -291,6 +291,8 @@ class NativeFont : public PhysicalFont {
protected:
NativeFont (double ptsize, const FontStyle &style, Color color) : _ptsize(ptsize), _style(style), _color(color) {}
+ using PhysicalFont::hAdvance;
+ using PhysicalFont::vAdvance;
private:
double _ptsize; ///< font size in PS point units
diff --git a/dviware/dvisvgm/src/FontCache.cpp b/dviware/dvisvgm/src/FontCache.cpp
index 95155dc366..b89dc091c7 100644
--- a/dviware/dvisvgm/src/FontCache.cpp
+++ b/dviware/dvisvgm/src/FontCache.cpp
@@ -281,7 +281,7 @@ bool FontCache::fontinfo (const string &dirname, vector<FontInfo> &infos, vector
string path = dirname+"/"+(fname.substr(1));
ifstream ifs(path, ios::binary);
if (fontinfo(ifs, info))
- infos.push_back(move(info));
+ infos.push_back(std::move(info));
else
invalid.push_back(fname.substr(1));
}
diff --git a/dviware/dvisvgm/src/FontManager.cpp b/dviware/dvisvgm/src/FontManager.cpp
index bc6f88d322..3dcf87eae1 100644
--- a/dviware/dvisvgm/src/FontManager.cpp
+++ b/dviware/dvisvgm/src/FontManager.cpp
@@ -233,12 +233,13 @@ int FontManager::registerFont (uint32_t fontnum, const string &name, uint32_t ch
else {
// create dummy font as a placeholder if the proper font is not available
newfont = util::make_unique<EmptyFont>(name);
- if (filename.rfind('.') == string::npos)
- filename += ".mf";
// print warning message about missing font file (only once for each filename)
static set<string> missing_fonts;
if (missing_fonts.find(filename) == missing_fonts.end()) {
- Message::wstream(true) << "font file '" << filename << "' not found\n";
+ if (filename.rfind('.') == string::npos)
+ Message::wstream(true) << "no font file found for '" << filename << "'\n";
+ else
+ Message::wstream(true) << "font file '" << filename << "' not found\n";
missing_fonts.insert(filename);
}
}
diff --git a/dviware/dvisvgm/src/FontMetrics.cpp b/dviware/dvisvgm/src/FontMetrics.cpp
index 6147f36ab1..0edc1a6a79 100644
--- a/dviware/dvisvgm/src/FontMetrics.cpp
+++ b/dviware/dvisvgm/src/FontMetrics.cpp
@@ -23,19 +23,42 @@
#include "FileFinder.hpp"
#include "FontMetrics.hpp"
#include "JFM.hpp"
+#include "OFM.hpp"
#include "utility.hpp"
using namespace std;
+static inline uint16_t read_uint16 (istream &is) {
+ uint16_t val = 256*is.get();
+ return val + is.get();
+}
+
+/** Reads the font metrics for a given font name from a TFM, JFM, or OFM file.
+ * @param[in] fontname name of font to get the metrics for.
+ * @return pointer to object that holds the font metrics, or nullptr if no matching file was found */
unique_ptr<FontMetrics> FontMetrics::read (const string &fontname) {
- const char *path = FileFinder::instance().lookup(fontname + ".tfm");
+ unique_ptr<FontMetrics> metrics;
+ const char *path = FileFinder::instance().lookup(fontname + ".ofm", false);
+ if (!path)
+ path = FileFinder::instance().lookup(fontname + ".tfm");
ifstream ifs(path, ios::binary);
- if (!ifs)
- return unique_ptr<FontMetrics>();
- uint16_t id = 256*ifs.get();
- id += ifs.get();
- if (id == 9 || id == 11) // Japanese font metric file?
- return util::make_unique<JFM>(ifs);
- return util::make_unique<TFM>(ifs);
+ if (ifs) {
+ auto id = read_uint16(ifs);
+ if (id == 0) { // OFM?
+ auto ofmLevel = read_uint16(ifs);
+ if (ofmLevel == 0)
+ metrics = util::make_unique<OFM0>();
+ else if (ofmLevel == 1)
+ metrics = util::make_unique<OFM1>();
+ else
+ throw FontMetricException("OFM level "+to_string(ofmLevel)+" not supported");
+ }
+ else if (id == 9 || id == 11) // Japanese font metric file?
+ metrics = util::make_unique<JFM>();
+ else
+ metrics = util::make_unique<TFM>();
+ metrics->read(ifs);
+ }
+ return metrics;
}
diff --git a/dviware/dvisvgm/src/FontMetrics.hpp b/dviware/dvisvgm/src/FontMetrics.hpp
index 79cb579b2e..85427720e7 100644
--- a/dviware/dvisvgm/src/FontMetrics.hpp
+++ b/dviware/dvisvgm/src/FontMetrics.hpp
@@ -21,6 +21,7 @@
#ifndef FONTMETRICS_HPP
#define FONTMETRICS_HPP
+#include <cstdint>
#include <istream>
#include <memory>
#include <string>
@@ -28,6 +29,7 @@
struct FontMetrics {
virtual ~FontMetrics () =default;
+ virtual void read (std::istream &is) {}
virtual double getDesignSize () const =0;
virtual double getCharWidth (int c) const =0;
virtual double getCharHeight (int c) const =0;
@@ -41,14 +43,15 @@ struct FontMetrics {
virtual double getDescent () const =0;
virtual bool verticalLayout () const =0;
virtual uint32_t getChecksum () const =0;
- virtual uint16_t firstChar () const =0;
- virtual uint16_t lastChar () const =0;
+ virtual uint32_t firstChar () const =0;
+ virtual uint32_t lastChar () const =0;
virtual bool isJFM () const {return false;}
+ virtual bool isOFM () const {return false;}
static std::unique_ptr<FontMetrics> read (const std::string &fontname);
};
-struct NullFontMetric : public FontMetrics {
+struct NullFontMetrics : public FontMetrics {
double getDesignSize () const override {return 1;}
double getCharWidth (int c) const override {return 0;}
double getCharHeight (int c) const override {return 0;}
@@ -62,8 +65,8 @@ struct NullFontMetric : public FontMetrics {
double getDescent () const override {return 0;}
bool verticalLayout () const override {return false;}
uint32_t getChecksum () const override {return 0;}
- uint16_t firstChar () const override {return 0;}
- uint16_t lastChar () const override {return 0;}
+ uint32_t firstChar () const override {return 0;}
+ uint32_t lastChar () const override {return 0;}
};
diff --git a/dviware/dvisvgm/src/Ghostscript.cpp b/dviware/dvisvgm/src/Ghostscript.cpp
index fa6f1eb0eb..a428c01b9a 100644
--- a/dviware/dvisvgm/src/Ghostscript.cpp
+++ b/dviware/dvisvgm/src/Ghostscript.cpp
@@ -256,7 +256,10 @@ string Ghostscript::revisionstr () {
int major = rev / 1000;
int minor = (rev - major*1000)/10;
int patch = rev % 10;
- revstr = to_string(major) + "." + to_string(minor) + "." + to_string(patch);
+ revstr = to_string(major) + ".";
+ if (minor > 0 && minor < 10)
+ revstr += '0';
+ revstr += to_string(minor) + "." + to_string(patch);
}
}
return revstr;
diff --git a/dviware/dvisvgm/src/GraphicsPathParser.hpp b/dviware/dvisvgm/src/GraphicsPathParser.hpp
index 41a850db27..099614757d 100644
--- a/dviware/dvisvgm/src/GraphicsPathParser.hpp
+++ b/dviware/dvisvgm/src/GraphicsPathParser.hpp
@@ -27,6 +27,22 @@
#include "GraphicsPath.hpp"
#include "MessageException.hpp"
+namespace internal {
+ template <typename NumType>
+ bool parse_number (std::istream &is, NumType &value) {
+ is >> value;
+ return !is.fail();
+ }
+
+ template <>
+ bool parse_number (std::istream &is, double &value) {
+ // don't use operator >> for parsing floating point values because it's implemented
+ // differently in libstdc++ and libc++. Instead, use our own function to read the
+ // value from the input stream.
+ return util::read_double(is, value);
+ }
+}
+
struct GraphicsPathParserException : public MessageException {
explicit GraphicsPathParserException (const std::string &msg) : MessageException(msg) {}
@@ -48,8 +64,7 @@ class GraphicsPathParser {
NumType parseNumberOfType (std::istream &is) const {
is >> std::ws;
NumType number;
- is >> number;
- if (is.fail())
+ if (!internal::parse_number(is, number))
error("number expected", is);
is >> std::ws;
return number;
diff --git a/dviware/dvisvgm/src/HtmlSpecialHandler.cpp b/dviware/dvisvgm/src/HtmlSpecialHandler.cpp
index e86de7fb96..2f43ebde79 100644
--- a/dviware/dvisvgm/src/HtmlSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/HtmlSpecialHandler.cpp
@@ -80,7 +80,7 @@ void HtmlSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) {
}
-vector<const char*> HtmlSpecialHandler::prefixes() const {
+vector<const char*> HtmlSpecialHandler::prefixes () const {
vector<const char*> pfx {"html:"};
return pfx;
}
diff --git a/dviware/dvisvgm/src/HtmlSpecialHandler.hpp b/dviware/dvisvgm/src/HtmlSpecialHandler.hpp
index f722060538..33f564f63b 100644
--- a/dviware/dvisvgm/src/HtmlSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/HtmlSpecialHandler.hpp
@@ -31,9 +31,10 @@ class HtmlSpecialHandler : public SpecialHandler {
public:
void preprocess (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
- const char* name () const override {return "html";}
const char* info () const override {return "hyperref specials";}
- std::vector<const char*> prefixes() const override;
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "html";}
+ std::vector<const char*> prefixes () const override;
protected:
void dviEndPage (unsigned pageno, SpecialActions &actions) override;
diff --git a/dviware/dvisvgm/src/JFM.cpp b/dviware/dvisvgm/src/JFM.cpp
index c801618178..fc8fe56d8a 100644
--- a/dviware/dvisvgm/src/JFM.cpp
+++ b/dviware/dvisvgm/src/JFM.cpp
@@ -19,7 +19,6 @@
*************************************************************************/
#include <algorithm>
-#include <cstring>
#include <fstream>
#include <sstream>
#include "JFM.hpp"
@@ -28,27 +27,27 @@
using namespace std;
-JFM::JFM (istream &is) {
+void JFM::read (istream &is) {
is.seekg(0);
StreamReader reader(is);
- uint16_t id = uint16_t(reader.readUnsigned(2)); // JFM ID (9 or 11)
+ auto id = uint16_t(reader.readUnsigned(2)); // JFM ID (9 or 11)
if (id != 9 && id != 11)
throw FontMetricException("invalid JFM identifier " + std::to_string(id) + " (9 or 11 expected)");
_vertical = (id == 9);
- uint16_t nt = uint16_t(reader.readUnsigned(2)); // length of character type table
- uint16_t lf = uint16_t(reader.readUnsigned(2)); // length of entire file in 4 byte words
- uint16_t lh = uint16_t(reader.readUnsigned(2)); // length of header in 4 byte words
- uint16_t bc = uint16_t(reader.readUnsigned(2)); // smallest character code in font
- uint16_t ec = uint16_t(reader.readUnsigned(2)); // largest character code in font
- uint16_t nw = uint16_t(reader.readUnsigned(2)); // number of words in width table
- uint16_t nh = uint16_t(reader.readUnsigned(2)); // number of words in height table
- uint16_t nd = uint16_t(reader.readUnsigned(2)); // number of words in depth table
- uint16_t ni = uint16_t(reader.readUnsigned(2)); // number of words in italic corr. table
- uint16_t nl = uint16_t(reader.readUnsigned(2)); // number of words in glue/kern table
- uint16_t nk = uint16_t(reader.readUnsigned(2)); // number of words in kern table
- uint16_t ng = uint16_t(reader.readUnsigned(2)); // number of words in glue table
- uint16_t np = uint16_t(reader.readUnsigned(2)); // number of font parameter words
+ auto nt = uint16_t(reader.readUnsigned(2)); // length of character type table
+ auto lf = uint16_t(reader.readUnsigned(2)); // length of entire file in 4 byte words
+ auto lh = uint16_t(reader.readUnsigned(2)); // length of header in 4 byte words
+ auto bc = uint16_t(reader.readUnsigned(2)); // smallest character code in font
+ auto ec = uint16_t(reader.readUnsigned(2)); // largest character code in font
+ auto nw = uint16_t(reader.readUnsigned(2)); // number of words in width table
+ auto nh = uint16_t(reader.readUnsigned(2)); // number of words in height table
+ auto nd = uint16_t(reader.readUnsigned(2)); // number of words in depth table
+ auto ni = uint16_t(reader.readUnsigned(2)); // number of words in italic corr. table
+ auto nl = uint16_t(reader.readUnsigned(2)); // number of words in glue/kern table
+ auto nk = uint16_t(reader.readUnsigned(2)); // number of words in kern table
+ auto ng = uint16_t(reader.readUnsigned(2)); // number of words in glue table
+ auto np = uint16_t(reader.readUnsigned(2)); // number of font parameter words
if (7+nt+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ng+np != lf)
throw FontMetricException("inconsistent length values");
@@ -57,7 +56,7 @@ JFM::JFM (istream &is) {
readHeader(reader);
is.seekg(28+lh*4);
readTables(reader, nt, nw, nh, nd, ni);
- is.seekg(4*(lf-np), ios::beg);
+ is.seekg(4*(lf-np));
readParameters(reader, np); // JFM files provide 9 parameters but we don't need all of them
}
@@ -69,7 +68,7 @@ void JFM::readTables (StreamReader &reader, int nt, int nw, int nh, int nd, int
// support new JFM spec by texjporg
uint32_t c = reader.readUnsigned(2);
c += 0x10000 * reader.readUnsigned(1);
- uint8_t t = uint8_t(reader.readUnsigned(1));
+ auto t = uint8_t(reader.readUnsigned(1));
if (t > 0) {
minchar = min(minchar, c);
maxchar = max(maxchar, c);
@@ -84,7 +83,7 @@ void JFM::readTables (StreamReader &reader, int nt, int nw, int nh, int nd, int
// support new JFM spec by texjporg
uint32_t c = reader.readUnsigned(2);
c += 0x10000 * reader.readUnsigned(1);
- uint8_t t = uint8_t(reader.readUnsigned(1));
+ auto t = uint8_t(reader.readUnsigned(1));
if (c >= minchar)
_charTypeTable[c-minchar] = t;
}
@@ -93,7 +92,7 @@ void JFM::readTables (StreamReader &reader, int nt, int nw, int nh, int nd, int
}
-int JFM::charIndex (int c) const {
+size_t JFM::charIndex (int c) const {
uint8_t chartype = 0;
if (!_charTypeTable.empty() && uint32_t(c) >= _minchar && uint32_t(c) < _minchar+_charTypeTable.size())
chartype = _charTypeTable[c-_minchar];
diff --git a/dviware/dvisvgm/src/JFM.hpp b/dviware/dvisvgm/src/JFM.hpp
index 110f0f3e1a..c24798073c 100644
--- a/dviware/dvisvgm/src/JFM.hpp
+++ b/dviware/dvisvgm/src/JFM.hpp
@@ -27,7 +27,8 @@
class JFM : public TFM {
public:
- explicit JFM (std::istream &is);
+ JFM () =default;
+ void read (std::istream &is) override;
bool verticalLayout () const override {return _vertical;}
bool isJFM () const override {return true;}
uint32_t minChar () const {return _minchar;}
@@ -35,11 +36,11 @@ class JFM : public TFM {
protected:
void readTables (StreamReader &reader, int nt, int nw, int nh, int nd, int ni);
- int charIndex (int c) const override;
+ size_t charIndex (int c) const override;
private:
- uint32_t _minchar; ///< character code of first entry in character type table
- bool _vertical; ///< true if metrics refer to vertical text layout
+ uint32_t _minchar=0; ///< character code of first entry in character type table
+ bool _vertical=false; ///< true if metrics refer to vertical text layout
std::vector<uint8_t> _charTypeTable;
};
diff --git a/dviware/dvisvgm/src/Makefile.am b/dviware/dvisvgm/src/Makefile.am
index 1272a216f3..4ccab654f0 100644
--- a/dviware/dvisvgm/src/Makefile.am
+++ b/dviware/dvisvgm/src/Makefile.am
@@ -105,6 +105,7 @@ libdvisvgm_la_SOURCES = \
MetafontWrapper.hpp MetafontWrapper.cpp \
NoPsSpecialHandler.hpp NoPsSpecialHandler.cpp \
NumericRanges.hpp \
+ OFM.hpp OFM.cpp \
Opacity.hpp Opacity.cpp \
PageRanges.hpp PageRanges.cpp \
PageSize.hpp PageSize.cpp \
diff --git a/dviware/dvisvgm/src/Makefile.in b/dviware/dvisvgm/src/Makefile.in
index 411c96252d..a576da9bc4 100644
--- a/dviware/dvisvgm/src/Makefile.in
+++ b/dviware/dvisvgm/src/Makefile.in
@@ -144,17 +144,17 @@ am_libdvisvgm_la_OBJECTS = BasicDVIReader.lo Bezier.lo \
Ghostscript.lo HashFunction.lo HtmlSpecialHandler.lo \
HyperlinkManager.lo ImageToSVG.lo InputBuffer.lo \
InputReader.lo JFM.lo Length.lo MapLine.lo Matrix.lo \
- Message.lo MetafontWrapper.lo NoPsSpecialHandler.lo Opacity.lo \
- PageRanges.lo PageSize.lo PapersizeSpecialHandler.lo \
- PathClipper.lo PDFHandler.lo PDFParser.lo PdfSpecialHandler.lo \
- PDFToSVG.lo PreScanDVIReader.lo Process.lo psdefs.lo \
- PSInterpreter.lo PSPattern.lo PSPreviewFilter.lo \
- PsSpecialHandler.lo RangeMap.lo ShadingPatch.lo \
- SignalHandler.lo SourceInput.lo SpecialManager.lo \
- StreamReader.lo StreamWriter.lo Subfont.lo SVGCharHandler.lo \
- SVGCharHandlerFactory.lo SVGCharPathHandler.lo \
- SVGCharTspanTextHandler.lo SVGElement.lo SVGOutput.lo \
- SVGSingleCharTextHandler.lo SVGTree.lo System.lo \
+ Message.lo MetafontWrapper.lo NoPsSpecialHandler.lo OFM.lo \
+ Opacity.lo PageRanges.lo PageSize.lo \
+ PapersizeSpecialHandler.lo PathClipper.lo PDFHandler.lo \
+ PDFParser.lo PdfSpecialHandler.lo PDFToSVG.lo \
+ PreScanDVIReader.lo Process.lo psdefs.lo PSInterpreter.lo \
+ PSPattern.lo PSPreviewFilter.lo PsSpecialHandler.lo \
+ RangeMap.lo ShadingPatch.lo SignalHandler.lo SourceInput.lo \
+ SpecialManager.lo StreamReader.lo StreamWriter.lo Subfont.lo \
+ SVGCharHandler.lo SVGCharHandlerFactory.lo \
+ SVGCharPathHandler.lo SVGCharTspanTextHandler.lo SVGElement.lo \
+ SVGOutput.lo SVGSingleCharTextHandler.lo SVGTree.lo System.lo \
TensorProductPatch.lo Terminal.lo TFM.lo ToUnicodeMap.lo \
TpicSpecialHandler.lo TriangularPatch.lo Unicode.lo utility.lo \
VFReader.lo XMLDocument.lo XMLNode.lo XMLParser.lo \
@@ -213,11 +213,12 @@ am__depfiles_remade = ./$(DEPDIR)/BasicDVIReader.Plo \
./$(DEPDIR)/JFM.Plo ./$(DEPDIR)/Length.Plo \
./$(DEPDIR)/MapLine.Plo ./$(DEPDIR)/Matrix.Plo \
./$(DEPDIR)/Message.Plo ./$(DEPDIR)/MetafontWrapper.Plo \
- ./$(DEPDIR)/NoPsSpecialHandler.Plo ./$(DEPDIR)/Opacity.Plo \
- ./$(DEPDIR)/PDFHandler.Plo ./$(DEPDIR)/PDFParser.Plo \
- ./$(DEPDIR)/PDFToSVG.Plo ./$(DEPDIR)/PSInterpreter.Plo \
- ./$(DEPDIR)/PSPattern.Plo ./$(DEPDIR)/PSPreviewFilter.Plo \
- ./$(DEPDIR)/PageRanges.Plo ./$(DEPDIR)/PageSize.Plo \
+ ./$(DEPDIR)/NoPsSpecialHandler.Plo ./$(DEPDIR)/OFM.Plo \
+ ./$(DEPDIR)/Opacity.Plo ./$(DEPDIR)/PDFHandler.Plo \
+ ./$(DEPDIR)/PDFParser.Plo ./$(DEPDIR)/PDFToSVG.Plo \
+ ./$(DEPDIR)/PSInterpreter.Plo ./$(DEPDIR)/PSPattern.Plo \
+ ./$(DEPDIR)/PSPreviewFilter.Plo ./$(DEPDIR)/PageRanges.Plo \
+ ./$(DEPDIR)/PageSize.Plo \
./$(DEPDIR)/PapersizeSpecialHandler.Plo \
./$(DEPDIR)/PathClipper.Plo ./$(DEPDIR)/PdfSpecialHandler.Plo \
./$(DEPDIR)/PreScanDVIReader.Plo ./$(DEPDIR)/Process.Plo \
@@ -587,6 +588,7 @@ libdvisvgm_la_SOURCES = \
MetafontWrapper.hpp MetafontWrapper.cpp \
NoPsSpecialHandler.hpp NoPsSpecialHandler.cpp \
NumericRanges.hpp \
+ OFM.hpp OFM.cpp \
Opacity.hpp Opacity.cpp \
PageRanges.hpp PageRanges.cpp \
PageSize.hpp PageSize.cpp \
@@ -820,6 +822,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Message.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetafontWrapper.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NoPsSpecialHandler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OFM.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Opacity.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PDFHandler.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PDFParser.Plo@am__quote@ # am--include-marker
@@ -1156,6 +1159,7 @@ distclean: distclean-recursive
-rm -f ./$(DEPDIR)/Message.Plo
-rm -f ./$(DEPDIR)/MetafontWrapper.Plo
-rm -f ./$(DEPDIR)/NoPsSpecialHandler.Plo
+ -rm -f ./$(DEPDIR)/OFM.Plo
-rm -f ./$(DEPDIR)/Opacity.Plo
-rm -f ./$(DEPDIR)/PDFHandler.Plo
-rm -f ./$(DEPDIR)/PDFParser.Plo
@@ -1299,6 +1303,7 @@ maintainer-clean: maintainer-clean-recursive
-rm -f ./$(DEPDIR)/Message.Plo
-rm -f ./$(DEPDIR)/MetafontWrapper.Plo
-rm -f ./$(DEPDIR)/NoPsSpecialHandler.Plo
+ -rm -f ./$(DEPDIR)/OFM.Plo
-rm -f ./$(DEPDIR)/Opacity.Plo
-rm -f ./$(DEPDIR)/PDFHandler.Plo
-rm -f ./$(DEPDIR)/PDFParser.Plo
diff --git a/dviware/dvisvgm/src/NoPsSpecialHandler.cpp b/dviware/dvisvgm/src/NoPsSpecialHandler.cpp
index 2c17e30690..644b2220d8 100644
--- a/dviware/dvisvgm/src/NoPsSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/NoPsSpecialHandler.cpp
@@ -39,7 +39,7 @@ void NoPsSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) {
}
-vector<const char*> NoPsSpecialHandler::prefixes() const {
+vector<const char*> NoPsSpecialHandler::prefixes () const {
vector<const char*> pfx {"header=", "psfile=", "PSfile=", "ps:", "ps::", "!", "\""};
return pfx;
}
diff --git a/dviware/dvisvgm/src/NoPsSpecialHandler.hpp b/dviware/dvisvgm/src/NoPsSpecialHandler.hpp
index f7132d2c75..3cd89b98f8 100644
--- a/dviware/dvisvgm/src/NoPsSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/NoPsSpecialHandler.hpp
@@ -26,9 +26,10 @@
class NoPsSpecialHandler : public SpecialHandler {
public:
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
- const char* name () const override {return nullptr;}
const char* info () const override {return nullptr;}
- std::vector<const char*> prefixes() const override;
+ const char* name () const override {return nullptr;}
+ static const char* handlerName () {return nullptr;}
+ std::vector<const char*> prefixes () const override;
protected:
void dviEndPage (unsigned pageno, SpecialActions &actions) override;
diff --git a/dviware/dvisvgm/src/OFM.cpp b/dviware/dvisvgm/src/OFM.cpp
new file mode 100644
index 0000000000..63872671f1
--- /dev/null
+++ b/dviware/dvisvgm/src/OFM.cpp
@@ -0,0 +1,270 @@
+/*************************************************************************
+** OFM.cpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2023 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 <cstdint>
+#include <string>
+#include "Length.hpp"
+#include "OFM.hpp"
+
+using namespace std;
+
+
+static uint32_t read_uint32 (StreamReader &reader, const string &name) {
+ uint32_t quad = reader.readUnsigned(4);
+ if (quad & 0x80000000)
+ throw FontMetricException("negative '"+name+"' value not permitted");
+ return quad;
+}
+
+void OFM::FileDimensions::read (StreamReader &reader) {
+ lf = read_uint32(reader, "lf");
+ lh = read_uint32(reader, "lh");
+ bc = read_uint32(reader, "bc");
+ ec = read_uint32(reader, "ec");
+ nw = read_uint32(reader, "nw");
+ nh = read_uint32(reader, "nh");
+ nd = read_uint32(reader, "nd");
+ ni = read_uint32(reader, "ni");
+ nl = read_uint32(reader, "nl");
+ nk = read_uint32(reader, "nk");
+ ne = read_uint32(reader, "ne");
+ np = read_uint32(reader, "np");
+ dir = read_uint32(reader, "font-dir");
+}
+
+
+/** Reads the common beginning of OFM level 0 and 1 files, and initializes
+ * the corresponding members.
+ * @param[in] is reads from this stream
+ * @param[in] maxNumWidths maximum number of width entries
+ * @return the collected data (file offsets, table sizes, writing direction) */
+OFM::FileDimensions OFM::read (istream &is, uint32_t maxNumWidths) {
+ OFM::FileDimensions dim;
+ if (is) {
+ is.seekg(0);
+ StreamReader sr(is);
+ uint32_t ofmLevel = sr.readUnsigned(4);
+ if (ofmLevel > 1)
+ throw FontMetricException("OFM level "+to_string(ofmLevel)+" not supported");
+ if (int(ofmLevel) != level())
+ throw FontMetricException("OFM level "+to_string(level())+" expected but found level "+to_string(ofmLevel));
+ dim.read(sr);
+ if (dim.nw > maxNumWidths)
+ throw FontMetricException("invalid size of width table");
+ _firstChar = dim.bc; // smallest character code in font
+ _lastChar = dim.ec; // largest character code in font
+ _vertical = (dim.dir > 0);
+ }
+ return dim;
+}
+
+
+/** Reads and stores the required data from the OFM header. */
+void OFM::readHeader (StreamReader &reader) {
+ _checksum = reader.readUnsigned(4);
+ _designSize = double(FixWord(reader.readSigned(4)))*Length::pt2bp;
+}
+
+
+/** Reads a sequence of values and stores them in a vector.
+ * @param[in] reader the TFM data is read from this object
+ * @param[out] words vector taking the read words
+ * @param[in] n number of entries to read */
+static void read_words (StreamReader &reader, vector<FixWord> &words, size_t n) {
+ words.resize(n);
+ for (size_t i=0; i < n; i++)
+ words[i] = reader.readSigned(4);
+}
+
+
+/** Reads and stores the required OFM tables (characters widths, heights, depths, ...). */
+void OFM::readTables (StreamReader &reader, const FileDimensions &dim) {
+ read_words(reader, _widthTable, dim.nw);
+ read_words(reader, _heightTable, dim.nh);
+ read_words(reader, _depthTable, dim.nd);
+ read_words(reader, _italicTable, dim.ni);
+ reader.skip(8*dim.nl + 4*dim.nk + 8*dim.ne);
+ read_words(reader, _params, min(dim.np, 7u)); // we only need params 0-6
+ _params.resize(7, 0); // ensure 7 parameters
+ for (FixWord h : _heightTable)
+ _ascent = max(_ascent, h);
+ for (FixWord d : _depthTable)
+ _descent = max(_descent, d);
+}
+
+
+/** Returns the character index for a given character or -1 if
+ * the OFM file doesn't contain information on the character. */
+size_t OFM::charIndex (int c) const {
+ uint32_t chr=c;
+ if (chr < _firstChar || chr > _lastChar || size_t(chr-_firstChar) >= numCharInfos())
+ return -1;
+ return chr-_firstChar;
+}
+
+
+/** Returns the width of a character in bp units. */
+double OFM::getCharWidth (int c) const {
+ auto cindex = charIndex(c);
+ if (cindex == size_t(-1))
+ return 0;
+ return double(_widthTable[widthIndex(cindex)])*_designSize;
+}
+
+
+/** Returns the height of a character in bp units. */
+double OFM::getCharHeight (int c) const {
+ auto cindex = charIndex(c);
+ if (cindex == size_t(-1))
+ return 0;
+ return double(_heightTable[heightIndex(cindex)])*_designSize;
+}
+
+
+/** Returns the depth of a character in bp units. */
+double OFM::getCharDepth (int c) const {
+ auto cindex = charIndex(c);
+ if (cindex == size_t(-1))
+ return 0;
+ return double(_depthTable[depthIndex(cindex)])*_designSize;
+}
+
+
+/** Returns the italic correction width of a character in bp units. */
+double OFM::getItalicCorr (int c) const {
+ auto cindex = charIndex(c);
+ if (cindex == size_t(-1))
+ return 0;
+ return double(_italicTable[italicIndex(cindex)])*_designSize;
+}
+
+/** Returns the optimal space width between words in bp units. */
+double OFM::getSpace () const {
+ return _params.empty() ? 0 : double(_params[1])*_designSize;
+}
+
+
+/** Returns the amount of glue stretching between words in bp units. */
+double OFM::getSpaceStretch () const {
+ return _params.empty() ? 0 : double(_params[2])*_designSize;
+}
+
+
+/** Returns the amount of glue shrinking between words in bp units. */
+double OFM::getSpaceShrink () const {
+ return _params.empty() ? 0 : double(_params[3])*_designSize;
+}
+
+
+/** Returns the size of one EM unit in bp units. */
+double OFM::getQuad () const {
+ if (_params.empty() || _params[5] == 0)
+ return _designSize;
+ return double(_params[5])*_designSize;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+/** Reads and stores the required data from an OFM level 0 data stream. */
+void OFM0::read (std::istream &is) {
+ auto dim = OFM::read(is, 0xFFFF);
+ if (_firstChar >= _lastChar || _lastChar > 0xFFFF)
+ throw FontMetricException("character codes out of range");
+ if (14 + dim.lh + 2*(dim.ec-dim.bc+1) + dim.nw + dim.nh + dim.nd + dim.ni +2*dim.nl + dim.nk + 2*dim.ne + dim.np != dim.lf)
+ throw FontMetricException("inconsistent table size values");
+ StreamReader sr(is);
+ readHeader(sr);
+ sr.seek(56 + dim.lh*4); // move to char info table
+ readCharInfos(sr);
+ readTables(sr, dim);
+}
+
+
+/** Reads and stores the required data from the char-info section.
+ * Expects the stream pointer to be located on the first byte of the first char-info entry. */
+void OFM0::readCharInfos (StreamReader &reader) {
+ auto numChars = _lastChar-_firstChar+1;
+ _charInfos.resize(numChars);
+ for (size_t i=0; i < numChars; i++) {
+ _charInfos[i] = uint64_t(reader.readUnsigned(4)) << 32;
+ _charInfos[i] |= reader.readUnsigned(4);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/** Reads and stores the required data from an OFM level 1 data stream. */
+void OFM1::read (std::istream &is) {
+ auto dim = OFM::read(is, 0x110000);
+ if (_firstChar >= _lastChar || _lastChar > 0x10FFFF)
+ throw FontMetricException("character codes out of range");
+ StreamReader sr(is);
+ uint32_t nco = sr.readUnsigned(4); // OFM1: offset of char-info table (in 4-byte words)
+ _ncw = sr.readUnsigned(4); // total number of character info words in OFM file
+ _npc = sr.readUnsigned(4); // number of parameters per character
+ // check validity of number entries for new (OFM level 1) table types
+ size_t sum=0, numTables=0;
+ for (int i=0; i < 12; i++) {
+ uint32_t num = sr.readUnsigned(4);
+ sum += num;
+ if (i%2 == 0)
+ numTables += num;
+ }
+ if (numTables > 32)
+ throw FontMetricException("too many OFM level 1 tables");
+ if (29 + dim.lh + _ncw + dim.nw + dim.nh + dim.nd + dim.ni +2*dim.nl + dim.nk + 2*dim.ne + dim.np + sum != dim.lf)
+ throw FontMetricException("inconsistent table size values");
+ readHeader(sr);
+ sr.seek(4*nco); // move to char info table
+ readCharInfos(sr);
+ readTables(sr, dim);
+}
+
+
+/** Reads and stores the required data from the char-info section.
+ * Expects the stream pointer to be located on the first byte of the first char-info entry. */
+void OFM1::readCharInfos (StreamReader &reader) {
+ auto numCharInfos = _ncw/(3 + _npc/2); // number of char info entries in file
+ auto numChars = _lastChar-_firstChar+1;
+ size_t numCharsRead=0;
+ _charInfos.reserve(numChars);
+ while (numCharsRead <= numChars && numCharInfos > 0) {
+ CharInfo info;
+ info.widthIndex = uint16_t(reader.readUnsigned(2));
+ info.heightIndex = uint8_t(reader.readUnsigned(1));
+ info.depthIndex = uint8_t(reader.readUnsigned(1));
+ info.italicIndex = uint8_t(reader.readUnsigned(1));
+ reader.skip(3); // skip RFU, ext-tag, tag, and remainder
+ auto repeats = uint16_t(reader.readUnsigned(2));
+ if (numCharsRead + repeats > numChars)
+ throw FontMetricException("number of characters exceeded due to too many char-info repeats");
+ reader.skip(_npc*2); // skip parameters
+ if (_npc%2 == 0)
+ reader.skip(2); // skip padding bytes
+ for (int j=0; j <= repeats; j++)
+ _charInfos.push_back(info);
+ numCharsRead += repeats+1;
+ numCharInfos--;
+ }
+ if (numCharInfos > 0)
+ throw FontMetricException("more char-info entries present than characters");
+ if (numCharsRead < numChars)
+ throw FontMetricException("not all characters covered by char-info entries");
+}
diff --git a/dviware/dvisvgm/src/OFM.hpp b/dviware/dvisvgm/src/OFM.hpp
new file mode 100644
index 0000000000..560bc1f634
--- /dev/null
+++ b/dviware/dvisvgm/src/OFM.hpp
@@ -0,0 +1,135 @@
+/*************************************************************************
+** OFM.hpp **
+** **
+** This file is part of dvisvgm -- a fast DVI to SVG converter **
+** Copyright (C) 2005-2023 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/>. **
+*************************************************************************/
+
+#ifndef OFM_HPP
+#define OFM_HPP
+
+#include <vector>
+#include "FixWord.hpp"
+#include "FontMetrics.hpp"
+#include "StreamReader.hpp"
+
+class OFM : public FontMetrics {
+ public:
+ virtual int level () const =0;
+ bool isOFM () const override {return true;}
+ uint32_t getChecksum () const override {return _checksum;}
+ uint32_t firstChar () const override {return _firstChar;}
+ uint32_t lastChar () const override {return _lastChar;}
+ bool verticalLayout () const override {return _vertical;}
+ double getDesignSize () const override {return _designSize;}
+ double getAscent () const override {return double(_ascent)*_designSize;}
+ double getDescent () const override {return double(_descent)*_designSize;}
+ double getCharWidth (int c) const override;
+ double getCharHeight (int c) const override;
+ double getCharDepth (int c) const override;
+ double getItalicCorr (int c) const override;
+ double getSpace () const override;
+ double getSpaceStretch () const override;
+ double getSpaceShrink () const override;
+ double getQuad () const override;
+ using FontMetrics::read;
+
+ protected:
+ struct FileDimensions {
+ uint32_t lf=0; // length of file in 4-byte words
+ uint32_t lh=0; // length of header data in 4-byte words
+ uint32_t bc=0; // smallest character code
+ uint32_t ec=0; // largest character code
+ uint32_t nw=0; // number of width entries
+ uint32_t nh=0; // number of height entries
+ uint32_t nd=0; // number of depth entries
+ uint32_t ni=0; // number of italic correction entries
+ uint32_t nl=0; // number of lig-kern entries
+ uint32_t nk=0; // number of kern entries
+ uint32_t ne=0; // number of extensible character entries
+ uint32_t np=0; // number of font parameter words
+ uint32_t dir=0; // writing direction of font
+ void read (StreamReader &reader);
+ };
+
+ FileDimensions read (std::istream &is, uint32_t maxNumWidths);
+ void readHeader (StreamReader &reader);
+ void readTables (StreamReader &reader, const FileDimensions &dim);
+ size_t charIndex (int c) const;
+ virtual size_t numCharInfos () const =0;
+ virtual size_t widthIndex (size_t n) const =0;
+ virtual size_t heightIndex (size_t n) const =0;
+ virtual size_t depthIndex (size_t n) const =0;
+ virtual size_t italicIndex (size_t n) const =0;
+
+ protected:
+ uint32_t _checksum=0;
+ uint32_t _firstChar=0, _lastChar=0;
+ double _designSize=0; ///< design size of the font in PS points (72bp = 1in)
+ std::vector<FixWord> _widthTable; ///< character widths in design size units
+ std::vector<FixWord> _heightTable; ///< character height in design size units
+ std::vector<FixWord> _depthTable; ///< character depth in design size units
+ std::vector<FixWord> _italicTable; ///< italic corrections in design size units
+ std::vector<FixWord> _params; ///< values of the OFM's param section
+ FixWord _ascent=0, _descent=0; ///< max. height and depth
+ bool _vertical=false; ///< true if metrics refer to vertical text layout
+};
+
+
+class OFM0 : public OFM {
+ public:
+ void read (std::istream &is) override;
+ int level () const override {return 0;}
+
+ protected:
+ void readCharInfos (StreamReader &reader);
+ size_t numCharInfos () const override {return _charInfos.size();}
+ size_t widthIndex (size_t n) const override {return (_charInfos[n] >> 48) & 0xFFFF;}
+ size_t heightIndex (size_t n) const override {return (_charInfos[n] >> 40) & 0xFF;}
+ size_t depthIndex (size_t n) const override {return (_charInfos[n] >> 32) & 0xFF;}
+ size_t italicIndex (size_t n) const override {return (_charInfos[n] >> 24) & 0xFF;}
+
+ private:
+ std::vector<uint64_t> _charInfos;
+};
+
+
+class OFM1 : public OFM {
+ struct CharInfo {
+ uint16_t widthIndex=0;
+ uint8_t heightIndex=0;
+ uint8_t depthIndex=0;
+ uint8_t italicIndex=0;
+ };
+ public:
+ void read (std::istream &is) override;
+ int level () const override {return 1;}
+
+ protected:
+ void readCharInfos (StreamReader &reader);
+ size_t numCharInfos () const override {return _charInfos.size();}
+ size_t widthIndex (size_t n) const override {return _charInfos[n].widthIndex;}
+ size_t heightIndex (size_t n) const override {return _charInfos[n].heightIndex;}
+ size_t depthIndex (size_t n) const override {return _charInfos[n].depthIndex;}
+ size_t italicIndex (size_t n) const override {return _charInfos[n].italicIndex;}
+
+ private:
+ uint32_t _ncw=0;
+ uint32_t _npc=0;
+ std::vector<CharInfo> _charInfos;
+};
+
+#endif
diff --git a/dviware/dvisvgm/src/PDFHandler.cpp b/dviware/dvisvgm/src/PDFHandler.cpp
index ba88e69852..9d374e9874 100644
--- a/dviware/dvisvgm/src/PDFHandler.cpp
+++ b/dviware/dvisvgm/src/PDFHandler.cpp
@@ -139,6 +139,12 @@ string PDFHandler::mutoolVersion () {
}
+/** Returns the total number of pages of a PDF file. */
+int PDFHandler::numberOfPages (const string &fname) {
+ return parse_value<int>(mtShow("\""+fname+"\"", "trailer/Root/Pages/Count"));
+}
+
+
/** Converts a single page of a PDF file to SVG. If no context element is given,
* the SVG page contents are added to a page group element of the SVG tree.
* Otherwise, they are added to the context element which is not inserted into
@@ -175,6 +181,7 @@ unique_ptr<SVGElement> PDFHandler::convert (const string &fname, int pageno, uni
void PDFHandler::initFile (const string &fname) {
finishFile();
_fname = FilePath(fname, true).absolute();
+ _fname = "\"" + _fname + "\"";
_numPages = parse_value<int>(mtShow("trailer/Root/Pages/Count"));
// extract image and font files from the PDF
string cwd = FileSystem::getcwd();
@@ -472,7 +479,7 @@ void PDFHandler::doClipPath (XMLElement *trcClipPathElement) {
auto clipPathElement = util::make_unique<SVGElement>("clipPath");
clipPathElement->addAttribute("id", id);
auto groupElement = util::make_unique<SVGElement>("g");
- _clipPathStack.emplace(ClipPathData{std::move(id), groupElement.get()});
+ _clipPathStack.emplace(std::move(id), groupElement.get());
groupElement->setClipPathUrl(_clipPathStack.top().id);
clipPathElement->append(std::move(pathElement));
_svg->appendToDefs(std::move(clipPathElement));
@@ -496,7 +503,7 @@ void PDFHandler::doClipStrokePath (XMLElement *trcClipStrokePathElement) {
maskElement->append(std::move(pathElement));
auto groupElement = util::make_unique<SVGElement>("g");
groupElement->setMaskUrl(id);
- _clipPathStack.emplace(ClipPathData{std::move(id), groupElement.get()});
+ _clipPathStack.emplace(std::move(id), groupElement.get());
_svg->appendToDefs(std::move(maskElement));
_svg->pushPageContext(std::move(groupElement));
}
@@ -508,7 +515,7 @@ void PDFHandler::doClipText (XMLElement *trcClipTextElement) {
auto clipPathElement = util::make_unique<SVGElement>("clipPath");
clipPathElement->addAttribute("id", id);
auto groupElement = util::make_unique<SVGElement>("g");
- _clipPathStack.emplace(ClipPathData{std::move(id), groupElement.get()});
+ _clipPathStack.emplace(std::move(id), groupElement.get());
groupElement->setClipPathUrl(_clipPathStack.top().id);
SVGElement *cpElementPtr = clipPathElement.get();
_svg->pushPageContext(std::move(clipPathElement));
@@ -630,9 +637,14 @@ void PDFHandler::doFillText (XMLElement *trcFillTextElement) {
auto trm = parse_attr_value<vector<double>>(spanElement, "trm");
if (trm.size() < 4 || trm[0] == 0)
continue;
- auto fontname = strip_subset_prefix(parse_attr_value<string>(spanElement, "font"));
- string filename;
+ auto fontname = parse_attr_value<string>(spanElement, "font");
auto it = _objDict.find(fontname);
+ if (it == _objDict.end()) {
+ // try to lookup font without subfont prefix
+ fontname = strip_subset_prefix(fontname);
+ it = _objDict.find(fontname);
+ }
+ string filename;
if (it != _objDict.end())
filename = it->second.fname;
if (filename.empty())
@@ -789,11 +801,10 @@ void PDFHandler::collectObjects () {
for (auto &entry : _extractedFiles) {
if (entry.second.substr(0, 5) == "font-") {
string filepath = tmpdir+entry.second; // path to font file
- string fontname = strip_subset_prefix(FontEngine::instance().getPSName(filepath));
- // If the extracted font file doesn't contain a font name,
- // try to get it from the corresponding PDF object.
- if (fontname.empty())
- fontname = mtShow(to_string(entry.first)+"/FontName", SearchPattern(R"(/(\w+))", "$1"));
+ string psFontname = FontEngine::instance().getPSName(filepath);
+ string fontname = mtShow(to_string(entry.first) + "/FontName", SearchPattern(R"(/((\w|[+-])+))", "$1"));
+ if (!psFontname.empty() && fontname.find('+') == string::npos)
+ fontname = std::move(psFontname);
_objDict.emplace(fontname, ObjID(entry.first, 0, filepath));
}
}
diff --git a/dviware/dvisvgm/src/PDFHandler.hpp b/dviware/dvisvgm/src/PDFHandler.hpp
index 3400a1d69d..708c9969ef 100644
--- a/dviware/dvisvgm/src/PDFHandler.hpp
+++ b/dviware/dvisvgm/src/PDFHandler.hpp
@@ -58,6 +58,7 @@ class PDFHandler {
std::unique_ptr<SVGElement> convert (const std::string &fname, int pageno, std::unique_ptr<SVGElement> context=nullptr);
static std::string mutoolVersion ();
static bool available () {return !mutoolVersion().empty();}
+ static int numberOfPages (const std::string &fname);
protected:
static std::string mutool (const std::string &cmd, bool readFromStderr=false);
diff --git a/dviware/dvisvgm/src/PDFParser.cpp b/dviware/dvisvgm/src/PDFParser.cpp
index b92ce54e7f..6a8fa2f3cf 100644
--- a/dviware/dvisvgm/src/PDFParser.cpp
+++ b/dviware/dvisvgm/src/PDFParser.cpp
@@ -275,7 +275,7 @@ static PDFStream parse_stream (InputReader &ir, const char *delim) {
do
ir.skipUntil("endstream");
while (ir.peek() >= 0 && !strchr(delim, ir.peek())); // ensure delimiter after "endstream"
- return PDFStream();
+ return {};
}
@@ -289,7 +289,7 @@ static PDFIndirectObject parse_indirect_object (InputReader &ir, const char *del
const int *objno = objects.back().get<int>();
objects.pop_back();
if (objno && genno)
- return PDFIndirectObject(*objno, *genno);
+ return {*objno, *genno};
}
throw PDFException("object and generation number expected before 'obj'");
}
@@ -302,7 +302,7 @@ static PDFObjectRef parse_object_ref (vector<PDFObject> &objects) {
const int *objno = objects.back().get<int>();
objects.pop_back();
if (objno && genno)
- return PDFObjectRef(*objno, *genno);
+ return {*objno, *genno};
}
throw PDFException("object and generation number expected before 'R'");
}
diff --git a/dviware/dvisvgm/src/PDFToSVG.cpp b/dviware/dvisvgm/src/PDFToSVG.cpp
index b0e3df58ba..9cb30d3971 100644
--- a/dviware/dvisvgm/src/PDFToSVG.cpp
+++ b/dviware/dvisvgm/src/PDFToSVG.cpp
@@ -45,7 +45,7 @@ void PDFToSVG::checkGSAndFileFormat () {
if (!PDFHandler::available()) {
ostringstream oss;
if (gsVersion() > 0) {
- oss << "To process PDF files, either Ghostscript < 10.1 or mutool is required.\n";
+ oss << "To process PDF files, either Ghostscript < 10.01.0 or mutool is required.\n";
oss << "The installed Ghostscript version " << Ghostscript().revisionstr() << " isn't supported.\n";
throw MessageException(oss.str());
}
@@ -59,7 +59,10 @@ void PDFToSVG::checkGSAndFileFormat () {
/** Returns the total number of pages in the PDF file. */
int PDFToSVG::totalPageCount () const {
if (_totalPageCount < 0) {
- _totalPageCount = psInterpreter().pdfPageCount(filename());
+ if (_useGS)
+ _totalPageCount = psInterpreter().pdfPageCount(filename());
+ else
+ _totalPageCount = PDFHandler::numberOfPages(filename());
if (_totalPageCount < 1)
throw MessageException("can't retrieve number of pages from file " + filename());
}
diff --git a/dviware/dvisvgm/src/Pair.hpp b/dviware/dvisvgm/src/Pair.hpp
index c1fdd5b6d5..176183ecea 100644
--- a/dviware/dvisvgm/src/Pair.hpp
+++ b/dviware/dvisvgm/src/Pair.hpp
@@ -22,6 +22,7 @@
#define PAIR_HPP
#include <cmath>
+#include <cstdint>
#include <ostream>
#include "macros.hpp"
diff --git a/dviware/dvisvgm/src/PapersizeSpecialHandler.cpp b/dviware/dvisvgm/src/PapersizeSpecialHandler.cpp
index b070643f6d..81169dbbb0 100644
--- a/dviware/dvisvgm/src/PapersizeSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/PapersizeSpecialHandler.cpp
@@ -92,7 +92,7 @@ void PapersizeSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actio
}
-vector<const char*> PapersizeSpecialHandler::prefixes() const {
+vector<const char*> PapersizeSpecialHandler::prefixes () const {
vector<const char*> pfx {"papersize="};
return pfx;
}
diff --git a/dviware/dvisvgm/src/PapersizeSpecialHandler.hpp b/dviware/dvisvgm/src/PapersizeSpecialHandler.hpp
index 621de709db..2f3e9e863f 100644
--- a/dviware/dvisvgm/src/PapersizeSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/PapersizeSpecialHandler.hpp
@@ -34,8 +34,9 @@ class PapersizeSpecialHandler : public SpecialHandler {
void preprocess (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
const char* info () const override {return "special to set the page size";}
- const char* name () const override {return "papersize";}
- std::vector<const char*> prefixes() const override;
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "papersize";}
+ std::vector<const char*> prefixes () const override;
void storePaperSize (unsigned pageno, Length width, Length height);
void reset () {_pageSizes.clear();}
diff --git a/dviware/dvisvgm/src/PathClipper.cpp b/dviware/dvisvgm/src/PathClipper.cpp
index 50030f9657..14588f8981 100644
--- a/dviware/dvisvgm/src/PathClipper.cpp
+++ b/dviware/dvisvgm/src/PathClipper.cpp
@@ -58,7 +58,7 @@ class FlattenActions : public CurvedPath::IterationActions {
if (p == _currentPoint && !_currentPoly.empty())
return;
closepath();
- _currentPoly.emplace_back(IntPoint(to_cInt(p.x()), to_cInt(p.y()), 0));
+ _currentPoly.emplace_back(to_cInt(p.x()), to_cInt(p.y()), 0);
_currentPoint = _startPoint = p;
}
@@ -66,10 +66,10 @@ class FlattenActions : public CurvedPath::IterationActions {
if (p == _currentPoint && !_currentPoly.empty())
return;
if (_currentPoly.empty()) // this shouldn't happen but in case it does...
- _currentPoly.emplace_back(IntPoint(0, 0, 0)); // ...add a start point first
+ _currentPoly.emplace_back(0, 0, 0); // ...add a start point first
_numLines--;
_currentPoly.back().Z.label2 = _numLines;
- _currentPoly.emplace_back(IntPoint(to_cInt(p.x()), to_cInt(p.y()), ZType(_numLines, 0)));
+ _currentPoly.emplace_back(to_cInt(p.x()), to_cInt(p.y()), ZType(_numLines, 0));
_currentPoint = p;
}
@@ -100,7 +100,7 @@ class FlattenActions : public CurvedPath::IterationActions {
protected:
void addCurvePoints (const CubicBezier &bezier) {
if (_currentPoly.empty()) // this shouldn't happen but in case it does, ...
- _currentPoly.emplace_back(IntPoint(0, 0, 0)); // ...add a start point first
+ _currentPoly.emplace_back(0, 0, 0); // ...add a start point first
vector<DPair> points; // points of flattened curve
vector<double> t; // corresponding 'time' parameters
bezier.approximate(0.01, points, &t);
@@ -113,7 +113,7 @@ class FlattenActions : public CurvedPath::IterationActions {
continue;
_currentPoly.back().Z.label2 = ZLabel(_curves.size(), t[i-1]);
ZLabel label(_curves.size(), t[i]);
- _currentPoly.emplace_back(IntPoint(to_cInt(p.x()), to_cInt(p.y()), ZType(label, label)));
+ _currentPoly.emplace_back(to_cInt(p.x()), to_cInt(p.y()), ZType(label, label));
_currentPoint = p;
}
}
@@ -211,7 +211,7 @@ inline ZLabel division_label (const IntPoint &p1, const IntPoint &p2, const IntP
int32_t id = segment_id(p1, p2, t1, t2);
if (id > 0)
s = t1+(t2-t1)*division_ratio(p1, p2, q);
- return ZLabel(id, s);
+ return {id, s};
}
diff --git a/dviware/dvisvgm/src/PdfSpecialHandler.cpp b/dviware/dvisvgm/src/PdfSpecialHandler.cpp
index 0af7303e8d..b3128512c9 100644
--- a/dviware/dvisvgm/src/PdfSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/PdfSpecialHandler.cpp
@@ -283,7 +283,7 @@ void PdfSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) {
}
-vector<const char*> PdfSpecialHandler::prefixes() const {
+vector<const char*> PdfSpecialHandler::prefixes () const {
vector<const char*> pfx {"pdf:"};
return pfx;
}
diff --git a/dviware/dvisvgm/src/PdfSpecialHandler.hpp b/dviware/dvisvgm/src/PdfSpecialHandler.hpp
index b5267939d7..4c5509d093 100644
--- a/dviware/dvisvgm/src/PdfSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/PdfSpecialHandler.hpp
@@ -27,11 +27,12 @@ class StreamInputReader;
class PdfSpecialHandler : public SpecialHandler {
public:
- const char* info () const override {return "PDF hyperlink, font map, and pagesize specials";}
- const char* name () const override {return "pdf";}
- std::vector<const char*> prefixes() const override;
void preprocess (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
+ const char* info () const override {return "PDF hyperlink, font map, and pagesize specials";}
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "pdf";}
+ std::vector<const char*> prefixes () const override;
protected:
// handlers for corresponding PDF specials
diff --git a/dviware/dvisvgm/src/Process.cpp b/dviware/dvisvgm/src/Process.cpp
index c79f6e9526..b7fb3929b8 100644
--- a/dviware/dvisvgm/src/Process.cpp
+++ b/dviware/dvisvgm/src/Process.cpp
@@ -74,13 +74,13 @@ string Subprocess::read (const SearchPattern &pattern, bool *error) {
const size_t bytesRead = readFromPipe(&_rdbuf[_bufstartpos], _rdbuf.size()-_bufstartpos, error);
const size_t bufendpos = _bufstartpos + bytesRead;
smatch matches;
- size_t matchendpos= bufendpos; // buffer position after last match
+ size_t matchendpos = bufendpos; // buffer position after last match
if (pattern.search.empty())
result.assign(_rdbuf.data(), matchendpos);
else {
bool matched=false;
regex re(pattern.search);
- for (auto it = cregex_iterator(&_rdbuf[0], &_rdbuf[bufendpos], re); it != cregex_iterator(); ++it) {
+ for (auto it = cregex_iterator(&_rdbuf[0], &_rdbuf[0]+bufendpos, re); it != cregex_iterator(); ++it) {
result += it->format(pattern.replace, regex_constants::format_no_copy);
matchendpos = it->position() + it->length();
matched = true;
@@ -121,11 +121,8 @@ bool Process::run (string *out, const SearchPattern &pattern, PipeFlags flags) {
if (out)
out->clear();
for (;;) {
- if (out) {
- string chunk;
- subprocess.readFromPipe(chunk, pattern);
- *out += chunk;
- }
+ if (out)
+ subprocess.readFromPipe(*out, pattern);
Subprocess::State state = subprocess.state();
if (state != Subprocess::State::RUNNING)
return state == Subprocess::State::FINISHED;
diff --git a/dviware/dvisvgm/src/PsSpecialHandler.cpp b/dviware/dvisvgm/src/PsSpecialHandler.cpp
index 5dfdfc0852..cb3a8a6bac 100644
--- a/dviware/dvisvgm/src/PsSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/PsSpecialHandler.cpp
@@ -1378,9 +1378,9 @@ void PsSpecialHandler::ClippingStack::push (const Path &path, int saveID) {
if (!_stack.empty())
prependedPath = _stack.top().prependedPath;
if (path.empty())
- _stack.emplace(Entry(saveID));
+ _stack.emplace(saveID);
else
- _stack.emplace(Entry(path, ++_maxID, saveID));
+ _stack.emplace(path, ++_maxID, saveID);
_stack.top().prependedPath = prependedPath;
}
@@ -1470,7 +1470,7 @@ void PsSpecialHandler::ClippingStack::setPrependedPath () {
}
-vector<const char*> PsSpecialHandler::prefixes() const {
+vector<const char*> PsSpecialHandler::prefixes () const {
vector<const char*> pfx {
"header=", // read and execute PS header file prior to the following PS statements
"pdffile=", // process PDF file
diff --git a/dviware/dvisvgm/src/PsSpecialHandler.hpp b/dviware/dvisvgm/src/PsSpecialHandler.hpp
index 695eb78d03..fb44e4bfa4 100644
--- a/dviware/dvisvgm/src/PsSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/PsSpecialHandler.hpp
@@ -91,11 +91,12 @@ class PsSpecialHandler : public SpecialHandler, protected PSActions {
public:
PsSpecialHandler ();
~PsSpecialHandler () override;
- const char* name () const override {return "ps";}
- const char* info () const override {return "dvips PostScript specials";}
- std::vector<const char*> prefixes() const override;
void preprocess (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
+ const char* info () const override {return "dvips PostScript specials";}
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "ps";}
+ std::vector<const char*> prefixes () const override;
void setDviScaleFactor (double dvi2bp) override {_previewFilter.setDviScaleFactor(dvi2bp);}
void enterBodySection ();
PSInterpreter& psInterpreter () {return _psi;}
diff --git a/dviware/dvisvgm/src/SVGCharPathHandler.cpp b/dviware/dvisvgm/src/SVGCharPathHandler.cpp
index fc59d2280e..2c753d2e5c 100644
--- a/dviware/dvisvgm/src/SVGCharPathHandler.cpp
+++ b/dviware/dvisvgm/src/SVGCharPathHandler.cpp
@@ -60,7 +60,7 @@ void SVGCharPathHandler::appendChar (uint32_t c, double x, double y) {
// Apply text color changes only if the color of the entire font is black.
// Glyphs of non-black fonts (e.g. defined in a XeTeX document) can't change their color.
CharProperty<Color> &color = (_fontColor.get() != Color::BLACK) ? _fontColor : _color;
- bool applyColor = color.get() != Color::BLACK;
+ bool applyColor = color.get() != Color::BLACK || (SVGElement::USE_CURRENTCOLOR && SVGElement::CURRENTCOLOR == Color::BLACK);
bool applyMatrix = !_matrix->isIdentity();
bool applyOpacity = !_opacity->isFillDefault();
if (!_groupNode) {
@@ -85,16 +85,19 @@ void SVGCharPathHandler::appendChar (uint32_t c, double x, double y) {
GlyphMetrics metrics;
font->getGlyphMetrics(c, _vertical, metrics);
x -= metrics.wl;
- if (auto pf = font_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, nullptr);
- y += exact_metrics.h+(metrics.d-exact_metrics.h-exact_metrics.d)/2;
+ if (_vertical) {
+ auto physicalFont = font_cast<const PhysicalFont *>(font);
+ if (!physicalFont)
+ y += metrics.d;
+ else {
+ // 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;
+ physicalFont->getExactGlyphBox(c, exact_metrics, false, nullptr);
+ y += exact_metrics.h + (metrics.d - exact_metrics.h - exact_metrics.d) / 2;
+ }
}
- else
- y += metrics.d;
}
Matrix rotation(1);
if (_vertical && !font->verticalLayout()) {
diff --git a/dviware/dvisvgm/src/SVGCharTspanTextHandler.cpp b/dviware/dvisvgm/src/SVGCharTspanTextHandler.cpp
index 9c23f33050..426934f426 100644
--- a/dviware/dvisvgm/src/SVGCharTspanTextHandler.cpp
+++ b/dviware/dvisvgm/src/SVGCharTspanTextHandler.cpp
@@ -46,7 +46,7 @@ void SVGCharTspanTextHandler::appendChar (uint32_t c, double x, double y) {
}
// Apply text color changes only if the color of the entire font is black.
// Glyphs of non-black fonts (e.g. defined in a XeTeX document) can't change their color.
- bool applyColor = _color.get() != Color::BLACK && _font.get()->color() == Color::BLACK;
+ bool applyColor = _color.get() != Color::BLACK || (SVGElement::USE_CURRENTCOLOR && _font.get()->color() == Color::BLACK);
bool applyOpacity = !_opacity->isFillDefault();
if (_xchanged || _ychanged || (_color.changed() && applyColor) || (_opacity.changed() && applyOpacity)) {
_tspanNode = pushContextNode(util::make_unique<SVGElement>("tspan"));
diff --git a/dviware/dvisvgm/src/SVGElement.cpp b/dviware/dvisvgm/src/SVGElement.cpp
index 68f7d2231c..b0f1db925c 100644
--- a/dviware/dvisvgm/src/SVGElement.cpp
+++ b/dviware/dvisvgm/src/SVGElement.cpp
@@ -27,6 +27,9 @@
using namespace std;
+bool SVGElement::USE_CURRENTCOLOR=false;
+Color SVGElement::CURRENTCOLOR;
+
void SVGElement::setClipPathUrl (const string &url) {
if (!url.empty())
@@ -41,7 +44,9 @@ void SVGElement::setClipRule (FillRule rule) {
void SVGElement::setFillColor (Color color, bool skipBlack) {
- if (color != Color::BLACK || !skipBlack)
+ if (USE_CURRENTCOLOR && color == CURRENTCOLOR)
+ addAttribute("fill", "currentColor");
+ else if (color != Color::BLACK || !skipBlack)
addAttribute("fill", color.svgColorString());
}
@@ -108,7 +113,7 @@ void SVGElement::setPoints (const vector<DPair> &points) {
void SVGElement::setStrokeColor (Color color) {
- addAttribute("stroke", color.svgColorString());
+ addAttribute("stroke", USE_CURRENTCOLOR && color == CURRENTCOLOR ? "currentColor" : color.svgColorString());
}
diff --git a/dviware/dvisvgm/src/SVGElement.hpp b/dviware/dvisvgm/src/SVGElement.hpp
index 632b6a4a84..3197cfc115 100644
--- a/dviware/dvisvgm/src/SVGElement.hpp
+++ b/dviware/dvisvgm/src/SVGElement.hpp
@@ -58,6 +58,9 @@ class SVGElement : public XMLElement {
void setStrokeWidth (double width);
void setStrokeMiterLimit (double limit);
void setTransform (const Matrix &matrix);
+
+ static bool USE_CURRENTCOLOR; ///< if true, apply color value "currentColor"
+ static Color CURRENTCOLOR; ///< color to be replaced with "currentColor"
};
#endif
diff --git a/dviware/dvisvgm/src/SVGSingleCharTextHandler.cpp b/dviware/dvisvgm/src/SVGSingleCharTextHandler.cpp
index d2a4f53ad1..1dcab96317 100644
--- a/dviware/dvisvgm/src/SVGSingleCharTextHandler.cpp
+++ b/dviware/dvisvgm/src/SVGSingleCharTextHandler.cpp
@@ -29,7 +29,7 @@ void SVGSingleCharTextHandler::appendChar (uint32_t c, double x, double y) {
textNode->append(XMLString(font->unicode(c), false));
// Apply color changes only if the color differs from black and if the font color itself is black.
// Glyphs from non-black fonts (e.g. defined in a XeTeX document) can't change their color.
- if (_color.get() != Color::BLACK && font->color() == Color::BLACK)
+ if (font->color() == Color::BLACK && (_color.get() != Color::BLACK || (SVGElement::USE_CURRENTCOLOR && SVGElement::CURRENTCOLOR == Color::BLACK)))
textNode->setFillColor(_color);
_color.changed(false);
if (!_opacity->isFillDefault())
diff --git a/dviware/dvisvgm/src/SVGTree.hpp b/dviware/dvisvgm/src/SVGTree.hpp
index 0453e53ac3..a368932d36 100644
--- a/dviware/dvisvgm/src/SVGTree.hpp
+++ b/dviware/dvisvgm/src/SVGTree.hpp
@@ -92,8 +92,8 @@ class SVGTree {
private:
XMLDocument _doc;
- SVGElement *_root, *_page, *_defs;
- XMLCData *_styleCDataNode;
+ SVGElement *_root=nullptr, *_page=nullptr, *_defs=nullptr;
+ XMLCData *_styleCDataNode=nullptr;
std::unique_ptr<SVGCharHandler> _charHandler;
std::stack<SVGElement*> _defsContextStack;
std::stack<SVGElement*> _pageContextStack;
diff --git a/dviware/dvisvgm/src/SpecialHandler.hpp b/dviware/dvisvgm/src/SpecialHandler.hpp
index 81c3146d35..860cfdea61 100644
--- a/dviware/dvisvgm/src/SpecialHandler.hpp
+++ b/dviware/dvisvgm/src/SpecialHandler.hpp
@@ -37,15 +37,14 @@ struct SpecialException : public MessageException {
class SpecialHandler {
- friend class SpecialManager;
public:
virtual ~SpecialHandler () =default;
- virtual const char* info () const=0;
- virtual const char* name () const=0;
- virtual std::vector<const char*> prefixes() const =0;
+ virtual const char* info () const =0;
+ virtual const char* name () const =0;
+ virtual std::vector<const char*> prefixes () const =0;
virtual void setDviScaleFactor (double dvi2bp) {}
virtual void preprocess (const std::string &prefix, std::istream &is, SpecialActions &actions) {}
- virtual bool process (const std::string &prefix, std::istream &is, SpecialActions &actions)=0;
+ virtual bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) =0;
virtual void dviPreprocessingFinished () {}
virtual void dviBeginPage (unsigned pageno, SpecialActions &actions) {}
virtual void dviEndPage (unsigned pageno, SpecialActions &actions) {}
diff --git a/dviware/dvisvgm/src/SpecialManager.hpp b/dviware/dvisvgm/src/SpecialManager.hpp
index 55da303b70..ed97f7f5be 100644
--- a/dviware/dvisvgm/src/SpecialManager.hpp
+++ b/dviware/dvisvgm/src/SpecialManager.hpp
@@ -21,12 +21,14 @@
#ifndef SPECIALMANAGER_HPP
#define SPECIALMANAGER_HPP
+#include <algorithm>
#include <memory>
#include <ostream>
#include <string>
#include <unordered_map>
#include <vector>
#include "SpecialHandler.hpp"
+#include "utility.hpp"
class SpecialActions;
@@ -38,6 +40,14 @@ class SpecialManager {
public:
SpecialManager (const SpecialManager &) =delete;
static SpecialManager& instance ();
+
+ template <class Handler>
+ static void registerHandler (const std::vector<std::string> &ignoredHandlerNames) {
+ const char *name = Handler::handlerName();
+ if (!name || find(ignoredHandlerNames.begin(), ignoredHandlerNames.end(), std::string(name)) == ignoredHandlerNames.end())
+ instance().registerHandler(util::make_unique<Handler>());
+ }
+
void registerHandler (std::unique_ptr<SpecialHandler> handler);
void registerHandlers (std::vector<std::unique_ptr<SpecialHandler>> &handlers, const char *ignorelist);
void unregisterHandlers ();
diff --git a/dviware/dvisvgm/src/StreamReader.cpp b/dviware/dvisvgm/src/StreamReader.cpp
index 196ce7affa..1513ae97db 100644
--- a/dviware/dvisvgm/src/StreamReader.cpp
+++ b/dviware/dvisvgm/src/StreamReader.cpp
@@ -40,7 +40,7 @@ istream& StreamReader::replaceStream (istream &in) {
uint32_t StreamReader::readUnsigned (int bytes) {
uint32_t ret = 0;
for (bytes--; bytes >= 0 && !_is->eof(); bytes--) {
- uint32_t b = uint32_t(_is->get());
+ auto b = uint32_t(_is->get());
ret |= b << (8*bytes);
}
return ret;
@@ -62,7 +62,7 @@ uint32_t StreamReader::readUnsigned (int n, HashFunction &hashfunc) {
* @param[in] bytes number of bytes to read (max. 4)
* @return read integer */
int32_t StreamReader::readSigned (int bytes) {
- uint32_t ret = uint32_t(_is->get());
+ auto ret = uint32_t(_is->get());
if (ret & 128) // negative value?
ret |= 0xffffff00;
for (bytes-=2; bytes >= 0 && !_is->eof(); bytes--)
@@ -84,12 +84,12 @@ int32_t StreamReader::readSigned (int n, HashFunction &hashfunc) {
/** Reads a string terminated by a 0-byte. */
string StreamReader::readString () {
- if (!_is)
- throw StreamReaderException("no stream assigned");
string ret;
- while (!_is->eof() && _is->peek() > 0)
- ret += char(_is->get());
- _is->get(); // skip 0-byte
+ if (_is) {
+ while (!_is->eof() && _is->peek() > 0)
+ ret += char(_is->get());
+ _is->get(); // skip 0-byte
+ }
return ret;
}
@@ -102,7 +102,7 @@ string StreamReader::readString (HashFunction &hashfunc, bool finalZero) {
string ret = readString();
hashfunc.update(ret.data(), ret.length());
if (finalZero)
- hashfunc.update(0, 1);
+ hashfunc.update(nullptr, 1);
return ret;
}
@@ -111,11 +111,11 @@ string StreamReader::readString (HashFunction &hashfunc, bool finalZero) {
* @param[in] length number of characters to read
* @return the string read */
string StreamReader::readString (int length) {
- if (!_is)
- throw StreamReaderException("no stream assigned");
- length = max(0, length);
- string str(length, '\0');
- _is->read(&str[0], length); // read 'length' bytes and append '\0'
+ string str;
+ if (_is) {
+ str.resize(max(0, length));
+ _is->read(&str[0], streamsize(str.length())); // read 'length' bytes and append '\0'
+ }
return str;
}
@@ -149,7 +149,7 @@ vector<uint8_t> StreamReader::readBytes (int n, HashFunction &hashfunc) {
int StreamReader::readByte (HashFunction &hashfunc) {
int ret = readByte();
if (ret >= 0) {
- char c = ret & 0xff;
+ char c = char(ret & 0xff);
hashfunc.update(&c, 1);
}
return ret;
diff --git a/dviware/dvisvgm/src/StreamReader.hpp b/dviware/dvisvgm/src/StreamReader.hpp
index 138751c33c..f775cd3bac 100644
--- a/dviware/dvisvgm/src/StreamReader.hpp
+++ b/dviware/dvisvgm/src/StreamReader.hpp
@@ -50,6 +50,7 @@ class StreamReader {
int readByte (HashFunction &hashfunc);
void seek (std::streampos pos, std::ios::seekdir dir) {_is->seekg(pos, dir);}
void seek (std::streampos pos) {_is->seekg(pos);}
+ void skip (std::streampos n) {_is->seekg(n, std::ios::cur);}
std::streampos tell () const {return _is->tellg();}
int peek () const {return _is->peek();}
diff --git a/dviware/dvisvgm/src/TFM.cpp b/dviware/dvisvgm/src/TFM.cpp
index c29de267bb..e2ba673647 100644
--- a/dviware/dvisvgm/src/TFM.cpp
+++ b/dviware/dvisvgm/src/TFM.cpp
@@ -20,7 +20,6 @@
#include <fstream>
#include <vector>
-#include "FileFinder.hpp"
#include "Length.hpp"
#include "Message.hpp"
#include "StreamReader.hpp"
@@ -35,47 +34,46 @@ using namespace std;
* @param[in] n number of words to be read */
template <typename T>
static void read_words (StreamReader &reader, vector<T> &v, unsigned n) {
- v.clear();
v.resize(n);
for (unsigned i=0; i < n; i++)
v[i] = reader.readUnsigned(4);
}
-TFM::TFM (istream &is) : _checksum(0), _firstChar(0), _lastChar(0), _designSize(0), _ascent(0), _descent(0) {
+void TFM::read (istream &is) {
if (!is)
return;
is.seekg(0);
StreamReader reader(is);
- uint16_t lf = uint16_t(reader.readUnsigned(2)); // length of entire file in 4 byte words
- uint16_t lh = uint16_t(reader.readUnsigned(2)); // length of header in 4 byte words
- _firstChar= uint16_t(reader.readUnsigned(2)); // smallest character code in font
- _lastChar = uint16_t(reader.readUnsigned(2)); // largest character code in font
- uint16_t nw = uint16_t(reader.readUnsigned(2)); // number of words in width table
- uint16_t nh = uint16_t(reader.readUnsigned(2)); // number of words in height table
- uint16_t nd = uint16_t(reader.readUnsigned(2)); // number of words in depth table
- uint16_t ni = uint16_t(reader.readUnsigned(2)); // number of words in italic corr. table
- uint16_t nl = uint16_t(reader.readUnsigned(2)); // number of words in lig/kern table
- uint16_t nk = uint16_t(reader.readUnsigned(2)); // number of words in kern table
- uint16_t ne = uint16_t(reader.readUnsigned(2)); // number of words in ext. char table
- uint16_t np = uint16_t(reader.readUnsigned(2)); // number of font parameter words
-
- if (6+lh+(_lastChar-_firstChar+1)+nw+nh+nd+ni+nl+nk+ne+np != lf)
+ auto lf = uint16_t(reader.readUnsigned(2)); // length of entire file in 4 byte words
+ auto lh = uint16_t(reader.readUnsigned(2)); // length of header in 4 byte words
+ auto bc = uint16_t(reader.readUnsigned(2)); // smallest character code in font
+ auto ec = uint16_t(reader.readUnsigned(2)); // largest character code in font
+ auto nw = uint16_t(reader.readUnsigned(2)); // number of words in width table
+ auto nh = uint16_t(reader.readUnsigned(2)); // number of words in height table
+ auto nd = uint16_t(reader.readUnsigned(2)); // number of words in depth table
+ auto ni = uint16_t(reader.readUnsigned(2)); // number of words in italic corr. table
+ auto nl = uint16_t(reader.readUnsigned(2)); // number of words in lig/kern table
+ auto nk = uint16_t(reader.readUnsigned(2)); // number of words in kern table
+ auto ne = uint16_t(reader.readUnsigned(2)); // number of words in ext. char table
+ auto np = uint16_t(reader.readUnsigned(2)); // number of font parameter words
+ if (6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np != lf)
throw FontMetricException("inconsistent length values");
- if (_firstChar >= _lastChar || _lastChar > 255 || ne > 256)
+ if (bc >= ec || ec > 255 || ne > 256)
throw FontMetricException("character codes out of range");
-
+ _firstChar = bc;
+ _lastChar = ec;
readHeader(reader);
is.seekg(24+lh*4); // move to char info table
readTables(reader, nw, nh, nd, ni);
- is.seekg(4*(lf-np), ios::beg); // move to param section
+ is.seekg(4*(lf-np)); // move to param section
readParameters(reader, np);
}
void TFM::readHeader (StreamReader &reader) {
_checksum = reader.readUnsigned(4);
- _designSize = double(FixWord(reader.readUnsigned(4)))*Length::pt2bp;
+ _designSize = double(FixWord(reader.readSigned(4)))*Length::pt2bp;
}
@@ -99,7 +97,7 @@ void TFM::readParameters (StreamReader &reader, int np) {
_params.resize(7);
np = min(np, 7);
for (int i=0; i < np; i++)
- _params[i] = reader.readUnsigned(4);
+ _params[i] = reader.readSigned(4);
for (int i=np; i < 7; i++)
_params[i] = 0;
}
@@ -134,7 +132,7 @@ double TFM::getQuad () const {
/** Returns the index to the entry of the character info table that describes the metric of a given character.
* @param[in] c character whose index is retrieved
* @return table index for character c, or -1 if there's no entry */
-int TFM::charIndex (int c) const {
+size_t TFM::charIndex (int c) const {
if (c < _firstChar || c > _lastChar || size_t(c-_firstChar) >= _charInfoTable.size())
return -1;
return c-_firstChar;
@@ -151,8 +149,8 @@ int TFM::charIndex (int c) const {
/** Returns the width of char c in PS point units. */
double TFM::getCharWidth (int c) const {
- int index = charIndex(c);
- if (index < 0)
+ size_t index = charIndex(c);
+ if (index == size_t(-1))
return 0;
index = (_charInfoTable[index] >> 24) & 0xFF;
return double(_widthTable[index]) * _designSize;
@@ -161,8 +159,8 @@ double TFM::getCharWidth (int c) const {
/** Returns the height of char c in PS point units. */
double TFM::getCharHeight (int c) const {
- int index = charIndex(c);
- if (index < 0)
+ size_t index = charIndex(c);
+ if (index == size_t(-1))
return 0;
index = (_charInfoTable[index] >> 20) & 0x0F;
return double(_heightTable[index]) * _designSize;
@@ -171,8 +169,8 @@ double TFM::getCharHeight (int c) const {
/** Returns the depth of char c in PS point units. */
double TFM::getCharDepth (int c) const {
- int index = charIndex(c);
- if (index < 0)
+ size_t index = charIndex(c);
+ if (index == size_t(-1))
return 0;
index = (_charInfoTable[index] >> 16) & 0x0F;
return double(_depthTable[index]) * _designSize;
@@ -181,8 +179,8 @@ double TFM::getCharDepth (int c) const {
/** Returns the italic correction of char c in PS point units. */
double TFM::getItalicCorr (int c) const {
- int index = charIndex(c);
- if (index < 0)
+ size_t index = charIndex(c);
+ if (index == size_t(-1))
return 0;
index = (_charInfoTable[index] >> 10) & 0x3F;
return double(_italicTable[index]) * _designSize;
diff --git a/dviware/dvisvgm/src/TFM.hpp b/dviware/dvisvgm/src/TFM.hpp
index 5e968ff201..dd3fa32401 100644
--- a/dviware/dvisvgm/src/TFM.hpp
+++ b/dviware/dvisvgm/src/TFM.hpp
@@ -32,7 +32,8 @@ class StreamReader;
class TFM : public FontMetrics {
public:
- explicit TFM (std::istream &is);
+ TFM () =default;
+ void read (std::istream &is) override;
double getCharWidth (int c) const override;
double getCharHeight (int c) const override;
double getCharDepth (int c) const override;
@@ -46,15 +47,14 @@ class TFM : public FontMetrics {
double getDescent () const override {return double(_descent)*_designSize;}
bool verticalLayout () const override {return false;}
uint32_t getChecksum () const override {return _checksum;}
- uint16_t firstChar () const override {return _firstChar;}
- uint16_t lastChar () const override {return _lastChar;}
+ uint32_t firstChar () const override {return _firstChar;}
+ uint32_t lastChar () const override {return _lastChar;}
protected:
- TFM () : _params(7) {}
void readHeader (StreamReader &reader);
void readTables (StreamReader &reader, int nw, int nh, int nd, int ni);
void readParameters (StreamReader &reader, int np);
- virtual int charIndex (int c) const;
+ virtual size_t charIndex (int c) const;
void setCharRange (int firstchar, int lastchar) {_firstChar=firstchar; _lastChar=lastchar;}
private:
@@ -67,7 +67,7 @@ class TFM : public FontMetrics {
std::vector<FixWord> _depthTable; ///< character depth in design size units
std::vector<FixWord> _italicTable; ///< italic corrections in design size units
std::vector<FixWord> _params; ///< values of the TFM's param section
- FixWord _ascent, _descent; ///< max. height and depth
+ FixWord _ascent=0, _descent=0; ///< max. height and depth
};
#endif
diff --git a/dviware/dvisvgm/src/TpicSpecialHandler.cpp b/dviware/dvisvgm/src/TpicSpecialHandler.cpp
index 86b49b1d20..e22970c31a 100644
--- a/dviware/dvisvgm/src/TpicSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/TpicSpecialHandler.cpp
@@ -354,7 +354,7 @@ bool TpicSpecialHandler::process (const string &prefix, istream &is, SpecialActi
}
-vector<const char*> TpicSpecialHandler::prefixes() const {
+vector<const char*> TpicSpecialHandler::prefixes () const {
vector<const char*> pfx {"ar", "bk", "da", "dt", "fp", "ia", "ip", "pa", "pn", "sh", "sp", "tx", "wh"};
return pfx;
}
diff --git a/dviware/dvisvgm/src/TpicSpecialHandler.hpp b/dviware/dvisvgm/src/TpicSpecialHandler.hpp
index e8a56649f8..341a6a441c 100644
--- a/dviware/dvisvgm/src/TpicSpecialHandler.hpp
+++ b/dviware/dvisvgm/src/TpicSpecialHandler.hpp
@@ -28,10 +28,11 @@
class TpicSpecialHandler : public SpecialHandler {
public:
TpicSpecialHandler ();
- const char* info () const override {return "TPIC specials";}
- const char* name () const override {return "tpic";}
- std::vector<const char*> prefixes() const override;
bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override;
+ const char* info () const override {return "TPIC specials";}
+ const char* name () const override {return handlerName();}
+ static const char* handlerName () {return "tpic";}
+ std::vector<const char*> prefixes () const override;
double penwidth () const {return _penwidth;}
double grayLevel () const {return _grayLevel;}
Color fillColor (bool grayOnly) const;
diff --git a/dviware/dvisvgm/src/XMLNode.cpp b/dviware/dvisvgm/src/XMLNode.cpp
index d5342e4d1e..b3d13e6a00 100644
--- a/dviware/dvisvgm/src/XMLNode.cpp
+++ b/dviware/dvisvgm/src/XMLNode.cpp
@@ -527,7 +527,7 @@ ostream& XMLCData::write (ostream &os) const {
void XMLCData::append (string &&str) {
if (_data.empty())
- _data = move(str);
+ _data = std::move(str);
else
_data += str;
}
diff --git a/dviware/dvisvgm/src/dvisvgm.cpp b/dviware/dvisvgm/src/dvisvgm.cpp
index 4c5bf550b2..5ba5998408 100644
--- a/dviware/dvisvgm/src/dvisvgm.cpp
+++ b/dviware/dvisvgm/src/dvisvgm.cpp
@@ -309,11 +309,11 @@ static void init_fontmap (const CommandLine &cmdline) {
* options affecting the SVG output. */
static string svg_options_hash (const CommandLine &cmdline) {
// options affecting the SVG output
- vector<const CL::Option*> svg_options = {
+ const CL::Option* svg_options[] = {
&cmdline.bboxOpt, &cmdline.clipjoinOpt, &cmdline.colornamesOpt, &cmdline.commentsOpt,
- &cmdline.exactBboxOpt, &cmdline.fontFormatOpt, &cmdline.fontmapOpt, &cmdline.gradOverlapOpt,
- &cmdline.gradSegmentsOpt, &cmdline.gradSimplifyOpt, &cmdline.linkmarkOpt, &cmdline.magOpt,
- &cmdline.noFontsOpt, &cmdline.noMergeOpt, &cmdline.noSpecialsOpt, &cmdline.noStylesOpt,
+ &cmdline.currentcolorOpt, &cmdline.exactBboxOpt, &cmdline.fontFormatOpt, &cmdline.fontmapOpt,
+ &cmdline.gradOverlapOpt, &cmdline.gradSegmentsOpt, &cmdline.gradSimplifyOpt, &cmdline.linkmarkOpt,
+ &cmdline.magOpt, &cmdline.noFontsOpt, &cmdline.noMergeOpt, &cmdline.noSpecialsOpt, &cmdline.noStylesOpt,
&cmdline.optimizeOpt, &cmdline.precisionOpt, &cmdline.relativeOpt, &cmdline.zoomOpt
};
string idString = get_transformation_string(cmdline);
@@ -345,6 +345,13 @@ static void set_variables (const CommandLine &cmdline) {
SpecialActions::PROGRESSBAR_DELAY = cmdline.progressOpt.value();
}
Color::SUPPRESS_COLOR_NAMES = !cmdline.colornamesOpt.given();
+ if ((SVGElement::USE_CURRENTCOLOR = cmdline.currentcolorOpt.given())) {
+ Color color;
+ if (color.setRGBHexString(cmdline.currentcolorOpt.value()))
+ SVGElement::CURRENTCOLOR = color;
+ else
+ throw CL::CommandLineException("invalid color string '"+cmdline.currentcolorOpt.value()+"'");
+ }
SVGTree::CREATE_CSS = !cmdline.noStylesOpt.given();
SVGTree::USE_FONTS = !cmdline.noFontsOpt.given();
if (!SVGTree::setFontFormat(cmdline.fontFormatOpt.value())) {
diff --git a/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp b/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
index d6a7f35bc4..889e011571 100644
--- a/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
+++ b/dviware/dvisvgm/src/optimizer/SVGOptimizer.cpp
@@ -39,12 +39,12 @@ string SVGOptimizer::MODULE_SEQUENCE;
SVGOptimizer::SVGOptimizer (SVGTree *svg) : _svg(svg) {
// optimizer modules available to the user; must be listed in default order
// _moduleEntries.emplace_back(ModuleEntry("remove-ws", util::make_unique<WSNodeRemover>()));
- _moduleEntries.emplace_back(ModuleEntry("simplify-text", util::make_unique<TextSimplifier>()));
- _moduleEntries.emplace_back(ModuleEntry("simplify-transform", util::make_unique<TransformSimplifier>()));
- _moduleEntries.emplace_back(ModuleEntry("group-attributes", util::make_unique<AttributeExtractor>()));
- _moduleEntries.emplace_back(ModuleEntry("collapse-groups", util::make_unique<GroupCollapser>()));
- _moduleEntries.emplace_back(ModuleEntry("remove-clippaths", util::make_unique<RedundantElementRemover>()));
- _moduleEntries.emplace_back(ModuleEntry("reassign-clippaths", util::make_unique<ClipPathReassigner>()));
+ _moduleEntries.emplace_back("simplify-text", util::make_unique<TextSimplifier>());
+ _moduleEntries.emplace_back("simplify-transform", util::make_unique<TransformSimplifier>());
+ _moduleEntries.emplace_back("group-attributes", util::make_unique<AttributeExtractor>());
+ _moduleEntries.emplace_back("collapse-groups", util::make_unique<GroupCollapser>());
+ _moduleEntries.emplace_back("remove-clippaths", util::make_unique<RedundantElementRemover>());
+ _moduleEntries.emplace_back("reassign-clippaths", util::make_unique<ClipPathReassigner>());
}
diff --git a/dviware/dvisvgm/src/options.dtd b/dviware/dvisvgm/src/options.dtd
index 43f75b1691..1a2349b002 100644
--- a/dviware/dvisvgm/src/options.dtd
+++ b/dviware/dvisvgm/src/options.dtd
@@ -41,7 +41,7 @@
<!ELEMENT arg EMPTY>
<!ATTLIST arg
- default NMTOKEN #IMPLIED
+ default CDATA #IMPLIED
name CDATA #REQUIRED
optional (yes|no) #IMPLIED
type NMTOKEN #REQUIRED>
diff --git a/dviware/dvisvgm/src/options.xml b/dviware/dvisvgm/src/options.xml
index 889fe7f081..bd7867970f 100644
--- a/dviware/dvisvgm/src/options.xml
+++ b/dviware/dvisvgm/src/options.xml
@@ -66,6 +66,10 @@
<option long="comments">
<description>add comments with additional information</description>
</option>
+ <option long="currentcolor">
+ <arg type="string" name="color" default="#000" optional="yes"/>
+ <description>replace given color with 'currentColor'</description>
+ </option>
<option long="embed-bitmaps">
<description>prevent references to external bitmap files</description>
</option>
diff --git a/dviware/dvisvgm/src/ttf/HmtxTable.cpp b/dviware/dvisvgm/src/ttf/HmtxTable.cpp
index 6e849768fd..e5dc63c7e8 100644
--- a/dviware/dvisvgm/src/ttf/HmtxTable.cpp
+++ b/dviware/dvisvgm/src/ttf/HmtxTable.cpp
@@ -57,6 +57,6 @@ void HmtxTable::updateWidthData (uint32_t c, int16_t xmin, int16_t xmax) {
_runLengthOfAdvWidth++;
else
_runLengthOfAdvWidth = 1;
- _widthInfos.emplace_back(CharWidthInfo(xmin, w));
+ _widthInfos.emplace_back(xmin, w);
ttfWriter()->updateGlobalAdvanceWidth(w, _widthInfos.size()-_runLengthOfAdvWidth+1);
} \ No newline at end of file
diff --git a/dviware/dvisvgm/src/ttf/TTFWriter.cpp b/dviware/dvisvgm/src/ttf/TTFWriter.cpp
index 2dacdfc567..a64f1ff641 100644
--- a/dviware/dvisvgm/src/ttf/TTFWriter.cpp
+++ b/dviware/dvisvgm/src/ttf/TTFWriter.cpp
@@ -368,14 +368,14 @@ bool TTFWriter::convertTTFToWOFF (istream &is, ostream &os) {
// read and process TTF header
vector<char> bufvec(12, 0);
is.read(&bufvec[0], 12);
- buffers.emplace_back(TableBuffer(0, std::move(bufvec)));
+ buffers.emplace_back(0, std::move(bufvec));
int numTables = buffers.back().getUInt16(4);
// read and process table records
bufvec.clear();
bufvec.resize(4 * 4 * numTables);
is.read(&bufvec[0], 4 * 4 * numTables);
- buffers.emplace_back(TableBuffer(0, std::move(bufvec)));
+ buffers.emplace_back(0, std::move(bufvec));
struct TableRecord {
TableRecord (const TableBuffer &buf, size_t ofs)
@@ -389,7 +389,7 @@ bool TTFWriter::convertTTFToWOFF (istream &is, ostream &os) {
tableRecords.reserve(numTables);
const TableBuffer &recbuf = buffers.back();
for (int i=0; i < numTables; i++)
- tableRecords.emplace_back(TableRecord(recbuf, 16*i));
+ tableRecords.emplace_back(recbuf, 16*i);
// read and process tables
for (const TableRecord &record : tableRecords) {
@@ -398,9 +398,9 @@ bool TTFWriter::convertTTFToWOFF (istream &is, ostream &os) {
is.seekg(record.offset);
is.read(&bufvec[0], record.length);
if (record.tag == TTFTable::name2id("head"))
- buffers.emplace_back(TableBuffer(record.tag, std::move(bufvec), HeadTable::offsetToChecksum()));
+ buffers.emplace_back(record.tag, std::move(bufvec), HeadTable::offsetToChecksum());
else
- buffers.emplace_back(TableBuffer(record.tag, std::move(bufvec)));
+ buffers.emplace_back(record.tag, std::move(bufvec));
}
return ttf_to_woff(std::move(buffers), os);
}
diff --git a/dviware/dvisvgm/src/ttf/VmtxTable.cpp b/dviware/dvisvgm/src/ttf/VmtxTable.cpp
index 6873bac9d2..ad695763d1 100644
--- a/dviware/dvisvgm/src/ttf/VmtxTable.cpp
+++ b/dviware/dvisvgm/src/ttf/VmtxTable.cpp
@@ -52,6 +52,6 @@ void VmtxTable::updateHeightData (uint32_t c, int16_t ymin, int16_t ymax) {
_runLengthOfAdvHeight++;
else
_runLengthOfAdvHeight = 1;
- _heightInfos.emplace_back(CharHeightInfo(ymin, h));
+ _heightInfos.emplace_back(ymin, h);
ttfWriter()->updateGlobalAdvanceHeight(h, _heightInfos.size()-_runLengthOfAdvHeight+1);
} \ No newline at end of file
diff --git a/dviware/dvisvgm/src/utility.cpp b/dviware/dvisvgm/src/utility.cpp
index 947be91634..8492cbdeed 100644
--- a/dviware/dvisvgm/src/utility.cpp
+++ b/dviware/dvisvgm/src/utility.cpp
@@ -58,7 +58,7 @@ vector<double> math::svd (const double (&m)[2][2]) {
theta = (a2-a1)/2;
}
}
- return vector<double>{phi, sx, sy, theta};
+ return {phi, sx, sy, theta};
}
@@ -68,7 +68,7 @@ vector<double> math::svd (const double (&m)[2][2]) {
* @param[in] t1 upper interval boundary
* @param[in] n number of slices the interval is divided into
* @param[in] f function to integrate */
-double math::integral (double t0, double t1, int n, const std::function<double(double)> &f) {
+double math::integral (double t0, double t1, int n, const function<double(double)> &f) {
double ti = t0, ui=0;
double h = (t1-t0)/n;
for (int i=0; i < n; i++) {
@@ -103,7 +103,7 @@ double math::normalize_0_2pi (double rad) {
* @param[in] str the string to process
* @param[in] ws characters treated as whitespace
* @return the trimmed string */
-string util::trim (const std::string &str, const char *ws) {
+string util::trim (const string &str, const char *ws) {
auto first = str.find_first_not_of(ws);
if (first == string::npos)
return "";
@@ -183,13 +183,8 @@ string util::tolower (const string &str) {
/** Converts a double to a string and strips redundant trailing digits/dots. */
string util::to_string (double val) {
string str = std::to_string(val);
- if (str.find('.') != string::npos) { // double value and not an integer?
- auto pos = str.find_last_not_of('0');
- if (pos != string::npos) // trailing zeros
- str.erase(pos+1, string::npos);
- if (str.back() == '.') // trailing dot?
- str.pop_back();
- }
+ str.erase(str.find_last_not_of('0')+1, string::npos);
+ str.erase(str.find_last_not_of('.')+1, string::npos);
return str;
}
@@ -206,11 +201,69 @@ int util::ilog10 (int n) {
}
+/** Reads an integer string of the form (+|-)?[0-9]+ from an input stream
+ * ana appends it to a given one.
+ * @param[in] is stream to read from
+ * @param[out] str the read string is appended to this one
+ * @param[in] allow_leading_sign true if the first character may be '+' or '-'
+ * @return true if the string coule be read successfully */
+static bool read_int_string (istream &is, string &str, bool allow_leading_sign=true) {
+ string intstr;
+ if (is.peek() == '-' || is.peek() == '+') {
+ if (!allow_leading_sign)
+ return false;
+ intstr += char(is.get());
+ if (!isdigit(is.peek()))
+ return false;
+ }
+ while (isdigit(is.peek()))
+ intstr += char(is.get());
+ str += intstr;
+ return !intstr.empty();
+}
+
+
+/** Reads and parses a double from an input stream.
+ * @param[in] is stream to read from
+ * @param[out] value the read double value
+ * @return true if the value was read and parsed successfully */
+bool util::read_double (istream &is, double &value) {
+ is >> ws;
+ string numstr;
+ // read optional leading sign
+ bool plusminus = (is.peek() == '-' || is.peek() == '+');
+ if (plusminus)
+ numstr += char(is.get());
+ // read optional integer part (before decimal dot)
+ read_int_string(is, numstr, !plusminus);
+ if (is.peek() == '.') {
+ numstr += char(is.get());
+ // read fractional part (after decimal dot)
+ if (!read_int_string(is, numstr, false))
+ return false;
+ }
+ // read optional exponential part
+ if (std::tolower(is.peek()) == 'e') {
+ numstr += char(is.get());
+ if (!read_int_string(is, numstr))
+ return false;
+ }
+ try {
+ size_t count;
+ value = stod(numstr, &count);
+ return count == numstr.length();
+ }
+ catch (...) {
+ return false;
+ }
+}
+
+
/** Returns the contents of a file.
* @param[in] fname name/path of the file */
string util::read_file_contents (const string &fname) {
ifstream ifs(fname, ios::binary);
- return string(istreambuf_iterator<char>(ifs.rdbuf()), istreambuf_iterator<char>());
+ return {istreambuf_iterator<char>(ifs.rdbuf()), istreambuf_iterator<char>()};
}
diff --git a/dviware/dvisvgm/src/utility.hpp b/dviware/dvisvgm/src/utility.hpp
index 9b1b7006ad..ee272e22ec 100644
--- a/dviware/dvisvgm/src/utility.hpp
+++ b/dviware/dvisvgm/src/utility.hpp
@@ -72,6 +72,7 @@ std::string mimetype (const std::string &fname);
std::vector<std::string> split (const std::string &str, const std::string &sep);
int ilog10 (int n);
+bool read_double (std::istream &is, double &value);
std::string read_file_contents (const std::string &fname);
void write_file_contents (const std::string &fname, std::string::iterator start, std::string::iterator end);