summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-1.2.2/src/dvisvgm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-1.2.2/src/dvisvgm.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-1.2.2/src/dvisvgm.cpp424
1 files changed, 424 insertions, 0 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-1.2.2/src/dvisvgm.cpp b/Build/source/texk/dvisvgm/dvisvgm-1.2.2/src/dvisvgm.cpp
new file mode 100644
index 00000000000..f275ee65e52
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-1.2.2/src/dvisvgm.cpp
@@ -0,0 +1,424 @@
+/*************************************************************************
+** dvisvgm.cpp **
+** **
+** This file is part of dvisvgm -- the DVI to SVG converter **
+** Copyright (C) 2005-2013 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 <cmath>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include "gzstream.h"
+#include "CommandLine.h"
+#include "DVIToSVG.h"
+#include "DVIToSVGActions.h"
+#include "EPSToSVG.h"
+#include "FilePath.h"
+#include "FileSystem.h"
+#include "Font.h"
+#include "FontCache.h"
+#include "FontEngine.h"
+#include "FontMap.h"
+#include "Ghostscript.h"
+#include "InputReader.h"
+#include "Message.h"
+#include "FileFinder.h"
+#include "PageSize.h"
+#include "SignalHandler.h"
+#include "SpecialManager.h"
+#include "SVGOutputBase.h"
+#include "System.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#include "PSInterpreter.h"
+#endif
+#ifndef TARGET_SYSTEM
+#define TARGET_SYSTEM ""
+#endif
+
+#ifdef __MSVC__
+#include <potracelib.h>
+#else
+extern "C" {
+#include <potracelib.h>
+}
+#endif
+
+using namespace std;
+
+class SVGOutput : public SVGOutputBase
+{
+ public:
+ SVGOutput (const char *base=0, string pattern="", int zip_level=0)
+ : _path(base ? base : ""),
+ _pattern(pattern),
+ _stdout(base == 0),
+ _zipLevel(zip_level),
+ _page(-1),
+ _os(0) {}
+
+
+ ~SVGOutput () {
+ delete _os;
+ }
+
+
+ /** Returns an output stream for the given page.
+ * @param[in] page number of current page
+ * @param[in] numPages total number of pages in the DVI file
+ * @return output stream for the given page */
+ ostream& getPageStream (int page, int numPages) const {
+ string fname = filename(page, numPages);
+ if (fname.empty()) {
+ delete _os;
+ _os = 0;
+ return cout;
+ }
+ if (page == _page)
+ return *_os;
+
+ _page = page;
+ delete _os;
+
+ if (_zipLevel > 0)
+ _os = new ogzstream(fname.c_str(), _zipLevel);
+ else
+ _os = new ofstream(fname.c_str());
+ if (!_os || !*_os) {
+ delete _os;
+ _os = 0;
+ throw MessageException("can't open file "+fname+" for writing");
+ }
+ return *_os;
+ }
+
+
+ /** Returns the name of the SVG file containing the given page.
+ * @param[in] page number of page */
+ string filename (int page, int numPages) const {
+ if (_stdout)
+ return "";
+ string fname = _pattern;
+ if (fname.empty())
+ fname = numPages > 1 ? "%f-%p" : "%f";
+ else if (numPages > 1 && fname.find("%p") == string::npos)
+ fname += FileSystem::isDirectory(fname.c_str()) ? "/%f-%p" : "-%p";
+
+ // replace pattern variables by their actual values
+ // %f: basename of the DVI file
+ // %p: current page number
+ ostringstream oss;
+ oss << setfill('0') << setw(max(2, int(1+log10((double)numPages)))) << page;
+ size_t pos=0;
+ while ((pos = fname.find('%', pos)) != string::npos && pos < fname.length()-1) {
+ switch (fname[pos+1]) {
+ case 'f': fname.replace(pos, 2, _path.basename()); pos += _path.basename().length(); break;
+ case 'p': fname.replace(pos, 2, oss.str()); pos += oss.str().length(); break;
+ default : ++pos;
+ }
+ }
+ FilePath outpath(fname, true);
+ if (outpath.suffix().empty())
+ outpath.suffix(_zipLevel > 0 ? "svgz" : "svg");
+ string apath = outpath.absolute();
+ string rpath = outpath.relative();
+ return apath.length() < rpath.length() ? apath : rpath;
+ }
+
+ private:
+ FilePath _path;
+ string _pattern;
+ bool _stdout;
+ int _zipLevel;
+ mutable int _page; // number of current page being written
+ mutable ostream *_os;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+static void show_help (const CommandLine &cmd) {
+ cout << PACKAGE_STRING "\n\n";
+ cmd.help(cmd.help_arg());
+ cout << "\nCopyright (C) 2005-2013 Martin Gieseking <martin.gieseking@uos.de> \n\n";
+}
+
+
+static string remove_path (string fname) {
+ fname = FileSystem::adaptPathSeperators(fname);
+ size_t slashpos = fname.rfind('/');
+ if (slashpos == string::npos)
+ return fname;
+ return fname.substr(slashpos+1);
+}
+
+
+static string ensure_suffix (string fname, const string &suffix) {
+ size_t dotpos = remove_path(fname).rfind('.');
+ if (dotpos == string::npos)
+ fname += "."+suffix;
+ return fname;
+}
+
+
+static string get_transformation_string (const CommandLine &args) {
+ ostringstream oss;
+ if (args.rotate_given())
+ oss << 'R' << args.rotate_arg() << ",w/2,h/2";
+ if (args.translate_given())
+ oss << 'T' << args.translate_arg();
+ if (args.scale_given())
+ oss << 'S' << args.scale_arg();
+ if (args.transform_given())
+ oss << args.transform_arg();
+ return oss.str();
+}
+
+
+static void set_libgs (CommandLine &args) {
+#if !defined(DISABLE_GS) && !defined(HAVE_LIBGS)
+ if (args.libgs_given())
+ Ghostscript::LIBGS_NAME = args.libgs_arg();
+ else if (getenv("LIBGS"))
+ Ghostscript::LIBGS_NAME = getenv("LIBGS");
+#endif
+}
+
+
+static bool set_cache_dir (const CommandLine &args) {
+ if (args.cache_given() && !args.cache_arg().empty()) {
+ if (args.cache_arg() == "none")
+ PhysicalFont::CACHE_PATH = 0;
+ else if (FileSystem::exists(args.cache_arg().c_str()))
+ PhysicalFont::CACHE_PATH = args.cache_arg().c_str();
+ else
+ Message::wstream(true) << "cache directory '" << args.cache_arg() << "' does not exist (caching disabled)\n";
+ }
+ else {
+ if (const char *userdir = FileSystem::userdir()) {
+ static string path = userdir;
+ path += "/.dvisvgm";
+ path = FileSystem::adaptPathSeperators(path);
+ const string cachepath = path+"/cache";
+ if (!FileSystem::exists(cachepath.c_str())) {
+ if (!FileSystem::exists(path.c_str()))
+ FileSystem::mkdir(cachepath.c_str());
+ else {
+ FileSystem::mkdir(cachepath.c_str());
+ // move existing cache files from former location to new one
+ vector<string> files;
+ FileSystem::collect(path.c_str(), files);
+ FORALL(files, vector<string>::iterator, it) {
+ if (it->at(0) == 'f' && it->length() > 4 && it->substr(it->length()-4, 4) == ".fgd") {
+ const char *fname = it->c_str()+1;
+ FileSystem::copy(path+"/"+fname, cachepath+"/"+fname, true);
+ }
+ }
+ }
+ }
+ path = cachepath;
+ PhysicalFont::CACHE_PATH = path.c_str();
+ }
+ if (args.cache_given() && args.cache_arg().empty()) {
+ cout << "cache directory: " << (PhysicalFont::CACHE_PATH ? PhysicalFont::CACHE_PATH : "(none)") << '\n';
+ FontCache::fontinfo(PhysicalFont::CACHE_PATH, cout, true);
+ return false;
+ }
+ }
+ return true;
+}
+
+
+static bool check_bbox (const string &bboxstr) {
+ const char *formats[] = {"none", "min", "dvi", 0};
+ for (const char **p=formats; *p; ++p)
+ if (bboxstr == *p)
+ return true;
+ if (isalpha(bboxstr[0])) {
+ try {
+ PageSize size(bboxstr);
+ return true;
+ }
+ catch (const PageSizeException &e) {
+ Message::estream(true) << "invalid bounding box format '" << bboxstr << "'\n";
+ return false;
+ }
+ }
+ try {
+ BoundingBox bbox;
+ bbox.set(bboxstr);
+ return true;
+ }
+ catch (const MessageException &e) {
+ Message::estream(true) << e.what() << '\n';
+ return false;
+ }
+}
+
+
+static void print_version (bool extended) {
+ ostringstream oss;
+ oss << PACKAGE_STRING;
+ if (extended) {
+ if (strlen(TARGET_SYSTEM) > 0)
+ oss << " (" TARGET_SYSTEM ")";
+ oss << "\n" << string(oss.str().length()-1, '-') << "\n"
+ "freetype: " << FontEngine::version() << "\n";
+
+ string gsver;
+ Ghostscript gs;
+ gsver = gs.revision(true);
+ if (!gsver.empty())
+ oss << "Ghostscript: " << gsver + "\n";
+ oss <<
+#ifdef MIKTEX
+ "MiKTeX: " << FileFinder::version() << "\n"
+#else
+ "kpathsea: " << FileFinder::version() << "\n"
+#endif
+ "potrace: " << (strchr(potrace_version(), ' ') ? strchr(potrace_version(), ' ')+1 : "unknown") << "\n"
+ "zlib: " << zlibVersion();
+ }
+ cout << oss.str() << endl;
+}
+
+
+static void init_fontmap (const CommandLine &args) {
+ const char *mapseq = args.fontmap_given() ? args.fontmap_arg().c_str() : 0;
+ bool additional = mapseq && strchr("+-=", *mapseq);
+ if (!mapseq || additional) {
+ const char *mapfiles[] = {"ps2pk.map", "dvipdfm.map", "psfonts.map", 0};
+ bool found = false;
+ for (const char **p=mapfiles; *p && !found; p++)
+ found = FontMap::instance().read(*p);
+ if (!found)
+ Message::wstream(true) << "none of the default map files could be found";
+ }
+ if (mapseq)
+ FontMap::instance().read(mapseq);
+}
+
+
+int main (int argc, char *argv[]) {
+ CommandLine args;
+ args.parse(argc, argv);
+ if (args.error())
+ return 1;
+
+ Message::COLORIZE = args.color_given();
+
+ set_libgs(args);
+ if (args.version_given()) {
+ print_version(args.version_arg());
+ return 0;
+ }
+ if (args.list_specials_given()) {
+ SVGOutput out;
+ DVIToSVG dvisvg(cin, out);
+ if (const SpecialManager *sm = dvisvg.setProcessSpecials())
+ sm->writeHandlerInfo(cout);
+ return 0;
+ }
+
+ if (!set_cache_dir(args))
+ return 0;
+
+ if (argc == 1 || args.help_given()) {
+ show_help(args);
+ return 0;
+ }
+
+ if (argc > 1 && args.numFiles() < 1) {
+ Message::estream(true) << "no input file given\n";
+ return 1;
+ }
+
+ if (args.stdout_given() && args.zip_given()) {
+ Message::estream(true) << "writing SVGZ files to stdout is not supported\n";
+ return 1;
+ }
+
+ if (!check_bbox(args.bbox_arg()))
+ return 1;
+
+ if (args.progress_given()) {
+ DVIReader::COMPUTE_PAGE_LENGTH = args.progress_given();
+ DVIToSVGActions::PROGRESSBAR_DELAY = args.progress_arg();
+ }
+ SVGTree::CREATE_STYLE = !args.no_styles_given();
+ SVGTree::USE_FONTS = !args.no_fonts_given();
+ SVGTree::CREATE_USE_ELEMENTS = args.no_fonts_arg() < 1;
+ DVIToSVGActions::EXACT_BBOX = args.exact_given();
+ DVIToSVG::TRACE_MODE = args.trace_all_given() ? (args.trace_all_arg() ? 'a' : 'm') : 0;
+ Message::LEVEL = args.verbosity_arg();
+ PhysicalFont::KEEP_TEMP_FILES = args.keep_given();
+ PhysicalFont::METAFONT_MAG = args.mag_arg();
+ XMLString::DECIMAL_PLACES = max(0, min(6, args.precision_arg()));
+
+ double start_time = System::time();
+ string inputfile = ensure_suffix(args.file(0), args.eps_given() ? "eps" : "dvi");
+ ifstream ifs(inputfile.c_str(), ios_base::binary|ios_base::in);
+ if (!ifs) {
+ Message::estream(true) << "can't open file '" << inputfile << "' for reading\n";
+ return 0;
+ }
+ try {
+ FileFinder::init(argv[0], "dvisvgm", !args.no_mktexmf_given());
+ SVGOutput out(args.stdout_given() ? 0 : inputfile.c_str(), args.output_arg(), args.zip_given() ? args.zip_arg() : 0);
+ SignalHandler::instance().start();
+ if (args.eps_given()) {
+ EPSToSVG eps2svg(inputfile, out);
+ eps2svg.convert();
+ Message::mstream().indent(0);
+ Message::mstream(false, Message::MC_PAGE_NUMBER)
+ << "file converted in " << (System::time()-start_time) << " seconds\n";
+ }
+ else {
+ DVIToSVG dvi2svg(ifs, out);
+ const char *ignore_specials = args.no_specials_given() ? (args.no_specials_arg().empty() ? "*" : args.no_specials_arg().c_str()) : 0;
+ dvi2svg.setProcessSpecials(ignore_specials, true);
+ dvi2svg.setTransformation(get_transformation_string(args));
+ dvi2svg.setPageSize(args.bbox_arg());
+
+ init_fontmap(args);
+ pair<int,int> pageinfo;
+ dvi2svg.convert(args.page_arg(), &pageinfo);
+ Message::mstream().indent(0);
+ Message::mstream(false, Message::MC_PAGE_NUMBER) << "\n" << pageinfo.first << " of " << pageinfo.second << " page";
+ if (pageinfo.second > 1)
+ Message::mstream(false, Message::MC_PAGE_NUMBER) << 's';
+ Message::mstream(false, Message::MC_PAGE_NUMBER) << " converted in " << (System::time()-start_time) << " seconds\n";
+ }
+ }
+ catch (DVIException &e) {
+ Message::estream() << "\nDVI error: " << e.what() << '\n';
+ }
+ catch (PSException &e) {
+ Message::estream() << "\nPostScript error: " << e.what() << '\n';
+ }
+ catch (SignalException &e) {
+ Message::wstream(true) << "execution interrupted by user\n";
+ }
+ catch (MessageException &e) {
+ Message::estream(true) << e.what() << '\n';
+ }
+ FileFinder::finish();
+ return 0;
+}
+