JKQTMathText: refactored \\instruction parsing
JKQTMathText: added \shaded{color}{...}, \ovalbox{}, ... commands
@ -42,6 +42,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
||||
<li>IMPROVED: rendering and size calculation of decorations</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>IMPROVED/NEW/breaking: refactored LaTeX parser in JKQTMathText</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>
|
||||
@ -54,6 +55,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
||||
<li>NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)</li>
|
||||
<li>NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)</li>
|
||||
<li>NEW: added \overbracket and \underbracket</li>
|
||||
<li>NEW: added \shaded{color}{...}</li>
|
||||
<li>NEW: added functions to set the font-size in pixels (as alternative to the existing functions that set them in points), implements request <a href="https://github.com/jkriege2/JKQtPlotter/issues/76">#76</a> from <a href="https://github.com/igormironchik">user:igormironchik</a> </li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.1 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_doublebox.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_doubleovalbox.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_fcolorbox.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_oovalbox.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_ovalboxed.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_shaded.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
@ -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<JKQTMathTextWhitespaceNode*>(node);
|
||||
JKQTMathTextSymbolNode* symN=dynamic_cast<JKQTMathTextSymbolNode*>(node);
|
||||
JKQTMathTextListNode* lstN=dynamic_cast<JKQTMathTextListNode*>(node);
|
||||
JKQTMathTextInstruction1Node* inst1N=dynamic_cast<JKQTMathTextInstruction1Node*>(node);
|
||||
JKQTMathTextModifiedTextPropsInstructionNode* inst1N=dynamic_cast<JKQTMathTextModifiedTextPropsInstructionNode*>(node);
|
||||
JKQTMathTextBoxInstructionNode* inst1B=dynamic_cast<JKQTMathTextBoxInstructionNode*>(node);
|
||||
JKQTMathTextSubscriptNode* subN=dynamic_cast<JKQTMathTextSubscriptNode*>(node);
|
||||
JKQTMathTextSuperscriptNode* superN=dynamic_cast<JKQTMathTextSuperscriptNode*>(node);
|
||||
JKQTMathTextBraceNode* braceN=dynamic_cast<JKQTMathTextBraceNode*>(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<JKQTMathTextNode*> list=lstN->getChildren();
|
||||
|
@ -1154,55 +1154,17 @@ 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 '"<<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 (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) {
|
||||
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") {
|
||||
@ -1243,7 +1205,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
|
||||
getNew=true;
|
||||
}
|
||||
} else if (currentInstructionName=="end") {
|
||||
if (getToken()==MTTtext) {
|
||||
if (getToken()==MTTopenbrace && getToken()==MTTtext) {
|
||||
QString envname=currentTokenName;
|
||||
while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name'
|
||||
if (envname==quitOnEnvironmentEnd) {
|
||||
@ -1256,44 +1218,8 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
|
||||
while (currentToken!=MTTclosebrace) getToken();
|
||||
getNew=true;
|
||||
}
|
||||
} else if (JKQTMathTextDecoratedNode::supportsInstructionName(currentInstructionName)) {
|
||||
nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::InstructionName2DecorationType(currentInstructionName), 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)));
|
||||
}
|
||||
}
|
||||
} 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 {
|
||||
//std::cout<<"did not find '{' after '"<<name.toStdString()<<"'\n";
|
||||
if (currentInstructionName=="right") {
|
||||
} else if (currentInstructionName=="right") {
|
||||
getToken();
|
||||
if (currentToken==MTTtext) {
|
||||
if (currentTokenName.size()>0) {
|
||||
bool tokenWasNoBrace=false;
|
||||
@ -1308,7 +1234,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
|
||||
}
|
||||
} else if (currentToken==MTTinstruction) {
|
||||
if (InstructionNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
|
||||
lastRightBraceType=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName);
|
||||
lastRightBraceType=InstructionName2JKQTMathTextBraceType(currentTokenName);
|
||||
break;
|
||||
}
|
||||
} else if (currentToken==MTTclosebracket) {
|
||||
@ -1317,9 +1243,10 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
getNew=false;
|
||||
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]);
|
||||
@ -1350,36 +1277,24 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
|
||||
} else {
|
||||
error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID));
|
||||
}
|
||||
|
||||
} else {
|
||||
getNew=false;
|
||||
//error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName));
|
||||
bool foundError=false;
|
||||
JKQTMathTextNode* node=parseInstruction(&foundError, &getNew);
|
||||
if (node) {
|
||||
if (foundError) {
|
||||
delete node;
|
||||
node=nullptr;
|
||||
} else {
|
||||
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!='}' && (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));
|
||||
child=new JKQTMathTextTextNode(this, text, 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 (JKQTMathTextDecoratedNode::supportsInstructionName(currentInstructionName)) {
|
||||
if (getToken()==MTTopenbrace) {
|
||||
child=new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::InstructionName2DecorationType(currentInstructionName), parseLatexString(true));
|
||||
} else {
|
||||
error_list.append(tr("error @ ch. %1: expected %3 arguments in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
|
||||
}
|
||||
} else if (JKQTMathTextFracNode::supportsInstructionName(currentInstructionName)) {
|
||||
if (getToken()==MTTopenbrace) {
|
||||
JKQTMathTextNode* n1=parseLatexString(true);
|
||||
JKQTMathTextNode* n2=nullptr;
|
||||
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
|
||||
if (n1 && n2) child=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 {
|
||||
error_list.append(tr("error @ ch. %1: expected %3 arguments in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
|
||||
}
|
||||
} else if (currentInstructionName=="binom") {
|
||||
if (getToken()==MTTopenbrace) {
|
||||
JKQTMathTextNode* n1=parseLatexString(true);
|
||||
JKQTMathTextNode* n2=nullptr;
|
||||
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
|
||||
if (n1 && n2) child=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 {
|
||||
error_list.append(tr("error @ ch. %1: expected %3 arguments in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
|
||||
}
|
||||
} else {
|
||||
if (getNew) *getNew=true;
|
||||
foundError=true;
|
||||
error_list.append(tr("error @ ch. %1: unknown instruction \\%2 or unsupported instruction at this location").arg(currentTokenID).arg(currentInstructionName));
|
||||
}
|
||||
if (_foundError) *_foundError=foundError;
|
||||
return child;
|
||||
}
|
||||
|
||||
QStringList JKQTMathText::parseStringParams(bool get, size_t Nparams, bool *foundError) {
|
||||
if (*foundError) *foundError=false;
|
||||
if (Nparams<=0) return QStringList();
|
||||
else {
|
||||
QStringList params;
|
||||
for (size_t n=0; n<Nparams; n++) {
|
||||
if (n>0 || (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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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="<<fcol;
|
||||
double width, baselineHeight, overallHeight, strikeoutPos;
|
||||
getChild()->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<QString, JKQTMathTextModifiedTextPropsInstructionNode::InstructionProperties> 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("<span style=\"%1\">").arg(s);
|
||||
bool ok=getChild()->toHtml(html, ev, defaultEv);
|
||||
if (s.size()>0) html=html+"</span>";
|
||||
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<QString, JKQTMathTextBoxInstructionNode::InstructionProperties> 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)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -27,17 +27,46 @@
|
||||
#include "jkqtmathtext/jkqtmathtexttools.h"
|
||||
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
|
||||
#include <QPainter>
|
||||
#include <functional>
|
||||
|
||||
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<void(JKQTMathTextEnvironment& ev, const QStringList& parameters)> 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<QString, InstructionProperties> 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<void(JKQTMathTextEnvironment& ev, const QStringList& parameters)> ModifyEnvironmentFunctor;
|
||||
static ModifyEnvironmentFunctor NoModification;
|
||||
/** \brief this functor returns the QPen to use for the box outline */
|
||||
typedef std::function<QPen(JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent)> 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<QBrush(JKQTMathTextEnvironment& ev, const QStringList& parameters, JKQTMathText* parent)> 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<QString, InstructionProperties> instructions;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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("⊔");
|
||||
|