diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox index 058713ff6d..b4d2b2f204 100644 --- a/doc/dox/whatsnew.dox +++ b/doc/dox/whatsnew.dox @@ -49,6 +49,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
  • NEW: LaTeX-Parser simplifies parrse-tree to increase speed of execution
  • NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)
  • NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)
  • +
  • NEW: added \overbracket and \underbracket
  • diff --git a/doc/images/jkqtmathtext/MTFMoverbracket.png b/doc/images/jkqtmathtext/MTFMoverbracket.png new file mode 100644 index 0000000000..f381390270 Binary files /dev/null and b/doc/images/jkqtmathtext/MTFMoverbracket.png differ diff --git a/doc/images/jkqtmathtext/MTFMunderbracket.png b/doc/images/jkqtmathtext/MTFMunderbracket.png new file mode 100644 index 0000000000..a6d4ccabc0 Binary files /dev/null and b/doc/images/jkqtmathtext/MTFMunderbracket.png differ diff --git a/examples/jkqtmathtext_test/testform.cpp b/examples/jkqtmathtext_test/testform.cpp index d927113863..f0689d34b4 100644 --- a/examples/jkqtmathtext_test/testform.cpp +++ b/examples/jkqtmathtext_test/testform.cpp @@ -155,9 +155,9 @@ TestForm::TestForm(QWidget *parent) : ui->cmbTestset->addItem("math 7", "$\\left(\\frac{\\partial^2}{\\partial x^2}+\\frac{\\partial^2}{\\partial y^2}\\right)\\left|\\varphi(x+\\mathrm{i}y)\\right|^2=0$"); ui->cmbTestset->addItem("math 8", "$2^{2^{2^{x}}}$"); ui->cmbTestset->addItem("math 9", "$\\iint_Df(x,y)\\;\\mathrm{d}x\\;\\mathrm{d}y$"); - ui->cmbTestset->addItem("math 10 (overbrace)", "$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}$"); - ui->cmbTestset->addItem("math 11 (underbrace)", "$\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}$"); - ui->cmbTestset->addItem("math 12 (under/overbrace)", "$\\underbrace{\\overbrace{x+x+...+x}{k\\ \\mathrm{times}} \\overbrace{x+x+...+x}{k\\ \\mathrm{times}}}{2k\\ \\mathrm{times}}$"); + ui->cmbTestset->addItem("math 10 (overbrace+overbracket)", "$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}\\ \\ \\ \\overbracket{x+x+...+x}{k\\ \\mathrm{times}}$"); + ui->cmbTestset->addItem("math 11 (underbrace+underbracket)", "$\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}\\ \\ \\ \\underbracket{x+x+...+x}{k\\ \\mathrm{times}}$"); + ui->cmbTestset->addItem("math 12 (under/overbrace+under/overbracket)", "$\\underbrace{\\overbrace{x+x+...+x}{k\\ \\mathrm{times}} \\overbrace{x+x+...+x}{k\\ \\mathrm{times}}}{2k\\ \\mathrm{times}}\\ \\ \\ \\underbracket{\\overbracket{x+x+...+x}{k\\ \\mathrm{times}} \\overbracket{x+x+...+x}{k\\ \\mathrm{times}}}{2k\\ \\mathrm{times}}$"); ui->cmbTestset->addItem("math 13", "$y_1''\\ \\ \\ y_2'''$"); ui->cmbTestset->addItem("math 14", "$f(x)=\\begin{cases} 1/3 & \\mathrm{if}\\ 0\\leq x\\leq1 \\\\ 2/3 & \\mathrm{if}\\ 3\\leq x\\leq4 \\\\0 & \\mathrm{elsewhere} \\end{cases}$"); ui->cmbTestset->addItem("math 15", "$\\Re(z) =\\frac{n\\pi \\dfrac{\\theta +\\psi}{2}}{\\left(\\dfrac{\\theta +\\psi}{2}\\right)^2 + \\left( \\dfrac{1}{2}\\log \\left\\lvert\\dfrac{B}{A}\\right\\rvert\\right)^2}.$"); diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp index fa2cae730b..e35ef4f576 100644 --- a/lib/jkqtmathtext/jkqtmathtext.cpp +++ b/lib/jkqtmathtext/jkqtmathtext.cpp @@ -1168,6 +1168,12 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType 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; @@ -1180,6 +1186,12 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType 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; diff --git a/lib/jkqtmathtext/jkqtmathtext.h b/lib/jkqtmathtext/jkqtmathtext.h index 9d43a31d39..715d889783 100644 --- a/lib/jkqtmathtext/jkqtmathtext.h +++ b/lib/jkqtmathtext/jkqtmathtext.h @@ -156,6 +156,8 @@ class JKQTMathTextNode; // forward There are also instructions that allow to under/overset braces, arrows, ...: - $\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}$ \image html jkqtmathtext/jkqtmathtext_brace_underbrace.png - $\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}$ \image html jkqtmathtext/jkqtmathtext_brace_overbrace.png + - $\\underbracket{x+x+...+x}{k\\ \\mathrm{times}}$ \image html jkqtmathtext/MTFMunderbracket.png + - $\\overbracket{x+x+...+x}{k\\ \\mathrm{times}}$ \image html jkqtmathtext/MTFMoverbracket.png - $\\overset{main}{over}$ \image html jkqtmathtext/jkqtmathtext_brace_overset.png - $\\underset{main}{under}$ \image html jkqtmathtext/jkqtmathtext_brace_underset.png . diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp index f360976785..d17fc9031f 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp @@ -53,6 +53,10 @@ QString JKQTMathTextFracNode::FracType2String(JKQTMathTextFracNode::FracType mod return "underbrace"; case JKQTMathTextFracNode::MTFMoverbrace: return "overbrace"; + case JKQTMathTextFracNode::MTFMunderbracket: + return "underbracket"; + case JKQTMathTextFracNode::MTFMoverbracket: + return "overbracket"; case JKQTMathTextFracNode::MTFMunderset: return "underset"; case JKQTMathTextFracNode::MTFMoverset: @@ -93,7 +97,7 @@ void JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro const double braceheight=fm.xHeight()*parentMathText->getUnderbraceBraceSizeXFactor(); const double braceseparation=fm.xHeight()*parentMathText->getUnderbraceSeparationXFactor(); - if (mode==JKQTMathTextFracNode::MTFMunderbrace || mode==JKQTMathTextFracNode::MTFMoverbrace) { + if (mode==JKQTMathTextFracNode::MTFMunderbrace || mode==JKQTMathTextFracNode::MTFMoverbrace||mode==JKQTMathTextFracNode::MTFMunderbracket || mode==JKQTMathTextFracNode::MTFMoverbracket) { ev2.fontSize=ev2.fontSize*parentMathText->getUnderbraceFactor(); } else if (mode==JKQTMathTextFracNode::MTFMunderset || mode==JKQTMathTextFracNode::MTFMoverset) { ev2.fontSize=ev2.fontSize*parentMathText->getUndersetFactor(); @@ -137,13 +141,13 @@ void JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro overallHeight=newascent+newdescent; baselineHeight=newascent; - } else if (mode==JKQTMathTextFracNode::MTFMunderbrace) { + } else if (mode==JKQTMathTextFracNode::MTFMunderbrace || mode==JKQTMathTextFracNode::MTFMunderbracket) { const double newdescent=descent1+overallHeight2+braceheight+2.0*braceseparation; overallHeight=newdescent+baselineHeight1; baselineHeight=baselineHeight1; width=qMax(width1, width2)+xwidth; strikeoutPos=line_ascent; - } else if (mode==JKQTMathTextFracNode::MTFMoverbrace) { + } else if (mode==JKQTMathTextFracNode::MTFMoverbrace || mode==JKQTMathTextFracNode::MTFMoverbracket) { overallHeight=overallHeight1+overallHeight2+braceheight+2.0*braceseparation; baselineHeight=baselineHeight1+overallHeight2+braceheight+2.0*braceseparation; width=qMax(width1, width2)+xwidth; @@ -196,7 +200,7 @@ double JKQTMathTextFracNode::draw(QPainter& painter, double x, double y, JKQTMat const double braceheight=fm.xHeight()*parentMathText->getUnderbraceBraceSizeXFactor(); const double braceseparation=fm.xHeight()*parentMathText->getUnderbraceSeparationXFactor(); - if (mode==JKQTMathTextFracNode::MTFMunderbrace || mode==JKQTMathTextFracNode::MTFMoverbrace) { + if (mode==JKQTMathTextFracNode::MTFMunderbrace || mode==JKQTMathTextFracNode::MTFMoverbrace||mode==JKQTMathTextFracNode::MTFMunderbracket || mode==JKQTMathTextFracNode::MTFMoverbracket) { ev2.fontSize=ev2.fontSize*parentMathText->getUnderbraceFactor(); } else if (mode==JKQTMathTextFracNode::MTFMunderset || mode==JKQTMathTextFracNode::MTFMoverset) { ev2.fontSize=ev2.fontSize*parentMathText->getUndersetFactor(); @@ -263,6 +267,24 @@ double JKQTMathTextFracNode::draw(QPainter& painter, double x, double y, JKQTMat child1->draw(painter, x+xwidth/2.0+(maxWidth-width1)/2.0, y, ev1); child2->draw(painter, x+xwidth/2.0+(maxWidth-width2)/2.0, ybot, ev2); deltaWidth=xwidth; + } else if (mode==JKQTMathTextFracNode::MTFMunderbracket) { + const double ybrace=y+descent1+braceseparation+braceheight/2.0; + const double ybot=y+descent1+2.0*braceseparation+braceheight+ascent2; + { + QPainterPath path; + const double y1=ybrace-braceheight/2.0; + const double y2=ybrace+braceheight/2.0; + const double x1=x+xwidth/2.0+p.width()/2.0; + const double x2=x+xwidth/2.0+maxWidth-p.width()/2.0; + path.moveTo(x1, y1); + path.lineTo(x1, y2); + path.lineTo(x2, y2); + path.lineTo(x2, y1); + painter.drawPath(path); + } + child1->draw(painter, x+xwidth/2.0+(maxWidth-width1)/2.0, y, ev1); + child2->draw(painter, x+xwidth/2.0+(maxWidth-width2)/2.0, ybot, ev2); + deltaWidth=xwidth; } else if (mode==JKQTMathTextFracNode::MTFMoverset) { child1->draw(painter, x+xwidth/2.0+(maxWidth-width1)/2.0, y, ev1); child2->draw(painter, x+xwidth/2.0+(maxWidth-width2)/2.0, y-ascent1-xheight/6.0-descent2, ev2); @@ -280,6 +302,24 @@ double JKQTMathTextFracNode::draw(QPainter& painter, double x, double y, JKQTMat painter.fillPath(path, QBrush(ev1.color)); } + child1->draw(painter, x+xwidth/2.0+(maxWidth-width1)/2.0, y, ev1); + child2->draw(painter, x+xwidth/2.0+(maxWidth-width2)/2.0, ytop, ev2); + deltaWidth=xwidth; + } else if (mode==JKQTMathTextFracNode::MTFMoverbracket) { + const double ybrace=y-ascent1-braceheight/2.0-braceseparation; + const double ytop=y-ascent1-2.0*braceseparation-braceheight-descent2; + { + QPainterPath path; + const double y1=ybrace+braceheight/2.0; + const double y2=ybrace-braceheight/2.0; + const double x1=x+xwidth/2.0+p.width()/2.0; + const double x2=x+xwidth/2.0+maxWidth-p.width()/2.0; + path.moveTo(x1, y1); + path.lineTo(x1, y2); + path.lineTo(x2, y2); + path.lineTo(x2, y1); + painter.drawPath(path); + } child1->draw(painter, x+xwidth/2.0+(maxWidth-width1)/2.0, y, ev1); child2->draw(painter, x+xwidth/2.0+(maxWidth-width2)/2.0, ytop, ev2); deltaWidth=xwidth; diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h index f5b53aa968..abb13ad32e 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextfracnode.h @@ -55,6 +55,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFracNode: public JKQTMathTextDualChild MTFMstfrac, /*!< \brief slanted text fraction \image html jkqtmathtext/MTFMstfrac.png */ MTFMunderbrace, /*!< \brief curly underbrace \image html jkqtmathtext/MTFMunderbrace.png */ MTFMoverbrace, /*!< \brief curly overbrace \image html jkqtmathtext/MTFMoverbrace.png */ + MTFMunderbracket, /*!< \brief square underbracket \image html jkqtmathtext/MTFMunderbracket.png */ + MTFMoverbracket, /*!< \brief square overbracket \image html jkqtmathtext/MTFMoverbracket.png */ MTFMstackrel, /*!< \brief binom/fraction without line \image html jkqtmathtext/MTFMstackrel.png */ MTFMunderset, /*!< \brief underset text \image html jkqtmathtext/MTFMunderset.png */ MTFMoverset /*!< \brief overset text \image html jkqtmathtext/MTFMoverset.png */