JKQTMathText: improved placement of sub-/superscript nodes by using JKQTMathtextNodeSize::baselineXCorrection to shift subscript to the left for e.g. preceding italic text or symbols that require such a shift

JKQTMathText: moved sub-/superscripts placed below/above a bit further apart from the central symbol/node
This commit is contained in:
jkriege2 2022-08-17 22:56:57 +02:00
parent bbbd0ce11a
commit dde8deb56f
51 changed files with 77 additions and 75 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -58,7 +58,7 @@ jkqtmathtext_doc_subsuper_italiccorrection.png
sub-/superscript:\\
\begin{tabular}{c|c}
italic-correction & no correction\\\hdashline
$x_\textcolor{blue}{\leftarrow}^\textcolor{red}{0}$ & $\mathrm{M}_\textcolor{red}{0}^\textcolor{red}{0}$
$x_\textcolor{blue}{\leftarrow}^\textcolor{red}{0}$\ \ \ $\alpha_\textcolor{blue}{\leftarrow}^\textcolor{red}{0}$\ \ \ $\nabla_\textcolor{blue}{\leftarrow}^\textcolor{red}{0}$ & $\mathrm{M}_\textcolor{red}{0}^\textcolor{red}{0}$\ \ \ $\upalpha_\textcolor{red}{0}^\textcolor{red}{0}$
\end{tabular}
---
jkqtmathtext_doc_subsuper_italiccorrection_boxes.png
@ -66,5 +66,5 @@ jkqtmathtext_doc_subsuper_italiccorrection_boxes.png
sub-/superscript:\\
\begin{tabular}{c|c}
italic-correction & no correction\\\hdashline
$x_\textcolor{blue}{\leftarrow}^\textcolor{red}{0}$ & $\mathrm{M}_\textcolor{red}{0}^\textcolor{red}{0}$
$x_\textcolor{blue}{\leftarrow}^\textcolor{red}{0}$\ \ \ $\alpha_\textcolor{blue}{\leftarrow}^\textcolor{red}{0}$\ \ \ $\nabla_\textcolor{blue}{\leftarrow}^\textcolor{red}{0}$ & $\mathrm{M}_\textcolor{red}{0}^\textcolor{red}{0}$\ \ \ $\upalpha_\textcolor{red}{0}^\textcolor{red}{0}$
\end{tabular}

View File

@ -63,7 +63,6 @@ JKQTMathText::JKQTMathText(QObject* parent):
fontSize=10;
fontSizeUnits=JKQTMathTextEnvironment::POINTS;
fontColor=QColor("black");
italic_correction_factor=0.4;
brace_factor=1.04;
brace_y_shift_factor=0.7;//-1;
@ -87,7 +86,7 @@ JKQTMathText::JKQTMathText(QObject* parent):
decoration_separation_factor=0.1;
operatorsubsuper_size_factor=0.65;
operatorsubsuper_distance_factor=0.25;
operatorsubsuper_distance_factor=0.35;
operatorsubsuper_extraspace_factor=0.5;
intsubsuper_xcorrection_factor=0.25;
intsubbesides_xcorrection_xfactor=0.33;
@ -206,7 +205,6 @@ void JKQTMathText::loadSettings(const QSettings& settings, const QString& group)
brace_factor=settings.value(group+"brace_factor", brace_factor).toDouble();
subsuper_size_factor=settings.value(group+"subsuper_size_factor", subsuper_size_factor).toDouble();
subsuper_mode_selection_by_size_factor=settings.value(group+"subsuper_mode_selection_by_size_factor", subsuper_mode_selection_by_size_factor).toDouble();
italic_correction_factor=settings.value(group+"italic_correction_factor", italic_correction_factor).toDouble();
super_shift_factor=settings.value(group+"super_shift_factor", super_shift_factor).toDouble();
sub_shift_factor=settings.value(group+"sub_shift_factor", sub_shift_factor).toDouble();
special_super_shift_factor=settings.value(group+"special_super_shift_factor", special_super_shift_factor).toDouble();
@ -254,7 +252,6 @@ void JKQTMathText::saveSettings(QSettings& settings, const QString& group) const
settings.setValue(group+ "brace_factor", brace_factor);
settings.setValue(group+ "subsuper_size_factor", subsuper_size_factor);
settings.setValue(group+ "subsuper_mode_selection_by_size_factor", subsuper_mode_selection_by_size_factor);
settings.setValue(group+ "italic_correction_factor", italic_correction_factor);
settings.setValue(group+ "sub_shift_factor", sub_shift_factor);
settings.setValue(group+ "super_shift_factor", super_shift_factor);
settings.setValue(group+ "special_sub_shift_factor", special_sub_shift_factor);
@ -711,16 +708,6 @@ double JKQTMathText::getSubsuperModeSelectionBySizeFactor() const
return subsuper_mode_selection_by_size_factor;
}
void JKQTMathText::setItalicCorrectionFactor(double __value)
{
this->italic_correction_factor = __value;
}
double JKQTMathText::getItalicCorrectionFactor() const
{
return this->italic_correction_factor;
}
void JKQTMathText::setOperatorsubsuperSizeFactor(double __value)
{
this->operatorsubsuper_size_factor = __value;

View File

@ -512,10 +512,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
void setSubsuperModeSelectionBySizeFactor(double __value);
/** \copydoc subsuper_mode_selection_by_size_factor */
double getSubsuperModeSelectionBySizeFactor() const;
/** \copydoc italic_correction_factor */
void setItalicCorrectionFactor(double __value);
/** \copydoc italic_correction_factor */
double getItalicCorrectionFactor() const;
/** \copydoc operatorsubsuper_size_factor */
void setOperatorsubsuperSizeFactor(double __value);
/** \copydoc operatorsubsuper_size_factor */
@ -721,14 +717,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
* by \c \\sum,\\int,... .
*/
double subsuper_mode_selection_by_size_factor;
/** \brief fraction of a whitespace by which to shift a sub-/superscript left/right when the previous text is italic
*
* \image html jkqtmathtext/jkqtmathtext_doc_subsuper_italiccorrection.png
*
* \image html jkqtmathtext/jkqtmathtext_doc_subsuper_italiccorrection_boxes.png
*
*/
double italic_correction_factor;
/** \brief like subsuper_size_factor, but for operators (\c \\sum , \c \\int , ...) where the text is placed above/below the symbol */
double operatorsubsuper_size_factor;
/** \brief for operators (\c \\sum , \c \\int , ...) where the text is placed above/below the symbol, this is the distance between the operator symbol and the sub-/super-text if multiplied by xHeight

View File

@ -596,7 +596,9 @@ JKQTMathTextNodeSize::JKQTMathTextNodeSize():
width(0),
baselineHeight(0),
overallHeight(0),
strikeoutPos()
strikeoutPos(),
baselineXCorrection(0),
topXCorrection(0)
{
}

View File

@ -339,6 +339,15 @@ struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNodeSize {
double overallHeight;
/** \brief strikeoutPos of whole block */
double strikeoutPos;
/** \brief x-correction (<0 = move to the left) for subscripts, i.e. approximately at the height of the baseline
*
* \image html jkqtmathtext/jkqtmathtext_doc_subsuper_italiccorrection.png
*
* \image html jkqtmathtext/jkqtmathtext_doc_subsuper_italiccorrection_boxes.png
*/
double baselineXCorrection;
/** \brief x-correction (>0 = move to the right) for superscripts, i.e. approximately at the top of the box */
double topXCorrection;
/** \brief calculate the descent */
inline double getDescent() const { return overallHeight-baselineHeight; }
/** \brief calculate the overall size in floating-point precision */

View File

@ -164,6 +164,7 @@ JKQTMathTextNodeSize JKQTMathTextDecoratedNode::getSizeInternal(QPainter& painte
s.baselineHeight=ascent;
s.strikeoutPos=cs.strikeoutPos;
s.width=std::max<double>(deco_miniwidth,cs.width);
s.baselineXCorrection=cs.baselineXCorrection;
return s;
}

View File

@ -54,12 +54,14 @@ QString JKQTMathTextHorizontalListNode::getTypeName() const
JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv) const {
JKQTMathTextNodeSize outSize;
const QFontMetricsF fm(currentEv.getFont(parentMathText));
const QFont f=currentEv.getFont(parentMathText);
const QFontMetricsF fm(f);
const double subsupershift=fm.xHeight()*parentMathText->getOperatorsubsuperDistanceFactor();
const double subsuperextrawidth=fm.boundingRect('x').width()*parentMathText->getOperatorsubsuperExtraSpaceFactor();
const double subsuperSpecialModeAscent=fm.ascent()*parentMathText->getSubsuperModeSelectionBySizeFactor();
const double subsuperSpecialModeDecent=fm.descent()*parentMathText->getSubsuperModeSelectionBySizeFactor();
const double spaceWidth=fm.boundingRect(' ').width();
//QRectF tbr=parent->getTightBoundingRect(currentEv.getFont(parent), "M", painter.device());
@ -81,6 +83,7 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
if (shouldUseSpecialSubscriptMode) prevNodeSizePtrForSubscript=&prevNodeSize;
if (shouldUseSpecialSuperscriptMode) prevNodeSizePtrForSuperscript=&prevNodeSize;
}
const double subscript_xcorrection=prevNodeSize.baselineXCorrection+fm.lineWidth()*0.5;
JKQTMathTextSuperscriptNode* nodeI_SuperScript=dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i]);
JKQTMathTextSubscriptNode* nodeI_SubScript=dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i]);
@ -116,7 +119,7 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
outSize.overallHeight=outSize.baselineHeight+ns2.getDescent();
outSize.strikeoutPos=ns2.strikeoutPos;
}
xnew+=qMax(ns.width+spaceWidth, ns2.width+prevNodeSize.subBesidesXCorrection);
xnew+=qMax(ns.width+spaceWidth, ns2.width+subscript_xcorrection);
doDraw=false;
//qDebug()<<"### super+sub";
@ -149,7 +152,7 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
outSize.overallHeight=outSize.baselineHeight+ns2.overallHeight-ns2.baselineHeight;
outSize.strikeoutPos=ns2.strikeoutPos;
}
xnew+=qMax(ns.width+prevNodeSize.subBesidesXCorrection, ns2.width+spaceWidth);
xnew+=qMax(ns.width+subscript_xcorrection, ns2.width+spaceWidth);
doDraw=false;
@ -167,7 +170,7 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
outSize.overallHeight=outSize.baselineHeight+ns.getDescent();
outSize.strikeoutPos=ns.strikeoutPos;
}
xnew+=ns.width-prevNodeSize.subBesidesXCorrection;
xnew+=ns.width+subscript_xcorrection;
doDraw=false;
}
@ -201,7 +204,7 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
//double d1=ns.overallHeight-ns.baselineHeight;
//double d2=oh2-bh2;
//double d3=oh3-bh3;
const double neww=qMax(qMax(ns.width, sub.width+prevNodeSize.subSuperXCorrection), sup.width+prevNodeSize.subSuperXCorrection)+subsuperextrawidth;
const double neww=qMax(qMax(ns.width, sub.width+prevNodeSize.subSuperAboveBelowXCorrection), sup.width+prevNodeSize.subSuperAboveBelowXCorrection)+subsuperextrawidth;
const double newBaselineHeight=ns.baselineHeight+sup.overallHeight+subsupershift;
if (newBaselineHeight>outSize.baselineHeight) {
const double extraBaselineHeight=newBaselineHeight-outSize.baselineHeight;
@ -244,7 +247,7 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
outSize.overallHeight=outSize.overallHeight+(nodeSize.baselineHeight-outSize.baselineHeight);
outSize.baselineHeight=nodeSize.baselineHeight;
}
const double neww=qMax(nodeSize.width, sub.width+nodeSize.subSuperXCorrection)+subsuperextrawidth;
const double neww=qMax(nodeSize.width, sub.width+nodeSize.subSuperAboveBelowXCorrection)+subsuperextrawidth;
i++;
doDraw=false;
xnew+=neww;
@ -274,7 +277,7 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
outSize.overallHeight=outSize.baselineHeight+descent1;
}
const double neww=qMax(nodeSize.width, sup.width+nodeSize.subSuperXCorrection)+subsuperextrawidth;
const double neww=qMax(nodeSize.width, sup.width+nodeSize.subSuperAboveBelowXCorrection)+subsuperextrawidth;
i++;
doDraw=false;
xnew+=neww;
@ -300,6 +303,8 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
outSize.overallHeight=outSize.baselineHeight+cDescent;
outSize.strikeoutPos=ns.strikeoutPos;
}
outSize.baselineXCorrection=ns.baselineXCorrection;
outSize.topXCorrection=ns.topXCorrection;
//qDebug()<<"### subsupop: else overallHeight="<<overallHeight<<" baselineHeight="<<baselineHeight;
xnew+=ns.width;
@ -343,6 +348,7 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
if (shouldUseSpecialSubscriptMode) prevNodeSizePtrForSubscript=&prevNodeSize;
if (shouldUseSpecialSuperscriptMode) prevNodeSizePtrForSuperscript=&prevNodeSize;
}
const double subscript_xcorrection=prevNodeSize.baselineXCorrection+fm.lineWidth()*0.5;
JKQTMathTextSuperscriptNode* nodeI_SuperScript=dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i]);
JKQTMathTextSubscriptNode* nodeI_SubScript=dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i]);
@ -361,7 +367,7 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
i++;
//painter.setPen(QPen("magenta"));
//painter.drawEllipse(xnew-4,ynew-4,8,8);
const double xnew2=nodeISucc_SubScript->drawWithSpecialPlacement(painter, xnew-prevNodeSize.subSuperXCorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
const double xnew2=nodeISucc_SubScript->drawWithSpecialPlacement(painter, xnew+subscript_xcorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
//i++;
xnew=qMax(xnewidth, xnew2);
doDraw=false;
@ -373,7 +379,7 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
if (nodeISucc_SuperScript) { // is this subscript?
//painter.setPen(QPen("red"));
//painter.drawEllipse(xnew-4,ynew+shift-(ccOverallHeight-ccBaselineHeight)-4,8,8);
double xnewidth=nodeI_SubScript->drawWithSpecialPlacement(painter, xnew-prevNodeSize.subSuperXCorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
double xnewidth=nodeI_SubScript->drawWithSpecialPlacement(painter, xnew+subscript_xcorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
i++;
//painter.setPen(QPen("magenta"));
//painter.drawEllipse(xnew-4,ynew-4,8,8);
@ -383,7 +389,7 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
doDraw=false;
}
} else {
xnew=nodeI_SubScript->drawWithSpecialPlacement(painter, xnew-prevNodeSize.subBesidesXCorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
xnew=nodeI_SubScript->drawWithSpecialPlacement(painter, xnew+subscript_xcorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
doDraw=false;
}
} else {
@ -427,10 +433,10 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
const double xn1=nodes[i]->draw(painter, xnew+(neww-nodeSize.width)/2.0, ynew, currentEv);
i++;
//double xnew2=
const double xnsub=subn->getChild()->draw(painter, xnew+(neww-sub.width)/2.0-nodeSize.subSuperXCorrection, ynew+sub.baselineHeight+descent1+subsupershift, ev);
const double xnsub=subn->getChild()->draw(painter, xnew+(neww-sub.width)/2.0-nodeSize.subSuperAboveBelowXCorrection, ynew+sub.baselineHeight+descent1+subsupershift, ev);
i++;
//double xnew3=
const double xnsup=supn->getChild()->draw(painter, xnew+(neww-sup.width)/2.0+nodeSize.subSuperXCorrection, ynew-nodeSize.baselineHeight-descent3-subsupershift, ev);
const double xnsup=supn->getChild()->draw(painter, xnew+(neww-sup.width)/2.0+nodeSize.subSuperAboveBelowXCorrection, ynew-nodeSize.baselineHeight-descent3-subsupershift, ev);
doDraw=false;
xnew=qMax(qMax(xn1, xnsub), xnsup)+subsuperextrawidth/2.0;
} else if (subn) { // is this subscript and no following superscript?
@ -452,7 +458,7 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
const double xn1=nodes[i]->draw(painter, xnew+(neww-nodeSize.width)/2.0, ynew, currentEv);
i++;
//double xnew2=
const double xnsub=subn->getChild()->draw(painter, xnew+(neww-sub.width)/2.0-nodeSize.subSuperXCorrection, ynew+sub.baselineHeight+descent1+subsupershift, ev)+subsupershift;
const double xnsub=subn->getChild()->draw(painter, xnew+(neww-sub.width)/2.0-nodeSize.subSuperAboveBelowXCorrection, ynew+sub.baselineHeight+descent1+subsupershift, ev)+subsupershift;
doDraw=false;
//xnew+=w;
xnew=qMax(xnsub, xn1)+subsuperextrawidth/2.0;
@ -476,7 +482,7 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
const double xn1=nodes[i]->draw(painter, xnew+(neww-nodeSize.width)/2.0, ynew, currentEv);
i++;
//double xnew3=
const double xnsup=supn->getChild()->draw(painter, xnew+(neww-sup.width)/2.0+nodeSize.subSuperXCorrection, ynew-nodeSize.baselineHeight-descent3-subsupershift, ev);
const double xnsup=supn->getChild()->draw(painter, xnew+(neww-sup.width)/2.0+nodeSize.subSuperAboveBelowXCorrection, ynew-nodeSize.baselineHeight-descent3-subsupershift, ev);
doDraw=false;
xnew=qMax(xn1, xnsup)+subsuperextrawidth/2.0;
}
@ -485,7 +491,7 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
if (i<nodes.size() && doDraw) {
if (nodeI_SuperScript) xnew=nodeI_SuperScript->drawWithSpecialPlacement(painter, xnew, ynew, currentEv, prevNodeSizePtrForSuperscript);
else if (nodeI_SubScript) xnew=nodeI_SubScript->drawWithSpecialPlacement(painter, xnew-prevNodeSize.subBesidesXCorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
else if (nodeI_SubScript) xnew=nodeI_SubScript->drawWithSpecialPlacement(painter, xnew+subscript_xcorrection, ynew, currentEv, prevNodeSizePtrForSubscript);
else xnew=nodes[i]->draw(painter, xnew, ynew, currentEv);
}
}

View File

@ -36,9 +36,19 @@ class JKQTMathText; // forward
/** \brief subclass representing a list of nodes in the syntax tree, layed out horizontally
* \ingroup jkqtmathtext_items
*
* \note This type of node also implements typesetting sub-/superscript above/below the previous node (if
* JKQTMathTextNode::is() is \c true for that previus node. The drawing is done as defined in the
* following image \image html jkqtmathtext_subsuper_with_limits.png
* This type of node also implements typesetting sub-/superscript above/below the previous node (if
* JKQTMathTextNode::is() is \c true for that previus node. The drawing is done as defined in the
* following image:
* \image html jkqtmathtext_subsuper_with_limits.png
*
* In addition this node also ensures that subscripts are moved to the left for italic previous
* text or nodes that require such a shift (e.g. \c \\nabla or \c \\int ):
*
* \image html jkqtmathtext/jkqtmathtext_doc_subsuper_italiccorrection.png
*
* \image html jkqtmathtext/jkqtmathtext_doc_subsuper_italiccorrection_boxes.png
*
* This is implemented using JKQTMathTextNodeSize::baselineXCorrection .
*
* \see JKQTMathTextVerticalListNode
*/

View File

@ -64,7 +64,6 @@ JKQTMathTextNodeSize JKQTMathTextSuperscriptNode::getSizeWithSpecialPlacement(QP
s.width=cs.width;
if (prevNodeSizeForSpecialPlacement!=nullptr) s.strikeoutPos=prevNodeSizeForSpecialPlacement->strikeoutPos;
else s.strikeoutPos=fm.strikeOutPos();
if (currentEv.italic && prevNodeSizeForSpecialPlacement==nullptr) s.width=s.width+double(fm.boundingRect(' ').width())*parentMathText->getItalicCorrectionFactor();
return s;
}
@ -91,7 +90,6 @@ double JKQTMathTextSuperscriptNode::drawWithSpecialPlacement(QPainter& painter,
}
double xx=x;
if (currentEv.italic && prevNodeSizeForSpecialPlacement==nullptr) xx=xx+double(fm.boundingRect(' ').width())*parentMathText->getItalicCorrectionFactor();
return getChild()->draw(painter, xx, y-(shiftToChildBottom+childDescent), ev);//+0.5*fm.boundingRect("A").width();
}
@ -137,7 +135,6 @@ JKQTMathTextNodeSize JKQTMathTextSubscriptNode::getSizeWithSpecialPlacement(QPai
ev.fontSize=ev.fontSize*parentMathText->getSubsuperSizeFactor();
const QFontMetricsF fm(ev.getFont(parentMathText), painter.device());
//const QRectF tbr_of_letterM=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parentMathText), "M", painter.device());
const double italic_xshift=qMax(0.0,-fm.rightBearing('x'));// double(fm.boundingRect('x').width())*parentMathText->getItalicCorrectionFactor();
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
//const double childDescent=cs.overallHeight-cs.baselineHeight;
@ -156,7 +153,6 @@ JKQTMathTextNodeSize JKQTMathTextSubscriptNode::getSizeWithSpecialPlacement(QPai
if (prevNodeSizeForSpecialPlacement!=nullptr) s.strikeoutPos=prevNodeSizeForSpecialPlacement->strikeoutPos;
else s.strikeoutPos=fm.strikeOutPos();
s.width=cs.width;
if (currentEv.italic && prevNodeSizeForSpecialPlacement==nullptr) s.width=s.width-italic_xshift;
return s;
}
@ -174,7 +170,6 @@ double JKQTMathTextSubscriptNode::drawWithSpecialPlacement(QPainter& painter, do
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
double shift_to_childBaseline=cs.baselineHeight-parentMathText->getSubShiftFactor()*fm.xHeight();
const double italic_xshift=qMax(0.0,-fm.rightBearing('x'));// double(fm.boundingRect('x').width())*parentMathText->getItalicCorrectionFactor();
if (prevNodeSizeForSpecialPlacement!=nullptr) {
//qDebug()<<"oldshift="<<shift<<", prevNodeSize->overallHeight="<<prevNodeSize->overallHeight<<", prevNodeSize->baselineHeight="<<prevNodeSize->baselineHeight;
@ -187,10 +182,6 @@ double JKQTMathTextSubscriptNode::drawWithSpecialPlacement(QPainter& painter, do
//qDebug()<<"baselineHeight="<<baselineHeight<<", overallHeight="<<overallHeight<<", strikeoutPos="<<strikeoutPos;
//qDebug()<<"shift="<<shift<<", yshift="<<yshift;
double xx=x;
if (currentEv.italic && prevNodeSizeForSpecialPlacement==nullptr) {
//std::cout<<"italic_xshift="<<italic_xshift<<"\n";
xx=xx-italic_xshift;
}
return getChild()->draw(painter, xx, y+shift_to_childBaseline, ev);//+0.5*fm.boundingRect("A").width();
}

View File

@ -160,7 +160,7 @@ double JKQTMathTextSymbolNode::draw(QPainter& painter, double x, double y, JKQTM
const double xShift=(s.width-tbr.width())/2.0;
const QPointF x0(x+xShift-tbr.x(), y+yShift);
double italic_xcorrection=fabs(tbr.width()-tbrNonItalic.width());
if (fabs(italic_xcorrection)<1e-6) italic_xcorrection=double(fm.boundingRect(' ').width())*parentMathText->getItalicCorrectionFactor();
if (fabs(italic_xcorrection)<1e-6) italic_xcorrection=double(fm.boundingRect(' ').width())*0.4;
//qDebug()<<"SYMB::draw(): symbolName="<<symbolName<<" font="<<f<<" sym="<<sym<<" yShiftFactor="<<symprops.yShiftFactor;
@ -246,6 +246,7 @@ JKQTMathTextSymbolNode::NodeSize JKQTMathTextSymbolNode::getSymbolSize(QPainter
const QRectF br=getBoundingRect(fm, sym, globalFlags);
const QRectF tbrNoSymbol=JKQTMathTextGetTightBoundingRect(f, "X", painter.device());
const QRectF mintbr=JKQTMathTextGetTightBoundingRect(f, "(", painter.device());
const QRectF dottbr=JKQTMathTextGetTightBoundingRect(f, ".", painter.device());
//const double yShift=symprops.yShiftFactor*tbr.height();
if (currentEv.insideMath) {
@ -280,8 +281,14 @@ JKQTMathTextSymbolNode::NodeSize JKQTMathTextSymbolNode::getSymbolSize(QPainter
s.strikeoutPos=fm.strikeOutPos();
if (has(globalFlags, IntLikeSymbolCorrection)) {
s.subSuperXCorrection=parentMathText->getIntSubSuperXCorrectionFactor()*tbr.width();
s.subBesidesXCorrection=parentMathText->getIntSubBesidesXCorrectionXFactor()*JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width();
if (has(globalFlags, SubSuperscriptBelowAboveSymbol)) {
s.subSuperAboveBelowXCorrection=parentMathText->getIntSubSuperXCorrectionFactor()*tbr.width();
}
s.baselineXCorrection=-parentMathText->getIntSubBesidesXCorrectionXFactor()*JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width();
s.topXCorrection=dottbr.width();
}
if (has(globalFlags, SubscriptCorrection) && sym.size()>0) {
s.baselineXCorrection=fm.rightBearing(sym[sym.size()-1]);
}
return s;
@ -410,7 +417,7 @@ JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::UprightGreekLett
void JKQTMathTextSymbolNode::addGreekLetterVariants_WinSymbol_Unicode_Html(const QString &baseInstructionName, const QString &letterWinSymbol, const QString &letterUnicode, const QString &html)
{
symbols[baseInstructionName]=MathGreekLetter_WinSymbol_Unicode_Html(letterWinSymbol, letterUnicode, html);
symbols[baseInstructionName]=MathGreekLetter_WinSymbol_Unicode_Html(letterWinSymbol, letterUnicode, html).addGlobalFlags(SubscriptCorrection);
symbols["text"+baseInstructionName]=AsOutsiudeGreekLetter_WinSymbol_Unicode_Html(letterWinSymbol, letterUnicode, html);
symbols["up"+baseInstructionName]=UprightGreekLetter_WinSymbol_Unicode_Html(letterWinSymbol, letterUnicode, html);
}
@ -533,7 +540,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
{ auto s=UnicodeSymbol(QChar(0x2103)).addUprightStd("°C").addUprightHtml("&deg;C");
symbols["celsius"]=s; symbols["degC"]=s; symbols["degreeCelsius"]=s; }
symbols["ell"]=UprightSymbolUnicode(QChar(0x2113), "&ell;");
symbols["wp"]=UprightSymbolUnicode(QChar(0x2118), "&wp;");
symbols["wp"]=UprightSymbolUnicode(QChar(0x2118), "&wp;").addGlobalFlags(SubscriptCorrection);
symbols["mho"]=UprightSymbolUnicode(QChar(0x2127), "&mho;");
symbols["lozenge"]=UprightSymbolUnicode(QChar(0x25CA), "&loz;");
symbols["cent"]=SimpleTextSymbol(QChar(0xA2), "&cent;");
@ -574,7 +581,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["glqq"]=UnicodeSymbol(QChar(0x201C)).addHtml("&OpenCurlyDoubleQuote;").addStd("\"");
symbols["grq"]=UnicodeSymbol(QChar(0x2019)).addHtml("&CloseCurlyQuote;").addStd("'");
symbols["grqq"]=UnicodeSymbol(QChar(0x201D)).addHtml("&CloseCurlyDoubleQuote;").addStd("\"");
symbols["hbar"]=UprightSymbolUnicode(QChar(0x210F)).addUprightHtml("&hbar;").addStd("h", ItalicOn|DrawLeftHBar);
symbols["hbar"]=UprightSymbolUnicode(QChar(0x210F)).addUprightHtml("&hbar;").addStd("h", ItalicOn|DrawLeftHBar).addGlobalFlags(SubscriptCorrection);
symbols["hexagon"]=UprightSymbolUnicode(QChar(0x2394));
symbols["ii"] = SymbolFullProps(SymbolProps("i", Upright|BoldOff), "i", Upright|BoldOff);
symbols["infty"]=UnicodeSymbol(QChar(0x221E)).addHtml("&infin;").addWinSymbol(QChar(0xA5)).addStd("8", RotateSymbol90);
@ -662,8 +669,8 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["lb"] = NarrowMathOperatorText("lb");
symbols["ld"] = NarrowMathOperatorText("ld");
symbols["lim"] = NarrowMathOperatorText("lim").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["liminf"] = NarrowMathOperatorText("lim inf", "lim&thinsp;inf").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["limsup"] = NarrowMathOperatorText("lim sup", "lim&thinsp;sup").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["liminf"] = NarrowMathOperatorText("lim inf", "lim&thinsp;inf").addGlobalFlags(SubSuperscriptBelowAboveSymbol).addGlobalFlags(SubscriptCorrection);
symbols["limsup"] = NarrowMathOperatorText("lim sup", "lim&thinsp;sup").addGlobalFlags(SubSuperscriptBelowAboveSymbol).addGlobalFlags(SubscriptCorrection);
symbols["ln"] = NarrowMathOperatorText("ln");
symbols["log"] = NarrowMathOperatorText("log");
symbols["max"] = NarrowMathOperatorText("max");
@ -731,7 +738,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["emptyset"]=s; symbols["varnothing"]=s; }
symbols["equiv"]=MathOperatorSymbolUnicode(QChar(0x2261)).addMathOperatorHtml("&equiv;").addMathOperatorWinSymbol(QChar(0xBA));
symbols["exists"]=NarrowMathOperatorSymbolUnicode(QChar(0x2203)).addMathOperatorHtml("&exist;").addMathOperatorWinSymbol(QChar(0x24)).addStd("E", ItalicOff|BoldOff|FlipSymbolLeftRight);
symbols["forall"]=NarrowMathOperatorSymbolUnicode(QChar(0x2200)).addMathOperatorHtml("&forall;").addMathOperatorWinSymbol(QChar(0x22)).addStd("A", ItalicOff|BoldOff|FlipSymbolUpDown);
symbols["forall"]=NarrowMathOperatorSymbolUnicode(QChar(0x2200)).addMathOperatorHtml("&forall;").addMathOperatorWinSymbol(QChar(0x22)).addStd("A", ItalicOff|BoldOff|FlipSymbolUpDown).addGlobalFlags(SubscriptCorrection);
{ auto s=MathOperatorSymbolUnicode(QChar(0x2265)).addMathOperatorHtml("&GreaterEqual;").addMathOperatorWinSymbol(QChar(0xB3));
symbols["geq"]=s; symbols["ge"]=s; }
symbols["geqq"]=MathOperatorSymbolUnicode(QChar(0x2267)).addMathOperatorHtml("&GreaterFullEqual;");
@ -765,7 +772,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["mid"]=MathOperatorSymbolUnicode(QChar(0x2223)).addMathOperatorHtml("&VerticalBar;").addMathOperatorWinSymbol(QChar(0xBD)).addMathOperatorStd("|");
symbols["mp"]=MathOperatorSymbolUnicode(QChar(0x2213)).addMathOperatorHtml("&mp;").addWinSymbol(QChar(0xB1),ItalicOff|BoldOff|FlipSymbolUpDown).addStd(QChar(0xB1),ItalicOff|BoldOff|FlipSymbolUpDown);
symbols["multimap"]=MathOperatorSymbolUnicode(QChar(0x22B8)).addMathOperatorHtml("&mumap;");
symbols["nabla"]=NarrowMathOperatorSymbolUnicode(QChar(0x2207)).addMathOperatorHtml("&nabla;").addMathOperatorWinSymbol(QChar(0xD1));
symbols["nabla"]=NarrowMathOperatorSymbolUnicode(QChar(0x2207)).addMathOperatorHtml("&nabla;").addMathOperatorWinSymbol(QChar(0xD1)).addGlobalFlags(IntLikeSymbolCorrection);
symbols["ne"]=NarrowMathOperatorSymbolUnicode(QChar(0x2260)).addMathOperatorHtml("&ne;").addMathOperatorWinSymbol(QChar(0xB9));
symbols["nearrow"]=UprightSymbolUnicode(QChar(0x2197)).addUprightHtml("&UpperRightArrow;");
{ auto s=MathOperatorSymbolUnicode(QChar(0x00AC)).addMathOperatorHtml("&not;").addMathOperatorWinSymbol(QChar(0xD8));
@ -1201,24 +1208,21 @@ QPair<QFont, JKQTMathTextSymbolNode::SymbolProps> JKQTMathTextSymbolNode::Symbol
JKQTMathTextSymbolNode::NodeSize::NodeSize():
JKQTMathTextNodeSize(),
subSuperXCorrection(0.0),
subBesidesXCorrection(0.0)
subSuperAboveBelowXCorrection(0.0)
{
}
JKQTMathTextSymbolNode::NodeSize &JKQTMathTextSymbolNode::NodeSize::operator=(const JKQTMathTextNodeSize &other)
{
subSuperXCorrection=0;
subBesidesXCorrection=0;
subSuperAboveBelowXCorrection=0;
JKQTMathTextNodeSize::operator=(other);
return *this;
}
JKQTMathTextSymbolNode::NodeSize &JKQTMathTextSymbolNode::NodeSize::operator=(const NodeSize &other)
{
subSuperXCorrection=other.subSuperXCorrection;
subBesidesXCorrection=other.subBesidesXCorrection;
subSuperAboveBelowXCorrection=other.subSuperAboveBelowXCorrection;
JKQTMathTextNodeSize::operator=(other);
return *this;
}

View File

@ -71,9 +71,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
struct NodeSize : JKQTMathTextNodeSize {
NodeSize();
/** \brief x-correction as described for JKQTMathParser::intsubsuper_xcorrection_factor for placing sub-/superscript below/above the symbol, e.g. for integral signs, where the subscript is slightly shifted to the left (from center) and the superscript slightly to the right */
double subSuperXCorrection;
/** \brief x-correction as described for JKQTMathParser::intsubbesides_xcorrection_xfactor for placing sub-/superscript besides the symbol */
double subBesidesXCorrection;
double subSuperAboveBelowXCorrection;
NodeSize& operator=(const JKQTMathTextNodeSize& other);
NodeSize& operator=(const NodeSize& other);
@ -144,6 +142,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
MakeWhitespaceHalf= 1 << 2, /*!< \brief symbol uses whitespaces in its text (SymbolProps::symbol). These should be typeset as half-spaces */
IntLikeSymbolCorrection= 1 << 3, /*!< \brief symbols, like \c \\int,\\iint,... require a correction in x-direction for subsequent sub-/superscripts ... this flag marks such symbols */
SubSuperscriptBelowAboveSymbol= 1 << 4, /*!< \brief symbols, like \c \\int,\\iint,... if appearing in math-mode cause typesetting following sub-/superscripts below/above the symbol, not besides it. */
SubscriptCorrection= 1 << 5, /*!< \brief symbols, like \c \\nabla,... require a subscript correction in x-direction for subsequent subscripts ... this flag marks such symbols */
};
friend inline GlobalSymbolFlags operator~ (GlobalSymbolFlags a) { return (GlobalSymbolFlags)~static_cast<uint64_t>(a); }

View File

@ -149,12 +149,15 @@ JKQTMathTextTextNode::LayoutInfo JKQTMathTextTextNode::calcLayout(QPainter &pain
double ascent=0;
double descent=0;
for (int i=0; i<l.textpart.size(); i++) {
l.baselineXCorrection=0;
l.topXCorrection=0;
QRectF br, tbr;
switch(l.fontMode[i]) {
case FMasDefined:
case FMasDefinedOutline:
br=fm.boundingRect(l.textpart[i]);
tbr=JKQTMathTextGetTightBoundingRect(f, l.textpart[i], painter.device());
if (f.italic() && l.textpart[i].size()>0) l.baselineXCorrection=fm.rightBearing(l.textpart[i].operator[](l.textpart[i].size()-1));
break;
case FMasDefinedForceUpright:
br=fmUpright.boundingRect(l.textpart[i]);
@ -163,10 +166,12 @@ JKQTMathTextTextNode::LayoutInfo JKQTMathTextTextNode::calcLayout(QPainter &pain
case FMroman:
br=fmRoman.boundingRect(l.textpart[i]);
tbr=JKQTMathTextGetTightBoundingRect(fRoman, l.textpart[i], painter.device());
if (fRoman.italic() && l.textpart[i].size()>0) l.baselineXCorrection=fmRoman.rightBearing(l.textpart[i].operator[](l.textpart[i].size()-1));
break;
case FMfallbackSymbol:
br=fmFallbackSym.boundingRect(l.textpart[i]);
tbr=JKQTMathTextGetTightBoundingRect(fFallbackSym, l.textpart[i], painter.device());
if (fFallbackSym.italic() && l.textpart[i].size()>0) l.baselineXCorrection=fmFallbackSym.rightBearing(l.textpart[i].operator[](l.textpart[i].size()-1));
break;
}
l.textpartXPos.append(l.width);