NEW: JKQTMathText: added \underbracket and \overbracket

This commit is contained in:
jkriege2 2022-06-28 10:15:54 +02:00
parent fc557c9aff
commit b83e0a3292
8 changed files with 64 additions and 7 deletions

View File

@ -49,6 +49,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: LaTeX-Parser simplifies parrse-tree to increase speed of execution</li> <li>NEW: LaTeX-Parser simplifies parrse-tree to increase speed of execution</li>
<li>NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)</li> <li>NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)</li>
<li>NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)</li> <li>NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)</li>
<li>NEW: added \overbracket and \underbracket</li>
</ul> </ul>
</ul> </ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -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 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 8", "$2^{2^{2^{x}}}$");
ui->cmbTestset->addItem("math 9", "$\\iint_Df(x,y)\\;\\mathrm{d}x\\;\\mathrm{d}y$"); 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 10 (overbrace+overbracket)", "$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}\\ \\ \\ \\overbracket{x+x+...+x}{k\\ \\mathrm{times}}$");
ui->cmbTestset->addItem("math 11 (underbrace)", "$\\underbrace{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)", "$\\underbrace{\\overbrace{x+x+...+x}{k\\ \\mathrm{times}} \\overbrace{x+x+...+x}{k\\ \\mathrm{times}}}{2k\\ \\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 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 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}.$"); 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}.$");

View File

@ -1168,6 +1168,12 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
if (getToken()==MTTopenbrace) n2=parseLatexString(true); if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbrace)); 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 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") { } else if (currentInstructionName=="underset") {
JKQTMathTextNode* n1=parseLatexString(true); JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr; JKQTMathTextNode* n2=nullptr;
@ -1180,6 +1186,12 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
if (getToken()==MTTopenbrace) n2=parseLatexString(true); if (getToken()==MTTopenbrace) n2=parseLatexString(true);
if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbrace)); 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 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") { } else if (currentInstructionName=="overset") {
JKQTMathTextNode* n1=parseLatexString(true); JKQTMathTextNode* n1=parseLatexString(true);
JKQTMathTextNode* n2=nullptr; JKQTMathTextNode* n2=nullptr;

View File

@ -156,6 +156,8 @@ class JKQTMathTextNode; // forward
There are also instructions that allow to under/overset braces, arrows, ...: There are also instructions that allow to under/overset braces, arrows, ...:
- <code>$\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/jkqtmathtext_brace_underbrace.png - <code>$\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/jkqtmathtext_brace_underbrace.png
- <code>$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/jkqtmathtext_brace_overbrace.png - <code>$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/jkqtmathtext_brace_overbrace.png
- <code>$\\underbracket{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/MTFMunderbracket.png
- <code>$\\overbracket{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/MTFMoverbracket.png
- <code>$\\overset{main}{over}$</code> \image html jkqtmathtext/jkqtmathtext_brace_overset.png - <code>$\\overset{main}{over}$</code> \image html jkqtmathtext/jkqtmathtext_brace_overset.png
- <code>$\\underset{main}{under}$</code> \image html jkqtmathtext/jkqtmathtext_brace_underset.png - <code>$\\underset{main}{under}$</code> \image html jkqtmathtext/jkqtmathtext_brace_underset.png
. .

View File

@ -53,6 +53,10 @@ QString JKQTMathTextFracNode::FracType2String(JKQTMathTextFracNode::FracType mod
return "underbrace"; return "underbrace";
case JKQTMathTextFracNode::MTFMoverbrace: case JKQTMathTextFracNode::MTFMoverbrace:
return "overbrace"; return "overbrace";
case JKQTMathTextFracNode::MTFMunderbracket:
return "underbracket";
case JKQTMathTextFracNode::MTFMoverbracket:
return "overbracket";
case JKQTMathTextFracNode::MTFMunderset: case JKQTMathTextFracNode::MTFMunderset:
return "underset"; return "underset";
case JKQTMathTextFracNode::MTFMoverset: case JKQTMathTextFracNode::MTFMoverset:
@ -93,7 +97,7 @@ void JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
const double braceheight=fm.xHeight()*parentMathText->getUnderbraceBraceSizeXFactor(); const double braceheight=fm.xHeight()*parentMathText->getUnderbraceBraceSizeXFactor();
const double braceseparation=fm.xHeight()*parentMathText->getUnderbraceSeparationXFactor(); 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(); ev2.fontSize=ev2.fontSize*parentMathText->getUnderbraceFactor();
} else if (mode==JKQTMathTextFracNode::MTFMunderset || mode==JKQTMathTextFracNode::MTFMoverset) { } else if (mode==JKQTMathTextFracNode::MTFMunderset || mode==JKQTMathTextFracNode::MTFMoverset) {
ev2.fontSize=ev2.fontSize*parentMathText->getUndersetFactor(); ev2.fontSize=ev2.fontSize*parentMathText->getUndersetFactor();
@ -137,13 +141,13 @@ void JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
overallHeight=newascent+newdescent; overallHeight=newascent+newdescent;
baselineHeight=newascent; baselineHeight=newascent;
} else if (mode==JKQTMathTextFracNode::MTFMunderbrace) { } else if (mode==JKQTMathTextFracNode::MTFMunderbrace || mode==JKQTMathTextFracNode::MTFMunderbracket) {
const double newdescent=descent1+overallHeight2+braceheight+2.0*braceseparation; const double newdescent=descent1+overallHeight2+braceheight+2.0*braceseparation;
overallHeight=newdescent+baselineHeight1; overallHeight=newdescent+baselineHeight1;
baselineHeight=baselineHeight1; baselineHeight=baselineHeight1;
width=qMax(width1, width2)+xwidth; width=qMax(width1, width2)+xwidth;
strikeoutPos=line_ascent; strikeoutPos=line_ascent;
} else if (mode==JKQTMathTextFracNode::MTFMoverbrace) { } else if (mode==JKQTMathTextFracNode::MTFMoverbrace || mode==JKQTMathTextFracNode::MTFMoverbracket) {
overallHeight=overallHeight1+overallHeight2+braceheight+2.0*braceseparation; overallHeight=overallHeight1+overallHeight2+braceheight+2.0*braceseparation;
baselineHeight=baselineHeight1+overallHeight2+braceheight+2.0*braceseparation; baselineHeight=baselineHeight1+overallHeight2+braceheight+2.0*braceseparation;
width=qMax(width1, width2)+xwidth; 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 braceheight=fm.xHeight()*parentMathText->getUnderbraceBraceSizeXFactor();
const double braceseparation=fm.xHeight()*parentMathText->getUnderbraceSeparationXFactor(); 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(); ev2.fontSize=ev2.fontSize*parentMathText->getUnderbraceFactor();
} else if (mode==JKQTMathTextFracNode::MTFMunderset || mode==JKQTMathTextFracNode::MTFMoverset) { } else if (mode==JKQTMathTextFracNode::MTFMunderset || mode==JKQTMathTextFracNode::MTFMoverset) {
ev2.fontSize=ev2.fontSize*parentMathText->getUndersetFactor(); 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); 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); child2->draw(painter, x+xwidth/2.0+(maxWidth-width2)/2.0, ybot, ev2);
deltaWidth=xwidth; 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) { } else if (mode==JKQTMathTextFracNode::MTFMoverset) {
child1->draw(painter, x+xwidth/2.0+(maxWidth-width1)/2.0, y, ev1); 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); 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)); 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); 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); child2->draw(painter, x+xwidth/2.0+(maxWidth-width2)/2.0, ytop, ev2);
deltaWidth=xwidth; deltaWidth=xwidth;

View File

@ -55,6 +55,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFracNode: public JKQTMathTextDualChild
MTFMstfrac, /*!< \brief slanted text fraction \image html jkqtmathtext/MTFMstfrac.png */ MTFMstfrac, /*!< \brief slanted text fraction \image html jkqtmathtext/MTFMstfrac.png */
MTFMunderbrace, /*!< \brief curly underbrace \image html jkqtmathtext/MTFMunderbrace.png */ MTFMunderbrace, /*!< \brief curly underbrace \image html jkqtmathtext/MTFMunderbrace.png */
MTFMoverbrace, /*!< \brief curly overbrace \image html jkqtmathtext/MTFMoverbrace.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 */ MTFMstackrel, /*!< \brief binom/fraction without line \image html jkqtmathtext/MTFMstackrel.png */
MTFMunderset, /*!< \brief underset text \image html jkqtmathtext/MTFMunderset.png */ MTFMunderset, /*!< \brief underset text \image html jkqtmathtext/MTFMunderset.png */
MTFMoverset /*!< \brief overset text \image html jkqtmathtext/MTFMoverset.png */ MTFMoverset /*!< \brief overset text \image html jkqtmathtext/MTFMoverset.png */