JKQTMathText:

- new options interface for JKQTMathText::parse()
  - breaking: removed JKQTMathtext::unparsedNode
  - several minor improvements
This commit is contained in:
jkriege2 2022-08-13 15:32:31 +02:00
parent ce6637fb4b
commit f83a3468b1
34 changed files with 335 additions and 100 deletions

View File

@ -48,10 +48,12 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>IMPROVED: rendering of sqrt</li>
<li>IMPROVED: rendering and size calculation of decorations</li>
<li>IMPROVED: tokenizing and parsing of text in text-mode: now a lot of accents with commands like \c \\\"a, \c \\'e and variants (e.g. \c {\\\"a}, \c \\\"{a}, ...) are supported now</li>
<li>IMPROVED/breaking: refactored symbol node JKQTMathTextSymbolNode and changed font-lookup!</li>
<li>IMPROVED/NEW/breaking: refactored whitespace-processing node JKQTMathTextWhitespaceNode, now all major LaTeX whitespace commands are supported properly</li>
<li>IMPROVED/NEW/breaking: refactored LaTeX parser in JKQTMathText</li>
<li>REMOVED/breaking: \c \\v[a-zA-Z] and shorthand for \c \\vec{a-zA-Z} was removed, implementation of \c \\bbR,\c \\bbC,... changed</li>
<li>IMPROVED/BREAKING: refactored symbol node JKQTMathTextSymbolNode and changed font-lookup!</li>
<li>IMPROVED/NEW/BREAKING: refactored whitespace-processing node JKQTMathTextWhitespaceNode, now all major LaTeX whitespace commands are supported properly</li>
<li>IMPROVED/NEW/BREAKING: refactored LaTeX parser in JKQTMathText</li>
<li>REMOVED/BREAKING: \c \\v[a-zA-Z] and shorthand for \c \\vec{a-zA-Z} was removed, implementation of \c \\bbR,\c \\bbC,... changed</li>
<li>MODIFIED/BREAKING: new options interface for JKQTMathText::parse()</li>
<li>EMOVED/BREAKING: removed JKQTMathtext::unparsedNode</li>
<li>IMPROVED/REWORKED rendering of text in text- and math-mode. Now it is more consistent with the output of LaTeX itself</li>
<li>IMPROVED/REWORKED rendering of blackboard font: now several different rendering modes can be selected using JKQTMathText::setFontBlackboradMode()</li>
<li>BREAKING/REWORKED: The \\verb!...!-command now works the same as in LaTeX</li>
@ -123,25 +125,25 @@ Changes, compared to \ref page_whatsnew_V2019_11 "v2019.11" include:
<li> fixed issue <a href="https://github.com/jkriege2/JKQtPlotter/issues/52">#52: 'runtime_error': is not a member of 'std'</a>, thanks to <a href="https://github.com/gomgomi">user:gomgomi</a></li>
<li> fixed issue <a href="https://github.com/jkriege2/JKQtPlotter/issues/56">#56: Logscale zoom multiple zeros? </a>, thanks to <a href="https://github.com/sufuk">user:sufuk</a></li>
<li> merged PR <a href="https://github.com/jkriege2/JKQtPlotter/pull/51">#51: Bug: JKMathParser exception return local variable </a>, thanks to <a href="https://github.com/StephanOostveen">user:StephanOostveen</a></li>
<li>renamed/breaking change: renamed JKQTPPlotObject->JKQTPGeometricPlotElement and added new base class JKQTPPlotAnnotationElement</li>
<li>renamed/breaking change: renamed JKQTPColorPaletteStyleAndToolsMixin::setPalette() -> JKQTPColorPaletteStyleAndToolsMixin::setColorPalette()</li>
<li>removed/breaking change: removed the usage of some deprecated functions and objects (e.g. QMatrix)</li>
<li>removed/breaking change: removed the overlay elements (derived from JKQTPOverlayElement), which were not very well set up and are more confusing than useful.</li>
<li>improved/breaking change: geometric objects now use an adaptive drawing algorithm to represent curves (before e.g. ellipses were always separated into a fixed number of line-segments)</li>
<li>improved/breaking change: geometric elements constructor: removed all styling properties, added setStyle()-functions to replace them. This is necessary to better work with the extended Styling system</li>
<li>renamed/BREAKING change: renamed JKQTPPlotObject->JKQTPGeometricPlotElement and added new base class JKQTPPlotAnnotationElement</li>
<li>renamed/BREAKING change: renamed JKQTPColorPaletteStyleAndToolsMixin::setPalette() -> JKQTPColorPaletteStyleAndToolsMixin::setColorPalette()</li>
<li>removed/BREAKING change: removed the usage of some deprecated functions and objects (e.g. QMatrix)</li>
<li>removed/BREAKING change: removed the overlay elements (derived from JKQTPOverlayElement), which were not very well set up and are more confusing than useful.</li>
<li>improved/BREAKING change: geometric objects now use an adaptive drawing algorithm to represent curves (before e.g. ellipses were always separated into a fixed number of line-segments)</li>
<li>improved/BREAKING change: geometric elements constructor: removed all styling properties, added setStyle()-functions to replace them. This is necessary to better work with the extended Styling system</li>
<li>improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)</li>
<li>improved/breaking change: reworked class hierarchy of parsed function plots and declared several setters as slots.</li>
<li>improved/breaking change: reworked class hierarchy of bar & impulse charts.</li>
<li>improved/breaking change: reworked class hierarchy of range charts.</li>
<li>improved/breaking change: reworked class hierarchy of special line (step) graphs.</li>
<li>improved/breaking change: reworked class hierarchy of filled line graphs.</li>
<li>improved/breaking change: reworked class hierarchy of range plot elements (JKQTPVerticalRange and JKQTPHorizontalRange).</li>
<li>improved/breaking change: reworked class hierarchy of boxplots.</li>
<li>improved/breaking change: reworked class hierarchy of violin plots.</li>
<li>improved/breaking change: extended styling system for graphs.</li>
<li>improved/breaking change: reworked graph Base-Classes (promoted several setters to slots, added Q_PROPERTY- and Q_ENUM-declarations...)</li>
<li>improved/breaking change: made more functions and function parameters const</li>
<li>improved/breaking change: image plots now manage CONST-data, not plain pointer arrays... This is OK, since the raw data is never owned nor modified by the plot, only referenced!.</li>
<li>improved/BREAKING change: reworked class hierarchy of parsed function plots and declared several setters as slots.</li>
<li>improved/BREAKING change: reworked class hierarchy of bar & impulse charts.</li>
<li>improved/BREAKING change: reworked class hierarchy of range charts.</li>
<li>improved/BREAKING change: reworked class hierarchy of special line (step) graphs.</li>
<li>improved/BREAKING change: reworked class hierarchy of filled line graphs.</li>
<li>improved/BREAKING change: reworked class hierarchy of range plot elements (JKQTPVerticalRange and JKQTPHorizontalRange).</li>
<li>improved/BREAKING change: reworked class hierarchy of boxplots.</li>
<li>improved/BREAKING change: reworked class hierarchy of violin plots.</li>
<li>improved/BREAKING change: extended styling system for graphs.</li>
<li>improved/BREAKING change: reworked graph Base-Classes (promoted several setters to slots, added Q_PROPERTY- and Q_ENUM-declarations...)</li>
<li>improved/BREAKING change: made more functions and function parameters const</li>
<li>improved/BREAKING change: image plots now manage CONST-data, not plain pointer arrays... This is OK, since the raw data is never owned nor modified by the plot, only referenced!.</li>
<li>bugfixed/improved: aspect ratio handling in JKQTPlotter.</li>
<li>new: switching to semantic versioning ... starting with v4.0.0</li>
<li>new: Compatibility with Qt 5.15 and Qt6</li>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 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: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 994 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 851 B

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -486,7 +486,7 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
int l=matrixN->getLines();
int c=matrixN->getColumns();
name=QString("MatrixNode: l*c=%1*%2").arg(l).arg(c);
QVector<QVector<JKQTMathTextNode*> > children=matrixN->getChildren();
QVector<QVector<JKQTMathTextNode*> > children=matrixN->getChildrenMatrix();
for (int y=0; y<l; y++) {
for (int x=0; x<c; x++) {
if (children[y].at(x)!=nullptr) {

View File

@ -185,10 +185,8 @@ JKQTMathText::JKQTMathText(QObject* parent):
//qDebug()<<"set fonts: "<<std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()-t0).count()/1000.0<<"ms"; t0=std::chrono::high_resolution_clock::now();
useXITS();
//qDebug()<<"useXITS: "<<std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()-t0).count()/1000.0<<"ms"; t0=std::chrono::high_resolution_clock::now();
useUnparsed=false;
parsedNode=nullptr;
unparsedNode=nullptr;
currentToken=MTTnone;
currentTokenName="";
@ -200,8 +198,6 @@ JKQTMathText::JKQTMathText(QObject* parent):
JKQTMathText::~JKQTMathText() {
if (parsedNode!=nullptr) delete parsedNode;
parsedNode=nullptr;
if (unparsedNode!=nullptr) delete unparsedNode;
unparsedNode=nullptr;
}
void JKQTMathText::loadSettings(const QSettings& settings, const QString& group){
@ -1058,16 +1054,6 @@ void JKQTMathText::setMatrixYPaddingFactor(double factor)
matrix_yPadding_factor=factor;
}
void JKQTMathText::setUseUnparsed(bool __value)
{
this->useUnparsed = __value;
}
bool JKQTMathText::isUsingUnparsed() const
{
return this->useUnparsed;
}
QStringList JKQTMathText::getErrorList() const {
return this->error_list;
}
@ -2288,15 +2274,15 @@ JKQTMathTextNode *JKQTMathText::getParsedNode() const {
bool JKQTMathText::parse(const QString& text, bool addSpaceBeforeAndAfter, bool allowLinebreaks){
QString ntext;
if (addSpaceBeforeAndAfter) ntext=QString("\\;")+text+QString("\\;");
else ntext=text;
bool JKQTMathText::parse(const QString& text, ParseOptions options){
QString ntext=text;
if (options.testFlag(StartWithMathMode)) ntext=QString("$")+ntext+QString("$");
if (options.testFlag(AddSpaceBeforeAndAfter)) ntext=QString("\\;")+ntext+QString("\\;");
if (parsedNode && parseString==ntext) return true;
if (parsedNode!=nullptr) delete parsedNode;
if (unparsedNode!=nullptr) delete unparsedNode;
//std::cout<<"JKQTMathText::parse('"<<ntext.toStdString()<<"', options="<<std::hex<<static_cast<int>(options)<<")\n";
parseString=ntext;
currentTokenID=-1;
@ -2306,35 +2292,41 @@ bool JKQTMathText::parse(const QString& text, bool addSpaceBeforeAndAfter, bool
lastLineCount.clear();
error_list.clear();
if (allowLinebreaks) {
if (options.testFlag(AllowLinebreaks)) {
parsedNode=parseMultilineLatexString(true, QString(""), MTHALeft, 1.0, MTSMDefaultSpacing, MTVOFirstLine);
} else {
parsedNode=parseLatexString(true);
}
unparsedNode=new JKQTMathTextVerbatimNode(this, text);
parsedNode=simplifyJKQTMathTextNode(parsedNode);
return (parsedNode!=nullptr);
}
QSizeF JKQTMathText::getSize(QPainter& painter){
if (getNodeTree()!=nullptr) {
double w=0, a=0, d=0, s=0;
getSizeDetail(painter, w, a, d, s);
return QSizeF(w, a+d);
const JKQTMathTextNodeSize s=getSizeDetail(painter);
return s.getSize();
}
return QSizeF(0,0);
}
QSize JKQTMathText::getIntSize(QPainter &painter)
{
if (getNodeTree()!=nullptr) {
const JKQTMathTextNodeSize s=getSizeDetail(painter);
return s.getIntSize();
}
return QSize(0,0);
}
double JKQTMathText::getDescent(QPainter& painter) {
double w=0, a=0, d=0, s=0;
getSizeDetail(painter, w, a, d, s);
return d;
const JKQTMathTextNodeSize s=getSizeDetail(painter);
return s.getDescent();
}
double JKQTMathText::getAscent(QPainter& painter) {
double w=0, a=0, d=0, s=0;
getSizeDetail(painter, w, a, d, s);
return a;
const JKQTMathTextNodeSize s=getSizeDetail(painter);
return s.baselineHeight;
}
void JKQTMathText::getSizeDetail(QPainter& painter, double& width, double& ascent, double& descent, double& strikeoutPos) {
@ -2516,7 +2508,6 @@ QPicture JKQTMathText::drawIntoPicture(bool drawBoxes)
JKQTMathTextNode *JKQTMathText::getNodeTree() const {
if (useUnparsed) return unparsedNode;
return parsedNode;
}

View File

@ -25,6 +25,7 @@
#ifndef JKQTMATHTEXT_H
#define JKQTMATHTEXT_H
#include <QFlags>
#include <QObject>
#include <QSettings>
#include <QPainter>
@ -214,16 +215,28 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
void loadSettings(const QSettings& settings, const QString& group=QString("mathtext/"));
/** \brief store the object settings to the given QSettings object with the given name prefix */
void saveSettings(QSettings& settings, const QString& group=QString("mathtext/")) const;
/** \brief options for parse() */
enum ParseOption {
AddSpaceBeforeAndAfter = 0x01, /*!< \brief If set, a little bit of space is added before and after the text. */
StartWithMathMode = 0x02, /*!< \brief if set, the parser assumes the LaTeX string is in math-mode (as if surrounded by \c $ ) */
AllowLinebreaks = 0x04, /*!< \brief If set, linebreak (i.e. \c \\ or \c \\newline ) are allowed, otherwise a single line wihtout such linebreak commands is expected */
DefaultParseOptions=AllowLinebreaks,
};
Q_DECLARE_FLAGS(ParseOptions, ParseOption)
Q_FLAG(ParseOptions)
/** \brief parse the given LaTeX string.
*
* \param addSpaceBeforeAndAfter If \ctrue a little bit of space is added before and after the text.
* \param allowLinebreaks If \c true , linebreak (i.e. \c \\ or \c \\newline ) are allowed, otherwise a single line wihtout such linebreak commands is expected
* \param options Options for parsing, \see ParseOptions
* \param allowLinebreaks
*
* \returns \c true on success.
*/
bool parse(const QString &text, bool addSpaceBeforeAndAfter=false, bool allowLinebreaks=true);
/** \brief get the size of the drawn representation. returns an invalid size if no text has been parsed. */
bool parse(const QString &text, ParseOptions options=DefaultParseOptions);
/** \brief get the size of the drawn representation. returns \c QSizeF(0,0) if no text has been parsed. */
QSizeF getSize(QPainter& painter);
/** \brief get the rounded (using ceil) to an integer size of the drawn representation. returns \c QSize(0,0) if no text has been parsed. */
QSize getIntSize(QPainter& painter);
/** \brief return the descent, i.e. the distance from the baseline to the lowest part of the representation */
double getDescent(QPainter& painter);
/** \brief return the ascentt, i.e. the distance from the baseline to the highest part of the representation */
@ -643,11 +656,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
void setMatrixYPaddingFactor(double factor);
/** \copydoc useUnparsed */
void setUseUnparsed(bool __value);
/** \copydoc useUnparsed */
bool isUsingUnparsed() const;
/** \copydoc error_list */
QStringList getErrorList() const;
/** \brief returns \c true when errors were registered in the system \see error_list */
@ -883,10 +891,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
/** \brief the result of parsing the last string supplied to the object via parse() */
JKQTMathTextNode* parsedNode;
/** \brief a tree containing the unparsed text as a single node */
JKQTMathTextNode* unparsedNode;
/** \brief if true, the unparsedNode is drawn \see unparsedNode */
bool useUnparsed;
/** \brief returns the syntax tree of JKQTMathTextNode's that was created by the last parse call */
JKQTMathTextNode* getNodeTree() const;

View File

@ -203,6 +203,7 @@ JKQTMathTextSimpleInstructionNode::InstructionProperties::InstructionProperties(
JKQTMathTextModifiedTextPropsInstructionNode::JKQTMathTextModifiedTextPropsInstructionNode(JKQTMathText* _parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters):
JKQTMathTextInstruction1Node(_parent, name, child, parameters)
{
fillInstructions();
}
JKQTMathTextModifiedTextPropsInstructionNode::~JKQTMathTextModifiedTextPropsInstructionNode() {
@ -215,6 +216,7 @@ QString JKQTMathTextModifiedTextPropsInstructionNode::getTypeName() const
}
void JKQTMathTextModifiedTextPropsInstructionNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
fillInstructions();
JKQTMathTextEnvironment ev=currentEv;
executeInstruction(ev);
@ -223,11 +225,12 @@ void JKQTMathTextModifiedTextPropsInstructionNode::getSizeInternal(QPainter& pai
}
double JKQTMathTextModifiedTextPropsInstructionNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
fillInstructions();
doDrawBoxes(painter, x, y, currentEv);
JKQTMathTextEnvironment ev=currentEv;
executeInstruction(ev);
//std::cout<<" MODNODE: "<<getInstructionName().toStdString()<<" ev.mathMode="<<ev.insideMath<<", ev.forceUpright="<<ev.insideMathForceDigitsUpright<<"\n";
return getChild()->draw(painter, x, y, ev);
}
@ -266,6 +269,7 @@ void JKQTMathTextModifiedTextPropsInstructionNode::modifyInMathEnvironment(const
void JKQTMathTextModifiedTextPropsInstructionNode::executeInstruction(JKQTMathTextEnvironment &ev) const
{
fillInstructions();
instructions.value(getInstructionName(), InstructionProperties()).modifier(ev, getParameters());
}
@ -649,6 +653,7 @@ JKQTMathTextModifiedTextPropsInstructionNode::InstructionProperties::Instruction
JKQTMathTextBoxInstructionNode::JKQTMathTextBoxInstructionNode(JKQTMathText* _parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters):
JKQTMathTextInstruction1Node(_parent, name, child, parameters)
{
fillInstructions();
}
JKQTMathTextBoxInstructionNode::~JKQTMathTextBoxInstructionNode() {

View File

@ -39,7 +39,7 @@
JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText* _parent, const QVector<QVector<JKQTMathTextNode *> > &children, const QString &columnSpec):
JKQTMathTextNode(_parent),
JKQTMathTextMultiChildNode(_parent),
verticalLineRHSColumn(),
verticalLineLeft(LTnone),
horizontalLineBottomRow(),
@ -52,7 +52,7 @@ JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText* _parent, const QVec
}
JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText *_parent, const QString &columnSpec):
JKQTMathTextNode(_parent),
JKQTMathTextMultiChildNode(_parent),
verticalLineRHSColumn(),
verticalLineLeft(LTnone),
horizontalLineBottomRow(),
@ -64,12 +64,7 @@ JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText *_parent, const QStr
}
JKQTMathTextMatrixNode::~JKQTMathTextMatrixNode() {
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
delete children[i].at(j);
}
}
children.clear();
clearChildrenImpl(true);
}
void JKQTMathTextMatrixNode::setChildren(const QVector<QVector<JKQTMathTextNode *> > &children)
@ -108,7 +103,7 @@ bool JKQTMathTextMatrixNode::toHtml(QString &/*html*/, JKQTMathTextEnvironment /
return false;
}
QVector<QVector<JKQTMathTextNode *> > JKQTMathTextMatrixNode::getChildren() const {
QVector<QVector<JKQTMathTextNode *> > JKQTMathTextMatrixNode::getChildrenMatrix() const {
return this->children;
}
@ -120,6 +115,106 @@ int JKQTMathTextMatrixNode::getLines() const {
return this->lines;
}
QList<JKQTMathTextNode *> JKQTMathTextMatrixNode::getChildren()
{
QList<JKQTMathTextNode *> l;
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
l<<children[i].at(j);
}
}
return l;
}
int JKQTMathTextMatrixNode::childCount() const
{
int s=0;
for (int i=0; i<children.size(); i++) {
s+=children[i].size();
}
return s;
}
void JKQTMathTextMatrixNode::clearChildren(bool deleteChildren)
{
clearChildrenImpl(deleteChildren);
}
void JKQTMathTextMatrixNode::clearChildrenImpl(bool deleteChildren)
{
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
if (deleteChildren) delete children[i].at(j);
}
}
children.clear();
}
void JKQTMathTextMatrixNode::deleteChild(int nn)
{
int n=0;
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
if (n==nn) {
delete children[i].operator[](j);
children[i].operator[](j)=new JKQTMathTextNoopNode(parentMathText);
children[i].operator[](j)->setParentNode(this);
return ;
}
n++;
}
}
return ;
}
JKQTMathTextNode *JKQTMathTextMatrixNode::getChild(int nn)
{
int n=0;
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
if (n==nn) {
return children[i].at(j);
}
n++;
}
}
return nullptr;
}
const JKQTMathTextNode *JKQTMathTextMatrixNode::getChild(int nn) const
{
int n=0;
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
if (n==nn) {
return children[i].at(j);
}
n++;
}
}
return nullptr;
}
JKQTMathTextNode *JKQTMathTextMatrixNode::replaceChild(int nn, JKQTMathTextNode *newChild)
{
int n=0;
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
if (n==nn) {
JKQTMathTextNode* old= children[i].at(j);
children[i].operator[](j)=newChild;
return old;
}
n++;
}
}
return nullptr;
}
void JKQTMathTextMatrixNode::setDrawBoxes(bool draw)
{

View File

@ -44,7 +44,7 @@ class JKQTMathText; // forward
*
* \image html jkqtmathtext/jkqtmathtext_array.png
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextMatrixNode: public JKQTMathTextNode {
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextMatrixNode: public JKQTMathTextMultiChildNode {
public:
/** \brief types of lines */
enum LineType {
@ -72,11 +72,25 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextMatrixNode: public JKQTMathTextNode {
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \brief returns the child nodes */
QVector<QVector<JKQTMathTextNode*> > getChildren() const;
QVector<QVector<JKQTMathTextNode*> > getChildrenMatrix() const;
/** \copydoc columns */
int getColumns() const;
/** \copydoc lines */
int getLines() const;
/** \copydoc JKQTMathTextMultiChildNode::getChildren() */
virtual QList<JKQTMathTextNode*> getChildren() override;
/** \copydoc JKQTMathTextMultiChildNode::childCount() */
virtual int childCount() const override;
/** \copydoc JKQTMathTextMultiChildNode::clearChildren() */
virtual void clearChildren(bool deleteChildren=true) override;
/** \copydoc JKQTMathTextMultiChildNode::deleteChild() */
virtual void deleteChild(int i) override;
/** \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;
protected:
/** \brief describes the layout of the whole node */
struct LayoutInfo: public JKQTMathTextNodeSize {
@ -135,6 +149,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextMatrixNode: public JKQTMathTextNode {
static void drawHLine(QPainter& painter, double x, double y, double width, LineType lt, double linewidth, double linewidthHeavy, QColor color, double doublelineseparation);
/** \brief parses a column specifier */
void parseColumnSpec(const QString& columnspec);
/** \copydoc JKQTMathTextMultiChildNode::clearChildren() */
void clearChildrenImpl(bool deleteChildren);
};
#endif // JKQTMATHTEXTMATRIXNODE_H

View File

@ -380,3 +380,37 @@ JKQTMathTextNodeSize JKQTMathTextNode::getSize(QPainter &painter, JKQTMathTextEn
getSize(painter, currentEv, s.width, s.baselineHeight, s.overallHeight, s.strikeoutPos, prevNodeSize);
return s;
}
JKQTMathTextNoopNode::JKQTMathTextNoopNode(JKQTMathText *parent):
JKQTMathTextNode(parent)
{
}
JKQTMathTextNoopNode::~JKQTMathTextNoopNode()
{
}
QString JKQTMathTextNoopNode::getTypeName() const
{
return "MTNoopNode";
}
bool JKQTMathTextNoopNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv)
{
return true;
}
double JKQTMathTextNoopNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize *prevNodeSize)
{
return x;
}
void JKQTMathTextNoopNode::getSizeInternal(QPainter &painter, JKQTMathTextEnvironment currentEv, double &width, double &baselineHeight, double &overallHeight, double &strikeoutPos, const JKQTMathTextNodeSize *prevNodeSize)
{
width=0;
baselineHeight=0;
overallHeight=0;
strikeoutPos=0;
}

View File

@ -279,4 +279,26 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextDualChildNode: public JKQTMathTextMult
JKQTMathTextNode* child2;
};
/** \brief subclass representing a node that outputs nothing
* \ingroup jkqtmathtext_items
*
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNoopNode: public JKQTMathTextNode {
public:
explicit JKQTMathTextNoopNode(JKQTMathText* parent);
virtual ~JKQTMathTextNoopNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) 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;
};
#endif // JKQTMATHTEXTNODE_H

View File

@ -30,26 +30,27 @@
JKQTMathTextNode *simplifyJKQTMathTextNode(JKQTMathTextNode *node)
{
JKQTMathTextHorizontalListNode* nl=dynamic_cast<JKQTMathTextHorizontalListNode*>(node);
JKQTMathTextVerticalListNode* vl=dynamic_cast<JKQTMathTextVerticalListNode*>(node);
JKQTMathTextMultiChildNode* nmc=dynamic_cast<JKQTMathTextMultiChildNode*>(node);
JKQTMathTextSingleChildNode* nsc=dynamic_cast<JKQTMathTextSingleChildNode*>(node);
if (nl) {
if (nl->childCount()==1) {
if ((nl || vl) && nmc) {
if (nmc->childCount()==1) {
// if there was only a single node: simplify the syntax tree, by removing the outer list node
JKQTMathTextNode* ret= simplifyJKQTMathTextNode(nl->getChild(0));
nl->clearChildren(false);
JKQTMathTextNode* ret= simplifyJKQTMathTextNode(nmc->getChild(0));
nmc->clearChildren(false);
ret->setParentNode(nullptr);
delete nl;
delete nmc;
return ret;
} else if (nl->childCount()>1) {
} else if (nmc->childCount()>1) {
// if there are several child nodes, apply this method recursively
for (int i=0; i<nl->childCount(); i++) {
JKQTMathTextNode* c=nl->getChild(i);
for (int i=0; i<nmc->childCount(); i++) {
JKQTMathTextNode* c=nmc->getChild(i);
JKQTMathTextNode* newc= simplifyJKQTMathTextNode(c);
if (c!=newc) nl->replaceAndDeleteChild(i, newc);
if (c!=newc) nmc->replaceAndDeleteChild(i, newc);
}
return nl;
return nmc;
}
return nl;
return nmc;
} else if (nmc) {
// apply this method recursively to any children
for (int i=0; i<nmc->childCount(); i++) {
@ -106,3 +107,32 @@ JKQTMathTextNode *simplifyAndTrimJKQTMathTextNode(JKQTMathTextNode *node)
}
return t;
}
namespace JKQTMathText_private {
QString JKQTMathTextNodeTree2String(JKQTMathTextNode *root, int level)
{
QString tree;
JKQTMathTextMultiChildNode* nmc=dynamic_cast<JKQTMathTextMultiChildNode*>(root);
JKQTMathTextSingleChildNode* nsc=dynamic_cast<JKQTMathTextSingleChildNode*>(root);
if (level>=1) {
for (int i=0; i<level-1; i++) tree+="| ";
}
if (level>0) tree+="+--";
tree+=root->getTypeName()+"\n";
if (nmc) {
for (int i=0; i<nmc->childCount(); i++) {
tree+=JKQTMathTextNodeTree2String(nmc->getChild(i), level+1);
}
} else if (nsc) {
tree+=JKQTMathTextNodeTree2String(nsc->getChild(), level+1);
}
return tree;
}
}
QString JKQTMathTextNodeTree2String(JKQTMathTextNode *root)
{
return JKQTMathText_private::JKQTMathTextNodeTree2String(root, 0);
}

View File

@ -44,6 +44,44 @@ JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNode* simplifyJKQTMathTextNode(JKQTMathTextN
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNode* simplifyAndTrimJKQTMathTextNode(JKQTMathTextNode* node);
/*! \brief converts a node-tree with the given \a root into a string, representing the node-tree
\ingroup jkqtmathtext_items
\see This method uses JKQTMathText::getTypeName()
Here is an example output for
\code
$x_{1/2}=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$
\endcode
The output looks like this:
\verbatim
JKQTMathTextModifiedTextPropsInstructionNode(equation)
+--MTHorizontalListNode
| +--JKQTMathTextTextNode(x)
| +--MTsubscriptNode
| | +--MTHorizontalListNode
| | | +--JKQTMathTextTextNode(1)
| | | +--JKQTMathTextTextNode(/)
| | | +--JKQTMathTextTextNode(2)
| +--JKQTMathTextSymbolNode(=)
| +--MTfracNode
| | +--MTHorizontalListNode
| | | +--JKQTMathTextSymbolNode(-)
| | | +--JKQTMathTextTextNode(b)
| | | +--JKQTMathTextSymbolNode(pm)
| | | +--MTsqrtNode
| | | | +--MTHorizontalListNode
| | | | | +--JKQTMathTextTextNode(b)
| | | | | +--MTsuperscriptNode
| | | | | | +--JKQTMathTextTextNode(2)
| | | | | +--JKQTMathTextSymbolNode(-)
| | | | | +--JKQTMathTextTextNode(4ac)
| | +--JKQTMathTextTextNode(2a)
\endverbatim
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextNodeTree2String(JKQTMathTextNode* root);
#endif // JKQTMATHTEXTNODETOOLS_H

View File

@ -302,8 +302,9 @@ double JKQTMathTextTextNode::draw(QPainter& painter, double x, double y, JKQTMat
//qDebug()<<"JKQTMathTextTextNode: text="<<text<<" font="<<f;
//std::cout<<" TEXT: currentEv.mathMode="<<currentEv.insideMath<<", currentEv.forceUpright="<<currentEv.insideMathForceDigitsUpright<<"\n";
for (int i=0; i<textpart.size(); i++) {
//std::cout<<" TEXT: mode="<<fontMode[i]<<", text='"<<textpart[i].toStdString()<<"'\n";
switch(fontMode[i]) {
case FMasDefined:
painter.setFont(f);

View File

@ -1738,7 +1738,6 @@ bool JKQTBasePlotter::printpreviewNew(QPaintDevice* paintDevice, bool setAbsolut
plotterStyle.widgetBackgroundBrush=bc;
paintMagnification=oldP;
mathText.setUseUnparsed(false);
return res;
@ -3744,7 +3743,6 @@ void JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
QFile::copy(fn, tempFM);
}
mathText.setUseUnparsed(!jkqtpPaintDeviceAdapters[adapterID]->useLatexParser());
gridPrintingCalc();
QPaintDevice* paintDevice=jkqtpPaintDeviceAdapters[adapterID]->createPaintdevice(fn, jkqtp_roundTo<int>(gridPrintingSize.width()), jkqtp_roundTo<int>(gridPrintingSize.height()));
@ -5104,11 +5102,6 @@ JKQTBasePlotter::textSizeData::textSizeData():
bool JKQTPPaintDeviceAdapter::useLatexParser() const
{
return true;
}
QPaintDevice *JKQTPPaintDeviceAdapter::createPaintdeviceMM(const QString &filename, double widthMM, double heightMM) const
{
#if QT_VERSION>=QT_VERSION_CHECK(6,0,0)

View File

@ -87,7 +87,6 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPaintDeviceAdapter {
virtual double getPrintSizeXInMM() const =0;
virtual double getPrintSizeYInMM() const =0;
virtual bool isPrinter() const=0;
virtual bool useLatexParser() const;
/** \brief create a paint device with a given size in pt */
virtual QPaintDevice* createPaintdevice(const QString& filename, int widthPix, int heightPix) const=0;
/** \brief create a paint device with a given size in millimeters ... the default implementation call createPaintdevice(), assuming the standard logical resolution of the desktop!!!) */

View File

@ -24,6 +24,7 @@
#include "jkqtmathtext/jkqtmathtextlabel.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include "jkqtmathtext/nodes/jkqtmathtextsymbolnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextnodetools.h"
#include <iostream>
void processFont(const QString font, QStringList& fonts, QString& mathFont)
@ -510,6 +511,8 @@ int main(int argc, char* argv[])
<<latex[i].toStdString()<<"\n"
<<"-----------------------------------------------------------\n"
<<mathText.getErrorList().join("\n").toStdString()<<"\n"
<<"-----------------------------------------------------------\n"
<<"RENDERTREE:\n"<<JKQTMathTextNodeTree2String(mathText.getParsedNode()).toStdString()
<<"-----------------------------------------------------------\n"
;
} else if (verbose) {
@ -517,6 +520,8 @@ int main(int argc, char* argv[])
<<"parsing duration: "<<durParseMS<<"ms\n"
<<"-----------------------------------------------------------\n"
<<latex[i].toStdString()<<"\n"
<<"-----------------------------------------------------------\n"
<<"RENDERTREE:\n"<<JKQTMathTextNodeTree2String(mathText.getParsedNode()).toStdString()
<<"-----------------------------------------------------------\n";
}