mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-11-15 10:05:47 +08:00
JKQTMathText:
- NEW: JKQTMathTextVerticalListNode allows to typeset a vertical list of lines - NEW: added \substack[lcr]{...\\...}, \lsubstack{...\\...}, \rsubstack{...\\...} instructions
This commit is contained in:
parent
edd7784d47
commit
326ba7313c
@ -46,7 +46,6 @@ This page lists several todos and wishes for future version of JKQTPlotter
|
||||
<li>explore options to make font-environment-modifying commands avails, like "{blacktext\\color{red}redtext}", today only commands like "\\textcolor{red}{redtext}" work</li>
|
||||
<li>maybe: add support for text with linebreaks by adding a JKQTMathTextVerticalListNode in addition to JKQTMathTextListNode</li>
|
||||
<li>maybe: add tool programs to auto-generate some example images</li>
|
||||
<li>add support for \\substack command below \\sum etc.</li>
|
||||
<li>improve support for array-environment with limited support for formatting string like l|r|c and maybe add support for \\hline command, possibly also \\cellcolor etz.</li>
|
||||
<li></li>
|
||||
</ul></li>
|
||||
|
@ -68,6 +68,8 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
||||
<li>NEW: added functions to set the font-size in pixels (as alternative to the existing functions that set them in points), implements request <a href="https://github.com/jkriege2/JKQtPlotter/issues/76">#76</a> from <a href="https://github.com/igormironchik">user:igormironchik</a> </li>
|
||||
<li>NEW: added \c \\userfont{SystemFontName}{Text} instruction</li>
|
||||
<li>NEW: added \c \\unicode{HEX} and \c \\utfeight{HEX} instruction to draw unicide characters by code</li>
|
||||
<li>NEW: JKQTMathTextVerticalListNode allows to typeset a vertical list of lines</li>
|
||||
<li>NEW: added \c \\substack[lcr]{...\\\\...} , \c \\lsubstack{...\\\\...} , \c \\rsubstack{...\\\\...} instructions</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
|
BIN
doc/images/jkqtmathtext/jkqtmathtext_horizontalalignment.cdr
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_horizontalalignment.cdr
Normal file
Binary file not shown.
BIN
doc/images/jkqtmathtext/jkqtmathtext_horizontalalignment.png
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_horizontalalignment.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_lsubstack.png
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_lsubstack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_rsubstack.png
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_rsubstack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_substack.png
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_substack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_verticalalignment.png
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_verticalalignment.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_verticallist.cdr
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_verticallist.cdr
Normal file
Binary file not shown.
BIN
doc/images/jkqtmathtext/jkqtmathtext_verticallist.png
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_verticallist.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
BIN
doc/images/jkqtmathtext/jkqtmathtext_verticalorientation.cdr
Normal file
BIN
doc/images/jkqtmathtext/jkqtmathtext_verticalorientation.cdr
Normal file
Binary file not shown.
@ -178,28 +178,22 @@ TestForm::TestForm(QWidget *parent) :
|
||||
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}$");
|
||||
ui->cmbTestset->addItem("math 3", "$\\mbox{det} \\begin{pmatrix} 1 & x_1 & \\ldots & x_1^{n-1} \\\\ 1 & x_2 & \\ldots & x_2^{n-1} \\\\ \\vdots & \\vdots & \\ddots & \\vdots \\\\ 1 & x_n & \\ldots & x_n^{n-1} \\end{pmatrix} = \\prod_{1 \\leq i < j \\leq n} (x_j - x_i) $");
|
||||
ui->cmbTestset->addItem("math: nestes sqrt", "$\\sqrt{1+\\sqrt{1+\\sqrt{1+\\sqrt{1+\\sqrt{1+\\sqrt{1+x}}}}}}$");
|
||||
ui->cmbTestset->addItem("math: nestes cbrt", "$\\sqrt[3]{1+\\sqrt[3]{1+\\sqrt[3]{1+\\sqrt[3]{1+\\sqrt[3]{1+\\sqrt[3]{1+x}}}}}}$");
|
||||
ui->cmbTestset->addItem("math: nestes sqrt, high contents", "$\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+x}}}}}}$");
|
||||
ui->cmbTestset->addItem("math 5 (frac+stackrel)", "$\\left(\\stackrel{p}{2}\\right)=x^2y^{p-2}-\\frac{1}{1-x}\\frac{1}{1-x^2}$");
|
||||
ui->cmbTestset->addItem("math 6 (nested frac)", "$a_0+\\frac{1}{a_1+\\frac{1}{a_2+\\frac{1}{a_3+\\frac{1}{a_4}}}}$");
|
||||
ui->cmbTestset->addItem("math 7 (partial derivatives)", "$\\left(\\frac{\\partial^2}{\\partial x^2}+\\frac{\\partial^2}{\\partial y^2}\\right)\\left|\\varphi(x+\\mathrm{i}y)\\right|^2=0$");
|
||||
ui->cmbTestset->addItem("math 8 (powers of powers)", "$2^{2^{2^{x}}}$");
|
||||
ui->cmbTestset->addItem("math 9 (integral)", "$\\iint_Df(x,y)\\;\\mathrm{d}x\\;\\mathrm{d}y$");
|
||||
ui->cmbTestset->addItem("math 10 (overbrace+overbracket)", "$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}\\ \\ \\ \\overbracket{x+x+...+x}{k\\ \\mathrm{times}}$");
|
||||
ui->cmbTestset->addItem("math 11 (underbrace+underbracket)", "$\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}\\ \\ \\ \\underbracket{x+x+...+x}{k\\ \\mathrm{times}}$");
|
||||
ui->cmbTestset->addItem("math 12 (under/overbrace+under/overbracket)", "$\\underbrace{\\overbrace{x+x+...+x}{k\\ \\mathrm{times}} \\overbrace{x+x+...+x}{k\\ \\mathrm{times}}}{2k\\ \\mathrm{times}}\\ \\ \\ \\underbracket{\\overbracket{x+x+...+x}{k\\ \\mathrm{times}} \\overbracket{x+x+...+x}{k\\ \\mathrm{times}}}{2k\\ \\mathrm{times}}$");
|
||||
ui->cmbTestset->addItem("math 13", "$y_1''\\ \\ \\ y_2'''$");
|
||||
ui->cmbTestset->addItem("math 14", "$f(x)=\\begin{cases} 1/3 & \\mathrm{if}\\ 0\\leq x\\leq1 \\\\ 2/3 & \\mathrm{if}\\ 3\\leq x\\leq4 \\\\0 & \\mathrm{elsewhere} \\end{cases}$");
|
||||
ui->cmbTestset->addItem("math 15", "$\\Re(z) =\\frac{n\\pi \\dfrac{\\theta +\\psi}{2}}{\\left(\\dfrac{\\theta +\\psi}{2}\\right)^2 + \\left( \\dfrac{1}{2}\\log \\left\\lvert\\dfrac{B}{A}\\right\\rvert\\right)^2}.$");
|
||||
ui->cmbTestset->addItem("math 16", "$\\sum_{m=1}^\\infty\\sum_{n=1}^\\infty\\frac{m^2\\,n}{3^m\\left(m\\,3^n+n\\,3^m\\right)}$");
|
||||
ui->cmbTestset->addItem("math 17", "$\\phi_n(\\kappa) =\\frac{1}{4\\pi^2\\kappa^2} \\int_0^\\infty\\frac{\\sin(\\kappa R)}{\\kappa R}\\frac{\\partial}{\\partial R}\\left[R^2\\frac{\\partial D_n(R)}{\\partial R}\\right]\\,dR$");
|
||||
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("math: nested sqrt", "$\\sqrt{1+\\sqrt{1+\\sqrt{1+\\sqrt{1+\\sqrt{1+\\sqrt{1+x}}}}}}$");
|
||||
ui->cmbTestset->addItem("math: nested cbrt", "$\\sqrt[3]{1+\\sqrt[3]{1+\\sqrt[3]{1+\\sqrt[3]{1+\\sqrt[3]{1+\\sqrt[3]{1+x}}}}}}$");
|
||||
ui->cmbTestset->addItem("math: nested sqrt, high contents", "$\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+\\sqrt{\\frac{1}{2}+x}}}}}}$");
|
||||
ui->cmbTestset->addItem("math: frac+stackrel", "$\\left(\\stackrel{p}{2}\\right)=x^2y^{p-2}-\\frac{1}{1-x}\\frac{1}{1-x^2}$");
|
||||
ui->cmbTestset->addItem("math: nested frac", "$a_0+\\frac{1}{a_1+\\frac{1}{a_2+\\frac{1}{a_3+\\frac{1}{a_4}}}}$");
|
||||
ui->cmbTestset->addItem("math: partial derivatives", "$\\left(\\frac{\\partial^2}{\\partial x^2}+\\frac{\\partial^2}{\\partial y^2}\\right)\\left|\\varphi(x+\\mathrm{i}y)\\right|^2=0$");
|
||||
ui->cmbTestset->addItem("math: powers of powers", "$2^{2^{2^{x}}}$");
|
||||
ui->cmbTestset->addItem("math: double-integral", "$\\iint_Df(x,y)\\;\\mathrm{d}x\\;\\mathrm{d}y$");
|
||||
ui->cmbTestset->addItem("math: overbrace+overbracket", "$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}\\ \\ \\ \\overbracket{x+x+...+x}{k\\ \\mathrm{times}}$");
|
||||
ui->cmbTestset->addItem("math: underbrace+underbracket", "$\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}\\ \\ \\ \\underbracket{x+x+...+x}{k\\ \\mathrm{times}}$");
|
||||
ui->cmbTestset->addItem("math: under/overbrace+under/overbracket", "$\\underbrace{\\overbrace{x+x+...+x}{k\\ \\mathrm{times}} \\overbrace{x+x+...+x}{k\\ \\mathrm{times}}}{2k\\ \\mathrm{times}}\\ \\ \\ \\underbracket{\\overbracket{x+x+...+x}{k\\ \\mathrm{times}} \\overbracket{x+x+...+x}{k\\ \\mathrm{times}}}{2k\\ \\mathrm{times}}$");
|
||||
ui->cmbTestset->addItem("math: apostrophy/prime derivatives", "$y_1'\\ y_2''\\ y_3'''\\ \\ \\ --\\ \\ \\ y_1^\\prime\\ y_2^\\dprime\\ y_3^\\trprime\\ \\ \\ --\\ \\ \\ y_1^\\prime\\ y_2^{\\prime\\prime}\\ y_3^{\\prime\\prime\\prime}$");
|
||||
ui->cmbTestset->addItem("math: cases", "$f(x)=\\begin{cases} 1/3 & \\mathrm{if}\\ 0\\leq x\\leq1 \\\\ 2/3 & \\mathrm{if}\\ 3\\leq x\\leq4 \\\\0 & \\mathrm{elsewhere} \\end{cases}$");
|
||||
ui->cmbTestset->addItem("math: 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: 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("math: substack", "substack: $\\substack{i=0\\\\\\sin(x)\\equiv\\pi\\\\a=a\\\\a=b}$\\ \\ \\ substack[l]: $\\substack[l]{i=0\\\\\\sin(x)\\equiv\\pi\\\\a=a\\\\a=b}$\\ \\ \\ lsubstack: $\\lsubstack{i=0\\\\\\sin(x)\\equiv\\pi\\\\a=a\\\\a=b}$\\ \\ \\ rsubstack: $\\rsubstack{i=0\\\\\\sin(x)\\equiv\\pi\\\\a=a\\\\a=b}$\\ \\ \\ comma: $\\sum\\limits_{0\\leq i\\leq 10, -5\\leq j\\leq100}f_{i,j}$\\ \\ \\ substack: $\\sum\\limits_\\substack{0\\leq i\\leq 10\\\\ -5\\leq j\\leq100}f_{i,j}$\\ \\ \\ rsubstack: $\\sum\\limits_\\rsubstack{0\\leq i\\leq 10\\\\ -5\\leq j\\leq100}f_{i,j}$");
|
||||
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$");
|
||||
@ -229,6 +223,13 @@ TestForm::TestForm(QWidget *parent) :
|
||||
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("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}$");
|
||||
ui->cmbTestset->addItem("math 3", "$\\mbox{det} \\begin{pmatrix} 1 & x_1 & \\ldots & x_1^{n-1} \\\\ 1 & x_2 & \\ldots & x_2^{n-1} \\\\ \\vdots & \\vdots & \\ddots & \\vdots \\\\ 1 & x_n & \\ldots & x_n^{n-1} \\end{pmatrix} = \\prod_{1 \\leq i < j \\leq n} (x_j - x_i) $");
|
||||
ui->cmbTestset->addItem("math 4", "$\\Re(z) =\\frac{n\\pi \\dfrac{\\theta +\\psi}{2}}{\\left(\\dfrac{\\theta +\\psi}{2}\\right)^2 + \\left( \\dfrac{1}{2}\\log \\left\\lvert\\dfrac{B}{A}\\right\\rvert\\right)^2}.$");
|
||||
ui->cmbTestset->addItem("math 5", "$\\sum_{m=1}^\\infty\\sum_{n=1}^\\infty\\frac{m^2\\,n}{3^m\\left(m\\,3^n+n\\,3^m\\right)}$");
|
||||
ui->cmbTestset->addItem("math 6", "$\\phi_n(\\kappa) =\\frac{1}{4\\pi^2\\kappa^2} \\int_0^\\infty\\frac{\\sin(\\kappa R)}{\\kappa R}\\frac{\\partial}{\\partial R}\\left[R^2\\frac{\\partial D_n(R)}{\\partial R}\\right]\\,dR$");
|
||||
ui->cmbTestset->addItem("math 7", "${}_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("User-Editable Text");
|
||||
//
|
||||
//ui->cmbTestset->addItem("", "$$");
|
||||
@ -429,7 +430,8 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
|
||||
JKQTMathTextTextNode* txtN=dynamic_cast<JKQTMathTextTextNode*>(node);
|
||||
JKQTMathTextWhitespaceNode* spN=dynamic_cast<JKQTMathTextWhitespaceNode*>(node);
|
||||
JKQTMathTextSymbolNode* symN=dynamic_cast<JKQTMathTextSymbolNode*>(node);
|
||||
JKQTMathTextListNode* lstN=dynamic_cast<JKQTMathTextListNode*>(node);
|
||||
JKQTMathTextHorizontalListNode* lstN=dynamic_cast<JKQTMathTextHorizontalListNode*>(node);
|
||||
JKQTMathTextVerticalListNode* lstNV=dynamic_cast<JKQTMathTextVerticalListNode*>(node);
|
||||
JKQTMathTextModifiedTextPropsInstructionNode* inst1N=dynamic_cast<JKQTMathTextModifiedTextPropsInstructionNode*>(node);
|
||||
JKQTMathTextBoxInstructionNode* inst1B=dynamic_cast<JKQTMathTextBoxInstructionNode*>(node);
|
||||
JKQTMathTextSimpleInstructionNode* instS=dynamic_cast<JKQTMathTextSimpleInstructionNode*>(node);
|
||||
@ -488,11 +490,17 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p
|
||||
name=QString("BoxInstructionNode: \'%1\' (subsuper=%2, params=%3)").arg(inst1B->getInstructionName()).arg(inst1B->isSubSuperscriptAboveBelowNode()).arg(inst1B->getParameters().join("/"));
|
||||
if (inst1B->getChild()) ti->addChild(createTree(inst1B->getChild(), ti));
|
||||
} else if (lstN) {
|
||||
name=QString("MTlistNode");
|
||||
name=QString("HListNode");
|
||||
QList<JKQTMathTextNode*> list=lstN->getChildren();
|
||||
for (int i=0; i<list.size(); i++) {
|
||||
ti->addChild(createTree(list[i], ti));
|
||||
}
|
||||
} else if (lstNV) {
|
||||
name=QString("VListNode (align=%1, spacingFactor=%2x, spacingMode=%3, verticalOrientation=%4)").arg(JKQTMathTextHorizontalAlignment2String(lstNV->getAlignment())).arg(lstNV->getLineSpacingFactor()).arg(lstNV->SpacingMode2String(lstNV->getSpacingMode())).arg(JKQTMathTextVerticalOrientation2String(lstNV->getVerticalOrientation()));
|
||||
QList<JKQTMathTextNode*> list=lstNV->getChildren();
|
||||
for (int i=0; i<list.size(); i++) {
|
||||
ti->addChild(createTree(list[i], ti));
|
||||
}
|
||||
} else if (symN) {
|
||||
name=QString("MTSymbolNode: \'%1\' (subsuper=%3)").arg(symN->getSymbolName()).arg(symN->isSubSuperscriptAboveBelowNode());
|
||||
} else if (spN) {
|
||||
|
@ -1300,6 +1300,13 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
|
||||
if (currentTokenID>=parseString.size()-1) return currentToken=MTTnone;
|
||||
c=parseString[currentTokenID];
|
||||
//----------------------------------------------------------
|
||||
// recognize linebreak "\\"
|
||||
if (c=='\\') {
|
||||
currentTokenName=c; // parse one-symbol instructions like \\, \& ...
|
||||
//std::cout<<"found text node '"<<currentTokenName.toStdString()<<"'\n";
|
||||
return currentToken=MTTinstructionNewline;
|
||||
}
|
||||
//----------------------------------------------------------
|
||||
// parsing single-character instruction
|
||||
if (SingleCharInstructions.contains(c)) {
|
||||
currentTokenName=c; // parse one-symbol instructions like \\, \& ...
|
||||
@ -1318,6 +1325,8 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
|
||||
}
|
||||
//std::cout<<"found instruction node '"<<currentTokenName.toStdString()<<"'\n";
|
||||
if (currentTokenName.size()==0) error_list.append(tr("error @ ch. %1: parser encountered empty istruction").arg(currentTokenID));
|
||||
if (currentTokenName=="newline") return MTTinstructionNewline;
|
||||
if (currentTokenName=="linebreak") return MTTinstructionNewline;
|
||||
return currentToken=MTTinstruction;
|
||||
//----------------------------------------------------------
|
||||
// check for $ character
|
||||
@ -1425,7 +1434,7 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
|
||||
|
||||
JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType quitOnClosingBrace, const QString& quitOnEnvironmentEnd, bool quitOnClosingBracket) {
|
||||
//std::cout<<" entering parseLatexString()\n";
|
||||
JKQTMathTextListNode* nl=new JKQTMathTextListNode(this);
|
||||
JKQTMathTextHorizontalListNode* nl=new JKQTMathTextHorizontalListNode(this);
|
||||
if (get) getToken();
|
||||
|
||||
//----------------------------------------------------------
|
||||
@ -1469,6 +1478,8 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
|
||||
} else {
|
||||
nl->addChild(new JKQTMathTextTextNode(this, text, addWhite, parsingMathEnvironment));
|
||||
}
|
||||
} else if (currentToken==MTTinstructionNewline) {
|
||||
break;
|
||||
} else if (currentToken==MTTwhitespace) {
|
||||
if (!parsingMathEnvironment) nl->addChild(new JKQTMathTextWhitespaceNode(this));
|
||||
} else if (currentToken==MTTinstruction) {
|
||||
@ -1489,7 +1500,7 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType
|
||||
bool first=true;
|
||||
QVector<JKQTMathTextNode*> line;
|
||||
//std::cout<<"found \\begin{matrix}\n";
|
||||
while (first || currentToken==MTTampersand || (currentToken==MTTinstruction && currentTokenName=="\\")) {
|
||||
while (first || currentToken==MTTampersand || currentToken==MTTinstructionNewline) {
|
||||
JKQTMathTextNode* it=parseLatexString(true, MTBTAny, envname);
|
||||
if (currentToken==MTTampersand) {
|
||||
//std::cout<<" appending item\n";
|
||||
@ -1736,6 +1747,31 @@ JKQTMathTextNode* JKQTMathText::parseInstruction(bool *_foundError, bool* getNew
|
||||
if (foundError){
|
||||
error_list.append(tr("error @ ch. %1: expected %3 arguments in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(Nparams+1));
|
||||
}
|
||||
} else if (currentInstructionName=="substack" || currentInstructionName=="rsubstack" || currentInstructionName=="lsubstack") {
|
||||
getToken();
|
||||
JKQTMathTextHorizontalAlignment alignment=MTHACentered;
|
||||
if (currentInstructionName=="rsubstack") alignment=MTHARight;
|
||||
if (currentInstructionName=="lsubstack") alignment=MTHALeft;
|
||||
|
||||
if (currentToken==MTTopenbracket) {
|
||||
alignment=String2JKQTMathTextHorizontalAlignment(parseSingleString(true));
|
||||
if (currentToken!=MTTclosebracket) {
|
||||
error_list.append(tr("error @ ch. %1: didn't find closing brace ']' after '\\%2[]{}' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
|
||||
}
|
||||
getToken();
|
||||
}
|
||||
if (currentToken==MTTopenbrace) {
|
||||
JKQTMathTextVerticalListNode* vlist = new JKQTMathTextVerticalListNode(this, alignment, 1.0, JKQTMathTextVerticalListNode::SMMinimal, MTVOFirstLine );
|
||||
child=vlist;
|
||||
bool first=true;
|
||||
while (first || currentToken==MTTinstructionNewline) {
|
||||
vlist->addChild(parseLatexString(true));
|
||||
first=false;
|
||||
}
|
||||
if (currentToken!=MTTclosebrace) error_list.append(tr("error @ ch. %1: didn't find closing brace '}' after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
|
||||
} else {
|
||||
error_list.append(tr("error @ ch. %1: expected one argument in '{...}' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName).arg(1));
|
||||
}
|
||||
} else if (currentInstructionName=="sqrt") {
|
||||
getToken();
|
||||
if (currentToken==MTTopenbrace) {
|
||||
@ -1850,6 +1886,25 @@ QStringList JKQTMathText::parseStringParams(bool get, size_t Nparams, bool *foun
|
||||
}
|
||||
}
|
||||
|
||||
QString JKQTMathText::parseSingleString(bool get) {
|
||||
const bool old_parsingMathEnvironment=parsingMathEnvironment;
|
||||
auto reset_parsingMathEnvironment=JKQTPFinally([&]() { parsingMathEnvironment=old_parsingMathEnvironment; });
|
||||
bool ok=true;
|
||||
QString thisparam="";
|
||||
while (ok) {
|
||||
if (get) getToken();
|
||||
get=true;
|
||||
if (currentToken==MTTtext) {
|
||||
thisparam+=currentTokenName;
|
||||
} else if (currentToken==MTTwhitespace) {
|
||||
thisparam+=" ";
|
||||
} else {
|
||||
ok=false;
|
||||
}
|
||||
}
|
||||
return thisparam;
|
||||
}
|
||||
|
||||
|
||||
JKQTMathTextNode *JKQTMathText::getParsedNode() const {
|
||||
return this->parsedNode;
|
||||
|
@ -802,6 +802,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
MTTnone, /*!< \brief no token */
|
||||
MTTtext, /*!< \brief a piece of general text */
|
||||
MTTinstruction, /*!< \brief an instruction, started by \c "\\", e.g. \c "\\textbf", ... */
|
||||
MTTinstructionNewline, /*!< \brief a newline instruction \c "\\\\" */
|
||||
MTTunderscore, /*!< \brief the character \c "_" */
|
||||
MTThat, /*!< \brief the character \c "^" */
|
||||
MTTdollar, /*!< \brief the character \c "$" */
|
||||
@ -810,7 +811,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
MTTopenbracket, /*!< \brief the character \c "[" */
|
||||
MTTclosebracket, /*!< \brief the character \c "]" */
|
||||
MTTwhitespace, /*!< \brief some whitespace */
|
||||
MTTampersand /*!< \brief the character \c "&" */
|
||||
MTTampersand, /*!< \brief the character \c "&" */
|
||||
};
|
||||
|
||||
/** \brief tokenizer for the LaTeX parser */
|
||||
@ -831,6 +832,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
* \return the list of parameter strings with Nparam entries or an empty or partial list on error
|
||||
*/
|
||||
QStringList parseStringParams(bool get, size_t Nparams, bool *foundError=nullptr);
|
||||
/** \brief parses a string, i.e. a sequence of text and whitespaces. returns after any other token was found */
|
||||
QString parseSingleString(bool get);
|
||||
/** \brief parses a single instruction (including it's parameters)
|
||||
*
|
||||
* \param[out] _foundError will be set to \c true if an error occured (unexpected token) or \c false otherwise
|
||||
|
@ -767,3 +767,45 @@ JKQTMathTextFontEncoding estimateJKQTMathTextFontEncoding(QFont font)
|
||||
if (fm.inFont(QChar(0x2208))) return JKQTMathTextFontEncoding::MTFEUnicode; // element
|
||||
return JKQTMathTextFontEncoding::MTFELatin1;
|
||||
}
|
||||
|
||||
QString JKQTMathTextHorizontalAlignment2String(JKQTMathTextHorizontalAlignment type)
|
||||
{
|
||||
switch(type) {
|
||||
case MTHALeft: return "left";
|
||||
case MTHARight: return "right";
|
||||
default:
|
||||
case MTHACentered: return "centered";
|
||||
}
|
||||
}
|
||||
|
||||
JKQTMathTextHorizontalAlignment String2JKQTMathTextHorizontalAlignment(QString tokenName)
|
||||
{
|
||||
tokenName=tokenName.toLower().trimmed();
|
||||
if (tokenName=="l" || tokenName=="left") return MTHALeft;
|
||||
if (tokenName=="r" || tokenName=="right") return MTHARight;
|
||||
if (tokenName=="c" || tokenName=="center" || tokenName=="centered") return MTHACentered;
|
||||
return MTHACentered;
|
||||
}
|
||||
|
||||
QString JKQTMathTextVerticalOrientation2String(JKQTMathTextVerticalOrientation mode)
|
||||
{
|
||||
switch(mode) {
|
||||
case MTVOTop: return "top";
|
||||
case MTVOCentered: return "centered";
|
||||
case MTVOLastLine: return "last_line";
|
||||
case MTVOBottom: return "bottom";
|
||||
default:
|
||||
case MTVOFirstLine: return "first_line";
|
||||
}
|
||||
}
|
||||
|
||||
JKQTMathTextVerticalOrientation String2JKQTMathTextVerticalOrientation(QString tokenName)
|
||||
{
|
||||
tokenName=tokenName.toLower().trimmed();
|
||||
if (tokenName=="p" || tokenName=="first_line" || tokenName=="first-line" || tokenName=="firstline" || tokenName=="line1") return MTVOFirstLine;
|
||||
if (tokenName=="last_line" || tokenName=="last-line" || tokenName=="lastline" || tokenName=="linen") return MTVOLastLine;
|
||||
if (tokenName=="t" || tokenName=="top") return MTVOTop;
|
||||
if (tokenName=="b" || tokenName=="bottom") return MTVOBottom;
|
||||
if (tokenName=="c" || tokenName=="center" || tokenName=="centered") return MTVOCentered;
|
||||
return MTVOCentered;
|
||||
}
|
||||
|
@ -385,6 +385,52 @@ JKQTMATHTEXT_LIB_EXPORT QRectF JKQTMathTextGetTightBoundingRect(const QFont &fm,
|
||||
JKQTMATHTEXT_LIB_EXPORT QFont JKQTMathTextGetNonItalic(const QFont& f);
|
||||
|
||||
|
||||
/** \brief types of horizontal alignment
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \image html jkqtmathtext_horizontalalignment.png
|
||||
*
|
||||
* \see JKQTMathTextVerticalOrientation2String(), String2JKQTMathTextVerticalOrientation(), JKQTMathTextVerticalListNode
|
||||
*/
|
||||
enum JKQTMathTextHorizontalAlignment {
|
||||
MTHALeft, /*!< \brief align left */
|
||||
MTHACentered, /*!< \brief align centered */
|
||||
MTHARight, /*!< \brief align right */
|
||||
};
|
||||
/** \brief convert a JKQTMathTextHorizontalAlignment into a string
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextHorizontalAlignment2String(JKQTMathTextHorizontalAlignment type);
|
||||
/** \brief convert a string \a tokenName into a JKQTMathTextHorizontalAlignment
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextHorizontalAlignment String2JKQTMathTextHorizontalAlignment(QString tokenName);
|
||||
|
||||
/** \brief type of ffractions represented by JKQTMathTextFracNode
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \image html jkqtmathtext_verticalorientation.png
|
||||
*
|
||||
* \see JKQTMathTextVerticalOrientation2String(), String2JKQTMathTextVerticalOrientation(), JKQTMathTextVerticalListNode
|
||||
*/
|
||||
enum JKQTMathTextVerticalOrientation {
|
||||
MTVOTop, /*!< \brief baseline of the whole block is at the top of the first */
|
||||
MTVOFirstLine, /*!< \brief baseline of the whole block is at the baseline of the first line */
|
||||
MTVOCentered, /*!< \brief baseline of the whole block is at the center of all lines */
|
||||
MTVOLastLine, /*!< \brief baseline of the whole block is at the baseline of the last line */
|
||||
MTVOBottom, /*!< \brief baseline of the whole block is at the bottom of the last line */
|
||||
};
|
||||
|
||||
/** \brief convert a JKQTMathTextVerticalOrientation into a QString
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextVerticalOrientation2String(JKQTMathTextVerticalOrientation mode);
|
||||
|
||||
/** \brief returns the JKQTMathTextVerticalOrientation corresponding to \a instructionName
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerticalOrientation String2JKQTMathTextVerticalOrientation(QString mode);
|
||||
|
||||
#endif // JKQTMATHTEXTTOOLS_H
|
||||
|
||||
|
||||
|
@ -36,23 +36,23 @@
|
||||
#include <QFont>
|
||||
|
||||
|
||||
JKQTMathTextListNode::JKQTMathTextListNode(JKQTMathText* _parent):
|
||||
JKQTMathTextHorizontalListNode::JKQTMathTextHorizontalListNode(JKQTMathText* _parent):
|
||||
JKQTMathTextMultiChildNode(_parent)
|
||||
{
|
||||
nodes.clear();
|
||||
// these operations cause sub/sup script to be typeset over/under the operator, not right besides!
|
||||
}
|
||||
|
||||
JKQTMathTextListNode::~JKQTMathTextListNode() {
|
||||
JKQTMathTextHorizontalListNode::~JKQTMathTextHorizontalListNode() {
|
||||
clearChildrenImpl(true);
|
||||
}
|
||||
|
||||
QString JKQTMathTextListNode::getTypeName() const
|
||||
QString JKQTMathTextHorizontalListNode::getTypeName() const
|
||||
{
|
||||
return "MTlistNode";
|
||||
return "MTHorizontalListNode";
|
||||
}
|
||||
|
||||
void JKQTMathTextListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
|
||||
void JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
|
||||
width=0;
|
||||
overallHeight=0;
|
||||
baselineHeight=0;
|
||||
@ -326,7 +326,7 @@ void JKQTMathTextListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro
|
||||
width=xnew;
|
||||
}
|
||||
|
||||
double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
|
||||
double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
double ynew=y;
|
||||
double xnew=x;
|
||||
@ -512,12 +512,12 @@ double JKQTMathTextListNode::draw(QPainter& painter, double x, double y, JKQTMat
|
||||
return xnew;
|
||||
}
|
||||
|
||||
void JKQTMathTextListNode::addChild(JKQTMathTextNode *n) {
|
||||
void JKQTMathTextHorizontalListNode::addChild(JKQTMathTextNode *n) {
|
||||
n->setParentNode(this);
|
||||
nodes.append(n);
|
||||
}
|
||||
|
||||
bool JKQTMathTextListNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
|
||||
bool JKQTMathTextHorizontalListNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
|
||||
bool ok=true;
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
QString h="";
|
||||
@ -527,18 +527,18 @@ bool JKQTMathTextListNode::toHtml(QString &html, JKQTMathTextEnvironment current
|
||||
return ok;
|
||||
}
|
||||
|
||||
QList<JKQTMathTextNode *> JKQTMathTextListNode::getChildren() {
|
||||
QList<JKQTMathTextNode *> JKQTMathTextHorizontalListNode::getChildren() {
|
||||
return this->nodes;
|
||||
}
|
||||
|
||||
|
||||
int JKQTMathTextListNode::childCount() const
|
||||
int JKQTMathTextHorizontalListNode::childCount() const
|
||||
{
|
||||
return nodes.size();
|
||||
}
|
||||
|
||||
|
||||
void JKQTMathTextListNode::clearChildrenImpl(bool deleteChildren)
|
||||
void JKQTMathTextHorizontalListNode::clearChildrenImpl(bool deleteChildren)
|
||||
{
|
||||
if (deleteChildren) {
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
@ -548,22 +548,22 @@ void JKQTMathTextListNode::clearChildrenImpl(bool deleteChildren)
|
||||
nodes.clear();
|
||||
}
|
||||
|
||||
void JKQTMathTextListNode::clearChildren(bool deleteChildren)
|
||||
void JKQTMathTextHorizontalListNode::clearChildren(bool deleteChildren)
|
||||
{
|
||||
clearChildrenImpl(deleteChildren);
|
||||
}
|
||||
|
||||
JKQTMathTextNode *JKQTMathTextListNode::getChild(int i)
|
||||
JKQTMathTextNode *JKQTMathTextHorizontalListNode::getChild(int i)
|
||||
{
|
||||
return nodes[i];
|
||||
}
|
||||
|
||||
const JKQTMathTextNode *JKQTMathTextListNode::getChild(int i) const
|
||||
const JKQTMathTextNode *JKQTMathTextHorizontalListNode::getChild(int i) const
|
||||
{
|
||||
return nodes[i];
|
||||
}
|
||||
|
||||
JKQTMathTextNode *JKQTMathTextListNode::replaceChild(int i, JKQTMathTextNode *newChild)
|
||||
JKQTMathTextNode *JKQTMathTextHorizontalListNode::replaceChild(int i, JKQTMathTextNode *newChild)
|
||||
{
|
||||
JKQTMathTextNode* c=nodes[i];
|
||||
nodes[i]=newChild;
|
||||
@ -571,3 +571,229 @@ JKQTMathTextNode *JKQTMathTextListNode::replaceChild(int i, JKQTMathTextNode *ne
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
QString JKQTMathTextVerticalListNode::SpacingMode2String(SpacingMode mode)
|
||||
{
|
||||
switch(mode) {
|
||||
case SMMinimal: return "minimal";
|
||||
default:
|
||||
case SMDefault: return "default";
|
||||
}
|
||||
}
|
||||
|
||||
JKQTMathTextVerticalListNode::SpacingMode JKQTMathTextVerticalListNode::String2SpacingMode(QString tokenName)
|
||||
{
|
||||
tokenName=tokenName.toLower().trimmed();
|
||||
if (tokenName=="default") return SMDefault;
|
||||
if (tokenName=="minimal" || tokenName=="min" || tokenName=="minimum") return SMMinimal;
|
||||
return SMDefault;
|
||||
}
|
||||
|
||||
JKQTMathTextVerticalListNode::JKQTMathTextVerticalListNode(JKQTMathText *_parent, JKQTMathTextHorizontalAlignment _alignment, double _linespacingFactor, SpacingMode spacingMode_, JKQTMathTextVerticalOrientation _verticalOrientation):
|
||||
JKQTMathTextMultiChildNode(_parent),
|
||||
alignment(_alignment),
|
||||
lineSpacingFactor(_linespacingFactor),
|
||||
verticalOrientation(_verticalOrientation),
|
||||
spacingMode(spacingMode_)
|
||||
{
|
||||
nodes.clear();
|
||||
// these operations cause sub/sup script to be typeset over/under the operator, not right besides!
|
||||
}
|
||||
|
||||
JKQTMathTextVerticalListNode::~JKQTMathTextVerticalListNode() {
|
||||
clearChildrenImpl(true);
|
||||
}
|
||||
|
||||
QString JKQTMathTextVerticalListNode::getTypeName() const
|
||||
{
|
||||
return "MTVerticalListNode";
|
||||
}
|
||||
|
||||
void JKQTMathTextVerticalListNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const JKQTMathTextNodeSize* prevNodeSize) {
|
||||
const LayoutInfo l=calcLayout(painter, currentEv);
|
||||
width=l.width;
|
||||
overallHeight=l.overallHeight;
|
||||
baselineHeight=l.baselineHeight;
|
||||
strikeoutPos=l.strikeoutPos;
|
||||
}
|
||||
|
||||
JKQTMathTextVerticalListNode::LayoutInfo JKQTMathTextVerticalListNode::calcLayout(QPainter &painter, JKQTMathTextEnvironment currentEv)
|
||||
{
|
||||
LayoutInfo l;
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText));
|
||||
const double linespacing=fm.lineSpacing()*lineSpacingFactor;
|
||||
const double fleading=fm.leading();
|
||||
const double synLeading=fm.lineWidth();
|
||||
const double lineLeading=((fabs(fleading)>1e-6)?fleading:synLeading)*lineSpacingFactor;
|
||||
|
||||
if (nodes.size()<=0) {
|
||||
return l;
|
||||
}
|
||||
|
||||
// from now on we have at least one child node!!!
|
||||
|
||||
QList<double> widths, heights, ascents, descents, strikeouts;
|
||||
double heightSum=0;
|
||||
QList<double> ysFromFirstLine; // y-position of each line, where the first line is always at y=0 (i.e. ysFromFirstLine[0]==0)
|
||||
double y=0;
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
double locWidth=0, locOverallHeight=0, locBaselineHeight=0, locStrikeoutPos=0;
|
||||
nodes[i]->getSize(painter, currentEv, locWidth, locBaselineHeight, locOverallHeight, locStrikeoutPos);
|
||||
|
||||
if (i==0) {
|
||||
heightSum=locBaselineHeight;
|
||||
} else if (i>0) {
|
||||
double deltaLine=0;
|
||||
if (spacingMode==SMMinimal) {
|
||||
deltaLine=descents.last()+lineLeading+locBaselineHeight;
|
||||
} else if (spacingMode==SMDefault) {
|
||||
deltaLine=qMax(linespacing, descents.last()+lineLeading+locBaselineHeight);
|
||||
}
|
||||
heightSum=heightSum+deltaLine;
|
||||
y=y+deltaLine;
|
||||
}
|
||||
widths<<locWidth;
|
||||
l.width=qMax(l.width, locWidth);
|
||||
heights<<locOverallHeight;
|
||||
ascents<<locBaselineHeight;
|
||||
descents<<(locOverallHeight-locBaselineHeight);
|
||||
strikeouts<<locStrikeoutPos;
|
||||
ysFromFirstLine<<y;
|
||||
}
|
||||
heightSum+=descents.last();
|
||||
|
||||
l.overallHeight=heightSum;
|
||||
double y0=0;
|
||||
if (verticalOrientation==MTVOTop) {
|
||||
l.baselineHeight=0;
|
||||
l.strikeoutPos=0;
|
||||
y0=ascents.first();
|
||||
} else if (verticalOrientation==MTVOFirstLine) {
|
||||
l.baselineHeight=ascents.first();
|
||||
l.strikeoutPos=strikeouts.first();
|
||||
y0=0;
|
||||
} else if (verticalOrientation==MTVOCentered) {
|
||||
l.baselineHeight=heightSum/2.0;
|
||||
l.strikeoutPos=heightSum/4.0;
|
||||
y0=-heightSum/2.0+ascents.first();
|
||||
} else if (verticalOrientation==MTVOLastLine) {
|
||||
l.baselineHeight=heightSum-descents.last();
|
||||
l.strikeoutPos=strikeouts.last();
|
||||
y0=-(heightSum-ascents.first()-descents.last());
|
||||
} else if (verticalOrientation==MTVOBottom) {
|
||||
l.baselineHeight=heightSum;
|
||||
l.strikeoutPos=0;
|
||||
y0=-(heightSum-ascents.first());
|
||||
}
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
double x=0;
|
||||
if (alignment==MTHARight) x=l.width-widths[i];
|
||||
else if (alignment==MTHACentered) x=(l.width-widths[i])/2.0;
|
||||
l.X<<QPointF(x,ysFromFirstLine[i]+y0);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
double JKQTMathTextVerticalListNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* /*prevNodeSize*/) {
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
const LayoutInfo l=calcLayout(painter, currentEv);
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
nodes[i]->draw(painter, x+l.X.at(i).x(), y+l.X.at(i).y(), currentEv);
|
||||
}
|
||||
return x+l.width;
|
||||
}
|
||||
|
||||
void JKQTMathTextVerticalListNode::addChild(JKQTMathTextNode *n) {
|
||||
n->setParentNode(this);
|
||||
nodes.append(n);
|
||||
}
|
||||
|
||||
bool JKQTMathTextVerticalListNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) {
|
||||
bool ok=true;
|
||||
if (alignment==MTHALeft) {
|
||||
html+="<div align=\"left\">";
|
||||
} else if (alignment==MTHACentered) {
|
||||
html+="<div align=\"center\">";
|
||||
} else if (alignment==MTHARight) {
|
||||
html+="<div align=\"right\">";
|
||||
}
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
QString h="";
|
||||
ok = ok && nodes[i]->toHtml(h, currentEv, defaultEv);
|
||||
if (i==0) html=html+h;
|
||||
else html=html+"<br/>"+h;
|
||||
}
|
||||
html+="</div>";
|
||||
return ok;
|
||||
}
|
||||
|
||||
QList<JKQTMathTextNode *> JKQTMathTextVerticalListNode::getChildren() {
|
||||
return this->nodes;
|
||||
}
|
||||
|
||||
|
||||
int JKQTMathTextVerticalListNode::childCount() const
|
||||
{
|
||||
return nodes.size();
|
||||
}
|
||||
|
||||
|
||||
void JKQTMathTextVerticalListNode::clearChildrenImpl(bool deleteChildren)
|
||||
{
|
||||
if (deleteChildren) {
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
delete nodes[i];
|
||||
}
|
||||
}
|
||||
nodes.clear();
|
||||
}
|
||||
|
||||
void JKQTMathTextVerticalListNode::clearChildren(bool deleteChildren)
|
||||
{
|
||||
clearChildrenImpl(deleteChildren);
|
||||
}
|
||||
|
||||
JKQTMathTextNode *JKQTMathTextVerticalListNode::getChild(int i)
|
||||
{
|
||||
return nodes[i];
|
||||
}
|
||||
|
||||
const JKQTMathTextNode *JKQTMathTextVerticalListNode::getChild(int i) const
|
||||
{
|
||||
return nodes[i];
|
||||
}
|
||||
|
||||
JKQTMathTextNode *JKQTMathTextVerticalListNode::replaceChild(int i, JKQTMathTextNode *newChild)
|
||||
{
|
||||
JKQTMathTextNode* c=nodes[i];
|
||||
nodes[i]=newChild;
|
||||
newChild->setParentNode(this);
|
||||
return c;
|
||||
}
|
||||
|
||||
JKQTMathTextHorizontalAlignment JKQTMathTextVerticalListNode::getAlignment() const
|
||||
{
|
||||
return alignment;
|
||||
}
|
||||
|
||||
JKQTMathTextVerticalOrientation JKQTMathTextVerticalListNode::getVerticalOrientation() const
|
||||
{
|
||||
return verticalOrientation;
|
||||
}
|
||||
|
||||
double JKQTMathTextVerticalListNode::getLineSpacingFactor() const
|
||||
{
|
||||
return lineSpacingFactor;
|
||||
}
|
||||
|
||||
JKQTMathTextVerticalListNode::SpacingMode JKQTMathTextVerticalListNode::getSpacingMode() const
|
||||
{
|
||||
return spacingMode;
|
||||
}
|
||||
|
||||
JKQTMathTextVerticalListNode::LayoutInfo::LayoutInfo():
|
||||
width(0),
|
||||
baselineHeight(0),
|
||||
overallHeight(0),
|
||||
strikeoutPos(0)
|
||||
{}
|
||||
|
@ -27,22 +27,25 @@
|
||||
#include "jkqtmathtext/jkqtmathtexttools.h"
|
||||
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
|
||||
#include <QPainter>
|
||||
#include <QFontMetricsF>
|
||||
|
||||
class JKQTMathText; // forward
|
||||
// JKQTMATHTEXT_LIB_EXPORT
|
||||
|
||||
|
||||
/** \brief subclass representing a list of nodes in the syntax tree
|
||||
/** \brief subclass representing a list of nodes in the syntax tree, layed out horizontally
|
||||
* \ingroup jkqtmathtext_items
|
||||
*
|
||||
* \note This type of node also implements typesetting sub-/superscript above/below the previous node (if
|
||||
* JKQTMathTextNode::is() is \c true for that previus node. The drawing is done as defined in the
|
||||
* following image \image html jkqtmathtext_subsuper_with_limits.png
|
||||
*
|
||||
* \see JKQTMathTextVerticalListNode
|
||||
*/
|
||||
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextListNode: public JKQTMathTextMultiChildNode {
|
||||
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextHorizontalListNode: public JKQTMathTextMultiChildNode {
|
||||
public:
|
||||
explicit JKQTMathTextListNode(JKQTMathText* parent);
|
||||
virtual ~JKQTMathTextListNode() override;
|
||||
explicit JKQTMathTextHorizontalListNode(JKQTMathText* parent);
|
||||
virtual ~JKQTMathTextHorizontalListNode() override;
|
||||
/** \copydoc JKQTMathTextNode::getTypeName() */
|
||||
virtual QString getTypeName() const override;
|
||||
/** \copydoc JKQTMathTextNode::draw() */
|
||||
@ -72,6 +75,119 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextListNode: public JKQTMathTextMultiChil
|
||||
void clearChildrenImpl(bool deleteChildren);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** \brief subclass representing a list of nodes in the syntax tree, layed out vertically
|
||||
* \ingroup jkqtmathtext_items
|
||||
*
|
||||
* Each child can be thought of as a line, so this node represents a list of lines.
|
||||
* The layout of the lines can left-aligned, right-aligned or centered.
|
||||
*
|
||||
* \image html jkqtmathtext_verticallist.png
|
||||
*
|
||||
* \image html jkqtmathtext_verticalalignment.png
|
||||
*
|
||||
* \image html jkqtmathtext_horizontalalignment.png
|
||||
*
|
||||
* \see JKQTMathTextHorizontalListNode
|
||||
*/
|
||||
class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerticalListNode: public JKQTMathTextMultiChildNode {
|
||||
public:
|
||||
/** \brief defines, how lines are beeing spaced by the node
|
||||
*
|
||||
* \image html jkqtmathtext_verticallist.png
|
||||
*/
|
||||
enum SpacingMode {
|
||||
SMDefault, /*!< space the lines with equilibrated spacing, i.e. the baselines are at least \c QFontMetricsF::lineSpacing()*JKQTMathTextVerticalListNode::lineSpacingFactor apart, but even more, if the height of the text bloxk is larger than the the font's ascent+descent */
|
||||
SMMinimal /*!< space the lines as tight as possible, i.e. each line is separated by \c QFontMetricsF::leading()*JKQTMathTextVerticalListNode::lineSpacingFactor from the next line. This is a s compact as possible */
|
||||
};
|
||||
/** \brief convert a SpacingMode to a String */
|
||||
static QString SpacingMode2String(SpacingMode mode);
|
||||
/** \brief convert a String to a SpacingMode */
|
||||
static SpacingMode String2SpacingMode(QString mode);
|
||||
|
||||
explicit JKQTMathTextVerticalListNode(JKQTMathText* parent, JKQTMathTextHorizontalAlignment _alignment=MTHACentered, double _linespacingFactor=1.0, SpacingMode spacingMode_=SMDefault, JKQTMathTextVerticalOrientation _verticalOrientation=MTVOFirstLine);
|
||||
virtual ~JKQTMathTextVerticalListNode() 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;
|
||||
/** \brief add a child node */
|
||||
void addChild(JKQTMathTextNode* n);
|
||||
/** \copydoc JKQTMathTextMultiChildNode::getChildren() */
|
||||
virtual QList<JKQTMathTextNode*> getChildren() override;
|
||||
/** \copydoc JKQTMathTextMultiChildNode::childCount() */
|
||||
virtual int childCount() const override;
|
||||
/** \copydoc JKQTMathTextMultiChildNode::clearChildren() */
|
||||
virtual void clearChildren(bool deleteChildren=true) override;
|
||||
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
|
||||
virtual JKQTMathTextNode* getChild(int i) override;
|
||||
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
|
||||
virtual const JKQTMathTextNode* getChild(int i) const override;
|
||||
/** \copydoc JKQTMathTextMultiChildNode::getChild() */
|
||||
virtual JKQTMathTextNode* replaceChild(int i, JKQTMathTextNode* newChild) override;
|
||||
/** \copydoc alignment */
|
||||
JKQTMathTextHorizontalAlignment getAlignment() const;
|
||||
/** \copydoc verticalOrientation */
|
||||
JKQTMathTextVerticalOrientation getVerticalOrientation() const;
|
||||
/** \copydoc lineSpacingFactor */
|
||||
double getLineSpacingFactor() const;
|
||||
/** \copydoc spacingMode */
|
||||
SpacingMode getSpacingMode() 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 describes the layout of the whole node */
|
||||
struct LayoutInfo {
|
||||
LayoutInfo();
|
||||
/** \brief drawing position for each line */
|
||||
QList<QPointF> X;
|
||||
/** \brief width of whole block */
|
||||
double width;
|
||||
/** \brief baselineHeight of whole block */
|
||||
double baselineHeight;
|
||||
/** \brief overallHeight of whole block */
|
||||
double overallHeight;
|
||||
/** \brief strikeoutPos of whole block */
|
||||
double strikeoutPos;
|
||||
};
|
||||
/** \brief calclates the layout of the whole block/node */
|
||||
LayoutInfo calcLayout(QPainter& painter, JKQTMathTextEnvironment currentEv);
|
||||
|
||||
/** \brief list of child nodes, each representing one line */
|
||||
QList<JKQTMathTextNode*> nodes;
|
||||
/** \brief alignment scheme used to lay out all lines
|
||||
*
|
||||
* \image html jkqtmathtext_horizontalalignment.png
|
||||
*/
|
||||
JKQTMathTextHorizontalAlignment alignment;
|
||||
/** \brief spacing of the separate lines, as factor of the default line-spacing [Default: 1].
|
||||
*
|
||||
* This property can be used to move the lines closer together or farther apart.
|
||||
*
|
||||
* \image html jkqtmathtext_verticallist.png
|
||||
*/
|
||||
double lineSpacingFactor;
|
||||
/** \brief vertical orientation of the baseline of the whole block (with respect to the single lines)
|
||||
*
|
||||
* \image html jkqtmathtext_verticalorientation.png
|
||||
*/
|
||||
JKQTMathTextVerticalOrientation verticalOrientation;
|
||||
/** \brief defines how the layout algorithm (see calcLayout() ) lays out the single lines */
|
||||
SpacingMode spacingMode;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
/** \brief internal implementation of clearChildren() that is non-virtual, so can be used in the destructor */
|
||||
void clearChildrenImpl(bool deleteChildren);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // JKQTMATHTEXTLISTNODE_H
|
||||
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
JKQTMathTextNode *simplifyJKQTMathTextNode(JKQTMathTextNode *node)
|
||||
{
|
||||
JKQTMathTextListNode* nl=dynamic_cast<JKQTMathTextListNode*>(node);
|
||||
JKQTMathTextHorizontalListNode* nl=dynamic_cast<JKQTMathTextHorizontalListNode*>(node);
|
||||
JKQTMathTextMultiChildNode* nmc=dynamic_cast<JKQTMathTextMultiChildNode*>(node);
|
||||
JKQTMathTextSingleChildNode* nsc=dynamic_cast<JKQTMathTextSingleChildNode*>(node);
|
||||
if (nl) {
|
||||
|
@ -32,7 +32,7 @@ class JKQTMathTextNode; // forward
|
||||
* \ingroup jkqtmathtext_items
|
||||
*
|
||||
* Basically this takes does the following steps (recursively):
|
||||
* - remove any JKQTMathTextListNode that has only one child
|
||||
* - remove any JKQTMathTextHorizontalListNode that has only one child
|
||||
* .
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNode* simplifyJKQTMathTextNode(JKQTMathTextNode* node);
|
||||
|
Loading…
Reference in New Issue
Block a user