File indexing completed on 2024-04-28 07:39:36

0001 /*.
0002     SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "latexformula.h"
0008 
0009 #include <QApplication>
0010 #include <QDebug>
0011 #include <QFile>
0012 #include <QProcess>
0013 #include <QStandardPaths>
0014 #include <QTemporaryDir>
0015 #include <QTextStream>
0016 
0017 #include <KLocalizedString>
0018 
0019 namespace {
0020 
0021 bool executeCommand(const QString& cmd, const QStringList& args,
0022                     const QString& workDir, const QString& resultFile, QString* error)
0023 {
0024     QProcess proc;
0025     proc.setProcessChannelMode(QProcess::MergedChannels);
0026     proc.setWorkingDirectory(workDir);
0027     proc.start(cmd, args);
0028 
0029     if(!proc.waitForStarted()) {
0030         *error = i18n("can not launch %1", cmd); return false;
0031     }
0032 
0033     proc.closeWriteChannel();
0034 
0035     while(proc.state() == QProcess::Running) {
0036         qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
0037     }
0038 
0039     if(proc.exitStatus() != QProcess::NormalExit) {
0040         *error = i18n("error running %1", cmd); return false;
0041     }
0042 
0043     if(proc.exitCode() != 0) { // XXX TODO: verbose error message
0044         *error = i18n("%1 reported an error (exit status %2):\n%3",
0045                     cmd, proc.exitCode(), QString::fromLocal8Bit(proc.readAll())); return false;
0046     }
0047 
0048     if(!QFile::exists(resultFile)) {
0049         *error = i18n("%1 did not create output file", cmd); return false;
0050     }
0051 
0052     return true;
0053 }
0054 
0055 }
0056 
0057 bool LatexFormula::isLatexInstalled()
0058 {
0059     if(QStandardPaths::findExecutable(QStringLiteral("latex")).isEmpty()) return false;
0060     if(QStandardPaths::findExecutable(QStringLiteral("dvips")).isEmpty()) return false;
0061     if(QStandardPaths::findExecutable(QStringLiteral("gs")).isEmpty()) return false;
0062     return true;
0063 }
0064 
0065 bool LatexFormula::compileFormula(const QString& formula, QByteArray* result, QString* error)
0066 {
0067     QTemporaryDir tempDir;
0068     if (!tempDir.isValid()) {
0069         // tempDir could not be created
0070         qDebug() << "tempDir.isValid() = false";
0071         return false;
0072     }
0073     qDebug() << "tempDir.path() = " << tempDir.path();
0074     QString baseFileName = tempDir.path() + "/formula";
0075     qDebug() << "baseFileName = " << baseFileName;
0076 
0077     QFile latexFile(baseFileName + ".tex");
0078     qDebug() << "latexFile filename = " << (baseFileName + ".tex");
0079 
0080     if(!latexFile.open(QIODevice::WriteOnly)) {
0081         *error = i18n("can not open temporary file");
0082         qDebug() << "cannot open latexFile:\n" << &error;
0083         return false;
0084     }
0085 
0086     QTextStream latexStream(&latexFile);
0087     latexStream << "\\documentclass[12pt]{article}\n"
0088                 << "\\pagestyle{empty}\n"
0089                 << "\\usepackage[utf8]{inputenc}\n"
0090                 << "\\usepackage[dvips]{graphicx}\n"
0091                 << "\\usepackage[dvips]{color}\n"
0092                 << "\\usepackage{amssymb,amsmath}\n"
0093                 << "\\begin{document}\n"
0094                 << "\\begin{displaymath}"
0095                 << formula 
0096                 << "\\end{displaymath}\n"
0097                 << "\\end{document}\n";
0098 
0099     latexFile.close();
0100 
0101     if(!executeCommand(QStringLiteral("latex"), QStringList() << QStringLiteral("--interaction=nonstopmode") << baseFileName + ".tex",
0102                             tempDir.path(), baseFileName+".tex", error)) return false;
0103 
0104     if(!executeCommand(QStringLiteral("dvips"), QStringList() << QStringLiteral("-E") << baseFileName+".dvi" << QStringLiteral("-o") << baseFileName+".eps",
0105                             tempDir.path(), baseFileName+".eps", error)) return false;
0106 
0107     QStringList gsArgs;
0108     gsArgs << QStringLiteral("-dNOPAUSE") << QStringLiteral("-dSAFER") << QStringLiteral("-dEPSCrop") << QStringLiteral("-r100")
0109            << QStringLiteral("-dTextAlphaBits=4") << QStringLiteral("-dGraphicsAlphaBits=4") << QStringLiteral("-sDEVICE=pngalpha")
0110            << "-sOutputFile="+baseFileName+".png" << QStringLiteral("-q") << QStringLiteral("-dBATCH") << baseFileName+".eps";
0111     if(!executeCommand(QStringLiteral("gs"), gsArgs, tempDir.path(), baseFileName+".png", error)) return false;
0112 
0113     QFile pngFile(baseFileName + ".png");
0114     if(!pngFile.open(QIODevice::ReadOnly)) {
0115         *error = i18n("can not open result file");
0116         return false;
0117     }
0118 
0119     *result = pngFile.readAll();
0120 
0121     return true;
0122 }
0123