diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox
index afd3759644..c9ef022bd9 100644
--- a/doc/dox/whatsnew.dox
+++ b/doc/dox/whatsnew.dox
@@ -42,6 +42,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
IMPROVED: rendering and size calculation of decorations
IMPROVED/breaking: refactored symbol node JKQTMathTextSymbolNode and changed font-lookup!
IMPROVED/NEW/breaking: refactored whitespace-processing node JKQTMathTextWhitespaceNode, now all major LaTeX whitespace commands are supported properly
+ IMPROVED/NEW/breaking: refactored LaTeX parser in JKQTMathText
REMOVED/breaking: \v[a-zA-Z] and shorthand for \vec{a-zA-Z} was removed, implementation of \bbR,\bbC,... changed
NEW: now supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve
NEW: reworked drawing of decorations: improved appearance and positioning!
@@ -54,6 +55,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)
NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)
NEW: added \overbracket and \underbracket
+ NEW: added \shaded{color}{...}
NEW: added functions to set the font-size in pixels (as alternative to the existing functions that set them in points), implements request #76 from user:igormironchik
diff --git a/doc/images/jkqtmathtext/jkqtmathtext_boxed.png b/doc/images/jkqtmathtext/jkqtmathtext_boxed.png
index db2f7009d2..0b6f51a5e5 100644
Binary files a/doc/images/jkqtmathtext/jkqtmathtext_boxed.png and b/doc/images/jkqtmathtext/jkqtmathtext_boxed.png differ
diff --git a/doc/images/jkqtmathtext/jkqtmathtext_colorbox.png b/doc/images/jkqtmathtext/jkqtmathtext_colorbox.png
index c4eaa57e45..46a73b97e8 100644
Binary files a/doc/images/jkqtmathtext/jkqtmathtext_colorbox.png and b/doc/images/jkqtmathtext/jkqtmathtext_colorbox.png differ
diff --git a/doc/images/jkqtmathtext/jkqtmathtext_doublebox.png b/doc/images/jkqtmathtext/jkqtmathtext_doublebox.png
new file mode 100644
index 0000000000..c980bffe5d
Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_doublebox.png differ
diff --git a/doc/images/jkqtmathtext/jkqtmathtext_doubleovalbox.png b/doc/images/jkqtmathtext/jkqtmathtext_doubleovalbox.png
new file mode 100644
index 0000000000..e2724146ab
Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_doubleovalbox.png differ
diff --git a/doc/images/jkqtmathtext/jkqtmathtext_fcolorbox.png b/doc/images/jkqtmathtext/jkqtmathtext_fcolorbox.png
new file mode 100644
index 0000000000..b658a701f5
Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_fcolorbox.png differ
diff --git a/doc/images/jkqtmathtext/jkqtmathtext_oovalbox.png b/doc/images/jkqtmathtext/jkqtmathtext_oovalbox.png
new file mode 100644
index 0000000000..80e75768c7
Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_oovalbox.png differ
diff --git a/doc/images/jkqtmathtext/jkqtmathtext_ovalboxed.png b/doc/images/jkqtmathtext/jkqtmathtext_ovalboxed.png
new file mode 100644
index 0000000000..11b7956f4f
Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_ovalboxed.png differ
diff --git a/doc/images/jkqtmathtext/jkqtmathtext_shaded.png b/doc/images/jkqtmathtext/jkqtmathtext_shaded.png
new file mode 100644
index 0000000000..0186d2608b
Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_shaded.png differ
diff --git a/examples/jkqtmathtext_test/testform.cpp b/examples/jkqtmathtext_test/testform.cpp
index ae8ebb9427..99c29df114 100644
--- a/examples/jkqtmathtext_test/testform.cpp
+++ b/examples/jkqtmathtext_test/testform.cpp
@@ -191,7 +191,7 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbTestset->addItem("math: operator test (textmode)", "x=0\\ \\ y>0\\ \\ x+y\\ \\ -1\\ \\ x-2\\ \\ x\\cdot y\\ \\ x\\geq 4\\ \\ x~4");
ui->cmbTestset->addItem("math: operator test (mathmode)", "$x=0\\ \\ y>0\\ \\ x+y\\ \\ -1\\ \\ x-2\\ \\ x\\cdot y\\ \\ x\\geq 4\\ \\ x~4$");
ui->cmbTestset->addItem("text: color test", "\\textcolor{red}{RED}\\textcolor{blue}{BLUE}");
- ui->cmbTestset->addItem("text: boxed test", "test: \\boxed{boxed text} in the middle");
+ ui->cmbTestset->addItem("text: boxed test", "test: {\\backslash}boxed: \\boxed{boxed text} {\\backslash}doublebox: \\doublebox{boxed text} {\\backslash}ovalbox: \\ovalbox{boxed text} {\\backslash}Ovalbox: \\Ovalbox{boxed text} {\\backslash}ovaldoublebox: \\ovaldoublebox{boxed text} {\\backslash}colorbox\\{red\\}: \\colorbox{red}{boxed text} {\\backslash}shaded\\{AliceBlue\\}: \\shaded{AliceBlue}{boxed text} {\\backslash}fcolorbox\\{red\\}\\{AliceBlue\\}: \\fcolorbox{red}{AliceBlue}{boxed text} in the middle");
ui->cmbTestset->addItem("mathboxed test", "$\\fbox{2^{2^{\\colorbox{red}{2^{x}}}}}$");
ui->cmbTestset->addItem("axiom of power test", "$\\forall A \\, \\exists P \\, \\forall B \\, [B \\in P \\iff \\forall C \\, (C \\in B \\Rightarrow C \\in A)]$");
ui->cmbTestset->addItem("math: De Morgan's law", "$\\neg(P\\land Q)\\iff(\\neg P)\\lor(\\neg Q)$ or $\\overline{\\bigcap_{i \\in I} A_{i}}\\equiv\\bigcup_{i \\in I} \\overline{A_{i}}$ or $\\overline{A \\cup B}\\equiv\\overline{A} \\cap \\overline{B}$");
@@ -417,7 +417,8 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
JKQTMathTextWhitespaceNode* spN=dynamic_cast(node);
JKQTMathTextSymbolNode* symN=dynamic_cast(node);
JKQTMathTextListNode* lstN=dynamic_cast(node);
- JKQTMathTextInstruction1Node* inst1N=dynamic_cast(node);
+ JKQTMathTextModifiedTextPropsInstructionNode* inst1N=dynamic_cast(node);
+ JKQTMathTextBoxInstructionNode* inst1B=dynamic_cast(node);
JKQTMathTextSubscriptNode* subN=dynamic_cast(node);
JKQTMathTextSuperscriptNode* superN=dynamic_cast(node);
JKQTMathTextBraceNode* braceN=dynamic_cast(node);
@@ -465,8 +466,11 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
name=QString("MTsubscriptNode");
if (subN->getChild()) ti->addChild(createTree(subN->getChild(), ti));
} else if (inst1N) {
- name=QString("MTinstruction1Node: \'%1\' (subsuper=%2").arg(inst1N->getName()).arg(inst1N->isSubSuperscriptAboveBelowNode());
+ name=QString("ModTxtPropsInstructionNode: \'%1\' (subsuper=%2, params=%3)").arg(inst1N->getInstructionName()).arg(inst1N->isSubSuperscriptAboveBelowNode()).arg(inst1N->getParameters().join("/"));
if (inst1N->getChild()) ti->addChild(createTree(inst1N->getChild(), ti));
+ } else if (inst1B) {
+ name=QString("BoxInstructionNode: \'%1\' (subsuper=%2, params=%3)").arg(inst1B->getInstructionName()).arg(inst1B->isSubSuperscriptAboveBelowNode()).arg(inst1B->getParameters().join("/"));
+ if (inst1B->getChild()) ti->addChild(createTree(inst1B->getChild(), ti));
} else if (lstN) {
name=QString("MTlistNode");
QList list=lstN->getChildren();
diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp
index 1fee1e03d9..7ac5d97ad6 100644
--- a/lib/jkqtmathtext/jkqtmathtext.cpp
+++ b/lib/jkqtmathtext/jkqtmathtext.cpp
@@ -1154,232 +1154,147 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
} else {
nl->addChild(new JKQTMathTextTextNode(this, text, addWhite, parsingMathEnvironment));
}
+ } else if (currentToken==MTTwhitespace) {
+ if (!parsingMathEnvironment) nl->addChild(new JKQTMathTextWhitespaceNode(this));
} else if (currentToken==MTTinstruction) {
const QString currentInstructionName=currentTokenName;
if (currentInstructionName=="\\") break; // break on linebrak character
- if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) {
- nl->addChild(new JKQTMathTextWhitespaceNode(currentInstructionName, this));
- } else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) {
- nl->addChild(new JKQTMathTextSymbolNode(this, currentInstructionName));
- if (JKQTMathTextSymbolNode::isSubSuperscriptBelowAboveSymbol(currentInstructionName) && parsingMathEnvironment) {
- nl->getLastChild()->setSubSuperscriptAboveBelowNode(true);
- }
- } else if (currentTokenName=="limits") {
+ if (currentInstructionName=="limits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true);
- } else if (currentTokenName=="nolimits") {
+ } else if (currentInstructionName=="nolimits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false);
- } else {
- getToken(); // look at next token
- if (currentToken==MTTopenbrace) {
- //std::cout<<"found '{' after '"<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!='}' && (currentTokenIDaddChild(new JKQTMathTextTextNode(this, text, false));
- }
- } else if (JKQTMathTextFracNode::supportsInstructionName(currentInstructionName)) {
- JKQTMathTextNode* n1=parseLatexString(true);
- JKQTMathTextNode* n2=nullptr;
- if (getToken()==MTTopenbrace) n2=parseLatexString(true);
- if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::InstructionName2FracType(currentInstructionName)));
- 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=="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 > items;
- //int lines=0;
- //int cols=0;
- bool first=true;
- QVector 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 "<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 if (currentInstructionName=="begin") {
+ if (getToken()==MTTopenbrace && 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 > items;
+ //int lines=0;
+ //int cols=0;
+ bool first=true;
+ QVector 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 {
- error_list.append(tr("error @ ch. %1: unknown environment '%2'").arg(currentTokenID).arg(envname));
+ line.append(it);
+ //std::cout<<" appending item and line with "<addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::InstructionName2DecorationType(currentInstructionName), parseLatexString(true)));
+ //std::cout<<" creating matrix-node with "<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 {
- 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)));
- }
+ error_list.append(tr("error @ ch. %1: unknown environment '%2'").arg(currentTokenID).arg(envname));
}
- } else if (currentToken==MTTopenbracket && currentInstructionName!="left") {
- //std::cout<<"found '[' after '"<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 { // 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()==MTTopenbrace && getToken()==MTTtext) {
+ QString envname=currentTokenName;
+ while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name'
+ if (envname==quitOnEnvironmentEnd) {
+ break;
} else {
- nl->addChild(new JKQTMathTextTextNode(this, "[", false));
+ error_list.append(tr("error @ ch. %1: '\\end{%2}' widthout preceding '\\begin{%3}'").arg(currentTokenID).arg(envname).arg(envname));
}
- } else {
- //std::cout<<"did not find '{' after '"<0) {
- bool tokenWasNoBrace=false;
- const QString firstTokenChar(currentTokenName[0]);
- if (TokenNameMatchesJKQTMathTextBraceType(firstTokenChar, quitOnClosingBrace, true, &tokenWasNoBrace)) {
- lastRightBraceType=TokenName2JKQTMathTextBraceType(firstTokenChar);
- if (quitOnClosingBrace!=MTBTAny) currentTokenName=currentTokenName.right(currentTokenName.size()-1);
- break;
- } else {
- getNew=false;
- }
- }
- } else if (currentToken==MTTinstruction) {
- if (InstructionNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
- lastRightBraceType=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName);
- break;
- }
- } else if (currentToken==MTTclosebracket) {
- if (quitOnClosingBrace==MTBTSquareBracket || quitOnClosingBrace==MTBTAny) {
- lastRightBraceType=MTBTSquareBracket;
- break;
- }
+ } 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=="right") {
+ getToken();
+ if (currentToken==MTTtext) {
+ if (currentTokenName.size()>0) {
+ bool tokenWasNoBrace=false;
+ const QString firstTokenChar(currentTokenName[0]);
+ if (TokenNameMatchesJKQTMathTextBraceType(firstTokenChar, quitOnClosingBrace, true, &tokenWasNoBrace)) {
+ lastRightBraceType=TokenName2JKQTMathTextBraceType(firstTokenChar);
+ if (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!
- JKQTMathTextNode* c=parseLatexString(currentTokenName.size()<=0, bracetype);
- nl->addChild(new JKQTMathTextBraceNode(this, bracetype, lastRightBraceType, c));
- } else {
- getNew=false;
- }
- }
- } else if (currentToken==MTTinstruction) {
- const JKQTMathTextBraceType bracetypeopening=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName);
- if (bracetypeopening!=MTBTUnknown) {
- JKQTMathTextNode* c=parseLatexString(true, bracetypeopening);
- nl->addChild(new JKQTMathTextBraceNode(this, bracetypeopening, lastRightBraceType, c));
- } else if (currentToken==MTTinstruction && TokenNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
- break;
- }
- } else if (currentToken==MTTopenbracket) {
- JKQTMathTextNode* c=parseLatexString(true, MTBTSquareBracket);
- nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, lastRightBraceType, c));
+ }
+ } else if (currentToken==MTTinstruction) {
+ if (InstructionNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
+ lastRightBraceType=InstructionName2JKQTMathTextBraceType(currentTokenName);
+ break;
+ }
+ } else if (currentToken==MTTclosebracket) {
+ if (quitOnClosingBrace==MTBTSquareBracket || quitOnClosingBrace==MTBTAny) {
+ lastRightBraceType=MTBTSquareBracket;
+ break;
+ }
+ } else {
+ error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID));
+ }
+ } else if (currentInstructionName=="left") {
+ getToken();
+ 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!
+ JKQTMathTextNode* c=parseLatexString(currentTokenName.size()<=0, bracetype);
+ nl->addChild(new JKQTMathTextBraceNode(this, bracetype, lastRightBraceType, c));
} else {
- error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID));
+ getNew=false;
}
-
+ }
+ } else if (currentToken==MTTinstruction) {
+ const JKQTMathTextBraceType bracetypeopening=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName);
+ if (bracetypeopening!=MTBTUnknown) {
+ JKQTMathTextNode* c=parseLatexString(true, bracetypeopening);
+ nl->addChild(new JKQTMathTextBraceNode(this, bracetypeopening, lastRightBraceType, c));
+ } else if (currentToken==MTTinstruction && TokenNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
+ break;
+ }
+ } else if (currentToken==MTTopenbracket) {
+ JKQTMathTextNode* c=parseLatexString(true, MTBTSquareBracket);
+ nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, lastRightBraceType, c));
+ } else {
+ error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID));
+ }
+ } else {
+ bool foundError=false;
+ JKQTMathTextNode* node=parseInstruction(&foundError, &getNew);
+ if (node) {
+ if (foundError) {
+ delete node;
+ node=nullptr;
} else {
- getNew=false;
- //error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName));
+ nl->addChild(node);
}
}
}
- } else if (currentToken==MTTwhitespace) {
- if (!parsingMathEnvironment) nl->addChild(new JKQTMathTextWhitespaceNode(this));
} else if (currentToken==MTTunderscore) {
getToken();
JKQTMathTextNode* child=nullptr;
JKQTMathTextNode* child2=nullptr;
if (currentToken==MTTinstruction) {
- const QString currentInstructionName=currentTokenName;
- getToken(); // look at next token
- if (currentToken==MTTopenbrace) {
- child=new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true));
- } else if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) {
- getNew=false;
- child=new JKQTMathTextWhitespaceNode(currentInstructionName, this);
- } else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) {
- getNew=false;
- child=new JKQTMathTextSymbolNode(this, currentInstructionName);
- if (JKQTMathTextSymbolNode::isSubSuperscriptBelowAboveSymbol(currentInstructionName) && parsingMathEnvironment) {
- child->setSubSuperscriptAboveBelowNode(true);
- }
- } else {
- error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName));
- }
+ child=parseInstruction(nullptr, &getNew);
} else if (currentToken==MTTopenbrace) {
child=parseLatexString(true);
} else if (currentToken==MTTtext) {
@@ -1399,24 +1314,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
JKQTMathTextNode* child=nullptr;
JKQTMathTextNode* child2=nullptr;
if (currentToken==MTTinstruction) {
- 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);
- if (JKQTMathTextSymbolNode::isSubSuperscriptBelowAboveSymbol(currentInstructionName) && parsingMathEnvironment) {
- child->setSubSuperscriptAboveBelowNode(true);
- }
- } else {
- 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));
- }
- }
+ child=parseInstruction(nullptr, &getNew);
} else if (currentToken==MTTopenbrace) {
child=parseLatexString(true);
} else if (currentToken==MTTtext) {
@@ -1448,7 +1346,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
break;
} else { // starting math environment
parsingMathEnvironment=true;
- nl->addChild(new JKQTMathTextInstruction1Node(this, "equation", parseLatexString(true)));
+ nl->addChild(new JKQTMathTextModifiedTextPropsInstructionNode(this, "equation", parseLatexString(true)));
}
}
if (getNew) getToken();
@@ -1457,6 +1355,177 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
return simplifyJKQTMathTextNode(nl);
}
+JKQTMathTextNode* JKQTMathText::parseInstruction(bool *_foundError, bool* getNew) {
+ if (currentToken!=MTTinstruction) {
+ if (_foundError) *_foundError=true;
+ if (getNew) *getNew=false;
+ error_list.append(tr("error @ ch. %1: expected instruction token").arg(currentTokenID));
+ return nullptr;
+ }
+ bool foundError=false;
+ const QString currentInstructionName=currentTokenName;
+ JKQTMathTextNode* child=nullptr;
+ if (getNew) *getNew=true;
+ if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) {
+ if (getNew) *getNew=true;
+ child= new JKQTMathTextWhitespaceNode(currentInstructionName, this);
+ } else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) {
+ child=new JKQTMathTextSymbolNode(this, currentInstructionName);
+ if (JKQTMathTextSymbolNode::isSubSuperscriptBelowAboveSymbol(currentInstructionName) && parsingMathEnvironment) {
+ child->setSubSuperscriptAboveBelowNode(true);
+ }
+ if (getNew) *getNew=true;
+ } else if (JKQTMathTextModifiedTextPropsInstructionNode::supportsInstructionName(currentInstructionName)) {
+ const size_t Nparams=JKQTMathTextModifiedTextPropsInstructionNode::countParametersOfInstruction(currentInstructionName);
+ bool foundError=false;
+ const QStringList params=parseStringParams(true, Nparams, &foundError);
+ if (!foundError) {
+ if (getToken()==MTTopenbrace) {
+ const bool oldParseMath=parsingMathEnvironment;
+ auto __finalpaint=JKQTPFinally(std::bind([&oldParseMath](bool& parsingMathEnvironment) { parsingMathEnvironment=oldParseMath; }, std::ref(parsingMathEnvironment)));
+ JKQTMathTextModifiedTextPropsInstructionNode::modifyInMathEnvironment(currentInstructionName, parsingMathEnvironment, params);
+ child=new JKQTMathTextModifiedTextPropsInstructionNode(this, currentInstructionName, parseLatexString(true), params);
+
+ } else {
+ foundError=true;
+ }
+ }
+ if (foundError){
+ error_list.append(tr("error @ ch. %1: expected %3 arguments in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(Nparams+1));
+ }
+ } else if (JKQTMathTextBoxInstructionNode::supportsInstructionName(currentInstructionName)) {
+ const size_t Nparams=JKQTMathTextBoxInstructionNode::countParametersOfInstruction(currentInstructionName);
+ bool foundError=false;
+ const QStringList params=parseStringParams(true, Nparams, &foundError);
+ if (!foundError) {
+ if (getNew) *getNew=true;
+ if (getToken()==MTTopenbrace) {
+ const bool oldParseMath=parsingMathEnvironment;
+ auto __finalpaint=JKQTPFinally(std::bind([&oldParseMath](bool& parsingMathEnvironment) { parsingMathEnvironment=oldParseMath; }, std::ref(parsingMathEnvironment)));
+ JKQTMathTextBoxInstructionNode::modifyInMathEnvironment(currentInstructionName, parsingMathEnvironment, params);
+ child=new JKQTMathTextBoxInstructionNode(this, currentInstructionName, parseLatexString(true), params);
+ } else {
+ foundError=true;
+ }
+ }
+ if (foundError){
+ error_list.append(tr("error @ ch. %1: expected %3 arguments in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(Nparams+1));
+ }
+ } else if (currentInstructionName=="sqrt") {
+ getToken();
+ if (currentToken==MTTopenbrace) {
+ child=new JKQTMathTextSqrtNode(this, parseLatexString(true));
+ } else if (currentToken==MTTopenbracket) {
+ 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) {
+ child=new JKQTMathTextSqrtNode(this, n2, n1);
+ } else {
+ if (n1) delete n1;
+ if (n2) delete n2;
+ error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
+ }
+ } else {
+ error_list.append(tr("error @ ch. %1: expected %3 arguments in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
+ }
+ } else if (currentInstructionName=="cbrt") {
+ if (getToken()==MTTopenbrace) {
+ child=new JKQTMathTextSqrtNode(this, parseLatexString(true), new JKQTMathTextTextNode(this, "3", false));
+ } else {
+ error_list.append(tr("error @ ch. %1: expected %3 arguments in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
+ }
+ } else if (currentInstructionName=="verb") {
+ if (getToken()==MTTopenbrace) {
+ QString text="";
+ currentTokenID++;
+ if (currentTokenID<=parseString.size()-1) {
+ QChar c=parseString[currentTokenID];
+ while (c!='}' && (currentTokenID0 || (n==0 && get)) getToken();
+ if (currentToken==MTTopenbrace) {
+ getToken();
+ if (currentToken==MTTtext) {
+ params.append(currentTokenName);
+ if (getToken()!=MTTclosebrace) {
+ if (*foundError) *foundError=true;
+ return params;
+ }
+ } else if (currentToken==MTTwhitespace) {
+ params.append(" ");
+ if (getToken()!=MTTclosebrace) {
+ if (*foundError) *foundError=true;
+ return params;
+ }
+ } else if (currentToken==MTTclosebrace) {
+ params.append("");
+ } else {
+ if (*foundError) *foundError=true;
+ return params;
+ }
+ } else {
+ if (*foundError) *foundError=true;
+ return params;
+ }
+ }
+ return params;
+ }
+}
+
JKQTMathTextNode *JKQTMathText::getParsedNode() const {
return this->parsedNode;
diff --git a/lib/jkqtmathtext/jkqtmathtext.h b/lib/jkqtmathtext/jkqtmathtext.h
index fef9ceca4e..630584b2e7 100644
--- a/lib/jkqtmathtext/jkqtmathtext.h
+++ b/lib/jkqtmathtext/jkqtmathtext.h
@@ -123,6 +123,13 @@ class JKQTMathTextNode; // forward
- \c \\tt{...} \c \\texttt{...} \c \\mathtt{...} : draw text in typewriter font \image html jkqtmathtext/jkqtmathtext_fonts.png
- \c \\textcolor{color}{...} \c \\color{color} \c \\mathcolor{color}{...} : draw colored text \image html jkqtmathtext/jkqtmathtext_colored.png
- \c \\boxed{...} : draw text with a box around it \image html jkqtmathtext/jkqtmathtext_boxed.png
+ - \c \\doublebox{...} : draw text with a rounded box around it \image html jkqtmathtext/jkqtmathtext_doublebox.png
+ - \c \\ovalbox{...} : draw text with a rounded box around it \image html jkqtmathtext/jkqtmathtext_ovalbox.png
+ - \c \\Ovalbox{...} : draw a thick oval box \image html jkqtmathtext/jkqtmathtext_oovalbox.png
+ - \c \\ovaldoublebox{...} : draw a double oval box \image html jkqtmathtext/jkqtmathtext_ovaldoublebox.png
+ - \c \\colorbox{bordercolor}{...} : draw a colored box \image html jkqtmathtext/jkqtmathtext_colorbox.png
+ - \c \\shaded{backgroundcolor}{...} : draw a filled box \image html jkqtmathtext/jkqtmathtext_shaded.png
+ - \c \\fcolorbox{bordercolor}{backgroundcolor}{...} : draw a colored, filled box \image html jkqtmathtext/jkqtmathtext_fcolorbox.png
- \c \\colorbox{color}{...} : draw a colored box around text \image html jkqtmathtext/jkqtmathtext_colorbox.png
- \c \\alpha ... : display the according greek letter \image html jkqtmathtext/jkqtmathtext_greek.png
- \c ^{...} \c _{...} : display the contents of braces in superscript/subscript \image html jkqtmathtext/jkqtmathtext_supersub.png
@@ -813,6 +820,22 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
* \param quitOnClosingBracket if \c true, quits on encountering a MTTclosebracket token
*/
JKQTMathTextNode* parseLatexString(bool get, JKQTMathTextBraceType quitOnClosingBrace=JKQTMathTextBraceType::MTBTAny, const QString& quitOnEnvironmentEnd=QString(""), bool quitOnClosingBracket=false);
+ /** \brief parses a list of string-arguments, i.e. \c {p1}{p2}{...}
+ *
+ * \param get call getToken() at the start, otherwise it is expected that currentToken==MTTopenbrace
+ * \param Nparams the number of parameters to expect
+ * \param[out] foundError will be set to \c true if an error occured (unexpected token) or \c false otherwise
+ * \return the list of parameter strings with Nparam entries or an empty or partial list on error
+ */
+ QStringList parseStringParams(bool get, size_t Nparams, bool *foundError=nullptr);
+ /** \brief parses a single instruction (including it's parameters)
+ *
+ * \param[out] _foundError will be set to \c true if an error occured (unexpected token) or \c false otherwise
+ * \param[out] getNew returns \c true if the parser has to call getToken() to go on
+ * \return the instruction node or \c nullptr on error (then also \a _foundError is set \c true )
+ * \note This method expects the current token currentToken to be MTTinstruction
+ */
+ JKQTMathTextNode* parseInstruction(bool *_foundError=nullptr, bool* getNew=nullptr);
/** \brief parse a LaTeX math environment */
JKQTMathTextNode* parseMath(bool get);
diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp
index a5c8b8da50..f8965b5688 100644
--- a/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp
+++ b/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp
@@ -36,117 +36,534 @@
-JKQTMathTextInstruction1Node::JKQTMathTextInstruction1Node(JKQTMathText* _parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters):
- JKQTMathTextSingleChildNode(child, _parent)
+JKQTMathTextInstruction1Node::JKQTMathTextInstruction1Node(JKQTMathText* _parent, const QString& _instructionName, JKQTMathTextNode* child, const QStringList& _parameters):
+ JKQTMathTextSingleChildNode(child, _parent),
+ instructionName(_instructionName),
+ parameters(_parameters)
{
- this->name=name;
- this->parameters=parameters;
-
- JKQTMathTextEnvironment ev;
- if (!setupMTenvironment(ev)) {
- parentMathText->addToErrorList(QObject::tr("unknown instruction '%1' found!").arg(name));
- }
}
JKQTMathTextInstruction1Node::~JKQTMathTextInstruction1Node() {
}
-QString JKQTMathTextInstruction1Node::getTypeName() const
-{
- return QLatin1String("MTinstruction1Node(")+name+")";
+const QString& JKQTMathTextInstruction1Node::getInstructionName() const {
+ return this->instructionName;
}
-void JKQTMathTextInstruction1Node::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
+const QStringList &JKQTMathTextInstruction1Node::getParameters() const {
+ return this->parameters;
+}
+
+
+
+
+
+JKQTMathTextModifiedTextPropsInstructionNode::JKQTMathTextModifiedTextPropsInstructionNode(JKQTMathText* _parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters):
+ JKQTMathTextInstruction1Node(_parent, name, child, parameters)
+{
+}
+
+JKQTMathTextModifiedTextPropsInstructionNode::~JKQTMathTextModifiedTextPropsInstructionNode() {
+}
+
+
+QString JKQTMathTextModifiedTextPropsInstructionNode::getTypeName() const
+{
+ return QLatin1String("JKQTMathTextModifiedTextPropsInstructionNode(")+instructionName+")";
+}
+
+void JKQTMathTextModifiedTextPropsInstructionNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
JKQTMathTextEnvironment ev=currentEv;
- setupMTenvironment(ev);
+ executeInstruction(ev);
getChild()->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
- if (name=="colorbox" || name=="fbox" || name=="boxed") {
- QFontMetricsF fm(ev.getFont(parentMathText));
- double xw=fm.boundingRect("x").width();
- width+=xw;
- overallHeight+=xw;
- baselineHeight+=xw/2.0;
- }
}
-double JKQTMathTextInstruction1Node::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
+double JKQTMathTextModifiedTextPropsInstructionNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
JKQTMathTextEnvironment ev=currentEv;
- setupMTenvironment(ev);
+ executeInstruction(ev);
- QPen oldPen=painter.pen();
- double shiftX=0;
- if (name=="colorbox" || name=="fbox" || name=="boxed") {
- QColor fcol=currentEv.color;
- if (name=="colorbox") fcol=QColor(parameters.value(0, ev.color.name()));
- //qDebug()<<"COLOR="<getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
- QPen p=painter.pen();
- QFontMetricsF fm(currentEv.getFont(parentMathText));
- double xw=fm.boundingRect("x").width();
- p.setColor(fcol);
- painter.setPen(p);
- painter.drawRect(QRectF(x,y-baselineHeight-xw/2,width+xw,overallHeight+xw));
- shiftX=xw/2.0;
- }
-
- double xnew= getChild()->draw(painter, x+shiftX, y, ev);
- painter.setPen(oldPen);
- return xnew;
+ return getChild()->draw(painter, x, y, ev);
}
-bool JKQTMathTextInstruction1Node::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
+bool JKQTMathTextModifiedTextPropsInstructionNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
JKQTMathTextEnvironment ev=currentEv;
-
- setupMTenvironment(ev);
+ fillInstructions();
+ executeInstruction(ev);
return getChild()->toHtml(html, ev, defaultEv);
}
-QString JKQTMathTextInstruction1Node::getName() const {
- return this->name;
-}
-
-QStringList JKQTMathTextInstruction1Node::getParameters() const {
- return this->parameters;
-}
-
-bool JKQTMathTextInstruction1Node::setupMTenvironment(JKQTMathTextEnvironment &ev) const
+bool JKQTMathTextModifiedTextPropsInstructionNode::supportsInstructionName(const QString &instructionName)
{
- if (name=="bf" || name=="textbf" || name=="mathbf") ev.bold=true;
- else if (name=="em") ev.italic=!ev.italic;
- else if (name=="it" || name=="textit" || name=="mathit") ev.italic=true;
- else if (name=="textcolor" || name=="mathcolor" || name=="color") ev.color=QColor(parameters.value(0, ev.color.name()));
- else if (name=="ensuremath" || name=="equation") { ev.italic=true; ev.insideMath=true; }
- else if (name=="sc" || name=="textsc" || name=="mathsc") ev.smallCaps=true;
- else if (name=="ul" || name=="underline" || name=="underlined") ev.underlined=true;
- else if (name=="ol" || name=="overline" || name=="overlined") ev.overline=true;
- else if (name=="strike") ev.strike=true;
- else if (name=="rm" || name=="textrm") { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }
- else if (name=="mathrm" || name=="unit" || name=="operatorname") { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }
- else if (name=="mathbfit" || name=="bfit" || name=="textbfit") { ev.bold=true; ev.italic=true; }
- else if (name=="text" || name=="mbox" || name=="ensuretext") { ev.insideMath=false; ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }
- else if (name=="mat") { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; ev.bold=true; }
- else if (name=="cal" || name=="textcal" || name=="mathcal") { ev.font=JKQTMathTextEnvironmentFont::MTEcaligraphic; ev.italic=false; }
- else if (name=="fcal" || name=="textfcal" || name=="mathfcal") { ev.font=JKQTMathTextEnvironmentFont::MTEcaligraphic; ev.bold=true; }
- else if (name=="frak" || name=="textfrak" || name=="mathfrak") { ev.font=JKQTMathTextEnvironmentFont::MTEfraktur; ev.italic=false; }
- else if (name=="ffrak" || name=="textffrak" || name=="mathffrak") { ev.font=JKQTMathTextEnvironmentFont::MTEfraktur; ev.bold=true; }
- else if (name=="bb" || name=="textbb" || name=="mathbb") { ev.font=JKQTMathTextEnvironmentFont::MTEblackboard; ev.italic=false; }
- else if (name=="tt" || name=="texttt" || name=="mathtt") { ev.font=JKQTMathTextEnvironmentFont::MTEtypewriter; ev.italic=false; }
- else if (name=="sf" || name=="textsf" || name=="mathsf") { ev.font=JKQTMathTextEnvironmentFont::MTEsans; ev.italic=false; }
- else if (name=="sfit" || name=="textsfit" || name=="mathsfit") { ev.font=JKQTMathTextEnvironmentFont::MTEsans; ev.italic=true; }
- else if (name=="script" || name=="scr" || name=="textscript" || name=="textscr" || name=="mathscript" || name=="mathscr") { ev.font=JKQTMathTextEnvironmentFont::MTEscript; ev.italic=false; }
- else if (name=="fscript" || name=="fscr" || name=="textfscript" || name=="textfscr" || name=="mathfscript" || name=="mathfscr") { ev.font=JKQTMathTextEnvironmentFont::MTEscript; ev.bold=true; ev.italic=false; }
- else if (name=="displaystyle") { ev.fontSize=ev.fontSize/0.8; }
- else if (name=="scriptstyle") { ev.fontSize=ev.fontSize*0.8; }
- else if (name=="scriptscriptstyle") { ev.fontSize=ev.fontSize*0.8*0.8; }
- else {
- return false;
+ fillInstructions();
+ return instructions.contains(instructionName);
+}
+
+size_t JKQTMathTextModifiedTextPropsInstructionNode::countParametersOfInstruction(const QString &instructionName)
+{
+ fillInstructions();
+ if (instructions.contains(instructionName)) return instructions[instructionName].NParams;
+ return 0;
+}
+
+void JKQTMathTextModifiedTextPropsInstructionNode::modifyInMathEnvironment(const QString &instructionName, bool &insideMath, const QStringList& params)
+{
+ fillInstructions();
+ if (instructions.contains(instructionName)) {
+ JKQTMathTextEnvironment ev;
+ ev.insideMath=insideMath;
+ instructions[instructionName].modifier(ev, params);
+ insideMath=ev.insideMath;
+ }
+}
+
+
+void JKQTMathTextModifiedTextPropsInstructionNode::executeInstruction(JKQTMathTextEnvironment &ev) const
+{
+ instructions.value(getInstructionName(), InstructionProperties()).modifier(ev, getParameters());
+}
+
+QHash JKQTMathTextModifiedTextPropsInstructionNode::instructions;
+
+void JKQTMathTextModifiedTextPropsInstructionNode::fillInstructions()
+{
+
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) {ev.bold=true; }, 0);
+ instructions["bf"] = i;
+ instructions["textbf"] = i;
+ instructions["mathbf"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) {ev.italic=!ev.italic; }, 0);
+ instructions["em"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) {ev.italic=true; }, 0);
+ instructions["it"] = i;
+ instructions["textit"] = i;
+ instructions["mathit"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) {ev.color=jkqtp_String2QColor(parameters.value(0, ev.color.name())); }, 1);
+ instructions["textcolor"] = i;
+ instructions["mathcolor"] = i;
+ instructions["color"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.italic=true; ev.insideMath=true; }, 0);
+ instructions["ensuremath"] = i;
+ instructions["equation"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) {ev.smallCaps=true; }, 0);
+ instructions["sc"] = i;
+ instructions["textsc"] = i;
+ instructions["mathsc"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) {ev.underlined=true; }, 0);
+ instructions["ul"] = i;
+ instructions["underline"] = i;
+ instructions["underlined"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) {ev.overline=true; }, 0);
+ instructions["ol"] = i;
+ instructions["overline"] = i;
+ instructions["overlined"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) {ev.strike=true; }, 0);
+ instructions["strike"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }, 0);
+ instructions["rm"] = i;
+ instructions["textrm"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }, 0);
+ instructions["mathrm"] = i;
+ instructions["unit"] = i;
+ instructions["operatorname"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.bold=true; ev.italic=true; }, 0);
+ instructions["mathbfit"] = i;
+ instructions["bfit"] = i;
+ instructions["textbfit"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.insideMath=false; ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }, 0);
+ instructions["text"] = i;
+ instructions["mbox"] = i;
+ instructions["ensuretext"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; ev.bold=true; }, 0);
+ instructions["mat"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEcaligraphic; ev.italic=false; }, 0);
+ instructions["cal"] = i;
+ instructions["textcal"] = i;
+ instructions["mathcal"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEcaligraphic; ev.bold=true; }, 0);
+ instructions["fcal"] = i;
+ instructions["textfcal"] = i;
+ instructions["mathfcal"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEfraktur; ev.italic=false; }, 0);
+ instructions["frak"] = i;
+ instructions["textfrak"] = i;
+ instructions["mathfrak"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEfraktur; ev.bold=true; }, 0);
+ instructions["ffrak"] = i;
+ instructions["textffrak"] = i;
+ instructions["mathffrak"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEblackboard; ev.italic=false; }, 0);
+ instructions["bb"] = i;
+ instructions["textbb"] = i;
+ instructions["mathbb"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEtypewriter; ev.italic=false; }, 0);
+ instructions["tt"] = i;
+ instructions["texttt"] = i;
+ instructions["mathtt"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEsans; ev.italic=false; }, 0);
+ instructions["sf"] = i;
+ instructions["textsf"] = i;
+ instructions["mathsf"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEsans; ev.italic=true; }, 0);
+ instructions["sfit"] = i;
+ instructions["textsfit"] = i;
+ instructions["mathsfit"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEscript; ev.italic=false; }, 0);
+ instructions["script"] = i;
+ instructions["scr"] = i;
+ instructions["textscript"] = i;
+ instructions["textscr"] = i;
+ instructions["mathscript"] = i;
+ instructions["mathscr"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.font=JKQTMathTextEnvironmentFont::MTEscript; ev.bold=true; ev.italic=false; }, 0);
+ instructions["fscript"] = i;
+ instructions["fscr"] = i;
+ instructions["textfscript"] = i;
+ instructions["textfscr"] = i;
+ instructions["mathfscript"] = i;
+ instructions["mathfscr"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.fontSize=ev.fontSize/0.8; }, 0);
+ instructions["displaystyle"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.fontSize=ev.fontSize*0.8; }, 0);
+ instructions["scriptstyle"]= i;
+ }
+ {
+ InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& parameters) { ev.fontSize=ev.fontSize*0.8*0.8; }, 0);
+ instructions["scriptscriptstyle"]= i;
+ }
+}
+
+JKQTMathTextModifiedTextPropsInstructionNode::InstructionProperties::InstructionProperties():
+ NParams(0),
+ modifier([](JKQTMathTextEnvironment&, const QStringList&) {})
+{
+
+}
+
+JKQTMathTextModifiedTextPropsInstructionNode::InstructionProperties::InstructionProperties(const ModifyEnvironmentFunctor &_modifier, size_t _NParams):
+ modifier(_modifier),
+ NParams(_NParams)
+{
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+JKQTMathTextBoxInstructionNode::JKQTMathTextBoxInstructionNode(JKQTMathText* _parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters):
+ JKQTMathTextInstruction1Node(_parent, name, child, parameters)
+{
+}
+
+JKQTMathTextBoxInstructionNode::~JKQTMathTextBoxInstructionNode() {
+}
+
+
+QString JKQTMathTextBoxInstructionNode::getTypeName() const
+{
+ return QLatin1String("JKQTMathTextBoxInstructionNode(")+instructionName+")";
+}
+
+void JKQTMathTextBoxInstructionNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
+ JKQTMathTextEnvironment ev=currentEv;
+
+ const auto& inst=instructions.value(getInstructionName());
+ inst.modifier(ev, getParameters());
+ const QPen p=inst.pen(ev, getParameters(), parentMathText);
+ const QBrush b=inst.brush(ev, getParameters(), parentMathText);
+ const QFontMetricsF fmNonItalic(JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText)));
+ const double lw=p.widthF();
+ const double padding=inst.paddingFactor*fmNonItalic.tightBoundingRect("x").width();
+
+ getChild()->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
+ width=width+2.0*(padding+lw/2.0);
+ baselineHeight=baselineHeight+padding+lw/2.0;
+ overallHeight=overallHeight+2.0*(padding+lw/2.0);
+}
+
+double JKQTMathTextBoxInstructionNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
+ doDrawBoxes(painter, x, y, currentEv);
+ JKQTMathTextEnvironment ev=currentEv;
+
+ const auto& inst=instructions.value(getInstructionName());
+ inst.modifier(ev, getParameters());
+ const QPen p=inst.pen(ev, getParameters(), parentMathText);
+ const QBrush b=inst.brush(ev, getParameters(), parentMathText);
+ const QFontMetricsF fmNonItalic(JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText)));
+ const double lw=p.widthF();
+ const double padding=inst.paddingFactor*fmNonItalic.tightBoundingRect("x").width();
+ const double rr=inst.roundingFactor*fmNonItalic.tightBoundingRect("x").width();
+ double width=0, baselineHeight=0, overallHeight=0, strikeoutPos=0;
+ getChild()->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
+
+ {
+ painter.save();
+ JKQTPFinalAct __finalpaint([&painter]() { painter.restore(); });
+ painter.setBrush(b);
+ painter.setPen(p);
+ const QRectF rect(x+lw/2.0, y-baselineHeight-padding-lw/2.0, width+2.0*padding, overallHeight+2.0*padding);
+ if (rr>0) painter.drawRoundedRect(rect, rr, rr, Qt::AbsoluteSize);
+ else painter.drawRect(rect);
+ if (inst.doubleLine) {
+ painter.setBrush(Qt::NoBrush);
+ QPen p2=p;
+ p2.setWidthF(p.widthF()*0.6);
+ const QRectF recti(x+lw*2.5, y-baselineHeight-lw/2.0-padding+2.0*lw, width+2.0*padding-4.0*lw, overallHeight+2.0*padding-4.0*lw);
+ if (rr>0) painter.drawRoundedRect(recti, rr, rr, Qt::AbsoluteSize);
+ else painter.drawRect(recti);
+ }
}
- return true;
+ double xnew = getChild()->draw(painter, x+padding+lw/2.0, y, ev);
+
+ return xnew+padding+lw/2.0;
+}
+
+bool JKQTMathTextBoxInstructionNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
+ JKQTMathTextEnvironment ev=currentEv;
+ fillInstructions();
+ const auto& inst=instructions.value(getInstructionName());
+ inst.modifier(ev, getParameters());
+ const QPen p=inst.pen(ev, getParameters(), parentMathText);
+ const QBrush b=inst.brush(ev, getParameters(), parentMathText);
+ const QFontMetricsF fmNonItalic(JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText)));
+ const double lw=p.widthF();
+ const double padding=inst.paddingFactor*fmNonItalic.tightBoundingRect("x").width();
+ const double rr=inst.roundingFactor*fmNonItalic.tightBoundingRect("x").width();
+ QString s=QString("padding: %1px").arg(padding);
+ if (p!=Qt::NoPen) {
+ if (s.size()>0 && s.right(2)!="; ") s=s+"; ";
+ if (p.widthF()>0 && p.color()!=Qt::transparent) s=s+"border-color: "+p.color().name();
+ if (s.size()>0 && s.right(2)!="; ") s=s+"; ";
+ if (p.widthF()>0 && p.color()!=Qt::transparent) s=s+QString("border-width: %1px").arg(p.width());
+ }
+ if (b!=Qt::NoBrush) {
+ if (s.size()>0 && s.right(2)!="; ") s=s+"; ";
+ if (b.color()!=Qt::transparent) s=s+"background-color: "+b.color().name();
+ }
+
+ if (s.size()>0) html=html+ QString("").arg(s);
+ bool ok=getChild()->toHtml(html, ev, defaultEv);
+ if (s.size()>0) html=html+"";
+ return ok;
+}
+
+bool JKQTMathTextBoxInstructionNode::supportsInstructionName(const QString &instructionName)
+{
+ fillInstructions();
+ return instructions.contains(instructionName);
+}
+
+size_t JKQTMathTextBoxInstructionNode::countParametersOfInstruction(const QString &instructionName)
+{
+ fillInstructions();
+ if (instructions.contains(instructionName)) return instructions[instructionName].NParams;
+ return 0;
+}
+
+void JKQTMathTextBoxInstructionNode::modifyInMathEnvironment(const QString &instructionName, bool &insideMath, const QStringList& params)
+{
+ fillInstructions();
+ if (instructions.contains(instructionName)) {
+ JKQTMathTextEnvironment ev;
+ ev.insideMath=insideMath;
+ instructions[instructionName].modifier(ev, params);
+ insideMath=ev.insideMath;
+ }
+}
+
+
+QHash JKQTMathTextBoxInstructionNode::instructions;
+
+void JKQTMathTextBoxInstructionNode::fillInstructions()
+{
+
+ {
+ InstructionProperties i(InstructionProperties::NoModification,
+ InstructionProperties::DefaultPen,
+ InstructionProperties::NoBrush,
+ InstructionProperties::DefaultPadding,
+ /*Nparams=*/0);
+ instructions["fbox"] = i;
+ instructions["framebox"] = i;
+ instructions["boxed"] = i;
+ instructions["framed"] = i;
+ }
+ {
+ InstructionProperties i(InstructionProperties::NoModification,
+ InstructionProperties::DefaultPen,
+ InstructionProperties::NoBrush,
+ InstructionProperties::DefaultPadding,
+ /*Nparams=*/0);
+ i.doubleLine=true;
+ instructions["doublebox"] = i;
+ }
+ {
+ InstructionProperties i(InstructionProperties::NoModification,
+ InstructionProperties::DefaultPen,
+ InstructionProperties::NoBrush,
+ InstructionProperties::DefaultPadding,
+ /*Nparams=*/0);
+ i.roundingFactor=0.7;
+ instructions["ovalbox"] = i;
+ }
+ {
+ InstructionProperties i(InstructionProperties::NoModification,
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent){
+ QPen p=InstructionProperties::DefaultPen(ev, parameters, parent);
+ p.setWidthF(p.widthF()*1.5);
+ return p;
+ },
+ InstructionProperties::NoBrush,
+ InstructionProperties::DefaultPadding,
+ /*Nparams=*/0);
+ i.roundingFactor=0.8;
+ instructions["Ovalbox"] = i;
+ }
+ {
+ InstructionProperties i(InstructionProperties::NoModification,
+ InstructionProperties::DefaultPen,
+ InstructionProperties::NoBrush,
+ InstructionProperties::DefaultPadding,
+ /*Nparams=*/0);
+ i.roundingFactor=0.7;
+ i.doubleLine=true;
+ instructions["ovaldoublebox"] = i;
+ }
+ {
+ InstructionProperties i(InstructionProperties::NoModification,
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent){
+ QPen p=InstructionProperties::DefaultPen(ev, parameters, parent);
+ p.setColor(jkqtp_String2QColor(parameters.value(0, p.color().name())));
+ return p;
+ },
+ InstructionProperties::NoBrush,
+ InstructionProperties::DefaultPadding,
+ /*Nparams=*/1);
+ instructions["colorbox"] = i;
+ }
+ {
+ InstructionProperties i(InstructionProperties::NoModification,
+ InstructionProperties::NoPen,
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent){
+ return QBrush(jkqtp_String2QColor(parameters.value(0, QColor(Qt::transparent).name())), Qt::SolidPattern);
+ },
+ InstructionProperties::DefaultPadding,
+ /*Nparams=*/1);
+ instructions["shaded"] = i;
+ }
+ {
+ InstructionProperties i(InstructionProperties::NoModification,
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent){
+ QPen p=InstructionProperties::DefaultPen(ev, parameters, parent);
+ p.setColor(jkqtp_String2QColor(parameters.value(0, p.color().name())));
+ return p;
+ },
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent){
+ return QBrush(jkqtp_String2QColor(parameters.value(1, QColor(Qt::transparent).name())), Qt::SolidPattern);
+ },
+ InstructionProperties::DefaultPadding,
+ /*Nparams=*/2);
+ instructions["fcolorbox"] = i;
+ }
+}
+
+JKQTMathTextBoxInstructionNode::InstructionProperties::ModifyEnvironmentFunctor JKQTMathTextBoxInstructionNode::InstructionProperties::NoModification=
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters){};
+JKQTMathTextBoxInstructionNode::InstructionProperties::GetBoxPenFunctor JKQTMathTextBoxInstructionNode::InstructionProperties::DefaultPen=
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent){ return QPen(ev.color, QFontMetricsF(ev.getFont(parent)).lineWidth(), Qt::SolidLine); };
+JKQTMathTextBoxInstructionNode::InstructionProperties::GetBoxPenFunctor JKQTMathTextBoxInstructionNode::InstructionProperties::NoPen=
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent){ return Qt::NoPen; };
+JKQTMathTextBoxInstructionNode::InstructionProperties::GetBoxBrushFunctor JKQTMathTextBoxInstructionNode::InstructionProperties::NoBrush=
+ [](JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent){ return Qt::NoBrush; };
+double JKQTMathTextBoxInstructionNode::InstructionProperties::DefaultPadding=0.5;
+
+JKQTMathTextBoxInstructionNode::InstructionProperties::InstructionProperties():
+ InstructionProperties(NoModification, DefaultPen, NoBrush, DefaultPadding, 0)
+{
+
+}
+
+JKQTMathTextBoxInstructionNode::InstructionProperties::InstructionProperties(const GetBoxPenFunctor &_pen, const GetBoxBrushFunctor &_brush, double _paddingFactor, size_t _NParams):
+ InstructionProperties(NoModification, _pen, _brush, _paddingFactor, _NParams)
+
+{
+
+}
+
+JKQTMathTextBoxInstructionNode::InstructionProperties::InstructionProperties(const ModifyEnvironmentFunctor &_modifier, const GetBoxPenFunctor &_pen, const GetBoxBrushFunctor &_brush, double _paddingFactor, size_t _NParams):
+ modifier(_modifier),
+ pen(_pen),
+ brush(_brush),
+ NParams(_NParams),
+ paddingFactor(_paddingFactor),
+ doubleLine(false),
+ roundingFactor(0.0)
+{
+
}
diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.h
index 39a8d00b38..aa8e8ab156 100644
--- a/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.h
+++ b/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.h
@@ -27,17 +27,46 @@
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include
+#include
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
-/** \brief subclass representing an instruction node with exactly one argument in the syntax tree
+/** \brief subclass representing an instruction node with exactly one argument and possibly additional parameters in the syntax tree
+ * This is a base-class without concrete implementations ... Implementations can be found in derived classes!
* \ingroup jkqtmathtext_items
+ *
+ * The parameters are sinple strings (e.g. directly for instructions like \c \\textcolor{color}{coloredLatexText},
+ * but they might also be translated into numbers or other properties.
+ *
+ * Typically derived nodes will provide static methods to determine the number of instructions
+ * and whether an instruction name is supported.
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextInstruction1Node: public JKQTMathTextSingleChildNode {
public:
explicit JKQTMathTextInstruction1Node(JKQTMathText* parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters=QStringList());
virtual ~JKQTMathTextInstruction1Node() override;
+ /** \copydoc name */
+ const QString& getInstructionName() const;
+ /** \copydoc parameters */
+ const QStringList& getParameters() const;
+ protected:
+ /** \brief instruction name */
+ QString instructionName;
+ /** \brief additional string-parameters */
+ QStringList parameters;
+};
+
+
+
+/** \brief subclass representing an instruction node which modifies the current font (as defined in JKQTMathTextEnvironment),
+ * i.e. it represents instructions like \c \\textbf{...}, \c \\ul{underlinedText}, ...
+ * \ingroup jkqtmathtext_items
+ */
+class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextModifiedTextPropsInstructionNode: public JKQTMathTextInstruction1Node {
+ public:
+ explicit JKQTMathTextModifiedTextPropsInstructionNode(JKQTMathText* parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters=QStringList());
+ virtual ~JKQTMathTextModifiedTextPropsInstructionNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::draw() */
@@ -45,19 +74,133 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextInstruction1Node: public JKQTMathTextS
/** \brief convert node to HTML and returns \c true on success */
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
- /** \copydoc name */
- QString getName() const;
- /** \copydoc parameters */
- QStringList getParameters() const;
+
+ /** \brief returns true, if the given \a instructionName can be represented by this node
+ * \see instructions
+ */
+ static bool supportsInstructionName(const QString& instructionName);
+ /** \brief returns the number of additional string parameters, required for the given \a instructionName
+ * \see instructions
+ */
+ static size_t countParametersOfInstruction(const QString& instructionName);
+ /** \brief sets \a insideMath to \c true if inside the node is to be parsed in math mode and \c false else
+ * \see instructions
+ */
+ static void modifyInMathEnvironment(const QString& instructionName, bool& insideMath, const QStringList ¶ms=QStringList());
+
+ 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 defines the implementation of an instruction represented by JKQTMathTextModifiedTextPropsInstructionNode */
+ struct InstructionProperties {
+ /** \brief this functor implements the instruction */
+ typedef std::function ModifyEnvironmentFunctor;
+ /** \brief default constructor, creates a NOP-instruction that does nothing */
+ InstructionProperties();
+ /** \brief constructor which gets a functor \a _modifier and a number of required parameters \a _NParams */
+ InstructionProperties(const ModifyEnvironmentFunctor& _modifier, size_t _NParams=0);
+ /** \brief number of parameters for this node */
+ size_t NParams;
+ /** \brief functor that modifies a JKQTMathTextEnvironment */
+ ModifyEnvironmentFunctor modifier;
+ };
+
+ /** \brief fills instructions
+ *
+ * \note this is the customization point for new instructions!
+ */
+ static void fillInstructions();
+ /** \brief defines all implemented instructions in this node */
+ static QHash instructions;
+ /** \brief executes the instruction on \a ev */
+ void executeInstruction(JKQTMathTextEnvironment& ev) const;
+};
+
+
+/** \brief subclass representing an instruction node which draws a (possibly colored) box around it's contents
+ * i.e. it represents instructions like \c \\fbox{...}, \c \\colorbox{color}{...}, ...
+ * \ingroup jkqtmathtext_items
+ */
+class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBoxInstructionNode: public JKQTMathTextInstruction1Node {
+ public:
+ explicit JKQTMathTextBoxInstructionNode(JKQTMathText* parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters=QStringList());
+ virtual ~JKQTMathTextBoxInstructionNode() override;
+ /** \copydoc JKQTMathTextNode::getTypeName() */
+ virtual QString getTypeName() const override;
+ /** \copydoc JKQTMathTextNode::draw() */
+ virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
+ /** \brief convert node to HTML and returns \c true on success */
+ /** \copydoc JKQTMathTextNode::toHtml() */
+ virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
+
+ /** \brief returns true, if the given \a instructionName can be represented by this node
+ * \see instructions
+ */
+ static bool supportsInstructionName(const QString& instructionName);
+ /** \brief returns true, if the given \a instructionName can be represented by this node
+ * \see instructions
+ */
+ static void modifyInMathEnvironment(const QString& instructionName, bool& insideMath);
+ /** \brief returns the number of additional string parameters, required for the given \a instructionName
+ * \see instructions
+ */
+ static size_t countParametersOfInstruction(const QString& instructionName);
+ /** \brief sets \a insideMath to \c true if inside the node is to be parsed in math mode and \c false else
+ * \see instructions
+ */
+ static void modifyInMathEnvironment(const QString& instructionName, bool& insideMath, const QStringList ¶ms=QStringList());
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 set all properties in \a ev, as appropriate for the represented instruction */
bool setupMTenvironment(JKQTMathTextEnvironment &ev) const;
- /** \brief instruction name */
- QString name;
- /** \brief additional string-parameters */
- QStringList parameters;
+
+ /** \brief defines the implementation of an instruction represented by JKQTMathTextModifiedTextPropsInstructionNode */
+ struct InstructionProperties {
+ /** \brief this functor implements the instruction */
+ typedef std::function ModifyEnvironmentFunctor;
+ static ModifyEnvironmentFunctor NoModification;
+ /** \brief this functor returns the QPen to use for the box outline */
+ typedef std::function GetBoxPenFunctor;
+ /** \bbrief generates a QPen with the lineWidth associated with the QFont of the environment (using QFontMetricsF::lineWidth() ) */
+ static GetBoxPenFunctor DefaultPen;
+ /** \bbrief generates an invisible pen with 0 width */
+ static GetBoxPenFunctor NoPen;
+ /** \brief this functor returns the QBrush to use for the box fill */
+ typedef std::function GetBoxBrushFunctor;
+ /** \brief generates an invisible QBrush */
+ static GetBoxBrushFunctor NoBrush;
+ /** \brief default padding factor 0.5 xWidth */
+ static double DefaultPadding;
+ /** \brief default constructor, creates a NOP-instruction that does nothing */
+ InstructionProperties();
+ /** \brief constructor */
+ InstructionProperties(const ModifyEnvironmentFunctor& _modifier, const GetBoxPenFunctor& _pen, const GetBoxBrushFunctor& _brush, double _paddingFactor=DefaultPadding, size_t _NParams=0);
+ /** \brief constructor */
+ InstructionProperties(const GetBoxPenFunctor& _pen, const GetBoxBrushFunctor& _brush, double _paddingFactor=DefaultPadding, size_t _NParams=0);
+ /** \brief number of parameters for this node */
+ size_t NParams;
+ /** \brief functor that modifies a JKQTMathTextEnvironment */
+ ModifyEnvironmentFunctor modifier;
+ /** \brief functor that creates a QPen for the box outline */
+ GetBoxPenFunctor pen;
+ /** \brief functor that creates a QBrush for the box fill */
+ GetBoxBrushFunctor brush;
+ /** \brief padding of the box, as a factor to xWidth of the current font */
+ double paddingFactor;
+ /** \brief draw a double-line */
+ bool doubleLine;
+ /** \brief rounding radius (rx=ry) of the box, as a factor to xWidth of the current font */
+ double roundingFactor;
+ };
+
+ /** \brief fills instructions
+ *
+ * \note this is the customization point for new instructions!
+ */
+ static void fillInstructions();
+ /** \brief defines all implemented instructions in this node */
+ static QHash instructions;
};
diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp
index db645875d6..6822470630 100644
--- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp
+++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp
@@ -726,7 +726,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["searrow"]=UprightSymbolUnicode(QChar(0x2198)).addUprightHtml("↘");
symbols["setminus"]=MathOperatorSymbolUnicode(QChar(0x2216)).addMathOperatorHtml("∖");
{ auto s=MathOperatorSymbolUnicode(QChar(0x223C)).addMathOperatorHtml("˜").addMathOperatorStd("~");
- symbols["~"]=s; symbols["sim"]=s; symbols["tilde"]=s; }
+ symbols["~"]=s; symbols["sim"]=s; }
symbols["simeq"]=MathOperatorSymbolUnicode(QChar(0x2243)).addMathOperatorHtml("≃");
symbols["sqcap"]=MathOperatorSymbolUnicode(QChar(0x2293)).addMathOperatorHtml("⊓");
symbols["sqcup"]=MathOperatorSymbolUnicode(QChar(0x2294)).addMathOperatorHtml("⊔");