summaryrefslogtreecommitdiff
path: root/dviware/dvisvgm/src
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-03-22 03:00:48 +0000
committerNorbert Preining <norbert@preining.info>2020-03-22 03:00:48 +0000
commit75d8dfa80524727ddb7d8ae217ed6463efba84cf (patch)
treea1a1db248828dd36aecb1697d64d28a2ff813d29 /dviware/dvisvgm/src
parent3e43bc594a14e8c4fc21d6a71f22a23dd78fe252 (diff)
CTAN sync 202003220300
Diffstat (limited to 'dviware/dvisvgm/src')
-rw-r--r--dviware/dvisvgm/src/Calculator.cpp1
-rw-r--r--dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp33
-rw-r--r--dviware/dvisvgm/src/Matrix.cpp2
-rw-r--r--dviware/dvisvgm/src/NumericRanges.hpp9
-rw-r--r--dviware/dvisvgm/src/PageRanges.cpp1
-rw-r--r--dviware/dvisvgm/src/PageRanges.hpp5
6 files changed, 39 insertions, 12 deletions
diff --git a/dviware/dvisvgm/src/Calculator.cpp b/dviware/dvisvgm/src/Calculator.cpp
index c5dc00df4d..0fdcf0f2fa 100644
--- a/dviware/dvisvgm/src/Calculator.cpp
+++ b/dviware/dvisvgm/src/Calculator.cpp
@@ -71,6 +71,7 @@ double Calculator::term (istream &is, bool skip) { // term:
for (;;)
switch (lookAhead(is)) {
case '*': left *= prim(is, true); break; // prim '*' prim => $1 * $3
+ case '(': left *= prim(is, false); break; // prim '*' prim => $1 * $3
case '/': { // prim '/' prim => $1 / $3
double denom = prim(is, true);
if (denom == 0)
diff --git a/dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp b/dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp
index b2af27d636..1f331659f0 100644
--- a/dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp
+++ b/dviware/dvisvgm/src/DvisvgmSpecialHandler.cpp
@@ -21,6 +21,7 @@
#include <array>
#include <cstring>
#include <utility>
+#include "Calculator.hpp"
#include "DvisvgmSpecialHandler.hpp"
#include "InputBuffer.hpp"
#include "InputReader.hpp"
@@ -190,6 +191,35 @@ static void expand_constants (string &str, SpecialActions &actions) {
}
+/** Evaluates substrings of the form {?(expr)} where 'expr' is a math expression,
+ * and replaces the substring by the computed value.
+ * @param[in,out] str string to scan for expressions */
+static void evaluate_expressions (string &str, SpecialActions &actions) {
+ size_t left = str.find("{?("); // start position of expression macro
+ while (left != string::npos) {
+ size_t right = str.find(")}", left+2); // end position of expression macro
+ if (right == string::npos)
+ break;
+ Calculator calc;
+ calc.setVariable("x", actions.getX());
+ calc.setVariable("y", actions.getY());
+ string expr = str.substr(left+3, right-left-3); // math expression to evaluate
+ if (util::normalize_space(expr).empty()) // no expression given, e.g. {?( )}
+ str.erase(left, right-left+2); // => replace with empty string
+ else {
+ try {
+ double val = calc.eval(expr);
+ str.replace(left, right-left+2, XMLString(val));
+ }
+ catch (CalculatorException &e) {
+ throw SpecialException(string(e.what())+" in '{?("+expr+")}'");
+ }
+ }
+ left = str.find("{?(", right+1); // find next expression macro
+ }
+}
+
+
/** Processes raw SVG fragments from the input stream. The SVG data must represent
* a single or multiple syntactically complete XML parts, like opening/closing tags,
* comments, or CDATA blocks. These must not be split and distributed over several
@@ -199,6 +229,7 @@ void DvisvgmSpecialHandler::processRaw (InputReader &ir, SpecialActions &actions
if (_nestingLevel == 0) {
string xml = ir.getLine();
if (!xml.empty()) {
+ evaluate_expressions(xml, actions);
expand_constants(xml, actions);
_pageParser.parse(xml, actions);
}
@@ -536,4 +567,4 @@ void DvisvgmSpecialHandler::XMLParser::flush (SpecialActions &actions) {
tags.resize(tags.length()-2);
throw SpecialException("missing closing tags: "+tags);
}
-} \ No newline at end of file
+}
diff --git a/dviware/dvisvgm/src/Matrix.cpp b/dviware/dvisvgm/src/Matrix.cpp
index 75d571877a..d0dcb2124d 100644
--- a/dviware/dvisvgm/src/Matrix.cpp
+++ b/dviware/dvisvgm/src/Matrix.cpp
@@ -538,7 +538,7 @@ Matrix Matrix::parseSVGTransform (const string &transform) {
}
else if (parse_transform_cmd(iss, "scale", 1, 2, params)) {
if (params.size() == 1)
- params.push_back(1);
+ params.push_back(params[0]);
if (ne(params[0], 1) || ne(params[1], 1))
matrix.rmultiply(ScalingMatrix(params[0], params[1]));
}
diff --git a/dviware/dvisvgm/src/NumericRanges.hpp b/dviware/dvisvgm/src/NumericRanges.hpp
index a6ee109568..1669f7ddce 100644
--- a/dviware/dvisvgm/src/NumericRanges.hpp
+++ b/dviware/dvisvgm/src/NumericRanges.hpp
@@ -26,8 +26,7 @@
#include <utility>
template <class T>
-class NumericRanges
-{
+class NumericRanges {
public:
using Range = std::pair<T,T>;
using Container = std::list<Range>;
@@ -54,7 +53,7 @@ template <class T>
void NumericRanges<T>::addRange (T first, T last) {
if (first > last)
std::swap(first, last);
- typename Container::iterator it = _ranges.begin();
+ auto it = _ranges.begin();
while (it != _ranges.end() && first > it->first+1 && first > it->second+1)
++it;
if (it == _ranges.end() || last < it->first-1 || first > it->second+1)
@@ -65,8 +64,8 @@ void NumericRanges<T>::addRange (T first, T last) {
}
// merge adjacent ranges
if (it != _ranges.end()) {
- typename Container::iterator l = it;
- typename Container::iterator r = it;
+ auto l = it;
+ auto r = it;
if (l == _ranges.begin())
l = _ranges.end();
else
diff --git a/dviware/dvisvgm/src/PageRanges.cpp b/dviware/dvisvgm/src/PageRanges.cpp
index a08ad4aa54..2623d2ef46 100644
--- a/dviware/dvisvgm/src/PageRanges.cpp
+++ b/dviware/dvisvgm/src/PageRanges.cpp
@@ -18,7 +18,6 @@
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
*************************************************************************/
-#include <sstream>
#include "InputBuffer.hpp"
#include "InputReader.hpp"
#include "PageRanges.hpp"
diff --git a/dviware/dvisvgm/src/PageRanges.hpp b/dviware/dvisvgm/src/PageRanges.hpp
index e6909b9cd1..555338449a 100644
--- a/dviware/dvisvgm/src/PageRanges.hpp
+++ b/dviware/dvisvgm/src/PageRanges.hpp
@@ -21,13 +21,10 @@
#ifndef PAGERANGES_HPP
#define PAGERANGES_HPP
-#include <list>
#include <string>
-#include <utility>
#include "NumericRanges.hpp"
-class PageRanges : public NumericRanges<int>
-{
+class PageRanges : public NumericRanges<int> {
public:
bool parse (const std::string &str, int max_page=0);
size_t numberOfPages () const;