NEW: JKQTMathText: LaTeX-Parser understands optional instruction parameters in [...] now

This commit is contained in:
jkriege2 2022-06-19 15:11:06 +02:00
parent 5c255712ce
commit d885f7f00a
10 changed files with 486 additions and 310 deletions

View File

@ -39,6 +39,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: reworked node class tree: inserted base-class nodes for single-child, dual-child!</li>
<li>NEW: improved frac-rendering: font-scaling takes nesting-level into account, overall-rendering, sizes, if a brace surrounds a frac, the heights are equal above and below to center the brace , ...</li>
<li>NEW: shows strikeoutPos when drawing Debug-Boxes</li>
<li>NEW: LaTeX-Parser understands optional instruction parameters in [...] now</li>
</ul>
</ul>

View File

@ -355,7 +355,7 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
name=QString("MTsqrtNode: deg=%1").arg(sqrtN->getDegree());
if (sqrtN->getChild()) ti->addChild(createTree(sqrtN->getChild(), ti));
} else if (braceN) {
name=QString("MTbraceNode: l[showL=%3]='%1', r[showR=%4]='%2'").arg(braceN->getOpenbrace()).arg(braceN->getClosebrace()).arg(braceN->getShowOpeningBrace()).arg(braceN->getShowClosingBrace());
name=QString("MTbraceNode: l='%1', r='%2'").arg(JKQTMathTextBraceType2String(braceN->getOpenbrace())).arg(JKQTMathTextBraceType2String(braceN->getClosebrace()));
if (braceN->getChild()) ti->addChild(createTree(braceN->getChild(), ti));
} else if (superN) {
name=QString("MTsuperscriptNode");

View File

@ -823,20 +823,33 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
if (currentTokenID>parseString.size()-1) return currentToken=MTTnone;
QChar c=parseString[currentTokenID];
currentTokenName="";
if (c=='\\') { // read an instruction name
//----------------------------------------------------------
// define some static sets for easy character lookup/identificattion
static QSet<QChar> TokenCharacters;
static QSet<QChar> mathEnvironmentSpecialChars, mathEnvironmentSpecialEndChars;
static QSet<QChar> SingleCharInstructions;
if (TokenCharacters.size()==0) {
mathEnvironmentSpecialChars<<'(' << '[' << '|' << ')' << ']' << '+' << '-' << '*' << '/' << '<' << '>' << '=';
mathEnvironmentSpecialEndChars<<'(' << '&' << '[' << '|' << ')' << ']' << '\\' << '$' << '{' << '}' << '_' << '^' << '+' << '-' << '/' << '*' << '=' << '<' << '>';
TokenCharacters<<'_'<<'^'<<'\\'<<'$'<<'&'<<'}'<<'{'<<'['<<']';
SingleCharInstructions<<'|'<<';'<<':'<<'!'<<','<<'_'<<'\\'<<'$'<<'%'<<'&'<<'#'<<'}'<<'{'<<' '<<'['<<']';
}
//----------------------------------------------------------
// read an instruction name
if (c=='\\') {
currentTokenID++;
if (currentTokenID>=parseString.size()-1) return currentToken=MTTnone;
c=parseString[currentTokenID];
/*if (c=='_' || c=='\\' || c=='$' || c=='%' || c=='&' || c=='#' || c=='}' || c=='{') {
currentTokenName=c; // parse special one-symbol instructions like \\, \& ...
// that may be directly converted to text
return currentToken=MTTtext;
} else*/ if (c=='|' || c==';' || c==':' || c=='!' || c==',' || c=='_' || c=='\\' || c=='$' ||
c=='%' || c=='&' || c=='#' || c=='}' || c=='{' || c==' ') {
//----------------------------------------------------------
// parsing single-character instruction
if (SingleCharInstructions.contains(c)) {
currentTokenName=c; // parse one-symbol instructions like \\, \& ...
//std::cout<<"found text node '"<<currentTokenName.toStdString()<<"'\n";
return currentToken=MTTinstruction;
} else { // parse letter instructions
//----------------------------------------------------------
// letter-only instruction name
} else {
while (c.isLetter()&& (currentTokenID<parseString.size())) {
currentTokenName+=c;
currentTokenID++;
@ -846,42 +859,64 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
currentTokenName=currentTokenName.trimmed();
}
//std::cout<<"found instruction node '"<<currentTokenName.toStdString()<<"'\n";
if (currentTokenName.size()==0) error_list.append(tr("error @ ch. %1: parser encountered empty istruction").arg(currentTokenID));
return currentToken=MTTinstruction;
//----------------------------------------------------------
// check for $ character
} else if (c=='$') {
//std::cout<<"found dollar\n";
return currentToken=MTTdollar;
//----------------------------------------------------------
// check for & character
} else if (c=='&') {
//std::cout<<"found ampersand\n";
return currentToken=MTTampersand;
//----------------------------------------------------------
// check for { character
} else if (c=='{') {
//std::cout<<"found openbrace\n";
return currentToken=MTTopenbrace;
//----------------------------------------------------------
// check for } character
} else if (c=='}') {
//std::cout<<"found closebrace\n";
return currentToken=MTTclosebrace;
//----------------------------------------------------------
// check for [ character
} else if (c=='[') {
//std::cout<<"found openbracket\n";
return currentToken=MTTopenbracket;
//----------------------------------------------------------
// check for ] character
} else if (c==']') {
//std::cout<<"found closebracket\n";
return currentToken=MTTclosebracket;
//----------------------------------------------------------
// check for _ character
} else if (c=='_') {
//std::cout<<"found underscore\n";
return currentToken=MTTunderscore;
//----------------------------------------------------------
// check for ^ character
} else if (c=='^') {
//std::cout<<"found hat\n";
return currentToken=MTThat;
//----------------------------------------------------------
// check for whitespace character
} else if (c.isSpace()) {
while (c.isSpace() &&(currentTokenID<parseString.size())) { // eat up whitespace
currentTokenID++;
if (currentTokenID<parseString.size())c=parseString[currentTokenID];
if (currentTokenID<parseString.size()) c=parseString[currentTokenID];
}
if (!c.isSpace()) currentTokenID--;
//std::cout<<"found whitespace\n";
return currentToken=MTTwhitespace;
} else {
//----------------------------------------------------------
// no instruction or special character => parse text
if (parsingMathEnvironment) {
// inside math environments we split texts at every brace {[(|)]} so that
// braces form their own JKQTMathTextTextNode and may be formated accordingly
static QSet<QChar> mathEnvironmentSpecialChars, mathEnvironmentSpecialEndChars;
if (mathEnvironmentSpecialChars.size()==0) {
mathEnvironmentSpecialChars<<'(' << '[' << '|' << ')' << ']' << '+' << '-' << '*' << '/' << '<' << '>' << '=';
mathEnvironmentSpecialEndChars<<'(' << '&' << '[' << '|' << ')' << ']' << '\\' << '$' << '{' << '}' << '_' << '^' << '+' << '-' << '/' << '*' << '=' << '<' << '>';
}
if (mathEnvironmentSpecialChars.contains(c)) {
currentTokenName=c;
//std::cout<<"found text node '"<<currentTokenName.toStdString()<<"'\n";
@ -896,14 +931,14 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
}
} else currentTokenName+=c;
currentTokenID++;
if (currentTokenID<parseString.size())c=parseString[currentTokenID];
if (currentTokenID<parseString.size()) c=parseString[currentTokenID];
}
if (mathEnvironmentSpecialEndChars.contains(c) || c.isSpace()) currentTokenID--;
//currentTokenName=currentTokenName.trimmed();
//std::cout<<"found text node '"<<currentTokenName.toStdString()<<"'\n";
return currentToken=MTTtext;
} else {
while ((!c.isSpace()) && c!='&' && c!='\\' && c!='$' && c!='{' && c!='}' && c!='_' && c!='^' && (currentTokenID<parseString.size())) {
while ((!c.isSpace()) && !TokenCharacters.contains(c) && (currentTokenID<parseString.size())) {
// add whitespaces only once
if (c.isSpace()) {
if (!currentTokenName.isEmpty()) {
@ -912,9 +947,9 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
}
} else currentTokenName+=c;
currentTokenID++;
if (currentTokenID<parseString.size())c=parseString[currentTokenID];
if (currentTokenID<parseString.size()) c=parseString[currentTokenID];
}
if (c=='&' || c=='\\' || c=='$' || c=='{' || c=='}' || c=='_' || c=='^' || c.isSpace()) currentTokenID--;
if (TokenCharacters.contains(c) || c.isSpace()) currentTokenID--;
//currentTokenName=currentTokenName.trimmed();
//std::cout<<"found text node '"<<currentTokenName.toStdString()<<"'\n";
return currentToken=MTTtext;
@ -923,10 +958,18 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
return currentToken=MTTnone;
}
JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOnClosingBrace, const QString& quitOnEnvironmentEnd) {
JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType quitOnClosingBrace, const QString& quitOnEnvironmentEnd, bool quitOnClosingBracket) {
//std::cout<<" entering parseLatexString()\n";
JKQTMathTextListNode* nl=new JKQTMathTextListNode(this);
if (get) getToken();
//----------------------------------------------------------
// initialize some static sets for easy and fast character lookup
static QSet<QString> mathEnvironmentSpecialText;
if (mathEnvironmentSpecialText.size()==0) {
mathEnvironmentSpecialText<<"+"<<"-"<<"="<<"*"<<"<"<<">"<<"|"<<"/";
}
bool getNew=true;
while (currentToken!=MTTnone) {
getNew=true;
@ -935,10 +978,6 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
bool addWhite=(getToken()==MTTwhitespace) && (!parsingMathEnvironment);
getNew=addWhite;
if (parsingMathEnvironment) {
static QSet<QString> mathEnvironmentSpecialText;
if (mathEnvironmentSpecialText.size()==0) {
mathEnvironmentSpecialText<<"+"<<"-"<<"="<<"*"<<"<"<<">"<<"|"<<"/";
}
if (mathEnvironmentSpecialText.contains(text.trimmed())) {
nl->addNode(new JKQTMathTextSymbolNode(this, text, addWhite));
} else {
@ -948,16 +987,16 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
nl->addNode(new JKQTMathTextTextNode(this, text, addWhite, parsingMathEnvironment));
}
} else if (currentToken==MTTinstruction) {
QString name=currentTokenName;
if (name=="\\") break; // break on linebrak character
const QString currentInstructionName=currentTokenName;
if (currentInstructionName=="\\") break; // break on linebrak character
getToken(); // look at next token
if (currentToken==MTTopenbrace) {
//std::cout<<"found '{' after '"<<name.toStdString()<<"'\n";
if (name=="sqrt") {
if (currentInstructionName=="sqrt") {
nl->addNode(new JKQTMathTextSqrtNode(this, parseLatexString(true)));
} else if (name=="cbrt") {
} else if (currentInstructionName=="cbrt") {
nl->addNode(new JKQTMathTextSqrtNode(this, parseLatexString(true), 3));
} else if (name=="verb") {
} else if (currentInstructionName=="verb") {
QString text="";
currentTokenID++;
if (currentTokenID<=parseString.size()-1) {
@ -967,76 +1006,76 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
currentTokenID++;
if (currentTokenID<parseString.size()) c=parseString[currentTokenID];
}
if (c!='}') error_list.append(tr("error @ ch. %1: \verb{...} not closed by '}'").arg(currentTokenID).arg(name));
if (c!='}') error_list.append(tr("error @ ch. %1: \verb{...} not closed by '}'").arg(currentTokenID).arg(currentInstructionName));
nl->addNode(new JKQTMathTextTextNode(this, text, false));
}
} else if (name=="frac") {
} else if (currentInstructionName=="frac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="dfrac" || name=="cfrac") {
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="dfrac" || currentInstructionName=="cfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMdfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="sfrac" || name=="slantfrac" || name=="xfrac") {
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="sfrac" || currentInstructionName=="slantfrac" || currentInstructionName=="xfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMsfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="stfrac" || name=="nicefrac" || name=="slanttextfrac" || name=="xtfrac") {
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="stfrac" || currentInstructionName=="nicefrac" || currentInstructionName=="slanttextfrac" || currentInstructionName=="xtfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="tfrac") {
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="tfrac") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMtfrac));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="stackrel") {
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="stackrel") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(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(name));
} else if (name=="binom") {
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->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTParenthesis, JKQTMathTextBraceNode::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(name));
} else if (name=="underbrace") {
if (n1 && n2) nl->addNode(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel)));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="underbrace") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbrace));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="underset") {
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="underset") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderset));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="overbrace") {
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="overbrace") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbrace));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="overset") {
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else if (currentInstructionName=="overset") {
JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addNode(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverset));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
} else if (name=="begin") {
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'
@ -1048,7 +1087,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
QVector<JKQTMathTextNode*> line;
//std::cout<<"found \\begin{matrix}\n";
while (first || currentToken==MTTampersand || (currentToken==MTTinstruction && currentTokenName=="\\")) {
JKQTMathTextNode* it=parseLatexString(true, "", envname);
JKQTMathTextNode* it=parseLatexString(true, MTBTAny, envname);
if (currentToken==MTTampersand) {
//std::cout<<" appending item\n";
line.append(it);
@ -1061,12 +1100,12 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
first=false;
}
//std::cout<<" creating matrix-node with "<<items.size()<<" items.\n";
if (envname=="pmatrix") nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTParenthesis, JKQTMathTextBraceNode::MTBTParenthesis, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="cases") nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTCurlyBracket, JKQTMathTextBraceNode::MTBTNone, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="bmatrix") nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTSquareBracket, JKQTMathTextBraceNode::MTBTSquareBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Bmatrix") nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTCurlyBracket, JKQTMathTextBraceNode::MTBTCurlyBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="vmatrix") nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTSingleLine, JKQTMathTextBraceNode::MTBTSingleLine, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Vmatrix") nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTDoubleLine, JKQTMathTextBraceNode::MTBTDoubleLine, new JKQTMathTextMatrixNode(this, items)));
if (envname=="pmatrix") nl->addNode(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="cases") nl->addNode(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTNone, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="bmatrix") nl->addNode(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Bmatrix") nl->addNode(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTCurlyBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="vmatrix") nl->addNode(new JKQTMathTextBraceNode(this, MTBTSingleLine, MTBTSingleLine, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Vmatrix") nl->addNode(new JKQTMathTextBraceNode(this, MTBTDoubleLine, MTBTDoubleLine, new JKQTMathTextMatrixNode(this, items)));
else nl->addNode(new JKQTMathTextMatrixNode(this, items));
//std::cout<<" creating matrix-node ... done!\n";
} else {
@ -1077,7 +1116,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
while (currentToken!=MTTclosebrace) getToken();
getNew=true;
}
} else if (name=="end") {
} else if (currentInstructionName=="end") {
if (getToken()==MTTtext) {
QString envname=currentTokenName;
while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name'
@ -1091,50 +1130,50 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
while (currentToken!=MTTclosebrace) getToken();
getNew=true;
}
} else if (name=="vec") {
} else if (currentInstructionName=="vec") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDvec, parseLatexString(true)));
} else if (name=="overline"||name=="oline"||name=="ol") {
} else if (currentInstructionName=="overline"||currentInstructionName=="oline"||currentInstructionName=="ol") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDoverline, parseLatexString(true)));
} else if (name=="underline"||name=="uline"||name=="ul") {
} else if (currentInstructionName=="underline"||currentInstructionName=="uline"||currentInstructionName=="ul") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDunderline, parseLatexString(true)));
} else if (name=="uuline"||name=="uul") {
} else if (currentInstructionName=="uuline"||currentInstructionName=="uul") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleunderline, parseLatexString(true)));
} else if (name=="ooline"||name=="ool") {
} else if (currentInstructionName=="ooline"||currentInstructionName=="ool") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleoverline, parseLatexString(true)));
} else if (name=="arrow"||name=="overrightarrow"||name=="overarrow") {
} else if (currentInstructionName=="arrow"||currentInstructionName=="overrightarrow"||currentInstructionName=="overarrow") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDarrow, parseLatexString(true)));
} else if (name=="hat" || name=="^") {
} else if (currentInstructionName=="hat" || currentInstructionName=="^") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDhat, parseLatexString(true)));
} else if (name=="widehat") {
} else if (currentInstructionName=="widehat") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidehat, parseLatexString(true)));
} else if (name=="check" || name=="v") {
} else if (currentInstructionName=="check" || currentInstructionName=="v") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcheck, parseLatexString(true)));
} else if (name=="widecheck") {
} else if (currentInstructionName=="widecheck") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidecheck, parseLatexString(true)));
} else if (name=="bar") {
} else if (currentInstructionName=="bar") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbar, parseLatexString(true)));
} else if (name=="dot" || name==".") {
} else if (currentInstructionName=="dot" || currentInstructionName==".") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdot, parseLatexString(true)));
} else if (name=="ocirc") {
} else if (currentInstructionName=="ocirc") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDocirc, parseLatexString(true)));
} else if (name=="tilde" || name=="~") {
} else if (currentInstructionName=="tilde" || currentInstructionName=="~") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDtilde, parseLatexString(true)));
} else if (name=="breve" || name=="u") {
} else if (currentInstructionName=="breve" || currentInstructionName=="u") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbreve, parseLatexString(true)));
} else if (name=="widetilde") {
} else if (currentInstructionName=="widetilde") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidetilde, parseLatexString(true)));
} else if (name=="ddot") {
} else if (currentInstructionName=="ddot") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDddot, parseLatexString(true)));
} else if (name=="cancel") {
} else if (currentInstructionName=="cancel") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcancel, parseLatexString(true)));
} else if (name=="xcancel") {
} else if (currentInstructionName=="xcancel") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDxcancel, parseLatexString(true)));
} else if (name=="bcancel") {
} else if (currentInstructionName=="bcancel") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbcancel, parseLatexString(true)));
} else if (name=="strike" || name=="st" || name=="sout") {
} else if (currentInstructionName=="strike" || currentInstructionName=="st" || currentInstructionName=="sout") {
nl->addNode(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDstrike, parseLatexString(true)));
} else {
if (name=="textcolor" || name=="mathcolor" || name=="color" || name=="colorbox") {
if (currentInstructionName=="textcolor" || currentInstructionName=="mathcolor" || currentInstructionName=="color" || currentInstructionName=="colorbox") {
bool foundError=true;
QString col="";
if (getToken()==MTTtext) {
@ -1145,127 +1184,106 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
}
}
}
if (foundError) error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(name));
else nl->addNode(new JKQTMathTextInstruction1Node(this, name, parseLatexString(true), QStringList(col)));
if (foundError) error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
else nl->addNode(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true), QStringList(col)));
} else {
nl->addNode(new JKQTMathTextInstruction1Node(this, name, parseLatexString(true)));
nl->addNode(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);
JKQTMathTextListNode* n1lst=dynamic_cast<JKQTMathTextListNode*>(n1);
JKQTMathTextTextNode* n1txt=dynamic_cast<JKQTMathTextTextNode*>(n1);
if (n1lst && n1lst->count()==1) {
n1txt=dynamic_cast<JKQTMathTextTextNode*>(n1lst->child(0));
}
int degree=2;
bool ok=false;
if (n1txt) degree=n1txt->getText().toInt(&ok);
if (!ok) {
degree=2;
error_list.append(tr("error @ ch. %1: an integer in [] after '%2' command").arg(currentTokenID).arg(currentInstructionName));
}
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->addNode(new JKQTMathTextSqrtNode(this, n2, degree));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else {
nl->addNode(new JKQTMathTextTextNode(this, "[", false));
}
} else {
//std::cout<<"did not find '{' after '"<<name.toStdString()<<"'\n";
if (name=="right") {
if (currentInstructionName=="right") {
if (currentToken==MTTtext) {
if (currentTokenName.size()>0) {
if (QString(currentTokenName[0])==quitOnClosingBrace || quitOnClosingBrace=="any" || QString(currentTokenName[0])==".") {
bool tokenWasNoBrace=false;
if (TokenNameMatchesJKQTMathTextBraceType(currentTokenName[0], quitOnClosingBrace, true, &tokenWasNoBrace)) {
//std::cout<<"found \\right '"<<currentTokenName.toStdString()<<"'\n";
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
showLeftBrace=(quitOnClosingBrace==MTBTAny || quitOnClosingBrace!=MTBTNone);
showRightBrace=!tokenWasNoBrace;
//if (!showRightBrace) std::cout<<"don't show right brace '"<<quitOnClosingBrace.toStdString()<<"' !!!\n";
if (quitOnClosingBrace!="any") currentTokenName=currentTokenName.right(currentTokenName.size()-1);
if (quitOnClosingBrace!=MTBTAny) currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else {
getNew=false;
}
}
} else if (currentToken==MTTinstruction) {
if (quitOnClosingBrace=="~" && (currentTokenName=="rceil" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace=="}" && (currentTokenName=="}" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace=="_" && (currentTokenName=="rfloor" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace=="#" && (currentTokenName=="|" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace==">" && (currentTokenName=="rangle" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace=="any") {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
//currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
if (InstructionNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
}
} else if (currentToken==MTTclosebracket) {
if (quitOnClosingBrace==MTBTSquareBracket || quitOnClosingBrace==MTBTAny) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
}
} else {
getNew=false;
}
} else if (name=="left") {
} else if (currentInstructionName=="left") {
if (currentToken==MTTtext) {
if (currentTokenName.size()>0) {
if (currentTokenName[0]=='(') {
const JKQTMathTextBraceType bracetype=TokenName2JKQTMathTextBraceType(currentTokenName[0]);
if (bracetype==MTBTNone) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
JKQTMathTextNode* cn=parseLatexString(currentTokenName.size()<=0, MTBTAny);
nl->addNode(new JKQTMathTextBraceNode(this, MTBTNone, bracetype, cn));
} else if (isPrintableJKQTMathTextBraceType(bracetype)) {
currentTokenName=currentTokenName.right(currentTokenName.size()-1); // we already used the first character from the text token!
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTParenthesis, JKQTMathTextBraceNode::MTBTParenthesis, parseLatexString(currentTokenName.size()<=0, ")"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='[') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTSquareBracket, JKQTMathTextBraceNode::MTBTSquareBracket, parseLatexString(currentTokenName.size()<=0, "]"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='{') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTCurlyBracket, JKQTMathTextBraceNode::MTBTCurlyBracket, parseLatexString(currentTokenName.size()<=0, "}"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='<') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTAngleBracket, JKQTMathTextBraceNode::MTBTAngleBracket, parseLatexString(currentTokenName.size()<=0, ">"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='|') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTSingleLine, JKQTMathTextBraceNode::MTBTSingleLine, parseLatexString(currentTokenName.size()<=0, "|"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='~') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTCeilBracket, JKQTMathTextBraceNode::MTBTCeilBracket, parseLatexString(currentTokenName.size()<=0, "~"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='_') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTFloorBracket, JKQTMathTextBraceNode::MTBTFloorBracket, parseLatexString(currentTokenName.size()<=0, "_"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='#') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTDoubleLine, JKQTMathTextBraceNode::MTBTDoubleLine, parseLatexString(currentTokenName.size()<=0, "#"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='.') {
showLeftBrace=false;
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
JKQTMathTextNode* cn=parseLatexString(currentTokenName.size()<=0, "any");
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTNone, JKQTMathTextBraceNode::TokenNameString2TokenType(currentTokenName), cn, showLeftBrace, showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, bracetype, bracetype, parseLatexString(currentTokenName.size()<=0, bracetype)));
} else {
getNew=false;
}
}
} else if (currentToken==MTTinstruction && currentTokenName=="langle") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTAngleBracket, JKQTMathTextBraceNode::MTBTAngleBracket, parseLatexString(true, ">"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName=="{") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTCurlyBracket, JKQTMathTextBraceNode::MTBTCurlyBracket, parseLatexString(currentTokenName.size()<=0, "}"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName=="lfloor") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTFloorBracket, JKQTMathTextBraceNode::MTBTFloorBracket, parseLatexString(true, "_"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName=="lceil") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTCeilBracket, JKQTMathTextBraceNode::MTBTCeilBracket, parseLatexString(true, "~"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName=="|") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, JKQTMathTextBraceNode::MTBTDoubleLine, JKQTMathTextBraceNode::MTBTDoubleLine, parseLatexString(currentTokenName.size()<=0, "#"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName==quitOnClosingBrace) {
break;
} else if (currentToken==MTTinstruction) {
const JKQTMathTextBraceType bracetypeopening=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName);
if (bracetypeopening!=MTBTUnknown) {
nl->addNode(new JKQTMathTextBraceNode(this, bracetypeopening, bracetypeopening, parseLatexString(true, bracetypeopening)));
} else if (currentToken==MTTinstruction && TokenNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) {
break;
}
} else if (currentToken==MTTopenbracket) {
nl->addNode(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, parseLatexString(true, MTBTSquareBracket)));
} else {
error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID));
}
} else {
//bool addWhite=(currentToken==MTTwhitespace);
//getNew=addWhite;
getNew=false;
bool done=false;
if (name.size()==2) {
QChar n0=name[0];
QChar n1=name[1];
if (currentInstructionName.size()==2) {
QChar n0=currentInstructionName[0];
QChar n1=currentInstructionName[1];
if (n0=='v' && n1.isLetter()) {
done=true;
//std::cout<<"found \\v... command\n";
@ -1275,16 +1293,16 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
//std::cout<<"found \\v... command\n";
nl->addNode(new JKQTMathTextInstruction1Node(this, "mathcal", new JKQTMathTextTextNode(this, QString(n1), false, parsingMathEnvironment)));
}
} else if (name.size()==3) {
QString n0=name.left(2);
QChar n1=name[name.size()-1];
} else if (currentInstructionName.size()==3) {
QString n0=currentInstructionName.left(2);
QChar n1=currentInstructionName[currentInstructionName.size()-1];
if (n0=="bb" && n1.isLetter()) {
done=true;
//std::cout<<"found \\v... command\n";
nl->addNode(new JKQTMathTextInstruction1Node(this, "mathbb", new JKQTMathTextTextNode(this, QString(n1), false, parsingMathEnvironment)));
}
}
if (!done) nl->addNode(new JKQTMathTextSymbolNode(this, name, false));//, addWhite));
if (!done) nl->addNode(new JKQTMathTextSymbolNode(this, currentInstructionName, false));//, addWhite));
}
}
@ -1354,6 +1372,11 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
nl->addNode(parseLatexString(true));
} else if (currentToken==MTTclosebrace) {
break;
} else if (currentToken==MTTopenbracket) {
nl->addNode(new JKQTMathTextTextNode(this, "[", false));
} else if (currentToken==MTTclosebracket) {
if (quitOnClosingBracket) break;
else nl->addNode(new JKQTMathTextTextNode(this, "]", false));
} else if (currentToken==MTTampersand) {
break;
} else if (currentToken==MTTdollar) {
@ -1368,9 +1391,10 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
if (getNew) getToken();
}
//std::cout<<" leaving parseLatexString()\n";
return nl;
return JKQTMathTextListNode::simplyfyListNode(nl);
}
JKQTMathTextNode *JKQTMathText::getParsedNode() const {
return this->parsedNode;
}

View File

@ -589,22 +589,30 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
/** \brief the token types that may arrise in the string */
enum tokenType {
MTTnone,
MTTtext,
MTTinstruction,
MTTunderscore,
MTThat,
MTTdollar,
MTTopenbrace,
MTTclosebrace,
MTTwhitespace,
MTTampersand
MTTnone, /*!< \brief no token */
MTTtext, /*!< \brief a piece of general text */
MTTinstruction, /*!< \brief an instruction, started by "\", e.g. "\textbf", ... */
MTTunderscore, /*!< \brief the character "_" */
MTThat, /*!< \brief the character "^" */
MTTdollar, /*!< \brief the character "$" */
MTTopenbrace, /*!< \brief the character "{" */
MTTclosebrace, /*!< \brief the character "}" */
MTTopenbracket, /*!< \brief the character "[" */
MTTclosebracket, /*!< \brief the character "]" */
MTTwhitespace, /*!< \brief some whitespace */
MTTampersand /*!< \brief the character "&" */
};
/** \brief tokenizer for the LaTeX parser */
tokenType getToken();
/** \brief parse a LaTeX string */
JKQTMathTextNode* parseLatexString(bool get, const QString& quitOnClosingBrace=QString(""), const QString& quitOnEnvironmentEnd=QString(""));
/** \brief parse a LaTeX string
*
* \param get if \c true this calls getToken()
* \param quitOnClosingBrace if unequal MTBTAny, this returns if the given closing brace is found
* \param quitOnEnvironmentEnd wuit if \end{quitOnEnvironmentEnd} is found
* \param quitOnClosingBracket if \c true, quits on encountering a MTTclosebracket token
*/
JKQTMathTextNode* parseLatexString(bool get, JKQTMathTextBraceType quitOnClosingBrace=JKQTMathTextBraceType::MTBTAny, const QString& quitOnEnvironmentEnd=QString(""), bool quitOnClosingBracket=false);
/** \brief parse a LaTeX math environment */
JKQTMathTextNode* parseMath(bool get);

View File

@ -325,6 +325,87 @@ QString JKQTMathTextFontEncoding2String(JKQTMathTextFontEncoding e)
return "???";
}
QString JKQTMathTextBraceType2String(JKQTMathTextBraceType type) {
switch(type) {
case MTBTAngleBracket:
return "angle_bracket";
case MTBTSquareBracket:
return "square_bracket";
case MTBTCeilBracket:
return "ceil_bracket";
case MTBTCurlyBracket:
return "curly_bracket";
case MTBTDoubleLine:
return "double_line";
case MTBTFloorBracket:
return "floor_bracket";
case MTBTParenthesis:
return "parenhesis";
case MTBTSingleLine:
return "single_line";
case MTBTAny:
return "any";
case MTBTNone:
return "none";
}
return "unknown";
}
JKQTMathTextBraceType TokenName2JKQTMathTextBraceType(const QString &tokenName)
{
if (tokenName=="(" || tokenName==")") return MTBTParenthesis;
if (tokenName=="[" || tokenName=="]") return MTBTSquareBracket;
if (tokenName=="{" || tokenName=="}") return MTBTCurlyBracket;
if (tokenName=="|") return MTBTSingleLine;
if (tokenName=="||" || tokenName=="#") return MTBTDoubleLine;
if (tokenName=="<" || tokenName==">" || tokenName=="langle" || tokenName=="rangle") return MTBTAngleBracket;
if (tokenName=="_" || tokenName=="lfloor" || tokenName=="rfloor") return MTBTFloorBracket;
if (tokenName=="~" || tokenName=="lceil" || tokenName=="rceil") return MTBTCeilBracket;
if (tokenName=="any") return MTBTAny;
if (tokenName=="." || tokenName=="" || tokenName=="none") return MTBTNone;
return MTBTUnknown;
}
JKQTMathTextBraceType InstructionName2OpeningJKQTMathTextBraceType(const QString &tokenName)
{
if (tokenName=="{") return MTBTCurlyBracket;
if (tokenName=="|") return MTBTDoubleLine;
if (tokenName=="langle") return MTBTAngleBracket;
if (tokenName=="lfloor") return MTBTFloorBracket;
if (tokenName=="lceil") return MTBTCeilBracket;
return MTBTUnknown;
}
JKQTMathTextBraceType InstructionName2JKQTMathTextBraceType(const QString &tokenName)
{
if (tokenName=="{" || tokenName=="}") return MTBTCurlyBracket;
if (tokenName=="|") return MTBTDoubleLine;
if (tokenName=="langle" || tokenName=="rangle") return MTBTAngleBracket;
if (tokenName=="lfloor" || tokenName=="rfloor") return MTBTFloorBracket;
if (tokenName=="lceil" || tokenName=="rceil") return MTBTCeilBracket;
return MTBTUnknown;
}
bool TokenNameMatchesJKQTMathTextBraceType(const QString &token, JKQTMathTextBraceType type, bool acceptMTBTNone, bool* tokenEqualsNone)
{
const JKQTMathTextBraceType bt=TokenName2JKQTMathTextBraceType(token);
if (tokenEqualsNone) *tokenEqualsNone=(bt==MTBTNone);
if (type==MTBTAny) return true;
if (acceptMTBTNone && bt==MTBTNone) return true;
return (bt==type);
}
bool InstructionNameMatchesJKQTMathTextBraceType(const QString &token, JKQTMathTextBraceType type, bool acceptMTBTNone, bool* tokenEqualsNone)
{
const JKQTMathTextBraceType bt=InstructionName2JKQTMathTextBraceType(token);
if (tokenEqualsNone) *tokenEqualsNone=(bt==MTBTNone);
if (type==MTBTAny) return true;
if (acceptMTBTNone && bt==MTBTNone) return true;
return (bt==type);
}
JKQTMathTextEnvironment::JKQTMathTextEnvironment() {
color=QColor("black");
font=MTEroman;
@ -577,3 +658,8 @@ QFont JKQTMathTextGetNonItalic(const QFont &font)
return f;
}
bool isPrintableJKQTMathTextBraceType(JKQTMathTextBraceType type)
{
return (type!=MTBTAny) && (type!=MTBTUnknown);
}

View File

@ -137,6 +137,65 @@ enum JKQTMathTextFontEncoding {
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextFontEncoding2String(JKQTMathTextFontEncoding e);
/** \brief types of available braces
* \ingroup jkqtmathtext
*/
enum JKQTMathTextBraceType {
MTBTParenthesis=0, /*!< \brief parantheses () \image html jkqtmathtext/jkqtmathtext_brace_round.png */
MTBTSquareBracket, /*!< \brief brackets [] \image html jkqtmathtext/jkqtmathtext_brace_rect.png */
MTBTCurlyBracket, /*!< \brief curly braces {} \image html jkqtmathtext/jkqtmathtext_brace_curly.png */
MTBTAngleBracket, /*!< \brief angle backets <> \image html jkqtmathtext/jkqtmathtext_brace_tri.png */
MTBTCeilBracket, /*!< \brief ceil brackets \image html jkqtmathtext/jkqtmathtext_brace_ceil.png */
MTBTFloorBracket, /*!< \brief floor brackets \image html jkqtmathtext/jkqtmathtext_brace_floor.png */
MTBTDoubleLine, /*!< \brief double-line brackets (norm ||...||) \image html jkqtmathtext/jkqtmathtext_brace_dblline.png */
MTBTSingleLine, /*!< \brief single-line brackets (abs |...|) \image html jkqtmathtext/jkqtmathtext_brace_oneline.png */
MTBTNone, /*!< \brief no bracket */
MTBTAny, /*!< \brief any bracket, used by JKQTMathText::parseLatexString() */
MTBTUnknown /*!< \brief an unknown tokenName presented to TokenName2JKQTMathTextBraceType() */
};
/** \brief convert a JKQTMathTextBraceType into a string
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextBraceType2String(JKQTMathTextBraceType type);
/** \brief convert a string \a tokenName describing a LaTeX Token or Instruction into an opening or closing JKQTMathTextBraceType
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceType TokenName2JKQTMathTextBraceType(const QString& tokenName);
/** \brief convert a string \a tokenName describing a LaTeX Instruction into an opening JKQTMathTextBraceType
* \ingroup jkqtmathtext
*
* This returns a JKQTMathTextBraceType for which isPrintableJKQTMathTextBraceType() is \c true, or MTBTUnknown,
* never MTBTNone or MTBTAny.
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceType InstructionName2OpeningJKQTMathTextBraceType(const QString& tokenName);
/** \brief convert a string \a tokenName describing a LaTeX Instruction into an opening or closing JKQTMathTextBraceType
* \ingroup jkqtmathtext
*
* This returns a JKQTMathTextBraceType for which isPrintableJKQTMathTextBraceType() is \c true, or MTBTUnknown,
* never MTBTNone or MTBTAny.
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceType InstructionName2JKQTMathTextBraceType(const QString& tokenName);
/** \brief return \c true if \a type represents a printable type of brace (including MTBTNone), basically \c true
* for any JKQTMathTextBraceType that can be used as parameter to JKQTMathTextBraceNode
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT bool isPrintableJKQTMathTextBraceType(JKQTMathTextBraceType type);
/** \brief returns true, if the given token/instruction-Name \a token ("{", "(", ..., "lceil", ".", ...) matches the given \a type (returns true, when \a type == MTBTAny )
* \ingroup jkqtmathtext
*
* This accepts TokenName2JKQTMathTextBraceType(toke)==MTBTNone for any \a type, iff \a acceptMTBTNone \a ==true.
*
* Optionally returns in \a tokenEqualsNone whether \a token was encoding for MTBTNone .
*/
JKQTMATHTEXT_LIB_EXPORT bool TokenNameMatchesJKQTMathTextBraceType(const QString &token, JKQTMathTextBraceType type, bool acceptMTBTNone, bool *tokenEqualsNone=nullptr);
/** \brief returns true, if the given instruction-Name \a token ("|", "{", ..., "lceil", ".", ...) matches the given \a type (returns true, when \a type == MTBTAny )
* \ingroup jkqtmathtext
*
* This accepts TokenName2JKQTMathTextBraceType(toke)==MTBTNone for any \a type, iff \a acceptMTBTNone \a ==true.
*
* Optionally returns in \a tokenEqualsNone whether \a token was encoding for MTBTNone .
*/
JKQTMATHTEXT_LIB_EXPORT bool InstructionNameMatchesJKQTMathTextBraceType(const QString &token, JKQTMathTextBraceType type, bool acceptMTBTNone, bool *tokenEqualsNone=nullptr);
/** \brief the available logical fonts (default is MTEroman)
* \ingroup jkqtmathtext

View File

@ -36,48 +36,11 @@
QString JKQTMathTextBraceNode::BraceType2String(BraceType type) {
switch(type) {
case MTBTAngleBracket:
return "angle_bracket";
case MTBTSquareBracket:
return "square_bracket";
case MTBTCeilBracket:
return "ceil_bracket";
case MTBTCurlyBracket:
return "curly_bracket";
case MTBTDoubleLine:
return "double_line";
case MTBTFloorBracket:
return "floor_bracket";
case MTBTParenthesis:
return "parenhesis";
case MTBTSingleLine:
return "single_line";
}
return "unknown";
}
JKQTMathTextBraceNode::BraceType JKQTMathTextBraceNode::TokenNameString2TokenType(const QString &type)
{
if (type=="(" || type==")") return MTBTParenthesis;
if (type=="[" || type=="]") return MTBTSquareBracket;
if (type=="{" || type=="}") return MTBTCurlyBracket;
if (type=="|") return MTBTSingleLine;
if (type=="||" || type=="#") return MTBTDoubleLine;
if (type=="<" || type==">" || type=="langle" || type=="rangle") return MTBTAngleBracket;
if (type=="_" || type=="lfloor" || type=="rfloor") return MTBTFloorBracket;
if (type=="~" || type=="lceil" || type=="rceil") return MTBTCeilBracket;
return MTBTNone;
}
JKQTMathTextBraceNode::JKQTMathTextBraceNode(JKQTMathText* _parent, JKQTMathTextBraceNode::BraceType openbrace, JKQTMathTextBraceNode::BraceType closebrace, JKQTMathTextNode* child, bool showOpeningBrace, bool showClosingBrace):
JKQTMathTextBraceNode::JKQTMathTextBraceNode(JKQTMathText* _parent, JKQTMathTextBraceType openbrace, JKQTMathTextBraceType closebrace, JKQTMathTextNode* child):
JKQTMathTextSingleChildNode(child, _parent)
{
this->openbrace=openbrace;
this->closebrace=closebrace;
this->showClosingBrace=showClosingBrace;
this->showOpeningBrace=showOpeningBrace;
}
@ -116,8 +79,8 @@ void JKQTMathTextBraceNode::getSizeInternalAndBrace(QPainter &painter, JKQTMathT
bracewidth=bracewidth/parentMathText->getBraceShrinkFactor();
if (showOpeningBrace) width+=bracewidth;
if (showClosingBrace) width+=bracewidth;
if (openbrace!=MTBTNone && openbrace!=MTBTAny) width+=bracewidth;
if (closebrace!=MTBTNone && closebrace!=MTBTAny) width+=bracewidth;
}
double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
@ -143,7 +106,8 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
painter.setPen(p);
const double paren_fraction=0.85;
const double brace_fraction=0.65;
if (showOpeningBrace) {
{
bool showOpeningBrace=true;
const double xbrace1=xnew+lw;
const double xbrace2=qMin(xnew+paren_fraction*bracewidth, xnew+bracewidth-lw/2.0);
const double xbrace2s=qMin(xnew+brace_fraction*bracewidth, xnew+bracewidth-lw/2.0);
@ -154,7 +118,7 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.moveTo(xbrace2, y1);
path.cubicTo(xbrace1, (y1+y2)/2.0+fabs(y1-y2)/6.0, xbrace1, (y1+y2)/2.0-fabs(y1-y2)/6.0 , xbrace2, y2);
painter.drawPath(path);
} else if (openbrace==JKQTMathTextBraceNode::MTBTSquareBracket) {
} else if (openbrace==MTBTSquareBracket) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
@ -163,14 +127,14 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace1, y2);
path.lineTo(xbrace2s, y2);
painter.drawPath(path);
} else if (openbrace==JKQTMathTextBraceNode::MTBTCurlyBracket) {
} else if (openbrace==MTBTCurlyBracket) {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,nodeOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.translate((xbrace1+xbrace2)/2.0, y-nodeBaselineHeight+nodeOverallHeight/2.0);
painter.rotate(90);
painter.drawPath(path);
} else if (openbrace==JKQTMathTextBraceNode::MTBTFloorBracket) {
} else if (openbrace==MTBTFloorBracket) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
@ -178,7 +142,7 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace1, y1);
path.lineTo(xbrace1, y2);
painter.drawPath(path);
} else if (openbrace==JKQTMathTextBraceNode::MTBTCeilBracket) {
} else if (openbrace==MTBTCeilBracket) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
@ -186,19 +150,19 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace1, y2);
path.lineTo(xbrace2s, y2);
painter.drawPath(path);
} else if (openbrace==JKQTMathTextBraceNode::MTBTSingleLine) {
} else if (openbrace==MTBTSingleLine) {
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
const QLineF l(xbrace1, y1, xbrace1, y2);
if (l.length()>0) painter.drawLine(l);
} else if (openbrace==JKQTMathTextBraceNode::MTBTDoubleLine) {
} else if (openbrace==MTBTDoubleLine) {
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
const QLineF l(xbrace1, y1, xbrace1, y2);
if (l.length()>0) painter.drawLine(l);
const QLineF l2(xbrace1+1.5*lw, y1, xbrace1+1.5*lw, y2);
if (l2.length()>0) painter.drawLine(l2);
} else if (openbrace==JKQTMathTextBraceNode::MTBTAngleBracket) {
} else if (openbrace==MTBTAngleBracket) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
@ -206,27 +170,32 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace1, (y2+y1)/2.0);
path.lineTo(xbrace2, y2);
painter.drawPath(path);
} else {
showOpeningBrace=false;
}
if (showOpeningBrace) {
xnew=xnew+bracewidth;
}
xnew=xnew+bracewidth;
}
painter.setPen(pold);
xnew= child->draw(painter, xnew, y, currentEv);
if (showClosingBrace) {
{
bool showClosingBrace=true;
const double xbrace1=qMax(xnew+bracewidth-paren_fraction*bracewidth, xnew+lw/2.0);
const double xbrace1s=qMax(xnew+bracewidth-brace_fraction*bracewidth, xnew+lw/2.0);
const double xbrace2=xnew+bracewidth-lw;
painter.setPen(p);
if (closebrace==JKQTMathTextBraceNode::MTBTParenthesis) {
if (closebrace==MTBTParenthesis) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace1, y1);
path.cubicTo(xbrace2, (y1+y2)/2.0+fabs(y1-y2)/6.0, xbrace2, (y1+y2)/2.0-fabs(y1-y2)/6.0 , xbrace1, y2);
painter.drawPath(path);
} else if (closebrace==JKQTMathTextBraceNode::MTBTSquareBracket) {
} else if (closebrace==MTBTSquareBracket) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
@ -235,14 +204,14 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace2, y2);
path.lineTo(xbrace1s, y2);
painter.drawPath(path);
} else if (closebrace==JKQTMathTextBraceNode::MTBTCurlyBracket) {
} else if (closebrace==MTBTCurlyBracket) {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,nodeOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.translate((xbrace1+xbrace2)/2.0, y-nodeBaselineHeight+nodeOverallHeight/2.0);
painter.rotate(270);
painter.drawPath(path);
} else if (closebrace==JKQTMathTextBraceNode::MTBTFloorBracket) {
} else if (closebrace==MTBTFloorBracket) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
@ -250,7 +219,7 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace2, y1);
path.lineTo(xbrace2, y2);
painter.drawPath(path);
} else if (closebrace==JKQTMathTextBraceNode::MTBTCeilBracket) {
} else if (closebrace==MTBTCeilBracket) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
@ -258,19 +227,19 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace2, y2);
path.lineTo(xbrace1s, y2);
painter.drawPath(path);
} else if (closebrace==JKQTMathTextBraceNode::MTBTSingleLine) {
} else if (closebrace==MTBTSingleLine) {
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
const QLineF l(xbrace2, y1, xbrace2, y2);
if (l.length()>0) painter.drawLine(l);
} else if (closebrace==JKQTMathTextBraceNode::MTBTDoubleLine) {
} else if (closebrace==MTBTDoubleLine) {
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
const QLineF l(xbrace2, y1, xbrace2, y2);
if (l.length()>0) painter.drawLine(l);
const QLineF l2(xbrace2-1.5*lw, y1, xbrace2-1.5*lw, y2);
if (l2.length()>0) painter.drawLine(l2);
} else if (closebrace==JKQTMathTextBraceNode::MTBTAngleBracket) {
} else if (closebrace==MTBTAngleBracket) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
@ -278,9 +247,13 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace2, (y2+y1)/2.0);
path.lineTo(xbrace1, y2);
painter.drawPath(path);
} else {
showClosingBrace=false;
}
painter.setPen(pold);
xnew=xnew+bracewidth;
if (showClosingBrace) {
xnew=xnew+bracewidth;
}
}
//qDebug()<<" ==> "<<bc<<fm.boundingRect(bc).width();
@ -290,22 +263,22 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
bool JKQTMathTextBraceNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
QString ob;
QString cb;
if (openbrace==JKQTMathTextBraceNode::MTBTAngleBracket) ob="&lang;";
else if (openbrace==JKQTMathTextBraceNode::MTBTFloorBracket) ob="&lfloor;";
else if (openbrace==JKQTMathTextBraceNode::MTBTCeilBracket) ob="&lceil;";
else if (openbrace==JKQTMathTextBraceNode::MTBTParenthesis) ob="(";
else if (openbrace==JKQTMathTextBraceNode::MTBTSquareBracket) ob="[";
else if (openbrace==JKQTMathTextBraceNode::MTBTCurlyBracket) ob="{";
else if (openbrace==JKQTMathTextBraceNode::MTBTSingleLine) ob="|";
else if (openbrace==JKQTMathTextBraceNode::MTBTDoubleLine) ob="||";
if (closebrace==JKQTMathTextBraceNode::MTBTAngleBracket) cb="&rang;";
else if (closebrace==JKQTMathTextBraceNode::MTBTFloorBracket) cb="&rfloor;";
else if (closebrace==JKQTMathTextBraceNode::MTBTCeilBracket) cb="&rceil;";
else if (closebrace==JKQTMathTextBraceNode::MTBTParenthesis) cb=")";
else if (closebrace==JKQTMathTextBraceNode::MTBTSquareBracket) cb="]";
else if (closebrace==JKQTMathTextBraceNode::MTBTCurlyBracket) cb="}";
else if (closebrace==JKQTMathTextBraceNode::MTBTSingleLine) cb="|";
else if (closebrace==JKQTMathTextBraceNode::MTBTDoubleLine) cb="||";
if (openbrace==MTBTAngleBracket) ob="&lang;";
else if (openbrace==MTBTFloorBracket) ob="&lfloor;";
else if (openbrace==MTBTCeilBracket) ob="&lceil;";
else if (openbrace==MTBTParenthesis) ob="(";
else if (openbrace==MTBTSquareBracket) ob="[";
else if (openbrace==MTBTCurlyBracket) ob="{";
else if (openbrace==MTBTSingleLine) ob="|";
else if (openbrace==MTBTDoubleLine) ob="||";
if (closebrace==MTBTAngleBracket) cb="&rang;";
else if (closebrace==MTBTFloorBracket) cb="&rfloor;";
else if (closebrace==MTBTCeilBracket) cb="&rceil;";
else if (closebrace==MTBTParenthesis) cb=")";
else if (closebrace==MTBTSquareBracket) cb="]";
else if (closebrace==MTBTCurlyBracket) cb="}";
else if (closebrace==MTBTSingleLine) cb="|";
else if (closebrace==MTBTDoubleLine) cb="||";
html=html+ob;
@ -319,32 +292,23 @@ bool JKQTMathTextBraceNode::toHtml(QString &html, JKQTMathTextEnvironment curren
QString JKQTMathTextBraceNode::getTypeName() const
{
return QLatin1String("MTbraceNode(")+BraceType2String(openbrace)+" "+BraceType2String(closebrace)+")";
return QLatin1String("MTbraceNode(")+JKQTMathTextBraceType2String(openbrace)+" "+JKQTMathTextBraceType2String(closebrace)+")";
}
JKQTMathTextBraceNode::BraceType JKQTMathTextBraceNode::getOpenbrace() const {
JKQTMathTextBraceType JKQTMathTextBraceNode::getOpenbrace() const {
return this->openbrace;
}
JKQTMathTextBraceNode::BraceType JKQTMathTextBraceNode::getClosebrace() const {
JKQTMathTextBraceType JKQTMathTextBraceNode::getClosebrace() const {
return this->closebrace;
}
bool JKQTMathTextBraceNode::getShowClosingBrace() const {
return this->showClosingBrace;
}
bool JKQTMathTextBraceNode::getShowOpeningBrace() const
{
return showOpeningBrace;
}
void JKQTMathTextBraceNode::getBraceSize(QPainter &/*painter*/, JKQTMathTextEnvironment ev, double /*baselineHeight*/, double overallHeight, double &bracewidth, double &braceheight) const
{
const double lw=qMax(0.25,ceil(ev.fontSize/12.0));
braceheight=overallHeight*parentMathText->getBraceFactor();
bracewidth=0.6*pow(braceheight, 0.6);
if (openbrace==JKQTMathTextBraceNode::MTBTCurlyBracket || closebrace==JKQTMathTextBraceNode::MTBTCurlyBracket) bracewidth=qMax(bracewidth, lw*3.5);
if (openbrace==MTBTCurlyBracket || closebrace==MTBTCurlyBracket) bracewidth=qMax(bracewidth, lw*3.5);
}

View File

@ -36,26 +36,16 @@ class JKQTMathText; // forward
* \ingroup jkqtmathtext_items
*
* \image html jkqtmathtext/jkqtmathtext_bracenode_geo.png
*/
*
* This node supports the brace-types encoded by JKQTMathTextBraceType:
* \copydetails JKQTMathTextBraceType
*
* In addition it is possible to switch the opening and the closing braces independently on and off.
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceNode: public JKQTMathTextSingleChildNode {
public:
/** \brief types of available braces */
enum BraceType {
MTBTParenthesis, /*!< \brief parantheses () \image html jkqtmathtext/jkqtmathtext_brace_round.png */
MTBTSquareBracket, /*!< \brief brackets [] \image html jkqtmathtext/jkqtmathtext_brace_rect.png */
MTBTCurlyBracket, /*!< \brief curly braces {} \image html jkqtmathtext/jkqtmathtext_brace_curly.png */
MTBTAngleBracket, /*!< \brief angle backets <> \image html jkqtmathtext/jkqtmathtext_brace_tri.png */
MTBTCeilBracket, /*!< \brief ceil brackets \image html jkqtmathtext/jkqtmathtext_brace_ceil.png */
MTBTFloorBracket, /*!< \brief floor brackets \image html jkqtmathtext/jkqtmathtext_brace_floor.png */
MTBTDoubleLine, /*!< \brief double-line brackets (norm ||...||) \image html jkqtmathtext/jkqtmathtext_brace_dblline.png */
MTBTSingleLine, /*!< \brief single-line brackets (abs |...|) \image html jkqtmathtext/jkqtmathtext_brace_oneline.png */
MTBTNone /*!< \brief no bracket */
};
/** \brief convert a BraceType into a string */
static QString BraceType2String(BraceType type);
/** \brief convert a string describing a LaTeX Token into a BraceType */
static BraceType TokenNameString2TokenType(const QString& type);
JKQTMathTextBraceNode(JKQTMathText* parent, BraceType openbrace, BraceType closebrace, JKQTMathTextNode* child, bool showOpeningBrace=true, bool showClosingBrace=true);
JKQTMathTextBraceNode(JKQTMathText* parent, JKQTMathTextBraceType openbrace, JKQTMathTextBraceType closebrace, JKQTMathTextNode* child);
virtual ~JKQTMathTextBraceNode() override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
@ -64,13 +54,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceNode: public JKQTMathTextSingleCh
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc openbrace */
BraceType getOpenbrace() const;
JKQTMathTextBraceType getOpenbrace() const;
/** \copydoc closebrace */
BraceType getClosebrace() const;
/** \copydoc showRightBrace */
bool getShowClosingBrace() const;
/** \copydoc showOpeningBrace */
bool getShowOpeningBrace() const;
JKQTMathTextBraceType getClosebrace() const;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal()
*
@ -80,13 +66,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceNode: public JKQTMathTextSingleCh
/** calculates the size of this node (also returned by getSizeInternal() ) and of the brace */
void getSizeInternalAndBrace(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& bracewidth, double&braceheight, const JKQTMathTextNodeSize* prevNodeSize=nullptr);
/**\brief opening brace */
BraceType openbrace;
JKQTMathTextBraceType openbrace;
/**\brief closing brace */
BraceType closebrace;
/**\brief if \c true, the closing (right hand side) brace is drawn */
bool showClosingBrace;
/**\brief if \c true, the opening (left hand side) brace is drawn */
bool showOpeningBrace;
JKQTMathTextBraceType closebrace;
/** \brief calculate the width of the brace */
void getBraceSize(QPainter& painter, JKQTMathTextEnvironment currentEv, double baselineHeight, double overallHeight, double& bracewidth, double& braceheight) const;
};

View File

@ -50,10 +50,7 @@ JKQTMathTextListNode::JKQTMathTextListNode(JKQTMathText* _parent):
}
JKQTMathTextListNode::~JKQTMathTextListNode() {
for (int i=0; i<nodes.size(); i++) {
delete nodes[i];
}
nodes.clear();
clearChildren(true);
}
QString JKQTMathTextListNode::getTypeName() const
@ -441,4 +438,47 @@ QList<JKQTMathTextNode *> JKQTMathTextListNode::getNodes() const {
return this->nodes;
}
int JKQTMathTextListNode::count() const
{
return nodes.size();
}
int JKQTMathTextListNode::size() const
{
return nodes.size();
}
void JKQTMathTextListNode::clearChildren(bool deleteChildren)
{
if (deleteChildren) {
for (int i=0; i<nodes.size(); i++) {
delete nodes[i];
}
}
nodes.clear();
}
JKQTMathTextNode *JKQTMathTextListNode::child(int i)
{
return nodes[i];
}
const JKQTMathTextNode *JKQTMathTextListNode::child(int i) const
{
return nodes[i];
}
JKQTMathTextNode *JKQTMathTextListNode::simplyfyListNode(JKQTMathTextListNode *nl) {
return nl;
if (nl==nullptr) return nl;
if (nl->count()==1) {
// if there was only a single node: simplify the syntax tree, by removing the outer list node
JKQTMathTextNode* ret= nl->child(0);
nl->clearChildren(false);
delete nl;
return ret;
}
return nl;
}

View File

@ -51,6 +51,18 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextListNode: public JKQTMathTextNode {
virtual void setDrawBoxes(bool draw) override;
/** \copydoc nodes */
QList<JKQTMathTextNode*> getNodes() const;
/** \brief return number of children */
int count() const;
/** \brief return number of children */
int size() const;
/** \brief clear all children, deleting them if \a deleteChildren==true */
void clearChildren(bool deleteChildren=true);
/** \brief return i-th child node */
JKQTMathTextNode* child(int i);
/** \brief return i-th child node */
const JKQTMathTextNode* child(int i) const;
/** \brief simplifies the given list-node, i.e. if it contains one child only, the child is returned and the list node destroyed, otherwise the list node \a nl is returned */
static JKQTMathTextNode* simplyfyListNode(JKQTMathTextListNode* nl);
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;