NEW/BREAKING: restructured JKQTMathText: broke up single, large CPP-file into several smaller files

added more examples to jkqtmathtext_test
This commit is contained in:
jkriege2 2022-06-08 15:38:26 +02:00
parent b0f8a2d0b9
commit 94ca27aed0
37 changed files with 6252 additions and 5067 deletions

View File

@ -26,8 +26,9 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: new "seaborn" style for plots</li>
<li>NEW/BREAKING CHANGE: changed JKQTPColorDerivationMode into a struct, which extends its capabilities above the previously available few enum-items</li>
<li>NEW: added debug-feature to show boxes around text in the plot</li>
<li>NEW: JKQTMathText supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve</li>
<li>NEW: JKQTMathText: now supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve</li>
<li>NEW: JKQTMathText: reworked drawing of decorations: improved appearance and positioning!</li>
<li>NEW: JKQTMathText: reworked code structure: broke up large, single CPP-files into several smaller files!</li>
</ul>
\subsection page_whatsnew_TRUNK_DOWNLOAD trunk: Download

View File

@ -23,7 +23,7 @@ And the source code of the main application is (see [`jkqtmathtext_simpletest.cp
#include <QApplication>
#include <QLabel>
#include <QPixmap>
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtmathtext/jkqtmathtextlabel.h"
int main(int argc, char* argv[])
{

View File

@ -7,7 +7,7 @@
#include <QApplication>
#include <QLabel>
#include <QPixmap>
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtmathtext/jkqtmathtextlabel.h"
int main(int argc, char* argv[])
{

View File

@ -1,6 +1,16 @@
#include "testform.h"
#include "ui_testform.h"
#include <QDebug>
#include "jkqtmathtext/nodes/jkqtmathtexttextnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextbracenode.h"
#include "jkqtmathtext/nodes/jkqtmathtextdecoratednode.h"
#include "jkqtmathtext/nodes/jkqtmathtextfracnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextinstructionnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextlistnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextmatrixnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsqrtnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsubsupernode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsymbolnode.h"
TestForm::TestForm(QWidget *parent) :
@ -8,24 +18,24 @@ TestForm::TestForm(QWidget *parent) :
ui(new Ui::TestForm)
{
ui->setupUi(this);
ui->cmbTestset->addItem("fonts", "rm: \\textrm{ABCabc123}, sf: \\textsf{ABCabc123}, tt: \\texttt{ABCabc123}, cal: \\textcal{ABCabc123}, scr: \\textscr{ABCabc123}, bb: \\textbb{ABCabc123}, frak: \\textfrak{ABCabc123}, ");
ui->cmbTestset->addItem("text: fonts", "rm: \\textrm{ABCabc123}, sf: \\textsf{ABCabc123}, tt: \\texttt{ABCabc123}, cal: \\textcal{ABCabc123}, scr: \\textscr{ABCabc123}, bb: \\textbb{ABCabc123}, frak: \\textfrak{ABCabc123}, ");
ui->cmbTestset->addItem("math-fonts", "rm: $\\mathrm{ABCabc123}$, sf: $\\mathsf{ABCabc123}$, tt: $\\mathtt{ABCabc123}$, cal: $\\mathcal{ABCabc123}$, scr: $\\mathscr{ABCabc123}$, bb: $\\mathbb{ABCabc123}$, frak: $\\mathfrak{ABCabc123}$, ");
ui->cmbTestset->addItem("simple relations", "$a{\\leq}b$, $a{\\geq}b$, $a{\\equiv}b$, $a=b$, $a{\\neq}b$, $a<b$, $a>b$");
ui->cmbTestset->addItem("simple relations in different modes", "math: $a{\\leq}b$, math/no braces: $a\\leq b$, no math: a{\\leq}b, no math/no braces: a\\leq b");
ui->cmbTestset->addItem("named symbols 1", "ll: $\\ll$\\ gg: $\\gg$\\ leq: $\\leq$\\ geq: $\\geq$\\ pm: $\\pm$\\ mp: $\\mp$\\ ");
ui->cmbTestset->addItem("named symbols 2", "nexists: $\\nexists$\\ ni: $\\ni$\\ notni: $\\notni$\\ circ: $\\circ$\\ sim: $\\sim$\\ emptyset: $\\emptyset$\\ odot: $\\odot$\\ ominus: $\\ominus$\\ subsetnot: $\\subsetnot$\\ bot: $\\bot$");
ui->cmbTestset->addItem("named symbols 3", "leftharpoonup: $\\leftharpoonup$\\ rightharpoonup: $\\rightharpoonup$\\ upharpoonleft: $\\upharpoonleft$\\ downharpoonleft: $\\downharpoonleft$\\ leftrightharpoon: $\\leftrightharpoon$\\ rightleftharpoon: $\\rightleftharpoon$");
ui->cmbTestset->addItem("named symbols 4", "coprod: $\\coprod$\\ leftharpoondown: $\\leftharpoondown$\\ rightharpoondown: $\\rightharpoondown$\\ upharpoonright: $\\upharpoonright$\\ downharpoonright: $\\downharpoonright$\\ nwarrow: $\\nwarrow$\\ nearrow: $\\nearrow$\\ ");
ui->cmbTestset->addItem("named symbols 5", "searrow: $\\searrow$\\ swarrow: $\\swarrow$\\ mapsto: $\\mapsto$\\ div: $\\div$\\ multimap: $\\multimap$\\ maporiginal: $\\maporiginal$\\ mapimage: $\\mapimage$\\ ");
ui->cmbTestset->addItem("named symbols 6", "times: $\\times$\\ ast: $\\ast$\\ star: $\\star$\\ propto: $\\propto$\\ bullet: $\\bullet$\\ neq: $\\neq$\\ ne: $\\ne$\\ equiv: $\\equiv$\\ approx: $\\approx$\\ otimes: $\\otimes$\\ oplus: $\\oplus$");
ui->cmbTestset->addItem("named symbols 7", "oslash: $\\oslash$\\ cap: $\\cap$\\ land: $\\land$\\ cup: $\\cup$\\ lor: $\\lor$\\ supset: $\\supset$\\ supseteq: $\\supseteq$\\ supsetnot: $\\supsetnot$\\ subset: $\\subset$");
ui->cmbTestset->addItem("named symbols 8", "subseteq: $\\subseteq$\\ in: $\\in$\\ notin: $\\notin$\\ cdot: $\\cdot$\\ wedge: $\\wedge$\\ vee: $\\vee$\\ cong: $\\cong$\\ bot: $\\bot$");
ui->cmbTestset->addItem("symbols", "$\\ll\\gg\\leq\\geq\\leftrightarrow\\leftarrow\\rightarrow\\to\\uparrow\\downarrow\\updownarrow\\Leftrightarrow\\iff\\Leftarrow\\Rightarrow\\Uparrow\\Downarrow\\Updownarrow\\pm\\mp\\nexists\\ni\\notni\\circ\\sim\\emptyset\\odot\\ominus\\subsetnot\\bot\\leftharpoonup\\rightharpoonup\\upharpoonleft\\downharpoonleft\\leftrightharpoon\\rightleftharpoon\\coprod\\leftharpoondown\\rightharpoondown\\upharpoonright\\downharpoonright\\nwarrow\\nearrow\\searrow\\swarrow\\mapsto\\div\\multimap\\maporiginal\\mapimage\\times\\propto\\bullet\\neq\\ne\\equiv\\approx\\otimes\\oplus\\oslash\\cap\\land\\cup\\lor\\supset\\supseteq\\supsetnot\\subset\\subseteq\\in\\notin\\cdot\\wedge\\vee\\cong\\bot$");
ui->cmbTestset->addItem("std dev", "$\\sigma_x=\\sqrt{\\langle (x-\\langle x\\rangle)^2\\rangle}=\\sqrt{\\frac{1}{N-1}\\cdot\\left( \\sum_{i=1}^N{x_i}^2-\\frac{1}{N}\\cdot\\left(\\sum_{i=1}^Nx_i\\right)^2\\right)}$");
ui->cmbTestset->addItem("std dev 2", "$\\sigma_x=\\sqrt{\\langle (x-\\langle x\\rangle)^2\\rangle}=\\sqrt{\\frac{1}{N-1}\\cdot\\left( \\sum_{i=1}^Nx_i^2-\\frac{1}{N}\\cdot\\left(\\sum_{i=1}^Nx_i\\right)^2\\right)}$");
ui->cmbTestset->addItem("rotation matrix", "$\\mathrm{\\mathbf{M}}(\\alpha) = \\left(\\begin{matrix}\\cos(\\alpha)+n_x^2\\cdot (1-\\cos(\\alpha)) & n_x\\cdot n_y\\cdot (1-\\cos(\\alpha))-n_z\\cdot \\sin(\\alpha) & n_x\\cdot n_z\\cdot (1-\\cos(\\alpha))+n_y\\cdot \\sin(\\alpha)\\\\n_x\\cdot n_y\\cdot (1-\\cos(\\alpha))+n_z\\cdot \\sin(\\alpha) & \\cos(\\alpha)+n_y^2\\cdot (1-\\cos(\\alpha)) & n_y\\cdot n_z\\cdot (1-\\cos(\\alpha))-n_x\\cdot \\sin(\\alpha)\\\\n_z\\cdot n_x\\cdot (1-\\cos(\\alpha))-n_y\\cdot \\sin(\\alpha) & n_z\\cdot n_y\\cdot (1-\\cos(\\alpha))+n_x\\cdot \\sin(\\alpha) & \\cos(\\alpha)+n_z^2\\cdot (1-\\cos(\\alpha))\\end{matrix}\\right)$");
ui->cmbTestset->addItem("like in label at bottom (no MM)", "\\left(\\left[\\sqrt{2\\pi\\cdot\\int_{-\\infty}^\\infty f(x)\\;\\mathrm{d}x}\\right]\\right)");
ui->cmbTestset->addItem("like in label at bottom (MM)", "$\\left(\\left[\\sqrt{2\\pi\\cdot\\int_{-\\infty}^\\infty f(x)\\;\\mathrm{d}x}\\right]\\right)$");
ui->cmbTestset->addItem("math: simple relations", "$a{\\leq}b$, $a{\\geq}b$, $a{\\equiv}b$, $a=b$, $a{\\neq}b$, $a<b$, $a>b$");
ui->cmbTestset->addItem("text/math: simple relations in different modes", "math: $a{\\leq}b$, math/no braces: $a\\leq b$, no math: a{\\leq}b, no math/no braces: a\\leq b");
ui->cmbTestset->addItem("math: named symbols 1", "ll: $\\ll$\\ gg: $\\gg$\\ leq: $\\leq$\\ geq: $\\geq$\\ pm: $\\pm$\\ mp: $\\mp$\\ ");
ui->cmbTestset->addItem("math: named symbols 2", "nexists: $\\nexists$\\ ni: $\\ni$\\ notni: $\\notni$\\ circ: $\\circ$\\ sim: $\\sim$\\ emptyset: $\\emptyset$\\ odot: $\\odot$\\ ominus: $\\ominus$\\ subsetnot: $\\subsetnot$\\ bot: $\\bot$");
ui->cmbTestset->addItem("math: named symbols 3", "leftharpoonup: $\\leftharpoonup$\\ rightharpoonup: $\\rightharpoonup$\\ upharpoonleft: $\\upharpoonleft$\\ downharpoonleft: $\\downharpoonleft$\\ leftrightharpoon: $\\leftrightharpoon$\\ rightleftharpoon: $\\rightleftharpoon$");
ui->cmbTestset->addItem("math: named symbols 4", "coprod: $\\coprod$\\ leftharpoondown: $\\leftharpoondown$\\ rightharpoondown: $\\rightharpoondown$\\ upharpoonright: $\\upharpoonright$\\ downharpoonright: $\\downharpoonright$\\ nwarrow: $\\nwarrow$\\ nearrow: $\\nearrow$\\ ");
ui->cmbTestset->addItem("math: named symbols 5", "searrow: $\\searrow$\\ swarrow: $\\swarrow$\\ mapsto: $\\mapsto$\\ div: $\\div$\\ multimap: $\\multimap$\\ maporiginal: $\\maporiginal$\\ mapimage: $\\mapimage$\\ ");
ui->cmbTestset->addItem("math: named symbols 6", "times: $\\times$\\ ast: $\\ast$\\ star: $\\star$\\ propto: $\\propto$\\ bullet: $\\bullet$\\ neq: $\\neq$\\ ne: $\\ne$\\ equiv: $\\equiv$\\ approx: $\\approx$\\ otimes: $\\otimes$\\ oplus: $\\oplus$");
ui->cmbTestset->addItem("math: named symbols 7", "oslash: $\\oslash$\\ cap: $\\cap$\\ land: $\\land$\\ cup: $\\cup$\\ lor: $\\lor$\\ supset: $\\supset$\\ supseteq: $\\supseteq$\\ supsetnot: $\\supsetnot$\\ subset: $\\subset$");
ui->cmbTestset->addItem("math: named symbols 8", "subseteq: $\\subseteq$\\ in: $\\in$\\ notin: $\\notin$\\ cdot: $\\cdot$\\ wedge: $\\wedge$\\ vee: $\\vee$\\ cong: $\\cong$\\ bot: $\\bot$");
ui->cmbTestset->addItem("math: symbols", "$\\ll\\gg\\leq\\geq\\leftrightarrow\\leftarrow\\rightarrow\\to\\uparrow\\downarrow\\updownarrow\\Leftrightarrow\\iff\\Leftarrow\\Rightarrow\\Uparrow\\Downarrow\\Updownarrow\\pm\\mp\\nexists\\ni\\notni\\circ\\sim\\emptyset\\odot\\ominus\\subsetnot\\bot\\leftharpoonup\\rightharpoonup\\upharpoonleft\\downharpoonleft\\leftrightharpoon\\rightleftharpoon\\coprod\\leftharpoondown\\rightharpoondown\\upharpoonright\\downharpoonright\\nwarrow\\nearrow\\searrow\\swarrow\\mapsto\\div\\multimap\\maporiginal\\mapimage\\times\\propto\\bullet\\neq\\ne\\equiv\\approx\\otimes\\oplus\\oslash\\cap\\land\\cup\\lor\\supset\\supseteq\\supsetnot\\subset\\subseteq\\in\\notin\\cdot\\wedge\\vee\\cong\\bot$");
ui->cmbTestset->addItem("math: std dev", "$\\sigma_x=\\sqrt{\\langle (x-\\langle x\\rangle)^2\\rangle}=\\sqrt{\\frac{1}{N-1}\\cdot\\left( \\sum_{i=1}^N{x_i}^2-\\frac{1}{N}\\cdot\\left(\\sum_{i=1}^Nx_i\\right)^2\\right)}$");
ui->cmbTestset->addItem("math: std dev 2", "$\\sigma_x=\\sqrt{\\langle (x-\\langle x\\rangle)^2\\rangle}=\\sqrt{\\frac{1}{N-1}\\cdot\\left( \\sum_{i=1}^Nx_i^2-\\frac{1}{N}\\cdot\\left(\\sum_{i=1}^Nx_i\\right)^2\\right)}$");
ui->cmbTestset->addItem("math: rotation matrix", "$\\mathrm{\\mathbf{M}}(\\alpha) = \\left(\\begin{matrix}\\cos(\\alpha)+n_x^2\\cdot (1-\\cos(\\alpha)) & n_x\\cdot n_y\\cdot (1-\\cos(\\alpha))-n_z\\cdot \\sin(\\alpha) & n_x\\cdot n_z\\cdot (1-\\cos(\\alpha))+n_y\\cdot \\sin(\\alpha)\\\\n_x\\cdot n_y\\cdot (1-\\cos(\\alpha))+n_z\\cdot \\sin(\\alpha) & \\cos(\\alpha)+n_y^2\\cdot (1-\\cos(\\alpha)) & n_y\\cdot n_z\\cdot (1-\\cos(\\alpha))-n_x\\cdot \\sin(\\alpha)\\\\n_z\\cdot n_x\\cdot (1-\\cos(\\alpha))-n_y\\cdot \\sin(\\alpha) & n_z\\cdot n_y\\cdot (1-\\cos(\\alpha))+n_x\\cdot \\sin(\\alpha) & \\cos(\\alpha)+n_z^2\\cdot (1-\\cos(\\alpha))\\end{matrix}\\right)$");
ui->cmbTestset->addItem("text: like in label at bottom)", "\\left(\\left[\\sqrt{2\\pi\\cdot\\int_{-\\infty}^\\infty f(x)\\;\\mathrm{d}x}\\right]\\right)");
ui->cmbTestset->addItem("math: like in label at bottom", "$\\left(\\left[\\sqrt{2\\pi\\cdot\\int_{-\\infty}^\\infty f(x)\\;\\mathrm{d}x}\\right]\\right)$");
ui->cmbTestset->addItem("text 0", "text");
ui->cmbTestset->addItem("text 1", "text \\mathbf{bold}");
ui->cmbTestset->addItem("text 2", "text \\mathbf{bold}\\textcolor{red}{RED}");
@ -33,76 +43,88 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbTestset->addItem("decoration: math", "$"+mathDecoExample("vec")+" -- "+mathDecoExample("dot")+" -- "+mathDecoExample("ddot")+" -- "+mathDecoExample("ocirc")+" -- "+mathDecoExample("overline")+" -- "+mathDecoExample("underline")+" -- "+mathDecoExample("hat")+" -- "+mathDecoExample("widehat")+" -- "+mathDecoExample("check")+" -- "+mathDecoExample("widecheck")+" -- "+mathDecoExample("breve")+" -- "+mathDecoExample("tilde")+" -- "+mathDecoExample("widetilde")+" -- "+mathDecoExample("uul")+" -- "+mathDecoExample("ool")+" -- "+mathDecoExample("bar")+" -- "+mathDecoExample("arrow")+" -- "+mathDecoExample("cancel")+" -- "+mathDecoExample("bcancel")+" -- "+mathDecoExample("xcancel")+" -- "+mathDecoExample("sout")+"$");
ui->cmbTestset->addItem("decoration: text", "Text \\ul{underlined Text Equator} -- \\ol{overlined Text Equator} -- \\sout{striked out Text Equator} -- \\cancel{canceled out Text Equator} -- \\bcancel{b-canceled out Text Equator} -- \\xcancel{x-canceled out Text Equator}");
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\\{\\va\\left|\\|\\va\\|_2\\geq2\\right.\\right\\} \\vr\\vR\\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("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("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}}$");
ui->cmbTestset->addItem("MSD test", "$\\mathrm{MSD}(\\tau)\\equiv\\langle r^2(\\tau)\\rangle=\\left\\langle (\\vec{r}(t)-\\vec{r}(t+\\tau) )^2\\right\\rangle=2n\\cdot\\frac{K_\\alpha}{\\Gamma(1+\\alpha)}\\cdot\\tau^\\alpha$");
ui->cmbTestset->addItem("f() test", "$f(\\vec{x})=\\frac{1}{\\sqrt{2\\pi\\cdot\\sigma^2}}\\exp\\left(-\\frac{(\\vec{x}-\\vec{x}_0)^2}{\\sigma^2}\\right)$");
ui->cmbTestset->addItem("chi^2 test", "$\\vec{p}^\\ast=\\argmax\\limits_{\\vec{p}}\\chi^2=\\argmax\\limits_{\\vec{p}}\\sum\\limits_{i=1}^N\\left|\\frac{\\hat{f}_i-f(x_i;\\vec{p})}{\\sigma_i}\\right|^2$");
ui->cmbTestset->addItem("symbol test", "\\vdots\\cdots\\ddots\\iddots\\lfloor\\rfloor\\lceil\\rceil\\langle\\rangle\\sum\\int \\iint \\oint \\prod \\leftrightarrow \\leftarrow\\Leftarrow\\rightarrow\\Rightarrow\\pm\\mp\\leq\\geq\\ll\\gg\\hbar\\euro\\bbC\\bbH\\bbN\\bbP\\bbQ\\bbZ\\bbR\\Angstrom\\Alef\\Bet\\Gimel\\Dalet\\nexists\\ni\\notni\\circ\\tilde\\oiint\\oiiint\\emptyset\\odot\\ominus\\subsetnot\\DC\\bot\\cdots\\perthousand\\leftharpoonup\\rightharpoonup \\upharpoonleft \\downharpoonleft \\leftrightharpoon \\rightleftharpoon \\coprod \\leftharpoondown \\rightharpoondown \\nwarrow \\nearrow \\mapsto \\cent \\pound \\yen \\div \\multimap \\maporiginal \\mapimage \\bigcap \\bigcup \\benzene \\times \\cdot \\propto \\equiv \\Im \\Re \\ ");
ui->cmbTestset->addItem("arrowtest 1", "$\\leftarrow \\longleftarrow \\Leftarrow \\Longleftarrow \\rightarrow \\longrightarrow \\Rightarrow \\Longrightarrow \\uparrow \\Uparrow \\downarrow \\Downarrow \\leftrightarrow \\Leftrightarrow \\longleftrightarrow \\Longleftrightarrow$");
ui->cmbTestset->addItem("arrowtest 2", "$\\nwarrow \\nearrow \\searrow \\swarrow \\mapsto \\leftharpoonup \\rightharpoonup \\upharpoonleft \\downharpoonleft \\leftrightharpoon \\rightleftharpoon \\leftharpoondown \\rightharpoondown \\upharpoonright \\downharpoonright $");
ui->cmbTestset->addItem("math: greek letters", "$\\alpha\\beta\\gamma\\delta\\epsilon\\varepsilon\\zeta\\eta\\theta\\vartheta\\iota\\kappa\\lambda\\mu\\nu\\xi\\pi\\varpi\\rho\\varrho\\sigma\\varsigma\\tau\\upsilon\\phi\\varphi\\chi\\psi\\omega\\Omega\\Gamma\\Delta\\Theta\\Lambda\\Xi\\Pi\\Sigma\\Upsilon\\Phi\\Psi$");
ui->cmbTestset->addItem("text: greek letters", "\\alpha\\beta\\gamma\\delta\\epsilon\\varepsilon\\zeta\\eta\\theta\\vartheta\\iota\\kappa\\lambda\\mu\\nu\\xi\\pi\\varpi\\rho\\varrho\\sigma\\varsigma\\tau\\upsilon\\phi\\varphi\\chi\\psi\\omega\\Omega\\Gamma\\Delta\\Theta\\Lambda\\Xi\\Pi\\Sigma\\Upsilon\\Phi\\Psi");
ui->cmbTestset->addItem("math: blackboard", "$\\mathbb{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math: bf", "$\\mathbf{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math: it", "$\\mathit{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math: frak", "$\\mathfrak{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math: sf", "$\\mathsf{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math: rm", "$\\mathrm{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math: cal", "$\\mathcal{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math: script", "$\\mathscr{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math: tt", "$\\mathtt{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("bf", "\\textbf{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("it", "\\textit{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("frak", "\\textfrak{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("sf", "\\textsf{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("rm", "\\textrm{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("cal", "\\textcal{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("script", "\\textscr{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("tt", "\\texttt{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("subscript test", "$r_{123}\\ \\ r_{\\frac{1}{2}}$");
ui->cmbTestset->addItem("subscript0 test", "$r_{123}$");
ui->cmbTestset->addItem("subscript1 test", "$r_{123}\\ $");
ui->cmbTestset->addItem("subscript2 test", "$r_{123}\\ \\ $");
ui->cmbTestset->addItem("subscript3 test", "$r_{123}r_{\\frac{1}{2}}$");
ui->cmbTestset->addItem("superscript test", "$r^{123}\\ \\ r^{\\frac{1}{2}}$");
ui->cmbTestset->addItem("superscript0 test", "$r^{123}$");
ui->cmbTestset->addItem("superscript1 test", "$r^{123}\\ $");
ui->cmbTestset->addItem("superscript2 test", "$r^{123}\\ \\ $");
ui->cmbTestset->addItem("superscript3 test", "$r^{123}r^{\\frac{1}{2}}$");
ui->cmbTestset->addItem("asuperscript test", "$a^{123}\\ \\ a^{\\frac{1}{2}}$");
ui->cmbTestset->addItem("asuperscript0 test", "$a^{123}$");
ui->cmbTestset->addItem("gsuperscript1 test", "$g^{123}\\ $");
ui->cmbTestset->addItem("gsuperscript2 test", "$g^{123}\\ \\ $");
ui->cmbTestset->addItem("gsuperscript3 test", "$g^{123}g^{\\frac{1}{2}}$");
ui->cmbTestset->addItem("subsuperscript test", "$r_{123}^2$\\ \\ $r^2_{123}$\\ \\ $\\left(\\stackrel{a}{b}\\right)_{123}^2$\\ \\ $\\left(\\stackrel{a}{b}\\right)^2_{123}$\\ \\ $r_{\\frac{1}{2}}^2$\\ \\ $r^2_{\\frac{1}{2}}$\\ \\ $r^{\\frac{1}{2}}_2$\\ \\ $r_2^{\\frac{1}{2}}$\\ \\ $\\left(\\stackrel{a}{b}\\right)_2^{\\frac{1}{2}}$\\ \\ $\\left(\\stackrel{a}{b}\\right)^{\\frac{1}{2}}_2$");
ui->cmbTestset->addItem("frac test", "$\\frac{a}{b}+\\frac{g}{a}-\\frac{a^2}{b^2}\\cdot\\frac{a^2}{b^{\\frac{1}{2}}}$");
ui->cmbTestset->addItem("tfrac test", "$\\tfrac{a}{b}+\\tfrac{g}{a}-\\tfrac{a^2}{b^2}\\cdot\\tfrac{a^2}{b^{\\tfrac{1}{2}}}$");
ui->cmbTestset->addItem("dfrac test", "$\\dfrac{a}{b}+\\dfrac{g}{a}-\\dfrac{a^2}{b^2}\\cdot\\dfrac{a^2}{b^{\\dfrac{1}{2}}}$");
ui->cmbTestset->addItem("sfrac test", "$\\sfrac{a}{b}+\\sfrac{g}{a}-\\sfrac{a^2}{b^2}\\cdot\\sfrac{a^2}{b^{\\sfrac{1}{2}}}$");
ui->cmbTestset->addItem("stfrac test", "$\\stfrac{a}{b}+\\stfrac{g}{a}-\\stfrac{a^2}{b^2}\\cdot\\stfrac{a^2}{b^{\\stfrac{1}{2}}}$");
ui->cmbTestset->addItem("number fractions test", "frac: \\frac{1}{2}, \\frac{3}{4},\\ \\ \\ tfrac: \\tfrac{1}{2}, \\tfrac{3}{4},\\ \\ \\ sfrac: \\sfrac{1}{2}, \\sfrac{3}{4},\\ \\ \\ stfrac: \\stfrac{1}{2}, \\stfrac{3}{4},\\ \\ \\ ");
ui->cmbTestset->addItem("stackrel test", "$\\stackrel{a}{b}+\\stackrel{g}{a}-\\stackrel{a^2}{b^2}\\cdot\\stackrel{a^2}{b^{\\stackrel{1}{2}}}$");
ui->cmbTestset->addItem("brace0 test", "\\langle\\langle -- $\\langle\\langle$");
ui->cmbTestset->addItem("brace1 test", "\\langle\\langle r^{123} -- $\\langle\\langle r^{123}$");
ui->cmbTestset->addItem("brace2 test", "\\langle\\langle r^{123}\\rangle\\rangle -- $\\langle\\langle r^{123}\\rangle\\rangle$");
ui->cmbTestset->addItem("brace3 test", "\\left\\langle r^{123}\\right\\rangle -- $\\left\\langle r^{123}\\right\\rangle$");
ui->cmbTestset->addItem("brace4 test", "\\left\\langle\\left\\langle\\left\\langle r^{123}\\right\\rangle\\right\\rangle\\right\\rangle -- $\\left\\langle\\left\\langle\\left\\langle r^{123}\\right\\rangle\\right\\rangle\\right\\rangle$");
ui->cmbTestset->addItem("brace5 test: ( )", "\\left(\\left(\\left( r^{123}\\right)\\right)\\right) -- $\\left(\\left(\\left( r^{123}\\right)\\right)\\right)$");
ui->cmbTestset->addItem("brace6 test: [ ]", "\\left[\\left[\\left[ r^{123}\\right]\\right]\\right] -- $\\left[\\left[\\left[ r^{123}\\right]\\right]\\right]$");
ui->cmbTestset->addItem("brace7 test: { }", "\\left\\{\\left\\{\\left\\{ r^{123}\\right\\}\\right\\}\\right\\} -- $\\left\\{\\left\\{\\left\\{ r^{123}\\right\\}\\right\\}\\right\\}$");
ui->cmbTestset->addItem("brace8 test: || ||", "\\left\\|\\left\\|\\left\\| r^{123}\\right\\|\\right\\|\\right\\| -- $\\left\\|\\left\\|\\left\\| r^{123}\\right\\|\\right\\|\\right\\|$");
ui->cmbTestset->addItem("brace9 test: | |", "\\left|\\left|\\left| r^{123}\\right|\\right|\\right| -- $\\left|\\left|\\left| r^{123}\\right|\\right|\\right|$");
ui->cmbTestset->addItem("brace10 test", "\\left\\{\\left[\\left( r^{123}\\right)\\right]\\right\\} -- $\\left\\{\\left[\\left( r^{123}\\right)\\right]\\right\\}$");
ui->cmbTestset->addItem("brace11 test: floor", "\\left\\lfloor\\left\\lfloor\\left\\lfloor r^{123}\\right\\rfloor\\right\\rfloor\\right\\rfloor -- $\\left\\lfloor\\left\\lfloor\\left\\lfloor r^{123}\\right\\rfloor\\right\\rfloor\\right\\rfloor$");
ui->cmbTestset->addItem("brace12 test: ceil", "\\left\\lceil\\left\\lceil\\left\\lceil r^{123}\\right\\rceil\\right\\rceil\\right\\rceil -- $\\left\\lceil\\left\\lceil\\left\\lceil r^{123}\\right\\rceil\\right\\rceil\\right\\rceil$");
ui->cmbTestset->addItem("brace13 test: non-left/right ( )", "(((r^{123}))) -- $(((r^{123})))$");
ui->cmbTestset->addItem("brace14 test: non-left/right [ ]", "[[[r^{123}]]] -- $[[[r^{123}]]]$");
ui->cmbTestset->addItem("brace15 test: non-left/right { }", "\\{\\{\\{r^{123}\\}\\}\\} -- $\\{\\{\\{ r^{123}\\}\\}\\}$");
ui->cmbTestset->addItem("brace16 test: non-left/right | |", "|||r^{123}||| -- $|||r^{123}|||$");
ui->cmbTestset->addItem("brace17 test: non-left/right { | }", "\\{r^{123}|r\\equiv 5\\} -- $\\{r^{123}|r\\equiv 5\\}$");
ui->cmbTestset->addItem("sub-, superscript test", "r^{1234}_{321} r_{321}^{1234} -- $r^{1234}_{321} r_{321}^{1234} -- \\kappa^2 -- \\kappa_2 -- \\kappa_2^2$");
ui->cmbTestset->addItem("super-, subscript test", "r^{123}_{4321} r_{4321}^{123} -- $r^{123}_{4321} r_{4321}^{123} -- \\kappa^2 -- \\kappa_2 -- \\kappa_2^2$");
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}}$");
ui->cmbTestset->addItem("math: MSD test", "$\\mathrm{MSD}(\\tau)\\equiv\\langle r^2(\\tau)\\rangle=\\left\\langle (\\vec{r}(t)-\\vec{r}(t+\\tau) )^2\\right\\rangle=2n\\cdot\\frac{K_\\alpha}{\\Gamma(1+\\alpha)}\\cdot\\tau^\\alpha$");
ui->cmbTestset->addItem("math: f() test", "$f(\\vec{x})=\\frac{1}{\\sqrt{2\\pi\\cdot\\sigma^2}}\\exp\\left(-\\frac{(\\vec{x}-\\vec{x}_0)^2}{\\sigma^2}\\right)$");
ui->cmbTestset->addItem("math: chi^2 test", "$\\vec{p}^\\ast=\\argmax\\limits_{\\vec{p}}\\chi^2=\\argmax\\limits_{\\vec{p}}\\sum\\limits_{i=1}^N\\left|\\frac{\\hat{f}_i-f(x_i;\\vec{p})}{\\sigma_i}\\right|^2$");
ui->cmbTestset->addItem("text: symbol test", "\\vdots\\cdots\\ddots\\iddots\\lfloor\\rfloor\\lceil\\rceil\\langle\\rangle\\sum\\int \\iint \\oint \\prod \\leftrightarrow \\leftarrow\\Leftarrow\\rightarrow\\Rightarrow\\pm\\mp\\leq\\geq\\ll\\gg\\hbar\\euro\\bbC\\bbH\\bbN\\bbP\\bbQ\\bbZ\\bbR\\Angstrom\\Alef\\Bet\\Gimel\\Dalet\\nexists\\ni\\notni\\circ\\tilde\\oiint\\oiiint\\emptyset\\odot\\ominus\\subsetnot\\DC\\bot\\cdots\\perthousand\\leftharpoonup\\rightharpoonup \\upharpoonleft \\downharpoonleft \\leftrightharpoon \\rightleftharpoon \\coprod \\leftharpoondown \\rightharpoondown \\nwarrow \\nearrow \\mapsto \\cent \\pound \\yen \\div \\multimap \\maporiginal \\mapimage \\bigcap \\bigcup \\benzene \\times \\cdot \\propto \\equiv \\Im \\Re \\ ");
ui->cmbTestset->addItem("math: arrowtest 1", "$\\leftarrow \\longleftarrow \\Leftarrow \\Longleftarrow \\rightarrow \\longrightarrow \\Rightarrow \\Longrightarrow \\uparrow \\Uparrow \\downarrow \\Downarrow \\leftrightarrow \\Leftrightarrow \\longleftrightarrow \\Longleftrightarrow$");
ui->cmbTestset->addItem("math: arrowtest 2", "$\\nwarrow \\nearrow \\searrow \\swarrow \\mapsto \\leftharpoonup \\rightharpoonup \\upharpoonleft \\downharpoonleft \\leftrightharpoon \\rightleftharpoon \\leftharpoondown \\rightharpoondown \\upharpoonright \\downharpoonright $");
ui->cmbTestset->addItem("math-font: greek letters", "$\\alpha\\beta\\gamma\\delta\\epsilon\\varepsilon\\zeta\\eta\\theta\\vartheta\\iota\\kappa\\lambda\\mu\\nu\\xi\\pi\\varpi\\rho\\varrho\\sigma\\varsigma\\tau\\upsilon\\phi\\varphi\\chi\\psi\\omega\\Omega\\Gamma\\Delta\\Theta\\Lambda\\Xi\\Pi\\Sigma\\Upsilon\\Phi\\Psi$");
ui->cmbTestset->addItem("text-font: greek letters", "\\alpha\\beta\\gamma\\delta\\epsilon\\varepsilon\\zeta\\eta\\theta\\vartheta\\iota\\kappa\\lambda\\mu\\nu\\xi\\pi\\varpi\\rho\\varrho\\sigma\\varsigma\\tau\\upsilon\\phi\\varphi\\chi\\psi\\omega\\Omega\\Gamma\\Delta\\Theta\\Lambda\\Xi\\Pi\\Sigma\\Upsilon\\Phi\\Psi");
ui->cmbTestset->addItem("math-font: blackboard", "$\\mathbb{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math-font: bf", "$\\mathbf{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math-font: it", "$\\mathit{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math-font: frak", "$\\mathfrak{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math-font: sf", "$\\mathsf{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math-font: rm", "$\\mathrm{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math-font: cal", "$\\mathcal{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math-font: script", "$\\mathscr{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("math-font: tt", "$\\mathtt{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}$");
ui->cmbTestset->addItem("text: bf", "\\textbf{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("text: it", "\\textit{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("text: frak", "\\textfrak{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("text: sf", "\\textsf{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("text: rm", "\\textrm{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("text: cal", "\\textcal{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("text: script", "\\textscr{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("text: tt", "\\texttt{ABCDEFGHIJKLMNOPQRSTUVWXYZ120}");
ui->cmbTestset->addItem("math: subscript test", "$r_{123}\\ \\ r_{\\frac{1}{2}}$");
ui->cmbTestset->addItem("math: subscript0 test", "$r_{123}$");
ui->cmbTestset->addItem("math: subscript1 test", "$r_{123}\\ $");
ui->cmbTestset->addItem("math: subscript2 test", "$r_{123}\\ \\ $");
ui->cmbTestset->addItem("math: subscript3 test", "$r_{123}r_{\\frac{1}{2}}$");
ui->cmbTestset->addItem("math: superscript test", "$r^{123}\\ \\ r^{\\frac{1}{2}}$");
ui->cmbTestset->addItem("math: superscript0 test", "$r^{123}$");
ui->cmbTestset->addItem("math: superscript1 test", "$r^{123}\\ $");
ui->cmbTestset->addItem("math: superscript2 test", "$r^{123}\\ \\ $");
ui->cmbTestset->addItem("math: superscript3 test", "$r^{123}r^{\\frac{1}{2}}$");
ui->cmbTestset->addItem("math: asuperscript test", "$a^{123}\\ \\ a^{\\frac{1}{2}}$");
ui->cmbTestset->addItem("math: asuperscript0 test", "$a^{123}$");
ui->cmbTestset->addItem("math: gsuperscript1 test", "$g^{123}\\ $");
ui->cmbTestset->addItem("math: gsuperscript2 test", "$g^{123}\\ \\ $");
ui->cmbTestset->addItem("math: gsuperscript3 test", "$g^{123}g^{\\frac{1}{2}}$");
ui->cmbTestset->addItem("math: subsuperscript test", "$r_{123}^2$\\ \\ $r^2_{123}$\\ \\ $\\left(\\stackrel{a}{b}\\right)_{123}^2$\\ \\ $\\left(\\stackrel{a}{b}\\right)^2_{123}$\\ \\ $r_{\\frac{1}{2}}^2$\\ \\ $r^2_{\\frac{1}{2}}$\\ \\ $r^{\\frac{1}{2}}_2$\\ \\ $r_2^{\\frac{1}{2}}$\\ \\ $\\left(\\stackrel{a}{b}\\right)_2^{\\frac{1}{2}}$\\ \\ $\\left(\\stackrel{a}{b}\\right)^{\\frac{1}{2}}_2$");
ui->cmbTestset->addItem("math: radicals", "$\\sqrt{a}\\sqrt{5}\\sqrt{-1}\\sqrt{h}\\sqrt{jA}\\sqrt{\\vec{A}}\\sqrt{\\frac{1}{a}}\\frac{\\sqrt{a}}{\\sqrt{a}}\\sqrt{\\frac{1}{1+\\frac{1}{a}}}\\frac{1}{\\sqrt{1+\\frac{1}{a}}}\\sqrt{a+\\sqrt{a+b}}$");
ui->cmbTestset->addItem("text: radicals", "\\sqrt{a}\\sqrt{5}\\sqrt{-1}\\sqrt{h}\\sqrt{jA}\\sqrt{\\vec{A}}\\sqrt{\\frac{1}{a}}\\frac{\\sqrt{a}}{\\sqrt{a}}\\sqrt{\\frac{1}{1+\\frac{1}{a}}}\\frac{1}{\\sqrt{1+\\frac{1}{a}}}\\sqrt{a+\\sqrt{a+b}}");
ui->cmbTestset->addItem("math: non-2 radicals", "$\\sqrt[3]{a}\\sqrt[3]{5}\\sqrt[3]{-1}\\sqrt[3]{h}\\sqrt[3]{\\vec{A}}\\sqrt[3]{\\frac{1}{a}}\\frac{\\sqrt[3]{a}}{\\sqrt[3]{a}}\\sqrt[3]{\\frac{1}{1+\\frac{1}{a}}}\\frac{1}{\\sqrt[3]{1+\\frac{1}{a}}}\\sqrt[3]{a+\\sqrt[3]{a+b}}$");
ui->cmbTestset->addItem("text: non-2 radicals", "\\sqrt[3]{a}\\sqrt[3]{5}\\sqrt[3]{-1}\\sqrt[3]{h}\\sqrt[3]{\\vec{A}}\\sqrt[3]{\\frac{1}{a}}\\frac{\\sqrt[3]{a}}{\\sqrt[3]{a}}\\sqrt[3]{\\frac{1}{1+\\frac{1}{a}}}\\frac{1}{\\sqrt[3]{1+\\frac{1}{a}}}\\sqrt[3]{a+\\sqrt[3]{a+b}}");
ui->cmbTestset->addItem("math: long non-2 radicals", "$\\sqrt[3.14156]{a}\\sqrt[3.14156]{5}$");
ui->cmbTestset->addItem("text: long non-2 radicals", "\\sqrt[3.14156]{a}\\sqrt[3.14156]{5}");
ui->cmbTestset->addItem("math: sum, prod, ...", "no-limits: $\\prod_{i=1}^n \\sum_{j=1}^c (i + j)\\cdot\\frac{1}{2}$\\ \\ \\ --\\ \\ \\ limits: $\\prod\\limits_{i=1}^n \\sum\\limits_{j=1}^c (i + j)\\cdot\\frac{1}{2}$\\ \\ \\ --\\ \\ \\ long-below: $\\sum_{n=\\{a,b,c,d,e,f,g\\}} f(x)$\\ \\ \\ --\\ \\ \\ long-above: $\\sum^{n=\\{a,b,c,d,e,f,g\\}} f(x)$");
ui->cmbTestset->addItem("text: sum, prod, ...", "no-limits: \\prod_{i=1}^n \\sum_{j=1}^c (i + j)\\cdot\\frac{1}{2}\\ \\ \\ --\\ \\ \\ limits: \\prod\\limits_{i=1}^n \\sum\\limits_{j=1}^c (i + j)\\cdot\\frac{1}{2}\\ \\ \\ --\\ \\ \\ long-below: \\sum_{n=\\{a,b,c,d,e,f,g\\}} f(x)\\ \\ \\ --\\ \\ \\ long-above: \\sum^{n=\\{a,b,c,d,e,f,g\\}} f(x)");
ui->cmbTestset->addItem("math: more sum-symbols ", "$\\sum_{i=0}^N\\prod_{i=0}^N\\coprod_{i=0}^N\\bigcup_{i=0}^N\\bigcap_{i=0}^N\\bigsqcup_{i=0}^N\\bigvee_{i=0}^N\\bigwedge_{i=0}^N\\bigoplus_{i=0}^N\\bigotimes_{i=0}^N\\bigodot_{i=0}^N\\biguplus_{i=0}^N$");
ui->cmbTestset->addItem("math: integrals", "no-limits: $\\int_{0}^1 f(x)\\;\\mathrm{d}x\\ \\iint_{0}^1 f(x)\\;\\mathrm{d}x\\ \\iiint_{0}^1 f(x)\\;\\mathrm{d}x\\ \\oint_{0}^1 f(x)\\;\\mathrm{d}x\\ \\int_{x} f(x)\\;\\mathrm{d}x$\\ \\ \\ --\\ \\ \\ limits: $\\int\\limits_{0}^1 f(x)\\;\\mathrm{d}x\\ \\iint\\limits_{0}^1 f(x)\\;\\mathrm{d}x\\ \\iiint\\limits_{0}^1 f(x)\\;\\mathrm{d}x\\ \\oint\\limits_{0}^1 f(x)\\;\\mathrm{d}x\\ \\int\\limits_{x} f(x)\\;\\mathrm{d}x$");
ui->cmbTestset->addItem("text: integrals", "no-limits: \\int_{0}^1 f(x)\\;\\mathrm{d}x\\ \\iint_{0}^1 f(x)\\;\\mathrm{d}x\\ \\iiint_{0}^1 f(x)\\;\\mathrm{d}x\\ \\oint_{0}^1 f(x)\\;\\mathrm{d}x\\ \\int_{x} f(x)\\;\\mathrm{d}x$\\ \\ \\ --\\ \\ \\ limits: $\\int\\limits_{0}^1 f(x)\\;\\mathrm{d}x\\ \\iint\\limits_{0}^1 f(x)\\;\\mathrm{d}x\\ \\iiint\\limits_{0}^1 f(x)\\;\\mathrm{d}x\\ \\oint\\limits_{0}^1 f(x)\\;\\mathrm{d}x\\ \\int\\limits_{x} f(x)\\;\\mathrm{d}x");
ui->cmbTestset->addItem("math: frac test", "$\\frac{a}{b}+\\frac{g}{a}-\\frac{a^2}{b^2}\\cdot\\frac{a^2}{b^{\\frac{1}{2}}}$");
ui->cmbTestset->addItem("math/text: stacked frac", "math: $\\frac{1+\\frac{a}{b}}{1+\\frac{1}{1+\\frac{1}{a}}}$\\ \\ text: \\frac{1+\\frac{a}{b}}{1+\\frac{1}{1+\\frac{1}{a}}}\\ \\ \\ \\ \\ --\\ \\ \\ \\ \\ math: $a_0+\\cfrac{1}{a_1+\\cfrac{1}{a_2+\\cfrac{1}{a_3+\\cdots}}}$\\ \\ text: a_0+\\cfrac{1}{a_1+\\cfrac{1}{a_2+\\cfrac{1}{a_3+\\cdots}}}");
ui->cmbTestset->addItem("math: tfrac test", "$\\tfrac{a}{b}+\\tfrac{g}{a}-\\tfrac{a^2}{b^2}\\cdot\\tfrac{a^2}{b^{\\tfrac{1}{2}}}$");
ui->cmbTestset->addItem("math: dfrac test", "$\\dfrac{a}{b}+\\dfrac{g}{a}-\\dfrac{a^2}{b^2}\\cdot\\dfrac{a^2}{b^{\\dfrac{1}{2}}}$");
ui->cmbTestset->addItem("math: sfrac test", "$\\sfrac{a}{b}+\\sfrac{g}{a}-\\sfrac{a^2}{b^2}\\cdot\\sfrac{a^2}{b^{\\sfrac{1}{2}}}$");
ui->cmbTestset->addItem("math: stfrac test", "$\\stfrac{a}{b}+\\stfrac{g}{a}-\\stfrac{a^2}{b^2}\\cdot\\stfrac{a^2}{b^{\\stfrac{1}{2}}}$");
ui->cmbTestset->addItem("text: number fractions test", "frac: \\frac{1}{2}, \\frac{3}{4},\\ \\ \\ tfrac: \\tfrac{1}{2}, \\tfrac{3}{4},\\ \\ \\ sfrac: \\sfrac{1}{2}, \\sfrac{3}{4},\\ \\ \\ stfrac: \\stfrac{1}{2}, \\stfrac{3}{4},\\ \\ \\ ");
ui->cmbTestset->addItem("math: stackrel test", "$\\stackrel{a}{b}+\\stackrel{g}{a}-\\stackrel{a^2}{b^2}\\cdot\\stackrel{a^2}{b^{\\stackrel{1}{2}}}$");
ui->cmbTestset->addItem("text/math: brace0 test", "text: \\langle\\langle -- math: $\\langle\\langle$");
ui->cmbTestset->addItem("text/math: brace1 test", "text: \\langle\\langle r^{123} -- math: $\\langle\\langle r^{123}$");
ui->cmbTestset->addItem("text/math: brace2 test", "text: \\langle\\langle r^{123}\\rangle\\rangle -- math: $\\langle\\langle r^{123}\\rangle\\rangle$");
ui->cmbTestset->addItem("text/math: brace3 test", "text: \\left\\langle r^{123}\\right\\rangle -- math: $\\left\\langle r^{123}\\right\\rangle$");
ui->cmbTestset->addItem("text/math: brace4 test", "text: \\left\\langle\\left\\langle\\left\\langle r^{123}\\right\\rangle\\right\\rangle\\right\\rangle -- math: $\\left\\langle\\left\\langle\\left\\langle r^{123}\\right\\rangle\\right\\rangle\\right\\rangle$");
ui->cmbTestset->addItem("text/math: brace5 test: ( )", "text: \\left(\\left(\\left( r^{123}\\right)\\right)\\right) -- math: $\\left(\\left(\\left( r^{123}\\right)\\right)\\right)$");
ui->cmbTestset->addItem("text/math: brace6 test: [ ]", "text: \\left[\\left[\\left[ r^{123}\\right]\\right]\\right] -- math: $\\left[\\left[\\left[ r^{123}\\right]\\right]\\right]$");
ui->cmbTestset->addItem("text/math: brace7 test: { }", "text: \\left\\{\\left\\{\\left\\{ r^{123}\\right\\}\\right\\}\\right\\} -- math: $\\left\\{\\left\\{\\left\\{ r^{123}\\right\\}\\right\\}\\right\\}$");
ui->cmbTestset->addItem("text/math: brace8 test: || ||", "text: \\left\\|\\left\\|\\left\\| r^{123}\\right\\|\\right\\|\\right\\| -- math: $\\left\\|\\left\\|\\left\\| r^{123}\\right\\|\\right\\|\\right\\|$");
ui->cmbTestset->addItem("text/math: brace9 test: | |", "text: \\left|\\left|\\left| r^{123}\\right|\\right|\\right| -- math: $\\left|\\left|\\left| r^{123}\\right|\\right|\\right|$");
ui->cmbTestset->addItem("text/math: brace10 test", "text: \\left\\{\\left[\\left( r^{123}\\right)\\right]\\right\\} -- math: $\\left\\{\\left[\\left( r^{123}\\right)\\right]\\right\\}$");
ui->cmbTestset->addItem("text/math: brace11 test: floor", "text: \\left\\lfloor\\left\\lfloor\\left\\lfloor r^{123}\\right\\rfloor\\right\\rfloor\\right\\rfloor -- math: $\\left\\lfloor\\left\\lfloor\\left\\lfloor r^{123}\\right\\rfloor\\right\\rfloor\\right\\rfloor$");
ui->cmbTestset->addItem("text/math: brace12 test: ceil", "text: \\left\\lceil\\left\\lceil\\left\\lceil r^{123}\\right\\rceil\\right\\rceil\\right\\rceil -- math: $\\left\\lceil\\left\\lceil\\left\\lceil r^{123}\\right\\rceil\\right\\rceil\\right\\rceil$");
ui->cmbTestset->addItem("text/math: brace13 test: non-left/right ( )", "text: (((r^{123}))) -- math: $(((r^{123})))$");
ui->cmbTestset->addItem("text/math: brace14 test: non-left/right [ ]", "text: [[[r^{123}]]] -- math: $[[[r^{123}]]]$");
ui->cmbTestset->addItem("text/math: brace15 test: non-left/right { }", "text: \\{\\{\\{r^{123}\\}\\}\\} -- math: $\\{\\{\\{ r^{123}\\}\\}\\}$");
ui->cmbTestset->addItem("text/math: brace16 test: non-left/right | |", "text: |||r^{123}||| -- math: $|||r^{123}|||$");
ui->cmbTestset->addItem("text/math: brace17 test: non-left/right { | }", "text: \\{r^{123}|r\\equiv 5\\} -- math: $\\{r^{123}|r\\equiv 5\\}$");
ui->cmbTestset->addItem("text/math: sub-, superscript test", "text: r^{1234}_{321} r_{321}^{1234} -- math: $r^{1234}_{321} r_{321}^{1234} -- \\kappa^2 -- \\kappa_2 -- \\kappa_2^2$");
ui->cmbTestset->addItem("text/math: super-, subscript test", "text: r^{123}_{4321} r_{4321}^{123} -- math: $r^{123}_{4321} r_{4321}^{123} -- \\kappa^2 -- \\kappa_2 -- \\kappa_2^2$");
//ui->cmbTestset->addItem("", "");
ui->cmbTestset->addItem("math 1", "$f(x)=\\int_{-\\infty}^xe^{-t^2}\\;\\mathrm{d}t$");
ui->cmbTestset->addItem("math 2", "$\\sum_{i=1}^\\infty\\frac{-e^{i\\pi}}{2^n}$");
@ -124,35 +146,35 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbTestset->addItem("math 18", "${}_pF_q(a_1,\\dots,a_p;c_1,\\dots,c_q;z)= \\sum_{n=0}^\\infty\\frac{(a_1)_n\\cdots(a_p)_n}{(c_1)_n\\cdots(c_q)_n}\\frac{z^n}{n!}$");
ui->cmbTestset->addItem("math 19 (overset)", "$X \\overset{=}{def} Y$\\ \\ \\ \\ \\ $X \\overset{=}{!} Y$\\ \\ \\ \\ \\ $X \\overset{\\rightarrow}{f} Y$\\ \\ \\ \\ \\ $\\frac{f(x+\\Delta x)-f(x)}{\\Delta x}\\overset{\\longrightarrow}{\\Delta x\\to 0}f'(x)$");
ui->cmbTestset->addItem("math 20 (underset)", "$X \\underset{=}{\\text{def (5)}} Y$\\ \\ \\ \\ \\ $X \\underset{\\rightarrow}{f} Y$\\ \\ \\ \\ \\ $\\frac{f(x+\\Delta x)-f(x)}{\\Delta x}\\underset{\\longrightarrow}{\\Delta x\\to 0}f'(x)$");
ui->cmbTestset->addItem("Jacobi Matrix and VarCov matrix", "$J_{ij}= \\left.\\frac{\\partial f(x,\\vec{p})}{\\partial p_i}\\right|_{\\vec{p},x=x_j}\\ \\ \\ \\ \\ \\mat{C}=\\left(\\mat{J}^\\mathrm{T}\\ J\\right)^{-1}\\ \\ \\ \\ \\ test: \\left|\\frac{\\partial f(x,\\vec{p})}{\\partial p_i}\\right|_{\\vec{p},x=x_j}^2$");
ui->cmbTestset->addItem("operator test (textmode)", "x=0\\ \\ y>0\\ \\ x+y\\ \\ -1\\ \\ x-2\\ \\ x\\cdot y\\ \\ x\\geq 4\\ \\ x~4");
ui->cmbTestset->addItem("operator test (mathmode)", "$x=0\\ \\ y>0\\ \\ x+y\\ \\ -1\\ \\ x-2\\ \\ x\\cdot y\\ \\ x\\geq 4\\ \\ x~4$");
ui->cmbTestset->addItem("color test", "\\textcolor{red}{RED}\\textcolor{blue}{BLUE}");
ui->cmbTestset->addItem("boxed test", "test: \\boxed{boxed text} in the middle");
ui->cmbTestset->addItem("mathboxed test", "\\fbox{2^{2^{\\colorbox{red}{2^{x}}}}}");
ui->cmbTestset->addItem("math: Jacobi Matrix and VarCov matrix", "$J_{ij}= \\left.\\frac{\\partial f(x,\\vec{p})}{\\partial p_i}\\right|_{\\vec{p},x=x_j}\\ \\ \\ \\ \\ \\mat{C}=\\left(\\mat{J}^\\mathrm{T}\\ J\\right)^{-1}\\ \\ \\ \\ \\ test: \\left|\\frac{\\partial f(x,\\vec{p})}{\\partial p_i}\\right|_{\\vec{p},x=x_j}^2$");
ui->cmbTestset->addItem("math: operator test (textmode)", "x=0\\ \\ y>0\\ \\ x+y\\ \\ -1\\ \\ x-2\\ \\ x\\cdot y\\ \\ x\\geq 4\\ \\ x~4");
ui->cmbTestset->addItem("math: operator test (mathmode)", "$x=0\\ \\ y>0\\ \\ x+y\\ \\ -1\\ \\ x-2\\ \\ x\\cdot y\\ \\ x\\geq 4\\ \\ x~4$");
ui->cmbTestset->addItem("text: color test", "\\textcolor{red}{RED}\\textcolor{blue}{BLUE}");
ui->cmbTestset->addItem("text: boxed test", "test: \\boxed{boxed text} in the middle");
ui->cmbTestset->addItem("mathboxed test", "$\\fbox{2^{2^{\\colorbox{red}{2^{x}}}}}$");
ui->cmbTestset->addItem("axiom of power test", "$\\forall A \\, \\exists P \\, \\forall B \\, [B \\in P \\iff \\forall C \\, (C \\in B \\Rightarrow C \\in A)]$");
ui->cmbTestset->addItem("De Morgan's law", "$\\neg(P\\land Q)\\iff(\\neg P)\\lor(\\neg Q)$ or $\\overline{\\bigcap_{i \\in I} A_{i}}\\equiv\\bigcup_{i \\in I} \\overline{A_{i}}$ or $\\overline{A \\cup B}\\equiv\\overline{A} \\cap \\overline{B}$");
ui->cmbTestset->addItem("quadratic formula", "$x=\\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}$");
ui->cmbTestset->addItem("combination", "$\\binom{n}{k} = \\frac{n(n-1)...(n-k+1)}{k(k-1)\\dots1}=\\frac{n!}{k!(n-k)!}$");
ui->cmbTestset->addItem("Sophomore's dream 1", "$\\int_0^1 x^{-x}\\,dx = \\sum_{n=1}^\\infty n^{-n}(\\scriptstyle{= 1.29128599706266354040728259059560054149861936827\\dots)}$");
ui->cmbTestset->addItem("Sophomore's dream 2", "$\\int_0^1 x^x \\,dx = \\sum_{n=1}^\\infty (-1)^{n+1}n^{-n} = - \\sum_{n=1}^\\infty (-n)^{-n} (\\scriptstyle{= 0.78343051071213440705926438652697546940768199014\\dots})$");
ui->cmbTestset->addItem("divergence 1", "$\\operatorname{div}\\vec{F} = \\nabla\\cdot\\vec{F}=\\frac{\\partial U}{\\partial x}+\\frac{\\partial V}{\\partial y}+\\frac{\\partial W}{\\partial z}$");
ui->cmbTestset->addItem("divergence 2", "$\\overrightarrow{\\operatorname{div}}\\,(\\mathbf{\\underline{\\underline{\\epsilon}}}) = "
ui->cmbTestset->addItem("math: De Morgan's law", "$\\neg(P\\land Q)\\iff(\\neg P)\\lor(\\neg Q)$ or $\\overline{\\bigcap_{i \\in I} A_{i}}\\equiv\\bigcup_{i \\in I} \\overline{A_{i}}$ or $\\overline{A \\cup B}\\equiv\\overline{A} \\cap \\overline{B}$");
ui->cmbTestset->addItem("math: quadratic formula", "$x=\\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}$");
ui->cmbTestset->addItem("math: combination", "$\\binom{n}{k} = \\frac{n(n-1)...(n-k+1)}{k(k-1)\\dots1}=\\frac{n!}{k!(n-k)!}$");
ui->cmbTestset->addItem("math: Sophomore's dream 1", "$\\int_0^1 x^{-x}\\,dx = \\sum_{n=1}^\\infty n^{-n}(\\scriptstyle{= 1.29128599706266354040728259059560054149861936827\\dots)}$");
ui->cmbTestset->addItem("math: Sophomore's dream 2", "$\\int_0^1 x^x \\,dx = \\sum_{n=1}^\\infty (-1)^{n+1}n^{-n} = - \\sum_{n=1}^\\infty (-n)^{-n} (\\scriptstyle{= 0.78343051071213440705926438652697546940768199014\\dots})$");
ui->cmbTestset->addItem("math: divergence 1", "$\\operatorname{div}\\vec{F} = \\nabla\\cdot\\vec{F}=\\frac{\\partial U}{\\partial x}+\\frac{\\partial V}{\\partial y}+\\frac{\\partial W}{\\partial z}$");
ui->cmbTestset->addItem("math: divergence 2", "$\\overrightarrow{\\operatorname{div}}\\,(\\mathbf{\\underline{\\underline{\\epsilon}}}) = "
"\\begin{bmatrix}"
"\\frac{\\partial \\epsilon_{xx}}{\\partial x} +\\frac{\\partial \\epsilon_{yx}}{\\partial y} +\\frac{\\partial \\epsilon_{zx}}{\\partial z} \\\\"
"\\frac{\\partial \\epsilon_{xy}}{\\partial x} +\\frac{\\partial \\epsilon_{yy}}{\\partial y} +\\frac{\\partial \\epsilon_{zy}}{\\partial z} \\\\"
"\\frac{\\partial \\epsilon_{xz}}{\\partial x} +\\frac{\\partial \\epsilon_{yz}}{\\partial y} +\\frac{\\partial \\epsilon_{zz}}{\\partial z}"
"\\end{bmatrix}$");
ui->cmbTestset->addItem("lim, sum ...", "$\\lim_{x\\to\\infty} f(x) = \\binom{k}{r} + \\frac{a}{b} \\sum_{n=1}^\\infty a_n + \\displaystyle{ \\left\\{ \\frac{1}{13} \\sum_{n=1}^\\infty b_n \\right\\} }.$");
ui->cmbTestset->addItem("array test", "$f(x) := \\left\\{\\begin{array} x^2 \\sin \\frac{1}{x} & \\textrm{if } x \\ne 0, \\\\ 0 & \\textrm{if } x = 0 . \\end{array}\\right.$");
ui->cmbTestset->addItem("Schwinger-Dyson", "$\\left\\langle\\psi\\left|\\mathcal{T}\\{F \\phi^j\\}\\right|\\psi\\right\\rangle=\\left\\langle\\psi\\left|\\mathcal{T}\\{iF_{,i}D^{ij}-FS_{int,i}D^{ij}\\}\\right|\\psi\\right\\rangle.$");
ui->cmbTestset->addItem(QLatin1String("Schrödinger's equation"), "$\\left[-\\frac{\\hbar^2}{2m}\\frac{\\partial^2}{\\partial x^2}+V\\right]\\Psi(x)=\\mathrm{i}\\hbar\\frac{\\partial}{\\partial t}\\Psi(x)$");
ui->cmbTestset->addItem("Cauchy-Schwarz inequality", "$\\left( \\sum_{k=1}^n a_k b_k \\right)^2 \\leq \\left( \\sum_{k=1}^n a_k^2 \\right) \\left( \\sum_{k=1}^n b_k^2 \\right)$");
ui->cmbTestset->addItem("Maxwell's equations", "$\\begin{aligned}\\nabla \\times \\vec{\\mathbf{B}} -\\, \\frac{1}{c}\\, \\frac{\\partial\\vec{\\mathbf{E}}}{\\partial t} & = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\ \\nabla \\cdot \\vec{\\mathbf{E}} & = 4 \\pi \\rho \\\\\\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \\frac{1}{c}\\, \\frac{\\partial\\vec{\\mathbf{B}}}{\\partial t} & = \\vec{\\mathbf{0}} \\\\\\nabla \\cdot \\vec{\\mathbf{B}} & = 0 \\end{aligned}$");
ui->cmbTestset->addItem("Langevin Equation", "$m \\dot{v}(t) = -\\gamma v(t) + F(x,t)+ f(t)$");
ui->cmbTestset->addItem("Fokker-Planck Equation", "$\\frac{\\partial}{\\partial t}P(y,t)=-\\frac{\\partial}{\\partial y}\\left[ A(y,t)P(y,t)\\right] +\\frac{\\Gamma}{2}\\frac{\\partial^2}{\\partial y^2}\\left[ P(y,t)\\right]$");
ui->cmbTestset->addItem("Hamilton Equations of motion", "$\\mathcal{H}(\\mathbf{q},\\mathbf{p})=\\frac{\\mathbf{p}^2}{2\\,m}+V(\\mathbf{q})\\ \\ \\ \\text{and}\\ \\ \\ \\dot{q}_k =\\frac{p_k}{m}\\ ,\\ \\dot{p}_k = - \\frac{\\partial V}{\\partial q_k}$");
ui->cmbTestset->addItem("Gaussian Distrubution", "$f(x | \\mu,\\sigma^2)=\\frac{1}{\\sqrt{2\\pi\\sigma^2}}\\operatorname{exp}\\left(-\\frac{(x-\\mu)^2}{2\\sigma^2}\\right)=\\frac{1}{\\sqrt{2\\pi\\sigma^2}} e^{-\\frac{(x-\\mu)^2}{2\\sigma^2}}\\quad -\\infty<x<\\infty$");
ui->cmbTestset->addItem("math: lim, sum ...", "$\\lim_{x\\to\\infty} f(x) = \\binom{k}{r} + \\frac{a}{b} \\sum_{n=1}^\\infty a_n + \\displaystyle{ \\left\\{ \\frac{1}{13} \\sum_{n=1}^\\infty b_n \\right\\} }.$");
ui->cmbTestset->addItem("math: array test", "$f(x) := \\left\\{\\begin{array} x^2 \\sin \\frac{1}{x} & \\textrm{if } x \\ne 0, \\\\ 0 & \\textrm{if } x = 0 . \\end{array}\\right.$");
ui->cmbTestset->addItem("math: Schwinger-Dyson", "$\\left\\langle\\psi\\left|\\mathcal{T}\\{F \\phi^j\\}\\right|\\psi\\right\\rangle=\\left\\langle\\psi\\left|\\mathcal{T}\\{iF_{,i}D^{ij}-FS_{int,i}D^{ij}\\}\\right|\\psi\\right\\rangle.$");
ui->cmbTestset->addItem(QLatin1String("math: Schrödinger's equation"), "$\\left[-\\frac{\\hbar^2}{2m}\\frac{\\partial^2}{\\partial x^2}+V\\right]\\Psi(x)=\\mathrm{i}\\hbar\\frac{\\partial}{\\partial t}\\Psi(x)$");
ui->cmbTestset->addItem("math: Cauchy-Schwarz inequality", "$\\left( \\sum_{k=1}^n a_k b_k \\right)^2 \\leq \\left( \\sum_{k=1}^n a_k^2 \\right) \\left( \\sum_{k=1}^n b_k^2 \\right)$");
ui->cmbTestset->addItem("math: Maxwell's equations", "$\\begin{aligned}\\nabla \\times \\vec{\\mathbf{B}} -\\, \\frac{1}{c}\\, \\frac{\\partial\\vec{\\mathbf{E}}}{\\partial t} & = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\ \\nabla \\cdot \\vec{\\mathbf{E}} & = 4 \\pi \\rho \\\\\\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \\frac{1}{c}\\, \\frac{\\partial\\vec{\\mathbf{B}}}{\\partial t} & = \\vec{\\mathbf{0}} \\\\\\nabla \\cdot \\vec{\\mathbf{B}} & = 0 \\end{aligned}$");
ui->cmbTestset->addItem("math: Langevin Equation", "$m \\dot{v}(t) = -\\gamma v(t) + F(x,t)+ f(t)$");
ui->cmbTestset->addItem("math: Fokker-Planck Equation", "$\\frac{\\partial}{\\partial t}P(y,t)=-\\frac{\\partial}{\\partial y}\\left[ A(y,t)P(y,t)\\right] +\\frac{\\Gamma}{2}\\frac{\\partial^2}{\\partial y^2}\\left[ P(y,t)\\right]$");
ui->cmbTestset->addItem("math: Hamilton Equations of motion", "$\\mathcal{H}(\\mathbf{q},\\mathbf{p})=\\frac{\\mathbf{p}^2}{2\\,m}+V(\\mathbf{q})\\ \\ \\ \\text{and}\\ \\ \\ \\dot{q}_k =\\frac{p_k}{m}\\ ,\\ \\dot{p}_k = - \\frac{\\partial V}{\\partial q_k}$");
ui->cmbTestset->addItem("math: Gaussian Distrubution", "$f(x | \\mu,\\sigma^2)=\\frac{1}{\\sqrt{2\\pi\\sigma^2}}\\operatorname{exp}\\left(-\\frac{(x-\\mu)^2}{2\\sigma^2}\\right)=\\frac{1}{\\sqrt{2\\pi\\sigma^2}} e^{-\\frac{(x-\\mu)^2}{2\\sigma^2}}\\quad -\\infty<x<\\infty$");
ui->cmbTestset->addItem("User-Editable Text");
//
//ui->cmbTestset->addItem("", "$$");
@ -178,10 +200,10 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbEncodingFraktur->setCurrentIndex(static_cast<int>(mt.getFontEncodingFraktur()));
ui->cmbUnicodeBlackboard->setCurrentFont(QFont(mt.getFontBlackboard()));
ui->cmbEncodingBlackboard->setCurrentIndex(static_cast<int>(mt.getFontEncodingBlackboard()));
ui->cmbUnicodeSymbol->setCurrentFont(QFont(mt.getSymbolfontSymbol(JKQTMathText::MTenvironmentFont::MTEroman)));
ui->cmbEncodingSymbol->setCurrentIndex(static_cast<int>(mt.getSymbolfontEncodingSymbol(JKQTMathText::MTenvironmentFont::MTEroman)));
ui->cmbUnicodeGreek->setCurrentFont(QFont(mt.getSymbolfontGreek(JKQTMathText::MTenvironmentFont::MTEroman)));
ui->cmbEncodingGreek->setCurrentIndex(static_cast<int>(mt.getSymbolfontEncodingGreek(JKQTMathText::MTenvironmentFont::MTEroman)));
ui->cmbUnicodeSymbol->setCurrentFont(QFont(mt.getSymbolfontSymbol(JKQTMathTextEnvironmentFont::MTEroman)));
ui->cmbEncodingSymbol->setCurrentIndex(static_cast<int>(mt.getSymbolfontEncodingSymbol(JKQTMathTextEnvironmentFont::MTEroman)));
ui->cmbUnicodeGreek->setCurrentFont(QFont(mt.getSymbolfontGreek(JKQTMathTextEnvironmentFont::MTEroman)));
ui->cmbEncodingGreek->setCurrentIndex(static_cast<int>(mt.getSymbolfontEncodingGreek(JKQTMathTextEnvironmentFont::MTEroman)));
ui->chkSimulateBlackboard->setChecked(mt.isFontBlackboardSimulated());
@ -282,34 +304,34 @@ double TestForm::draw(QPainter& painter, double X, double YY, JKQTMathText& mt,
return mt.getDescent(painter)+mt.getAscent(painter)+40;
}
QTreeWidgetItem *TestForm::createTree(JKQTMathText::MTnode *node, QTreeWidgetItem* parent)
QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* parent)
{
QString name;
JKQTMathText::MTtextNode* txtN=dynamic_cast<JKQTMathText::MTtextNode*>(node);
JKQTMathText::MTwhitespaceNode* spN=dynamic_cast<JKQTMathText::MTwhitespaceNode*>(node);
JKQTMathText::MTsymbolNode* symN=dynamic_cast<JKQTMathText::MTsymbolNode*>(node);
JKQTMathText::MTlistNode* lstN=dynamic_cast<JKQTMathText::MTlistNode*>(node);
JKQTMathText::MTinstruction1Node* inst1N=dynamic_cast<JKQTMathText::MTinstruction1Node*>(node);
JKQTMathText::MTsubscriptNode* subN=dynamic_cast<JKQTMathText::MTsubscriptNode*>(node);
JKQTMathText::MTsuperscriptNode* superN=dynamic_cast<JKQTMathText::MTsuperscriptNode*>(node);
JKQTMathText::MTbraceNode* braceN=dynamic_cast<JKQTMathText::MTbraceNode*>(node);
JKQTMathText::MTsqrtNode* sqrtN=dynamic_cast<JKQTMathText::MTsqrtNode*>(node);
JKQTMathText::MTfracNode* fracN=dynamic_cast<JKQTMathText::MTfracNode*>(node);
JKQTMathText::MTmatrixNode* matrixN=dynamic_cast<JKQTMathText::MTmatrixNode*>(node);
JKQTMathText::MTdecoratedNode* decoN=dynamic_cast<JKQTMathText::MTdecoratedNode*>(node);
JKQTMathTextTextNode* txtN=dynamic_cast<JKQTMathTextTextNode*>(node);
JKQTMathTextWhitespaceNode* spN=dynamic_cast<JKQTMathTextWhitespaceNode*>(node);
JKQTMathTextSymbolNode* symN=dynamic_cast<JKQTMathTextSymbolNode*>(node);
JKQTMathTextListNode* lstN=dynamic_cast<JKQTMathTextListNode*>(node);
JKQTMathTextInstruction1Node* inst1N=dynamic_cast<JKQTMathTextInstruction1Node*>(node);
JKQTMathTextSubscriptNode* subN=dynamic_cast<JKQTMathTextSubscriptNode*>(node);
JKQTMathTextSuperscriptNode* superN=dynamic_cast<JKQTMathTextSuperscriptNode*>(node);
JKQTMathTextBraceNode* braceN=dynamic_cast<JKQTMathTextBraceNode*>(node);
JKQTMathTextSqrtNode* sqrtN=dynamic_cast<JKQTMathTextSqrtNode*>(node);
JKQTMathTextFracNode* fracN=dynamic_cast<JKQTMathTextFracNode*>(node);
JKQTMathTextMatrixNode* matrixN=dynamic_cast<JKQTMathTextMatrixNode*>(node);
JKQTMathTextDecoratedNode* decoN=dynamic_cast<JKQTMathTextDecoratedNode*>(node);
QTreeWidgetItem* ti=nullptr;
if (parent) ti=new QTreeWidgetItem(parent);
else ti=new QTreeWidgetItem(ui->tree);
if (decoN) {
name=QString("MTdecoratedNode: mode='%1'").arg(JKQTMathText::decorationToString(decoN->getDecoration()));
name=QString("MTdecoratedNode: mode='%1'").arg(JKQTMathTextDecorationToString(decoN->getDecoration()));
if (decoN->getChild()) ti->addChild(createTree(decoN->getChild(), ti));
} else if (matrixN) {
int l=matrixN->getLines();
int c=matrixN->getColumns();
name=QString("MTmatrixNode: l*c=%1*%2").arg(l).arg(c);
QVector<QVector<JKQTMathText::MTnode*> > children=matrixN->getChildren();
QVector<QVector<JKQTMathTextNode*> > children=matrixN->getChildren();
for (int y=0; y<l; y++) {
for (int x=0; x<c; x++) {
if (children[y].at(x)!=nullptr) {
@ -320,7 +342,7 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathText::MTnode *node, QTreeWidgetIte
}
}
} else if (fracN) {
name=QString("MTfracNode: mode='%1'").arg(JKQTMathText::fracModeToString(fracN->getMode()));
name=QString("MTfracNode: mode='%1'").arg(JKQTMathTextFracModeToString(fracN->getMode()));
if (fracN->getChild1()) ti->addChild(createTree(fracN->getChild1(), ti));
if (fracN->getChild2()) ti->addChild(createTree(fracN->getChild2(), ti));
} else if (sqrtN) {
@ -340,16 +362,16 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathText::MTnode *node, QTreeWidgetIte
if (inst1N->getChild()) ti->addChild(createTree(inst1N->getChild(), ti));
} else if (lstN) {
name=QString("MTlistNode");
QList<JKQTMathText::MTnode*> list=lstN->getNodes();
QList<JKQTMathTextNode*> list=lstN->getNodes();
for (int i=0; i<list.size(); i++) {
ti->addChild(createTree(list[i], ti));
}
} else if (symN) {
name=QString("MTsymbolNode: \'%1\' (addWhite: %2)").arg(symN->getSymbolName()).arg(symN->getAddWhitespace());
name=QString("JKQTMathTextSymbolNode: \'%1\' (addWhite: %2)").arg(symN->getSymbolName()).arg(symN->getAddWhitespace());
} else if (spN) {
name=QString("MTwhitespaceNode :\'%1\'").arg(txtN->getText());
name=QString("JKQTMathTextWhitespaceNode :\'%1\'").arg(txtN->getText());
} else if (txtN) {
name=QString("MTtextNode: \'%1\'").arg(txtN->getText());
name=QString("JKQTMathTextTextNode: \'%1\'").arg(txtN->getText());
} else {
name=QString("unknown");
@ -418,17 +440,17 @@ void TestForm::updateMath()
mt.setFontRoman(ui->cmbUnicodeSerif->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingSerif->currentIndex()));
mt.setFontSans(ui->cmbUnicodeSans->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingSans->currentIndex()));
mt.setFontMathRoman(ui->cmbUnicodeSerifMath->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingSerifMath->currentIndex()));
mt.setFontMathSans(ui->cmbUnicodeSansMath->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingSansMath->currentIndex()));
mt.setFontTypewriter(ui->cmbUnicodeFixed->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingTypewriter->currentIndex()));
mt.setFontCaligraphic(ui->cmbCaligraphic->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingCaligraphic->currentIndex()));
mt.setFontScript(ui->cmbScript->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingScript->currentIndex()));
mt.setFontFraktur(ui->cmbUnicodeFraktur->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingFraktur->currentIndex()));
mt.setFontBlackboard(ui->cmbUnicodeBlackboard->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingBlackboard->currentIndex()));
mt.setSymbolfontSymbol(ui->cmbUnicodeSymbol->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingSymbol->currentIndex()));
mt.setSymbolfontGreek(ui->cmbUnicodeGreek->currentFont().family(), static_cast<JKQTMathText::MTfontEncoding>(ui->cmbEncodingGreek->currentIndex()));
mt.setFontRoman(ui->cmbUnicodeSerif->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSerif->currentIndex()));
mt.setFontSans(ui->cmbUnicodeSans->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSans->currentIndex()));
mt.setFontMathRoman(ui->cmbUnicodeSerifMath->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSerifMath->currentIndex()));
mt.setFontMathSans(ui->cmbUnicodeSansMath->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSansMath->currentIndex()));
mt.setFontTypewriter(ui->cmbUnicodeFixed->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingTypewriter->currentIndex()));
mt.setFontCaligraphic(ui->cmbCaligraphic->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingCaligraphic->currentIndex()));
mt.setFontScript(ui->cmbScript->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingScript->currentIndex()));
mt.setFontFraktur(ui->cmbUnicodeFraktur->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingFraktur->currentIndex()));
mt.setFontBlackboard(ui->cmbUnicodeBlackboard->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingBlackboard->currentIndex()));
mt.setSymbolfontSymbol(ui->cmbUnicodeSymbol->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingSymbol->currentIndex()));
mt.setSymbolfontGreek(ui->cmbUnicodeGreek->currentFont().family(), static_cast<JKQTMathTextFontEncoding>(ui->cmbEncodingGreek->currentIndex()));
mt.setFontBlackboardSimulated(ui->chkSimulateBlackboard->isChecked());
if (ui->cmbFont->currentIndex()==1) qDebug()<<"useXITS: "<<mt.useXITS();

View File

@ -29,7 +29,7 @@ class TestForm : public QWidget
JKQTPHighResTimer ht;
double draw(QPainter& painter, double X, double YY, JKQTMathText& mt, QString name, double &durationSizingMS, double &durationTimingMS);
QTreeWidgetItem* createTree(JKQTMathText::MTnode* node, QTreeWidgetItem *parent=NULL);
QTreeWidgetItem* createTree(JKQTMathTextNode* node, QTreeWidgetItem *parent=NULL);
};
#endif // TESTFORM_H

View File

@ -828,7 +828,7 @@
<customwidget>
<class>JKQTMathTextLabel</class>
<extends>QLabel</extends>
<header>jkqtmathtext/jkqtmathtext.h</header>
<header>jkqtmathtext/jkqtmathtextlabel.h</header>
</customwidget>
</customwidgets>
<resources/>

View File

@ -5,9 +5,35 @@ isEmpty(JKQTP_MATHTEXT_PRI_INCLUDED) {
INCLUDEPATH += $PWD
HEADERS += $$PWD/jkqtmathtext/jkqtmathtext.h
HEADERS += $$PWD/jkqtmathtext/jkqtmathtext.h \
$$PWD/jkqtmathtext/jkqtmathtextlabel.h \
$$PWD/jkqtmathtext/jkqtmathtexttools.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextnode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtexttextnode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextbracenode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextdecoratednode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextfracnode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextinstructionnode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextlistnode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextmatrixnode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextsqrtnode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextsubsupernode.h \
$$PWD/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h
SOURCES += $$PWD/jkqtmathtext/jkqtmathtext.cpp
SOURCES += $$PWD/jkqtmathtext/jkqtmathtext.cpp \
$$PWD/jkqtmathtext/jkqtmathtextlabel.cpp \
$$PWD/jkqtmathtext/jkqtmathtexttools.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextnode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextbracenode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextdecoratednode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextfracnode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextinstructionnode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextlistnode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextmatrixnode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextsqrtnode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextsubsupernode.cpp \
$$PWD/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp
include($$PWD/jkqtmathtext/resources/xits.pri)
DEFINES += AUTOLOAD_XITS_FONTS

View File

@ -22,11 +22,50 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# Set up source files
set(SOURCES
${CMAKE_CURRENT_LIST_DIR}/jkqtmathtext.cpp
${CMAKE_CURRENT_LIST_DIR}/jkqtmathtexttools.cpp
${CMAKE_CURRENT_LIST_DIR}/jkqtmathtextlabel.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextnode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtexttextnode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextbracenode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextdecoratednode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextfracnode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextinstructionnode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextlistnode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextmatrixnode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsqrtnode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsubsupernode.cpp
${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsymbolnode.cpp
)
set(HEADERS
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/jkqtmathtext.h>
$<INSTALL_INTERFACE:jkqtmathtext.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/jkqtmathtexttools.h>
$<INSTALL_INTERFACE:jkqtmathtexttools.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/jkqtmathtextlabel.h>
$<INSTALL_INTERFACE:jkqtmathtextlabel.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextnode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtexttextnode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtexttextnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextbracenode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextbracenode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextdecoratednode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextdecoratednode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextfracnode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextfracnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextinstructionnode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextinstructionnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextlistnode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextlistnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextmatrixnode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextmatrixnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsqrtnode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextsqrtnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsubsupernode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextsubsupernode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsymbolnode.h>
$<INSTALL_INTERFACE:nodes/jkqtmathtextsymbolnode.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/jkqtmathtext_imexport.h>
$<INSTALL_INTERFACE:jkqtmathtext_imexport.h>
)

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2020 Jan W. Krieger (<jan@jkrieger.de>)
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
@ -19,11 +19,6 @@
*/
/*
Name: jkqtmathtext.h
Copyright: (c) 2010-2019
Author: Jan krieger <jan@jkrieger.de>, http://www.jkrieger.de/
*/
@ -37,87 +32,14 @@
#include <QSet>
#include <QFile>
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include <QWidget>
#include <QLabel>
#include <QHash>
/** \brief initialized Qt-ressources necessary for JKQTMathText
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT void initJKQTMathTextResources();
/*! \brief represents a font specifier for JKQTMathText. The font consists of two parts: the actual font and the font used for math output (which may be empty)
\ingroup jkqtmathtext
\section JKQTMathTextFontSpecifier_specialNames Special FOnt Names
This object also implements replacing special font names with actual fonts. Supported special font names are:
- \c default / \c app / \c application - the applications default font
- \c times / \c serif - a general serif font
- \c sans-serif - a general sans-serif font
- \c typewriter - a general typewrter/monospaced font
- \c cursive
- \c decorative
- \c fantasy
- \c monospace
- \c system
.
If copiled with Qt>5.3 you can also use these:
- \c fixed
- \c smallest_readable
- \c title
- \c general
.
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontSpecifier {
JKQTMathTextFontSpecifier();
JKQTMathTextFontSpecifier(const QString& fontName, const QString& mathFontName);
/** \brief construct a JKQTMathTextFontSpecifier, by parsing a \a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
static JKQTMathTextFontSpecifier fromFontSpec(const QString& fontSpec);
/** \brief initialises the object with values from parsing a \a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
void setFontSpec(const QString& fontSpec);
/** \brief returns the object's constents as a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
QString getFontSpec() const;
/** \copydoc m_fontName */
QString fontName() const;
/** \copydoc m_mathFontName */
QString mathFontName() const;
/** \copydoc m_fontName */
void setFontName(const QString& name);
/** \copydoc m_mathFontName */
void setmathFontName(const QString& name);
/** \brief finds actual fonts for some predefined special font names, as listed in \ref JKQTMathTextFontSpecifier_specialNames */
static QString transformFontName(const QString& fontName);
/** \brief same as transformFontName(), but also finds the actual name for XITS, STIX, ASANA,... */
static QString transformFontNameAndDecodeSpecialFonts(const QString& fontName);
/** \brief leiefert \c true, wenn ein fontName() verfügbar ist */
bool hasFontName() const;
/** \brief leiefert \c true, wenn ein mathFontName() verfügbar ist */
bool hasMathFontName() const;
/** \brief initialize with the font-families from the XITS package for text and math */
static JKQTMathTextFontSpecifier getXITSFamilies();
/** \brief initialize with the font-families from the XITS package for text and math */
static JKQTMathTextFontSpecifier getASANAFamilies();
/** \brief initialize with the font-families from the STIX package for text and math */
static JKQTMathTextFontSpecifier getSTIXFamilies();
private:
/** \brief specifies the main font name */
QString m_fontName;
/** \brief specifies the math font to use in addition to fontName */
QString m_mathFontName;
};
class JKQTMathTextNode; // forward
/*! \brief this class parses a LaTeX string and can then draw the contained text/equation onto a <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a>
\ingroup jkqtmathtext
@ -329,35 +251,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
/** \brief convert LaTeX to HTML. returns \c ok=true on success and \c ok=false else. */
QString toHtml(bool* ok=nullptr, double fontPointSize=10);
/*! \brief used to specify the font encoding used for drawing
*/
enum MTfontEncoding {
MTFEwinSymbol, /*!< \brief This assumes that symbols shall be taken from a MS Windows style Symbol font */
MTFEunicode, /*!< \brief This assumes that symbols shall be taken from a Unicode font (e.g. the STIX fonts from <a href="http://www.stixfonts.org/">http://www.stixfonts.org/</a>)*/
MTFEunicodeLimited, /*!< \brief This assumes that the fonts used are Unicode, but only offer a limited set of symbols. Especially math symbols are missing from this encoding */
MTFEStandard, /*!< \brief the encoding of a standard TTF font (i.e. we can only expect letters,number and not many special characters) */
};
/** \brief convert MTfontEncoding to a string */
static QString encoding2String(MTfontEncoding e);
/** \brief the available logical fonts (default is MTEroman) */
enum MTenvironmentFont {
MTEroman, /*!< \brief roman font, e.g. <code>\\rm{}</code> */
MTEsans, /*!< \brief sans-serif font, e.g. <code>\\sf{}</code> */
MTEmathRoman, /*!< \brief math-mode roman font, e.g. <code>\\mathrm{}</code> */
MTEmathSans, /*!< \brief math-mode sans-serif font, e.g. <code>\\mathsf{}</code> */
MTEtypewriter, /*!< \brief typewriter font, e.g. <code>\\tt{},\\mathtt{}</code> */
MTEscript, /*!< \brief script font, e.g. <code>\\script{},\\mathscript{}</code> */
MTEblackboard, /*!< \brief blackboard font, e.g. <code>\\mathbb{}</code> */
MTEcaligraphic, /*!< \brief caligraphic font, e.g. <code>\\mathcal{}</code> */
MTEfraktur, /*!< \brief fraktur font, e.g. <code>\\mathfrak{}</code> */
MTenvironmentFontCount /*!< \brief internal enum value that allows to iterate over MTenvironmentFont \internal */
};
/** \copydoc fontColor */
void setFontColor(const QColor & __value);
/** \copydoc fontColor */
@ -386,10 +279,11 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
* \param useFont replacement font for nonUseFont
* \param useFontEncoding encoding of the replacement font
*/
void addReplacementFont(const QString& nonUseFont, const QString& useFont, MTfontEncoding useFontEncoding);
void addReplacementFont(const QString& nonUseFont, const QString& useFont, JKQTMathTextFontEncoding useFontEncoding);
/** \brief retrieves a replacement for the given font name \a nonUseFont, including its encoding. Returns the given default values \a defaultFont and/or \a defaultFontEncoding if one of the two is not found */
QPair<QString, MTfontEncoding> getReplacementFont(const QString &nonUseFont, const QString &defaultFont, MTfontEncoding defaultFontEncoding) const;
QPair<QString, JKQTMathTextFontEncoding> getReplacementFont(const QString &nonUseFont, const QString &defaultFont, JKQTMathTextFontEncoding defaultFontEncoding) const;
/** \brief font subclasses, used by getFontData() */
enum class FontSubclass {
Text,
Default=Text,
@ -398,43 +292,43 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
};
/** \brief retrieve the font and encoding to be used for \a font, which might optionally be typeset inside a math environment, specified by in_math_environment, possibly for the given font subclass \a subclass */
QPair<QString, MTfontEncoding> getFontData(MTenvironmentFont font, bool in_math_environment=false, FontSubclass subclass=FontSubclass::Default) const;
QPair<QString, JKQTMathTextFontEncoding> getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment=false, FontSubclass subclass=FontSubclass::Default) const;
/*! \brief calls setFontRoman(), or calls useXITS() if \a __value \c =="XITS". calls useSTIX() if \a __value \c =="STIX", ...
\see setFontRoman(), useXITS(), useSTIX() for more information */
void setFontRomanOrSpecial(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontRomanOrSpecial(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/*! \brief calls setFontRoman(), or calls useXITS() if \a __value \c =="XITS". calls useSTIX() if \a __value \c =="STIX", ...
\see setFontRoman(), useXITS(), useSTIX() for more information */
void setFontRomanOrSpecial(const JKQTMathTextFontSpecifier & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontRomanOrSpecial(const JKQTMathTextFontSpecifier & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEroman */
void setFontRoman(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontRoman(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for text in the logical font MTEroman */
QString getFontRoman() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEsans */
void setFontSans(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontSans(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for text in the logical font MTEsans */
QString getFontSans() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEtypewriter */
void setFontTypewriter(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontTypewriter(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for text in the logical font MTEtypewriter */
QString getFontTypewriter() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEscript */
void setFontScript(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontScript(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for text in the logical font MTEscript */
QString getFontScript() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEfraktur */
void setFontFraktur(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontFraktur(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for text in the logical font MTEfraktur */
QString getFontFraktur() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEcaligraphic */
void setFontCaligraphic(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontCaligraphic(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for text in the logical font MTEcaligraphic */
QString getFontCaligraphic() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEblackboard */
void setFontBlackboard(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontBlackboard(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief blackboard font is simulated by using roman with outlines only */
void setFontBlackboardSimulated(bool doSimulate);
/** \brief is blackboard font simulated by using roman with outlines only */
@ -442,50 +336,50 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
/** \brief retrieves the font to be used for text in the logical font MTEblackboard */
QString getFontBlackboard() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for greek letters in the logical font \a font */
void setSymbolfontGreek(MTenvironmentFont font, const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setSymbolfontGreek(JKQTMathTextEnvironmentFont font, const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief set the font \a fontName and it's encoding \a encoding to be used for integrals in all logical fonts */
void setSymbolfontGreek(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setSymbolfontGreek(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for greek letters in the logical font \a font */
QString getSymbolfontGreek(MTenvironmentFont font) const;
QString getSymbolfontGreek(JKQTMathTextEnvironmentFont font) const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for symbols in the logical font \a font */
void setSymbolfontSymbol(MTenvironmentFont font, const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setSymbolfontSymbol(JKQTMathTextEnvironmentFont font, const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief set the font \a fontName and it's encoding \a encoding to be used for integrals in all logical fonts */
void setSymbolfontSymbol(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setSymbolfontSymbol(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for symbols in the logical font \a font */
QString getSymbolfontSymbol(MTenvironmentFont font) const;
QString getSymbolfontSymbol(JKQTMathTextEnvironmentFont font) const;
/** \brief retrieves the encoding used for the symbol font to be used for symbols in the logical font \a font */
MTfontEncoding getSymbolfontEncodingSymbol(MTenvironmentFont font) const;
JKQTMathTextFontEncoding getSymbolfontEncodingSymbol(JKQTMathTextEnvironmentFont font) const;
/** \brief retrieves the encoding used for the greek letter font to be used for symbols in the logical font \a font */
MTfontEncoding getSymbolfontEncodingGreek(MTenvironmentFont font) const;
JKQTMathTextFontEncoding getSymbolfontEncodingGreek(JKQTMathTextEnvironmentFont font) const;
/** \brief retrieves the encoding used for the script font */
MTfontEncoding getFontEncodingScript() const;
JKQTMathTextFontEncoding getFontEncodingScript() const;
/** \brief retrieves the encoding used for the Fraktur font */
MTfontEncoding getFontEncodingFraktur() const;
JKQTMathTextFontEncoding getFontEncodingFraktur() const;
/** \brief retrieves the encoding used for the typewriter font */
MTfontEncoding getFontEncodingTypewriter() const;
JKQTMathTextFontEncoding getFontEncodingTypewriter() const;
/** \brief retrieves the encoding used for the sans-serif font */
MTfontEncoding getFontEncodingSans() const;
JKQTMathTextFontEncoding getFontEncodingSans() const;
/** \brief retrieves the encoding used for the roman font */
MTfontEncoding getFontEncodingRoman() const;
JKQTMathTextFontEncoding getFontEncodingRoman() const;
/** \brief retrieves the encoding used for the blackboard font */
MTfontEncoding getFontEncodingBlackboard() const;
JKQTMathTextFontEncoding getFontEncodingBlackboard() const;
/** \brief retrieves the encoding used for the caligraphic font */
JKQTMathText::MTfontEncoding getFontEncodingCaligraphic() const;
JKQTMathTextFontEncoding getFontEncodingCaligraphic() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEmathRoman */
void setFontMathRoman(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontMathRoman(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for text in the logical font MTEroman */
QString getFontMathRoman() const;
/** \brief set the font \a fontName and it's encoding \a encoding to be used for text in the logical font MTEmathSans */
void setFontMathSans(const QString & fontName, MTfontEncoding encoding=MTfontEncoding::MTFEStandard);
void setFontMathSans(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard);
/** \brief retrieves the font to be used for text in the logical font MTEsans */
QString getFontMathSans() const;
/** \brief retrieves the encoding used for the math-mode sans-serif font */
MTfontEncoding getFontEncodingMathSans() const;
JKQTMathTextFontEncoding getFontEncodingMathSans() const;
/** \brief retrieves the encoding used for the math-mode roman font */
MTfontEncoding getFontEncodingMathRoman() const;
JKQTMathTextFontEncoding getFontEncodingMathRoman() const;
/** \brief configures the class to use the STIX fonts in mathmode
*
@ -528,7 +422,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
* <code>setAnyUnicode("Comic Sans MS", "Comic Sans MS")</code>:<br>\image html jkqtmathparser_comicsans.png <br><br>
*
*/
void useAnyUnicode(QString timesFont=QString(""), const QString& sansFont=QString(""), MTfontEncoding encodingTimes=MTfontEncoding::MTFEunicode, MTfontEncoding encodingSans=MTfontEncoding::MTFEunicode);
void useAnyUnicode(QString timesFont=QString(""), const QString& sansFont=QString(""), JKQTMathTextFontEncoding encodingTimes=JKQTMathTextFontEncoding::MTFEunicode, JKQTMathTextFontEncoding encodingSans=JKQTMathTextFontEncoding::MTFEunicode);
@ -601,567 +495,19 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
void setUseUnparsed(bool __value);
/** \copydoc useUnparsed */
bool isUsingUnparsed() const;
/** \copydoc error_list */
/** \copydoc error_list */
QStringList getErrorList() const;
protected:
/** \brief describes the current drawing environment (base fontname ...) */
struct MTenvironment {
MTenvironment();
/** \brief current font color */
QColor color;
/** \brief current font */
MTenvironmentFont font;
/** \brief current font size [pt] */
double fontSize;
/** \brief is the text currently bold? */
bool bold;
/** \brief is the text currently italic? */
bool italic;
/** \brief is the text currently in small caps? */
bool smallCaps;
/** \brief is the text currently underlined? */
bool underlined;
/** \brief is the text currently overlined? */
bool overline;
/** \brief is the text currently stroke through? */
bool strike;
/** \brief is the text currently are we inside a math environment? */
bool insideMath;
/** \copydoc error_list */
void addToErrorList(const QString& error);
/** \brief build a QFont object from the settings in this object */
QFont getFont(JKQTMathText* parent) const;
/** \brief generate a HTML prefix that formats the text after it according to the settings in this object
*
* \param defaultEv environment before applying the current object (to detect changes)
* \see toHtmlAfter()
*/
QString toHtmlStart(MTenvironment defaultEv) const;
/** \brief generate a HTML postfix that formats the text in front of it according to the settings in this object
*
* \param defaultEv environment before applying the current object (to detect changes)
* \see toHtmlAfter()
*/
QString toHtmlAfter(MTenvironment defaultEv) const;
};
/** \brief beschreibt die Größe eines Knotens */
struct JKQTMATHTEXT_LIB_EXPORT MTnodeSize {
MTnodeSize();
double width;
double baselineHeight;
double overallHeight;
double strikeoutPos;
};
public:
/** \brief subclass representing one node in the syntax tree
* \ingroup jkqtmathtext_items
*
* \image html jkqtmathtext_node_geo.png
*/
class JKQTMATHTEXT_LIB_EXPORT MTnode {
public:
explicit MTnode(JKQTMathText* parent);
MTnode(const MTnode&)=delete;
MTnode& operator=(const MTnode&)=delete;
virtual ~MTnode();
/** \brief determine the size of the node, calls getSizeInternal() implementation of the actual type \see getSizeInternal()
*
* \param painter painter to use for determining the size
* \param currentEv current environment object
* \param[out] width width of the block/node
* \param[out] baselineHeight distance from the bottom of the block/node-box to the baseline
* \param[out] overallHeight overall height (bottom to top) of the node, the ascent is \c overallHeight-baselineHeight
* \param[out] strikeoutPos position of the strikeout-line
* \param[in] prevNodeSize optional parameter, describing the size of the previous node (on the left). This may be used for layout of some nodes (e.g. sub/super to move correctly next to large parantheses ...)
*
*/
void getSize(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr);
/** \brief calculates the x-size-difference between the given (probably) italic (width externally calculated: \A width_potentiallyitalic, \a ev_potentiallyitalic) and the non-italic version of \a child */
double getNonItalicXCorretion(QPainter &painter, double width_potentiallyitalic, const MTenvironment &ev_potentiallyitalic, JKQTMathText::MTnode* child) const;
/** \brief draw the contents at the designated position
*
* \param painter QPainter to use
* \param x x-position, where the drawing starts [Pixel]
* \param y Y-position of the baseline, where the drawing starts [Pixel]
* \param currentEv JKQTMathText::MTenvironment object describing the current drawing environment/settings
* \param[in] prevNodeSize optional parameter, describing the size of the previous node (on the left). This may be used for layout of some nodes (e.g. sub/super to move correctly next to large parantheses ...)
* \return the x position which to use for the next part of the text
*/
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr)=0;
/** \brief convert node to HTML and returns \c true on success
* \param[out] html new HTML code is APPENDED to this string
* \param currentEv JKQTMathText::MTenvironment object describing the current drawing environment/settings
* \param defaultEv JKQTMathText::MTenvironment object describing the default drawing environment/settings when starting to interpret a node tree
* \return \c true on success
*/
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv);
/** \brief returns the drawing of colored boxes (for DEBUGGING) around the actual output of the node is enabled */
bool getDrawBoxes() const;
/** \brief enables the drawing of colored boxes (for DEBUGGING) around the actual output of the node */
virtual void setDrawBoxes(bool draw);
/** \brief return the name of this class as a string */
virtual QString getTypeName() const;
protected:
/** \brief determine the size of the node, overwrite this function in derived classes
*
* \param painter painter to use for determining the size
* \param currentEv current environment object
* \param[out] width width of the block/node
* \param[out] baselineHeight distance from the bottom of the block/node-box to the baseline
* \param[out] overallHeight overall height (bottom to top) of the node, the ascent is \c overallHeight-baselineHeight
* \param[out] strikeoutPos position of the strikeout-line
* \param[in] prevNodeSize optional parameter, describing the size of the previous node (on the left). This may be used for layout of some nodes (e.g. sub/super to move correctly next to large parantheses ...)
*
*/
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr)=0;
/** \brief parent JKQTMathText object (required for several drawing operations */
JKQTMathText* parent;
/** \brief enables the drawing of colored boxes (for DEBUGGING) around the actual output of the node */
bool drawBoxes;
/** \brief draws colored boxes (for DEBUGGING) around the actual output of the node
*
* \param painter QPainter to use
* \param x x-position, where the drawing starts [Pixel]
* \param y Y-position of the baseline, where the drawing starts [Pixel]
* \param currentEv JKQTMathText::MTenvironment object describing the current drawing environment/settings
*/
void doDrawBoxes(QPainter& painter, double x, double y, JKQTMathText::MTenvironment currentEv);
};
/** \brief subclass representing one text node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTtextNode: public MTnode {
public:
explicit MTtextNode(JKQTMathText* parent, const QString& text, bool addWhitespace, bool stripInnerWhitepace=false);
virtual ~MTtextNode() override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc text */
QString getText() const;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override ;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
/** \brief text-contents of the node */
QString text;
/** \brief transforms the text before sizing/drawing (may e.g. exchange special letters for other unicode symbols etc.) */
virtual QString textTransform(const QString& text, JKQTMathText::MTenvironment currentEv, bool forSize=false);
};
/** \brief subclass representing one text node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTplainTextNode: public MTtextNode {
public:
explicit MTplainTextNode(JKQTMathText* parent, const QString& text, bool addWhitespace, bool stripInnerWhitepace=false);
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
protected:
/** \copydoc MTtextNode::textTransform() */
virtual QString textTransform(const QString& text, JKQTMathText::MTenvironment currentEv, bool forSize=false) override;
};
/** \brief subclass representing one whitepsace node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTwhitespaceNode: public MTtextNode {
public:
explicit MTwhitespaceNode(JKQTMathText* parent);
virtual ~MTwhitespaceNode() override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
};
/** \brief subclass representing one symbol (e.g. \c \\alpha , \c \\cdot ...) node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTsymbolNode: public MTnode {
public:
explicit MTsymbolNode(JKQTMathText* parent, const QString& name, bool addWhitespace);
virtual ~MTsymbolNode() override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc symbolName */
QString getSymbolName() const;
/** \brief get font name of the symbol */
QString getSymbolfontName() const;
/** \copydoc addWhitespace */
bool getAddWhitespace() const;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
/** \brief this string will be sent to the drawText method with properly set fonts */
QString symbolName;
/** \brief add a whitespace to the symbol? */
bool addWhitespace;
struct SymbolProps {
/** \brief the symbol name supplied to the constructor */
QString symbol;
/** \brief font to use for output */
QString font;
/** \brief magnification factor for the font size */
double fontFactor;
/** \brief 0: leave italic setting as is, >0: set italic, <0 set italic to false */
char italic;
/** \brief 0: leave bold setting as is, >0: set bold, <0 set bold to false */
char bold;
/** \brief this corrects the y position of a symbol: draws at y <- y+ height*yfactor) */
double yfactor;
/** \brief indicates whether to draw a bar (like for \c \\hbar ) */
bool drawBar;
bool heightIsAscent;
bool exactAscent;
bool extendWidthInMathmode;
};
/** \brief retrieve the properties to render the given symbol \a symName in the current environment \a currentEv */
SymbolProps getSymbolProp(const QString& symName, const MTenvironment& currentEv) const;
/** \brief fill \a props for the symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using Unicode font (or WinSymbol as Fallback)*/
bool getSymbolProp(JKQTMathText::MTsymbolNode::SymbolProps &props, const QString &n, const MTenvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the greek letter symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using Unicode font (or WinSymbol as Fallback) */
bool getGreekSymbolProp(JKQTMathText::MTsymbolNode::SymbolProps &props, const QString &n, const MTenvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using WinSymbol font */
bool getWinSymbolProp(JKQTMathText::MTsymbolNode::SymbolProps &props, const QString &n, const MTenvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using any font, does not alter the font name!!! */
bool getStandardTextSymbolProp(JKQTMathText::MTsymbolNode::SymbolProps &props, const QString &n) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using any unicode font, does not alter the font name!!! */
bool getUnicodeBaseSymbolProp(JKQTMathText::MTsymbolNode::SymbolProps &props, const QString &n) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using a full unicode font, does not alter the font name!!! */
bool getUnicodeFullSymbolProp(JKQTMathText::MTsymbolNode::SymbolProps &props, const QString &n, double mathFontFactor) const;
};
/** \brief subclass representing a list of nodes in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTlistNode: public MTnode {
public:
explicit MTlistNode(JKQTMathText* parent);
virtual ~MTlistNode() override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \brief add a child node */
void addNode(MTnode* n) { nodes.append(n); }
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \copydoc nodes */
QList<MTnode*> getNodes() const;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
QList<MTnode*> nodes;
QSet<QString> subsupOperations;
};
/** \brief subclass representing an instruction node with exactly one argument in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTinstruction1Node: public MTnode {
public:
explicit MTinstruction1Node(JKQTMathText* parent, const QString& name, MTnode* child, const QStringList& parameters=QStringList());
virtual ~MTinstruction1Node() override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \brief convert node to HTML and returns \c true on success */
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \brief returns the child node */
MTnode* getChild() const;
/** \copydoc name */
QString getName() const;
/** \copydoc parameters */
QStringList getParameters() const;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
bool setupMTenvironment(JKQTMathText::MTenvironment &ev);
MTnode* child;
QString name;
QStringList parameters;
};
/** \brief subclass representing an subscript node with exactly one argument in the syntax tree
* \ingroup jkqtmathtext_items
*
* \image html jkqtmathtext_subscriptnode_getSizeInternal.png
*/
class JKQTMATHTEXT_LIB_EXPORT MTsubscriptNode: public MTnode {
public:
explicit MTsubscriptNode(JKQTMathText* parent, MTnode* child);
virtual ~MTsubscriptNode() override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override; /** \brief returns the child node */
/** \brief returns the child node */
MTnode *getChild() const;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
MTnode* child;
};
/** \brief subclass representing an superscript node with exactly one argument in the syntax tree
* \ingroup jkqtmathtext_items
*
* \image html jkqtmathtext_subscriptnode_getSizeInternal.png
*
* \note a MTlistNode might modify the positioning slightly for special cases (e.g. \c \\int , \c \\sum ... or after braces)
*/
class JKQTMATHTEXT_LIB_EXPORT MTsuperscriptNode: public MTnode {
public:
explicit MTsuperscriptNode(JKQTMathText* parent, MTnode* child);
virtual ~MTsuperscriptNode() override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \brief returns the child node */
MTnode* getChild() const;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
MTnode* child;
};
/** \brief subclass representing a brace node
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTbraceNode: public MTnode {
public:
MTbraceNode(JKQTMathText* parent, const QString& openbrace, const QString& closebrace, MTnode* child, bool showRightBrace=true);
virtual ~MTbraceNode() override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
/** \brief returns the child node */
inline MTnode* getChild() const {
return this->child;
}
/** \copydoc openbrace */
inline QString getOpenbrace() const {
return this->openbrace;
}
/** \copydoc closebrace */
inline QString getClosebrace() const {
return this->closebrace;
}
/** \copydoc showRightBrace */
inline bool getShowRightBrace() const {
return this->showRightBrace;
}
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
MTnode* child;
QString openbrace;
QString closebrace;
bool showRightBrace;
void getBraceWidth(QPainter& painter, MTenvironment currentEv, double baselineHeight, double overallHeight, double& bracewidth, double& braceheight);
};
/** \brief subclass representing a sqrt node
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTsqrtNode: public MTnode {
public:
MTsqrtNode(JKQTMathText* parent, MTnode* child, int degree=2);
virtual ~MTsqrtNode() override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override ;
/** \brief returns the child node */
MTnode *getChild() const;
/** \copydoc degree */
int getDegree() const;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
MTnode* child;
int degree;
};
enum MTfracMode {
MTFMfrac, /*!< \brief normal fraction \image html mathparser/MTFMfrac.png */
MTFMdfrac, /*!< \brief normal fraction, without scaling of under/over text \image html mathparser/MTFMdfrac.png */
MTFMtfrac, /*!< \brief text fraction (smaller than MTFMfrac) \image html mathparser/MTFMtfrac.png */
MTFMsfrac, /*!< \brief slanted fraction \image html mathparser/MTFMsfrac.png */
MTFMstfrac, /*!< \brief slanted text fraction \image html mathparser/MTFMstfrac.png */
MTFMunderbrace, /*!< \brief curly underbrace \image html mathparser/MTFMunderbrace.png */
MTFMoverbrace, /*!< \brief curly overbrace \image html mathparser/MTFMoverbrace.png */
MTFMstackrel, /*!< \brief binom/fraction without line \image html mathparser/MTFMstackrel.png */
MTFMunderset, /*!< \brief underset text \image html mathparser/MTFMunderset.png */
MTFMoverset /*!< \brief overset text \image html mathparser/MTFMoverset.png */
};
static QString fracModeToString(MTfracMode mode);
/** \brief subclass representing a \\frac node
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTfracNode: public MTnode {
public:
MTfracNode(JKQTMathText* parent, MTnode* child_top, MTnode* child_bottom, MTfracMode mode);
virtual ~MTfracNode() override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \brief returns the 1st child node */
MTnode* getChild1() const;
/** \brief returns the 2nd child node */
MTnode* getChild2() const;
/** \copydoc mode */
MTfracMode getMode() const;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
MTnode* child1;
MTnode* child2;
MTfracMode mode;
};
/** \brief subclass representing a \\begin{matrix} node
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTmatrixNode: public MTnode {
public:
MTmatrixNode(JKQTMathText* parent, QVector<QVector<MTnode*> > children);
virtual ~MTmatrixNode() override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override;
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \brief returns the child nodes */
QVector<QVector<MTnode*> > getChildren() const;
/** \copydoc columns */
int getColumns() const;
/** \copydoc lines */
int getLines() const;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
QVector<QVector<MTnode*> > children;
int columns;
int lines;
};
/** \brief types of decoration available in a MTdecoratedNode */
enum MTdecoration {
MTDvec, /*!< \brief vector arrow over block \image html mathparser/MTDvec.png */
MTDhat, /*!< \brief small hat over block \image html mathparser/MTDhat.png */
MTDwidehat, /*!< \brief full-width hat over block \image html mathparser/MTDwidehat.png */
MTDcheck, /*!< \brief small v over block \image html mathparser/MTDcheck.png */
MTDwidecheck, /*!< \brief full-width v over block \image html mathparser/MTDwidecheck.png */
MTDbreve, /*!< \brief small tilde over block \image html mathparser/MTDbreve.png */
MTDocirc, /*!< \brief single circle over block \image html mathparser/MTDocirc.png */
MTDdot, /*!< \brief single dot over block \image html mathparser/MTDvec.png */
MTDddot, /*!< \brief double dot over block \image html mathparser/MTDddot.png */
MTDbar, /*!< \brief bar over block \image html mathparser/MTDbar.png */
MTDarrow, /*!< \brief arrow over block \image html mathparser/MTDarrow.png */
MTDoverline, /*!< \brief overline over block \image html mathparser/MTDoverline.png */
MTDdoubleoverline, /*!< \brief double overline over block \image html mathparser/MTDdoubleoverline.png */
MTDunderline, /*!< \brief underline under block \image html mathparser/MTDunderline.png */
MTDdoubleunderline, /*!< \brief double underline under block \image html mathparser/MTDdoubleunderline.png */
MTDtilde, /*!< \brief small tilde over block \image html mathparser/MTDtilde.png */
MTDwidetilde, /*!< \brief full width tilde over block \image html mathparser/MTDwidetilde.png */
MTDcancel, /*!< \brief cancel text with sloped line \image html mathparser/MTDcancel.png */
MTDbcancel, /*!< \brief cancel text with backward sloped line \image html mathparser/MTDbcancel.png */
MTDxcancel, /*!< \brief cancel text with X \image html mathparser/MTDxcancel.png */
MTDstrike /*!< \brief strikethrough text \image html mathparser/MTDstrike.png */
};
/** \brief convert a MTdecoration into a string */
static QString decorationToString(MTdecoration mode);
/** \brief subclass representing a decorated text m (e.g. \c \\vec \c \\hat ...) node
* \ingroup jkqtmathtext_items
*
* \image html mathparser/decoration_sizing.png
*
*/
class JKQTMATHTEXT_LIB_EXPORT MTdecoratedNode: public MTnode {
public:
MTdecoratedNode(JKQTMathText* parent, MTdecoration decoration, MTnode* child);
virtual ~MTdecoratedNode() override;
/** \copydoc MTnode::draw() */
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
/** \copydoc MTnode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
/** \copydoc MTnode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \copydoc MTnode::getTypeName() */
virtual QString getTypeName() const override ;
/** \brief returns the child node */
MTnode* getChild() const;
/** \copydoc decoration */
MTdecoration getDecoration() const;
protected:
/** \copydoc MTnode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
/** \brief child node that is decorated by this node */
MTnode* child;
/** \brief type of decoration that is added to the child node */
MTdecoration decoration;
};
protected:
/** \brief table with font replacements to use (e.g. if it is known that a certain font is not good for rendering, you can add
* an alternative using addReplacementFont(). These are automatically applied, when setting a new font name! */
QMap<QString, QString> fontReplacements;
/** \brief acompanies fontReplacements and collects the encodings of the replacement fonts, if no entry is present, the default encoding is used, as given to the setter! */
QMap<QString, MTfontEncoding> fontEncodingReplacements;
QMap<QString, JKQTMathTextFontEncoding> fontEncodingReplacements;
/** \brief font color */
QColor fontColor;
@ -1169,27 +515,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
double fontSize;
/*! \brief summarizes all information available on a font for a specific MTenvironmentFont
\see fontDefinitions */
struct FontDefinition {
FontDefinition();
/** \brief name of the font */
QString fontName;
/** \brief specifies the encoding of the font (default is \c MTFEwinSymbol ) */
MTfontEncoding fontEncoding;
/** \brief symbol font used for greek symbols, or empty when \a fontName shall be used */
QString symbolfontGreek;
/** \brief specifies the encoding of symbolfontGreek */
MTfontEncoding symbolfontGreekEncoding;
/** \brief symbol font, used for math symbols, or empty when \a fontName shall be used */
QString symbolfontSymbol;
/** \brief specifies the encoding of symbolfontSymbol */
MTfontEncoding symbolfontSymbolEncoding;
};
/** \brief stores information about the different fonts used by LaTeX markup */
QHash<MTenvironmentFont, FontDefinition> fontDefinitions;
QHash<JKQTMathTextEnvironmentFont, JKQTMathTextFontDefinition> fontDefinitions;
/** \brief if enabled, the blackboard-characters are simulated by using font outlines only */
bool blackboardSimulated;
@ -1242,13 +569,13 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
bool showRightBrace;
/** \brief the result of parsing the last string supplied to the object via parse() */
MTnode* parsedNode;
JKQTMathTextNode* parsedNode;
/** \brief a tree containing the unparsed text as a single node */
MTnode* unparsedNode;
JKQTMathTextNode* unparsedNode;
/** \brief if true, the unparsedNode is drawn */
bool useUnparsed;
MTnode* getTree() const;
JKQTMathTextNode* getTree() const;
/** \brief the token types that may arrise in the string */
enum tokenType {
@ -1267,9 +594,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
/** \brief tokenizer for the LaTeX parser */
tokenType getToken();
/** \brief parse a LaTeX string */
MTnode* parseLatexString(bool get, const QString& quitOnClosingBrace=QString(""), const QString& quitOnEnvironmentEnd=QString(""));
JKQTMathTextNode* parseLatexString(bool get, const QString& quitOnClosingBrace=QString(""), const QString& quitOnEnvironmentEnd=QString(""));
/** \brief parse a LaTeX math environment */
MTnode* parseMath(bool get);
JKQTMathTextNode* parseMath(bool get);
/** \brief used by the tokenizer. type of the current token */
tokenType currentToken;
@ -1285,71 +612,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
public:
/** \copydoc parsedNode */
MTnode *getParsedNode() const;
JKQTMathTextNode *getParsedNode() const;
struct JKQTMATHTEXT_LIB_EXPORT tbrData {
explicit tbrData(const QFont& f, const QString& text, QPaintDevice *pd);
QFontMetricsF fm;
QString text;
QRectF tbr;
QFont f;
int ldpiX, ldpiY, pdpiX, pdpiY;
//QPaintDevice *pd;
bool operator==(const tbrData& other) const;
};
struct JKQTMATHTEXT_LIB_EXPORT tbrDataH {
explicit tbrDataH(const QFont& f, const QString& text, QPaintDevice *pd);
QString text;
QFont f;
int ldpiX, ldpiY, pdpiX, pdpiY;
bool operator==(const tbrDataH& other) const;
};
static QList<JKQTMathText::tbrData> tbrs;
static QHash<JKQTMathText::tbrDataH, QRectF> tbrh;
static QRectF getTightBoundingRect(const QFont &fm, const QString& text, QPaintDevice *pd);
/** \brief returns a copy of \a f, but with the italic-property set to \c false */
static QFont getNonItalic(const QFont& f);
};
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
inline size_t qHash(const JKQTMathText::tbrDataH& data, size_t /*seed=0*/) {
#else
inline uint qHash(const JKQTMathText::tbrDataH& data) {
#endif
return qHash(data.f.family())+qHash(data.text);
}
/*! \brief A QLabel-derived class that draws an equation with LaTeX markup using JKQTMathText
\ingroup jkqtmathtext
\see JKQTMathText
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextLabel: public QLabel {
Q_OBJECT
public:
explicit JKQTMathTextLabel(QWidget* parent=nullptr);
virtual ~JKQTMathTextLabel();
/** \brief returns the internal JKQTMathText instance used for drawing
*
* Use this function to set the font, font size and other properties of the used renderer.
*/
JKQTMathText* getMathText() const;
/** \brief set the equation to draw */
void setMath(const QString& text, bool doRepaint=true);
protected:
JKQTMathText* m_mathText;
QString lastText;
QPixmap buffer;
bool repaintDo;
void internalPaint();
void paintEvent(QPaintEvent * event);
};

View File

@ -3,7 +3,7 @@
/*
Copyright (c) 2008-2020 Jan W. Krieger (<jan@jkrieger.de>)
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
last modification: $LastChangedDate: 2015-04-02 13:55:22 +0200 (Do, 02 Apr 2015) $ (revision $Rev: 3902 $)

View File

@ -0,0 +1,114 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/jkqtmathtextlabel.h"
#include <QDebug>
#include <QApplication>
JKQTMathTextLabel::JKQTMathTextLabel(QWidget *parent):
QLabel(parent)
{
m_mathText=new JKQTMathText(this);
m_mathText->useXITS();
m_mathText->setFontSize(font().pointSizeF()*1.3);
lastText="";
repaintDo=true;
buffer=QPixmap();
}
JKQTMathTextLabel::~JKQTMathTextLabel()
= default;
JKQTMathText *JKQTMathTextLabel::getMathText() const
{
return m_mathText;
}
void JKQTMathTextLabel::setMath(const QString &text, bool doRepaint)
{
if (text!=lastText || doRepaint){
lastText=text;
repaintDo=true;
internalPaint();
update();
}
}
void JKQTMathTextLabel::internalPaint()
{
//return;
//qDebug()<<"internalPaint "<<lastText<<repaintDo;
//if (repaintDo) {
QSizeF size;
{
repaintDo=false;
//qDebug()<<"internalPaint(): parse "<<m_mathText->parse(lastText)<<"\n "<<m_mathText->getErrorList().join("\n")<<"\n\n";
if (!m_mathText->parse(lastText)) {
//qDebug()<<"JKQTMathTextLabel::internalPaint(): parse '"<<lastText<<"': "<<m_mathText->parse(lastText)<<"\n "<<m_mathText->getErrorList().join("\n")<<"\n\n";
}
if (buffer.width()<=0 || buffer.height()<=0) {
const qreal dpr = devicePixelRatioF();
buffer=QPixmap(1000*dpr,100*dpr);
buffer.setDevicePixelRatio(dpr);
}
//qDebug()<<"internalPaint(): buffer "<<buffer.size();
QPainter p;
//qDebug()<<"internalPaint(): "<<p.begin(&buffer);
p.begin(&buffer);
p.setRenderHint(QPainter::Antialiasing);
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
p.setRenderHint(QPainter::HighQualityAntialiasing);
#endif
p.setRenderHint(QPainter::TextAntialiasing);
size=m_mathText->getSize(p);
p.end();
}
const qreal dpr = devicePixelRatioF();
buffer=QPixmap(static_cast<int>(qMax(32.0,size.width()*1.2))*dpr, static_cast<int>(qMax(10.0,size.height()*1.1))*dpr);
buffer.setDevicePixelRatio(dpr);
buffer.fill(Qt::transparent);
{
qDebug()<<"internalPaint(): buffer.size()="<<buffer.size()<<" size="<<size<<" dpr="<<dpr;
QPainter p;
//qDebug()<<"internalPaint(): "<<p.begin(&buffer);
p.begin(&buffer);
p.setRenderHint(QPainter::Antialiasing);
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
p.setRenderHint(QPainter::HighQualityAntialiasing);
#endif
p.setRenderHint(QPainter::TextAntialiasing);
m_mathText->draw(p,alignment(), QRectF(QPointF(0,0), size));
p.end();
}
setPixmap(buffer);
//}
//qDebug()<<"internalPaint(): setPixmap";
QApplication::processEvents();
//qDebug()<<"internalPaint(): DONE";
}
void JKQTMathTextLabel::paintEvent(QPaintEvent *event)
{
QLabel::paintEvent(event);
}

View File

@ -0,0 +1,63 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTLABEL_H
#define JKQTMATHTEXTLABEL_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include <QWidget>
#include <QLabel>
/*! \brief A QLabel-derived class that draws an equation with LaTeX markup using JKQTMathText
\ingroup jkqtmathtext
\see JKQTMathText
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextLabel: public QLabel {
Q_OBJECT
public:
explicit JKQTMathTextLabel(QWidget* parent=nullptr);
virtual ~JKQTMathTextLabel();
/** \brief returns the internal JKQTMathText instance used for drawing
*
* Use this function to set the font, font size and other properties of the used renderer.
*/
JKQTMathText* getMathText() const;
/** \brief set the equation to draw */
void setMath(const QString& text, bool doRepaint=true);
protected:
JKQTMathText* m_mathText;
QString lastText;
QPixmap buffer;
bool repaintDo;
void internalPaint();
void paintEvent(QPaintEvent * event);
};
#endif // JKQTMATHTEXTLABEL_H

View File

@ -0,0 +1,655 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
void initJKQTMathTextResources()
{
static bool initialized=false;
if (!initialized) {
#ifdef JKQTMATHTEXT_COMPILED_WITH_XITS
Q_INIT_RESOURCE(xits);
#endif
initialized=true;
}
}
JKQTMathTextFontSpecifier::JKQTMathTextFontSpecifier():
m_fontName(""),
m_mathFontName("")
{
}
JKQTMathTextFontSpecifier::JKQTMathTextFontSpecifier(const QString &_fontName, const QString &_mathFontName):
m_fontName(_fontName),
m_mathFontName(_mathFontName)
{
}
JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::fromFontSpec(const QString &fontSpec)
{
JKQTMathTextFontSpecifier s;
s.setFontSpec(fontSpec);
return s;
}
void JKQTMathTextFontSpecifier::setFontSpec(const QString &fontSpec)
{
QStringList splitspec=fontSpec.split('+');
if (splitspec.size()==0) {
m_fontName=m_mathFontName="";
} else if (splitspec.size()==1) {
m_fontName=splitspec[0];
m_mathFontName="";
} else if (splitspec.size()==2) {
m_fontName=splitspec[0];
m_mathFontName=splitspec[1];
} else if (splitspec.size()>2) {
m_fontName=splitspec.mid(0, splitspec.size()-1).join('+');
m_mathFontName=splitspec.last();
}
}
QString JKQTMathTextFontSpecifier::getFontSpec() const
{
QString res=m_fontName;
if (m_mathFontName.size()>0) res+="+"+m_mathFontName;
return res;
}
QString JKQTMathTextFontSpecifier::fontName() const
{
return transformFontName(m_fontName);
}
QString JKQTMathTextFontSpecifier::mathFontName() const
{
return transformFontName(m_mathFontName);
}
QString JKQTMathTextFontSpecifier::transformFontName(const QString &fontName)
{
const QString fnt=fontName.trimmed().toLower();
QFont testFnt;
if (fnt=="serif") {
testFnt.setStyleHint(QFont::StyleHint::Serif);
return testFnt.defaultFamily();
}
if (fnt=="sans-serif" || fnt=="sansserif" || fnt=="sans" || fnt=="sans serif") {
testFnt.setStyleHint(QFont::StyleHint::SansSerif);
return testFnt.defaultFamily();
}
if (fnt=="cursive") {
testFnt.setStyleHint(QFont::StyleHint::Cursive);
return testFnt.defaultFamily();
}
if (fnt=="typewriter") {
testFnt.setStyleHint(QFont::StyleHint::TypeWriter);
return testFnt.defaultFamily();
}
if (fnt=="monospace") {
testFnt.setStyleHint(QFont::StyleHint::Monospace);
return testFnt.defaultFamily();
}
if (fnt=="fantasy") {
testFnt.setStyleHint(QFont::StyleHint::Fantasy);
return testFnt.defaultFamily();
}
if (fnt=="system") {
testFnt.setStyleHint(QFont::StyleHint::System);
return testFnt.defaultFamily();
}
if (fnt=="decorative") {
testFnt.setStyleHint(QFont::StyleHint::Decorative);
return testFnt.defaultFamily();
}
if (fnt=="default" || fnt=="app" || fnt=="application") {
return QGuiApplication::font().family();
}
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
if (fnt=="fixed") {
return QFontDatabase::systemFont(QFontDatabase::SystemFont::FixedFont).family();
}
if (fnt=="smallest_readable" || fnt=="smallestreadable" || fnt=="smallest readable" || fnt=="smallest") {
return QFontDatabase::systemFont(QFontDatabase::SystemFont::SmallestReadableFont).family();
}
if (fnt=="title") {
return QFontDatabase::systemFont(QFontDatabase::SystemFont::TitleFont).family();
}
if (fnt=="general") {
return QFontDatabase::systemFont(QFontDatabase::SystemFont::GeneralFont).family();
}
#elif QT_VERSION >= QT_VERSION_CHECK(5,2,0)
QFontDatabase fontDB;
if (fnt=="fixed") {
return fontDB.systemFont(QFontDatabase::SystemFont::FixedFont).family();
}
if (fnt=="smallest_readable" || fnt=="smallestreadable" || fnt=="smallest readable" || fnt=="smallest") {
return fontDB.systemFont(QFontDatabase::SystemFont::SmallestReadableFont).family();
}
if (fnt=="title") {
return fontDB.systemFont(QFontDatabase::SystemFont::TitleFont).family();
}
if (fnt=="general") {
return fontDB.systemFont(QFontDatabase::SystemFont::GeneralFont).family();
}
#endif
return fontName;
}
QString JKQTMathTextFontSpecifier::transformFontNameAndDecodeSpecialFonts(const QString &fontName)
{
const QString fnt=fontName.toLower().trimmed();
if (fnt=="xits") {
return getXITSFamilies().fontName();
} else if (fnt=="asana") {
return getASANAFamilies().fontName();
} else if (fnt=="stix") {
return getSTIXFamilies().fontName();
}
return transformFontName(fontName);
}
bool JKQTMathTextFontSpecifier::hasFontName() const
{
return !m_fontName.isEmpty();
}
bool JKQTMathTextFontSpecifier::hasMathFontName() const
{
return !m_mathFontName.isEmpty();
}
JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getXITSFamilies()
{
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
QFontDatabase fdb;
const auto fontFamilies=fdb.families();
#else
const auto fontFamilies=QFontDatabase::families();
#endif
if (!fontFamilies.contains("XITS")) {
if (QFile::exists(":/JKQTMathText/fonts/xits-bold.otf")) { QFontDatabase::addApplicationFont(":/JKQTMathText/fonts/xits-bold.otf"); }
if (QFile::exists(":/JKQTMathText/fonts/xits-bolditalic.otf")) { QFontDatabase::addApplicationFont(":/JKQTMathText/fonts/xits-bolditalic.otf"); }
if (QFile::exists(":/JKQTMathText/fonts/xits-italic.otf")) { QFontDatabase::addApplicationFont(":/JKQTMathText/fonts/xits-italic.otf"); }
if (QFile::exists(":/JKQTMathText/fonts/xits-math.otf")) { QFontDatabase::addApplicationFont(":/JKQTMathText/fonts/xits-math.otf"); }
if (QFile::exists(":/JKQTMathText/fonts/xits-mathbold.otf")) { QFontDatabase::addApplicationFont(":/JKQTMathText/fonts/xits-mathbold.otf"); }
if (QFile::exists(":/JKQTMathText/fonts/xits-regular.otf")) { QFontDatabase::addApplicationFont(":/JKQTMathText/fonts/xits-regular.otf"); }
}
static JKQTMathTextFontSpecifier fontSpec;
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
for (int i=0; i<fontFamilies.size(); i++) {
if (fontFamilies.at(i).contains("XITS Math")) {
fontSpec.m_mathFontName=fontFamilies.at(i);
} else if (fontFamilies.at(i).contains("XITS")) {
fontSpec.m_fontName=fontFamilies.at(i);
}
if (fontSpec.m_mathFontName.size()>0 && fontSpec.m_fontName.size()>0) {
break;
}
}
if (fontSpec.m_mathFontName.isEmpty() && !fontSpec.m_fontName.isEmpty()) {
fontSpec.m_mathFontName=fontSpec.m_fontName;
} else if (!fontSpec.m_mathFontName.isEmpty() && fontSpec.m_fontName.isEmpty()) {
fontSpec.m_fontName=fontSpec.m_mathFontName;
}
}
return fontSpec;
}
JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getASANAFamilies()
{
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
QFontDatabase fdb;
const auto fontFamilies=fdb.families();
#else
const auto fontFamilies=QFontDatabase::families();
#endif
if (!fontFamilies.contains("Asana") && !fontFamilies.contains("Asana Math")) {
if (QFile::exists(":/JKQTMathText/fonts/asana-math.otf")) { /*i=*/QFontDatabase::addApplicationFont(":/JKQTMathText/fonts/asana-math.otf"); }
}
static JKQTMathTextFontSpecifier fontSpec;
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
for (int i=0; i<fontFamilies.size(); i++) {
if (fontFamilies.at(i).contains("Asana Math")) {
fontSpec.m_mathFontName=fontFamilies.at(i);
} else if (fontFamilies.at(i).contains("Asana")) {
fontSpec.m_fontName=fontFamilies.at(i);
}
if (fontSpec.m_mathFontName.size()>0 && fontSpec.m_fontName.size()>0) {
break;
}
}
if (fontSpec.m_mathFontName.isEmpty() && !fontSpec.m_fontName.isEmpty()) {
fontSpec.m_mathFontName=fontSpec.m_fontName;
} else if (!fontSpec.m_mathFontName.isEmpty() && fontSpec.m_fontName.isEmpty()) {
fontSpec.m_fontName=fontSpec.m_mathFontName;
}
}
return fontSpec;
}
JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getSTIXFamilies()
{
static QStringList mathNames{"STIX Two Math", "STIX Math", "STIX Two Math Standard", "STIX Math Standard"};
static QStringList textNames{"STIX", "STIXGeneral", "STIX General"};
static JKQTMathTextFontSpecifier fontSpec;
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
QFontDatabase fdb;
const auto fontFamilies=fdb.families();
#else
const auto fontFamilies=QFontDatabase::families();
#endif
for (const QString& name:mathNames) {
for (int i=0; i<fontFamilies.size(); i++) {
if (fontFamilies.at(i).contains(name) ) {
fontSpec.m_mathFontName=fontFamilies.at(i);
}
if (fontSpec.m_mathFontName.size()>0) {
break;
}
}
if (fontSpec.m_mathFontName.size()>0) {
break;
}
}
for (const QString& name:textNames) {
for (int i=0; i<fontFamilies.size(); i++) {
if (fontFamilies.at(i).contains(name) ) {
fontSpec.m_fontName=fontFamilies.at(i);
}
if (fontSpec.m_fontName.size()>0) {
break;
}
}
if (fontSpec.m_fontName.size()>0) {
break;
}
}
if (fontSpec.m_mathFontName.isEmpty() && !fontSpec.m_fontName.isEmpty()) {
fontSpec.m_mathFontName=fontSpec.m_fontName;
} else if (!fontSpec.m_mathFontName.isEmpty() && fontSpec.m_fontName.isEmpty()) {
fontSpec.m_fontName=fontSpec.m_mathFontName;
}
}
return fontSpec;
}
QString JKQTMathTextFontEncoding2String(JKQTMathTextFontEncoding e)
{
switch(e) {
case MTFEunicode: return "MTFEunicode";
case MTFEStandard: return "MTFEStandard";
case MTFEunicodeLimited: return "MTFEunicodeLimited";
case MTFEwinSymbol: return "MTFEwinSymbol";
}
return "???";
}
JKQTMathTextEnvironment::JKQTMathTextEnvironment() {
color=QColor("black");
font=MTEroman;
fontSize=10;
bold=false;
italic=false;
smallCaps=false;
underlined=false;
overline=false;
strike=false;
insideMath=false;
}
QFont JKQTMathTextEnvironment::getFont(JKQTMathText* parent) const {
QFont f;
switch (font) {
case MTEsans: if (insideMath) {
f.setFamily(parent->getFontMathSans());
} else {
f.setFamily(parent->getFontSans());
}
break;
case MTEmathSans: f.setFamily(parent->getFontMathSans()); break;
case MTEtypewriter: f.setFamily(parent->getFontTypewriter()); break;
case MTEscript: f.setFamily(parent->getFontScript()); break;
case MTEcaligraphic: f.setFamily(parent->getFontCaligraphic()); break;
case MTEblackboard: f.setFamily(parent->getFontBlackboard()); break;
case MTEfraktur: f.setFamily(parent->getFontFraktur()); break;
case MTEmathRoman: f.setFamily(parent->getFontMathRoman()); break;
default:
case MTEroman: if (insideMath) {
f.setFamily(parent->getFontMathRoman());
} else {
f.setFamily(parent->getFontRoman());
}
break;
}
f.setBold(bold);
f.setItalic(italic);
f.setUnderline(underlined);
f.setOverline(overline);
f.setStrikeOut(strike);
f.setCapitalization(QFont::MixedCase);
if (smallCaps) f.setCapitalization(QFont::SmallCaps);
f.setPointSizeF(fontSize);
f.setStyleStrategy(QFont::NoFontMerging);
return f;
}
QString JKQTMathTextEnvironment::toHtmlStart(JKQTMathTextEnvironment defaultEv) const {
QString s;
s=s+"font-size: "+QLocale::c().toString(fontSize)+"pt; ";
if (insideMath) {
if (defaultEv.italic) {
if (!italic) s=s+"font-style: italic; ";
if (italic) s=s+"font-style: normal; ";
} else {
if (!italic) s=s+"font-style: italic; ";
}
} else {
if (!defaultEv.italic && italic) s=s+"font-style: italic; ";
}
if (bold && !defaultEv.bold) s=s+"font-weight: bold";
QStringList td;
if (underlined && !defaultEv.underlined) td<<"underline";
if (overline && !defaultEv.overline) td<<"overline";
if (strike && !defaultEv.strike) td<<"line-through";
if (td.size()>0) s=s+"text-decoration: "+td.join(", ");
return "<span style=\""+s+"\">";
}
QString JKQTMathTextEnvironment::toHtmlAfter(JKQTMathTextEnvironment /*defaultEv*/) const {
return "</span>";
}
JKQTMathTextNodeSize::JKQTMathTextNodeSize():
width(0),
baselineHeight(0),
overallHeight(0),
strikeoutPos()
{
}
JKQTMathTextFontDefinition::JKQTMathTextFontDefinition():
fontName("Times New Roman"), fontEncoding(MTFEStandard),
symbolfontGreek("Symbol"), symbolfontGreekEncoding(MTFEwinSymbol),
symbolfontSymbol("Symbol"), symbolfontSymbolEncoding(MTFEwinSymbol)
{
}
QString JKQTMathTextFracModeToString(JKQTMathTextFracMode mode)
{
switch(mode) {
case MTFMfrac:
return "frac";
case MTFMdfrac:
return "dfrac";
case MTFMsfrac:
return "sfrac";
case MTFMstfrac:
return "stfrac";
case MTFMtfrac:
return "tfrac";
case MTFMunderbrace:
return "underbrace";
case MTFMoverbrace:
return "overbrace";
case MTFMunderset:
return "underset";
case MTFMoverset:
return "overset";
case MTFMstackrel:
return "stackrel";
}
return "unknown";
}
QString JKQTMathTextDecorationToString(JKQTMathTextDecoration mode)
{
switch(mode) {
case MTDvec:
return "vec";
case MTDtilde:
return "tilde";
case MTDbreve:
return "breve";
case MTDwidetilde:
return "widetilde";
case MTDhat:
return "hat";
case MTDwidehat:
return "widehat";
case MTDcheck:
return "check";
case MTDwidecheck:
return "widecheck";
case MTDocirc:
return "ocirc";
case MTDdot:
return "dot";
case MTDddot:
return "ddot";
case MTDbar:
return "bar";
case MTDarrow:
return "arrow";
case MTDoverline:
return "overline";
case MTDdoubleoverline:
return "double overline";
case MTDunderline:
return "underline";
case MTDdoubleunderline:
return "double underline";
case MTDcancel:
return "cancel";
case MTDbcancel:
return "bcancel";
case MTDxcancel:
return "xcancel";
case MTDstrike:
return "strike";
}
return "unknown";
}
QPainterPath JKQTMathTextMakeDArrow(double x, double y, double width, double arrowW, bool left, bool right) {
double x1=x;
double x2=x+width;
double dx=arrowW/4.0;
double y1=y-dx;
double y2=y+dx;
double x3=x2-arrowW/2.0;
double y3u=y-arrowW/2.0;
double y3d=y+arrowW/2.0;
double x3l=x+arrowW/2.0;
QPainterPath path;
path.moveTo(x1+dx, y1);
path.lineTo(x2-dx, y1);
path.moveTo(x1+dx, y2);
path.lineTo(x2-dx, y2);
if (right) {
path.moveTo(x3, y3u);
path.lineTo(x2, y);
path.lineTo(x3, y3d);
}
if (left) {
path.moveTo(x3l, y3u);
path.lineTo(x1, y);
path.lineTo(x3l, y3d);
}
return path;
}
QPainterPath JKQTMathTextMakeArrow(double x, double y, double width, double arrowW, bool left, bool right) {
double x1=x;
double x2=x+width;
double x3=x2-arrowW/2.0;
double y3u=y-arrowW/2.0;
double y3d=y+arrowW/2.0;
double x3l=x+arrowW/2.0;
QPainterPath path;
path.moveTo(x1, y);
path.lineTo(x2, y);
if (right) {
path.moveTo(x3, y3u);
path.lineTo(x2, y);
path.lineTo(x3, y3d);
}
if (left) {
path.moveTo(x3l, y3u);
path.lineTo(x1, y);
path.lineTo(x3l, y3d);
}
return path;
}
QPainterPath JKQTMathTextMakeHBracePath(double x, double ybrace, double width, double bw, double cubicshrink, double cubiccontrolfac) {
double xl1=x-(width)*cubicshrink+bw*cubicshrink;
double xr2=x+(width)*cubicshrink-bw*cubicshrink;
double xl2=x-bw*cubicshrink;
double xr1=x+bw*cubicshrink;
QPainterPath path;
path.moveTo(xl1-bw*cubicshrink, ybrace-bw*cubicshrink);
path.cubicTo(xl1-bw*cubicshrink, ybrace-bw*cubicshrink+bw*cubiccontrolfac, xl1-bw*cubiccontrolfac, ybrace, xl1, ybrace);
path.lineTo(xl2, ybrace);
path.cubicTo(xl2+bw*cubiccontrolfac, ybrace, (xl2+xr1)/2.0, ybrace+bw*cubicshrink-bw*cubiccontrolfac, (xl2+xr1)/2.0, ybrace+bw*cubicshrink);
path.cubicTo((xl2+xr1)/2.0, ybrace+bw*cubicshrink-bw*cubiccontrolfac, xr1-bw*cubiccontrolfac, ybrace, xr1, ybrace);
path.lineTo(xr2, ybrace);
path.cubicTo(xr2+bw*cubiccontrolfac, ybrace, xr2+bw*cubicshrink, ybrace-bw*cubicshrink+bw*cubiccontrolfac, xr2+bw*cubicshrink, ybrace-bw*cubicshrink);
return path;
}
JKQTMathTextTBRData::JKQTMathTextTBRData(const QFont &f, const QString &text, QPaintDevice *pd):
fm(f, pd)
{
this->text=text;
this->tbr=this->fm.tightBoundingRect(text);
this->f=f;
//this->pd=pd;
if (pd) {
ldpiX=pd->logicalDpiX();
ldpiY=pd->logicalDpiY();
pdpiX=pd->physicalDpiX();
pdpiY=pd->physicalDpiY();
} else {
ldpiX=0;
ldpiY=0;
pdpiX=0;
pdpiY=0;
}
}
bool JKQTMathTextTBRData::operator==(const JKQTMathTextTBRData &other) const
{
return ldpiX==other.ldpiX && ldpiY==other.ldpiY && text==other.text && f==other.f;
}
JKQTMathTextTBRDataH::JKQTMathTextTBRDataH(const QFont &f, const QString &text, QPaintDevice *pd)
{
this->text=text;
this->f=f;
if (pd) {
ldpiX=pd->logicalDpiX();
ldpiY=pd->logicalDpiY();
pdpiX=pd->physicalDpiX();
pdpiY=pd->physicalDpiY();
} else {
ldpiX=0;
ldpiY=0;
pdpiX=0;
pdpiY=0;
}
}
bool JKQTMathTextTBRDataH::operator==(const JKQTMathTextTBRDataH &other) const
{
return ldpiX==other.ldpiX && ldpiY==other.ldpiY && text==other.text && f==other.f;
}
QRectF JKQTMathTextGetTightBoundingRect(const QFont &fm, const QString &text, QPaintDevice *pd)
{
static QList<JKQTMathTextTBRData> JKQTMathText_tbrs=QList<JKQTMathTextTBRData>();
static QHash<JKQTMathTextTBRDataH, QRectF> JKQTMathText_tbrh=QHash<JKQTMathTextTBRDataH, QRectF>();
JKQTMathTextTBRDataH dh(fm, text, pd);
if (pd) {
if (JKQTMathText_tbrh.contains(dh)) return JKQTMathText_tbrh[dh];
/*for (int i=0; i<tbrs.size(); i++) {
if (tbrs[i].f==fm && tbrs[i].text==text && (tbrs[i].ldpiX==pd->logicalDpiX() && tbrs[i].ldpiY==pd->logicalDpiY() && tbrs[i].pdpiX==pd->physicalDpiX() && tbrs[i].pdpiY==pd->physicalDpiY())) {
//qDebug()<<" ### "<<fm<<pd<<tbrs[i].text<<tbrs[i].tbr;
return tbrs[i].tbr;
}
}*/
} else {
//qDebug()<<"warning no pd";
}
JKQTMathTextTBRData d(fm, text, pd);
JKQTMathText_tbrs.append(d);
JKQTMathText_tbrh[dh]=d.tbr;
//qDebug()<<"TBRs lits: "<<tbrs.size();
//qDebug()<<"+++ "<<fm<<pd<<d.text<<d.tbr;
return d.tbr;
}
QFont JKQTMathTextGetNonItalic(const QFont &font)
{
QFont f=font;
f.setItalic(false);
return f;
}

View File

@ -0,0 +1,358 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Name: jkqtmathtext.h
Copyright: (c) 2010-2019
Author: Jan krieger <jan@jkrieger.de>, http://www.jkrieger.de/
*/
#ifndef JKQTMATHTEXTTOOLS_H
#define JKQTMATHTEXTTOOLS_H
#include <QObject>
#include <QSettings>
#include <QPainter>
#include <QString>
#include <QSet>
#include <QFile>
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include <QWidget>
#include <QLabel>
#include <QHash>
#include <QPainterPath>
class JKQTMathText; // forward
/** \brief initialized Qt-ressources necessary for JKQTMathText
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT void initJKQTMathTextResources();
/*! \brief represents a font specifier for JKQTMathText. The font consists of two parts: the actual font and the font used for math output (which may be empty)
\ingroup jkqtmathtext
\section JKQTMathTextFontSpecifier_specialNames Special FOnt Names
This object also implements replacing special font names with actual fonts. Supported special font names are:
- \c default / \c app / \c application - the applications default font
- \c times / \c serif - a general serif font
- \c sans-serif - a general sans-serif font
- \c typewriter - a general typewrter/monospaced font
- \c cursive
- \c decorative
- \c fantasy
- \c monospace
- \c system
.
If copiled with Qt>5.3 you can also use these:
- \c fixed
- \c smallest_readable
- \c title
- \c general
.
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontSpecifier {
JKQTMathTextFontSpecifier();
JKQTMathTextFontSpecifier(const QString& fontName, const QString& mathFontName);
/** \brief construct a JKQTMathTextFontSpecifier, by parsing a \a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
static JKQTMathTextFontSpecifier fromFontSpec(const QString& fontSpec);
/** \brief initialises the object with values from parsing a \a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
void setFontSpec(const QString& fontSpec);
/** \brief returns the object's constents as a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
QString getFontSpec() const;
/** \copydoc m_fontName */
QString fontName() const;
/** \copydoc m_mathFontName */
QString mathFontName() const;
/** \copydoc m_fontName */
void setFontName(const QString& name);
/** \copydoc m_mathFontName */
void setmathFontName(const QString& name);
/** \brief finds actual fonts for some predefined special font names, as listed in \ref JKQTMathTextFontSpecifier_specialNames */
static QString transformFontName(const QString& fontName);
/** \brief same as transformFontName(), but also finds the actual name for XITS, STIX, ASANA,... */
static QString transformFontNameAndDecodeSpecialFonts(const QString& fontName);
/** \brief leiefert \c true, wenn ein fontName() verfügbar ist */
bool hasFontName() const;
/** \brief leiefert \c true, wenn ein mathFontName() verfügbar ist */
bool hasMathFontName() const;
/** \brief initialize with the font-families from the XITS package for text and math */
static JKQTMathTextFontSpecifier getXITSFamilies();
/** \brief initialize with the font-families from the XITS package for text and math */
static JKQTMathTextFontSpecifier getASANAFamilies();
/** \brief initialize with the font-families from the STIX package for text and math */
static JKQTMathTextFontSpecifier getSTIXFamilies();
private:
/** \brief specifies the main font name */
QString m_fontName;
/** \brief specifies the math font to use in addition to fontName */
QString m_mathFontName;
};
/** \brief used to specify the font encoding used for drawing
* \ingroup jkqtmathtext
*/
enum JKQTMathTextFontEncoding {
MTFEwinSymbol, /*!< \brief This assumes that symbols shall be taken from a MS Windows style Symbol font */
MTFEunicode, /*!< \brief This assumes that symbols shall be taken from a Unicode font (e.g. the STIX fonts from <a href="http://www.stixfonts.org/">http://www.stixfonts.org/</a>)*/
MTFEunicodeLimited, /*!< \brief This assumes that the fonts used are Unicode, but only offer a limited set of symbols. Especially math symbols are missing from this encoding */
MTFEStandard, /*!< \brief the encoding of a standard TTF font (i.e. we can only expect letters,number and not many special characters) */
};
/** \brief convert MTfontEncoding to a string
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextFontEncoding2String(JKQTMathTextFontEncoding e);
/** \brief the available logical fonts (default is MTEroman)
* \ingroup jkqtmathtext
*/
enum JKQTMathTextEnvironmentFont {
MTEroman, /*!< \brief roman font, e.g. <code>\\rm{}</code> */
MTEsans, /*!< \brief sans-serif font, e.g. <code>\\sf{}</code> */
MTEmathRoman, /*!< \brief math-mode roman font, e.g. <code>\\mathrm{}</code> */
MTEmathSans, /*!< \brief math-mode sans-serif font, e.g. <code>\\mathsf{}</code> */
MTEtypewriter, /*!< \brief typewriter font, e.g. <code>\\tt{},\\mathtt{}</code> */
MTEscript, /*!< \brief script font, e.g. <code>\\script{},\\mathscript{}</code> */
MTEblackboard, /*!< \brief blackboard font, e.g. <code>\\mathbb{}</code> */
MTEcaligraphic, /*!< \brief caligraphic font, e.g. <code>\\mathcal{}</code> */
MTEfraktur, /*!< \brief fraktur font, e.g. <code>\\mathfrak{}</code> */
MTenvironmentFontCount /*!< \brief internal enum value that allows to iterate over MTenvironmentFont \internal */
};
/** \brief describes the current drawing environment (base fontname ...)
* \ingroup jkqtmathtext
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextEnvironment {
JKQTMathTextEnvironment();
/** \brief current font color */
QColor color;
/** \brief current font */
JKQTMathTextEnvironmentFont font;
/** \brief current font size [pt] */
double fontSize;
/** \brief is the text currently bold? */
bool bold;
/** \brief is the text currently italic? */
bool italic;
/** \brief is the text currently in small caps? */
bool smallCaps;
/** \brief is the text currently underlined? */
bool underlined;
/** \brief is the text currently overlined? */
bool overline;
/** \brief is the text currently stroke through? */
bool strike;
/** \brief is the text currently are we inside a math environment? */
bool insideMath;
/** \brief build a QFont object from the settings in this object */
QFont getFont(JKQTMathText* parent) const;
/** \brief generate a HTML prefix that formats the text after it according to the settings in this object
*
* \param defaultEv environment before applying the current object (to detect changes)
* \see toHtmlAfter()
*/
QString toHtmlStart(JKQTMathTextEnvironment defaultEv) const;
/** \brief generate a HTML postfix that formats the text in front of it according to the settings in this object
*
* \param defaultEv environment before applying the current object (to detect changes)
* \see toHtmlAfter()
*/
QString toHtmlAfter(JKQTMathTextEnvironment defaultEv) const;
};
/** \brief beschreibt die Größe eines Knotens
* \ingroup jkqtmathtext
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNodeSize {
JKQTMathTextNodeSize();
double width;
double baselineHeight;
double overallHeight;
double strikeoutPos;
};
/** \brief summarizes all information available on a font for a specific MTenvironmentFont
* \ingroup jkqtmathtext
* \see fontDefinitions
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontDefinition {
JKQTMathTextFontDefinition();
/** \brief name of the font */
QString fontName;
/** \brief specifies the encoding of the font (default is \c MTFEwinSymbol ) */
JKQTMathTextFontEncoding fontEncoding;
/** \brief symbol font used for greek symbols, or empty when \a fontName shall be used */
QString symbolfontGreek;
/** \brief specifies the encoding of symbolfontGreek */
JKQTMathTextFontEncoding symbolfontGreekEncoding;
/** \brief symbol font, used for math symbols, or empty when \a fontName shall be used */
QString symbolfontSymbol;
/** \brief specifies the encoding of symbolfontSymbol */
JKQTMathTextFontEncoding symbolfontSymbolEncoding;
};
/** \brief type of ffractions represented by JKQTMathTextFracNode
* \ingroup jkqtmathtext
* \see JKQTMathTextFracNode, JKQTMathTextFracModeToString()
*/
enum JKQTMathTextFracMode {
MTFMfrac, /*!< \brief normal fraction \image html mathparser/MTFMfrac.png */
MTFMdfrac, /*!< \brief normal fraction, without scaling of under/over text \image html mathparser/MTFMdfrac.png */
MTFMtfrac, /*!< \brief text fraction (smaller than MTFMfrac) \image html mathparser/MTFMtfrac.png */
MTFMsfrac, /*!< \brief slanted fraction \image html mathparser/MTFMsfrac.png */
MTFMstfrac, /*!< \brief slanted text fraction \image html mathparser/MTFMstfrac.png */
MTFMunderbrace, /*!< \brief curly underbrace \image html mathparser/MTFMunderbrace.png */
MTFMoverbrace, /*!< \brief curly overbrace \image html mathparser/MTFMoverbrace.png */
MTFMstackrel, /*!< \brief binom/fraction without line \image html mathparser/MTFMstackrel.png */
MTFMunderset, /*!< \brief underset text \image html mathparser/MTFMunderset.png */
MTFMoverset /*!< \brief overset text \image html mathparser/MTFMoverset.png */
};
/** \brief convert a JKQTMathTextFracMode into a QString
* \ingroup jkqtmathtext
* \see JKQTMathTextFracMode
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextFracModeToString(JKQTMathTextFracMode mode);
/** \brief types of decoration available in a JKQTMathTextDecoratedNode
* \ingroup jkqtmathtext
*/
enum JKQTMathTextDecoration {
MTDvec, /*!< \brief vector arrow over block \image html mathparser/MTDvec.png */
MTDhat, /*!< \brief small hat over block \image html mathparser/MTDhat.png */
MTDwidehat, /*!< \brief full-width hat over block \image html mathparser/MTDwidehat.png */
MTDcheck, /*!< \brief small v over block \image html mathparser/MTDcheck.png */
MTDwidecheck, /*!< \brief full-width v over block \image html mathparser/MTDwidecheck.png */
MTDbreve, /*!< \brief small tilde over block \image html mathparser/MTDbreve.png */
MTDocirc, /*!< \brief single circle over block \image html mathparser/MTDocirc.png */
MTDdot, /*!< \brief single dot over block \image html mathparser/MTDvec.png */
MTDddot, /*!< \brief double dot over block \image html mathparser/MTDddot.png */
MTDbar, /*!< \brief bar over block \image html mathparser/MTDbar.png */
MTDarrow, /*!< \brief arrow over block \image html mathparser/MTDarrow.png */
MTDoverline, /*!< \brief overline over block \image html mathparser/MTDoverline.png */
MTDdoubleoverline, /*!< \brief double overline over block \image html mathparser/MTDdoubleoverline.png */
MTDunderline, /*!< \brief underline under block \image html mathparser/MTDunderline.png */
MTDdoubleunderline, /*!< \brief double underline under block \image html mathparser/MTDdoubleunderline.png */
MTDtilde, /*!< \brief small tilde over block \image html mathparser/MTDtilde.png */
MTDwidetilde, /*!< \brief full width tilde over block \image html mathparser/MTDwidetilde.png */
MTDcancel, /*!< \brief cancel text with sloped line \image html mathparser/MTDcancel.png */
MTDbcancel, /*!< \brief cancel text with backward sloped line \image html mathparser/MTDbcancel.png */
MTDxcancel, /*!< \brief cancel text with X \image html mathparser/MTDxcancel.png */
MTDstrike /*!< \brief strikethrough text \image html mathparser/MTDstrike.png */
};
/** \brief convert a JKQTMathTextDecoration into a string
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextDecorationToString(JKQTMathTextDecoration mode);
/** \brief create a QPainterPath for drawing horizontal braces
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeHBracePath(double x, double ybrace, double width, double bw, double cubicshrink=0.5, double cubiccontrolfac=0.3);
/** \brief create a QPainterPath for drawing horizontal arrows
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeArrow(double x, double y, double width, double arrowW, bool left=false, bool right=true);
/** \brief create a QPainterPath for drawing horizontal double arrows
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeDArrow(double x, double y, double width, double arrowW, bool left=false, bool right=true);
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTBRData {
explicit JKQTMathTextTBRData(const QFont& f, const QString& text, QPaintDevice *pd);
QFontMetricsF fm;
QString text;
QRectF tbr;
QFont f;
int ldpiX, ldpiY, pdpiX, pdpiY;
//QPaintDevice *pd;
bool operator==(const JKQTMathTextTBRData& other) const;
};
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTBRDataH {
explicit JKQTMathTextTBRDataH(const QFont& f, const QString& text, QPaintDevice *pd);
QString text;
QFont f;
int ldpiX, ldpiY, pdpiX, pdpiY;
bool operator==(const JKQTMathTextTBRDataH& other) const;
};
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
inline size_t qHash(const JKQTMathTextTBRDataH& data, size_t /*seed=0*/) {
#else
inline uint qHash(const JKQTMathTextTBRDataH& data) {
#endif
return qHash(data.f.family())+qHash(data.text);
}
/** \brief calculates the tight bounding rectangle around \a text, uses internal hashing to not redo a calculation that has already been performed
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT QRectF JKQTMathTextGetTightBoundingRect(const QFont &fm, const QString& text, QPaintDevice *pd);
/** \brief returns a copy of \a f, but with the italic-property set to \c false
* \ingroup jkqtmathtext
*/
JKQTMATHTEXT_LIB_EXPORT QFont JKQTMathTextGetNonItalic(const QFont& f);
#endif // JKQTMATHTEXTTOOLS_H

View File

@ -0,0 +1,297 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextbracenode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
#include <QPainterPath>
JKQTMathTextBraceNode::JKQTMathTextBraceNode(JKQTMathText* _parent, const QString& openbrace, const QString& closebrace, JKQTMathTextNode* child, bool showRightBrace):
JKQTMathTextNode(_parent)
{
this->child=child;
this->openbrace=openbrace;
this->closebrace=closebrace;
this->showRightBrace=showRightBrace;
}
JKQTMathTextBraceNode::~JKQTMathTextBraceNode() {
if (child!=nullptr) delete child;
}
void JKQTMathTextBraceNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
JKQTMathTextEnvironment ev=currentEv;
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
double bracewidth=0, braceheight=0;
getBraceWidth(painter, ev, baselineHeight, overallHeight, bracewidth, braceheight);
bracewidth=bracewidth/parent->getBraceShrinkFactor();
baselineHeight=/*qMin(baselineHeight, braceheight)*/ baselineHeight*parent->getBraceFactor();
overallHeight=qMax(overallHeight, braceheight)*parent->getBraceFactor(); //fm.height();
width=width+bracewidth*2.0;
}
double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
//std::cout<<"drawing brace-node: '"<<openbrace.toStdString()<<"' ... '"<<closebrace.toStdString()<<"'\n";
doDrawBoxes(painter, x, y, currentEv);
JKQTMathTextEnvironment ev=currentEv;
double width=0;
double baselineHeight=0;
double overallHeight=0, strikeoutPos=0;
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
double bracewidth=0, braceheight=0;
getBraceWidth(painter, ev, baselineHeight, overallHeight, bracewidth, braceheight);
double cWidth=0;
double cBaselineHeight=0;
double cOverallHeight=0, cstrikeoutPos=0;
getSize(painter, currentEv, cWidth, cBaselineHeight, cOverallHeight, cstrikeoutPos);
double lw=qMax(0.25,ceil(currentEv.fontSize/16.0));//fm.lineWidth();
double xnew=x+lw;
QPen pold=painter.pen();
QPen p=pold;
p.setWidthF(lw);
p.setColor(currentEv.color);
painter.setPen(p);
double brace_fraction=0.85;
if (openbrace=="(") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+brace_fraction*bracewidth, y1);
path.cubicTo(xnew, (y1+y2)/2.0+fabs(y1-y2)/6.0, xnew, (y1+y2)/2.0-fabs(y1-y2)/6.0 , xnew+brace_fraction*bracewidth, y2);
painter.drawPath(path);
} else if (openbrace=="[") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+brace_fraction*bracewidth, y1);
path.lineTo(xnew+lw/2.0, y1);
path.lineTo(xnew+lw/2.0, y2);
path.lineTo(xnew+brace_fraction*bracewidth, y2);
painter.drawPath(path);
} else if (openbrace=="{") {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,cOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.translate(xnew+bracewidth*(1.0-brace_fraction), y-cBaselineHeight+cOverallHeight/2.0);
painter.rotate(90);
painter.drawPath(path);
} else if (openbrace=="_") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+brace_fraction*bracewidth, y1);
path.lineTo(xnew, y1);
path.lineTo(xnew, y2);
painter.drawPath(path);
} else if (openbrace=="~") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew, y1);
path.lineTo(xnew, y2);
path.lineTo(xnew+brace_fraction*bracewidth, y2);
painter.drawPath(path);
} else if (openbrace=="|") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
QLineF l(xnew+brace_fraction*bracewidth, y1, xnew+brace_fraction*bracewidth, y2);
if (l.length()>0) painter.drawLine(l);
painter.drawPath(path);
} else if (openbrace=="#" || openbrace=="||") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
QLineF l(xnew+brace_fraction*bracewidth, y1, xnew+brace_fraction*bracewidth, y2);
if (l.length()>0) painter.drawLine(l);
l=QLineF(xnew+brace_fraction*bracewidth-1.5*lw, y1, xnew+brace_fraction*bracewidth-1.5*lw, y2);
if (l.length()>0) painter.drawLine(l);
} else if (openbrace=="<") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+brace_fraction*bracewidth, y1);
path.lineTo(xnew, (y2+y1)/2.0);
path.lineTo(xnew+brace_fraction*bracewidth, y2);
painter.drawPath(path);
}
painter.setPen(pold);
xnew= child->draw(painter, xnew+bracewidth/parent->getBraceShrinkFactor()-lw, y, currentEv)+lw;
if (showRightBrace) {
painter.setPen(p);
if (closebrace==")") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+(1.0-brace_fraction)*bracewidth, y1);
path.cubicTo(xnew+bracewidth, (y1+y2)/2.0+fabs(y1-y2)/6.0, xnew+bracewidth, (y1+y2)/2.0-fabs(y1-y2)/6.0 , xnew+(1.0-brace_fraction)*bracewidth, y2);
painter.drawPath(path);
} else if (closebrace=="]") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+(1.0-brace_fraction)*bracewidth, y1);
path.lineTo(xnew+bracewidth-lw/2.0, y1);
path.lineTo(xnew+bracewidth-lw/2.0, y2);
path.lineTo(xnew+(1.0-brace_fraction)*bracewidth, y2);
painter.drawPath(path);
} else if (closebrace=="}") {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,cOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.translate(xnew+bracewidth*brace_fraction, y-cBaselineHeight+cOverallHeight/2.0);
painter.rotate(270);
painter.drawPath(path);
} else if (closebrace=="_") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+(1.0-brace_fraction)*bracewidth, y1);
path.lineTo(xnew+bracewidth, y1);
path.lineTo(xnew+bracewidth, y2);
painter.drawPath(path);
} else if (closebrace=="~") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+bracewidth, y1);
path.lineTo(xnew+bracewidth, y2);
path.lineTo(xnew+(1.0-brace_fraction)*bracewidth, y2);
painter.drawPath(path);
} else if (closebrace=="|") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
QLineF l(xnew+(1.0-brace_fraction)*bracewidth, y1, xnew+(1.0-brace_fraction)*bracewidth, y2);
if (l.length()>0) painter.drawLine(l);
painter.drawPath(path);
} else if (closebrace=="#" || closebrace=="||") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
QLineF l(xnew+(1.0-brace_fraction)*bracewidth, y1, xnew+(1.0-brace_fraction)*bracewidth, y2);
if (l.length()>0) painter.drawLine(l);
l=QLineF(xnew+(1.0-brace_fraction)*bracewidth+1.5*lw, y1, xnew+(1.0-brace_fraction)*bracewidth+1.5*lw, y2);
if (l.length()>0) painter.drawLine(l);
} else if (closebrace==">") {
QPainterPath path;
double y1=y+(cOverallHeight-cBaselineHeight);
double y2=y-cBaselineHeight;
path.moveTo(xnew+(1.0-brace_fraction)*bracewidth, y1);
path.lineTo(xnew+bracewidth, (y2+y1)/2.0);
path.lineTo(xnew+(1.0-brace_fraction)*bracewidth, y2);
painter.drawPath(path);
}
painter.setPen(pold);
}
//qDebug()<<" ==> "<<bc<<fm.boundingRect(bc).width();
return xnew+bracewidth/parent->getBraceShrinkFactor()-lw;
}
bool JKQTMathTextBraceNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
QString ob=openbrace;
QString cb=closebrace;
if (ob=="<") ob="&lang;";
else if (ob=="_") ob="&lfloor;";
else if (ob=="~") ob="&lceil;";
else if (ob=="||" || ob=="#") ob="||";
if (cb=="<") cb="&rang;";
else if (cb=="_") cb="&rfloor;";
else if (cb=="~") cb="&rceil;";
else if (cb=="||" || cb=="#") cb="||";
html=html+ob;
bool ok=child->toHtml(html, currentEv, defaultEv);
html=html+cb;
return ok;
}
void JKQTMathTextBraceNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
child->setDrawBoxes(draw);
}
QString JKQTMathTextBraceNode::getTypeName() const
{
return QLatin1String("MTbraceNode(")+openbrace+" "+closebrace+")";
}
void JKQTMathTextBraceNode::getBraceWidth(QPainter &/*painter*/, JKQTMathTextEnvironment ev, double /*baselineHeight*/, double overallHeight, double &bracewidth, double &braceheight)
{
/*QFont evf=ev.getFont(parent);
if (ev.insideMath) evf.setItalic(false);
ev.italic=false;
while (ev.fontSize<10*parent->getFontSize()) {
const QFontMetricsF fme(evf, painter.device());
if (fme.ascent()>overallHeight) break;
ev.fontSize+=0.5;
evf.setPointSizeF(ev.fontSize);
}
ev.fontSize=ev.fontSize*parent->getBraceFactor();
evf.setPointSizeF(ev.fontSize);
QFontMetricsF fm(evf, painter.device());
QString bc="_X";
bracewidth=fm.width("I")*parent->getBraceShrinkFactor();
braceheight=parent->getTBR(evf, bc, painter.device()).height();*/
double lw=qMax(0.25,ceil(ev.fontSize/12.0));
braceheight=overallHeight*parent->getBraceFactor();
bracewidth=0.6*pow(braceheight, 0.6);
if (openbrace=="{" || closebrace=="}") bracewidth=qMax(bracewidth, lw*3.5);
}

View File

@ -0,0 +1,86 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTBRACENODE_H
#define JKQTMATHTEXTBRACENODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing a brace node
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceNode: public JKQTMathTextNode {
public:
JKQTMathTextBraceNode(JKQTMathText* parent, const QString& openbrace, const QString& closebrace, JKQTMathTextNode* child, bool showRightBrace=true);
virtual ~JKQTMathTextBraceNode() override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \brief returns the child node */
inline JKQTMathTextNode* getChild() const {
return this->child;
}
/** \copydoc openbrace */
inline QString getOpenbrace() const {
return this->openbrace;
}
/** \copydoc closebrace */
inline QString getClosebrace() const {
return this->closebrace;
}
/** \copydoc showRightBrace */
inline bool getShowRightBrace() const {
return this->showRightBrace;
}
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
JKQTMathTextNode* child;
QString openbrace;
QString closebrace;
bool showRightBrace;
void getBraceWidth(QPainter& painter, JKQTMathTextEnvironment currentEv, double baselineHeight, double overallHeight, double& bracewidth, double& braceheight);
};
#endif // JKQTMATHTEXTBRACENODE_H

View File

@ -0,0 +1,302 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextdecoratednode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextDecoratedNode::JKQTMathTextDecoratedNode(JKQTMathText* _parent, JKQTMathTextDecoration decoration, JKQTMathTextNode* child):
JKQTMathTextNode(_parent)
{
this->child=child;
this->decoration=decoration;
}
JKQTMathTextDecoratedNode::~JKQTMathTextDecoratedNode() {
if (child!=nullptr) delete child;
}
void JKQTMathTextDecoratedNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
const QFontMetricsF fm(currentEv.getFont(parent), painter.device());
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
const double italic_xcorrection=getNonItalicXCorretion(painter, width, currentEv, child);
const double decoheightfactor=parent->getDecorationHeightFactor();
const double deco_miniwidth=((decoration==MTDtilde||decoration==MTDbreve)?fm.boundingRect("~").width():fm.boundingRect("^").width())-italic_xcorrection;
const double decoAboveAscent_yposdelta=fm.ascent()*(1.0+2.0*decoheightfactor);
const double decoAboveBaselineheight_yposdelta=baselineHeight*(1.0+decoheightfactor);
const double descent=overallHeight-baselineHeight;
baselineHeight=decoAboveBaselineheight_yposdelta;
if (decoration==MTDbar) {
baselineHeight=std::max<double>(baselineHeight, decoAboveAscent_yposdelta);
}
overallHeight=baselineHeight+descent;
width=std::max<double>(deco_miniwidth,width);
}
double JKQTMathTextDecoratedNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
JKQTMathTextEnvironment ev=currentEv;
double width=0, baselineHeight=0, overallHeight=0, strikeoutPos=0;
child->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
const QFont font=ev.getFont(parent);
const QFontMetricsF fm(font, painter.device());
const double width_X=fm.boundingRect("X").width();
const double width_x=fm.boundingRect("x").width();
const double width_dot=fm.boundingRect(".").width()/2.0;
const double decoheightfactor=parent->getDecorationHeightFactor();
const double deco_ypos=y-baselineHeight*(1.0+decoheightfactor);
const double decoAboveAscent_ypos=y-fm.ascent()*(1.0+decoheightfactor);
const double strike_ypos=y-baselineHeight/2.0;
const double decobelow_ypos=y+qMax((overallHeight-baselineHeight)*(1.0+decoheightfactor), fm.xHeight()*decoheightfactor);
const double deco_height=decoheightfactor*baselineHeight;
const double italic_xcorrection=getNonItalicXCorretion(painter, width, ev, child);
const double deco_xoffset=parent->getDecorationWidthReductionXFactor()*width_X/2.0;
const double deco_width=std::max<double>(width_x*0.5,width-2.0*deco_xoffset-italic_xcorrection);
const double deco_vecwidth=width_x*0.33;
const double deco_miniwidth=((decoration==MTDtilde||decoration==MTDbreve)?fm.boundingRect("~").width():fm.boundingRect("^").width())-italic_xcorrection;
const double decotop_xcenter=x+italic_xcorrection+(width-italic_xcorrection)/2.0;
const double decotop_xstart=decotop_xcenter-deco_width/2.0;
const double decotop_xend=decotop_xcenter+deco_width/2.0;
const double decobot_xstart=x;
const double decobot_xend=x+width-italic_xcorrection;
const double decobot_xcenter=(decobot_xstart+decobot_xend)/2.0;
QPen pold=painter.pen();
QPen p=pold;
p.setColor(ev.color);
p.setWidthF(qMax(parent->ABS_MIN_LINEWIDTH, fm.lineWidth()));//ceil(currentEv.fontSize/16.0));
double xnew=child->draw(painter, x, y, ev);
if (decoration==MTDvec) {
painter.setPen(p);
QPolygonF poly;
poly<<QPointF(decotop_xstart, deco_ypos)<<QPointF(decotop_xend, deco_ypos)<<QPointF(decotop_xend-deco_vecwidth, deco_ypos-deco_height*2.0/3.0);
painter.drawPolyline(poly);
painter.setPen(pold);
} else if (decoration==MTDoverline) {
painter.setPen(p);
const QLineF l(decotop_xstart, deco_ypos, decotop_xend, deco_ypos);
if (l.length()>0) painter.drawLine(l);
painter.setPen(pold);
} else if (decoration==MTDbar) {
painter.setPen(p);
const QLineF l(decotop_xstart, decoAboveAscent_ypos, decotop_xend, decoAboveAscent_ypos);
if (l.length()>0) painter.drawLine(l);
painter.setPen(pold);
} else if (decoration==MTDdoubleoverline) {
painter.setPen(p);
const QLineF l(decotop_xstart, deco_ypos, decotop_xend, deco_ypos);
if (l.length()>0) painter.drawLine(l);
const QLineF l2(decotop_xstart, deco_ypos-2.0*p.widthF(), decotop_xend, deco_ypos-2.0*p.widthF());
if (l2.length()>0) painter.drawLine(l2);
painter.setPen(pold);
} else if (decoration==MTDunderline) {
painter.setPen(p);
const QLineF l(decobot_xstart, decobelow_ypos, decobot_xend, decobelow_ypos);
if (l.length()>0) painter.drawLine(l);
painter.setPen(pold);
} else if (decoration==MTDdoubleunderline) {
painter.setPen(p);
const QLineF l(decobot_xstart, decobelow_ypos, decobot_xend, decobelow_ypos);
if (l.length()>0) painter.drawLine(l);
QLineF l2(decobot_xstart, decobelow_ypos+2.0*p.widthF(), decobot_xend, decobelow_ypos+2.0*p.widthF());
if (l2.length()>0) painter.drawLine(l2);
painter.setPen(pold);
} else if (decoration==MTDarrow) {
painter.setPen(p);
const QLineF l(decotop_xstart, deco_ypos+deco_height/2.0, decotop_xend, deco_ypos+deco_height/2.0);
if (l.length()>0) painter.drawLine(l);
QPolygonF poly;
poly<<QPointF(decotop_xend-deco_vecwidth, deco_ypos)<<QPointF(decotop_xend, deco_ypos+deco_height/2.0)<<QPointF(decotop_xend-deco_vecwidth, deco_ypos+deco_height);
painter.drawPolyline(poly);
painter.setPen(pold);
} else if (decoration==MTDhat) {
painter.setPen(p);
QPolygonF poly;
poly<<QPointF(decotop_xcenter-0.5*deco_miniwidth, deco_ypos+deco_height/3.0)<<QPointF(decotop_xcenter, deco_ypos)<<QPointF(decotop_xcenter+0.5*deco_miniwidth, deco_ypos+deco_height/3.0);
painter.drawPolyline(poly);
painter.setPen(pold);
} else if (decoration==MTDwidehat) {
painter.setPen(p);
QPolygonF poly;
poly<<QPointF(decotop_xstart, deco_ypos+deco_height/2.0)<<QPointF(decotop_xcenter, deco_ypos+deco_height/3.0)<<QPointF(decotop_xend, deco_ypos+deco_height/2.0);
painter.drawPolyline(poly);
painter.setPen(pold);
} else if (decoration==MTDcheck) {
painter.setPen(p);
QPolygonF poly;
poly<<QPointF(decotop_xcenter-0.5*deco_miniwidth, deco_ypos)<<QPointF(decotop_xcenter, deco_ypos+deco_height/3.0)<<QPointF(decotop_xcenter+0.5*deco_miniwidth, deco_ypos);
painter.drawPolyline(poly);
painter.setPen(pold);
} else if (decoration==MTDwidecheck) {
painter.setPen(p);
QPolygonF poly;
poly<<QPointF(decotop_xstart, deco_ypos-deco_height/2.0)<<QPointF(decotop_xcenter, deco_ypos+deco_height/3.0)<<QPointF(decotop_xend, deco_ypos-deco_height/2.0);
painter.drawPolyline(poly);
painter.setPen(pold);
} else if (decoration==MTDbreve) {
painter.setPen(p);
QPainterPath path;
const double x0=decotop_xcenter-deco_miniwidth/2.0;
const double x1=decotop_xcenter+deco_miniwidth/2.0;
path.moveTo(x0, deco_ypos);
path.cubicTo(x0, deco_ypos+deco_height, x1, deco_ypos+deco_height , x1, deco_ypos);
painter.drawPath(path);
painter.setPen(pold);
} else if (decoration==MTDtilde) {
painter.setPen(p);
QPainterPath path;
const double x0=decotop_xcenter-deco_miniwidth/2.0;
const double x1=decotop_xcenter+deco_miniwidth/2.0;
path.moveTo(x0, deco_ypos);
path.cubicTo((x0+x1)/2.0, deco_ypos+deco_height, (x0+x1)/2.0, deco_ypos-deco_height , x1, deco_ypos);
painter.drawPath(path);
painter.setPen(pold);
} else if (decoration==MTDwidetilde) {
painter.setPen(p);
QPainterPath path;
const double x0=decotop_xstart;
const double x1=decotop_xend;
path.moveTo(x0, deco_ypos);
path.cubicTo((x0+x1)/2.0, deco_ypos+deco_height, (x0+x1)/2.0, deco_ypos-deco_height , x1, deco_ypos);
painter.drawPath(path);
painter.setPen(pold);
} else if (decoration==MTDocirc) {
painter.setPen(p);
const QBrush bold=painter.brush();
painter.setBrush(Qt::NoBrush);
painter.drawEllipse(QPointF(decotop_xcenter, deco_ypos), width_dot/1.5, width_dot/1.5);
painter.setBrush(bold);
painter.setPen(pold);
} else if (decoration==MTDdot) {
p.setWidthF(0.01);
painter.setPen(p);
QBrush b=painter.brush();
const QBrush bold=b;
b.setColor(ev.color);
b.setStyle(Qt::SolidPattern);
painter.setBrush(b);
painter.drawEllipse(QPointF(decotop_xcenter, deco_ypos), width_dot/2.0, width_dot/2.0);
painter.setBrush(bold);
painter.setPen(pold);
} else if (decoration==MTDddot) {
p.setWidthF(0.01);
painter.setPen(p);
QBrush b=painter.brush();
const QBrush bold=b;
b.setColor(ev.color);
b.setStyle(Qt::SolidPattern);
painter.setBrush(b);
painter.drawEllipse(QPointF(decotop_xcenter-width_dot, deco_ypos), width_dot/2.0, width_dot/2.0);
painter.drawEllipse(QPointF(decotop_xcenter+width_dot, deco_ypos), width_dot/2.0, width_dot/2.0);
painter.setBrush(bold);
painter.setPen(pold);
painter.setBrush(bold);
} else if (decoration==MTDstrike) {
painter.setPen(p);
const QLineF l((decotop_xstart+decobot_xstart)/2.0, strike_ypos, (decotop_xend+decobot_xend)/2.0, strike_ypos);
if (l.length()>0) painter.drawLine(l);
painter.setPen(pold);
} else if (decoration==MTDcancel) {
painter.setPen(p);
const QLineF l(decobot_xstart, decobelow_ypos, decotop_xend, deco_ypos);
if (l.length()>0) painter.drawLine(l);
painter.setPen(pold);
} else if (decoration==MTDbcancel) {
painter.setPen(p);
const QLineF l(decobot_xstart, deco_ypos, decotop_xend, decobelow_ypos);
if (l.length()>0) painter.drawLine(l);
painter.setPen(pold);
} else if (decoration==MTDxcancel) {
painter.setPen(p);
const QLineF l(decobot_xstart, deco_ypos, decotop_xend, decobelow_ypos);
if (l.length()>0) painter.drawLine(l);
const QLineF l1(decobot_xstart, decobelow_ypos, decotop_xend, deco_ypos);
if (l1.length()>0) painter.drawLine(l1);
painter.setPen(pold);
}
/*painter.setPen(QPen(Qt::red, 1.5));
painter.drawLine(QLineF(x, deco_ypos, xnew, deco_ypos));
painter.setPen(QPen(Qt::green, 1.5));
painter.drawLine(QLineF(deco_xstart, deco_ypos+2, deco_xend, deco_ypos+2));
painter.drawEllipse(QPointF(deco_xpos_center, deco_ypos+2), 5, 5);
painter.setPen(pold);*/
return xnew;
}
bool JKQTMathTextDecoratedNode::toHtml(QString &/*html*/, JKQTMathTextEnvironment /*currentEv*/, JKQTMathTextEnvironment /*defaultEv*/) {
//QString f;
//JKQTMathTextEnvironment ev=currentEv;
//bool ok=child->toHtml(html, ev, defaultEv);
return false;
}
void JKQTMathTextDecoratedNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
child->setDrawBoxes(draw);
}
QString JKQTMathTextDecoratedNode::getTypeName() const
{
return "MTdecoratedNode";
}
JKQTMathTextNode *JKQTMathTextDecoratedNode::getChild() const {
return this->child;
}
JKQTMathTextDecoration JKQTMathTextDecoratedNode::getDecoration() const {
return this->decoration;
}

View File

@ -0,0 +1,74 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTDECORATEDNODE_H
#define JKQTMATHTEXTDECORATEDNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing a decorated text m (e.g. \c \\vec \c \\hat ...) node
* \ingroup jkqtmathtext_items
*
* \image html mathparser/decoration_sizing.png
*
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextDecoratedNode: public JKQTMathTextNode {
public:
JKQTMathTextDecoratedNode(JKQTMathText* parent, JKQTMathTextDecoration decoration, JKQTMathTextNode* child);
virtual ~JKQTMathTextDecoratedNode() override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override ;
/** \brief returns the child node */
JKQTMathTextNode* getChild() const;
/** \copydoc decoration */
JKQTMathTextDecoration getDecoration() const;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \brief child node that is decorated by this node */
JKQTMathTextNode* child;
/** \brief type of decoration that is added to the child node */
JKQTMathTextDecoration decoration;
};
#endif // JKQTMATHTEXTDECORATEDNODE_H

View File

@ -0,0 +1,262 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextfracnode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextFracNode::JKQTMathTextFracNode(JKQTMathText* _parent, JKQTMathTextNode* child_top, JKQTMathTextNode* child_bottom, JKQTMathTextFracMode mode):
JKQTMathTextNode(_parent)
{
this->child1=child_top;
this->child2=child_bottom;
this->mode=mode;
}
JKQTMathTextFracNode::~JKQTMathTextFracNode() {
if (child1!=nullptr) delete child1;
if (child2!=nullptr) delete child2;
}
QString JKQTMathTextFracNode::getTypeName() const
{
return "MTfracNode";
}
void JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
QFontMetricsF fm(currentEv.getFont(parent), painter.device());
JKQTMathTextEnvironment ev1=currentEv;
JKQTMathTextEnvironment ev2=currentEv;
double xh=fm.xHeight(); //tightBoundingRect("x").height();
double sp=xh;
double Ah=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parent), "M", painter.device()).height();//fm.ascent();
double xw=fm.boundingRect("x").width();
if (mode==MTFMunderbrace || mode==MTFMoverbrace) {
ev2.fontSize=ev2.fontSize*parent->getUnderbraceFactor();
} else if (mode==MTFMunderset || mode==MTFMoverset) {
ev2.fontSize=ev2.fontSize*parent->getUndersetFactor();
} else if (mode==MTFMfrac || mode==MTFMsfrac) {
ev1.fontSize=ev1.fontSize*parent->getFracFactor();
ev2.fontSize=ev2.fontSize*parent->getFracFactor();
} else if (mode==MTFMtfrac || mode==MTFMstfrac) {
ev1.fontSize=ev1.fontSize*parent->getFracFactor()*0.7;
ev2.fontSize=ev2.fontSize*parent->getFracFactor()*0.7;
}
double width1=0, baselineHeight1=0, overallHeight1=0, strikeoutPos1=0;
double width2=0, baselineHeight2=0, overallHeight2=0, strikeoutPos2=0;
child1->getSize(painter, ev1, width1, baselineHeight1, overallHeight1, strikeoutPos1);
child2->getSize(painter, ev2, width2, baselineHeight2, overallHeight2, strikeoutPos2);
overallHeight=0;
baselineHeight=0;
width=0;
if (mode==MTFMfrac || mode==MTFMdfrac || mode==MTFMtfrac) {
//std::cout<<"\nxh="<<xh;
//std::cout<<"\n baselineHeight1="<<baselineHeight1<<", overallHeight1="<<overallHeight1;
//std::cout<<"\n baselineHeight2="<<baselineHeight2<<", overallHeight2="<<overallHeight2<<std::endl;
//overallHeight=overallHeight1+overallHeight2+sp*(2.0*parent->getFracShiftFactor());
//baselineHeight=overallHeight1+xh*(2.0*parent->getFracShiftFactor());
overallHeight=2.0*qMax(overallHeight1, overallHeight2)+sp*(2.0*parent->getFracShiftFactor());
baselineHeight=qMax(overallHeight1, overallHeight2)+xh*(2.0*parent->getFracShiftFactor());
//std::cout<<"=> baselineHeight="<<baselineHeight<<", overallHeight="<<overallHeight<<std::endl;
width=qMax(width1, width2)+ xw;
strikeoutPos=sp;
} else if (mode==MTFMstfrac || mode==MTFMsfrac) {
overallHeight=2.0*qMax(overallHeight1, overallHeight2)+sp*(2.0*parent->getFracShiftFactor());
baselineHeight=qMax(overallHeight1, overallHeight2)+xh*(2.0*parent->getFracShiftFactor());
width=width1+width2+xw;
strikeoutPos=sp;
} else if (mode==MTFMstackrel) {
//overallHeight=overallHeight1+overallHeight2+sp*(2.0*parent->getFracShiftFactor());
//baselineHeight=overallHeight1+xh*(2.0*parent->getFracShiftFactor());
overallHeight=2.0*qMax(overallHeight1, overallHeight2)+sp*(2.0*parent->getFracShiftFactor());
baselineHeight=qMax(overallHeight1, overallHeight2)+xh*(2.0*parent->getFracShiftFactor());
width=qMax(width1, width2)+ xw;
strikeoutPos=sp;
} else if (mode==MTFMunderbrace) {
overallHeight=overallHeight1+overallHeight2+Ah/2.0;
baselineHeight=baselineHeight1;
width=qMax(width1, width2)+xw;
strikeoutPos=sp;
} else if (mode==MTFMoverbrace) {
overallHeight=overallHeight1+overallHeight2+Ah/2.0;
baselineHeight=baselineHeight1+overallHeight2+Ah/2.0;
width=qMax(width1, width2)+xw;
strikeoutPos=sp;
} else if (mode==MTFMunderset) {
overallHeight=overallHeight1+overallHeight2+xh/6.0;
baselineHeight=baselineHeight1;
width=qMax(width1, width2)+xw;
strikeoutPos=sp;
} else if (mode==MTFMoverset) {
overallHeight=overallHeight1+overallHeight2+xh/6.0;
baselineHeight=baselineHeight1+overallHeight2+xh/6.0;
width=qMax(width1, width2)+xw;
strikeoutPos=sp;
}
}
double JKQTMathTextFracNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
QFont f=currentEv.getFont(parent);
QFontMetricsF fm(f, painter.device());
JKQTMathTextEnvironment ev1=currentEv;
JKQTMathTextEnvironment ev2=currentEv;
double xh=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height(); //fm.xHeight();
double xw=fm.boundingRect("x").width();
double lw=qMax(0.0,ceil(currentEv.fontSize/16.0));//fm.lineWidth();
double Ah=JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height();//fm.ascent();
double bw=Ah/2.0;
if (mode==MTFMunderbrace || mode==MTFMoverbrace) {
ev2.fontSize=ev2.fontSize*parent->getUnderbraceFactor();
} else if (mode==MTFMunderset || mode==MTFMoverset) {
ev2.fontSize=ev2.fontSize*parent->getUndersetFactor();
} else if (mode==MTFMfrac || mode==MTFMsfrac) {
ev1.fontSize=ev1.fontSize*parent->getFracFactor();
ev2.fontSize=ev2.fontSize*parent->getFracFactor();
} else if (mode==MTFMtfrac || mode==MTFMstfrac) {
ev1.fontSize=ev1.fontSize*parent->getFracFactor()*0.7;
ev2.fontSize=ev2.fontSize*parent->getFracFactor()*0.7;
}
double width1=0, baselineHeight1=0, overallHeight1=0;//, strikeoutPos1=0;
double width2=0, baselineHeight2=0, overallHeight2=0, strikeoutPos=0;
child1->getSize(painter, ev1, width1, baselineHeight1, overallHeight1, strikeoutPos);
child2->getSize(painter, ev2, width2, baselineHeight2, overallHeight2, strikeoutPos);
double ascent1=baselineHeight1;
double descent1=overallHeight1-baselineHeight1;
double ascent2=baselineHeight2;
double descent2=overallHeight2-baselineHeight2;
double yline=y-xh*0.5;
//double overallHeight=overallHeight1+overallHeight2+xh;
//double baselineHeight=3.0*xh/2.0+overallHeight1;
double width=qMax(width1, width2);
QPen p=painter.pen();
p.setColor(ev1.color);
p.setStyle(Qt::SolidLine);
p.setWidthF(qMax(parent->ABS_MIN_LINEWIDTH, lw));
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(p);
if (mode==MTFMfrac || mode==MTFMdfrac || mode==MTFMtfrac) {
QLineF l(x+xw/4.0, yline, x+width+xw/2.0, yline);
if (l.length()>0) painter.drawLine(l);
child1->draw(painter, x+xw/2.0+(width-width1)/2.0, yline-xh*(parent->getFracShiftFactor())-descent1, ev1);
child2->draw(painter, x+xw/2.0+(width-width2)/2.0, yline+xh*(parent->getFracShiftFactor())+ascent2, ev2);
} else if (mode==MTFMstfrac || mode==MTFMsfrac) {
child1->draw(painter, x, yline-descent1, ev1);
child2->draw(painter, x+width+xw, yline+ascent2, ev2);
QLineF l(x+width+1.2*xw, yline-descent1-ascent1, x+width-0.2*xw, yline+ascent1+descent1);
if (l.length()>0) painter.drawLine(l);
} else if (mode==MTFMstackrel) {
child1->draw(painter, x+xw/2.0+(width-width1)/2.0, yline-xh*(parent->getFracShiftFactor())-descent1, ev1);
child2->draw(painter, x+xw/2.0+(width-width2)/2.0, yline+xh*(parent->getFracShiftFactor())+ascent2, ev2);
} else if (mode==MTFMunderset) {
child1->draw(painter, x+xw/2.0+(width-width1)/2.0, y, ev1);
child2->draw(painter, x+xw/2.0+(width-width2)/2.0, y+descent1+xh/6.0+ascent2, ev2);
} else if (mode==MTFMunderbrace) {
double ybrace=y+descent1+bw/2.0;
QPainterPath path=JKQTMathTextMakeHBracePath(x+xw/2.0+(width1)/2.0, ybrace, width, bw);
painter.drawPath(path);
child1->draw(painter, x+xw/2.0+(width-width1)/2.0, y, ev1);
child2->draw(painter, x+xw/2.0+(width-width2)/2.0, y+descent1+bw+ascent2, ev2);
} else if (mode==MTFMoverset) {
child1->draw(painter, x+xw/2.0+(width-width1)/2.0, y, ev1);
child2->draw(painter, x+xw/2.0+(width-width2)/2.0, y-ascent1-xh/6.0-descent2, ev2);
} else if (mode==MTFMoverbrace) {
double ybrace=y-ascent1-bw/2.0;
{
painter.save(); auto __finalpaintinner=JKQTPFinally([&painter]() {painter.restore();});
painter.translate(x+xw/2.0+(width1)/2.0, ybrace);
painter.rotate(180);
QPainterPath path=JKQTMathTextMakeHBracePath(0,0, width, bw);
painter.drawPath(path);
}
child1->draw(painter, x+xw/2.0+(width-width1)/2.0, y, ev1);
child2->draw(painter, x+xw/2.0+(width-width2)/2.0, y-ascent1-bw-descent2, ev2);
}
if (mode==MTFMstackrel) return x+width+ xw;
else if (mode==MTFMstfrac || mode==MTFMsfrac) return x+width+width2+xw;
else return x+width+xw;
}
bool JKQTMathTextFracNode::toHtml(QString &/*html*/, JKQTMathTextEnvironment /*currentEv*/, JKQTMathTextEnvironment /*defaultEv*/) {
bool ok=false;
return ok;
}
void JKQTMathTextFracNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
child1->setDrawBoxes(draw);
child2->setDrawBoxes(draw);
}
JKQTMathTextNode *JKQTMathTextFracNode::getChild1() const {
return this->child1;
}
JKQTMathTextNode *JKQTMathTextFracNode::getChild2() const {
return this->child2;
}
JKQTMathTextFracMode JKQTMathTextFracNode::getMode() const {
return this->mode;
}

View File

@ -0,0 +1,74 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTFRACNODE_H
#define JKQTMATHTEXTFRACNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing a \\frac node
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFracNode: public JKQTMathTextNode {
public:
JKQTMathTextFracNode(JKQTMathText* parent, JKQTMathTextNode* child_top, JKQTMathTextNode* child_bottom, JKQTMathTextFracMode mode);
virtual ~JKQTMathTextFracNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \brief returns the 1st child node */
JKQTMathTextNode* getChild1() const;
/** \brief returns the 2nd child node */
JKQTMathTextNode* getChild2() const;
/** \copydoc mode */
JKQTMathTextFracMode getMode() const;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
JKQTMathTextNode* child1;
JKQTMathTextNode* child2;
JKQTMathTextFracMode mode;
};
#endif // JKQTMATHTEXTFRACNODE_H

View File

@ -0,0 +1,164 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextinstructionnode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextInstruction1Node::JKQTMathTextInstruction1Node(JKQTMathText* _parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters):
JKQTMathTextNode(_parent)
{
this->name=name;
this->child=child;
this->parameters=parameters;
JKQTMathTextEnvironment ev;
if (!setupMTenvironment(ev)) {
parent->addToErrorList(QObject::tr("unknown instruction '%1' found!").arg(name));
}
}
JKQTMathTextInstruction1Node::~JKQTMathTextInstruction1Node() {
if (child!=nullptr) delete child;
}
QString JKQTMathTextInstruction1Node::getTypeName() const
{
return QLatin1String("MTinstruction1Node(")+name+")";
}
void JKQTMathTextInstruction1Node::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
JKQTMathTextEnvironment ev=currentEv;
setupMTenvironment(ev);
child->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
if (name=="colorbox" || name=="fbox" || name=="boxed") {
QFontMetricsF fm(ev.getFont(parent));
double xw=fm.boundingRect("x").width();
width+=xw;
overallHeight+=xw;
baselineHeight+=xw/2.0;
}
}
double JKQTMathTextInstruction1Node::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
JKQTMathTextEnvironment ev=currentEv;
setupMTenvironment(ev);
QPen oldPen=painter.pen();
double shiftX=0;
if (name=="colorbox" || name=="fbox" || name=="boxed") {
QColor fcol=currentEv.color;
if (name=="colorbox") fcol=QColor(parameters.value(0, ev.color.name()));
//qDebug()<<"COLOR="<<fcol;
double width, baselineHeight, overallHeight, strikeoutPos;
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
QPen p=painter.pen();
QFontMetricsF fm(currentEv.getFont(parent));
double xw=fm.boundingRect("x").width();
p.setColor(fcol);
painter.setPen(p);
painter.drawRect(QRectF(x,y-baselineHeight-xw/2,width+xw,overallHeight+xw));
shiftX=xw/2.0;
}
double xnew= child->draw(painter, x+shiftX, y, ev);
painter.setPen(oldPen);
return xnew;
}
bool JKQTMathTextInstruction1Node::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
JKQTMathTextEnvironment ev=currentEv;
setupMTenvironment(ev);
return child->toHtml(html, ev, defaultEv);
}
void JKQTMathTextInstruction1Node::setDrawBoxes(bool draw)
{
drawBoxes=draw;
child->setDrawBoxes(draw);
}
JKQTMathTextNode *JKQTMathTextInstruction1Node::getChild() const {
return this->child;
}
QString JKQTMathTextInstruction1Node::getName() const {
return this->name;
}
QStringList JKQTMathTextInstruction1Node::getParameters() const {
return this->parameters;
}
bool JKQTMathTextInstruction1Node::setupMTenvironment(JKQTMathTextEnvironment &ev)
{
if (name=="bf" || name=="textbf" || name=="mathbf") ev.bold=true;
else if (name=="em") ev.italic=!ev.italic;
else if (name=="it" || name=="textit" || name=="mathit") ev.italic=true;
else if (name=="textcolor" || name=="mathcolor" || name=="color") ev.color=QColor(parameters.value(0, ev.color.name()));
else if (name=="ensuremath" || name=="equation") { ev.italic=true; ev.insideMath=true; }
else if (name=="sc" || name=="textsc" || name=="mathsc") ev.smallCaps=true;
else if (name=="ul" || name=="underline" || name=="underlined") ev.underlined=true;
else if (name=="ol" || name=="overline" || name=="overlined") ev.overline=true;
else if (name=="strike") ev.strike=true;
else if (name=="rm" || name=="textrm") { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }
else if (name=="mathrm" || name=="unit" || name=="operatorname") { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }
else if (name=="mathbfit" || name=="bfit" || name=="textbfit") { ev.bold=true; ev.italic=true; }
else if (name=="text" || name=="mbox" || name=="ensuretext") { ev.insideMath=false; ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; }
else if (name=="mat") { ev.font=JKQTMathTextEnvironmentFont::MTEroman; ev.italic=false; ev.bold=true; }
else if (name=="cal" || name=="textcal" || name=="mathcal") { ev.font=JKQTMathTextEnvironmentFont::MTEcaligraphic; ev.italic=false; }
else if (name=="fcal" || name=="textfcal" || name=="mathfcal") { ev.font=JKQTMathTextEnvironmentFont::MTEcaligraphic; ev.bold=true; }
else if (name=="frak" || name=="textfrak" || name=="mathfrak") { ev.font=JKQTMathTextEnvironmentFont::MTEfraktur; ev.italic=false; }
else if (name=="ffrak" || name=="textffrak" || name=="mathffrak") { ev.font=JKQTMathTextEnvironmentFont::MTEfraktur; ev.bold=true; }
else if (name=="bb" || name=="textbb" || name=="mathbb") { ev.font=JKQTMathTextEnvironmentFont::MTEblackboard; ev.italic=false; }
else if (name=="tt" || name=="texttt" || name=="mathtt") { ev.font=JKQTMathTextEnvironmentFont::MTEtypewriter; ev.italic=false; }
else if (name=="sf" || name=="textsf" || name=="mathsf") { ev.font=JKQTMathTextEnvironmentFont::MTEsans; ev.italic=false; }
else if (name=="sfit" || name=="textsfit" || name=="mathsfit") { ev.font=JKQTMathTextEnvironmentFont::MTEsans; ev.italic=true; }
else if (name=="script" || name=="scr" || name=="textscript" || name=="textscr" || name=="mathscript" || name=="mathscr") { ev.font=JKQTMathTextEnvironmentFont::MTEscript; ev.italic=false; }
else if (name=="fscript" || name=="fscr" || name=="textfscript" || name=="textfscr" || name=="mathfscript" || name=="mathfscr") { ev.font=JKQTMathTextEnvironmentFont::MTEscript; ev.bold=true; ev.italic=false; }
else if (name=="displaystyle") { ev.fontSize=ev.fontSize/0.8; }
else if (name=="scriptstyle") { ev.fontSize=ev.fontSize*0.8; }
else if (name=="scriptscriptstyle") { ev.fontSize=ev.fontSize*0.8*0.8; }
else {
return false;
}
return true;
}

View File

@ -0,0 +1,79 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTINSTRUCTIONNODE_H
#define JKQTMATHTEXTINSTRUCTIONNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing an instruction node with exactly one argument in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextInstruction1Node: public JKQTMathTextNode {
public:
explicit JKQTMathTextInstruction1Node(JKQTMathText* parent, const QString& name, JKQTMathTextNode* child, const QStringList& parameters=QStringList());
virtual ~JKQTMathTextInstruction1Node() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \brief convert node to HTML and returns \c true on success */
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \brief returns the child node */
JKQTMathTextNode* getChild() const;
/** \copydoc name */
QString getName() const;
/** \copydoc parameters */
QStringList getParameters() const;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
bool setupMTenvironment(JKQTMathTextEnvironment &ev);
JKQTMathTextNode* child;
QString name;
QStringList parameters;
};
#endif // JKQTMATHTEXTINSTRUCTIONNODE_H

View File

@ -0,0 +1,440 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextlistnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsymbolnode.h"
#include "jkqtmathtext/nodes/jkqtmathtextbracenode.h"
#include "jkqtmathtext/nodes/jkqtmathtextsubsupernode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextListNode::JKQTMathTextListNode(JKQTMathText* _parent):
JKQTMathTextNode(_parent)
{
nodes.clear();
// these operations cause sub/sup script to be typeset over/under the operator, not right besides!
subsupOperations<<"sum"<<"prod"<<"coprod"
<<"bigcap"<<"bigcup"<<"bigvee"<<"bighat"
<<"int"<<"iint"<<"iiint"<<"oint"<<"oiint"<<"oiiint"
<<"mod"<<"median"<<"max"<<"min"<<"argmax"<<"argmin"<<"sup"<<"inf"
<<"liminf"<<"limsup"<<"lim"<<"max"<<"min";
}
JKQTMathTextListNode::~JKQTMathTextListNode() {
for (int i=0; i<nodes.size(); i++) {
delete nodes[i];
}
nodes.clear();
}
QString JKQTMathTextListNode::getTypeName() const
{
return "MTlistNode";
}
void JKQTMathTextListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
width=0;
overallHeight=0;
baselineHeight=0;
strikeoutPos=0;
QFontMetricsF fm(currentEv.getFont(parent));
//QRectF tbr=parent->getTightBoundingRect(currentEv.getFont(parent), "M", painter.device());
double xnew=0;
bool wasBrace=false;
for (int i=0; i<nodes.size(); i++) {
JKQTMathTextNodeSize prevNodeSize;
JKQTMathTextNodeSize* prevNodeSizePtr=nullptr;
if (i>0 && wasBrace) {
nodes[i-1]->getSize(painter, currentEv, prevNodeSize.width, prevNodeSize.baselineHeight, prevNodeSize.overallHeight, prevNodeSize.strikeoutPos);
prevNodeSizePtr=&prevNodeSize;
}
bool doDraw=true;
JKQTMathTextSymbolNode* smb=dynamic_cast<JKQTMathTextSymbolNode*>(nodes[i]);
// if we find a subscript/superscript node we check whether the next node is super/subscript
// if so, we typeset them at the same x-psotion, so sub/superscripts appear correctly
if (dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i])) {
if (i+1<nodes.size()) { // is there one mor node behind?
if (dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i+1])) { // is this subscript?
double w1, w2, oh, bh, sp;
nodes[i]->getSize(painter, currentEv, w1, bh, oh, sp, prevNodeSizePtr);
if (bh>baselineHeight) {
overallHeight=overallHeight+bh-baselineHeight;
baselineHeight=bh;
strikeoutPos=sp;
}
if (baselineHeight+oh-bh>overallHeight) {
overallHeight=baselineHeight+oh-bh;
strikeoutPos=sp;
}
i++;
nodes[i]->getSize(painter, currentEv, w2, bh, oh, sp, prevNodeSizePtr);
//qDebug()<<"super_sub: sub: "<<nodes[i]->getTypeName()<<" w2="<<w2<<" bh"<<bh<<" oh="<<oh<<" sp="<<sp;
if (bh>baselineHeight) {
overallHeight=overallHeight+bh-baselineHeight;
baselineHeight=bh;
strikeoutPos=sp;
}
if (baselineHeight+oh-bh>overallHeight) {
overallHeight=baselineHeight+oh-bh;
strikeoutPos=sp;
}
xnew+=qMax(w1+fm.boundingRect(' ').width(), w2);
doDraw=false;
//qDebug()<<"### super+sub";
//qDebug()<<"### subsupop: super+sub overallHeight="<<overallHeight<<" baselineHeight="<<baselineHeight;
}
}
} else if (dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i])) {
if (i+1<nodes.size()) { // is there one mor node behind?
if (dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i+1])) { // is this subscript?
double w1, w2, oh, bh, sp;
nodes[i]->getSize(painter, currentEv, w1, bh, oh, sp, prevNodeSizePtr);
if (bh>baselineHeight) {
overallHeight=overallHeight+bh-baselineHeight;
baselineHeight=bh;
strikeoutPos=sp;
}
if (baselineHeight+oh-bh>overallHeight) {
overallHeight=baselineHeight+oh-bh;
strikeoutPos=sp;
}
i++;
nodes[i]->getSize(painter, currentEv, w2, bh, oh, sp, prevNodeSizePtr);
if (bh>baselineHeight) {
overallHeight=overallHeight+bh-baselineHeight;
baselineHeight=bh;
strikeoutPos=sp;
}
if (baselineHeight+oh-bh>overallHeight) {
overallHeight=baselineHeight+oh-bh;
strikeoutPos=sp;
}
xnew+=qMax(w1, w2+fm.boundingRect(' ').width());
doDraw=false;
//qDebug()<<"### sub+super";
//qDebug()<<"### subsupop: sub+super1 overallHeight="<<overallHeight<<" baselineHeight="<<baselineHeight;
}
}
} else if (smb) {
QString s=smb->getSymbolName();
if (subsupOperations.contains(s)) {
JKQTMathTextSubscriptNode* subn=nullptr;
if (i+1<nodes.size()) subn=dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i+1]);
JKQTMathTextSuperscriptNode* supn=nullptr;
if (i+2<nodes.size()) supn=dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i+2]);
//std::cout<<"symbol ='"<<s.toStdString()<<"' subn="<<subn<<" supn="<<supn<<"\n";
if (subn && supn) { // is this subscript and superscript?
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getOperatorsubsuperSizeFactor();
double w1=0, w2=0, w3=0;
double oh1=0, oh2=0, oh3=0;
double bh1=0, bh2=0, bh3=0;
double sp1=0, sp2=0, sp3=0;
nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp1);
//qDebug()<<"sub_super: node: "<<nodes[i]->getTypeName()<<" w1="<<w1<<" bh"<<bh1<<" oh="<<oh1<<" sp="<<sp1;
subn->getChild()->getSize(painter, ev, w2, bh2, oh2, sp2);
//qDebug()<<"sub_super: node: "<<subn->getTypeName()<<" w2="<<w2<<" bh2"<<bh2<<" oh2="<<oh2<<" sp2="<<sp2;
supn->getChild()->getSize(painter, ev, w3, bh3, oh3, sp3);
//qDebug()<<"sub_super: node: "<<supn->getTypeName()<<" w3="<<w3<<" bh3"<<bh3<<" oh3="<<oh3<<" sp3="<<sp3;
//double d1=oh1-bh1;
//double d2=oh2-bh2;
//double d3=oh3-bh3;
double w=qMax(qMax(w1, w2), w3)+fm.boundingRect(' ').width();
double oh=oh1+oh2+oh3;
double bh=bh1+oh3;
if (oh>overallHeight) overallHeight=oh;
if (bh>baselineHeight) { baselineHeight=bh; strikeoutPos=sp1; }
if (oh-bh>overallHeight-baselineHeight) {
overallHeight=baselineHeight+oh-bh;
}
i++;
i++;
doDraw=false;
xnew+=w;
//qDebug()<<"### subsupop: sub+super2 overallHeight="<<overallHeight<<" baselineHeight="<<baselineHeight;
/*} else if (subn && supn) { // is this subscript and superscript?
MTenvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getOperatorsubsuperSizeFactor();
double w1=0, w2=0, w3=0;
double oh1=0, oh2=0, oh3=0;
double bh1=0, bh2=0, bh3=0;
double sp1=0, sp2=0, sp3=0;
nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp1);
supn->getChild()->getSize(painter, ev, w3, bh3, oh3, sp3);
//double d1=oh1-bh1;
//double d2=oh2-bh2;
//double d3=oh3-bh3;
double w=qMax(w1, w3)+fm.boundingRect(' ').width();
double oh=oh1+oh3;
double bh=bh1+oh3;
if (oh>overallHeight) overallHeight=oh;
if (bh>baselineHeight) { baselineHeight=bh; strikeoutPos=sp1; }
if (oh-bh>overallHeight-baselineHeight) {
overallHeight=baselineHeight+oh-bh;
}
i++;
i++;
doDraw=false;
xnew+=w;
//qDebug()<<"### subsupop: sub+super";*/
} else if (subn) { // is this subscript?
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getOperatorsubsuperSizeFactor();
double w1=0, w2=0;
double oh1=0, oh2=0;
double bh1=0, bh2=0;
double sp1=0, sp2=0;//, sp3=0;
nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp1);
subn->getChild()->getSize(painter, ev, w2, bh2, oh2, sp2);
//double d1=oh1-bh1;
//double d2=oh2-bh2;
double oh=oh1+oh2;
double sh=oh1-bh1+oh2*1.1;
if (oh>overallHeight) overallHeight=oh;
if (bh1>baselineHeight) baselineHeight=bh1;
if (sh>overallHeight-baselineHeight) {
overallHeight=baselineHeight+sh;
}
double w=qMax(w1, w2)+fm.boundingRect(' ').width();
i++;
doDraw=false;
xnew+=w;
//qDebug()<<"### subsupop: sub overallHeight="<<overallHeight<<" baselineHeight="<<baselineHeight;
}
}
}
if (i<nodes.size() && doDraw) {
double w, oh, bh, sp;
nodes[i]->getSize(painter, currentEv, w, bh, oh, sp, prevNodeSizePtr);
//qDebug()<<"### else: bh="<<bh<<" baselineHeight="<<baselineHeight<<" oh="<<oh<<" overallHeight="<<overallHeight;
if (bh>baselineHeight) {
overallHeight=overallHeight+bh-baselineHeight;
baselineHeight=bh;
strikeoutPos=sp;
}
if (baselineHeight+oh-bh>overallHeight) {
overallHeight=baselineHeight+oh-bh;
strikeoutPos=sp;
}
//qDebug()<<"### subsupop: else overallHeight="<<overallHeight<<" baselineHeight="<<baselineHeight;
xnew+=w;
//qDebug()<<i<<xnew;
}
wasBrace=dynamic_cast<JKQTMathTextBraceNode*>(nodes[i]);
}
width=xnew;
}
double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
double ynew=y;
double xnew=x;
//qDebug()<<"listNode: "<<currentEv.fontSize;
QFontMetricsF fm(currentEv.getFont(parent));
bool wasBrace=false;
for (int i=0; i<nodes.size(); i++) {
bool doDraw=true;
JKQTMathTextNodeSize prevNodeSize;
JKQTMathTextNodeSize* prevNodeSizePtr=nullptr;
if (i>0 && wasBrace) {
nodes[i-1]->getSize(painter, currentEv, prevNodeSize.width, prevNodeSize.baselineHeight, prevNodeSize.overallHeight, prevNodeSize.strikeoutPos);
prevNodeSizePtr=&prevNodeSize;
}
JKQTMathTextSymbolNode* smb=dynamic_cast<JKQTMathTextSymbolNode*>(nodes[i]);
// if we find a subscript/superscript node we check whether the next node is super/subscript
// if so, we typeset them at the same x-psotion, so sub/superscripts appear correctly
if (dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i])) {
if (i+1<nodes.size()) { // is there one mor node behind?
if (dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i+1])) { // is this subscript?
//painter.setPen(QPen("red"));
//painter.drawEllipse(xnew-4,ynew+shift-(ccOverallHeight-ccBaselineHeight)-4,8,8);
double xnew1=nodes[i]->draw(painter, xnew, ynew, currentEv, prevNodeSizePtr);
i++;
//painter.setPen(QPen("magenta"));
//painter.drawEllipse(xnew-4,ynew-4,8,8);
double xnew2=nodes[i]->draw(painter, xnew, ynew, currentEv, prevNodeSizePtr);
//i++;
xnew=qMax(xnew1, xnew2);
doDraw=false;
}
}
} else if (dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i])) {
if (i+1<nodes.size()) { // is there one mor node behind?
if (dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i+1])) { // is this subscript?
//painter.setPen(QPen("red"));
//painter.drawEllipse(xnew-4,ynew+shift-(ccOverallHeight-ccBaselineHeight)-4,8,8);
double xnew1=nodes[i]->draw(painter, xnew, ynew, currentEv, prevNodeSizePtr);
i++;
//painter.setPen(QPen("magenta"));
//painter.drawEllipse(xnew-4,ynew-4,8,8);
double xnew2=nodes[i]->draw(painter, xnew, ynew, currentEv, prevNodeSizePtr);
//i++;
xnew=qMax(xnew1, xnew2);
doDraw=false;
}
}
} else {
if (smb) {
QString s=smb->getSymbolName();
if (subsupOperations.contains(s)) {
JKQTMathTextSubscriptNode* subn=nullptr;
if (i+1<nodes.size()) subn=dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i+1]);
JKQTMathTextSuperscriptNode* supn=nullptr;
if (i+2<nodes.size()) supn=dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i+2]);
//std::cout<<"symbol ='"<<s.toStdString()<<"' subn="<<subn<<" supn="<<supn<<"\n";
if (subn && supn) { // is this subscript and superscript?
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getOperatorsubsuperSizeFactor();
double w1=0, w2=0, w3=0;
double oh1=0, oh2=0, oh3=0;
double bh1=0, bh2=0, bh3=0, sp;
nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
subn->getChild()->getSize(painter, ev, w2, bh2, oh2, sp);
supn->getChild()->getSize(painter, ev, w3, bh3, oh3, sp);
double d1=oh1-bh1;
//double d2=oh2-bh2;
double d3=oh3-bh3;
double w=qMax(qMax(w1, w2), w3);
//double xnew1=
double xn1=nodes[i]->draw(painter, xnew+(w-w1)/2.0, ynew, currentEv);
i++;
//double xnew2=
double xn2=subn->getChild()->draw(painter, xnew+(w-w2)/2.0, ynew+bh2+d1, ev);
i++;
//double xnew3=
double xn3=supn->getChild()->draw(painter, xnew+(w-w3)/2.0, ynew-bh1-d3-fm.xHeight()/4.0, ev);
doDraw=false;
xnew=qMax(qMax(xn1, xn2), xn3)+fm.boundingRect(' ').width();
} else if (subn) { // is this subscript and not superscript?
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getOperatorsubsuperSizeFactor();
double w1=0, w2=0;
double oh1=0, oh2=0;
double bh1=0, bh2=0, sp=0;
nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
subn->getChild()->getSize(painter, ev, w2, bh2, oh2, sp);
double d1=oh1-bh1;
//double d2=oh2-bh2;
double w=qMax(w1, w2);
//double xnew1=
double xn2=nodes[i]->draw(painter, xnew+(w-w1)/2.0, ynew, currentEv);
i++;
//double xnew2=
double xn1=subn->getChild()->draw(painter, xnew+(w-w2)/2.0, ynew+bh2+d1, ev)+fm.boundingRect(' ').width();
doDraw=false;
//xnew+=w;
xnew=qMax(xn1, xn2);
} else if (supn) { // is this subscript and superscript?
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getOperatorsubsuperSizeFactor();
double w1=0, w3=0;
double oh1=0, oh3=0;
double bh1=0, bh3=0, sp;
nodes[i]->getSize(painter, currentEv, w1, bh1, oh1, sp);
supn->getChild()->getSize(painter, ev, w3, bh3, oh3, sp);
//double d1=oh1-bh1;
//double d2=oh2-bh2;
double d3=oh3-bh3;
double w=qMax(w1, w3);
//double xnew1=
double xn1=nodes[i]->draw(painter, xnew+(w-w1)/2.0, ynew, currentEv);
i++;
//double xnew3=
double xn3=supn->getChild()->draw(painter, xnew+(w-w3)/2.0, ynew-bh1-d3-fm.xHeight()/4.0, ev);
doDraw=false;
xnew=qMax(xn1, xn3)+fm.boundingRect(' ').width();
}
}
}
}
if (i<nodes.size() && doDraw) {
xnew=nodes[i]->draw(painter, xnew, ynew, currentEv, prevNodeSizePtr);
}
wasBrace=dynamic_cast<JKQTMathTextBraceNode*>(nodes[i]);
}
return xnew;
}
bool JKQTMathTextListNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
bool ok=true;
for (int i=0; i<nodes.size(); i++) {
QString h="";
ok = ok && nodes[i]->toHtml(h, currentEv, defaultEv);
html=html+h;
}
return ok;
}
void JKQTMathTextListNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
for (int i=0; i<nodes.size(); i++) {
nodes[i]->setDrawBoxes(draw);
}
}
QList<JKQTMathTextNode *> JKQTMathTextListNode::getNodes() const {
return this->nodes;
}

View File

@ -0,0 +1,70 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTLISTNODE_H
#define JKQTMATHTEXTLISTNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing a list of nodes in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextListNode: public JKQTMathTextNode {
public:
explicit JKQTMathTextListNode(JKQTMathText* parent);
virtual ~JKQTMathTextListNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \brief add a child node */
void addNode(JKQTMathTextNode* n) { nodes.append(n); }
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \copydoc nodes */
QList<JKQTMathTextNode*> getNodes() const;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
QList<JKQTMathTextNode*> nodes;
QSet<QString> subsupOperations;
};
#endif // JKQTMATHTEXTLISTNODE_H

View File

@ -0,0 +1,198 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextmatrixnode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextMatrixNode::JKQTMathTextMatrixNode(JKQTMathText* _parent, QVector<QVector<JKQTMathTextNode*> > children):
JKQTMathTextNode(_parent)
{
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;
}
JKQTMathTextMatrixNode::~JKQTMathTextMatrixNode() {
for (int i=0; i<children.size(); i++) {
for (int j=0; j<children[i].size(); j++) {
delete children[i].at(j);
}
}
children.clear();
}
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(parent), 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(parent), 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*/)
{
return false;
}
QVector<QVector<JKQTMathTextNode *> > JKQTMathTextMatrixNode::getChildren() const {
return this->children;
}
int JKQTMathTextMatrixNode::getColumns() const {
return this->columns;
}
int JKQTMathTextMatrixNode::getLines() const {
return this->lines;
}
void JKQTMathTextMatrixNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
for (int i=0; i<lines; i++) {
for (int j=0; j<children[i].size(); j++) {
children[i].at(j)->setDrawBoxes(draw);
}
}
}

View File

@ -0,0 +1,71 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTMATRIXNODE_H
#define JKQTMATHTEXTMATRIXNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing a \\begin{matrix} node
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextMatrixNode: public JKQTMathTextNode {
public:
JKQTMathTextMatrixNode(JKQTMathText* parent, QVector<QVector<JKQTMathTextNode*> > children);
virtual ~JKQTMathTextMatrixNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \brief returns the child nodes */
QVector<QVector<JKQTMathTextNode*> > getChildren() const;
/** \copydoc columns */
int getColumns() const;
/** \copydoc lines */
int getLines() const;
protected:
/** \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;
QVector<QVector<JKQTMathTextNode*> > children;
int columns;
int lines;
};
#endif // JKQTMATHTEXTMATRIXNODE_H

View File

@ -0,0 +1,115 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
// --------------------------------------------------------------------------------------------------
// -- implementation of the JKQTMathTextNode's methods
// --------------------------------------------------------------------------------------------------
JKQTMathTextNode::JKQTMathTextNode(JKQTMathText* parent) {
this->parent=parent;
drawBoxes=false;
}
JKQTMathTextNode::~JKQTMathTextNode()
= default;
void JKQTMathTextNode::getSize(QPainter &painter, JKQTMathTextEnvironment currentEv, double &width, double &baselineHeight, double &overallHeight, double &strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize)
{
double w=width, b=baselineHeight, o=overallHeight, s=strikeoutPos;
getSizeInternal(painter, currentEv, w, b, o, s, prevNodeSize);
if (w<1e5) width=w;
if (b<1e5) baselineHeight=b;
if (o<1e5) overallHeight=o;
if (s<1e5) strikeoutPos=s;
}
double JKQTMathTextNode::getNonItalicXCorretion(QPainter &painter, double width_potentiallyitalic, const JKQTMathTextEnvironment &ev_potentiallyitalic, JKQTMathTextNode* child) const
{
double italic_xcorrection=0.0;
if (ev_potentiallyitalic.italic) {
JKQTMathTextEnvironment ev_nonitalic=ev_potentiallyitalic;
ev_nonitalic.italic=false;
double width_nonitalic=0, baselineHeight_nonitalic=0, overallHeight_nonitalic=0, strikeoutPos_nonitalic=0;
child->getSize(painter, ev_nonitalic, width_nonitalic, baselineHeight_nonitalic, overallHeight_nonitalic, strikeoutPos_nonitalic);
italic_xcorrection=width_potentiallyitalic-width_nonitalic;
}
return italic_xcorrection;
}
bool JKQTMathTextNode::toHtml(QString &/*html*/, JKQTMathTextEnvironment /*currentEv*/, JKQTMathTextEnvironment /*defaultEv*/) {
return false;
}
bool JKQTMathTextNode::getDrawBoxes() const {
return this->drawBoxes;
}
void JKQTMathTextNode::doDrawBoxes(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) {
if (drawBoxes) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
double w, oh, bh, sp;
getSize(painter, currentEv, w, bh, oh, sp);
QPen p=painter.pen();
p.setColor("lightcoral");
p.setWidthF(0.5);
painter.setPen(p);
QRectF r(x, y-bh, w, oh);
painter.drawRect(r);
p.setColor("lightblue");
painter.setPen(p);
if (w>0) painter.drawLine(QLineF(x, y, x+w, y));
p.setColor("green");
painter.setPen(p);
painter.drawEllipse(QRectF(x-3.0,y-3.0,6.0,6.0));
p.setColor("lightgreen");
painter.setPen(p);
painter.drawLine(QLineF(x-2.0, y, x+2.0, y));
painter.drawLine(QLineF(x, y-2, x, y+2.0));
}
}
void JKQTMathTextNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
}
QString JKQTMathTextNode::getTypeName() const
{
return "JKQTMathTextNode";
}

View File

@ -0,0 +1,118 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTNODE_H
#define JKQTMATHTEXTNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include <QPainter>
class JKQTMathText; // forward
/** \brief subclass representing one node in the syntax tree
* \ingroup jkqtmathtext_items
*
* \image html jkqtmathtext_node_geo.png
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNode {
public:
explicit JKQTMathTextNode(JKQTMathText* parent);
JKQTMathTextNode(const JKQTMathTextNode&)=delete;
JKQTMathTextNode& operator=(const JKQTMathTextNode&)=delete;
virtual ~JKQTMathTextNode();
/** \brief determine the size of the node, calls getSizeInternal() implementation of the actual type \see getSizeInternal()
*
* \param painter painter to use for determining the size
* \param currentEv current environment object
* \param[out] width width of the block/node
* \param[out] baselineHeight distance from the bottom of the block/node-box to the baseline
* \param[out] overallHeight overall height (bottom to top) of the node, the ascent is \c overallHeight-baselineHeight
* \param[out] strikeoutPos position of the strikeout-line
* \param[in] prevNodeSize optional parameter, describing the size of the previous node (on the left). This may be used for layout of some nodes (e.g. sub/super to move correctly next to large parantheses ...)
*
*/
void getSize(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr);
/** \brief calculates the x-size-difference between the given (probably) italic (width externally calculated: \A width_potentiallyitalic, \a ev_potentiallyitalic) and the non-italic version of \a child */
double getNonItalicXCorretion(QPainter &painter, double width_potentiallyitalic, const JKQTMathTextEnvironment &ev_potentiallyitalic, JKQTMathTextNode* child) const;
/** \brief draw the contents at the designated position
*
* \param painter QPainter to use
* \param x x-position, where the drawing starts [Pixel]
* \param y Y-position of the baseline, where the drawing starts [Pixel]
* \param currentEv JKQTMathTextEnvironment object describing the current drawing environment/settings
* \param[in] prevNodeSize optional parameter, describing the size of the previous node (on the left). This may be used for layout of some nodes (e.g. sub/super to move correctly next to large parantheses ...)
* \return the x position which to use for the next part of the text
*/
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr)=0;
/** \brief convert node to HTML and returns \c true on success
* \param[out] html new HTML code is APPENDED to this string
* \param currentEv JKQTMathTextEnvironment object describing the current drawing environment/settings
* \param defaultEv JKQTMathTextEnvironment object describing the default drawing environment/settings when starting to interpret a node tree
* \return \c true on success
*/
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv);
/** \brief returns the drawing of colored boxes (for DEBUGGING) around the actual output of the node is enabled */
bool getDrawBoxes() const;
/** \brief enables the drawing of colored boxes (for DEBUGGING) around the actual output of the node */
virtual void setDrawBoxes(bool draw);
/** \brief return the name of this class as a string */
virtual QString getTypeName() const;
protected:
/** \brief determine the size of the node, overwrite this function in derived classes
*
* \param painter painter to use for determining the size
* \param currentEv current environment object
* \param[out] width width of the block/node
* \param[out] baselineHeight distance from the bottom of the block/node-box to the baseline
* \param[out] overallHeight overall height (bottom to top) of the node, the ascent is \c overallHeight-baselineHeight
* \param[out] strikeoutPos position of the strikeout-line
* \param[in] prevNodeSize optional parameter, describing the size of the previous node (on the left). This may be used for layout of some nodes (e.g. sub/super to move correctly next to large parantheses ...)
*
*/
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr)=0;
/** \brief parent JKQTMathText object (required for several drawing operations */
JKQTMathText* parent;
/** \brief enables the drawing of colored boxes (for DEBUGGING) around the actual output of the node */
bool drawBoxes;
/** \brief draws colored boxes (for DEBUGGING) around the actual output of the node
*
* \param painter QPainter to use
* \param x x-position, where the drawing starts [Pixel]
* \param y Y-position of the baseline, where the drawing starts [Pixel]
* \param currentEv JKQTMathTextEnvironment object describing the current drawing environment/settings
*/
void doDrawBoxes(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv);
};
#endif // JKQTMATHTEXTNODE_H

View File

@ -0,0 +1,127 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextsqrtnode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextSqrtNode::JKQTMathTextSqrtNode(JKQTMathText* _parent, JKQTMathTextNode* child, int degree):
JKQTMathTextNode(_parent)
{
this->child=child;
this->degree=degree;
}
JKQTMathTextSqrtNode::~JKQTMathTextSqrtNode() {
if (child!=nullptr) delete child;
}
void JKQTMathTextSqrtNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
QFontMetricsF fm(currentEv.getFont(parent), painter.device());
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
overallHeight=overallHeight*1.2;//+fm.ascent()*0.1;
baselineHeight=baselineHeight*1.2;//+fm.ascent()*0.1;
width=width+fm.boundingRect("A").width()*2; // 1.53
}
double JKQTMathTextSqrtNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
double width=0, baselineHeight=0, overallHeight=0, sp=0;
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, sp);
QFont f=currentEv.getFont(parent);
QFont fsmall=f;
QFontMetricsF fm(f, painter.device());
double w=fm.boundingRect("A").width();
double a=baselineHeight*1.15;
double d=overallHeight-baselineHeight;
//painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen p=painter.pen();
p.setColor(currentEv.color);
p.setWidthF(fm.lineWidth());
//painter.setPen(p);
QPainterPath path;
if (w>0) {
path.moveTo(x+0.1*w, y-0.4*a);
path.lineTo(x+0.33*w, y-0.4*a);
path.lineTo( x+0.66*w, y+0.5*d);
path.lineTo(x+w, y-a);
}
if (degree!=2) {
fsmall.setPointSizeF(fsmall.pointSizeF()/2.0);
fsmall.setItalic(false);
painter.setFont(fsmall);
painter.drawText(QPointF(x+0.33*w, y-0.55*a), QLocale::c().toString(degree));
}
//painter.restore();
double xnew=child->draw(painter, x+1.2*w, y, currentEv);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(p);
if (w>0) {
path.lineTo( xnew+0.2*w, y-a);
path.lineTo(xnew+0.2*w, y-0.8*a);
painter.drawPath(path);
}
return xnew+0.33*w;
}
bool JKQTMathTextSqrtNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
html=html+"&radic;<span style=\"text-decoration:overline\">";
bool ok=child->toHtml(html, currentEv, defaultEv);
html=html+"&nbsp;</span>";
return ok;
}
void JKQTMathTextSqrtNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
child->setDrawBoxes(draw);
}
QString JKQTMathTextSqrtNode::getTypeName() const
{
return "MTsqrtNode";
}
JKQTMathTextNode *JKQTMathTextSqrtNode::getChild() const {
return this->child;
}
int JKQTMathTextSqrtNode::getDegree() const {
return this->degree;
}

View File

@ -0,0 +1,71 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTSQRTNODE_H
#define JKQTMATHTEXTSQRTNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing a sqrt node
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSqrtNode: public JKQTMathTextNode {
public:
JKQTMathTextSqrtNode(JKQTMathText* parent, JKQTMathTextNode* child, int degree=2);
virtual ~JKQTMathTextSqrtNode() override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override ;
/** \brief returns the child node */
JKQTMathTextNode *getChild() const;
/** \copydoc degree */
int getDegree() const;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
JKQTMathTextNode* child;
int degree;
};
#endif // JKQTMATHTEXTSQRTNODE_H

View File

@ -0,0 +1,203 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtextsubsupernode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextSuperscriptNode::JKQTMathTextSuperscriptNode(JKQTMathText* _parent, JKQTMathTextNode* child):
JKQTMathTextNode(_parent)
{
this->child=child;
}
JKQTMathTextSuperscriptNode::~JKQTMathTextSuperscriptNode() {
if (child!=nullptr) delete child;
}
void JKQTMathTextSuperscriptNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize) {
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getSubsuperSizeFactor();
QFontMetricsF fm(currentEv.getFont(parent), painter.device());
QRectF tbr=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parent), "M", painter.device());
child->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
double shift=parent->getSuperShiftFactor()*tbr.height();
if (prevNodeSize!=nullptr && prevNodeSize->baselineHeight>tbr.height()) {
shift=prevNodeSize->baselineHeight-(overallHeight-baselineHeight)-shift;
}
double yshift=shift+overallHeight-baselineHeight;
baselineHeight=overallHeight=overallHeight+shift;
strikeoutPos=strikeoutPos-yshift;
if (currentEv.italic && prevNodeSize==nullptr) width=width+double(fm.boundingRect(' ').width())*parent->getItalicCorrectionFactor();
}
double JKQTMathTextSuperscriptNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize) {
doDrawBoxes(painter, x, y, currentEv);
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getSubsuperSizeFactor();
double cWidth, cBaselineHeight, cOverallHeight, cStrikeoutPos;
child->getSize(painter, ev, cWidth, cBaselineHeight, cOverallHeight, cStrikeoutPos);
QFontMetricsF fm(currentEv.getFont(parent), painter.device());
QRectF tbr=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parent), "M", painter.device());
double shift=parent->getSuperShiftFactor()*tbr.height();
if (prevNodeSize!=nullptr && prevNodeSize->baselineHeight>tbr.height()) {
shift=prevNodeSize->baselineHeight-(cOverallHeight-cBaselineHeight)-shift;
}
double yshift=shift+cOverallHeight-cBaselineHeight;
double xx=x;
if (currentEv.italic && prevNodeSize==nullptr) xx=xx+double(fm.boundingRect(' ').width())*parent->getItalicCorrectionFactor();
return child->draw(painter, xx, y-yshift, ev);//+0.5*fm.boundingRect("A").width();
}
JKQTMathTextNode *JKQTMathTextSuperscriptNode::getChild() const {
return this->child;
}
QString JKQTMathTextSuperscriptNode::getTypeName() const
{
return "MTsuperscriptNode";
}
bool JKQTMathTextSuperscriptNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv)
{
html=html+"<sup>";
bool ok=child->toHtml(html, currentEv, defaultEv);
html=html+"</sup>";
return ok;
}
void JKQTMathTextSuperscriptNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
child->setDrawBoxes(draw);
}
JKQTMathTextSubscriptNode::JKQTMathTextSubscriptNode(JKQTMathText* _parent, JKQTMathTextNode* child):
JKQTMathTextNode(_parent)
{
this->child=child;
}
JKQTMathTextSubscriptNode::~JKQTMathTextSubscriptNode() {
if (child!=nullptr) delete child;
}
void JKQTMathTextSubscriptNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize) {
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getSubsuperSizeFactor();
child->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
QFontMetricsF fm(ev.getFont(parent), painter.device());
QRectF tbr=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parent), "M", painter.device());
double shift=parent->getSubShiftFactor()*tbr.height();
if (prevNodeSize!=nullptr && prevNodeSize->overallHeight-prevNodeSize->baselineHeight>shift) {
shift=-1.0*(prevNodeSize->overallHeight-prevNodeSize->baselineHeight-shift);
}
double yshift=baselineHeight-shift;
baselineHeight=shift;
strikeoutPos=fm.strikeOutPos()+yshift;
if (currentEv.italic && prevNodeSize==nullptr) width=width-double(fm.boundingRect(' ').width())*parent->getItalicCorrectionFactor();
}
double JKQTMathTextSubscriptNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize) {
doDrawBoxes(painter, x, y, currentEv);
JKQTMathTextEnvironment ev=currentEv;
ev.fontSize=ev.fontSize*parent->getSubsuperSizeFactor();
QFontMetricsF fm(ev.getFont(parent), painter.device());
QRectF tbr=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parent), "M", painter.device());
double width=0, baselineHeight=0, overallHeight=0, strikeoutPos=0;
child->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
double shift=parent->getSubShiftFactor()*tbr.height();
if (prevNodeSize!=nullptr && prevNodeSize->overallHeight-prevNodeSize->baselineHeight>shift) {
//qDebug()<<"oldshift="<<shift<<", prevNodeSize->overallHeight="<<prevNodeSize->overallHeight<<", prevNodeSize->baselineHeight="<<prevNodeSize->baselineHeight;
shift=-1.0*(prevNodeSize->overallHeight-prevNodeSize->baselineHeight-shift);
//qDebug()<<"newshift="<<shift;
}
double yshift=baselineHeight-shift;
//qDebug()<<"baselineHeight="<<baselineHeight<<", overallHeight="<<overallHeight<<", strikeoutPos="<<strikeoutPos;
//qDebug()<<"shift="<<shift<<", yshift="<<yshift;
double xx=x;
if (currentEv.italic && prevNodeSize==nullptr) xx=xx-double(fm.boundingRect(' ').width())*parent->getItalicCorrectionFactor();
return child->draw(painter, xx, y+yshift, ev);//+0.5*fm.boundingRect("A").width();
}
QString JKQTMathTextSubscriptNode::getTypeName() const
{
return "MTsubscriptNode";
}
JKQTMathTextNode *JKQTMathTextSubscriptNode::getChild() const {
return this->child;
}
bool JKQTMathTextSubscriptNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
html=html+"<sub>";
bool ok=child->toHtml(html, currentEv, defaultEv);
html=html+"</sub>";
return ok;
}
void JKQTMathTextSubscriptNode::setDrawBoxes(bool draw)
{
this->drawBoxes=draw;
child->setDrawBoxes(draw);
}

View File

@ -0,0 +1,96 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTSUBSUPERSCRIPTNODE_H
#define JKQTMATHTEXTSUBSUPERSCRIPTNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing an subscript node with exactly one argument in the syntax tree
* \ingroup jkqtmathtext_items
*
* \image html jkqtmathtext_subscriptnode_getSizeInternal.png
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSubscriptNode: public JKQTMathTextNode {
public:
explicit JKQTMathTextSubscriptNode(JKQTMathText* parent, JKQTMathTextNode* child);
virtual ~JKQTMathTextSubscriptNode() override;
/** \copydoc JKQTMathTextNode::draw() */
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 returns the child node */
/** \brief returns the child node */
JKQTMathTextNode *getChild() const;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
JKQTMathTextNode* child;
};
/** \brief subclass representing an superscript node with exactly one argument in the syntax tree
* \ingroup jkqtmathtext_items
*
* \image html jkqtmathtext_subscriptnode_getSizeInternal.png
*
* \note a MTlistNode might modify the positioning slightly for special cases (e.g. \c \\int , \c \\sum ... or after braces)
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSuperscriptNode: public JKQTMathTextNode {
public:
explicit JKQTMathTextSuperscriptNode(JKQTMathText* parent, JKQTMathTextNode* child);
virtual ~JKQTMathTextSuperscriptNode() override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \brief returns the child node */
JKQTMathTextNode* getChild() const;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc JKQTMathTextNode::setDrawBoxes() */
virtual void setDrawBoxes(bool draw) override;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
JKQTMathTextNode* child;
};
#endif // JKQTMATHTEXTSUBSUPERSCRIPTNODE_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,106 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTSYMBOLNODE_H
#define JKQTMATHTEXTSYMBOLNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing one symbol (e.g. \c \\alpha , \c \\cdot ...) node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
public:
explicit JKQTMathTextSymbolNode(JKQTMathText* parent, const QString& name, bool addWhitespace);
virtual ~JKQTMathTextSymbolNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc symbolName */
QString getSymbolName() const;
/** \brief get font name of the symbol */
QString getSymbolfontName() const;
/** \copydoc addWhitespace */
bool getAddWhitespace() const;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \brief this string will be sent to the drawText method with properly set fonts */
QString symbolName;
/** \brief add a whitespace to the symbol? */
bool addWhitespace;
struct SymbolProps {
/** \brief the symbol name supplied to the constructor */
QString symbol;
/** \brief font to use for output */
QString font;
/** \brief magnification factor for the font size */
double fontFactor;
/** \brief 0: leave italic setting as is, >0: set italic, <0 set italic to false */
char italic;
/** \brief 0: leave bold setting as is, >0: set bold, <0 set bold to false */
char bold;
/** \brief this corrects the y position of a symbol: draws at y <- y+ height*yfactor) */
double yfactor;
/** \brief indicates whether to draw a bar (like for \c \\hbar ) */
bool drawBar;
bool heightIsAscent;
bool exactAscent;
bool extendWidthInMathmode;
};
/** \brief retrieve the properties to render the given symbol \a symName in the current environment \a currentEv */
SymbolProps getSymbolProp(const QString& symName, const JKQTMathTextEnvironment& currentEv) const;
/** \brief fill \a props for the symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using Unicode font (or WinSymbol as Fallback)*/
bool getSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n, const JKQTMathTextEnvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the greek letter symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using Unicode font (or WinSymbol as Fallback) */
bool getGreekSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n, const JKQTMathTextEnvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the symbol named \a n in the given environment \a currentEv and with the given \a mathFontFactor , returns \c true if the symbol can be drawn using WinSymbol font */
bool getWinSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n, const JKQTMathTextEnvironment &currentEv, double mathFontFactor) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using any font, does not alter the font name!!! */
bool getStandardTextSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using any unicode font, does not alter the font name!!! */
bool getUnicodeBaseSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n) const;
/** \brief fill \a props for the symbol named \a n , returns \c true if the symbol can be drawn using a full unicode font, does not alter the font name!!! */
bool getUnicodeFullSymbolProp(JKQTMathTextSymbolNode::SymbolProps &props, const QString &n, double mathFontFactor) const;
};
#endif // JKQTMATHTEXTSYMBOLNODE_H

View File

@ -0,0 +1,264 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtmathtext/nodes/jkqtmathtexttextnode.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <cmath>
#include <QFontMetricsF>
#include <QDebug>
#include <QFontDatabase>
#include <QFontInfo>
#include <QApplication>
#include <QFont>
JKQTMathTextTextNode::JKQTMathTextTextNode(JKQTMathText* _parent, const QString& textIn, bool addWhitespace, bool stripInnerWhitepace):
JKQTMathTextNode(_parent)
{
QString text=textIn;
if (stripInnerWhitepace) {
text="";
for (int i=0; i<textIn.size(); i++) {
if (!textIn[i].isSpace()) text+=textIn[i];
}
}
this->text=text;
// strip all whitespace from left
while (this->text.size()>1 && this->text[0].isSpace()) {
this->text=this->text.right(this->text.size()-1);
}
if (addWhitespace /*&& (this->text.size()>0)*/ && (!this->text[this->text.size()-1].isSpace())) this->text=this->text+" ";
//qDebug()<<"JKQTMathTextTextNode( text="<<text<<" addWhitespace="<<addWhitespace<<") [=> this->text="<<this->text<<"]";
}
JKQTMathTextTextNode::~JKQTMathTextTextNode() = default;
void JKQTMathTextTextNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
QFont f=currentEv.getFont(parent);
if (currentEv.insideMath && (text=="(" || text=="[" || text=="|" || text=="]" || text==")" || text=="<" || text==">" ||
text==QString(QChar(0x2329)) || text==QString(QChar(0x232A)) || text==QString(QChar(0x2308)) ||
text==QString(QChar(0x2309)) || text==QString(QChar(0x230A)) || text==QString(QChar(0x230B)))) {
f.setItalic(false);
//f.setFamily(parent->getFontData(currentEv.font, currentEv.insideMath, FontSubclass::Text).first);
}
QString txt=textTransform(text, currentEv, true);
QFontMetricsF fm(f, painter.device());
QRectF br=fm.boundingRect(txt);
QRectF tbr=JKQTMathTextGetTightBoundingRect(f, txt, painter.device()); //fm.tightBoundingRect(txt);
if (txt=="|") {
br=fm.boundingRect("X");
tbr=QRectF(0,0,fm.boundingRect("X").width(), fm.ascent());//fm.boundingRect("X");
br.setWidth(0.7*br.width());
}
width=br.width();//width(text);
if (txt.size()>0) {
if (txt[0].isSpace() /*&& br.width()<=0*/) width=width+fm.boundingRect("I").width();
if (txt.size()>1 && txt[txt.size()-1].isSpace() /*&& (fm.boundingRect("a ").width()==fm.boundingRect("a").width())*/) width=width+fm.boundingRect("I").width();
}
//qDebug()<<"text: "<<text<<" "<<tbr.height()<<tbr.top()<<tbr.bottom();
overallHeight=tbr.height()*1.1; //fm.height();
baselineHeight=1.1*(tbr.height()-(tbr.height()+tbr.top()));//fm.ascent();
strikeoutPos=fm.strikeOutPos()*1.1;
}
double JKQTMathTextTextNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
doDrawBoxes(painter, x, y, currentEv);
double width=0;
double baselineHeight=0;
double overallHeight=0;
double sp=0;
getSize(painter, currentEv, width, baselineHeight, overallHeight, sp);
QString txt=textTransform(text, currentEv);
bool hasDigits=false;
bool onlyDigits=true;
for (int i=0; i<txt.size(); i++) {
if (txt[i].isDigit()) {
hasDigits=true;
}
if (!txt[i].isDigit() && !txt[i].isSpace()) {
onlyDigits=false;
}
}
QPen pold=painter.pen();
QFont fold=painter.font();
QFont f=currentEv.getFont(parent);
if (currentEv.insideMath && (text=="(" || text=="[" || text=="|" || text=="]" || text==")" || text=="<" || text==">" ||
text==QString(QChar(0x2329)) || text==QString(QChar(0x232A)) || text==QString(QChar(0x2308)) ||
text==QString(QChar(0x2309)) || text==QString(QChar(0x230A)) || text==QString(QChar(0x230B)))) {
f.setItalic(false);
}
if (onlyDigits && currentEv.insideMath) {
f.setItalic(false);
}
painter.setFont(f);
//qDebug()<<"JKQTMathTextTextNode: text="<<text<<" font="<<f;
QPen p=painter.pen();
p.setColor(currentEv.color);
painter.setPen(p);
double dx=0;
QFontMetricsF fm(f, painter.device());
/*if (txt.size()>1 && txt[txt.size()-1].isSpace()) {
QFontMetricsF fm(f, painter.device());
//if ((fm.QFMF_WIDTH("a ")==fm.QFMF_WIDTH("a"))) dx=fm.boundingRect("I").QFMF_WIDTH();
}*/
if (!hasDigits || !f.italic()) {
if (currentEv.font==MTEblackboard && parent->isFontBlackboardSimulated()) {
QPainterPath path;
path.addText(QPointF(x+dx, y), f, txt);
painter.drawPath(path);
} else {
painter.drawText(QPointF(x+dx, y), txt);//.simplified());
}
} else {
int i=0;
double xx=x+dx;
QFont ff=f;
QFontMetricsF fmff(ff, painter.device());
ff.setItalic(false);
while (i<txt.size()) {
if (txt[i].isDigit()) {
if (currentEv.font==MTEblackboard && parent->isFontBlackboardSimulated()) {
QPainterPath path;
path.addText(QPointF(xx, y), ff, QString(txt[i]));
painter.drawPath(path);
} else {
painter.setFont(ff);
painter.drawText(QPointF(xx, y), QString(txt[i]));
}
xx=xx+fmff.boundingRect(txt[i]).width();
} else {
if (currentEv.font==MTEblackboard && parent->isFontBlackboardSimulated()) {
QPainterPath path;
path.addText(QPointF(xx, y), f, QString(txt[i]));
painter.drawPath(path);
} else {
painter.setFont(f);
painter.drawText(QPointF(xx, y), QString(txt[i]));
}
xx=xx+fm.boundingRect(txt[i]).width();
}
i++;
}
}
painter.setPen(pold);
painter.setFont(fold);
return x+width;
}
bool JKQTMathTextTextNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
html=html+currentEv.toHtmlStart(defaultEv)+text+currentEv.toHtmlAfter(defaultEv);
return true;
}
QString JKQTMathTextTextNode::getText() const {
return this->text;
}
QString JKQTMathTextTextNode::getTypeName() const
{
return QLatin1String("JKQTMathTextTextNode(")+text+")";
}
QString JKQTMathTextTextNode::textTransform(const QString &text, JKQTMathTextEnvironment currentEv, bool /*forSize*/)
{
QString txt=text;
auto fnt=parent->getFontData(currentEv.font, currentEv.insideMath);
if (fnt.second==MTFEunicode || fnt.second==MTFEunicodeLimited) {
if (currentEv.insideMath) {
txt="";
for (int i=0; i<text.size(); i++) {
QChar c=text[i];
switch(c.unicode()) {
case '-': txt+=QString(QString(" ")+QChar(0x2212)); break;
case '+': txt+=QString(QString(" +")); break;
case '/': txt+=QString(QString(" /")); break;
case '<': txt+=QString(QString(" <")); break;
case '>': txt+=QString(QString(" >")); break;
case '=': txt+=QString(QString(" =")); break;
case ';': txt+=QString(QString("; ")); break;
case ',': txt+=QString(QString(", ")); break;
default: txt+=c; break;
}
}
txt=txt.replace(" ", " ");
}
}
return txt;
}
MTplainTextNode::MTplainTextNode(JKQTMathText *_parent, const QString& _text, bool addWhitespace, bool stripInnerWhitepace):
JKQTMathTextTextNode(_parent, _text, addWhitespace, stripInnerWhitepace)
{
}
QString MTplainTextNode::getTypeName() const
{
return QLatin1String("MTplainTextNode(")+text+")";
}
QString MTplainTextNode::textTransform(const QString &_text, JKQTMathTextEnvironment /*currentEv*/, bool /*forSize*/)
{
return _text;
}
JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(JKQTMathText *_parent):
JKQTMathTextTextNode(_parent, " ", false, false)
{
}
JKQTMathTextWhitespaceNode::~JKQTMathTextWhitespaceNode()
= default;
QString JKQTMathTextWhitespaceNode::getTypeName() const
{
return QLatin1String("JKQTMathTextWhitespaceNode(")+text+")";
}
bool JKQTMathTextWhitespaceNode::toHtml(QString &html, JKQTMathTextEnvironment /*currentEv*/, JKQTMathTextEnvironment /*defaultEv*/) {
html=html+"&nbsp;";
return true;
}

View File

@ -0,0 +1,93 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTMATHTEXTTEXTNODE_H
#define JKQTMATHTEXTTEXTNODE_H
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
#include <QPainter>
class JKQTMathText; // forward
// JKQTMATHTEXT_LIB_EXPORT
/** \brief subclass representing one text node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTextNode: public JKQTMathTextNode {
public:
explicit JKQTMathTextTextNode(JKQTMathText* parent, const QString& text, bool addWhitespace, bool stripInnerWhitepace=false);
virtual ~JKQTMathTextTextNode() override;
/** \copydoc JKQTMathTextNode::draw() */
virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
/** \copydoc text */
QString getText() const;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override ;
protected:
/** \copydoc JKQTMathTextNode::getSizeInternal() */
virtual void getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize=nullptr) override;
/** \brief text-contents of the node */
QString text;
/** \brief transforms the text before sizing/drawing (may e.g. exchange special letters for other unicode symbols etc.) */
virtual QString textTransform(const QString& text, JKQTMathTextEnvironment currentEv, bool forSize=false);
};
/** \brief subclass representing one text node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT MTplainTextNode: public JKQTMathTextTextNode {
public:
explicit MTplainTextNode(JKQTMathText* parent, const QString& text, bool addWhitespace, bool stripInnerWhitepace=false);
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
protected:
/** \copydoc JKQTMathTextTextNode::textTransform() */
virtual QString textTransform(const QString& text, JKQTMathTextEnvironment currentEv, bool forSize=false) override;
};
/** \brief subclass representing one whitepsace node in the syntax tree
* \ingroup jkqtmathtext_items
*/
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextWhitespaceNode: public JKQTMathTextTextNode {
public:
explicit JKQTMathTextWhitespaceNode(JKQTMathText* parent);
virtual ~JKQTMathTextWhitespaceNode() override;
/** \copydoc JKQTMathTextNode::getTypeName() */
virtual QString getTypeName() const override;
/** \copydoc JKQTMathTextNode::toHtml() */
virtual bool toHtml(QString& html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) override;
};
#endif // JKQTMATHTEXTTEXTNODE_H