diff options
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.cpp')
-rw-r--r-- | Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.cpp new file mode 100644 index 00000000000..16cd1611020 --- /dev/null +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SpecialActions.cpp @@ -0,0 +1,111 @@ +/************************************************************************* +** SpecialActions.cpp ** +** ** +** This file is part of dvisvgm -- a fast DVI to SVG converter ** +** Copyright (C) 2005-2024 Martin Gieseking <martin.gieseking@uos.de> ** +** ** +** This program is free software; you can redistribute it and/or ** +** modify it under the terms of the GNU General Public License as ** +** published by the Free Software Foundation; either version 3 of ** +** the License, or (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, but ** +** WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program; if not, see <http://www.gnu.org/licenses/>. ** +*************************************************************************/ + +#include <cstring> +#include "Calculator.hpp" +#include "SpecialActions.hpp" + +using namespace std; + +/** Replaces constants of the form {?name} by their corresponding value. + * @param[in,out] str text to expand + * @param[in] actions interfcae to the world outside the special handler */ +static void expand_constants (string &str, SpecialActions &actions) { + bool repl_bbox = true; + while (repl_bbox) { + const auto pos = str.find("{?bbox "); + if (pos == string::npos) + repl_bbox = false; + else { + auto endpos = pos+7; + while (endpos < str.length() && isalnum(str[endpos])) + ++endpos; + if (str[endpos] != '}') + repl_bbox = false; + else { + BoundingBox &box = actions.bbox(str.substr(pos+7, endpos-pos-7)); + str.replace(pos, endpos-pos+1, box.svgViewBoxString()); + } + } + } + const struct Constant { + const char *name; + string val; + } constants[] = { + {"x", XMLString(actions.getX())}, + {"y", XMLString(actions.getY())}, + {"color", SVGElement::USE_CURRENTCOLOR && SVGElement::CURRENTCOLOR == actions.getColor() ? "currentColor" : actions.getColor().svgColorString()}, + {"matrix", actions.getMatrix().toSVG()}, + {"nl", "\n"}, + {"pageno", to_string(actions.getCurrentPageNumber())}, + {"svgfile", actions.getSVGFilePath(actions.getCurrentPageNumber()).relative()}, + {"svgpath", actions.getSVGFilePath(actions.getCurrentPageNumber()).absolute()}, + }; + for (const Constant &constant : constants) { + const string pattern = string("{?")+constant.name+"}"; + auto pos = str.find(pattern); + while (pos != string::npos) { + str.replace(pos, strlen(constant.name)+3, constant.val); + pos = str.find(pattern, pos+constant.val.length()); // look for further matches + } + } +} + + +/** 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, const SpecialActions &actions) { + auto left = str.find("{?("); // start position of expression macro + while (left != string::npos) { + auto 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); + XMLString valstr(val); + str.replace(left, right-left+2, valstr); + right = left+valstr.length()-1; + } + catch (CalculatorException &e) { + throw SpecialException(string(e.what())+" in '{?("+expr+")}'"); + } + } + left = str.find("{?(", right+1); // find next expression macro + } +} + + +/** Returns a given string with macros and arithmetic expressions expanded. + * @param[in] text string to be processed + * @return the expanded text */ +string SpecialActions::expandText (const string &text) { + string ret = text; + evaluate_expressions(ret, *this); + expand_constants(ret, *this); + return ret; +}
\ No newline at end of file |