diff --git a/doc/dox/jkqtmathtext_supportedlatex.dox b/doc/dox/jkqtmathtext_supportedlatex.dox index dc3dadd696..c6878213c5 100644 --- a/doc/dox/jkqtmathtext_supportedlatex.dox +++ b/doc/dox/jkqtmathtext_supportedlatex.dox @@ -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: + - $\\begin{tabular}{COLSPEC} a & b & ...\\\\ c & d & ...\\end{tabular}$ + \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
Special subscript/superscript typesetting applies, when the sub/super follows \c \\sum \c \\Prod ...: \image html jkqtmathtext/jkqtmathtext_specialsubsuper.png + - $\\substack[lrc]{...\\\\...}$ 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: - $\\frac{...}{...}$ \image html jkqtmathtext/MTFMfrac.png - $\\tfrac{...}{...}$ (70% smaller font) \image html jkqtmathtext/MTFMtfrac.png - $\\dfrac{...}{...}$ \image html jkqtmathtext/MTFMdfrac.png - $\\sfrac{...}{...}$ \image html jkqtmathtext/MTFMsfrac.png - $\\stfrac{...}{...}$ (70% smaller font) \image html jkqtmathtext/MTFMstfrac.png + - $\\stackrel{...}{...}$ $\\binom{...}{...}$ \image html jkqtmathtext/jkqtmathtext_brace_stackrel.png . \subsection JKQTMathTextSuppoertedLaTeXMatrix Matrix/Array Type Instructions - Several Matrix/Array-typed LaTeX instructions are supported: + Simple instructions are: - $\\stackrel{...}{...}$ $\\binom{...}{...}$ \image html jkqtmathtext/jkqtmathtext_brace_stackrel.png + . + + Several Matrix/Array-typed LaTeX instructions are supported: - $\\begin{cases} ... & ... \\\\ ... & ... \\end{cases}$ \image html jkqtmathtext/jkqtmathtext_brace_begincases.png - - $\\begin{array} a & b & ...\\\\ c & d & ...\\end{array}$ $\\begin{matrix} a & b & ...\\\\ c & d & ...\\end{matrix}$ \image html jkqtmathtext/jkqtmathtext_array.png + - $\\begin{matrix} a & b & ...\\\\ c & d & ...\\end{matrix}$ \image html jkqtmathtext/jkqtmathtext_matrix.png - $\\begin{pmatrix} a & b & ...\\\\ c & d & ...\\end{pmatrix}$ \image html jkqtmathtext/jkqtmathtext_pmatrix.png - $\\begin{bmatrix} a & b & ...\\\\ c & d & ...\\end{bmatrix}$ \image html jkqtmathtext/jkqtmathtext_bmatrix.png - $\\begin{Bmatrix} a & b & ...\\\\ c & d & ...\\end{Bmatrix}$ \image html jkqtmathtext/jkqtmathtext_bbmatrix.png - $\\begin{vmatrix} a & b & ...\\\\ c & d & ...\\end{vmatrix}$ \image html jkqtmathtext/jkqtmathtext_vmatrix.png - $\\begin{Vmatrix} a & b & ...\\\\ c & d & ...\\end{Vmatrix}$ \image html jkqtmathtext/jkqtmathtext_vvmatrix.png - - $\\substack[lrc]{...\\\\...}$ \image html jkqtmathtext/jkqtmathtext_substack.png - $\\lsubstack{...\\\\...}$ \image html jkqtmathtext/jkqtmathtext_lsubstack.png - $\\rsubstack{...\\\\...}$ \image html jkqtmathtext/jkqtmathtext_rsubstack.png - . + - $\\begin{array}{COLSPEC} a & b & ...\\\\ c & d & ...\\end{array}$ \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 + . diff --git a/doc/dox/todo.dox b/doc/dox/todo.dox index a2bbc67751..f9c5ff7c22 100644 --- a/doc/dox/todo.dox +++ b/doc/dox/todo.dox @@ -41,7 +41,6 @@ This page lists several todos and wishes for future version of JKQTPlotter
  • JKQTMathText:
  • diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox index 381d992b2d..485be8599c 100644 --- a/doc/dox/whatsnew.dox +++ b/doc/dox/whatsnew.dox @@ -89,6 +89,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
  • NEW: additional method JKQTMathtext::getSizeDetail() that returns all size-properties as a convenient struct, also added matching varinat JKQTMathTextNode::getSize()
  • 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
  • NEW: added command line tool \ref JKQTMathTextRenderCmdLineTool that renders LaTeX into images, using it to generate the documentation images for JKQTMathText
  • +
  • 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
  • diff --git a/doc/images/jkqtmathtext/jkqtmathtext_array.png b/doc/images/jkqtmathtext/jkqtmathtext_array.png index 319b342508..e1b521453a 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_array.png and b/doc/images/jkqtmathtext/jkqtmathtext_array.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_bbmatrix.png b/doc/images/jkqtmathtext/jkqtmathtext_bbmatrix.png index 7372fcaeb1..2c8cbbaee9 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_bbmatrix.png and b/doc/images/jkqtmathtext/jkqtmathtext_bbmatrix.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_bmatrix.png b/doc/images/jkqtmathtext/jkqtmathtext_bmatrix.png index 256895bba7..892c5cba57 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_bmatrix.png and b/doc/images/jkqtmathtext/jkqtmathtext_bmatrix.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_array.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_array.png deleted file mode 100644 index aa0ac052f4..0000000000 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_brace_array.png and /dev/null differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_brace_begincases.png b/doc/images/jkqtmathtext/jkqtmathtext_brace_begincases.png index 39f7553cee..7f92792a27 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_brace_begincases.png and b/doc/images/jkqtmathtext/jkqtmathtext_brace_begincases.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_limits.png b/doc/images/jkqtmathtext/jkqtmathtext_limits.png new file mode 100644 index 0000000000..c70e44e9a3 Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_limits.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_mathaccents.png b/doc/images/jkqtmathtext/jkqtmathtext_mathaccents.png index 6aa260c21a..60061851a8 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_mathaccents.png and b/doc/images/jkqtmathtext/jkqtmathtext_mathaccents.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_mathmode_and_textmode.png b/doc/images/jkqtmathtext/jkqtmathtext_mathmode_and_textmode.png index a03451802f..00e5b19bb5 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_mathmode_and_textmode.png and b/doc/images/jkqtmathtext/jkqtmathtext_mathmode_and_textmode.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_mathoperator_width_factor.png b/doc/images/jkqtmathtext/jkqtmathtext_mathoperator_width_factor.png index f1c1ad7843..2478da921f 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_mathoperator_width_factor.png and b/doc/images/jkqtmathtext/jkqtmathtext_mathoperator_width_factor.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_matrix.png b/doc/images/jkqtmathtext/jkqtmathtext_matrix.png new file mode 100644 index 0000000000..fb18ddf6c0 Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_matrix.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_matrix_geometry.cdr b/doc/images/jkqtmathtext/jkqtmathtext_matrix_geometry.cdr new file mode 100644 index 0000000000..b7541e26b4 Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_matrix_geometry.cdr differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_matrix_geometry.png b/doc/images/jkqtmathtext/jkqtmathtext_matrix_geometry.png new file mode 100644 index 0000000000..f1bc5b21be Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_matrix_geometry.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_pmatrix.png b/doc/images/jkqtmathtext/jkqtmathtext_pmatrix.png index 6f46d80328..06b3d71b29 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_pmatrix.png and b/doc/images/jkqtmathtext/jkqtmathtext_pmatrix.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_tabular.png b/doc/images/jkqtmathtext/jkqtmathtext_tabular.png new file mode 100644 index 0000000000..74df993e32 Binary files /dev/null and b/doc/images/jkqtmathtext/jkqtmathtext_tabular.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_textaccents.png b/doc/images/jkqtmathtext/jkqtmathtext_textaccents.png index 7bcb2b6830..8dec679b50 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_textaccents.png and b/doc/images/jkqtmathtext/jkqtmathtext_textaccents.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_vmatrix.png b/doc/images/jkqtmathtext/jkqtmathtext_vmatrix.png index 4e4161371a..a799b1ee64 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_vmatrix.png and b/doc/images/jkqtmathtext/jkqtmathtext_vmatrix.png differ diff --git a/doc/images/jkqtmathtext/jkqtmathtext_vvmatrix.png b/doc/images/jkqtmathtext/jkqtmathtext_vvmatrix.png index 0af8d51253..3d9cd102e1 100644 Binary files a/doc/images/jkqtmathtext/jkqtmathtext_vvmatrix.png and b/doc/images/jkqtmathtext/jkqtmathtext_vvmatrix.png differ diff --git a/doc/jkqtmathtext_docimages_accents.jkmt b/doc/jkqtmathtext_docimages_accents.jkmt index 25b58952f2..bd686cfe71 100644 --- a/doc/jkqtmathtext_docimages_accents.jkmt +++ b/doc/jkqtmathtext_docimages_accents.jkmt @@ -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}$ \\ diff --git a/doc/jkqtmathtext_docimages_braces.jkmt b/doc/jkqtmathtext_docimages_braces.jkmt index 6f5b019637..abb52884a3 100644 --- a/doc/jkqtmathtext_docimages_braces.jkmt +++ b/doc/jkqtmathtext_docimages_braces.jkmt @@ -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]$ --- diff --git a/doc/jkqtmathtext_docimages_math.jkmt b/doc/jkqtmathtext_docimages_math.jkmt index 0967ffde39..da465cdba3 100644 --- a/doc/jkqtmathtext_docimages_math.jkmt +++ b/doc/jkqtmathtext_docimages_math.jkmt @@ -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)$ diff --git a/doc/jkqtmathtext_docimages_matrix.jkmt b/doc/jkqtmathtext_docimages_matrix.jkmt index 28662c46aa..879df80e02 100644 --- a/doc/jkqtmathtext_docimages_matrix.jkmt +++ b/doc/jkqtmathtext_docimages_matrix.jkmt @@ -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)$ diff --git a/examples/jkqtmathtext_test/testform.cpp b/examples/jkqtmathtext_test/testform.cpp index e9d984b104..e056c80f4d 100644 --- a/examples/jkqtmathtext_test/testform.cpp +++ b/examples/jkqtmathtext_test/testform.cpp @@ -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}}$"); diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp index 96be8c4267..8d02cba2a2 100644 --- a/lib/jkqtmathtext/jkqtmathtext.cpp +++ b/lib/jkqtmathtext/jkqtmathtext.cpp @@ -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 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 > items; //int lines=0; //int cols=0; bool first=true; + bool firstLine=true; QVector 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 "<(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(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 "<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); diff --git a/lib/jkqtmathtext/jkqtmathtext.h b/lib/jkqtmathtext/jkqtmathtext.h index fec3314822..19ad678537 100644 --- a/lib/jkqtmathtext/jkqtmathtext.h +++ b/lib/jkqtmathtext/jkqtmathtext.h @@ -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 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 */ diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp index c6817ec81f..7645fc1229 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp @@ -553,6 +553,14 @@ void JKQTMathTextHorizontalListNode::clearChildren(bool deleteChildren) clearChildrenImpl(deleteChildren); } +void JKQTMathTextHorizontalListNode::deleteChild(int i) +{ + if (i>=0 && i=0 && i > children): - JKQTMathTextNode(_parent) +JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText* _parent, const QVector > &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; ithis->columns) this->columns=children[i].size(); - } - this->children=children; - for (int i=0; isetParentNode(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 > &children) +{ + this->lines=children.size(); + this->columns=0; + for (int i=0; ithis->columns) this->columns=children[i].size(); + } + this->children=children; + for (int i=0; isetParentNode(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 colwidth, rowheight; - //QVector > widths, heights, baselines; - - double width1=0, baselineHeight1=0, overallHeight1=0, strikeoutPos1=0; - //widths.resize(lines); - colwidth.resize(columns); for (int i=0; igetSize(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; igetFracFactor(); - - - QVector colwidth, rowheight, rowascent; - //QVector > widths, heights, baselines; - - double width1=0, baselineHeight1=0, overallHeight1=0, strikeoutPos=0; - //widths.resize(lines); - colwidth.resize(columns); for (int i=0; igetSize(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; i0) yy=yy+rowascent[0]; - for (int i=0; idraw(painter, xx, yy, ev1); - xx=xx+colwidth[j]+xw; - } - - if (ilines; } + 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 (iaddToErrorList(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 ¤tEv) 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, 0.0); + QVector rowdescent; + rowdescent.resize(lines); + for (int i=0; igetSize(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; igetMatrixXPaddingFactor()*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; idraw(painter, xx+xoffset, yy, ev1); + xx=xx+l.colwidth[j]+XSeparation; + if (i==0 && j > 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 >& children, const QString& columnSpec=QString()); + JKQTMathTextMatrixNode(JKQTMathText* parent, const QString& columnSpec=QString()); virtual ~JKQTMathTextMatrixNode() override; + /** \brief sets the child nodes */ + void setChildren(const QVector >& 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 colwidth; + /** \brief widths of the cells */ + QVector > 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 rowheight; + /** \brief ascents of the rows */ + QVector 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 > children; + /** \brief alignment of the columns */ + QVector columnAlignment; + /** \brief lines to the right of each column */ + QMap verticalLineRHSColumn; + /** \brief line at the left of the table */ + LineType verticalLineLeft; + /** \brief lines to the bottom of each row */ + QMap 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 diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextnode.cpp index 1fd9fdfb9d..15d92b53bb 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextnode.cpp @@ -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) { diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextnode.h index b80b7ed0f1..c07e98bd11 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextnode.h @@ -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 */ diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextnodetools.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextnodetools.cpp index 9bc5d6f0a8..fb0706c29d 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextnodetools.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextnodetools.cpp @@ -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 @@ -65,3 +67,42 @@ JKQTMathTextNode *simplifyJKQTMathTextNode(JKQTMathTextNode *node) } return node; } + +JKQTMathTextNode *simplifyAndTrimJKQTMathTextNode(JKQTMathTextNode *node) +{ + auto cleanText=[](JKQTMathTextNode* t) { + JKQTMathTextMultiChildNode* nmc=dynamic_cast(t); + JKQTMathTextNode* tt0=(nmc&&nmc->childCount()>0)?nmc->getFirstChild():t; + JKQTMathTextNode* tt1=(nmc&&nmc->childCount()>0)?nmc->getLastChild():t; + JKQTMathTextTextNode* txt0=dynamic_cast(tt0); + if (txt0) { + txt0->removeLeadingWhitespace(); + } + JKQTMathTextTextNode* txt1=dynamic_cast(tt1); + if (txt1) { + txt1->removeTrailingWhitespace(); + } + }; + JKQTMathTextNode* t=node; + for (int iter=0; iter<3; iter++) { + t=simplifyJKQTMathTextNode(t); + JKQTMathTextMultiChildNode* nmc=dynamic_cast(t); + if (nmc && nmc->childCount()>0) { + bool done=false; + cleanText(nmc); + while (!done && nmc->childCount()>0) { + JKQTMathTextWhitespaceNode* ws0=dynamic_cast(nmc->getFirstChild()); + JKQTMathTextWhitespaceNode* ws1=dynamic_cast(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; +} diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextnodetools.h b/lib/jkqtmathtext/nodes/jkqtmathtextnodetools.h index eafc409cb1..3ea902703d 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextnodetools.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextnodetools.h @@ -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 diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp index 602e890e81..e9d895997b 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp @@ -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; + } +} + diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h index 52948eddd1..42468d548d 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h @@ -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() */ diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp index 5a4aec5cb2..bdc9d811fa 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp @@ -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("•").addUprightWinSymbol(QChar(0xB7)); symbols["bullet"]=s; symbols["textbullet"]=s; } - symbols["cdots"]=UnicodeSymbol(QChar(0x22EF)).addHtml("···").addStd(QString(3, QChar(0xB7))); + symbols["cdots"]=UprightSymbolUnicode(QChar(0x22EF)).addHtml("···").addStd(QString(3, QChar(0xB7))); { auto s=UnicodeSymbol(QChar(0x2103)).addUprightStd("°C").addUprightHtml("°C"); symbols["celsius"]=s; symbols["degC"]=s; symbols["degreeCelsius"]=s; } symbols["ell"]=UprightSymbolUnicode(QChar(0x2113), "ℓ"); @@ -583,8 +593,6 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["infty"]=UnicodeSymbol(QChar(0x221E)).addHtml("∞").addWinSymbol(QChar(0xA5)).addStd("8", RotateSymbol90); symbols["langle"]=UprightSymbolUnicode(QChar(0x2329)).addWinSymbol(QChar(0xE1)); symbols["lceil"]=UprightSymbolUnicode(QChar(0x2308)).addHtml("⌈").addWinSymbol(QChar(0xE9)); - { auto s=SimpleTextSymbol("...").addUnicode(QChar(0x2026)).addWinSymbol(QChar(0xB6)); - symbols["ldots"]=s; symbols["dots"]=s; } symbols["lfloor"]=UprightSymbolUnicode(QChar(0x230A)).addHtml("⌊").addWinSymbol(QChar(0xEB)); symbols["lightning"]=UnicodeSymbol(QChar(0x21AF)); symbols["male"]=UnicodeSymbol(QChar(0x2642)).addHtml("♂"); @@ -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 max").addGlobalFlags(SubSuperscriptBelowAboveSymbol); - symbols["argmin"] = MathOperatorText("arg min", "arg 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 inf").addGlobalFlags(SubSuperscriptBelowAboveSymbol); - symbols["limsup"] = MathOperatorText("lim sup", "lim 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 max").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["argmin"] = NarrowMathOperatorText("arg min", "arg 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 inf").addGlobalFlags(SubSuperscriptBelowAboveSymbol); + symbols["limsup"] = NarrowMathOperatorText("lim sup", "lim 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("⇕"); symbols["approx"]=MathOperatorSymbolUnicode(QChar(0x2248)).addMathOperatorHtml("≈").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("∵"); symbols["bigcap"]=NarrowMathOperatorSymbolUnicode(QChar(0x22C2)).addMathOperatorHtml("⋂").addMathOperatorWinSymbol(QChar(0xC7), 1.8).addGlobalFlags(SubSuperscriptBelowAboveSymbol); symbols["bigcup"]=NarrowMathOperatorSymbolUnicode(QChar(0x22C3)).addMathOperatorHtml("⋃").addMathOperatorWinSymbol(QChar(0xC8), 1.8).addGlobalFlags(SubSuperscriptBelowAboveSymbol); @@ -727,7 +735,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["coprod"]=NarrowMathOperatorSymbolUnicode(QChar(0x2210)).addMathOperatorHtml("∐").addWinSymbol(QChar(0xD5), ItalicOff|BoldOff|FlipSymbolUpDown, 1.8, 0.1).addGlobalFlags(SubSuperscriptBelowAboveSymbol); { auto s=MathOperatorSymbolUnicode(QChar(0x222A)).addMathOperatorHtml("∪").addMathOperatorWinSymbol(QChar(0xC8)); symbols["cup"]=s; symbols["lor"]=s; } - symbols["ddots"]=MathOperatorSymbolUnicode(QChar(0x22F1)).addMathOperatorHtml("⋱"); + symbols["ddots"]=UprightSymbolUnicode(QChar(0x22F1)).addMathOperatorHtml("⋱"); symbols["div"]=MathOperatorSymbolUnicode(QChar(0x00F7)).addMathOperatorHtml("÷").addMathOperatorWinSymbol(QChar(0xB8)); symbols["downarrow"]=UprightSymbolUnicode(QChar(0x2193)).addUprightHtml("↓").addUprightWinSymbol(QChar(0xAF)); symbols["downharpoonleft"]=UprightSymbolUnicode(QChar(0x21C3)).addUprightHtml("⇃"); @@ -735,13 +743,13 @@ void JKQTMathTextSymbolNode::fillSymbolTables() { auto s=MathOperatorSymbolUnicode(QChar(0x2205)).addMathOperatorHtml("∅").addMathOperatorWinSymbol(QChar(0xC6)).addStd("0", BoldOff|ItalicOff|DrawSlash); symbols["emptyset"]=s; symbols["varnothing"]=s; } symbols["equiv"]=MathOperatorSymbolUnicode(QChar(0x2261)).addMathOperatorHtml("≡").addMathOperatorWinSymbol(QChar(0xBA)); - symbols["exists"]=MathOperatorSymbolUnicode(QChar(0x2203)).addMathOperatorHtml("∃").addMathOperatorWinSymbol(QChar(0x24)).addStd("E", ItalicOff|BoldOff|FlipSymbolLeftRight); - symbols["forall"]=MathOperatorSymbolUnicode(QChar(0x2200)).addMathOperatorHtml("∀").addMathOperatorWinSymbol(QChar(0x22)).addStd("A", ItalicOff|BoldOff|FlipSymbolUpDown); + symbols["exists"]=NarrowMathOperatorSymbolUnicode(QChar(0x2203)).addMathOperatorHtml("∃").addMathOperatorWinSymbol(QChar(0x24)).addStd("E", ItalicOff|BoldOff|FlipSymbolLeftRight); + symbols["forall"]=NarrowMathOperatorSymbolUnicode(QChar(0x2200)).addMathOperatorHtml("∀").addMathOperatorWinSymbol(QChar(0x22)).addStd("A", ItalicOff|BoldOff|FlipSymbolUpDown); { auto s=MathOperatorSymbolUnicode(QChar(0x2265)).addMathOperatorHtml("≥").addMathOperatorWinSymbol(QChar(0xB3)); symbols["geq"]=s; symbols["ge"]=s; } symbols["geqq"]=MathOperatorSymbolUnicode(QChar(0x2267)).addMathOperatorHtml("≧"); symbols["gg"]=MathOperatorSymbolUnicode(QChar(0x226B)).addMathOperatorHtml("≫").addMathOperatorStd(">>"); - symbols["iddots"]=MathOperatorSymbolUnicode(QChar(0x22F0)).addMathOperatorHtml("⋰"); + symbols["iddots"]=UprightSymbolUnicode(QChar(0x22F0)).addMathOperatorHtml("⋰"); { auto s=UprightSymbolUnicode(QChar(0x21D4)).addUprightHtml("⇔").addUprightWinSymbol(QChar(0xDB)); symbols["iff"]=s; symbols["Leftrightarrow"]=s; } symbols["iiint"]=NarrowMathOperatorSymbolUnicode(QChar(0x222D)).addGlobalFlags(IntLikeSymbolCorrection | SubSuperscriptBelowAboveSymbol).addMathOperatorHtml("∭").addMathOperatorWinSymbol(QString(3, QChar(0xF2)), 1.8, 0.1); @@ -770,17 +778,17 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["mid"]=MathOperatorSymbolUnicode(QChar(0x2223)).addMathOperatorHtml("∣").addMathOperatorWinSymbol(QChar(0xBD)).addMathOperatorStd("|"); symbols["mp"]=MathOperatorSymbolUnicode(QChar(0x2213)).addMathOperatorHtml("∓").addWinSymbol(QChar(0xB1),ItalicOff|BoldOff|FlipSymbolUpDown).addStd(QChar(0xB1),ItalicOff|BoldOff|FlipSymbolUpDown); symbols["multimap"]=MathOperatorSymbolUnicode(QChar(0x22B8)).addMathOperatorHtml("⊸"); - symbols["nabla"]=MathOperatorSymbolUnicode(QChar(0x2207)).addMathOperatorHtml("∇").addMathOperatorWinSymbol(QChar(0xD1)); - symbols["ne"]=MathOperatorSymbolUnicode(QChar(0x2260)).addMathOperatorHtml("≠").addMathOperatorWinSymbol(QChar(0xB9)); + symbols["nabla"]=NarrowMathOperatorSymbolUnicode(QChar(0x2207)).addMathOperatorHtml("∇").addMathOperatorWinSymbol(QChar(0xD1)); + symbols["ne"]=NarrowMathOperatorSymbolUnicode(QChar(0x2260)).addMathOperatorHtml("≠").addMathOperatorWinSymbol(QChar(0xB9)); symbols["nearrow"]=UprightSymbolUnicode(QChar(0x2197)).addUprightHtml("↗"); { auto s=MathOperatorSymbolUnicode(QChar(0x00AC)).addMathOperatorHtml("¬").addMathOperatorWinSymbol(QChar(0xD8)); symbols["neg"]=s; symbols["lnot"]=s; } symbols["neq"]=MathOperatorSymbolUnicode(QChar(0x2260)).addMathOperatorHtml("≠").addMathOperatorWinSymbol(QChar(0xB9)).addStd("=", ItalicOff|BoldOff|DrawSlash); - symbols["nexists"]=MathOperatorSymbolUnicode(QChar(0x2204)).addMathOperatorHtml("∄").addStd("E", ItalicOff|BoldOff|FlipSymbolLeftRight|DrawSlash).addMathOperatorWinSymbol(QChar(0x24), ItalicOff|BoldOff|DrawSlash); - symbols["ni"]=MathOperatorSymbolUnicode(QChar(0x220B)).addMathOperatorHtml("∋").addMathOperatorWinSymbol(QChar(0xCE), ItalicOff|BoldOff|FlipSymbolLeftRight); - symbols["nmid"]=MathOperatorSymbolUnicode(QChar(0x2224)).addMathOperatorHtml("∤"); - symbols["notin"]=MathOperatorSymbolUnicode(QChar(0x2209)).addMathOperatorHtml("∉").addMathOperatorWinSymbol(QChar(0xCF)); - symbols["notni"]=MathOperatorSymbolUnicode(QChar(0x220C)).addMathOperatorHtml("∌"); + symbols["nexists"]=NarrowMathOperatorSymbolUnicode(QChar(0x2204)).addMathOperatorHtml("∄").addStd("E", ItalicOff|BoldOff|FlipSymbolLeftRight|DrawSlash).addMathOperatorWinSymbol(QChar(0x24), ItalicOff|BoldOff|DrawSlash); + symbols["ni"]=NarrowMathOperatorSymbolUnicode(QChar(0x220B)).addMathOperatorHtml("∋").addMathOperatorWinSymbol(QChar(0xCE), ItalicOff|BoldOff|FlipSymbolLeftRight); + symbols["nmid"]=NarrowMathOperatorSymbolUnicode(QChar(0x2224)).addMathOperatorHtml("∤"); + symbols["notin"]=NarrowMathOperatorSymbolUnicode(QChar(0x2209)).addMathOperatorHtml("∉").addMathOperatorWinSymbol(QChar(0xCF)); + symbols["notni"]=NarrowMathOperatorSymbolUnicode(QChar(0x220C)).addMathOperatorHtml("∌"); symbols["nparallel"]=MathOperatorSymbolUnicode(QChar(0x2226)).addMathOperatorHtml("∦"); symbols["nwarrow"]=UprightSymbolUnicode(QChar(0x2196)).addUprightHtml("↖"); symbols["odot"]=MathOperatorSymbolUnicode(QChar(0x2299)).addMathOperatorHtml("⊙"); @@ -791,7 +799,7 @@ void JKQTMathTextSymbolNode::fillSymbolTables() symbols["oplus"]=MathOperatorSymbolUnicode(QChar(0x2295)).addMathOperatorHtml("⊕").addMathOperatorWinSymbol(QChar(0xC5)); symbols["oslash"]=MathOperatorSymbolUnicode(QChar(0x2298)).addMathOperatorHtml("⊘"); symbols["otimes"]=MathOperatorSymbolUnicode(QChar(0x2297)).addMathOperatorHtml("⊗").addMathOperatorWinSymbol(QChar(0xC4)); - symbols["parallel"]=MathOperatorSymbolUnicode(QChar(0x2225)).addMathOperatorHtml("∥").addMathOperatorStd("||"); + symbols["parallel"]=NarrowMathOperatorSymbolUnicode(QChar(0x2225)).addMathOperatorHtml("∥").addMathOperatorStd("||"); symbols["pm"] = MathOperatorSymbol(QChar(0xB1), "±").addMathOperatorWinSymbol(QChar(0xB1)); symbols["prec"]=MathOperatorSymbolUnicode(QChar(0x227A)).addMathOperatorHtml("≺"); symbols["prod"]=NarrowMathOperatorSymbolUnicode(QChar(0x220F)).addMathOperatorWinSymbol(QChar(0xD5), 1.8, 0.1).addMathOperatorHtml("∏").addGlobalFlags(SubSuperscriptBelowAboveSymbol); @@ -821,13 +829,13 @@ void JKQTMathTextSymbolNode::fillSymbolTables() { auto s=UprightSymbolUnicode(QChar(0x2192)).addUprightHtml("→").addUprightWinSymbol(QChar(0xAE)); symbols["to"]=s; symbols["rightarrow"]=s; } symbols["top"]=MathOperatorSymbolUnicode(QChar(0x22A4)).addMathOperatorHtml("⊤").addMathOperatorWinSymbol(QChar(0x5E)); - symbols["triangle"]=MathOperatorSymbolUnicode(QChar(0x2206)); + symbols["triangle"]=NarrowMathOperatorSymbolUnicode(QChar(0x2206)); symbols["uparrow"]=UprightSymbolUnicode(QChar(0x2191)).addUprightHtml("↑").addUprightWinSymbol(QChar(0xAD)); symbols["updownarrow"]=UprightSymbolUnicode(QChar(0x2195)).addUprightHtml("↕"); symbols["upharpoonleft"]=UprightSymbolUnicode(QChar(0x21BF)).addUprightHtml("↿"); symbols["upharpoonright"]=UprightSymbolUnicode(QChar(0x21BE)).addUprightHtml("↾"); - symbols["vartriangleleft"]=MathOperatorSymbolUnicode(QChar(0x22B2)).addMathOperatorHtml("⊲"); - symbols["vdots"]=MathOperatorSymbolUnicode(QChar(0x22EE)).addMathOperatorHtml("⋮"); + symbols["vartriangleleft"]=NarrowMathOperatorSymbolUnicode(QChar(0x22B2)).addMathOperatorHtml("⊲"); + symbols["vdots"]=UprightSymbolUnicode(QChar(0x22EE)).addMathOperatorHtml("⋮"); symbols["vee"]=MathOperatorSymbolUnicode(QChar(0x2228)).addMathOperatorHtml("∨").addMathOperatorWinSymbol(QChar(0xDA)); symbols["vdash"]=MathOperatorSymbolUnicode(QChar(0x22A2)).addMathOperatorHtml("⊢"); symbols["dashv"]=MathOperatorSymbolUnicode(QChar(0x22A3)).addMathOperatorHtml("⊣"); diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h index 54c1a06bbd..5d59fb5d87 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h @@ -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 */ diff --git a/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp index 8d5a4adebb..222223e66b 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp @@ -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 ¤tEv) const { QString txt=text; diff --git a/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.h b/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.h index 8d996df4f6..f5f76fa622 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.h @@ -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 {