mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-24 18:35:37 +00:00
Add LatexRenderer class
This commit is contained in:
parent
9ed86abb6c
commit
33b9ff1a36
|
@ -152,6 +152,7 @@ set(okularpart_SRCS
|
|||
ui/formwidgets.cpp
|
||||
ui/guiutils.cpp
|
||||
ui/ktreeviewsearchline.cpp
|
||||
ui/latexrenderer.cpp
|
||||
ui/minibar.cpp
|
||||
ui/pageitemdelegate.cpp
|
||||
ui/pagepainter.cpp
|
||||
|
|
195
ui/latexrenderer.cpp
Normal file
195
ui/latexrenderer.cpp
Normal file
|
@ -0,0 +1,195 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2004 by Duncan Mac-Vicar Prett <duncan@kde.org> *
|
||||
* Copyright (C) 2004-2005 by Olivier Goffart <ogoffart@kde.org> *
|
||||
* Copyright (C) 2011 by Niels Ole Salscheider *
|
||||
* <niels_ole@salscheider-online.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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "latexrenderer.h"
|
||||
|
||||
#include <QtGui>
|
||||
#include <kstandarddirs.h>
|
||||
#include <kprocess.h>
|
||||
#include <ktemporaryfile.h>
|
||||
|
||||
namespace GuiUtils
|
||||
{
|
||||
|
||||
LatexRenderer::LatexRenderer()
|
||||
{
|
||||
m_filelist = new QVector<QString>();
|
||||
}
|
||||
|
||||
LatexRenderer::~LatexRenderer()
|
||||
{
|
||||
while (!m_filelist->isEmpty())
|
||||
{
|
||||
QFile::remove(m_filelist->last());
|
||||
m_filelist->pop_back();
|
||||
}
|
||||
|
||||
delete m_filelist;
|
||||
}
|
||||
|
||||
|
||||
LatexRenderer::Error LatexRenderer::renderLatexInHtml( QString& html, const QColor& textColor, int fontSize, int resolution, QString& latexOutput )
|
||||
{
|
||||
if( !html.contains("$$"))
|
||||
return NoError;
|
||||
|
||||
// this searches for $$formula$$
|
||||
QRegExp rg("\\$\\$.+\\$\\$");
|
||||
rg.setMinimal(true);
|
||||
|
||||
int pos = 0;
|
||||
|
||||
QMap<QString, QString> replaceMap;
|
||||
while (pos >= 0 && pos < html.length())
|
||||
{
|
||||
pos = rg.indexIn(html, pos);
|
||||
|
||||
if (pos >= 0 )
|
||||
{
|
||||
const QString match = rg.cap(0);
|
||||
pos += rg.matchedLength();
|
||||
|
||||
QString formul=match;
|
||||
// first remove the $$ delimiters on start and end
|
||||
formul.remove("$$");
|
||||
// then trim the result, so we can skip totally empty/whitespace-only formulas
|
||||
formul = formul.trimmed();
|
||||
if (formul.isEmpty() || !securityCheck(formul))
|
||||
continue;
|
||||
|
||||
QString fileName;
|
||||
Error returnCode = handleLatex(fileName, formul, textColor, fontSize, resolution, latexOutput);
|
||||
if (returnCode != NoError)
|
||||
return returnCode;
|
||||
|
||||
replaceMap[match] = fileName;
|
||||
}
|
||||
}
|
||||
|
||||
if(replaceMap.isEmpty()) //we haven't found any LaTeX strings
|
||||
return NoError;
|
||||
|
||||
int imagePxWidth,imagePxHeight;
|
||||
for (QMap<QString,QString>::ConstIterator it = replaceMap.constBegin(); it != replaceMap.constEnd(); ++it)
|
||||
{
|
||||
QImage theImage(*it);
|
||||
if(theImage.isNull())
|
||||
continue;
|
||||
imagePxWidth = theImage.width();
|
||||
imagePxHeight = theImage.height();
|
||||
QString escapedLATEX=Qt::escape(it.key()).replace('\"',"""); //we need the escape quotes because that string will be in a title="" argument, but not the \n
|
||||
html.replace(Qt::escape(it.key()), " <img width=\"" + QString::number(imagePxWidth) + "\" height=\"" + QString::number(imagePxHeight) + "\" align=\"middle\" src=\"" + (*it) + "\" alt=\"" + escapedLATEX +"\" title=\"" + escapedLATEX +"\" /> ");
|
||||
}
|
||||
return NoError;
|
||||
}
|
||||
|
||||
bool LatexRenderer::mightContainLatex (const QString& text)
|
||||
{
|
||||
if( !text.contains("$$"))
|
||||
return false;
|
||||
|
||||
// this searches for $$formula$$
|
||||
QRegExp rg("\\$\\$.+\\$\\$");
|
||||
rg.setMinimal(true);
|
||||
if( rg.lastIndexIn(text) == -1 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LatexRenderer::Error LatexRenderer::handleLatex( QString& fileName, const QString& latexFormula, const QColor& textColor, int fontSize, int resolution, QString& latexOutput )
|
||||
{
|
||||
KProcess latexProc;
|
||||
KProcess dvipngProc;
|
||||
|
||||
KTemporaryFile *tempFile = new KTemporaryFile();
|
||||
tempFile->setPrefix("kdelatex-");
|
||||
tempFile->setSuffix(".tex");
|
||||
tempFile->open();
|
||||
QString tempFileName = tempFile->fileName();
|
||||
QFileInfo *tempFileInfo = new QFileInfo(tempFileName);
|
||||
QString tempFileNameNS = tempFileInfo->absolutePath() + QDir::separator() + tempFileInfo->baseName();
|
||||
QString tempFilePath = tempFileInfo->absolutePath();
|
||||
delete tempFileInfo;
|
||||
QTextStream tempStream(tempFile);
|
||||
|
||||
tempStream << "\
|
||||
\\documentclass[" << fontSize << "pt]{article} \
|
||||
\\usepackage{color} \
|
||||
\\usepackage{amsmath,latexsym,amsfonts,amssymb,ulem} \
|
||||
\\pagestyle{empty} \
|
||||
\\begin{document} \
|
||||
{\\color[rgb]{" << textColor.redF() << "," << textColor.greenF() << "," << textColor.blueF() << "} \
|
||||
\\begin{eqnarray*} \
|
||||
" << latexFormula << " \
|
||||
\\end{eqnarray*}} \
|
||||
\\end{document}";
|
||||
|
||||
tempFile->close();
|
||||
QString latexExecutable = KStandardDirs::findExe("latex");
|
||||
if (latexExecutable.isEmpty())
|
||||
{
|
||||
qDebug() << "Could not find latex!";
|
||||
delete tempFile;
|
||||
fileName = QString("");
|
||||
return LatexNotFound;
|
||||
}
|
||||
latexProc << latexExecutable << "-interaction=nonstopmode" << "-halt-on-error" << QString("-output-directory=%1").arg(tempFilePath) << tempFile->fileName();
|
||||
latexProc.setOutputChannelMode( KProcess::MergedChannels );
|
||||
latexProc.execute();
|
||||
latexOutput = latexProc.readAll();
|
||||
tempFile->remove();
|
||||
|
||||
QFile::remove(tempFileNameNS + QString(".log"));
|
||||
QFile::remove(tempFileNameNS + QString(".aux"));
|
||||
delete tempFile;
|
||||
|
||||
if (!QFile::exists(tempFileNameNS + QString(".dvi")))
|
||||
{
|
||||
fileName = QString("");
|
||||
return LatexFailed;
|
||||
}
|
||||
|
||||
QString dvipngExecutable = KStandardDirs::findExe("dvipng");
|
||||
if (dvipngExecutable.isEmpty())
|
||||
{
|
||||
qDebug() << "Could not find dvipng!";
|
||||
fileName = QString("");
|
||||
return DvipngNotFound;
|
||||
}
|
||||
|
||||
dvipngProc << dvipngExecutable << QString("-o%1").arg(tempFileNameNS + QString(".png")) << "-Ttight" << "-bgTransparent" << QString("-D %1").arg(resolution) << QString("%1").arg(tempFileNameNS + QString(".dvi"));
|
||||
dvipngProc.setOutputChannelMode( KProcess::MergedChannels );
|
||||
dvipngProc.execute();
|
||||
|
||||
QFile::remove(tempFileNameNS + QString(".dvi"));
|
||||
|
||||
if (!QFile::exists(tempFileNameNS + QString(".png")))
|
||||
{
|
||||
fileName = QString("");
|
||||
return DvipngFailed;
|
||||
}
|
||||
|
||||
m_filelist->append(tempFileNameNS + QString(".png"));
|
||||
fileName = tempFileNameNS + QString(".png");
|
||||
return NoError;
|
||||
}
|
||||
|
||||
bool LatexRenderer::securityCheck( const QString &latexFormula )
|
||||
{
|
||||
return !latexFormula.contains(QRegExp("\\\\(def|let|futurelet|newcommand|renewcomment|else|fi|write|input|include"
|
||||
"|chardef|catcode|makeatletter|noexpand|toksdef|every|errhelp|errorstopmode|scrollmode|nonstopmode|batchmode"
|
||||
"|read|csname|newhelp|relax|afterground|afterassignment|expandafter|noexpand|special|command|loop|repeat|toks"
|
||||
"|output|line|mathcode|name|item|section|mbox|DeclareRobustCommand)[^a-zA-Z]"));
|
||||
}
|
||||
|
||||
}
|
51
ui/latexrenderer.h
Normal file
51
ui/latexrenderer.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2004 by Duncan Mac-Vicar Prett <duncan@kde.org> *
|
||||
* Copyright (C) 2004-2005 by Olivier Goffart <ogoffart@kde.org> *
|
||||
* Copyright (C) 2011 by Niels Ole Salscheider *
|
||||
* <niels_ole@salscheider-online.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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef LATEXRENDERER_H
|
||||
#define LATEXRENDERER_H
|
||||
#include "guiutils.h"
|
||||
|
||||
#include <QVector>
|
||||
class QString;
|
||||
class QColor;
|
||||
|
||||
namespace GuiUtils
|
||||
{
|
||||
|
||||
class LatexRenderer
|
||||
{
|
||||
|
||||
public:
|
||||
enum Error {
|
||||
NoError,
|
||||
LatexNotFound,
|
||||
DvipngNotFound,
|
||||
LatexFailed,
|
||||
DvipngFailed
|
||||
};
|
||||
|
||||
LatexRenderer();
|
||||
virtual ~LatexRenderer();
|
||||
|
||||
Error renderLatexInHtml( QString& html, const QColor &textColor, int fontSize, int resolution, QString &latexOutput );
|
||||
static bool mightContainLatex ( const QString& text );
|
||||
|
||||
private:
|
||||
Error handleLatex( QString &fileName, const QString &latexFormula, const QColor &textColor, int fontSize, int resolution, QString &latexOutput );
|
||||
static bool securityCheck( const QString &latexFormula );
|
||||
|
||||
QVector<QString> *m_filelist;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LATEXRENDERER_H
|
Loading…
Reference in a new issue