NEW: JKQTMathText::parse() by default allows linebreaks in the LaTeX string to be parsed. This can be switched off by a parameter

NEW: TabSize can be set in JKQTMathTextVerbatimNode
This commit is contained in:
jkriege2 2022-08-13 13:37:13 +02:00
parent c58fc985ce
commit ce6637fb4b
27 changed files with 199 additions and 91 deletions

View File

@ -55,14 +55,20 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>IMPROVED/REWORKED rendering of text in text- and math-mode. Now it is more consistent with the output of LaTeX itself</li>
<li>IMPROVED/REWORKED rendering of blackboard font: now several different rendering modes can be selected using JKQTMathText::setFontBlackboradMode()</li>
<li>BREAKING/REWORKED: The \\verb!...!-command now works the same as in LaTeX</li>
<li>NEW: now supports new decoration instructions: \c \\cancel, \c \\xcancel, \c \\bcancel, \c \\sout, \c \\ocirc, \c \\widetilde, \c \\widehat, \c \\breve</li>
<li>NEW: JKQTMathTextVerticalListNode allows to typeset a vertical list of lines</li>
<li>NEW: JKQTMathText::parse() by default allows linebreaks in the LaTeX string to be parsed. This can be switched off by a parameter</li>
<li>NEW: added functions to set the font-size in pixels (as alternative to the existing functions that set them in points), implements request <a href="https://github.com/jkriege2/JKQtPlotter/issues/76">#76</a> from <a href="https://github.com/igormironchik">user:igormironchik</a> </li>
<li>NEW: reworked drawing of decorations: improved appearance and positioning!</li>
<li>NEW: additional method JKQTMathtext::getSizeDetail() that returns all size-properties as a convenient struct, also added matching varinat JKQTMathTextNode::getSize() </li>
<li>NEW: additional method JKQTMathtext::drawIntoPixmap(), JKQTMathtext::drawIntoPicture(), JKQTMathtext::drawIntoImage() which returns a QPixmap, QPicture and QImage respectively that contains the render result of the currently parsed markup</li>
<li>NEW: array/tabular-environments have limited support for formatting string like \c l|r|c and for \c \\hline , \c \\hdashline , \c \\toprule , \c \\midrule , \c \\bottomrule</li>
<li>NEW: reworked code structure: broke up large, single CPP-files into several smaller files!</li>
<li>NEW: reworked node class tree: inserted base-class nodes for single-child, dual-child!</li>
<li>NEW: improved frac-rendering: font-scaling takes nesting-level into account, overall-rendering, sizes, if a brace surrounds a frac, the heights are equal above and below to center the brace , ...</li>
<li>NEW: shows strikeoutPos when drawing Debug-Boxes</li>
<li>NEW: LaTeX-Parser understands optional instruction parameters in [...] now</li>
<li>NEW: LaTeX-Parser simplifies parse-tree to increase speed of execution</li>
<li>NEW: added new decoration instructions: \c \\cancel, \c \\xcancel, \c \\bcancel, \c \\sout, \c \\ocirc, \c \\widetilde, \c \\widehat, \c \\breve</li>
<li>NEW: \c \\limits and \c \\nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)</li>
<li>NEW: added top-corner (\c \\ulcorner/\c \\urcorner ) and bottom-corner brackets (\c \\llcorner/\c \\lrcorner )</li>
<li>NEW: added \c \\overbracket and \c \\underbracket</li>
@ -74,10 +80,8 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: added \c \\acute{X}, \c \\grave{X}, \c \\acute{X}</li>
<li>NEW: added \c \\dashuline{X}, \c \\dotuline{X}</li>
<li>NEW: added \c \\underleftarrow{X}, \c \\underrightarrow{X}, \c \\underleftrightarrow{X}, \c \\overleftarrow{X}, \c \\overrightarrow{X}, \c \\overleftrightarrow{X}</li>
<li>NEW: added functions to set the font-size in pixels (as alternative to the existing functions that set them in points), implements request <a href="https://github.com/jkriege2/JKQtPlotter/issues/76">#76</a> from <a href="https://github.com/igormironchik">user:igormironchik</a> </li>
<li>NEW: added \c \\userfont{SystemFontName}{Text} instruction</li>
<li>NEW: added \c \\unicode{HEX} and \c \\utfeight{HEX} instruction to draw unicide characters by code</li>
<li>NEW: JKQTMathTextVerticalListNode allows to typeset a vertical list of lines</li>
<li>NEW: added \c \\substack[lcr]{...\\\\...} , \c \\lsubstack{...\\\\...} , \c \\rsubstack{...\\\\...} instructions</li>
<li>NEW: added \c \\phantom{xXy} , \c \\vphantom{xXy} and \c \\hphantom{xXy} instructions for whitespaces with the size of \c xXy </li>
<li>NEW: added support for flushleft/flushright/center-environments with linebreaks</li>
@ -86,10 +90,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: added support for \c \\char\"HEX , \c \\char\'OCTAL and \c \\charDECIMAL for inserting any uicode character code</li>
<li>NEW: added support for \\bigl,\\bigr,\\Bigr,... commands for fixed-size but enlarged paramtheses</li>
<li>NEW: added support for \\begin{verbatim}...\\end{verbatim}, \\begin{verbatim*}...\\end{verbatim*}</li>
<li>NEW: additional method JKQTMathtext::getSizeDetail() that returns all size-properties as a convenient struct, also added matching varinat JKQTMathTextNode::getSize() </li>
<li>NEW: additional method JKQTMathtext::drawIntoPixmap(), JKQTMathtext::drawIntoPicture(), JKQTMathtext::drawIntoImage() which returns a QPixmap, QPicture and QImage respectively that contains the render result of the currently parsed markup</li>
<li>NEW: added command line tool \ref JKQTMathTextRenderCmdLineTool that renders LaTeX into images, using it to generate the documentation images for JKQTMathText</li>
<li>NEW: array/tabular-environments have limited support for formatting string like \c l|r|c and for \c \\hline , \c \\hdashline , \c \\toprule , \c \\midrule , \c \\bottomrule</li>
</ul></li>
</ul>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -3,23 +3,23 @@ jkqtmathtext_verb.png
\verb!\LaTeX{} is not pares inside \verb~..~! outside {\backslash}verb
---
jkqtmathtext_verbatim.png
outside\begin{verbatim}
outside -- \begin{verbatim}
inside \LaTeX verbatim
2nd verbaimline
2nd verbaimline
3rd line
\end{verbatim}
---
jkqtmathtext_lstlisting.png
outside\begin{lstlisting}
outside -- \begin{lstlisting}
int main() {
printf("Hello World\n");
printf("Hello World\n");
}
\end{lstlisting}
---
jkqtmathtext_verbatimast.png
outside\begin{verbatim*}
outside -- \begin{verbatim*}
inside \LaTeX verbatim
2nd verbaimline
2nd verbaimline
3rd line
\end{verbatim*}

View File

@ -3,6 +3,7 @@
#include <QDebug>
#include <sstream>
#include "jkqtcommon/jkqtpstringtools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtmathtext/nodes/jkqtmathtexttextnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextbracenode.h"
#include "jkqtmathtext/nodes/jkqtmathtextdecoratednode.h"
@ -26,7 +27,7 @@ TestForm::TestForm(QWidget *parent) :
const QString testTextUmla="\\\"Aq{\\\"u}\\\"{a}t{\\oe}r00, 123-45+6.0\\%\\S";
const QString umla_math="\\ddot{A}\\ddot{a}\\grave{A}\\grave{a}\\acute{A}\\acute{a}\\hat{A}\\hat{a}\\tilde{A}\\tilde{a}\\r{A}\\r{a}\\u{A}\\u{a}\\bar{A}\\bar{a}\\AA\\aa{\\AE}{\\ae}\\check{C}\\check{c}\\ddot{E}\\ddot{e}\\dot{e}\\L\\l\\ddot{O}\\ddot{o}\\grave{O}\\grave{o}\\acute{O}\\acute{o}\\hat{O}\\hat{o}\\tilde{O}\\tilde{o}\\O\\o{\\OE}{\\ae}\\check{S}\\check{s}\\ss\\ddot{U}\\ddot{u}\\grave{U}\\grave{u}\\acute{U}\\acute{u}\\hat{U}\\hat{u}\\tilde{U}\\tilde{u}";
const QString testTextUmla_math="\\ddot{A}q{\\ddot{u}}\\ddot{{}a}t{\\oe}r00, 123-45+6.0\\%\\S";
ui->cmbTestset->addItem("text: fonts", "rm: \\textrm{"+testText+"}, sf: \\textsf{"+testText+"}, tt: \\texttt{"+testText+"}, cal: \\textcal{"+testText+"}, scr: \\textscr{"+testText+"}, bb: \\textbb{"+testText+"}, frak: \\textfrak{"+testText+"}, ");
ui->cmbTestset->addItem("text: fonts", "rm: \\textrm{"+testText+"},\\\\sf: \\textsf{"+testText+"},\\\\tt: \\texttt{"+testText+"},\\\\cal: \\textcal{"+testText+"},\\\\scr: \\textscr{"+testText+"},\\\\bb: \\textbb{"+testText+"},\\\\frak: \\textfrak{"+testText+"}");
ui->cmbTestset->addItem("text/math: font comparison",
"\\begin{matrix}\n"
" text: & abc123+d/e\\\\\n"
@ -530,7 +531,7 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
ti->addChild(createTree(list[i], ti));
}
} else if (lstNV) {
name=QString("VerticalListNode (align=%1, spacingFactor=%2x, spacingMode=%3, verticalOrientation=%4)").arg(JKQTMathTextHorizontalAlignment2String(lstNV->getAlignment())).arg(lstNV->getLineSpacingFactor()).arg(lstNV->SpacingMode2String(lstNV->getSpacingMode())).arg(JKQTMathTextVerticalOrientation2String(lstNV->getVerticalOrientation()));
name=QString("VerticalListNode (align=%1, spacingFactor=%2x, spacingMode=%3, verticalOrientation=%4)").arg(JKQTMathTextHorizontalAlignment2String(lstNV->getAlignment())).arg(lstNV->getLineSpacingFactor()).arg(JKQTMathTextLineSpacingMode2String(lstNV->getSpacingMode())).arg(JKQTMathTextVerticalOrientation2String(lstNV->getVerticalOrientation()));
QList<JKQTMathTextNode*> list=lstNV->getChildren();
for (int i=0; i<list.size(); i++) {
ti->addChild(createTree(list[i], ti));

View File

@ -1496,13 +1496,13 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
if (parseString[currentTokenID]!='{') error_list.append(tr("error @ ch. %1: didn't find '{' after '\\begin'").arg(currentTokenID)); // find closing brace '}' after '\\begin{name');
currentTokenName=readUntil(true, "}");
if (currentTokenName=="verbatim") {
currentTokenName=readUntil(true, "\\end{verbatim}");
currentTokenName=readUntil(true, "\\end{verbatim}", true);
return currentToken=MTTinstructionVerbatim;
} else if (currentTokenName=="verbatim*") {
currentTokenName=readUntil(true, "\\end{verbatim*}");
currentTokenName=readUntil(true, "\\end{verbatim*}", true);
return currentToken=MTTinstructionVerbatimVisibleSpace;
} else if (currentTokenName=="lstlisting") {
currentTokenName=readUntil(true, "\\end{lstlisting}");
currentTokenName=readUntil(true, "\\end{lstlisting}", true);
return currentToken=MTTinstructionVerbatim;
}
return currentToken=MTTinstructionBegin;
@ -1904,24 +1904,14 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
JKQTMathTextHorizontalAlignment alignment=MTHALeft;
if (envname=="document") alignment=MTHALeft;
else alignment=String2JKQTMathTextHorizontalAlignment(envname);
JKQTMathTextVerticalListNode* vlist = new JKQTMathTextVerticalListNode(this, alignment, 1.0, JKQTMathTextVerticalListNode::SMDefault, MTVOFirstLine );
nl->addChild(vlist);
bool first=true;
while (first || currentToken==MTTinstructionNewline) {
vlist->addChild(parseLatexString(true, MTBTAny, envname));
first=false;
}
nl->addChild(parseMultilineLatexString(true, envname, alignment, 1.0, MTSMDefaultSpacing, MTVOFirstLine));
} else if (envname=="framed" || envname=="shaded" || envname=="snugshade") {
JKQTMathTextHorizontalAlignment alignment=MTHALeft;
JKQTMathTextVerticalListNode* vlist = new JKQTMathTextVerticalListNode(this, alignment, 1.0, JKQTMathTextVerticalListNode::SMDefault, MTVOFirstLine );
JKQTMathTextVerticalListNode* vlist = parseMultilineLatexString(true, envname, alignment, 1.0, MTSMDefaultSpacing, MTVOFirstLine);
QStringList color;
color<<jkqtp_QColor2String(Qt::lightGray);
nl->addChild(new JKQTMathTextBoxInstructionNode(this, envname, vlist, color));
bool first=true;
while (first || currentToken==MTTinstructionNewline) {
vlist->addChild(parseLatexString(true, MTBTAny, envname));
first=false;
}
} else {
error_list.append(tr("error @ ch. %1: unknown environment '%2'").arg(currentTokenID).arg(envname));
}
@ -1954,6 +1944,18 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
return simplifyJKQTMathTextNode(nl);
}
JKQTMathTextVerticalListNode *JKQTMathText::parseMultilineLatexString(bool get, const QString &quitOnEnvironmentEnd, JKQTMathTextHorizontalAlignment _alignment, double _linespacingFactor, JKQTMathTextLineSpacingMode spacingMode_, JKQTMathTextVerticalOrientation _verticalOrientation)
{
JKQTMathTextVerticalListNode* vlist = new JKQTMathTextVerticalListNode(this, _alignment, _linespacingFactor, spacingMode_, _verticalOrientation );
bool first=true;
while (first || currentToken==MTTinstructionNewline) {
vlist->addChild(simplifyAndTrimJKQTMathTextNode(parseLatexString(true, MTBTAny, quitOnEnvironmentEnd)));
first=false;
}
return vlist;
}
JKQTMathTextNode* JKQTMathText::parseInstruction(bool *_foundError, bool* getNew) {
static QHash<QString,double> big_instructions_family;
if (big_instructions_family.size()==0) {
@ -2099,13 +2101,7 @@ JKQTMathTextNode* JKQTMathText::parseInstruction(bool *_foundError, bool* getNew
getToken();
}
if (currentToken==MTTopenbrace) {
JKQTMathTextVerticalListNode* vlist = new JKQTMathTextVerticalListNode(this, alignment, 1.0, JKQTMathTextVerticalListNode::SMMinimal, MTVOFirstLine );
child=vlist;
bool first=true;
while (first || currentToken==MTTinstructionNewline) {
vlist->addChild(parseLatexString(true));
first=false;
}
child=parseMultilineLatexString(true, "", alignment, 1.0, MTSMMinimalSpacing, MTVOFirstLine);
if (currentToken!=MTTclosebrace) error_list.append(tr("error @ ch. %1: didn't find closing brace '}' after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
} else {
error_list.append(tr("error @ ch. %1: expected one argument in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
@ -2243,7 +2239,7 @@ QString JKQTMathText::parseSingleString(bool get) {
return thisparam;
}
QString JKQTMathText::readUntil(bool get, const QString &endsequence)
QString JKQTMathText::readUntil(bool get, const QString &endsequence, bool removeFirstlineWhitespace)
{
if (get) currentTokenID++;
QString seq;
@ -2255,6 +2251,31 @@ QString JKQTMathText::readUntil(bool get, const QString &endsequence)
if (seq.endsWith(endsequence)) {
seq=seq.left(seq.size()-endsequence.size());
}
if (removeFirstlineWhitespace) {
QStringList sl=seq.split('\n');
if (sl.size()>0) {
bool allWS=true;
for (const QChar& ch: sl.first()) {
if (!ch.isSpace()) {
allWS=false;
break;
}
}
if (allWS) sl.removeFirst();
}
if (sl.size()>0) {
bool allWS=true;
for (const QChar& ch: sl.last()) {
if (!ch.isSpace()) {
allWS=false;
break;
}
}
if (allWS) sl.removeLast();
}
seq=sl.join("\n");
}
return seq;
}
@ -2267,7 +2288,7 @@ JKQTMathTextNode *JKQTMathText::getParsedNode() const {
bool JKQTMathText::parse(const QString& text, bool addSpaceBeforeAndAfter){
bool JKQTMathText::parse(const QString& text, bool addSpaceBeforeAndAfter, bool allowLinebreaks){
QString ntext;
if (addSpaceBeforeAndAfter) ntext=QString("\\;")+text+QString("\\;");
else ntext=text;
@ -2285,7 +2306,11 @@ bool JKQTMathText::parse(const QString& text, bool addSpaceBeforeAndAfter){
lastLineCount.clear();
error_list.clear();
parsedNode=parseLatexString(true);
if (allowLinebreaks) {
parsedNode=parseMultilineLatexString(true, QString(""), MTHALeft, 1.0, MTSMDefaultSpacing, MTVOFirstLine);
} else {
parsedNode=parseLatexString(true);
}
unparsedNode=new JKQTMathTextVerbatimNode(this, text);
return (parsedNode!=nullptr);
}

View File

@ -43,6 +43,7 @@
class JKQTMathTextNode; // forward
class JKQTMathTextVerticalListNode; // forward
/*! \brief this class parses a LaTeX string and can then draw the contained text/equation onto a <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a>
\ingroup jkqtmathtext_render
@ -213,8 +214,14 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
void loadSettings(const QSettings& settings, const QString& group=QString("mathtext/"));
/** \brief store the object settings to the given QSettings object with the given name prefix */
void saveSettings(QSettings& settings, const QString& group=QString("mathtext/")) const;
/** \brief parse the given enhanced string. If \c addSpaceBeforeAndAfter==true a little bit of space is added before and after the text. Returns \c true on success. */
bool parse(const QString &text, bool addSpaceBeforeAndAfter=false);
/** \brief parse the given LaTeX string.
*
* \param addSpaceBeforeAndAfter If \ctrue a little bit of space is added before and after the text.
* \param allowLinebreaks If \c true , linebreak (i.e. \c \\ or \c \\newline ) are allowed, otherwise a single line wihtout such linebreak commands is expected
*
* \returns \c true on success.
*/
bool parse(const QString &text, bool addSpaceBeforeAndAfter=false, bool allowLinebreaks=true);
/** \brief get the size of the drawn representation. returns an invalid size if no text has been parsed. */
QSizeF getSize(QPainter& painter);
/** \brief return the descent, i.e. the distance from the baseline to the lowest part of the representation */
@ -923,6 +930,18 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
* \param quitOnClosingBracket if \c true, quits on encountering a MTTclosebracket token
*/
JKQTMathTextNode* parseLatexString(bool get, JKQTMathTextBraceType quitOnClosingBrace=JKQTMathTextBraceType::MTBTAny, const QString& quitOnEnvironmentEnd=QString(""), bool quitOnClosingBracket=false);
/** \brief parse a LaTeX string with linebreaks
*
* \param get if \c true this calls getToken()
* \param quitOnEnvironmentEnd wuit if \c \\end{quitOnEnvironmentEnd} is found
* \param _alignment horizontal alignment of the JKQTMathTextVerticalListNode \see JKQTMathTextVerticalListNode::alignment and JKQTMathTextHorizontalAlignment
* \param _linespacingFactor line spacing factor of the lines \see JKQTMathTextVerticalListNode::linespacingFactor
* \param spacingMode_ spacing mode/algorithm for the lines \see JKQTMathTextLineSpacingMode and JKQTMathTextLineSpacingMode
* \param _verticalOrientation vertical orientation of the block of all lines, see JKQTMathTextVerticalListNode::verticalOrientation and JKQTMathTextVerticalOrientation
*
* \returns JKQTMathTextVerticalListNode with the lines as children
*/
JKQTMathTextVerticalListNode *parseMultilineLatexString(bool get, const QString& quitOnEnvironmentEnd=QString(""), JKQTMathTextHorizontalAlignment _alignment=MTHALeft, double _linespacingFactor=1.0, JKQTMathTextLineSpacingMode spacingMode_=MTSMDefaultSpacing, JKQTMathTextVerticalOrientation _verticalOrientation=MTVOFirstLine);
/** \brief parses a list of string-arguments, i.e. \c {p1}{p2}{...}
*
* \param get call getToken() at the start, otherwise it is expected that currentToken==MTTopenbrace
@ -937,9 +956,10 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
*
* \param get if \c true the functions begins by reading a new character, otherwise the current character is used as first character
* \param endsequence the sequence, ending the read
* \param removeFirstlineWhitespace if \c true the returned string does not contain the first whitespace-line and a possible trailing whitespace line
* \return the read string, excluding the \a endsequence
*/
QString readUntil(bool get, const QString& endsequence);
QString readUntil(bool get, const QString& endsequence, bool removeFirstlineWhitespace=false);
/** \brief parses a single instruction (including it's parameters)
*
* \param[out] _foundError will be set to \c true if an error occured (unexpected token) or \c false otherwise

View File

@ -892,3 +892,21 @@ void JKQTMathTextDrawStringSimBlackboard(QPainter &painter, const QFont &f, cons
path.addText(QPointF(x+fm.lineWidth()/2.0, y), f, txt);
painter.drawPath(path);
}
QString JKQTMathTextLineSpacingMode2String(JKQTMathTextLineSpacingMode mode)
{
switch(mode) {
case MTSMMinimalSpacing: return "minimal";
default:
case MTSMDefaultSpacing: return "default";
}
}
JKQTMathTextLineSpacingMode String2JKQTMathTextLineSpacingMode(QString tokenName)
{
tokenName=tokenName.toLower().trimmed();
if (tokenName=="default") return MTSMDefaultSpacing;
if (tokenName=="minimal" || tokenName=="min" || tokenName=="minimum") return MTSMMinimalSpacing;
return MTSMDefaultSpacing;
}

View File

@ -469,7 +469,7 @@ JKQTMATHTEXT_LIB_EXPORT JKQTMathTextHorizontalAlignment String2JKQTMathTextHoriz
*
* \image html jkqtmathtext_verticalorientation.png
*
* \see JKQTMathTextVerticalOrientation2String(), String2JKQTMathTextVerticalOrientation(), JKQTMathTextVerticalListNode
* \see JKQTMathTextVerticalOrientation2String(), String2JKQTMathTextVerticalOrientation(), JKQTMathTextVerticalListNode, JKQTMathTextVerbatimNode
*/
enum JKQTMathTextVerticalOrientation {
MTVOTop, /*!< \brief baseline of the whole block is at the top of the first */
@ -481,14 +481,43 @@ enum JKQTMathTextVerticalOrientation {
/** \brief convert a JKQTMathTextVerticalOrientation into a QString
* \ingroup jkqtmathtext_tools
*
* \see JKQTMathTextVerticalOrientation2String(), String2JKQTMathTextVerticalOrientation(), JKQTMathTextVerticalListNode, JKQTMathTextVerbatimNode
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextVerticalOrientation2String(JKQTMathTextVerticalOrientation mode);
/** \brief returns the JKQTMathTextVerticalOrientation corresponding to \a instructionName
* \ingroup jkqtmathtext_tools
*
* \see JKQTMathTextVerticalOrientation2String(), String2JKQTMathTextVerticalOrientation(), JKQTMathTextVerticalListNode, JKQTMathTextVerbatimNode
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerticalOrientation String2JKQTMathTextVerticalOrientation(QString mode);
/** \brief defines, how lines are beeing spaced by the node
* \ingroup jkqtmathtext_tool
*
* \image html jkqtmathtext_verticallist.png
*
* \see JKQTMathTextLineSpacingMode2String(), String2JKQTMathTextLineSpacingMode(), JKQTMathTextVerticalListNode
*/
enum JKQTMathTextLineSpacingMode {
MTSMDefaultSpacing, /*!< space the lines with equilibrated spacing, i.e. the baselines are at least \c QFontMetricsF::lineSpacing()*JKQTMathTextVerticalListNode::lineSpacingFactor apart, but even more, if the height of the text bloxk is larger than the the font's ascent+descent */
MTSMMinimalSpacing /*!< space the lines as tight as possible, i.e. each line is separated by \c QFontMetricsF::leading()*JKQTMathTextVerticalListNode::lineSpacingFactor from the next line. This is a s compact as possible */
};
/** \brief convert a SpacingMode to a String
* \ingroup jkqtmathtext_tools
*
* \see JKQTMathTextLineSpacingMode2String(), String2JKQTMathTextLineSpacingMode(), JKQTMathTextVerticalListNode
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextLineSpacingMode2String(JKQTMathTextLineSpacingMode mode);
/** \brief convert a String to a SpacingMode
* \ingroup jkqtmathtext_tools
*
* \see JKQTMathTextLineSpacingMode2String(), String2JKQTMathTextLineSpacingMode(), JKQTMathTextVerticalListNode
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextLineSpacingMode String2JKQTMathTextLineSpacingMode(QString mode);
#endif // JKQTMATHTEXTTOOLS_H

View File

@ -580,24 +580,7 @@ JKQTMathTextNode *JKQTMathTextHorizontalListNode::replaceChild(int i, JKQTMathTe
}
QString JKQTMathTextVerticalListNode::SpacingMode2String(SpacingMode mode)
{
switch(mode) {
case SMMinimal: return "minimal";
default:
case SMDefault: return "default";
}
}
JKQTMathTextVerticalListNode::SpacingMode JKQTMathTextVerticalListNode::String2SpacingMode(QString tokenName)
{
tokenName=tokenName.toLower().trimmed();
if (tokenName=="default") return SMDefault;
if (tokenName=="minimal" || tokenName=="min" || tokenName=="minimum") return SMMinimal;
return SMDefault;
}
JKQTMathTextVerticalListNode::JKQTMathTextVerticalListNode(JKQTMathText *_parent, JKQTMathTextHorizontalAlignment _alignment, double _linespacingFactor, SpacingMode spacingMode_, JKQTMathTextVerticalOrientation _verticalOrientation):
JKQTMathTextVerticalListNode::JKQTMathTextVerticalListNode(JKQTMathText *_parent, JKQTMathTextHorizontalAlignment _alignment, double _linespacingFactor, JKQTMathTextLineSpacingMode spacingMode_, JKQTMathTextVerticalOrientation _verticalOrientation):
JKQTMathTextMultiChildNode(_parent),
alignment(_alignment),
lineSpacingFactor(_linespacingFactor),
@ -652,9 +635,9 @@ JKQTMathTextVerticalListNode::LayoutInfo JKQTMathTextVerticalListNode::calcLayou
heightSum=locBaselineHeight;
} else if (i>0) {
double deltaLine=0;
if (spacingMode==SMMinimal) {
if (spacingMode==MTSMMinimalSpacing) {
deltaLine=descents.last()+lineLeading+locBaselineHeight;
} else if (spacingMode==SMDefault) {
} else if (spacingMode==MTSMDefaultSpacing) {
deltaLine=qMax(linespacing, descents.last()+lineLeading+locBaselineHeight);
}
heightSum=heightSum+deltaLine;
@ -801,11 +784,31 @@ double JKQTMathTextVerticalListNode::getLineSpacingFactor() const
return lineSpacingFactor;
}
JKQTMathTextVerticalListNode::SpacingMode JKQTMathTextVerticalListNode::getSpacingMode() const
JKQTMathTextLineSpacingMode JKQTMathTextVerticalListNode::getSpacingMode() const
{
return spacingMode;
}
void JKQTMathTextVerticalListNode::setAlignment(JKQTMathTextHorizontalAlignment value)
{
alignment=value;
}
void JKQTMathTextVerticalListNode::setVerticalOrientation(JKQTMathTextVerticalOrientation value)
{
verticalOrientation=value;
}
void JKQTMathTextVerticalListNode::setLineSpacingFactor(double value)
{
lineSpacingFactor=value;
}
void JKQTMathTextVerticalListNode::setSpacingMode(JKQTMathTextLineSpacingMode value)
{
spacingMode=value;
}
JKQTMathTextVerticalListNode::LayoutInfo::LayoutInfo():
JKQTMathTextNodeSize(), X()
{}

View File

@ -95,20 +95,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextHorizontalListNode: public JKQTMathTex
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerticalListNode: public JKQTMathTextMultiChildNode {
public:
/** \brief defines, how lines are beeing spaced by the node
*
* \image html jkqtmathtext_verticallist.png
*/
enum SpacingMode {
SMDefault, /*!< space the lines with equilibrated spacing, i.e. the baselines are at least \c QFontMetricsF::lineSpacing()*JKQTMathTextVerticalListNode::lineSpacingFactor apart, but even more, if the height of the text bloxk is larger than the the font's ascent+descent */
SMMinimal /*!< space the lines as tight as possible, i.e. each line is separated by \c QFontMetricsF::leading()*JKQTMathTextVerticalListNode::lineSpacingFactor from the next line. This is a s compact as possible */
};
/** \brief convert a SpacingMode to a String */
static QString SpacingMode2String(SpacingMode mode);
/** \brief convert a String to a SpacingMode */
static SpacingMode String2SpacingMode(QString mode);
explicit JKQTMathTextVerticalListNode(JKQTMathText* parent, JKQTMathTextHorizontalAlignment _alignment=MTHACentered, double _linespacingFactor=1.0, SpacingMode spacingMode_=SMDefault, JKQTMathTextVerticalOrientation _verticalOrientation=MTVOFirstLine);
explicit JKQTMathTextVerticalListNode(JKQTMathText* parent, JKQTMathTextHorizontalAlignment _alignment=MTHACentered, double _linespacingFactor=1.0, JKQTMathTextLineSpacingMode spacingMode_=MTSMDefaultSpacing, JKQTMathTextVerticalOrientation _verticalOrientation=MTVOFirstLine);
virtual ~JKQTMathTextVerticalListNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
@ -139,7 +127,15 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerticalListNode: public JKQTMathTextM
/** \copydoc lineSpacingFactor */
double getLineSpacingFactor() const;
/** \copydoc spacingMode */
SpacingMode getSpacingMode() const;
JKQTMathTextLineSpacingMode getSpacingMode() const;
/** \copydoc alignment */
void setAlignment(JKQTMathTextHorizontalAlignment value) ;
/** \copydoc verticalOrientation */
void setVerticalOrientation(JKQTMathTextVerticalOrientation value) ;
/** \copydoc lineSpacingFactor */
void setLineSpacingFactor(double value);
/** \copydoc spacingMode */
void setSpacingMode(JKQTMathTextLineSpacingMode value) ;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
@ -173,7 +169,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerticalListNode: public JKQTMathTextM
*/
JKQTMathTextVerticalOrientation verticalOrientation;
/** \brief defines how the layout algorithm (see calcLayout() ) lays out the single lines */
SpacingMode spacingMode;
JKQTMathTextLineSpacingMode spacingMode;

View File

@ -388,12 +388,13 @@ QString JKQTMathTextTextNode::textTransform(const QString &text, const JKQTMathT
JKQTMathTextVerbatimNode::JKQTMathTextVerbatimNode(JKQTMathText *_parent, const QString& _text, bool visibleWhitespace_, JKQTMathTextHorizontalAlignment _alignment, double _linespacingFactor, JKQTMathTextVerticalOrientation _verticalOrientation):
JKQTMathTextVerbatimNode::JKQTMathTextVerbatimNode(JKQTMathText *_parent, const QString& _text, bool visibleWhitespace_, JKQTMathTextHorizontalAlignment _alignment, double _linespacingFactor, JKQTMathTextVerticalOrientation _verticalOrientation, size_t tabSize_):
JKQTMathTextTextBaseNode(_parent, _text),
alignment(_alignment),
lineSpacingFactor(_linespacingFactor),
verticalOrientation(_verticalOrientation),
visibleWhitespace(visibleWhitespace_)
visibleWhitespace(visibleWhitespace_),
tabSize(tabSize_)
{
}
@ -423,6 +424,11 @@ bool JKQTMathTextVerbatimNode::getVisibleWhitespace() const
return visibleWhitespace;
}
size_t JKQTMathTextVerbatimNode::getTabSize() const
{
return tabSize;
}
double JKQTMathTextVerbatimNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize *prevNodeSize)
{
doDrawBoxes(painter, x, y, currentEv);
@ -560,9 +566,9 @@ QString JKQTMathTextVerbatimNode::textTransform(const QString &text, const JKQTM
if (!fm.inFont(spRep[0])) {
spRep=QChar(0x2423);
}
QString tabRep=QString(4,QChar(0x2192));
QString tabRep=QString(tabSize,QChar(0x2192));
if (!fm.inFont(tabRep[0])) {
spRep=QString(4,QChar(0xAC));
spRep=QString(tabSize,QChar(0xAC));
}
QString res=JKQTMathTextTextBaseNode::textTransform(text, currentEv);
@ -572,6 +578,9 @@ QString JKQTMathTextVerbatimNode::textTransform(const QString &text, const JKQTM
res.replace(' ', spRep);
res.replace('\t', tabRep);
return res;
} else {
res.replace('\t', QString(tabSize, ' '));
return res;
}
return res;
}

View File

@ -116,7 +116,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTextNode: public JKQTMathTextTextBaseN
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerbatimNode: public JKQTMathTextTextBaseNode {
public:
explicit JKQTMathTextVerbatimNode(JKQTMathText* parent, const QString& text, bool visibleWhitespace=false, JKQTMathTextHorizontalAlignment _alignment=MTHALeft, double _linespacingFactor=1.0, JKQTMathTextVerticalOrientation _verticalOrientation=MTVOFirstLine);
explicit JKQTMathTextVerbatimNode(JKQTMathText* parent, const QString& text, bool visibleWhitespace=false, JKQTMathTextHorizontalAlignment _alignment=MTHALeft, double _linespacingFactor=1.0, JKQTMathTextVerticalOrientation _verticalOrientation=MTVOFirstLine, size_t tabSize_=4);
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc alignment */
@ -127,6 +127,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerbatimNode: public JKQTMathTextTextB
double getLineSpacingFactor() const;
/** \copydoc visibleWhitespace */
bool getVisibleWhitespace() const;
/** \copydoc tabSize */
size_t getTabSize() const;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::toHtml() */
@ -151,6 +153,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerbatimNode: public JKQTMathTextTextB
JKQTMathTextVerticalOrientation verticalOrientation;
/** \brief when \c true, whitespaces are displayed with a visible character */
bool visibleWhitespace;
/** \brief number of whitespaces, each tab character stands for */
size_t tabSize;
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;

View File

@ -325,8 +325,10 @@ int main(int argc, char* argv[])
bool isFile=true;
bool beforeLatex=true;
while (!f.atEnd()) {
const QString line=f.readLine().trimmed();
const QString line_simple=line.simplified();
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();
if (line_simple=="---" || line_simple=="###") {
if (currentOutFile.size()>0) {
outputFilename.append(currentOutFile);
@ -339,11 +341,11 @@ int main(int argc, char* argv[])
currentOptions.clear();
}
} else if (isFile) {
currentOutFile=line;
currentOutFile=line_trimmed;
isFile=false;
} else if (beforeLatex) {
if (line.startsWith("--")) {
QStringList commands=line.right(line.size()-2).split("--");
if (line_trimmed.startsWith("--")) {
QStringList commands=line_trimmed.right(line_trimmed.size()-2).split("--");
for (QString cmd: commands) {
cmd=cmd.trimmed();
QString cmdn="", param="";
@ -532,7 +534,7 @@ int main(int argc, char* argv[])
const QString outname=outputDir.absoluteFilePath(outputFilename[i]);
if (QFileInfo::exists(outname)) QFile::remove(outname);
if (!pix.save(outname)) {
std::cerr<<"ERROR storing to "<<outname.toStdString()<<"\n";
std::cerr<<"ERROR storing to "<<outname.toStdString()<<", fileExists="<<std::boolalpha<<QFileInfo::exists(outname)<<" permissions=0x"<<std::hex<<QFileInfo(outname).permissions()<<"\n";
} else {
if (verbose) std::cout<<"stored to "<<outname.toStdString()<<"\n"
<<" size "<<static_cast<double>(QFileInfo(outname).size())/1024.0<<"kBytes\n";