diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox index 6485321c9e..494f6c354f 100644 --- a/doc/dox/whatsnew.dox +++ b/doc/dox/whatsnew.dox @@ -47,7 +47,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
  • 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 , ...
  • NEW: shows strikeoutPos when drawing Debug-Boxes
  • NEW: LaTeX-Parser understands optional instruction parameters in [...] now
  • -
  • NEW: LaTeX-Parser simplifies parrse-tree to increase speed of execution
  • +
  • NEW: LaTeX-Parser simplifies parse-tree to increase speed of execution
  • NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)
  • NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)
  • NEW: added \overbracket and \underbracket
  • diff --git a/examples/jkqtmathtext_test/testform.cpp b/examples/jkqtmathtext_test/testform.cpp index ce3ce5cf12..45ce7f86c6 100644 --- a/examples/jkqtmathtext_test/testform.cpp +++ b/examples/jkqtmathtext_test/testform.cpp @@ -369,7 +369,8 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p if (fracN->getChild1()) ti->addChild(createTree(fracN->getChild1(), ti)); if (fracN->getChild2()) ti->addChild(createTree(fracN->getChild2(), ti)); } 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)); } else if (braceN) { name=QString("MTbraceNode: l='%1', r='%2'").arg(JKQTMathTextBraceType2String(braceN->getOpenbrace())).arg(JKQTMathTextBraceType2String(braceN->getClosebrace())); diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp index e8b14ced3c..27eb754957 100644 --- a/lib/jkqtmathtext/jkqtmathtext.cpp +++ b/lib/jkqtmathtext/jkqtmathtext.cpp @@ -1146,7 +1146,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType if (currentInstructionName=="sqrt") { nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true))); } 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") { QString text=""; currentTokenID++; @@ -1370,24 +1370,11 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType //std::cout<<"found '[' after '"<(n1); - JKQTMathTextTextNode* n1txt=dynamic_cast(n1); - if (n1lst && n1lst->childCount()==1) { - n1txt=dynamic_cast(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; 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)); - 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 { nl->addChild(new JKQTMathTextTextNode(this, "[", false)); diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp index 66d072e981..bd8a44d535 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp @@ -35,21 +35,24 @@ -JKQTMathTextSqrtNode::JKQTMathTextSqrtNode(JKQTMathText* _parent, JKQTMathTextNode* child, int degree): - JKQTMathTextSingleChildNode(child, _parent) +JKQTMathTextSqrtNode::JKQTMathTextSqrtNode(JKQTMathText* _parent, JKQTMathTextNode* child__, JKQTMathTextNode *childDegree__): + JKQTMathTextMultiChildNode(_parent), + child(child__), childDegree(childDegree__) { - this->degree=degree; + if (child) child->setParentNode(this); + if (childDegree) childDegree->setParentNode(this); } 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*/) { const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device()); - QFont fsmall=currentEv.getFont(parentMathText); - fsmall.setPointSizeF(fsmall.pointSizeF()*parentMathText->getSqrtSmallFontFactor()); - fsmall.setItalic(false); - const QFontMetricsF fmsmall(fsmall, painter.device()); + JKQTMathTextEnvironment evSmall=currentEv; + evSmall.fontSize=currentEv.fontSize*parentMathText->getSqrtSmallFontFactor(); + evSmall.italic=false; getChild()->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos); const double descent=overallHeight-baselineHeight; @@ -60,9 +63,9 @@ void JKQTMathTextSqrtNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro overallHeight=newAscent+newDescent;; baselineHeight=newAscent; width=width+sqrtwidth; - if (degree!=2) { - const QString degreetext=QLocale::c().toString(degree); - const double degwidth=fmsmall.width(degreetext); + if (childDegree) { + double degwidth=0, degBH=0, degOH=0, degSP=0; + childDegree->getSize(painter, evSmall, degwidth, degBH, degOH, degSP); const double smalltextIndent=0.6*sqrtwidth; 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); const QFont f=currentEv.getFont(parentMathText); - QFont fsmall=f; const QFontMetricsF fm(f, painter.device()); - fsmall.setPointSizeF(fsmall.pointSizeF()*parentMathText->getSqrtSmallFontFactor()); - fsmall.setItalic(false); - const QFontMetricsF fmsmall(fsmall, painter.device()); + JKQTMathTextEnvironment evSmall=currentEv; + evSmall.fontSize=currentEv.fontSize*parentMathText->getSqrtSmallFontFactor(); + evSmall.italic=false; double width=0, baselineHeight=0, overallHeight=0, strikeoutPos=0; 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 tinyhookSize=sqrtwidth*0.1; const double smalltextIndent=0.6*sqrtwidth; - const QString degreetext=(degree!=2)?QLocale::c().toString(degree):""; - const double degwidth=fmsmall.width(degreetext); - const double degheight=fmsmall.boundingRect(degreetext).height(); + + double degwidth=0, degBH=0, degOH=0, degSP=0; + if (childDegree) childDegree->getSize(painter, evSmall, degwidth, degBH, degOH, degSP); + const double degheight=degOH; const double degree_overwidth=(degwidth>smalltextIndent)?(degwidth-smalltextIndent):0.0; //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_hooktop=(!useAltForm)?(x_start+sqrtwidth):x_hookbottom; 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) { QPainterPath path; 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.drawPath(path); } - if (degree!=2) { - painter.setFont(fsmall); - painter.drawText(QPointF(x_smalltextend-degwidth, y_smalltext), degreetext); + if (childDegree) { + childDegree->draw(painter, x_smalltextend-degwidth, y_smalltext, evSmall); } return xnew; } 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+""; + ok=ok&&childDegree->toHtml(html, evSmall, defaultEv); + html=html+""; + } html=html+"√"; - bool ok=getChild()->toHtml(html, currentEv, defaultEv); + ok=ok&&getChild()->toHtml(html, currentEv, defaultEv); html=html+" "; return ok; } @@ -145,8 +156,71 @@ QString JKQTMathTextSqrtNode::getTypeName() const return "MTsqrtNode"; } -int JKQTMathTextSqrtNode::getDegree() const { - return this->degree; +JKQTMathTextNode *JKQTMathTextSqrtNode::getChild() +{ + 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; + } +} diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h index a14da4087d..52948eddd1 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h @@ -40,9 +40,9 @@ class JKQTMathText; // forward * \image html jkqtmathtext/jkqtmathtext_sqrt.png * \image html jkqtmathtext/jkqtmathtext_cbrt.png */ -class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSqrtNode: public JKQTMathTextSingleChildNode { +class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSqrtNode: public JKQTMathTextMultiChildNode { public: - JKQTMathTextSqrtNode(JKQTMathText* parent, JKQTMathTextNode* child, int degree=2); + JKQTMathTextSqrtNode(JKQTMathText* parent, JKQTMathTextNode* child__, JKQTMathTextNode* childDegree__=nullptr); virtual ~JKQTMathTextSqrtNode() override; /** \copydoc JKQTMathTextNode::draw() */ 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; /** \copydoc JKQTMathTextNode::getTypeName() */ 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: /** \copydoc JKQTMathTextNode::getSizeInternal() */ 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) */ - int degree; + /** \brief child node for the part under the root */ + JKQTMathTextNode* child; + /** \brief second child node for the degree of the root (or nullptr if nothing) */ + JKQTMathTextNode* childDegree; }; #endif // JKQTMATHTEXTSQRTNODE_H