diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox
index 22a2446428..058713ff6d 100644
--- a/doc/dox/whatsnew.dox
+++ b/doc/dox/whatsnew.dox
@@ -37,6 +37,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
IMPROVED: typesetting of sub-/supercripts, especially for large math operators and braces
MODIFIED: brace node now calculates the extension of the child height above or below the strikeoutPos, in order to center braces around the strikeoutPos
IMPROVED: improved drawing of parantheses, square brackets ... , underbrace/overbrace
+ IMPROVED: added x-correction for sub/superscript above/below/besides integrals
remove/breaking: \v[a-zA-Z] and shorthand for \vec{a-zA-Z} was removed, implementation of \bbR,\bbC,... changed
NEW: now supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve
NEW: reworked drawing of decorations: improved appearance and positioning!
diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp
index 9f44662b3f..fa2cae730b 100644
--- a/lib/jkqtmathtext/jkqtmathtext.cpp
+++ b/lib/jkqtmathtext/jkqtmathtext.cpp
@@ -87,6 +87,8 @@ JKQTMathText::JKQTMathText(QObject* parent):
operatorsubsuper_size_factor=0.65;
operatorsubsuper_distance_factor=0.25;
operatorsubsuper_extraspace_factor=0.5;
+ intsubsuper_xcorrection_factor=0.25;
+ intsubbesides_xcorrection_xfactor=0.33;
mathoperator_width_factor=1.5;
bigmathoperator_font_factor=1.8;
@@ -230,6 +232,8 @@ void JKQTMathText::loadSettings(const QSettings& settings, const QString& group)
operatorsubsuper_distance_factor=settings.value(group+"operatorsubsuper_distance_factor", operatorsubsuper_distance_factor).toDouble();
operatorsubsuper_extraspace_factor=settings.value(group+"operatorsubsuper_extraspace_factor", operatorsubsuper_extraspace_factor).toDouble();
mathoperator_width_factor=settings.value(group+"mathoperator_width_factor", mathoperator_width_factor).toDouble();
+ intsubsuper_xcorrection_factor=settings.value(group+"intsubsuper_xcorrection_factor", intsubsuper_xcorrection_factor).toDouble();
+ intsubbesides_xcorrection_xfactor=settings.value(group+"intsubbesides_xcorrection_xfactor", intsubbesides_xcorrection_xfactor).toDouble();
if (settings.value(group+"use_stix_fonts", false).toBool()) useSTIX();
@@ -260,6 +264,8 @@ void JKQTMathText::saveSettings(QSettings& settings, const QString& group) const
settings.setValue(group+ "operatorsubsuper_distance_factor", operatorsubsuper_distance_factor);
settings.setValue(group+ "operatorsubsuper_extraspace_factor", operatorsubsuper_extraspace_factor);
settings.setValue(group+ "mathoperator_width_factor", mathoperator_width_factor);
+ settings.setValue(group+ "intsubsuper_xcorrection_factor", intsubsuper_xcorrection_factor);
+ settings.setValue(group+ "intsubbesides_xcorrection_xfactor", intsubbesides_xcorrection_xfactor);
settings.setValue(group+ "brace_y_shift_factor", brace_y_shift_factor);
settings.setValue(group+ "decoration_height_factor", decoration_height_factor);
settings.setValue(group+ "decoration_width_reduction_xfactor", decoration_width_reduction_Xfactor);
@@ -722,6 +728,26 @@ double JKQTMathText::getMathoperatorWidthFactor() const
return this->mathoperator_width_factor;
}
+void JKQTMathText::setIntSubSuperXCorrectionFactor(double __value)
+{
+ intsubsuper_xcorrection_factor=__value;
+}
+
+double JKQTMathText::getIntSubSuperXCorrectionFactor() const
+{
+ return intsubsuper_xcorrection_factor;
+}
+
+void JKQTMathText::setIntSubBesidesXCorrectionXFactor(double __value)
+{
+ intsubbesides_xcorrection_xfactor=__value;
+}
+
+double JKQTMathText::getIntSubBesidesXCorrectionXFactor() const
+{
+ return intsubbesides_xcorrection_xfactor;
+}
+
void JKQTMathText::setBigMathoperatorFontFactor(double __value)
{
bigmathoperator_font_factor=__value;
diff --git a/lib/jkqtmathtext/jkqtmathtext.h b/lib/jkqtmathtext/jkqtmathtext.h
index c5a878b9d6..9d43a31d39 100644
--- a/lib/jkqtmathtext/jkqtmathtext.h
+++ b/lib/jkqtmathtext/jkqtmathtext.h
@@ -458,6 +458,14 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
void setMathoperatorWidthFactor(double __value);
/** \copydoc mathoperator_width_factor */
double getMathoperatorWidthFactor() const;
+ /** \copydoc intsubsuper_xcorrection_factor */
+ void setIntSubSuperXCorrectionFactor(double __value);
+ /** \copydoc intsubsuper_xcorrection_factor */
+ double getIntSubSuperXCorrectionFactor() const;
+ /** \copydoc intsubbesides_xcorrection_xfactor */
+ void setIntSubBesidesXCorrectionXFactor(double __value);
+ /** \copydoc intsubbesides_xcorrection_xfactor */
+ double getIntSubBesidesXCorrectionXFactor() const;
/** \copydoc bigmathoperator_font_factor */
void setBigMathoperatorFontFactor(double __value);
/** \copydoc bigmathoperator_font_factor */
@@ -592,6 +600,23 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
* \image html jkqtmathtext_subsuper_with_limits.png
*/
double operatorsubsuper_extraspace_factor;
+ /** \brief for integrals (\c \\int , \c \\oint , ...) the sub-/superscripts above/below the symbol have to be shifted a bit to the left/right to accomodate the shape of the operator symbol (i.e. some free space at the top-left and bottom-right)
+ *
+ * This factor is multiplied by the symbol width: xshift=intsubsuper_xcorrection_factor*symbolWidth
+ * Then the subscript below is placed at centerx(symbol)-xshift and the superscript at centerx(symbol)+shiftx.
+ * This is also used to correct a subset next to the symbol by shifting it to rightx(symbol)-xshift.
+ *
+ * This correction is applied to \\int, \\iint, \\iiint, \\oint, ...
+ */
+ double intsubsuper_xcorrection_factor;
+ /** \brief for integrals (\c \\int , \c \\oint , ...) the subscripts besides the symbol have to be shifted to the left a bit to the left to accomodate the shape of the operator symbol (i.e. some free space at the bottom-right)
+ *
+ * This factor is multiplied by the width of an x: xshift=intsubbesides_xcorrection_xfactor*xWidth
+ * Then the subscript besides the symbol is shifted by xshift to the left
+ *
+ * This correction is applied to \\int, \\iint, \\iiint, \\oint, ...
+ */
+ double intsubbesides_xcorrection_xfactor;
/** \brief factor, used to extend the size of an operator in math mode
*
* The next image demonstrates the effect of this property, which adds extra space
diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp
index 4fefc17369..bd0b552534 100644
--- a/lib/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp
+++ b/lib/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp
@@ -72,9 +72,13 @@ void JKQTMathTextListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
JKQTMathTextNodeSize prevNodeSize;
JKQTMathTextNodeSize* prevNodeSizePtrForSubscript=nullptr;
JKQTMathTextNodeSize* prevNodeSizePtrForSuperscript=nullptr;
+ double subSuperXCorrection=0;
+ double subBesidesXCorrection=0;
if (i>0) {
- nodes[i-1]->getSize(painter, currentEv, prevNodeSize.width, prevNodeSize.baselineHeight, prevNodeSize.overallHeight, prevNodeSize.strikeoutPos);
+ JKQTMathTextSymbolNode* symbN=dynamic_cast(nodes[i-1]);
+ if (symbN) symbN->getSymbolSize(painter, currentEv, prevNodeSize.width, prevNodeSize.baselineHeight, prevNodeSize.overallHeight, prevNodeSize.strikeoutPos, subSuperXCorrection, subBesidesXCorrection);
+ else nodes[i-1]->getSize(painter, currentEv, prevNodeSize.width, prevNodeSize.baselineHeight, prevNodeSize.overallHeight, prevNodeSize.strikeoutPos);
const double prevAscent=prevNodeSize.baselineHeight;
const double prevDescent=prevNodeSize.overallHeight-prevNodeSize.baselineHeight;
const bool shouldUseSpecialSubscriptMode=prevAscent>=subsuperSpecialModeAscent;
@@ -117,7 +121,7 @@ void JKQTMathTextListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
overallHeight=baselineHeight+oh-bh;
strikeoutPos=sp;
}
- xnew+=qMax(w1+spaceWidth, w2);
+ xnew+=qMax(w1+spaceWidth, w2+subBesidesXCorrection);
doDraw=false;
//qDebug()<<"### super+sub";
@@ -150,13 +154,28 @@ void JKQTMathTextListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
overallHeight=baselineHeight+oh-bh;
strikeoutPos=sp;
}
- xnew+=qMax(w1, w2+spaceWidth);
+ xnew+=qMax(w1+subBesidesXCorrection, w2+spaceWidth);
doDraw=false;
//qDebug()<<"### sub+super";
//qDebug()<<"### subsupop: sub+super1 overallHeight="<getOperatorsubsuperSizeFactor();
double w1=0, wsub=0, wsup=0;
double oh1=0, ohsub=0, ohsup=0;
@@ -187,18 +207,18 @@ void JKQTMathTextListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
//qDebug()<<"sub_super: node: "<getTypeName()<<" w2="<getTypeName()<<" w3="<draw(painter, xnew, ynew, currentEv, prevNodeSizePtrForSubscript);
+ double xnew2=nodes[i]->draw(painter, xnew-subSuperXCorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
//i++;
xnew=qMax(xnew1, xnew2);
doDraw=false;
@@ -341,7 +387,7 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
if (dynamic_cast(nodes[i+1])) { // is this subscript?
//painter.setPen(QPen("red"));
//painter.drawEllipse(xnew-4,ynew+shift-(ccOverallHeight-ccBaselineHeight)-4,8,8);
- double xnew1=nodes[i]->draw(painter, xnew, ynew, currentEv, prevNodeSizePtrForSubscript);
+ double xnew1=nodes[i]->draw(painter, xnew-subSuperXCorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
i++;
//painter.setPen(QPen("magenta"));
//painter.drawEllipse(xnew-4,ynew-4,8,8);
@@ -350,6 +396,9 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
xnew=qMax(xnew1, xnew2);
doDraw=false;
}
+ } else {
+ xnew=nodes[i]->draw(painter, xnew-subBesidesXCorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
+ doDraw=false;
}
} else {
@@ -375,7 +424,14 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
double w1=0, wsub=0, wsup=0;
double oh1=0, ohsub=0, ohsup=0;
double bh1=0, bhsub=0, bhsup=0, spsub, spsup, sp;
- nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
+ JKQTMathTextSymbolNode* symbN=dynamic_cast(nodes[i]);
+ if (symbN) {
+ symbN->getSymbolSize(painter, currentEv, w1, bh1, oh1, sp, subSuperXCorrection, subBesidesXCorrection);
+ } else {
+ nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
+ }
+
+
subn->getChild()->getSize(painter, ev, wsub, bhsub, ohsub, spsub);
supn->getChild()->getSize(painter, ev, wsup, bhsup, ohsup, spsup);
const double descent1=oh1-bh1;
@@ -387,10 +443,10 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
const double xn1=nodes[i]->draw(painter, xnew+(neww-w1)/2.0, ynew, currentEv);
i++;
//double xnew2=
- const double xnsub=subn->getChild()->draw(painter, xnew+(neww-wsub)/2.0, ynew+bhsub+descent1+subsupershift, ev);
+ const double xnsub=subn->getChild()->draw(painter, xnew+(neww-wsub)/2.0-subSuperXCorrection, ynew+bhsub+descent1+subsupershift, ev);
i++;
//double xnew3=
- const double xnsup=supn->getChild()->draw(painter, xnew+(neww-wsup)/2.0, ynew-bh1-descent3-subsupershift, ev);
+ const double xnsup=supn->getChild()->draw(painter, xnew+(neww-wsup)/2.0+subSuperXCorrection, ynew-bh1-descent3-subsupershift, ev);
doDraw=false;
xnew=qMax(qMax(xn1, xnsub), xnsup)+subsuperextrawidth/2.0;
} else if (subn) { // is this subscript and no following superscript?
@@ -399,7 +455,12 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
double w1=0, wsub=0;
double oh1=0, ohsub=0;
double bh1=0, bhsub=0, sp=0, spsub=0;
- nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
+ JKQTMathTextSymbolNode* symbN=dynamic_cast(nodes[i]);
+ if (symbN) {
+ symbN->getSymbolSize(painter, currentEv, w1, bh1, oh1, sp, subSuperXCorrection, subBesidesXCorrection);
+ } else {
+ nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
+ }
subn->getChild()->getSize(painter, ev, wsub, bhsub, ohsub, spsub);
const double descent1=oh1-bh1;
//double d2=oh2-bh2;
@@ -409,7 +470,7 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
const double xn1=nodes[i]->draw(painter, xnew+(neww-w1)/2.0, ynew, currentEv);
i++;
//double xnew2=
- const double xnsub=subn->getChild()->draw(painter, xnew+(neww-wsub)/2.0, ynew+bhsub+descent1+subsupershift, ev)+subsupershift;
+ const double xnsub=subn->getChild()->draw(painter, xnew+(neww-wsub)/2.0-subSuperXCorrection, ynew+bhsub+descent1+subsupershift, ev)+subsupershift;
doDraw=false;
//xnew+=w;
xnew=qMax(xnsub, xn1)+subsuperextrawidth/2.0;
@@ -419,7 +480,12 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
double w1=0, wsup=0;
double oh1=0, ohsup=0;
double bh1=0, bhsup=0, sp, spsup;
- nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
+ JKQTMathTextSymbolNode* symbN=dynamic_cast(nodes[i]);
+ if (symbN) {
+ symbN->getSymbolSize(painter, currentEv, w1, bh1, oh1, sp, subSuperXCorrection, subBesidesXCorrection);
+ } else {
+ nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
+ }
supn->getChild()->getSize(painter, ev, wsup, bhsup, ohsup, spsup);
//double d1=oh1-bh1;
//double d2=oh2-bh2;
@@ -430,7 +496,7 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
const double xn1=nodes[i]->draw(painter, xnew+(neww-w1)/2.0, ynew, currentEv);
i++;
//double xnew3=
- const double xnsup=supn->getChild()->draw(painter, xnew+(neww-wsup)/2.0, ynew-bh1-descent3-subsupershift, ev);
+ const double xnsup=supn->getChild()->draw(painter, xnew+(neww-wsup)/2.0+subSuperXCorrection, ynew-bh1-descent3-subsupershift, ev);
doDraw=false;
xnew=qMax(xn1, xnsup)+subsuperextrawidth/2.0;
}
@@ -439,7 +505,7 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
if (idraw(painter, xnew, ynew, currentEv, prevNodeSizePtrForSuperscript);
- else if (nodeI_SubScript) xnew=nodes[i]->draw(painter, xnew, ynew, currentEv, prevNodeSizePtrForSubscript);
+ else if (nodeI_SubScript) xnew=nodes[i]->draw(painter, xnew-subBesidesXCorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
else xnew=nodes[i]->draw(painter, xnew, ynew, currentEv, nullptr);
}
}
diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp
index ef5534fb56..410ca67458 100644
--- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp
+++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp
@@ -891,7 +891,13 @@ JKQTMathTextSymbolNode::SymbolProps JKQTMathTextSymbolNode::getSymbolProp(const
}
-void JKQTMathTextSymbolNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
+void JKQTMathTextSymbolNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize) {
+ double dummy1, dummy2;
+ getSymbolSizeInternal(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos, dummy1, dummy2, prevNodeSize);
+}
+
+void JKQTMathTextSymbolNode::getSymbolSizeInternal(QPainter &painter, JKQTMathTextEnvironment currentEv, double &width, double &baselineHeight, double &overallHeight, double &strikeoutPos, double &subSuperXCorrection, double &subBesidesXCorrection, const JKQTMathTextNodeSize *prevNodeSize)
+{
QFont f=currentEv.getFont(parentMathText);
auto props=getSymbolProp(symbolName, currentEv);
f.setFamily(props.font);
@@ -942,6 +948,11 @@ void JKQTMathTextSymbolNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvi
if (props.extendWidthInMathmode && currentEv.insideMath) width=width*parentMathText->getMathoperatorWidthFactor();
+ static QSet intCorrectionSymbolNames=QSet()<<"int"<<"iint"<<"iiint"<<"oint"<<"oiint"<<"oiiint";
+ if (intCorrectionSymbolNames.contains(symbolName)) {
+ subSuperXCorrection=parentMathText->getIntSubSuperXCorrectionFactor()*tbr.width();
+ subBesidesXCorrection=parentMathText->getIntSubBesidesXCorrectionXFactor()*JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width();
+ }
}
double JKQTMathTextSymbolNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
@@ -1316,3 +1327,16 @@ bool JKQTMathTextSymbolNode::getAddWhitespace() const
return addWhitespace;
}
+void JKQTMathTextSymbolNode::getSymbolSize(QPainter &painter, JKQTMathTextEnvironment currentEv, double &width, double &baselineHeight, double &overallHeight, double &strikeoutPos, double &subSuperXCorrection, double &subBesidesXCorrection, const JKQTMathTextNodeSize *prevNodeSize)
+{
+ double w=width, b=baselineHeight, o=overallHeight, s=strikeoutPos;
+ getSymbolSizeInternal(painter, currentEv, w, b, o, s, subSuperXCorrection, subBesidesXCorrection, prevNodeSize);
+
+ if (w<1e5) width=w;
+ if (b<1e5) baselineHeight=b;
+ if (o<1e5) overallHeight=o;
+ if (s<1e5) strikeoutPos=s;
+
+}
+
+
diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h
index c5fbdf085a..c564a7dcfa 100644
--- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h
+++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h
@@ -51,9 +51,25 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
QString getSymbolfontName() const;
/** \copydoc addWhitespace */
bool getAddWhitespace() const;
+ /** \brief determine the size of the node, calls getSizeInternal() implementation of the actual type \see getSizeInternal()
+ *
+ * \param painter painter to use for determining the size
+ * \param currentEv current environment object
+ * \param[out] width width of the block/node
+ * \param[out] baselineHeight distance from the bottom of the block/node-box to the baseline
+ * \param[out] overallHeight overall height (bottom to top) of the node, the ascent is \c overallHeight-baselineHeight
+ * \param[out] strikeoutPos position of the strikeout-line
+ * \param[out] subSuperXCorrection x-correction as described for JKQTMathParser::intsubsuper_xcorrection_factor for placing sub-/superscript below/above the symbol
+ * \param[out] subBesidesXCorrection x-correction as described for JKQTMathParser::intsubbesides_xcorrection_xfactor for placing sub-/superscript below/above the symbol
+ * \param[in] prevNodeSize optional parameter, describing the size of the previous node (on the left). This may be used for layout of some nodes (e.g. sub/super to move correctly next to large parantheses ...)
+ *
+ */
+ void getSymbolSize(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& subSuperXCorrection, double& subBesidesXCorrection, const JKQTMathTextNodeSize* prevNodeSize=nullptr);
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
+ /** \copydoc JKQTMathTextNode::getSizeInternal() */
+ virtual void getSymbolSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& subSuperXCorrection, double& subBesidesXCorrection, const JKQTMathTextNodeSize* prevNodeSize=nullptr) ;
/** \brief this string will be sent to the drawText method with properly set fonts */
QString symbolName;