JKQTMathText: NEW: array/tabular-environments have limited support for formatting string like l|r|c and for \hline , \hdashline , \toprule , \midrule , \bottomrule

This commit is contained in:
jkriege2 2022-08-12 12:54:10 +02:00
parent cda22a9d7a
commit 67579da1bc
41 changed files with 856 additions and 209 deletions

View File

@ -184,12 +184,56 @@
.
\section JKQTMathTextSuppoertedLaTeXTabular Tabular Environments
\see Additional matrix-environments are listed in \ref
For text-mode tables, the \c tabular -environment is supported:
- <code>$\\begin{tabular}{COLSPEC} a & b & ...\\\\ c & d & ...\\end{tabular}$</code>
\c COLSPEC is a LaTeX column specifier, i.e. a sequence composed of these parts:
- \c l : left-aligned column
- \c c : centered column
- \c r : right-aligned column
- \c | : single line
- \c || : double line
- \c : : single dashed line
- \c :: : double dashed line
.
.
In all these environments, you can use the following instructions to draw lines above/below a row in the matrix:
- \c \\hline or \c \\midrule: a single line
- \c \\hline\\hline : a double line
- \c \\toprule or \c \\bottomrule : a heavy line
- \c \\hdashline : a single dashed line
- \c \\hdashline\\hdashline : a double dashed line
.
Here is an example:
\code
\begin{tabular}{:l|cr||}
\hdashline
a1--- & b1--- & c1---\\
a2- & b2- & c2-\\
\hline
a3 & b3 & c3\\
\hline\hline
a4 & b4 & c4\\
\bottomrule
\end{tabular}
\endcode
\image html jkqtmathtext/jkqtmathtext_tabular.png
\section JKQTMathTextSuppoertedLaTeXMathSupport Supported Mathematical Constructs
\subsection JKQTMathTextSuppoertedLaTeXSubSuper Sub- and Superscript
The standard LaTeX sub-/superscript instructions (i.e. \c text_{sub} or \c text^{super} ) are supported:
- \c ^{...} \c _{...} : display the contents of braces in superscript/subscript \image html jkqtmathtext/jkqtmathtext_supersub.png
- \c ^{...} \c _{...} : display the contents of braces in superscript/subscript \image html jkqtmathtext/jkqtmathtext_supersub.png
<br>Special subscript/superscript typesetting applies, when the sub/super follows \c \\sum \c \\Prod ...: \image html jkqtmathtext/jkqtmathtext_specialsubsuper.png
- <code>$\\substack[lrc]{...\\\\...}$</code> allows to e.g. subset several lines below a \c \\sum using \c \\sum\\limits_\\substack{a<5\\\\b<100}: \image html jkqtmathtext/jkqtmathtext_substack.png
- \c \\limits , \c \\nolimits : Several special symbols, like \c \\sum , \c \\lim , ... cause sub-/superscripts to be positioned below/above the symbol, not besides it. This behaviour can be altered by using \c \\limits and \c \\nolimits : \image html jkqtmathtext/jkqtmathtext_limits.png
.
\subsection JKQTMathTextSuppoertedLaTeXBraces Braces/Parantheses ...
@ -235,28 +279,48 @@
.
\subsection JKQTMathTextSuppoertedLaTeXFrac Fraction Type Instructions
Several Matrix/Array-typed LaTeX instructions are supported:
Several fraction-typed LaTeX instructions are supported:
- <code>$\\frac{...}{...}$</code> \image html jkqtmathtext/MTFMfrac.png
- <code>$\\tfrac{...}{...}$</code> (70% smaller font) \image html jkqtmathtext/MTFMtfrac.png
- <code>$\\dfrac{...}{...}$</code> \image html jkqtmathtext/MTFMdfrac.png
- <code>$\\sfrac{...}{...}$</code> \image html jkqtmathtext/MTFMsfrac.png
- <code>$\\stfrac{...}{...}$</code> (70% smaller font) \image html jkqtmathtext/MTFMstfrac.png
- <code>$\\stackrel{...}{...}$ $\\binom{...}{...}$</code> \image html jkqtmathtext/jkqtmathtext_brace_stackrel.png
.
\subsection JKQTMathTextSuppoertedLaTeXMatrix Matrix/Array Type Instructions
Several Matrix/Array-typed LaTeX instructions are supported:
Simple instructions are:
- <code>$\\stackrel{...}{...}$ $\\binom{...}{...}$</code> \image html jkqtmathtext/jkqtmathtext_brace_stackrel.png
.
Several Matrix/Array-typed LaTeX instructions are supported:
- <code>$\\begin{cases} ... & ... \\\\ ... & ... \\end{cases}$</code> \image html jkqtmathtext/jkqtmathtext_brace_begincases.png
- <code>$\\begin{array} a & b & ...\\\\ c & d & ...\\end{array}$</code> <code>$\\begin{matrix} a & b & ...\\\\ c & d & ...\\end{matrix}$</code> \image html jkqtmathtext/jkqtmathtext_array.png
- <code>$\\begin{matrix} a & b & ...\\\\ c & d & ...\\end{matrix}$</code> \image html jkqtmathtext/jkqtmathtext_matrix.png
- <code>$\\begin{pmatrix} a & b & ...\\\\ c & d & ...\\end{pmatrix}$</code> \image html jkqtmathtext/jkqtmathtext_pmatrix.png
- <code>$\\begin{bmatrix} a & b & ...\\\\ c & d & ...\\end{bmatrix}$</code> \image html jkqtmathtext/jkqtmathtext_bmatrix.png
- <code>$\\begin{Bmatrix} a & b & ...\\\\ c & d & ...\\end{Bmatrix}$</code> \image html jkqtmathtext/jkqtmathtext_bbmatrix.png
- <code>$\\begin{vmatrix} a & b & ...\\\\ c & d & ...\\end{vmatrix}$</code> \image html jkqtmathtext/jkqtmathtext_vmatrix.png
- <code>$\\begin{Vmatrix} a & b & ...\\\\ c & d & ...\\end{Vmatrix}$</code> \image html jkqtmathtext/jkqtmathtext_vvmatrix.png
- <code>$\\substack[lrc]{...\\\\...}$</code> \image html jkqtmathtext/jkqtmathtext_substack.png
- <code>$\\lsubstack{...\\\\...}$</code> \image html jkqtmathtext/jkqtmathtext_lsubstack.png
- <code>$\\rsubstack{...\\\\...}$</code> \image html jkqtmathtext/jkqtmathtext_rsubstack.png
.
- <code>$\\begin{array}{COLSPEC} a & b & ...\\\\ c & d & ...\\end{array}$</code> \image html jkqtmathtext/jkqtmathtext_array.png
\c COLSPEC is a LaTeX column specifier, i.e. a sequence composed of these parts:
- \c l : left-aligned column
- \c c : centered column
- \c r : right-aligned column
- \c | : single line
- \c || : double line
- \c : : single dashed line
- \c :: : double dashed line
.
.
In all these environments, you can use the following instructions to draw lines above/below a row in the matrix:
- \c \\hline or \c \\midrule: a single line
- \c \\hline\\hline : a double line
- \c \\toprule or \c \\bottomrule : a heavy line
- \c \\hdashline : a single dashed line
- \c \\hdashline\\hdashline : a double dashed line
.

View File

@ -41,7 +41,6 @@ This page lists several todos and wishes for future version of JKQTPlotter
<li>JKQTMathText:<ul>
<li>check sub/superscript with italic text in math mode, possibly a correction is necessary</li>
<li>explore options to make font-environment-modifying commands avails, like "{blacktext\\color{red}redtext}", today only commands like "\\textcolor{red}{redtext}" work</li>
<li>improve support for array-environment with limited support for formatting string like l|r|c and maybe add support for \\hline command, possibly also \\cellcolor etz.</li>
<li></li>
</ul></li>
</ul>

View File

@ -89,6 +89,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: additional method JKQTMathtext::getSizeDetail() that returns all size-properties as a convenient struct, also added matching varinat JKQTMathTextNode::getSize() </li>
<li>NEW: additional method JKQTMathtext::drawIntoPixmap(), JKQTMathtext::drawIntoPicture(), JKQTMathtext::drawIntoImage() which returns a QPixmap, QPicture and QImage respectively that contains the render result of the currently parsed markup</li>
<li>NEW: added command line tool \ref JKQTMathTextRenderCmdLineTool that renders LaTeX into images, using it to generate the documentation images for JKQTMathText</li>
<li>NEW: array/tabular-environments have limited support for formatting string like \c l|r|c and for \c \\hline , \c \\hdashline , \c \\toprule , \c \\midrule , \c \\bottomrule</li>
</ul></li>
</ul>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 995 B

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 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: 9.2 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -84,7 +84,7 @@ jkqtmathtext_mathdeco.png
$\vec{x}\ \dot{x}\ \ddot{x}\ \overline{x}\ \underline{x}\ \hat{x}\ \tilde{x}\ \uul{x}\ \ool{x}\ \bar{x}\ \arrow{x}\ \widehat{x}\ \widetilde{x}\ ...$
---
jkqtmathtext_textaccents.png
\begin{array}
\begin{array}{llll}
{\backslash}"A: & \"A\"a & {\backslash}`A: & \`A\`a \\
{\backslash}'A: & \'A\'a &{\backslash}{\circonflex}A: & \^A\^a \\
{\backslash}{\sim}A: & \~A\~a &{\backslash}r\{A\}: & \r{A}\r{a} \\
@ -96,7 +96,7 @@ jkqtmathtext_textaccents.png
\end{array}
---
jkqtmathtext_mathaccents.png
\begin{array}
\begin{array}{llll}
{\backslash}dot\{A\}: & $\dot{A}\dot{a}$ & {\backslash}ddot\{A\}: & $\ddot{A}\ddot{a}$ \\
{\backslash}grave\{A\}: & $\grave{A}\grave{a}$ & {\backslash}acute\{A\}: & $\acute{A}\acute{a}$ \\
{\backslash}acute\{A\}: & $\acute{A}\acute{a}$ & {\backslash}tilde\{A\}: & $\tilde{A}\tilde{a}$ \\

View File

@ -1,7 +1,4 @@
---
jkqtmathtext_brace_array.png
$\left\langle\begin{array}a&b&...\\ c&d&...\end{array}\right\rangle$
---
jkqtmathtext_brace_bbig.png
$\Bigl[\Bigl(r^{123}\Bigr)\Bigr]$
---

View File

@ -28,8 +28,11 @@ jkqtmathtext_substack.png
{\backslash}substack: $\sum\limits_\substack{0\leq i\leq10\\-5\leq j\leq1000}f_{i,j}$
---
jkqtmathtext_mathmode_and_textmode.png
\begin{array}text: & abc123+d/e\\ math: & $abc123+d/e$\end{array}
\begin{matrix}text: & abc123+d/e\\ math: & $abc123+d/e$\end{matrix}
---
jkqtmathtext_mathoperator_width_factor.png
--showboxes
\begin{array}Math: $a=b$ & text: a=b\\\textcolor{blue}{extra space}&\textcolor{blue}{normal spacing}\end{array}
\begin{matrix}Math: $a=b$ & text: a=b\\\textcolor{blue}{extra space}&\textcolor{blue}{normal spacing}\end{matrix}
---
jkqtmathtext_limits.png
no specifier: $\sum_{i=0}^\infty k_i^2\ \ \lim_{x\rightarrow0}f(x)\ \ \nabla_{x}f(x)$ \ \ \ \ \ {\backslash}limits: $\sum\limits_{i=0}^\infty k_i^2\ \ \lim\limits_{x\rightarrow0}f(x)\ \ \nabla\limits_{x}f(x)$ \ \ \ \ \ {\backslash}nolimits: $\sum\nolimits_{i=0}^\infty k_i^2\ \ \lim\nolimits_{x\rightarrow0}f(x)\ \ \nabla\nolimits_{x}f(x)$

View File

@ -1,6 +1,6 @@
---
jkqtmathtext_array.png
$\begin{array}a&b&...\\ c&d&...\end{array}$
jkqtmathtext_matrix.png
$\mat{M}_1=\begin{matrix}a&b&...\\ c&d&...\end{matrix}\ \ \ \ \ \ \mat{M}_2=\left\langle\begin{matrix}a&b&...\\ c&d&...\end{matrix}\right\rangle$
---
jkqtmathtext_bmatrix.png
$\begin{bmatrix}a&b&...\\ c&d&...\end{bmatrix}$
@ -18,4 +18,30 @@ jkqtmathtext_vvmatrix.png
$\begin{Vmatrix}a&b&...\\ c&d&...\end{Vmatrix}$
---
jkqtmathtext_brace_begincases.png
$f(x)=\begin{cases}\sfrac{1}{2} & \text{if} 0\leq x\leq 1 \\ \sfrac{2}{3} & \text{if} 3\leq x\leq 4 \\ 0 & \text{elsewhere} \end{cases}$
$f(x)=\begin{cases}\sfrac{1}{2} & \text{if}\ 0\leq x\leq 1 \\ \sfrac{2}{3} & \text{if}\ 3\leq x\leq 4 \\ 0 & \text{elsewhere} \end{cases}$
---
jkqtmathtext_tabular.png
\begin{tabular}{:l|cr||}
\hdashline
a1--- & b1--- & c1---\\
a2- & b2- & c2-\\
\hline
a3 & b3 & c3\\
\hline\hline
a4 & b4 & c4\\
\bottomrule
\end{tabular}
---
jkqtmathtext_array.png
$\mat{M}_\cdot=\begin{array}{l:ll}
\alpha & a & \ldots \\
\hdashline
\beta & b & \ldots \\
\vdots & \vdots & \ddots \\
\end{array}
\ \ \ \ \ \mat{M}_{()}=\left(\begin{array}{l:ll}
\alpha & a & \ldots \\
\hdashline
\beta & b & \ldots \\
\vdots & \vdots & \ddots \\
\end{array}\right)$

View File

@ -97,6 +97,8 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbTestset->addItem("text: framed", "\\begin{framed}text\\\\\\textbf{2^{nd} line of text}\\\\last \\textit{line!} $\\frac{1}{2}$\\end{framed}");
ui->cmbTestset->addItem("text: shaded", "\\begin{shaded}text\\\\\\textbf{2^{nd} line of text}\\\\last \\textit{line!} $\\frac{1}{2}$\\end{shaded}");
ui->cmbTestset->addItem("text: snugshade", "\\begin{snugshade}text\\\\\\textbf{2^{nd} line of text}\\\\last \\textit{line!} $\\frac{1}{2}$\\end{snugshade}");
ui->cmbTestset->addItem("text: tabular", "\\begin{tabular}{:l|cr||}\\hdashline a1--- & b1-- & c1---\\\\ a2-- & b2\\_ & c2\\_\\\\\\hline a3 & b3 & c3\\\\\\hline\\hline a4 & b4 & c4\\\\\\bottomrule\\end{tabular}");
ui->cmbTestset->addItem("math: array", "$\\mat{M}=\\left(\\begin{array}{l:ll} \\alpha & a & \\ldots \\\\ \\hdashline \\beta & b & \\ldots \\\\ \\vdots & \\vdots & \\ddots \\\\ \\end{array}\\right)$");
ui->cmbTestset->addItem("mathtest", "This is normal text: $this is math:\\langle r^2(\\tau)\\rangle=\\left\\langle (\\vec{r}(t)-\\vec{r}(t+\\tau) )^2\\right\\rangle\\ \\ \\ g(\\tau)=\\frac{1}{N}\\cdot\\left(1+\\frac{2}{3}\\frac{\\langle r^2(\\tau)\\rangle}{w_{xy}^2}\\right)^{-1} \\lfloor\\rfloor\\lceil\\rceil\\langle\\rangle\\left\\{\\vec{a}\\left|\\|\\vec{a}\\|_2\\geq2\\right.\\right\\} \\vec{r}\\vec{R}\\frac{\\sqrt{\\sqrt{\\sqrt{\\sum_{i=0}^\\infty \\hat{i}^2}+y^\\alpha}+1}}{\\dot{v}\\equiv\\ddot{r}}\\argmin_{\\vec{k}}\\sum_{\\sqrt{i}=0}^{N}\\int_{x_0}^{x_1}\\left(\\left(\\left(x\\right)\\right)\\right)\\underbrace{\\left[\\left\\{\\frac{\\partial f}{\\partial x}\\right\\}\\cdot\\frac{1}{2}\\right]}{\\text{underbraced text \\hbar}}\\cdots\\frac{\\sqrt{\\sum_{i=0}^2 \\hat{i}^2}+y^\\alpha}{\\dot{v}\\equiv\\ddot{r}}, \\hat{t}\\hat{T} \\overbrace{\\left|\\sqrt{x\\cdot Y}\\right|}{\\propto\\bbN\\circ\\bbZ} \\left<\\arrow{x(\\tau)}\\cdot\\vec{R}(t+\\bar{\\tau})\\right> \\alpha\\beta\\gamma\\delta\\epsilon\\Gamma\\Delta\\Theta\\Omega \\left\\_\\left~\\cbrt{\\hbar\\omega}\\right~\\right\\_$");
ui->cmbTestset->addItem("math: upper/lower parantheses test:", "$\\text{bblabla} \\frac{1}{2}\\cdot\\left(\\frac{1}{\\mathrm{e}^x+\\mathrm{e}^{-x}}\\right)\\cdot\\left(\\frac{1}{\\frac{1+2}{5+x}}\\right)\\cdot\\left(\\frac{1}{\\exp\\left[-\\frac{y^2}{\\sqrt{x}}\\right]\\cdot\\exp\\left[-\\frac{1}{\\frac{1}{2}}\\right]}\\right) $");
ui->cmbTestset->addItem("math: ACF test", "$g_{rg}^{ab}(\\tau)=\\frac{1}{N}\\cdot\\left(1+\\frac{2}{3}\\frac{\\langle r^2(\\tau)\\rangle}{w_{xy}^2}\\right)^{-1}\\cdot\\left(1+\\frac{2}{3}\\frac{\\langle r^2(\\tau)\\rangle}{w_{xy}^2}\\right)^{-\\frac{1}{2}}$");

View File

@ -99,6 +99,14 @@ JKQTMathText::JKQTMathText(QObject* parent):
sqrt_height_factor=1.2;
sqrt_smallfont_factor=0.57;
matrix_linewidth_thin_factor=0.4;
matrix_linewidth_heavy_factor=1.5;
matrix_line_separation_factor=2.0;
matrix_xSeparation_factor=0.5;
matrix_ySeparation_factor=0.5;
matrix_xPadding_factor=0.5;
matrix_yPadding_factor=0.5;
blackboradFontMode=MTBBDMdefault;
@ -231,6 +239,13 @@ void JKQTMathText::loadSettings(const QSettings& settings, const QString& group)
bigmathoperator_font_factor=settings.value(group+"bigmathoperator_font_factor", bigmathoperator_font_factor).toDouble();
frac_nested_factor=settings.value(group+"frac_nested_factor", frac_nested_factor).toDouble();
matrix_linewidth_thin_factor=settings.value(group+"matrix_linewidth_thin_factor", matrix_linewidth_thin_factor).toDouble();
matrix_linewidth_heavy_factor=settings.value(group+"matrix_linewidth_heavy_factor", matrix_linewidth_heavy_factor).toDouble();
matrix_line_separation_factor=settings.value(group+"matrix_line_separation_factor", matrix_line_separation_factor).toDouble();
matrix_xSeparation_factor=settings.value(group+"matrix_xSeparation_factor", matrix_xSeparation_factor).toDouble();
matrix_ySeparation_factor=settings.value(group+"matrix_ySeparation_factor", matrix_ySeparation_factor).toDouble();
matrix_xPadding_factor=settings.value(group+"matrix_xPadding_factor", matrix_xPadding_factor).toDouble();
matrix_yPadding_factor=settings.value(group+"matrix_yPadding_factor", matrix_yPadding_factor).toDouble();
if (settings.value(group+"use_stix_fonts", false).toBool()) useSTIX();
if (settings.value(group+"use_xits_fonts", false).toBool()) useXITS();
@ -272,6 +287,13 @@ void JKQTMathText::saveSettings(QSettings& settings, const QString& group) const
settings.setValue(group+ "sqrt_smallfont_factor", sqrt_smallfont_factor);
settings.setValue(group+ "bigmathoperator_font_factor", bigmathoperator_font_factor);
settings.setValue(group+ "frac_nested_factor", frac_nested_factor);
settings.setValue(group+ "matrix_linewidth_thin_factor", matrix_linewidth_thin_factor);
settings.setValue(group+ "matrix_linewidth_heavy_factor", matrix_linewidth_heavy_factor);
settings.setValue(group+ "matrix_line_separation_factor", matrix_line_separation_factor);
settings.setValue(group+ "matrix_xSeparation_factor", matrix_xSeparation_factor);
settings.setValue(group+ "matrix_ySeparation_factor", matrix_ySeparation_factor);
settings.setValue(group+ "matrix_xPadding_factor", matrix_xPadding_factor);
settings.setValue(group+ "matrix_yPadding_factor", matrix_yPadding_factor);
}
bool JKQTMathText::useSTIX(bool mathModeOnly) {
@ -966,6 +988,76 @@ double JKQTMathText::getSqrtSmallFontFactor() const
return sqrt_smallfont_factor;
}
double JKQTMathText::getMatrixLinewidthThinFactor()
{
return matrix_linewidth_thin_factor;
}
void JKQTMathText::setMatrixLinewidthThinFactor(double factor)
{
matrix_linewidth_thin_factor=factor;
}
double JKQTMathText::getMatrixLinewidthHeavyFactor()
{
return matrix_linewidth_heavy_factor;
}
void JKQTMathText::setMatrixLinewidthHeavyFactor(double factor)
{
matrix_linewidth_heavy_factor=factor;
}
double JKQTMathText::getMatrixLineSeparationFactor()
{
return matrix_line_separation_factor;
}
void JKQTMathText::setMatrixLineSeparationFactor(double factor)
{
matrix_line_separation_factor=factor;
}
double JKQTMathText::getMatrixXSeparationFactor()
{
return matrix_xSeparation_factor;
}
void JKQTMathText::setMatrixXSeparationFactor(double factor)
{
matrix_xSeparation_factor=factor;
}
double JKQTMathText::getMatrixYSeparationFactor()
{
return matrix_ySeparation_factor;
}
void JKQTMathText::setMatrixYSeparationFactor(double factor)
{
matrix_ySeparation_factor=factor;
}
double JKQTMathText::getMatrixXPaddingFactor()
{
return matrix_xPadding_factor;
}
void JKQTMathText::setMatrixXPaddingFactor(double factor)
{
matrix_xPadding_factor=factor;
}
double JKQTMathText::getMatrixYPaddingFactor()
{
return matrix_yPadding_factor;
}
void JKQTMathText::setMatrixYPaddingFactor(double factor)
{
matrix_yPadding_factor=factor;
}
void JKQTMathText::setUseUnparsed(bool __value)
{
this->useUnparsed = __value;
@ -1531,6 +1623,7 @@ void JKQTMathText::giveBackToTokenizer(size_t count)
}
JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType quitOnClosingBrace, const QString& quitOnEnvironmentEnd, bool quitOnClosingBracket) {
QMap<QString,size_t> countLine;
//std::cout<<" entering parseLatexString()\n";
JKQTMathTextHorizontalListNode* nl=new JKQTMathTextHorizontalListNode(this);
if (get) getToken();
@ -1593,6 +1686,12 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true);
} else if (currentInstructionName=="nolimits") {
if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false);
} else if (currentInstructionName=="hline" || currentInstructionName=="midrule") {
countLine["hline"]=countLine.value("hline",0)+1;
} else if (currentInstructionName=="hdashline") {
countLine["hdashline"]=countLine.value("hdashline",0)+1;
} else if (currentInstructionName=="toprule" || currentInstructionName=="bottomrule") {
countLine["heavyline"]=countLine.value("heavyline",0)+1;
} else if (currentInstructionName=="right") {
getToken();
if (currentToken==MTTtext) {
@ -1717,34 +1816,89 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
} else if (currentToken==MTTinstructionBegin) {
const QString envname=currentTokenName;
if (envname=="matrix" || envname=="array" || envname=="aligned" || envname=="align" || envname=="cases" || envname=="pmatrix"|| envname=="bmatrix"|| envname=="Bmatrix"|| envname=="vmatrix"|| envname=="Vmatrix") {
if (envname=="matrix" || envname=="array" || envname=="aligned" || envname=="align" || envname=="cases" || envname=="pmatrix"|| envname=="bmatrix"|| envname=="Bmatrix"|| envname=="vmatrix"|| envname=="Vmatrix" || envname=="tabular") {
QString colspec="";
if (envname=="tabular" || envname=="array") {
if (getToken()==MTTopenbrace) {
colspec=readUntil(true, "}");
} else {
error_list.append(tr("error @ ch. %1: expected {COLUMNSPEC} after '\\begin{%2}'").arg(currentTokenID).arg(envname));
}
}
JKQTMathTextMatrixNode* matrixNode=new JKQTMathTextMatrixNode(this, colspec);
QVector< QVector<JKQTMathTextNode*> > items;
//int lines=0;
//int cols=0;
bool first=true;
bool firstLine=true;
QVector<JKQTMathTextNode*> line;
size_t colCount=0;
//std::cout<<"found \\begin{matrix}\n";
while (first || currentToken==MTTampersand || currentToken==MTTinstructionNewline) {
JKQTMathTextNode* it=parseLatexString(true, MTBTAny, envname);
while (getToken()==MTTwhitespace) ; // eat whitespace
JKQTMathTextNode* it=simplifyAndTrimJKQTMathTextNode(parseLatexString(false, MTBTAny, envname));
if (firstLine) {
if (lastLineCount.value("hline",0)==1) {
matrixNode->setTopLine(JKQTMathTextMatrixNode::LTline);
} else if (lastLineCount.value("hline",0)>1) {
matrixNode->setTopLine(JKQTMathTextMatrixNode::LTdoubleline);
} else if (lastLineCount.value("heavyline",0)>0) {
matrixNode->setTopLine(JKQTMathTextMatrixNode::LTheavyline);
} else if (lastLineCount.value("hdashline",0)==1) {
matrixNode->setTopLine(JKQTMathTextMatrixNode::LTdashed);
} else if (lastLineCount.value("hdashline",0)>1) {
matrixNode->setTopLine(JKQTMathTextMatrixNode::LTdoubleDashed);
}
} else {
if (lastLineCount.value("hline",0)==1) {
matrixNode->setRowBottomLine(items.size()-1, JKQTMathTextMatrixNode::LTline);
} else if (lastLineCount.value("hline",0)>1) {
matrixNode->setRowBottomLine(items.size()-1, JKQTMathTextMatrixNode::LTdoubleline);
} else if (lastLineCount.value("heavyline",0)>0) {
matrixNode->setRowBottomLine(items.size()-1, JKQTMathTextMatrixNode::LTheavyline);
} else if (lastLineCount.value("hdashline",0)==1) {
matrixNode->setRowBottomLine(items.size()-1, JKQTMathTextMatrixNode::LTdashed);
} else if (lastLineCount.value("hdashline",0)>1) {
matrixNode->setRowBottomLine(items.size()-1, JKQTMathTextMatrixNode::LTdoubleDashed);
}
}
if (currentToken==MTTampersand) {
//std::cout<<" appending item\n";
line.append(it);
} else {
line.append(it);
//std::cout<<" appending item and line with "<<line.size()<<" items.\n";
items.append(line);
if (currentToken==MTTinstructionEnd) {
JKQTMathTextMultiChildNode* mnc=dynamic_cast<JKQTMathTextMultiChildNode*>(it);
if (mnc && mnc->childCount()>0) {
line.append(it);
} else {
line.append(it);
}
} else {
line.append(it);
}
if (currentToken==MTTinstructionNewline || line.size()>0) {
colCount=qMax(colCount, static_cast<size_t>(line.size()));
if (line.size()==0 || (line.size()>1 && line.size()==colCount)) {
items.append(line);
} else if (line.size()>1 && line.size()!=colCount) {
error_list.append(tr("error @ ch. %1: wrong number of entries widthin '\\begin{%2}...\\end{%2}'").arg(currentTokenID).arg(envname));
}
}
line.clear();
firstLine=false;
}
first=false;
}
//std::cout<<" creating matrix-node with "<<items.size()<<" items.\n";
if (envname=="pmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="cases") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTNone, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTCurlyBracket, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSingleLine, MTBTSingleLine, new JKQTMathTextMatrixNode(this, items)));
else if (envname=="Vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTDoubleLine, MTBTDoubleLine, new JKQTMathTextMatrixNode(this, items)));
else nl->addChild(new JKQTMathTextMatrixNode(this, items));
matrixNode->setChildren(items);
if (envname=="pmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, matrixNode));
else if (envname=="cases") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTNone, matrixNode));
else if (envname=="bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, matrixNode));
else if (envname=="Bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTCurlyBracket, matrixNode));
else if (envname=="vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSingleLine, MTBTSingleLine, matrixNode));
else if (envname=="Vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTDoubleLine, MTBTDoubleLine, matrixNode));
else nl->addChild(matrixNode);
//std::cout<<" creating matrix-node ... done!\n";
} else if (envname=="center" || envname=="document" || envname=="flushleft" || envname=="flushright") {
JKQTMathTextHorizontalAlignment alignment=MTHALeft;
@ -1795,6 +1949,8 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
if (getNew) getToken();
}
//std::cout<<" leaving parseLatexString()\n";
lastLineCount=countLine;
return simplifyJKQTMathTextNode(nl);
}
@ -2126,6 +2282,8 @@ bool JKQTMathText::parse(const QString& text, bool addSpaceBeforeAndAfter){
currentToken=MTTnone;
currentTokenName="";
parsingMathEnvironment=false;
lastLineCount.clear();
error_list.clear();
parsedNode=parseLatexString(true);
unparsedNode=new JKQTMathTextVerbatimNode(this, text);

View File

@ -606,6 +606,35 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
/** \copydoc sqrt_smallfont_factor */
double getSqrtSmallFontFactor() const;
/** \copydoc matrix_linewidth_thin_factor */
double getMatrixLinewidthThinFactor();
/** \copydoc matrix_linewidth_thin_factor */
void setMatrixLinewidthThinFactor(double factor);
/** \copydoc matrix_linewidth_heavy_factor */
double getMatrixLinewidthHeavyFactor();
/** \copydoc matrix_linewidth_heavy_factor */
void setMatrixLinewidthHeavyFactor(double factor);
/** \copydoc matrix_line_separation_factor */
double getMatrixLineSeparationFactor();
/** \copydoc matrix_line_separation_factor */
void setMatrixLineSeparationFactor(double factor);
/** \copydoc matrix_xSeparation_factor */
double getMatrixXSeparationFactor();
/** \copydoc matrix_xSeparation_factor */
void setMatrixXSeparationFactor(double factor);
/** \copydoc matrix_ySeparation_factor */
double getMatrixYSeparationFactor();
/** \copydoc matrix_ySeparation_factor */
void setMatrixYSeparationFactor(double factor);
/** \copydoc matrix_xPadding_factor */
double getMatrixXPaddingFactor();
/** \copydoc matrix_xPadding_factor */
void setMatrixXPaddingFactor(double factor);
/** \copydoc matrix_yPadding_factor */
double getMatrixYPaddingFactor();
/** \copydoc matrix_yPadding_factor */
void setMatrixYPaddingFactor(double factor);
/** \copydoc useUnparsed */
@ -798,6 +827,43 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
double sqrt_width_Xfactor;
/** \brief height-increase of the sqrt-symbol, as factor of the child's height */
double sqrt_height_factor;
/** \brief width of thin table lines, this factor is multiplied with the current \c font.linewidth()
*
* \image html jkqtmathtext/jkqtmathtext_matrix_geometry.png
*/
double matrix_linewidth_thin_factor;
/** \brief width of heavy table lines, this factor is multiplied with the current \c font.linewidth()
*
* \image html jkqtmathtext/jkqtmathtext_matrix_geometry.png
*/
double matrix_linewidth_heavy_factor;
/** \brief separation of double-lines in tables, this factor is multiplied with the \c font.linewidth()
*
* \image html jkqtmathtext/jkqtmathtext_matrix_geometry.png
*/
double matrix_line_separation_factor;
/** \brief x-separation of two columns, this factor is multiplied with the \c font.width("x")
*
* \image html jkqtmathtext/jkqtmathtext_matrix_geometry.png
*/
double matrix_xSeparation_factor;
/** \brief y-separation of two columns, this factor is multiplied with the \c font.width("x")
*
* \image html jkqtmathtext/jkqtmathtext_matrix_geometry.png
*/
double matrix_ySeparation_factor;
/** \brief x-padding of two columns, this factor is multiplied with the \c font.width("x")
*
* \image html jkqtmathtext/jkqtmathtext_matrix_geometry.png
*/
double matrix_xPadding_factor;
/** \brief y-padding of two columns, this factor is multiplied with the \c font.width("x")
*
* \image html jkqtmathtext/jkqtmathtext_matrix_geometry.png
*/
double matrix_yPadding_factor;
/** \brief a list that will be filled with error messages while parsing, if any error occur
*
* This list of errors is (mostly) filled during a call to parse(). During rendering (e.g. with draw() )
@ -891,6 +957,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
tokenType currentToken;
/** \brief the JKQTMathTextBraceType associated with the last \c \\right command the parser encountered */
JKQTMathTextBraceType lastRightBraceType;
/** \brief returns the number of \c \\hline , \c \\hdashline , ... commands in the last parseLatexString() call */
QMap<QString,size_t> lastLineCount;
/** \brief used by the tokenizer. Name of the current token, id applicable */
QString currentTokenName;
/** \brief used by the tokenizer. Points to the currently read character in parseString */

View File

@ -553,6 +553,14 @@ void JKQTMathTextHorizontalListNode::clearChildren(bool deleteChildren)
clearChildrenImpl(deleteChildren);
}
void JKQTMathTextHorizontalListNode::deleteChild(int i)
{
if (i>=0 && i<nodes.size()) {
delete nodes[i];
nodes.remove(i);
}
}
JKQTMathTextNode *JKQTMathTextHorizontalListNode::getChild(int i)
{
return nodes[i];
@ -748,6 +756,13 @@ void JKQTMathTextVerticalListNode::clearChildrenImpl(bool deleteChildren)
nodes.clear();
}
void JKQTMathTextVerticalListNode::deleteChild(int i)
{
if (i>=0 && i<nodes.size()) {
delete nodes[i];
nodes.remove(i);
}
}
void JKQTMathTextVerticalListNode::clearChildren(bool deleteChildren)
{
clearChildrenImpl(deleteChildren);

View File

@ -60,6 +60,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextHorizontalListNode: public JKQTMathTex
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() */
@ -122,6 +124,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerticalListNode: public JKQTMathTextM
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() */

View File

@ -38,20 +38,29 @@
JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText* _parent, QVector<QVector<JKQTMathTextNode*> > children):
JKQTMathTextNode(_parent)
JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText* _parent, const QVector<QVector<JKQTMathTextNode *> > &children, const QString &columnSpec):
JKQTMathTextNode(_parent),
verticalLineRHSColumn(),
verticalLineLeft(LTnone),
horizontalLineBottomRow(),
horizontalLineTop(LTnone),
columns(0),
lines(0)
{
this->lines=children.size();
this->columns=0;
for (int i=0; i<children.size(); i++) {
if (children[i].size()>this->columns) this->columns=children[i].size();
}
this->children=children;
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
children[i].operator[](j)->setParentNode(this);
}
}
setChildren(children);
parseColumnSpec(columnSpec);
}
JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText *_parent, const QString &columnSpec):
JKQTMathTextNode(_parent),
verticalLineRHSColumn(),
verticalLineLeft(LTnone),
horizontalLineBottomRow(),
horizontalLineTop(LTnone),
columns(0),
lines(0)
{
parseColumnSpec(columnSpec);
}
JKQTMathTextMatrixNode::~JKQTMathTextMatrixNode() {
@ -63,113 +72,36 @@ JKQTMathTextMatrixNode::~JKQTMathTextMatrixNode() {
children.clear();
}
void JKQTMathTextMatrixNode::setChildren(const QVector<QVector<JKQTMathTextNode *> > &children)
{
this->lines=children.size();
this->columns=0;
for (int i=0; i<children.size(); i++) {
if (children[i].size()>this->columns) this->columns=children[i].size();
}
this->children=children;
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
children[i].operator[](j)->setParentNode(this);
}
}
}
void JKQTMathTextMatrixNode::setRowBottomLine(int col, LineType line)
{
horizontalLineBottomRow[col]=line;
}
void JKQTMathTextMatrixNode::setTopLine(LineType line)
{
horizontalLineTop=line;
}
QString JKQTMathTextMatrixNode::getTypeName() const
{
return "MTmatrixNode";
}
void JKQTMathTextMatrixNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
JKQTMathTextEnvironment ev1=currentEv;
double xh=fm.strikeOutPos();//fm.xHeight();
//double Ah=fm.ascent();
double xw=fm.boundingRect("x").width();
//ev1.fontSize=ev1.fontSize*parent->getFracFactor();
QVector<double> colwidth, rowheight;
//QVector<QVector<double> > widths, heights, baselines;
double width1=0, baselineHeight1=0, overallHeight1=0, strikeoutPos1=0;
//widths.resize(lines);
colwidth.resize(columns); for (int i=0; i<columns; i++) colwidth[i]=0;
rowheight.resize(lines);
//heights=baselines=widths;
for (int i=0; i<lines; i++) {
rowheight[i]=0;
//widths[i].resize(columns);
//baselines[i]=heights[i]=widths[i];
for (int j=0; j<children[i].size(); j++) {
children[i].at(j)->getSize(painter, ev1, width1, baselineHeight1, overallHeight1, strikeoutPos1);
/*widths[i].operator[](j)=width1;
baselines[i].operator[](j)=baselineHeight;
heights[i].operator[](j)=overallHeight1;*/
if (overallHeight1>rowheight[i]) rowheight[i]=overallHeight1;
if (width1>colwidth[j]) colwidth[j]=width1;
}
}
overallHeight=(lines-1)*xw/2.0;
width=columns*xw;
for (int i=0; i<columns; i++) width=width+colwidth[i];
for (int i=0; i<lines; i++) overallHeight=overallHeight+rowheight[i];
baselineHeight=overallHeight/2.0+xh;
strikeoutPos=xh;
}
double JKQTMathTextMatrixNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
JKQTMathTextEnvironment ev1=currentEv;
double xh=fm.strikeOutPos();//fm.xHeight();
//double Ah=fm.ascent();
double xw=fm.boundingRect("x").width();
//ev1.fontSize=ev1.fontSize;*parent->getFracFactor();
QVector<double> colwidth, rowheight, rowascent;
//QVector<QVector<double> > widths, heights, baselines;
double width1=0, baselineHeight1=0, overallHeight1=0, strikeoutPos=0;
//widths.resize(lines);
colwidth.resize(columns); for (int i=0; i<columns; i++) colwidth[i]=0;
rowheight.resize(lines);
rowascent.resize(lines);
//heights=baselines=widths;
for (int i=0; i<lines; i++) {
rowheight[i]=0;
rowascent[i]=0;
//widths[i].resize(columns);
//baselines[i]=heights[i]=widths[i];
for (int j=0; j<children[i].size(); j++) {
if (children[i].at(j)!=nullptr) children[i].at(j)->getSize(painter, ev1, width1, baselineHeight1, overallHeight1, strikeoutPos);
/*widths[i].operator[](j)=width1;
baselines[i].operator[](j)=baselineHeight;
heights[i].operator[](j)=overallHeight1;*/
if (overallHeight1>rowheight[i]) rowheight[i]=overallHeight1;
if (baselineHeight1>rowascent[i]) rowascent[i]=baselineHeight1;
if (width1>colwidth[j]) colwidth[j]=width1;
}
}
double overallHeight=(lines-1)*xw/2.0;
double width=(columns)*xw;
for (int i=0; i<columns; i++) width=width+colwidth[i];
for (int i=0; i<lines; i++) overallHeight=overallHeight+rowheight[i];
double baselineHeight=overallHeight/2.0+xh;
double xx=x;
double yy=y-baselineHeight;
if (lines>0) yy=yy+rowascent[0];
for (int i=0; i<lines; i++) {
xx=x;
for (int j=0; j<children[i].size(); j++) {
children[i].at(j)->draw(painter, xx, yy, ev1);
xx=xx+colwidth[j]+xw;
}
if (i<lines-1) yy=yy+(rowheight[i]-rowascent[i])+xw/2.0+rowascent[i+1];
}
return x+width;
}
bool JKQTMathTextMatrixNode::toHtml(QString &/*html*/, JKQTMathTextEnvironment /*currentEv*/, JKQTMathTextEnvironment /*defaultEv*/)
{
@ -188,6 +120,7 @@ int JKQTMathTextMatrixNode::getLines() const {
return this->lines;
}
void JKQTMathTextMatrixNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
@ -199,5 +132,204 @@ void JKQTMathTextMatrixNode::setDrawBoxes(bool draw)
}
void JKQTMathTextMatrixNode::drawVLine(QPainter &painter, double x, double y, double height, LineType lt, double linewidth, double linewidthHeavy, QColor color, double doublelineseparation)
{
if (lt==LTnone) return;
QPen p(color, linewidth, Qt::SolidLine);
if (lt==LTdashed || lt==LTdoubleDashed) p.setStyle(Qt::DashLine);
if (lt==LTheavyline) p.setWidth(linewidthHeavy);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(p);
if (lt==LTline || lt==LTdashed || lt==LTheavyline) {
painter.drawLine(QPointF(x,y), QPointF(x,y+height));
} else if (lt==LTdoubleline || lt==LTdoubleDashed) {
painter.drawLine(QPointF(x-doublelineseparation/2.0,y), QPointF(x-doublelineseparation/2.0,y+height));
painter.drawLine(QPointF(x+doublelineseparation/2.0,y), QPointF(x+doublelineseparation/2.0,y+height));
}
}
void JKQTMathTextMatrixNode::drawHLine(QPainter &painter, double x, double y, double width, LineType lt, double linewidth, double linewidthHeavy, QColor color, double doublelineseparation)
{
if (lt==LTnone) return;
QPen p(color, linewidth, Qt::SolidLine);
if (lt==LTdashed || lt==LTdoubleDashed) p.setStyle(Qt::DashLine);
if (lt==LTheavyline) p.setWidth(linewidthHeavy);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(p);
if (lt==LTline || lt==LTdashed || lt==LTheavyline) {
painter.drawLine(QPointF(x,y), QPointF(x+width,y));
} else if (lt==LTdoubleline || lt==LTdoubleDashed) {
painter.drawLine(QPointF(x,y-doublelineseparation/2.0), QPointF(x+width,y-doublelineseparation/2.0));
painter.drawLine(QPointF(x,y+doublelineseparation/2.0), QPointF(x+width,y+doublelineseparation/2.0));
}
}
void JKQTMathTextMatrixNode::parseColumnSpec(const QString &columnSpec)
{
int i=0;
while (i<columnSpec.size()) {
if (columnSpec[i]=='l') {
columnAlignment<<MTHALeft;
} else if (columnSpec[i]=='c') {
columnAlignment<<MTHACentered;
} else if (columnSpec[i]=='r') {
columnAlignment<<MTHARight;
} else if (columnSpec.mid(i,2)=="||") {
if (columnAlignment.size()==0) {
verticalLineLeft=LTdoubleline;
} else {
verticalLineRHSColumn[columnAlignment.size()-1]=LTdoubleline;
}
i++;
} else if (columnSpec.mid(i,2)=="::") {
if (columnAlignment.size()==0) {
verticalLineLeft=LTdoubleDashed;
} else {
verticalLineRHSColumn[columnAlignment.size()-1]=LTdoubleDashed;
}
i++;
} else if (columnSpec.mid(i,1)=="|") {
if (columnAlignment.size()==0) {
verticalLineLeft=LTline;
} else {
verticalLineRHSColumn[columnAlignment.size()-1]=LTline;
}
} else if (columnSpec.mid(i,1)==":") {
if (columnAlignment.size()==0) {
verticalLineLeft=LTdashed;
} else {
verticalLineRHSColumn[columnAlignment.size()-1]=LTdashed;
}
} else if (!columnSpec[i].isSpace()){
parentMathText->addToErrorList(QString("array spec has unknown character '%1' (full spec was '%2')").arg(columnSpec[i]).arg(columnSpec));
}
i++;
}
}
JKQTMathTextMatrixNode::LayoutInfo::LayoutInfo():
JKQTMathTextNodeSize(), colwidth(), rowheight()
{
}
JKQTMathTextMatrixNode::LayoutInfo JKQTMathTextMatrixNode::calcLayout(QPainter &painter, const JKQTMathTextEnvironment &currentEv) const
{
LayoutInfo l;
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
JKQTMathTextEnvironment ev1=currentEv;
const double xheight=fm.strikeOutPos();
const double xwidth=fm.boundingRect("x").width();
const double XPadding=parentMathText->getMatrixXPaddingFactor()*xwidth;
const double YPadding=parentMathText->getMatrixYPaddingFactor()*xwidth;
const double XSeparation=parentMathText->getMatrixXSeparationFactor()*xwidth;
const double YSeparation=parentMathText->getMatrixYSeparationFactor()*xwidth;
l.colwidth.resize(columns); for (int i=0; i<columns; i++) l.colwidth[i]=0;
l.rowheight.resize(lines);
l.rowascent.resize(lines);
l.cellwidth.resize(lines);
l.leftPadding=(verticalLineLeft==LTnone)?0:XPadding;
l.rightPadding=(verticalLineRHSColumn.value(columns-1,LTnone)==LTnone)?0:XPadding;
l.topPadding=(horizontalLineTop==LTnone)?0:YPadding;
l.bottomPadding=(horizontalLineBottomRow.value(lines-1,LTnone)==LTnone)?0:YPadding;
for (int ll=0; ll<lines; ll++) l.cellwidth[ll]=QVector<double>(columns, 0.0);
QVector<double> rowdescent;
rowdescent.resize(lines);
for (int i=0; i<lines; i++) {
l.rowheight[i]=0;
l.rowascent[i]=0;
rowdescent[i]=0;
for (int j=0; j<children[i].size(); j++) {
const JKQTMathTextNodeSize cs=children[i].at(j)->getSize(painter, ev1);
l.cellwidth[i].operator[](j)=cs.width;
l.colwidth[j]=qMax(l.colwidth[j], cs.width);
l.rowascent[i]=qMax(l.rowascent[i], cs.baselineHeight);
rowdescent[i]=qMax(rowdescent[i], cs.getDescent());
}
l.rowheight[i]=l.rowascent[i]+rowdescent[i];
}
l.overallHeight=(lines-1)*YSeparation+l.topPadding+l.bottomPadding;
l.width=(columns-1)*XSeparation+l.leftPadding+l.rightPadding;
for (int i=0; i<columns; i++) l.width=l.width+l.colwidth[i];
for (int i=0; i<lines; i++) l.overallHeight=l.overallHeight+l.rowheight[i];
l.baselineHeight=l.overallHeight/2.0+xheight;
l.strikeoutPos=xheight;
return l;
}
void JKQTMathTextMatrixNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
const LayoutInfo l=calcLayout(painter, currentEv);
width=l.width;
overallHeight=l.overallHeight;
baselineHeight=l.baselineHeight;
strikeoutPos=l.strikeoutPos;
}
double JKQTMathTextMatrixNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
JKQTMathTextEnvironment ev1=currentEv;
const LayoutInfo l=calcLayout(painter, currentEv);
const double xheight=fm.strikeOutPos();
const double xwidth=fm.boundingRect("x").width();
//const double XPadding=parentMathText->getMatrixXPaddingFactor()*xwidth;
//const double YPadding=parentMathText->getMatrixYPaddingFactor()*xwidth;
const double XSeparation=parentMathText->getMatrixXSeparationFactor()*xwidth;
const double YSeparation=parentMathText->getMatrixYSeparationFactor()*xwidth;
const double yTop=y-l.baselineHeight+l.topPadding;
const double xLeft=x+l.leftPadding;
const double linewidth=parentMathText->getMatrixLinewidthThinFactor()*fm.lineWidth();
const double linewidthThick=parentMathText->getMatrixLinewidthHeavyFactor()*fm.lineWidth();
const double lineSeparation=parentMathText->getMatrixLineSeparationFactor()*fm.lineWidth();
double leftlineX=xLeft-l.leftPadding/2.0;
double rightlineX=x+l.width-l.rightPadding/2.0;
double toplineY=yTop-l.topPadding/2.0;
double bottomlineY=y+l.getDescent()-l.bottomPadding/2;
if (verticalLineLeft==LTdoubleline || verticalLineLeft==LTdoubleDashed) leftlineX-=linewidth;
if (horizontalLineTop==LTdoubleline || horizontalLineTop==LTdoubleDashed) toplineY-=linewidth;
if (verticalLineRHSColumn.value(lines-1, LTnone)==LTdoubleline || verticalLineRHSColumn.value(lines-1, LTnone)==LTdoubleDashed) rightlineX+=linewidth;
if (horizontalLineBottomRow.value(columns-1, LTnone)==LTdoubleline || horizontalLineBottomRow.value(columns-1, LTnone)==LTdoubleDashed) bottomlineY+=linewidth;
double xx;
double yy=yTop;
if (lines>0) yy=yy+l.rowascent[0];
for (int i=0; i<lines; i++) {
xx=xLeft;
for (int j=0; j<children[i].size(); j++) {
const double cw=l.getCellwidth(i, j);
double xoffset=0;
if (columnAlignment.value(j, MTHALeft)==MTHACentered) xoffset=(l.colwidth[j]-cw)/2.0;
else if (columnAlignment.value(j, MTHALeft)==MTHARight) xoffset=(l.colwidth[j]-cw);
children[i].at(j)->draw(painter, xx+xoffset, yy, ev1);
xx=xx+l.colwidth[j]+XSeparation;
if (i==0 && j<columns-1) drawVLine(painter, xx-XSeparation/2.0, toplineY, bottomlineY-toplineY, verticalLineRHSColumn.value(j, LTnone), linewidth, linewidthThick, currentEv.color, lineSeparation);
}
if (i<lines-1) {
double yline=yy+(l.rowheight[i]-l.rowascent[i])+YSeparation/2.0;
yy=yline+YSeparation/2.0+l.rowascent[i+1];
drawHLine(painter, leftlineX, yline, rightlineX-leftlineX, horizontalLineBottomRow.value(i, LTnone), linewidth, linewidthThick, currentEv.color, lineSeparation);
}
}
drawVLine(painter, leftlineX, toplineY, bottomlineY-toplineY, verticalLineLeft, linewidth, linewidthThick, currentEv.color, lineSeparation);
drawVLine(painter, rightlineX, toplineY, bottomlineY-toplineY, verticalLineRHSColumn.value(columns-1, LTnone), linewidth, linewidthThick, currentEv.color, lineSeparation);
drawHLine(painter, leftlineX, toplineY, rightlineX-leftlineX, verticalLineLeft, linewidth, linewidthThick, currentEv.color, lineSeparation);
drawHLine(painter, leftlineX, bottomlineY, rightlineX-leftlineX, horizontalLineBottomRow.value(lines-1, LTnone), linewidth, linewidthThick, currentEv.color, lineSeparation);
return x+l.width;
}

View File

@ -32,13 +32,39 @@ class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing a \\begin{matrix} node
/** \brief subclass representing a \c \\begin{matrix} , \c \\begin{tabular} , \c \\begin{array} , ... node
* \ingroup jkqtmathtext_items
*
* Definition of the matrix geometry
* \image html jkqtmathtext/jkqtmathtext_matrix_geometry.png
*
*
* Two examples:
* \image html jkqtmathtext/jkqtmathtext_tabular.png
*
* \image html jkqtmathtext/jkqtmathtext_array.png
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextMatrixNode: public JKQTMathTextNode {
public:
JKQTMathTextMatrixNode(JKQTMathText* parent, QVector<QVector<JKQTMathTextNode*> > children);
/** \brief types of lines */
enum LineType {
LTnone, /*!< \brief noline */
LTline, /*!< \brief single line */
LTdoubleline, /*!< \brief double line */
LTheavyline, /*!< \brief heavier/thick line */
LTdashed, /*!< \brief single dashed line */
LTdoubleDashed, /*!< \brief double dashed line */
LTdefault=LTnone
};
JKQTMathTextMatrixNode(JKQTMathText* parent, const QVector<QVector<JKQTMathTextNode*> >& children, const QString& columnSpec=QString());
JKQTMathTextMatrixNode(JKQTMathText* parent, const QString& columnSpec=QString());
virtual ~JKQTMathTextMatrixNode() override;
/** \brief sets the child nodes */
void setChildren(const QVector<QVector<JKQTMathTextNode*> >& children);
/** \copydoc horizontalLineBottomRow */
void setRowBottomLine(int col, LineType line);
/** \copydoc horizontalLineTop */
void setTopLine(LineType line);
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::draw() */
@ -52,16 +78,63 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextMatrixNode: public JKQTMathTextNode {
/** \copydoc lines */
int getLines() const;
protected:
/** \brief describes the layout of the whole node */
struct LayoutInfo: public JKQTMathTextNodeSize {
LayoutInfo();
/** \brief widths of the columns */
QVector<double> colwidth;
/** \brief widths of the cells */
QVector<QVector<double> > cellwidth;
inline double& getCellwidth(int line, int col) {
return cellwidth[line].operator[](col);
}
inline const double& getCellwidth(int line, int col) const {
return cellwidth[line].operator[](col);
}
/** \brief heights of the rows */
QVector<double> rowheight;
/** \brief ascents of the rows */
QVector<double> rowascent;
double leftPadding;
double rightPadding;
double topPadding;
double bottomPadding;
};
/** \brief calclates the layout of the whole block/node
*
* \note This function does NOT call transformEnvironment();
* it has to be called before calling this!
*/
LayoutInfo calcLayout(QPainter& painter, const JKQTMathTextEnvironment& currentEv) const;
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \brief child nodes making up the matrix, vector of rows */
QVector<QVector<JKQTMathTextNode*> > children;
/** \brief alignment of the columns */
QVector<JKQTMathTextHorizontalAlignment> columnAlignment;
/** \brief lines to the right of each column */
QMap<int,LineType> verticalLineRHSColumn;
/** \brief line at the left of the table */
LineType verticalLineLeft;
/** \brief lines to the bottom of each row */
QMap<int,LineType> horizontalLineBottomRow;
/** \brief line at the top of the table */
LineType horizontalLineTop;
/** \brief number of columns in the matrix */
int columns;
/** \brief number of rows in the matrix */
int lines;
/** \brief draw a vertical line starting at pixel position (\a x, \a y ) with length \a height, using linetype \a lt, width \a linewidth and \a color */
static void drawVLine(QPainter& painter, double x, double y, double height, LineType lt, double linewidth, double linewidthHeavy, QColor color, double doublelineseparation);
/** \brief draw a horizontal line starting at pixel position (\a x, \a y ) with length \a width, using linetype \a lt, width \a linewidth and \a color */
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);
};
#endif // JKQTMATHTEXTMATRIXNODE_H

View File

@ -285,6 +285,18 @@ void JKQTMathTextDualChildNode::clearChildren(bool deleteChildren)
if (deleteChildren&&c2) delete c2;
}
void JKQTMathTextDualChildNode::deleteChild(int i)
{
if (child1&&i==0) {
delete child1;
child1=nullptr;
}
if (child2&&i==1) {
delete child2;
child2=nullptr;
}
}
JKQTMathTextMultiChildNode::JKQTMathTextMultiChildNode(JKQTMathText *parentMathText):
JKQTMathTextNode(parentMathText)
{

View File

@ -232,6 +232,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextMultiChildNode: public JKQTMathTextNod
/** \brief clear all children, deleting them if \a deleteChildren==true */
virtual void clearChildren(bool deleteChildren=true) =0;
/** \brief delete the i-th child */
virtual void deleteChild(int i) =0;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
@ -266,6 +268,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextDualChildNode: public JKQTMathTextMult
virtual int childCount() const override;
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
virtual void clearChildren(bool deleteChildren=true) override;
/** \copydoc JKQTMathTextMultiChildNode::deleteChild() */
virtual void deleteChild(int i) override;
protected:
/** \brief first child node of this node */

View File

@ -21,6 +21,8 @@
#include "jkqtmathtext/nodes/jkqtmathtextnodetools.h"
#include "jkqtmathtext/nodes/jkqtmathtextlistnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h"
#include "jkqtmathtext/nodes/jkqtmathtexttextnode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include <QDebug>
@ -65,3 +67,42 @@ JKQTMathTextNode *simplifyJKQTMathTextNode(JKQTMathTextNode *node)
}
return node;
}
JKQTMathTextNode *simplifyAndTrimJKQTMathTextNode(JKQTMathTextNode *node)
{
auto cleanText=[](JKQTMathTextNode* t) {
JKQTMathTextMultiChildNode* nmc=dynamic_cast<JKQTMathTextMultiChildNode*>(t);
JKQTMathTextNode* tt0=(nmc&&nmc->childCount()>0)?nmc->getFirstChild():t;
JKQTMathTextNode* tt1=(nmc&&nmc->childCount()>0)?nmc->getLastChild():t;
JKQTMathTextTextNode* txt0=dynamic_cast<JKQTMathTextTextNode*>(tt0);
if (txt0) {
txt0->removeLeadingWhitespace();
}
JKQTMathTextTextNode* txt1=dynamic_cast<JKQTMathTextTextNode*>(tt1);
if (txt1) {
txt1->removeTrailingWhitespace();
}
};
JKQTMathTextNode* t=node;
for (int iter=0; iter<3; iter++) {
t=simplifyJKQTMathTextNode(t);
JKQTMathTextMultiChildNode* nmc=dynamic_cast<JKQTMathTextMultiChildNode*>(t);
if (nmc && nmc->childCount()>0) {
bool done=false;
cleanText(nmc);
while (!done && nmc->childCount()>0) {
JKQTMathTextWhitespaceNode* ws0=dynamic_cast<JKQTMathTextWhitespaceNode*>(nmc->getFirstChild());
JKQTMathTextWhitespaceNode* ws1=dynamic_cast<JKQTMathTextWhitespaceNode*>(nmc->getLastChild());
if (ws0 && ws0->getWhitespaceType()==JKQTMathTextWhitespaceNode::WSTNormal) {
nmc->deleteChild(0);
} else if (ws1 && ws1->getWhitespaceType()==JKQTMathTextWhitespaceNode::WSTNormal) {
nmc->deleteChild(nmc->childCount()-1);
} else {
done=true;
}
}
}
cleanText(t);
}
return t;
}

View File

@ -37,6 +37,13 @@ class JKQTMathTextNode; // forward
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNode* simplifyJKQTMathTextNode(JKQTMathTextNode* node);
/** \brief calls simplifyJKQTMathTextNode(). In addition it tries to clear whitespace at the start and end of the tree
* \ingroup jkqtmathtext_items
*
* \see simplifyJKQTMathTextNode()
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNode* simplifyAndTrimJKQTMathTextNode(JKQTMathTextNode* node);
#endif // JKQTMATHTEXTNODETOOLS_H

View File

@ -227,3 +227,15 @@ void JKQTMathTextSqrtNode::clearChildren(bool deleteChildren)
}
}
void JKQTMathTextSqrtNode::deleteChild(int i)
{
if (child && i==0) {
delete child;
child=nullptr;
}
if (childDegree && i==1) {
delete childDegree;
childDegree=nullptr;
}
}

View File

@ -70,6 +70,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSqrtNode: public JKQTMathTextMultiChil
virtual int childCount() const override;
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
virtual void clearChildren(bool deleteChildren=true) override;
/** \copydoc JKQTMathTextMultiChildNode::deleteChild() */
virtual void deleteChild(int i) override;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */

View File

@ -376,6 +376,16 @@ JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorText
return SymbolFullProps(SymbolProps(op, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0)).addGlobalFlags(ExtendWidthInMathmode|MakeWhitespaceHalf).addHtml(ophtml, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0);
}
JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::NarrowMathOperatorText(const QString &op)
{
return NarrowMathOperatorText(op, op);
}
JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::NarrowMathOperatorText(const QString &op, const QString &ophtml)
{
return SymbolFullProps(SymbolProps(op, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0)).addGlobalFlags(SmallExtendWidthInMathmode|MakeWhitespaceHalf).addHtml(ophtml, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0);
}
JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorSymbolUnicode(const QString &unicode)
{
return SymbolFullProps(MTFEUnicode, SymbolProps(unicode, ItalicOff|BoldOff, 1.0, 0.0)).addGlobalFlags(ExtendWidthInMathmode|MakeWhitespaceHalf);
@ -532,7 +542,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["brcorner"]=s; symbols["lrcorner"]=s; }
{ auto s=UprightSymbolUnicode(QChar(0x2022)).addUprightHtml("&bull;").addUprightWinSymbol(QChar(0xB7));
symbols["bullet"]=s; symbols["textbullet"]=s; }
symbols["cdots"]=UnicodeSymbol(QChar(0x22EF)).addHtml("&middot;&middot;&middot;").addStd(QString(3, QChar(0xB7)));
symbols["cdots"]=UprightSymbolUnicode(QChar(0x22EF)).addHtml("&middot;&middot;&middot;").addStd(QString(3, QChar(0xB7)));
{ 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;");
@ -583,8 +593,6 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["infty"]=UnicodeSymbol(QChar(0x221E)).addHtml("&infin;").addWinSymbol(QChar(0xA5)).addStd("8", RotateSymbol90);
symbols["langle"]=UprightSymbolUnicode(QChar(0x2329)).addWinSymbol(QChar(0xE1));
symbols["lceil"]=UprightSymbolUnicode(QChar(0x2308)).addHtml("&LeftCeiling;").addWinSymbol(QChar(0xE9));
{ auto s=SimpleTextSymbol("...").addUnicode(QChar(0x2026)).addWinSymbol(QChar(0xB6));
symbols["ldots"]=s; symbols["dots"]=s; }
symbols["lfloor"]=UprightSymbolUnicode(QChar(0x230A)).addHtml("&LeftFloor;").addWinSymbol(QChar(0xEB));
symbols["lightning"]=UnicodeSymbol(QChar(0x21AF));
symbols["male"]=UnicodeSymbol(QChar(0x2642)).addHtml("&male;");
@ -642,46 +650,46 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
/**************************************************************************************
* STANDARD MathOperator Strings
**************************************************************************************/
symbols["Pr"] = MathOperatorText("Pr");
symbols["acos"] = MathOperatorText("acos");
symbols["arccos"] = MathOperatorText("arccos");
symbols["arcsin"] = MathOperatorText("arcsin");
symbols["arctan"] = MathOperatorText("arctan");
symbols["arg"] = MathOperatorText("arg").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["argmax"] = MathOperatorText("arg max", "arg&thinsp;max").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["argmin"] = MathOperatorText("arg min", "arg&thinsp;min").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["asin"] = MathOperatorText("asin");
symbols["atan"] = MathOperatorText("atan");
symbols["cos"] = MathOperatorText("cos");
symbols["cosh"] = MathOperatorText("cosh");
symbols["cot"] = MathOperatorText("cot");
symbols["coth"] = MathOperatorText("coth");
symbols["coth"] = MathOperatorText("coth");
symbols["deg"] = MathOperatorText("deg");
symbols["det"] = MathOperatorText("det");
symbols["dim"] = MathOperatorText("dim");
symbols["exp"] = MathOperatorText("exp");
symbols["gcd"] = MathOperatorText("gcd");
symbols["hom"] = MathOperatorText("hom");
symbols["ker"] = MathOperatorText("ker");
symbols["lb"] = MathOperatorText("lb");
symbols["ld"] = MathOperatorText("ld");
symbols["lim"] = MathOperatorText("lim").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["liminf"] = MathOperatorText("lim inf", "lim&thinsp;inf").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["limsup"] = MathOperatorText("lim sup", "lim&thinsp;sup").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["ln"] = MathOperatorText("ln");
symbols["log"] = MathOperatorText("log");
symbols["max"] = MathOperatorText("max");
symbols["median"] = MathOperatorText("median");
symbols["min"] = MathOperatorText("min");
symbols["mod"] = MathOperatorText("mod");
symbols["sec"] = MathOperatorText("sec");
symbols["sgn"] = MathOperatorText("sgn");
symbols["sign"] = MathOperatorText("sign");
symbols["sin"] = MathOperatorText("sin");
symbols["sinh"] = MathOperatorText("sinh");
symbols["tan"] = MathOperatorText("tan");
symbols["tanh"] = MathOperatorText("tanh");
symbols["Pr"] = NarrowMathOperatorText("Pr");
symbols["acos"] = NarrowMathOperatorText("acos");
symbols["arccos"] = NarrowMathOperatorText("arccos");
symbols["arcsin"] = NarrowMathOperatorText("arcsin");
symbols["arctan"] = NarrowMathOperatorText("arctan");
symbols["arg"] = NarrowMathOperatorText("arg").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["argmax"] = NarrowMathOperatorText("arg max", "arg&thinsp;max").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["argmin"] = NarrowMathOperatorText("arg min", "arg&thinsp;min").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["asin"] = NarrowMathOperatorText("asin");
symbols["atan"] = NarrowMathOperatorText("atan");
symbols["cos"] = NarrowMathOperatorText("cos");
symbols["cosh"] = NarrowMathOperatorText("cosh");
symbols["cot"] = NarrowMathOperatorText("cot");
symbols["coth"] = NarrowMathOperatorText("coth");
symbols["coth"] = NarrowMathOperatorText("coth");
symbols["deg"] = NarrowMathOperatorText("deg");
symbols["det"] = NarrowMathOperatorText("det");
symbols["dim"] = NarrowMathOperatorText("dim");
symbols["exp"] = NarrowMathOperatorText("exp");
symbols["gcd"] = NarrowMathOperatorText("gcd");
symbols["hom"] = NarrowMathOperatorText("hom");
symbols["ker"] = NarrowMathOperatorText("ker");
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["ln"] = NarrowMathOperatorText("ln");
symbols["log"] = NarrowMathOperatorText("log");
symbols["max"] = NarrowMathOperatorText("max");
symbols["median"] = NarrowMathOperatorText("median");
symbols["min"] = NarrowMathOperatorText("min");
symbols["mod"] = NarrowMathOperatorText("mod");
symbols["sec"] = NarrowMathOperatorText("sec");
symbols["sgn"] = NarrowMathOperatorText("sgn");
symbols["sign"] = NarrowMathOperatorText("sign");
symbols["sin"] = NarrowMathOperatorText("sin");
symbols["sinh"] = NarrowMathOperatorText("sinh");
symbols["tan"] = NarrowMathOperatorText("tan");
symbols["tanh"] = NarrowMathOperatorText("tanh");
/**************************************************************************************
* STANDARD MathOperator Symbols
@ -701,12 +709,12 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["Updownarrow"]=UprightSymbolUnicode(QChar(0x21D5)).addUprightHtml("&Updownarrow;");
symbols["approx"]=MathOperatorSymbolUnicode(QChar(0x2248)).addMathOperatorHtml("&asymp;").addMathOperatorWinSymbol(QChar(0xBB));
symbols["bbC"]=UnicodeSymbol(QChar(0x2102));
symbols["bbH"]=MathOperatorSymbolUnicode(QChar(0x210D));
symbols["bbN"]=MathOperatorSymbolUnicode(QChar(0x2115));
symbols["bbP"]=MathOperatorSymbolUnicode(QChar(0x2119));
symbols["bbQ"]=MathOperatorSymbolUnicode(QChar(0x211A));
symbols["bbR"]=MathOperatorSymbolUnicode(QChar(0x211D));
symbols["bbZ"]=MathOperatorSymbolUnicode(QChar(0x2124));
symbols["bbH"]=UnicodeSymbol(QChar(0x210D));
symbols["bbN"]=UnicodeSymbol(QChar(0x2115));
symbols["bbP"]=UnicodeSymbol(QChar(0x2119));
symbols["bbQ"]=UnicodeSymbol(QChar(0x211A));
symbols["bbR"]=UnicodeSymbol(QChar(0x211D));
symbols["bbZ"]=UnicodeSymbol(QChar(0x2124));
symbols["because"]=MathOperatorSymbolUnicode(QChar(0x2235)).addMathOperatorHtml("&because;");
symbols["bigcap"]=NarrowMathOperatorSymbolUnicode(QChar(0x22C2)).addMathOperatorHtml("&Intersection;").addMathOperatorWinSymbol(QChar(0xC7), 1.8).addGlobalFlags(SubSuperscriptBelowAboveSymbol);
symbols["bigcup"]=NarrowMathOperatorSymbolUnicode(QChar(0x22C3)).addMathOperatorHtml("&xcup;").addMathOperatorWinSymbol(QChar(0xC8), 1.8).addGlobalFlags(SubSuperscriptBelowAboveSymbol);
@ -727,7 +735,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["coprod"]=NarrowMathOperatorSymbolUnicode(QChar(0x2210)).addMathOperatorHtml("&Coproduct;").addWinSymbol(QChar(0xD5), ItalicOff|BoldOff|FlipSymbolUpDown, 1.8, 0.1).addGlobalFlags(SubSuperscriptBelowAboveSymbol);
{ auto s=MathOperatorSymbolUnicode(QChar(0x222A)).addMathOperatorHtml("&cup;").addMathOperatorWinSymbol(QChar(0xC8));
symbols["cup"]=s; symbols["lor"]=s; }
symbols["ddots"]=MathOperatorSymbolUnicode(QChar(0x22F1)).addMathOperatorHtml("&dtdot;");
symbols["ddots"]=UprightSymbolUnicode(QChar(0x22F1)).addMathOperatorHtml("&dtdot;");
symbols["div"]=MathOperatorSymbolUnicode(QChar(0x00F7)).addMathOperatorHtml("&div;").addMathOperatorWinSymbol(QChar(0xB8));
symbols["downarrow"]=UprightSymbolUnicode(QChar(0x2193)).addUprightHtml("&ShortDownArrow;").addUprightWinSymbol(QChar(0xAF));
symbols["downharpoonleft"]=UprightSymbolUnicode(QChar(0x21C3)).addUprightHtml("&LeftDownVector;");
@ -735,13 +743,13 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
{ auto s=MathOperatorSymbolUnicode(QChar(0x2205)).addMathOperatorHtml("&varnothing;").addMathOperatorWinSymbol(QChar(0xC6)).addStd("0", BoldOff|ItalicOff|DrawSlash);
symbols["emptyset"]=s; symbols["varnothing"]=s; }
symbols["equiv"]=MathOperatorSymbolUnicode(QChar(0x2261)).addMathOperatorHtml("&equiv;").addMathOperatorWinSymbol(QChar(0xBA));
symbols["exists"]=MathOperatorSymbolUnicode(QChar(0x2203)).addMathOperatorHtml("&exist;").addMathOperatorWinSymbol(QChar(0x24)).addStd("E", ItalicOff|BoldOff|FlipSymbolLeftRight);
symbols["forall"]=MathOperatorSymbolUnicode(QChar(0x2200)).addMathOperatorHtml("&forall;").addMathOperatorWinSymbol(QChar(0x22)).addStd("A", ItalicOff|BoldOff|FlipSymbolUpDown);
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);
{ auto s=MathOperatorSymbolUnicode(QChar(0x2265)).addMathOperatorHtml("&GreaterEqual;").addMathOperatorWinSymbol(QChar(0xB3));
symbols["geq"]=s; symbols["ge"]=s; }
symbols["geqq"]=MathOperatorSymbolUnicode(QChar(0x2267)).addMathOperatorHtml("&GreaterFullEqual;");
symbols["gg"]=MathOperatorSymbolUnicode(QChar(0x226B)).addMathOperatorHtml("&NestedGreaterGreater;").addMathOperatorStd(">>");
symbols["iddots"]=MathOperatorSymbolUnicode(QChar(0x22F0)).addMathOperatorHtml("&utdot;");
symbols["iddots"]=UprightSymbolUnicode(QChar(0x22F0)).addMathOperatorHtml("&utdot;");
{ auto s=UprightSymbolUnicode(QChar(0x21D4)).addUprightHtml("&DoubleLeftRightArrow;").addUprightWinSymbol(QChar(0xDB));
symbols["iff"]=s; symbols["Leftrightarrow"]=s; }
symbols["iiint"]=NarrowMathOperatorSymbolUnicode(QChar(0x222D)).addGlobalFlags(IntLikeSymbolCorrection | SubSuperscriptBelowAboveSymbol).addMathOperatorHtml("&tint;").addMathOperatorWinSymbol(QString(3, QChar(0xF2)), 1.8, 0.1);
@ -770,17 +778,17 @@ 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"]=MathOperatorSymbolUnicode(QChar(0x2207)).addMathOperatorHtml("&nabla;").addMathOperatorWinSymbol(QChar(0xD1));
symbols["ne"]=MathOperatorSymbolUnicode(QChar(0x2260)).addMathOperatorHtml("&ne;").addMathOperatorWinSymbol(QChar(0xB9));
symbols["nabla"]=NarrowMathOperatorSymbolUnicode(QChar(0x2207)).addMathOperatorHtml("&nabla;").addMathOperatorWinSymbol(QChar(0xD1));
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));
symbols["neg"]=s; symbols["lnot"]=s; }
symbols["neq"]=MathOperatorSymbolUnicode(QChar(0x2260)).addMathOperatorHtml("&ne;").addMathOperatorWinSymbol(QChar(0xB9)).addStd("=", ItalicOff|BoldOff|DrawSlash);
symbols["nexists"]=MathOperatorSymbolUnicode(QChar(0x2204)).addMathOperatorHtml("&NotExists;").addStd("E", ItalicOff|BoldOff|FlipSymbolLeftRight|DrawSlash).addMathOperatorWinSymbol(QChar(0x24), ItalicOff|BoldOff|DrawSlash);
symbols["ni"]=MathOperatorSymbolUnicode(QChar(0x220B)).addMathOperatorHtml("&ReverseElement;").addMathOperatorWinSymbol(QChar(0xCE), ItalicOff|BoldOff|FlipSymbolLeftRight);
symbols["nmid"]=MathOperatorSymbolUnicode(QChar(0x2224)).addMathOperatorHtml("&NotVerticalBar;");
symbols["notin"]=MathOperatorSymbolUnicode(QChar(0x2209)).addMathOperatorHtml("&notin;").addMathOperatorWinSymbol(QChar(0xCF));
symbols["notni"]=MathOperatorSymbolUnicode(QChar(0x220C)).addMathOperatorHtml("&NotReverseElement;");
symbols["nexists"]=NarrowMathOperatorSymbolUnicode(QChar(0x2204)).addMathOperatorHtml("&NotExists;").addStd("E", ItalicOff|BoldOff|FlipSymbolLeftRight|DrawSlash).addMathOperatorWinSymbol(QChar(0x24), ItalicOff|BoldOff|DrawSlash);
symbols["ni"]=NarrowMathOperatorSymbolUnicode(QChar(0x220B)).addMathOperatorHtml("&ReverseElement;").addMathOperatorWinSymbol(QChar(0xCE), ItalicOff|BoldOff|FlipSymbolLeftRight);
symbols["nmid"]=NarrowMathOperatorSymbolUnicode(QChar(0x2224)).addMathOperatorHtml("&NotVerticalBar;");
symbols["notin"]=NarrowMathOperatorSymbolUnicode(QChar(0x2209)).addMathOperatorHtml("&notin;").addMathOperatorWinSymbol(QChar(0xCF));
symbols["notni"]=NarrowMathOperatorSymbolUnicode(QChar(0x220C)).addMathOperatorHtml("&NotReverseElement;");
symbols["nparallel"]=MathOperatorSymbolUnicode(QChar(0x2226)).addMathOperatorHtml("&NotDoubleVerticalBar;");
symbols["nwarrow"]=UprightSymbolUnicode(QChar(0x2196)).addUprightHtml("&UpperLeftArrow;");
symbols["odot"]=MathOperatorSymbolUnicode(QChar(0x2299)).addMathOperatorHtml("&odot;");
@ -791,7 +799,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
symbols["oplus"]=MathOperatorSymbolUnicode(QChar(0x2295)).addMathOperatorHtml("&CirclePlus;").addMathOperatorWinSymbol(QChar(0xC5));
symbols["oslash"]=MathOperatorSymbolUnicode(QChar(0x2298)).addMathOperatorHtml("&osol;");
symbols["otimes"]=MathOperatorSymbolUnicode(QChar(0x2297)).addMathOperatorHtml("&CircleTimes;").addMathOperatorWinSymbol(QChar(0xC4));
symbols["parallel"]=MathOperatorSymbolUnicode(QChar(0x2225)).addMathOperatorHtml("&shortparallel;").addMathOperatorStd("||");
symbols["parallel"]=NarrowMathOperatorSymbolUnicode(QChar(0x2225)).addMathOperatorHtml("&shortparallel;").addMathOperatorStd("||");
symbols["pm"] = MathOperatorSymbol(QChar(0xB1), "&plusmn;").addMathOperatorWinSymbol(QChar(0xB1));
symbols["prec"]=MathOperatorSymbolUnicode(QChar(0x227A)).addMathOperatorHtml("&prec;");
symbols["prod"]=NarrowMathOperatorSymbolUnicode(QChar(0x220F)).addMathOperatorWinSymbol(QChar(0xD5), 1.8, 0.1).addMathOperatorHtml("&prod;").addGlobalFlags(SubSuperscriptBelowAboveSymbol);
@ -821,13 +829,13 @@ void JKQTMathTextSymbolNode::fillSymbolTables()
{ auto s=UprightSymbolUnicode(QChar(0x2192)).addUprightHtml("&rarr;").addUprightWinSymbol(QChar(0xAE));
symbols["to"]=s; symbols["rightarrow"]=s; }
symbols["top"]=MathOperatorSymbolUnicode(QChar(0x22A4)).addMathOperatorHtml("&top;").addMathOperatorWinSymbol(QChar(0x5E));
symbols["triangle"]=MathOperatorSymbolUnicode(QChar(0x2206));
symbols["triangle"]=NarrowMathOperatorSymbolUnicode(QChar(0x2206));
symbols["uparrow"]=UprightSymbolUnicode(QChar(0x2191)).addUprightHtml("&ShortUpArrow;").addUprightWinSymbol(QChar(0xAD));
symbols["updownarrow"]=UprightSymbolUnicode(QChar(0x2195)).addUprightHtml("&updownarrow;");
symbols["upharpoonleft"]=UprightSymbolUnicode(QChar(0x21BF)).addUprightHtml("&LeftUpVector;");
symbols["upharpoonright"]=UprightSymbolUnicode(QChar(0x21BE)).addUprightHtml("&RightUpVector;");
symbols["vartriangleleft"]=MathOperatorSymbolUnicode(QChar(0x22B2)).addMathOperatorHtml("&LeftTriangle;");
symbols["vdots"]=MathOperatorSymbolUnicode(QChar(0x22EE)).addMathOperatorHtml("&vellip;");
symbols["vartriangleleft"]=NarrowMathOperatorSymbolUnicode(QChar(0x22B2)).addMathOperatorHtml("&LeftTriangle;");
symbols["vdots"]=UprightSymbolUnicode(QChar(0x22EE)).addMathOperatorHtml("&vellip;");
symbols["vee"]=MathOperatorSymbolUnicode(QChar(0x2228)).addMathOperatorHtml("&vee;").addMathOperatorWinSymbol(QChar(0xDA));
symbols["vdash"]=MathOperatorSymbolUnicode(QChar(0x22A2)).addMathOperatorHtml("&vdash;");
symbols["dashv"]=MathOperatorSymbolUnicode(QChar(0x22A3)).addMathOperatorHtml("&dashv;");

View File

@ -289,6 +289,10 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
static SymbolFullProps NarrowMathOperatorSymbolStd(const QString& symbol);
/** \brief constructs a SymbolProps for a narrow math-operator symbol like \c \\pm ... in unicode-full-encoding, i.e. ItalicOff, BoldOff, SmallExtendWidthInMathmode */
static SymbolFullProps NarrowMathOperatorSymbolStd(const QString& symbol, const QString& symbolHTML);
/** \brief constructs a SymbolProps for a narrow math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, HeightIsAscent, ExtendWidthInMathmode */
static SymbolFullProps NarrowMathOperatorText(const QString& op);
/** \brief constructs a SymbolProps with explicit HTML for a narrow math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, HeightIsAscent, ExtendWidthInMathmode */
static SymbolFullProps NarrowMathOperatorText(const QString& op, const QString& ophtml);
/** \brief symbols that can be generated in any standard-font */

View File

@ -337,6 +337,16 @@ QString JKQTMathTextTextNode::getTypeName() const
return QLatin1String("JKQTMathTextTextNode(")+text+")";
}
void JKQTMathTextTextNode::removeTrailingWhitespace()
{
while (text.size()>0 && text[text.size()-1].isSpace()) text=text.left(text.size()-1);
}
void JKQTMathTextTextNode::removeLeadingWhitespace()
{
while (text.size()>0 && text[0].isSpace()) text=text.right(text.size()-1);
}
QString JKQTMathTextTextNode::textTransform(const QString &text, const JKQTMathTextEnvironment &currentEv) const
{
QString txt=text;

View File

@ -68,6 +68,10 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTextNode: public JKQTMathTextTextBaseN
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override ;
/** \brief remove trailing whitespace, is used by simplifyJKQTMathTextNode() */
void removeTrailingWhitespace();
/** \brief remove leading whitespace, is used by simplifyJKQTMathTextNode() */
void removeLeadingWhitespace();
protected:
/** \brief defines how a character shold be drawn, used by splitTextForLayout */
enum FontMode {