From 36aeec13aa14f323df46490b5c0883db91c360d3 Mon Sep 17 00:00:00 2001 From: jkriege2 Date: Wed, 6 Jul 2022 22:44:02 +0200 Subject: [PATCH] refactored/simplified JKQTMathText::parseLatexString() bugfixed regression: JKQTMathText displays \left.\right)-type braces and \sum,\int,... with and without \limits correctly again --- lib/jkqtmathtext/jkqtmathtext.cpp | 190 ++++-------------- lib/jkqtmathtext/jkqtmathtext.h | 2 + .../nodes/jkqtmathtextdecoratednode.cpp | 56 ++++++ .../nodes/jkqtmathtextdecoratednode.h | 13 ++ .../nodes/jkqtmathtextfracnode.cpp | 43 +++- lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h | 14 ++ .../nodes/jkqtmathtextsymbolnode.cpp | 131 ++++++------ .../nodes/jkqtmathtextsymbolnode.h | 10 +- 8 files changed, 241 insertions(+), 218 deletions(-) diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp index 6e37776e05..1fee1e03d9 100644 --- a/lib/jkqtmathtext/jkqtmathtext.cpp +++ b/lib/jkqtmathtext/jkqtmathtext.cpp @@ -1161,6 +1161,13 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType 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 (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); + } else if (currentTokenName=="nolimits") { + if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false); } else { getToken(); // look at next token if (currentToken==MTTopenbrace) { @@ -1182,41 +1189,11 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType if (c!='}') error_list.append(tr("error @ ch. %1: \verb{...} not closed by '}'").arg(currentTokenID).arg(currentInstructionName)); nl->addChild(new JKQTMathTextTextNode(this, text, false)); } - } else if (currentInstructionName=="frac") { + } 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::MTFMfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="dfrac" || currentInstructionName=="cfrac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMdfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="sfrac" || currentInstructionName=="slantfrac" || currentInstructionName=="xfrac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMsfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="stfrac" || currentInstructionName=="nicefrac" || currentInstructionName=="slanttextfrac" || currentInstructionName=="xtfrac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="tfrac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMtfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="stackrel") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel)); + 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); @@ -1224,42 +1201,6 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType if (getToken()==MTTopenbrace) n2=parseLatexString(true); if (n1 && n2) nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel))); else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="underbrace") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbrace)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="underbracket") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbracket)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="underset") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderset)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="overbrace") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbrace)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="overbracket") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbracket)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="overset") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverset)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); } else if (currentInstructionName=="begin") { if (getToken()==MTTtext) { QString envname=currentTokenName; @@ -1315,48 +1256,8 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType while (currentToken!=MTTclosebrace) getToken(); getNew=true; } - } else if (currentInstructionName=="vec") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDvec, parseLatexString(true))); - } else if (currentInstructionName=="overline"||currentInstructionName=="oline"||currentInstructionName=="ol") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDoverline, parseLatexString(true))); - } else if (currentInstructionName=="underline"||currentInstructionName=="uline"||currentInstructionName=="ul") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDunderline, parseLatexString(true))); - } else if (currentInstructionName=="uuline"||currentInstructionName=="uul") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleunderline, parseLatexString(true))); - } else if (currentInstructionName=="ooline"||currentInstructionName=="ool") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleoverline, parseLatexString(true))); - } else if (currentInstructionName=="arrow"||currentInstructionName=="overrightarrow"||currentInstructionName=="overarrow") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDarrow, parseLatexString(true))); - } else if (currentInstructionName=="hat" || currentInstructionName=="^") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDhat, parseLatexString(true))); - } else if (currentInstructionName=="widehat") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidehat, parseLatexString(true))); - } else if (currentInstructionName=="check" || currentInstructionName=="v") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcheck, parseLatexString(true))); - } else if (currentInstructionName=="widecheck") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidecheck, parseLatexString(true))); - } else if (currentInstructionName=="bar") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbar, parseLatexString(true))); - } else if (currentInstructionName=="dot" || currentInstructionName==".") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdot, parseLatexString(true))); - } else if (currentInstructionName=="ocirc") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDocirc, parseLatexString(true))); - } else if (currentInstructionName=="tilde" || currentInstructionName=="~") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDtilde, parseLatexString(true))); - } else if (currentInstructionName=="breve" || currentInstructionName=="u") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbreve, parseLatexString(true))); - } else if (currentInstructionName=="widetilde") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidetilde, parseLatexString(true))); - } else if (currentInstructionName=="ddot") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDddot, parseLatexString(true))); - } else if (currentInstructionName=="cancel") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcancel, parseLatexString(true))); - } else if (currentInstructionName=="xcancel") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDxcancel, parseLatexString(true))); - } else if (currentInstructionName=="bcancel") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbcancel, parseLatexString(true))); - } else if (currentInstructionName=="strike" || currentInstructionName=="st" || currentInstructionName=="sout") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDstrike, parseLatexString(true))); + } else if (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; @@ -1377,17 +1278,6 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true))); } } - if (getNew) getToken(); - if (currentToken==MTTinstruction && currentTokenName=="limits") { - if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); - getNew=true; - } else if (currentToken==MTTinstruction && currentTokenName=="nolimits") { - if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false); - getNew=true; - } else { - getNew=false; - } - } else if (currentToken==MTTopenbracket && currentInstructionName!="left") { //std::cout<<"found '[' after '"<addChild(new JKQTMathTextTextNode(this, "[", false)); } } else { - bool subSuperscriptAboveBelowNode=false; //std::cout<<"did not find '{' after '"<addChild(new JKQTMathTextBraceNode(this, MTBTNone, bracetype, cn)); } else if (isPrintableJKQTMathTextBraceType(bracetype)) { currentTokenName=currentTokenName.right(currentTokenName.size()-1); // we already used the first character from the text token! - nl->addChild(new JKQTMathTextBraceNode(this, bracetype, bracetype, parseLatexString(currentTokenName.size()<=0, bracetype))); + JKQTMathTextNode* c=parseLatexString(currentTokenName.size()<=0, bracetype); + nl->addChild(new JKQTMathTextBraceNode(this, bracetype, lastRightBraceType, c)); } else { getNew=false; } @@ -1448,38 +1339,21 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType } else if (currentToken==MTTinstruction) { const JKQTMathTextBraceType bracetypeopening=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName); if (bracetypeopening!=MTBTUnknown) { - nl->addChild(new JKQTMathTextBraceNode(this, bracetypeopening, bracetypeopening, parseLatexString(true, bracetypeopening))); + JKQTMathTextNode* c=parseLatexString(true, bracetypeopening); + nl->addChild(new JKQTMathTextBraceNode(this, bracetypeopening, lastRightBraceType, c)); } else if (currentToken==MTTinstruction && TokenNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) { break; } } else if (currentToken==MTTopenbracket) { - nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, parseLatexString(true, MTBTSquareBracket))); + JKQTMathTextNode* c=parseLatexString(true, MTBTSquareBracket); + nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, lastRightBraceType, c)); } else { error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID)); } - } else if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) { - nl->addChild(new JKQTMathTextWhitespaceNode(currentInstructionName, this)); - } else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) { - nl->addChild(new JKQTMathTextSymbolNode(this, currentInstructionName)); - static QSet subsupOperations= (QSet()<<"sum"<<"prod"<<"coprod" - <<"bigcap"<<"bigcup"<<"bigvee"<<"bighat" - <<"int"<<"iint"<<"iiint"<<"oint"<<"oiint"<<"oiiint" - <<"mod"<<"median"<<"max"<<"min"<<"argmax"<<"argmin"<<"sup"<<"inf" - <<"liminf"<<"limsup"<<"lim"<<"max"<<"min"); - if (subsupOperations.contains(currentInstructionName) && parsingMathEnvironment) { - nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); - } - if (currentToken==MTTinstruction && currentTokenName=="limits") { - if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); - } else if (currentToken==MTTinstruction && currentTokenName=="nolimits") { - if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false); - } else { - getNew=false; - } - } else { - error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName)); + getNew=false; + //error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName)); } } } @@ -1490,18 +1364,21 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType JKQTMathTextNode* child=nullptr; JKQTMathTextNode* child2=nullptr; if (currentToken==MTTinstruction) { - QString name=currentTokenName; + const QString currentInstructionName=currentTokenName; getToken(); // look at next token if (currentToken==MTTopenbrace) { - child=new JKQTMathTextInstruction1Node(this, name, parseLatexString(true)); - } else if (JKQTMathTextWhitespaceNode::supportsInstructionName(name)) { + child=new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true)); + } else if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) { getNew=false; - child=new JKQTMathTextWhitespaceNode(name, this); - } else if (JKQTMathTextSymbolNode::hasSymbol(name)) { + child=new JKQTMathTextWhitespaceNode(currentInstructionName, this); + } else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) { getNew=false; - child=new JKQTMathTextSymbolNode(this, name); + 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(name)); + error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName)); } } else if (currentToken==MTTopenbrace) { child=parseLatexString(true); @@ -1529,6 +1406,9 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType } 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) { diff --git a/lib/jkqtmathtext/jkqtmathtext.h b/lib/jkqtmathtext/jkqtmathtext.h index 78c616bf46..fef9ceca4e 100644 --- a/lib/jkqtmathtext/jkqtmathtext.h +++ b/lib/jkqtmathtext/jkqtmathtext.h @@ -818,6 +818,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject { /** \brief used by the tokenizer. type of the current token */ tokenType currentToken; + /** \brief the JKQTMathTextBraceType associated with the last \c \\right command the parser encountered */ + JKQTMathTextBraceType lastRightBraceType; /** \brief used by the tokenizer. Name of the current token, id applicable */ QString currentTokenName; /** \brief used by the tokenizer. Points to the currently read character in parseString */ diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextdecoratednode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextdecoratednode.cpp index 8c8edc2458..7cc86ddf21 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextdecoratednode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextdecoratednode.cpp @@ -86,6 +86,18 @@ QString JKQTMathTextDecoratedNode::DecorationType2String(JKQTMathTextDecoratedNo return "unknown"; } +JKQTMathTextDecoratedNode::DecorationType JKQTMathTextDecoratedNode::InstructionName2DecorationType(const QString &mode) +{ + fillInstructions(); + return instructions[mode]; +} + +bool JKQTMathTextDecoratedNode::supportsInstructionName(const QString &instructionName) +{ + fillInstructions(); + return instructions.contains(instructionName); +} + JKQTMathTextDecoratedNode::JKQTMathTextDecoratedNode(JKQTMathText* _parent, DecorationType decoration, JKQTMathTextNode* child): @@ -132,6 +144,50 @@ void JKQTMathTextDecoratedNode::getSizeInternal(QPainter& painter, JKQTMathTextE width=std::max(deco_miniwidth,cwidth); } +QHash JKQTMathTextDecoratedNode::instructions; + +void JKQTMathTextDecoratedNode::fillInstructions() +{ + if (instructions.size()>0) return; + + instructions["vec"]=MTDvec; + instructions["overline"]=MTDoverline; + instructions["oline"]=MTDoverline; + instructions["ol"]=MTDoverline; + instructions["underline"]=MTDunderline; + instructions["uline"]=MTDunderline; + instructions["ul"]=MTDunderline; + instructions["uuline"]=MTDdoubleunderline; + instructions["uul"]=MTDdoubleunderline; + instructions["ooline"]=MTDdoubleoverline; + instructions["ool"]=MTDdoubleoverline; + instructions["arrow"]=MTDarrow; + instructions["overrightarrow"]=MTDarrow; + instructions["overarrow"]=MTDarrow; + instructions["hat"]=MTDhat; + instructions["^"]=MTDhat; + instructions["widehat"]=MTDwidehat; + instructions["check"]=MTDcheck; + instructions["v"]=MTDcheck; + instructions["widecheck"]=MTDwidecheck; + instructions["bar"]=MTDbar; + instructions["dot"]=MTDdot; + instructions["."]=MTDdot; + instructions["ocirc"]=MTDocirc; + instructions["tilde"]=MTDtilde; + instructions["~"]=MTDtilde; + instructions["breve"]=MTDbreve; + instructions["u"]=MTDbreve; + instructions["widetilde"]=MTDwidetilde; + instructions["ddot"]=MTDddot; + instructions["cancel"]=MTDcancel; + instructions["xcancel"]=MTDxcancel; + instructions["bcancel"]=MTDbcancel; + instructions["strike"]=MTDstrike; + instructions["st"]=MTDstrike; + instructions["sout"]=MTDstrike; +} + double JKQTMathTextDecoratedNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) { doDrawBoxes(painter, x, y, currentEv); JKQTMathTextEnvironment ev=currentEv; diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextdecoratednode.h b/lib/jkqtmathtext/nodes/jkqtmathtextdecoratednode.h index 12e49443cd..b14f8d5406 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextdecoratednode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextdecoratednode.h @@ -68,6 +68,15 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextDecoratedNode: public JKQTMathTextSing /** \brief convert a DecorationType into a string */ static QString DecorationType2String(DecorationType mode); + /** \brief returns the FracType corresponding to \a instructionName + * \see JKQTMathTextFracNode::FracType + */ + static DecorationType InstructionName2DecorationType(const QString& mode); + + /** \brief returns true, if the given \a instructionName can be converted to a FracType + * \see JKQTMathTextFracNode::FracType + */ + static bool supportsInstructionName(const QString& instructionName); JKQTMathTextDecoratedNode(JKQTMathText* parent, DecorationType decoration, JKQTMathTextNode* child); virtual ~JKQTMathTextDecoratedNode() override; @@ -84,6 +93,10 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextDecoratedNode: public JKQTMathTextSing virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override; /** \brief type of decoration that is added to the child node */ DecorationType decoration; + /** \brief lists all supported instructions */ + static QHash instructions; + /** \biref fills instructions */ + static void fillInstructions(); }; #endif // JKQTMATHTEXTDECORATEDNODE_H diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp index dd4c50ff6c..bfc8ca401c 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp @@ -34,6 +34,34 @@ #include +QHash JKQTMathTextFracNode::instructions; + + +void JKQTMathTextFracNode::fillInstructions() +{ + if (instructions.size()>0) return; + instructions["frac"]=MTFMfrac; + instructions["dfrac"] = MTFMdfrac; + instructions["cfrac"]=MTFMdfrac; + instructions["sfrac"] = MTFMsfrac; + instructions["slantfrac"] = MTFMsfrac; + instructions["xfrac"]=MTFMsfrac; + instructions["stfrac"] = MTFMstfrac; + instructions["nicefrac"] = MTFMstfrac; + instructions["slanttextfrac"] = MTFMstfrac; + instructions["xtfrac"]=MTFMstfrac; + instructions["tfrac"]=MTFMtfrac; + instructions["stackrel"]=MTFMstackrel; + instructions["underbrace"]=MTFMunderbrace; + instructions["underbracket"]=MTFMunderbracket; + instructions["underset"]=MTFMunderset; + instructions["overbrace"]=MTFMoverbrace; + instructions["overbracket"]=MTFMoverbracket; + instructions["overset"]=MTFMoverset; +} + + + QString JKQTMathTextFracNode::FracType2String(JKQTMathTextFracNode::FracType mode) @@ -67,6 +95,18 @@ QString JKQTMathTextFracNode::FracType2String(JKQTMathTextFracNode::FracType mod return "unknown"; } +JKQTMathTextFracNode::FracType JKQTMathTextFracNode::InstructionName2FracType(const QString &mode) +{ + fillInstructions(); + return instructions.value(mode, MTFMfrac); +} + +bool JKQTMathTextFracNode::supportsInstructionName(const QString &instructionName) +{ + fillInstructions(); + return instructions.contains(instructionName); +} + JKQTMathTextFracNode::JKQTMathTextFracNode(JKQTMathText* _parent, JKQTMathTextNode* child_top, JKQTMathTextNode* child_bottom, JKQTMathTextFracNode::FracType mode): @@ -342,6 +382,3 @@ bool JKQTMathTextFracNode::toHtml(QString &/*html*/, JKQTMathTextEnvironment /*c JKQTMathTextFracNode::FracType JKQTMathTextFracNode::getMode() const { return this->mode; } - - - diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h index abb13ad32e..206a7f6520 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h @@ -67,6 +67,16 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFracNode: public JKQTMathTextDualChild */ static QString FracType2String(FracType mode); + /** \brief returns the FracType corresponding to \a instructionName + * \see JKQTMathTextFracNode::FracType + */ + static FracType InstructionName2FracType(const QString& mode); + + /** \brief returns true, if the given \a instructionName can be converted to a FracType + * \see JKQTMathTextFracNode::FracType + */ + static bool supportsInstructionName(const QString& instructionName); + JKQTMathTextFracNode(JKQTMathText* parent, JKQTMathTextNode* child_top, JKQTMathTextNode* child_bottom, JKQTMathTextFracNode::FracType mode); virtual ~JKQTMathTextFracNode() override; @@ -79,6 +89,10 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFracNode: public JKQTMathTextDualChild /** \copydoc mode */ JKQTMathTextFracNode::FracType getMode() const; protected: + /** \brief lists all supported instructions */ + static QHash instructions; + /** \biref fills instructions */ + static void fillInstructions(); /** \copydoc JKQTMathTextNode::getSizeInternal() */ virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override; /** \brief actual display type of fraction object */ diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp index 52fc26aec7..db645875d6 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp @@ -75,7 +75,10 @@ void JKQTMathTextSymbolNode::getSymbolSizeInternal(QPainter &painter, JKQTMathTe if (currentEv.insideMath) { width=qMax(br.width(), mintbr.width()); - if (has(globalFlags, ExtendWidthInMathmode)) { + if (has(globalFlags, SmallExtendWidthInMathmode)) { + if (!symprops.getSymbolSingleChar().isNull()) width=width*(1.0+(parentMathText->getMathoperatorWidthFactor()-1.0)/2.0); + else width=width+mintbr.width(); + } else if (has(globalFlags, ExtendWidthInMathmode)) { if (!symprops.getSymbolSingleChar().isNull()) width=width*parentMathText->getMathoperatorWidthFactor(); else width=width+mintbr.width(); } @@ -302,6 +305,15 @@ bool JKQTMathTextSymbolNode::hasSymbol(const QString &symbolName) return symbols.contains(symbolName); } +bool JKQTMathTextSymbolNode::isSubSuperscriptBelowAboveSymbol(const QString &symbolName) +{ + fillSymbolTables(); + if (symbols.contains(symbolName)) { + return has(symbols[symbolName].globalFlags, SubSuperscriptBelowAboveSymbol); + } + return false; +} + JKQTMathTextSymbolNode::SymbolProps::SymbolProps(): @@ -326,7 +338,7 @@ JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorSymb JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorSymbol(const QString &op, const QString &ophtml) { - return SymbolFullProps(SymbolProps(op, ItalicOff|BoldOff, 1.0, 0.0)).setGlobalFlags(ExtendWidthInMathmode).addHtml(ophtml, ItalicOff|BoldOff, 1.0, 0.0); + return SymbolFullProps(SymbolProps(op, ItalicOff|BoldOff, 1.0, 0.0)).addGlobalFlags(ExtendWidthInMathmode).addHtml(ophtml, ItalicOff|BoldOff, 1.0, 0.0); } JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorText(const QString &op) @@ -336,12 +348,17 @@ JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorText JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorText(const QString &op, const QString &ophtml) { - return SymbolFullProps(SymbolProps(op, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0)).setGlobalFlags(ExtendWidthInMathmode|MakeWhitespaceHalf).addHtml(ophtml, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0); + return SymbolFullProps(SymbolProps(op, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0)).addGlobalFlags(ExtendWidthInMathmode|MakeWhitespaceHalf).addHtml(ophtml, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0); } JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorSymbolUnicode(const QString &unicode) { - return SymbolFullProps(MTFEUnicode, SymbolProps(unicode, ItalicOff|BoldOff, 1.0, 0.0)).setGlobalFlags(ExtendWidthInMathmode|MakeWhitespaceHalf); + return SymbolFullProps(MTFEUnicode, SymbolProps(unicode, ItalicOff|BoldOff, 1.0, 0.0)).addGlobalFlags(ExtendWidthInMathmode|MakeWhitespaceHalf); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::NarrowMathOperatorSymbolUnicode(const QString &unicode) +{ + return SymbolFullProps(MTFEUnicode, SymbolProps(unicode, ItalicOff|BoldOff, 1.0, 0.0)).addGlobalFlags(SmallExtendWidthInMathmode|MakeWhitespaceHalf); } JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::GreekLetter_WinSymbol_Unicode_Html(const QString &letterWinSymbol, const QString &letterUnicode, const QString &html) @@ -422,8 +439,6 @@ void JKQTMathTextSymbolNode::fillSymbolTables() /************************************************************************************** * STANDARD Symbols available in all standard fonts **************************************************************************************/ - symbols[" "]=SimpleTextSymbol(" ", " "); - symbols[""]=SimpleTextSymbol(" ", " "); symbols["#"]=SimpleTextSymbol("#", "#"); symbols["%"]=SimpleTextSymbol("%", "≫"); symbols["&"]=SimpleTextSymbol("&", "&"); @@ -565,45 +580,45 @@ void JKQTMathTextSymbolNode::fillSymbolTables() * STANDARD MathOperator Strings **************************************************************************************/ symbols["Pr"] = MathOperatorText("Pr"); - symbols["acos"] = MathOperatorText("acos"); - symbols["arccos"] = MathOperatorText("arccos"); - symbols["arcsin"] = MathOperatorText("arcsin"); - symbols["arctan"] = MathOperatorText("arctan"); - symbols["arg"] = MathOperatorText("arg"); - symbols["argmax"] = MathOperatorText("arg max", "arg max"); - symbols["argmin"] = MathOperatorText("arg min", "arg min"); - symbols["asin"] = MathOperatorText("asin"); - symbols["atan"] = MathOperatorText("atan"); - symbols["cos"] = MathOperatorText("cos"); - symbols["cosh"] = MathOperatorText("cosh"); - symbols["cot"] = MathOperatorText("cot"); - symbols["coth"] = MathOperatorText("coth"); - symbols["coth"] = MathOperatorText("coth"); - symbols["deg"] = MathOperatorText("deg"); - symbols["det"] = MathOperatorText("det"); - symbols["dim"] = MathOperatorText("dim"); - symbols["exp"] = MathOperatorText("exp"); - symbols["gcd"] = MathOperatorText("gcd"); - symbols["hom"] = MathOperatorText("hom"); - symbols["ker"] = MathOperatorText("ker"); - symbols["lb"] = MathOperatorText("lb"); - symbols["ld"] = MathOperatorText("ld"); - symbols["lim"] = MathOperatorText("lim"); - symbols["liminf"] = MathOperatorText("lim inf", "lim inf"); - symbols["limsup"] = MathOperatorText("lim sup", "lim sup"); - symbols["ln"] = MathOperatorText("ln"); - symbols["log"] = MathOperatorText("log"); - symbols["max"] = MathOperatorText("max"); - symbols["median"] = MathOperatorText("median"); - symbols["min"] = MathOperatorText("min"); - symbols["mod"] = MathOperatorText("mod"); - symbols["sec"] = MathOperatorText("sec"); - symbols["sgn"] = MathOperatorText("sgn"); - symbols["sign"] = MathOperatorText("sign"); - symbols["sin"] = MathOperatorText("sin"); - symbols["sinh"] = MathOperatorText("sinh"); - symbols["tan"] = MathOperatorText("tan"); - symbols["tanh"] = MathOperatorText("tanh"); + symbols["acos"] = MathOperatorText("acos").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["arccos"] = MathOperatorText("arccos").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["arcsin"] = MathOperatorText("arcsin").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["arctan"] = MathOperatorText("arctan").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["arg"] = MathOperatorText("arg").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["argmax"] = MathOperatorText("arg max", "arg max").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["argmin"] = MathOperatorText("arg min", "arg min").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["asin"] = MathOperatorText("asin").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["atan"] = MathOperatorText("atan").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["cos"] = MathOperatorText("cos").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["cosh"] = MathOperatorText("cosh").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["cot"] = MathOperatorText("cot").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["coth"] = MathOperatorText("coth").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["coth"] = MathOperatorText("coth").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["deg"] = MathOperatorText("deg").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["det"] = MathOperatorText("det").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["dim"] = MathOperatorText("dim").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["exp"] = MathOperatorText("exp").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["gcd"] = MathOperatorText("gcd").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["hom"] = MathOperatorText("hom").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["ker"] = MathOperatorText("ker").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["lb"] = MathOperatorText("lb").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["ld"] = MathOperatorText("ld").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["lim"] = MathOperatorText("lim").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["liminf"] = MathOperatorText("lim inf", "lim inf").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["limsup"] = MathOperatorText("lim sup", "lim sup").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["ln"] = MathOperatorText("ln").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["log"] = MathOperatorText("log").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["max"] = MathOperatorText("max").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["median"] = MathOperatorText("median").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["min"] = MathOperatorText("min").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["mod"] = MathOperatorText("mod").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["sec"] = MathOperatorText("sec").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["sgn"] = MathOperatorText("sgn").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["sign"] = MathOperatorText("sign").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["sin"] = MathOperatorText("sin").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["sinh"] = MathOperatorText("sinh").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["tan"] = MathOperatorText("tan").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["tanh"] = MathOperatorText("tanh").addGlobalFlags(SubSuperscriptBelowAboveSymbol); /************************************************************************************** * STANDARD MathOperator Symbols @@ -629,17 +644,17 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["bbR"]=MathOperatorSymbolUnicode(QChar(0x211D)); symbols["bbZ"]=MathOperatorSymbolUnicode(QChar(0x2124)); symbols["because"]=MathOperatorSymbolUnicode(QChar(0x2235)).addMathOperatorHtml("∵"); - symbols["bigcap"]=MathOperatorSymbolUnicode(QChar(0x22C2)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xC7), 1.8); - symbols["bigcup"]=MathOperatorSymbolUnicode(QChar(0x22C3)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xC8), 1.8); - symbols["bighat"]=MathOperatorSymbolUnicode(QChar(0x22C0)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xD9), 1.8); - symbols["bigvee"]=MathOperatorSymbolUnicode(QChar(0x22C1)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xDA), 1.8); + symbols["bigcap"]=NarrowMathOperatorSymbolUnicode(QChar(0x22C2)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xC7), 1.8).addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["bigcup"]=NarrowMathOperatorSymbolUnicode(QChar(0x22C3)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xC8), 1.8).addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["bighat"]=NarrowMathOperatorSymbolUnicode(QChar(0x22C0)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xD9), 1.8).addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["bigvee"]=NarrowMathOperatorSymbolUnicode(QChar(0x22C1)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xDA), 1.8).addGlobalFlags(SubSuperscriptBelowAboveSymbol); { auto s=MathOperatorSymbolUnicode(QChar(0x22A5)).addMathOperatorHtml("⊥"); symbols["bot"]=s; symbols["perp"]=s; } { auto s=MathOperatorSymbolUnicode(QChar(0x2229)).addMathOperatorHtml("∩").addMathOperatorWinSymbol(QChar(0xC7)); symbols["cap"]=s; symbols["land"]=s; } symbols["cdot"]=MathOperatorSymbol(QChar(0xB7)).addMathOperatorHtml("·").addMathOperatorWinSymbol(QChar(0xD7)); symbols["cong"]=MathOperatorSymbolUnicode(QChar(0x2245)).addMathOperatorHtml("≅"); - symbols["coprod"]=MathOperatorSymbolUnicode(QChar(0x2210)).addMathOperatorHtml("∐").addWinSymbol(QChar(0xD5), ItalicOff|BoldOff|FlipSymbolUpDown, 1.8, 0.1); + symbols["coprod"]=NarrowMathOperatorSymbolUnicode(QChar(0x2210)).addMathOperatorHtml("∐").addWinSymbol(QChar(0xD5), ItalicOff|BoldOff|FlipSymbolUpDown, 1.8, 0.1).addGlobalFlags(SubSuperscriptBelowAboveSymbol); { auto s=MathOperatorSymbolUnicode(QChar(0x222A)).addMathOperatorHtml("∪").addMathOperatorWinSymbol(QChar(0xC8)); symbols["cup"]=s; symbols["lor"]=s; } symbols["ddots"]=MathOperatorSymbolUnicode(QChar(0x22F1)).addMathOperatorHtml("⋱"); @@ -659,10 +674,10 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["iddots"]=MathOperatorSymbolUnicode(QChar(0x22F0)).addMathOperatorHtml("⋰"); { auto s=UprightSymbolUnicode(QChar(0x21D4)).addUprightHtml("⇔").addUprightWinSymbol(QChar(0xDB)); symbols["iff"]=s; symbols["Leftrightarrow"]=s; } - symbols["iiint"]=MathOperatorSymbolUnicode(QChar(0x222D)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∭").addMathOperatorWinSymbol(QString(3, QChar(0xF2)), 1.8, 0.1); - symbols["iint"]=MathOperatorSymbolUnicode(QChar(0x222C)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∬").addMathOperatorWinSymbol(QString(2, QChar(0xF2)), 1.8, 0.1); + symbols["iiint"]=NarrowMathOperatorSymbolUnicode(QChar(0x222D)).addGlobalFlags(IntLikeSymbolCorrection | SubSuperscriptBelowAboveSymbol).addMathOperatorHtml("∭").addMathOperatorWinSymbol(QString(3, QChar(0xF2)), 1.8, 0.1); + symbols["iint"]=NarrowMathOperatorSymbolUnicode(QChar(0x222C)).addGlobalFlags(IntLikeSymbolCorrection | SubSuperscriptBelowAboveSymbol).addMathOperatorHtml("∬").addMathOperatorWinSymbol(QString(2, QChar(0xF2)), 1.8, 0.1); symbols["in"]=MathOperatorSymbolUnicode(QChar(0x2208)).addMathOperatorHtml("∈").addMathOperatorWinSymbol(QChar(0xCE)); - symbols["int"]=MathOperatorSymbolUnicode(QChar(0x222B)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xF2), 1.8, 0.1); + symbols["int"]=NarrowMathOperatorSymbolUnicode(QChar(0x222B)).addGlobalFlags(IntLikeSymbolCorrection | SubSuperscriptBelowAboveSymbol).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xF2), 1.8, 0.1); symbols["leftarrow"]=UprightSymbolUnicode(QChar(0x2190)).addUprightHtml("←").addUprightWinSymbol(QChar(0xAC)); symbols["leftharpoondown"]=UprightSymbolUnicode(QChar(0x21BD)).addUprightHtml("↽"); symbols["leftharpoonup"]=UprightSymbolUnicode(QChar(0x21BC)).addUprightHtml("↼"); @@ -693,9 +708,9 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["nparallel"]=MathOperatorSymbolUnicode(QChar(0x2226)).addMathOperatorHtml("∦"); symbols["nwarrow"]=UprightSymbolUnicode(QChar(0x2196)).addUprightHtml("↖"); symbols["odot"]=MathOperatorSymbolUnicode(QChar(0x2299)).addMathOperatorHtml("⊙"); - symbols["oiiint"]=MathOperatorSymbolUnicode(QChar(0x2230)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∰"); - symbols["oiint"]=MathOperatorSymbolUnicode(QChar(0x222F)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∯"); - symbols["oint"]=MathOperatorSymbolUnicode(QChar(0x222E)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∮"); + symbols["oiiint"]=NarrowMathOperatorSymbolUnicode(QChar(0x2230)).addGlobalFlags(IntLikeSymbolCorrection | SubSuperscriptBelowAboveSymbol).addMathOperatorHtml("∰"); + symbols["oiint"]=NarrowMathOperatorSymbolUnicode(QChar(0x222F)).addGlobalFlags(IntLikeSymbolCorrection | SubSuperscriptBelowAboveSymbol).addMathOperatorHtml("∯"); + symbols["oint"]=NarrowMathOperatorSymbolUnicode(QChar(0x222E)).addGlobalFlags(IntLikeSymbolCorrection | SubSuperscriptBelowAboveSymbol).addMathOperatorHtml("∮"); symbols["ominus"]=MathOperatorSymbolUnicode(QChar(0x2296)).addMathOperatorHtml("⊖"); symbols["oplus"]=MathOperatorSymbolUnicode(QChar(0x2295)).addMathOperatorHtml("⊕").addMathOperatorWinSymbol(QChar(0xC5)); symbols["oslash"]=MathOperatorSymbolUnicode(QChar(0x2298)).addMathOperatorHtml("⊘"); @@ -703,7 +718,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["parallel"]=MathOperatorSymbolUnicode(QChar(0x2225)).addMathOperatorHtml("∥").addMathOperatorStd("||"); symbols["pm"] = MathOperatorSymbol(QChar(0xB1), "±").addMathOperatorWinSymbol(QChar(0xB1)); symbols["prec"]=MathOperatorSymbolUnicode(QChar(0x227A)).addMathOperatorHtml("≺"); - symbols["prod"]=MathOperatorSymbolUnicode(QChar(0x220F)).addMathOperatorWinSymbol(QChar(0xD5), 1.8, 0.1).addMathOperatorHtml("∏"); + symbols["prod"]=NarrowMathOperatorSymbolUnicode(QChar(0x220F)).addMathOperatorWinSymbol(QChar(0xD5), 1.8, 0.1).addMathOperatorHtml("∏").addGlobalFlags(SubSuperscriptBelowAboveSymbol); symbols["propto"]=MathOperatorSymbolUnicode(QChar(0x221D)).addMathOperatorWinSymbol(QChar(0xB5)).addMathOperatorHtml("∝"); symbols["rightharpoondown"]=UprightSymbolUnicode(QChar(0x21C1)).addUprightHtml("⇁"); symbols["rightharpoonup"]=UprightSymbolUnicode(QChar(0x21C0)).addUprightHtml("⇀"); @@ -720,7 +735,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["subseteq"]=MathOperatorSymbolUnicode(QChar(0x2286)).addMathOperatorHtml("⊆").addMathOperatorWinSymbol(QChar(0xCD)); symbols["subsetnot"]=MathOperatorSymbolUnicode(QChar(0x2284)).addMathOperatorHtml("⊄").addMathOperatorWinSymbol(QChar(0xCB)); symbols["succ"]=MathOperatorSymbolUnicode(QChar(0x227B)).addMathOperatorHtml("≻"); - symbols["sum"]=MathOperatorSymbolUnicode(QChar(0x2211)).addMathOperatorWinSymbol(QChar(0xE5), 1.8, 0.1).addMathOperatorHtml("∑"); + symbols["sum"]=NarrowMathOperatorSymbolUnicode(QChar(0x2211)).addMathOperatorWinSymbol(QChar(0xE5), 1.8, 0.1).addMathOperatorHtml("∑").addGlobalFlags(SubSuperscriptBelowAboveSymbol); symbols["supset"]=MathOperatorSymbolUnicode(QChar(0x2283)).addMathOperatorHtml("⊃").addMathOperatorWinSymbol(QChar(0xC9)); symbols["supseteq"]=MathOperatorSymbolUnicode(QChar(0x2287)).addMathOperatorHtml("⊇").addMathOperatorWinSymbol(QChar(0xCA)); symbols["supsetnot"]=MathOperatorSymbolUnicode(QChar(0x2285)).addMathOperatorHtml("⊅"); diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h index c44dbf53d8..ed81273d5c 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h @@ -83,6 +83,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode { void getSymbolSize(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& subSuperXCorrection, double& subBesidesXCorrection, const JKQTMathTextNodeSize* prevNodeSize=nullptr); /** \brief checks whether the given symbol name can be prepresented by this type of node */ static bool hasSymbol(const QString& symbolName); + /** \brief checks whether the given symbol name can be prepresented by this type of node */ + static bool isSubSuperscriptBelowAboveSymbol(const QString& symbolName); protected: /** \copydoc JKQTMathTextNode::getSizeInternal() */ virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override; @@ -126,8 +128,10 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode { enum GlobalSymbolFlags: uint64_t { NoGLobalSymbolFlags= 0, /*!< \brief indicates that no properties are activated */ ExtendWidthInMathmode= 1 << 0, /*!< \brief this symbol has an extended width, when used within a moth-environment/in math-mode */ - MakeWhitespaceHalf= 1 << 1, /*!< \brief symbol uses whitespaces in its text (SymbolProps::symbol). These should be typeset as half-spaces */ - IntLikeSymbolCorrection= 1 << 2, /*!< \brief symbols, like \c \\int,\\iint,... require a correction in x-direction for subsequent sub-/superscripts ... this flag marks such symbols */ + SmallExtendWidthInMathmode= 1 << 1, /*!< \brief like ExtendWidthInMathmode but adds a smaller whitespace */ + MakeWhitespaceHalf= 1 << 2, /*!< \brief symbol uses whitespaces in its text (SymbolProps::symbol). These should be typeset as half-spaces */ + IntLikeSymbolCorrection= 1 << 3, /*!< \brief symbols, like \c \\int,\\iint,... require a correction in x-direction for subsequent sub-/superscripts ... this flag marks such symbols */ + SubSuperscriptBelowAboveSymbol= 1 << 4, /*!< \brief symbols, like \c \\int,\\iint,... if appearing in math-mode cause typesetting following sub-/superscripts below/above the symbol, not besides it. */ }; friend inline GlobalSymbolFlags operator~ (GlobalSymbolFlags a) { return (GlobalSymbolFlags)~static_cast(a); } @@ -271,6 +275,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode { static SymbolFullProps UprightSymbolUnicode(const QString& symbol, const QString& html=QString()); /** \brief constructs a SymbolProps for a math-operator symbol like \c \\pm ... in unicode-full-encoding, i.e. ItalicOff, BoldOff, ExtendWidthInMathmode */ static SymbolFullProps MathOperatorSymbolUnicode(const QString& unicode); + /** \brief constructs a SymbolProps for a math-operator symbol like \c \\pm ... in unicode-full-encoding, i.e. ItalicOff, BoldOff, SmallExtendWidthInMathmode */ + static SymbolFullProps NarrowMathOperatorSymbolUnicode(const QString& unicode); /** \brief symbols that can be generated in any standard-font */