diff --git a/doc/dox/jkqtmathtext_supportedlatex.dox b/doc/dox/jkqtmathtext_supportedlatex.dox index a1cb01dcce..d92a1299d1 100644 --- a/doc/dox/jkqtmathtext_supportedlatex.dox +++ b/doc/dox/jkqtmathtext_supportedlatex.dox @@ -109,13 +109,24 @@ - \c \\left( \c \\right) : default meaning (), \image html jkqtmathtext/jkqtmathtext_brace_round.png - \c \\left[ \c \\right] : default meaning [], \image html jkqtmathtext/jkqtmathtext_brace_rect.png - \c \\left\\{ \c \\right\\} : default meaning {}, \image html jkqtmathtext/jkqtmathtext_brace_curly.png - - \c \\left< \c \\right> : "averaging" braces , \image html jkqtmathtext/jkqtmathtext_brace_tri.png + - \c \\left\\langle \c \\right\\rangle : "averaging" braces , \image html jkqtmathtext/jkqtmathtext_brace_tri.png - \c \\left\\lfloor \c \\right\\rfloor : floor braces , \image html jkqtmathtext/jkqtmathtext_brace_floor.png - - \c \\left~ \c \\right~ \c \\left\\lceil \c \\right\\rceil : ceil braces , \image html jkqtmathtext/jkqtmathtext_brace_ceil.png - - \c \\left| \c \\right| : absolute value braces | |, \image html jkqtmathtext/jkqtmathtext_brace_oneline.png + - \c \\left\\lceil \c \\right\\rceil : ceil braces , \image html jkqtmathtext/jkqtmathtext_brace_ceil.png + - \c \\left| \c \\right| : absolute value braces | |, \image html jkqtmathtext/jkqtmathtext_bracejkqtmathtext_brace_ucorner_oneline.png - \c \\left\\| \c \\right\\| \endcode : norm braces || ||, \image html jkqtmathtext/jkqtmathtext_brace_dblline.png + - \c \\left\\llcorner \c \\right\\lrcorner : lower corner braces , \image html jkqtmathtext/jkqtmathtext_brace_lcorner.png + - \c \\left\\ulcorner \c \\right\\urcorner : upper corner braces , \image html jkqtmathtext/.png - You can use \c \\left. or \c \\right. to have only right or only left brace . + + In additional fixed-size parantheses are available with the following family of instructions: + - \c \\bigl([\\{\\langle... , \c \\big([\\{\\langle... and \c \\bigr)]\\}\\rangle... \image html jkqtmathtext/jkqtmathtext_brace_big.png + - \c \\Bigl([\\{\\langle... , \c \\Big([\\{\\langle... and \c \\Bigr)]\\}\\rangle... \image html jkqtmathtext/jkqtmathtext_brace_bbig.png + - \c \\biggl([\\{\\langle... , \c \\bigg([\\{\\langle... and \c \\biggr)]\\}\\rangle... \image html jkqtmathtext/jkqtmathtext_brace_bigg.png + - \c \\Biggl([\\{\\langle... , \c \\Bigg([\\{\\langle... and \c \\Biggr)]\\}\\rangle... \image html jkqtmathtext/jkqtmathtext_brace_bbigg.png + . + They use the same rendering code as the standard \c \\left and \c \\right instructions. Here is an example: + \image html jkqtmathtext/jkqtmathtext_brace_bigfamily.png generated by $\Biggl\langle\biggl\{\Bigl[\bigl( r^{123}\bigr)\Bigr]\biggr\}\Biggr\rangle$ \subsection JKQTMathTextSuppoertedLaTeXRoots Roots There are also instructions that allow to write roots: diff --git a/doc/dox/todo.dox b/doc/dox/todo.dox index 558cb9ce4f..e29a488cf0 100644 --- a/doc/dox/todo.dox +++ b/doc/dox/todo.dox @@ -40,7 +40,6 @@ This page lists several todos and wishes for future version of JKQTPlotter
  • JKQTMathText:
  • diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_bbig.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_bbig.png new file mode 100644 index 0000000000..21940b3f4c Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_brace_bbig.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_bbigg.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_bbigg.png new file mode 100644 index 0000000000..6be7aa544b Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_brace_bbigg.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_big.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_big.png new file mode 100644 index 0000000000..493bcd06d1 Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_brace_big.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_bigfamily.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_bigfamily.png new file mode 100644 index 0000000000..8e8ca580af Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_brace_bigfamily.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_bigg.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_bigg.png new file mode 100644 index 0000000000..2c40530251 Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_brace_bigg.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_lcorner.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_lcorner.png new file mode 100644 index 0000000000..7825fef2dd Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_brace_lcorner.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_ucorner.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_ucorner.png new file mode 100644 index 0000000000..8513bb5229 Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_brace_ucorner.png differ diff --git a/examples/jkqtmathtext_test/testform.cpp b/examples/jkqtmathtext_test/testform.cpp index 06239d8dcb..272039dd75 100644 --- a/examples/jkqtmathtext_test/testform.cpp +++ b/examples/jkqtmathtext_test/testform.cpp @@ -195,6 +195,7 @@ TestForm::TestForm(QWidget *parent) : ui->cmbTestset->addItem("text/math: brace test: non-left/right top-corner", "text: \\ulcorner\\ulcorner\\ulcorner r^{123}\\urcorner\\urcorner\\urcorner -- math: $\\ulcorner\\ulcorner\\ulcorner r^{123}\\urcorner\\urcorner\\urcorner$"); ui->cmbTestset->addItem("text/math: brace test: non-left/right bottom-corner", "text: \\llcorner\\llcorner\\llcorner r^{123}\\lrcorner\\lrcorner\\lrcorner -- math: $\\llcorner\\llcorner\\llcorner r^{123}\\lrcorner\\lrcorner\\lrcorner$"); ui->cmbTestset->addItem("text/math: brace test: non-left/right { | }", "text: \\{r^{123}|r\\equiv 5\\} -- math: $\\{r^{123}|r\\equiv 5\\}$"); + ui->cmbTestset->addItem("math: brace test: bigl/Bigl/... mixed", "math: $\\Biggl\\langle\\biggl\\{\\Bigl[\\bigl(( r^{123})\\bigr)\\Bigr]\\biggr\\}\\Biggr\\rangle$"); ui->cmbTestset->addItem("text/math: sub-, superscript test", "text: r^{1234}_{321} r_{321}^{1234} -- math: $r^{1234}_{321} r_{321}^{1234} -- \\kappa^2 -- \\kappa_2 -- \\kappa_2^2$"); ui->cmbTestset->addItem("text/math: super-, subscript test", "text: r^{123}_{4321} r_{4321}^{123} -- math: $r^{123}_{4321} r_{4321}^{123} -- \\kappa^2 -- \\kappa_2 -- \\kappa_2^2$"); //ui->cmbTestset->addItem("", ""); @@ -462,6 +463,7 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p JKQTMathTextFracNode* fracN=dynamic_cast(node); JKQTMathTextMatrixNode* matrixN=dynamic_cast(node); JKQTMathTextDecoratedNode* decoN=dynamic_cast(node); + JKQTMathTextEmptyBoxNode* emptyN=dynamic_cast(node); QTreeWidgetItem* ti=nullptr; if (parent) ti=new QTreeWidgetItem(parent); @@ -527,6 +529,8 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p name=QString("WhitespaceNode :type=%1, count=%2").arg(spN->Type2String(spN->getWhitespaceType())).arg(spN->getWhitespaceCount()); } else if (txtN) { name=QString("TextNode: \'%1\'").arg(txtN->getText()); + } else if (emptyN) { + name=QString("EmptyBoxNode %1%2 x %3%4").arg(emptyN->getWidth()).arg(JKQTMathTextEmptyBoxNode::Units2String(emptyN->getWidthUnit())).arg(emptyN->getHeight()).arg(JKQTMathTextEmptyBoxNode::Units2String(emptyN->getHeightUnit())); } else { name=QString("unknown"); } diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp index 43c62d4b0b..8db92080e2 100644 --- a/lib/jkqtmathtext/jkqtmathtext.cpp +++ b/lib/jkqtmathtext/jkqtmathtext.cpp @@ -1008,8 +1008,10 @@ JKQTMathText::tokenType JKQTMathText::getToken() { auto fAddUml=[](const QString& cmd, const QChar& letter, const QChar& ch) { QString i; if (cmd.size()>0 && !letter.isNull()) { - i="\\"+cmd+letter; - accentLetters[i]=ch; accentLetters_LenBackslash.insert(i.size()); + if (cmd.size()==1 && !cmd[0].isLetter()) { + i="\\"+cmd+letter; + accentLetters[i]=ch; accentLetters_LenBackslash.insert(i.size()); + } i="{\\"+cmd+letter+"}"; accentLetters[i]=ch; accentLetters_LenCurly.insert(i.size()); i="\\"+cmd+"{"+letter+"}"; @@ -1490,6 +1492,11 @@ JKQTMathText::tokenType JKQTMathText::getToken() { return currentToken=MTTnone; } +void JKQTMathText::giveBackToTokenizer(size_t count) +{ + currentTokenID-=count; +} + JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType quitOnClosingBrace, const QString& quitOnEnvironmentEnd, bool quitOnClosingBracket) { //std::cout<<" entering parseLatexString()\n"; JKQTMathTextHorizontalListNode* nl=new JKQTMathTextHorizontalListNode(this); @@ -1499,7 +1506,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType // initialize some static sets for easy and fast character lookup static QSet mathEnvironmentSpecialText; if (mathEnvironmentSpecialText.size()==0) { - mathEnvironmentSpecialText<<"+"<<"-"<<"="<<"*"<<"<"<<">"<<"|"<<"/"; + mathEnvironmentSpecialText<<"+"<<"-"<<"="<<"*"<<"<"<<">"; } bool getNew=true; @@ -1769,6 +1776,28 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType } JKQTMathTextNode* JKQTMathText::parseInstruction(bool *_foundError, bool* getNew) { + static QHash big_instructions_family; + if (big_instructions_family.size()==0) { + big_instructions_family["big"]=0.85;//1.2; + big_instructions_family["bigl"]=0.85;//1.2; + big_instructions_family["bigm"]=0.85;//1.2; + big_instructions_family["bigr"]=0.85;//1.2; + + big_instructions_family["Big"]=1.15;//1.85; + big_instructions_family["Bigl"]=1.15;//1.85; + big_instructions_family["Bigm"]=1.15;//1.85; + big_instructions_family["Bigr"]=1.15;//1.85; + + big_instructions_family["bigg"]=1.45;//2.4; + big_instructions_family["biggl"]=1.45;//2.4; + big_instructions_family["biggm"]=1.45;//2.4; + big_instructions_family["biggr"]=1.45;//2.4; + + big_instructions_family["Bigg"]=1.75;//3.1; + big_instructions_family["Biggl"]=1.75;//3.1; + big_instructions_family["Biggm"]=1.75;//3.1; + big_instructions_family["Biggr"]=1.75;//3.1; + } if (currentToken!=MTTinstruction) { if (_foundError) *_foundError=true; if (getNew) *getNew=false; @@ -1788,6 +1817,42 @@ JKQTMathTextNode* JKQTMathText::parseInstruction(bool *_foundError, bool* getNew child->setSubSuperscriptAboveBelowNode(true); } if (getNew) *getNew=true; + } else if (big_instructions_family.contains(currentInstructionName)) { + // after \big,\bigl... we expect a symbol-instruction or at least one character of text + while (getToken()==MTTwhitespace);// eat whitespace + + JKQTMathTextBraceType bracetype=MTBTUnknown; + bool openbrace=true; + if (currentToken==MTTinstruction) { + bracetype=TokenName2JKQTMathTextBraceType(currentTokenName, &openbrace); + } else if (currentToken==MTTtext) { + const QString firstTokenChar(currentTokenName[0]); + bracetype=TokenName2JKQTMathTextBraceType(firstTokenChar, &openbrace); + if (bracetype!=MTBTUnknown) { + giveBackToTokenizer(currentTokenName.size()-1); + } else { + giveBackToTokenizer(currentTokenName.size()); + } + } else if (currentToken==MTTopenbracket) { + bracetype=MTBTSquareBracket; + openbrace=true; + } else if (currentToken==MTTclosebracket) { + bracetype=MTBTSquareBracket; + openbrace=false; + } else { + error_list.append(tr("error @ ch. %1: expected symbol-encoding instruction or a character after '\\%2' command, but found token type %3").arg(currentTokenID).arg(currentInstructionName).arg(tokenType2String(currentToken))); + } + if (bracetype!=MTBTUnknown) { + JKQTMathTextEmptyBoxNode* sizeChild=new JKQTMathTextEmptyBoxNode(this, 0, JKQTMathTextEmptyBoxNode::EBUem, big_instructions_family[currentInstructionName], JKQTMathTextEmptyBoxNode::EBUem); + if (openbrace) { + child=new JKQTMathTextBraceNode(this, bracetype, MTBTNone, sizeChild); + } else { + child=new JKQTMathTextBraceNode(this, MTBTNone, bracetype, sizeChild); + } + } else { + error_list.append(tr("error @ ch. %1: expected symbol-encoding instruction or character after '\\%2' command").arg(currentTokenID).arg(currentInstructionName)); + } + if (getNew) *getNew=true; } else if (JKQTMathTextModifiedTextPropsInstructionNode::supportsInstructionName(currentInstructionName)) { const size_t Nparams=JKQTMathTextModifiedTextPropsInstructionNode::countParametersOfInstruction(currentInstructionName); bool foundError=false; @@ -2128,6 +2193,29 @@ JKQTMathTextNode *JKQTMathText::getNodeTree() const { return parsedNode; } +QString JKQTMathText::tokenType2String(tokenType type) +{ + switch(type) { + case MTTnone: return "MTTnone"; + case MTTtext: return "MTTtext"; + case MTTinstruction: return "MTTinstruction"; + case MTTinstructionNewline: return "MTTinstructionNewline"; + case MTTunderscore: return "MTTunderscore"; + case MTThat: return "MTThat"; + case MTTdollar: return "MTTdollar"; + case MTTopenbrace: return "MTTopenbrace"; + case MTTclosebrace: return "MTTclosebrace"; + case MTTopenbracket: return "MTTopenbracket"; + case MTTclosebracket: return "MTTclosebracket"; + case MTTwhitespace: return "MTTwhitespace"; + case MTTampersand: return "MTTampersand"; + case MTThyphen: return "MTThyphen"; + case MTTendash: return "MTTendash"; + case MTTemdash: return "MTTemdash"; + } + return "???"; +} + diff --git a/lib/jkqtmathtext/jkqtmathtext.h b/lib/jkqtmathtext/jkqtmathtext.h index 10b958c200..84877bb8a6 100644 --- a/lib/jkqtmathtext/jkqtmathtext.h +++ b/lib/jkqtmathtext/jkqtmathtext.h @@ -729,9 +729,13 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject { MTTendash, /*!< \brief the en-dash character sequence \c "--" in text-mode */ MTTemdash, /*!< \brief the em-dash character sequence \c "---" in text-mode */ }; + /** \biref convert a tokenType into a string, e.g. for debugging output */ + static QString tokenType2String(tokenType type); /** \brief tokenizer for the LaTeX parser */ tokenType getToken(); + /** \brief returns some characters to the Tokenizer */ + void giveBackToTokenizer(size_t count); /** \brief parse a LaTeX string * * \param get if \c true this calls getToken() diff --git a/lib/jkqtmathtext/jkqtmathtexttools.cpp b/lib/jkqtmathtext/jkqtmathtexttools.cpp index 0ca129faa5..124c0558dc 100644 --- a/lib/jkqtmathtext/jkqtmathtexttools.cpp +++ b/lib/jkqtmathtext/jkqtmathtexttools.cpp @@ -358,18 +358,29 @@ QString JKQTMathTextBraceType2String(JKQTMathTextBraceType type) { return "???"; } -JKQTMathTextBraceType TokenName2JKQTMathTextBraceType(const QString &tokenName) +JKQTMathTextBraceType TokenName2JKQTMathTextBraceType(const QString &tokenName, bool* isOpening) { - 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=="ulcorner" || tokenName=="urcorner"||tokenName=="tlcorner" || tokenName=="trcorner") return MTBTTopCorner; - if (tokenName=="blcorner" || tokenName=="brcorner"||tokenName=="llcorner" || tokenName=="lrcorner") return MTBTBottomCorner; + if (tokenName=="(") { if (isOpening) *isOpening=true; return MTBTParenthesis; } + if (tokenName==")") { if (isOpening) *isOpening=false; return MTBTParenthesis; } + if (tokenName=="[") { if (isOpening) *isOpening=true; return MTBTSquareBracket; } + if (tokenName=="]") { if (isOpening) *isOpening=false; return MTBTSquareBracket; } + if (tokenName=="{") { if (isOpening) *isOpening=true; return MTBTCurlyBracket; } + if (tokenName=="}") { if (isOpening) *isOpening=false; return MTBTCurlyBracket; } + if (tokenName=="|") { if (isOpening) *isOpening=true; return MTBTSingleLine; } + if (tokenName=="||" || tokenName=="#") { if (isOpening) *isOpening=true; return MTBTDoubleLine; } + + if (tokenName=="<" || tokenName=="langle") { if (isOpening) *isOpening=true; return MTBTAngleBracket; } + if (tokenName==">" || tokenName=="rangle") { if (isOpening) *isOpening=false; return MTBTAngleBracket; } + if (tokenName=="_" || tokenName=="lfloor") { if (isOpening) *isOpening=true; return MTBTFloorBracket; } + if (tokenName=="_" || tokenName=="rfloor") { if (isOpening) *isOpening=false; return MTBTFloorBracket; } + if (tokenName=="~" || tokenName=="lceil") { if (isOpening) *isOpening=true; return MTBTCeilBracket; } + if (tokenName=="~" || tokenName=="rceil") { if (isOpening) *isOpening=false; return MTBTCeilBracket; } + if (tokenName=="ulcorner" || tokenName=="tlcorner") { if (isOpening) *isOpening=true; return MTBTTopCorner; } + if (tokenName=="urcorner" || tokenName=="trcorner") { if (isOpening) *isOpening=false; return MTBTTopCorner; } + if (tokenName=="blcorner" || tokenName=="llcorner") { if (isOpening) *isOpening=true; return MTBTBottomCorner; } + if (tokenName=="brcorner" || tokenName=="lrcorner") { if (isOpening) *isOpening=false; return MTBTBottomCorner; } + if (isOpening) *isOpening=true; + if (tokenName=="any") return MTBTAny; if (tokenName=="." || tokenName=="" || tokenName=="none") return MTBTNone; return MTBTUnknown; diff --git a/lib/jkqtmathtext/jkqtmathtexttools.h b/lib/jkqtmathtext/jkqtmathtexttools.h index 80944d1eaa..4e564107f3 100644 --- a/lib/jkqtmathtext/jkqtmathtexttools.h +++ b/lib/jkqtmathtext/jkqtmathtexttools.h @@ -169,7 +169,7 @@ JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextBraceType2String(JKQTMathTextBraceTy /** \brief convert a string \a tokenName describing a LaTeX Token or Instruction into an opening or closing JKQTMathTextBraceType * \ingroup jkqtmathtext_tools */ -JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceType TokenName2JKQTMathTextBraceType(const QString& tokenName); +JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceType TokenName2JKQTMathTextBraceType(const QString& tokenName, bool *isOpening=nullptr); /** \brief convert a string \a tokenName describing a LaTeX Instruction into an opening JKQTMathTextBraceType * \ingroup jkqtmathtext_tools * diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp index 36c1fc9eac..84f41cf5ec 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp @@ -591,6 +591,32 @@ void JKQTMathTextModifiedTextPropsInstructionNode::fillInstructions() }, 0); instructions["scriptscriptstyle"]= i; } + + + { + InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/) { + ev.fontSize=ev.fontSize*1.2; + }, 0); + instructions["bigsize"]= i; + } + { + InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/) { + ev.fontSize=ev.fontSize*1.85; + }, 0); + instructions["Bigsize"]= i; + } + { + InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/) { + ev.fontSize=ev.fontSize*2.4; + }, 0); + instructions["biggsize"]= i; + } + { + InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/) { + ev.fontSize=ev.fontSize*3.1; + }, 0); + instructions["Biggsize"]= i; + } } JKQTMathTextModifiedTextPropsInstructionNode::InstructionProperties::InstructionProperties(): diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.cpp index 16aaf27427..ad053203e9 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.cpp @@ -102,8 +102,9 @@ size_t JKQTMathTextWhitespaceNode::getWhitespaceCount() const return whitespace.count; } -double JKQTMathTextWhitespaceNode::draw(QPainter &painter, double x, double /*y*/, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize *prevNodeSize) +double JKQTMathTextWhitespaceNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize *prevNodeSize) { + doDrawBoxes(painter, x,y,currentEv); double width=0, bh=0, oh=0, sp=0; getSize(painter, currentEv, width, bh, oh, sp, prevNodeSize); return x+width; @@ -215,3 +216,101 @@ QString JKQTMathTextWhitespaceNode::Type2HTML(Types type) return " "; } + +QString JKQTMathTextEmptyBoxNode::Units2String(Units type) +{ + switch(type) { + case EBUem: return "em"; + case EBUex: return "ex"; + } + return "?"; +} + +JKQTMathTextEmptyBoxNode::Units JKQTMathTextEmptyBoxNode::String2Units(QString type) +{ + type=type.toLower().trimmed(); + if (type=="ex") return EBUex; + if (type=="em") return EBUem; + return EBUem; +} + +double JKQTMathTextEmptyBoxNode::Units2PixelWidth(double value, Units unit, JKQTMathTextEnvironment currentEv, QPaintDevice *pd) const +{ + const QFontMetricsF fm(currentEv.getFont(parentMathText), pd); + if (unit==EBUem) { +#if (QT_VERSION>=QT_VERSION_CHECK(5, 15, 0)) + const double em=fm.horizontalAdvance(QChar(0x2003));//currentEv.fontSize; +#else + const double em=fm.width(QChar(0x2003));//currentEv.fontSize; +#endif + return value*em; + } else if (unit==EBUex) { + const double ex=fm.xHeight(); + return value*ex; + } + return 0; +} + +JKQTMathTextEmptyBoxNode::JKQTMathTextEmptyBoxNode(JKQTMathText *parent, double width_, Units widthUnit_, double height_, Units heightUnit_): + JKQTMathTextNode(parent), + width(width_), widthUnit(widthUnit_), + height(height_),heightUnit(heightUnit_) +{ + +} + +JKQTMathTextEmptyBoxNode::~JKQTMathTextEmptyBoxNode() +{ + +} + +QString JKQTMathTextEmptyBoxNode::getTypeName() const +{ + return QString("JKQTMathTextEmptyBoxNode(%1%2 x %3%4)").arg(getWidth()).arg(JKQTMathTextEmptyBoxNode::Units2String(getWidthUnit())).arg(getHeight()).arg(JKQTMathTextEmptyBoxNode::Units2String(getHeightUnit())); +} + +bool JKQTMathTextEmptyBoxNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) +{ + return true; +} + +JKQTMathTextEmptyBoxNode::Units JKQTMathTextEmptyBoxNode::getWidthUnit() const +{ + return widthUnit; +} + +double JKQTMathTextEmptyBoxNode::getWidth() const +{ + return width; +} + +JKQTMathTextEmptyBoxNode::Units JKQTMathTextEmptyBoxNode::getHeightUnit() const +{ + return heightUnit; +} + +double JKQTMathTextEmptyBoxNode::getHeight() const +{ + return height; +} + +double JKQTMathTextEmptyBoxNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize *prevNodeSize) +{ + doDrawBoxes(painter, x,y,currentEv); + double width=0, bh=0, oh=0, sp=0; + getSize(painter, currentEv, width, bh, oh, sp, prevNodeSize); + return x+width; +} + +void JKQTMathTextEmptyBoxNode::getSizeInternal(QPainter &painter, JKQTMathTextEnvironment currentEv, double &width, double &baselineHeight, double &overallHeight, double &strikeoutPos, const JKQTMathTextNodeSize */*prevNodeSize*/) +{ + const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device()); + width=Units2PixelWidth(width, widthUnit, currentEv, painter.device()); + overallHeight=Units2PixelWidth(height, heightUnit, currentEv, painter.device()); + if (height>0) { + baselineHeight=overallHeight; + } else { + baselineHeight=0; + } + strikeoutPos=fm.strikeOutPos(); +} diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h b/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h index 1080946b6f..7275acf754 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h @@ -76,9 +76,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextWhitespaceNode: public JKQTMathTextNod virtual QString getTypeName() const override; /** \copydoc JKQTMathTextNode::toHtml() */ virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override; - /** \brief copydoc WhitespaceProps::type */ + /** \copydoc WhitespaceProps::type */ Types getWhitespaceType() const; - /** \brief copydoc WhitespaceProps::count */ + /** \copydoc WhitespaceProps::count */ size_t getWhitespaceCount() const; /** \copydoc JKQTMathTextNode::draw() */ virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override; @@ -103,6 +103,53 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextWhitespaceNode: public JKQTMathTextNod static void fillSupportedInstructions(); }; + +/** \brief subclass representing an empty bbox with defined width/height in the syntax tree + * \ingroup jkqtmathtext_items + * + */ +class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextEmptyBoxNode: public JKQTMathTextNode { + public: + enum Units { + EBUem, /*!< \brief 1em = width('M') */ + EBUex, /*!< \brief 1ex = xHeight */ + }; + /** \brief converts Types \a type into a string */ + static QString Units2String(Units type); + /** \brief converts Types \a type into a string */ + static Units String2Units(QString type); + /** \brief converts Types \a type into its width in pixels, based on \a currentEv and \a pd */ + double Units2PixelWidth(double value, Units unit, JKQTMathTextEnvironment currentEv, QPaintDevice *pd) const; + /** \brief constructs a node */ + explicit JKQTMathTextEmptyBoxNode(JKQTMathText* parent, double width_, Units widthUnit_, double height_, Units heightUnit_); + virtual ~JKQTMathTextEmptyBoxNode() override; + /** \copydoc JKQTMathTextNode::getTypeName() */ + virtual QString getTypeName() const override; + /** \copydoc JKQTMathTextNode::toHtml() */ + virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override; + /** \copydoc widthUnit */ + Units getWidthUnit() const; + /** \copydoc width */ + double getWidth() const; + /** \copydoc heightUnit */ + Units getHeightUnit() const; + /** \copydoc height */ + double getHeight() const; + /** \copydoc JKQTMathTextNode::draw() */ + virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override; + protected: + /** \copydoc JKQTMathTextNode::getSizeInternal() */ + virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override; + /** \brief width of the (empty) box, units of this value defined in widthUnit */ + double width; + /** \biref units to interpret width */ + Units widthUnit; + /** \brief height of the (empty) box, units of this value defined in heightUnit */ + double height; + /** \biref units to interpret height */ + Units heightUnit; +}; + #endif // JKQTMATHTEXTWHITESPACENODE_H