NEW: JKQTMathText: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)

This commit is contained in:
jkriege2 2022-06-26 21:17:42 +02:00
parent a8abebf268
commit 2d2acc3b19
8 changed files with 92 additions and 21 deletions

View File

@ -46,6 +46,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: LaTeX-Parser understands optional instruction parameters in [...] now</li>
<li>NEW: LaTeX-Parser simplifies parrse-tree to increase speed of execution</li>
<li>NEW: \limits and \nolimits works as in LaTeX now (before it was simply removed and the functionality implemented for a fixed list of symbols)</li>
<li>NEW: added top-corner (\ulcorner/\urcorner) and bottom-corner brackets (\llcorner/\lrcorner)</li>
</ul>
</ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1022 B

View File

@ -105,30 +105,36 @@ TestForm::TestForm(QWidget *parent) :
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: brace test langle", "text: \\langle\\langle -- math: $\\langle\\langle$");
ui->cmbTestset->addItem("text/math: brace test lange+super 1", "text: \\langle\\langle r^{123} -- math: $\\langle\\langle r^{123}$");
ui->cmbTestset->addItem("text/math: brace test lange+super 2", "text: \\langle\\langle r^{123}\\rangle\\rangle -- math: $\\langle\\langle r^{123}\\rangle\\rangle$");
ui->cmbTestset->addItem("text/math: brace test left-langle 1", "text: \\left\\langle r^{123}\\right\\rangle -- math: $\\left\\langle r^{123}\\right\\rangle$");
ui->cmbTestset->addItem("text/math: brace test left-langle 2", "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$");
auto fAddBraceTest=[](const QString& open, const QString& close) {
QString res= "\\left"+open+"\\left"+open+"\\left"+open+" r^{123}\\right"+close+"\\right"+close+"\\right"+close;
res += "\\left"+open+"\\left"+open+"\\left"+open+" r_{123}\\right"+close+"\\right"+close+"\\right"+close;
res += "\\left"+open+"\\left"+open+"\\left"+open+" r_{123}^{123}\\right"+close+"\\right"+close+"\\right"+close;
return res;
};
ui->cmbTestset->addItem("text/math: brace5 test: ( )", "text: "+fAddBraceTest("(",")")+" -- math: $"+fAddBraceTest("(",")")+"$");
ui->cmbTestset->addItem("text/math: brace6 test: [ ]", "text: "+fAddBraceTest("[","]")+" -- math: $"+fAddBraceTest("[","]")+"$");
ui->cmbTestset->addItem("text/math: brace7 test: { }", "text: "+fAddBraceTest("\\{","\\}")+" -- math: $"+fAddBraceTest("\\{","\\}")+"$");
ui->cmbTestset->addItem("text/math: brace8 test: || ||", "text: "+fAddBraceTest("\\|","\\|")+" -- math: $"+fAddBraceTest("\\|","\\|")+"$");
ui->cmbTestset->addItem("text/math: brace9 test: | |", "text: "+fAddBraceTest("|","|")+" -- math: $"+fAddBraceTest("|","|")+"$");
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: brace test: left/right ( )", "text: "+fAddBraceTest("(",")")+" -- math: $"+fAddBraceTest("(",")")+"$");
ui->cmbTestset->addItem("text/math: brace test: left/right [ ]", "text: "+fAddBraceTest("[","]")+" -- math: $"+fAddBraceTest("[","]")+"$");
ui->cmbTestset->addItem("text/math: brace test: left/right { }", "text: "+fAddBraceTest("\\{","\\}")+" -- math: $"+fAddBraceTest("\\{","\\}")+"$");
ui->cmbTestset->addItem("text/math: brace test: left/right || ||", "text: "+fAddBraceTest("\\|","\\|")+" -- math: $"+fAddBraceTest("\\|","\\|")+"$");
ui->cmbTestset->addItem("text/math: brace test: left/right | |", "text: "+fAddBraceTest("|","|")+" -- math: $"+fAddBraceTest("|","|")+"$");
ui->cmbTestset->addItem("text/math: brace test: left/right 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: brace test: left/right 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: brace test: left/right top-corner", "text: "+fAddBraceTest("\\ulcorner","\\urcorner")+" -- math: $"+fAddBraceTest("\\ulcorner","\\urcorner")+"$");
ui->cmbTestset->addItem("text/math: brace test: left/right bottom-corner", "text: "+fAddBraceTest("\\llcorner","\\lrcorner")+" -- math: $"+fAddBraceTest("\\llcorner","\\lrcorner")+"$");
ui->cmbTestset->addItem("text/math: brace test: left/right mixed", "text: \\left\\{\\left[\\left( r^{123}\\right)\\right]\\right\\} -- math: $\\left\\{\\left[\\left( r^{123}\\right)\\right]\\right\\}$");
ui->cmbTestset->addItem("text/math: brace test: non-left/right ( )", "text: (((r^{123}))) -- math: $(((r^{123})))$");
ui->cmbTestset->addItem("text/math: brace test: non-left/right [ ]", "text: [[[r^{123}]]] -- math: $[[[r^{123}]]]$");
ui->cmbTestset->addItem("text/math: brace test: non-left/right { }", "text: \\{\\{\\{r^{123}\\}\\}\\} -- math: $\\{\\{\\{ r^{123}\\}\\}\\}$");
ui->cmbTestset->addItem("text/math: brace test: non-left/right | |", "text: |||r^{123}||| -- math: $|||r^{123}|||$");
ui->cmbTestset->addItem("text/math: brace test: non-left/right floor", "text: \\lfloor\\lfloor\\lfloor r^{123}\\rfloor\\rfloor\\rfloor -- math: $\\lfloor\\lfloor\\lfloor r^{123}\\rfloor\\rfloor\\rfloor$");
ui->cmbTestset->addItem("text/math: brace test: non-left/right ceil", "text: \\lceil\\lceil\\lceil r^{123}\\rceil\\rceil\\rceil -- math: $\\lceil\\lceil\\lceil r^{123}\\rceil\\rceil\\rceil$");
ui->cmbTestset->addItem("text/math: brace test: non-left/right top-corner", "text: \\ulcorner\\ulcorner\\ulcorner r^{123}\\urcorner\\urcorner\\urcorner -- math: $\\ulcorner\\ulcorner\\ulcorner r^{123}\\urcorner\\urcorner\\urcorner$");
ui->cmbTestset->addItem("text/math: brace test: non-left/right bottom-corner", "text: \\llcorner\\llcorner\\llcorner r^{123}\\lrcorner\\lrcorner\\lrcorner -- math: $\\llcorner\\llcorner\\llcorner r^{123}\\lrcorner\\lrcorner\\lrcorner$");
ui->cmbTestset->addItem("text/math: brace 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("", "");

View File

@ -345,6 +345,10 @@ QString JKQTMathTextBraceType2String(JKQTMathTextBraceType type) {
return "parenhesis";
case MTBTSingleLine:
return "single_line";
case MTBTTopCorner:
return "top_corner";
case MTBTBottomCorner:
return "bottom_corner";
case MTBTAny:
return "any";
case MTBTNone:
@ -363,6 +367,8 @@ JKQTMathTextBraceType TokenName2JKQTMathTextBraceType(const QString &tokenName)
if (tokenName=="<" || tokenName==">" || tokenName=="langle" || tokenName=="rangle") return MTBTAngleBracket;
if (tokenName=="_" || tokenName=="lfloor" || tokenName=="rfloor") return MTBTFloorBracket;
if (tokenName=="~" || tokenName=="lceil" || tokenName=="rceil") return MTBTCeilBracket;
if (tokenName=="ulcorner" || tokenName=="urcorner"||tokenName=="tlcorner" || tokenName=="trcorner") return MTBTTopCorner;
if (tokenName=="blcorner" || tokenName=="brcorner"||tokenName=="llcorner" || tokenName=="lrcorner") return MTBTBottomCorner;
if (tokenName=="any") return MTBTAny;
if (tokenName=="." || tokenName=="" || tokenName=="none") return MTBTNone;
return MTBTUnknown;
@ -375,6 +381,8 @@ JKQTMathTextBraceType InstructionName2OpeningJKQTMathTextBraceType(const QString
if (tokenName=="langle") return MTBTAngleBracket;
if (tokenName=="lfloor") return MTBTFloorBracket;
if (tokenName=="lceil") return MTBTCeilBracket;
if (tokenName=="tlcorner"||tokenName=="ulcorner") return MTBTTopCorner;
if (tokenName=="blcorner"||tokenName=="llcorner") return MTBTBottomCorner;
return MTBTUnknown;
}
@ -385,6 +393,8 @@ JKQTMathTextBraceType InstructionName2JKQTMathTextBraceType(const QString &token
if (tokenName=="langle" || tokenName=="rangle") return MTBTAngleBracket;
if (tokenName=="lfloor" || tokenName=="rfloor") return MTBTFloorBracket;
if (tokenName=="lceil" || tokenName=="rceil") return MTBTCeilBracket;
if (tokenName=="ulcorner" || tokenName=="urcorner"||tokenName=="tlcorner" || tokenName=="trcorner") return MTBTTopCorner;
if (tokenName=="blcorner" || tokenName=="brcorner"||tokenName=="llcorner" || tokenName=="lrcorner") return MTBTBottomCorner;
return MTBTUnknown;
}

View File

@ -149,6 +149,8 @@ enum JKQTMathTextBraceType {
MTBTFloorBracket, /*!< \brief floor brackets \image html jkqtmathtext/jkqtmathtext_brace_floor.png */
MTBTDoubleLine, /*!< \brief double-line brackets (norm ||...||) \image html jkqtmathtext/jkqtmathtext_brace_dblline.png */
MTBTSingleLine, /*!< \brief single-line brackets (abs |...|) \image html jkqtmathtext/jkqtmathtext_brace_oneline.png */
MTBTTopCorner, /*!< \brief top-corner brackets \image html jkqtmathtext/jkqtmathtext_brace_topcorner.png */
MTBTBottomCorner, /*!< \brief bottom-corner brackets \image html jkqtmathtext/jkqtmathtext_brace_bottomcorner.png */
MTBTNone, /*!< \brief no bracket */
MTBTAny, /*!< \brief any bracket, used by JKQTMathText::parseLatexString() */
MTBTUnknown /*!< \brief an unknown tokenName presented to TokenName2JKQTMathTextBraceType() */

View File

@ -109,8 +109,8 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
{
bool showOpeningBrace=true;
const double xbrace1=xnew+lw;
const double xbrace2=qMin(xnew+paren_fraction*bracewidth, xnew+bracewidth-lw/2.0);
const double xbrace2s=qMin(xnew+brace_fraction*bracewidth, xnew+bracewidth-lw/2.0);
const double xbrace2=xnew+qMin(paren_fraction*bracewidth, bracewidth-lw/2.0);
const double xbrace2s=xnew+qMin(brace_fraction*bracewidth, bracewidth-lw/2.0);
if (openbrace==MTBTParenthesis) {
QPainterPath path;
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
@ -127,6 +127,22 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace1, y2);
path.lineTo(xbrace2s, y2);
painter.drawPath(path);
} else if (openbrace==MTBTTopCorner) {
QPainterPath path;
const double dx=fabs(xbrace2s-xbrace1);
const double y1=y-nodeBaselineHeight;
path.moveTo(xbrace2s, y1);
path.lineTo(xbrace1, y1);
path.lineTo(xbrace1, y1+dx);
painter.drawPath(path);
} else if (openbrace==MTBTBottomCorner) {
QPainterPath path;
const double dx=fabs(xbrace2s-xbrace1);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
path.moveTo(xbrace2s, y1);
path.lineTo(xbrace1, y1);
path.lineTo(xbrace1, y1-dx);
painter.drawPath(path);
} else if (openbrace==MTBTCurlyBracket) {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,nodeOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
@ -204,6 +220,22 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
path.lineTo(xbrace2, y2);
path.lineTo(xbrace1s, y2);
painter.drawPath(path);
} else if (closebrace==MTBTBottomCorner) {
QPainterPath path;
const double dx=fabs(xbrace1s-xbrace2);
const double y1=y+(nodeOverallHeight-nodeBaselineHeight);
path.moveTo(xbrace1s, y1);
path.lineTo(xbrace2, y1);
path.lineTo(xbrace2, y1-dx);
painter.drawPath(path);
} else if (closebrace==MTBTTopCorner) {
QPainterPath path;
const double dx=fabs(xbrace1s-xbrace2);
const double y1=y-nodeBaselineHeight;
path.moveTo(xbrace1s, y1);
path.lineTo(xbrace2, y1);
path.lineTo(xbrace2, y1+dx);
painter.drawPath(path);
} else if (closebrace==MTBTCurlyBracket) {
QPainterPath path=JKQTMathTextMakeHBracePath(0,0,nodeOverallHeight, bracewidth*brace_fraction);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
@ -271,6 +303,8 @@ bool JKQTMathTextBraceNode::toHtml(QString &html, JKQTMathTextEnvironment curren
else if (openbrace==MTBTCurlyBracket) ob="{";
else if (openbrace==MTBTSingleLine) ob="|";
else if (openbrace==MTBTDoubleLine) ob="||";
else if (openbrace==MTBTTopCorner) ob="&ulcorner;";
else if (openbrace==MTBTBottomCorner) ob="&llcorner;";
if (closebrace==MTBTAngleBracket) cb="&rang;";
else if (closebrace==MTBTFloorBracket) cb="&rfloor;";
else if (closebrace==MTBTCeilBracket) cb="&rceil;";
@ -279,6 +313,8 @@ bool JKQTMathTextBraceNode::toHtml(QString &html, JKQTMathTextEnvironment curren
else if (closebrace==MTBTCurlyBracket) cb="}";
else if (closebrace==MTBTSingleLine) cb="|";
else if (closebrace==MTBTDoubleLine) cb="||";
else if (closebrace==MTBTTopCorner) ob="&urcorner;";
else if (closebrace==MTBTBottomCorner) ob="&lrcorner;";
html=html+ob;

View File

@ -513,6 +513,14 @@ bool JKQTMathTextSymbolNode::getUnicodeFullSymbolProp(JKQTMathTextSymbolNode::Sy
unicodeSymbol.insert("rceil", QChar(0x2309));
unicodeSymbol.insert("lfloor", QChar(0x230A));
unicodeSymbol.insert("rfloor", QChar(0x230B));
unicodeSymbol.insert("llcorner", QChar(0x231E));
unicodeSymbol.insert("lrcorner", QChar(0x231F));
unicodeSymbol.insert("ulcorner", QChar(0x231C));
unicodeSymbol.insert("urcorner", QChar(0x231D));
unicodeSymbol.insert("blcorner", QChar(0x231E));
unicodeSymbol.insert("brcorner", QChar(0x231F));
unicodeSymbol.insert("tlcorner", QChar(0x231C));
unicodeSymbol.insert("trcorner", QChar(0x231D));
unicodeSymbol.insert("subsetnot", QChar(0x2284));
unicodeSymbol.insert("DC", QChar(0x2393));
unicodeSymbol.insert("bot", QChar(0x22A4));
@ -916,7 +924,7 @@ void JKQTMathTextSymbolNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvi
else if (symbolName=="longleftrightarrow") { width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.5; symb="x"; }
else if (symbolName=="Longleftrightarrow") { width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.5; symb="x"; }
}
const QRectF tbr=JKQTMathTextGetTightBoundingRect(f, symb, painter.device());
const QRectF tbr=(symb.isEmpty())?JKQTMathTextGetTightBoundingRect(f, "X", painter.device()):JKQTMathTextGetTightBoundingRect(f, symb, painter.device());
overallHeight=tbr.height();// fm.height();
baselineHeight=tbr.height()-tbr.bottom();
if (props.exactAscent) {
@ -1208,6 +1216,14 @@ bool JKQTMathTextSymbolNode::toHtml(QString &html, JKQTMathTextEnvironment curre
entitylut.insert("exists", "&exist;");
entitylut.insert("cong", "&sim;");
entitylut.insert("bot", "&perp;");
entitylut.insert("llcorner", "&ulcorner;");
entitylut.insert("lrcorner", "&urcorner;");
entitylut.insert("ulcorner", "&ulcorner;");
entitylut.insert("urcorner", "&urcorner;");
entitylut.insert("blcorner", "&llcorner;");
entitylut.insert("brcorner", "&llcorner;");
entitylut.insert("tlcorner", "&lrcorner;");
entitylut.insert("trcorner", "&lrcorner;");
entitylut.insert("ll", "<<");