IMPROVED: JKQTMathText: optional parameter of \sqrt is properly parsed now

This commit is contained in:
jkriege2 2022-06-28 21:59:50 +02:00
parent 6c26e250da
commit 9a7e44889f
5 changed files with 130 additions and 47 deletions

View File

@ -47,7 +47,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<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: 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> <li>NEW: shows strikeoutPos when drawing Debug-Boxes</li>
<li>NEW: LaTeX-Parser understands optional instruction parameters in [...] now</li> <li>NEW: LaTeX-Parser understands optional instruction parameters in [...] now</li>
<li>NEW: LaTeX-Parser simplifies parrse-tree to increase speed of execution</li> <li>NEW: LaTeX-Parser simplifies parse-tree to increase speed of execution</li>
<li>NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)</li> <li>NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)</li>
<li>NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)</li> <li>NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)</li>
<li>NEW: added \overbracket and \underbracket</li> <li>NEW: added \overbracket and \underbracket</li>

View File

@ -369,7 +369,8 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
if (fracN->getChild1()) ti->addChild(createTree(fracN->getChild1(), ti)); if (fracN->getChild1()) ti->addChild(createTree(fracN->getChild1(), ti));
if (fracN->getChild2()) ti->addChild(createTree(fracN->getChild2(), ti)); if (fracN->getChild2()) ti->addChild(createTree(fracN->getChild2(), ti));
} else if (sqrtN) { } else if (sqrtN) {
name=QString("MTsqrtNode: deg=%1").arg(sqrtN->getDegree()); name=QString("MTsqrtNode");
if (sqrtN->getChildDegree()) ti->addChild(createTree(sqrtN->getChildDegree(), ti));
if (sqrtN->getChild()) ti->addChild(createTree(sqrtN->getChild(), ti)); if (sqrtN->getChild()) ti->addChild(createTree(sqrtN->getChild(), ti));
} else if (braceN) { } else if (braceN) {
name=QString("MTbraceNode: l='%1', r='%2'").arg(JKQTMathTextBraceType2String(braceN->getOpenbrace())).arg(JKQTMathTextBraceType2String(braceN->getClosebrace())); name=QString("MTbraceNode: l='%1', r='%2'").arg(JKQTMathTextBraceType2String(braceN->getOpenbrace())).arg(JKQTMathTextBraceType2String(braceN->getClosebrace()));

View File

@ -1146,7 +1146,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
if (currentInstructionName=="sqrt") { if (currentInstructionName=="sqrt") {
nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true))); nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true)));
} else if (currentInstructionName=="cbrt") { } else if (currentInstructionName=="cbrt") {
nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true), 3)); nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true), new JKQTMathTextTextNode(this, "3", false)));
} else if (currentInstructionName=="verb") { } else if (currentInstructionName=="verb") {
QString text=""; QString text="";
currentTokenID++; currentTokenID++;
@ -1370,24 +1370,11 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
//std::cout<<"found '[' after '"<<name.toStdString()<<"'\n"; //std::cout<<"found '[' after '"<<name.toStdString()<<"'\n";
if (currentInstructionName=="sqrt") { if (currentInstructionName=="sqrt") {
JKQTMathTextNode* n1=parseLatexString(true, MTBTAny, "", true); JKQTMathTextNode* n1=parseLatexString(true, MTBTAny, "", true);
JKQTMathTextListNode* n1lst=dynamic_cast<JKQTMathTextListNode*>(n1);
JKQTMathTextTextNode* n1txt=dynamic_cast<JKQTMathTextTextNode*>(n1);
if (n1lst && n1lst->childCount()==1) {
n1txt=dynamic_cast<JKQTMathTextTextNode*>(n1lst->getChild(0));
}
int degree=2;
bool ok=false;
if (n1txt) degree=n1txt->getText().toInt(&ok);
if (!ok) {
degree=2;
error_list.append(tr("error @ ch. %1: an integer in [] after '%2' command").arg(currentTokenID).arg(currentInstructionName));
}
JKQTMathTextNode* n2=nullptr; JKQTMathTextNode* n2=nullptr;
if (getToken()==MTTopenbrace) n2=parseLatexString(true); if (getToken()==MTTopenbrace) n2=parseLatexString(true);
else error_list.append(tr("error @ ch. %1: expected one argument in '{' braces after '%2' command with an optional argument in []").arg(currentTokenID).arg(currentInstructionName)); else error_list.append(tr("error @ ch. %1: expected one argument in '{' braces after '%2' command with an optional argument in []").arg(currentTokenID).arg(currentInstructionName));
if (n1 && n2) nl->addChild(new JKQTMathTextSqrtNode(this, n2, degree)); if (n1 && n2) nl->addChild(new JKQTMathTextSqrtNode(this, n2, n1));
else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName));
} else { } else {
nl->addChild(new JKQTMathTextTextNode(this, "[", false)); nl->addChild(new JKQTMathTextTextNode(this, "[", false));

View File

@ -35,21 +35,24 @@
JKQTMathTextSqrtNode::JKQTMathTextSqrtNode(JKQTMathText* _parent, JKQTMathTextNode* child, int degree): JKQTMathTextSqrtNode::JKQTMathTextSqrtNode(JKQTMathText* _parent, JKQTMathTextNode* child__, JKQTMathTextNode *childDegree__):
JKQTMathTextSingleChildNode(child, _parent) JKQTMathTextMultiChildNode(_parent),
child(child__), childDegree(childDegree__)
{ {
this->degree=degree; if (child) child->setParentNode(this);
if (childDegree) childDegree->setParentNode(this);
} }
JKQTMathTextSqrtNode::~JKQTMathTextSqrtNode() { JKQTMathTextSqrtNode::~JKQTMathTextSqrtNode() {
if (child) delete child; child=nullptr;
if (childDegree) delete childDegree; childDegree=nullptr;
} }
void JKQTMathTextSqrtNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) { void JKQTMathTextSqrtNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device()); const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
QFont fsmall=currentEv.getFont(parentMathText); JKQTMathTextEnvironment evSmall=currentEv;
fsmall.setPointSizeF(fsmall.pointSizeF()*parentMathText->getSqrtSmallFontFactor()); evSmall.fontSize=currentEv.fontSize*parentMathText->getSqrtSmallFontFactor();
fsmall.setItalic(false); evSmall.italic=false;
const QFontMetricsF fmsmall(fsmall, painter.device());
getChild()->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos); getChild()->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
const double descent=overallHeight-baselineHeight; const double descent=overallHeight-baselineHeight;
@ -60,9 +63,9 @@ void JKQTMathTextSqrtNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
overallHeight=newAscent+newDescent;; overallHeight=newAscent+newDescent;;
baselineHeight=newAscent; baselineHeight=newAscent;
width=width+sqrtwidth; width=width+sqrtwidth;
if (degree!=2) { if (childDegree) {
const QString degreetext=QLocale::c().toString(degree); double degwidth=0, degBH=0, degOH=0, degSP=0;
const double degwidth=fmsmall.width(degreetext); childDegree->getSize(painter, evSmall, degwidth, degBH, degOH, degSP);
const double smalltextIndent=0.6*sqrtwidth; const double smalltextIndent=0.6*sqrtwidth;
if (degwidth>smalltextIndent) width=width+(degwidth-smalltextIndent); if (degwidth>smalltextIndent) width=width+(degwidth-smalltextIndent);
} }
@ -72,11 +75,10 @@ double JKQTMathTextSqrtNode::draw(QPainter& painter, double x, double y, JKQTMat
doDrawBoxes(painter, x, y, currentEv); doDrawBoxes(painter, x, y, currentEv);
const QFont f=currentEv.getFont(parentMathText); const QFont f=currentEv.getFont(parentMathText);
QFont fsmall=f;
const QFontMetricsF fm(f, painter.device()); const QFontMetricsF fm(f, painter.device());
fsmall.setPointSizeF(fsmall.pointSizeF()*parentMathText->getSqrtSmallFontFactor()); JKQTMathTextEnvironment evSmall=currentEv;
fsmall.setItalic(false); evSmall.fontSize=currentEv.fontSize*parentMathText->getSqrtSmallFontFactor();
const QFontMetricsF fmsmall(fsmall, painter.device()); evSmall.italic=false;
double width=0, baselineHeight=0, overallHeight=0, strikeoutPos=0; double width=0, baselineHeight=0, overallHeight=0, strikeoutPos=0;
getChild()->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos); getChild()->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
@ -87,9 +89,10 @@ double JKQTMathTextSqrtNode::draw(QPainter& painter, double x, double y, JKQTMat
const double linewidth=fm.lineWidth(); const double linewidth=fm.lineWidth();
const double tinyhookSize=sqrtwidth*0.1; const double tinyhookSize=sqrtwidth*0.1;
const double smalltextIndent=0.6*sqrtwidth; const double smalltextIndent=0.6*sqrtwidth;
const QString degreetext=(degree!=2)?QLocale::c().toString(degree):"";
const double degwidth=fmsmall.width(degreetext); double degwidth=0, degBH=0, degOH=0, degSP=0;
const double degheight=fmsmall.boundingRect(degreetext).height(); if (childDegree) childDegree->getSize(painter, evSmall, degwidth, degBH, degOH, degSP);
const double degheight=degOH;
const double degree_overwidth=(degwidth>smalltextIndent)?(degwidth-smalltextIndent):0.0; const double degree_overwidth=(degwidth>smalltextIndent)?(degwidth-smalltextIndent):0.0;
//painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); //painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
@ -111,7 +114,7 @@ double JKQTMathTextSqrtNode::draw(QPainter& painter, double x, double y, JKQTMat
const double x_hookbottom=(!useAltForm)?(x_start+0.33*sqrtwidth):(x_start+0.66*sqrtwidth); const double x_hookbottom=(!useAltForm)?(x_start+0.33*sqrtwidth):(x_start+0.66*sqrtwidth);
const double x_hooktop=(!useAltForm)?(x_start+sqrtwidth):x_hookbottom; const double x_hooktop=(!useAltForm)?(x_start+sqrtwidth):x_hookbottom;
const double x_smalltextend=x_start+smalltextIndent; const double x_smalltextend=x_start+smalltextIndent;
const double y_smalltext=y_top+fmsmall.ascent()+(fabs(y_top-(y_tinyhooktop-linewidth))-degheight)/2.0; const double y_smalltext=y_top+degBH+(fabs(y_top-(y_tinyhooktop-linewidth))-degheight)/2.0;
if (sqrtwidth>0) { if (sqrtwidth>0) {
QPainterPath path; QPainterPath path;
path.moveTo(x_start, y_tinyhooktop+tinyhookSize); path.moveTo(x_start, y_tinyhooktop+tinyhookSize);
@ -125,17 +128,25 @@ double JKQTMathTextSqrtNode::draw(QPainter& painter, double x, double y, JKQTMat
painter.setPen(p); painter.setPen(p);
painter.drawPath(path); painter.drawPath(path);
} }
if (degree!=2) { if (childDegree) {
painter.setFont(fsmall); childDegree->draw(painter, x_smalltextend-degwidth, y_smalltext, evSmall);
painter.drawText(QPointF(x_smalltextend-degwidth, y_smalltext), degreetext);
} }
return xnew; return xnew;
} }
bool JKQTMathTextSqrtNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) { bool JKQTMathTextSqrtNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
bool ok=true;
if (childDegree) {
JKQTMathTextEnvironment evSmall=currentEv;
evSmall.fontSize=currentEv.fontSize*parentMathText->getSqrtSmallFontFactor();
evSmall.italic=false;
html=html+"<sup>";
ok=ok&&childDegree->toHtml(html, evSmall, defaultEv);
html=html+"</sup>";
}
html=html+"&radic;<span style=\"text-decoration:overline\">"; html=html+"&radic;<span style=\"text-decoration:overline\">";
bool ok=getChild()->toHtml(html, currentEv, defaultEv); ok=ok&&getChild()->toHtml(html, currentEv, defaultEv);
html=html+"&nbsp;</span>"; html=html+"&nbsp;</span>";
return ok; return ok;
} }
@ -145,8 +156,71 @@ QString JKQTMathTextSqrtNode::getTypeName() const
return "MTsqrtNode"; return "MTsqrtNode";
} }
int JKQTMathTextSqrtNode::getDegree() const { JKQTMathTextNode *JKQTMathTextSqrtNode::getChild()
return this->degree; {
return child;
} }
const JKQTMathTextNode *JKQTMathTextSqrtNode::getChild() const
{
return child;
}
JKQTMathTextNode *JKQTMathTextSqrtNode::getChildDegree()
{
return childDegree;
}
const JKQTMathTextNode *JKQTMathTextSqrtNode::getChildDegree() const
{
return childDegree;
}
JKQTMathTextNode *JKQTMathTextSqrtNode::getChild(int i)
{
if (i==0) return child;
if (i==1) return childDegree;
return nullptr;
}
const JKQTMathTextNode *JKQTMathTextSqrtNode::getChild(int i) const
{
if (i==0) return child;
if (i==1) return childDegree;
return nullptr;
}
JKQTMathTextNode *JKQTMathTextSqrtNode::replaceChild(int i, JKQTMathTextNode *newChild)
{
if (i==0) {
JKQTMathTextNode* c=child;
child=newChild;
if (child) child->setParentNode(this);
return c;
}
if (i==1) {
JKQTMathTextNode* c=childDegree;
childDegree=newChild;
if (childDegree) childDegree->setParentNode(this);
return c;
}
}
int JKQTMathTextSqrtNode::childCount() const
{
if (childDegree) return 2;
return 1;
}
void JKQTMathTextSqrtNode::clearChildren(bool deleteChildren)
{
if (child) {
if (deleteChildren) delete child;
child=nullptr;
}
if (childDegree) {
if (deleteChildren) delete childDegree;
childDegree=nullptr;
}
}

View File

@ -40,9 +40,9 @@ class JKQTMathText; // forward
* \image html jkqtmathtext/jkqtmathtext_sqrt.png * \image html jkqtmathtext/jkqtmathtext_sqrt.png
* \image html jkqtmathtext/jkqtmathtext_cbrt.png * \image html jkqtmathtext/jkqtmathtext_cbrt.png
*/ */
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSqrtNode: public JKQTMathTextSingleChildNode { class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSqrtNode: public JKQTMathTextMultiChildNode {
public: public:
JKQTMathTextSqrtNode(JKQTMathText* parent, JKQTMathTextNode* child, int degree=2); JKQTMathTextSqrtNode(JKQTMathText* parent, JKQTMathTextNode* child__, JKQTMathTextNode* childDegree__=nullptr);
virtual ~JKQTMathTextSqrtNode() override; virtual ~JKQTMathTextSqrtNode() override;
/** \copydoc JKQTMathTextNode::draw() */ /** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override; virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
@ -50,13 +50,34 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSqrtNode: public JKQTMathTextSingleChi
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override; virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::getTypeName() */ /** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override ; virtual QString getTypeName() const override ;
/** \copydoc degree */
int getDegree() const; /** \copydoc child */
JKQTMathTextNode* getChild();
/** \copydoc child */
const JKQTMathTextNode* getChild() const;
/** \copydoc childDegree */
JKQTMathTextNode* getChildDegree();
/** \copydoc childDegree */
const JKQTMathTextNode* getChildDegree() const;
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
virtual JKQTMathTextNode* getChild(int i) override;
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
virtual const JKQTMathTextNode* getChild(int i) const override;
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
virtual JKQTMathTextNode* replaceChild(int i, JKQTMathTextNode* newChild) override;
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
virtual int childCount() const override;
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
virtual void clearChildren(bool deleteChildren=true) override;
protected: protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */ /** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override; virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \brief degree of the radical (shown of !=2) */ /** \brief child node for the part under the root */
int degree; JKQTMathTextNode* child;
/** \brief second child node for the degree of the root (or nullptr if nothing) */
JKQTMathTextNode* childDegree;
}; };
#endif // JKQTMATHTEXTSQRTNODE_H #endif // JKQTMATHTEXTSQRTNODE_H