2022-08-08 00:00:05 +08:00
/** \example jkqtmathtext_render.cpp
* A very basic example for the usage of JKQTMathText
*
* \ ref JKQTMathTextRenderCmdLineTool
*/
# include <QApplication>
# include <QPixmap>
# include <QPainter>
# include <QCommandLineParser>
# include <QCommandLineOption>
# include <QElapsedTimer>
# include <QFile>
# include <QDir>
2022-08-08 04:59:32 +08:00
# include <QTextStream>
2022-08-08 16:39:15 +08:00
# include <algorithm>
2022-08-08 00:00:05 +08:00
# if (QT_VERSION>=QT_VERSION_CHECK(6, 0, 0))
# include<QRegularExpression>
# include<QRegularExpressionMatch>
# else
# include<QRegExp>
# endif
# include "jkqtmathtext/jkqtmathtextlabel.h"
# include "jkqtcommon/jkqtpstringtools.h"
2022-08-08 04:13:31 +08:00
# include "jkqtmathtext/nodes/jkqtmathtextsymbolnode.h"
2022-08-13 21:32:31 +08:00
# include "jkqtmathtext/nodes/jkqtmathtextnodetools.h"
2022-08-08 00:00:05 +08:00
# include <iostream>
void processFont ( const QString font , QStringList & fonts , QString & mathFont )
{
fonts . clear ( ) ;
mathFont = " " ;
QString current = " " ;
bool isExtra = false ;
for ( int i = 0 ; i < font . size ( ) ; i + + ) {
if ( font [ i ] = = ' , ' ) {
fonts . push_back ( current ) ;
current = " " ;
} else if ( font [ i ] = = ' + ' ) {
fonts . push_back ( current ) ;
isExtra = true ;
current = " " ;
} else {
if ( isExtra ) {
mathFont + = font [ i ] ;
} else {
current + = font [ i ] ;
}
}
}
if ( current . size ( ) > 0 ) {
fonts . append ( current ) ;
}
}
int main ( int argc , char * argv [ ] )
{
// 1. create Qt Appcilation object and a QCommandLineParser to go with it
QApplication app ( argc , argv ) ;
QCommandLineParser parser ;
parser . setApplicationDescription ( " JKQTMathText command line tool that renders LaTeX markup into an image " ) ;
parser . addHelpOption ( ) ;
parser . addVersionOption ( ) ;
parser . addPositionalArgument ( " latex " , " LaTeX markup to be rendered " ) ;
parser . addPositionalArgument ( " output " , " output image file (extensions determines file type) " ) ;
QCommandLineOption inputfileOption ( " inputfile " , " read from a file instead of from command line. " , " inputfile " , " " ) ;
parser . addOption ( inputfileOption ) ;
QCommandLineOption outputDirectoryOption ( " outputdir " , " write results into this directory. " , " outputdir " , app . applicationDirPath ( ) ) ;
parser . addOption ( outputDirectoryOption ) ;
2022-08-08 04:13:31 +08:00
QCommandLineOption listsymbolsOption ( " listsymbols " , " list all symbols in the given output file and generate images. " , " listsymbols " , " " ) ;
parser . addOption ( listsymbolsOption ) ;
2022-09-01 20:36:34 +08:00
QCommandLineOption listsymbolsfontsOption ( " listsymbolsfonts " , " fonts for listsymbols. " , " listsymbolsfonts " , " XITS " ) ;
parser . addOption ( listsymbolsfontsOption ) ;
2022-08-10 18:12:30 +08:00
QCommandLineOption drawBoxesOption ( QStringList ( ) < < " drawboxes " < < " showboxes " , " draw boxes. " ) ;
2022-08-08 00:00:05 +08:00
parser . addOption ( drawBoxesOption ) ;
QCommandLineOption verboseOption ( " verbose " , " verbose output. " ) ;
parser . addOption ( verboseOption ) ;
2022-09-01 20:36:34 +08:00
QCommandLineOption guifontsOption ( " guifonts " , " use GUI fonts. " ) ;
parser . addOption ( guifontsOption ) ;
2022-08-08 00:00:05 +08:00
QCommandLineOption fontOption ( " font " , " font( size) s ) to use . " , " font " , " XITS " ) ;
parser . addOption ( fontOption ) ;
QCommandLineOption fontsizeOption ( " fontsize " , " font size. " , " fontsize " , " 12 " ) ;
parser . addOption ( fontsizeOption ) ;
QCommandLineOption fontRomanOption ( " fontroman " , " set the text-mode roman font to use. " , " fontroman " , " " ) ;
parser . addOption ( fontRomanOption ) ;
QCommandLineOption fontSansOption ( " fontsans " , " set the text-mode sans font to use. " , " fontsans " , " " ) ;
parser . addOption ( fontSansOption ) ;
QCommandLineOption fontMathRomanOption ( " fontmathroman " , " set the math-mode roman font to use. " , " fontmathroman " , " " ) ;
parser . addOption ( fontMathRomanOption ) ;
QCommandLineOption fontMathSansOption ( " fontmathsans " , " set the math-mode sans font to use. " , " fontmathsans " , " " ) ;
parser . addOption ( fontMathSansOption ) ;
QCommandLineOption fontFallbackSymbolOption ( " fontfallbacksymbol " , " set the fallback symbol font to use. " , " fontfallbacksymbol " , " " ) ;
parser . addOption ( fontFallbackSymbolOption ) ;
QCommandLineOption fontFallbackSymbol_symbolencodingOption ( " fontfallbacksymbol_symbolencoding " , " set the fallback symbol font to use and use the encoding of the MS Symbol font for it. " , " fontfallbacksymbol_symbolencoding " , " " ) ;
parser . addOption ( fontFallbackSymbol_symbolencodingOption ) ;
QCommandLineOption fontTypewriterOption ( " fonttypewriter " , " set the typewriter font to use. " , " fonttypewriter " , " " ) ;
parser . addOption ( fontTypewriterOption ) ;
QCommandLineOption fontScriptOption ( " fontscript " , " set the Script font to use. " , " fontscript " , " " ) ;
parser . addOption ( fontScriptOption ) ;
QCommandLineOption fontFrakturOption ( " fontfraktur " , " set the Fraktur font to use. " , " fontfraktur " , " " ) ;
parser . addOption ( fontFrakturOption ) ;
QCommandLineOption fontcaligraphicOption ( " fontcaligraphic " , " set the caligraphic font to use. " , " fontcaligraphic " , " " ) ;
parser . addOption ( fontcaligraphicOption ) ;
QCommandLineOption fontblackboardOption ( " fontblackboard " , " set the blackboard font to use. " , " fontblackboard " , " " ) ;
parser . addOption ( fontblackboardOption ) ;
2022-08-10 18:12:30 +08:00
QCommandLineOption fontblackboardmodeOption ( " fontblackboardmode " , " set the usage mode for the blackboard font. " , " fontblackboardmode " , " default " ) ;
parser . addOption ( fontblackboardmodeOption ) ;
2022-08-08 00:00:05 +08:00
QCommandLineOption textcolorOption ( " textcolor " , " set the color of the text. " , " textcolor " , " black " ) ;
parser . addOption ( textcolorOption ) ;
QCommandLineOption sizeincreaseOption ( " sizeincrease " , " additional pixels around output. " , " sizeincrease " , " 2 " ) ;
parser . addOption ( sizeincreaseOption ) ;
QCommandLineOption resolutionOption ( " resolution " , " set output image resolution in DPI. " , " resolution " , " 96 " ) ;
parser . addOption ( resolutionOption ) ;
QCommandLineOption backgroundOption ( " background " , " background color. " , " background " , " white " ) ;
parser . addOption ( backgroundOption ) ;
parser . process ( app ) ;
const QStringList args = parser . positionalArguments ( ) ;
const QString latex_cmdline = args . value ( 0 , " $x_{1/2}= \\ frac{-b \\ pm \\ sqrt{b^2-4ac}}{2a}$ " ) ;
const QDir outputDir ( parser . value ( outputDirectoryOption ) ) ;
const QString outputFilename_cmdline = outputDir . absoluteFilePath ( args . value ( 1 , " output.png " ) ) ;
const QString inputfile = parser . value ( inputfileOption ) ;
2022-08-08 04:13:31 +08:00
const QString listsymbols = parser . value ( listsymbolsOption ) ;
2022-09-01 20:36:34 +08:00
const QStringList listsymbolsfonts = parser . value ( listsymbolsfontsOption ) . split ( ' , ' ) ;
2022-08-08 00:00:05 +08:00
const bool verbose = parser . isSet ( verboseOption ) ;
QStringList latex , outputFilename ;
QList < QMap < QString , QString > > cmdoptions ;
2022-08-08 04:13:31 +08:00
if ( listsymbols . size ( ) > 0 ) {
//std::cout<<"LISTSYMBOLS: "<<outputDir.absoluteFilePath(listsymbols).toStdString()<<"\n";
QFile fileListF ( outputDir . absoluteFilePath ( listsymbols ) ) ;
if ( fileListF . open ( QFile : : WriteOnly | QFile : : Text ) ) {
QTextStream fileList ( & fileListF ) ;
2022-08-11 17:33:29 +08:00
QStringList symbolsAll = JKQTMathTextSymbolNode : : getSymbols ( ) ;
2022-08-11 21:11:38 +08:00
QSet < QString > symbolsRemaining ;
for ( const QString & s : symbolsAll ) symbolsRemaining . insert ( s ) ;
2022-08-11 17:33:29 +08:00
std : : sort ( symbolsAll . begin ( ) , symbolsAll . end ( ) , [ ] ( const QString & a , const QString & b ) { const QString al = a . toLower ( ) ; const QString bl = b . toLower ( ) ; if ( al = = bl ) { return a < b ; } else return al < bl ; } ) ;
2022-08-11 15:06:06 +08:00
static QStringList greekLetterNames = QStringList ( ) < < " alpha " < < " beta " < < " gamma " < < " delta " < < " epsilon " < < " zeta " < < " eta " < < " theta " < < " iota " < < " kappa " < < " lambda " < < " mu " < < " nu " < < " xi " < < " pi " < < " rho " < < " sigma " < < " tau " < < " upsilon " < < " phi " < < " chi " < < " psi " < < " omega " ;
static QStringList arrowNames = QStringList ( ) < < " arrow " < < " harpoon " < < " mapsto " ;
2022-08-08 04:13:31 +08:00
int i = 1 ;
fileList < < " /*! \n "
" \\ defgroup jkqtmathtext_supportedlatexsymbols Supported LaTeX-Symbols \n "
2022-08-20 22:19:40 +08:00
" \\ ingroup jkqtmathtext_general_latex \n \n \\ tableofcontents \n \n " ;
2022-09-01 20:36:34 +08:00
fileList < < " Symbols are shown in these fonts: \n "
" <ul> \n " ;
for ( const QString & fnt : listsymbolsfonts ) {
fileList < < " <li> " < < fnt < < " </li> \n " ;
}
fileList < < " </ul> \n \n \n " ;
2022-08-11 17:33:29 +08:00
fileList < < " \\ section jkqtmathtext_supportedlatexsymbols_greek Greek Letters \n " ;
2022-08-11 15:06:06 +08:00
fileList < < " The following table lists all greek letters and their variants available in JKQTMathParser. They are defined in the node-class JKQTMathTextSymbolNode: \n " ;
2022-08-08 04:13:31 +08:00
fileList < < " <table> \n " ;
fileList < < " <tr> \n " ;
2022-08-11 15:06:06 +08:00
for ( const QString & gletter : greekLetterNames ) {
QString code = " " ;
2022-08-11 17:33:29 +08:00
for ( const QString & symbol : symbolsAll ) {
2022-08-11 15:06:06 +08:00
if ( symbol . size ( ) > 0 & & ( symbol . toLower ( ) = = gletter | | symbol . toLower ( ) = = " var " + gletter ) & & symbol [ 0 ] . isLetter ( ) ) {
code + = " \\ " + symbol + " \\ ; " ;
2022-08-11 17:33:29 +08:00
symbolsRemaining . remove ( symbol ) ;
2022-08-11 15:06:06 +08:00
}
}
2022-08-11 17:33:29 +08:00
for ( const QString & symbol : symbolsAll ) {
2022-08-11 15:06:06 +08:00
if ( symbol . size ( ) > 0 & & ( symbol . toLower ( ) = = " up " + gletter | | symbol . toLower ( ) = = " upvar " + gletter ) & & symbol [ 0 ] . isLetter ( ) ) {
code + = " \\ " + symbol + " \\ ; " ;
2022-08-11 17:33:29 +08:00
symbolsRemaining . remove ( symbol ) ;
}
}
for ( const QString & symbol : symbolsAll ) {
if ( symbol . size ( ) > 0 & & ( symbol . toLower ( ) = = " text " + gletter | | symbol . toLower ( ) = = " textvar " + gletter ) & & symbol [ 0 ] . isLetter ( ) ) {
code + = " \\ " + symbol + " \\ ; " ;
symbolsRemaining . remove ( symbol ) ;
2022-08-11 15:06:06 +08:00
}
}
QString symbol_lower ;
for ( const QChar & ch : gletter ) {
if ( ch . isUpper ( ) ) symbol_lower + = QString ( 2 , ch ) . toLower ( ) ;
else symbol_lower + = ch ;
}
2022-09-01 20:36:34 +08:00
for ( const QString & fnt : listsymbolsfonts ) {
latex . append ( code + " \\ vphantom{Iq} " ) ;
outputFilename . append ( " jkqtmathtext_greek_ " + symbol_lower + " _ " + fnt + " .png " ) ;
QMap < QString , QString > localoptions ;
localoptions [ " fontmathroman " ] = fnt ;
cmdoptions . append ( localoptions ) ;
}
2022-08-11 15:06:06 +08:00
//std::cout<<" - "<<latex.last().toStdString()<<": "<<outputFilename.last().toStdString()<<"\n";
2022-08-11 17:33:29 +08:00
code = code . replace ( " \\ ; " , " " ) ;
2022-08-11 15:06:06 +08:00
code = code . replace ( " \\ " , " \\ \\ " ) ;
2022-09-01 20:36:34 +08:00
fileList < < " <td><code> " < < code < < " </code>: \n <td> " ;
for ( int i = 0 ; i < listsymbolsfonts . size ( ) ; i + + ) {
if ( i > 0 ) fileList < < " " ;
fileList < < " \\ image html jkqtmathtext/symbols/ " < < outputFilename [ outputFilename . size ( ) - listsymbolsfonts . size ( ) + i ] < < " \n " ;
}
2022-08-11 17:33:29 +08:00
//if (i%2==0) {
2022-08-11 15:06:06 +08:00
fileList < < " </tr> \n <tr> \n " ;
2022-08-11 17:33:29 +08:00
//}
2022-08-11 15:06:06 +08:00
i + + ;
}
fileList < < " </tr> " ;
fileList < < " </table> \n \n \n " ;
2022-08-11 17:33:29 +08:00
fileList < < " \\ section jkqtmathtext_supportedlatexsymbols_arrows Arrows \n " ;
2022-08-11 15:06:06 +08:00
fileList < < " The following table lists all arrow-typed symbols available in JKQTMathParser. They are defined in the node-class JKQTMathTextSymbolNode: \n " ;
fileList < < " <table> \n " ;
fileList < < " <tr> \n " ;
2022-08-11 17:33:29 +08:00
i = 1 ;
std : : sort ( symbolsAll . begin ( ) , symbolsAll . end ( ) , [ ] ( const QString & a , const QString & b ) { if ( a . contains ( " harpoon " ) & & ! b . contains ( " harpoon " ) ) return false ;
else if ( a . isLower ( ) & & b . isUpper ( ) ) return true ;
else if ( a . isUpper ( ) & & b . isLower ( ) ) return false ;
else return a < b ;
} ) ;
2022-08-11 15:06:06 +08:00
for ( const QString & arrow : arrowNames ) {
QString code = " " ;
2022-08-11 17:33:29 +08:00
for ( const QString & symbol : symbolsAll ) {
2022-08-11 15:06:06 +08:00
if ( symbol . size ( ) > 0 & & symbol . toLower ( ) . contains ( arrow ) & & symbol [ 0 ] . isLetter ( ) ) {
2022-08-11 17:33:29 +08:00
symbolsRemaining . remove ( symbol ) ;
2022-08-11 15:06:06 +08:00
QString symbol_lower ;
for ( const QChar & ch : symbol ) {
if ( ch . isUpper ( ) ) symbol_lower + = QString ( 2 , ch ) . toLower ( ) ;
else symbol_lower + = ch ;
}
2022-09-01 20:36:34 +08:00
for ( const QString & fnt : listsymbolsfonts ) {
latex . append ( " \\ " + symbol + " \\ vphantom{Iq} " ) ;
outputFilename . append ( " jkqtmathtext_greek_ " + symbol_lower + " _ " + fnt + " .png " ) ;
QMap < QString , QString > localoptions ;
localoptions [ " fontmathroman " ] = fnt ;
cmdoptions . append ( localoptions ) ;
}
fileList < < " <td><code> \\ \\ " < < symbol < < " </code>: \n " ;
fileList < < " <td> " ;
for ( int i = 0 ; i < listsymbolsfonts . size ( ) ; i + + ) {
if ( i > 0 ) fileList < < " " ;
fileList < < " \\ image html jkqtmathtext/symbols/ " < < outputFilename [ outputFilename . size ( ) - listsymbolsfonts . size ( ) + i ] < < " \n " ;
}
2022-08-11 15:06:06 +08:00
if ( i % 3 = = 0 ) {
fileList < < " </tr> \n <tr> \n " ;
}
i + + ;
}
}
}
fileList < < " </tr> " ;
fileList < < " </table> \n \n \n " ;
2022-08-11 17:33:29 +08:00
std : : sort ( symbolsAll . begin ( ) , symbolsAll . end ( ) , [ ] ( const QString & a , const QString & b ) { const QString al = a . toLower ( ) ; const QString bl = b . toLower ( ) ; if ( al = = bl ) { return a < b ; } else return al < bl ; } ) ;
fileList < < " \\ section jkqtmathtext_supportedlatexsymbols_bigmathop Big Math Operators \n " ;
fileList < < " The following table lists all math-operator symbols like \\ c \\ \\ sum, \\ \\ int, \\ \\ lim... that allow to over/underset sub-/superscript using \\ c \\ \\ limits (and \\ c \\ \\ nolimits ) available in JKQTMathParser. They are defined in the node-class JKQTMathTextSymbolNode: \n " ;
2022-08-11 15:06:06 +08:00
fileList < < " <table> \n " ;
fileList < < " <tr> \n " ;
i = 1 ;
2022-08-11 17:33:29 +08:00
{
for ( const QString & symbol : symbolsAll ) {
if ( symbol . size ( ) > 0 & & JKQTMathTextSymbolNode : : isSubSuperscriptBelowAboveSymbol ( symbol ) & & symbol [ 0 ] . isLetter ( ) ) {
symbolsRemaining . remove ( symbol ) ;
QString symbol_lower ;
for ( const QChar & ch : symbol ) {
if ( ch . isUpper ( ) ) symbol_lower + = QString ( 2 , ch ) . toLower ( ) ;
else symbol_lower + = ch ;
}
2022-08-11 21:11:38 +08:00
static QSet < QString > specialSymbols = QSet < QString > ( ) < < " lim " < < " liminf " < < " limsup " < < " arg " < < " argmin " < < " argmax " ;
2022-09-01 20:36:34 +08:00
QString code = " " ;
2022-08-11 21:11:38 +08:00
if ( JKQTMathTextSymbolNode : : getSymbolLength ( symbol ) > 1 & & ! specialSymbols . contains ( symbol ) ) {
2022-09-01 20:36:34 +08:00
code = " $ \\ " + symbol + " ( \\ cdot)$ " ;
2022-08-11 21:11:38 +08:00
} else {
if ( JKQTMathTextSymbolNode : : getSymbolLength ( symbol ) > 1 ) {
2022-09-01 20:36:34 +08:00
code = " $ \\ " + symbol + " \\ limits_{x \\ rightarrow \\ infty}f(x)$ " ;
2022-08-11 21:11:38 +08:00
} else {
2022-09-01 20:36:34 +08:00
code = " $ \\ " + symbol + " \\ limits_{x=0}^ \\ infty f(x)$ " ;
2022-08-11 21:11:38 +08:00
}
}
2022-09-01 20:36:34 +08:00
for ( const QString & fnt : listsymbolsfonts ) {
latex . append ( code + " \\ vphantom{Iq} " ) ;
outputFilename . append ( " jkqtmathtext_greek_ " + symbol_lower + " _ " + fnt + " .png " ) ;
QMap < QString , QString > localoptions ;
localoptions [ " fontmathroman " ] = fnt ;
cmdoptions . append ( localoptions ) ;
}
fileList < < " <td><code> \\ \\ " < < symbol < < " </code>: \n " ;
fileList < < " <td> " ;
for ( int i = 0 ; i < listsymbolsfonts . size ( ) ; i + + ) {
if ( i > 0 ) fileList < < " " ;
fileList < < " \\ image html jkqtmathtext/symbols/ " < < outputFilename [ outputFilename . size ( ) - listsymbolsfonts . size ( ) + i ] < < " \n " ;
}
2022-08-11 17:33:29 +08:00
if ( i % 3 = = 0 ) {
fileList < < " </tr> \n <tr> \n " ;
}
i + + ;
2022-08-11 15:06:06 +08:00
}
}
2022-08-11 17:33:29 +08:00
}
fileList < < " </tr> " ;
fileList < < " </table> \n \n \n " ;
2022-08-11 21:11:38 +08:00
fileList < < " \\ section jkqtmathtext_supportedlatexsymbols_mathspecialfunctions Math Special Functions \n " ;
2022-08-11 17:33:29 +08:00
fileList < < " The following table lists all remaining math-operator symbols like available in JKQTMathParser. They are defined in the node-class JKQTMathTextSymbolNode: \n " ;
fileList < < " <table> \n " ;
fileList < < " <tr> \n " ;
i = 1 ;
{
for ( const QString & symbol : symbolsAll ) {
2022-08-11 21:11:38 +08:00
if ( symbol . size ( ) > 0 & & symbolsRemaining . contains ( symbol ) & & JKQTMathTextSymbolNode : : isExtendedWidthSymbol ( symbol ) & & JKQTMathTextSymbolNode : : getSymbolLength ( symbol ) > 1 & & symbol [ 0 ] . isLetter ( ) ) {
2022-08-11 17:33:29 +08:00
symbolsRemaining . remove ( symbol ) ;
QString symbol_lower ;
for ( const QChar & ch : symbol ) {
if ( ch . isUpper ( ) ) symbol_lower + = QString ( 2 , ch ) . toLower ( ) ;
else symbol_lower + = ch ;
}
2022-09-01 20:36:34 +08:00
for ( const QString & fnt : listsymbolsfonts ) {
latex . append ( " $ \\ " + symbol + " ( \\ cdot)$ \\ vphantom{Iq} " ) ;
outputFilename . append ( " jkqtmathtext_greek_ " + symbol_lower + " _ " + fnt + " .png " ) ;
QMap < QString , QString > localoptions ;
localoptions [ " fontmathroman " ] = fnt ;
cmdoptions . append ( localoptions ) ;
}
fileList < < " <td><code> \\ \\ " < < symbol < < " </code>: \n " ;
fileList < < " <td> " ;
for ( int i = 0 ; i < listsymbolsfonts . size ( ) ; i + + ) {
if ( i > 0 ) fileList < < " " ;
fileList < < " \\ image html jkqtmathtext/symbols/ " < < outputFilename [ outputFilename . size ( ) - listsymbolsfonts . size ( ) + i ] < < " \n " ;
}
2022-08-11 17:33:29 +08:00
if ( i % 3 = = 0 ) {
fileList < < " </tr> \n <tr> \n " ;
}
i + + ;
2022-08-11 15:06:06 +08:00
}
}
2022-08-11 17:33:29 +08:00
}
fileList < < " </tr> " ;
fileList < < " </table> \n \n \n " ;
fileList < < " \\ section jkqtmathtext_supportedlatexsymbols_other Other Symbols \n " ;
fileList < < " The following table lists all other symbols that are available in JKQTMathParser. They are defined in the node-class JKQTMathTextSymbolNode: \n " ;
fileList < < " <table> \n " ;
fileList < < " <tr> \n " ;
i = 1 ;
2022-08-11 21:11:38 +08:00
QStringList symbolsRemainingL ;
for ( const QString & s : symbolsRemaining ) symbolsRemainingL . append ( s ) ;
2022-08-11 17:33:29 +08:00
std : : sort ( symbolsRemainingL . begin ( ) , symbolsRemainingL . end ( ) , [ ] ( const QString & a , const QString & b ) { const QString al = a . toLower ( ) ; const QString bl = b . toLower ( ) ; if ( al = = bl ) { return a < b ; } else return al < bl ; } ) ;
for ( const QString & symbol : symbolsRemainingL ) {
if ( symbol . size ( ) > 0 & & symbol [ 0 ] . isLetter ( ) ) {
2022-08-08 04:59:32 +08:00
QString symbol_lower ;
for ( const QChar & ch : symbol ) {
if ( ch . isUpper ( ) ) symbol_lower + = QString ( 2 , ch ) . toLower ( ) ;
else symbol_lower + = ch ;
}
2022-08-11 15:06:06 +08:00
const QString code = " \\ " + symbol + " \\ vphantom{Iq} " ;
2022-09-01 20:36:34 +08:00
for ( const QString & fnt : listsymbolsfonts ) {
latex . append ( code + " \\ vphantom{Iq} " ) ;
outputFilename . append ( " jkqtmathtext_greek_ " + symbol_lower + " _ " + fnt + " .png " ) ;
QMap < QString , QString > localoptions ;
localoptions [ " fontmathroman " ] = fnt ;
cmdoptions . append ( localoptions ) ;
}
fileList < < " <td><code> \\ \\ " < < symbol < < " </code>: \n " ;
fileList < < " <td> " ;
for ( int i = 0 ; i < listsymbolsfonts . size ( ) ; i + + ) {
if ( i > 0 ) fileList < < " " ;
fileList < < " \\ image html jkqtmathtext/symbols/ " < < outputFilename [ outputFilename . size ( ) - listsymbolsfonts . size ( ) + i ] < < " \n " ;
2022-08-11 15:06:06 +08:00
}
2022-08-08 04:13:31 +08:00
if ( i % 3 = = 0 ) {
fileList < < " </tr> \n <tr> \n " ;
}
i + + ;
}
}
fileList < < " </tr> " ;
2022-08-11 15:06:06 +08:00
fileList < < " </table> \n " ; fileList < < " */ \n " ;
2022-08-08 04:13:31 +08:00
}
} else if ( inputfile . size ( ) > 0 ) {
2022-08-08 00:00:05 +08:00
QFile f ( inputfile ) ;
if ( f . open ( QFile : : ReadOnly | QFile : : Text ) ) {
QString currentOutFile = " " ;
QString currentLatex = " " ;
QMap < QString , QString > currentOptions ;
bool isFile = true ;
bool beforeLatex = true ;
while ( ! f . atEnd ( ) ) {
2022-08-13 19:37:13 +08:00
QString line = f . readLine ( ) ;
while ( line . endsWith ( ' \n ' ) | | line . endsWith ( ' \r ' ) | | line . endsWith ( QChar ( 0x0 ) ) ) line = line . left ( line . size ( ) - 1 ) ;
const QString line_trimmed = line . trimmed ( ) ;
const QString line_simple = line_trimmed . simplified ( ) ;
2022-08-08 00:00:05 +08:00
if ( line_simple = = " --- " | | line_simple = = " ### " ) {
if ( currentOutFile . size ( ) > 0 ) {
outputFilename . append ( currentOutFile ) ;
latex . append ( currentLatex ) ;
cmdoptions . append ( currentOptions ) ;
isFile = true ;
beforeLatex = true ;
currentLatex = " " ;
currentOutFile = " " ;
currentOptions . clear ( ) ;
}
} else if ( isFile ) {
2022-08-13 19:37:13 +08:00
currentOutFile = line_trimmed ;
2022-08-08 00:00:05 +08:00
isFile = false ;
} else if ( beforeLatex ) {
2022-08-13 19:37:13 +08:00
if ( line_trimmed . startsWith ( " -- " ) ) {
QStringList commands = line_trimmed . right ( line_trimmed . size ( ) - 2 ) . split ( " -- " ) ;
2022-08-08 00:00:05 +08:00
for ( QString cmd : commands ) {
cmd = cmd . trimmed ( ) ;
QString cmdn = " " , param = " " ;
bool iscmd = true ;
for ( const QChar & ch : cmd ) {
if ( iscmd ) {
if ( ch = = ' = ' ) {
iscmd = false ;
} else {
cmdn + = ch ;
}
} else {
param + = ch ;
}
}
currentOptions [ cmdn . trimmed ( ) ] = param . trimmed ( ) ;
}
} else {
if ( currentLatex . size ( ) > 0 ) currentLatex + = " \n " ;
currentLatex + = line ;
}
beforeLatex = false ;
} else {
if ( currentLatex . size ( ) > 0 ) currentLatex + = " \n " ;
currentLatex + = line ;
}
}
f . close ( ) ;
if ( currentOutFile . size ( ) > 0 ) {
outputFilename . append ( currentOutFile ) ;
latex . append ( currentLatex ) ;
cmdoptions . append ( currentOptions ) ;
}
}
2022-08-08 04:13:31 +08:00
} else {
latex . append ( latex_cmdline ) ;
outputFilename . append ( outputFilename_cmdline ) ;
cmdoptions . append ( QMap < QString , QString > ( ) ) ;
2022-08-08 00:00:05 +08:00
}
if ( verbose ) {
std : : cout
< < " =========================================================== \n "
< < " = jkqtmathtext_render: " ;
2022-08-08 04:13:31 +08:00
if ( inputfile . size ( ) > 0 ) std : : cout < < " FILE-MODE (read from " < < inputfile . toStdString ( ) < < " ) \n " ;
else if ( listsymbols . size ( ) > 0 ) std : : cout < < " LIST-SYMBOLS-MODE (store to " < < listsymbols . toStdString ( ) < < " ) \n " ;
2022-08-08 00:00:05 +08:00
else std : : cout < < " COMMAND-LINE-MODE \n " ;
std : : cout < < " \n "
< < " =========================================================== \n " ;
}
for ( int i = 0 ; i < latex . size ( ) ; i + + ) {
if ( inputfile . size ( ) > 0 & & verbose ) {
std : : cout < < " \n +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ \n "
< < " + processing entry " < < ( i + 1 ) < < " / " < < latex . size ( ) < < " \n " ;
if ( cmdoptions [ i ] . size ( ) > 0 ) {
std : : cout < < " + additional command-line options: " ;
for ( const QString & key : cmdoptions [ i ] . keys ( ) ) {
std : : cout < < " -- " < < key . toStdString ( ) < < " = " < < cmdoptions [ i ] . value ( key ) . toStdString ( ) ;
}
std : : cout < < " \n " ;
}
}
QStringList fonts ;
QString mathFont = " " ;
processFont ( parser . value ( fontOption ) , fonts , mathFont ) ;
bool drawBoxes = parser . isSet ( drawBoxesOption ) ;
double fontsize = parser . value ( fontsizeOption ) . toDouble ( ) ;
int sizeincrease = parser . value ( sizeincreaseOption ) . toInt ( ) ;
int resolution_dpi = parser . value ( resolutionOption ) . toInt ( ) ;
QColor backgroundColor = jkqtp_String2QColor ( parser . value ( backgroundOption ) ) ;
QColor textColor = jkqtp_String2QColor ( parser . value ( textcolorOption ) ) ;
QString fontBlackboard = parser . value ( fontblackboardOption ) ;
QString fontRoman = parser . value ( fontRomanOption ) ;
QString fontSans = parser . value ( fontSansOption ) ;
QString fontMathRoman = parser . value ( fontMathRomanOption ) ;
QString fontMathSans = parser . value ( fontMathSansOption ) ;
QString fontFallbackSymbol = parser . value ( fontFallbackSymbolOption ) ;
QString fontFallbackSymbol_symbolencoding = parser . value ( fontFallbackSymbol_symbolencodingOption ) ;
QString fontTypewriter = parser . value ( fontTypewriterOption ) ;
QString fontScript = parser . value ( fontScriptOption ) ;
QString fontFraktur = parser . value ( fontFrakturOption ) ;
QString fontCaligraphic = parser . value ( fontcaligraphicOption ) ;
2022-08-10 18:12:30 +08:00
JKQTMathTextBlackboradDrawingMode fontBlackboardMode = String2JKQTMathTextBlackboradDrawingMode ( parser . value ( fontblackboardmodeOption ) ) ;
2022-09-01 20:36:34 +08:00
bool guiFonts = parser . isSet ( guifontsOption ) ;
2022-08-08 00:00:05 +08:00
if ( cmdoptions [ i ] . size ( ) > 0 ) {
for ( const QString & key : cmdoptions [ i ] . keys ( ) ) {
2022-08-10 18:12:30 +08:00
if ( key = = " drawboxes " | | key = = " showboxes " ) drawBoxes = true ;
2022-09-01 20:36:34 +08:00
else if ( key = = " nodrawboxes " | | key = = " noshowboxes " ) drawBoxes = false ;
else if ( key = = " guifonts " ) guiFonts = true ;
else if ( key = = " noguifonts " ) guiFonts = false ;
2022-08-08 00:00:05 +08:00
else if ( key = = " fontsize " ) fontsize = cmdoptions [ i ] . value ( key ) . toDouble ( ) ;
else if ( key = = " sizeincrease " ) sizeincrease = cmdoptions [ i ] . value ( key ) . toInt ( ) ;
else if ( key = = " background " ) backgroundColor = jkqtp_String2QColor ( cmdoptions [ i ] . value ( key ) ) ;
else if ( key = = " textcolor " ) textColor = jkqtp_String2QColor ( cmdoptions [ i ] . value ( key ) ) ;
else if ( key = = " fontblackboard " ) fontBlackboard = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " font " ) processFont ( cmdoptions [ i ] . value ( key ) , fonts , mathFont ) ;
else if ( key = = " fontroman " ) fontRoman = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fontsans " ) fontSans = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fontmathroman " ) fontMathRoman = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fontmathsans " ) fontMathSans = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fonttypewriter " ) fontTypewriter = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fontfallbacksymbol " ) fontFallbackSymbol = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fontfallbacksymbol_symbolencoding " ) fontFallbackSymbol_symbolencoding = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fontscript " ) fontScript = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fontcaligraphic " ) fontCaligraphic = cmdoptions [ i ] . value ( key ) ;
else if ( key = = " fontfraktur " ) fontFraktur = cmdoptions [ i ] . value ( key ) ;
2022-08-10 18:12:30 +08:00
else if ( key = = " fontblackboardmode " ) fontBlackboardMode = String2JKQTMathTextBlackboradDrawingMode ( cmdoptions [ i ] . value ( key ) ) ;
else {
std : : cerr < < " unknown command-line option -- " < < key . toStdString ( ) < < " in inputfile \n " ;
}
2022-08-08 00:00:05 +08:00
}
}
// 2. now we create a JKQTMathText object and configure it
JKQTMathText mathText ;
if ( fonts . size ( ) = = 1 ) {
mathText . useAnyUnicode ( fonts [ 0 ] , mathText . getFontSans ( ) ) ;
} else if ( fonts . size ( ) = = 2 ) {
mathText . useAnyUnicode ( fonts [ 0 ] , fonts [ 1 ] ) ;
} else if ( fonts . size ( ) = = 4 ) {
mathText . useAnyUnicodeForTextOnly ( fonts [ 0 ] , fonts [ 1 ] ) ;
mathText . useAnyUnicodeForMathOnly ( fonts [ 2 ] , fonts [ 3 ] ) ;
}
if ( mathFont . toUpper ( ) = = " XITS " ) mathText . useXITS ( true ) ;
else if ( mathFont . toUpper ( ) = = " XITS_MATHANDTEXT " ) mathText . useXITS ( false ) ;
if ( mathFont . toUpper ( ) = = " STIX " ) mathText . useSTIX ( true ) ;
else if ( mathFont . toUpper ( ) = = " STIX_MATHANDTEXT " ) mathText . useSTIX ( false ) ;
if ( mathFont . toUpper ( ) = = " ASANA " ) mathText . useASANA ( true ) ;
else if ( mathFont . toUpper ( ) = = " ASANA_MATHANDTEXT " ) mathText . useASANA ( false ) ;
2022-09-01 20:36:34 +08:00
if ( mathFont . toUpper ( ) = = " FIRA " ) mathText . useFiraMath ( true ) ;
else if ( mathFont . toUpper ( ) = = " FIRA_MATHANDTEXT " ) mathText . useFiraMath ( false ) ;
2022-08-08 00:00:05 +08:00
if ( fontRoman . size ( ) > 0 ) mathText . setFontRoman ( fontRoman , MTFEUnicode ) ;
if ( fontSans . size ( ) > 0 ) mathText . setFontSans ( fontSans , MTFEUnicode ) ;
if ( fontMathRoman . size ( ) > 0 ) {
if ( fontMathRoman . toUpper ( ) = = " XITS " ) mathText . useXITS ( true ) ;
else if ( fontMathRoman . toUpper ( ) = = " STIX " ) mathText . useSTIX ( true ) ;
else if ( fontMathRoman . toUpper ( ) = = " ASANA " ) mathText . useASANA ( true ) ;
2022-09-01 20:36:34 +08:00
else if ( fontMathRoman . toUpper ( ) = = " FIRA " ) mathText . useFiraMath ( true ) ;
else if ( fontMathRoman . toUpper ( ) = = " XITS_MATHANDTEXT " ) mathText . useXITS ( false ) ;
else if ( fontMathRoman . toUpper ( ) = = " STIX_MATHANDTEXT " ) mathText . useSTIX ( false ) ;
else if ( fontMathRoman . toUpper ( ) = = " ASANA_MATHANDTEXT " ) mathText . useASANA ( false ) ;
else if ( fontMathRoman . toUpper ( ) = = " FIRA_MATHANDTEXT " ) mathText . useFiraMath ( false ) ;
2022-08-08 00:00:05 +08:00
else mathText . setFontMathRoman ( fontMathRoman , MTFEUnicode ) ;
}
if ( fontMathSans . size ( ) > 0 ) mathText . setFontMathSans ( fontMathSans , MTFEUnicode ) ;
if ( fontTypewriter . size ( ) > 0 ) mathText . setFontTypewriter ( fontTypewriter , MTFEUnicode ) ;
if ( fontScript . size ( ) > 0 ) mathText . setFontScript ( fontScript , MTFEUnicode ) ;
if ( fontCaligraphic . size ( ) > 0 ) mathText . setFontCaligraphic ( fontCaligraphic , MTFEUnicode ) ;
if ( fontFraktur . size ( ) > 0 ) mathText . setFontFraktur ( fontFraktur , MTFEUnicode ) ;
if ( fontFallbackSymbol . size ( ) > 0 ) mathText . setFallbackFontSymbols ( fontFallbackSymbol , MTFEUnicode ) ;
if ( fontFallbackSymbol_symbolencoding . size ( ) > 0 ) mathText . setFallbackFontSymbols ( fontFallbackSymbol_symbolencoding , MTFEWinSymbol ) ;
if ( fontBlackboard . size ( ) > 0 ) {
mathText . setFontBlackboard ( fontBlackboard , MTFEUnicode ) ;
}
2022-08-10 18:12:30 +08:00
mathText . setFontBlackboradMode ( fontBlackboardMode ) ;
2022-08-08 00:00:05 +08:00
mathText . setFontSize ( fontsize ) ;
mathText . setFontColor ( textColor ) ;
2022-09-01 20:36:34 +08:00
if ( guiFonts ) {
mathText . useGuiFonts ( ) ;
}
2022-08-08 00:00:05 +08:00
// 3. now we parse some LaTeX code
QElapsedTimer timer ;
timer . start ( ) ;
mathText . parse ( latex [ i ] ) ;
const double durParseMS = static_cast < double > ( timer . nsecsElapsed ( ) ) / 1.0e6 ;
if ( mathText . hadErrors ( ) ) {
std : : cerr < < " ERRORS while parsing LaTeX: \n "
< < " ----------------------------------------------------------- \n "
< < latex [ i ] . toStdString ( ) < < " \n "
< < " ----------------------------------------------------------- \n "
< < mathText . getErrorList ( ) . join ( " \n " ) . toStdString ( ) < < " \n "
2022-08-13 21:32:31 +08:00
< < " ----------------------------------------------------------- \n "
2022-08-20 22:19:40 +08:00
< < " RENDERTREE: \n " < < JKQTMathTextNodeTree2String ( mathText . getNodeTree ( ) ) . toStdString ( )
2022-08-13 21:32:31 +08:00
< < " ----------------------------------------------------------- \n "
2022-08-08 00:00:05 +08:00
;
} else if ( verbose ) {
std : : cout < < " parsing LaTeX: OK \n "
< < " parsing duration: " < < durParseMS < < " ms \n "
< < " ----------------------------------------------------------- \n "
< < latex [ i ] . toStdString ( ) < < " \n "
2022-08-13 21:32:31 +08:00
< < " ----------------------------------------------------------- \n "
2022-08-20 22:19:40 +08:00
< < " RENDERTREE: \n " < < JKQTMathTextNodeTree2String ( mathText . getNodeTree ( ) ) . toStdString ( )
2022-08-08 00:00:05 +08:00
< < " ----------------------------------------------------------- \n " ;
}
// 4. now we draw the result into a QPixmap
timer . start ( ) ;
const QImage pix = mathText . drawIntoImage ( drawBoxes , backgroundColor , sizeincrease , 1.0 , resolution_dpi ) ;
const double durRenderMS = static_cast < double > ( timer . nsecsElapsed ( ) ) / 1.0e6 ;
if ( verbose ) std : : cout < < " rendering into QImage " < < pix . width ( ) < < " x " < < pix . height ( ) < < " pixels \n "
< < " rendering duration: " < < durRenderMS < < " ms \n "
< < " rendering resolution: " < < pix . dotsPerMeterX ( ) / ( 1000.0 / 25.4 ) < < " x " < < pix . dotsPerMeterY ( ) / ( 1000.0 / 25.4 ) < < " dpi \n "
< < " devicepixelratio: " < < pix . devicePixelRatioF ( ) < < " \n "
;
// 5. before ending the application, we store the result into a file
const QString outname = outputDir . absoluteFilePath ( outputFilename [ i ] ) ;
if ( QFileInfo : : exists ( outname ) ) QFile : : remove ( outname ) ;
if ( ! pix . save ( outname ) ) {
2022-08-13 19:37:13 +08:00
std : : cerr < < " ERROR storing to " < < outname . toStdString ( ) < < " , fileExists= " < < std : : boolalpha < < QFileInfo : : exists ( outname ) < < " permissions=0x " < < std : : hex < < QFileInfo ( outname ) . permissions ( ) < < " \n " ;
2022-08-08 00:00:05 +08:00
} else {
if ( verbose ) std : : cout < < " stored to " < < outname . toStdString ( ) < < " \n "
< < " size " < < static_cast < double > ( QFileInfo ( outname ) . size ( ) ) / 1024.0 < < " kBytes \n " ;
}
}
return EXIT_SUCCESS ;
}