MODIFIED: brace node now calculates the extension of the child height above or below the strikeoutPos, in order to center braces around the strikeoutPos

fixed: strikeoutPos was not correctly calculated in sub-/superscript node
NEW: JKQTMathText shows strikeoutPos when drawing Debug-Boxes
This commit is contained in:
jkriege2 2022-06-09 14:30:15 +02:00
parent 143ae54ae8
commit 992cad7ff3
20 changed files with 274 additions and 237 deletions

View File

@ -41,7 +41,7 @@ This page lists several todos and wishes for future version of JKQTPlotter
<li>add instruction for unicode-characters \char"XXXX, \unicode{XXXX}, \utf8{XXXX}, \utf16{XXXX}, \utf32{XXXX} ...</li>
<li>check sub/superscript with italic text in math mode, possibly a correction is necessary</li>
<li>explore where QFontMetricsF::horizontalAdvance() can be used (for Qt >=5.15)</li>
<li>correction of frac-height (2*maxHeight or height1+height2) should be done by brace-node, not frac-node</li>
<li></li>
<li></li>
<li></li>
</ul></li>

View File

@ -15,10 +15,10 @@ This page lists release notes for the different version of JKQTPlotter
Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<ul>
<li>JKQtPlotter:<ul>
<li>fixed issue described in <a href="https://github.com/jkriege2/JKQtPlotter/pull/62">#62: Fix custom labels draw, because giving exactly two label-strings did not display all of them</a>, thanks to <a href="https://github.com/FalsinSoft">user:FalsinSoft</a></li>
<li>fixed issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/70">#70: Typo in jkqtplotter/CMakeLists.txt</a>, thanks to <a href="https://github.com/tedlinlab">user:tedlinlab</a></li>
<li>fixed: styling was not properly applied to coordinate axes of colorbars outside the plot</li>
<li>improved: QT6-compatibility by removing deprecated warnings</li>
<li>FIXED issue described in <a href="https://github.com/jkriege2/JKQtPlotter/pull/62">#62: Fix custom labels draw, because giving exactly two label-strings did not display all of them</a>, thanks to <a href="https://github.com/FalsinSoft">user:FalsinSoft</a></li>
<li>FIXED issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/70">#70: Typo in jkqtplotter/CMakeLists.txt</a>, thanks to <a href="https://github.com/tedlinlab">user:tedlinlab</a></li>
<li>FIXED: styling was not properly applied to coordinate axes of colorbars outside the plot</li>
<li>IMPROVED: QT6-compatibility by removing deprecated warnings</li>
<li>NEW: JKQTPFilledCurveXGraph and JKQTPFilledCurveYGraph can now plot wiggle plots with different fill styles above and below the baseline (feature request <a href="https://github.com/jkriege2/JKQtPlotter/issues/68">#68 Wiggle Plots</a> from <a href="https://github.com/xichaoqiang">user:xichaoqiang</a> </li>
<li>NEW/BREAKING CHANGE: data tooltip can now also be shown when "just" moving the mouse (so far this was only possible when dragging the mouse with a button pressed). This also removes JKQtPlotter::getActMouseLeftAsToolTip() and adds JKQtPlotter::getActMouseMoveToolTip() instead! Also the default toolbars and context menus changed!</li>
<li>NEW: new "seaborn" style for plots</li>
@ -27,15 +27,18 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
</ul>
<li>JKQTMathText:<ul>
<li>fixed: JKQTMathText added a little whitespace before and after the LaTeX-string. This was removed as it disturbed the layout of text in plots</li>
<li>fixed: height-calculation of frac-like instructions: before the ascent and descent were equal, even if the numerator and denominator have different hieghts</li>
<li>fixes/improvements: JKQTMathText renders several LaTeX strings better (simple braces in math mode, +-*... as symbols with proper sizes in math mode, added some missing instruction aliases, improved size of \vec and \hat, corrrected fonts usage for mathrm</li>
<li>improved: high-dpr-support in JKQTMathText</li>
<li>FIXED: JKQTMathText added a little whitespace before and after the LaTeX-string. This was removed as it disturbed the layout of text in plots</li>
<li>FIXED: height-calculation of frac-like instructions: before the ascent and descent were equal, even if the numerator and denominator have different heights</li>
<li>FIXED: strikeoutPos was not correctly calculated in sub-/superscript node</li>
<li>FIXED/IMPROVED: JKQTMathText renders several LaTeX strings better (simple braces in math mode, +-*... as symbols with proper sizes in math mode, added some missing instruction aliases, improved size of \vec and \hat, corrrected fonts usage for mathrm</li>
<li>IMPROVED: high-dpr-support in JKQTMathText</li>
<li>MODIFIED: brace node now calculates the extension of the child height above or below the strikeoutPos, in order to center braces around the strikeoutPos</li>
<li>NEW: now supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve</li>
<li>NEW: reworked drawing of decorations: improved appearance and positioning!</li>
<li>NEW: reworked code structure: broke up large, single CPP-files into several smaller files!</li>
<li>NEW: reworked node class tree: inserted base-class nodes for single-child, dual-child!</li>
<li>NEW: improved frac-rendering: font-scaling takes nesting-level into account, overall-rendering, sizes, if a brace surrounds a frac, the heights are equal above and below to center the brace , ...</li>
<li>NEW: shows strikeoutPos when drawing Debug-Boxes</li>
</ul>
</ul>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -35,6 +35,9 @@
\newcommand{\uul}[1]{\uuline{#1}}
\newcommand{\ool}[1]{\overline{\overline{#1}}}
\newcommand{\arrow}[1]{\overrightarrow{#1}}
\newcommand{\stkout}[1]{\ifmmode\text{\sout{\ensuremath{#1}}}\else\sout{#1}\fi}
\begin{document}
\begin{itemize}
@ -130,6 +133,7 @@
\item\textbf{math: integrals:} no-limits: \[Hxq \int_{0}^1 f(x)\;\mathrm{d}x\ \iint_{0}^1 f(x)\;\mathrm{d}x\ \iiint_{0}^1 f(x)\;\mathrm{d}x\ \oint_{0}^1 f(x)\;\mathrm{d}x\ \int_{x} f(x)\;\mathrm{d}x\]\ \ \ --\ \ \ limits: \[\int\limits_{0}^1 f(x)\;\mathrm{d}x\ \iint\limits_{0}^1 f(x)\;\mathrm{d}x\ \iiint\limits_{0}^1 f(x)\;\mathrm{d}x\ \oint\limits_{0}^1 f(x)\;\mathrm{d}x\ \int\limits_{x} f(x)\;\mathrm{d}x\]
\item\textbf{math: frac test:} \[\frac{a}{b}+\frac{g}{a}-\frac{a^2}{b^2}\cdot\frac{a^2}{b^{\frac{1}{2}}}\]
\item\textbf{sfrac:} Hxq \sfrac{1}{2} \ \ -- \ \ $Hxq \frac{1}{2}\ \ \sfrac{1}{2}\ \ \frac{1}{2+\frac{1}{2}}\ \ \sfrac{1}{2+\sfrac{1}{2}}\ \ \sfrac{1}{2+\frac{1}{2}}\ \ \sfrac{\frac{1}{2+\frac{1}{2}}}{2}\ \ e^{\sfrac{1}{2}}$
\item\textbf{brace+sub/superscript:} $\stkout{\left\langle \stkout{r_{123}}\right\rangle\left\langle r^{123}\right\rangle\left\langle r_{123}^{123}\right\rangle}$
\end{itemize}

View File

@ -110,11 +110,17 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbTestset->addItem("text/math: brace2 test", "text: \\langle\\langle r^{123}\\rangle\\rangle -- math: $\\langle\\langle r^{123}\\rangle\\rangle$");
ui->cmbTestset->addItem("text/math: brace3 test", "text: \\left\\langle r^{123}\\right\\rangle -- math: $\\left\\langle r^{123}\\right\\rangle$");
ui->cmbTestset->addItem("text/math: brace4 test", "text: \\left\\langle\\left\\langle\\left\\langle r^{123}\\right\\rangle\\right\\rangle\\right\\rangle -- math: $\\left\\langle\\left\\langle\\left\\langle r^{123}\\right\\rangle\\right\\rangle\\right\\rangle$");
ui->cmbTestset->addItem("text/math: brace5 test: ( )", "text: \\left(\\left(\\left( r^{123}\\right)\\right)\\right) -- math: $\\left(\\left(\\left( r^{123}\\right)\\right)\\right)$");
ui->cmbTestset->addItem("text/math: brace6 test: [ ]", "text: \\left[\\left[\\left[ r^{123}\\right]\\right]\\right] -- math: $\\left[\\left[\\left[ r^{123}\\right]\\right]\\right]$");
ui->cmbTestset->addItem("text/math: brace7 test: { }", "text: \\left\\{\\left\\{\\left\\{ r^{123}\\right\\}\\right\\}\\right\\} -- math: $\\left\\{\\left\\{\\left\\{ r^{123}\\right\\}\\right\\}\\right\\}$");
ui->cmbTestset->addItem("text/math: brace8 test: || ||", "text: \\left\\|\\left\\|\\left\\| r^{123}\\right\\|\\right\\|\\right\\| -- math: $\\left\\|\\left\\|\\left\\| r^{123}\\right\\|\\right\\|\\right\\|$");
ui->cmbTestset->addItem("text/math: brace9 test: | |", "text: \\left|\\left|\\left| r^{123}\\right|\\right|\\right| -- math: $\\left|\\left|\\left| r^{123}\\right|\\right|\\right|$");
auto fAddBraceTest=[](const QString& open, const QString& close) {
QString res= "\\left"+open+"\\left"+open+"\\left"+open+" r^{123}\\right"+close+"\\right"+close+"\\right"+close;
res += "\\left"+open+"\\left"+open+"\\left"+open+" r_{123}\\right"+close+"\\right"+close+"\\right"+close;
res += "\\left"+open+"\\left"+open+"\\left"+open+" r_{123}^{123}\\right"+close+"\\right"+close+"\\right"+close;
return res;
};
ui->cmbTestset->addItem("text/math: brace5 test: ( )", "text: "+fAddBraceTest("(",")")+" -- math: $"+fAddBraceTest("(",")")+"$");
ui->cmbTestset->addItem("text/math: brace6 test: [ ]", "text: "+fAddBraceTest("[","]")+" -- math: $"+fAddBraceTest("[","]")+"$");
ui->cmbTestset->addItem("text/math: brace7 test: { }", "text: "+fAddBraceTest("\\{","\\}")+" -- math: $"+fAddBraceTest("\\{","\\}")+"$");
ui->cmbTestset->addItem("text/math: brace8 test: || ||", "text: "+fAddBraceTest("\\|","\\|")+" -- math: $"+fAddBraceTest("\\|","\\|")+"$");
ui->cmbTestset->addItem("text/math: brace9 test: | |", "text: "+fAddBraceTest("|","|")+" -- math: $"+fAddBraceTest("|","|")+"$");
ui->cmbTestset->addItem("text/math: brace10 test", "text: \\left\\{\\left[\\left( r^{123}\\right)\\right]\\right\\} -- math: $\\left\\{\\left[\\left( r^{123}\\right)\\right]\\right\\}$");
ui->cmbTestset->addItem("text/math: brace11 test: floor", "text: \\left\\lfloor\\left\\lfloor\\left\\lfloor r^{123}\\right\\rfloor\\right\\rfloor\\right\\rfloor -- math: $\\left\\lfloor\\left\\lfloor\\left\\lfloor r^{123}\\right\\rfloor\\right\\rfloor\\right\\rfloor$");
ui->cmbTestset->addItem("text/math: brace12 test: ceil", "text: \\left\\lceil\\left\\lceil\\left\\lceil r^{123}\\right\\rceil\\right\\rceil\\right\\rceil -- math: $\\left\\lceil\\left\\lceil\\left\\lceil r^{123}\\right\\rceil\\right\\rceil\\right\\rceil$");
@ -349,7 +355,7 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
name=QString("MTsqrtNode: deg=%1").arg(sqrtN->getDegree());
if (sqrtN->getChild()) ti->addChild(createTree(sqrtN->getChild(), ti));
} else if (braceN) {
name=QString("MTbraceNode: l='%1', r='%2', showR=%3").arg(braceN->getOpenbrace()).arg(braceN->getClosebrace()).arg(braceN->getShowRightBrace());
name=QString("MTbraceNode: l[showL=%3]='%1', r[showR=%4]='%2'").arg(braceN->getOpenbrace()).arg(braceN->getClosebrace()).arg(braceN->getShowOpeningBrace()).arg(braceN->getShowClosingBrace());
if (braceN->getChild()) ti->addChild(createTree(braceN->getChild(), ti));
} else if (superN) {
name=QString("MTsuperscriptNode");

View File

@ -81,6 +81,9 @@ JKQTMathText::JKQTMathText(QObject* parent):
expensiveRendering=true;
blackboardSimulated=true;
showLeftBrace=true;
showRightBrace=true;
static QString serifFont="serif";
static QString sansFont="sans";
@ -1157,6 +1160,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
if (currentTokenName.size()>0) {
if (QString(currentTokenName[0])==quitOnClosingBrace || quitOnClosingBrace=="any" || QString(currentTokenName[0])==".") {
//std::cout<<"found \\right '"<<currentTokenName.toStdString()<<"'\n";
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
//if (!showRightBrace) std::cout<<"don't show right brace '"<<quitOnClosingBrace.toStdString()<<"' !!!\n";
if (quitOnClosingBrace!="any") currentTokenName=currentTokenName.right(currentTokenName.size()-1);
@ -1167,26 +1171,32 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
}
} else if (currentToken==MTTinstruction) {
if (quitOnClosingBrace=="~" && (currentTokenName=="rceil" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace=="}" && (currentTokenName=="}" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace=="_" && (currentTokenName=="rfloor" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace=="#" && (currentTokenName=="|" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace==">" && (currentTokenName=="rangle" || QString(currentTokenName[0])==".")) {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
} else if (quitOnClosingBrace=="any") {
showLeftBrace=true;
showRightBrace=(QString(currentTokenName[0])!=".");
//currentTokenName=currentTokenName.right(currentTokenName.size()-1);
break;
@ -1199,51 +1209,52 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, const QString& quitOn
if (currentTokenName.size()>0) {
if (currentTokenName[0]=='(') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1); // we already used the first character from the text token!
nl->addNode(new JKQTMathTextBraceNode(this, "(", ")", parseLatexString(currentTokenName.size()<=0, ")"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "(", ")", parseLatexString(currentTokenName.size()<=0, ")"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='[') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "[", "]", parseLatexString(currentTokenName.size()<=0, "]"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "[", "]", parseLatexString(currentTokenName.size()<=0, "]"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='{') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "{", "}", parseLatexString(currentTokenName.size()<=0, "}"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "{", "}", parseLatexString(currentTokenName.size()<=0, "}"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='<') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "<", ">", parseLatexString(currentTokenName.size()<=0, ">"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "<", ">", parseLatexString(currentTokenName.size()<=0, ">"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='|') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "|", "|", parseLatexString(currentTokenName.size()<=0, "|"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "|", "|", parseLatexString(currentTokenName.size()<=0, "|"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='~') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "~", "~", parseLatexString(currentTokenName.size()<=0, "~"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "~", "~", parseLatexString(currentTokenName.size()<=0, "~"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='_') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "_", "_", parseLatexString(currentTokenName.size()<=0, "_"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "_", "_", parseLatexString(currentTokenName.size()<=0, "_"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='#') {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "#", "#", parseLatexString(currentTokenName.size()<=0, "#"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "#", "#", parseLatexString(currentTokenName.size()<=0, "#"), showLeftBrace, showRightBrace));
} else if (currentTokenName[0]=='.') {
showLeftBrace=false;
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
JKQTMathTextNode* cn=parseLatexString(currentTokenName.size()<=0, "any");
nl->addNode(new JKQTMathTextBraceNode(this, ".", currentTokenName, cn, showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, ".", currentTokenName, cn, showLeftBrace, showRightBrace));
} else {
getNew=false;
}
}
} else if (currentToken==MTTinstruction && currentTokenName=="langle") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "<", ">", parseLatexString(true, ">"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "<", ">", parseLatexString(true, ">"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName=="{") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "{", "}", parseLatexString(currentTokenName.size()<=0, "}"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "{", "}", parseLatexString(currentTokenName.size()<=0, "}"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName=="lfloor") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "_", "_", parseLatexString(true, "_"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "_", "_", parseLatexString(true, "_"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName=="lceil") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "~", "~", parseLatexString(true, "~"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "~", "~", parseLatexString(true, "~"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName=="|") {
currentTokenName=currentTokenName.right(currentTokenName.size()-1);
nl->addNode(new JKQTMathTextBraceNode(this, "#", "#", parseLatexString(currentTokenName.size()<=0, "#"), showRightBrace));
nl->addNode(new JKQTMathTextBraceNode(this, "#", "#", parseLatexString(currentTokenName.size()<=0, "#"), showLeftBrace, showRightBrace));
} else if (currentToken==MTTinstruction && currentTokenName==quitOnClosingBrace) {
break;
}

View File

@ -575,6 +575,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
QStringList error_list;
/** \brief used by the parser. This is used to implement brace pairs with \\right. */
bool showRightBrace;
/** \brief used by the parser. This is used to implement brace pairs with \\left. */
bool showLeftBrace;
/** \brief the result of parsing the last string supplied to the object via parse() */
JKQTMathTextNode* parsedNode;

View File

@ -290,18 +290,24 @@ JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextDecorationToString(JKQTMathTextDecor
/** \brief create a QPainterPath for drawing horizontal braces
* \ingroup jkqtmathtext
*
* \image html mathparser/JKQTMathTextMakeHBracePath.png
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeHBracePath(double x, double ybrace, double width, double bw, double cubicshrink=0.5, double cubiccontrolfac=0.3);
/** \brief create a QPainterPath for drawing horizontal arrows
* \ingroup jkqtmathtext
*
* \image html mathparser/JKQTMathTextMakeArrow.png
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeArrow(double x, double y, double width, double arrowW, bool left=false, bool right=true);
/** \brief create a QPainterPath for drawing horizontal double arrows
* \ingroup jkqtmathtext
*
* \image html mathparser/JKQTMathTextMakeDArrow.png
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeDArrow(double x, double y, double width, double arrowW, bool left=false, bool right=true);
@ -317,6 +323,7 @@ struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTBRData {
bool operator==(const JKQTMathTextTBRData& other) const;
};
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTBRDataH {
explicit JKQTMathTextTBRDataH(const QFont& f, const QString& text, QPaintDevice *pd);
QString text;

View File

@ -36,34 +36,53 @@
JKQTMathTextBraceNode::JKQTMathTextBraceNode(JKQTMathText* _parent, const QString& openbrace, const QString& closebrace, JKQTMathTextNode* child, bool showRightBrace):
JKQTMathTextBraceNode::JKQTMathTextBraceNode(JKQTMathText* _parent, const QString& openbrace, const QString& closebrace, JKQTMathTextNode* child, bool showOpeningBrace, bool showClosingBrace):
JKQTMathTextSingleChildNode(child, _parent)
{
this->openbrace=openbrace;
this->closebrace=closebrace;
this->showRightBrace=showRightBrace;
this->showClosingBrace=showClosingBrace;
this->showOpeningBrace=showOpeningBrace;
}
JKQTMathTextBraceNode::~JKQTMathTextBraceNode() {
}
void JKQTMathTextBraceNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
void JKQTMathTextBraceNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize) {
double braceWidth=0, braceHeight=0;
getSizeInternalAndBrace(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos, braceWidth, braceHeight, prevNodeSize);
}
void JKQTMathTextBraceNode::getSizeInternalAndBrace(QPainter &painter, JKQTMathTextEnvironment currentEv, double &width, double &baselineHeight, double &overallHeight, double &strikeoutPos, double &bracewidth, double &braceheight, const JKQTMathTextNodeSize */*prevNodeSize*/)
{
const JKQTMathTextEnvironment ev=currentEv;
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
double bracewidth=0, braceheight=0;
getBraceWidth(painter, ev, baselineHeight, overallHeight, bracewidth, braceheight);
const double cAscentAboveStrike=baselineHeight-strikeoutPos;
const double cDescentBelowStrike=overallHeight-baselineHeight+strikeoutPos;
//qDebug()<<"getSizeInternalAndBrace(): showOpeningBrace="<<showOpeningBrace<<", openbrace="<<openbrace<<", showClosingBrace="<<showClosingBrace<<", closebrace="<<closebrace;
//qDebug()<<"getSizeInternalAndBrace(): child: baselineHeight="<<baselineHeight<<", strikeoutPos="<<strikeoutPos<<", overallHeight="<<overallHeight;
//qDebug()<<"getSizeInternalAndBrace(): child: cAscentAboveStrike="<<cAscentAboveStrike<<", cDescentBelowStrike="<<cDescentBelowStrike;
const double heightAboveBelowStrike=qMax(cAscentAboveStrike, cDescentBelowStrike);
baselineHeight=strikeoutPos+heightAboveBelowStrike*parentMathText->getBraceFactor();
overallHeight=2.0*heightAboveBelowStrike*parentMathText->getBraceFactor(); //fm.height();
//qDebug()<<"getSizeInternalAndBrace(): heightAboveBelowStrike="<<heightAboveBelowStrike<<", baselineHeight="<<baselineHeight<<", overallHeight="<<overallHeight;
bracewidth=0;
braceheight=0;
getBraceSize(painter, ev, baselineHeight, overallHeight, bracewidth, braceheight);
bracewidth=bracewidth/parentMathText->getBraceShrinkFactor();
baselineHeight=/*qMin(baselineHeight, braceheight)*/ baselineHeight*parentMathText->getBraceFactor();
overallHeight=qMax(overallHeight, braceheight)*parentMathText->getBraceFactor(); //fm.height();
width=width+bracewidth*2.0;
if (showOpeningBrace) width+=bracewidth;
if (showClosingBrace) width+=bracewidth;
}
double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
@ -71,163 +90,166 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
doDrawBoxes(painter, x, y, currentEv);
JKQTMathTextEnvironment ev=currentEv;
double width=0;
double baselineHeight=0;
double overallHeight=0, strikeoutPos=0;
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
double nodeWidth=0;
double nodeBaselineHeight=0;
double nodeOverallHeight=0, nodeStrikeoutPos=0;
double bracewidth=0, braceheight=0;
getBraceWidth(painter, ev, baselineHeight, overallHeight, bracewidth, braceheight);
getSizeInternalAndBrace(painter, currentEv, nodeWidth, nodeBaselineHeight, nodeOverallHeight, nodeStrikeoutPos, bracewidth, braceheight);
double cWidth=0;
double cBaselineHeight=0;
double cOverallHeight=0, cstrikeoutPos=0;
getSize(painter, currentEv, cWidth, cBaselineHeight, cOverallHeight, cstrikeoutPos);
const double lw=qMax(0.25,ceil(currentEv.fontSize/16.0));//fm.lineWidth();
double xnew=x+lw;
double xnew=x;
const QPen pold=painter.pen();
QPen p=pold;
p.setWidthF(lw);
p.setColor(currentEv.color);
painter.setPen(p);
double brace_fraction=0.85;
if (openbrace=="(") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+brace_fraction*bracewidth, y1);
path.cubicTo(xnew, (y1+y2)/2.0+fabs(y1-y2)/6.0, xnew, (y1+y2)/2.0-fabs(y1-y2)/6.0 , xnew+brace_fraction*bracewidth, y2);
painter.drawPath(path);
} else if (openbrace=="[") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+brace_fraction*bracewidth, y1);
path.lineTo(xnew+lw/2.0, y1);
path.lineTo(xnew+lw/2.0, y2);
path.lineTo(xnew+brace_fraction*bracewidth, y2);
painter.drawPath(path);
} else if (openbrace=="{") {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,cOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.translate(xnew+bracewidth*(1.0-brace_fraction), y-cBaselineHeight+cOverallHeight/2.0);
painter.rotate(90);
painter.drawPath(path);
const double paren_fraction=0.85;
const double brace_fraction=0.65;
if (showOpeningBrace) {
const double xbrace1=xnew+lw;
const double xbrace2=qMin(xnew+paren_fraction*bracewidth, xnew+bracewidth-lw/2.0);
const double xbrace2s=qMin(xnew+brace_fraction*bracewidth, xnew+bracewidth-lw/2.0);
if (openbrace=="(") {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace2, y1);
path.cubicTo(xbrace1, (y1+y2)/2.0+fabs(y1-y2)/6.0, xbrace1, (y1+y2)/2.0-fabs(y1-y2)/6.0 , xbrace2, y2);
painter.drawPath(path);
} else if (openbrace=="[") {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace2s, y1);
path.lineTo(xbrace1, y1);
path.lineTo(xbrace1, y2);
path.lineTo(xbrace2s, y2);
painter.drawPath(path);
} else if (openbrace=="{") {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,nodeOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.translate((xbrace1+xbrace2)/2.0, y-nodeBaselineHeight+nodeOverallHeight/2.0);
painter.rotate(90);
painter.drawPath(path);
} else if (openbrace=="_") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+brace_fraction*bracewidth, y1);
path.lineTo(xnew, y1);
path.lineTo(xnew, y2);
painter.drawPath(path);
} else if (openbrace=="~") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew, y1);
path.lineTo(xnew, y2);
path.lineTo(xnew+brace_fraction*bracewidth, y2);
painter.drawPath(path);
} else if (openbrace=="|") {
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
QLineF l(xnew+brace_fraction*bracewidth, y1, xnew+brace_fraction*bracewidth, y2);
if (l.length()>0) painter.drawLine(l);
} else if (openbrace=="#" || openbrace=="||") {
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
QLineF l(xnew+brace_fraction*bracewidth, y1, xnew+brace_fraction*bracewidth, y2);
if (l.length()>0) painter.drawLine(l);
l=QLineF(xnew+brace_fraction*bracewidth-1.5*lw, y1, xnew+brace_fraction*bracewidth-1.5*lw, y2);
if (l.length()>0) painter.drawLine(l);
} else if (openbrace=="<") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+brace_fraction*bracewidth, y1);
path.lineTo(xnew, (y2+y1)/2.0);
path.lineTo(xnew+brace_fraction*bracewidth, y2);
painter.drawPath(path);
} else if (openbrace=="_") {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace2s, y1);
path.lineTo(xbrace1, y1);
path.lineTo(xbrace1, y2);
painter.drawPath(path);
} else if (openbrace=="~") {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace1, y1);
path.lineTo(xbrace1, y2);
path.lineTo(xbrace2s, y2);
painter.drawPath(path);
} else if (openbrace=="|") {
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
const QLineF l(xbrace1, y1, xbrace1, y2);
if (l.length()>0) painter.drawLine(l);
} else if (openbrace=="#" || openbrace=="||") {
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
const QLineF l(xbrace1, y1, xbrace1, y2);
if (l.length()>0) painter.drawLine(l);
const QLineF l2(xbrace1+1.5*lw, y1, xbrace1+1.5*lw, y2);
if (l2.length()>0) painter.drawLine(l2);
} else if (openbrace=="<") {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace2, y1);
path.lineTo(xbrace1, (y2+y1)/2.0);
path.lineTo(xbrace2, y2);
painter.drawPath(path);
}
xnew=xnew+bracewidth;
}
painter.setPen(pold);
xnew= child->draw(painter, xnew+bracewidth/parentMathText->getBraceShrinkFactor()-lw, y, currentEv)+lw;
xnew= child->draw(painter, xnew, y, currentEv);
if (showRightBrace) {
if (showClosingBrace) {
const double xbrace1=qMax(xnew+bracewidth-paren_fraction*bracewidth, xnew+lw/2.0);
const double xbrace1s=qMax(xnew+bracewidth-brace_fraction*bracewidth, xnew+lw/2.0);
const double xbrace2=xnew+bracewidth-lw;
painter.setPen(p);
if (closebrace==")") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+(1.0-brace_fraction)*bracewidth, y1);
path.cubicTo(xnew+bracewidth, (y1+y2)/2.0+fabs(y1-y2)/6.0, xnew+bracewidth, (y1+y2)/2.0-fabs(y1-y2)/6.0 , xnew+(1.0-brace_fraction)*bracewidth, y2);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace1, y1);
path.cubicTo(xbrace2, (y1+y2)/2.0+fabs(y1-y2)/6.0, xbrace2, (y1+y2)/2.0-fabs(y1-y2)/6.0 , xbrace1, y2);
painter.drawPath(path);
} else if (closebrace=="]") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+(1.0-brace_fraction)*bracewidth, y1);
path.lineTo(xnew+bracewidth-lw/2.0, y1);
path.lineTo(xnew+bracewidth-lw/2.0, y2);
path.lineTo(xnew+(1.0-brace_fraction)*bracewidth, y2);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace1s, y1);
path.lineTo(xbrace2, y1);
path.lineTo(xbrace2, y2);
path.lineTo(xbrace1s, y2);
painter.drawPath(path);
} else if (closebrace=="}") {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,cOverallHeight, bracewidth*brace_fraction);
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,nodeOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.translate(xnew+bracewidth*brace_fraction, y-cBaselineHeight+cOverallHeight/2.0);
painter.translate((xbrace1+xbrace2)/2.0, y-nodeBaselineHeight+nodeOverallHeight/2.0);
painter.rotate(270);
painter.drawPath(path);
} else if (closebrace=="_") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+(1.0-brace_fraction)*bracewidth, y1);
path.lineTo(xnew+bracewidth, y1);
path.lineTo(xnew+bracewidth, y2);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace1s, y1);
path.lineTo(xbrace2, y1);
path.lineTo(xbrace2, y2);
painter.drawPath(path);
} else if (closebrace=="~") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+bracewidth, y1);
path.lineTo(xnew+bracewidth, y2);
path.lineTo(xnew+(1.0-brace_fraction)*bracewidth, y2);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace2, y1);
path.lineTo(xbrace2, y2);
path.lineTo(xbrace1s, y2);
painter.drawPath(path);
} else if (closebrace=="|") {
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
QLineF l(xnew+(1.0-brace_fraction)*bracewidth, y1, xnew+(1.0-brace_fraction)*bracewidth, y2);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
const QLineF l(xbrace2, y1, xbrace2, y2);
if (l.length()>0) painter.drawLine(l);
} else if (closebrace=="#" || closebrace=="||") {
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
QLineF l(xnew+(1.0-brace_fraction)*bracewidth, y1, xnew+(1.0-brace_fraction)*bracewidth, y2);
if (l.length()>0) painter.drawLine(l);
l=QLineF(xnew+(1.0-brace_fraction)*bracewidth+1.5*lw, y1, xnew+(1.0-brace_fraction)*bracewidth+1.5*lw, y2);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
const QLineF l(xbrace2, y1, xbrace2, y2);
if (l.length()>0) painter.drawLine(l);
const QLineF l2(xbrace2-1.5*lw, y1, xbrace2-1.5*lw, y2);
if (l2.length()>0) painter.drawLine(l2);
} else if (closebrace==">") {
QPainterPath path;
const double y1=y+(cOverallHeight-cBaselineHeight);
const double y2=y-cBaselineHeight;
path.moveTo(xnew+(1.0-brace_fraction)*bracewidth, y1);
path.lineTo(xnew+bracewidth, (y2+y1)/2.0);
path.lineTo(xnew+(1.0-brace_fraction)*bracewidth, y2);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
const double y2=y-nodeBaselineHeight;
path.moveTo(xbrace1, y1);
path.lineTo(xbrace2, (y2+y1)/2.0);
path.lineTo(xbrace1, y2);
painter.drawPath(path);
}
painter.setPen(pold);
xnew=xnew+bracewidth;
}
//qDebug()<<" ==> "<<bc<<fm.boundingRect(bc).width();
return xnew+bracewidth/parentMathText->getBraceShrinkFactor()-lw;
return xnew;
}
bool JKQTMathTextBraceNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
@ -265,28 +287,18 @@ QString JKQTMathTextBraceNode::getClosebrace() const {
return this->closebrace;
}
bool JKQTMathTextBraceNode::getShowRightBrace() const {
return this->showRightBrace;
bool JKQTMathTextBraceNode::getShowClosingBrace() const {
return this->showClosingBrace;
}
void JKQTMathTextBraceNode::getBraceWidth(QPainter &/*painter*/, JKQTMathTextEnvironment ev, double /*baselineHeight*/, double overallHeight, double &bracewidth, double &braceheight) const
bool JKQTMathTextBraceNode::getShowOpeningBrace() const
{
/*QFont evf=ev.getFont(parent);
if (ev.insideMath) evf.setItalic(false);
ev.italic=false;
while (ev.fontSize<10*parent->getFontSize()) {
const QFontMetricsF fme(evf, painter.device());
if (fme.ascent()>overallHeight) break;
ev.fontSize+=0.5;
evf.setPointSizeF(ev.fontSize);
}
ev.fontSize=ev.fontSize*parent->getBraceFactor();
evf.setPointSizeF(ev.fontSize);
QFontMetricsF fm(evf, painter.device());
QString bc="_X";
bracewidth=fm.width("I")*parent->getBraceShrinkFactor();
braceheight=parent->getTBR(evf, bc, painter.device()).height();*/
double lw=qMax(0.25,ceil(ev.fontSize/12.0));
return showOpeningBrace;
}
void JKQTMathTextBraceNode::getBraceSize(QPainter &/*painter*/, JKQTMathTextEnvironment ev, double /*baselineHeight*/, double overallHeight, double &bracewidth, double &braceheight) const
{
const double lw=qMax(0.25,ceil(ev.fontSize/12.0));
braceheight=overallHeight*parentMathText->getBraceFactor();
bracewidth=0.6*pow(braceheight, 0.6);
if (openbrace=="{" || closebrace=="}") bracewidth=qMax(bracewidth, lw*3.5);

View File

@ -34,10 +34,12 @@ class JKQTMathText; // forward
/** \brief subclass representing a brace node
* \ingroup jkqtmathtext_items
*
* \image html jkqtmathtext_bracenode_geo.png
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceNode: public JKQTMathTextSingleChildNode {
public:
JKQTMathTextBraceNode(JKQTMathText* parent, const QString& openbrace, const QString& closebrace, JKQTMathTextNode* child, bool showRightBrace=true);
JKQTMathTextBraceNode(JKQTMathText* parent, const QString& openbrace, const QString& closebrace, JKQTMathTextNode* child, bool showOpeningBrace=true, bool showClosingBrace=true);
virtual ~JKQTMathTextBraceNode() override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
@ -50,18 +52,27 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceNode: public JKQTMathTextSingleCh
/** \copydoc closebrace */
QString getClosebrace() const;
/** \copydoc showRightBrace */
bool getShowRightBrace() const;
bool getShowClosingBrace() const;
/** \copydoc showOpeningBrace */
bool getShowOpeningBrace() const;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
/** \copydoc JKQTMathTextNode::getSizeInternal()
*
* \note This function internally calls getSizeInternalAndBrace() and returns part of its results.
*/
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** calculates the size of this node (also returned by getSizeInternal() ) and of the brace */
void getSizeInternalAndBrace(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& bracewidth, double&braceheight, const JKQTMathTextNodeSize* prevNodeSize=nullptr);
/**\brief opening brace */
QString openbrace;
/**\brief closing brace */
QString closebrace;
/**\brief if \c true, the right-hand-side brace is drawn */
bool showRightBrace;
/**\brief if \c true, the closing (right hand side) brace is drawn */
bool showClosingBrace;
/**\brief if \c true, the opening (left hand side) brace is drawn */
bool showOpeningBrace;
/** \brief calculate the width of the brace */
void getBraceWidth(QPainter& painter, JKQTMathTextEnvironment currentEv, double baselineHeight, double overallHeight, double& bracewidth, double& braceheight) const;
void getBraceSize(QPainter& painter, JKQTMathTextEnvironment currentEv, double baselineHeight, double overallHeight, double& bracewidth, double& braceheight) const;
};
#endif // JKQTMATHTEXTBRACENODE_H

View File

@ -84,20 +84,14 @@ void JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
child2->getSize(painter, ev2, width2, baselineHeight2, overallHeight2, strikeoutPos2);
const double maxHeight=qMax(overallHeight1,overallHeight2);
const bool _isBraceParentNearerThanFrac=isBraceParentNearerThanFrac();
const double height1OrMaxHeight=(_isBraceParentNearerThanFrac)?maxHeight:overallHeight1;
const double height2OrMaxHeight=(_isBraceParentNearerThanFrac)?maxHeight:overallHeight2;
overallHeight=0;
baselineHeight=0;
width=0;
if (mode==MTFMfrac || mode==MTFMdfrac || mode==MTFMtfrac || mode==MTFMstackrel) {
const double top_ascent=line_ascent+xheight*parentMathText->getFracShiftFactor();
const double bot_ascent=line_ascent-xheight*parentMathText->getFracShiftFactor();
// here we use maxHeight (as LaTeX does) so braces are centered around the xHieght!!!
// if there are no braces, we can use the actual height
const double newascent=height1OrMaxHeight+top_ascent;
const double newdescent=height2OrMaxHeight-bot_ascent;
const double newascent=overallHeight1+top_ascent;
const double newdescent=overallHeight2-bot_ascent;
width=qMax(width1, width2);
if (mode!=MTFMstackrel) width+=xwidth/2.0;
strikeoutPos=line_ascent;
@ -107,10 +101,8 @@ void JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
} else if (mode==MTFMstfrac || mode==MTFMsfrac) {
const double top_ascent=line_ascent;
// here we use maxHeight (as LaTeX does) so braces are centered around the xHieght!!!
// if there are no braces, we can use the actual height
const double newascent=height1OrMaxHeight+top_ascent;
const double newdescent=qMax(height2OrMaxHeight-baselineHeight2, qheight-xheight);
const double newascent=overallHeight1+top_ascent;
const double newdescent=qMax(overallHeight2-baselineHeight2, qheight-xheight);
width=width1+width2+xwidth/2.0;
strikeoutPos=line_ascent;
@ -158,19 +150,6 @@ double JKQTMathTextFracNode::getFracScalingFactor() const
return parentMathText->getFracFactor();
}
bool JKQTMathTextFracNode::isBraceParentNearerThanFrac() const
{
auto parents=getParents<JKQTMathTextNode>();
for (const auto& p: parents) {
if (p!=nullptr) {
if (dynamic_cast<const JKQTMathTextBraceNode*>(p)!=nullptr) return true;
if (dynamic_cast<const JKQTMathTextFracNode*>(p)!=nullptr) return false;
}
}
return false;
}
double JKQTMathTextFracNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
const QFont f=currentEv.getFont(parentMathText);

View File

@ -62,8 +62,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFracNode: public JKQTMathTextDualChild
int getNestingLevel(bool sameType=false) const;
/** \brief determines the scaling factor of the fraction (takes into account the nesting level) */
double getFracScalingFactor() const;
/** \brief determines whether in the list of parents a brace-node or another frac-node appears first */
bool isBraceParentNearerThanFrac() const;
};

View File

@ -98,7 +98,12 @@ void JKQTMathTextNode::doDrawBoxes(QPainter& painter, double x, double y, JKQTMa
p.setColor("lightblue");
painter.setPen(p);
if (w>0) painter.drawLine(QLineF(x, y, x+w, y));
p.setColor("pink");
p.setStyle(Qt::DashLine);
painter.setPen(p);
if (w>0) painter.drawLine(QLineF(x, y-sp, x+w, y-sp));
p.setColor("green");
p.setStyle(Qt::SolidLine);
painter.setPen(p);
painter.drawEllipse(QRectF(x-3.0,y-3.0,6.0,6.0));
p.setColor("lightgreen");

View File

@ -48,18 +48,19 @@ JKQTMathTextSuperscriptNode::~JKQTMathTextSuperscriptNode() {
void JKQTMathTextSuperscriptNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize) {
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parentMathText->getSubsuperSizeFactor();
QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
QRectF tbr=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parentMathText), "M", painter.device());
child->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
const QRectF tbr=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parentMathText), "M", painter.device());
double cstrikeoutPos=0;
child->getSize(painter, ev, width, baselineHeight, overallHeight, cstrikeoutPos);
double shift=parentMathText->getSuperShiftFactor()*tbr.height();
if (prevNodeSize!=nullptr && prevNodeSize->baselineHeight>tbr.height()) {
shift=prevNodeSize->baselineHeight-(overallHeight-baselineHeight)-shift;
}
double yshift=shift+overallHeight-baselineHeight;
baselineHeight=overallHeight=overallHeight+shift;
strikeoutPos=strikeoutPos-yshift;
if (prevNodeSize!=nullptr) strikeoutPos=prevNodeSize->strikeoutPos;
else strikeoutPos=fm.strikeOutPos();
if (currentEv.italic && prevNodeSize==nullptr) width=width+double(fm.boundingRect(' ').width())*parentMathText->getItalicCorrectionFactor();
}
@ -130,9 +131,9 @@ void JKQTMathTextSubscriptNode::getSizeInternal(QPainter& painter, JKQTMathTextE
shift=-1.0*(prevNodeSize->overallHeight-prevNodeSize->baselineHeight-shift);
}
double yshift=baselineHeight-shift;
baselineHeight=shift;
strikeoutPos=fm.strikeOutPos()+yshift;
if (prevNodeSize!=nullptr) strikeoutPos=prevNodeSize->strikeoutPos;
else strikeoutPos=fm.strikeOutPos();
if (currentEv.italic && prevNodeSize==nullptr) width=width-double(fm.boundingRect(' ').width())*parentMathText->getItalicCorrectionFactor();
}

View File

@ -1007,43 +1007,41 @@ double JKQTMathTextSymbolNode::draw(QPainter& painter, double x, double y, JKQTM
} else if (symbolName==",") { // 25% space
} else if (symbolName=="!") { // -25% space
} else if (symbolName=="longleftarrow") {
double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, false);
painter.drawPath(path);
const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
const QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, false);
} else if (symbolName=="longrightarrow"){
double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, false, true);
const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
const QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, false, true);
painter.drawPath(path);
} else if (symbolName=="Longleftarrow") {
double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, false);
painter.drawPath(path);
const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
const QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, false);
} else if (symbolName=="Longrightarrow") {
double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, false, true);
const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
const QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, false, true);
painter.drawPath(path);
} else if (symbolName=="longleftrightarrow") {
double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, true);
const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
const QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, true);
painter.drawPath(path);
} else if (symbolName=="Longleftrightarrow") {
double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, true);
const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0;
const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25;
const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0;
const QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, true);
painter.drawPath(path);
} else { // draw a box to indicate an unavailable symbol
QRectF tbr=JKQTMathTextGetTightBoundingRect(f, "M", painter.device());
const QRectF tbr=JKQTMathTextGetTightBoundingRect(f, "M", painter.device());
painter.drawRect(QRectF(x+shift,y-tbr.height(), xwi, tbr.height()*0.8));
}
painter.setPen(pold);