diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox
index c686ded028..9740fa3a24 100644
--- a/doc/dox/whatsnew.dox
+++ b/doc/dox/whatsnew.dox
@@ -18,6 +18,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
fixed issue #70: Typo in jkqtplotter/CMakeLists.txt, thanks to user:tedlinlab
fixed: styling was not properly applied to coordinate axes of colorbars outside the plot
fixed: JKQTMathText added a little whitespace before and after the LaTeX-string. This was removed as it disturbed the layout of text in plots
+ fixes/improvements: JKQTMathText renders several LaTeX strings better (simple braces in math mode, +-*... as symbols with proper sizes in math mode, added some missing instruction aliases, improved size of \vec and \hat, corrrected fonts usage for mathrm
improved: high-dpr-support in JKQTMathText
improved: QT6-compatibility by removing deprecated warnings
NEW: JKQTPFilledCurveXGraph and JKQTPFilledCurveYGraph can now plot wiggle plots with different fill styles above and below the baseline (feature request #68 Wiggle Plots from user:xichaoqiang
diff --git a/examples/jkqtmathtext_test/testform.cpp b/examples/jkqtmathtext_test/testform.cpp
index 9aff919fbf..2388dbdb1e 100644
--- a/examples/jkqtmathtext_test/testform.cpp
+++ b/examples/jkqtmathtext_test/testform.cpp
@@ -17,7 +17,7 @@ TestForm::TestForm(QWidget *parent) :
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$\\ propto: $\\propto$\\ bullet: $\\bullet$\\ neq: $\\neq$\\ ne: $\\ne$\\ equiv: $\\equiv$\\ approx: $\\approx$\\ otimes: $\\otimes$\\ oplus: $\\oplus$");
+ 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$");
@@ -94,6 +94,11 @@ TestForm::TestForm(QWidget *parent) :
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("", "");
@@ -111,7 +116,7 @@ TestForm::TestForm(QWidget *parent) :
ui->cmbTestset->addItem("math 12 (under/overbrace)", "$\\underbrace{\\overbrace{x+x+...+x}{k\\ \\mathrm{times}} \\overbrace{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 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!}$");
diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp
index effdce4047..e72df19f30 100644
--- a/lib/jkqtmathtext/jkqtmathtext.cpp
+++ b/lib/jkqtmathtext/jkqtmathtext.cpp
@@ -415,11 +415,12 @@ QString JKQTMathText::MTtextNode::textTransform(const QString &text, JKQTMathTex
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;
+ case '>': txt+=QString(QString(" >")); break;
+ case '=': txt+=QString(QString(" =")); break;
case ';': txt+=QString(QString("; ")); break;
+ case ',': txt+=QString(QString(", ")); break;
default: txt+=c; break;
}
}
@@ -539,7 +540,7 @@ bool JKQTMathText::MTinstruction1Node::setupMTenvironment(JKQTMathText::MTenviro
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=JKQTMathText::MTEroman; ev.italic=false; }
- else if (name=="mathrm" || name=="operatorname") { ev.font=JKQTMathText::MTEroman; ev.italic=false; }
+ else if (name=="mathrm" || name=="unit" || name=="operatorname") { ev.font=JKQTMathText::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=JKQTMathText::MTEroman; ev.italic=false; }
else if (name=="mat") { ev.font=JKQTMathText::MTEroman; ev.italic=false; ev.bold=true; }
@@ -1185,7 +1186,7 @@ double JKQTMathText::MTdecoratedNode::draw(QPainter& painter, double x, double y
if (decoration==MTDvec) {
painter.setPen(p);
QPolygonF poly;
- poly<") { props.symbol = ">"; props.bold = 0; props.italic = 0; }
+ else if (n == "<") { props.symbol = "<"; props.bold = 0; props.italic = 0; }
else if (n == "$") { props.symbol = "$"; props.bold = 0; props.italic = 0; }
else if (n == "%") { props.symbol = "%"; props.bold = 0; props.italic = 0; }
else if (n == "&") { props.symbol = "&"; props.bold = 0; props.italic = 0; }
else if (n == "#") { props.symbol = "#"; props.bold = 0; props.italic = 0; }
else if (n == "ast") { props.symbol = "*"; props.bold = 0; props.italic = 0; }
+ else if (n == "asterisk") { props.symbol = "*"; props.bold = 0; props.italic = 0; }
else if (n == "glq") { props.symbol = "'"; props.bold = 0; props.italic = 0; }
else if (n == "grq") { props.symbol = "'"; props.bold = 0; props.italic = 0; }
else if (n == "glqq") { props.symbol = "\""; props.bold = 0; props.italic = 0; }
@@ -2354,9 +2368,21 @@ bool JKQTMathText::MTsymbolNode::getStandardTextSymbolProp(JKQTMathText::MTsymbo
//qDebug()<<" +--- getStandardTextSymbolProp("<") { props.symbol = ">"; props.bold = 0; }
+ else if (n == "|") { props.symbol = "|"; props.bold = 0; }
else if (n == "}") { props.symbol = "}"; }
else if (n == "{") { props.symbol = "{"; }
- else if (n == "backslash") { props.symbol = "\\"; props.bold = 0; props.italic = 0; }
+ else if (n == "]") { props.symbol = "]"; }
+ else if (n == "[") { props.symbol = "["; }
+ else if (n == "(") { props.symbol = "("; }
+ else if (n == ")") { props.symbol = ")"; }
+ else if (n == "|") { props.symbol = "|"; }
else if (n == "$") { props.symbol = "$"; }
else if (n == "%") { props.symbol = "%"; }
else if (n == "&") { props.symbol = "&"; }
@@ -2381,6 +2407,10 @@ bool JKQTMathText::MTsymbolNode::getUnicodeBaseSymbolProp(JKQTMathText::MTsymbol
unicodeBaseSymbol.insert("infty", QChar(0x221E));
unicodeBaseSymbol.insert("partial", QChar(0x2202));
unicodeBaseSymbol.insert("times", QChar(0x2A2F));
+ unicodeBaseSymbol.insert("*", QChar(0x2217));
+ unicodeBaseSymbol.insert("ast", QChar(0x2217));
+ unicodeBaseSymbol.insert("asterisk", QChar(0x2217));
+ unicodeBaseSymbol.insert("star", QChar(0x22C6));
unicodeBaseSymbol.insert("bullet", QChar(0x2219));
unicodeBaseSymbol.insert("copyright", QChar(0x00A9));
unicodeBaseSymbol.insert("registered", QChar(0x00AE));
@@ -2413,6 +2443,9 @@ bool JKQTMathText::MTsymbolNode::getUnicodeBaseSymbolProp(JKQTMathText::MTsymbol
unicodeBaseSymbol.insert("cdots", QString(QChar(0x00B7)) + QString(QChar(0x00B7)) + QString(QChar(0x00B7)));
unicodeBaseSymbol.insert("approx", QChar(0x2248));
unicodeBaseSymbol.insert("Angstroem", QChar(0x212B));
+ unicodeBaseSymbol.insert("-", QChar(0x2212));
+ unicodeBaseSymbol.insert("dots", QChar(0x2026));
+ unicodeBaseSymbol.insert("ldots", QChar(0x2026));
}
QHash::iterator itbasesymbol = unicodeBaseSymbol.find(n);
@@ -2738,7 +2771,7 @@ JKQTMathText::MTsymbolNode::SymbolProps JKQTMathText::MTsymbolNode::getSymbolPro
<<"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"<<"mid";
+ <<"subset"<<"subseteq"<<"in"<<"notin"<<"cdot"<<"wedge"<<"vee"<<"cong"<<"bot"<<"mid"<<"+"<<"-"<<"|"<<"*"<<"/"<<"<"<<">";
}
if (extendWInMM.contains(n)) {
@@ -2820,23 +2853,34 @@ JKQTMathText::MTsymbolNode::SymbolProps JKQTMathText::MTsymbolNode::getSymbolPro
if (itsimplehia != simpleTranslations_heightIsAscent.end()) {
props.symbol = itsimplehia.value();
props.heightIsAscent = true;
- } else {
- props.font=fnt.first;
- if (!getSymbolProp(props, n, currentEv, mathFontFactor)) {
- errorExplanation="didn't find symbol given font def:"+fnt.first+"["+encoding2String(fnt.second)+"] / sym:"+fntSym.first+"["+encoding2String(fntSym.second)+"] / grk:"+fntGreek.first+"["+encoding2String(fntGreek.second)+"]";
- }
+ } else {
+ props.font=fnt.first;
+ if (!getSymbolProp(props, n, currentEv, mathFontFactor)) {
+ errorExplanation="didn't find symbol given font def:"+fnt.first+"["+encoding2String(fnt.second)+"] / sym:"+fntSym.first+"["+encoding2String(fntSym.second)+"] / grk:"+fntGreek.first+"["+encoding2String(fntGreek.second)+"]";
}
+ }
}
if (addWhitespace) props.symbol+=" ";
static QSet extraSymbolName = {
"infty",
- "|", " ", "quad", "qquad", "space", ";", ":", ",", "!",
+ "|", " ", "quad", "qquad", "space", ";", ":", ",", "!","%"
"longleftarrow", "longrightarrow",
"Longleftarrow", "Longrightarrow",
"longleftrightarrow", "Longleftrightarrow"
};
+
+ static QSet extraSymbolNonItalic = {
+ "+", "-", "*", "/", "<", ">", "=", "|", "{", "(", "[", "]", ")", "}", "\\"
+ };
+
+ if (props.symbol.simplified().isEmpty() && extraSymbolNonItalic.contains(n)) {
+ props.symbol=n;
+ if (n=="=") props.symbol="= ";
+ props.italic=-1;
+ }
+
if (props.symbol.simplified().isEmpty() && !extraSymbolName.contains(n)) {
parent->error_list.append(tr("unknown symbol '%1' found (%2)!").arg(n).arg(errorExplanation));
}
@@ -3129,6 +3173,9 @@ bool JKQTMathText::MTsymbolNode::toHtml(QString &html, JKQTMathText::MTenvironme
entitylut.insert("propto", "∝");
entitylut.insert("partial", "∂");
entitylut.insert("bullet", "•");
+ entitylut.insert("star", "⋆");
+ entitylut.insert("ast", "∗");
+ entitylut.insert("asterisk", "∗");
entitylut.insert("neq", "≠");
entitylut.insert("ne", "≠");
entitylut.insert("equiv", "≡");
@@ -3194,6 +3241,7 @@ bool JKQTMathText::MTsymbolNode::toHtml(QString &html, JKQTMathText::MTenvironme
entitylut.insert("DC", "=");
entitylut.insert("cdots", "⋅⋅⋅");
entitylut.insert("dots", "...");
+ entitylut.insert("ldots", "...");
entitylut.insert("cent", "¢");
@@ -3585,8 +3633,12 @@ QPair JKQTMathText::getReplacementFont(con
return res;
}
-QPair JKQTMathText::getFontData(JKQTMathText::MTenvironmentFont font, bool /*in_math_environment*/, FontSubclass subclass) const
+QPair JKQTMathText::getFontData(JKQTMathText::MTenvironmentFont font, bool in_math_environment, FontSubclass subclass) const
{
+ if (in_math_environment) {
+ if (font==MTEroman) font=MTEmathRoman;
+ if (font==MTEsans) font=MTEmathSans;
+ }
const auto fd=fontDefinitions.value(font);
if (subclass==FontSubclass::Greek) return QPair(fd.symbolfontGreek, fd.symbolfontGreekEncoding);
if (subclass==FontSubclass::Symbols) return QPair(fd.symbolfontSymbol, fd.symbolfontSymbolEncoding);
@@ -4055,12 +4107,17 @@ JKQTMathText::tokenType JKQTMathText::getToken() {
if (parsingMathEnvironment) {
// inside math environments we split texts at every brace {[(|)]} so that
// braces form their own MTtextNode and may be formated accordingly
- if (c=='(' || c=='[' || c=='|' || c==')' || c==']') {
+ static QSet mathEnvironmentSpecialChars, mathEnvironmentSpecialEndChars;
+ if (mathEnvironmentSpecialChars.size()==0) {
+ mathEnvironmentSpecialChars<<'(' << '[' << '|' << ')' << ']' << '+' << '-' << '*' << '/' << '<' << '>' << '=';
+ mathEnvironmentSpecialEndChars<<'(' << '&' << '[' << '|' << ')' << ']' << '\\' << '$' << '{' << '}' << '_' << '^' << '+' << '-' << '/' << '*' << '=' << '<' << '>';
+ }
+ if (mathEnvironmentSpecialChars.contains(c)) {
currentTokenName=c;
//std::cout<<"found text node '"<addNode(new MTtextNode(this, text, addWhite, parsingMathEnvironment));
+ if (parsingMathEnvironment) {
+ static QSet mathEnvironmentSpecialText;
+ if (mathEnvironmentSpecialText.size()==0) {
+ mathEnvironmentSpecialText<<"+"<<"-"<<"="<<"*"<<"<"<<">"<<"|"<<"/";
+ }
+ if (mathEnvironmentSpecialText.contains(text.trimmed())) {
+ nl->addNode(new MTsymbolNode(this, text, addWhite));
+ } else {
+ nl->addNode(new MTtextNode(this, text, addWhite, parsingMathEnvironment));
+ }
+ } else {
+ nl->addNode(new MTtextNode(this, text, addWhite, parsingMathEnvironment));
+ }
} else if (currentToken==MTTinstruction) {
QString name=currentTokenName;
if (name=="\\") break; // break on linebrak character
@@ -4262,7 +4331,7 @@ JKQTMathText::MTnode* JKQTMathText::parseLatexString(bool get, const QString& qu
nl->addNode(new MTdecoratedNode(this, MTDdoubleunderline, parseLatexString(true)));
} else if (name=="ooline"||name=="ool") {
nl->addNode(new MTdecoratedNode(this, MTDdoubleoverline, parseLatexString(true)));
- } else if (name=="arrow") {
+ } else if (name=="arrow"||name=="overrightarrow"||name=="overarrow") {
nl->addNode(new MTdecoratedNode(this, MTDarrow, parseLatexString(true)));
} else if (name=="hat") {
nl->addNode(new MTdecoratedNode(this, MTDhat, parseLatexString(true)));