- JKQTMathText: IMPROVED/breaking: refactored symbol node JKQTMathTextSymbolNode and changed font-lookup!

- JKQTMathText: IMPROVED/NEW/breaking: refactored whitespace-processing node JKQTMathTextWhitespaceNode, now all major LaTeX whitespace commands are supported properly
This commit is contained in:
jkriege2 2022-07-03 20:30:12 +02:00
parent 8814523e63
commit 0f958cc2d6
15 changed files with 2204 additions and 2097 deletions

View File

@ -40,7 +40,9 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>IMPROVED: added x-correction for sub/superscript above/below/besides integrals</li>
<li>IMPROVED: rendering of sqrt</li>
<li>IMPROVED: rendering and size calculation of decorations</li>
<li>remove/breaking: \v[a-zA-Z] and shorthand for \vec{a-zA-Z} was removed, implementation of \bbR,\bbC,... changed</li>
<li>IMPROVED/breaking: refactored symbol node JKQTMathTextSymbolNode and changed font-lookup!</li>
<li>IMPROVED/NEW/breaking: refactored whitespace-processing node JKQTMathTextWhitespaceNode, now all major LaTeX whitespace commands are supported properly</li>
<li>REMOVED/breaking: \v[a-zA-Z] and shorthand for \vec{a-zA-Z} was removed, implementation of \bbR,\bbC,... changed</li>
<li>NEW: now supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve</li>
<li>NEW: reworked drawing of decorations: improved appearance and positioning!</li>
<li>NEW: reworked code structure: broke up large, single CPP-files into several smaller files!</li>

View File

@ -11,6 +11,7 @@
#include "jkqtmathtext/nodes/jkqtmathtextsqrtnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsubsupernode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsymbolnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h"
TestForm::TestForm(QWidget *parent) :
@ -21,6 +22,19 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbTestset->addItem("text: fonts", "rm: \\textrm{ABCabc123}, sf: \\textsf{ABCabc123}, tt: \\texttt{ABCabc123}, cal: \\textcal{ABCabc123}, scr: \\textscr{ABCabc123}, bb: \\textbb{ABCabc123}, frak: \\textfrak{ABCabc123}, ");
ui->cmbTestset->addItem("math-fonts", "rm: $\\mathrm{ABCabc123}$, sf: $\\mathsf{ABCabc123}$, tt: $\\mathtt{ABCabc123}$, cal: $\\mathcal{ABCabc123}$, scr: $\\mathscr{ABCabc123}$, bb: $\\mathbb{ABCabc123}$, frak: $\\mathfrak{ABCabc123}$, ");
ui->cmbTestset->addItem("math: simple relations", "$a{\\leq}b$, $a{\\geq}b$, $a{\\equiv}b$, $a=b$, $a{\\neq}b$, $a<b$, $a>b$");
const auto wsExample=[](const QStringList& spaces, const QString before, const QString& after)->QString {
QString s;
for (int i=0; i<spaces.size(); i++) {
s+="text: {\\backslash}"+spaces[i]+": "+before+"{\\"+spaces[i]+"}"+after;
s+="\\ \\ \\ \\ ";
}
return s;
};
QStringList whitespaces=QStringList()<<" "<<"enspace"<<"quad"<<"qquad"<<","<<":"<<";"<<"!"<<"negmedspace"<<"negthickspace";
ui->cmbTestset->addItem("text: whitespaces arrows", "text: "+wsExample(whitespaces, "\\rightarrow", "\\leftarrow"));
ui->cmbTestset->addItem("text: whitespaces fg", "text: "+wsExample(whitespaces, "f", "g"));
ui->cmbTestset->addItem("math: whitespaces arrows", "math: "+wsExample(whitespaces, "$\\rightarrow", "\\leftarrow$"));
ui->cmbTestset->addItem("math: whitespaces fg", "math: "+wsExample(whitespaces, "$f", "g$"));
ui->cmbTestset->addItem("text/math: simple relations in different modes", "math: $a{\\leq}b$, math/no braces: $a\\leq b$, no math: a{\\leq}b, no math/no braces: a\\leq b");
ui->cmbTestset->addItem("math: named symbols 1", "ll: $\\ll$\\ gg: $\\gg$\\ leq: $\\leq$\\ geq: $\\geq$\\ pm: $\\pm$\\ mp: $\\mp$\\ ");
ui->cmbTestset->addItem("math: named symbols 2", "nexists: $\\nexists$\\ ni: $\\ni$\\ notni: $\\notni$\\ circ: $\\circ$\\ sim: $\\sim$\\ emptyset: $\\emptyset$\\ odot: $\\odot$\\ ominus: $\\ominus$\\ subsetnot: $\\subsetnot$\\ bot: $\\bot$");
@ -212,7 +226,7 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbEncodingSerifMath->setCurrentIndex(static_cast<int>(mt.getFontEncodingMathRoman()));
ui->cmbUnicodeSansMath->setCurrentFont(QFont(mt.getFontMathSans()));
ui->cmbEncodingSansMath->setCurrentIndex(static_cast<int>(mt.getFontEncodingMathSans()));
ui->cmbUnicodeFixed->setCurrentFont(QFont(mt.getFontTypewriter()));
ui->cmbUnicodeTypewriter->setCurrentFont(QFont(mt.getFontTypewriter()));
ui->cmbEncodingTypewriter->setCurrentIndex(static_cast<int>(mt.getFontEncodingTypewriter()));
ui->cmbCaligraphic->setCurrentFont(QFont(mt.getFontCaligraphic()));
ui->cmbEncodingCaligraphic->setCurrentIndex(static_cast<int>(mt.getFontEncodingCaligraphic()));
@ -222,10 +236,10 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbEncodingFraktur->setCurrentIndex(static_cast<int>(mt.getFontEncodingFraktur()));
ui->cmbUnicodeBlackboard->setCurrentFont(QFont(mt.getFontBlackboard()));
ui->cmbEncodingBlackboard->setCurrentIndex(static_cast<int>(mt.getFontEncodingBlackboard()));
ui->cmbUnicodeSymbol->setCurrentFont(QFont(mt.getSymbolfontSymbol(JKQTMathTextEnvironmentFont::MTEroman)));
ui->cmbEncodingSymbol->setCurrentIndex(static_cast<int>(mt.getSymbolfontEncodingSymbol(JKQTMathTextEnvironmentFont::MTEroman)));
ui->cmbUnicodeGreek->setCurrentFont(QFont(mt.getSymbolfontGreek(JKQTMathTextEnvironmentFont::MTEroman)));
ui->cmbEncodingGreek->setCurrentIndex(static_cast<int>(mt.getSymbolfontEncodingGreek(JKQTMathTextEnvironmentFont::MTEroman)));
ui->cmbUnicodeSymbol->setCurrentFont(QFont(mt.getFallbackFontSymbols()));
ui->cmbEncodingSymbol->setCurrentIndex(static_cast<int>(mt.getFontEncodingFallbackFontSymbols()));
ui->cmbUnicodeGreek->setCurrentFont(QFont(mt.getFallbackFontGreek()));
ui->cmbEncodingGreek->setCurrentIndex(static_cast<int>(mt.getFontEncodingFallbackFontGreek()));
ui->chkSimulateBlackboard->setChecked(mt.isFontBlackboardSimulated());
@ -250,7 +264,7 @@ TestForm::TestForm(QWidget *parent) :
connect(ui->cmbUnicodeSansMath, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath()));
connect(ui->cmbEncodingSans, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath()));
connect(ui->cmbEncodingSansMath, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath()));
connect(ui->cmbUnicodeFixed, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath()));
connect(ui->cmbUnicodeTypewriter, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath()));
connect(ui->cmbUnicodeGreek, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath()));
connect(ui->cmbUnicodeSerif, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath()));
connect(ui->cmbUnicodeSerifMath, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath()));
@ -393,7 +407,7 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
} else if (symN) {
name=QString("MTSymbolNode: \'%1\' (addWhite: %2, subsuper=%3)").arg(symN->getSymbolName()).arg(symN->getAddWhitespace()).arg(symN->isSubSuperscriptAboveBelowNode());
} else if (spN) {
name=QString("MTWhitespaceNode :\'%1\'").arg(txtN->getText());
name=QString("MTWhitespaceNode :type=%1, count=%2").arg(spN->Type2String(spN->getWhitespaceType())).arg(spN->getWhitespaceCount());
} else if (txtN) {
name=QString("MTTextNode: \'%1\'").arg(txtN->getText());
@ -468,13 +482,13 @@ void TestForm::updateMath()
mt.setFontSans(ui->cmbUnicodeSans->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSans->currentIndex()));
mt.setFontMathRoman(ui->cmbUnicodeSerifMath->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSerifMath->currentIndex()));
mt.setFontMathSans(ui->cmbUnicodeSansMath->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSansMath->currentIndex()));
mt.setFontTypewriter(ui->cmbUnicodeFixed->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingTypewriter->currentIndex()));
mt.setFontTypewriter(ui->cmbUnicodeTypewriter->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingTypewriter->currentIndex()));
mt.setFontCaligraphic(ui->cmbCaligraphic->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingCaligraphic->currentIndex()));
mt.setFontScript(ui->cmbScript->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingScript->currentIndex()));
mt.setFontFraktur(ui->cmbUnicodeFraktur->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingFraktur->currentIndex()));
mt.setFontBlackboard(ui->cmbUnicodeBlackboard->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingBlackboard->currentIndex()));
mt.setSymbolfontSymbol(ui->cmbUnicodeSymbol->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSymbol->currentIndex()));
mt.setSymbolfontGreek(ui->cmbUnicodeGreek->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingGreek->currentIndex()));
mt.setFallbackFontSymbols(ui->cmbUnicodeSymbol->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSymbol->currentIndex()));
mt.setFallbackFontGreek(ui->cmbUnicodeGreek->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingGreek->currentIndex()));
} else if (ui->cmbFont->currentIndex()==5 || ui->cmbFont->currentIndex()==6) {
mt.setFontRoman(QGuiApplication::font().family());
} else if (ui->cmbFont->currentIndex()==7) {

View File

@ -144,70 +144,25 @@
</item>
<item row="1" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Symbol/Unicode fonts:</string>
</property>
</widget>
</item>
<item row="0" column="12">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_18">
<property name="text">
<string>blackboard:</string>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="QLabel" name="label_7">
<property name="text">
<string>symbol:</string>
<string>fallback-greek:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QFontComboBox" name="cmbUnicodeSerif">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QFontComboBox" name="cmbUnicodeBlackboard">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_17">
<item row="0" column="4">
<widget class="QLabel" name="label_14">
<property name="text">
<string> roman:</string>
<string>sans:</string>
</property>
</widget>
</item>
<item row="2" column="8">
<widget class="QFontComboBox" name="cmbUnicodeSymbol">
<property name="currentFont">
<font/>
<item row="1" column="3">
<widget class="QComboBox" name="cmbEncodingSerifMath">
<property name="currentIndex">
<number>2</number>
</property>
</widget>
</item>
<item row="2" column="9">
<widget class="QComboBox" name="cmbEncodingSymbol">
<item>
<property name="text">
<string>WinSymbol</string>
@ -220,20 +175,67 @@
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_14">
<item row="0" column="8">
<widget class="QFontComboBox" name="cmbUnicodeTypewriter">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>sans:</string>
<string>Symbol/Unicode fonts:</string>
</property>
</widget>
</item>
<item row="2" column="9">
<widget class="QComboBox" name="cmbEncodingGreek">
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="0" column="9">
<widget class="QComboBox" name="cmbEncodingTypewriter">
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Latin-1</string>
</property>
</item>
</widget>
</item>
<item row="2" column="2">
<widget class="QFontComboBox" name="cmbUnicodeBlackboard">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
@ -254,39 +256,7 @@
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
</property>
</item>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="cmbEncodingSerif">
<property name="currentIndex">
<number>2</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
<string>Latin1</string>
</property>
</item>
</widget>
@ -308,23 +278,40 @@
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="0" column="8">
<widget class="QFontComboBox" name="cmbUnicodeGreek">
<property name="currentFont">
<font/>
<item row="2" column="1">
<widget class="QLabel" name="label_18">
<property name="text">
<string>blackboard:</string>
</property>
</widget>
</item>
<item row="3" column="9">
<widget class="QComboBox" name="cmbEncodingSymbol">
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="0" column="5">
<widget class="QFontComboBox" name="cmbUnicodeSans">
<property name="currentFont">
@ -332,258 +319,8 @@
</property>
</widget>
</item>
<item row="0" column="9">
<widget class="QComboBox" name="cmbEncodingGreek">
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
</property>
</item>
</widget>
</item>
<item row="0" column="7">
<widget class="QLabel" name="label_19">
<property name="text">
<string>greek:</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="chkSimulateBlackboard">
<property name="text">
<string>simulate blackboard</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="label_21">
<property name="text">
<string>fraktur:</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QFontComboBox" name="cmbUnicodeFraktur">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QComboBox" name="cmbEncodingFraktur">
<property name="currentIndex">
<number>1</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
</property>
</item>
</widget>
</item>
<item row="3" column="4">
<widget class="QLabel" name="label_16">
<property name="text">
<string>caligraphic:</string>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QFontComboBox" name="cmbCaligraphic">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="QComboBox" name="cmbEncodingCaligraphic">
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
</property>
</item>
</widget>
</item>
<item row="3" column="7">
<widget class="QLabel" name="label_20">
<property name="text">
<string>script:</string>
</property>
</widget>
</item>
<item row="3" column="8">
<widget class="QFontComboBox" name="cmbScript">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="3" column="9">
<widget class="QComboBox" name="cmbEncodingScript">
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
</property>
</item>
</widget>
</item>
<item row="1" column="7">
<widget class="QLabel" name="label_15">
<property name="text">
<string>typewriter:</string>
</property>
</widget>
</item>
<item row="1" column="8">
<widget class="QFontComboBox" name="cmbUnicodeFixed">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="1" column="9">
<widget class="QComboBox" name="cmbEncodingTypewriter">
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_22">
<property name="text">
<string>math- roman:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QFontComboBox" name="cmbUnicodeSerifMath">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QComboBox" name="cmbEncodingSerifMath">
<property name="currentIndex">
<number>2</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
</property>
</item>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_23">
<property name="text">
<string>math-sans:</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QFontComboBox" name="cmbUnicodeSansMath">
<widget class="QFontComboBox" name="cmbUnicodeSymbol">
<property name="currentFont">
<font/>
</property>
@ -606,14 +343,222 @@
</item>
<item>
<property name="text">
<string>Unicode Limited</string>
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="3" column="6">
<widget class="QComboBox" name="cmbEncodingCaligraphic">
<property name="currentIndex">
<number>-1</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Standard</string>
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="2" column="6">
<widget class="QComboBox" name="cmbEncodingFraktur">
<property name="currentIndex">
<number>1</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="0" column="12">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="7">
<widget class="QLabel" name="label_15">
<property name="text">
<string>script:</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_23">
<property name="text">
<string>math-sans:</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QFontComboBox" name="cmbUnicodeFraktur">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QFontComboBox" name="cmbUnicodeSerifMath">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="1" column="9">
<widget class="QComboBox" name="cmbEncodingScript">
<property name="currentIndex">
<number>-1</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="1" column="5">
<widget class="QFontComboBox" name="cmbUnicodeSansMath">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="cmbEncodingSerif">
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>WinSymbol</string>
</property>
</item>
<item>
<property name="text">
<string>Unicode</string>
</property>
</item>
<item>
<property name="text">
<string>Latin1</string>
</property>
</item>
</widget>
</item>
<item row="3" column="4">
<widget class="QLabel" name="label_16">
<property name="text">
<string>caligraphic:</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="chkSimulateBlackboard">
<property name="text">
<string>simulate blackboard</string>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QLabel" name="label_19">
<property name="text">
<string>typewriter:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_22">
<property name="text">
<string>math- roman:</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="label_21">
<property name="text">
<string>fraktur:</string>
</property>
</widget>
</item>
<item row="2" column="8">
<widget class="QFontComboBox" name="cmbUnicodeGreek">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QFontComboBox" name="cmbCaligraphic">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_17">
<property name="text">
<string> roman:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QFontComboBox" name="cmbUnicodeSerif">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="1" column="8">
<widget class="QFontComboBox" name="cmbScript">
<property name="currentFont">
<font/>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="QLabel" name="label_20">
<property name="text">
<string>fallback-symbol:</string>
</property>
</widget>
</item>
</layout>

View File

@ -112,7 +112,7 @@ TestWidgetBarcharts::TestWidgetBarcharts(QWidget *parent) :
spinBarLabelAngel=new QSpinBox(this);
spinBarLabelAngel->setPrefix(tr("rotation angel: "));
spinBarLabelAngel->setSuffix(QLatin1String("\xB0"));
spinBarLabelAngel->setSuffix(QChar(0xB0));
spinBarLabelAngel->setRange(-180,180);
spinBarLabelAngel->setValue(0);
spinBarLabelAngel->setSingleStep(15);
@ -121,7 +121,7 @@ TestWidgetBarcharts::TestWidgetBarcharts(QWidget *parent) :
spinBarLabelAngel2=new QSpinBox(this);
spinBarLabelAngel2->setPrefix(tr("rotation angel: "));
spinBarLabelAngel2->setSuffix(QLatin1String("\xB0"));
spinBarLabelAngel2->setSuffix(QChar(0xB0));
spinBarLabelAngel2->setRange(-180,180);
spinBarLabelAngel2->setValue(0);
spinBarLabelAngel2->setSingleStep(15);

View File

@ -36,6 +36,7 @@ set(SOURCES
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsubsupernode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsymbolnode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextnodetools.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextwhitespacenode.cpp
)
set(HEADERS
@ -69,6 +70,8 @@ set(HEADERS
$<INSTALL_INTERFACE:nodes/jkqtmathtextsymbolnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextnodetools.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextnodetools.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextwhitespacenode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextwhitespacenode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/jkqtmathtext_imexport.h>
$<INSTALL_INTERFACE:jkqtmathtext_imexport.h>
)

View File

@ -33,6 +33,7 @@
#include "jkqtmathtext/nodes/jkqtmathtextsqrtnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsubsupernode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsymbolnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h"
#include "jkqtmathtext/nodes/jkqtmathtextnodetools.h"
#include <cmath>
#include <QFontMetricsF>
@ -180,16 +181,21 @@ JKQTMathText::JKQTMathText(QObject* parent):
addReplacementFont("blackboard", blackboardFont);
}
//qDebug()<<"add replacement fonts: "<<std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()-t0).count()/1000.0<<"ms"; t0=std::chrono::high_resolution_clock::now();
setFontSans(sansFont, MTFEStandard);
setFontMathSans(sansFont, MTFEStandard);
setFontTypewriter(typewriterFont, MTFEStandard);
setFontRoman(serifFont, MTFEStandard);
setFontMathRoman(serifFont, MTFEStandard);
setFontCaligraphic(decorativeFont, MTFEStandard);
setFontBlackboard(blackboardFont, MTFEStandard);
setFontBlackboardSimulated(blackboardFont=="blackboard");
setFontScript(scriptFont, MTFEStandard);
setFontFraktur(fracturFont, MTFEStandard);
setFontSans(sansFont, estimateJKQTMathTextFontEncoding(sansFont));
setFontMathSans(sansFont, estimateJKQTMathTextFontEncoding(sansFont));
setFontTypewriter(typewriterFont, estimateJKQTMathTextFontEncoding(typewriterFont));
setFontRoman(serifFont, estimateJKQTMathTextFontEncoding(serifFont));
setFontMathRoman(serifFont, estimateJKQTMathTextFontEncoding(serifFont));
setFontCaligraphic(decorativeFont, estimateJKQTMathTextFontEncoding(decorativeFont));
if (blackboardFont!="blackboard") {
setFontBlackboard(blackboardFont, estimateJKQTMathTextFontEncoding(blackboardFont));
} else {
setFontBlackboardSimulated(blackboardFont=="blackboard");
}
setFontScript(scriptFont, estimateJKQTMathTextFontEncoding(scriptFont));
setFontFraktur(fracturFont, estimateJKQTMathTextFontEncoding(fracturFont));
setFallbackFontGreek(symbolFont, estimateJKQTMathTextFontEncoding(symbolFont));
setFallbackFontSymbols(symbolFont, estimateJKQTMathTextFontEncoding(symbolFont));
//qDebug()<<"set fonts: "<<std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()-t0).count()/1000.0<<"ms"; t0=std::chrono::high_resolution_clock::now();
useXITS();
//qDebug()<<"useXITS: "<<std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()-t0).count()/1000.0<<"ms"; t0=std::chrono::high_resolution_clock::now();
@ -229,7 +235,7 @@ void JKQTMathText::loadSettings(const QSettings& settings, const QString& group)
underbrace_factor=settings.value(group+"underbrace_factor", underbrace_factor).toDouble();
underbrace_bracesize_xfactor=settings.value(group+"underbrace_bracesize_xfactor", underbrace_bracesize_xfactor).toDouble();
underbrace_separation_xfactor=settings.value(group+"underbrace_separation_xfactor", underbrace_separation_xfactor).toDouble();
underset_factor=settings.value(group+"undersetFactor", underset_factor).toDouble();
underset_factor=settings.value(group+"underset_factor", underset_factor).toDouble();
brace_y_shift_factor=settings.value(group+"brace_y_shift_factor", brace_y_shift_factor).toDouble();
decoration_height_factor=settings.value(group+"decoration_height_factor", decoration_height_factor).toDouble();
decoration_separation_factor=settings.value(group+"decoration_separation_factor", decoration_separation_factor).toDouble();
@ -243,6 +249,8 @@ void JKQTMathText::loadSettings(const QSettings& settings, const QString& group)
sqrt_width_Xfactor=settings.value(group+"sqrt_width_Xfactor", sqrt_width_Xfactor).toDouble();
sqrt_height_factor=settings.value(group+"sqrt_height_factor", sqrt_height_factor).toDouble();
sqrt_smallfont_factor=settings.value(group+"sqrt_smallfont_factor", sqrt_smallfont_factor).toDouble();
bigmathoperator_font_factor=settings.value(group+"bigmathoperator_font_factor", bigmathoperator_font_factor).toDouble();
frac_nested_factor=settings.value(group+"frac_nested_factor", frac_nested_factor).toDouble();
if (settings.value(group+"use_stix_fonts", false).toBool()) useSTIX();
@ -268,7 +276,7 @@ void JKQTMathText::saveSettings(QSettings& settings, const QString& group) const
settings.setValue(group+ "underbrace_factor", underbrace_factor);
settings.setValue(group+ "underbrace_bracesize_xfactor", underbrace_bracesize_xfactor);
settings.setValue(group+ "underbrace_separation_xfactor", underbrace_separation_xfactor);
settings.setValue(group+ "undersetFactor", underset_factor);
settings.setValue(group+ "underset_factor", underset_factor);
settings.setValue(group+ "operatorsubsuper_size_factor", operatorsubsuper_size_factor);
settings.setValue(group+ "operatorsubsuper_distance_factor", operatorsubsuper_distance_factor);
settings.setValue(group+ "operatorsubsuper_extraspace_factor", operatorsubsuper_extraspace_factor);
@ -282,22 +290,28 @@ void JKQTMathText::saveSettings(QSettings& settings, const QString& group) const
settings.setValue(group+ "sqrt_width_Xfactor", sqrt_width_Xfactor);
settings.setValue(group+ "sqrt_height_factor", sqrt_height_factor);
settings.setValue(group+ "sqrt_smallfont_factor", sqrt_smallfont_factor);
settings.setValue(group+ "bigmathoperator_font_factor", bigmathoperator_font_factor);
settings.setValue(group+ "frac_nested_factor", frac_nested_factor);
}
bool JKQTMathText::useSTIX(bool mathModeOnly) {
const JKQTMathTextFontSpecifier xits=JKQTMathTextFontSpecifier::getSTIXFamilies();
const JKQTMathTextFontSpecifier stixs=JKQTMathTextFontSpecifier::getSTIXFamilies();
bool res=false;
if (!mathModeOnly && !xits.fontName().isEmpty()) {
setFontRoman(xits.fontName(), MTFEunicode);
if (!mathModeOnly && !stixs.fontName().isEmpty()) {
setFontRoman(stixs.fontName(), MTFEUnicode);
res=true;
}
if (!xits.mathFontName().isEmpty()) {
setFontMathRoman(xits.mathFontName(), MTFEunicode);
if (!stixs.mathFontName().isEmpty()) {
setFontMathRoman(stixs.mathFontName(), MTFEUnicode);
setFallbackFontGreek(stixs.mathFontName(), MTFEUnicode);
setFallbackFontSymbols(stixs.mathFontName(), MTFEUnicode);
res=true;
} else if (!xits.fontName().isEmpty()) {
setFontMathRoman(xits.fontName(), MTFEunicode);
} else if (!stixs.fontName().isEmpty()) {
setFontMathRoman(stixs.fontName(), MTFEUnicode);
setFallbackFontGreek(stixs.fontName(), MTFEUnicode);
setFallbackFontSymbols(stixs.fontName(), MTFEUnicode);
res=true;
}
@ -311,15 +325,15 @@ bool JKQTMathText::useXITS(bool mathModeOnly)
bool res=false;
if (!mathModeOnly && !xits.fontName().isEmpty()) {
setFontRoman(xits.fontName(), MTFEunicode);
setSymbolfontSymbol(xits.fontName(), MTFEunicode);
setSymbolfontGreek(xits.fontName(), MTFEunicode);
setFontRoman(xits.fontName(), MTFEUnicode);
setFallbackFontGreek(xits.fontName(), MTFEUnicode);
setFallbackFontSymbols(xits.fontName(), MTFEUnicode);
res=true;
}
if (!xits.mathFontName().isEmpty()) {
setFontMathRoman(xits.mathFontName(), MTFEunicode);
setSymbolfontSymbol(xits.fontName(), MTFEunicode);
setSymbolfontGreek(xits.fontName(), MTFEunicode);
setFontMathRoman(xits.mathFontName(), MTFEUnicode);
setFallbackFontGreek(xits.mathFontName(), MTFEUnicode);
setFallbackFontSymbols(xits.mathFontName(), MTFEUnicode);
res=true;
}
@ -333,11 +347,15 @@ bool JKQTMathText::useASANA(bool mathModeOnly)
bool res=false;
if (!mathModeOnly && !asana.fontName().isEmpty()) {
setFontRoman(asana.fontName(), MTFEunicode);
setFontRoman(asana.fontName(), MTFEUnicode);
setFallbackFontGreek(asana.fontName(), MTFEUnicode);
setFallbackFontSymbols(asana.fontName(), MTFEUnicode);
res=true;
}
if (!asana.mathFontName().isEmpty()) {
setFontMathRoman(asana.mathFontName(), MTFEunicode);
setFontMathRoman(asana.mathFontName(), MTFEUnicode);
setFallbackFontGreek(asana.mathFontName(), MTFEUnicode);
setFallbackFontSymbols(asana.mathFontName(), MTFEUnicode);
res=true;
}
@ -412,15 +430,13 @@ QPair<QString,JKQTMathTextFontEncoding> JKQTMathText::getReplacementFont(const Q
return res;
}
QPair<QString, JKQTMathTextFontEncoding> JKQTMathText::getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment, FontSubclass subclass) const
QPair<QString, JKQTMathTextFontEncoding> JKQTMathText::getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment) const
{
if (in_math_environment) {
if (font==MTEroman) font=MTEmathRoman;
if (font==MTEsans) font=MTEmathSans;
}
const auto fd=fontDefinitions.value(font);
if (subclass==FontSubclass::Greek) return QPair<QString, JKQTMathTextFontEncoding>(fd.symbolfontGreek, fd.symbolfontGreekEncoding);
if (subclass==FontSubclass::Symbols) return QPair<QString, JKQTMathTextFontEncoding>(fd.symbolfontSymbol, fd.symbolfontSymbolEncoding);
return QPair<QString, JKQTMathTextFontEncoding>(fd.fontName, fd.fontEncoding);
}
@ -533,52 +549,40 @@ JKQTMathTextFontEncoding JKQTMathText::getFontEncodingFraktur() const
{
return fontDefinitions[MTEfraktur].fontEncoding;
}
void JKQTMathText::setSymbolfontGreek(JKQTMathTextEnvironmentFont font, const QString &__value, JKQTMathTextFontEncoding encoding)
void JKQTMathText::setFallbackFontGreek(const QString &fontName, JKQTMathTextFontEncoding encoding)
{
auto f=getReplacementFont(__value, __value, encoding);
fontDefinitions[font].symbolfontGreek = f.first;
fontDefinitions[font].symbolfontGreekEncoding = f.second;
auto f=getReplacementFont(fontName, fontName, encoding);
fontDefinitions[MTEFallbackGreek].fontName = f.first;
fontDefinitions[MTEFallbackGreek].fontEncoding = f.second;
}
void JKQTMathText::setSymbolfontGreek(const QString &fontName, JKQTMathTextFontEncoding encoding)
void JKQTMathText::setFallbackFontSymbols(const QString &fontName, JKQTMathTextFontEncoding encoding)
{
for (int f=0; f<static_cast<int>(MTenvironmentFontCount); f++) {
setSymbolfontGreek(static_cast<JKQTMathTextEnvironmentFont>(f), fontName, encoding);
}
auto f=getReplacementFont(fontName, fontName, encoding);
fontDefinitions[MTEFallbackSymbols].fontName = f.first;
fontDefinitions[MTEFallbackSymbols].fontEncoding = f.second;
}
QString JKQTMathText::getSymbolfontGreek(JKQTMathTextEnvironmentFont font) const
QString JKQTMathText::getFallbackFontGreek() const
{
return fontDefinitions[font].symbolfontGreek;
return fontDefinitions[MTEFallbackGreek].fontName;
}
JKQTMathTextFontEncoding JKQTMathText::getSymbolfontEncodingGreek(JKQTMathTextEnvironmentFont font) const
QString JKQTMathText::getFallbackFontSymbols() const
{
return fontDefinitions[font].symbolfontGreekEncoding;
return fontDefinitions[MTEFallbackSymbols].fontName;
}
void JKQTMathText::setSymbolfontSymbol(JKQTMathTextEnvironmentFont font, const QString &__value, JKQTMathTextFontEncoding encoding)
JKQTMathTextFontEncoding JKQTMathText::getFontEncodingFallbackFontGreek() const
{
auto f=getReplacementFont(__value, __value, encoding);
fontDefinitions[font].symbolfontSymbol = f.first;
fontDefinitions[font].symbolfontSymbolEncoding = f.second;
return fontDefinitions[MTEFallbackGreek].fontEncoding;
}
void JKQTMathText::setSymbolfontSymbol(const QString &fontName, JKQTMathTextFontEncoding encoding)
JKQTMathTextFontEncoding JKQTMathText::getFontEncodingFallbackFontSymbols() const
{
for (int f=0; f<static_cast<int>(MTenvironmentFontCount); f++) {
setSymbolfontSymbol(static_cast<JKQTMathTextEnvironmentFont>(f), fontName, encoding);
}
}
QString JKQTMathText::getSymbolfontSymbol(JKQTMathTextEnvironmentFont font) const
{
return fontDefinitions[font].symbolfontSymbol;
}
JKQTMathTextFontEncoding JKQTMathText::getSymbolfontEncodingSymbol(JKQTMathTextEnvironmentFont font) const
{
return fontDefinitions[font].symbolfontSymbolEncoding;
return fontDefinitions[MTEFallbackSymbols].fontEncoding;
}
void JKQTMathText::setFontCaligraphic(const QString &__value, JKQTMathTextFontEncoding encoding)
@ -1138,12 +1142,12 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
while (currentToken!=MTTnone) {
getNew=true;
if (currentToken==MTTtext) {
QString text=currentTokenName;
bool addWhite=(getToken()==MTTwhitespace) && (!parsingMathEnvironment);
const QString text=currentTokenName;
const bool addWhite=(getToken()==MTTwhitespace) && (!parsingMathEnvironment);
getNew=addWhite;
if (parsingMathEnvironment) {
if (mathEnvironmentSpecialText.contains(text.trimmed())) {
nl->addChild(new JKQTMathTextSymbolNode(this, text, addWhite));
if (mathEnvironmentSpecialText.contains(text.trimmed()) && JKQTMathTextSymbolNode::hasSymbol(text.trimmed())) {
nl->addChild(new JKQTMathTextSymbolNode(this, text.trimmed(), addWhite));
} else {
nl->addChild(new JKQTMathTextTextNode(this, text, addWhite, parsingMathEnvironment));
}
@ -1153,321 +1157,330 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
} else if (currentToken==MTTinstruction) {
const QString currentInstructionName=currentTokenName;
if (currentInstructionName=="\\") break; // break on linebrak character
getToken(); // look at next token
if (currentToken==MTTopenbrace) {
//std::cout<<"found '{' after '"<<name.toStdString()<<"'\n";
if (currentInstructionName=="sqrt") {
nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true)));
} else if (currentInstructionName=="cbrt") {
nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true), new JKQTMathTextTextNode(this, "3", false)));
} else if (currentInstructionName=="verb") {
QString text="";
currentTokenID++;
if (currentTokenID<=parseString.size()-1) {
QChar c=parseString[currentTokenID];
while (c!='}' && (currentTokenID<parseString.size())) {
text=text+c;
currentTokenID++;
if (currentTokenID<parseString.size()) c=parseString[currentTokenID];
}
if (c!='}') error_list.append(tr("error @ ch. %1: \verb{...} not closed by '}'").arg(currentTokenID).arg(currentInstructionName));
nl->addChild(new JKQTMathTextTextNode(this, text, false));
}
} else if (currentInstructionName=="frac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="dfrac" || currentInstructionName=="cfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMdfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="sfrac" || currentInstructionName=="slantfrac" || currentInstructionName=="xfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMsfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="stfrac" || currentInstructionName=="nicefrac" || currentInstructionName=="slanttextfrac" || currentInstructionName=="xtfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="tfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMtfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="stackrel") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="binom") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel)));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="underbrace") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbrace));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="underbracket") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbracket));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="underset") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderset));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="overbrace") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbrace));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="overbracket") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbracket));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="overset") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverset));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="begin") {
if (getToken()==MTTtext) {
QString envname=currentTokenName;
while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name'
if (envname=="matrix" || envname=="array" || envname=="aligned" || envname=="align" || envname=="cases" || envname=="pmatrix"|| envname=="bmatrix"|| envname=="Bmatrix"|| envname=="vmatrix"|| envname=="Vmatrix") {
QVector< QVector<JKQTMathTextNode*> > items;
//int lines=0;
//int cols=0;
bool first=true;
QVector<JKQTMathTextNode*> line;
//std::cout<<"found \\begin{matrix}\n";
while (first || currentToken==MTTampersand || (currentToken==MTTinstruction && currentTokenName=="\\")) {
JKQTMathTextNode* it=parseLatexString(true, MTBTAny, envname);
if (currentToken==MTTampersand) {
//std::cout<<" appending item\n";
line.append(it);
} else {
line.append(it);
//std::cout<<" appending item and line with "<<line.size()<<" items.\n";
items.append(line);
line.clear();
}
first=false;
}
//std::cout<<" creating matrix-node with "<<items.size()<<" items.\n";
if (envname=="pmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="cases") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTNone, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTCurlyBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSingleLine, MTBTSingleLine, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTDoubleLine, MTBTDoubleLine, new JKQTMathTextMatrixNode(this, items)));
else nl->addChild(new JKQTMathTextMatrixNode(this, items));
//std::cout<<" creating matrix-node ... done!\n";
} else {
error_list.append(tr("error @ ch. %1: unknown environment '%2'").arg(currentTokenID).arg(envname));
}
} else { // find next '}'
error_list.append(tr("error @ ch. %1: text after '\\begin{' expected!").arg(currentTokenID));
while (currentToken!=MTTclosebrace) getToken();
getNew=true;
}
} else if (currentInstructionName=="end") {
if (getToken()==MTTtext) {
QString envname=currentTokenName;
while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name'
if (envname==quitOnEnvironmentEnd) {
break;
} else {
error_list.append(tr("error @ ch. %1: '\\end{%2}' widthout preceding '\\begin{%3}'").arg(currentTokenID).arg(envname).arg(envname));
}
} else { // find next '}'
error_list.append(tr("error @ ch. %1: text after '\\begin{' expected!").arg(currentTokenID));
while (currentToken!=MTTclosebrace) getToken();
getNew=true;
}
} else if (currentInstructionName=="vec") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDvec, parseLatexString(true)));
} else if (currentInstructionName=="overline"||currentInstructionName=="oline"||currentInstructionName=="ol") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDoverline, parseLatexString(true)));
} else if (currentInstructionName=="underline"||currentInstructionName=="uline"||currentInstructionName=="ul") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDunderline, parseLatexString(true)));
} else if (currentInstructionName=="uuline"||currentInstructionName=="uul") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleunderline, parseLatexString(true)));
} else if (currentInstructionName=="ooline"||currentInstructionName=="ool") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleoverline, parseLatexString(true)));
} else if (currentInstructionName=="arrow"||currentInstructionName=="overrightarrow"||currentInstructionName=="overarrow") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDarrow, parseLatexString(true)));
} else if (currentInstructionName=="hat" || currentInstructionName=="^") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDhat, parseLatexString(true)));
} else if (currentInstructionName=="widehat") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidehat, parseLatexString(true)));
} else if (currentInstructionName=="check" || currentInstructionName=="v") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcheck, parseLatexString(true)));
} else if (currentInstructionName=="widecheck") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidecheck, parseLatexString(true)));
} else if (currentInstructionName=="bar") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbar, parseLatexString(true)));
} else if (currentInstructionName=="dot" || currentInstructionName==".") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdot, parseLatexString(true)));
} else if (currentInstructionName=="ocirc") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDocirc, parseLatexString(true)));
} else if (currentInstructionName=="tilde" || currentInstructionName=="~") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDtilde, parseLatexString(true)));
} else if (currentInstructionName=="breve" || currentInstructionName=="u") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbreve, parseLatexString(true)));
} else if (currentInstructionName=="widetilde") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidetilde, parseLatexString(true)));
} else if (currentInstructionName=="ddot") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDddot, parseLatexString(true)));
} else if (currentInstructionName=="cancel") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcancel, parseLatexString(true)));
} else if (currentInstructionName=="xcancel") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDxcancel, parseLatexString(true)));
} else if (currentInstructionName=="bcancel") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbcancel, parseLatexString(true)));
} else if (currentInstructionName=="strike" || currentInstructionName=="st" || currentInstructionName=="sout") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDstrike, parseLatexString(true)));
} else {
if (currentInstructionName=="textcolor" || currentInstructionName=="mathcolor" || currentInstructionName=="color" || currentInstructionName=="colorbox") {
bool foundError=true;
QString col="";
if (getToken()==MTTtext) {
col=currentTokenName;
if (getToken()==MTTclosebrace) {
if (getToken()==MTTopenbrace) {
foundError=false;
}
}
}
if (foundError) error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
else nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true), QStringList(col)));
} else {
nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true)));
}
}
if (getNew) getToken();
if (currentToken==MTTinstruction && currentTokenName=="limits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true);
getNew=true;
} else if (currentToken==MTTinstruction && currentTokenName=="nolimits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false);
getNew=true;
} else {
getNew=false;
}
} else if (currentToken==MTTopenbracket && currentInstructionName!="left") {
//std::cout<<"found '[' after '"<<name.toStdString()<<"'\n";
if (currentInstructionName=="sqrt") {
JKQTMathTextNode* n1=parseLatexString(true, MTBTAny, "", true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
else error_list.append(tr("error @ ch. %1: expected one argument in '{' braces after '%2' command with an optional argument in []").arg(currentTokenID).arg(currentInstructionName));
if (n1 && n2) nl->addChild(new JKQTMathTextSqrtNode(this, n2, n1));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else {
nl->addChild(new JKQTMathTextTextNode(this, "[", false));
}
if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) {
nl->addChild(new JKQTMathTextWhitespaceNode(currentInstructionName, this));
} else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) {
nl->addChild(new JKQTMathTextSymbolNode(this, currentInstructionName, false));
} else {
bool subSuperscriptAboveBelowNode=false;
//std::cout<<"did not find '{' after '"<<name.toStdString()<<"'\n";
if (currentInstructionName=="right") {
if (currentToken==MTTtext) {
if (currentTokenName.size()>0) {
bool tokenWasNoBrace=false;
const QString firstTokenChar(currentTokenName[0]);
if (TokenNameMatchesJKQTMathTextBraceType(firstTokenChar, quitOnClosingBrace, true, &tokenWasNoBrace)) {
if (quitOnClosingBrace!=MTBTAny) currentTokenName=currentTokenName.right(currentTokenName.size()-1);
getToken(); // look at next token
if (currentToken==MTTopenbrace) {
//std::cout<<"found '{' after '"<<name.toStdString()<<"'\n";
if (currentInstructionName=="sqrt") {
nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true)));
} else if (currentInstructionName=="cbrt") {
nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true), new JKQTMathTextTextNode(this, "3", false)));
} else if (currentInstructionName=="verb") {
QString text="";
currentTokenID++;
if (currentTokenID<=parseString.size()-1) {
QChar c=parseString[currentTokenID];
while (c!='}' && (currentTokenID<parseString.size())) {
text=text+c;
currentTokenID++;
if (currentTokenID<parseString.size()) c=parseString[currentTokenID];
}
if (c!='}') error_list.append(tr("error @ ch. %1: \verb{...} not closed by '}'").arg(currentTokenID).arg(currentInstructionName));
nl->addChild(new JKQTMathTextTextNode(this, text, false));
}
} else if (currentInstructionName=="frac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="dfrac" || currentInstructionName=="cfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMdfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="sfrac" || currentInstructionName=="slantfrac" || currentInstructionName=="xfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMsfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="stfrac" || currentInstructionName=="nicefrac" || currentInstructionName=="slanttextfrac" || currentInstructionName=="xtfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="tfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMtfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="stackrel") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="binom") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel)));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="underbrace") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbrace));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="underbracket") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbracket));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="underset") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderset));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="overbrace") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbrace));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="overbracket") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbracket));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="overset") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverset));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="begin") {
if (getToken()==MTTtext) {
QString envname=currentTokenName;
while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name'
if (envname=="matrix" || envname=="array" || envname=="aligned" || envname=="align" || envname=="cases" || envname=="pmatrix"|| envname=="bmatrix"|| envname=="Bmatrix"|| envname=="vmatrix"|| envname=="Vmatrix") {
QVector< QVector<JKQTMathTextNode*> > items;
//int lines=0;
//int cols=0;
bool first=true;
QVector<JKQTMathTextNode*> line;
//std::cout<<"found \\begin{matrix}\n";
while (first || currentToken==MTTampersand || (currentToken==MTTinstruction && currentTokenName=="\\")) {
JKQTMathTextNode* it=parseLatexString(true, MTBTAny, envname);
if (currentToken==MTTampersand) {
//std::cout<<" appending item\n";
line.append(it);
} else {
line.append(it);
//std::cout<<" appending item and line with "<<line.size()<<" items.\n";
items.append(line);
line.clear();
}
first=false;
}
//std::cout<<" creating matrix-node with "<<items.size()<<" items.\n";
if (envname=="pmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="cases") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTNone, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTCurlyBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSingleLine, MTBTSingleLine, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTDoubleLine, MTBTDoubleLine, new JKQTMathTextMatrixNode(this, items)));
else nl->addChild(new JKQTMathTextMatrixNode(this, items));
//std::cout<<" creating matrix-node ... done!\n";
} else {
error_list.append(tr("error @ ch. %1: unknown environment '%2'").arg(currentTokenID).arg(envname));
}
} else { // find next '}'
error_list.append(tr("error @ ch. %1: text after '\\begin{' expected!").arg(currentTokenID));
while (currentToken!=MTTclosebrace) getToken();
getNew=true;
}
} else if (currentInstructionName=="end") {
if (getToken()==MTTtext) {
QString envname=currentTokenName;
while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name'
if (envname==quitOnEnvironmentEnd) {
break;
} else {
getNew=false;
error_list.append(tr("error @ ch. %1: '\\end{%2}' widthout preceding '\\begin{%3}'").arg(currentTokenID).arg(envname).arg(envname));
}
} else { // find next '}'
error_list.append(tr("error @ ch. %1: text after '\\begin{' expected!").arg(currentTokenID));
while (currentToken!=MTTclosebrace) getToken();
getNew=true;
}
} else if (currentToken==MTTinstruction) {
if (InstructionNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
}
} else if (currentToken==MTTclosebracket) {
if (quitOnClosingBrace==MTBTSquareBracket || quitOnClosingBrace==MTBTAny) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
}
} else if (currentInstructionName=="vec") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDvec, parseLatexString(true)));
} else if (currentInstructionName=="overline"||currentInstructionName=="oline"||currentInstructionName=="ol") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDoverline, parseLatexString(true)));
} else if (currentInstructionName=="underline"||currentInstructionName=="uline"||currentInstructionName=="ul") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDunderline, parseLatexString(true)));
} else if (currentInstructionName=="uuline"||currentInstructionName=="uul") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleunderline, parseLatexString(true)));
} else if (currentInstructionName=="ooline"||currentInstructionName=="ool") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleoverline, parseLatexString(true)));
} else if (currentInstructionName=="arrow"||currentInstructionName=="overrightarrow"||currentInstructionName=="overarrow") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDarrow, parseLatexString(true)));
} else if (currentInstructionName=="hat" || currentInstructionName=="^") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDhat, parseLatexString(true)));
} else if (currentInstructionName=="widehat") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidehat, parseLatexString(true)));
} else if (currentInstructionName=="check" || currentInstructionName=="v") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcheck, parseLatexString(true)));
} else if (currentInstructionName=="widecheck") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidecheck, parseLatexString(true)));
} else if (currentInstructionName=="bar") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbar, parseLatexString(true)));
} else if (currentInstructionName=="dot" || currentInstructionName==".") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdot, parseLatexString(true)));
} else if (currentInstructionName=="ocirc") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDocirc, parseLatexString(true)));
} else if (currentInstructionName=="tilde" || currentInstructionName=="~") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDtilde, parseLatexString(true)));
} else if (currentInstructionName=="breve" || currentInstructionName=="u") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbreve, parseLatexString(true)));
} else if (currentInstructionName=="widetilde") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidetilde, parseLatexString(true)));
} else if (currentInstructionName=="ddot") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDddot, parseLatexString(true)));
} else if (currentInstructionName=="cancel") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcancel, parseLatexString(true)));
} else if (currentInstructionName=="xcancel") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDxcancel, parseLatexString(true)));
} else if (currentInstructionName=="bcancel") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbcancel, parseLatexString(true)));
} else if (currentInstructionName=="strike" || currentInstructionName=="st" || currentInstructionName=="sout") {
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDstrike, parseLatexString(true)));
} else {
getNew=false;
}
} else if (currentInstructionName=="left") {
if (currentToken==MTTtext) {
if (currentTokenName.size()>0) {
const QString firstTokenChar(currentTokenName[0]);
const JKQTMathTextBraceType bracetype=TokenName2JKQTMathTextBraceType(firstTokenChar);
if (bracetype==MTBTNone) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
JKQTMathTextNode* cn=parseLatexString(currentTokenName.size()<=0, MTBTAny);
nl->addChild(new JKQTMathTextBraceNode(this, MTBTNone, bracetype, cn));
} else if (isPrintableJKQTMathTextBraceType(bracetype)) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1); // we already used the first character from the text token!
nl->addChild(new JKQTMathTextBraceNode(this, bracetype, bracetype, parseLatexString(currentTokenName.size()<=0, bracetype)));
} else {
getNew=false;
if (currentInstructionName=="textcolor" || currentInstructionName=="mathcolor" || currentInstructionName=="color" || currentInstructionName=="colorbox") {
bool foundError=true;
QString col="";
if (getToken()==MTTtext) {
col=currentTokenName;
if (getToken()==MTTclosebrace) {
if (getToken()==MTTopenbrace) {
foundError=false;
}
}
}
}
} else if (currentToken==MTTinstruction) {
const JKQTMathTextBraceType bracetypeopening=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName);
if (bracetypeopening!=MTBTUnknown) {
nl->addChild(new JKQTMathTextBraceNode(this, bracetypeopening, bracetypeopening, parseLatexString(true, bracetypeopening)));
} else if (currentToken==MTTinstruction && TokenNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
break;
}
} else if (currentToken==MTTopenbracket) {
nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, parseLatexString(true, MTBTSquareBracket)));
} else {
error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID));
}
if (foundError) error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
else nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true), QStringList(col)));
} else {
nl->addChild(new JKQTMathTextSymbolNode(this, currentInstructionName, false));
static QSet<QString> subsupOperations= (QSet<QString>()<<"sum"<<"prod"<<"coprod"
<<"bigcap"<<"bigcup"<<"bigvee"<<"bighat"
<<"int"<<"iint"<<"iiint"<<"oint"<<"oiint"<<"oiiint"
<<"mod"<<"median"<<"max"<<"min"<<"argmax"<<"argmin"<<"sup"<<"inf"
<<"liminf"<<"limsup"<<"lim"<<"max"<<"min");
if (subsupOperations.contains(currentInstructionName) && parsingMathEnvironment) {
nl->getLastChild()->setSubSuperscriptAboveBelowNode(true);
} else {
nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true)));
}
}
if (getNew) getToken();
if (currentToken==MTTinstruction && currentTokenName=="limits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true);
getNew=true;
} else if (currentToken==MTTinstruction && currentTokenName=="nolimits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false);
getNew=true;
} else {
getNew=false;
}
} else if (currentToken==MTTopenbracket && currentInstructionName!="left") {
//std::cout<<"found '[' after '"<<name.toStdString()<<"'\n";
if (currentInstructionName=="sqrt") {
JKQTMathTextNode* n1=parseLatexString(true, MTBTAny, "", true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
else error_list.append(tr("error @ ch. %1: expected one argument in '{' braces after '%2' command with an optional argument in []").arg(currentTokenID).arg(currentInstructionName));
if (n1 && n2) nl->addChild(new JKQTMathTextSqrtNode(this, n2, n1));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else {
nl->addChild(new JKQTMathTextTextNode(this, "[", false));
}
} else {
bool subSuperscriptAboveBelowNode=false;
//std::cout<<"did not find '{' after '"<<name.toStdString()<<"'\n";
if (currentInstructionName=="right") {
if (currentToken==MTTtext) {
if (currentTokenName.size()>0) {
bool tokenWasNoBrace=false;
const QString firstTokenChar(currentTokenName[0]);
if (TokenNameMatchesJKQTMathTextBraceType(firstTokenChar, quitOnClosingBrace, true, &tokenWasNoBrace)) {
if (quitOnClosingBrace!=MTBTAny) currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else {
getNew=false;
}
}
} else if (currentToken==MTTinstruction) {
if (InstructionNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
}
} else if (currentToken==MTTclosebracket) {
if (quitOnClosingBrace==MTBTSquareBracket || quitOnClosingBrace==MTBTAny) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
}
} else {
getNew=false;
}
} else if (currentInstructionName=="left") {
if (currentToken==MTTtext) {
if (currentTokenName.size()>0) {
const QString firstTokenChar(currentTokenName[0]);
const JKQTMathTextBraceType bracetype=TokenName2JKQTMathTextBraceType(firstTokenChar);
if (bracetype==MTBTNone) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
JKQTMathTextNode* cn=parseLatexString(currentTokenName.size()<=0, MTBTAny);
nl->addChild(new JKQTMathTextBraceNode(this, MTBTNone, bracetype, cn));
} else if (isPrintableJKQTMathTextBraceType(bracetype)) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1); // we already used the first character from the text token!
nl->addChild(new JKQTMathTextBraceNode(this, bracetype, bracetype, parseLatexString(currentTokenName.size()<=0, bracetype)));
} else {
getNew=false;
}
}
} else if (currentToken==MTTinstruction) {
const JKQTMathTextBraceType bracetypeopening=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName);
if (bracetypeopening!=MTBTUnknown) {
nl->addChild(new JKQTMathTextBraceNode(this, bracetypeopening, bracetypeopening, parseLatexString(true, bracetypeopening)));
} else if (currentToken==MTTinstruction && TokenNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
break;
}
} else if (currentToken==MTTopenbracket) {
nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, parseLatexString(true, MTBTSquareBracket)));
} else {
error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID));
}
} else if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) {
nl->addChild(new JKQTMathTextWhitespaceNode(currentInstructionName, this));
} else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) {
nl->addChild(new JKQTMathTextSymbolNode(this, currentInstructionName, false));
static QSet<QString> subsupOperations= (QSet<QString>()<<"sum"<<"prod"<<"coprod"
<<"bigcap"<<"bigcup"<<"bigvee"<<"bighat"
<<"int"<<"iint"<<"iiint"<<"oint"<<"oiint"<<"oiiint"
<<"mod"<<"median"<<"max"<<"min"<<"argmax"<<"argmin"<<"sup"<<"inf"
<<"liminf"<<"limsup"<<"lim"<<"max"<<"min");
if (subsupOperations.contains(currentInstructionName) && parsingMathEnvironment) {
nl->getLastChild()->setSubSuperscriptAboveBelowNode(true);
}
if (currentToken==MTTinstruction && currentTokenName=="limits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true);
} else if (currentToken==MTTinstruction && currentTokenName=="nolimits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false);
} else {
getNew=false;
}
} else {
error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName));
}
}
}
} else if (currentToken==MTTwhitespace) {
@ -1481,12 +1494,14 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
getToken(); // look at next token
if (currentToken==MTTopenbrace) {
child=new JKQTMathTextInstruction1Node(this, name, parseLatexString(true));
} else {
//bool addWhite=(currentToken==MTTwhitespace);
//getNew=addWhite;
//child=new JKQTMathTextSymbolNode(this, name, addWhite);
} else if (JKQTMathTextWhitespaceNode::supportsInstructionName(name)) {
getNew=false;
child=new JKQTMathTextWhitespaceNode(name, this);
} else if (JKQTMathTextSymbolNode::hasSymbol(name)) {
getNew=false;
child=new JKQTMathTextSymbolNode(this, name, false);
} else {
error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(name));
}
} else if (currentToken==MTTopenbrace) {
child=parseLatexString(true);
@ -1507,16 +1522,20 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
JKQTMathTextNode* child=nullptr;
JKQTMathTextNode* child2=nullptr;
if (currentToken==MTTinstruction) {
QString name=currentTokenName;
getToken(); // look at next token
if (currentToken==MTTopenbrace) {
child=new JKQTMathTextInstruction1Node(this, name, parseLatexString(true));
const QString currentInstructionName=currentTokenName;
if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) {
getNew=true;
nl->addChild(new JKQTMathTextWhitespaceNode(currentInstructionName, this));
} else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)){
getNew=true;
child=new JKQTMathTextSymbolNode(this, currentInstructionName, false);
} else {
//bool addWhite=(currentToken==MTTwhitespace);
//getNew=addWhite;
//child=new JKQTMathTextSymbolNode(this, name, addWhite);
getNew=false;
child=new JKQTMathTextSymbolNode(this, name, false);
getToken(); // look at next token
if (currentToken==MTTopenbrace) {
child=new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true));
} else {
error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName));
}
}
} else if (currentToken==MTTopenbrace) {
child=parseLatexString(true);

View File

@ -186,18 +186,19 @@ class JKQTMathTextNode; // forward
\section JKQTMathTextSuppoertedFonts Font Handling
Several fonts are defined as properties to the class:
- A "roman" font used as the standard font ( setFontRoman() )
- A "sans-serif" font which may be activated with \c \\sf ... ( setFontSans() )
- A "typewriter" font which may be activated with \c \\tt ... ( setFontTypewriter() )
- A "script" font which may be activated with \c \\script ... ( setFontScript() )
- A greek font which is used to display greek letters \c \\alpha ... ( setSymbolfontGreek() )
- A symbol font used to display special (math) symbols. ( setSymbolfontSymbol() )
- A "roman" font used as the standard font in math mode ( setFontMathRoman() )
- A "sans-serif" used as sans serif font in math mode ( setFontMathSans() )
- A "blackboard" font used to display double stroked characters ( setFontBlackboard() )
- A "caligraphic" font used to display caligraphic characters ( setFontCaligraphic() )
- A "roman" (MTEroman / MTEmathRoman) font used as the standard font ( setFontRoman() and for use in math mode setFontMathRoman() )
- A "sans-serif" (MTEsans / MTEmathSans) font which may be activated with \c \\sf ... ( setFontSans() and for use in math mode setFontMathSans() )
- A "typewriter" (MTEtypewriter) font which may be activated with \c \\tt ... ( setFontTypewriter() )
- A "script" (MTEscript) font which may be activated with \c \\script ... ( setFontScript() )
- A "math-roman" (MTEmathRoman) font used as the standard font in math mode ( setFontMathRoman() )
- A "math-sans-serif" (MTEmathSans) used as sans serif font in math mode ( setFontMathSans() )
- A "blackboard" (MTEblackboard) font used to display double stroked characters ( setFontBlackboard() )
- A "caligraphic" (MTEcaligraphic) font used to display caligraphic characters ( setFontCaligraphic() )
- A "fraktur" (MTEfraktur) font used to display fraktur characters ( setFontFraktur() )
- A fallback font MTEFallbackGreek for greek letter (if the letters are not present in the currently used font) \c \\alpha ... ( setFallbackFontGreek() )
- A fallback font MTEFallbackSymbols for (math) symbols (if the symbols are not present in the currently used font). ( setFallbackFontSymbols() )
.
These fonts are generic font classes, which font is actually used can be configured in JKQTMathText class with the \c set...() functions mentioned above. You can also use these functions to set the fonts used for math rendering in math-mode:
- useSTIX() use the STIX fonts from <a href="https://www.stixfonts.org/">https://www.stixfonts.org/</a> in math-mode<br>\image html jkqtmathtext/jkqtmathparser_stix.png
- useXITS() use the XITS fonts from <a href="https://github.com/alif-type/xits">https://github.com/alif-type/xits</a> in math-mode. These are included by default in this library and also activated by default.<br>\image html jkqtmathtext/jkqtmathparser_xits.png
@ -208,11 +209,16 @@ class JKQTMathTextNode; // forward
<br>using "Comic Sans MS": \image html jkqtmathtext/jkqtmathparser_comicsans.png
.
Math-mode is activated by enclosing your equation in \c $...$ or \c \\[...\\] . This mode is optimized for mathematical equations. Here is an example of the difference:
- <b>math-mode (XITS fonts are used, whitespaces are mostly not drawn directly, symbol spacing is different)</b> \c $...$: <br>\image html jkqtmathtext/schreq_mathmode.png
- <b>normal mode (Times new Roman is used, whitespaces are evaluated directly)</b>: <br>\image html jkqtmathtext/schreq_normalmode.png
- <b>math-mode (MTEmathRoman and MTEmathSans, whitespaces are mostly not drawn directly, symbol spacing is different)</b> \c $...$: <br>\image html jkqtmathtext/schreq_mathmode.png
- <b>normal mode (MTEroman and MTEsans is used, whitespaces are evaluated directly)</b>: <br>\image html jkqtmathtext/schreq_normalmode.png
.
Font Lookup for symbols works as follows in JKQTMathTextSymbolNode:
- if a character is found in the current (or to be used) font, it is taken from there
- if the character is not found, it is looked for in the fallback fonts MTEFallbackGreek and MTEFallbackSymbols
- as a last resort, some symbols can be created otherwise, so if neither of the two options above
contain the required symbol, the symbol might be synthesized otherwise, or a rectangle with the size of "X" is drawn instead
\section JKQTMathTextToHTML Convert to HTML
@ -291,16 +297,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
/** \brief retrieves a replacement for the given font name \a nonUseFont, including its encoding. Returns the given default values \a defaultFont and/or \a defaultFontEncoding if one of the two is not found */
QPair<QString, JKQTMathTextFontEncoding> getReplacementFont(const QString &nonUseFont, const QString &defaultFont, JKQTMathTextFontEncoding defaultFontEncoding) const;
/** \brief font subclasses, used by getFontData() */
enum class FontSubclass {
Text,
Default=Text,
Symbols,
Greek,
};
/** \brief retrieve the font and encoding to be used for \a font, which might optionally be typeset inside a math environment, specified by in_math_environment, possibly for the given font subclass \a subclass */
QPair<QString, JKQTMathTextFontEncoding> getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment=false, FontSubclass subclass=FontSubclass::Default) const;
QPair<QString, JKQTMathTextFontEncoding> getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment=false) const;
/*! \brief calls setFontRoman(), or calls useXITS() if \a __value \c =="XITS". calls useSTIX() if \a __value \c =="STIX", ...
@ -344,22 +342,18 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
/** \brief retrieves the font to be used for text in the logical font MTEblackboard */
QString getFontBlackboard() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for greek letters in the logical font \a font */
void setSymbolfontGreek(JKQTMathTextEnvironmentFont font, const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief set the font \a fontName and it's encoding \a encoding to be used for integrals in all logical fonts */
void setSymbolfontGreek(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
void setFallbackFontGreek(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for greek letters in the logical font \a font */
QString getSymbolfontGreek(JKQTMathTextEnvironmentFont font) const;
QString getFallbackFontGreek() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for symbols in the logical font \a font */
void setSymbolfontSymbol(JKQTMathTextEnvironmentFont font, const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief set the font \a fontName and it's encoding \a encoding to be used for integrals in all logical fonts */
void setSymbolfontSymbol(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
void setFallbackFontSymbols(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for symbols in the logical font \a font */
QString getSymbolfontSymbol(JKQTMathTextEnvironmentFont font) const;
QString getFallbackFontSymbols() const;
/** \brief retrieves the encoding used for the symbol font to be used for symbols in the logical font \a font */
JKQTMathTextFontEncoding getSymbolfontEncodingSymbol(JKQTMathTextEnvironmentFont font) const;
/** \brief retrieves the encoding used for the greek letter font to be used for symbols in the logical font \a font */
JKQTMathTextFontEncoding getSymbolfontEncodingGreek(JKQTMathTextEnvironmentFont font) const;
/** \brief retrieves the encoding used for the symbol font to be used for symbols */
JKQTMathTextFontEncoding getFontEncodingFallbackFontSymbols() const;
/** \brief retrieves the encoding used for the greek letter font to be used for greek letters */
JKQTMathTextFontEncoding getFontEncodingFallbackFontGreek() const;
/** \brief retrieves the encoding used for the script font */
JKQTMathTextFontEncoding getFontEncodingScript() const;
/** \brief retrieves the encoding used for the Fraktur font */
@ -430,7 +424,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
* <code>useAnyUnicode("Comic Sans MS", "Comic Sans MS")</code>:<br>\image html jkqtmathtext/jkqtmathparser_comicsans.png <br><br>
*
*/
void useAnyUnicode(QString timesFont=QString(""), const QString& sansFont=QString(""), JKQTMathTextFontEncoding encodingTimes=JKQTMathTextFontEncoding::MTFEunicode, JKQTMathTextFontEncoding encodingSans=JKQTMathTextFontEncoding::MTFEunicode);
void useAnyUnicode(QString timesFont=QString(""), const QString& sansFont=QString(""), JKQTMathTextFontEncoding encodingTimes=JKQTMathTextFontEncoding::MTFEUnicode, JKQTMathTextFontEncoding encodingSans=JKQTMathTextFontEncoding::MTFEUnicode);

View File

@ -317,10 +317,9 @@ JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getSTIXFamilies()
QString JKQTMathTextFontEncoding2String(JKQTMathTextFontEncoding e)
{
switch(e) {
case MTFEunicode: return "MTFEunicode";
case MTFEStandard: return "MTFEStandard";
case MTFEunicodeLimited: return "MTFEunicodeLimited";
case MTFEwinSymbol: return "MTFEwinSymbol";
case MTFEUnicode: return "MTFEUnicode";
case MTFEStandard: return "MTFELatin1";
case MTFEWinSymbol: return "MTFEWinSymbol";
}
return "???";
}
@ -429,6 +428,33 @@ JKQTMathTextEnvironment::JKQTMathTextEnvironment() {
insideMath=false;
}
JKQTMathTextFontEncoding JKQTMathTextEnvironment::getFontEncoding(JKQTMathText* parent) const {
switch (font) {
case MTEsans: if (insideMath) {
return parent->getFontEncodingMathSans();
} else {
return parent->getFontEncodingSans();
}
break;
case MTEmathSans: return parent->getFontEncodingMathSans(); break;
case MTEtypewriter: return parent->getFontEncodingTypewriter(); break;
case MTEscript: return parent->getFontEncodingScript(); break;
case MTEcaligraphic: return parent->getFontEncodingCaligraphic(); break;
case MTEblackboard: return parent->getFontEncodingBlackboard(); break;
case MTEfraktur: return parent->getFontEncodingFraktur(); break;
case MTEmathRoman: return parent->getFontEncodingMathRoman(); break;
case MTEroman: if (insideMath) {
return parent->getFontEncodingMathRoman();
} else {
return parent->getFontEncodingRoman();
}
break;
default:
return MTFEStandard;
}
return MTFEStandard;
}
QFont JKQTMathTextEnvironment::getFont(JKQTMathText* parent) const {
QFont f;
switch (font) {
@ -445,6 +471,9 @@ QFont JKQTMathTextEnvironment::getFont(JKQTMathText* parent) const {
case MTEblackboard: f.setFamily(parent->getFontBlackboard()); break;
case MTEfraktur: f.setFamily(parent->getFontFraktur()); break;
case MTEmathRoman: f.setFamily(parent->getFontMathRoman()); break;
case MTEFallbackSymbols: f.setFamily(parent->getFallbackFontSymbols()); break;
case MTEFallbackGreek: f.setFamily(parent->getFallbackFontGreek()); break;
case MTECustomFont: f.setFamily(customFontName); break;
default:
case MTEroman: if (insideMath) {
f.setFamily(parent->getFontMathRoman());
@ -503,9 +532,7 @@ JKQTMathTextNodeSize::JKQTMathTextNodeSize():
JKQTMathTextFontDefinition::JKQTMathTextFontDefinition():
fontName("Times New Roman"), fontEncoding(MTFEStandard),
symbolfontGreek("Symbol"), symbolfontGreekEncoding(MTFEwinSymbol),
symbolfontSymbol("Symbol"), symbolfontSymbolEncoding(MTFEwinSymbol)
fontName("Times New Roman"), fontEncoding(MTFEStandard)
{
}
@ -704,3 +731,17 @@ bool isPrintableJKQTMathTextBraceType(JKQTMathTextBraceType type)
{
return (type!=MTBTAny) && (type!=MTBTUnknown);
}
JKQTMathTextFontEncoding estimateJKQTMathTextFontEncoding(QFont font)
{
font.setStyleStrategy(QFont::NoFontMerging);
const QString fontFamily=font.family().toLower();
if (fontFamily=="symbol") return JKQTMathTextFontEncoding::MTFEWinSymbol;
if (fontFamily.startsWith("xits") || fontFamily.startsWith("stix")||fontFamily.startsWith("asana")) return JKQTMathTextFontEncoding::MTFEUnicode;
const QFontMetricsF fm(font);
if (fm.inFont(QChar(0x3B1))) return JKQTMathTextFontEncoding::MTFEUnicode; // griechisch alpha
if (fm.inFont(QChar(0x2192))) return JKQTMathTextFontEncoding::MTFEUnicode; // pfeil nach rechts
if (fm.inFont(QChar(0x2202))) return JKQTMathTextFontEncoding::MTFEUnicode; // partial
if (fm.inFont(QChar(0x2208))) return JKQTMathTextFontEncoding::MTFEUnicode; // element
return JKQTMathTextFontEncoding::MTFELatin1;
}

View File

@ -126,12 +126,19 @@ private:
* \ingroup jkqtmathtext_tools
*/
enum JKQTMathTextFontEncoding {
MTFEwinSymbol, /*!< \brief This assumes that symbols shall be taken from a MS Windows style Symbol font */
MTFEunicode, /*!< \brief This assumes that symbols shall be taken from a Unicode font (e.g. the STIX fonts from <a href="http://www.stixfonts.org/">http://www.stixfonts.org/</a>)*/
MTFEunicodeLimited, /*!< \brief This assumes that the fonts used are Unicode, but only offer a limited set of symbols. Especially math symbols are missing from this encoding */
MTFEStandard, /*!< \brief the encoding of a standard TTF font (i.e. we can only expect letters,number and not many special characters) */
MTFEWinSymbol=0, /*!< \brief This assumes that symbols shall be taken from a MS Windows style Symbol font */
MTFEUnicode=1, /*!< \brief This assumes that symbols shall be taken from a Unicode font, which ideally offers full symbol support (e.g. the XITS fonts, STIX fonts from <a href="http://www.stixfonts.org/">http://www.stixfonts.org/</a>)*/
MTFELatin1=2, /*!< \brief the encoding of a standard Latin1 TTF font (i.e. we can only expect letters,number and not many special characters) */
MTFEStandard=MTFELatin1
};
/** \brief this function tries to determine the JKQTMathTextFontEncoding of a given font (HEURISTICS!!!)
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontEncoding estimateJKQTMathTextFontEncoding(QFont font);
/** \brief convert MTfontEncoding to a string
* \ingroup jkqtmathtext_tools
*/
@ -213,7 +220,11 @@ enum JKQTMathTextEnvironmentFont {
MTEcaligraphic, /*!< \brief caligraphic font, e.g. <code>\\mathcal{}</code> */
MTEfraktur, /*!< \brief fraktur font, e.g. <code>\\mathfrak{}</code> */
MTenvironmentFontCount /*!< \brief internal enum value that allows to iterate over MTenvironmentFont \internal */
MTEEnvironmentFontCount, /*!< \brief internal enum value that allows to iterate over MTenvironmentFont \internal */
MTECurrentFont, /*!< \brief internal enum value that specifies that the currently set font shall be used \internal */
MTECustomFont, /*!< \brief internal enum value that specifies that a custom font specified elsewhere shall be used \internal */
MTEFallbackSymbols, /*!< \brief symbol font */
MTEFallbackGreek, /*!< \brief greek letters font */
};
@ -226,6 +237,8 @@ struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextEnvironment {
QColor color;
/** \brief current font */
JKQTMathTextEnvironmentFont font;
/** \brief custom font, when font==MTECustomFont */
QString customFontName;
/** \brief current font size [pt] */
double fontSize;
/** \brief is the text currently bold? */
@ -246,6 +259,8 @@ struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextEnvironment {
/** \brief build a QFont object from the settings in this object */
QFont getFont(JKQTMathText* parent) const;
/** \brief return the encoding of the given Font */
JKQTMathTextFontEncoding getFontEncoding(JKQTMathText *parent) const;
/** \brief generate a HTML prefix that formats the text after it according to the settings in this object
*
* \param defaultEv environment before applying the current object (to detect changes)
@ -281,15 +296,6 @@ struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontDefinition {
QString fontName;
/** \brief specifies the encoding of the font (default is \c MTFEwinSymbol ) */
JKQTMathTextFontEncoding fontEncoding;
/** \brief symbol font used for greek symbols, or empty when \a fontName shall be used */
QString symbolfontGreek;
/** \brief specifies the encoding of symbolfontGreek */
JKQTMathTextFontEncoding symbolfontGreekEncoding;
/** \brief symbol font, used for math symbols, or empty when \a fontName shall be used */
QString symbolfontSymbol;
/** \brief specifies the encoding of symbolfontSymbol */
JKQTMathTextFontEncoding symbolfontSymbolEncoding;
};

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
#include <cstdint>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
@ -34,6 +35,25 @@ class JKQTMathText; // forward
/** \brief subclass representing one symbol (e.g. \c \\alpha , \c \\cdot ...) node in the syntax tree
* \ingroup jkqtmathtext_items
*
* All supported symbols are stored in the static table symbols, which is filled by fillSymbolTable().
* The latter function is also the customization point for new symbols:
* - For each symbol, the instruction name is stored as key, e.g. for \c \\alpha the key \c "alpha" is stored.
* - for each instruction a SymbolFullProps describes the symbol and stores how to draw it.
* - Each symbol has global properties (GlobalSymbolFlags, e.g. how to treat it's with etz.) and a set of representations.
* Each representation is for one font-encoding (JKQTMathTextFontEncoding, i.e. Unicode, WinSymbol or Standard)
* - each encoding representation SymbolProps specifies a text to represent the symol in SymbolProps::symbol and
* can have additional flags, properties etc.
* .
*
* Font Lookup for symbols works as follows in JKQTMathTextSymbolNode:
* - if a character is found in the current (or to be used) font, it is taken from there (the font is specified in
* SymbolFullProps::fontType)
* - if the character is not found, it is looked for in the fallback fonts MTEFallbackGreek and MTEFallbackSymbols
* - as a last resort, some symbols can be created otherwise, so if neither of the two options above
* contain the required symbol, the symbol might be synthesized otherwise, or a rectangle with the size of "X" is drawn instead
* .
*
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
public:
@ -47,8 +67,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc symbolName */
QString getSymbolName() const;
/** \brief get font name of the symbol */
QString getSymbolfontName() const;
/** \copydoc addWhitespace */
bool getAddWhitespace() const;
/** \brief determine the size of the node, calls getSizeInternal() implementation of the actual type \see getSizeInternal()
@ -65,49 +83,186 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
*
*/
void getSymbolSize(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& subSuperXCorrection, double& subBesidesXCorrection, const JKQTMathTextNodeSize* prevNodeSize=nullptr);
/** \brief checks whether the given symbol name can be prepresented by this type of node */
static bool hasSymbol(const QString& symbolName);
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSymbolSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& subSuperXCorrection, double& subBesidesXCorrection, const JKQTMathTextNodeSize* prevNodeSize=nullptr) ;
/** \brief this string will be sent to the drawText method with properly set fonts */
QString symbolName;
/** \brief add a whitespace to the symbol? */
bool addWhitespace;
struct SymbolProps {
/** \brief the symbol name supplied to the constructor */
QString symbol;
/** \brief font to use for output */
QString font;
/** \brief magnification factor for the font size */
double fontFactor;
/** \brief 0: leave italic setting as is, >0: set italic, <0 set italic to false */
char italic;
/** \brief 0: leave bold setting as is, >0: set bold, <0 set bold to false */
char bold;
/** \brief this corrects the y position of a symbol: draws at y <- y+ height*yfactor) */
double yfactor;
/** \brief indicates whether to draw a bar (like for \c \\hbar ) */
bool drawBar;
bool heightIsAscent;
bool exactAscent;
bool extendWidthInMathmode;
/** \brief flags specifying additional symbol features */
enum SymbolFlags: uint64_t {
AsOutside= 0, /*!< \brief indicates that no properties are activated */
ItalicOn= 1 << 0, /*!< \brief make font italic in any case */
ItalicOff= 1 << 1, /*!< \brief make font non-italic (i.e. upright) in any case */
BoldOn= 1 << 2, /*!< \brief make font bold in any case */
BoldOff= 1 << 3, /*!< \brief make font non-bold (i,,e, normal weight) in any case */
DrawBar= 1 << 4, /*!< \brief indicates whether to draw a bar (like for \c \\hbar ) */
FlipUpDown=1 << 5, /*!< \brief indicates to flip the given symbol upside-down */
FlipLeftRight=1 << 6, /*!< \brief indicates to flip the given symbol left-right */
Rotate90=1 << 7, /*!< \brief indicates to rotate the symbol 90 degree */
DrawSlash=1 << 8, /*!< \brief indicates to overdraw a backslash (e.g. to combine 0 and / to form \\varnothing ) */
HeightIsAscent= 1 << 9, /*!< \brief if true, the height of the symbol equals the ascent of the font */
Upright=ItalicOff,
NormalWeight=BoldOff,
};
friend inline SymbolFlags operator~ (SymbolFlags a) { return (SymbolFlags)~static_cast<uint64_t>(a); }
friend inline SymbolFlags operator| (SymbolFlags a, SymbolFlags b) { return static_cast<SymbolFlags>(static_cast<uint64_t>(a) | static_cast<uint64_t>(b)); }
friend inline SymbolFlags operator& (SymbolFlags a, SymbolFlags b) { return static_cast<SymbolFlags>(static_cast<uint64_t>(a) & static_cast<uint64_t>(b)); }
friend inline SymbolFlags operator^ (SymbolFlags a, SymbolFlags b) { return static_cast<SymbolFlags>(static_cast<uint64_t>(a) ^ static_cast<uint64_t>(b)); }
friend inline SymbolFlags& operator|= (SymbolFlags& a, SymbolFlags b) { return reinterpret_cast<SymbolFlags&>(reinterpret_cast<uint64_t&>(a) |= static_cast<uint64_t>(b)); }
friend inline SymbolFlags& operator&= (SymbolFlags& a, SymbolFlags b) { return reinterpret_cast<SymbolFlags&>(reinterpret_cast<uint64_t&>(a) &= static_cast<uint64_t>(b)); }
friend inline SymbolFlags& operator^= (SymbolFlags& a, SymbolFlags b) { return reinterpret_cast<SymbolFlags&>(reinterpret_cast<uint64_t&>(a) ^= static_cast<uint64_t>(b)); }
friend inline bool has(SymbolFlags a, SymbolFlags b) { return (a&b)==b; }
/** \brief flags specifying additional symbol features */
enum GlobalSymbolFlags: uint64_t {
NoGLobalSymbolFlags= 0, /*!< \brief indicates that no properties are activated */
ExtendWidthInMathmode= 1 << 0, /*!< \brief this symbol has an extended width, when used within a moth-environment/in math-mode */
MakeWhitespaceHalf= 1 << 1, /*!< \brief symbol uses whitespaces in its text (SymbolProps::symbol). These should be typeset as half-spaces */
IntLikeSymbolCorrection= 1 << 2, /*!< \brief symbols, like \c \\int,\\iint,... require a correction in x-direction for subsequent sub-/superscripts ... this flag marks such symbols */
};
friend inline GlobalSymbolFlags operator~ (GlobalSymbolFlags a) { return (GlobalSymbolFlags)~static_cast<uint64_t>(a); }
friend inline GlobalSymbolFlags operator| (GlobalSymbolFlags a, GlobalSymbolFlags b) { return static_cast<GlobalSymbolFlags>(static_cast<uint64_t>(a) | static_cast<uint64_t>(b)); }
friend inline GlobalSymbolFlags operator& (GlobalSymbolFlags a, GlobalSymbolFlags b) { return static_cast<GlobalSymbolFlags>(static_cast<uint64_t>(a) & static_cast<uint64_t>(b)); }
friend inline GlobalSymbolFlags operator^ (GlobalSymbolFlags a, GlobalSymbolFlags b) { return static_cast<GlobalSymbolFlags>(static_cast<uint64_t>(a) ^ static_cast<uint64_t>(b)); }
friend inline GlobalSymbolFlags& operator|= (GlobalSymbolFlags& a, GlobalSymbolFlags b) { return reinterpret_cast<GlobalSymbolFlags&>(reinterpret_cast<uint64_t&>(a) |= static_cast<uint64_t>(b)); }
friend inline GlobalSymbolFlags& operator&= (GlobalSymbolFlags& a, GlobalSymbolFlags b) { return reinterpret_cast<GlobalSymbolFlags&>(reinterpret_cast<uint64_t&>(a) &= static_cast<uint64_t>(b)); }
friend inline GlobalSymbolFlags& operator^= (GlobalSymbolFlags& a, GlobalSymbolFlags b) { return reinterpret_cast<GlobalSymbolFlags&>(reinterpret_cast<uint64_t&>(a) ^= static_cast<uint64_t>(b)); }
friend inline bool has(GlobalSymbolFlags a, GlobalSymbolFlags b) { return (a&b)==b; }
/** \brief calculates the bounding rect of \a text using \a fm and taking the flags from \a globalFlags into account */
static QRectF getBoundingRect(const QFontMetricsF& fm, const QString& text, GlobalSymbolFlags globalFlags);
/** \brief calculates the tight bounding rect of \a text using \a fm and taking the flags from \a globalFlags into account */
static QRectF getTightBoundingRect(const QFontMetricsF& fm, const QString& text, GlobalSymbolFlags globalFlags);
/** \brief draw \a text at (0,0) using QPainter \a p and taking the flags from \a globalFlags into account */
static void drawText(QPainter &p, const QString &text, GlobalSymbolFlags globalFlags);
/** \brief properties of the symbol */
struct SymbolProps {
SymbolProps();
/** \brief this constructor sets the given properties and sets html=symbol! replaces whitespaces in \a _ymbol with \c &thinsp; for html, iff MakeWhitespaceHalf is set in \a _flags*/
SymbolProps(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
/** \brief the symbol or text used to render the symbol (i.e. not the name,
* e.g. if the instruction/symbol name \c \\int is used, this would be \c QChar(0xF2) ,
* for \c \\sin it would be \c QString("sin") ...) */
QString symbol;
/** \brief if \a symbol is a single character, this returns it, otherwise (empty or multi-character) it returns QChar() */
inline QChar getSymbolSingleChar() const {
if (symbol.size()==1) return symbol[0];
return QChar();
}
/** \brief flags switching special features */
SymbolFlags flags;
/** \brief magnification factor for the font size */
double fontScalingFactor;
/** \brief this corrects the y position of a symbol: draws at y <- y+ height*yfactor) */
double yShiftFactor;
};
/** \brief properties of the symbol, extends SymbolProps with font... */
struct SymbolFullProps {
/** \brief default constructor */
SymbolFullProps();
/** \brief typesets the symbol (described in \a props ) from the specified \a font, \a props is stored with encoding MTFEStandard, an optional HTML-string \A _html can be given */
SymbolFullProps(const QString& font, const SymbolProps& props, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief typesets the \a symbol from the specified \a font, \a props is stored with encoding MTFEStandard, an optional HTML-string \A _html can be given */
SymbolFullProps(const QString& font, const QString& symbol, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief \a props is stored with encoding MTFEStandard, an optional HTML-string \A _html can be given */
SymbolFullProps(const SymbolProps& props, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief \a props is stored with encoding MTFEStandard, uses the specified \a _fontType for drawing, an optional HTML-string \A _html can be given */
SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, const SymbolProps& props, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief takes a \a symbol from the specified \a _fontType assuming MTFEStandard encoding, an optional HTML-string \A _html can be given */
SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, const QString& symbol, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief single-alternative symbol for encoding \a enc0 and using symbol description \a props0 for it. An optional HTML-string \a _html can be provided */
SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps& props0, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief single-alternative symbol for encoding \a enc0 and using symbol description \a props0 for it, uses the specified \a _fontType for drawing. An optional HTML-string \a _html can be provided */
SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps& props0, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief double-alternative symbol for encoding \a enc0 + \a enc1 and using symbol descriptions \a props0 + \a props1 for it. An optional HTML-string \a _html can be provided */
SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps& props0, JKQTMathTextFontEncoding enc1, const SymbolProps& props1, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief double-alternative symbol for encoding \a enc0 + \a enc1 and using symbol descriptions \a props0 + \a props1 for it, uses the specified \a _fontType for drawing. An optional HTML-string \a _html can be provided */
SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps& props0, JKQTMathTextFontEncoding enc1, const SymbolProps& props1, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief triple-alternative symbol for encoding \a enc0 + \a enc1 + \a enc2 and using symbol descriptions \a props0 + \a props1 + \a props2 for it. An optional HTML-string \a _html can be provided */
SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps& props0, JKQTMathTextFontEncoding enc1, const SymbolProps& props1, JKQTMathTextFontEncoding enc2, const SymbolProps& props2, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief triple-alternative symbol for encoding \a enc0 + \a enc1 + \a enc2 and using symbol descriptions \a props0 + \a props1 + \a props2 for it, uses the specified \a _fontType for drawing. An optional HTML-string \a _html can be provided */
SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps& props0, JKQTMathTextFontEncoding enc1, const SymbolProps& props1, JKQTMathTextFontEncoding enc2, const SymbolProps& props2, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0);
/** \brief font type to use for typesetting the symbol (default is MTcurrentFont, which just takes the font set in the surrounding environment) */
JKQTMathTextEnvironmentFont fontType;
/** \brief font to use for output when fontType==MTcustomFont */
QString customFontFamily;
/** \brief here the actual symbol properties for each JKQTMathTextFontEncoding are stored */
QHash<JKQTMathTextFontEncoding, SymbolProps> props;
/** \brief HTML entity/text to represent the symbol (empty html.symbol not available) */
SymbolProps html;
/** \brief specifies global symbol flags */
GlobalSymbolFlags globalFlags;
SymbolFullProps &add(JKQTMathTextFontEncoding enc, const SymbolProps& props);
SymbolFullProps& addWinSymbol(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addMathOperatorWinSymbol(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addUprightWinSymbol(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addUnicode(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addUprightUnicode(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addMathOperatorUnicode(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addStd(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addMathOperatorStd(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addUprightStd(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addHtml(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addMathOperatorHtml(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addUprightHtml(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0);
SymbolFullProps& addGlobalFlags(GlobalSymbolFlags addglobalFlags);
SymbolFullProps& setGlobalFlags(GlobalSymbolFlags addglobalFlags);
/** \brief returns the QFont to use for drawing and the QString to draw with it */
QPair<QFont, SymbolProps> getDrawingData(JKQTMathTextEnvironment currentEv, JKQTMathText *parent) const;
};
/** \brief creates a SymbolFullProps object for a symbol that can be typeset in any font, for SymbolFullProps::html the same text as a\a symbol is used */
static SymbolFullProps SimpleTextSymbol(const QString& symbol);
/** \brief creates a SymbolFullProps object for a symbol that can be typeset in any font, a special html-string is given */
static SymbolFullProps SimpleTextSymbol(const QString& symbol, const QString& html);
/** \brief creates a SymbolFullProps object for a symbol that can be typeset in any font, for SymbolFullProps::html the same text as a\a symbol is used */
static SymbolFullProps SimpleUprightTextSymbol(const QString& symbol);
/** \brief creates a SymbolFullProps object for a symbol that can be typeset in any font, a special html-string is given */
static SymbolFullProps SimpleUprightTextSymbol(const QString& symbol, const QString& html);
/** \brief constructs a SymbolProps for a math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, ExtendWidthInMathmode */
static SymbolFullProps MathOperatorSymbol(const QString& op);
/** \brief constructs a SymbolProps with explicit HTML for a math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, ExtendWidthInMathmode */
static SymbolFullProps MathOperatorSymbol(const QString& op, const QString& ophtml);
/** \brief constructs a SymbolProps for a math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, HeightIsAscent, ExtendWidthInMathmode */
static SymbolFullProps MathOperatorText(const QString& op);
/** \brief constructs a SymbolProps with explicit HTML for a math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, HeightIsAscent, ExtendWidthInMathmode */
static SymbolFullProps MathOperatorText(const QString& op, const QString& ophtml);
/** \brief constructs a SymbolProps for greek letter with the symbol in unicode-encoding \a letterUnicode and in WinSymbol-encoding letterWinWsymbol */
static SymbolFullProps GreekLetter_WinSymbol_Unicode_Html(const QString& letterWinSymbol, const QString& letterUnicode, const QString& html);
/** \brief constructs a SymbolProps for a symbol with encoding in Standard-fonts a */
static SymbolFullProps SymbolStd(const QString& symbol, const QString& html=QString());
/** \brief constructs a SymbolProps for a symbol with encoding in UnicodeFull-fonts a */
static SymbolFullProps SymbolUnicode(const QString& symbol, const QString& html=QString());
/** \brief constructs a SymbolProps for a symbol with encoding in Standard-fonts a */
static SymbolFullProps UprightSymbolStd(const QString& symbol, const QString& html=QString());
/** \brief constructs a SymbolProps for a symbol with encoding in UnicodeFull-fonts a */
static SymbolFullProps UprightSymbolUnicode(const QString& symbol, const QString& html=QString());
/** \brief constructs a SymbolProps for a math-operator symbol like \c \\pm ... in unicode-full-encoding, i.e. ItalicOff, BoldOff, ExtendWidthInMathmode */
static SymbolFullProps MathOperatorSymbolUnicode(const QString& unicode);
/** \brief symbols that can be generated in any standard-font */
static QHash<QString, SymbolFullProps> symbols;
/** \brief fill the symbol tables standardTextSymbols, winSymbolSymbol, ... with contents */
static void fillSymbolTables();
/** \brief retrieve the properties to render the given symbol \a symName in the current environment \a currentEv */
SymbolProps getSymbolProp(const QString& symName, const JKQTMathTextEnvironment& currentEv) const;
/** \brief fill \a props for the symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using Unicode font (or WinSymbol as Fallback)*/
bool getSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n, const JKQTMathTextEnvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the greek letter symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using Unicode font (or WinSymbol as Fallback) */
bool getGreekSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n, const JKQTMathTextEnvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using WinSymbol font */
bool getWinSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n, const JKQTMathTextEnvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using any font, does not alter the font name!!! */
bool getStandardTextSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using any unicode font, does not alter the font name!!! */
bool getUnicodeBaseSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using a full unicode font, does not alter the font name!!! */
bool getUnicodeFullSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n, double mathFontFactor) const;
SymbolFullProps getSymbolProp(const QString& symName, const JKQTMathTextEnvironment& currentEv) const;
};
#endif // JKQTMATHTEXTSYMBOLNODE_H

View File

@ -63,7 +63,6 @@ void JKQTMathTextTextNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
text==QString(QChar(0x2329)) || text==QString(QChar(0x232A)) || text==QString(QChar(0x2308)) ||
text==QString(QChar(0x2309)) || text==QString(QChar(0x230A)) || text==QString(QChar(0x230B)))) {
f.setItalic(false);
//f.setFamily(parent->getFontData(currentEv.font, currentEv.insideMath, FontSubclass::Text).first);
}
QString txt=textTransform(text, currentEv, true);
QFontMetricsF fm(f, painter.device());
@ -200,7 +199,7 @@ QString JKQTMathTextTextNode::textTransform(const QString &text, JKQTMathTextEnv
{
QString txt=text;
auto fnt=parentMathText->getFontData(currentEv.font, currentEv.insideMath);
if (fnt.second==MTFEunicode || fnt.second==MTFEunicodeLimited) {
if (fnt.second==MTFEUnicode || fnt.second==MTFEUnicode) {
if (currentEv.insideMath) {
txt="";
for (int i=0; i<text.size(); i++) {
@ -244,21 +243,3 @@ QString MTplainTextNode::textTransform(const QString &_text, JKQTMathTextEnviron
}
JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(JKQTMathText *_parent):
JKQTMathTextTextNode(_parent, " ", false, false)
{
}
JKQTMathTextWhitespaceNode::~JKQTMathTextWhitespaceNode()
= default;
QString JKQTMathTextWhitespaceNode::getTypeName() const
{
return QLatin1String("JKQTMathTextWhitespaceNode(")+text+")";
}
bool JKQTMathTextWhitespaceNode::toHtml(QString &html, JKQTMathTextEnvironment /*currentEv*/, JKQTMathTextEnvironment /*defaultEv*/) {
html=html+"&nbsp;";
return true;
}

View File

@ -68,18 +68,6 @@ class JKQTMATHTEXT_LIB_EXPORT MTplainTextNode: public JKQTMathTextTextNode {
/** \copydoc JKQTMathTextTextNode::textTransform() */
virtual QString textTransform(const QString& text, JKQTMathTextEnvironment currentEv, bool forSize=false) override;
};
/** \brief subclass representing one whitepsace node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextWhitespaceNode: public JKQTMathTextTextNode {
public:
explicit JKQTMathTextWhitespaceNode(JKQTMathText* parent);
virtual ~JKQTMathTextWhitespaceNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
};
#endif // JKQTMATHTEXTTEXTNODE_H

View File

@ -0,0 +1,211 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 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 Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(Types type, JKQTMathText *_parent):
JKQTMathTextWhitespaceNode(type, 1, _parent)
{
}
JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(JKQTMathText *_parent):
JKQTMathTextWhitespaceNode(WSTNormal, 1, _parent)
{
}
JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(const QString &_type, JKQTMathText *parent):
JKQTMathTextWhitespaceNode(parent)
{
fillSupportedInstructions();
whitespace=supportedInstructions[_type];
}
JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(const QString &_type, size_t count, JKQTMathText *parent):
JKQTMathTextWhitespaceNode(parent)
{
fillSupportedInstructions();
whitespace=supportedInstructions[_type];
whitespace.count=whitespace.count*count;
}
JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(Types type, size_t count, JKQTMathText *parent):
JKQTMathTextNode(parent),
whitespace(type, count)
{
fillSupportedInstructions();
}
JKQTMathTextWhitespaceNode::~JKQTMathTextWhitespaceNode() {
}
QString JKQTMathTextWhitespaceNode::getTypeName() const
{
return QLatin1String("JKQTMathTextWhitespaceNode(")+Type2String(whitespace.type)+", count="+QString::number(whitespace.count)+")";
}
bool JKQTMathTextWhitespaceNode::toHtml(QString &html, JKQTMathTextEnvironment /*currentEv*/, JKQTMathTextEnvironment /*defaultEv*/) {
for (size_t i=0; i<whitespace.count; i++) {
html=html+Type2HTML(whitespace.type);
}
return true;
}
JKQTMathTextWhitespaceNode::WhitespaceProps::WhitespaceProps(JKQTMathTextWhitespaceNode::Types _type, size_t _count):
type(_type), count(_count)
{
}
JKQTMathTextWhitespaceNode::Types JKQTMathTextWhitespaceNode::getWhitespaceType() const
{
return whitespace.type;
}
size_t JKQTMathTextWhitespaceNode::getWhitespaceCount() const
{
return whitespace.count;
}
double JKQTMathTextWhitespaceNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize *prevNodeSize)
{
double width=0, bh=0, oh=0, sp=0;
getSize(painter, currentEv, width, bh, oh, sp, prevNodeSize);
return x+width;
}
void JKQTMathTextWhitespaceNode::getSizeInternal(QPainter &painter, JKQTMathTextEnvironment currentEv, double &width, double &baselineHeight, double &overallHeight, double &strikeoutPos, const JKQTMathTextNodeSize *prevNodeSize)
{
const double singelWidthPT=Type2PointWidth(whitespace.type, currentEv);
const double singelWidthPIX=singelWidthPT/72.0*painter.device()->logicalDpiX();
const QFontMetricsF fm(currentEv.getFont(parentMathText));
width=singelWidthPIX*static_cast<double>(whitespace.count);
baselineHeight=0;
overallHeight=0;
strikeoutPos=fm.strikeOutPos();
}
QHash<QString, JKQTMathTextWhitespaceNode::WhitespaceProps> JKQTMathTextWhitespaceNode::supportedInstructions;
void JKQTMathTextWhitespaceNode::fillSupportedInstructions()
{
if (supportedInstructions.size()==0) {
supportedInstructions[" "]=WhitespaceProps(WSTthicker, 1);
supportedInstructions["nbsp"]=WhitespaceProps(WSTNonbreaking, 1);
supportedInstructions["enspace"]=WhitespaceProps(WST1en, 1);
supportedInstructions["quad"]=supportedInstructions["emspace"]=WhitespaceProps(WSTQuad, 1);
supportedInstructions["qquad"]=WhitespaceProps(WSTQuad, 2);
supportedInstructions[","]=supportedInstructions["thinspace"]=WhitespaceProps(WSTthin, 1);
supportedInstructions[":"]=supportedInstructions["medspace"]=WhitespaceProps(WSTmedium, 1);
supportedInstructions[";"]=supportedInstructions["thickspace"]=WhitespaceProps(WSTthick, 1);
supportedInstructions["!"]=supportedInstructions["negthinspace"]=WhitespaceProps(WSTnegthin, 1);
supportedInstructions["negmedspace"]=WhitespaceProps(WSTnegmedium, 1);
supportedInstructions["negthickspace"]=WhitespaceProps(WSTnegthick, 1);
}
}
QString JKQTMathTextWhitespaceNode::Type2String(Types type)
{
switch (type) {
case WSTNormal: return "WSTNormal";
case WSTNonbreaking: return "WSTNonbreaking";
case WST1en: return "WST1en";
case WST1em: return "WST1em";
case WSThair: return "WSThair";
case WSTthin: return "WSTthin";
case WSTnegthin: return "WSTnegthin";
case WSTmedium: return "WSTmedium";
case WSTnegmedium: return "WSTnegmedium";
case WSTthick: return "WSTthick";
case WSTnegthick: return "WSTnegthick";
case WSTthicker: return "WSTthicker";
}
return "???";
}
double JKQTMathTextWhitespaceNode::Type2PointWidth(Types type, JKQTMathTextEnvironment currentEv) const
{
const double em=currentEv.fontSize;
const double en=em/2.0;
switch (type) {
case WSTNormal: return QFontMetricsF(currentEv.getFont(parentMathText)).width(' ');
case WSTNonbreaking: return QFontMetricsF(currentEv.getFont(parentMathText)).width(' ');
case WST1en: return en;
case WST1em: return em;
case WSThair: return em/12.0;
case WSTthin: return em/6.0;
case WSTnegthin: return -em/6.0;
case WSTmedium: return em*2.0/9.0;
case WSTnegmedium: return -em*2.0/9.0;
case WSTthick: return em*5.0/18.0;
case WSTnegthick: return -em*5.0/18.0;
case WSTthicker: return em/3.0;
}
return 0.0;
}
bool JKQTMathTextWhitespaceNode::supportsInstructionName(const QString &instruction)
{
fillSupportedInstructions();
return supportedInstructions.contains(instruction);
}
QString JKQTMathTextWhitespaceNode::Type2HTML(Types type)
{
switch (type) {
case WSTNonbreaking: return "&nbsp;";
case WST1en: return "&ensp;";
case WST1em: return "&emsp;";
case WSThair: return "&hairsp";
case WSTthin: return "&thinsp;";
case WSTnegthin: return "";
case WSTmedium: return "&emsp14;";
case WSTnegmedium: return "";
case WSTthick: return "&emsp13;";
case WSTnegthick: return "";
case WSTthicker: return "&thinsp;&thinsp;";
case WSTNormal:
default:
return " ";
}
return " ";
}

View File

@ -0,0 +1,115 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 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 Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTWHITESPACENODE_H
#define JKQTMATHTEXTWHITESPACENODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
/** \brief subclass representing one whitepsace node in the syntax tree
* \ingroup jkqtmathtext_items
*
* It can represent different types of spaces, see Types and different multiples of that space.
* so \c JKQTMathTextWhitespaceNode(WST1em,2,parent) will represent two 1em wide spaces, i.e. a 2em space.
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextWhitespaceNode: public JKQTMathTextNode {
public:
enum Types {
WSTNormal, /*!< \brief a normal-width whitespace */
WSTNonbreaking, /*!< \brief a normal-width, non-breaking whitespace */
WST1en, /*!< \brief 1en (= 0.5 * pointsize of the font) whitespace */
WST1em, /*!< \brief 1em (= pointsize of the font) whitespace */
WSTQuad=WST1em, /*!< \copydoc WST1em */
WSThair, /*!< \brief hair (thinner than thin) whitespace (1/12 em = pointsize/12) */
WSTthin, /*!< \brief thin whitespace (1/6 em = pointsize/6) */
WSTnegthin, /*!< \brief negative thin whitespace (-1/6 em = -pointsize/6) */
WSTmedium, /*!< \brief medium whitespace (2/9 em = pointsize*2/9) */
WSTnegmedium, /*!< \brief negative medium whitespace (-2/9 em = -pointsize*2/9) */
WSTthick, /*!< \brief thick whitespace (5/18 em = pointsize*5/18) */
WSTnegthick, /*!< \brief negative thick whitespace (-5/18 em = -pointsize*5/18) */
WSTthicker, /*!< \brief thicker whitespace (1/3 em = pointsize/3) */
};
/** \brief converts Types \a type into a string */
static QString Type2String(Types type);
/** \brief converts Types \a type into its width in points (pt), based on \a currentEv */
double Type2PointWidth(Types type, JKQTMathTextEnvironment currentEv) const;
/** \brief checks whether a given LaTeX instruction name is supported by this node class type */
static bool supportsInstructionName(const QString& instruction);
/** \brief constructs a node with count=1 and type=WSTNormal */
explicit JKQTMathTextWhitespaceNode(JKQTMathText* parent);
/** \brief constructs a node with count=1 and the width derived from the instruction name \a type */
explicit JKQTMathTextWhitespaceNode(const QString& type, JKQTMathText* parent);
/** \brief constructs a node with the specified \a count and the width derived from the instruction name \a type */
explicit JKQTMathTextWhitespaceNode(const QString& type, size_t count, JKQTMathText* parent);
/** \brief constructs a node with count=1 and the given \a type */
explicit JKQTMathTextWhitespaceNode(Types type, JKQTMathText* parent);
/** \brief constructs a node with the given \a type and \a count */
explicit JKQTMathTextWhitespaceNode(Types type, size_t cound, JKQTMathText* parent);
virtual ~JKQTMathTextWhitespaceNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \brief copydoc WhitespaceProps::type */
Types getWhitespaceType() const;
/** \brief copydoc WhitespaceProps::count */
size_t getWhitespaceCount() const;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \brief describes a whitespace */
struct WhitespaceProps {
WhitespaceProps(Types type=WSTNormal, size_t count=1);
/** \brief type of the whitespace represented by this node */
Types type;
/** \brief number of whitespaces of the given type, represented by this node (default: 1) */
size_t count;
};
/** \brief properties of the whitespace represented by this node */
WhitespaceProps whitespace;
/** \brief converts Types \a type into its HTML representation */
static QString Type2HTML(Types type);
/** \brief translation table between latex instruction and WhitespaceProps */
static QHash<QString, WhitespaceProps> supportedInstructions;
/** \brief initializes supportedInstructions */
static void fillSupportedInstructions();
};
#endif // JKQTMATHTEXTWHITESPACENODE_H